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_reg_u64 (cpu
, rd
, NO_SP
, val
);
3452 for (i
= 0; i
< (full
? 8 : 4); i
++)
3453 val
+= aarch64_get_vec_u16 (cpu
, vm
, i
);
3454 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val
);
3458 for (i
= 0; i
< (full
? 4 : 2); i
++)
3459 val
+= aarch64_get_vec_u32 (cpu
, vm
, i
);
3460 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val
);
3466 val
= aarch64_get_vec_u64 (cpu
, vm
, 0);
3467 val
+= aarch64_get_vec_u64 (cpu
, vm
, 1);
3468 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val
);
3474 do_vec_ins_2 (sim_cpu
*cpu
)
3476 /* instr[31,21] = 01001110000
3477 instr[20,18] = size & element selector
3479 instr[13] = direction: to vec(0), from vec (1)
3485 unsigned vm
= INSTR (9, 5);
3486 unsigned vd
= INSTR (4, 0);
3488 NYI_assert (31, 21, 0x270);
3489 NYI_assert (17, 14, 0);
3490 NYI_assert (12, 10, 7);
3492 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3493 if (INSTR (13, 13) == 1)
3495 if (INSTR (18, 18) == 1)
3498 elem
= INSTR (20, 19);
3499 aarch64_set_reg_u64 (cpu
, vd
, NO_SP
,
3500 aarch64_get_vec_u32 (cpu
, vm
, elem
));
3505 if (INSTR (19, 19) != 1)
3508 elem
= INSTR (20, 20);
3509 aarch64_set_reg_u64 (cpu
, vd
, NO_SP
,
3510 aarch64_get_vec_u64 (cpu
, vm
, elem
));
3515 if (INSTR (18, 18) == 1)
3518 elem
= INSTR (20, 19);
3519 aarch64_set_vec_u32 (cpu
, vd
, elem
,
3520 aarch64_get_reg_u32 (cpu
, vm
, NO_SP
));
3525 if (INSTR (19, 19) != 1)
3528 elem
= INSTR (20, 20);
3529 aarch64_set_vec_u64 (cpu
, vd
, elem
,
3530 aarch64_get_reg_u64 (cpu
, vm
, NO_SP
));
3535 #define DO_VEC_WIDENING_MUL(N, DST_TYPE, READ_TYPE, WRITE_TYPE) \
3538 DST_TYPE a[N], b[N]; \
3540 for (i = 0; i < (N); i++) \
3542 a[i] = aarch64_get_vec_##READ_TYPE (cpu, vn, i + bias); \
3543 b[i] = aarch64_get_vec_##READ_TYPE (cpu, vm, i + bias); \
3545 for (i = 0; i < (N); i++) \
3546 aarch64_set_vec_##WRITE_TYPE (cpu, vd, i, a[i] * b[i]); \
3551 do_vec_mull (sim_cpu
*cpu
)
3554 instr[30] = lower(0)/upper(1) selector
3555 instr[29] = signed(0)/unsigned(1)
3556 instr[28,24] = 0 1110
3557 instr[23,22] = size: 8-bit (00), 16-bit (01), 32-bit (10)
3560 instr[15,10] = 11 0000
3564 int unsign
= INSTR (29, 29);
3565 int bias
= INSTR (30, 30);
3566 unsigned vm
= INSTR (20, 16);
3567 unsigned vn
= INSTR ( 9, 5);
3568 unsigned vd
= INSTR ( 4, 0);
3571 NYI_assert (28, 24, 0x0E);
3572 NYI_assert (15, 10, 0x30);
3574 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3575 /* NB: Read source values before writing results, in case
3576 the source and destination vectors are the same. */
3577 switch (INSTR (23, 22))
3583 DO_VEC_WIDENING_MUL (8, uint16_t, u8
, u16
);
3585 DO_VEC_WIDENING_MUL (8, int16_t, s8
, s16
);
3592 DO_VEC_WIDENING_MUL (4, uint32_t, u16
, u32
);
3594 DO_VEC_WIDENING_MUL (4, int32_t, s16
, s32
);
3601 DO_VEC_WIDENING_MUL (2, uint64_t, u32
, u64
);
3603 DO_VEC_WIDENING_MUL (2, int64_t, s32
, s64
);
3612 do_vec_fadd (sim_cpu
*cpu
)
3615 instr[30] = half(0)/full(1)
3616 instr[29,24] = 001110
3617 instr[23] = FADD(0)/FSUB(1)
3618 instr[22] = float (0)/double(1)
3621 instr[15,10] = 110101
3625 unsigned vm
= INSTR (20, 16);
3626 unsigned vn
= INSTR (9, 5);
3627 unsigned vd
= INSTR (4, 0);
3629 int full
= INSTR (30, 30);
3631 NYI_assert (29, 24, 0x0E);
3632 NYI_assert (21, 21, 1);
3633 NYI_assert (15, 10, 0x35);
3635 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3643 for (i
= 0; i
< 2; i
++)
3644 aarch64_set_vec_double (cpu
, vd
, i
,
3645 aarch64_get_vec_double (cpu
, vn
, i
)
3646 - aarch64_get_vec_double (cpu
, vm
, i
));
3650 for (i
= 0; i
< (full
? 4 : 2); i
++)
3651 aarch64_set_vec_float (cpu
, vd
, i
,
3652 aarch64_get_vec_float (cpu
, vn
, i
)
3653 - aarch64_get_vec_float (cpu
, vm
, i
));
3663 for (i
= 0; i
< 2; i
++)
3664 aarch64_set_vec_double (cpu
, vd
, i
,
3665 aarch64_get_vec_double (cpu
, vm
, i
)
3666 + aarch64_get_vec_double (cpu
, vn
, i
));
3670 for (i
= 0; i
< (full
? 4 : 2); i
++)
3671 aarch64_set_vec_float (cpu
, vd
, i
,
3672 aarch64_get_vec_float (cpu
, vm
, i
)
3673 + aarch64_get_vec_float (cpu
, vn
, i
));
3679 do_vec_add (sim_cpu
*cpu
)
3682 instr[30] = full/half selector
3683 instr[29,24] = 001110
3684 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3687 instr[15,10] = 100001
3691 unsigned vm
= INSTR (20, 16);
3692 unsigned vn
= INSTR (9, 5);
3693 unsigned vd
= INSTR (4, 0);
3695 int full
= INSTR (30, 30);
3697 NYI_assert (29, 24, 0x0E);
3698 NYI_assert (21, 21, 1);
3699 NYI_assert (15, 10, 0x21);
3701 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3702 switch (INSTR (23, 22))
3705 for (i
= 0; i
< (full
? 16 : 8); i
++)
3706 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vn
, i
)
3707 + aarch64_get_vec_u8 (cpu
, vm
, i
));
3711 for (i
= 0; i
< (full
? 8 : 4); i
++)
3712 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vn
, i
)
3713 + aarch64_get_vec_u16 (cpu
, vm
, i
));
3717 for (i
= 0; i
< (full
? 4 : 2); i
++)
3718 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vn
, i
)
3719 + aarch64_get_vec_u32 (cpu
, vm
, i
));
3725 aarch64_set_vec_u64 (cpu
, vd
, 0, aarch64_get_vec_u64 (cpu
, vn
, 0)
3726 + aarch64_get_vec_u64 (cpu
, vm
, 0));
3727 aarch64_set_vec_u64 (cpu
, vd
, 1,
3728 aarch64_get_vec_u64 (cpu
, vn
, 1)
3729 + aarch64_get_vec_u64 (cpu
, vm
, 1));
3735 do_vec_mul (sim_cpu
*cpu
)
3738 instr[30] = full/half selector
3739 instr[29,24] = 00 1110
3740 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3743 instr[15,10] = 10 0111
3747 unsigned vm
= INSTR (20, 16);
3748 unsigned vn
= INSTR (9, 5);
3749 unsigned vd
= INSTR (4, 0);
3751 int full
= INSTR (30, 30);
3754 NYI_assert (29, 24, 0x0E);
3755 NYI_assert (21, 21, 1);
3756 NYI_assert (15, 10, 0x27);
3758 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3759 switch (INSTR (23, 22))
3762 DO_VEC_WIDENING_MUL (full
? 16 : 8, uint8_t, u8
, u8
);
3766 DO_VEC_WIDENING_MUL (full
? 8 : 4, uint16_t, u16
, u16
);
3770 DO_VEC_WIDENING_MUL (full
? 4 : 2, uint32_t, u32
, u32
);
3779 do_vec_MLA (sim_cpu
*cpu
)
3782 instr[30] = full/half selector
3783 instr[29,24] = 00 1110
3784 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3787 instr[15,10] = 1001 01
3791 unsigned vm
= INSTR (20, 16);
3792 unsigned vn
= INSTR (9, 5);
3793 unsigned vd
= INSTR (4, 0);
3795 int full
= INSTR (30, 30);
3797 NYI_assert (29, 24, 0x0E);
3798 NYI_assert (21, 21, 1);
3799 NYI_assert (15, 10, 0x25);
3801 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3802 switch (INSTR (23, 22))
3806 uint16_t a
[16], b
[16];
3808 for (i
= 0; i
< (full
? 16 : 8); i
++)
3810 a
[i
] = aarch64_get_vec_u8 (cpu
, vn
, i
);
3811 b
[i
] = aarch64_get_vec_u8 (cpu
, vm
, i
);
3814 for (i
= 0; i
< (full
? 16 : 8); i
++)
3816 uint16_t v
= aarch64_get_vec_u8 (cpu
, vd
, i
);
3818 aarch64_set_vec_u16 (cpu
, vd
, i
, v
+ (a
[i
] * b
[i
]));
3825 uint32_t a
[8], b
[8];
3827 for (i
= 0; i
< (full
? 8 : 4); i
++)
3829 a
[i
] = aarch64_get_vec_u16 (cpu
, vn
, i
);
3830 b
[i
] = aarch64_get_vec_u16 (cpu
, vm
, i
);
3833 for (i
= 0; i
< (full
? 8 : 4); i
++)
3835 uint32_t v
= aarch64_get_vec_u16 (cpu
, vd
, i
);
3837 aarch64_set_vec_u32 (cpu
, vd
, i
, v
+ (a
[i
] * b
[i
]));
3844 uint64_t a
[4], b
[4];
3846 for (i
= 0; i
< (full
? 4 : 2); i
++)
3848 a
[i
] = aarch64_get_vec_u32 (cpu
, vn
, i
);
3849 b
[i
] = aarch64_get_vec_u32 (cpu
, vm
, i
);
3852 for (i
= 0; i
< (full
? 4 : 2); i
++)
3854 uint64_t v
= aarch64_get_vec_u32 (cpu
, vd
, i
);
3856 aarch64_set_vec_u64 (cpu
, vd
, i
, v
+ (a
[i
] * b
[i
]));
3867 fmaxnm (float a
, float b
)
3872 return a
> b
? a
: b
;
3875 else if (! isnan (b
))
3881 fminnm (float a
, float b
)
3886 return a
< b
? a
: b
;
3889 else if (! isnan (b
))
3895 dmaxnm (double a
, double b
)
3900 return a
> b
? a
: b
;
3903 else if (! isnan (b
))
3909 dminnm (double a
, double b
)
3914 return a
< b
? a
: b
;
3917 else if (! isnan (b
))
3923 do_vec_FminmaxNMP (sim_cpu
*cpu
)
3926 instr [30] = half (0)/full (1)
3927 instr [29,24] = 10 1110
3928 instr [23] = max(0)/min(1)
3929 instr [22] = float (0)/double (1)
3932 instr [15,10] = 1100 01
3934 instr [4.0] = Vd. */
3936 unsigned vm
= INSTR (20, 16);
3937 unsigned vn
= INSTR (9, 5);
3938 unsigned vd
= INSTR (4, 0);
3939 int full
= INSTR (30, 30);
3941 NYI_assert (29, 24, 0x2E);
3942 NYI_assert (21, 21, 1);
3943 NYI_assert (15, 10, 0x31);
3945 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3948 double (* fn
)(double, double) = INSTR (23, 23)
3953 aarch64_set_vec_double (cpu
, vd
, 0,
3954 fn (aarch64_get_vec_double (cpu
, vn
, 0),
3955 aarch64_get_vec_double (cpu
, vn
, 1)));
3956 aarch64_set_vec_double (cpu
, vd
, 0,
3957 fn (aarch64_get_vec_double (cpu
, vm
, 0),
3958 aarch64_get_vec_double (cpu
, vm
, 1)));
3962 float (* fn
)(float, float) = INSTR (23, 23)
3965 aarch64_set_vec_float (cpu
, vd
, 0,
3966 fn (aarch64_get_vec_float (cpu
, vn
, 0),
3967 aarch64_get_vec_float (cpu
, vn
, 1)));
3969 aarch64_set_vec_float (cpu
, vd
, 1,
3970 fn (aarch64_get_vec_float (cpu
, vn
, 2),
3971 aarch64_get_vec_float (cpu
, vn
, 3)));
3973 aarch64_set_vec_float (cpu
, vd
, (full
? 2 : 1),
3974 fn (aarch64_get_vec_float (cpu
, vm
, 0),
3975 aarch64_get_vec_float (cpu
, vm
, 1)));
3977 aarch64_set_vec_float (cpu
, vd
, 3,
3978 fn (aarch64_get_vec_float (cpu
, vm
, 2),
3979 aarch64_get_vec_float (cpu
, vm
, 3)));
3984 do_vec_AND (sim_cpu
*cpu
)
3987 instr[30] = half (0)/full (1)
3988 instr[29,21] = 001110001
3990 instr[15,10] = 000111
3994 unsigned vm
= INSTR (20, 16);
3995 unsigned vn
= INSTR (9, 5);
3996 unsigned vd
= INSTR (4, 0);
3998 int full
= INSTR (30, 30);
4000 NYI_assert (29, 21, 0x071);
4001 NYI_assert (15, 10, 0x07);
4003 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4004 for (i
= 0; i
< (full
? 4 : 2); i
++)
4005 aarch64_set_vec_u32 (cpu
, vd
, i
,
4006 aarch64_get_vec_u32 (cpu
, vn
, i
)
4007 & aarch64_get_vec_u32 (cpu
, vm
, i
));
4011 do_vec_BSL (sim_cpu
*cpu
)
4014 instr[30] = half (0)/full (1)
4015 instr[29,21] = 101110011
4017 instr[15,10] = 000111
4021 unsigned vm
= INSTR (20, 16);
4022 unsigned vn
= INSTR (9, 5);
4023 unsigned vd
= INSTR (4, 0);
4025 int full
= INSTR (30, 30);
4027 NYI_assert (29, 21, 0x173);
4028 NYI_assert (15, 10, 0x07);
4030 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4031 for (i
= 0; i
< (full
? 16 : 8); i
++)
4032 aarch64_set_vec_u8 (cpu
, vd
, i
,
4033 ( aarch64_get_vec_u8 (cpu
, vd
, i
)
4034 & aarch64_get_vec_u8 (cpu
, vn
, i
))
4035 | ((~ aarch64_get_vec_u8 (cpu
, vd
, i
))
4036 & aarch64_get_vec_u8 (cpu
, vm
, i
)));
4040 do_vec_EOR (sim_cpu
*cpu
)
4043 instr[30] = half (0)/full (1)
4044 instr[29,21] = 10 1110 001
4046 instr[15,10] = 000111
4050 unsigned vm
= INSTR (20, 16);
4051 unsigned vn
= INSTR (9, 5);
4052 unsigned vd
= INSTR (4, 0);
4054 int full
= INSTR (30, 30);
4056 NYI_assert (29, 21, 0x171);
4057 NYI_assert (15, 10, 0x07);
4059 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4060 for (i
= 0; i
< (full
? 4 : 2); i
++)
4061 aarch64_set_vec_u32 (cpu
, vd
, i
,
4062 aarch64_get_vec_u32 (cpu
, vn
, i
)
4063 ^ aarch64_get_vec_u32 (cpu
, vm
, i
));
4067 do_vec_bit (sim_cpu
*cpu
)
4070 instr[30] = half (0)/full (1)
4071 instr[29,23] = 10 1110 1
4072 instr[22] = BIT (0) / BIF (1)
4075 instr[15,10] = 0001 11
4079 unsigned vm
= INSTR (20, 16);
4080 unsigned vn
= INSTR (9, 5);
4081 unsigned vd
= INSTR (4, 0);
4082 unsigned full
= INSTR (30, 30);
4083 unsigned test_false
= INSTR (22, 22);
4086 NYI_assert (29, 23, 0x5D);
4087 NYI_assert (21, 21, 1);
4088 NYI_assert (15, 10, 0x07);
4090 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4093 for (i
= 0; i
< (full
? 16 : 8); i
++)
4094 if (aarch64_get_vec_u32 (cpu
, vn
, i
) == 0)
4095 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vm
, i
));
4099 for (i
= 0; i
< (full
? 16 : 8); i
++)
4100 if (aarch64_get_vec_u32 (cpu
, vn
, i
) != 0)
4101 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vm
, i
));
4106 do_vec_ORN (sim_cpu
*cpu
)
4109 instr[30] = half (0)/full (1)
4110 instr[29,21] = 00 1110 111
4112 instr[15,10] = 00 0111
4116 unsigned vm
= INSTR (20, 16);
4117 unsigned vn
= INSTR (9, 5);
4118 unsigned vd
= INSTR (4, 0);
4120 int full
= INSTR (30, 30);
4122 NYI_assert (29, 21, 0x077);
4123 NYI_assert (15, 10, 0x07);
4125 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4126 for (i
= 0; i
< (full
? 16 : 8); i
++)
4127 aarch64_set_vec_u8 (cpu
, vd
, i
,
4128 aarch64_get_vec_u8 (cpu
, vn
, i
)
4129 | ~ aarch64_get_vec_u8 (cpu
, vm
, i
));
4133 do_vec_ORR (sim_cpu
*cpu
)
4136 instr[30] = half (0)/full (1)
4137 instr[29,21] = 00 1110 101
4139 instr[15,10] = 0001 11
4143 unsigned vm
= INSTR (20, 16);
4144 unsigned vn
= INSTR (9, 5);
4145 unsigned vd
= INSTR (4, 0);
4147 int full
= INSTR (30, 30);
4149 NYI_assert (29, 21, 0x075);
4150 NYI_assert (15, 10, 0x07);
4152 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4153 for (i
= 0; i
< (full
? 16 : 8); i
++)
4154 aarch64_set_vec_u8 (cpu
, vd
, i
,
4155 aarch64_get_vec_u8 (cpu
, vn
, i
)
4156 | aarch64_get_vec_u8 (cpu
, vm
, i
));
4160 do_vec_BIC (sim_cpu
*cpu
)
4163 instr[30] = half (0)/full (1)
4164 instr[29,21] = 00 1110 011
4166 instr[15,10] = 00 0111
4170 unsigned vm
= INSTR (20, 16);
4171 unsigned vn
= INSTR (9, 5);
4172 unsigned vd
= INSTR (4, 0);
4174 int full
= INSTR (30, 30);
4176 NYI_assert (29, 21, 0x073);
4177 NYI_assert (15, 10, 0x07);
4179 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4180 for (i
= 0; i
< (full
? 16 : 8); i
++)
4181 aarch64_set_vec_u8 (cpu
, vd
, i
,
4182 aarch64_get_vec_u8 (cpu
, vn
, i
)
4183 & ~ aarch64_get_vec_u8 (cpu
, vm
, i
));
4187 do_vec_XTN (sim_cpu
*cpu
)
4190 instr[30] = first part (0)/ second part (1)
4191 instr[29,24] = 00 1110
4192 instr[23,22] = size: byte(00), half(01), word (10)
4193 instr[21,10] = 1000 0100 1010
4197 unsigned vs
= INSTR (9, 5);
4198 unsigned vd
= INSTR (4, 0);
4199 unsigned bias
= INSTR (30, 30);
4202 NYI_assert (29, 24, 0x0E);
4203 NYI_assert (21, 10, 0x84A);
4205 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4206 switch (INSTR (23, 22))
4210 for (i
= 0; i
< 8; i
++)
4211 aarch64_set_vec_u8 (cpu
, vd
, i
+ 8,
4212 aarch64_get_vec_u16 (cpu
, vs
, i
) >> 8);
4214 for (i
= 0; i
< 8; i
++)
4215 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vs
, i
));
4220 for (i
= 0; i
< 4; i
++)
4221 aarch64_set_vec_u16 (cpu
, vd
, i
+ 4,
4222 aarch64_get_vec_u32 (cpu
, vs
, i
) >> 16);
4224 for (i
= 0; i
< 4; i
++)
4225 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vs
, i
));
4230 for (i
= 0; i
< 2; i
++)
4231 aarch64_set_vec_u32 (cpu
, vd
, i
+ 4,
4232 aarch64_get_vec_u64 (cpu
, vs
, i
) >> 32);
4234 for (i
= 0; i
< 2; i
++)
4235 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u64 (cpu
, vs
, i
));
4241 do_vec_maxv (sim_cpu
*cpu
)
4244 instr[30] = half(0)/full(1)
4245 instr[29] = signed (0)/unsigned(1)
4246 instr[28,24] = 0 1110
4247 instr[23,22] = size: byte(00), half(01), word (10)
4249 instr[20,17] = 1 000
4250 instr[16] = max(0)/min(1)
4251 instr[15,10] = 1010 10
4252 instr[9,5] = V source
4253 instr[4.0] = R dest. */
4255 unsigned vs
= INSTR (9, 5);
4256 unsigned rd
= INSTR (4, 0);
4257 unsigned full
= INSTR (30, 30);
4260 NYI_assert (28, 24, 0x0E);
4261 NYI_assert (21, 21, 1);
4262 NYI_assert (20, 17, 8);
4263 NYI_assert (15, 10, 0x2A);
4265 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4266 switch ((INSTR (29, 29) << 1) | INSTR (16, 16))
4268 case 0: /* SMAXV. */
4271 switch (INSTR (23, 22))
4274 smax
= aarch64_get_vec_s8 (cpu
, vs
, 0);
4275 for (i
= 1; i
< (full
? 16 : 8); i
++)
4276 smax
= max (smax
, aarch64_get_vec_s8 (cpu
, vs
, i
));
4279 smax
= aarch64_get_vec_s16 (cpu
, vs
, 0);
4280 for (i
= 1; i
< (full
? 8 : 4); i
++)
4281 smax
= max (smax
, aarch64_get_vec_s16 (cpu
, vs
, i
));
4284 smax
= aarch64_get_vec_s32 (cpu
, vs
, 0);
4285 for (i
= 1; i
< (full
? 4 : 2); i
++)
4286 smax
= max (smax
, aarch64_get_vec_s32 (cpu
, vs
, i
));
4291 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, smax
);
4295 case 1: /* SMINV. */
4298 switch (INSTR (23, 22))
4301 smin
= aarch64_get_vec_s8 (cpu
, vs
, 0);
4302 for (i
= 1; i
< (full
? 16 : 8); i
++)
4303 smin
= min (smin
, aarch64_get_vec_s8 (cpu
, vs
, i
));
4306 smin
= aarch64_get_vec_s16 (cpu
, vs
, 0);
4307 for (i
= 1; i
< (full
? 8 : 4); i
++)
4308 smin
= min (smin
, aarch64_get_vec_s16 (cpu
, vs
, i
));
4311 smin
= aarch64_get_vec_s32 (cpu
, vs
, 0);
4312 for (i
= 1; i
< (full
? 4 : 2); i
++)
4313 smin
= min (smin
, aarch64_get_vec_s32 (cpu
, vs
, i
));
4319 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, smin
);
4323 case 2: /* UMAXV. */
4326 switch (INSTR (23, 22))
4329 umax
= aarch64_get_vec_u8 (cpu
, vs
, 0);
4330 for (i
= 1; i
< (full
? 16 : 8); i
++)
4331 umax
= max (umax
, aarch64_get_vec_u8 (cpu
, vs
, i
));
4334 umax
= aarch64_get_vec_u16 (cpu
, vs
, 0);
4335 for (i
= 1; i
< (full
? 8 : 4); i
++)
4336 umax
= max (umax
, aarch64_get_vec_u16 (cpu
, vs
, i
));
4339 umax
= aarch64_get_vec_u32 (cpu
, vs
, 0);
4340 for (i
= 1; i
< (full
? 4 : 2); i
++)
4341 umax
= max (umax
, aarch64_get_vec_u32 (cpu
, vs
, i
));
4347 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, umax
);
4351 case 3: /* UMINV. */
4354 switch (INSTR (23, 22))
4357 umin
= aarch64_get_vec_u8 (cpu
, vs
, 0);
4358 for (i
= 1; i
< (full
? 16 : 8); i
++)
4359 umin
= min (umin
, aarch64_get_vec_u8 (cpu
, vs
, i
));
4362 umin
= aarch64_get_vec_u16 (cpu
, vs
, 0);
4363 for (i
= 1; i
< (full
? 8 : 4); i
++)
4364 umin
= min (umin
, aarch64_get_vec_u16 (cpu
, vs
, i
));
4367 umin
= aarch64_get_vec_u32 (cpu
, vs
, 0);
4368 for (i
= 1; i
< (full
? 4 : 2); i
++)
4369 umin
= min (umin
, aarch64_get_vec_u32 (cpu
, vs
, i
));
4375 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, umin
);
4382 do_vec_fminmaxV (sim_cpu
*cpu
)
4384 /* instr[31,24] = 0110 1110
4385 instr[23] = max(0)/min(1)
4386 instr[22,14] = 011 0000 11
4387 instr[13,12] = nm(00)/normal(11)
4389 instr[9,5] = V source
4390 instr[4.0] = R dest. */
4392 unsigned vs
= INSTR (9, 5);
4393 unsigned rd
= INSTR (4, 0);
4395 float res
= aarch64_get_vec_float (cpu
, vs
, 0);
4397 NYI_assert (31, 24, 0x6E);
4398 NYI_assert (22, 14, 0x0C3);
4399 NYI_assert (11, 10, 2);
4401 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4404 switch (INSTR (13, 12))
4406 case 0: /* FMNINNMV. */
4407 for (i
= 1; i
< 4; i
++)
4408 res
= fminnm (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4411 case 3: /* FMINV. */
4412 for (i
= 1; i
< 4; i
++)
4413 res
= min (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4422 switch (INSTR (13, 12))
4424 case 0: /* FMNAXNMV. */
4425 for (i
= 1; i
< 4; i
++)
4426 res
= fmaxnm (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4429 case 3: /* FMAXV. */
4430 for (i
= 1; i
< 4; i
++)
4431 res
= max (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4439 aarch64_set_FP_float (cpu
, rd
, res
);
4443 do_vec_Fminmax (sim_cpu
*cpu
)
4446 instr[30] = half(0)/full(1)
4447 instr[29,24] = 00 1110
4448 instr[23] = max(0)/min(1)
4449 instr[22] = float(0)/double(1)
4453 instr[13,12] = nm(00)/normal(11)
4458 unsigned vm
= INSTR (20, 16);
4459 unsigned vn
= INSTR (9, 5);
4460 unsigned vd
= INSTR (4, 0);
4461 unsigned full
= INSTR (30, 30);
4462 unsigned min
= INSTR (23, 23);
4465 NYI_assert (29, 24, 0x0E);
4466 NYI_assert (21, 21, 1);
4467 NYI_assert (15, 14, 3);
4468 NYI_assert (11, 10, 1);
4470 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4473 double (* func
)(double, double);
4478 if (INSTR (13, 12) == 0)
4479 func
= min
? dminnm
: dmaxnm
;
4480 else if (INSTR (13, 12) == 3)
4481 func
= min
? fmin
: fmax
;
4485 for (i
= 0; i
< 2; i
++)
4486 aarch64_set_vec_double (cpu
, vd
, i
,
4487 func (aarch64_get_vec_double (cpu
, vn
, i
),
4488 aarch64_get_vec_double (cpu
, vm
, i
)));
4492 float (* func
)(float, float);
4494 if (INSTR (13, 12) == 0)
4495 func
= min
? fminnm
: fmaxnm
;
4496 else if (INSTR (13, 12) == 3)
4497 func
= min
? fminf
: fmaxf
;
4501 for (i
= 0; i
< (full
? 4 : 2); i
++)
4502 aarch64_set_vec_float (cpu
, vd
, i
,
4503 func (aarch64_get_vec_float (cpu
, vn
, i
),
4504 aarch64_get_vec_float (cpu
, vm
, i
)));
4509 do_vec_SCVTF (sim_cpu
*cpu
)
4513 instr[29,23] = 00 1110 0
4514 instr[22] = float(0)/double(1)
4515 instr[21,10] = 10 0001 1101 10
4519 unsigned vn
= INSTR (9, 5);
4520 unsigned vd
= INSTR (4, 0);
4521 unsigned full
= INSTR (30, 30);
4522 unsigned size
= INSTR (22, 22);
4525 NYI_assert (29, 23, 0x1C);
4526 NYI_assert (21, 10, 0x876);
4528 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4534 for (i
= 0; i
< 2; i
++)
4536 double val
= (double) aarch64_get_vec_u64 (cpu
, vn
, i
);
4537 aarch64_set_vec_double (cpu
, vd
, i
, val
);
4542 for (i
= 0; i
< (full
? 4 : 2); i
++)
4544 float val
= (float) aarch64_get_vec_u32 (cpu
, vn
, i
);
4545 aarch64_set_vec_float (cpu
, vd
, i
, val
);
4550 #define VEC_CMP(SOURCE, CMP) \
4556 for (i = 0; i < (full ? 16 : 8); i++) \
4557 aarch64_set_vec_u8 (cpu, vd, i, \
4558 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4560 aarch64_get_vec_##SOURCE##8 (cpu, vm, i) \
4564 for (i = 0; i < (full ? 8 : 4); i++) \
4565 aarch64_set_vec_u16 (cpu, vd, i, \
4566 aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4568 aarch64_get_vec_##SOURCE##16 (cpu, vm, i) \
4572 for (i = 0; i < (full ? 4 : 2); i++) \
4573 aarch64_set_vec_u32 (cpu, vd, i, \
4574 aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4576 aarch64_get_vec_##SOURCE##32 (cpu, vm, i) \
4582 for (i = 0; i < 2; i++) \
4583 aarch64_set_vec_u64 (cpu, vd, i, \
4584 aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4586 aarch64_get_vec_##SOURCE##64 (cpu, vm, i) \
4593 #define VEC_CMP0(SOURCE, CMP) \
4599 for (i = 0; i < (full ? 16 : 8); i++) \
4600 aarch64_set_vec_u8 (cpu, vd, i, \
4601 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4605 for (i = 0; i < (full ? 8 : 4); i++) \
4606 aarch64_set_vec_u16 (cpu, vd, i, \
4607 aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4611 for (i = 0; i < (full ? 4 : 2); i++) \
4612 aarch64_set_vec_u32 (cpu, vd, i, \
4613 aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4619 for (i = 0; i < 2; i++) \
4620 aarch64_set_vec_u64 (cpu, vd, i, \
4621 aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4622 CMP 0 ? -1ULL : 0); \
4628 #define VEC_FCMP0(CMP) \
4633 if (INSTR (22, 22)) \
4637 for (i = 0; i < 2; i++) \
4638 aarch64_set_vec_u64 (cpu, vd, i, \
4639 aarch64_get_vec_double (cpu, vn, i) \
4640 CMP 0.0 ? -1 : 0); \
4644 for (i = 0; i < (full ? 4 : 2); i++) \
4645 aarch64_set_vec_u32 (cpu, vd, i, \
4646 aarch64_get_vec_float (cpu, vn, i) \
4647 CMP 0.0 ? -1 : 0); \
4653 #define VEC_FCMP(CMP) \
4656 if (INSTR (22, 22)) \
4660 for (i = 0; i < 2; i++) \
4661 aarch64_set_vec_u64 (cpu, vd, i, \
4662 aarch64_get_vec_double (cpu, vn, i) \
4664 aarch64_get_vec_double (cpu, vm, i) \
4669 for (i = 0; i < (full ? 4 : 2); i++) \
4670 aarch64_set_vec_u32 (cpu, vd, i, \
4671 aarch64_get_vec_float (cpu, vn, i) \
4673 aarch64_get_vec_float (cpu, vm, i) \
4681 do_vec_compare (sim_cpu
*cpu
)
4684 instr[30] = half(0)/full(1)
4685 instr[29] = part-of-comparison-type
4686 instr[28,24] = 0 1110
4687 instr[23,22] = size of integer compares: byte(00), half(01), word (10), long (11)
4688 type of float compares: single (-0) / double (-1)
4690 instr[20,16] = Vm or 00000 (compare vs 0)
4691 instr[15,10] = part-of-comparison-type
4695 int full
= INSTR (30, 30);
4696 int size
= INSTR (23, 22);
4697 unsigned vm
= INSTR (20, 16);
4698 unsigned vn
= INSTR (9, 5);
4699 unsigned vd
= INSTR (4, 0);
4702 NYI_assert (28, 24, 0x0E);
4703 NYI_assert (21, 21, 1);
4705 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4708 || ((INSTR (11, 11) == 0
4709 && INSTR (10, 10) == 0)))
4711 /* A compare vs 0. */
4714 if (INSTR (15, 10) == 0x2A)
4716 else if (INSTR (15, 10) == 0x32
4717 || INSTR (15, 10) == 0x3E)
4718 do_vec_fminmaxV (cpu
);
4719 else if (INSTR (29, 23) == 0x1C
4720 && INSTR (21, 10) == 0x876)
4730 /* A floating point compare. */
4731 unsigned decode
= (INSTR (29, 29) << 5) | (INSTR (23, 23) << 4)
4734 NYI_assert (15, 15, 1);
4738 case /* 0b010010: GT#0 */ 0x12: VEC_FCMP0 (>);
4739 case /* 0b110010: GE#0 */ 0x32: VEC_FCMP0 (>=);
4740 case /* 0b010110: EQ#0 */ 0x16: VEC_FCMP0 (==);
4741 case /* 0b110110: LE#0 */ 0x36: VEC_FCMP0 (<=);
4742 case /* 0b011010: LT#0 */ 0x1A: VEC_FCMP0 (<);
4743 case /* 0b111001: GT */ 0x39: VEC_FCMP (>);
4744 case /* 0b101001: GE */ 0x29: VEC_FCMP (>=);
4745 case /* 0b001001: EQ */ 0x09: VEC_FCMP (==);
4753 unsigned decode
= (INSTR (29, 29) << 6) | INSTR (15, 10);
4757 case 0x0D: /* 0001101 GT */ VEC_CMP (s
, > );
4758 case 0x0F: /* 0001111 GE */ VEC_CMP (s
, >= );
4759 case 0x22: /* 0100010 GT #0 */ VEC_CMP0 (s
, > );
4760 case 0x26: /* 0100110 EQ #0 */ VEC_CMP0 (s
, == );
4761 case 0x2A: /* 0101010 LT #0 */ VEC_CMP0 (s
, < );
4762 case 0x4D: /* 1001101 HI */ VEC_CMP (u
, > );
4763 case 0x4F: /* 1001111 HS */ VEC_CMP (u
, >= );
4764 case 0x62: /* 1100010 GE #0 */ VEC_CMP0 (s
, >= );
4765 case 0x63: /* 1100011 EQ */ VEC_CMP (u
, == );
4766 case 0x66: /* 1100110 LE #0 */ VEC_CMP0 (s
, <= );
4776 do_vec_SSHL (sim_cpu
*cpu
)
4779 instr[30] = first part (0)/ second part (1)
4780 instr[29,24] = 00 1110
4781 instr[23,22] = size: byte(00), half(01), word (10), long (11)
4784 instr[15,10] = 0100 01
4788 unsigned full
= INSTR (30, 30);
4789 unsigned vm
= INSTR (20, 16);
4790 unsigned vn
= INSTR (9, 5);
4791 unsigned vd
= INSTR (4, 0);
4795 NYI_assert (29, 24, 0x0E);
4796 NYI_assert (21, 21, 1);
4797 NYI_assert (15, 10, 0x11);
4799 /* FIXME: What is a signed shift left in this context ?. */
4801 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4802 switch (INSTR (23, 22))
4805 for (i
= 0; i
< (full
? 16 : 8); i
++)
4807 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
);
4809 aarch64_set_vec_s8 (cpu
, vd
, i
, aarch64_get_vec_s8 (cpu
, vn
, i
)
4812 aarch64_set_vec_s8 (cpu
, vd
, i
, aarch64_get_vec_s8 (cpu
, vn
, i
)
4818 for (i
= 0; i
< (full
? 8 : 4); i
++)
4820 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 2);
4822 aarch64_set_vec_s16 (cpu
, vd
, i
, aarch64_get_vec_s16 (cpu
, vn
, i
)
4825 aarch64_set_vec_s16 (cpu
, vd
, i
, aarch64_get_vec_s16 (cpu
, vn
, i
)
4831 for (i
= 0; i
< (full
? 4 : 2); i
++)
4833 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 4);
4835 aarch64_set_vec_s32 (cpu
, vd
, i
, aarch64_get_vec_s32 (cpu
, vn
, i
)
4838 aarch64_set_vec_s32 (cpu
, vd
, i
, aarch64_get_vec_s32 (cpu
, vn
, i
)
4846 for (i
= 0; i
< 2; i
++)
4848 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 8);
4850 aarch64_set_vec_s64 (cpu
, vd
, i
, aarch64_get_vec_s64 (cpu
, vn
, i
)
4853 aarch64_set_vec_s64 (cpu
, vd
, i
, aarch64_get_vec_s64 (cpu
, vn
, i
)
4861 do_vec_USHL (sim_cpu
*cpu
)
4864 instr[30] = first part (0)/ second part (1)
4865 instr[29,24] = 10 1110
4866 instr[23,22] = size: byte(00), half(01), word (10), long (11)
4869 instr[15,10] = 0100 01
4873 unsigned full
= INSTR (30, 30);
4874 unsigned vm
= INSTR (20, 16);
4875 unsigned vn
= INSTR (9, 5);
4876 unsigned vd
= INSTR (4, 0);
4880 NYI_assert (29, 24, 0x2E);
4881 NYI_assert (15, 10, 0x11);
4883 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4884 switch (INSTR (23, 22))
4887 for (i
= 0; i
< (full
? 16 : 8); i
++)
4889 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
);
4891 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vn
, i
)
4894 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vn
, i
)
4900 for (i
= 0; i
< (full
? 8 : 4); i
++)
4902 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 2);
4904 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vn
, i
)
4907 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vn
, i
)
4913 for (i
= 0; i
< (full
? 4 : 2); i
++)
4915 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 4);
4917 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vn
, i
)
4920 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vn
, i
)
4928 for (i
= 0; i
< 2; i
++)
4930 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 8);
4932 aarch64_set_vec_u64 (cpu
, vd
, i
, aarch64_get_vec_u64 (cpu
, vn
, i
)
4935 aarch64_set_vec_u64 (cpu
, vd
, i
, aarch64_get_vec_u64 (cpu
, vn
, i
)
4943 do_vec_FMLA (sim_cpu
*cpu
)
4946 instr[30] = full/half selector
4947 instr[29,23] = 0011100
4948 instr[22] = size: 0=>float, 1=>double
4951 instr[15,10] = 1100 11
4955 unsigned vm
= INSTR (20, 16);
4956 unsigned vn
= INSTR (9, 5);
4957 unsigned vd
= INSTR (4, 0);
4959 int full
= INSTR (30, 30);
4961 NYI_assert (29, 23, 0x1C);
4962 NYI_assert (21, 21, 1);
4963 NYI_assert (15, 10, 0x33);
4965 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4970 for (i
= 0; i
< 2; i
++)
4971 aarch64_set_vec_double (cpu
, vd
, i
,
4972 aarch64_get_vec_double (cpu
, vn
, i
) *
4973 aarch64_get_vec_double (cpu
, vm
, i
) +
4974 aarch64_get_vec_double (cpu
, vd
, i
));
4978 for (i
= 0; i
< (full
? 4 : 2); i
++)
4979 aarch64_set_vec_float (cpu
, vd
, i
,
4980 aarch64_get_vec_float (cpu
, vn
, i
) *
4981 aarch64_get_vec_float (cpu
, vm
, i
) +
4982 aarch64_get_vec_float (cpu
, vd
, i
));
4987 do_vec_max (sim_cpu
*cpu
)
4990 instr[30] = full/half selector
4991 instr[29] = SMAX (0) / UMAX (1)
4992 instr[28,24] = 0 1110
4993 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
4996 instr[15,10] = 0110 01
5000 unsigned vm
= INSTR (20, 16);
5001 unsigned vn
= INSTR (9, 5);
5002 unsigned vd
= INSTR (4, 0);
5004 int full
= INSTR (30, 30);
5006 NYI_assert (28, 24, 0x0E);
5007 NYI_assert (21, 21, 1);
5008 NYI_assert (15, 10, 0x19);
5010 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5013 switch (INSTR (23, 22))
5016 for (i
= 0; i
< (full
? 16 : 8); i
++)
5017 aarch64_set_vec_u8 (cpu
, vd
, i
,
5018 aarch64_get_vec_u8 (cpu
, vn
, i
)
5019 > aarch64_get_vec_u8 (cpu
, vm
, i
)
5020 ? aarch64_get_vec_u8 (cpu
, vn
, i
)
5021 : aarch64_get_vec_u8 (cpu
, vm
, i
));
5025 for (i
= 0; i
< (full
? 8 : 4); i
++)
5026 aarch64_set_vec_u16 (cpu
, vd
, i
,
5027 aarch64_get_vec_u16 (cpu
, vn
, i
)
5028 > aarch64_get_vec_u16 (cpu
, vm
, i
)
5029 ? aarch64_get_vec_u16 (cpu
, vn
, i
)
5030 : aarch64_get_vec_u16 (cpu
, vm
, i
));
5034 for (i
= 0; i
< (full
? 4 : 2); i
++)
5035 aarch64_set_vec_u32 (cpu
, vd
, i
,
5036 aarch64_get_vec_u32 (cpu
, vn
, i
)
5037 > aarch64_get_vec_u32 (cpu
, vm
, i
)
5038 ? aarch64_get_vec_u32 (cpu
, vn
, i
)
5039 : aarch64_get_vec_u32 (cpu
, vm
, i
));
5048 switch (INSTR (23, 22))
5051 for (i
= 0; i
< (full
? 16 : 8); i
++)
5052 aarch64_set_vec_s8 (cpu
, vd
, i
,
5053 aarch64_get_vec_s8 (cpu
, vn
, i
)
5054 > aarch64_get_vec_s8 (cpu
, vm
, i
)
5055 ? aarch64_get_vec_s8 (cpu
, vn
, i
)
5056 : aarch64_get_vec_s8 (cpu
, vm
, i
));
5060 for (i
= 0; i
< (full
? 8 : 4); i
++)
5061 aarch64_set_vec_s16 (cpu
, vd
, i
,
5062 aarch64_get_vec_s16 (cpu
, vn
, i
)
5063 > aarch64_get_vec_s16 (cpu
, vm
, i
)
5064 ? aarch64_get_vec_s16 (cpu
, vn
, i
)
5065 : aarch64_get_vec_s16 (cpu
, vm
, i
));
5069 for (i
= 0; i
< (full
? 4 : 2); i
++)
5070 aarch64_set_vec_s32 (cpu
, vd
, i
,
5071 aarch64_get_vec_s32 (cpu
, vn
, i
)
5072 > aarch64_get_vec_s32 (cpu
, vm
, i
)
5073 ? aarch64_get_vec_s32 (cpu
, vn
, i
)
5074 : aarch64_get_vec_s32 (cpu
, vm
, i
));
5084 do_vec_min (sim_cpu
*cpu
)
5087 instr[30] = full/half selector
5088 instr[29] = SMIN (0) / UMIN (1)
5089 instr[28,24] = 0 1110
5090 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
5093 instr[15,10] = 0110 11
5097 unsigned vm
= INSTR (20, 16);
5098 unsigned vn
= INSTR (9, 5);
5099 unsigned vd
= INSTR (4, 0);
5101 int full
= INSTR (30, 30);
5103 NYI_assert (28, 24, 0x0E);
5104 NYI_assert (21, 21, 1);
5105 NYI_assert (15, 10, 0x1B);
5107 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5110 switch (INSTR (23, 22))
5113 for (i
= 0; i
< (full
? 16 : 8); i
++)
5114 aarch64_set_vec_u8 (cpu
, vd
, i
,
5115 aarch64_get_vec_u8 (cpu
, vn
, i
)
5116 < aarch64_get_vec_u8 (cpu
, vm
, i
)
5117 ? aarch64_get_vec_u8 (cpu
, vn
, i
)
5118 : aarch64_get_vec_u8 (cpu
, vm
, i
));
5122 for (i
= 0; i
< (full
? 8 : 4); i
++)
5123 aarch64_set_vec_u16 (cpu
, vd
, i
,
5124 aarch64_get_vec_u16 (cpu
, vn
, i
)
5125 < aarch64_get_vec_u16 (cpu
, vm
, i
)
5126 ? aarch64_get_vec_u16 (cpu
, vn
, i
)
5127 : aarch64_get_vec_u16 (cpu
, vm
, i
));
5131 for (i
= 0; i
< (full
? 4 : 2); i
++)
5132 aarch64_set_vec_u32 (cpu
, vd
, i
,
5133 aarch64_get_vec_u32 (cpu
, vn
, i
)
5134 < aarch64_get_vec_u32 (cpu
, vm
, i
)
5135 ? aarch64_get_vec_u32 (cpu
, vn
, i
)
5136 : aarch64_get_vec_u32 (cpu
, vm
, i
));
5145 switch (INSTR (23, 22))
5148 for (i
= 0; i
< (full
? 16 : 8); i
++)
5149 aarch64_set_vec_s8 (cpu
, vd
, i
,
5150 aarch64_get_vec_s8 (cpu
, vn
, i
)
5151 < aarch64_get_vec_s8 (cpu
, vm
, i
)
5152 ? aarch64_get_vec_s8 (cpu
, vn
, i
)
5153 : aarch64_get_vec_s8 (cpu
, vm
, i
));
5157 for (i
= 0; i
< (full
? 8 : 4); i
++)
5158 aarch64_set_vec_s16 (cpu
, vd
, i
,
5159 aarch64_get_vec_s16 (cpu
, vn
, i
)
5160 < aarch64_get_vec_s16 (cpu
, vm
, i
)
5161 ? aarch64_get_vec_s16 (cpu
, vn
, i
)
5162 : aarch64_get_vec_s16 (cpu
, vm
, i
));
5166 for (i
= 0; i
< (full
? 4 : 2); i
++)
5167 aarch64_set_vec_s32 (cpu
, vd
, i
,
5168 aarch64_get_vec_s32 (cpu
, vn
, i
)
5169 < aarch64_get_vec_s32 (cpu
, vm
, i
)
5170 ? aarch64_get_vec_s32 (cpu
, vn
, i
)
5171 : aarch64_get_vec_s32 (cpu
, vm
, i
));
5181 do_vec_sub_long (sim_cpu
*cpu
)
5184 instr[30] = lower (0) / upper (1)
5185 instr[29] = signed (0) / unsigned (1)
5186 instr[28,24] = 0 1110
5187 instr[23,22] = size: bytes (00), half (01), word (10)
5190 instr[15,10] = 0010 00
5192 instr[4,0] = V dest. */
5194 unsigned size
= INSTR (23, 22);
5195 unsigned vm
= INSTR (20, 16);
5196 unsigned vn
= INSTR (9, 5);
5197 unsigned vd
= INSTR (4, 0);
5201 NYI_assert (28, 24, 0x0E);
5202 NYI_assert (21, 21, 1);
5203 NYI_assert (15, 10, 0x08);
5208 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5209 switch (INSTR (30, 29))
5211 case 2: /* SSUBL2. */
5213 case 0: /* SSUBL. */
5218 for (i
= 0; i
< 8; i
++)
5219 aarch64_set_vec_s16 (cpu
, vd
, i
,
5220 aarch64_get_vec_s8 (cpu
, vn
, i
+ bias
)
5221 - aarch64_get_vec_s8 (cpu
, vm
, i
+ bias
));
5226 for (i
= 0; i
< 4; i
++)
5227 aarch64_set_vec_s32 (cpu
, vd
, i
,
5228 aarch64_get_vec_s16 (cpu
, vn
, i
+ bias
)
5229 - aarch64_get_vec_s16 (cpu
, vm
, i
+ bias
));
5233 for (i
= 0; i
< 2; i
++)
5234 aarch64_set_vec_s64 (cpu
, vd
, i
,
5235 aarch64_get_vec_s32 (cpu
, vn
, i
+ bias
)
5236 - aarch64_get_vec_s32 (cpu
, vm
, i
+ bias
));
5244 case 3: /* USUBL2. */
5246 case 1: /* USUBL. */
5251 for (i
= 0; i
< 8; i
++)
5252 aarch64_set_vec_u16 (cpu
, vd
, i
,
5253 aarch64_get_vec_u8 (cpu
, vn
, i
+ bias
)
5254 - aarch64_get_vec_u8 (cpu
, vm
, i
+ bias
));
5259 for (i
= 0; i
< 4; i
++)
5260 aarch64_set_vec_u32 (cpu
, vd
, i
,
5261 aarch64_get_vec_u16 (cpu
, vn
, i
+ bias
)
5262 - aarch64_get_vec_u16 (cpu
, vm
, i
+ bias
));
5266 for (i
= 0; i
< 2; i
++)
5267 aarch64_set_vec_u64 (cpu
, vd
, i
,
5268 aarch64_get_vec_u32 (cpu
, vn
, i
+ bias
)
5269 - aarch64_get_vec_u32 (cpu
, vm
, i
+ bias
));
5280 do_vec_ADDP (sim_cpu
*cpu
)
5283 instr[30] = half(0)/full(1)
5284 instr[29,24] = 00 1110
5285 instr[23,22] = size: bytes (00), half (01), word (10), long (11)
5288 instr[15,10] = 1011 11
5290 instr[4,0] = V dest. */
5294 unsigned full
= INSTR (30, 30);
5295 unsigned size
= INSTR (23, 22);
5296 unsigned vm
= INSTR (20, 16);
5297 unsigned vn
= INSTR (9, 5);
5298 unsigned vd
= INSTR (4, 0);
5301 NYI_assert (29, 24, 0x0E);
5302 NYI_assert (21, 21, 1);
5303 NYI_assert (15, 10, 0x2F);
5305 /* Make copies of the source registers in case vd == vn/vm. */
5306 copy_vn
= cpu
->fr
[vn
];
5307 copy_vm
= cpu
->fr
[vm
];
5309 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5313 range
= full
? 8 : 4;
5314 for (i
= 0; i
< range
; i
++)
5316 aarch64_set_vec_u8 (cpu
, vd
, i
,
5317 copy_vn
.b
[i
* 2] + copy_vn
.b
[i
* 2 + 1]);
5318 aarch64_set_vec_u8 (cpu
, vd
, i
+ range
,
5319 copy_vm
.b
[i
* 2] + copy_vm
.b
[i
* 2 + 1]);
5324 range
= full
? 4 : 2;
5325 for (i
= 0; i
< range
; i
++)
5327 aarch64_set_vec_u16 (cpu
, vd
, i
,
5328 copy_vn
.h
[i
* 2] + copy_vn
.h
[i
* 2 + 1]);
5329 aarch64_set_vec_u16 (cpu
, vd
, i
+ range
,
5330 copy_vm
.h
[i
* 2] + copy_vm
.h
[i
* 2 + 1]);
5335 range
= full
? 2 : 1;
5336 for (i
= 0; i
< range
; i
++)
5338 aarch64_set_vec_u32 (cpu
, vd
, i
,
5339 copy_vn
.w
[i
* 2] + copy_vn
.w
[i
* 2 + 1]);
5340 aarch64_set_vec_u32 (cpu
, vd
, i
+ range
,
5341 copy_vm
.w
[i
* 2] + copy_vm
.w
[i
* 2 + 1]);
5348 aarch64_set_vec_u64 (cpu
, vd
, 0, copy_vn
.v
[0] + copy_vn
.v
[1]);
5349 aarch64_set_vec_u64 (cpu
, vd
, 1, copy_vm
.v
[0] + copy_vm
.v
[1]);
5355 do_vec_UMOV (sim_cpu
*cpu
)
5358 instr[30] = 32-bit(0)/64-bit(1)
5359 instr[29,21] = 00 1110 000
5360 insrt[20,16] = size & index
5361 instr[15,10] = 0011 11
5362 instr[9,5] = V source
5363 instr[4,0] = R dest. */
5365 unsigned vs
= INSTR (9, 5);
5366 unsigned rd
= INSTR (4, 0);
5369 NYI_assert (29, 21, 0x070);
5370 NYI_assert (15, 10, 0x0F);
5372 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5375 /* Byte transfer. */
5376 index
= INSTR (20, 17);
5377 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
5378 aarch64_get_vec_u8 (cpu
, vs
, index
));
5380 else if (INSTR (17, 17))
5382 index
= INSTR (20, 18);
5383 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
5384 aarch64_get_vec_u16 (cpu
, vs
, index
));
5386 else if (INSTR (18, 18))
5388 index
= INSTR (20, 19);
5389 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
5390 aarch64_get_vec_u32 (cpu
, vs
, index
));
5394 if (INSTR (30, 30) != 1)
5397 index
= INSTR (20, 20);
5398 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
5399 aarch64_get_vec_u64 (cpu
, vs
, index
));
5404 do_vec_FABS (sim_cpu
*cpu
)
5407 instr[30] = half(0)/full(1)
5408 instr[29,23] = 00 1110 1
5409 instr[22] = float(0)/double(1)
5410 instr[21,16] = 10 0000
5411 instr[15,10] = 1111 10
5415 unsigned vn
= INSTR (9, 5);
5416 unsigned vd
= INSTR (4, 0);
5417 unsigned full
= INSTR (30, 30);
5420 NYI_assert (29, 23, 0x1D);
5421 NYI_assert (21, 10, 0x83E);
5423 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5429 for (i
= 0; i
< 2; i
++)
5430 aarch64_set_vec_double (cpu
, vd
, i
,
5431 fabs (aarch64_get_vec_double (cpu
, vn
, i
)));
5435 for (i
= 0; i
< (full
? 4 : 2); i
++)
5436 aarch64_set_vec_float (cpu
, vd
, i
,
5437 fabsf (aarch64_get_vec_float (cpu
, vn
, i
)));
5442 do_vec_FCVTZS (sim_cpu
*cpu
)
5445 instr[30] = half (0) / all (1)
5446 instr[29,23] = 00 1110 1
5447 instr[22] = single (0) / double (1)
5448 instr[21,10] = 10 0001 1011 10
5452 unsigned rn
= INSTR (9, 5);
5453 unsigned rd
= INSTR (4, 0);
5454 unsigned full
= INSTR (30, 30);
5457 NYI_assert (31, 31, 0);
5458 NYI_assert (29, 23, 0x1D);
5459 NYI_assert (21, 10, 0x86E);
5461 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5467 for (i
= 0; i
< 2; i
++)
5468 aarch64_set_vec_s64 (cpu
, rd
, i
,
5469 (int64_t) aarch64_get_vec_double (cpu
, rn
, i
));
5472 for (i
= 0; i
< (full
? 4 : 2); i
++)
5473 aarch64_set_vec_s32 (cpu
, rd
, i
,
5474 (int32_t) aarch64_get_vec_float (cpu
, rn
, i
));
5478 do_vec_REV64 (sim_cpu
*cpu
)
5481 instr[30] = full/half
5482 instr[29,24] = 00 1110
5484 instr[21,10] = 10 0000 0000 10
5488 unsigned rn
= INSTR (9, 5);
5489 unsigned rd
= INSTR (4, 0);
5490 unsigned size
= INSTR (23, 22);
5491 unsigned full
= INSTR (30, 30);
5495 NYI_assert (29, 24, 0x0E);
5496 NYI_assert (21, 10, 0x802);
5498 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5502 for (i
= 0; i
< (full
? 16 : 8); i
++)
5503 val
.b
[i
^ 0x7] = aarch64_get_vec_u8 (cpu
, rn
, i
);
5507 for (i
= 0; i
< (full
? 8 : 4); i
++)
5508 val
.h
[i
^ 0x3] = aarch64_get_vec_u16 (cpu
, rn
, i
);
5512 for (i
= 0; i
< (full
? 4 : 2); i
++)
5513 val
.w
[i
^ 0x1] = aarch64_get_vec_u32 (cpu
, rn
, i
);
5520 aarch64_set_vec_u64 (cpu
, rd
, 0, val
.v
[0]);
5522 aarch64_set_vec_u64 (cpu
, rd
, 1, val
.v
[1]);
5526 do_vec_REV16 (sim_cpu
*cpu
)
5529 instr[30] = full/half
5530 instr[29,24] = 00 1110
5532 instr[21,10] = 10 0000 0001 10
5536 unsigned rn
= INSTR (9, 5);
5537 unsigned rd
= INSTR (4, 0);
5538 unsigned size
= INSTR (23, 22);
5539 unsigned full
= INSTR (30, 30);
5543 NYI_assert (29, 24, 0x0E);
5544 NYI_assert (21, 10, 0x806);
5546 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5550 for (i
= 0; i
< (full
? 16 : 8); i
++)
5551 val
.b
[i
^ 0x1] = aarch64_get_vec_u8 (cpu
, rn
, i
);
5558 aarch64_set_vec_u64 (cpu
, rd
, 0, val
.v
[0]);
5560 aarch64_set_vec_u64 (cpu
, rd
, 1, val
.v
[1]);
5564 do_vec_op1 (sim_cpu
*cpu
)
5567 instr[30] = half/full
5568 instr[29,24] = 00 1110
5571 instr[15,10] = sub-opcode
5574 NYI_assert (29, 24, 0x0E);
5576 if (INSTR (21, 21) == 0)
5578 if (INSTR (23, 22) == 0)
5580 if (INSTR (30, 30) == 1
5581 && INSTR (17, 14) == 0
5582 && INSTR (12, 10) == 7)
5583 return do_vec_ins_2 (cpu
);
5585 switch (INSTR (15, 10))
5587 case 0x01: do_vec_DUP_vector_into_vector (cpu
); return;
5588 case 0x03: do_vec_DUP_scalar_into_vector (cpu
); return;
5589 case 0x07: do_vec_INS (cpu
); return;
5590 case 0x0A: do_vec_TRN (cpu
); return;
5593 if (INSTR (17, 16) == 0)
5595 do_vec_MOV_into_scalar (cpu
);
5604 do_vec_TBL (cpu
); return;
5608 do_vec_UZP (cpu
); return;
5612 do_vec_ZIP (cpu
); return;
5619 switch (INSTR (13, 10))
5621 case 0x6: do_vec_UZP (cpu
); return;
5622 case 0xE: do_vec_ZIP (cpu
); return;
5623 case 0xA: do_vec_TRN (cpu
); return;
5624 case 0xF: do_vec_UMOV (cpu
); return;
5629 switch (INSTR (15, 10))
5631 case 0x02: do_vec_REV64 (cpu
); return;
5632 case 0x06: do_vec_REV16 (cpu
); return;
5635 switch (INSTR (23, 21))
5637 case 1: do_vec_AND (cpu
); return;
5638 case 3: do_vec_BIC (cpu
); return;
5639 case 5: do_vec_ORR (cpu
); return;
5640 case 7: do_vec_ORN (cpu
); return;
5644 case 0x08: do_vec_sub_long (cpu
); return;
5645 case 0x0a: do_vec_XTN (cpu
); return;
5646 case 0x11: do_vec_SSHL (cpu
); return;
5647 case 0x19: do_vec_max (cpu
); return;
5648 case 0x1B: do_vec_min (cpu
); return;
5649 case 0x21: do_vec_add (cpu
); return;
5650 case 0x25: do_vec_MLA (cpu
); return;
5651 case 0x27: do_vec_mul (cpu
); return;
5652 case 0x2F: do_vec_ADDP (cpu
); return;
5653 case 0x30: do_vec_mull (cpu
); return;
5654 case 0x33: do_vec_FMLA (cpu
); return;
5655 case 0x35: do_vec_fadd (cpu
); return;
5658 switch (INSTR (20, 16))
5660 case 0x00: do_vec_ABS (cpu
); return;
5661 case 0x01: do_vec_FCVTZS (cpu
); return;
5662 case 0x11: do_vec_ADDV (cpu
); return;
5668 do_vec_Fminmax (cpu
); return;
5680 do_vec_compare (cpu
); return;
5683 do_vec_FABS (cpu
); return;
5691 do_vec_xtl (sim_cpu
*cpu
)
5694 instr[30,29] = SXTL (00), UXTL (01), SXTL2 (10), UXTL2 (11)
5695 instr[28,22] = 0 1111 00
5696 instr[21,16] = size & shift (USHLL, SSHLL, USHLL2, SSHLL2)
5697 instr[15,10] = 1010 01
5698 instr[9,5] = V source
5699 instr[4,0] = V dest. */
5701 unsigned vs
= INSTR (9, 5);
5702 unsigned vd
= INSTR (4, 0);
5703 unsigned i
, shift
, bias
= 0;
5705 NYI_assert (28, 22, 0x3C);
5706 NYI_assert (15, 10, 0x29);
5708 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5709 switch (INSTR (30, 29))
5711 case 2: /* SXTL2, SSHLL2. */
5713 case 0: /* SXTL, SSHLL. */
5718 shift
= INSTR (20, 16);
5719 /* Get the source values before setting the destination values
5720 in case the source and destination are the same. */
5721 val1
= aarch64_get_vec_s32 (cpu
, vs
, bias
) << shift
;
5722 val2
= aarch64_get_vec_s32 (cpu
, vs
, bias
+ 1) << shift
;
5723 aarch64_set_vec_s64 (cpu
, vd
, 0, val1
);
5724 aarch64_set_vec_s64 (cpu
, vd
, 1, val2
);
5726 else if (INSTR (20, 20))
5729 int32_t v1
,v2
,v3
,v4
;
5731 shift
= INSTR (19, 16);
5733 for (i
= 0; i
< 4; i
++)
5734 v
[i
] = aarch64_get_vec_s16 (cpu
, vs
, bias
+ i
) << shift
;
5735 for (i
= 0; i
< 4; i
++)
5736 aarch64_set_vec_s32 (cpu
, vd
, i
, v
[i
]);
5741 NYI_assert (19, 19, 1);
5743 shift
= INSTR (18, 16);
5745 for (i
= 0; i
< 8; i
++)
5746 v
[i
] = aarch64_get_vec_s8 (cpu
, vs
, i
+ bias
) << shift
;
5747 for (i
= 0; i
< 8; i
++)
5748 aarch64_set_vec_s16 (cpu
, vd
, i
, v
[i
]);
5752 case 3: /* UXTL2, USHLL2. */
5754 case 1: /* UXTL, USHLL. */
5758 shift
= INSTR (20, 16);
5759 v1
= aarch64_get_vec_u32 (cpu
, vs
, bias
) << shift
;
5760 v2
= aarch64_get_vec_u32 (cpu
, vs
, bias
+ 1) << shift
;
5761 aarch64_set_vec_u64 (cpu
, vd
, 0, v1
);
5762 aarch64_set_vec_u64 (cpu
, vd
, 1, v2
);
5764 else if (INSTR (20, 20))
5767 shift
= INSTR (19, 16);
5769 for (i
= 0; i
< 4; i
++)
5770 v
[i
] = aarch64_get_vec_u16 (cpu
, vs
, i
+ bias
) << shift
;
5771 for (i
= 0; i
< 4; i
++)
5772 aarch64_set_vec_u32 (cpu
, vd
, i
, v
[i
]);
5777 NYI_assert (19, 19, 1);
5779 shift
= INSTR (18, 16);
5781 for (i
= 0; i
< 8; i
++)
5782 v
[i
] = aarch64_get_vec_u8 (cpu
, vs
, i
+ bias
) << shift
;
5783 for (i
= 0; i
< 8; i
++)
5784 aarch64_set_vec_u16 (cpu
, vd
, i
, v
[i
]);
5791 do_vec_SHL (sim_cpu
*cpu
)
5794 instr [30] = half(0)/full(1)
5795 instr [29,23] = 001 1110
5796 instr [22,16] = size and shift amount
5797 instr [15,10] = 01 0101
5799 instr [4, 0] = Vd. */
5802 int full
= INSTR (30, 30);
5803 unsigned vs
= INSTR (9, 5);
5804 unsigned vd
= INSTR (4, 0);
5807 NYI_assert (29, 23, 0x1E);
5808 NYI_assert (15, 10, 0x15);
5810 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5813 shift
= INSTR (21, 16);
5818 for (i
= 0; i
< 2; i
++)
5820 uint64_t val
= aarch64_get_vec_u64 (cpu
, vs
, i
);
5821 aarch64_set_vec_u64 (cpu
, vd
, i
, val
<< shift
);
5829 shift
= INSTR (20, 16);
5831 for (i
= 0; i
< (full
? 4 : 2); i
++)
5833 uint32_t val
= aarch64_get_vec_u32 (cpu
, vs
, i
);
5834 aarch64_set_vec_u32 (cpu
, vd
, i
, val
<< shift
);
5842 shift
= INSTR (19, 16);
5844 for (i
= 0; i
< (full
? 8 : 4); i
++)
5846 uint16_t val
= aarch64_get_vec_u16 (cpu
, vs
, i
);
5847 aarch64_set_vec_u16 (cpu
, vd
, i
, val
<< shift
);
5853 if (INSTR (19, 19) == 0)
5856 shift
= INSTR (18, 16);
5858 for (i
= 0; i
< (full
? 16 : 8); i
++)
5860 uint8_t val
= aarch64_get_vec_u8 (cpu
, vs
, i
);
5861 aarch64_set_vec_u8 (cpu
, vd
, i
, val
<< shift
);
5866 do_vec_SSHR_USHR (sim_cpu
*cpu
)
5869 instr [30] = half(0)/full(1)
5870 instr [29] = signed(0)/unsigned(1)
5871 instr [28,23] = 0 1111 0
5872 instr [22,16] = size and shift amount
5873 instr [15,10] = 0000 01
5875 instr [4, 0] = Vd. */
5877 int full
= INSTR (30, 30);
5878 int sign
= ! INSTR (29, 29);
5879 unsigned shift
= INSTR (22, 16);
5880 unsigned vs
= INSTR (9, 5);
5881 unsigned vd
= INSTR (4, 0);
5884 NYI_assert (28, 23, 0x1E);
5885 NYI_assert (15, 10, 0x01);
5887 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5890 shift
= 128 - shift
;
5896 for (i
= 0; i
< 2; i
++)
5898 int64_t val
= aarch64_get_vec_s64 (cpu
, vs
, i
);
5899 aarch64_set_vec_s64 (cpu
, vd
, i
, val
>> shift
);
5902 for (i
= 0; i
< 2; i
++)
5904 uint64_t val
= aarch64_get_vec_u64 (cpu
, vs
, i
);
5905 aarch64_set_vec_u64 (cpu
, vd
, i
, val
>> shift
);
5916 for (i
= 0; i
< (full
? 4 : 2); i
++)
5918 int32_t val
= aarch64_get_vec_s32 (cpu
, vs
, i
);
5919 aarch64_set_vec_s32 (cpu
, vd
, i
, val
>> shift
);
5922 for (i
= 0; i
< (full
? 4 : 2); i
++)
5924 uint32_t val
= aarch64_get_vec_u32 (cpu
, vs
, i
);
5925 aarch64_set_vec_u32 (cpu
, vd
, i
, val
>> shift
);
5936 for (i
= 0; i
< (full
? 8 : 4); i
++)
5938 int16_t val
= aarch64_get_vec_s16 (cpu
, vs
, i
);
5939 aarch64_set_vec_s16 (cpu
, vd
, i
, val
>> shift
);
5942 for (i
= 0; i
< (full
? 8 : 4); i
++)
5944 uint16_t val
= aarch64_get_vec_u16 (cpu
, vs
, i
);
5945 aarch64_set_vec_u16 (cpu
, vd
, i
, val
>> shift
);
5951 if (INSTR (19, 19) == 0)
5957 for (i
= 0; i
< (full
? 16 : 8); i
++)
5959 int8_t val
= aarch64_get_vec_s8 (cpu
, vs
, i
);
5960 aarch64_set_vec_s8 (cpu
, vd
, i
, val
>> shift
);
5963 for (i
= 0; i
< (full
? 16 : 8); i
++)
5965 uint8_t val
= aarch64_get_vec_u8 (cpu
, vs
, i
);
5966 aarch64_set_vec_u8 (cpu
, vd
, i
, val
>> shift
);
5971 do_vec_MUL_by_element (sim_cpu
*cpu
)
5974 instr[30] = half/full
5975 instr[29,24] = 00 1111
5986 unsigned full
= INSTR (30, 30);
5987 unsigned L
= INSTR (21, 21);
5988 unsigned H
= INSTR (11, 11);
5989 unsigned vn
= INSTR (9, 5);
5990 unsigned vd
= INSTR (4, 0);
5991 unsigned size
= INSTR (23, 22);
5996 NYI_assert (29, 24, 0x0F);
5997 NYI_assert (15, 12, 0x8);
5998 NYI_assert (10, 10, 0);
6000 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6005 /* 16 bit products. */
6010 index
= (H
<< 2) | (L
<< 1) | INSTR (20, 20);
6011 vm
= INSTR (19, 16);
6012 element2
= aarch64_get_vec_u16 (cpu
, vm
, index
);
6014 for (e
= 0; e
< (full
? 8 : 4); e
++)
6016 element1
= aarch64_get_vec_u16 (cpu
, vn
, e
);
6017 product
= element1
* element2
;
6018 aarch64_set_vec_u16 (cpu
, vd
, e
, product
);
6025 /* 32 bit products. */
6030 index
= (H
<< 1) | L
;
6031 vm
= INSTR (20, 16);
6032 element2
= aarch64_get_vec_u32 (cpu
, vm
, index
);
6034 for (e
= 0; e
< (full
? 4 : 2); e
++)
6036 element1
= aarch64_get_vec_u32 (cpu
, vn
, e
);
6037 product
= element1
* element2
;
6038 aarch64_set_vec_u32 (cpu
, vd
, e
, product
);
6049 do_FMLA_by_element (sim_cpu
*cpu
)
6052 instr[30] = half/full
6053 instr[29,23] = 00 1111 1
6063 unsigned full
= INSTR (30, 30);
6064 unsigned size
= INSTR (22, 22);
6065 unsigned L
= INSTR (21, 21);
6066 unsigned vm
= INSTR (20, 16);
6067 unsigned H
= INSTR (11, 11);
6068 unsigned vn
= INSTR (9, 5);
6069 unsigned vd
= INSTR (4, 0);
6072 NYI_assert (29, 23, 0x1F);
6073 NYI_assert (15, 12, 0x1);
6074 NYI_assert (10, 10, 0);
6076 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6079 double element1
, element2
;
6084 element2
= aarch64_get_vec_double (cpu
, vm
, H
);
6086 for (e
= 0; e
< 2; e
++)
6088 element1
= aarch64_get_vec_double (cpu
, vn
, e
);
6089 element1
*= element2
;
6090 element1
+= aarch64_get_vec_double (cpu
, vd
, e
);
6091 aarch64_set_vec_double (cpu
, vd
, e
, element1
);
6097 float element2
= aarch64_get_vec_float (cpu
, vm
, (H
<< 1) | L
);
6099 for (e
= 0; e
< (full
? 4 : 2); e
++)
6101 element1
= aarch64_get_vec_float (cpu
, vn
, e
);
6102 element1
*= element2
;
6103 element1
+= aarch64_get_vec_float (cpu
, vd
, e
);
6104 aarch64_set_vec_float (cpu
, vd
, e
, element1
);
6110 do_vec_op2 (sim_cpu
*cpu
)
6113 instr[30] = half/full
6114 instr[29,24] = 00 1111
6116 instr[22,16] = element size & index
6117 instr[15,10] = sub-opcode
6121 NYI_assert (29, 24, 0x0F);
6123 if (INSTR (23, 23) != 0)
6125 switch (INSTR (15, 10))
6129 do_FMLA_by_element (cpu
);
6134 do_vec_MUL_by_element (cpu
);
6143 switch (INSTR (15, 10))
6145 case 0x01: do_vec_SSHR_USHR (cpu
); return;
6146 case 0x15: do_vec_SHL (cpu
); return;
6148 case 0x22: do_vec_MUL_by_element (cpu
); return;
6149 case 0x29: do_vec_xtl (cpu
); return;
6156 do_vec_neg (sim_cpu
*cpu
)
6159 instr[30] = full(1)/half(0)
6160 instr[29,24] = 10 1110
6161 instr[23,22] = size: byte(00), half (01), word (10), long (11)
6162 instr[21,10] = 1000 0010 1110
6166 int full
= INSTR (30, 30);
6167 unsigned vs
= INSTR (9, 5);
6168 unsigned vd
= INSTR (4, 0);
6171 NYI_assert (29, 24, 0x2E);
6172 NYI_assert (21, 10, 0x82E);
6174 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6175 switch (INSTR (23, 22))
6178 for (i
= 0; i
< (full
? 16 : 8); i
++)
6179 aarch64_set_vec_s8 (cpu
, vd
, i
, - aarch64_get_vec_s8 (cpu
, vs
, i
));
6183 for (i
= 0; i
< (full
? 8 : 4); i
++)
6184 aarch64_set_vec_s16 (cpu
, vd
, i
, - aarch64_get_vec_s16 (cpu
, vs
, i
));
6188 for (i
= 0; i
< (full
? 4 : 2); i
++)
6189 aarch64_set_vec_s32 (cpu
, vd
, i
, - aarch64_get_vec_s32 (cpu
, vs
, i
));
6195 for (i
= 0; i
< 2; i
++)
6196 aarch64_set_vec_s64 (cpu
, vd
, i
, - aarch64_get_vec_s64 (cpu
, vs
, i
));
6202 do_vec_sqrt (sim_cpu
*cpu
)
6205 instr[30] = full(1)/half(0)
6206 instr[29,23] = 101 1101
6207 instr[22] = single(0)/double(1)
6208 instr[21,10] = 1000 0111 1110
6212 int full
= INSTR (30, 30);
6213 unsigned vs
= INSTR (9, 5);
6214 unsigned vd
= INSTR (4, 0);
6217 NYI_assert (29, 23, 0x5B);
6218 NYI_assert (21, 10, 0x87E);
6220 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6221 if (INSTR (22, 22) == 0)
6222 for (i
= 0; i
< (full
? 4 : 2); i
++)
6223 aarch64_set_vec_float (cpu
, vd
, i
,
6224 sqrtf (aarch64_get_vec_float (cpu
, vs
, i
)));
6226 for (i
= 0; i
< 2; i
++)
6227 aarch64_set_vec_double (cpu
, vd
, i
,
6228 sqrt (aarch64_get_vec_double (cpu
, vs
, i
)));
6232 do_vec_mls_indexed (sim_cpu
*cpu
)
6235 instr[30] = half(0)/full(1)
6236 instr[29,24] = 10 1111
6237 instr[23,22] = 16-bit(01)/32-bit(10)
6238 instr[21,20+11] = index (if 16-bit)
6239 instr[21+11] = index (if 32-bit)
6242 instr[11] = part of index
6247 int full
= INSTR (30, 30);
6248 unsigned vs
= INSTR (9, 5);
6249 unsigned vd
= INSTR (4, 0);
6250 unsigned vm
= INSTR (20, 16);
6253 NYI_assert (15, 12, 4);
6254 NYI_assert (10, 10, 0);
6256 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6257 switch (INSTR (23, 22))
6267 elem
= (INSTR (21, 20) << 1) | INSTR (11, 11);
6268 val
= aarch64_get_vec_u16 (cpu
, vm
, elem
);
6270 for (i
= 0; i
< (full
? 8 : 4); i
++)
6271 aarch64_set_vec_u32 (cpu
, vd
, i
,
6272 aarch64_get_vec_u32 (cpu
, vd
, i
) -
6273 (aarch64_get_vec_u32 (cpu
, vs
, i
) * val
));
6279 unsigned elem
= (INSTR (21, 21) << 1) | INSTR (11, 11);
6280 uint64_t val
= aarch64_get_vec_u32 (cpu
, vm
, elem
);
6282 for (i
= 0; i
< (full
? 4 : 2); i
++)
6283 aarch64_set_vec_u64 (cpu
, vd
, i
,
6284 aarch64_get_vec_u64 (cpu
, vd
, i
) -
6285 (aarch64_get_vec_u64 (cpu
, vs
, i
) * val
));
6297 do_vec_SUB (sim_cpu
*cpu
)
6300 instr [30] = half(0)/full(1)
6301 instr [29,24] = 10 1110
6302 instr [23,22] = size: byte(00, half(01), word (10), long (11)
6305 instr [15,10] = 10 0001
6307 instr [4, 0] = Vd. */
6309 unsigned full
= INSTR (30, 30);
6310 unsigned vm
= INSTR (20, 16);
6311 unsigned vn
= INSTR (9, 5);
6312 unsigned vd
= INSTR (4, 0);
6315 NYI_assert (29, 24, 0x2E);
6316 NYI_assert (21, 21, 1);
6317 NYI_assert (15, 10, 0x21);
6319 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6320 switch (INSTR (23, 22))
6323 for (i
= 0; i
< (full
? 16 : 8); i
++)
6324 aarch64_set_vec_s8 (cpu
, vd
, i
,
6325 aarch64_get_vec_s8 (cpu
, vn
, i
)
6326 - aarch64_get_vec_s8 (cpu
, vm
, i
));
6330 for (i
= 0; i
< (full
? 8 : 4); i
++)
6331 aarch64_set_vec_s16 (cpu
, vd
, i
,
6332 aarch64_get_vec_s16 (cpu
, vn
, i
)
6333 - aarch64_get_vec_s16 (cpu
, vm
, i
));
6337 for (i
= 0; i
< (full
? 4 : 2); i
++)
6338 aarch64_set_vec_s32 (cpu
, vd
, i
,
6339 aarch64_get_vec_s32 (cpu
, vn
, i
)
6340 - aarch64_get_vec_s32 (cpu
, vm
, i
));
6347 for (i
= 0; i
< 2; i
++)
6348 aarch64_set_vec_s64 (cpu
, vd
, i
,
6349 aarch64_get_vec_s64 (cpu
, vn
, i
)
6350 - aarch64_get_vec_s64 (cpu
, vm
, i
));
6356 do_vec_MLS (sim_cpu
*cpu
)
6359 instr [30] = half(0)/full(1)
6360 instr [29,24] = 10 1110
6361 instr [23,22] = size: byte(00, half(01), word (10)
6364 instr [15,10] = 10 0101
6366 instr [4, 0] = Vd. */
6368 unsigned full
= INSTR (30, 30);
6369 unsigned vm
= INSTR (20, 16);
6370 unsigned vn
= INSTR (9, 5);
6371 unsigned vd
= INSTR (4, 0);
6374 NYI_assert (29, 24, 0x2E);
6375 NYI_assert (21, 21, 1);
6376 NYI_assert (15, 10, 0x25);
6378 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6379 switch (INSTR (23, 22))
6382 for (i
= 0; i
< (full
? 16 : 8); i
++)
6383 aarch64_set_vec_u8 (cpu
, vd
, i
,
6384 aarch64_get_vec_u8 (cpu
, vd
, i
)
6385 - (aarch64_get_vec_u8 (cpu
, vn
, i
)
6386 * aarch64_get_vec_u8 (cpu
, vm
, i
)));
6390 for (i
= 0; i
< (full
? 8 : 4); i
++)
6391 aarch64_set_vec_u16 (cpu
, vd
, i
,
6392 aarch64_get_vec_u16 (cpu
, vd
, i
)
6393 - (aarch64_get_vec_u16 (cpu
, vn
, i
)
6394 * aarch64_get_vec_u16 (cpu
, vm
, i
)));
6398 for (i
= 0; i
< (full
? 4 : 2); i
++)
6399 aarch64_set_vec_u32 (cpu
, vd
, i
,
6400 aarch64_get_vec_u32 (cpu
, vd
, i
)
6401 - (aarch64_get_vec_u32 (cpu
, vn
, i
)
6402 * aarch64_get_vec_u32 (cpu
, vm
, i
)));
6411 do_vec_FDIV (sim_cpu
*cpu
)
6414 instr [30] = half(0)/full(1)
6415 instr [29,23] = 10 1110 0
6416 instr [22] = float()/double(1)
6419 instr [15,10] = 1111 11
6421 instr [4, 0] = Vd. */
6423 unsigned full
= INSTR (30, 30);
6424 unsigned vm
= INSTR (20, 16);
6425 unsigned vn
= INSTR (9, 5);
6426 unsigned vd
= INSTR (4, 0);
6429 NYI_assert (29, 23, 0x5C);
6430 NYI_assert (21, 21, 1);
6431 NYI_assert (15, 10, 0x3F);
6433 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6439 for (i
= 0; i
< 2; i
++)
6440 aarch64_set_vec_double (cpu
, vd
, i
,
6441 aarch64_get_vec_double (cpu
, vn
, i
)
6442 / aarch64_get_vec_double (cpu
, vm
, i
));
6445 for (i
= 0; i
< (full
? 4 : 2); i
++)
6446 aarch64_set_vec_float (cpu
, vd
, i
,
6447 aarch64_get_vec_float (cpu
, vn
, i
)
6448 / aarch64_get_vec_float (cpu
, vm
, i
));
6452 do_vec_FMUL (sim_cpu
*cpu
)
6455 instr [30] = half(0)/full(1)
6456 instr [29,23] = 10 1110 0
6457 instr [22] = float(0)/double(1)
6460 instr [15,10] = 1101 11
6462 instr [4, 0] = Vd. */
6464 unsigned full
= INSTR (30, 30);
6465 unsigned vm
= INSTR (20, 16);
6466 unsigned vn
= INSTR (9, 5);
6467 unsigned vd
= INSTR (4, 0);
6470 NYI_assert (29, 23, 0x5C);
6471 NYI_assert (21, 21, 1);
6472 NYI_assert (15, 10, 0x37);
6474 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6480 for (i
= 0; i
< 2; i
++)
6481 aarch64_set_vec_double (cpu
, vd
, i
,
6482 aarch64_get_vec_double (cpu
, vn
, i
)
6483 * aarch64_get_vec_double (cpu
, vm
, i
));
6486 for (i
= 0; i
< (full
? 4 : 2); i
++)
6487 aarch64_set_vec_float (cpu
, vd
, i
,
6488 aarch64_get_vec_float (cpu
, vn
, i
)
6489 * aarch64_get_vec_float (cpu
, vm
, i
));
6493 do_vec_FADDP (sim_cpu
*cpu
)
6496 instr [30] = half(0)/full(1)
6497 instr [29,23] = 10 1110 0
6498 instr [22] = float(0)/double(1)
6501 instr [15,10] = 1101 01
6503 instr [4, 0] = Vd. */
6505 unsigned full
= INSTR (30, 30);
6506 unsigned vm
= INSTR (20, 16);
6507 unsigned vn
= INSTR (9, 5);
6508 unsigned vd
= INSTR (4, 0);
6510 NYI_assert (29, 23, 0x5C);
6511 NYI_assert (21, 21, 1);
6512 NYI_assert (15, 10, 0x35);
6514 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6517 /* Extract values before adding them incase vd == vn/vm. */
6518 double tmp1
= aarch64_get_vec_double (cpu
, vn
, 0);
6519 double tmp2
= aarch64_get_vec_double (cpu
, vn
, 1);
6520 double tmp3
= aarch64_get_vec_double (cpu
, vm
, 0);
6521 double tmp4
= aarch64_get_vec_double (cpu
, vm
, 1);
6526 aarch64_set_vec_double (cpu
, vd
, 0, tmp1
+ tmp2
);
6527 aarch64_set_vec_double (cpu
, vd
, 1, tmp3
+ tmp4
);
6531 /* Extract values before adding them incase vd == vn/vm. */
6532 float tmp1
= aarch64_get_vec_float (cpu
, vn
, 0);
6533 float tmp2
= aarch64_get_vec_float (cpu
, vn
, 1);
6534 float tmp5
= aarch64_get_vec_float (cpu
, vm
, 0);
6535 float tmp6
= aarch64_get_vec_float (cpu
, vm
, 1);
6539 float tmp3
= aarch64_get_vec_float (cpu
, vn
, 2);
6540 float tmp4
= aarch64_get_vec_float (cpu
, vn
, 3);
6541 float tmp7
= aarch64_get_vec_float (cpu
, vm
, 2);
6542 float tmp8
= aarch64_get_vec_float (cpu
, vm
, 3);
6544 aarch64_set_vec_float (cpu
, vd
, 0, tmp1
+ tmp2
);
6545 aarch64_set_vec_float (cpu
, vd
, 1, tmp3
+ tmp4
);
6546 aarch64_set_vec_float (cpu
, vd
, 2, tmp5
+ tmp6
);
6547 aarch64_set_vec_float (cpu
, vd
, 3, tmp7
+ tmp8
);
6551 aarch64_set_vec_float (cpu
, vd
, 0, tmp1
+ tmp2
);
6552 aarch64_set_vec_float (cpu
, vd
, 1, tmp5
+ tmp6
);
6558 do_vec_FSQRT (sim_cpu
*cpu
)
6561 instr[30] = half(0)/full(1)
6562 instr[29,23] = 10 1110 1
6563 instr[22] = single(0)/double(1)
6564 instr[21,10] = 10 0001 1111 10
6566 instr[4,0] = Vdest. */
6568 unsigned vn
= INSTR (9, 5);
6569 unsigned vd
= INSTR (4, 0);
6570 unsigned full
= INSTR (30, 30);
6573 NYI_assert (29, 23, 0x5D);
6574 NYI_assert (21, 10, 0x87E);
6576 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6582 for (i
= 0; i
< 2; i
++)
6583 aarch64_set_vec_double (cpu
, vd
, i
,
6584 sqrt (aarch64_get_vec_double (cpu
, vn
, i
)));
6588 for (i
= 0; i
< (full
? 4 : 2); i
++)
6589 aarch64_set_vec_float (cpu
, vd
, i
,
6590 sqrtf (aarch64_get_vec_float (cpu
, vn
, i
)));
6595 do_vec_FNEG (sim_cpu
*cpu
)
6598 instr[30] = half (0)/full (1)
6599 instr[29,23] = 10 1110 1
6600 instr[22] = single (0)/double (1)
6601 instr[21,10] = 10 0000 1111 10
6603 instr[4,0] = Vdest. */
6605 unsigned vn
= INSTR (9, 5);
6606 unsigned vd
= INSTR (4, 0);
6607 unsigned full
= INSTR (30, 30);
6610 NYI_assert (29, 23, 0x5D);
6611 NYI_assert (21, 10, 0x83E);
6613 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6619 for (i
= 0; i
< 2; i
++)
6620 aarch64_set_vec_double (cpu
, vd
, i
,
6621 - aarch64_get_vec_double (cpu
, vn
, i
));
6625 for (i
= 0; i
< (full
? 4 : 2); i
++)
6626 aarch64_set_vec_float (cpu
, vd
, i
,
6627 - aarch64_get_vec_float (cpu
, vn
, i
));
6632 do_vec_NOT (sim_cpu
*cpu
)
6635 instr[30] = half (0)/full (1)
6636 instr[29,10] = 10 1110 0010 0000 0101 10
6640 unsigned vn
= INSTR (9, 5);
6641 unsigned vd
= INSTR (4, 0);
6643 int full
= INSTR (30, 30);
6645 NYI_assert (29, 10, 0xB8816);
6647 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6648 for (i
= 0; i
< (full
? 16 : 8); i
++)
6649 aarch64_set_vec_u8 (cpu
, vd
, i
, ~ aarch64_get_vec_u8 (cpu
, vn
, i
));
6653 clz (uint64_t val
, unsigned size
)
6658 mask
<<= (size
- 1);
6673 do_vec_CLZ (sim_cpu
*cpu
)
6676 instr[30] = half (0)/full (1)
6677 instr[29,24] = 10 1110
6679 instr[21,10] = 10 0000 0100 10
6683 unsigned vn
= INSTR (9, 5);
6684 unsigned vd
= INSTR (4, 0);
6686 int full
= INSTR (30,30);
6688 NYI_assert (29, 24, 0x2E);
6689 NYI_assert (21, 10, 0x812);
6691 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6692 switch (INSTR (23, 22))
6695 for (i
= 0; i
< (full
? 16 : 8); i
++)
6696 aarch64_set_vec_u8 (cpu
, vd
, i
, clz (aarch64_get_vec_u8 (cpu
, vn
, i
), 8));
6699 for (i
= 0; i
< (full
? 8 : 4); i
++)
6700 aarch64_set_vec_u16 (cpu
, vd
, i
, clz (aarch64_get_vec_u16 (cpu
, vn
, i
), 16));
6703 for (i
= 0; i
< (full
? 4 : 2); i
++)
6704 aarch64_set_vec_u32 (cpu
, vd
, i
, clz (aarch64_get_vec_u32 (cpu
, vn
, i
), 32));
6709 aarch64_set_vec_u64 (cpu
, vd
, 0, clz (aarch64_get_vec_u64 (cpu
, vn
, 0), 64));
6710 aarch64_set_vec_u64 (cpu
, vd
, 1, clz (aarch64_get_vec_u64 (cpu
, vn
, 1), 64));
6716 do_vec_MOV_element (sim_cpu
*cpu
)
6718 /* instr[31,21] = 0110 1110 000
6719 instr[20,16] = size & dest index
6721 instr[14,11] = source index
6726 unsigned vs
= INSTR (9, 5);
6727 unsigned vd
= INSTR (4, 0);
6731 NYI_assert (31, 21, 0x370);
6732 NYI_assert (15, 15, 0);
6733 NYI_assert (10, 10, 1);
6735 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6739 src_index
= INSTR (14, 11);
6740 dst_index
= INSTR (20, 17);
6741 aarch64_set_vec_u8 (cpu
, vd
, dst_index
,
6742 aarch64_get_vec_u8 (cpu
, vs
, src_index
));
6744 else if (INSTR (17, 17))
6747 NYI_assert (11, 11, 0);
6748 src_index
= INSTR (14, 12);
6749 dst_index
= INSTR (20, 18);
6750 aarch64_set_vec_u16 (cpu
, vd
, dst_index
,
6751 aarch64_get_vec_u16 (cpu
, vs
, src_index
));
6753 else if (INSTR (18, 18))
6756 NYI_assert (12, 11, 0);
6757 src_index
= INSTR (14, 13);
6758 dst_index
= INSTR (20, 19);
6759 aarch64_set_vec_u32 (cpu
, vd
, dst_index
,
6760 aarch64_get_vec_u32 (cpu
, vs
, src_index
));
6764 NYI_assert (19, 19, 1);
6765 NYI_assert (13, 11, 0);
6766 src_index
= INSTR (14, 14);
6767 dst_index
= INSTR (20, 20);
6768 aarch64_set_vec_u64 (cpu
, vd
, dst_index
,
6769 aarch64_get_vec_u64 (cpu
, vs
, src_index
));
6774 do_vec_REV32 (sim_cpu
*cpu
)
6777 instr[30] = full/half
6778 instr[29,24] = 10 1110
6780 instr[21,10] = 10 0000 0000 10
6784 unsigned rn
= INSTR (9, 5);
6785 unsigned rd
= INSTR (4, 0);
6786 unsigned size
= INSTR (23, 22);
6787 unsigned full
= INSTR (30, 30);
6791 NYI_assert (29, 24, 0x2E);
6792 NYI_assert (21, 10, 0x802);
6794 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6798 for (i
= 0; i
< (full
? 16 : 8); i
++)
6799 val
.b
[i
^ 0x3] = aarch64_get_vec_u8 (cpu
, rn
, i
);
6803 for (i
= 0; i
< (full
? 8 : 4); i
++)
6804 val
.h
[i
^ 0x1] = aarch64_get_vec_u16 (cpu
, rn
, i
);
6811 aarch64_set_vec_u64 (cpu
, rd
, 0, val
.v
[0]);
6813 aarch64_set_vec_u64 (cpu
, rd
, 1, val
.v
[1]);
6817 do_vec_EXT (sim_cpu
*cpu
)
6820 instr[30] = full/half
6821 instr[29,21] = 10 1110 000
6824 instr[14,11] = source index
6829 unsigned vm
= INSTR (20, 16);
6830 unsigned vn
= INSTR (9, 5);
6831 unsigned vd
= INSTR (4, 0);
6832 unsigned src_index
= INSTR (14, 11);
6833 unsigned full
= INSTR (30, 30);
6838 NYI_assert (31, 21, 0x370);
6839 NYI_assert (15, 15, 0);
6840 NYI_assert (10, 10, 0);
6842 if (!full
&& (src_index
& 0x8))
6847 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6848 for (i
= src_index
; i
< (full
? 16 : 8); i
++)
6849 val
.b
[j
++] = aarch64_get_vec_u8 (cpu
, vn
, i
);
6850 for (i
= 0; i
< src_index
; i
++)
6851 val
.b
[j
++] = aarch64_get_vec_u8 (cpu
, vm
, i
);
6853 aarch64_set_vec_u64 (cpu
, vd
, 0, val
.v
[0]);
6855 aarch64_set_vec_u64 (cpu
, vd
, 1, val
.v
[1]);
6859 dexAdvSIMD0 (sim_cpu
*cpu
)
6861 /* instr [28,25] = 0 111. */
6862 if ( INSTR (15, 10) == 0x07
6866 if (INSTR (31, 21) == 0x075
6867 || INSTR (31, 21) == 0x275)
6869 do_vec_MOV_whole_vector (cpu
);
6874 if (INSTR (29, 19) == 0x1E0)
6876 do_vec_MOV_immediate (cpu
);
6880 if (INSTR (29, 19) == 0x5E0)
6886 if (INSTR (29, 19) == 0x1C0
6887 || INSTR (29, 19) == 0x1C1)
6889 if (INSTR (15, 10) == 0x03)
6891 do_vec_DUP_scalar_into_vector (cpu
);
6896 switch (INSTR (29, 24))
6898 case 0x0E: do_vec_op1 (cpu
); return;
6899 case 0x0F: do_vec_op2 (cpu
); return;
6902 if (INSTR (21, 21) == 1)
6904 switch (INSTR (15, 10))
6911 switch (INSTR (23, 22))
6913 case 0: do_vec_EOR (cpu
); return;
6914 case 1: do_vec_BSL (cpu
); return;
6916 case 3: do_vec_bit (cpu
); return;
6920 case 0x08: do_vec_sub_long (cpu
); return;
6921 case 0x11: do_vec_USHL (cpu
); return;
6922 case 0x12: do_vec_CLZ (cpu
); return;
6923 case 0x16: do_vec_NOT (cpu
); return;
6924 case 0x19: do_vec_max (cpu
); return;
6925 case 0x1B: do_vec_min (cpu
); return;
6926 case 0x21: do_vec_SUB (cpu
); return;
6927 case 0x25: do_vec_MLS (cpu
); return;
6928 case 0x31: do_vec_FminmaxNMP (cpu
); return;
6929 case 0x35: do_vec_FADDP (cpu
); return;
6930 case 0x37: do_vec_FMUL (cpu
); return;
6931 case 0x3F: do_vec_FDIV (cpu
); return;
6934 switch (INSTR (20, 16))
6936 case 0x00: do_vec_FNEG (cpu
); return;
6937 case 0x01: do_vec_FSQRT (cpu
); return;
6951 do_vec_compare (cpu
); return;
6958 if (INSTR (31, 21) == 0x370)
6961 do_vec_MOV_element (cpu
);
6967 switch (INSTR (21, 10))
6969 case 0x82E: do_vec_neg (cpu
); return;
6970 case 0x87E: do_vec_sqrt (cpu
); return;
6972 if (INSTR (15, 10) == 0x30)
6982 switch (INSTR (15, 10))
6984 case 0x01: do_vec_SSHR_USHR (cpu
); return;
6986 case 0x12: do_vec_mls_indexed (cpu
); return;
6987 case 0x29: do_vec_xtl (cpu
); return;
7001 /* Float multiply add. */
7003 fmadds (sim_cpu
*cpu
)
7005 unsigned sa
= INSTR (14, 10);
7006 unsigned sm
= INSTR (20, 16);
7007 unsigned sn
= INSTR ( 9, 5);
7008 unsigned sd
= INSTR ( 4, 0);
7010 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7011 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sa
)
7012 + aarch64_get_FP_float (cpu
, sn
)
7013 * aarch64_get_FP_float (cpu
, sm
));
7016 /* Double multiply add. */
7018 fmaddd (sim_cpu
*cpu
)
7020 unsigned sa
= INSTR (14, 10);
7021 unsigned sm
= INSTR (20, 16);
7022 unsigned sn
= INSTR ( 9, 5);
7023 unsigned sd
= INSTR ( 4, 0);
7025 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7026 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sa
)
7027 + aarch64_get_FP_double (cpu
, sn
)
7028 * aarch64_get_FP_double (cpu
, sm
));
7031 /* Float multiply subtract. */
7033 fmsubs (sim_cpu
*cpu
)
7035 unsigned sa
= INSTR (14, 10);
7036 unsigned sm
= INSTR (20, 16);
7037 unsigned sn
= INSTR ( 9, 5);
7038 unsigned sd
= INSTR ( 4, 0);
7040 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7041 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sa
)
7042 - aarch64_get_FP_float (cpu
, sn
)
7043 * aarch64_get_FP_float (cpu
, sm
));
7046 /* Double multiply subtract. */
7048 fmsubd (sim_cpu
*cpu
)
7050 unsigned sa
= INSTR (14, 10);
7051 unsigned sm
= INSTR (20, 16);
7052 unsigned sn
= INSTR ( 9, 5);
7053 unsigned sd
= INSTR ( 4, 0);
7055 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7056 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sa
)
7057 - aarch64_get_FP_double (cpu
, sn
)
7058 * aarch64_get_FP_double (cpu
, sm
));
7061 /* Float negative multiply add. */
7063 fnmadds (sim_cpu
*cpu
)
7065 unsigned sa
= INSTR (14, 10);
7066 unsigned sm
= INSTR (20, 16);
7067 unsigned sn
= INSTR ( 9, 5);
7068 unsigned sd
= INSTR ( 4, 0);
7070 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7071 aarch64_set_FP_float (cpu
, sd
, - aarch64_get_FP_float (cpu
, sa
)
7072 + (- aarch64_get_FP_float (cpu
, sn
))
7073 * aarch64_get_FP_float (cpu
, sm
));
7076 /* Double negative multiply add. */
7078 fnmaddd (sim_cpu
*cpu
)
7080 unsigned sa
= INSTR (14, 10);
7081 unsigned sm
= INSTR (20, 16);
7082 unsigned sn
= INSTR ( 9, 5);
7083 unsigned sd
= INSTR ( 4, 0);
7085 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7086 aarch64_set_FP_double (cpu
, sd
, - aarch64_get_FP_double (cpu
, sa
)
7087 + (- aarch64_get_FP_double (cpu
, sn
))
7088 * aarch64_get_FP_double (cpu
, sm
));
7091 /* Float negative multiply subtract. */
7093 fnmsubs (sim_cpu
*cpu
)
7095 unsigned sa
= INSTR (14, 10);
7096 unsigned sm
= INSTR (20, 16);
7097 unsigned sn
= INSTR ( 9, 5);
7098 unsigned sd
= INSTR ( 4, 0);
7100 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7101 aarch64_set_FP_float (cpu
, sd
, - aarch64_get_FP_float (cpu
, sa
)
7102 + aarch64_get_FP_float (cpu
, sn
)
7103 * aarch64_get_FP_float (cpu
, sm
));
7106 /* Double negative multiply subtract. */
7108 fnmsubd (sim_cpu
*cpu
)
7110 unsigned sa
= INSTR (14, 10);
7111 unsigned sm
= INSTR (20, 16);
7112 unsigned sn
= INSTR ( 9, 5);
7113 unsigned sd
= INSTR ( 4, 0);
7115 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7116 aarch64_set_FP_double (cpu
, sd
, - aarch64_get_FP_double (cpu
, sa
)
7117 + aarch64_get_FP_double (cpu
, sn
)
7118 * aarch64_get_FP_double (cpu
, sm
));
7122 dexSimpleFPDataProc3Source (sim_cpu
*cpu
)
7124 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
7126 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
7129 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
7130 instr[21] ==> o1 : 0 ==> unnegated, 1 ==> negated
7131 instr[15] ==> o2 : 0 ==> ADD, 1 ==> SUB */
7133 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
7134 /* dispatch on combined type:o1:o2. */
7135 uint32_t dispatch
= (INSTR (23, 21) << 1) | INSTR (15, 15);
7142 case 0: fmadds (cpu
); return;
7143 case 1: fmsubs (cpu
); return;
7144 case 2: fnmadds (cpu
); return;
7145 case 3: fnmsubs (cpu
); return;
7146 case 4: fmaddd (cpu
); return;
7147 case 5: fmsubd (cpu
); return;
7148 case 6: fnmaddd (cpu
); return;
7149 case 7: fnmsubd (cpu
); return;
7151 /* type > 1 is currently unallocated. */
7157 dexSimpleFPFixedConvert (sim_cpu
*cpu
)
7163 dexSimpleFPCondCompare (sim_cpu
*cpu
)
7165 /* instr [31,23] = 0001 1110 0
7169 instr [15,12] = condition
7173 instr [3,0] = nzcv */
7175 unsigned rm
= INSTR (20, 16);
7176 unsigned rn
= INSTR (9, 5);
7178 NYI_assert (31, 23, 0x3C);
7179 NYI_assert (11, 10, 0x1);
7180 NYI_assert (4, 4, 0);
7182 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7183 if (! testConditionCode (cpu
, INSTR (15, 12)))
7185 aarch64_set_CPSR (cpu
, INSTR (3, 0));
7191 /* Double precision. */
7192 double val1
= aarch64_get_vec_double (cpu
, rn
, 0);
7193 double val2
= aarch64_get_vec_double (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
);
7205 /* Single precision. */
7206 float val1
= aarch64_get_vec_float (cpu
, rn
, 0);
7207 float val2
= aarch64_get_vec_float (cpu
, rm
, 0);
7209 /* FIXME: Check for NaNs. */
7211 aarch64_set_CPSR (cpu
, (Z
| C
));
7212 else if (val1
< val2
)
7213 aarch64_set_CPSR (cpu
, N
);
7214 else /* val1 > val2 */
7215 aarch64_set_CPSR (cpu
, C
);
7223 fadds (sim_cpu
*cpu
)
7225 unsigned sm
= INSTR (20, 16);
7226 unsigned sn
= INSTR ( 9, 5);
7227 unsigned sd
= INSTR ( 4, 0);
7229 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7230 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
7231 + aarch64_get_FP_float (cpu
, sm
));
7236 faddd (sim_cpu
*cpu
)
7238 unsigned sm
= INSTR (20, 16);
7239 unsigned sn
= INSTR ( 9, 5);
7240 unsigned sd
= INSTR ( 4, 0);
7242 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7243 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
7244 + aarch64_get_FP_double (cpu
, sm
));
7249 fdivs (sim_cpu
*cpu
)
7251 unsigned sm
= INSTR (20, 16);
7252 unsigned sn
= INSTR ( 9, 5);
7253 unsigned sd
= INSTR ( 4, 0);
7255 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7256 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
7257 / aarch64_get_FP_float (cpu
, sm
));
7260 /* Double divide. */
7262 fdivd (sim_cpu
*cpu
)
7264 unsigned sm
= INSTR (20, 16);
7265 unsigned sn
= INSTR ( 9, 5);
7266 unsigned sd
= INSTR ( 4, 0);
7268 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7269 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
7270 / aarch64_get_FP_double (cpu
, sm
));
7273 /* Float multiply. */
7275 fmuls (sim_cpu
*cpu
)
7277 unsigned sm
= INSTR (20, 16);
7278 unsigned sn
= INSTR ( 9, 5);
7279 unsigned sd
= INSTR ( 4, 0);
7281 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7282 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
7283 * aarch64_get_FP_float (cpu
, sm
));
7286 /* Double multiply. */
7288 fmuld (sim_cpu
*cpu
)
7290 unsigned sm
= INSTR (20, 16);
7291 unsigned sn
= INSTR ( 9, 5);
7292 unsigned sd
= INSTR ( 4, 0);
7294 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7295 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
7296 * aarch64_get_FP_double (cpu
, sm
));
7299 /* Float negate and multiply. */
7301 fnmuls (sim_cpu
*cpu
)
7303 unsigned sm
= INSTR (20, 16);
7304 unsigned sn
= INSTR ( 9, 5);
7305 unsigned sd
= INSTR ( 4, 0);
7307 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7308 aarch64_set_FP_float (cpu
, sd
, - (aarch64_get_FP_float (cpu
, sn
)
7309 * aarch64_get_FP_float (cpu
, sm
)));
7312 /* Double negate and multiply. */
7314 fnmuld (sim_cpu
*cpu
)
7316 unsigned sm
= INSTR (20, 16);
7317 unsigned sn
= INSTR ( 9, 5);
7318 unsigned sd
= INSTR ( 4, 0);
7320 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7321 aarch64_set_FP_double (cpu
, sd
, - (aarch64_get_FP_double (cpu
, sn
)
7322 * aarch64_get_FP_double (cpu
, sm
)));
7325 /* Float subtract. */
7327 fsubs (sim_cpu
*cpu
)
7329 unsigned sm
= INSTR (20, 16);
7330 unsigned sn
= INSTR ( 9, 5);
7331 unsigned sd
= INSTR ( 4, 0);
7333 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7334 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
7335 - aarch64_get_FP_float (cpu
, sm
));
7338 /* Double subtract. */
7340 fsubd (sim_cpu
*cpu
)
7342 unsigned sm
= INSTR (20, 16);
7343 unsigned sn
= INSTR ( 9, 5);
7344 unsigned sd
= INSTR ( 4, 0);
7346 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7347 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
7348 - aarch64_get_FP_double (cpu
, sm
));
7352 do_FMINNM (sim_cpu
*cpu
)
7354 /* instr[31,23] = 0 0011 1100
7355 instr[22] = float(0)/double(1)
7358 instr[15,10] = 01 1110
7362 unsigned sm
= INSTR (20, 16);
7363 unsigned sn
= INSTR ( 9, 5);
7364 unsigned sd
= INSTR ( 4, 0);
7366 NYI_assert (31, 23, 0x03C);
7367 NYI_assert (15, 10, 0x1E);
7369 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7371 aarch64_set_FP_double (cpu
, sd
,
7372 dminnm (aarch64_get_FP_double (cpu
, sn
),
7373 aarch64_get_FP_double (cpu
, sm
)));
7375 aarch64_set_FP_float (cpu
, sd
,
7376 fminnm (aarch64_get_FP_float (cpu
, sn
),
7377 aarch64_get_FP_float (cpu
, sm
)));
7381 do_FMAXNM (sim_cpu
*cpu
)
7383 /* instr[31,23] = 0 0011 1100
7384 instr[22] = float(0)/double(1)
7387 instr[15,10] = 01 1010
7391 unsigned sm
= INSTR (20, 16);
7392 unsigned sn
= INSTR ( 9, 5);
7393 unsigned sd
= INSTR ( 4, 0);
7395 NYI_assert (31, 23, 0x03C);
7396 NYI_assert (15, 10, 0x1A);
7398 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7400 aarch64_set_FP_double (cpu
, sd
,
7401 dmaxnm (aarch64_get_FP_double (cpu
, sn
),
7402 aarch64_get_FP_double (cpu
, sm
)));
7404 aarch64_set_FP_float (cpu
, sd
,
7405 fmaxnm (aarch64_get_FP_float (cpu
, sn
),
7406 aarch64_get_FP_float (cpu
, sm
)));
7410 dexSimpleFPDataProc2Source (sim_cpu
*cpu
)
7412 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
7414 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
7417 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
7420 instr[15,12] ==> opcode : 0000 ==> FMUL, 0001 ==> FDIV
7421 0010 ==> FADD, 0011 ==> FSUB,
7422 0100 ==> FMAX, 0101 ==> FMIN
7423 0110 ==> FMAXNM, 0111 ==> FMINNM
7424 1000 ==> FNMUL, ow ==> UNALLOC
7429 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
7430 uint32_t type
= INSTR (23, 22);
7431 /* Dispatch on opcode. */
7432 uint32_t dispatch
= INSTR (15, 12);
7443 case 0: fmuld (cpu
); return;
7444 case 1: fdivd (cpu
); return;
7445 case 2: faddd (cpu
); return;
7446 case 3: fsubd (cpu
); return;
7447 case 6: do_FMAXNM (cpu
); return;
7448 case 7: do_FMINNM (cpu
); return;
7449 case 8: fnmuld (cpu
); return;
7451 /* Have not yet implemented fmax and fmin. */
7459 else /* type == 0 => floats. */
7462 case 0: fmuls (cpu
); return;
7463 case 1: fdivs (cpu
); return;
7464 case 2: fadds (cpu
); return;
7465 case 3: fsubs (cpu
); return;
7466 case 6: do_FMAXNM (cpu
); return;
7467 case 7: do_FMINNM (cpu
); return;
7468 case 8: fnmuls (cpu
); return;
7480 dexSimpleFPCondSelect (sim_cpu
*cpu
)
7483 instr[31,23] = 0 0011 1100
7484 instr[22] = 0=>single 1=>double
7491 unsigned sm
= INSTR (20, 16);
7492 unsigned sn
= INSTR ( 9, 5);
7493 unsigned sd
= INSTR ( 4, 0);
7494 uint32_t set
= testConditionCode (cpu
, INSTR (15, 12));
7496 NYI_assert (31, 23, 0x03C);
7497 NYI_assert (11, 10, 0x3);
7499 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7501 aarch64_set_FP_double (cpu
, sd
, (set
? aarch64_get_FP_double (cpu
, sn
)
7502 : aarch64_get_FP_double (cpu
, sm
)));
7504 aarch64_set_FP_float (cpu
, sd
, (set
? aarch64_get_FP_float (cpu
, sn
)
7505 : aarch64_get_FP_float (cpu
, sm
)));
7508 /* Store 32 bit unscaled signed 9 bit. */
7510 fsturs (sim_cpu
*cpu
, int32_t offset
)
7512 unsigned int rn
= INSTR (9, 5);
7513 unsigned int st
= INSTR (4, 0);
7515 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7516 aarch64_set_mem_u32 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, 1) + offset
,
7517 aarch64_get_vec_u32 (cpu
, st
, 0));
7520 /* Store 64 bit unscaled signed 9 bit. */
7522 fsturd (sim_cpu
*cpu
, int32_t offset
)
7524 unsigned int rn
= INSTR (9, 5);
7525 unsigned int st
= INSTR (4, 0);
7527 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7528 aarch64_set_mem_u64 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, 1) + offset
,
7529 aarch64_get_vec_u64 (cpu
, st
, 0));
7532 /* Store 128 bit unscaled signed 9 bit. */
7534 fsturq (sim_cpu
*cpu
, int32_t offset
)
7536 unsigned int rn
= INSTR (9, 5);
7537 unsigned int st
= INSTR (4, 0);
7540 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7541 aarch64_get_FP_long_double (cpu
, st
, & a
);
7542 aarch64_set_mem_long_double (cpu
,
7543 aarch64_get_reg_u64 (cpu
, rn
, 1)
7547 /* TODO FP move register. */
7549 /* 32 bit fp to fp move register. */
7551 ffmovs (sim_cpu
*cpu
)
7553 unsigned int rn
= INSTR (9, 5);
7554 unsigned int st
= INSTR (4, 0);
7556 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7557 aarch64_set_FP_float (cpu
, st
, aarch64_get_FP_float (cpu
, rn
));
7560 /* 64 bit fp to fp move register. */
7562 ffmovd (sim_cpu
*cpu
)
7564 unsigned int rn
= INSTR (9, 5);
7565 unsigned int st
= INSTR (4, 0);
7567 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7568 aarch64_set_FP_double (cpu
, st
, aarch64_get_FP_double (cpu
, rn
));
7571 /* 32 bit GReg to Vec move register. */
7573 fgmovs (sim_cpu
*cpu
)
7575 unsigned int rn
= INSTR (9, 5);
7576 unsigned int st
= INSTR (4, 0);
7578 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7579 aarch64_set_vec_u32 (cpu
, st
, 0, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
));
7582 /* 64 bit g to fp move register. */
7584 fgmovd (sim_cpu
*cpu
)
7586 unsigned int rn
= INSTR (9, 5);
7587 unsigned int st
= INSTR (4, 0);
7589 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7590 aarch64_set_vec_u64 (cpu
, st
, 0, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
7593 /* 32 bit fp to g move register. */
7595 gfmovs (sim_cpu
*cpu
)
7597 unsigned int rn
= INSTR (9, 5);
7598 unsigned int st
= INSTR (4, 0);
7600 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7601 aarch64_set_reg_u64 (cpu
, st
, NO_SP
, aarch64_get_vec_u32 (cpu
, rn
, 0));
7604 /* 64 bit fp to g move register. */
7606 gfmovd (sim_cpu
*cpu
)
7608 unsigned int rn
= INSTR (9, 5);
7609 unsigned int st
= INSTR (4, 0);
7611 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7612 aarch64_set_reg_u64 (cpu
, st
, NO_SP
, aarch64_get_vec_u64 (cpu
, rn
, 0));
7615 /* FP move immediate
7617 These install an immediate 8 bit value in the target register
7618 where the 8 bits comprise 1 sign bit, 4 bits of fraction and a 3
7622 fmovs (sim_cpu
*cpu
)
7624 unsigned int sd
= INSTR (4, 0);
7625 uint32_t imm
= INSTR (20, 13);
7626 float f
= fp_immediate_for_encoding_32 (imm
);
7628 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7629 aarch64_set_FP_float (cpu
, sd
, f
);
7633 fmovd (sim_cpu
*cpu
)
7635 unsigned int sd
= INSTR (4, 0);
7636 uint32_t imm
= INSTR (20, 13);
7637 double d
= fp_immediate_for_encoding_64 (imm
);
7639 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7640 aarch64_set_FP_double (cpu
, sd
, d
);
7644 dexSimpleFPImmediate (sim_cpu
*cpu
)
7646 /* instr[31,23] == 00111100
7647 instr[22] == type : single(0)/double(1)
7649 instr[20,13] == imm8
7651 instr[9,5] == imm5 : 00000 ==> PK, ow ==> UNALLOC
7653 uint32_t imm5
= INSTR (9, 5);
7655 NYI_assert (31, 23, 0x3C);
7666 /* TODO specific decode and execute for group Load Store. */
7668 /* TODO FP load/store single register (unscaled offset). */
7670 /* TODO load 8 bit unscaled signed 9 bit. */
7671 /* TODO load 16 bit unscaled signed 9 bit. */
7673 /* Load 32 bit unscaled signed 9 bit. */
7675 fldurs (sim_cpu
*cpu
, int32_t offset
)
7677 unsigned int rn
= INSTR (9, 5);
7678 unsigned int st
= INSTR (4, 0);
7680 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7681 aarch64_set_vec_u32 (cpu
, st
, 0, aarch64_get_mem_u32
7682 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
));
7685 /* Load 64 bit unscaled signed 9 bit. */
7687 fldurd (sim_cpu
*cpu
, int32_t offset
)
7689 unsigned int rn
= INSTR (9, 5);
7690 unsigned int st
= INSTR (4, 0);
7692 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7693 aarch64_set_vec_u64 (cpu
, st
, 0, aarch64_get_mem_u64
7694 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
));
7697 /* Load 128 bit unscaled signed 9 bit. */
7699 fldurq (sim_cpu
*cpu
, int32_t offset
)
7701 unsigned int rn
= INSTR (9, 5);
7702 unsigned int st
= INSTR (4, 0);
7704 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
;
7706 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7707 aarch64_get_mem_long_double (cpu
, addr
, & a
);
7708 aarch64_set_FP_long_double (cpu
, st
, a
);
7711 /* TODO store 8 bit unscaled signed 9 bit. */
7712 /* TODO store 16 bit unscaled signed 9 bit. */
7717 /* Float absolute value. */
7719 fabss (sim_cpu
*cpu
)
7721 unsigned sn
= INSTR (9, 5);
7722 unsigned sd
= INSTR (4, 0);
7723 float value
= aarch64_get_FP_float (cpu
, sn
);
7725 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7726 aarch64_set_FP_float (cpu
, sd
, fabsf (value
));
7729 /* Double absolute value. */
7731 fabcpu (sim_cpu
*cpu
)
7733 unsigned sn
= INSTR (9, 5);
7734 unsigned sd
= INSTR (4, 0);
7735 double value
= aarch64_get_FP_double (cpu
, sn
);
7737 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7738 aarch64_set_FP_double (cpu
, sd
, fabs (value
));
7741 /* Float negative value. */
7743 fnegs (sim_cpu
*cpu
)
7745 unsigned sn
= INSTR (9, 5);
7746 unsigned sd
= INSTR (4, 0);
7748 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7749 aarch64_set_FP_float (cpu
, sd
, - aarch64_get_FP_float (cpu
, sn
));
7752 /* Double negative value. */
7754 fnegd (sim_cpu
*cpu
)
7756 unsigned sn
= INSTR (9, 5);
7757 unsigned sd
= INSTR (4, 0);
7759 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7760 aarch64_set_FP_double (cpu
, sd
, - aarch64_get_FP_double (cpu
, sn
));
7763 /* Float square root. */
7765 fsqrts (sim_cpu
*cpu
)
7767 unsigned sn
= INSTR (9, 5);
7768 unsigned sd
= INSTR (4, 0);
7770 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7771 aarch64_set_FP_float (cpu
, sd
, sqrtf (aarch64_get_FP_float (cpu
, sn
)));
7774 /* Double square root. */
7776 fsqrtd (sim_cpu
*cpu
)
7778 unsigned sn
= INSTR (9, 5);
7779 unsigned sd
= INSTR (4, 0);
7781 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7782 aarch64_set_FP_double (cpu
, sd
,
7783 sqrt (aarch64_get_FP_double (cpu
, sn
)));
7786 /* Convert double to float. */
7788 fcvtds (sim_cpu
*cpu
)
7790 unsigned sn
= INSTR (9, 5);
7791 unsigned sd
= INSTR (4, 0);
7793 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7794 aarch64_set_FP_float (cpu
, sd
, (float) aarch64_get_FP_double (cpu
, sn
));
7797 /* Convert float to double. */
7799 fcvtcpu (sim_cpu
*cpu
)
7801 unsigned sn
= INSTR (9, 5);
7802 unsigned sd
= INSTR (4, 0);
7804 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7805 aarch64_set_FP_double (cpu
, sd
, (double) aarch64_get_FP_float (cpu
, sn
));
7809 do_FRINT (sim_cpu
*cpu
)
7811 /* instr[31,23] = 0001 1110 0
7812 instr[22] = single(0)/double(1)
7814 instr[17,15] = rounding mode
7815 instr[14,10] = 10000
7817 instr[4,0] = dest */
7820 unsigned rs
= INSTR (9, 5);
7821 unsigned rd
= INSTR (4, 0);
7822 unsigned int rmode
= INSTR (17, 15);
7824 NYI_assert (31, 23, 0x03C);
7825 NYI_assert (21, 18, 0x9);
7826 NYI_assert (14, 10, 0x10);
7828 if (rmode
== 6 || rmode
== 7)
7829 /* FIXME: Add support for rmode == 6 exactness check. */
7830 rmode
= uimm (aarch64_get_FPSR (cpu
), 23, 22);
7832 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7835 double val
= aarch64_get_FP_double (cpu
, rs
);
7839 case 0: /* mode N: nearest or even. */
7841 double rval
= round (val
);
7843 if (val
- rval
== 0.5)
7845 if (((rval
/ 2.0) * 2.0) != rval
)
7849 aarch64_set_FP_double (cpu
, rd
, round (val
));
7853 case 1: /* mode P: towards +inf. */
7855 aarch64_set_FP_double (cpu
, rd
, trunc (val
));
7857 aarch64_set_FP_double (cpu
, rd
, round (val
));
7860 case 2: /* mode M: towards -inf. */
7862 aarch64_set_FP_double (cpu
, rd
, round (val
));
7864 aarch64_set_FP_double (cpu
, rd
, trunc (val
));
7867 case 3: /* mode Z: towards 0. */
7868 aarch64_set_FP_double (cpu
, rd
, trunc (val
));
7871 case 4: /* mode A: away from 0. */
7872 aarch64_set_FP_double (cpu
, rd
, round (val
));
7875 case 6: /* mode X: use FPCR with exactness check. */
7876 case 7: /* mode I: use FPCR mode. */
7884 val
= aarch64_get_FP_float (cpu
, rs
);
7888 case 0: /* mode N: nearest or even. */
7890 float rval
= roundf (val
);
7892 if (val
- rval
== 0.5)
7894 if (((rval
/ 2.0) * 2.0) != rval
)
7898 aarch64_set_FP_float (cpu
, rd
, rval
);
7902 case 1: /* mode P: towards +inf. */
7904 aarch64_set_FP_float (cpu
, rd
, truncf (val
));
7906 aarch64_set_FP_float (cpu
, rd
, roundf (val
));
7909 case 2: /* mode M: towards -inf. */
7911 aarch64_set_FP_float (cpu
, rd
, truncf (val
));
7913 aarch64_set_FP_float (cpu
, rd
, roundf (val
));
7916 case 3: /* mode Z: towards 0. */
7917 aarch64_set_FP_float (cpu
, rd
, truncf (val
));
7920 case 4: /* mode A: away from 0. */
7921 aarch64_set_FP_float (cpu
, rd
, roundf (val
));
7924 case 6: /* mode X: use FPCR with exactness check. */
7925 case 7: /* mode I: use FPCR mode. */
7933 /* Convert half to float. */
7935 do_FCVT_half_to_single (sim_cpu
*cpu
)
7937 unsigned rn
= INSTR (9, 5);
7938 unsigned rd
= INSTR (4, 0);
7940 NYI_assert (31, 10, 0x7B890);
7942 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7943 aarch64_set_FP_float (cpu
, rd
, (float) aarch64_get_FP_half (cpu
, rn
));
7946 /* Convert half to double. */
7948 do_FCVT_half_to_double (sim_cpu
*cpu
)
7950 unsigned rn
= INSTR (9, 5);
7951 unsigned rd
= INSTR (4, 0);
7953 NYI_assert (31, 10, 0x7B8B0);
7955 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7956 aarch64_set_FP_double (cpu
, rd
, (double) aarch64_get_FP_half (cpu
, rn
));
7960 do_FCVT_single_to_half (sim_cpu
*cpu
)
7962 unsigned rn
= INSTR (9, 5);
7963 unsigned rd
= INSTR (4, 0);
7965 NYI_assert (31, 10, 0x788F0);
7967 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7968 aarch64_set_FP_half (cpu
, rd
, aarch64_get_FP_float (cpu
, rn
));
7971 /* Convert double to half. */
7973 do_FCVT_double_to_half (sim_cpu
*cpu
)
7975 unsigned rn
= INSTR (9, 5);
7976 unsigned rd
= INSTR (4, 0);
7978 NYI_assert (31, 10, 0x798F0);
7980 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7981 aarch64_set_FP_half (cpu
, rd
, (float) aarch64_get_FP_double (cpu
, rn
));
7985 dexSimpleFPDataProc1Source (sim_cpu
*cpu
)
7987 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
7989 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
7992 instr[23,22] ==> type : 00 ==> source is single,
7993 01 ==> source is double
7995 11 ==> UNALLOC or source is half
7997 instr[20,15] ==> opcode : with type 00 or 01
7998 000000 ==> FMOV, 000001 ==> FABS,
7999 000010 ==> FNEG, 000011 ==> FSQRT,
8000 000100 ==> UNALLOC, 000101 ==> FCVT,(to single/double)
8001 000110 ==> UNALLOC, 000111 ==> FCVT (to half)
8002 001000 ==> FRINTN, 001001 ==> FRINTP,
8003 001010 ==> FRINTM, 001011 ==> FRINTZ,
8004 001100 ==> FRINTA, 001101 ==> UNALLOC
8005 001110 ==> FRINTX, 001111 ==> FRINTI
8007 000100 ==> FCVT (half-to-single)
8008 000101 ==> FCVT (half-to-double)
8009 instr[14,10] = 10000. */
8011 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
8012 uint32_t type
= INSTR (23, 22);
8013 uint32_t opcode
= INSTR (20, 15);
8021 do_FCVT_half_to_single (cpu
);
8022 else if (opcode
== 5)
8023 do_FCVT_half_to_double (cpu
);
8075 case 8: /* FRINTN etc. */
8087 do_FCVT_double_to_half (cpu
);
8089 do_FCVT_single_to_half (cpu
);
8100 /* 32 bit signed int to float. */
8102 scvtf32 (sim_cpu
*cpu
)
8104 unsigned rn
= INSTR (9, 5);
8105 unsigned sd
= INSTR (4, 0);
8107 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8108 aarch64_set_FP_float
8109 (cpu
, sd
, (float) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
));
8112 /* signed int to float. */
8114 scvtf (sim_cpu
*cpu
)
8116 unsigned rn
= INSTR (9, 5);
8117 unsigned sd
= INSTR (4, 0);
8119 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8120 aarch64_set_FP_float
8121 (cpu
, sd
, (float) aarch64_get_reg_s64 (cpu
, rn
, NO_SP
));
8124 /* 32 bit signed int to double. */
8126 scvtd32 (sim_cpu
*cpu
)
8128 unsigned rn
= INSTR (9, 5);
8129 unsigned sd
= INSTR (4, 0);
8131 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8132 aarch64_set_FP_double
8133 (cpu
, sd
, (double) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
));
8136 /* signed int to double. */
8138 scvtd (sim_cpu
*cpu
)
8140 unsigned rn
= INSTR (9, 5);
8141 unsigned sd
= INSTR (4, 0);
8143 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8144 aarch64_set_FP_double
8145 (cpu
, sd
, (double) aarch64_get_reg_s64 (cpu
, rn
, NO_SP
));
8148 static const float FLOAT_INT_MAX
= (float) INT_MAX
;
8149 static const float FLOAT_INT_MIN
= (float) INT_MIN
;
8150 static const double DOUBLE_INT_MAX
= (double) INT_MAX
;
8151 static const double DOUBLE_INT_MIN
= (double) INT_MIN
;
8152 static const float FLOAT_LONG_MAX
= (float) LONG_MAX
;
8153 static const float FLOAT_LONG_MIN
= (float) LONG_MIN
;
8154 static const double DOUBLE_LONG_MAX
= (double) LONG_MAX
;
8155 static const double DOUBLE_LONG_MIN
= (double) LONG_MIN
;
8159 static const float FLOAT_UINT_MAX
= (float) UINT_MAX
;
8160 static const float FLOAT_UINT_MIN
= (float) UINT_MIN
;
8161 static const double DOUBLE_UINT_MAX
= (double) UINT_MAX
;
8162 static const double DOUBLE_UINT_MIN
= (double) UINT_MIN
;
8163 static const float FLOAT_ULONG_MAX
= (float) ULONG_MAX
;
8164 static const float FLOAT_ULONG_MIN
= (float) ULONG_MIN
;
8165 static const double DOUBLE_ULONG_MAX
= (double) ULONG_MAX
;
8166 static const double DOUBLE_ULONG_MIN
= (double) ULONG_MIN
;
8168 /* Check for FP exception conditions:
8171 Out of Range raises IO and IX and saturates value
8172 Denormal raises ID and IX and sets to zero. */
8173 #define RAISE_EXCEPTIONS(F, VALUE, FTYPE, ITYPE) \
8176 switch (fpclassify (F)) \
8180 aarch64_set_FPSR (cpu, IO); \
8182 VALUE = ITYPE##_MAX; \
8184 VALUE = ITYPE##_MIN; \
8188 if (F >= FTYPE##_##ITYPE##_MAX) \
8190 aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX); \
8191 VALUE = ITYPE##_MAX; \
8193 else if (F <= FTYPE##_##ITYPE##_MIN) \
8195 aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX); \
8196 VALUE = ITYPE##_MIN; \
8200 case FP_SUBNORMAL: \
8201 aarch64_set_FPSR_bits (cpu, IO | IX | ID, IX | ID); \
8213 /* 32 bit convert float to signed int truncate towards zero. */
8215 fcvtszs32 (sim_cpu
*cpu
)
8217 unsigned sn
= INSTR (9, 5);
8218 unsigned rd
= INSTR (4, 0);
8219 /* TODO : check that this rounds toward zero. */
8220 float f
= aarch64_get_FP_float (cpu
, sn
);
8221 int32_t value
= (int32_t) f
;
8223 RAISE_EXCEPTIONS (f
, value
, FLOAT
, INT
);
8225 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8226 /* Avoid sign extension to 64 bit. */
8227 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) value
);
8230 /* 64 bit convert float to signed int truncate towards zero. */
8232 fcvtszs (sim_cpu
*cpu
)
8234 unsigned sn
= INSTR (9, 5);
8235 unsigned rd
= INSTR (4, 0);
8236 float f
= aarch64_get_FP_float (cpu
, sn
);
8237 int64_t value
= (int64_t) f
;
8239 RAISE_EXCEPTIONS (f
, value
, FLOAT
, LONG
);
8241 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8242 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, value
);
8245 /* 32 bit convert double to signed int truncate towards zero. */
8247 fcvtszd32 (sim_cpu
*cpu
)
8249 unsigned sn
= INSTR (9, 5);
8250 unsigned rd
= INSTR (4, 0);
8251 /* TODO : check that this rounds toward zero. */
8252 double d
= aarch64_get_FP_double (cpu
, sn
);
8253 int32_t value
= (int32_t) d
;
8255 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, INT
);
8257 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8258 /* Avoid sign extension to 64 bit. */
8259 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) value
);
8262 /* 64 bit convert double to signed int truncate towards zero. */
8264 fcvtszd (sim_cpu
*cpu
)
8266 unsigned sn
= INSTR (9, 5);
8267 unsigned rd
= INSTR (4, 0);
8268 /* TODO : check that this rounds toward zero. */
8269 double d
= aarch64_get_FP_double (cpu
, sn
);
8272 value
= (int64_t) d
;
8274 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, LONG
);
8276 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8277 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, value
);
8281 do_fcvtzu (sim_cpu
*cpu
)
8283 /* instr[31] = size: 32-bit (0), 64-bit (1)
8284 instr[30,23] = 00111100
8285 instr[22] = type: single (0)/ double (1)
8286 instr[21] = enable (0)/disable(1) precision
8287 instr[20,16] = 11001
8288 instr[15,10] = precision
8292 unsigned rs
= INSTR (9, 5);
8293 unsigned rd
= INSTR (4, 0);
8295 NYI_assert (30, 23, 0x3C);
8296 NYI_assert (20, 16, 0x19);
8298 if (INSTR (21, 21) != 1)
8299 /* Convert to fixed point. */
8302 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8305 /* Convert to unsigned 64-bit integer. */
8308 double d
= aarch64_get_FP_double (cpu
, rs
);
8309 uint64_t value
= (uint64_t) d
;
8311 /* Do not raise an exception if we have reached ULONG_MAX. */
8312 if (value
!= (1UL << 63))
8313 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, ULONG
);
8315 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
8319 float f
= aarch64_get_FP_float (cpu
, rs
);
8320 uint64_t value
= (uint64_t) f
;
8322 /* Do not raise an exception if we have reached ULONG_MAX. */
8323 if (value
!= (1UL << 63))
8324 RAISE_EXCEPTIONS (f
, value
, FLOAT
, ULONG
);
8326 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
8333 /* Convert to unsigned 32-bit integer. */
8336 double d
= aarch64_get_FP_double (cpu
, rs
);
8338 value
= (uint32_t) d
;
8339 /* Do not raise an exception if we have reached UINT_MAX. */
8340 if (value
!= (1UL << 31))
8341 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, UINT
);
8345 float f
= aarch64_get_FP_float (cpu
, rs
);
8347 value
= (uint32_t) f
;
8348 /* Do not raise an exception if we have reached UINT_MAX. */
8349 if (value
!= (1UL << 31))
8350 RAISE_EXCEPTIONS (f
, value
, FLOAT
, UINT
);
8353 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
8358 do_UCVTF (sim_cpu
*cpu
)
8360 /* instr[31] = size: 32-bit (0), 64-bit (1)
8361 instr[30,23] = 001 1110 0
8362 instr[22] = type: single (0)/ double (1)
8363 instr[21] = enable (0)/disable(1) precision
8364 instr[20,16] = 0 0011
8365 instr[15,10] = precision
8369 unsigned rs
= INSTR (9, 5);
8370 unsigned rd
= INSTR (4, 0);
8372 NYI_assert (30, 23, 0x3C);
8373 NYI_assert (20, 16, 0x03);
8375 if (INSTR (21, 21) != 1)
8378 /* FIXME: Add exception raising. */
8379 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8382 uint64_t value
= aarch64_get_reg_u64 (cpu
, rs
, NO_SP
);
8385 aarch64_set_FP_double (cpu
, rd
, (double) value
);
8387 aarch64_set_FP_float (cpu
, rd
, (float) value
);
8391 uint32_t value
= aarch64_get_reg_u32 (cpu
, rs
, NO_SP
);
8394 aarch64_set_FP_double (cpu
, rd
, (double) value
);
8396 aarch64_set_FP_float (cpu
, rd
, (float) value
);
8401 float_vector_move (sim_cpu
*cpu
)
8403 /* instr[31,17] == 100 1111 0101 0111
8404 instr[16] ==> direction 0=> to GR, 1=> from GR
8406 instr[9,5] ==> source
8407 instr[4,0] ==> dest. */
8409 unsigned rn
= INSTR (9, 5);
8410 unsigned rd
= INSTR (4, 0);
8412 NYI_assert (31, 17, 0x4F57);
8414 if (INSTR (15, 10) != 0)
8417 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8419 aarch64_set_vec_u64 (cpu
, rd
, 1, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
8421 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, aarch64_get_vec_u64 (cpu
, rn
, 1));
8425 dexSimpleFPIntegerConvert (sim_cpu
*cpu
)
8427 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
8429 instr[29] = S : 0 ==> OK, 1 ==> UNALLOC
8432 instr[23,22] = type : 00 ==> single, 01 ==> double, 1x ==> UNALLOC
8434 instr[20,19] = rmode
8435 instr[18,16] = opcode
8436 instr[15,10] = 10 0000 */
8438 uint32_t rmode_opcode
;
8444 if (INSTR (31, 17) == 0x4F57)
8446 float_vector_move (cpu
);
8450 size
= INSTR (31, 31);
8455 type
= INSTR (23, 22);
8459 rmode_opcode
= INSTR (20, 16);
8460 size_type
= (size
<< 1) | type
; /* 0==32f, 1==32d, 2==64f, 3==64d. */
8462 switch (rmode_opcode
)
8464 case 2: /* SCVTF. */
8467 case 0: scvtf32 (cpu
); return;
8468 case 1: scvtd32 (cpu
); return;
8469 case 2: scvtf (cpu
); return;
8470 case 3: scvtd (cpu
); return;
8473 case 6: /* FMOV GR, Vec. */
8476 case 0: gfmovs (cpu
); return;
8477 case 3: gfmovd (cpu
); return;
8478 default: HALT_UNALLOC
;
8481 case 7: /* FMOV vec, GR. */
8484 case 0: fgmovs (cpu
); return;
8485 case 3: fgmovd (cpu
); return;
8486 default: HALT_UNALLOC
;
8489 case 24: /* FCVTZS. */
8492 case 0: fcvtszs32 (cpu
); return;
8493 case 1: fcvtszd32 (cpu
); return;
8494 case 2: fcvtszs (cpu
); return;
8495 case 3: fcvtszd (cpu
); return;
8498 case 25: do_fcvtzu (cpu
); return;
8499 case 3: do_UCVTF (cpu
); return;
8501 case 0: /* FCVTNS. */
8502 case 1: /* FCVTNU. */
8503 case 4: /* FCVTAS. */
8504 case 5: /* FCVTAU. */
8505 case 8: /* FCVPTS. */
8506 case 9: /* FCVTPU. */
8507 case 16: /* FCVTMS. */
8508 case 17: /* FCVTMU. */
8515 set_flags_for_float_compare (sim_cpu
*cpu
, float fvalue1
, float fvalue2
)
8519 /* FIXME: Add exception raising. */
8520 if (isnan (fvalue1
) || isnan (fvalue2
))
8522 else if (isinf (fvalue1
) && isinf (fvalue2
))
8524 /* Subtracting two infinities may give a NaN. We only need to compare
8525 the signs, which we can get from isinf. */
8526 int result
= isinf (fvalue1
) - isinf (fvalue2
);
8530 else if (result
< 0)
8532 else /* (result > 0). */
8537 float result
= fvalue1
- fvalue2
;
8541 else if (result
< 0)
8543 else /* (result > 0). */
8547 aarch64_set_CPSR (cpu
, flags
);
8551 fcmps (sim_cpu
*cpu
)
8553 unsigned sm
= INSTR (20, 16);
8554 unsigned sn
= INSTR ( 9, 5);
8556 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8557 float fvalue2
= aarch64_get_FP_float (cpu
, sm
);
8559 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8560 set_flags_for_float_compare (cpu
, fvalue1
, fvalue2
);
8563 /* Float compare to zero -- Invalid Operation exception
8564 only on signaling NaNs. */
8566 fcmpzs (sim_cpu
*cpu
)
8568 unsigned sn
= INSTR ( 9, 5);
8569 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8571 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8572 set_flags_for_float_compare (cpu
, fvalue1
, 0.0f
);
8575 /* Float compare -- Invalid Operation exception on all NaNs. */
8577 fcmpes (sim_cpu
*cpu
)
8579 unsigned sm
= INSTR (20, 16);
8580 unsigned sn
= INSTR ( 9, 5);
8582 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8583 float fvalue2
= aarch64_get_FP_float (cpu
, sm
);
8585 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8586 set_flags_for_float_compare (cpu
, fvalue1
, fvalue2
);
8589 /* Float compare to zero -- Invalid Operation exception on all NaNs. */
8591 fcmpzes (sim_cpu
*cpu
)
8593 unsigned sn
= INSTR ( 9, 5);
8594 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8596 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8597 set_flags_for_float_compare (cpu
, fvalue1
, 0.0f
);
8601 set_flags_for_double_compare (sim_cpu
*cpu
, double dval1
, double dval2
)
8605 /* FIXME: Add exception raising. */
8606 if (isnan (dval1
) || isnan (dval2
))
8608 else if (isinf (dval1
) && isinf (dval2
))
8610 /* Subtracting two infinities may give a NaN. We only need to compare
8611 the signs, which we can get from isinf. */
8612 int result
= isinf (dval1
) - isinf (dval2
);
8616 else if (result
< 0)
8618 else /* (result > 0). */
8623 double result
= dval1
- dval2
;
8627 else if (result
< 0)
8629 else /* (result > 0). */
8633 aarch64_set_CPSR (cpu
, flags
);
8636 /* Double compare -- Invalid Operation exception only on signaling NaNs. */
8638 fcmpd (sim_cpu
*cpu
)
8640 unsigned sm
= INSTR (20, 16);
8641 unsigned sn
= INSTR ( 9, 5);
8643 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8644 double dvalue2
= aarch64_get_FP_double (cpu
, sm
);
8646 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8647 set_flags_for_double_compare (cpu
, dvalue1
, dvalue2
);
8650 /* Double compare to zero -- Invalid Operation exception
8651 only on signaling NaNs. */
8653 fcmpzd (sim_cpu
*cpu
)
8655 unsigned sn
= INSTR ( 9, 5);
8656 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8658 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8659 set_flags_for_double_compare (cpu
, dvalue1
, 0.0);
8662 /* Double compare -- Invalid Operation exception on all NaNs. */
8664 fcmped (sim_cpu
*cpu
)
8666 unsigned sm
= INSTR (20, 16);
8667 unsigned sn
= INSTR ( 9, 5);
8669 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8670 double dvalue2
= aarch64_get_FP_double (cpu
, sm
);
8672 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8673 set_flags_for_double_compare (cpu
, dvalue1
, dvalue2
);
8676 /* Double compare to zero -- Invalid Operation exception on all NaNs. */
8678 fcmpzed (sim_cpu
*cpu
)
8680 unsigned sn
= INSTR ( 9, 5);
8681 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8683 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8684 set_flags_for_double_compare (cpu
, dvalue1
, 0.0);
8688 dexSimpleFPCompare (sim_cpu
*cpu
)
8690 /* assert instr[28,25] == 1111
8691 instr[30:24:21:13,10] = 0011000
8692 instr[31] = M : 0 ==> OK, 1 ==> UNALLOC
8693 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
8694 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
8695 instr[15,14] ==> op : 00 ==> OK, ow ==> UNALLOC
8696 instr[4,0] ==> opcode2 : 00000 ==> FCMP, 10000 ==> FCMPE,
8697 01000 ==> FCMPZ, 11000 ==> FCMPEZ,
8700 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
8701 uint32_t type
= INSTR (23, 22);
8702 uint32_t op
= INSTR (15, 14);
8703 uint32_t op2_2_0
= INSTR (2, 0);
8717 /* dispatch on type and top 2 bits of opcode. */
8718 dispatch
= (type
<< 2) | INSTR (4, 3);
8722 case 0: fcmps (cpu
); return;
8723 case 1: fcmpzs (cpu
); return;
8724 case 2: fcmpes (cpu
); return;
8725 case 3: fcmpzes (cpu
); return;
8726 case 4: fcmpd (cpu
); return;
8727 case 5: fcmpzd (cpu
); return;
8728 case 6: fcmped (cpu
); return;
8729 case 7: fcmpzed (cpu
); return;
8734 do_scalar_FADDP (sim_cpu
*cpu
)
8736 /* instr [31,23] = 0111 1110 0
8737 instr [22] = single(0)/double(1)
8738 instr [21,10] = 11 0000 1101 10
8740 instr [4,0] = Fd. */
8742 unsigned Fn
= INSTR (9, 5);
8743 unsigned Fd
= INSTR (4, 0);
8745 NYI_assert (31, 23, 0x0FC);
8746 NYI_assert (21, 10, 0xC36);
8748 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8751 double val1
= aarch64_get_vec_double (cpu
, Fn
, 0);
8752 double val2
= aarch64_get_vec_double (cpu
, Fn
, 1);
8754 aarch64_set_FP_double (cpu
, Fd
, val1
+ val2
);
8758 float val1
= aarch64_get_vec_float (cpu
, Fn
, 0);
8759 float val2
= aarch64_get_vec_float (cpu
, Fn
, 1);
8761 aarch64_set_FP_float (cpu
, Fd
, val1
+ val2
);
8765 /* Floating point absolute difference. */
8768 do_scalar_FABD (sim_cpu
*cpu
)
8770 /* instr [31,23] = 0111 1110 1
8771 instr [22] = float(0)/double(1)
8774 instr [15,10] = 1101 01
8776 instr [4, 0] = Rd. */
8778 unsigned rm
= INSTR (20, 16);
8779 unsigned rn
= INSTR (9, 5);
8780 unsigned rd
= INSTR (4, 0);
8782 NYI_assert (31, 23, 0x0FD);
8783 NYI_assert (21, 21, 1);
8784 NYI_assert (15, 10, 0x35);
8786 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8788 aarch64_set_FP_double (cpu
, rd
,
8789 fabs (aarch64_get_FP_double (cpu
, rn
)
8790 - aarch64_get_FP_double (cpu
, rm
)));
8792 aarch64_set_FP_float (cpu
, rd
,
8793 fabsf (aarch64_get_FP_float (cpu
, rn
)
8794 - aarch64_get_FP_float (cpu
, rm
)));
8798 do_scalar_CMGT (sim_cpu
*cpu
)
8800 /* instr [31,21] = 0101 1110 111
8802 instr [15,10] = 00 1101
8804 instr [4, 0] = Rd. */
8806 unsigned rm
= INSTR (20, 16);
8807 unsigned rn
= INSTR (9, 5);
8808 unsigned rd
= INSTR (4, 0);
8810 NYI_assert (31, 21, 0x2F7);
8811 NYI_assert (15, 10, 0x0D);
8813 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8814 aarch64_set_vec_u64 (cpu
, rd
, 0,
8815 aarch64_get_vec_u64 (cpu
, rn
, 0) >
8816 aarch64_get_vec_u64 (cpu
, rm
, 0) ? -1L : 0L);
8820 do_scalar_USHR (sim_cpu
*cpu
)
8822 /* instr [31,23] = 0111 1111 0
8823 instr [22,16] = shift amount
8824 instr [15,10] = 0000 01
8826 instr [4, 0] = Rd. */
8828 unsigned amount
= 128 - INSTR (22, 16);
8829 unsigned rn
= INSTR (9, 5);
8830 unsigned rd
= INSTR (4, 0);
8832 NYI_assert (31, 23, 0x0FE);
8833 NYI_assert (15, 10, 0x01);
8835 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8836 aarch64_set_vec_u64 (cpu
, rd
, 0,
8837 aarch64_get_vec_u64 (cpu
, rn
, 0) >> amount
);
8841 do_scalar_SSHL (sim_cpu
*cpu
)
8843 /* instr [31,21] = 0101 1110 111
8845 instr [15,10] = 0100 01
8847 instr [4, 0] = Rd. */
8849 unsigned rm
= INSTR (20, 16);
8850 unsigned rn
= INSTR (9, 5);
8851 unsigned rd
= INSTR (4, 0);
8852 signed int shift
= aarch64_get_vec_s8 (cpu
, rm
, 0);
8854 NYI_assert (31, 21, 0x2F7);
8855 NYI_assert (15, 10, 0x11);
8857 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8859 aarch64_set_vec_s64 (cpu
, rd
, 0,
8860 aarch64_get_vec_s64 (cpu
, rn
, 0) << shift
);
8862 aarch64_set_vec_s64 (cpu
, rd
, 0,
8863 aarch64_get_vec_s64 (cpu
, rn
, 0) >> - shift
);
8867 do_scalar_shift (sim_cpu
*cpu
)
8869 /* instr [31,23] = 0101 1111 0
8870 instr [22,16] = shift amount
8871 instr [15,10] = 0101 01 [SHL]
8872 instr [15,10] = 0000 01 [SSHR]
8874 instr [4, 0] = Rd. */
8876 unsigned rn
= INSTR (9, 5);
8877 unsigned rd
= INSTR (4, 0);
8880 NYI_assert (31, 23, 0x0BE);
8882 if (INSTR (22, 22) == 0)
8885 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8886 switch (INSTR (15, 10))
8888 case 0x01: /* SSHR */
8889 amount
= 128 - INSTR (22, 16);
8890 aarch64_set_vec_s64 (cpu
, rd
, 0,
8891 aarch64_get_vec_s64 (cpu
, rn
, 0) >> amount
);
8893 case 0x15: /* SHL */
8894 amount
= INSTR (22, 16) - 64;
8895 aarch64_set_vec_u64 (cpu
, rd
, 0,
8896 aarch64_get_vec_u64 (cpu
, rn
, 0) << amount
);
8903 /* FCMEQ FCMGT FCMGE. */
8905 do_scalar_FCM (sim_cpu
*cpu
)
8907 /* instr [31,30] = 01
8909 instr [28,24] = 1 1110
8914 instr [15,12] = 1110
8918 instr [4, 0] = Rd. */
8920 unsigned rm
= INSTR (20, 16);
8921 unsigned rn
= INSTR (9, 5);
8922 unsigned rd
= INSTR (4, 0);
8923 unsigned EUac
= (INSTR (23, 23) << 2) | (INSTR (29, 29) << 1) | INSTR (11, 11);
8928 NYI_assert (31, 30, 1);
8929 NYI_assert (28, 24, 0x1E);
8930 NYI_assert (21, 21, 1);
8931 NYI_assert (15, 12, 0xE);
8932 NYI_assert (10, 10, 1);
8934 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8937 double val1
= aarch64_get_FP_double (cpu
, rn
);
8938 double val2
= aarch64_get_FP_double (cpu
, rm
);
8943 result
= val1
== val2
;
8951 result
= val1
>= val2
;
8959 result
= val1
> val2
;
8966 aarch64_set_vec_u32 (cpu
, rd
, 0, result
? -1 : 0);
8970 val1
= aarch64_get_FP_float (cpu
, rn
);
8971 val2
= aarch64_get_FP_float (cpu
, rm
);
8976 result
= val1
== val2
;
8980 val1
= fabsf (val1
);
8981 val2
= fabsf (val2
);
8984 result
= val1
>= val2
;
8988 val1
= fabsf (val1
);
8989 val2
= fabsf (val2
);
8992 result
= val1
> val2
;
8999 aarch64_set_vec_u32 (cpu
, rd
, 0, result
? -1 : 0);
9002 /* An alias of DUP. */
9004 do_scalar_MOV (sim_cpu
*cpu
)
9006 /* instr [31,21] = 0101 1110 000
9007 instr [20,16] = imm5
9008 instr [15,10] = 0000 01
9010 instr [4, 0] = Rd. */
9012 unsigned rn
= INSTR (9, 5);
9013 unsigned rd
= INSTR (4, 0);
9016 NYI_assert (31, 21, 0x2F0);
9017 NYI_assert (15, 10, 0x01);
9019 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9023 index
= INSTR (20, 17);
9025 (cpu
, rd
, 0, aarch64_get_vec_u8 (cpu
, rn
, index
));
9027 else if (INSTR (17, 17))
9030 index
= INSTR (20, 18);
9032 (cpu
, rd
, 0, aarch64_get_vec_u16 (cpu
, rn
, index
));
9034 else if (INSTR (18, 18))
9037 index
= INSTR (20, 19);
9039 (cpu
, rd
, 0, aarch64_get_vec_u32 (cpu
, rn
, index
));
9041 else if (INSTR (19, 19))
9044 index
= INSTR (20, 20);
9046 (cpu
, rd
, 0, aarch64_get_vec_u64 (cpu
, rn
, index
));
9053 do_scalar_NEG (sim_cpu
*cpu
)
9055 /* instr [31,10] = 0111 1110 1110 0000 1011 10
9057 instr [4, 0] = Rd. */
9059 unsigned rn
= INSTR (9, 5);
9060 unsigned rd
= INSTR (4, 0);
9062 NYI_assert (31, 10, 0x1FB82E);
9064 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9065 aarch64_set_vec_u64 (cpu
, rd
, 0, - aarch64_get_vec_u64 (cpu
, rn
, 0));
9069 do_scalar_USHL (sim_cpu
*cpu
)
9071 /* instr [31,21] = 0111 1110 111
9073 instr [15,10] = 0100 01
9075 instr [4, 0] = Rd. */
9077 unsigned rm
= INSTR (20, 16);
9078 unsigned rn
= INSTR (9, 5);
9079 unsigned rd
= INSTR (4, 0);
9080 signed int shift
= aarch64_get_vec_s8 (cpu
, rm
, 0);
9082 NYI_assert (31, 21, 0x3F7);
9083 NYI_assert (15, 10, 0x11);
9085 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9087 aarch64_set_vec_u64 (cpu
, rd
, 0, aarch64_get_vec_u64 (cpu
, rn
, 0) << shift
);
9089 aarch64_set_vec_u64 (cpu
, rd
, 0, aarch64_get_vec_u64 (cpu
, rn
, 0) >> - shift
);
9093 do_double_add (sim_cpu
*cpu
)
9095 /* instr [31,21] = 0101 1110 111
9097 instr [15,10] = 1000 01
9099 instr [4,0] = Fd. */
9106 NYI_assert (31, 21, 0x2F7);
9107 NYI_assert (15, 10, 0x21);
9111 Fn
= INSTR (20, 16);
9113 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9114 val1
= aarch64_get_FP_double (cpu
, Fm
);
9115 val2
= aarch64_get_FP_double (cpu
, Fn
);
9117 aarch64_set_FP_double (cpu
, Fd
, val1
+ val2
);
9121 do_scalar_UCVTF (sim_cpu
*cpu
)
9123 /* instr [31,23] = 0111 1110 0
9124 instr [22] = single(0)/double(1)
9125 instr [21,10] = 10 0001 1101 10
9127 instr [4,0] = rd. */
9129 unsigned rn
= INSTR (9, 5);
9130 unsigned rd
= INSTR (4, 0);
9132 NYI_assert (31, 23, 0x0FC);
9133 NYI_assert (21, 10, 0x876);
9135 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9138 uint64_t val
= aarch64_get_vec_u64 (cpu
, rn
, 0);
9140 aarch64_set_vec_double (cpu
, rd
, 0, (double) val
);
9144 uint32_t val
= aarch64_get_vec_u32 (cpu
, rn
, 0);
9146 aarch64_set_vec_float (cpu
, rd
, 0, (float) val
);
9151 do_scalar_vec (sim_cpu
*cpu
)
9153 /* instr [30] = 1. */
9154 /* instr [28,25] = 1111. */
9155 switch (INSTR (31, 23))
9158 switch (INSTR (15, 10))
9160 case 0x01: do_scalar_MOV (cpu
); return;
9161 case 0x39: do_scalar_FCM (cpu
); return;
9162 case 0x3B: do_scalar_FCM (cpu
); return;
9166 case 0xBE: do_scalar_shift (cpu
); return;
9169 switch (INSTR (15, 10))
9172 switch (INSTR (21, 16))
9174 case 0x30: do_scalar_FADDP (cpu
); return;
9175 case 0x21: do_scalar_UCVTF (cpu
); return;
9178 case 0x39: do_scalar_FCM (cpu
); return;
9179 case 0x3B: do_scalar_FCM (cpu
); return;
9184 switch (INSTR (15, 10))
9186 case 0x0D: do_scalar_CMGT (cpu
); return;
9187 case 0x11: do_scalar_USHL (cpu
); return;
9188 case 0x2E: do_scalar_NEG (cpu
); return;
9189 case 0x35: do_scalar_FABD (cpu
); return;
9190 case 0x39: do_scalar_FCM (cpu
); return;
9191 case 0x3B: do_scalar_FCM (cpu
); return;
9196 case 0xFE: do_scalar_USHR (cpu
); return;
9199 switch (INSTR (15, 10))
9201 case 0x21: do_double_add (cpu
); return;
9202 case 0x11: do_scalar_SSHL (cpu
); return;
9213 dexAdvSIMD1 (sim_cpu
*cpu
)
9215 /* instr [28,25] = 1 111. */
9217 /* We are currently only interested in the basic
9218 scalar fp routines which all have bit 30 = 0. */
9220 do_scalar_vec (cpu
);
9222 /* instr[24] is set for FP data processing 3-source and clear for
9223 all other basic scalar fp instruction groups. */
9224 else if (INSTR (24, 24))
9225 dexSimpleFPDataProc3Source (cpu
);
9227 /* instr[21] is clear for floating <-> fixed conversions and set for
9228 all other basic scalar fp instruction groups. */
9229 else if (!INSTR (21, 21))
9230 dexSimpleFPFixedConvert (cpu
);
9232 /* instr[11,10] : 01 ==> cond compare, 10 ==> Data Proc 2 Source
9233 11 ==> cond select, 00 ==> other. */
9235 switch (INSTR (11, 10))
9237 case 1: dexSimpleFPCondCompare (cpu
); return;
9238 case 2: dexSimpleFPDataProc2Source (cpu
); return;
9239 case 3: dexSimpleFPCondSelect (cpu
); return;
9242 /* Now an ordered cascade of tests.
9243 FP immediate has instr [12] == 1.
9244 FP compare has instr [13] == 1.
9245 FP Data Proc 1 Source has instr [14] == 1.
9246 FP floating <--> integer conversions has instr [15] == 0. */
9248 dexSimpleFPImmediate (cpu
);
9250 else if (INSTR (13, 13))
9251 dexSimpleFPCompare (cpu
);
9253 else if (INSTR (14, 14))
9254 dexSimpleFPDataProc1Source (cpu
);
9256 else if (!INSTR (15, 15))
9257 dexSimpleFPIntegerConvert (cpu
);
9260 /* If we get here then instr[15] == 1 which means UNALLOC. */
9265 /* PC relative addressing. */
9268 pcadr (sim_cpu
*cpu
)
9270 /* instr[31] = op : 0 ==> ADR, 1 ==> ADRP
9271 instr[30,29] = immlo
9272 instr[23,5] = immhi. */
9274 unsigned rd
= INSTR (4, 0);
9275 uint32_t isPage
= INSTR (31, 31);
9276 union { int64_t u64
; uint64_t s64
; } imm
;
9279 imm
.s64
= simm64 (aarch64_get_instr (cpu
), 23, 5);
9281 offset
= (offset
<< 2) | INSTR (30, 29);
9283 address
= aarch64_get_PC (cpu
);
9291 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9292 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, address
+ offset
);
9295 /* Specific decode and execute for group Data Processing Immediate. */
9298 dexPCRelAddressing (sim_cpu
*cpu
)
9300 /* assert instr[28,24] = 10000. */
9304 /* Immediate logical.
9305 The bimm32/64 argument is constructed by replicating a 2, 4, 8,
9306 16, 32 or 64 bit sequence pulled out at decode and possibly
9309 N.B. the output register (dest) can normally be Xn or SP
9310 the exception occurs for flag setting instructions which may
9311 only use Xn for the output (dest). The input register can
9314 /* 32 bit and immediate. */
9316 and32 (sim_cpu
*cpu
, uint32_t bimm
)
9318 unsigned rn
= INSTR (9, 5);
9319 unsigned rd
= INSTR (4, 0);
9321 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9322 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9323 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
) & bimm
);
9326 /* 64 bit and immediate. */
9328 and64 (sim_cpu
*cpu
, uint64_t bimm
)
9330 unsigned rn
= INSTR (9, 5);
9331 unsigned rd
= INSTR (4, 0);
9333 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9334 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9335 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) & bimm
);
9338 /* 32 bit and immediate set flags. */
9340 ands32 (sim_cpu
*cpu
, uint32_t bimm
)
9342 unsigned rn
= INSTR (9, 5);
9343 unsigned rd
= INSTR (4, 0);
9345 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9346 uint32_t value2
= bimm
;
9348 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9349 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9350 set_flags_for_binop32 (cpu
, value1
& value2
);
9353 /* 64 bit and immediate set flags. */
9355 ands64 (sim_cpu
*cpu
, uint64_t bimm
)
9357 unsigned rn
= INSTR (9, 5);
9358 unsigned rd
= INSTR (4, 0);
9360 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9361 uint64_t value2
= bimm
;
9363 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9364 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9365 set_flags_for_binop64 (cpu
, value1
& value2
);
9368 /* 32 bit exclusive or immediate. */
9370 eor32 (sim_cpu
*cpu
, uint32_t bimm
)
9372 unsigned rn
= INSTR (9, 5);
9373 unsigned rd
= INSTR (4, 0);
9375 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9376 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9377 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
) ^ bimm
);
9380 /* 64 bit exclusive or immediate. */
9382 eor64 (sim_cpu
*cpu
, uint64_t bimm
)
9384 unsigned rn
= INSTR (9, 5);
9385 unsigned rd
= INSTR (4, 0);
9387 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9388 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9389 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) ^ bimm
);
9392 /* 32 bit or immediate. */
9394 orr32 (sim_cpu
*cpu
, uint32_t bimm
)
9396 unsigned rn
= INSTR (9, 5);
9397 unsigned rd
= INSTR (4, 0);
9399 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9400 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9401 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
) | bimm
);
9404 /* 64 bit or immediate. */
9406 orr64 (sim_cpu
*cpu
, uint64_t bimm
)
9408 unsigned rn
= INSTR (9, 5);
9409 unsigned rd
= INSTR (4, 0);
9411 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9412 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9413 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) | bimm
);
9416 /* Logical shifted register.
9417 These allow an optional LSL, ASR, LSR or ROR to the second source
9418 register with a count up to the register bit count.
9419 N.B register args may not be SP. */
9421 /* 32 bit AND shifted register. */
9423 and32_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_u32 (cpu
, rn
, NO_SP
)
9432 & shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9435 /* 64 bit AND shifted register. */
9437 and64_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 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9445 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9446 & shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9449 /* 32 bit AND shifted register setting flags. */
9451 ands32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9453 unsigned rm
= INSTR (20, 16);
9454 unsigned rn
= INSTR (9, 5);
9455 unsigned rd
= INSTR (4, 0);
9457 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9458 uint32_t value2
= shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
9461 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9462 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9463 set_flags_for_binop32 (cpu
, value1
& value2
);
9466 /* 64 bit AND shifted register setting flags. */
9468 ands64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9470 unsigned rm
= INSTR (20, 16);
9471 unsigned rn
= INSTR (9, 5);
9472 unsigned rd
= INSTR (4, 0);
9474 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9475 uint64_t value2
= shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
9478 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9479 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9480 set_flags_for_binop64 (cpu
, value1
& value2
);
9483 /* 32 bit BIC shifted register. */
9485 bic32_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_u32 (cpu
, rn
, NO_SP
)
9494 & ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9497 /* 64 bit BIC shifted register. */
9499 bic64_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 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9507 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9508 & ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9511 /* 32 bit BIC shifted register setting flags. */
9513 bics32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9515 unsigned rm
= INSTR (20, 16);
9516 unsigned rn
= INSTR (9, 5);
9517 unsigned rd
= INSTR (4, 0);
9519 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9520 uint32_t value2
= ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
9523 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9524 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9525 set_flags_for_binop32 (cpu
, value1
& value2
);
9528 /* 64 bit BIC shifted register setting flags. */
9530 bics64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9532 unsigned rm
= INSTR (20, 16);
9533 unsigned rn
= INSTR (9, 5);
9534 unsigned rd
= INSTR (4, 0);
9536 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9537 uint64_t value2
= ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
9540 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9541 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9542 set_flags_for_binop64 (cpu
, value1
& value2
);
9545 /* 32 bit EON shifted register. */
9547 eon32_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_u32 (cpu
, rn
, NO_SP
)
9556 ^ ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9559 /* 64 bit EON shifted register. */
9561 eon64_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_u64 (cpu
, rn
, NO_SP
)
9570 ^ ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9573 /* 32 bit EOR shifted register. */
9575 eor32_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_u32 (cpu
, rn
, NO_SP
)
9584 ^ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9587 /* 64 bit EOR shifted register. */
9589 eor64_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_u64 (cpu
, rn
, NO_SP
)
9598 ^ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9601 /* 32 bit ORR shifted register. */
9603 orr32_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_u32 (cpu
, rn
, NO_SP
)
9612 | shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9615 /* 64 bit ORR shifted register. */
9617 orr64_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_u64 (cpu
, rn
, NO_SP
)
9626 | shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9629 /* 32 bit ORN shifted register. */
9631 orn32_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_u32 (cpu
, rn
, NO_SP
)
9640 | ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9643 /* 64 bit ORN shifted register. */
9645 orn64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9647 unsigned rm
= INSTR (20, 16);
9648 unsigned rn
= INSTR (9, 5);
9649 unsigned rd
= INSTR (4, 0);
9651 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9653 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9654 | ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9658 dexLogicalImmediate (sim_cpu
*cpu
)
9660 /* assert instr[28,23] = 1001000
9661 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9662 instr[30,29] = op : 0 ==> AND, 1 ==> ORR, 2 ==> EOR, 3 ==> ANDS
9663 instr[22] = N : used to construct immediate mask
9669 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
9670 uint32_t size
= INSTR (31, 31);
9671 uint32_t N
= INSTR (22, 22);
9672 /* uint32_t immr = INSTR (21, 16);. */
9673 /* uint32_t imms = INSTR (15, 10);. */
9674 uint32_t index
= INSTR (22, 10);
9675 uint64_t bimm64
= LITable
[index
];
9676 uint32_t dispatch
= INSTR (30, 29);
9686 uint32_t bimm
= (uint32_t) bimm64
;
9690 case 0: and32 (cpu
, bimm
); return;
9691 case 1: orr32 (cpu
, bimm
); return;
9692 case 2: eor32 (cpu
, bimm
); return;
9693 case 3: ands32 (cpu
, bimm
); return;
9700 case 0: and64 (cpu
, bimm64
); return;
9701 case 1: orr64 (cpu
, bimm64
); return;
9702 case 2: eor64 (cpu
, bimm64
); return;
9703 case 3: ands64 (cpu
, bimm64
); return;
9710 The uimm argument is a 16 bit value to be inserted into the
9711 target register the pos argument locates the 16 bit word in the
9712 dest register i.e. it is in {0, 1} for 32 bit and {0, 1, 2,
9714 N.B register arg may not be SP so it should be.
9715 accessed using the setGZRegisterXXX accessors. */
9717 /* 32 bit move 16 bit immediate zero remaining shorts. */
9719 movz32 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9721 unsigned rd
= INSTR (4, 0);
9723 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9724 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val
<< (pos
* 16));
9727 /* 64 bit move 16 bit immediate zero remaining shorts. */
9729 movz64 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9731 unsigned rd
= INSTR (4, 0);
9733 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9734 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, ((uint64_t) val
) << (pos
* 16));
9737 /* 32 bit move 16 bit immediate negated. */
9739 movn32 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9741 unsigned rd
= INSTR (4, 0);
9743 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9744 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, ((val
<< (pos
* 16)) ^ 0xffffffffU
));
9747 /* 64 bit move 16 bit immediate negated. */
9749 movn64 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9751 unsigned rd
= INSTR (4, 0);
9753 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9755 (cpu
, rd
, NO_SP
, ((((uint64_t) val
) << (pos
* 16))
9756 ^ 0xffffffffffffffffULL
));
9759 /* 32 bit move 16 bit immediate keep remaining shorts. */
9761 movk32 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9763 unsigned rd
= INSTR (4, 0);
9764 uint32_t current
= aarch64_get_reg_u32 (cpu
, rd
, NO_SP
);
9765 uint32_t value
= val
<< (pos
* 16);
9766 uint32_t mask
= ~(0xffffU
<< (pos
* 16));
9768 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9769 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (value
| (current
& mask
)));
9772 /* 64 bit move 16 it immediate keep remaining shorts. */
9774 movk64 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9776 unsigned rd
= INSTR (4, 0);
9777 uint64_t current
= aarch64_get_reg_u64 (cpu
, rd
, NO_SP
);
9778 uint64_t value
= (uint64_t) val
<< (pos
* 16);
9779 uint64_t mask
= ~(0xffffULL
<< (pos
* 16));
9781 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9782 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (value
| (current
& mask
)));
9786 dexMoveWideImmediate (sim_cpu
*cpu
)
9788 /* assert instr[28:23] = 100101
9789 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9790 instr[30,29] = op : 0 ==> MOVN, 1 ==> UNALLOC, 2 ==> MOVZ, 3 ==> MOVK
9791 instr[22,21] = shift : 00 == LSL#0, 01 = LSL#16, 10 = LSL#32, 11 = LSL#48
9792 instr[20,5] = uimm16
9795 /* N.B. the (multiple of 16) shift is applied by the called routine,
9796 we just pass the multiplier. */
9799 uint32_t size
= INSTR (31, 31);
9800 uint32_t op
= INSTR (30, 29);
9801 uint32_t shift
= INSTR (22, 21);
9803 /* 32 bit can only shift 0 or 1 lot of 16.
9804 anything else is an unallocated instruction. */
9805 if (size
== 0 && (shift
> 1))
9811 imm
= INSTR (20, 5);
9816 movn32 (cpu
, imm
, shift
);
9818 movz32 (cpu
, imm
, shift
);
9820 movk32 (cpu
, imm
, shift
);
9825 movn64 (cpu
, imm
, shift
);
9827 movz64 (cpu
, imm
, shift
);
9829 movk64 (cpu
, imm
, shift
);
9833 /* Bitfield operations.
9834 These take a pair of bit positions r and s which are in {0..31}
9835 or {0..63} depending on the instruction word size.
9836 N.B register args may not be SP. */
9838 /* OK, we start with ubfm which just needs to pick
9839 some bits out of source zero the rest and write
9840 the result to dest. Just need two logical shifts. */
9842 /* 32 bit bitfield move, left and right of affected zeroed
9843 if r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
9845 ubfm32 (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9848 unsigned rn
= INSTR (9, 5);
9849 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9851 /* Pick either s+1-r or s+1 consecutive bits out of the original word. */
9854 /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
9855 We want only bits s:xxx:r at the bottom of the word
9856 so we LSL bit s up to bit 31 i.e. by 31 - s
9857 and then we LSR to bring bit 31 down to bit s - r
9858 i.e. by 31 + r - s. */
9860 value
>>= 31 + r
- s
;
9864 /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0
9865 We want only bits s:xxx:0 starting at it 31-(r-1)
9866 so we LSL bit s up to bit 31 i.e. by 31 - s
9867 and then we LSL to bring bit 31 down to 31-(r-1)+s
9868 i.e. by r - (s + 1). */
9870 value
>>= r
- (s
+ 1);
9873 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9875 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
9878 /* 64 bit bitfield move, left and right of affected zeroed
9879 if r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
9881 ubfm (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9884 unsigned rn
= INSTR (9, 5);
9885 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9889 /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
9890 We want only bits s:xxx:r at the bottom of the word.
9891 So we LSL bit s up to bit 63 i.e. by 63 - s
9892 and then we LSR to bring bit 63 down to bit s - r
9893 i.e. by 63 + r - s. */
9895 value
>>= 63 + r
- s
;
9899 /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0.
9900 We want only bits s:xxx:0 starting at it 63-(r-1).
9901 So we LSL bit s up to bit 63 i.e. by 63 - s
9902 and then we LSL to bring bit 63 down to 63-(r-1)+s
9903 i.e. by r - (s + 1). */
9905 value
>>= r
- (s
+ 1);
9908 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9910 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
9913 /* The signed versions need to insert sign bits
9914 on the left of the inserted bit field. so we do
9915 much the same as the unsigned version except we
9916 use an arithmetic shift right -- this just means
9917 we need to operate on signed values. */
9919 /* 32 bit bitfield move, left of affected sign-extended, right zeroed. */
9920 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
9922 sbfm32 (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9925 unsigned rn
= INSTR (9, 5);
9926 /* as per ubfm32 but use an ASR instead of an LSR. */
9927 int32_t value
= aarch64_get_reg_s32 (cpu
, rn
, NO_SP
);
9932 value
>>= 31 + r
- s
;
9937 value
>>= r
- (s
+ 1);
9940 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9942 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) value
);
9945 /* 64 bit bitfield move, left of affected sign-extended, right zeroed. */
9946 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
9948 sbfm (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9951 unsigned rn
= INSTR (9, 5);
9952 /* acpu per ubfm but use an ASR instead of an LSR. */
9953 int64_t value
= aarch64_get_reg_s64 (cpu
, rn
, NO_SP
);
9958 value
>>= 63 + r
- s
;
9963 value
>>= r
- (s
+ 1);
9966 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9968 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, value
);
9971 /* Finally, these versions leave non-affected bits
9972 as is. so we need to generate the bits as per
9973 ubfm and also generate a mask to pick the
9974 bits from the original and computed values. */
9976 /* 32 bit bitfield move, non-affected bits left as is.
9977 If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
9979 bfm32 (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9981 unsigned rn
= INSTR (9, 5);
9982 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9987 /* Pick either s+1-r or s+1 consecutive bits out of the original word. */
9990 /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
9991 We want only bits s:xxx:r at the bottom of the word
9992 so we LSL bit s up to bit 31 i.e. by 31 - s
9993 and then we LSR to bring bit 31 down to bit s - r
9994 i.e. by 31 + r - s. */
9996 value
>>= 31 + r
- s
;
9997 /* the mask must include the same bits. */
9999 mask
>>= 31 + r
- s
;
10003 /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0.
10004 We want only bits s:xxx:0 starting at it 31-(r-1)
10005 so we LSL bit s up to bit 31 i.e. by 31 - s
10006 and then we LSL to bring bit 31 down to 31-(r-1)+s
10007 i.e. by r - (s + 1). */
10009 value
>>= r
- (s
+ 1);
10010 /* The mask must include the same bits. */
10012 mask
>>= r
- (s
+ 1);
10016 value2
= aarch64_get_reg_u32 (cpu
, rd
, NO_SP
);
10021 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10022 aarch64_set_reg_u64
10023 (cpu
, rd
, NO_SP
, (aarch64_get_reg_u32 (cpu
, rd
, NO_SP
) & ~mask
) | value
);
10026 /* 64 bit bitfield move, non-affected bits left as is.
10027 If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
10029 bfm (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
10032 unsigned rn
= INSTR (9, 5);
10033 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
10034 uint64_t mask
= 0xffffffffffffffffULL
;
10038 /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
10039 We want only bits s:xxx:r at the bottom of the word
10040 so we LSL bit s up to bit 63 i.e. by 63 - s
10041 and then we LSR to bring bit 63 down to bit s - r
10042 i.e. by 63 + r - s. */
10044 value
>>= 63 + r
- s
;
10045 /* The mask must include the same bits. */
10047 mask
>>= 63 + r
- s
;
10051 /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0
10052 We want only bits s:xxx:0 starting at it 63-(r-1)
10053 so we LSL bit s up to bit 63 i.e. by 63 - s
10054 and then we LSL to bring bit 63 down to 63-(r-1)+s
10055 i.e. by r - (s + 1). */
10057 value
>>= r
- (s
+ 1);
10058 /* The mask must include the same bits. */
10060 mask
>>= r
- (s
+ 1);
10063 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10065 aarch64_set_reg_u64
10066 (cpu
, rd
, NO_SP
, (aarch64_get_reg_u64 (cpu
, rd
, NO_SP
) & ~mask
) | value
);
10070 dexBitfieldImmediate (sim_cpu
*cpu
)
10072 /* assert instr[28:23] = 100110
10073 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
10074 instr[30,29] = op : 0 ==> SBFM, 1 ==> BFM, 2 ==> UBFM, 3 ==> UNALLOC
10075 instr[22] = N : must be 0 for 32 bit, 1 for 64 bit ow UNALLOC
10076 instr[21,16] = immr : 0xxxxx for 32 bit, xxxxxx for 64 bit
10077 instr[15,10] = imms : 0xxxxx for 32 bit, xxxxxx for 64 bit
10081 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
10084 uint32_t size
= INSTR (31, 31);
10085 uint32_t N
= INSTR (22, 22);
10086 /* 32 bit operations must have immr[5] = 0 and imms[5] = 0. */
10087 /* or else we have an UNALLOC. */
10088 uint32_t immr
= INSTR (21, 16);
10093 if (!size
&& uimm (immr
, 5, 5))
10096 imms
= INSTR (15, 10);
10097 if (!size
&& uimm (imms
, 5, 5))
10100 /* Switch on combined size and op. */
10101 dispatch
= INSTR (31, 29);
10104 case 0: sbfm32 (cpu
, immr
, imms
); return;
10105 case 1: bfm32 (cpu
, immr
, imms
); return;
10106 case 2: ubfm32 (cpu
, immr
, imms
); return;
10107 case 4: sbfm (cpu
, immr
, imms
); return;
10108 case 5: bfm (cpu
, immr
, imms
); return;
10109 case 6: ubfm (cpu
, immr
, imms
); return;
10110 default: HALT_UNALLOC
;
10115 do_EXTR_32 (sim_cpu
*cpu
)
10117 /* instr[31:21] = 00010011100
10119 instr[15,10] = imms : 0xxxxx for 32 bit
10122 unsigned rm
= INSTR (20, 16);
10123 unsigned imms
= INSTR (15, 10) & 31;
10124 unsigned rn
= INSTR ( 9, 5);
10125 unsigned rd
= INSTR ( 4, 0);
10129 val1
= aarch64_get_reg_u32 (cpu
, rm
, NO_SP
);
10131 val2
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
10132 val2
<<= (32 - imms
);
10134 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10135 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val1
| val2
);
10139 do_EXTR_64 (sim_cpu
*cpu
)
10141 /* instr[31:21] = 10010011100
10143 instr[15,10] = imms
10146 unsigned rm
= INSTR (20, 16);
10147 unsigned imms
= INSTR (15, 10) & 63;
10148 unsigned rn
= INSTR ( 9, 5);
10149 unsigned rd
= INSTR ( 4, 0);
10152 val
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
10154 val
|= (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) << (64 - imms
));
10156 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val
);
10160 dexExtractImmediate (sim_cpu
*cpu
)
10162 /* assert instr[28:23] = 100111
10163 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
10164 instr[30,29] = op21 : 0 ==> EXTR, 1,2,3 ==> UNALLOC
10165 instr[22] = N : must be 0 for 32 bit, 1 for 64 bit or UNALLOC
10166 instr[21] = op0 : must be 0 or UNALLOC
10168 instr[15,10] = imms : 0xxxxx for 32 bit, xxxxxx for 64 bit
10172 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
10173 /* 64 bit operations must have N = 1 or else we have an UNALLOC. */
10175 uint32_t size
= INSTR (31, 31);
10176 uint32_t N
= INSTR (22, 22);
10177 /* 32 bit operations must have imms[5] = 0
10178 or else we have an UNALLOC. */
10179 uint32_t imms
= INSTR (15, 10);
10184 if (!size
&& uimm (imms
, 5, 5))
10187 /* Switch on combined size and op. */
10188 dispatch
= INSTR (31, 29);
10193 else if (dispatch
== 4)
10196 else if (dispatch
== 1)
10203 dexDPImm (sim_cpu
*cpu
)
10205 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
10206 assert group == GROUP_DPIMM_1000 || grpoup == GROUP_DPIMM_1001
10207 bits [25,23] of a DPImm are the secondary dispatch vector. */
10208 uint32_t group2
= dispatchDPImm (aarch64_get_instr (cpu
));
10212 case DPIMM_PCADR_000
:
10213 case DPIMM_PCADR_001
:
10214 dexPCRelAddressing (cpu
);
10217 case DPIMM_ADDSUB_010
:
10218 case DPIMM_ADDSUB_011
:
10219 dexAddSubtractImmediate (cpu
);
10222 case DPIMM_LOG_100
:
10223 dexLogicalImmediate (cpu
);
10226 case DPIMM_MOV_101
:
10227 dexMoveWideImmediate (cpu
);
10230 case DPIMM_BITF_110
:
10231 dexBitfieldImmediate (cpu
);
10234 case DPIMM_EXTR_111
:
10235 dexExtractImmediate (cpu
);
10239 /* Should never reach here. */
10245 dexLoadUnscaledImmediate (sim_cpu
*cpu
)
10247 /* instr[29,24] == 111_00
10250 instr[31,30] = size
10253 instr[20,12] = simm9
10254 instr[9,5] = rn may be SP. */
10255 /* unsigned rt = INSTR (4, 0); */
10256 uint32_t V
= INSTR (26, 26);
10257 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
10258 int32_t imm
= simm32 (aarch64_get_instr (cpu
), 20, 12);
10262 /* GReg operations. */
10265 case 0: sturb (cpu
, imm
); return;
10266 case 1: ldurb32 (cpu
, imm
); return;
10267 case 2: ldursb64 (cpu
, imm
); return;
10268 case 3: ldursb32 (cpu
, imm
); return;
10269 case 4: sturh (cpu
, imm
); return;
10270 case 5: ldurh32 (cpu
, imm
); return;
10271 case 6: ldursh64 (cpu
, imm
); return;
10272 case 7: ldursh32 (cpu
, imm
); return;
10273 case 8: stur32 (cpu
, imm
); return;
10274 case 9: ldur32 (cpu
, imm
); return;
10275 case 10: ldursw (cpu
, imm
); return;
10276 case 12: stur64 (cpu
, imm
); return;
10277 case 13: ldur64 (cpu
, imm
); return;
10290 /* FReg operations. */
10293 case 2: fsturq (cpu
, imm
); return;
10294 case 3: fldurq (cpu
, imm
); return;
10295 case 8: fsturs (cpu
, imm
); return;
10296 case 9: fldurs (cpu
, imm
); return;
10297 case 12: fsturd (cpu
, imm
); return;
10298 case 13: fldurd (cpu
, imm
); return;
10300 case 0: /* STUR 8 bit FP. */
10301 case 1: /* LDUR 8 bit FP. */
10302 case 4: /* STUR 16 bit FP. */
10303 case 5: /* LDUR 8 bit FP. */
10317 /* N.B. A preliminary note regarding all the ldrs<x>32
10320 The signed value loaded by these instructions is cast to unsigned
10321 before being assigned to aarch64_get_reg_u64 (cpu, N) i.e. to the
10322 64 bit element of the GReg union. this performs a 32 bit sign extension
10323 (as required) but avoids 64 bit sign extension, thus ensuring that the
10324 top half of the register word is zero. this is what the spec demands
10325 when a 32 bit load occurs. */
10327 /* 32 bit load sign-extended byte scaled unsigned 12 bit. */
10329 ldrsb32_abs (sim_cpu
*cpu
, uint32_t offset
)
10331 unsigned int rn
= INSTR (9, 5);
10332 unsigned int rt
= INSTR (4, 0);
10334 /* The target register may not be SP but the source may be
10335 there is no scaling required for a byte load. */
10336 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
;
10337 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
10338 (int64_t) aarch64_get_mem_s8 (cpu
, address
));
10341 /* 32 bit load sign-extended byte scaled or unscaled zero-
10342 or sign-extended 32-bit register offset. */
10344 ldrsb32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10346 unsigned int rm
= INSTR (20, 16);
10347 unsigned int rn
= INSTR (9, 5);
10348 unsigned int rt
= INSTR (4, 0);
10350 /* rn may reference SP, rm and rt must reference ZR. */
10352 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10353 int64_t displacement
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10356 /* There is no scaling required for a byte load. */
10357 aarch64_set_reg_u64
10358 (cpu
, rt
, NO_SP
, (int64_t) aarch64_get_mem_s8 (cpu
, address
10362 /* 32 bit load sign-extended byte unscaled signed 9 bit with
10363 pre- or post-writeback. */
10365 ldrsb32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10368 unsigned int rn
= INSTR (9, 5);
10369 unsigned int rt
= INSTR (4, 0);
10371 if (rn
== rt
&& wb
!= NoWriteBack
)
10374 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10379 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
10380 (int64_t) aarch64_get_mem_s8 (cpu
, address
));
10385 if (wb
!= NoWriteBack
)
10386 aarch64_set_reg_u64 (cpu
, rn
, NO_SP
, address
);
10389 /* 8 bit store scaled. */
10391 fstrb_abs (sim_cpu
*cpu
, uint32_t offset
)
10393 unsigned st
= INSTR (4, 0);
10394 unsigned rn
= INSTR (9, 5);
10396 aarch64_set_mem_u8 (cpu
,
10397 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
10398 aarch64_get_vec_u8 (cpu
, st
, 0));
10401 /* 8 bit store scaled or unscaled zero- or
10402 sign-extended 8-bit register offset. */
10404 fstrb_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10406 unsigned rm
= INSTR (20, 16);
10407 unsigned rn
= INSTR (9, 5);
10408 unsigned st
= INSTR (4, 0);
10410 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10411 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10413 uint64_t displacement
= scaling
== Scaled
? extended
: 0;
10416 (cpu
, address
+ displacement
, aarch64_get_vec_u8 (cpu
, st
, 0));
10419 /* 16 bit store scaled. */
10421 fstrh_abs (sim_cpu
*cpu
, uint32_t offset
)
10423 unsigned st
= INSTR (4, 0);
10424 unsigned rn
= INSTR (9, 5);
10426 aarch64_set_mem_u16
10428 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 16),
10429 aarch64_get_vec_u16 (cpu
, st
, 0));
10432 /* 16 bit store scaled or unscaled zero-
10433 or sign-extended 16-bit register offset. */
10435 fstrh_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10437 unsigned rm
= INSTR (20, 16);
10438 unsigned rn
= INSTR (9, 5);
10439 unsigned st
= INSTR (4, 0);
10441 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10442 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10444 uint64_t displacement
= OPT_SCALE (extended
, 16, scaling
);
10446 aarch64_set_mem_u16
10447 (cpu
, address
+ displacement
, aarch64_get_vec_u16 (cpu
, st
, 0));
10450 /* 32 bit store scaled unsigned 12 bit. */
10452 fstrs_abs (sim_cpu
*cpu
, uint32_t offset
)
10454 unsigned st
= INSTR (4, 0);
10455 unsigned rn
= INSTR (9, 5);
10457 aarch64_set_mem_u32
10459 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 32),
10460 aarch64_get_vec_u32 (cpu
, st
, 0));
10463 /* 32 bit store unscaled signed 9 bit with pre- or post-writeback. */
10465 fstrs_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10467 unsigned rn
= INSTR (9, 5);
10468 unsigned st
= INSTR (4, 0);
10470 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10475 aarch64_set_mem_u32 (cpu
, address
, aarch64_get_vec_u32 (cpu
, st
, 0));
10480 if (wb
!= NoWriteBack
)
10481 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
10484 /* 32 bit store scaled or unscaled zero-
10485 or sign-extended 32-bit register offset. */
10487 fstrs_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10489 unsigned rm
= INSTR (20, 16);
10490 unsigned rn
= INSTR (9, 5);
10491 unsigned st
= INSTR (4, 0);
10493 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10494 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10496 uint64_t displacement
= OPT_SCALE (extended
, 32, scaling
);
10498 aarch64_set_mem_u32
10499 (cpu
, address
+ displacement
, aarch64_get_vec_u32 (cpu
, st
, 0));
10502 /* 64 bit store scaled unsigned 12 bit. */
10504 fstrd_abs (sim_cpu
*cpu
, uint32_t offset
)
10506 unsigned st
= INSTR (4, 0);
10507 unsigned rn
= INSTR (9, 5);
10509 aarch64_set_mem_u64
10511 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 64),
10512 aarch64_get_vec_u64 (cpu
, st
, 0));
10515 /* 64 bit store unscaled signed 9 bit with pre- or post-writeback. */
10517 fstrd_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10519 unsigned rn
= INSTR (9, 5);
10520 unsigned st
= INSTR (4, 0);
10522 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10527 aarch64_set_mem_u64 (cpu
, address
, aarch64_get_vec_u64 (cpu
, st
, 0));
10532 if (wb
!= NoWriteBack
)
10533 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
10536 /* 64 bit store scaled or unscaled zero-
10537 or sign-extended 32-bit register offset. */
10539 fstrd_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10541 unsigned rm
= INSTR (20, 16);
10542 unsigned rn
= INSTR (9, 5);
10543 unsigned st
= INSTR (4, 0);
10545 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10546 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10548 uint64_t displacement
= OPT_SCALE (extended
, 64, scaling
);
10550 aarch64_set_mem_u64
10551 (cpu
, address
+ displacement
, aarch64_get_vec_u64 (cpu
, st
, 0));
10554 /* 128 bit store scaled unsigned 12 bit. */
10556 fstrq_abs (sim_cpu
*cpu
, uint32_t offset
)
10559 unsigned st
= INSTR (4, 0);
10560 unsigned rn
= INSTR (9, 5);
10563 aarch64_get_FP_long_double (cpu
, st
, & a
);
10565 addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 128);
10566 aarch64_set_mem_long_double (cpu
, addr
, a
);
10569 /* 128 bit store unscaled signed 9 bit with pre- or post-writeback. */
10571 fstrq_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10574 unsigned rn
= INSTR (9, 5);
10575 unsigned st
= INSTR (4, 0);
10576 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10581 aarch64_get_FP_long_double (cpu
, st
, & a
);
10582 aarch64_set_mem_long_double (cpu
, address
, a
);
10587 if (wb
!= NoWriteBack
)
10588 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
10591 /* 128 bit store scaled or unscaled zero-
10592 or sign-extended 32-bit register offset. */
10594 fstrq_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10596 unsigned rm
= INSTR (20, 16);
10597 unsigned rn
= INSTR (9, 5);
10598 unsigned st
= INSTR (4, 0);
10600 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10601 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10603 uint64_t displacement
= OPT_SCALE (extended
, 128, scaling
);
10607 aarch64_get_FP_long_double (cpu
, st
, & a
);
10608 aarch64_set_mem_long_double (cpu
, address
+ displacement
, a
);
10612 dexLoadImmediatePrePost (sim_cpu
*cpu
)
10614 /* instr[31,30] = size
10620 instr[20,12] = simm9
10621 instr[11] = wb : 0 ==> Post, 1 ==> Pre
10623 instr[9,5] = Rn may be SP.
10626 uint32_t V
= INSTR (26, 26);
10627 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
10628 int32_t imm
= simm32 (aarch64_get_instr (cpu
), 20, 12);
10629 WriteBack wb
= INSTR (11, 11);
10633 /* GReg operations. */
10636 case 0: strb_wb (cpu
, imm
, wb
); return;
10637 case 1: ldrb32_wb (cpu
, imm
, wb
); return;
10638 case 2: ldrsb_wb (cpu
, imm
, wb
); return;
10639 case 3: ldrsb32_wb (cpu
, imm
, wb
); return;
10640 case 4: strh_wb (cpu
, imm
, wb
); return;
10641 case 5: ldrh32_wb (cpu
, imm
, wb
); return;
10642 case 6: ldrsh64_wb (cpu
, imm
, wb
); return;
10643 case 7: ldrsh32_wb (cpu
, imm
, wb
); return;
10644 case 8: str32_wb (cpu
, imm
, wb
); return;
10645 case 9: ldr32_wb (cpu
, imm
, wb
); return;
10646 case 10: ldrsw_wb (cpu
, imm
, wb
); return;
10647 case 12: str_wb (cpu
, imm
, wb
); return;
10648 case 13: ldr_wb (cpu
, imm
, wb
); return;
10658 /* FReg operations. */
10661 case 2: fstrq_wb (cpu
, imm
, wb
); return;
10662 case 3: fldrq_wb (cpu
, imm
, wb
); return;
10663 case 8: fstrs_wb (cpu
, imm
, wb
); return;
10664 case 9: fldrs_wb (cpu
, imm
, wb
); return;
10665 case 12: fstrd_wb (cpu
, imm
, wb
); return;
10666 case 13: fldrd_wb (cpu
, imm
, wb
); return;
10668 case 0: /* STUR 8 bit FP. */
10669 case 1: /* LDUR 8 bit FP. */
10670 case 4: /* STUR 16 bit FP. */
10671 case 5: /* LDUR 8 bit FP. */
10686 dexLoadRegisterOffset (sim_cpu
*cpu
)
10688 /* instr[31,30] = size
10695 instr[15,13] = option : 010 ==> UXTW, 011 ==> UXTX/LSL,
10696 110 ==> SXTW, 111 ==> SXTX,
10701 instr[4,0] = rt. */
10703 uint32_t V
= INSTR (26, 26);
10704 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
10705 Scaling scale
= INSTR (12, 12);
10706 Extension extensionType
= INSTR (15, 13);
10708 /* Check for illegal extension types. */
10709 if (uimm (extensionType
, 1, 1) == 0)
10712 if (extensionType
== UXTX
|| extensionType
== SXTX
)
10713 extensionType
= NoExtension
;
10717 /* GReg operations. */
10720 case 0: strb_scale_ext (cpu
, scale
, extensionType
); return;
10721 case 1: ldrb32_scale_ext (cpu
, scale
, extensionType
); return;
10722 case 2: ldrsb_scale_ext (cpu
, scale
, extensionType
); return;
10723 case 3: ldrsb32_scale_ext (cpu
, scale
, extensionType
); return;
10724 case 4: strh_scale_ext (cpu
, scale
, extensionType
); return;
10725 case 5: ldrh32_scale_ext (cpu
, scale
, extensionType
); return;
10726 case 6: ldrsh_scale_ext (cpu
, scale
, extensionType
); return;
10727 case 7: ldrsh32_scale_ext (cpu
, scale
, extensionType
); return;
10728 case 8: str32_scale_ext (cpu
, scale
, extensionType
); return;
10729 case 9: ldr32_scale_ext (cpu
, scale
, extensionType
); return;
10730 case 10: ldrsw_scale_ext (cpu
, scale
, extensionType
); return;
10731 case 12: str_scale_ext (cpu
, scale
, extensionType
); return;
10732 case 13: ldr_scale_ext (cpu
, scale
, extensionType
); return;
10733 case 14: prfm_scale_ext (cpu
, scale
, extensionType
); return;
10742 /* FReg operations. */
10745 case 1: /* LDUR 8 bit FP. */
10747 case 3: fldrq_scale_ext (cpu
, scale
, extensionType
); return;
10748 case 5: /* LDUR 8 bit FP. */
10750 case 9: fldrs_scale_ext (cpu
, scale
, extensionType
); return;
10751 case 13: fldrd_scale_ext (cpu
, scale
, extensionType
); return;
10753 case 0: fstrb_scale_ext (cpu
, scale
, extensionType
); return;
10754 case 2: fstrq_scale_ext (cpu
, scale
, extensionType
); return;
10755 case 4: fstrh_scale_ext (cpu
, scale
, extensionType
); return;
10756 case 8: fstrs_scale_ext (cpu
, scale
, extensionType
); return;
10757 case 12: fstrd_scale_ext (cpu
, scale
, extensionType
); return;
10771 dexLoadUnsignedImmediate (sim_cpu
*cpu
)
10773 /* instr[29,24] == 111_01
10774 instr[31,30] = size
10777 instr[21,10] = uimm12 : unsigned immediate offset
10778 instr[9,5] = rn may be SP.
10779 instr[4,0] = rt. */
10781 uint32_t V
= INSTR (26,26);
10782 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
10783 uint32_t imm
= INSTR (21, 10);
10787 /* GReg operations. */
10790 case 0: strb_abs (cpu
, imm
); return;
10791 case 1: ldrb32_abs (cpu
, imm
); return;
10792 case 2: ldrsb_abs (cpu
, imm
); return;
10793 case 3: ldrsb32_abs (cpu
, imm
); return;
10794 case 4: strh_abs (cpu
, imm
); return;
10795 case 5: ldrh32_abs (cpu
, imm
); return;
10796 case 6: ldrsh_abs (cpu
, imm
); return;
10797 case 7: ldrsh32_abs (cpu
, imm
); return;
10798 case 8: str32_abs (cpu
, imm
); return;
10799 case 9: ldr32_abs (cpu
, imm
); return;
10800 case 10: ldrsw_abs (cpu
, imm
); return;
10801 case 12: str_abs (cpu
, imm
); return;
10802 case 13: ldr_abs (cpu
, imm
); return;
10803 case 14: prfm_abs (cpu
, imm
); return;
10812 /* FReg operations. */
10815 case 0: fstrb_abs (cpu
, imm
); return;
10816 case 4: fstrh_abs (cpu
, imm
); return;
10817 case 8: fstrs_abs (cpu
, imm
); return;
10818 case 12: fstrd_abs (cpu
, imm
); return;
10819 case 2: fstrq_abs (cpu
, imm
); return;
10821 case 1: fldrb_abs (cpu
, imm
); return;
10822 case 5: fldrh_abs (cpu
, imm
); return;
10823 case 9: fldrs_abs (cpu
, imm
); return;
10824 case 13: fldrd_abs (cpu
, imm
); return;
10825 case 3: fldrq_abs (cpu
, imm
); return;
10839 dexLoadExclusive (sim_cpu
*cpu
)
10841 /* assert instr[29:24] = 001000;
10842 instr[31,30] = size
10843 instr[23] = 0 if exclusive
10844 instr[22] = L : 1 if load, 0 if store
10845 instr[21] = 1 if pair
10847 instr[15] = o0 : 1 if ordered
10850 instr[4.0] = Rt. */
10852 switch (INSTR (22, 21))
10854 case 2: ldxr (cpu
); return;
10855 case 0: stxr (cpu
); return;
10861 dexLoadOther (sim_cpu
*cpu
)
10865 /* instr[29,25] = 111_0
10866 instr[24] == 0 ==> dispatch, 1 ==> ldst reg unsigned immediate
10867 instr[21:11,10] is the secondary dispatch. */
10868 if (INSTR (24, 24))
10870 dexLoadUnsignedImmediate (cpu
);
10874 dispatch
= ((INSTR (21, 21) << 2) | INSTR (11, 10));
10877 case 0: dexLoadUnscaledImmediate (cpu
); return;
10878 case 1: dexLoadImmediatePrePost (cpu
); return;
10879 case 3: dexLoadImmediatePrePost (cpu
); return;
10880 case 6: dexLoadRegisterOffset (cpu
); return;
10892 store_pair_u32 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10894 unsigned rn
= INSTR (14, 10);
10895 unsigned rd
= INSTR (9, 5);
10896 unsigned rm
= INSTR (4, 0);
10897 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10899 if ((rn
== rd
|| rm
== rd
) && wb
!= NoWriteBack
)
10900 HALT_UNALLOC
; /* ??? */
10907 aarch64_set_mem_u32 (cpu
, address
,
10908 aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
10909 aarch64_set_mem_u32 (cpu
, address
+ 4,
10910 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
));
10915 if (wb
!= NoWriteBack
)
10916 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10920 store_pair_u64 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10922 unsigned rn
= INSTR (14, 10);
10923 unsigned rd
= INSTR (9, 5);
10924 unsigned rm
= INSTR (4, 0);
10925 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10927 if ((rn
== rd
|| rm
== rd
) && wb
!= NoWriteBack
)
10928 HALT_UNALLOC
; /* ??? */
10935 aarch64_set_mem_u64 (cpu
, address
,
10936 aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
10937 aarch64_set_mem_u64 (cpu
, address
+ 8,
10938 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
10943 if (wb
!= NoWriteBack
)
10944 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10948 load_pair_u32 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10950 unsigned rn
= INSTR (14, 10);
10951 unsigned rd
= INSTR (9, 5);
10952 unsigned rm
= INSTR (4, 0);
10953 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10955 /* Treat this as unalloc to make sure we don't do it. */
10964 aarch64_set_reg_u64 (cpu
, rm
, SP_OK
, aarch64_get_mem_u32 (cpu
, address
));
10965 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, aarch64_get_mem_u32 (cpu
, address
+ 4));
10970 if (wb
!= NoWriteBack
)
10971 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10975 load_pair_s32 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10977 unsigned rn
= INSTR (14, 10);
10978 unsigned rd
= INSTR (9, 5);
10979 unsigned rm
= INSTR (4, 0);
10980 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10982 /* Treat this as unalloc to make sure we don't do it. */
10991 aarch64_set_reg_s64 (cpu
, rm
, SP_OK
, aarch64_get_mem_s32 (cpu
, address
));
10992 aarch64_set_reg_s64 (cpu
, rn
, SP_OK
, aarch64_get_mem_s32 (cpu
, address
+ 4));
10997 if (wb
!= NoWriteBack
)
10998 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11002 load_pair_u64 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11004 unsigned rn
= INSTR (14, 10);
11005 unsigned rd
= INSTR (9, 5);
11006 unsigned rm
= INSTR (4, 0);
11007 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11009 /* Treat this as unalloc to make sure we don't do it. */
11018 aarch64_set_reg_u64 (cpu
, rm
, SP_OK
, aarch64_get_mem_u64 (cpu
, address
));
11019 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, aarch64_get_mem_u64 (cpu
, address
+ 8));
11024 if (wb
!= NoWriteBack
)
11025 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11029 dex_load_store_pair_gr (sim_cpu
*cpu
)
11031 /* instr[31,30] = size (10=> 64-bit, 01=> signed 32-bit, 00=> 32-bit)
11032 instr[29,25] = instruction encoding: 101_0
11033 instr[26] = V : 1 if fp 0 if gp
11034 instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
11035 instr[22] = load/store (1=> load)
11036 instr[21,15] = signed, scaled, offset
11039 instr[ 4, 0] = Rm. */
11041 uint32_t dispatch
= ((INSTR (31, 30) << 3) | INSTR (24, 22));
11042 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 21, 15);
11046 case 2: store_pair_u32 (cpu
, offset
, Post
); return;
11047 case 3: load_pair_u32 (cpu
, offset
, Post
); return;
11048 case 4: store_pair_u32 (cpu
, offset
, NoWriteBack
); return;
11049 case 5: load_pair_u32 (cpu
, offset
, NoWriteBack
); return;
11050 case 6: store_pair_u32 (cpu
, offset
, Pre
); return;
11051 case 7: load_pair_u32 (cpu
, offset
, Pre
); return;
11053 case 11: load_pair_s32 (cpu
, offset
, Post
); return;
11054 case 13: load_pair_s32 (cpu
, offset
, NoWriteBack
); return;
11055 case 15: load_pair_s32 (cpu
, offset
, Pre
); return;
11057 case 18: store_pair_u64 (cpu
, offset
, Post
); return;
11058 case 19: load_pair_u64 (cpu
, offset
, Post
); return;
11059 case 20: store_pair_u64 (cpu
, offset
, NoWriteBack
); return;
11060 case 21: load_pair_u64 (cpu
, offset
, NoWriteBack
); return;
11061 case 22: store_pair_u64 (cpu
, offset
, Pre
); return;
11062 case 23: load_pair_u64 (cpu
, offset
, Pre
); return;
11070 store_pair_float (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11072 unsigned rn
= INSTR (14, 10);
11073 unsigned rd
= INSTR (9, 5);
11074 unsigned rm
= INSTR (4, 0);
11075 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11082 aarch64_set_mem_u32 (cpu
, address
, aarch64_get_vec_u32 (cpu
, rm
, 0));
11083 aarch64_set_mem_u32 (cpu
, address
+ 4, aarch64_get_vec_u32 (cpu
, rn
, 0));
11088 if (wb
!= NoWriteBack
)
11089 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11093 store_pair_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11095 unsigned rn
= INSTR (14, 10);
11096 unsigned rd
= INSTR (9, 5);
11097 unsigned rm
= INSTR (4, 0);
11098 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11105 aarch64_set_mem_u64 (cpu
, address
, aarch64_get_vec_u64 (cpu
, rm
, 0));
11106 aarch64_set_mem_u64 (cpu
, address
+ 8, aarch64_get_vec_u64 (cpu
, rn
, 0));
11111 if (wb
!= NoWriteBack
)
11112 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11116 store_pair_long_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11119 unsigned rn
= INSTR (14, 10);
11120 unsigned rd
= INSTR (9, 5);
11121 unsigned rm
= INSTR (4, 0);
11122 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11129 aarch64_get_FP_long_double (cpu
, rm
, & a
);
11130 aarch64_set_mem_long_double (cpu
, address
, a
);
11131 aarch64_get_FP_long_double (cpu
, rn
, & a
);
11132 aarch64_set_mem_long_double (cpu
, address
+ 16, a
);
11137 if (wb
!= NoWriteBack
)
11138 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11142 load_pair_float (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11144 unsigned rn
= INSTR (14, 10);
11145 unsigned rd
= INSTR (9, 5);
11146 unsigned rm
= INSTR (4, 0);
11147 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11157 aarch64_set_vec_u32 (cpu
, rm
, 0, aarch64_get_mem_u32 (cpu
, address
));
11158 aarch64_set_vec_u32 (cpu
, rn
, 0, aarch64_get_mem_u32 (cpu
, address
+ 4));
11163 if (wb
!= NoWriteBack
)
11164 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11168 load_pair_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11170 unsigned rn
= INSTR (14, 10);
11171 unsigned rd
= INSTR (9, 5);
11172 unsigned rm
= INSTR (4, 0);
11173 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11183 aarch64_set_vec_u64 (cpu
, rm
, 0, aarch64_get_mem_u64 (cpu
, address
));
11184 aarch64_set_vec_u64 (cpu
, rn
, 0, aarch64_get_mem_u64 (cpu
, address
+ 8));
11189 if (wb
!= NoWriteBack
)
11190 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11194 load_pair_long_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11197 unsigned rn
= INSTR (14, 10);
11198 unsigned rd
= INSTR (9, 5);
11199 unsigned rm
= INSTR (4, 0);
11200 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11210 aarch64_get_mem_long_double (cpu
, address
, & a
);
11211 aarch64_set_FP_long_double (cpu
, rm
, a
);
11212 aarch64_get_mem_long_double (cpu
, address
+ 16, & a
);
11213 aarch64_set_FP_long_double (cpu
, rn
, a
);
11218 if (wb
!= NoWriteBack
)
11219 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11223 dex_load_store_pair_fp (sim_cpu
*cpu
)
11225 /* instr[31,30] = size (10=> 128-bit, 01=> 64-bit, 00=> 32-bit)
11226 instr[29,25] = instruction encoding
11227 instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
11228 instr[22] = load/store (1=> load)
11229 instr[21,15] = signed, scaled, offset
11232 instr[ 4, 0] = Rm */
11234 uint32_t dispatch
= ((INSTR (31, 30) << 3) | INSTR (24, 22));
11235 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 21, 15);
11239 case 2: store_pair_float (cpu
, offset
, Post
); return;
11240 case 3: load_pair_float (cpu
, offset
, Post
); return;
11241 case 4: store_pair_float (cpu
, offset
, NoWriteBack
); return;
11242 case 5: load_pair_float (cpu
, offset
, NoWriteBack
); return;
11243 case 6: store_pair_float (cpu
, offset
, Pre
); return;
11244 case 7: load_pair_float (cpu
, offset
, Pre
); return;
11246 case 10: store_pair_double (cpu
, offset
, Post
); return;
11247 case 11: load_pair_double (cpu
, offset
, Post
); return;
11248 case 12: store_pair_double (cpu
, offset
, NoWriteBack
); return;
11249 case 13: load_pair_double (cpu
, offset
, NoWriteBack
); return;
11250 case 14: store_pair_double (cpu
, offset
, Pre
); return;
11251 case 15: load_pair_double (cpu
, offset
, Pre
); return;
11253 case 18: store_pair_long_double (cpu
, offset
, Post
); return;
11254 case 19: load_pair_long_double (cpu
, offset
, Post
); return;
11255 case 20: store_pair_long_double (cpu
, offset
, NoWriteBack
); return;
11256 case 21: load_pair_long_double (cpu
, offset
, NoWriteBack
); return;
11257 case 22: store_pair_long_double (cpu
, offset
, Pre
); return;
11258 case 23: load_pair_long_double (cpu
, offset
, Pre
); return;
11265 static inline unsigned
11266 vec_reg (unsigned v
, unsigned o
)
11268 return (v
+ o
) & 0x3F;
11271 /* Load multiple N-element structures to N consecutive registers. */
11273 vec_load (sim_cpu
*cpu
, uint64_t address
, unsigned N
)
11275 int all
= INSTR (30, 30);
11276 unsigned size
= INSTR (11, 10);
11277 unsigned vd
= INSTR (4, 0);
11282 case 0: /* 8-bit operations. */
11284 for (i
= 0; i
< (16 * N
); i
++)
11285 aarch64_set_vec_u8 (cpu
, vec_reg (vd
, i
>> 4), i
& 15,
11286 aarch64_get_mem_u8 (cpu
, address
+ i
));
11288 for (i
= 0; i
< (8 * N
); i
++)
11289 aarch64_set_vec_u8 (cpu
, vec_reg (vd
, i
>> 3), i
& 7,
11290 aarch64_get_mem_u8 (cpu
, address
+ i
));
11293 case 1: /* 16-bit operations. */
11295 for (i
= 0; i
< (8 * N
); i
++)
11296 aarch64_set_vec_u16 (cpu
, vec_reg (vd
, i
>> 3), i
& 7,
11297 aarch64_get_mem_u16 (cpu
, address
+ i
* 2));
11299 for (i
= 0; i
< (4 * N
); i
++)
11300 aarch64_set_vec_u16 (cpu
, vec_reg (vd
, i
>> 2), i
& 3,
11301 aarch64_get_mem_u16 (cpu
, address
+ i
* 2));
11304 case 2: /* 32-bit operations. */
11306 for (i
= 0; i
< (4 * N
); i
++)
11307 aarch64_set_vec_u32 (cpu
, vec_reg (vd
, i
>> 2), i
& 3,
11308 aarch64_get_mem_u32 (cpu
, address
+ i
* 4));
11310 for (i
= 0; i
< (2 * N
); i
++)
11311 aarch64_set_vec_u32 (cpu
, vec_reg (vd
, i
>> 1), i
& 1,
11312 aarch64_get_mem_u32 (cpu
, address
+ i
* 4));
11315 case 3: /* 64-bit operations. */
11317 for (i
= 0; i
< (2 * N
); i
++)
11318 aarch64_set_vec_u64 (cpu
, vec_reg (vd
, i
>> 1), i
& 1,
11319 aarch64_get_mem_u64 (cpu
, address
+ i
* 8));
11321 for (i
= 0; i
< N
; i
++)
11322 aarch64_set_vec_u64 (cpu
, vec_reg (vd
, i
), 0,
11323 aarch64_get_mem_u64 (cpu
, address
+ i
* 8));
11328 /* LD4: load multiple 4-element to four consecutive registers. */
11330 LD4 (sim_cpu
*cpu
, uint64_t address
)
11332 vec_load (cpu
, address
, 4);
11335 /* LD3: load multiple 3-element structures to three consecutive registers. */
11337 LD3 (sim_cpu
*cpu
, uint64_t address
)
11339 vec_load (cpu
, address
, 3);
11342 /* LD2: load multiple 2-element structures to two consecutive registers. */
11344 LD2 (sim_cpu
*cpu
, uint64_t address
)
11346 vec_load (cpu
, address
, 2);
11349 /* Load multiple 1-element structures into one register. */
11351 LD1_1 (sim_cpu
*cpu
, uint64_t address
)
11353 int all
= INSTR (30, 30);
11354 unsigned size
= INSTR (11, 10);
11355 unsigned vd
= INSTR (4, 0);
11361 /* LD1 {Vd.16b}, addr, #16 */
11362 /* LD1 {Vd.8b}, addr, #8 */
11363 for (i
= 0; i
< (all
? 16 : 8); i
++)
11364 aarch64_set_vec_u8 (cpu
, vd
, i
,
11365 aarch64_get_mem_u8 (cpu
, address
+ i
));
11369 /* LD1 {Vd.8h}, addr, #16 */
11370 /* LD1 {Vd.4h}, addr, #8 */
11371 for (i
= 0; i
< (all
? 8 : 4); i
++)
11372 aarch64_set_vec_u16 (cpu
, vd
, i
,
11373 aarch64_get_mem_u16 (cpu
, address
+ i
* 2));
11377 /* LD1 {Vd.4s}, addr, #16 */
11378 /* LD1 {Vd.2s}, addr, #8 */
11379 for (i
= 0; i
< (all
? 4 : 2); i
++)
11380 aarch64_set_vec_u32 (cpu
, vd
, i
,
11381 aarch64_get_mem_u32 (cpu
, address
+ i
* 4));
11385 /* LD1 {Vd.2d}, addr, #16 */
11386 /* LD1 {Vd.1d}, addr, #8 */
11387 for (i
= 0; i
< (all
? 2 : 1); i
++)
11388 aarch64_set_vec_u64 (cpu
, vd
, i
,
11389 aarch64_get_mem_u64 (cpu
, address
+ i
* 8));
11394 /* Load multiple 1-element structures into two registers. */
11396 LD1_2 (sim_cpu
*cpu
, uint64_t address
)
11398 /* FIXME: This algorithm is *exactly* the same as the LD2 version.
11399 So why have two different instructions ? There must be something
11400 wrong somewhere. */
11401 vec_load (cpu
, address
, 2);
11404 /* Load multiple 1-element structures into three registers. */
11406 LD1_3 (sim_cpu
*cpu
, uint64_t address
)
11408 /* FIXME: This algorithm is *exactly* the same as the LD3 version.
11409 So why have two different instructions ? There must be something
11410 wrong somewhere. */
11411 vec_load (cpu
, address
, 3);
11414 /* Load multiple 1-element structures into four registers. */
11416 LD1_4 (sim_cpu
*cpu
, uint64_t address
)
11418 /* FIXME: This algorithm is *exactly* the same as the LD4 version.
11419 So why have two different instructions ? There must be something
11420 wrong somewhere. */
11421 vec_load (cpu
, address
, 4);
11424 /* Store multiple N-element structures to N consecutive registers. */
11426 vec_store (sim_cpu
*cpu
, uint64_t address
, unsigned N
)
11428 int all
= INSTR (30, 30);
11429 unsigned size
= INSTR (11, 10);
11430 unsigned vd
= INSTR (4, 0);
11435 case 0: /* 8-bit operations. */
11437 for (i
= 0; i
< (16 * N
); i
++)
11440 aarch64_get_vec_u8 (cpu
, vec_reg (vd
, i
>> 4), i
& 15));
11442 for (i
= 0; i
< (8 * N
); i
++)
11445 aarch64_get_vec_u8 (cpu
, vec_reg (vd
, i
>> 3), i
& 7));
11448 case 1: /* 16-bit operations. */
11450 for (i
= 0; i
< (8 * N
); i
++)
11451 aarch64_set_mem_u16
11452 (cpu
, address
+ i
* 2,
11453 aarch64_get_vec_u16 (cpu
, vec_reg (vd
, i
>> 3), i
& 7));
11455 for (i
= 0; i
< (4 * N
); i
++)
11456 aarch64_set_mem_u16
11457 (cpu
, address
+ i
* 2,
11458 aarch64_get_vec_u16 (cpu
, vec_reg (vd
, i
>> 2), i
& 3));
11461 case 2: /* 32-bit operations. */
11463 for (i
= 0; i
< (4 * N
); i
++)
11464 aarch64_set_mem_u32
11465 (cpu
, address
+ i
* 4,
11466 aarch64_get_vec_u32 (cpu
, vec_reg (vd
, i
>> 2), i
& 3));
11468 for (i
= 0; i
< (2 * N
); i
++)
11469 aarch64_set_mem_u32
11470 (cpu
, address
+ i
* 4,
11471 aarch64_get_vec_u32 (cpu
, vec_reg (vd
, i
>> 1), i
& 1));
11474 case 3: /* 64-bit operations. */
11476 for (i
= 0; i
< (2 * N
); i
++)
11477 aarch64_set_mem_u64
11478 (cpu
, address
+ i
* 8,
11479 aarch64_get_vec_u64 (cpu
, vec_reg (vd
, i
>> 1), i
& 1));
11481 for (i
= 0; i
< N
; i
++)
11482 aarch64_set_mem_u64
11483 (cpu
, address
+ i
* 8,
11484 aarch64_get_vec_u64 (cpu
, vec_reg (vd
, i
), 0));
11489 /* Store multiple 4-element structure to four consecutive registers. */
11491 ST4 (sim_cpu
*cpu
, uint64_t address
)
11493 vec_store (cpu
, address
, 4);
11496 /* Store multiple 3-element structures to three consecutive registers. */
11498 ST3 (sim_cpu
*cpu
, uint64_t address
)
11500 vec_store (cpu
, address
, 3);
11503 /* Store multiple 2-element structures to two consecutive registers. */
11505 ST2 (sim_cpu
*cpu
, uint64_t address
)
11507 vec_store (cpu
, address
, 2);
11510 /* Store multiple 1-element structures into one register. */
11512 ST1_1 (sim_cpu
*cpu
, uint64_t address
)
11514 int all
= INSTR (30, 30);
11515 unsigned size
= INSTR (11, 10);
11516 unsigned vd
= INSTR (4, 0);
11522 for (i
= 0; i
< (all
? 16 : 8); i
++)
11523 aarch64_set_mem_u8 (cpu
, address
+ i
,
11524 aarch64_get_vec_u8 (cpu
, vd
, i
));
11528 for (i
= 0; i
< (all
? 8 : 4); i
++)
11529 aarch64_set_mem_u16 (cpu
, address
+ i
* 2,
11530 aarch64_get_vec_u16 (cpu
, vd
, i
));
11534 for (i
= 0; i
< (all
? 4 : 2); i
++)
11535 aarch64_set_mem_u32 (cpu
, address
+ i
* 4,
11536 aarch64_get_vec_u32 (cpu
, vd
, i
));
11540 for (i
= 0; i
< (all
? 2 : 1); i
++)
11541 aarch64_set_mem_u64 (cpu
, address
+ i
* 8,
11542 aarch64_get_vec_u64 (cpu
, vd
, i
));
11547 /* Store multiple 1-element structures into two registers. */
11549 ST1_2 (sim_cpu
*cpu
, uint64_t address
)
11551 /* FIXME: This algorithm is *exactly* the same as the ST2 version.
11552 So why have two different instructions ? There must be
11553 something wrong somewhere. */
11554 vec_store (cpu
, address
, 2);
11557 /* Store multiple 1-element structures into three registers. */
11559 ST1_3 (sim_cpu
*cpu
, uint64_t address
)
11561 /* FIXME: This algorithm is *exactly* the same as the ST3 version.
11562 So why have two different instructions ? There must be
11563 something wrong somewhere. */
11564 vec_store (cpu
, address
, 3);
11567 /* Store multiple 1-element structures into four registers. */
11569 ST1_4 (sim_cpu
*cpu
, uint64_t address
)
11571 /* FIXME: This algorithm is *exactly* the same as the ST4 version.
11572 So why have two different instructions ? There must be
11573 something wrong somewhere. */
11574 vec_store (cpu
, address
, 4);
11578 do_vec_LDnR (sim_cpu
*cpu
, uint64_t address
)
11581 instr[30] = element selector 0=>half, 1=>all elements
11582 instr[29,24] = 00 1101
11583 instr[23] = 0=>simple, 1=>post
11585 instr[21] = width: LD1R-or-LD3R (0) / LD2R-or-LD4R (1)
11586 instr[20,16] = 0 0000 (simple), Vinc (reg-post-inc, no SP),
11587 11111 (immediate post inc)
11589 instr[13] = width: LD1R-or-LD2R (0) / LD3R-or-LD4R (1)
11591 instr[11,10] = element size 00=> byte(b), 01=> half(h),
11592 10=> word(s), 11=> double(d)
11593 instr[9,5] = address
11596 unsigned full
= INSTR (30, 30);
11597 unsigned vd
= INSTR (4, 0);
11598 unsigned size
= INSTR (11, 10);
11601 NYI_assert (29, 24, 0x0D);
11602 NYI_assert (22, 22, 1);
11603 NYI_assert (15, 14, 3);
11604 NYI_assert (12, 12, 0);
11606 switch ((INSTR (13, 13) << 1) | INSTR (21, 21))
11608 case 0: /* LD1R. */
11613 uint8_t val
= aarch64_get_mem_u8 (cpu
, address
);
11614 for (i
= 0; i
< (full
? 16 : 8); i
++)
11615 aarch64_set_vec_u8 (cpu
, vd
, i
, val
);
11621 uint16_t val
= aarch64_get_mem_u16 (cpu
, address
);
11622 for (i
= 0; i
< (full
? 8 : 4); i
++)
11623 aarch64_set_vec_u16 (cpu
, vd
, i
, val
);
11629 uint32_t val
= aarch64_get_mem_u32 (cpu
, address
);
11630 for (i
= 0; i
< (full
? 4 : 2); i
++)
11631 aarch64_set_vec_u32 (cpu
, vd
, i
, val
);
11637 uint64_t val
= aarch64_get_mem_u64 (cpu
, address
);
11638 for (i
= 0; i
< (full
? 2 : 1); i
++)
11639 aarch64_set_vec_u64 (cpu
, vd
, i
, val
);
11648 case 1: /* LD2R. */
11653 uint8_t val1
= aarch64_get_mem_u8 (cpu
, address
);
11654 uint8_t val2
= aarch64_get_mem_u8 (cpu
, address
+ 1);
11656 for (i
= 0; i
< (full
? 16 : 8); i
++)
11658 aarch64_set_vec_u8 (cpu
, vd
, 0, val1
);
11659 aarch64_set_vec_u8 (cpu
, vd
+ 1, 0, val2
);
11666 uint16_t val1
= aarch64_get_mem_u16 (cpu
, address
);
11667 uint16_t val2
= aarch64_get_mem_u16 (cpu
, address
+ 2);
11669 for (i
= 0; i
< (full
? 8 : 4); i
++)
11671 aarch64_set_vec_u16 (cpu
, vd
, 0, val1
);
11672 aarch64_set_vec_u16 (cpu
, vd
+ 1, 0, val2
);
11679 uint32_t val1
= aarch64_get_mem_u32 (cpu
, address
);
11680 uint32_t val2
= aarch64_get_mem_u32 (cpu
, address
+ 4);
11682 for (i
= 0; i
< (full
? 4 : 2); i
++)
11684 aarch64_set_vec_u32 (cpu
, vd
, 0, val1
);
11685 aarch64_set_vec_u32 (cpu
, vd
+ 1, 0, val2
);
11692 uint64_t val1
= aarch64_get_mem_u64 (cpu
, address
);
11693 uint64_t val2
= aarch64_get_mem_u64 (cpu
, address
+ 8);
11695 for (i
= 0; i
< (full
? 2 : 1); i
++)
11697 aarch64_set_vec_u64 (cpu
, vd
, 0, val1
);
11698 aarch64_set_vec_u64 (cpu
, vd
+ 1, 0, val2
);
11708 case 2: /* LD3R. */
11713 uint8_t val1
= aarch64_get_mem_u8 (cpu
, address
);
11714 uint8_t val2
= aarch64_get_mem_u8 (cpu
, address
+ 1);
11715 uint8_t val3
= aarch64_get_mem_u8 (cpu
, address
+ 2);
11717 for (i
= 0; i
< (full
? 16 : 8); i
++)
11719 aarch64_set_vec_u8 (cpu
, vd
, 0, val1
);
11720 aarch64_set_vec_u8 (cpu
, vd
+ 1, 0, val2
);
11721 aarch64_set_vec_u8 (cpu
, vd
+ 2, 0, val3
);
11728 uint32_t val1
= aarch64_get_mem_u16 (cpu
, address
);
11729 uint32_t val2
= aarch64_get_mem_u16 (cpu
, address
+ 2);
11730 uint32_t val3
= aarch64_get_mem_u16 (cpu
, address
+ 4);
11732 for (i
= 0; i
< (full
? 8 : 4); i
++)
11734 aarch64_set_vec_u16 (cpu
, vd
, 0, val1
);
11735 aarch64_set_vec_u16 (cpu
, vd
+ 1, 0, val2
);
11736 aarch64_set_vec_u16 (cpu
, vd
+ 2, 0, val3
);
11743 uint32_t val1
= aarch64_get_mem_u32 (cpu
, address
);
11744 uint32_t val2
= aarch64_get_mem_u32 (cpu
, address
+ 4);
11745 uint32_t val3
= aarch64_get_mem_u32 (cpu
, address
+ 8);
11747 for (i
= 0; i
< (full
? 4 : 2); i
++)
11749 aarch64_set_vec_u32 (cpu
, vd
, 0, val1
);
11750 aarch64_set_vec_u32 (cpu
, vd
+ 1, 0, val2
);
11751 aarch64_set_vec_u32 (cpu
, vd
+ 2, 0, val3
);
11758 uint64_t val1
= aarch64_get_mem_u64 (cpu
, address
);
11759 uint64_t val2
= aarch64_get_mem_u64 (cpu
, address
+ 8);
11760 uint64_t val3
= aarch64_get_mem_u64 (cpu
, address
+ 16);
11762 for (i
= 0; i
< (full
? 2 : 1); i
++)
11764 aarch64_set_vec_u64 (cpu
, vd
, 0, val1
);
11765 aarch64_set_vec_u64 (cpu
, vd
+ 1, 0, val2
);
11766 aarch64_set_vec_u64 (cpu
, vd
+ 2, 0, val3
);
11776 case 3: /* LD4R. */
11781 uint8_t val1
= aarch64_get_mem_u8 (cpu
, address
);
11782 uint8_t val2
= aarch64_get_mem_u8 (cpu
, address
+ 1);
11783 uint8_t val3
= aarch64_get_mem_u8 (cpu
, address
+ 2);
11784 uint8_t val4
= aarch64_get_mem_u8 (cpu
, address
+ 3);
11786 for (i
= 0; i
< (full
? 16 : 8); i
++)
11788 aarch64_set_vec_u8 (cpu
, vd
, 0, val1
);
11789 aarch64_set_vec_u8 (cpu
, vd
+ 1, 0, val2
);
11790 aarch64_set_vec_u8 (cpu
, vd
+ 2, 0, val3
);
11791 aarch64_set_vec_u8 (cpu
, vd
+ 3, 0, val4
);
11798 uint32_t val1
= aarch64_get_mem_u16 (cpu
, address
);
11799 uint32_t val2
= aarch64_get_mem_u16 (cpu
, address
+ 2);
11800 uint32_t val3
= aarch64_get_mem_u16 (cpu
, address
+ 4);
11801 uint32_t val4
= aarch64_get_mem_u16 (cpu
, address
+ 6);
11803 for (i
= 0; i
< (full
? 8 : 4); i
++)
11805 aarch64_set_vec_u16 (cpu
, vd
, 0, val1
);
11806 aarch64_set_vec_u16 (cpu
, vd
+ 1, 0, val2
);
11807 aarch64_set_vec_u16 (cpu
, vd
+ 2, 0, val3
);
11808 aarch64_set_vec_u16 (cpu
, vd
+ 3, 0, val4
);
11815 uint32_t val1
= aarch64_get_mem_u32 (cpu
, address
);
11816 uint32_t val2
= aarch64_get_mem_u32 (cpu
, address
+ 4);
11817 uint32_t val3
= aarch64_get_mem_u32 (cpu
, address
+ 8);
11818 uint32_t val4
= aarch64_get_mem_u32 (cpu
, address
+ 12);
11820 for (i
= 0; i
< (full
? 4 : 2); i
++)
11822 aarch64_set_vec_u32 (cpu
, vd
, 0, val1
);
11823 aarch64_set_vec_u32 (cpu
, vd
+ 1, 0, val2
);
11824 aarch64_set_vec_u32 (cpu
, vd
+ 2, 0, val3
);
11825 aarch64_set_vec_u32 (cpu
, vd
+ 3, 0, val4
);
11832 uint64_t val1
= aarch64_get_mem_u64 (cpu
, address
);
11833 uint64_t val2
= aarch64_get_mem_u64 (cpu
, address
+ 8);
11834 uint64_t val3
= aarch64_get_mem_u64 (cpu
, address
+ 16);
11835 uint64_t val4
= aarch64_get_mem_u64 (cpu
, address
+ 24);
11837 for (i
= 0; i
< (full
? 2 : 1); i
++)
11839 aarch64_set_vec_u64 (cpu
, vd
, 0, val1
);
11840 aarch64_set_vec_u64 (cpu
, vd
+ 1, 0, val2
);
11841 aarch64_set_vec_u64 (cpu
, vd
+ 2, 0, val3
);
11842 aarch64_set_vec_u64 (cpu
, vd
+ 3, 0, val4
);
11858 do_vec_load_store (sim_cpu
*cpu
)
11860 /* {LD|ST}<N> {Vd..Vd+N}, vaddr
11863 instr[30] = element selector 0=>half, 1=>all elements
11864 instr[29,25] = 00110
11866 instr[23] = 0=>simple, 1=>post
11867 instr[22] = 0=>store, 1=>load
11868 instr[21] = 0 (LDn) / small(0)-large(1) selector (LDnR)
11869 instr[20,16] = 00000 (simple), Vinc (reg-post-inc, no SP),
11870 11111 (immediate post inc)
11871 instr[15,12] = elements and destinations. eg for load:
11872 0000=>LD4 => load multiple 4-element to
11873 four consecutive registers
11874 0100=>LD3 => load multiple 3-element to
11875 three consecutive registers
11876 1000=>LD2 => load multiple 2-element to
11877 two consecutive registers
11878 0010=>LD1 => load multiple 1-element to
11879 four consecutive registers
11880 0110=>LD1 => load multiple 1-element to
11881 three consecutive registers
11882 1010=>LD1 => load multiple 1-element to
11883 two consecutive registers
11884 0111=>LD1 => load multiple 1-element to
11888 instr[11,10] = element size 00=> byte(b), 01=> half(h),
11889 10=> word(s), 11=> double(d)
11890 instr[9,5] = Vn, can be SP
11899 if (INSTR (31, 31) != 0 || INSTR (29, 25) != 0x06)
11902 type
= INSTR (15, 12);
11903 if (type
!= 0xE && type
!= 0xE && INSTR (21, 21) != 0)
11906 post
= INSTR (23, 23);
11907 load
= INSTR (22, 22);
11909 address
= aarch64_get_reg_u64 (cpu
, vn
, SP_OK
);
11913 unsigned vm
= INSTR (20, 16);
11917 unsigned sizeof_operation
;
11921 case 0: sizeof_operation
= 32; break;
11922 case 4: sizeof_operation
= 24; break;
11923 case 8: sizeof_operation
= 16; break;
11926 sizeof_operation
= INSTR (21, 21) ? 2 : 1;
11927 sizeof_operation
<<= INSTR (11, 10);
11931 sizeof_operation
= INSTR (21, 21) ? 8 : 4;
11932 sizeof_operation
<<= INSTR (11, 10);
11936 /* One register, immediate offset variant. */
11937 sizeof_operation
= 8;
11941 /* Two registers, immediate offset variant. */
11942 sizeof_operation
= 16;
11946 /* Three registers, immediate offset variant. */
11947 sizeof_operation
= 24;
11951 /* Four registers, immediate offset variant. */
11952 sizeof_operation
= 32;
11959 if (INSTR (30, 30))
11960 sizeof_operation
*= 2;
11962 aarch64_set_reg_u64 (cpu
, vn
, SP_OK
, address
+ sizeof_operation
);
11965 aarch64_set_reg_u64 (cpu
, vn
, SP_OK
,
11966 address
+ aarch64_get_reg_u64 (cpu
, vm
, NO_SP
));
11970 NYI_assert (20, 16, 0);
11977 case 0: LD4 (cpu
, address
); return;
11978 case 4: LD3 (cpu
, address
); return;
11979 case 8: LD2 (cpu
, address
); return;
11980 case 2: LD1_4 (cpu
, address
); return;
11981 case 6: LD1_3 (cpu
, address
); return;
11982 case 10: LD1_2 (cpu
, address
); return;
11983 case 7: LD1_1 (cpu
, address
); return;
11986 case 0xC: do_vec_LDnR (cpu
, address
); return;
11996 case 0: ST4 (cpu
, address
); return;
11997 case 4: ST3 (cpu
, address
); return;
11998 case 8: ST2 (cpu
, address
); return;
11999 case 2: ST1_4 (cpu
, address
); return;
12000 case 6: ST1_3 (cpu
, address
); return;
12001 case 10: ST1_2 (cpu
, address
); return;
12002 case 7: ST1_1 (cpu
, address
); return;
12009 dexLdSt (sim_cpu
*cpu
)
12011 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
12012 assert group == GROUP_LDST_0100 || group == GROUP_LDST_0110 ||
12013 group == GROUP_LDST_1100 || group == GROUP_LDST_1110
12014 bits [29,28:26] of a LS are the secondary dispatch vector. */
12015 uint32_t group2
= dispatchLS (aarch64_get_instr (cpu
));
12020 dexLoadExclusive (cpu
); return;
12024 dexLoadLiteral (cpu
); return;
12028 dexLoadOther (cpu
); return;
12030 case LS_ADVSIMD_001
:
12031 do_vec_load_store (cpu
); return;
12034 dex_load_store_pair_gr (cpu
); return;
12037 dex_load_store_pair_fp (cpu
); return;
12040 /* Should never reach here. */
12045 /* Specific decode and execute for group Data Processing Register. */
12048 dexLogicalShiftedRegister (sim_cpu
*cpu
)
12050 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12052 instr[28:24] = 01010
12053 instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> ROR
12056 instr[15,10] = count : must be 0xxxxx for 32 bit
12060 uint32_t size
= INSTR (31, 31);
12061 Shift shiftType
= INSTR (23, 22);
12062 uint32_t count
= INSTR (15, 10);
12064 /* 32 bit operations must have count[5] = 0.
12065 or else we have an UNALLOC. */
12066 if (size
== 0 && uimm (count
, 5, 5))
12069 /* Dispatch on size:op:N. */
12070 switch ((INSTR (31, 29) << 1) | INSTR (21, 21))
12072 case 0: and32_shift (cpu
, shiftType
, count
); return;
12073 case 1: bic32_shift (cpu
, shiftType
, count
); return;
12074 case 2: orr32_shift (cpu
, shiftType
, count
); return;
12075 case 3: orn32_shift (cpu
, shiftType
, count
); return;
12076 case 4: eor32_shift (cpu
, shiftType
, count
); return;
12077 case 5: eon32_shift (cpu
, shiftType
, count
); return;
12078 case 6: ands32_shift (cpu
, shiftType
, count
); return;
12079 case 7: bics32_shift (cpu
, shiftType
, count
); return;
12080 case 8: and64_shift (cpu
, shiftType
, count
); return;
12081 case 9: bic64_shift (cpu
, shiftType
, count
); return;
12082 case 10:orr64_shift (cpu
, shiftType
, count
); return;
12083 case 11:orn64_shift (cpu
, shiftType
, count
); return;
12084 case 12:eor64_shift (cpu
, shiftType
, count
); return;
12085 case 13:eon64_shift (cpu
, shiftType
, count
); return;
12086 case 14:ands64_shift (cpu
, shiftType
, count
); return;
12087 case 15:bics64_shift (cpu
, shiftType
, count
); return;
12091 /* 32 bit conditional select. */
12093 csel32 (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_u32 (cpu
, rn
, NO_SP
)
12102 : aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12105 /* 64 bit conditional select. */
12107 csel64 (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_u64 (cpu
, rn
, NO_SP
)
12116 : aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
12119 /* 32 bit conditional increment. */
12121 csinc32 (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_u32 (cpu
, rn
, NO_SP
)
12130 : aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) + 1);
12133 /* 64 bit conditional increment. */
12135 csinc64 (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_u64 (cpu
, rn
, NO_SP
)
12144 : aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) + 1);
12147 /* 32 bit conditional invert. */
12149 csinv32 (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_u32 (cpu
, rn
, NO_SP
)
12158 : ~ aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12161 /* 64 bit conditional invert. */
12163 csinv64 (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_u64 (cpu
, rn
, NO_SP
)
12172 : ~ aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
12175 /* 32 bit conditional negate. */
12177 csneg32 (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_u32 (cpu
, rn
, NO_SP
)
12186 : - aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12189 /* 64 bit conditional negate. */
12191 csneg64 (sim_cpu
*cpu
, CondCode cc
)
12193 unsigned rm
= INSTR (20, 16);
12194 unsigned rn
= INSTR (9, 5);
12195 unsigned rd
= INSTR (4, 0);
12197 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12198 testConditionCode (cpu
, cc
)
12199 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12200 : - aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
12204 dexCondSelect (sim_cpu
*cpu
)
12206 /* instr[28,21] = 11011011
12207 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12208 instr[30:11,10] = op : 000 ==> CSEL, 001 ==> CSINC,
12209 100 ==> CSINV, 101 ==> CSNEG,
12211 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
12212 instr[15,12] = cond
12213 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC */
12215 CondCode cc
= INSTR (15, 12);
12216 uint32_t S
= INSTR (29, 29);
12217 uint32_t op2
= INSTR (11, 10);
12225 switch ((INSTR (31, 30) << 1) | op2
)
12227 case 0: csel32 (cpu
, cc
); return;
12228 case 1: csinc32 (cpu
, cc
); return;
12229 case 2: csinv32 (cpu
, cc
); return;
12230 case 3: csneg32 (cpu
, cc
); return;
12231 case 4: csel64 (cpu
, cc
); return;
12232 case 5: csinc64 (cpu
, cc
); return;
12233 case 6: csinv64 (cpu
, cc
); return;
12234 case 7: csneg64 (cpu
, cc
); return;
12238 /* Some helpers for counting leading 1 or 0 bits. */
12240 /* Counts the number of leading bits which are the same
12241 in a 32 bit value in the range 1 to 32. */
12243 leading32 (uint32_t value
)
12245 int32_t mask
= 0xffff0000;
12246 uint32_t count
= 16; /* Counts number of bits set in mask. */
12247 uint32_t lo
= 1; /* Lower bound for number of sign bits. */
12248 uint32_t hi
= 32; /* Upper bound for number of sign bits. */
12250 while (lo
+ 1 < hi
)
12252 int32_t test
= (value
& mask
);
12254 if (test
== 0 || test
== mask
)
12257 count
= (lo
+ hi
) / 2;
12258 mask
>>= (count
- lo
);
12263 count
= (lo
+ hi
) / 2;
12264 mask
<<= hi
- count
;
12273 test
= (value
& mask
);
12275 if (test
== 0 || test
== mask
)
12284 /* Counts the number of leading bits which are the same
12285 in a 64 bit value in the range 1 to 64. */
12287 leading64 (uint64_t value
)
12289 int64_t mask
= 0xffffffff00000000LL
;
12290 uint64_t count
= 32; /* Counts number of bits set in mask. */
12291 uint64_t lo
= 1; /* Lower bound for number of sign bits. */
12292 uint64_t hi
= 64; /* Upper bound for number of sign bits. */
12294 while (lo
+ 1 < hi
)
12296 int64_t test
= (value
& mask
);
12298 if (test
== 0 || test
== mask
)
12301 count
= (lo
+ hi
) / 2;
12302 mask
>>= (count
- lo
);
12307 count
= (lo
+ hi
) / 2;
12308 mask
<<= hi
- count
;
12317 test
= (value
& mask
);
12319 if (test
== 0 || test
== mask
)
12328 /* Bit operations. */
12329 /* N.B register args may not be SP. */
12331 /* 32 bit count leading sign bits. */
12333 cls32 (sim_cpu
*cpu
)
12335 unsigned rn
= INSTR (9, 5);
12336 unsigned rd
= INSTR (4, 0);
12338 /* N.B. the result needs to exclude the leading bit. */
12339 aarch64_set_reg_u64
12340 (cpu
, rd
, NO_SP
, leading32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)) - 1);
12343 /* 64 bit count leading sign bits. */
12345 cls64 (sim_cpu
*cpu
)
12347 unsigned rn
= INSTR (9, 5);
12348 unsigned rd
= INSTR (4, 0);
12350 /* N.B. the result needs to exclude the leading bit. */
12351 aarch64_set_reg_u64
12352 (cpu
, rd
, NO_SP
, leading64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)) - 1);
12355 /* 32 bit count leading zero bits. */
12357 clz32 (sim_cpu
*cpu
)
12359 unsigned rn
= INSTR (9, 5);
12360 unsigned rd
= INSTR (4, 0);
12361 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12363 /* if the sign (top) bit is set then the count is 0. */
12364 if (pick32 (value
, 31, 31))
12365 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, 0L);
12367 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, leading32 (value
));
12370 /* 64 bit count leading zero bits. */
12372 clz64 (sim_cpu
*cpu
)
12374 unsigned rn
= INSTR (9, 5);
12375 unsigned rd
= INSTR (4, 0);
12376 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12378 /* if the sign (top) bit is set then the count is 0. */
12379 if (pick64 (value
, 63, 63))
12380 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, 0L);
12382 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, leading64 (value
));
12385 /* 32 bit reverse bits. */
12387 rbit32 (sim_cpu
*cpu
)
12389 unsigned rn
= INSTR (9, 5);
12390 unsigned rd
= INSTR (4, 0);
12391 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12392 uint32_t result
= 0;
12395 for (i
= 0; i
< 32; i
++)
12398 result
|= (value
& 1);
12401 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12404 /* 64 bit reverse bits. */
12406 rbit64 (sim_cpu
*cpu
)
12408 unsigned rn
= INSTR (9, 5);
12409 unsigned rd
= INSTR (4, 0);
12410 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12411 uint64_t result
= 0;
12414 for (i
= 0; i
< 64; i
++)
12417 result
|= (value
& 1UL);
12420 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12423 /* 32 bit reverse bytes. */
12425 rev32 (sim_cpu
*cpu
)
12427 unsigned rn
= INSTR (9, 5);
12428 unsigned rd
= INSTR (4, 0);
12429 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12430 uint32_t result
= 0;
12433 for (i
= 0; i
< 4; i
++)
12436 result
|= (value
& 0xff);
12439 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12442 /* 64 bit reverse bytes. */
12444 rev64 (sim_cpu
*cpu
)
12446 unsigned rn
= INSTR (9, 5);
12447 unsigned rd
= INSTR (4, 0);
12448 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12449 uint64_t result
= 0;
12452 for (i
= 0; i
< 8; i
++)
12455 result
|= (value
& 0xffULL
);
12458 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12461 /* 32 bit reverse shorts. */
12462 /* N.B.this reverses the order of the bytes in each half word. */
12464 revh32 (sim_cpu
*cpu
)
12466 unsigned rn
= INSTR (9, 5);
12467 unsigned rd
= INSTR (4, 0);
12468 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12469 uint32_t result
= 0;
12472 for (i
= 0; i
< 2; i
++)
12475 result
|= (value
& 0x00ff00ff);
12478 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12481 /* 64 bit reverse shorts. */
12482 /* N.B.this reverses the order of the bytes in each half word. */
12484 revh64 (sim_cpu
*cpu
)
12486 unsigned rn
= INSTR (9, 5);
12487 unsigned rd
= INSTR (4, 0);
12488 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12489 uint64_t result
= 0;
12492 for (i
= 0; i
< 2; i
++)
12495 result
|= (value
& 0x00ff00ff00ff00ffULL
);
12498 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12502 dexDataProc1Source (sim_cpu
*cpu
)
12505 instr[28,21] = 111010110
12506 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12507 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
12508 instr[20,16] = opcode2 : 00000 ==> ok, ow ==> UNALLOC
12509 instr[15,10] = opcode : 000000 ==> RBIT, 000001 ==> REV16,
12510 000010 ==> REV, 000011 ==> UNALLOC
12511 000100 ==> CLZ, 000101 ==> CLS
12513 instr[9,5] = rn : may not be SP
12514 instr[4,0] = rd : may not be SP. */
12516 uint32_t S
= INSTR (29, 29);
12517 uint32_t opcode2
= INSTR (20, 16);
12518 uint32_t opcode
= INSTR (15, 10);
12519 uint32_t dispatch
= ((INSTR (31, 31) << 3) | opcode
);
12532 case 0: rbit32 (cpu
); return;
12533 case 1: revh32 (cpu
); return;
12534 case 2: rev32 (cpu
); return;
12535 case 4: clz32 (cpu
); return;
12536 case 5: cls32 (cpu
); return;
12537 case 8: rbit64 (cpu
); return;
12538 case 9: revh64 (cpu
); return;
12539 case 10:rev32 (cpu
); return;
12540 case 11:rev64 (cpu
); return;
12541 case 12:clz64 (cpu
); return;
12542 case 13:cls64 (cpu
); return;
12543 default: HALT_UNALLOC
;
12548 Shifts by count supplied in register.
12549 N.B register args may not be SP.
12550 These all use the shifted auxiliary function for
12551 simplicity and clarity. Writing the actual shift
12552 inline would avoid a branch and so be faster but
12553 would also necessitate getting signs right. */
12555 /* 32 bit arithmetic shift right. */
12557 asrv32 (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 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), ASR
,
12566 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12569 /* 64 bit arithmetic shift right. */
12571 asrv64 (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 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), ASR
,
12580 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12583 /* 32 bit logical shift left. */
12585 lslv32 (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 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), LSL
,
12594 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12597 /* 64 bit arithmetic shift left. */
12599 lslv64 (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 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), LSL
,
12608 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12611 /* 32 bit logical shift right. */
12613 lsrv32 (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 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), LSR
,
12622 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12625 /* 64 bit logical shift right. */
12627 lsrv64 (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 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), LSR
,
12636 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12639 /* 32 bit rotate right. */
12641 rorv32 (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 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), ROR
,
12650 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12653 /* 64 bit rotate right. */
12655 rorv64 (sim_cpu
*cpu
)
12657 unsigned rm
= INSTR (20, 16);
12658 unsigned rn
= INSTR (9, 5);
12659 unsigned rd
= INSTR (4, 0);
12661 aarch64_set_reg_u64
12663 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), ROR
,
12664 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12670 /* 32 bit signed divide. */
12672 cpuiv32 (sim_cpu
*cpu
)
12674 unsigned rm
= INSTR (20, 16);
12675 unsigned rn
= INSTR (9, 5);
12676 unsigned rd
= INSTR (4, 0);
12677 /* N.B. the pseudo-code does the divide using 64 bit data. */
12678 /* TODO : check that this rounds towards zero as required. */
12679 int64_t dividend
= aarch64_get_reg_s32 (cpu
, rn
, NO_SP
);
12680 int64_t divisor
= aarch64_get_reg_s32 (cpu
, rm
, NO_SP
);
12682 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
,
12683 divisor
? ((int32_t) (dividend
/ divisor
)) : 0);
12686 /* 64 bit signed divide. */
12688 cpuiv64 (sim_cpu
*cpu
)
12690 unsigned rm
= INSTR (20, 16);
12691 unsigned rn
= INSTR (9, 5);
12692 unsigned rd
= INSTR (4, 0);
12694 /* TODO : check that this rounds towards zero as required. */
12695 int64_t divisor
= aarch64_get_reg_s64 (cpu
, rm
, NO_SP
);
12697 aarch64_set_reg_s64
12699 divisor
? (aarch64_get_reg_s64 (cpu
, rn
, NO_SP
) / divisor
) : 0);
12702 /* 32 bit unsigned divide. */
12704 udiv32 (sim_cpu
*cpu
)
12706 unsigned rm
= INSTR (20, 16);
12707 unsigned rn
= INSTR (9, 5);
12708 unsigned rd
= INSTR (4, 0);
12710 /* N.B. the pseudo-code does the divide using 64 bit data. */
12711 uint64_t dividend
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12712 uint64_t divisor
= aarch64_get_reg_u32 (cpu
, rm
, NO_SP
);
12714 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12715 divisor
? (uint32_t) (dividend
/ divisor
) : 0);
12718 /* 64 bit unsigned divide. */
12720 udiv64 (sim_cpu
*cpu
)
12722 unsigned rm
= INSTR (20, 16);
12723 unsigned rn
= INSTR (9, 5);
12724 unsigned rd
= INSTR (4, 0);
12726 /* TODO : check that this rounds towards zero as required. */
12727 uint64_t divisor
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
12729 aarch64_set_reg_u64
12731 divisor
? (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) / divisor
) : 0);
12735 dexDataProc2Source (sim_cpu
*cpu
)
12737 /* assert instr[30] == 0
12738 instr[28,21] == 11010110
12739 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12740 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
12741 instr[15,10] = opcode : 000010 ==> UDIV, 000011 ==> CPUIV,
12742 001000 ==> LSLV, 001001 ==> LSRV
12743 001010 ==> ASRV, 001011 ==> RORV
12747 uint32_t S
= INSTR (29, 29);
12748 uint32_t opcode
= INSTR (15, 10);
12756 dispatch
= ( (INSTR (31, 31) << 3)
12757 | (uimm (opcode
, 3, 3) << 2)
12758 | uimm (opcode
, 1, 0));
12761 case 2: udiv32 (cpu
); return;
12762 case 3: cpuiv32 (cpu
); return;
12763 case 4: lslv32 (cpu
); return;
12764 case 5: lsrv32 (cpu
); return;
12765 case 6: asrv32 (cpu
); return;
12766 case 7: rorv32 (cpu
); return;
12767 case 10: udiv64 (cpu
); return;
12768 case 11: cpuiv64 (cpu
); return;
12769 case 12: lslv64 (cpu
); return;
12770 case 13: lsrv64 (cpu
); return;
12771 case 14: asrv64 (cpu
); return;
12772 case 15: rorv64 (cpu
); return;
12773 default: HALT_UNALLOC
;
12780 /* 32 bit multiply and add. */
12782 madd32 (sim_cpu
*cpu
)
12784 unsigned rm
= INSTR (20, 16);
12785 unsigned ra
= INSTR (14, 10);
12786 unsigned rn
= INSTR (9, 5);
12787 unsigned rd
= INSTR (4, 0);
12789 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12790 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12791 aarch64_get_reg_u32 (cpu
, ra
, NO_SP
)
12792 + aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12793 * aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12796 /* 64 bit multiply and add. */
12798 madd64 (sim_cpu
*cpu
)
12800 unsigned rm
= INSTR (20, 16);
12801 unsigned ra
= INSTR (14, 10);
12802 unsigned rn
= INSTR (9, 5);
12803 unsigned rd
= INSTR (4, 0);
12805 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12806 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12807 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
12808 + (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12809 * aarch64_get_reg_u64 (cpu
, rm
, NO_SP
)));
12812 /* 32 bit multiply and sub. */
12814 msub32 (sim_cpu
*cpu
)
12816 unsigned rm
= INSTR (20, 16);
12817 unsigned ra
= INSTR (14, 10);
12818 unsigned rn
= INSTR (9, 5);
12819 unsigned rd
= INSTR (4, 0);
12821 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12822 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12823 aarch64_get_reg_u32 (cpu
, ra
, NO_SP
)
12824 - aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12825 * aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12828 /* 64 bit multiply and sub. */
12830 msub64 (sim_cpu
*cpu
)
12832 unsigned rm
= INSTR (20, 16);
12833 unsigned ra
= INSTR (14, 10);
12834 unsigned rn
= INSTR (9, 5);
12835 unsigned rd
= INSTR (4, 0);
12837 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12838 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12839 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
12840 - aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12841 * aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
12844 /* Signed multiply add long -- source, source2 : 32 bit, source3 : 64 bit. */
12846 smaddl (sim_cpu
*cpu
)
12848 unsigned rm
= INSTR (20, 16);
12849 unsigned ra
= INSTR (14, 10);
12850 unsigned rn
= INSTR (9, 5);
12851 unsigned rd
= INSTR (4, 0);
12853 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12854 obtain a 64 bit product. */
12855 aarch64_set_reg_s64
12857 aarch64_get_reg_s64 (cpu
, ra
, NO_SP
)
12858 + ((int64_t) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
))
12859 * ((int64_t) aarch64_get_reg_s32 (cpu
, rm
, NO_SP
)));
12862 /* Signed multiply sub long -- source, source2 : 32 bit, source3 : 64 bit. */
12864 smsubl (sim_cpu
*cpu
)
12866 unsigned rm
= INSTR (20, 16);
12867 unsigned ra
= INSTR (14, 10);
12868 unsigned rn
= INSTR (9, 5);
12869 unsigned rd
= INSTR (4, 0);
12871 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12872 obtain a 64 bit product. */
12873 aarch64_set_reg_s64
12875 aarch64_get_reg_s64 (cpu
, ra
, NO_SP
)
12876 - ((int64_t) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
))
12877 * ((int64_t) aarch64_get_reg_s32 (cpu
, rm
, NO_SP
)));
12880 /* Integer Multiply/Divide. */
12882 /* First some macros and a helper function. */
12883 /* Macros to test or access elements of 64 bit words. */
12885 /* Mask used to access lo 32 bits of 64 bit unsigned int. */
12886 #define LOW_WORD_MASK ((1ULL << 32) - 1)
12887 /* Return the lo 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int. */
12888 #define lowWordToU64(_value_u64) ((_value_u64) & LOW_WORD_MASK)
12889 /* Return the hi 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int. */
12890 #define highWordToU64(_value_u64) ((_value_u64) >> 32)
12892 /* Offset of sign bit in 64 bit signed integger. */
12893 #define SIGN_SHIFT_U64 63
12894 /* The sign bit itself -- also identifies the minimum negative int value. */
12895 #define SIGN_BIT_U64 (1UL << SIGN_SHIFT_U64)
12896 /* Return true if a 64 bit signed int presented as an unsigned int is the
12897 most negative value. */
12898 #define isMinimumU64(_value_u64) ((_value_u64) == SIGN_BIT_U64)
12899 /* Return true (non-zero) if a 64 bit signed int presented as an unsigned
12900 int has its sign bit set to false. */
12901 #define isSignSetU64(_value_u64) ((_value_u64) & SIGN_BIT_U64)
12902 /* Return 1L or -1L according to whether a 64 bit signed int presented as
12903 an unsigned int has its sign bit set or not. */
12904 #define signOfU64(_value_u64) (1L + (((value_u64) >> SIGN_SHIFT_U64) * -2L)
12905 /* Clear the sign bit of a 64 bit signed int presented as an unsigned int. */
12906 #define clearSignU64(_value_u64) ((_value_u64) &= ~SIGN_BIT_U64)
12908 /* Multiply two 64 bit ints and return.
12909 the hi 64 bits of the 128 bit product. */
12912 mul64hi (uint64_t value1
, uint64_t value2
)
12914 uint64_t resultmid1
;
12916 uint64_t value1_lo
= lowWordToU64 (value1
);
12917 uint64_t value1_hi
= highWordToU64 (value1
) ;
12918 uint64_t value2_lo
= lowWordToU64 (value2
);
12919 uint64_t value2_hi
= highWordToU64 (value2
);
12921 /* Cross-multiply and collect results. */
12922 uint64_t xproductlo
= value1_lo
* value2_lo
;
12923 uint64_t xproductmid1
= value1_lo
* value2_hi
;
12924 uint64_t xproductmid2
= value1_hi
* value2_lo
;
12925 uint64_t xproducthi
= value1_hi
* value2_hi
;
12926 uint64_t carry
= 0;
12927 /* Start accumulating 64 bit results. */
12928 /* Drop bottom half of lowest cross-product. */
12929 uint64_t resultmid
= xproductlo
>> 32;
12930 /* Add in middle products. */
12931 resultmid
= resultmid
+ xproductmid1
;
12933 /* Check for overflow. */
12934 if (resultmid
< xproductmid1
)
12935 /* Carry over 1 into top cross-product. */
12938 resultmid1
= resultmid
+ xproductmid2
;
12940 /* Check for overflow. */
12941 if (resultmid1
< xproductmid2
)
12942 /* Carry over 1 into top cross-product. */
12945 /* Drop lowest 32 bits of middle cross-product. */
12946 result
= resultmid1
>> 32;
12948 /* Add top cross-product plus and any carry. */
12949 result
+= xproducthi
+ carry
;
12954 /* Signed multiply high, source, source2 :
12955 64 bit, dest <-- high 64-bit of result. */
12957 smulh (sim_cpu
*cpu
)
12961 unsigned rm
= INSTR (20, 16);
12962 unsigned rn
= INSTR (9, 5);
12963 unsigned rd
= INSTR (4, 0);
12964 GReg ra
= INSTR (14, 10);
12965 int64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12966 int64_t value2
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
12969 int64_t signum
= 1;
12974 /* Convert to unsigned and use the unsigned mul64hi routine
12975 the fix the sign up afterwards. */
12996 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12997 uresult
= mul64hi (uvalue1
, uvalue2
);
13001 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, result
);
13004 /* Unsigned multiply add long -- source, source2 :
13005 32 bit, source3 : 64 bit. */
13007 umaddl (sim_cpu
*cpu
)
13009 unsigned rm
= INSTR (20, 16);
13010 unsigned ra
= INSTR (14, 10);
13011 unsigned rn
= INSTR (9, 5);
13012 unsigned rd
= INSTR (4, 0);
13014 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13015 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
13016 obtain a 64 bit product. */
13017 aarch64_set_reg_u64
13019 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
13020 + ((uint64_t) aarch64_get_reg_u32 (cpu
, rn
, NO_SP
))
13021 * ((uint64_t) aarch64_get_reg_u32 (cpu
, rm
, NO_SP
)));
13024 /* Unsigned multiply sub long -- source, source2 : 32 bit, source3 : 64 bit. */
13026 umsubl (sim_cpu
*cpu
)
13028 unsigned rm
= INSTR (20, 16);
13029 unsigned ra
= INSTR (14, 10);
13030 unsigned rn
= INSTR (9, 5);
13031 unsigned rd
= INSTR (4, 0);
13033 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13034 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
13035 obtain a 64 bit product. */
13036 aarch64_set_reg_u64
13038 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
13039 - ((uint64_t) aarch64_get_reg_u32 (cpu
, rn
, NO_SP
))
13040 * ((uint64_t) aarch64_get_reg_u32 (cpu
, rm
, NO_SP
)));
13043 /* Unsigned multiply high, source, source2 :
13044 64 bit, dest <-- high 64-bit of result. */
13046 umulh (sim_cpu
*cpu
)
13048 unsigned rm
= INSTR (20, 16);
13049 unsigned rn
= INSTR (9, 5);
13050 unsigned rd
= INSTR (4, 0);
13051 GReg ra
= INSTR (14, 10);
13056 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13057 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
13058 mul64hi (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
),
13059 aarch64_get_reg_u64 (cpu
, rm
, NO_SP
)));
13063 dexDataProc3Source (sim_cpu
*cpu
)
13065 /* assert instr[28,24] == 11011. */
13066 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit (for rd at least)
13067 instr[30,29] = op54 : 00 ==> ok, ow ==> UNALLOC
13068 instr[23,21] = op31 : 111 ==> UNALLOC, o2 ==> ok
13069 instr[15] = o0 : 0/1 ==> ok
13070 instr[23,21:15] ==> op : 0000 ==> MADD, 0001 ==> MSUB, (32/64 bit)
13071 0010 ==> SMADDL, 0011 ==> SMSUBL, (64 bit only)
13072 0100 ==> SMULH, (64 bit only)
13073 1010 ==> UMADDL, 1011 ==> UNSUBL, (64 bit only)
13074 1100 ==> UMULH (64 bit only)
13078 uint32_t size
= INSTR (31, 31);
13079 uint32_t op54
= INSTR (30, 29);
13080 uint32_t op31
= INSTR (23, 21);
13081 uint32_t o0
= INSTR (15, 15);
13098 dispatch
= (op31
<< 1) | o0
;
13102 case 0: madd64 (cpu
); return;
13103 case 1: msub64 (cpu
); return;
13104 case 2: smaddl (cpu
); return;
13105 case 3: smsubl (cpu
); return;
13106 case 4: smulh (cpu
); return;
13107 case 10: umaddl (cpu
); return;
13108 case 11: umsubl (cpu
); return;
13109 case 12: umulh (cpu
); return;
13110 default: HALT_UNALLOC
;
13115 dexDPReg (sim_cpu
*cpu
)
13117 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
13118 assert group == GROUP_DPREG_0101 || group == GROUP_DPREG_1101
13119 bits [28:24:21] of a DPReg are the secondary dispatch vector. */
13120 uint32_t group2
= dispatchDPReg (aarch64_get_instr (cpu
));
13124 case DPREG_LOG_000
:
13125 case DPREG_LOG_001
:
13126 dexLogicalShiftedRegister (cpu
); return;
13128 case DPREG_ADDSHF_010
:
13129 dexAddSubtractShiftedRegister (cpu
); return;
13131 case DPREG_ADDEXT_011
:
13132 dexAddSubtractExtendedRegister (cpu
); return;
13134 case DPREG_ADDCOND_100
:
13136 /* This set bundles a variety of different operations. */
13138 /* 1) add/sub w carry. */
13139 uint32_t mask1
= 0x1FE00000U
;
13140 uint32_t val1
= 0x1A000000U
;
13141 /* 2) cond compare register/immediate. */
13142 uint32_t mask2
= 0x1FE00000U
;
13143 uint32_t val2
= 0x1A400000U
;
13144 /* 3) cond select. */
13145 uint32_t mask3
= 0x1FE00000U
;
13146 uint32_t val3
= 0x1A800000U
;
13147 /* 4) data proc 1/2 source. */
13148 uint32_t mask4
= 0x1FE00000U
;
13149 uint32_t val4
= 0x1AC00000U
;
13151 if ((aarch64_get_instr (cpu
) & mask1
) == val1
)
13152 dexAddSubtractWithCarry (cpu
);
13154 else if ((aarch64_get_instr (cpu
) & mask2
) == val2
)
13157 else if ((aarch64_get_instr (cpu
) & mask3
) == val3
)
13158 dexCondSelect (cpu
);
13160 else if ((aarch64_get_instr (cpu
) & mask4
) == val4
)
13162 /* Bit 30 is clear for data proc 2 source
13163 and set for data proc 1 source. */
13164 if (aarch64_get_instr (cpu
) & (1U << 30))
13165 dexDataProc1Source (cpu
);
13167 dexDataProc2Source (cpu
);
13171 /* Should not reach here. */
13177 case DPREG_3SRC_110
:
13178 dexDataProc3Source (cpu
); return;
13180 case DPREG_UNALLOC_101
:
13183 case DPREG_3SRC_111
:
13184 dexDataProc3Source (cpu
); return;
13187 /* Should never reach here. */
13192 /* Unconditional Branch immediate.
13193 Offset is a PC-relative byte offset in the range +/- 128MiB.
13194 The offset is assumed to be raw from the decode i.e. the
13195 simulator is expected to scale them from word offsets to byte. */
13197 /* Unconditional branch. */
13199 buc (sim_cpu
*cpu
, int32_t offset
)
13201 aarch64_set_next_PC_by_offset (cpu
, offset
);
13204 static unsigned stack_depth
= 0;
13206 /* Unconditional branch and link -- writes return PC to LR. */
13208 bl (sim_cpu
*cpu
, int32_t offset
)
13210 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13211 aarch64_save_LR (cpu
);
13212 aarch64_set_next_PC_by_offset (cpu
, offset
);
13214 if (TRACE_BRANCH_P (cpu
))
13218 " %*scall %" PRIx64
" [%s]"
13219 " [args: %" PRIx64
" %" PRIx64
" %" PRIx64
"]",
13220 stack_depth
, " ", aarch64_get_next_PC (cpu
),
13221 aarch64_get_func (CPU_STATE (cpu
),
13222 aarch64_get_next_PC (cpu
)),
13223 aarch64_get_reg_u64 (cpu
, 0, NO_SP
),
13224 aarch64_get_reg_u64 (cpu
, 1, NO_SP
),
13225 aarch64_get_reg_u64 (cpu
, 2, NO_SP
)
13230 /* Unconditional Branch register.
13231 Branch/return address is in source register. */
13233 /* Unconditional branch. */
13237 unsigned rn
= INSTR (9, 5);
13238 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13239 aarch64_set_next_PC (cpu
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
13242 /* Unconditional branch and link -- writes return PC to LR. */
13246 unsigned rn
= INSTR (9, 5);
13248 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13249 /* The pseudo code in the spec says we update LR before fetching.
13250 the value from the rn. */
13251 aarch64_save_LR (cpu
);
13252 aarch64_set_next_PC (cpu
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
13254 if (TRACE_BRANCH_P (cpu
))
13258 " %*scall %" PRIx64
" [%s]"
13259 " [args: %" PRIx64
" %" PRIx64
" %" PRIx64
"]",
13260 stack_depth
, " ", aarch64_get_next_PC (cpu
),
13261 aarch64_get_func (CPU_STATE (cpu
),
13262 aarch64_get_next_PC (cpu
)),
13263 aarch64_get_reg_u64 (cpu
, 0, NO_SP
),
13264 aarch64_get_reg_u64 (cpu
, 1, NO_SP
),
13265 aarch64_get_reg_u64 (cpu
, 2, NO_SP
)
13270 /* Return -- assembler will default source to LR this is functionally
13271 equivalent to br but, presumably, unlike br it side effects the
13272 branch predictor. */
13276 unsigned rn
= INSTR (9, 5);
13277 aarch64_set_next_PC (cpu
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
13279 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13280 if (TRACE_BRANCH_P (cpu
))
13283 " %*sreturn [result: %" PRIx64
"]",
13284 stack_depth
, " ", aarch64_get_reg_u64 (cpu
, 0, NO_SP
));
13289 /* NOP -- we implement this and call it from the decode in case we
13290 want to intercept it later. */
13295 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13298 /* Data synchronization barrier. */
13303 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13306 /* Data memory barrier. */
13311 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13314 /* Instruction synchronization barrier. */
13319 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13323 dexBranchImmediate (sim_cpu
*cpu
)
13325 /* assert instr[30,26] == 00101
13326 instr[31] ==> 0 == B, 1 == BL
13327 instr[25,0] == imm26 branch offset counted in words. */
13329 uint32_t top
= INSTR (31, 31);
13330 /* We have a 26 byte signed word offset which we need to pass to the
13331 execute routine as a signed byte offset. */
13332 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 25, 0) << 2;
13340 /* Control Flow. */
13342 /* Conditional branch
13344 Offset is a PC-relative byte offset in the range +/- 1MiB pos is
13345 a bit position in the range 0 .. 63
13347 cc is a CondCode enum value as pulled out of the decode
13349 N.B. any offset register (source) can only be Xn or Wn. */
13352 bcc (sim_cpu
*cpu
, int32_t offset
, CondCode cc
)
13354 /* The test returns TRUE if CC is met. */
13355 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13356 if (testConditionCode (cpu
, cc
))
13357 aarch64_set_next_PC_by_offset (cpu
, offset
);
13360 /* 32 bit branch on register non-zero. */
13362 cbnz32 (sim_cpu
*cpu
, int32_t offset
)
13364 unsigned rt
= INSTR (4, 0);
13366 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13367 if (aarch64_get_reg_u32 (cpu
, rt
, NO_SP
) != 0)
13368 aarch64_set_next_PC_by_offset (cpu
, offset
);
13371 /* 64 bit branch on register zero. */
13373 cbnz (sim_cpu
*cpu
, int32_t offset
)
13375 unsigned rt
= INSTR (4, 0);
13377 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13378 if (aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) != 0)
13379 aarch64_set_next_PC_by_offset (cpu
, offset
);
13382 /* 32 bit branch on register non-zero. */
13384 cbz32 (sim_cpu
*cpu
, int32_t offset
)
13386 unsigned rt
= INSTR (4, 0);
13388 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13389 if (aarch64_get_reg_u32 (cpu
, rt
, NO_SP
) == 0)
13390 aarch64_set_next_PC_by_offset (cpu
, offset
);
13393 /* 64 bit branch on register zero. */
13395 cbz (sim_cpu
*cpu
, int32_t offset
)
13397 unsigned rt
= INSTR (4, 0);
13399 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13400 if (aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) == 0)
13401 aarch64_set_next_PC_by_offset (cpu
, offset
);
13404 /* Branch on register bit test non-zero -- one size fits all. */
13406 tbnz (sim_cpu
*cpu
, uint32_t pos
, int32_t offset
)
13408 unsigned rt
= INSTR (4, 0);
13410 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13411 if (aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) & (((uint64_t) 1) << pos
))
13412 aarch64_set_next_PC_by_offset (cpu
, offset
);
13415 /* Branch on register bit test zero -- one size fits all. */
13417 tbz (sim_cpu
*cpu
, uint32_t pos
, int32_t offset
)
13419 unsigned rt
= INSTR (4, 0);
13421 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13422 if (!(aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) & (((uint64_t) 1) << pos
)))
13423 aarch64_set_next_PC_by_offset (cpu
, offset
);
13427 dexCompareBranchImmediate (sim_cpu
*cpu
)
13429 /* instr[30,25] = 01 1010
13430 instr[31] = size : 0 ==> 32, 1 ==> 64
13431 instr[24] = op : 0 ==> CBZ, 1 ==> CBNZ
13432 instr[23,5] = simm19 branch offset counted in words
13435 uint32_t size
= INSTR (31, 31);
13436 uint32_t op
= INSTR (24, 24);
13437 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 23, 5) << 2;
13442 cbz32 (cpu
, offset
);
13444 cbnz32 (cpu
, offset
);
13451 cbnz (cpu
, offset
);
13456 dexTestBranchImmediate (sim_cpu
*cpu
)
13458 /* instr[31] = b5 : bit 5 of test bit idx
13459 instr[30,25] = 01 1011
13460 instr[24] = op : 0 ==> TBZ, 1 == TBNZ
13461 instr[23,19] = b40 : bits 4 to 0 of test bit idx
13462 instr[18,5] = simm14 : signed offset counted in words
13463 instr[4,0] = uimm5 */
13465 uint32_t pos
= ((INSTR (31, 31) << 5) | INSTR (23, 19));
13466 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 18, 5) << 2;
13468 NYI_assert (30, 25, 0x1b);
13470 if (INSTR (24, 24) == 0)
13471 tbz (cpu
, pos
, offset
);
13473 tbnz (cpu
, pos
, offset
);
13477 dexCondBranchImmediate (sim_cpu
*cpu
)
13479 /* instr[31,25] = 010 1010
13480 instr[24] = op1; op => 00 ==> B.cond
13481 instr[23,5] = simm19 : signed offset counted in words
13483 instr[3,0] = cond */
13486 uint32_t op
= ((INSTR (24, 24) << 1) | INSTR (4, 4));
13488 NYI_assert (31, 25, 0x2a);
13493 offset
= simm32 (aarch64_get_instr (cpu
), 23, 5) << 2;
13495 bcc (cpu
, offset
, INSTR (3, 0));
13499 dexBranchRegister (sim_cpu
*cpu
)
13501 /* instr[31,25] = 110 1011
13502 instr[24,21] = op : 0 ==> BR, 1 => BLR, 2 => RET, 3 => ERET, 4 => DRPS
13503 instr[20,16] = op2 : must be 11111
13504 instr[15,10] = op3 : must be 000000
13505 instr[4,0] = op2 : must be 11111. */
13507 uint32_t op
= INSTR (24, 21);
13508 uint32_t op2
= INSTR (20, 16);
13509 uint32_t op3
= INSTR (15, 10);
13510 uint32_t op4
= INSTR (4, 0);
13512 NYI_assert (31, 25, 0x6b);
13514 if (op2
!= 0x1F || op3
!= 0 || op4
!= 0)
13528 /* ERET and DRPS accept 0b11111 for rn = instr [4,0]. */
13529 /* anything else is unallocated. */
13530 uint32_t rn
= INSTR (4, 0);
13535 if (op
== 4 || op
== 5)
13542 /* FIXME: We should get the Angel SWI values from ../../libgloss/aarch64/svc.h
13543 but this may not be available. So instead we define the values we need
13545 #define AngelSVC_Reason_Open 0x01
13546 #define AngelSVC_Reason_Close 0x02
13547 #define AngelSVC_Reason_Write 0x05
13548 #define AngelSVC_Reason_Read 0x06
13549 #define AngelSVC_Reason_IsTTY 0x09
13550 #define AngelSVC_Reason_Seek 0x0A
13551 #define AngelSVC_Reason_FLen 0x0C
13552 #define AngelSVC_Reason_Remove 0x0E
13553 #define AngelSVC_Reason_Rename 0x0F
13554 #define AngelSVC_Reason_Clock 0x10
13555 #define AngelSVC_Reason_Time 0x11
13556 #define AngelSVC_Reason_System 0x12
13557 #define AngelSVC_Reason_Errno 0x13
13558 #define AngelSVC_Reason_GetCmdLine 0x15
13559 #define AngelSVC_Reason_HeapInfo 0x16
13560 #define AngelSVC_Reason_ReportException 0x18
13561 #define AngelSVC_Reason_Elapsed 0x30
13565 handle_halt (sim_cpu
*cpu
, uint32_t val
)
13567 uint64_t result
= 0;
13569 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13572 TRACE_SYSCALL (cpu
, " HLT [0x%x]", val
);
13573 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13574 sim_stopped
, SIM_SIGTRAP
);
13577 /* We have encountered an Angel SVC call. See if we can process it. */
13578 switch (aarch64_get_reg_u32 (cpu
, 0, NO_SP
))
13580 case AngelSVC_Reason_HeapInfo
:
13582 /* Get the values. */
13583 uint64_t stack_top
= aarch64_get_stack_start (cpu
);
13584 uint64_t heap_base
= aarch64_get_heap_start (cpu
);
13586 /* Get the pointer */
13587 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13588 ptr
= aarch64_get_mem_u64 (cpu
, ptr
);
13590 /* Fill in the memory block. */
13591 /* Start addr of heap. */
13592 aarch64_set_mem_u64 (cpu
, ptr
+ 0, heap_base
);
13593 /* End addr of heap. */
13594 aarch64_set_mem_u64 (cpu
, ptr
+ 8, stack_top
);
13595 /* Lowest stack addr. */
13596 aarch64_set_mem_u64 (cpu
, ptr
+ 16, heap_base
);
13597 /* Initial stack addr. */
13598 aarch64_set_mem_u64 (cpu
, ptr
+ 24, stack_top
);
13600 TRACE_SYSCALL (cpu
, " AngelSVC: Get Heap Info");
13604 case AngelSVC_Reason_Open
:
13606 /* Get the pointer */
13607 /* uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);. */
13608 /* FIXME: For now we just assume that we will only be asked
13609 to open the standard file descriptors. */
13613 TRACE_SYSCALL (cpu
, " AngelSVC: Open file %d", fd
- 1);
13617 case AngelSVC_Reason_Close
:
13619 uint64_t fh
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13620 TRACE_SYSCALL (cpu
, " AngelSVC: Close file %d", (int) fh
);
13625 case AngelSVC_Reason_Errno
:
13627 TRACE_SYSCALL (cpu
, " AngelSVC: Get Errno");
13630 case AngelSVC_Reason_Clock
:
13632 #ifdef CLOCKS_PER_SEC
13633 (CLOCKS_PER_SEC
>= 100)
13634 ? (clock () / (CLOCKS_PER_SEC
/ 100))
13635 : ((clock () * 100) / CLOCKS_PER_SEC
)
13637 /* Presume unix... clock() returns microseconds. */
13641 TRACE_SYSCALL (cpu
, " AngelSVC: Get Clock");
13644 case AngelSVC_Reason_GetCmdLine
:
13646 /* Get the pointer */
13647 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13648 ptr
= aarch64_get_mem_u64 (cpu
, ptr
);
13650 /* FIXME: No command line for now. */
13651 aarch64_set_mem_u64 (cpu
, ptr
, 0);
13652 TRACE_SYSCALL (cpu
, " AngelSVC: Get Command Line");
13656 case AngelSVC_Reason_IsTTY
:
13658 TRACE_SYSCALL (cpu
, " AngelSVC: IsTTY ?");
13661 case AngelSVC_Reason_Write
:
13663 /* Get the pointer */
13664 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13665 /* Get the write control block. */
13666 uint64_t fd
= aarch64_get_mem_u64 (cpu
, ptr
);
13667 uint64_t buf
= aarch64_get_mem_u64 (cpu
, ptr
+ 8);
13668 uint64_t len
= aarch64_get_mem_u64 (cpu
, ptr
+ 16);
13670 TRACE_SYSCALL (cpu
, "write of %" PRIx64
" bytes from %"
13671 PRIx64
" on descriptor %" PRIx64
,
13676 TRACE_SYSCALL (cpu
,
13677 " AngelSVC: Write: Suspiciously long write: %ld",
13679 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13680 sim_stopped
, SIM_SIGBUS
);
13684 printf ("%.*s", (int) len
, aarch64_get_mem_ptr (cpu
, buf
));
13688 TRACE (cpu
, 0, "\n");
13689 sim_io_eprintf (CPU_STATE (cpu
), "%.*s",
13690 (int) len
, aarch64_get_mem_ptr (cpu
, buf
));
13691 TRACE (cpu
, 0, "\n");
13695 TRACE_SYSCALL (cpu
,
13696 " AngelSVC: Write: Unexpected file handle: %d",
13698 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13699 sim_stopped
, SIM_SIGABRT
);
13704 case AngelSVC_Reason_ReportException
:
13706 /* Get the pointer */
13707 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13708 /*ptr = aarch64_get_mem_u64 (cpu, ptr);. */
13709 uint64_t type
= aarch64_get_mem_u64 (cpu
, ptr
);
13710 uint64_t state
= aarch64_get_mem_u64 (cpu
, ptr
+ 8);
13712 TRACE_SYSCALL (cpu
,
13713 "Angel Exception: type 0x%" PRIx64
" state %" PRIx64
,
13716 if (type
== 0x20026)
13717 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13718 sim_exited
, state
);
13720 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13721 sim_stopped
, SIM_SIGINT
);
13725 case AngelSVC_Reason_Read
:
13726 case AngelSVC_Reason_FLen
:
13727 case AngelSVC_Reason_Seek
:
13728 case AngelSVC_Reason_Remove
:
13729 case AngelSVC_Reason_Time
:
13730 case AngelSVC_Reason_System
:
13731 case AngelSVC_Reason_Rename
:
13732 case AngelSVC_Reason_Elapsed
:
13734 TRACE_SYSCALL (cpu
, " HLT [Unknown angel %x]",
13735 aarch64_get_reg_u32 (cpu
, 0, NO_SP
));
13736 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13737 sim_stopped
, SIM_SIGTRAP
);
13740 aarch64_set_reg_u64 (cpu
, 0, NO_SP
, result
);
13744 dexExcpnGen (sim_cpu
*cpu
)
13746 /* instr[31:24] = 11010100
13747 instr[23,21] = opc : 000 ==> GEN EXCPN, 001 ==> BRK
13748 010 ==> HLT, 101 ==> DBG GEN EXCPN
13749 instr[20,5] = imm16
13750 instr[4,2] = opc2 000 ==> OK, ow ==> UNALLOC
13751 instr[1,0] = LL : discriminates opc */
13753 uint32_t opc
= INSTR (23, 21);
13754 uint32_t imm16
= INSTR (20, 5);
13755 uint32_t opc2
= INSTR (4, 2);
13758 NYI_assert (31, 24, 0xd4);
13765 /* We only implement HLT and BRK for now. */
13766 if (opc
== 1 && LL
== 0)
13768 TRACE_EVENTS (cpu
, " BRK [0x%x]", imm16
);
13769 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13770 sim_exited
, aarch64_get_reg_s32 (cpu
, R0
, SP_OK
));
13773 if (opc
== 2 && LL
== 0)
13774 handle_halt (cpu
, imm16
);
13776 else if (opc
== 0 || opc
== 5)
13783 /* Stub for accessing system registers. */
13786 system_get (sim_cpu
*cpu
, unsigned op0
, unsigned op1
, unsigned crn
,
13787 unsigned crm
, unsigned op2
)
13789 if (crn
== 0 && op1
== 3 && crm
== 0 && op2
== 7)
13790 /* DCZID_EL0 - the Data Cache Zero ID register.
13791 We do not support DC ZVA at the moment, so
13792 we return a value with the disable bit set.
13793 We implement support for the DCZID register since
13794 it is used by the C library's memset function. */
13795 return ((uint64_t) 1) << 4;
13797 if (crn
== 0 && op1
== 3 && crm
== 0 && op2
== 1)
13798 /* Cache Type Register. */
13799 return 0x80008000UL
;
13801 if (crn
== 13 && op1
== 3 && crm
== 0 && op2
== 2)
13802 /* TPIDR_EL0 - thread pointer id. */
13803 return aarch64_get_thread_id (cpu
);
13805 if (op1
== 3 && crm
== 4 && op2
== 0)
13806 return aarch64_get_FPCR (cpu
);
13808 if (op1
== 3 && crm
== 4 && op2
== 1)
13809 return aarch64_get_FPSR (cpu
);
13811 else if (op1
== 3 && crm
== 2 && op2
== 0)
13812 return aarch64_get_CPSR (cpu
);
13818 system_set (sim_cpu
*cpu
, unsigned op0
, unsigned op1
, unsigned crn
,
13819 unsigned crm
, unsigned op2
, uint64_t val
)
13821 if (op1
== 3 && crm
== 4 && op2
== 0)
13822 aarch64_set_FPCR (cpu
, val
);
13824 else if (op1
== 3 && crm
== 4 && op2
== 1)
13825 aarch64_set_FPSR (cpu
, val
);
13827 else if (op1
== 3 && crm
== 2 && op2
== 0)
13828 aarch64_set_CPSR (cpu
, val
);
13835 do_mrs (sim_cpu
*cpu
)
13837 /* instr[31:20] = 1101 0101 0001 1
13844 unsigned sys_op0
= INSTR (19, 19) + 2;
13845 unsigned sys_op1
= INSTR (18, 16);
13846 unsigned sys_crn
= INSTR (15, 12);
13847 unsigned sys_crm
= INSTR (11, 8);
13848 unsigned sys_op2
= INSTR (7, 5);
13849 unsigned rt
= INSTR (4, 0);
13851 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13852 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
13853 system_get (cpu
, sys_op0
, sys_op1
, sys_crn
, sys_crm
, sys_op2
));
13857 do_MSR_immediate (sim_cpu
*cpu
)
13859 /* instr[31:19] = 1101 0101 0000 0
13861 instr[15,12] = 0100
13864 instr[4,0] = 1 1111 */
13866 unsigned op1
= INSTR (18, 16);
13867 /*unsigned crm = INSTR (11, 8);*/
13868 unsigned op2
= INSTR (7, 5);
13870 NYI_assert (31, 19, 0x1AA0);
13871 NYI_assert (15, 12, 0x4);
13872 NYI_assert (4, 0, 0x1F);
13877 HALT_NYI
; /* set SPSel. */
13884 HALT_NYI
; /* set DAIFset. */
13886 HALT_NYI
; /* set DAIFclr. */
13895 do_MSR_reg (sim_cpu
*cpu
)
13897 /* instr[31:20] = 1101 0101 0001
13905 unsigned sys_op0
= INSTR (19, 19) + 2;
13906 unsigned sys_op1
= INSTR (18, 16);
13907 unsigned sys_crn
= INSTR (15, 12);
13908 unsigned sys_crm
= INSTR (11, 8);
13909 unsigned sys_op2
= INSTR (7, 5);
13910 unsigned rt
= INSTR (4, 0);
13912 NYI_assert (31, 20, 0xD51);
13914 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13915 system_set (cpu
, sys_op0
, sys_op1
, sys_crn
, sys_crm
, sys_op2
,
13916 aarch64_get_reg_u64 (cpu
, rt
, NO_SP
));
13920 do_SYS (sim_cpu
*cpu
)
13922 /* instr[31,19] = 1101 0101 0000 1
13928 NYI_assert (31, 19, 0x1AA1);
13930 /* FIXME: For now we just silently accept system ops. */
13934 dexSystem (sim_cpu
*cpu
)
13936 /* instr[31:22] = 1101 01010 0
13943 instr[4,0] = uimm5 */
13945 /* We are interested in HINT, DSB, DMB and ISB
13947 Hint #0 encodes NOOP (this is the only hint we care about)
13948 L == 0, op0 == 0, op1 = 011, CRn = 0010, Rt = 11111,
13949 CRm op2 != 0000 000 OR CRm op2 == 0000 000 || CRm op > 0000 101
13951 DSB, DMB, ISB are data store barrier, data memory barrier and
13952 instruction store barrier, respectively, where
13954 L == 0, op0 == 0, op1 = 011, CRn = 0011, Rt = 11111,
13955 op2 : DSB ==> 100, DMB ==> 101, ISB ==> 110
13956 CRm<3:2> ==> domain, CRm<1:0> ==> types,
13957 domain : 00 ==> OuterShareable, 01 ==> Nonshareable,
13958 10 ==> InerShareable, 11 ==> FullSystem
13959 types : 01 ==> Reads, 10 ==> Writes,
13960 11 ==> All, 00 ==> All (domain == FullSystem). */
13962 unsigned rt
= INSTR (4, 0);
13964 NYI_assert (31, 22, 0x354);
13966 switch (INSTR (21, 12))
13971 /* NOP has CRm != 0000 OR. */
13972 /* (CRm == 0000 AND (op2 == 000 OR op2 > 101)). */
13973 uint32_t crm
= INSTR (11, 8);
13974 uint32_t op2
= INSTR (7, 5);
13976 if (crm
!= 0 || (op2
== 0 || op2
> 5))
13978 /* Actually call nop method so we can reimplement it later. */
13987 uint32_t op2
= INSTR (7, 5);
13992 case 4: dsb (cpu
); return;
13993 case 5: dmb (cpu
); return;
13994 case 6: isb (cpu
); return;
13995 default: HALT_UNALLOC
;
14006 do_SYS (cpu
); /* DC is an alias of SYS. */
14010 if (INSTR (21, 20) == 0x1)
14012 else if (INSTR (21, 19) == 0 && INSTR (15, 12) == 0x4)
14013 do_MSR_immediate (cpu
);
14021 dexBr (sim_cpu
*cpu
)
14023 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
14024 assert group == GROUP_BREXSYS_1010 || group == GROUP_BREXSYS_1011
14025 bits [31,29] of a BrExSys are the secondary dispatch vector. */
14026 uint32_t group2
= dispatchBrExSys (aarch64_get_instr (cpu
));
14031 return dexBranchImmediate (cpu
);
14033 case BR_IMMCMP_001
:
14034 /* Compare has bit 25 clear while test has it set. */
14035 if (!INSTR (25, 25))
14036 dexCompareBranchImmediate (cpu
);
14038 dexTestBranchImmediate (cpu
);
14041 case BR_IMMCOND_010
:
14042 /* This is a conditional branch if bit 25 is clear otherwise
14044 if (!INSTR (25, 25))
14045 dexCondBranchImmediate (cpu
);
14050 case BR_UNALLOC_011
:
14054 dexBranchImmediate (cpu
);
14057 case BR_IMMCMP_101
:
14058 /* Compare has bit 25 clear while test has it set. */
14059 if (!INSTR (25, 25))
14060 dexCompareBranchImmediate (cpu
);
14062 dexTestBranchImmediate (cpu
);
14066 /* Unconditional branch reg has bit 25 set. */
14067 if (INSTR (25, 25))
14068 dexBranchRegister (cpu
);
14070 /* This includes both Excpn Gen, System and unalloc operations.
14071 We need to decode the Excpn Gen operation BRK so we can plant
14072 debugger entry points.
14073 Excpn Gen operations have instr [24] = 0.
14074 we need to decode at least one of the System operations NOP
14075 which is an alias for HINT #0.
14076 System operations have instr [24,22] = 100. */
14077 else if (INSTR (24, 24) == 0)
14080 else if (INSTR (24, 22) == 4)
14088 case BR_UNALLOC_111
:
14092 /* Should never reach here. */
14098 aarch64_decode_and_execute (sim_cpu
*cpu
, uint64_t pc
)
14100 /* We need to check if gdb wants an in here. */
14101 /* checkBreak (cpu);. */
14103 uint64_t group
= dispatchGroup (aarch64_get_instr (cpu
));
14107 case GROUP_PSEUDO_0000
: dexPseudo (cpu
); break;
14108 case GROUP_LDST_0100
: dexLdSt (cpu
); break;
14109 case GROUP_DPREG_0101
: dexDPReg (cpu
); break;
14110 case GROUP_LDST_0110
: dexLdSt (cpu
); break;
14111 case GROUP_ADVSIMD_0111
: dexAdvSIMD0 (cpu
); break;
14112 case GROUP_DPIMM_1000
: dexDPImm (cpu
); break;
14113 case GROUP_DPIMM_1001
: dexDPImm (cpu
); break;
14114 case GROUP_BREXSYS_1010
: dexBr (cpu
); break;
14115 case GROUP_BREXSYS_1011
: dexBr (cpu
); break;
14116 case GROUP_LDST_1100
: dexLdSt (cpu
); break;
14117 case GROUP_DPREG_1101
: dexDPReg (cpu
); break;
14118 case GROUP_LDST_1110
: dexLdSt (cpu
); break;
14119 case GROUP_ADVSIMD_1111
: dexAdvSIMD1 (cpu
); break;
14121 case GROUP_UNALLOC_0001
:
14122 case GROUP_UNALLOC_0010
:
14123 case GROUP_UNALLOC_0011
:
14127 /* Should never reach here. */
14133 aarch64_step (sim_cpu
*cpu
)
14135 uint64_t pc
= aarch64_get_PC (cpu
);
14137 if (pc
== TOP_LEVEL_RETURN_PC
)
14140 aarch64_set_next_PC (cpu
, pc
+ 4);
14142 /* Code is always little-endian. */
14143 sim_core_read_buffer (CPU_STATE (cpu
), cpu
, read_map
,
14144 & aarch64_get_instr (cpu
), pc
, 4);
14145 aarch64_get_instr (cpu
) = endian_le2h_4 (aarch64_get_instr (cpu
));
14147 TRACE_INSN (cpu
, " pc = %" PRIx64
" instr = %08x", pc
,
14148 aarch64_get_instr (cpu
));
14149 TRACE_DISASM (cpu
, pc
);
14151 aarch64_decode_and_execute (cpu
, pc
);
14157 aarch64_run (SIM_DESC sd
)
14159 sim_cpu
*cpu
= STATE_CPU (sd
, 0);
14161 while (aarch64_step (cpu
))
14163 aarch64_update_PC (cpu
);
14165 if (sim_events_tick (sd
))
14166 sim_events_process (sd
);
14169 sim_engine_halt (sd
, cpu
, NULL
, aarch64_get_PC (cpu
),
14170 sim_exited
, aarch64_get_reg_s32 (cpu
, R0
, NO_SP
));
14174 aarch64_init (sim_cpu
*cpu
, uint64_t pc
)
14176 uint64_t sp
= aarch64_get_stack_start (cpu
);
14178 /* Install SP, FP and PC and set LR to -20
14179 so we can detect a top-level return. */
14180 aarch64_set_reg_u64 (cpu
, SP
, SP_OK
, sp
);
14181 aarch64_set_reg_u64 (cpu
, FP
, SP_OK
, sp
);
14182 aarch64_set_reg_u64 (cpu
, LR
, SP_OK
, TOP_LEVEL_RETURN_PC
);
14183 aarch64_set_next_PC (cpu
, pc
);
14184 aarch64_update_PC (cpu
);
14185 aarch64_init_LIT_table ();