1 /* simulator.c -- Interface for the AArch64 simulator.
3 Copyright (C) 2015-2017 Free Software Foundation, Inc.
5 Contributed by Red Hat.
7 This file is part of GDB.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
26 #include <sys/types.h>
31 #include "simulator.h"
38 #define TST(_flag) (aarch64_test_CPSR_bit (cpu, _flag))
39 #define IS_SET(_X) (TST (( _X )) ? 1 : 0)
40 #define IS_CLEAR(_X) (TST (( _X )) ? 0 : 1)
42 /* Space saver macro. */
43 #define INSTR(HIGH, LOW) uimm (aarch64_get_instr (cpu), (HIGH), (LOW))
45 #define HALT_UNALLOC \
48 TRACE_DISASM (cpu, aarch64_get_PC (cpu)); \
50 "Unallocated instruction detected at sim line %d," \
51 " exe addr %" PRIx64, \
52 __LINE__, aarch64_get_PC (cpu)); \
53 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),\
54 sim_stopped, SIM_SIGILL); \
61 TRACE_DISASM (cpu, aarch64_get_PC (cpu)); \
63 "Unimplemented instruction detected at sim line %d," \
64 " exe addr %" PRIx64, \
65 __LINE__, aarch64_get_PC (cpu)); \
66 if (! TRACE_ANY_P (cpu)) \
67 sim_io_eprintf (CPU_STATE (cpu), "SIM Error: Unimplemented instruction: %#08x\n", \
68 aarch64_get_instr (cpu)); \
69 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),\
70 sim_stopped, SIM_SIGABRT); \
74 #define NYI_assert(HI, LO, EXPECTED) \
77 if (INSTR ((HI), (LO)) != (EXPECTED)) \
82 /* Helper functions used by expandLogicalImmediate. */
84 /* for i = 1, ... N result<i-1> = 1 other bits are zero */
85 static inline uint64_t
88 return (N
== 64 ? (uint64_t)-1UL : ((1UL << N
) - 1));
91 /* result<0> to val<N> */
92 static inline uint64_t
93 pickbit (uint64_t val
, int N
)
95 return pickbits64 (val
, N
, N
);
99 expand_logical_immediate (uint32_t S
, uint32_t R
, uint32_t N
)
105 /* The immediate value is S+1 bits to 1, left rotated by SIMDsize - R
106 (in other words, right rotated by R), then replicated. */
110 mask
= 0xffffffffffffffffull
;
116 case 0x00 ... 0x1f: /* 0xxxxx */ simd_size
= 32; break;
117 case 0x20 ... 0x2f: /* 10xxxx */ simd_size
= 16; S
&= 0xf; break;
118 case 0x30 ... 0x37: /* 110xxx */ simd_size
= 8; S
&= 0x7; break;
119 case 0x38 ... 0x3b: /* 1110xx */ simd_size
= 4; S
&= 0x3; break;
120 case 0x3c ... 0x3d: /* 11110x */ simd_size
= 2; S
&= 0x1; break;
123 mask
= (1ull << simd_size
) - 1;
124 /* Top bits are IGNORED. */
128 /* NOTE: if S = simd_size - 1 we get 0xf..f which is rejected. */
129 if (S
== simd_size
- 1)
132 /* S+1 consecutive bits to 1. */
133 /* NOTE: S can't be 63 due to detection above. */
134 imm
= (1ull << (S
+ 1)) - 1;
136 /* Rotate to the left by simd_size - R. */
138 imm
= ((imm
<< (simd_size
- R
)) & mask
) | (imm
>> R
);
140 /* Replicate the value according to SIMD size. */
143 case 2: imm
= (imm
<< 2) | imm
;
144 case 4: imm
= (imm
<< 4) | imm
;
145 case 8: imm
= (imm
<< 8) | imm
;
146 case 16: imm
= (imm
<< 16) | imm
;
147 case 32: imm
= (imm
<< 32) | imm
;
155 /* Instr[22,10] encodes N immr and imms. we want a lookup table
156 for each possible combination i.e. 13 bits worth of int entries. */
157 #define LI_TABLE_SIZE (1 << 13)
158 static uint64_t LITable
[LI_TABLE_SIZE
];
161 aarch64_init_LIT_table (void)
165 for (index
= 0; index
< LI_TABLE_SIZE
; index
++)
167 uint32_t N
= uimm (index
, 12, 12);
168 uint32_t immr
= uimm (index
, 11, 6);
169 uint32_t imms
= uimm (index
, 5, 0);
171 LITable
[index
] = expand_logical_immediate (imms
, immr
, N
);
176 dexNotify (sim_cpu
*cpu
)
178 /* instr[14,0] == type : 0 ==> method entry, 1 ==> method reentry
179 2 ==> exit Java, 3 ==> start next bytecode. */
180 uint32_t type
= INSTR (14, 0);
182 TRACE_EVENTS (cpu
, "Notify Insn encountered, type = 0x%x", type
);
187 /* aarch64_notifyMethodEntry (aarch64_get_reg_u64 (cpu, R23, 0),
188 aarch64_get_reg_u64 (cpu, R22, 0)); */
191 /* aarch64_notifyMethodReentry (aarch64_get_reg_u64 (cpu, R23, 0),
192 aarch64_get_reg_u64 (cpu, R22, 0)); */
195 /* aarch64_notifyMethodExit (); */
198 /* aarch64_notifyBCStart (aarch64_get_reg_u64 (cpu, R23, 0),
199 aarch64_get_reg_u64 (cpu, R22, 0)); */
204 /* secondary decode within top level groups */
207 dexPseudo (sim_cpu
*cpu
)
209 /* assert instr[28,27] = 00
211 We provide 2 pseudo instructions:
213 HALT stops execution of the simulator causing an immediate
214 return to the x86 code which entered it.
216 CALLOUT initiates recursive entry into x86 code. A register
217 argument holds the address of the x86 routine. Immediate
218 values in the instruction identify the number of general
219 purpose and floating point register arguments to be passed
220 and the type of any value to be returned. */
222 uint32_t PSEUDO_HALT
= 0xE0000000U
;
223 uint32_t PSEUDO_CALLOUT
= 0x00018000U
;
224 uint32_t PSEUDO_CALLOUTR
= 0x00018001U
;
225 uint32_t PSEUDO_NOTIFY
= 0x00014000U
;
228 if (aarch64_get_instr (cpu
) == PSEUDO_HALT
)
230 TRACE_EVENTS (cpu
, " Pseudo Halt Instruction");
231 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
232 sim_stopped
, SIM_SIGTRAP
);
235 dispatch
= INSTR (31, 15);
237 /* We do not handle callouts at the moment. */
238 if (dispatch
== PSEUDO_CALLOUT
|| dispatch
== PSEUDO_CALLOUTR
)
240 TRACE_EVENTS (cpu
, " Callout");
241 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
242 sim_stopped
, SIM_SIGABRT
);
245 else if (dispatch
== PSEUDO_NOTIFY
)
252 /* Load-store single register (unscaled offset)
253 These instructions employ a base register plus an unscaled signed
256 N.B. the base register (source) can be Xn or SP. all other
257 registers may not be SP. */
259 /* 32 bit load 32 bit unscaled signed 9 bit. */
261 ldur32 (sim_cpu
*cpu
, int32_t offset
)
263 unsigned rn
= INSTR (9, 5);
264 unsigned rt
= INSTR (4, 0);
266 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
267 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u32
268 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
272 /* 64 bit load 64 bit unscaled signed 9 bit. */
274 ldur64 (sim_cpu
*cpu
, int32_t offset
)
276 unsigned rn
= INSTR (9, 5);
277 unsigned rt
= INSTR (4, 0);
279 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
280 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u64
281 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
285 /* 32 bit load zero-extended byte unscaled signed 9 bit. */
287 ldurb32 (sim_cpu
*cpu
, int32_t offset
)
289 unsigned rn
= INSTR (9, 5);
290 unsigned rt
= INSTR (4, 0);
292 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
293 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u8
294 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
298 /* 32 bit load sign-extended byte unscaled signed 9 bit. */
300 ldursb32 (sim_cpu
*cpu
, int32_t offset
)
302 unsigned rn
= INSTR (9, 5);
303 unsigned rt
= INSTR (4, 0);
305 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
306 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, (uint32_t) aarch64_get_mem_s8
307 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
311 /* 64 bit load sign-extended byte unscaled signed 9 bit. */
313 ldursb64 (sim_cpu
*cpu
, int32_t offset
)
315 unsigned rn
= INSTR (9, 5);
316 unsigned rt
= INSTR (4, 0);
318 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
319 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, aarch64_get_mem_s8
320 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
324 /* 32 bit load zero-extended short unscaled signed 9 bit */
326 ldurh32 (sim_cpu
*cpu
, int32_t offset
)
328 unsigned rn
= INSTR (9, 5);
329 unsigned rd
= INSTR (4, 0);
331 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
332 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, aarch64_get_mem_u16
333 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
337 /* 32 bit load sign-extended short unscaled signed 9 bit */
339 ldursh32 (sim_cpu
*cpu
, int32_t offset
)
341 unsigned rn
= INSTR (9, 5);
342 unsigned rd
= INSTR (4, 0);
344 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
345 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) aarch64_get_mem_s16
346 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
350 /* 64 bit load sign-extended short unscaled signed 9 bit */
352 ldursh64 (sim_cpu
*cpu
, int32_t offset
)
354 unsigned rn
= INSTR (9, 5);
355 unsigned rt
= INSTR (4, 0);
357 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
358 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, aarch64_get_mem_s16
359 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
363 /* 64 bit load sign-extended word unscaled signed 9 bit */
365 ldursw (sim_cpu
*cpu
, int32_t offset
)
367 unsigned rn
= INSTR (9, 5);
368 unsigned rd
= INSTR (4, 0);
370 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
371 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) aarch64_get_mem_s32
372 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
376 /* N.B. with stores the value in source is written to the address
377 identified by source2 modified by offset. */
379 /* 32 bit store 32 bit unscaled signed 9 bit. */
381 stur32 (sim_cpu
*cpu
, int32_t offset
)
383 unsigned rn
= INSTR (9, 5);
384 unsigned rd
= INSTR (4, 0);
386 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
387 aarch64_set_mem_u32 (cpu
,
388 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
389 aarch64_get_reg_u32 (cpu
, rd
, NO_SP
));
392 /* 64 bit store 64 bit unscaled signed 9 bit */
394 stur64 (sim_cpu
*cpu
, int32_t offset
)
396 unsigned rn
= INSTR (9, 5);
397 unsigned rd
= INSTR (4, 0);
399 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
400 aarch64_set_mem_u64 (cpu
,
401 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
402 aarch64_get_reg_u64 (cpu
, rd
, NO_SP
));
405 /* 32 bit store byte unscaled signed 9 bit */
407 sturb (sim_cpu
*cpu
, int32_t offset
)
409 unsigned rn
= INSTR (9, 5);
410 unsigned rd
= INSTR (4, 0);
412 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
413 aarch64_set_mem_u8 (cpu
,
414 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
415 aarch64_get_reg_u8 (cpu
, rd
, NO_SP
));
418 /* 32 bit store short unscaled signed 9 bit */
420 sturh (sim_cpu
*cpu
, int32_t offset
)
422 unsigned rn
= INSTR (9, 5);
423 unsigned rd
= INSTR (4, 0);
425 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
426 aarch64_set_mem_u16 (cpu
,
427 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
428 aarch64_get_reg_u16 (cpu
, rd
, NO_SP
));
431 /* Load single register pc-relative label
432 Offset is a signed 19 bit immediate count in words
435 /* 32 bit pc-relative load */
437 ldr32_pcrel (sim_cpu
*cpu
, int32_t offset
)
439 unsigned rd
= INSTR (4, 0);
441 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
442 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
444 (cpu
, aarch64_get_PC (cpu
) + offset
* 4));
447 /* 64 bit pc-relative load */
449 ldr_pcrel (sim_cpu
*cpu
, int32_t offset
)
451 unsigned rd
= INSTR (4, 0);
453 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
454 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
456 (cpu
, aarch64_get_PC (cpu
) + offset
* 4));
459 /* sign extended 32 bit pc-relative load */
461 ldrsw_pcrel (sim_cpu
*cpu
, int32_t offset
)
463 unsigned rd
= INSTR (4, 0);
465 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
466 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
468 (cpu
, aarch64_get_PC (cpu
) + offset
* 4));
471 /* float pc-relative load */
473 fldrs_pcrel (sim_cpu
*cpu
, int32_t offset
)
475 unsigned int rd
= INSTR (4, 0);
477 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
478 aarch64_set_vec_u32 (cpu
, rd
, 0,
480 (cpu
, aarch64_get_PC (cpu
) + offset
* 4));
483 /* double pc-relative load */
485 fldrd_pcrel (sim_cpu
*cpu
, int32_t offset
)
487 unsigned int st
= INSTR (4, 0);
489 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
490 aarch64_set_vec_u64 (cpu
, st
, 0,
492 (cpu
, aarch64_get_PC (cpu
) + offset
* 4));
495 /* long double pc-relative load. */
497 fldrq_pcrel (sim_cpu
*cpu
, int32_t offset
)
499 unsigned int st
= INSTR (4, 0);
500 uint64_t addr
= aarch64_get_PC (cpu
) + offset
* 4;
503 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
504 aarch64_get_mem_long_double (cpu
, addr
, & a
);
505 aarch64_set_FP_long_double (cpu
, st
, a
);
508 /* This can be used to scale an offset by applying
509 the requisite shift. the second argument is either
512 #define SCALE(_offset, _elementSize) \
513 ((_offset) << ScaleShift ## _elementSize)
515 /* This can be used to optionally scale a register derived offset
516 by applying the requisite shift as indicated by the Scaling
517 argument. The second argument is either Byte, Short, Word
518 or Long. The third argument is either Scaled or Unscaled.
519 N.B. when _Scaling is Scaled the shift gets ANDed with
520 all 1s while when it is Unscaled it gets ANDed with 0. */
522 #define OPT_SCALE(_offset, _elementType, _Scaling) \
523 ((_offset) << (_Scaling ? ScaleShift ## _elementType : 0))
525 /* This can be used to zero or sign extend a 32 bit register derived
526 value to a 64 bit value. the first argument must be the value as
527 a uint32_t and the second must be either UXTW or SXTW. The result
528 is returned as an int64_t. */
530 static inline int64_t
531 extend (uint32_t value
, Extension extension
)
539 /* A branchless variant of this ought to be possible. */
540 if (extension
== UXTW
|| extension
== NoExtension
)
547 /* Scalar Floating Point
549 FP load/store single register (4 addressing modes)
551 N.B. the base register (source) can be the stack pointer.
552 The secondary source register (source2) can only be an Xn register. */
554 /* Load 32 bit unscaled signed 9 bit with pre- or post-writeback. */
556 fldrs_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
558 unsigned rn
= INSTR (9, 5);
559 unsigned st
= INSTR (4, 0);
560 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
565 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
566 aarch64_set_vec_u32 (cpu
, st
, 0, aarch64_get_mem_u32 (cpu
, address
));
570 if (wb
!= NoWriteBack
)
571 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
574 /* Load 8 bit with unsigned 12 bit offset. */
576 fldrb_abs (sim_cpu
*cpu
, uint32_t offset
)
578 unsigned rd
= INSTR (4, 0);
579 unsigned rn
= INSTR (9, 5);
580 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
;
582 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
583 aarch64_set_vec_u8 (cpu
, rd
, 0, aarch64_get_mem_u32 (cpu
, addr
));
586 /* Load 16 bit scaled unsigned 12 bit. */
588 fldrh_abs (sim_cpu
*cpu
, uint32_t offset
)
590 unsigned rd
= INSTR (4, 0);
591 unsigned rn
= INSTR (9, 5);
592 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 16);
594 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
595 aarch64_set_vec_u16 (cpu
, rd
, 0, aarch64_get_mem_u16 (cpu
, addr
));
598 /* Load 32 bit scaled unsigned 12 bit. */
600 fldrs_abs (sim_cpu
*cpu
, uint32_t offset
)
602 unsigned rd
= INSTR (4, 0);
603 unsigned rn
= INSTR (9, 5);
604 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 32);
606 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
607 aarch64_set_vec_u32 (cpu
, rd
, 0, aarch64_get_mem_u32 (cpu
, addr
));
610 /* Load 64 bit scaled unsigned 12 bit. */
612 fldrd_abs (sim_cpu
*cpu
, uint32_t offset
)
614 unsigned rd
= INSTR (4, 0);
615 unsigned rn
= INSTR (9, 5);
616 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 64);
618 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
619 aarch64_set_vec_u64 (cpu
, rd
, 0, aarch64_get_mem_u64 (cpu
, addr
));
622 /* Load 128 bit scaled unsigned 12 bit. */
624 fldrq_abs (sim_cpu
*cpu
, uint32_t offset
)
626 unsigned rd
= INSTR (4, 0);
627 unsigned rn
= INSTR (9, 5);
628 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 128);
630 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
631 aarch64_set_vec_u64 (cpu
, rd
, 0, aarch64_get_mem_u64 (cpu
, addr
));
632 aarch64_set_vec_u64 (cpu
, rd
, 1, aarch64_get_mem_u64 (cpu
, addr
+ 8));
635 /* Load 32 bit scaled or unscaled zero- or sign-extended
636 32-bit register offset. */
638 fldrs_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
640 unsigned rm
= INSTR (20, 16);
641 unsigned rn
= INSTR (9, 5);
642 unsigned st
= INSTR (4, 0);
643 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
644 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
645 uint64_t displacement
= OPT_SCALE (extended
, 32, scaling
);
647 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
648 aarch64_set_vec_u32 (cpu
, st
, 0, aarch64_get_mem_u32
649 (cpu
, address
+ displacement
));
652 /* Load 64 bit unscaled signed 9 bit with pre- or post-writeback. */
654 fldrd_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
656 unsigned rn
= INSTR (9, 5);
657 unsigned st
= INSTR (4, 0);
658 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
663 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
664 aarch64_set_vec_u64 (cpu
, st
, 0, aarch64_get_mem_u64 (cpu
, address
));
669 if (wb
!= NoWriteBack
)
670 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
673 /* Load 64 bit scaled or unscaled zero- or sign-extended 32-bit register offset. */
675 fldrd_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
677 unsigned rm
= INSTR (20, 16);
678 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
679 uint64_t displacement
= OPT_SCALE (extended
, 64, scaling
);
681 fldrd_wb (cpu
, displacement
, NoWriteBack
);
684 /* Load 128 bit unscaled signed 9 bit with pre- or post-writeback. */
686 fldrq_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
689 unsigned rn
= INSTR (9, 5);
690 unsigned st
= INSTR (4, 0);
691 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
696 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
697 aarch64_get_mem_long_double (cpu
, address
, & a
);
698 aarch64_set_FP_long_double (cpu
, st
, a
);
703 if (wb
!= NoWriteBack
)
704 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
707 /* Load 128 bit scaled or unscaled zero- or sign-extended 32-bit register offset */
709 fldrq_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
711 unsigned rm
= INSTR (20, 16);
712 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
713 uint64_t displacement
= OPT_SCALE (extended
, 128, scaling
);
715 fldrq_wb (cpu
, displacement
, NoWriteBack
);
720 load-store single register
721 There are four addressing modes available here which all employ a
722 64 bit source (base) register.
724 N.B. the base register (source) can be the stack pointer.
725 The secondary source register (source2)can only be an Xn register.
727 Scaled, 12-bit, unsigned immediate offset, without pre- and
729 Unscaled, 9-bit, signed immediate offset with pre- or post-index
731 scaled or unscaled 64-bit register offset.
732 scaled or unscaled 32-bit extended register offset.
734 All offsets are assumed to be raw from the decode i.e. the
735 simulator is expected to adjust scaled offsets based on the
736 accessed data size with register or extended register offset
737 versions the same applies except that in the latter case the
738 operation may also require a sign extend.
740 A separate method is provided for each possible addressing mode. */
742 /* 32 bit load 32 bit scaled unsigned 12 bit */
744 ldr32_abs (sim_cpu
*cpu
, uint32_t offset
)
746 unsigned rn
= INSTR (9, 5);
747 unsigned rt
= INSTR (4, 0);
749 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
750 /* The target register may not be SP but the source may be. */
751 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u32
752 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
753 + SCALE (offset
, 32)));
756 /* 32 bit load 32 bit unscaled signed 9 bit with pre- or post-writeback. */
758 ldr32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
760 unsigned rn
= INSTR (9, 5);
761 unsigned rt
= INSTR (4, 0);
764 if (rn
== rt
&& wb
!= NoWriteBack
)
767 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
772 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
773 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u32 (cpu
, address
));
778 if (wb
!= NoWriteBack
)
779 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
782 /* 32 bit load 32 bit scaled or unscaled
783 zero- or sign-extended 32-bit register offset */
785 ldr32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
787 unsigned rm
= INSTR (20, 16);
788 unsigned rn
= INSTR (9, 5);
789 unsigned rt
= INSTR (4, 0);
790 /* rn may reference SP, rm and rt must reference ZR */
792 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
793 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
794 uint64_t displacement
= OPT_SCALE (extended
, 32, scaling
);
796 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
797 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
798 aarch64_get_mem_u32 (cpu
, address
+ displacement
));
801 /* 64 bit load 64 bit scaled unsigned 12 bit */
803 ldr_abs (sim_cpu
*cpu
, uint32_t offset
)
805 unsigned rn
= INSTR (9, 5);
806 unsigned rt
= INSTR (4, 0);
808 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
809 /* The target register may not be SP but the source may be. */
810 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u64
811 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
812 + SCALE (offset
, 64)));
815 /* 64 bit load 64 bit unscaled signed 9 bit with pre- or post-writeback. */
817 ldr_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
819 unsigned rn
= INSTR (9, 5);
820 unsigned rt
= INSTR (4, 0);
823 if (rn
== rt
&& wb
!= NoWriteBack
)
826 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
831 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
832 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u64 (cpu
, address
));
837 if (wb
!= NoWriteBack
)
838 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
841 /* 64 bit load 64 bit scaled or unscaled zero-
842 or sign-extended 32-bit register offset. */
844 ldr_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
846 unsigned rm
= INSTR (20, 16);
847 unsigned rn
= INSTR (9, 5);
848 unsigned rt
= INSTR (4, 0);
849 /* rn may reference SP, rm and rt must reference ZR */
851 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
852 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
853 uint64_t displacement
= OPT_SCALE (extended
, 64, scaling
);
855 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
856 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
857 aarch64_get_mem_u64 (cpu
, address
+ displacement
));
860 /* 32 bit load zero-extended byte scaled unsigned 12 bit. */
862 ldrb32_abs (sim_cpu
*cpu
, uint32_t offset
)
864 unsigned rn
= INSTR (9, 5);
865 unsigned rt
= INSTR (4, 0);
867 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
868 /* The target register may not be SP but the source may be
869 there is no scaling required for a byte load. */
870 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
872 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
));
875 /* 32 bit load zero-extended byte unscaled signed 9 bit with pre- or post-writeback. */
877 ldrb32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
879 unsigned rn
= INSTR (9, 5);
880 unsigned rt
= INSTR (4, 0);
883 if (rn
== rt
&& wb
!= NoWriteBack
)
886 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
891 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
892 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u8 (cpu
, address
));
897 if (wb
!= NoWriteBack
)
898 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
901 /* 32 bit load zero-extended byte scaled or unscaled zero-
902 or sign-extended 32-bit register offset. */
904 ldrb32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
906 unsigned rm
= INSTR (20, 16);
907 unsigned rn
= INSTR (9, 5);
908 unsigned rt
= INSTR (4, 0);
909 /* rn may reference SP, rm and rt must reference ZR */
911 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
912 int64_t displacement
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
915 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
916 /* There is no scaling required for a byte load. */
917 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
918 aarch64_get_mem_u8 (cpu
, address
+ displacement
));
921 /* 64 bit load sign-extended byte unscaled signed 9 bit
922 with pre- or post-writeback. */
924 ldrsb_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
926 unsigned rn
= INSTR (9, 5);
927 unsigned rt
= INSTR (4, 0);
931 if (rn
== rt
&& wb
!= NoWriteBack
)
934 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
939 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
940 val
= aarch64_get_mem_s8 (cpu
, address
);
941 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, val
);
946 if (wb
!= NoWriteBack
)
947 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
950 /* 64 bit load sign-extended byte scaled unsigned 12 bit. */
952 ldrsb_abs (sim_cpu
*cpu
, uint32_t offset
)
954 ldrsb_wb (cpu
, offset
, NoWriteBack
);
957 /* 64 bit load sign-extended byte scaled or unscaled zero-
958 or sign-extended 32-bit register offset. */
960 ldrsb_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
962 unsigned rm
= INSTR (20, 16);
963 unsigned rn
= INSTR (9, 5);
964 unsigned rt
= INSTR (4, 0);
965 /* rn may reference SP, rm and rt must reference ZR */
967 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
968 int64_t displacement
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
970 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
971 /* There is no scaling required for a byte load. */
972 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
,
973 aarch64_get_mem_s8 (cpu
, address
+ displacement
));
976 /* 32 bit load zero-extended short scaled unsigned 12 bit. */
978 ldrh32_abs (sim_cpu
*cpu
, uint32_t offset
)
980 unsigned rn
= INSTR (9, 5);
981 unsigned rt
= INSTR (4, 0);
984 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
985 /* The target register may not be SP but the source may be. */
986 val
= aarch64_get_mem_u16 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
987 + SCALE (offset
, 16));
988 aarch64_set_reg_u32 (cpu
, rt
, NO_SP
, val
);
991 /* 32 bit load zero-extended short unscaled signed 9 bit
992 with pre- or post-writeback. */
994 ldrh32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
996 unsigned rn
= INSTR (9, 5);
997 unsigned rt
= INSTR (4, 0);
1000 if (rn
== rt
&& wb
!= NoWriteBack
)
1003 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1008 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1009 aarch64_set_reg_u32 (cpu
, rt
, NO_SP
, aarch64_get_mem_u16 (cpu
, address
));
1014 if (wb
!= NoWriteBack
)
1015 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1018 /* 32 bit load zero-extended short scaled or unscaled zero-
1019 or sign-extended 32-bit register offset. */
1021 ldrh32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1023 unsigned rm
= INSTR (20, 16);
1024 unsigned rn
= INSTR (9, 5);
1025 unsigned rt
= INSTR (4, 0);
1026 /* rn may reference SP, rm and rt must reference ZR */
1028 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1029 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
1030 uint64_t displacement
= OPT_SCALE (extended
, 16, scaling
);
1032 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1033 aarch64_set_reg_u32 (cpu
, rt
, NO_SP
,
1034 aarch64_get_mem_u16 (cpu
, address
+ displacement
));
1037 /* 32 bit load sign-extended short scaled unsigned 12 bit. */
1039 ldrsh32_abs (sim_cpu
*cpu
, uint32_t offset
)
1041 unsigned rn
= INSTR (9, 5);
1042 unsigned rt
= INSTR (4, 0);
1045 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1046 /* The target register may not be SP but the source may be. */
1047 val
= aarch64_get_mem_s16 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
1048 + SCALE (offset
, 16));
1049 aarch64_set_reg_s32 (cpu
, rt
, NO_SP
, val
);
1052 /* 32 bit load sign-extended short unscaled signed 9 bit
1053 with pre- or post-writeback. */
1055 ldrsh32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1057 unsigned rn
= INSTR (9, 5);
1058 unsigned rt
= INSTR (4, 0);
1061 if (rn
== rt
&& wb
!= NoWriteBack
)
1064 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1069 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1070 aarch64_set_reg_s32 (cpu
, rt
, NO_SP
,
1071 (int32_t) aarch64_get_mem_s16 (cpu
, address
));
1076 if (wb
!= NoWriteBack
)
1077 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1080 /* 32 bit load sign-extended short scaled or unscaled zero-
1081 or sign-extended 32-bit register offset. */
1083 ldrsh32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1085 unsigned rm
= INSTR (20, 16);
1086 unsigned rn
= INSTR (9, 5);
1087 unsigned rt
= INSTR (4, 0);
1088 /* rn may reference SP, rm and rt must reference ZR */
1090 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1091 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
1092 uint64_t displacement
= OPT_SCALE (extended
, 16, scaling
);
1094 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1095 aarch64_set_reg_s32 (cpu
, rt
, NO_SP
,
1096 (int32_t) aarch64_get_mem_s16
1097 (cpu
, address
+ displacement
));
1100 /* 64 bit load sign-extended short scaled unsigned 12 bit. */
1102 ldrsh_abs (sim_cpu
*cpu
, uint32_t offset
)
1104 unsigned rn
= INSTR (9, 5);
1105 unsigned rt
= INSTR (4, 0);
1108 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1109 /* The target register may not be SP but the source may be. */
1110 val
= aarch64_get_mem_s16 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
1111 + SCALE (offset
, 16));
1112 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, val
);
1115 /* 64 bit load sign-extended short unscaled signed 9 bit
1116 with pre- or post-writeback. */
1118 ldrsh64_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1120 unsigned rn
= INSTR (9, 5);
1121 unsigned rt
= INSTR (4, 0);
1125 if (rn
== rt
&& wb
!= NoWriteBack
)
1128 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1129 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1134 val
= aarch64_get_mem_s16 (cpu
, address
);
1135 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, val
);
1140 if (wb
!= NoWriteBack
)
1141 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1144 /* 64 bit load sign-extended short scaled or unscaled zero-
1145 or sign-extended 32-bit register offset. */
1147 ldrsh_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1149 unsigned rm
= INSTR (20, 16);
1150 unsigned rn
= INSTR (9, 5);
1151 unsigned rt
= INSTR (4, 0);
1153 /* rn may reference SP, rm and rt must reference ZR */
1155 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1156 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
1157 uint64_t displacement
= OPT_SCALE (extended
, 16, scaling
);
1160 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1161 val
= aarch64_get_mem_s16 (cpu
, address
+ displacement
);
1162 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, val
);
1165 /* 64 bit load sign-extended 32 bit scaled unsigned 12 bit. */
1167 ldrsw_abs (sim_cpu
*cpu
, uint32_t offset
)
1169 unsigned rn
= INSTR (9, 5);
1170 unsigned rt
= INSTR (4, 0);
1173 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1174 val
= aarch64_get_mem_s32 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
1175 + SCALE (offset
, 32));
1176 /* The target register may not be SP but the source may be. */
1177 return aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, val
);
1180 /* 64 bit load sign-extended 32 bit unscaled signed 9 bit
1181 with pre- or post-writeback. */
1183 ldrsw_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1185 unsigned rn
= INSTR (9, 5);
1186 unsigned rt
= INSTR (4, 0);
1189 if (rn
== rt
&& wb
!= NoWriteBack
)
1192 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1197 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1198 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, aarch64_get_mem_s32 (cpu
, address
));
1203 if (wb
!= NoWriteBack
)
1204 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1207 /* 64 bit load sign-extended 32 bit scaled or unscaled zero-
1208 or sign-extended 32-bit register offset. */
1210 ldrsw_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1212 unsigned rm
= INSTR (20, 16);
1213 unsigned rn
= INSTR (9, 5);
1214 unsigned rt
= INSTR (4, 0);
1215 /* rn may reference SP, rm and rt must reference ZR */
1217 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1218 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
1219 uint64_t displacement
= OPT_SCALE (extended
, 32, scaling
);
1221 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1222 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
,
1223 aarch64_get_mem_s32 (cpu
, address
+ displacement
));
1226 /* N.B. with stores the value in source is written to the
1227 address identified by source2 modified by source3/offset. */
1229 /* 32 bit store scaled unsigned 12 bit. */
1231 str32_abs (sim_cpu
*cpu
, uint32_t offset
)
1233 unsigned rn
= INSTR (9, 5);
1234 unsigned rt
= INSTR (4, 0);
1236 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1237 /* The target register may not be SP but the source may be. */
1238 aarch64_set_mem_u32 (cpu
, (aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
1239 + SCALE (offset
, 32)),
1240 aarch64_get_reg_u32 (cpu
, rt
, NO_SP
));
1243 /* 32 bit store unscaled signed 9 bit with pre- or post-writeback. */
1245 str32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1247 unsigned rn
= INSTR (9, 5);
1248 unsigned rt
= INSTR (4, 0);
1251 if (rn
== rt
&& wb
!= NoWriteBack
)
1254 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1258 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1259 aarch64_set_mem_u32 (cpu
, address
, aarch64_get_reg_u32 (cpu
, rt
, NO_SP
));
1264 if (wb
!= NoWriteBack
)
1265 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1268 /* 32 bit store scaled or unscaled zero- or
1269 sign-extended 32-bit register offset. */
1271 str32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1273 unsigned rm
= INSTR (20, 16);
1274 unsigned rn
= INSTR (9, 5);
1275 unsigned rt
= INSTR (4, 0);
1277 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1278 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
1279 uint64_t displacement
= OPT_SCALE (extended
, 32, scaling
);
1281 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1282 aarch64_set_mem_u32 (cpu
, address
+ displacement
,
1283 aarch64_get_reg_u64 (cpu
, rt
, NO_SP
));
1286 /* 64 bit store scaled unsigned 12 bit. */
1288 str_abs (sim_cpu
*cpu
, uint32_t offset
)
1290 unsigned rn
= INSTR (9, 5);
1291 unsigned rt
= INSTR (4, 0);
1293 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1294 aarch64_set_mem_u64 (cpu
,
1295 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
1296 + SCALE (offset
, 64),
1297 aarch64_get_reg_u64 (cpu
, rt
, NO_SP
));
1300 /* 64 bit store unscaled signed 9 bit with pre- or post-writeback. */
1302 str_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1304 unsigned rn
= INSTR (9, 5);
1305 unsigned rt
= INSTR (4, 0);
1308 if (rn
== rt
&& wb
!= NoWriteBack
)
1311 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1316 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1317 aarch64_set_mem_u64 (cpu
, address
, aarch64_get_reg_u64 (cpu
, rt
, NO_SP
));
1322 if (wb
!= NoWriteBack
)
1323 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1326 /* 64 bit store scaled or unscaled zero-
1327 or sign-extended 32-bit register offset. */
1329 str_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1331 unsigned rm
= INSTR (20, 16);
1332 unsigned rn
= INSTR (9, 5);
1333 unsigned rt
= INSTR (4, 0);
1334 /* rn may reference SP, rm and rt must reference ZR */
1336 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1337 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
1339 uint64_t displacement
= OPT_SCALE (extended
, 64, scaling
);
1341 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1342 aarch64_set_mem_u64 (cpu
, address
+ displacement
,
1343 aarch64_get_reg_u64 (cpu
, rt
, NO_SP
));
1346 /* 32 bit store byte scaled unsigned 12 bit. */
1348 strb_abs (sim_cpu
*cpu
, uint32_t offset
)
1350 unsigned rn
= INSTR (9, 5);
1351 unsigned rt
= INSTR (4, 0);
1353 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1354 /* The target register may not be SP but the source may be.
1355 There is no scaling required for a byte load. */
1356 aarch64_set_mem_u8 (cpu
,
1357 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
1358 aarch64_get_reg_u8 (cpu
, rt
, NO_SP
));
1361 /* 32 bit store byte unscaled signed 9 bit with pre- or post-writeback. */
1363 strb_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1365 unsigned rn
= INSTR (9, 5);
1366 unsigned rt
= INSTR (4, 0);
1369 if (rn
== rt
&& wb
!= NoWriteBack
)
1372 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1377 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1378 aarch64_set_mem_u8 (cpu
, address
, aarch64_get_reg_u8 (cpu
, rt
, NO_SP
));
1383 if (wb
!= NoWriteBack
)
1384 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1387 /* 32 bit store byte scaled or unscaled zero-
1388 or sign-extended 32-bit register offset. */
1390 strb_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1392 unsigned rm
= INSTR (20, 16);
1393 unsigned rn
= INSTR (9, 5);
1394 unsigned rt
= INSTR (4, 0);
1395 /* rn may reference SP, rm and rt must reference ZR */
1397 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1398 int64_t displacement
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
1401 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1402 /* There is no scaling required for a byte load. */
1403 aarch64_set_mem_u8 (cpu
, address
+ displacement
,
1404 aarch64_get_reg_u8 (cpu
, rt
, NO_SP
));
1407 /* 32 bit store short scaled unsigned 12 bit. */
1409 strh_abs (sim_cpu
*cpu
, uint32_t offset
)
1411 unsigned rn
= INSTR (9, 5);
1412 unsigned rt
= INSTR (4, 0);
1414 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1415 /* The target register may not be SP but the source may be. */
1416 aarch64_set_mem_u16 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
1417 + SCALE (offset
, 16),
1418 aarch64_get_reg_u16 (cpu
, rt
, NO_SP
));
1421 /* 32 bit store short unscaled signed 9 bit with pre- or post-writeback. */
1423 strh_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1425 unsigned rn
= INSTR (9, 5);
1426 unsigned rt
= INSTR (4, 0);
1429 if (rn
== rt
&& wb
!= NoWriteBack
)
1432 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1437 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1438 aarch64_set_mem_u16 (cpu
, address
, aarch64_get_reg_u16 (cpu
, rt
, NO_SP
));
1443 if (wb
!= NoWriteBack
)
1444 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1447 /* 32 bit store short scaled or unscaled zero-
1448 or sign-extended 32-bit register offset. */
1450 strh_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1452 unsigned rm
= INSTR (20, 16);
1453 unsigned rn
= INSTR (9, 5);
1454 unsigned rt
= INSTR (4, 0);
1455 /* rn may reference SP, rm and rt must reference ZR */
1457 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1458 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
1459 uint64_t displacement
= OPT_SCALE (extended
, 16, scaling
);
1461 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1462 aarch64_set_mem_u16 (cpu
, address
+ displacement
,
1463 aarch64_get_reg_u16 (cpu
, rt
, NO_SP
));
1466 /* Prefetch unsigned 12 bit. */
1468 prfm_abs (sim_cpu
*cpu
, uint32_t offset
)
1470 /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1471 00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1472 00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1473 10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1474 10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1475 10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1477 PrfOp prfop = prfop (instr, 4, 0);
1478 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK)
1479 + SCALE (offset, 64). */
1481 /* TODO : implement prefetch of address. */
1484 /* Prefetch scaled or unscaled zero- or sign-extended 32-bit register offset. */
1486 prfm_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1488 /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1489 00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1490 00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1491 10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1492 10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1493 10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1495 rn may reference SP, rm may only reference ZR
1496 PrfOp prfop = prfop (instr, 4, 0);
1497 uint64_t base = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1498 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1500 uint64_t displacement = OPT_SCALE (extended, 64, scaling);
1501 uint64_t address = base + displacement. */
1503 /* TODO : implement prefetch of address */
1506 /* 64 bit pc-relative prefetch. */
1508 prfm_pcrel (sim_cpu
*cpu
, int32_t offset
)
1510 /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1511 00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1512 00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1513 10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1514 10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1515 10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1517 PrfOp prfop = prfop (instr, 4, 0);
1518 uint64_t address = aarch64_get_PC (cpu) + offset. */
1520 /* TODO : implement this */
1523 /* Load-store exclusive. */
1528 unsigned rn
= INSTR (9, 5);
1529 unsigned rt
= INSTR (4, 0);
1530 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1531 int size
= INSTR (31, 30);
1532 /* int ordered = INSTR (15, 15); */
1533 /* int exclusive = ! INSTR (23, 23); */
1535 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1539 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u8 (cpu
, address
));
1542 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u16 (cpu
, address
));
1545 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u32 (cpu
, address
));
1548 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u64 (cpu
, address
));
1556 unsigned rn
= INSTR (9, 5);
1557 unsigned rt
= INSTR (4, 0);
1558 unsigned rs
= INSTR (20, 16);
1559 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1560 int size
= INSTR (31, 30);
1561 uint64_t data
= aarch64_get_reg_u64 (cpu
, rt
, NO_SP
);
1565 case 0: aarch64_set_mem_u8 (cpu
, address
, data
); break;
1566 case 1: aarch64_set_mem_u16 (cpu
, address
, data
); break;
1567 case 2: aarch64_set_mem_u32 (cpu
, address
, data
); break;
1568 case 3: aarch64_set_mem_u64 (cpu
, address
, data
); break;
1571 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1572 aarch64_set_reg_u64 (cpu
, rs
, NO_SP
, 0); /* Always exclusive... */
1576 dexLoadLiteral (sim_cpu
*cpu
)
1578 /* instr[29,27] == 011
1580 instr[31,30:26] = opc: 000 ==> LDRW, 001 ==> FLDRS
1581 010 ==> LDRX, 011 ==> FLDRD
1582 100 ==> LDRSW, 101 ==> FLDRQ
1583 110 ==> PRFM, 111 ==> UNALLOC
1584 instr[26] ==> V : 0 ==> GReg, 1 ==> FReg
1585 instr[23, 5] == simm19 */
1587 /* unsigned rt = INSTR (4, 0); */
1588 uint32_t dispatch
= (INSTR (31, 30) << 1) | INSTR (26, 26);
1589 int32_t imm
= simm32 (aarch64_get_instr (cpu
), 23, 5);
1593 case 0: ldr32_pcrel (cpu
, imm
); break;
1594 case 1: fldrs_pcrel (cpu
, imm
); break;
1595 case 2: ldr_pcrel (cpu
, imm
); break;
1596 case 3: fldrd_pcrel (cpu
, imm
); break;
1597 case 4: ldrsw_pcrel (cpu
, imm
); break;
1598 case 5: fldrq_pcrel (cpu
, imm
); break;
1599 case 6: prfm_pcrel (cpu
, imm
); break;
1606 /* Immediate arithmetic
1607 The aimm argument is a 12 bit unsigned value or a 12 bit unsigned
1608 value left shifted by 12 bits (done at decode).
1610 N.B. the register args (dest, source) can normally be Xn or SP.
1611 the exception occurs for flag setting instructions which may
1612 only use Xn for the output (dest). */
1614 /* 32 bit add immediate. */
1616 add32 (sim_cpu
*cpu
, uint32_t aimm
)
1618 unsigned rn
= INSTR (9, 5);
1619 unsigned rd
= INSTR (4, 0);
1621 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1622 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
1623 aarch64_get_reg_u32 (cpu
, rn
, SP_OK
) + aimm
);
1626 /* 64 bit add immediate. */
1628 add64 (sim_cpu
*cpu
, uint32_t aimm
)
1630 unsigned rn
= INSTR (9, 5);
1631 unsigned rd
= INSTR (4, 0);
1633 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1634 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
1635 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + aimm
);
1639 set_flags_for_add32 (sim_cpu
*cpu
, int32_t value1
, int32_t value2
)
1641 int32_t result
= value1
+ value2
;
1642 int64_t sresult
= (int64_t) value1
+ (int64_t) value2
;
1643 uint64_t uresult
= (uint64_t)(uint32_t) value1
1644 + (uint64_t)(uint32_t) value2
;
1650 if (result
& (1 << 31))
1653 if (uresult
!= result
)
1656 if (sresult
!= result
)
1659 aarch64_set_CPSR (cpu
, flags
);
1662 #define NEG(a) (((a) & signbit) == signbit)
1663 #define POS(a) (((a) & signbit) == 0)
1666 set_flags_for_add64 (sim_cpu
*cpu
, uint64_t value1
, uint64_t value2
)
1668 uint64_t result
= value1
+ value2
;
1670 uint64_t signbit
= 1ULL << 63;
1678 if ( (NEG (value1
) && NEG (value2
))
1679 || (NEG (value1
) && POS (result
))
1680 || (NEG (value2
) && POS (result
)))
1683 if ( (NEG (value1
) && NEG (value2
) && POS (result
))
1684 || (POS (value1
) && POS (value2
) && NEG (result
)))
1687 aarch64_set_CPSR (cpu
, flags
);
1691 set_flags_for_sub32 (sim_cpu
*cpu
, uint32_t value1
, uint32_t value2
)
1693 uint32_t result
= value1
- value2
;
1695 uint32_t signbit
= 1U << 31;
1703 if ( (NEG (value1
) && POS (value2
))
1704 || (NEG (value1
) && POS (result
))
1705 || (POS (value2
) && POS (result
)))
1708 if ( (NEG (value1
) && POS (value2
) && POS (result
))
1709 || (POS (value1
) && NEG (value2
) && NEG (result
)))
1712 aarch64_set_CPSR (cpu
, flags
);
1716 set_flags_for_sub64 (sim_cpu
*cpu
, uint64_t value1
, uint64_t value2
)
1718 uint64_t result
= value1
- value2
;
1720 uint64_t signbit
= 1ULL << 63;
1728 if ( (NEG (value1
) && POS (value2
))
1729 || (NEG (value1
) && POS (result
))
1730 || (POS (value2
) && POS (result
)))
1733 if ( (NEG (value1
) && POS (value2
) && POS (result
))
1734 || (POS (value1
) && NEG (value2
) && NEG (result
)))
1737 aarch64_set_CPSR (cpu
, flags
);
1741 set_flags_for_binop32 (sim_cpu
*cpu
, uint32_t result
)
1750 if (result
& (1 << 31))
1755 aarch64_set_CPSR (cpu
, flags
);
1759 set_flags_for_binop64 (sim_cpu
*cpu
, uint64_t result
)
1768 if (result
& (1ULL << 63))
1773 aarch64_set_CPSR (cpu
, flags
);
1776 /* 32 bit add immediate set flags. */
1778 adds32 (sim_cpu
*cpu
, uint32_t aimm
)
1780 unsigned rn
= INSTR (9, 5);
1781 unsigned rd
= INSTR (4, 0);
1782 /* TODO : do we need to worry about signs here? */
1783 int32_t value1
= aarch64_get_reg_s32 (cpu
, rn
, SP_OK
);
1785 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1786 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ aimm
);
1787 set_flags_for_add32 (cpu
, value1
, aimm
);
1790 /* 64 bit add immediate set flags. */
1792 adds64 (sim_cpu
*cpu
, uint32_t aimm
)
1794 unsigned rn
= INSTR (9, 5);
1795 unsigned rd
= INSTR (4, 0);
1796 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1797 uint64_t value2
= aimm
;
1799 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1800 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
);
1801 set_flags_for_add64 (cpu
, value1
, value2
);
1804 /* 32 bit sub immediate. */
1806 sub32 (sim_cpu
*cpu
, uint32_t aimm
)
1808 unsigned rn
= INSTR (9, 5);
1809 unsigned rd
= INSTR (4, 0);
1811 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1812 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
1813 aarch64_get_reg_u32 (cpu
, rn
, SP_OK
) - aimm
);
1816 /* 64 bit sub immediate. */
1818 sub64 (sim_cpu
*cpu
, uint32_t aimm
)
1820 unsigned rn
= INSTR (9, 5);
1821 unsigned rd
= INSTR (4, 0);
1823 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1824 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
1825 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) - aimm
);
1828 /* 32 bit sub immediate set flags. */
1830 subs32 (sim_cpu
*cpu
, uint32_t aimm
)
1832 unsigned rn
= INSTR (9, 5);
1833 unsigned rd
= INSTR (4, 0);
1834 uint32_t value1
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1835 uint32_t value2
= aimm
;
1837 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1838 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
1839 set_flags_for_sub32 (cpu
, value1
, value2
);
1842 /* 64 bit sub immediate set flags. */
1844 subs64 (sim_cpu
*cpu
, uint32_t aimm
)
1846 unsigned rn
= INSTR (9, 5);
1847 unsigned rd
= INSTR (4, 0);
1848 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1849 uint32_t value2
= aimm
;
1851 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1852 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
1853 set_flags_for_sub64 (cpu
, value1
, value2
);
1856 /* Data Processing Register. */
1858 /* First two helpers to perform the shift operations. */
1860 static inline uint32_t
1861 shifted32 (uint32_t value
, Shift shift
, uint32_t count
)
1867 return (value
<< count
);
1869 return (value
>> count
);
1872 int32_t svalue
= value
;
1873 return (svalue
>> count
);
1877 uint32_t top
= value
>> count
;
1878 uint32_t bottom
= value
<< (32 - count
);
1879 return (bottom
| top
);
1884 static inline uint64_t
1885 shifted64 (uint64_t value
, Shift shift
, uint32_t count
)
1891 return (value
<< count
);
1893 return (value
>> count
);
1896 int64_t svalue
= value
;
1897 return (svalue
>> count
);
1901 uint64_t top
= value
>> count
;
1902 uint64_t bottom
= value
<< (64 - count
);
1903 return (bottom
| top
);
1908 /* Arithmetic shifted register.
1909 These allow an optional LSL, ASR or LSR to the second source
1910 register with a count up to the register bit count.
1912 N.B register args may not be SP. */
1914 /* 32 bit ADD shifted register. */
1916 add32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1918 unsigned rm
= INSTR (20, 16);
1919 unsigned rn
= INSTR (9, 5);
1920 unsigned rd
= INSTR (4, 0);
1922 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1923 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
1924 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
1925 + shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
1929 /* 64 bit ADD shifted register. */
1931 add64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1933 unsigned rm
= INSTR (20, 16);
1934 unsigned rn
= INSTR (9, 5);
1935 unsigned rd
= INSTR (4, 0);
1937 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1938 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
1939 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
1940 + shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
1944 /* 32 bit ADD shifted register setting flags. */
1946 adds32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1948 unsigned rm
= INSTR (20, 16);
1949 unsigned rn
= INSTR (9, 5);
1950 unsigned rd
= INSTR (4, 0);
1952 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
1953 uint32_t value2
= shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
1956 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1957 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
);
1958 set_flags_for_add32 (cpu
, value1
, value2
);
1961 /* 64 bit ADD shifted register setting flags. */
1963 adds64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1965 unsigned rm
= INSTR (20, 16);
1966 unsigned rn
= INSTR (9, 5);
1967 unsigned rd
= INSTR (4, 0);
1969 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
1970 uint64_t value2
= shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
1973 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1974 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
);
1975 set_flags_for_add64 (cpu
, value1
, value2
);
1978 /* 32 bit SUB shifted register. */
1980 sub32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1982 unsigned rm
= INSTR (20, 16);
1983 unsigned rn
= INSTR (9, 5);
1984 unsigned rd
= INSTR (4, 0);
1986 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1987 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
1988 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
1989 - shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
1993 /* 64 bit SUB shifted register. */
1995 sub64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1997 unsigned rm
= INSTR (20, 16);
1998 unsigned rn
= INSTR (9, 5);
1999 unsigned rd
= INSTR (4, 0);
2001 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2002 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
2003 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
2004 - shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
2008 /* 32 bit SUB shifted register setting flags. */
2010 subs32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
2012 unsigned rm
= INSTR (20, 16);
2013 unsigned rn
= INSTR (9, 5);
2014 unsigned rd
= INSTR (4, 0);
2016 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
2017 uint32_t value2
= shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
2020 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2021 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
2022 set_flags_for_sub32 (cpu
, value1
, value2
);
2025 /* 64 bit SUB shifted register setting flags. */
2027 subs64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
2029 unsigned rm
= INSTR (20, 16);
2030 unsigned rn
= INSTR (9, 5);
2031 unsigned rd
= INSTR (4, 0);
2033 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
2034 uint64_t value2
= shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
2037 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2038 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
2039 set_flags_for_sub64 (cpu
, value1
, value2
);
2042 /* First a couple more helpers to fetch the
2043 relevant source register element either
2044 sign or zero extended as required by the
2048 extreg32 (sim_cpu
*cpu
, unsigned int lo
, Extension extension
)
2052 case UXTB
: return aarch64_get_reg_u8 (cpu
, lo
, NO_SP
);
2053 case UXTH
: return aarch64_get_reg_u16 (cpu
, lo
, NO_SP
);
2054 case UXTW
: /* Fall through. */
2055 case UXTX
: return aarch64_get_reg_u32 (cpu
, lo
, NO_SP
);
2056 case SXTB
: return aarch64_get_reg_s8 (cpu
, lo
, NO_SP
);
2057 case SXTH
: return aarch64_get_reg_s16 (cpu
, lo
, NO_SP
);
2058 case SXTW
: /* Fall through. */
2059 case SXTX
: /* Fall through. */
2060 default: return aarch64_get_reg_s32 (cpu
, lo
, NO_SP
);
2065 extreg64 (sim_cpu
*cpu
, unsigned int lo
, Extension extension
)
2069 case UXTB
: return aarch64_get_reg_u8 (cpu
, lo
, NO_SP
);
2070 case UXTH
: return aarch64_get_reg_u16 (cpu
, lo
, NO_SP
);
2071 case UXTW
: return aarch64_get_reg_u32 (cpu
, lo
, NO_SP
);
2072 case UXTX
: return aarch64_get_reg_u64 (cpu
, lo
, NO_SP
);
2073 case SXTB
: return aarch64_get_reg_s8 (cpu
, lo
, NO_SP
);
2074 case SXTH
: return aarch64_get_reg_s16 (cpu
, lo
, NO_SP
);
2075 case SXTW
: return aarch64_get_reg_s32 (cpu
, lo
, NO_SP
);
2077 default: return aarch64_get_reg_s64 (cpu
, lo
, NO_SP
);
2081 /* Arithmetic extending register
2082 These allow an optional sign extension of some portion of the
2083 second source register followed by an optional left shift of
2084 between 1 and 4 bits (i.e. a shift of 0-4 bits???)
2086 N.B output (dest) and first input arg (source) may normally be Xn
2087 or SP. However, for flag setting operations dest can only be
2088 Xn. Second input registers are always Xn. */
2090 /* 32 bit ADD extending register. */
2092 add32_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2094 unsigned rm
= INSTR (20, 16);
2095 unsigned rn
= INSTR (9, 5);
2096 unsigned rd
= INSTR (4, 0);
2098 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2099 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
2100 aarch64_get_reg_u32 (cpu
, rn
, SP_OK
)
2101 + (extreg32 (cpu
, rm
, extension
) << shift
));
2104 /* 64 bit ADD extending register.
2105 N.B. This subsumes the case with 64 bit source2 and UXTX #n or LSL #0. */
2107 add64_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2109 unsigned rm
= INSTR (20, 16);
2110 unsigned rn
= INSTR (9, 5);
2111 unsigned rd
= INSTR (4, 0);
2113 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2114 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
2115 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
2116 + (extreg64 (cpu
, rm
, extension
) << shift
));
2119 /* 32 bit ADD extending register setting flags. */
2121 adds32_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2123 unsigned rm
= INSTR (20, 16);
2124 unsigned rn
= INSTR (9, 5);
2125 unsigned rd
= INSTR (4, 0);
2127 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, SP_OK
);
2128 uint32_t value2
= extreg32 (cpu
, rm
, extension
) << shift
;
2130 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2131 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
);
2132 set_flags_for_add32 (cpu
, value1
, value2
);
2135 /* 64 bit ADD extending register setting flags */
2136 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0 */
2138 adds64_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2140 unsigned rm
= INSTR (20, 16);
2141 unsigned rn
= INSTR (9, 5);
2142 unsigned rd
= INSTR (4, 0);
2144 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
2145 uint64_t value2
= extreg64 (cpu
, rm
, extension
) << shift
;
2147 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2148 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
);
2149 set_flags_for_add64 (cpu
, value1
, value2
);
2152 /* 32 bit SUB extending register. */
2154 sub32_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2156 unsigned rm
= INSTR (20, 16);
2157 unsigned rn
= INSTR (9, 5);
2158 unsigned rd
= INSTR (4, 0);
2160 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2161 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
2162 aarch64_get_reg_u32 (cpu
, rn
, SP_OK
)
2163 - (extreg32 (cpu
, rm
, extension
) << shift
));
2166 /* 64 bit SUB extending register. */
2167 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0. */
2169 sub64_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2171 unsigned rm
= INSTR (20, 16);
2172 unsigned rn
= INSTR (9, 5);
2173 unsigned rd
= INSTR (4, 0);
2175 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2176 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
2177 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
2178 - (extreg64 (cpu
, rm
, extension
) << shift
));
2181 /* 32 bit SUB extending register setting flags. */
2183 subs32_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2185 unsigned rm
= INSTR (20, 16);
2186 unsigned rn
= INSTR (9, 5);
2187 unsigned rd
= INSTR (4, 0);
2189 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, SP_OK
);
2190 uint32_t value2
= extreg32 (cpu
, rm
, extension
) << shift
;
2192 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2193 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
2194 set_flags_for_sub32 (cpu
, value1
, value2
);
2197 /* 64 bit SUB extending register setting flags */
2198 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0 */
2200 subs64_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2202 unsigned rm
= INSTR (20, 16);
2203 unsigned rn
= INSTR (9, 5);
2204 unsigned rd
= INSTR (4, 0);
2206 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
2207 uint64_t value2
= extreg64 (cpu
, rm
, extension
) << shift
;
2209 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2210 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
2211 set_flags_for_sub64 (cpu
, value1
, value2
);
2215 dexAddSubtractImmediate (sim_cpu
*cpu
)
2217 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2218 instr[30] = op : 0 ==> ADD, 1 ==> SUB
2219 instr[29] = set : 0 ==> no flags, 1 ==> set flags
2220 instr[28,24] = 10001
2221 instr[23,22] = shift : 00 == LSL#0, 01 = LSL#12 1x = UNALLOC
2222 instr[21,10] = uimm12
2226 /* N.B. the shift is applied at decode before calling the add/sub routine. */
2227 uint32_t shift
= INSTR (23, 22);
2228 uint32_t imm
= INSTR (21, 10);
2229 uint32_t dispatch
= INSTR (31, 29);
2231 NYI_assert (28, 24, 0x11);
2241 case 0: add32 (cpu
, imm
); break;
2242 case 1: adds32 (cpu
, imm
); break;
2243 case 2: sub32 (cpu
, imm
); break;
2244 case 3: subs32 (cpu
, imm
); break;
2245 case 4: add64 (cpu
, imm
); break;
2246 case 5: adds64 (cpu
, imm
); break;
2247 case 6: sub64 (cpu
, imm
); break;
2248 case 7: subs64 (cpu
, imm
); break;
2253 dexAddSubtractShiftedRegister (sim_cpu
*cpu
)
2255 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2256 instr[30,29] = op : 00 ==> ADD, 01 ==> ADDS, 10 ==> SUB, 11 ==> SUBS
2257 instr[28,24] = 01011
2258 instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> UNALLOC
2261 instr[15,10] = count : must be 0xxxxx for 32 bit
2265 uint32_t size
= INSTR (31, 31);
2266 uint32_t count
= INSTR (15, 10);
2267 Shift shiftType
= INSTR (23, 22);
2269 NYI_assert (28, 24, 0x0B);
2270 NYI_assert (21, 21, 0);
2272 /* Shift encoded as ROR is unallocated. */
2273 if (shiftType
== ROR
)
2276 /* 32 bit operations must have count[5] = 0
2277 or else we have an UNALLOC. */
2278 if (size
== 0 && uimm (count
, 5, 5))
2281 /* Dispatch on size:op i.e instr [31,29]. */
2282 switch (INSTR (31, 29))
2284 case 0: add32_shift (cpu
, shiftType
, count
); break;
2285 case 1: adds32_shift (cpu
, shiftType
, count
); break;
2286 case 2: sub32_shift (cpu
, shiftType
, count
); break;
2287 case 3: subs32_shift (cpu
, shiftType
, count
); break;
2288 case 4: add64_shift (cpu
, shiftType
, count
); break;
2289 case 5: adds64_shift (cpu
, shiftType
, count
); break;
2290 case 6: sub64_shift (cpu
, shiftType
, count
); break;
2291 case 7: subs64_shift (cpu
, shiftType
, count
); break;
2296 dexAddSubtractExtendedRegister (sim_cpu
*cpu
)
2298 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2299 instr[30] = op : 0 ==> ADD, 1 ==> SUB
2300 instr[29] = set? : 0 ==> no flags, 1 ==> set flags
2301 instr[28,24] = 01011
2302 instr[23,22] = opt : 0 ==> ok, 1,2,3 ==> UNALLOC
2305 instr[15,13] = option : 000 ==> UXTB, 001 ==> UXTH,
2306 000 ==> LSL|UXTW, 001 ==> UXTZ,
2307 000 ==> SXTB, 001 ==> SXTH,
2308 000 ==> SXTW, 001 ==> SXTX,
2309 instr[12,10] = shift : 0,1,2,3,4 ==> ok, 5,6,7 ==> UNALLOC
2313 Extension extensionType
= INSTR (15, 13);
2314 uint32_t shift
= INSTR (12, 10);
2316 NYI_assert (28, 24, 0x0B);
2317 NYI_assert (21, 21, 1);
2319 /* Shift may not exceed 4. */
2323 /* Dispatch on size:op:set?. */
2324 switch (INSTR (31, 29))
2326 case 0: add32_ext (cpu
, extensionType
, shift
); break;
2327 case 1: adds32_ext (cpu
, extensionType
, shift
); break;
2328 case 2: sub32_ext (cpu
, extensionType
, shift
); break;
2329 case 3: subs32_ext (cpu
, extensionType
, shift
); break;
2330 case 4: add64_ext (cpu
, extensionType
, shift
); break;
2331 case 5: adds64_ext (cpu
, extensionType
, shift
); break;
2332 case 6: sub64_ext (cpu
, extensionType
, shift
); break;
2333 case 7: subs64_ext (cpu
, extensionType
, shift
); break;
2337 /* Conditional data processing
2338 Condition register is implicit 3rd source. */
2340 /* 32 bit add with carry. */
2341 /* N.B register args may not be SP. */
2344 adc32 (sim_cpu
*cpu
)
2346 unsigned rm
= INSTR (20, 16);
2347 unsigned rn
= INSTR (9, 5);
2348 unsigned rd
= INSTR (4, 0);
2350 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2351 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
2352 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
2353 + aarch64_get_reg_u32 (cpu
, rm
, NO_SP
)
2357 /* 64 bit add with carry */
2359 adc64 (sim_cpu
*cpu
)
2361 unsigned rm
= INSTR (20, 16);
2362 unsigned rn
= INSTR (9, 5);
2363 unsigned rd
= INSTR (4, 0);
2365 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2366 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
2367 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
2368 + aarch64_get_reg_u64 (cpu
, rm
, NO_SP
)
2372 /* 32 bit add with carry setting flags. */
2374 adcs32 (sim_cpu
*cpu
)
2376 unsigned rm
= INSTR (20, 16);
2377 unsigned rn
= INSTR (9, 5);
2378 unsigned rd
= INSTR (4, 0);
2380 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
2381 uint32_t value2
= aarch64_get_reg_u32 (cpu
, rm
, NO_SP
);
2382 uint32_t carry
= IS_SET (C
);
2384 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2385 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
+ carry
);
2386 set_flags_for_add32 (cpu
, value1
, value2
+ carry
);
2389 /* 64 bit add with carry setting flags. */
2391 adcs64 (sim_cpu
*cpu
)
2393 unsigned rm
= INSTR (20, 16);
2394 unsigned rn
= INSTR (9, 5);
2395 unsigned rd
= INSTR (4, 0);
2397 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
2398 uint64_t value2
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
2399 uint64_t carry
= IS_SET (C
);
2401 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2402 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
+ carry
);
2403 set_flags_for_add64 (cpu
, value1
, value2
+ carry
);
2406 /* 32 bit sub with carry. */
2408 sbc32 (sim_cpu
*cpu
)
2410 unsigned rm
= INSTR (20, 16);
2411 unsigned rn
= INSTR (9, 5); /* ngc iff rn == 31. */
2412 unsigned rd
= INSTR (4, 0);
2414 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2415 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
2416 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
2417 - aarch64_get_reg_u32 (cpu
, rm
, NO_SP
)
2421 /* 64 bit sub with carry */
2423 sbc64 (sim_cpu
*cpu
)
2425 unsigned rm
= INSTR (20, 16);
2426 unsigned rn
= INSTR (9, 5);
2427 unsigned rd
= INSTR (4, 0);
2429 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2430 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
2431 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
2432 - aarch64_get_reg_u64 (cpu
, rm
, NO_SP
)
2436 /* 32 bit sub with carry setting flags */
2438 sbcs32 (sim_cpu
*cpu
)
2440 unsigned rm
= INSTR (20, 16);
2441 unsigned rn
= INSTR (9, 5);
2442 unsigned rd
= INSTR (4, 0);
2444 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
2445 uint32_t value2
= aarch64_get_reg_u32 (cpu
, rm
, NO_SP
);
2446 uint32_t carry
= IS_SET (C
);
2447 uint32_t result
= value1
- value2
+ 1 - carry
;
2449 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2450 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
2451 set_flags_for_sub32 (cpu
, value1
, value2
+ 1 - carry
);
2454 /* 64 bit sub with carry setting flags */
2456 sbcs64 (sim_cpu
*cpu
)
2458 unsigned rm
= INSTR (20, 16);
2459 unsigned rn
= INSTR (9, 5);
2460 unsigned rd
= INSTR (4, 0);
2462 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
2463 uint64_t value2
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
2464 uint64_t carry
= IS_SET (C
);
2465 uint64_t result
= value1
- value2
+ 1 - carry
;
2467 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2468 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
2469 set_flags_for_sub64 (cpu
, value1
, value2
+ 1 - carry
);
2473 dexAddSubtractWithCarry (sim_cpu
*cpu
)
2475 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2476 instr[30] = op : 0 ==> ADC, 1 ==> SBC
2477 instr[29] = set? : 0 ==> no flags, 1 ==> set flags
2478 instr[28,21] = 1 1010 000
2480 instr[15,10] = op2 : 00000 ==> ok, ow ==> UNALLOC
2484 uint32_t op2
= INSTR (15, 10);
2486 NYI_assert (28, 21, 0xD0);
2491 /* Dispatch on size:op:set?. */
2492 switch (INSTR (31, 29))
2494 case 0: adc32 (cpu
); break;
2495 case 1: adcs32 (cpu
); break;
2496 case 2: sbc32 (cpu
); break;
2497 case 3: sbcs32 (cpu
); break;
2498 case 4: adc64 (cpu
); break;
2499 case 5: adcs64 (cpu
); break;
2500 case 6: sbc64 (cpu
); break;
2501 case 7: sbcs64 (cpu
); break;
2506 testConditionCode (sim_cpu
*cpu
, CondCode cc
)
2508 /* This should be reduceable to branchless logic
2509 by some careful testing of bits in CC followed
2510 by the requisite masking and combining of bits
2511 from the flag register.
2513 For now we do it with a switch. */
2518 case EQ
: res
= IS_SET (Z
); break;
2519 case NE
: res
= IS_CLEAR (Z
); break;
2520 case CS
: res
= IS_SET (C
); break;
2521 case CC
: res
= IS_CLEAR (C
); break;
2522 case MI
: res
= IS_SET (N
); break;
2523 case PL
: res
= IS_CLEAR (N
); break;
2524 case VS
: res
= IS_SET (V
); break;
2525 case VC
: res
= IS_CLEAR (V
); break;
2526 case HI
: res
= IS_SET (C
) && IS_CLEAR (Z
); break;
2527 case LS
: res
= IS_CLEAR (C
) || IS_SET (Z
); break;
2528 case GE
: res
= IS_SET (N
) == IS_SET (V
); break;
2529 case LT
: res
= IS_SET (N
) != IS_SET (V
); break;
2530 case GT
: res
= IS_CLEAR (Z
) && (IS_SET (N
) == IS_SET (V
)); break;
2531 case LE
: res
= IS_SET (Z
) || (IS_SET (N
) != IS_SET (V
)); break;
2542 CondCompare (sim_cpu
*cpu
) /* aka: ccmp and ccmn */
2544 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2545 instr[30] = compare with positive (1) or negative value (0)
2546 instr[29,21] = 1 1101 0010
2547 instr[20,16] = Rm or const
2549 instr[11] = compare reg (0) or const (1)
2553 instr[3,0] = value for CPSR bits if the comparison does not take place. */
2558 NYI_assert (29, 21, 0x1d2);
2559 NYI_assert (10, 10, 0);
2560 NYI_assert (4, 4, 0);
2562 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2563 if (! testConditionCode (cpu
, INSTR (15, 12)))
2565 aarch64_set_CPSR (cpu
, INSTR (3, 0));
2569 negate
= INSTR (30, 30) ? 1 : -1;
2570 rm
= INSTR (20, 16);
2576 set_flags_for_sub64 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
),
2577 negate
* (uint64_t) rm
);
2579 set_flags_for_sub64 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
),
2580 negate
* aarch64_get_reg_u64 (cpu
, rm
, SP_OK
));
2585 set_flags_for_sub32 (cpu
, aarch64_get_reg_u32 (cpu
, rn
, SP_OK
),
2588 set_flags_for_sub32 (cpu
, aarch64_get_reg_u32 (cpu
, rn
, SP_OK
),
2589 negate
* aarch64_get_reg_u32 (cpu
, rm
, SP_OK
));
2594 do_vec_MOV_whole_vector (sim_cpu
*cpu
)
2596 /* MOV Vd.T, Vs.T (alias for ORR Vd.T, Vn.T, Vm.T where Vn == Vm)
2599 instr[30] = half(0)/full(1)
2600 instr[29,21] = 001110101
2602 instr[15,10] = 000111
2606 unsigned vs
= INSTR (9, 5);
2607 unsigned vd
= INSTR (4, 0);
2609 NYI_assert (29, 21, 0x075);
2610 NYI_assert (15, 10, 0x07);
2612 if (INSTR (20, 16) != vs
)
2615 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2617 aarch64_set_vec_u64 (cpu
, vd
, 1, aarch64_get_vec_u64 (cpu
, vs
, 1));
2619 aarch64_set_vec_u64 (cpu
, vd
, 0, aarch64_get_vec_u64 (cpu
, vs
, 0));
2623 do_vec_MOV_into_scalar (sim_cpu
*cpu
)
2626 instr[30] = word(0)/long(1)
2627 instr[29,21] = 00 1110 000
2628 instr[20,18] = element size and index
2629 instr[17,10] = 00 0011 11
2630 instr[9,5] = V source
2631 instr[4,0] = R dest */
2633 unsigned vs
= INSTR (9, 5);
2634 unsigned rd
= INSTR (4, 0);
2636 NYI_assert (29, 21, 0x070);
2637 NYI_assert (17, 10, 0x0F);
2639 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2640 switch (INSTR (20, 18))
2643 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, aarch64_get_vec_u64 (cpu
, vs
, 0));
2647 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, aarch64_get_vec_u64 (cpu
, vs
, 1));
2654 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, aarch64_get_vec_u32
2655 (cpu
, vs
, INSTR (20, 19)));
2664 do_vec_INS (sim_cpu
*cpu
)
2666 /* instr[31,21] = 01001110000
2667 instr[20,16] = element size and index
2668 instr[15,10] = 000111
2669 instr[9,5] = W source
2670 instr[4,0] = V dest */
2673 unsigned rs
= INSTR (9, 5);
2674 unsigned vd
= INSTR (4, 0);
2676 NYI_assert (31, 21, 0x270);
2677 NYI_assert (15, 10, 0x07);
2679 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2682 index
= INSTR (20, 17);
2683 aarch64_set_vec_u8 (cpu
, vd
, index
,
2684 aarch64_get_reg_u8 (cpu
, rs
, NO_SP
));
2686 else if (INSTR (17, 17))
2688 index
= INSTR (20, 18);
2689 aarch64_set_vec_u16 (cpu
, vd
, index
,
2690 aarch64_get_reg_u16 (cpu
, rs
, NO_SP
));
2692 else if (INSTR (18, 18))
2694 index
= INSTR (20, 19);
2695 aarch64_set_vec_u32 (cpu
, vd
, index
,
2696 aarch64_get_reg_u32 (cpu
, rs
, NO_SP
));
2698 else if (INSTR (19, 19))
2700 index
= INSTR (20, 20);
2701 aarch64_set_vec_u64 (cpu
, vd
, index
,
2702 aarch64_get_reg_u64 (cpu
, rs
, NO_SP
));
2709 do_vec_DUP_vector_into_vector (sim_cpu
*cpu
)
2712 instr[30] = half(0)/full(1)
2713 instr[29,21] = 00 1110 000
2714 instr[20,16] = element size and index
2715 instr[15,10] = 0000 01
2716 instr[9,5] = V source
2717 instr[4,0] = V dest. */
2719 unsigned full
= INSTR (30, 30);
2720 unsigned vs
= INSTR (9, 5);
2721 unsigned vd
= INSTR (4, 0);
2724 NYI_assert (29, 21, 0x070);
2725 NYI_assert (15, 10, 0x01);
2727 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2730 index
= INSTR (20, 17);
2732 for (i
= 0; i
< (full
? 16 : 8); i
++)
2733 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vs
, index
));
2735 else if (INSTR (17, 17))
2737 index
= INSTR (20, 18);
2739 for (i
= 0; i
< (full
? 8 : 4); i
++)
2740 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vs
, index
));
2742 else if (INSTR (18, 18))
2744 index
= INSTR (20, 19);
2746 for (i
= 0; i
< (full
? 4 : 2); i
++)
2747 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vs
, index
));
2751 if (INSTR (19, 19) == 0)
2757 index
= INSTR (20, 20);
2759 for (i
= 0; i
< 2; i
++)
2760 aarch64_set_vec_u64 (cpu
, vd
, i
, aarch64_get_vec_u64 (cpu
, vs
, index
));
2765 do_vec_TBL (sim_cpu
*cpu
)
2768 instr[30] = half(0)/full(1)
2769 instr[29,21] = 00 1110 000
2772 instr[14,13] = vec length
2774 instr[9,5] = V start
2775 instr[4,0] = V dest */
2777 int full
= INSTR (30, 30);
2778 int len
= INSTR (14, 13) + 1;
2779 unsigned vm
= INSTR (20, 16);
2780 unsigned vn
= INSTR (9, 5);
2781 unsigned vd
= INSTR (4, 0);
2784 NYI_assert (29, 21, 0x070);
2785 NYI_assert (12, 10, 0);
2787 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2788 for (i
= 0; i
< (full
? 16 : 8); i
++)
2790 unsigned int selector
= aarch64_get_vec_u8 (cpu
, vm
, i
);
2794 val
= aarch64_get_vec_u8 (cpu
, vn
, selector
);
2795 else if (selector
< 32)
2796 val
= len
< 2 ? 0 : aarch64_get_vec_u8 (cpu
, vn
+ 1, selector
- 16);
2797 else if (selector
< 48)
2798 val
= len
< 3 ? 0 : aarch64_get_vec_u8 (cpu
, vn
+ 2, selector
- 32);
2799 else if (selector
< 64)
2800 val
= len
< 4 ? 0 : aarch64_get_vec_u8 (cpu
, vn
+ 3, selector
- 48);
2804 aarch64_set_vec_u8 (cpu
, vd
, i
, val
);
2809 do_vec_TRN (sim_cpu
*cpu
)
2812 instr[30] = half(0)/full(1)
2813 instr[29,24] = 00 1110
2818 instr[14] = TRN1 (0) / TRN2 (1)
2820 instr[9,5] = V source
2821 instr[4,0] = V dest. */
2823 int full
= INSTR (30, 30);
2824 int second
= INSTR (14, 14);
2825 unsigned vm
= INSTR (20, 16);
2826 unsigned vn
= INSTR (9, 5);
2827 unsigned vd
= INSTR (4, 0);
2830 NYI_assert (29, 24, 0x0E);
2831 NYI_assert (13, 10, 0xA);
2833 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2834 switch (INSTR (23, 22))
2837 for (i
= 0; i
< (full
? 8 : 4); i
++)
2841 aarch64_get_vec_u8 (cpu
, second
? vm
: vn
, i
* 2));
2843 (cpu
, vd
, 1 * 2 + 1,
2844 aarch64_get_vec_u8 (cpu
, second
? vn
: vm
, i
* 2 + 1));
2849 for (i
= 0; i
< (full
? 4 : 2); i
++)
2853 aarch64_get_vec_u16 (cpu
, second
? vm
: vn
, i
* 2));
2855 (cpu
, vd
, 1 * 2 + 1,
2856 aarch64_get_vec_u16 (cpu
, second
? vn
: vm
, i
* 2 + 1));
2862 (cpu
, vd
, 0, aarch64_get_vec_u32 (cpu
, second
? vm
: vn
, 0));
2864 (cpu
, vd
, 1, aarch64_get_vec_u32 (cpu
, second
? vn
: vm
, 1));
2866 (cpu
, vd
, 2, aarch64_get_vec_u32 (cpu
, second
? vm
: vn
, 2));
2868 (cpu
, vd
, 3, aarch64_get_vec_u32 (cpu
, second
? vn
: vm
, 3));
2875 aarch64_set_vec_u64 (cpu
, vd
, 0,
2876 aarch64_get_vec_u64 (cpu
, second
? vm
: vn
, 0));
2877 aarch64_set_vec_u64 (cpu
, vd
, 1,
2878 aarch64_get_vec_u64 (cpu
, second
? vn
: vm
, 1));
2884 do_vec_DUP_scalar_into_vector (sim_cpu
*cpu
)
2887 instr[30] = 0=> zero top 64-bits, 1=> duplicate into top 64-bits
2888 [must be 1 for 64-bit xfer]
2889 instr[29,20] = 00 1110 0000
2890 instr[19,16] = element size: 0001=> 8-bits, 0010=> 16-bits,
2891 0100=> 32-bits. 1000=>64-bits
2892 instr[15,10] = 0000 11
2893 instr[9,5] = W source
2894 instr[4,0] = V dest. */
2897 unsigned Vd
= INSTR (4, 0);
2898 unsigned Rs
= INSTR (9, 5);
2899 int both
= INSTR (30, 30);
2901 NYI_assert (29, 20, 0x0E0);
2902 NYI_assert (15, 10, 0x03);
2904 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2905 switch (INSTR (19, 16))
2908 for (i
= 0; i
< (both
? 16 : 8); i
++)
2909 aarch64_set_vec_u8 (cpu
, Vd
, i
, aarch64_get_reg_u8 (cpu
, Rs
, NO_SP
));
2913 for (i
= 0; i
< (both
? 8 : 4); i
++)
2914 aarch64_set_vec_u16 (cpu
, Vd
, i
, aarch64_get_reg_u16 (cpu
, Rs
, NO_SP
));
2918 for (i
= 0; i
< (both
? 4 : 2); i
++)
2919 aarch64_set_vec_u32 (cpu
, Vd
, i
, aarch64_get_reg_u32 (cpu
, Rs
, NO_SP
));
2925 aarch64_set_vec_u64 (cpu
, Vd
, 0, aarch64_get_reg_u64 (cpu
, Rs
, NO_SP
));
2926 aarch64_set_vec_u64 (cpu
, Vd
, 1, aarch64_get_reg_u64 (cpu
, Rs
, NO_SP
));
2935 do_vec_UZP (sim_cpu
*cpu
)
2938 instr[30] = half(0)/full(1)
2939 instr[29,24] = 00 1110
2940 instr[23,22] = size: byte(00), half(01), word (10), long (11)
2944 instr[14] = lower (0) / upper (1)
2949 int full
= INSTR (30, 30);
2950 int upper
= INSTR (14, 14);
2952 unsigned vm
= INSTR (20, 16);
2953 unsigned vn
= INSTR (9, 5);
2954 unsigned vd
= INSTR (4, 0);
2956 uint64_t val_m1
= aarch64_get_vec_u64 (cpu
, vm
, 0);
2957 uint64_t val_m2
= aarch64_get_vec_u64 (cpu
, vm
, 1);
2958 uint64_t val_n1
= aarch64_get_vec_u64 (cpu
, vn
, 0);
2959 uint64_t val_n2
= aarch64_get_vec_u64 (cpu
, vn
, 1);
2964 uint64_t input2
= full
? val_n2
: val_m1
;
2966 NYI_assert (29, 24, 0x0E);
2967 NYI_assert (21, 21, 0);
2968 NYI_assert (15, 15, 0);
2969 NYI_assert (13, 10, 6);
2971 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2972 switch (INSTR (23, 22))
2975 val1
= (val_n1
>> (upper
* 8)) & 0xFFULL
;
2976 val1
|= (val_n1
>> ((upper
* 8) + 8)) & 0xFF00ULL
;
2977 val1
|= (val_n1
>> ((upper
* 8) + 16)) & 0xFF0000ULL
;
2978 val1
|= (val_n1
>> ((upper
* 8) + 24)) & 0xFF000000ULL
;
2980 val1
|= (input2
<< (32 - (upper
* 8))) & 0xFF00000000ULL
;
2981 val1
|= (input2
<< (24 - (upper
* 8))) & 0xFF0000000000ULL
;
2982 val1
|= (input2
<< (16 - (upper
* 8))) & 0xFF000000000000ULL
;
2983 val1
|= (input2
<< (8 - (upper
* 8))) & 0xFF00000000000000ULL
;
2987 val2
= (val_m1
>> (upper
* 8)) & 0xFFULL
;
2988 val2
|= (val_m1
>> ((upper
* 8) + 8)) & 0xFF00ULL
;
2989 val2
|= (val_m1
>> ((upper
* 8) + 16)) & 0xFF0000ULL
;
2990 val2
|= (val_m1
>> ((upper
* 8) + 24)) & 0xFF000000ULL
;
2992 val2
|= (val_m2
<< (32 - (upper
* 8))) & 0xFF00000000ULL
;
2993 val2
|= (val_m2
<< (24 - (upper
* 8))) & 0xFF0000000000ULL
;
2994 val2
|= (val_m2
<< (16 - (upper
* 8))) & 0xFF000000000000ULL
;
2995 val2
|= (val_m2
<< (8 - (upper
* 8))) & 0xFF00000000000000ULL
;
3000 val1
= (val_n1
>> (upper
* 16)) & 0xFFFFULL
;
3001 val1
|= (val_n1
>> ((upper
* 16) + 16)) & 0xFFFF0000ULL
;
3003 val1
|= (input2
<< (32 - (upper
* 16))) & 0xFFFF00000000ULL
;;
3004 val1
|= (input2
<< (16 - (upper
* 16))) & 0xFFFF000000000000ULL
;
3008 val2
= (val_m1
>> (upper
* 16)) & 0xFFFFULL
;
3009 val2
|= (val_m1
>> ((upper
* 16) + 16)) & 0xFFFF0000ULL
;
3011 val2
|= (val_m2
<< (32 - (upper
* 16))) & 0xFFFF00000000ULL
;
3012 val2
|= (val_m2
<< (16 - (upper
* 16))) & 0xFFFF000000000000ULL
;
3017 val1
= (val_n1
>> (upper
* 32)) & 0xFFFFFFFF;
3018 val1
|= (input2
<< (32 - (upper
* 32))) & 0xFFFFFFFF00000000ULL
;
3022 val2
= (val_m1
>> (upper
* 32)) & 0xFFFFFFFF;
3023 val2
|= (val_m2
<< (32 - (upper
* 32))) & 0xFFFFFFFF00000000ULL
;
3031 val1
= upper
? val_n2
: val_n1
;
3032 val2
= upper
? val_m2
: val_m1
;
3036 aarch64_set_vec_u64 (cpu
, vd
, 0, val1
);
3038 aarch64_set_vec_u64 (cpu
, vd
, 1, val2
);
3042 do_vec_ZIP (sim_cpu
*cpu
)
3045 instr[30] = half(0)/full(1)
3046 instr[29,24] = 00 1110
3047 instr[23,22] = size: byte(00), hald(01), word (10), long (11)
3051 instr[14] = lower (0) / upper (1)
3056 int full
= INSTR (30, 30);
3057 int upper
= INSTR (14, 14);
3059 unsigned vm
= INSTR (20, 16);
3060 unsigned vn
= INSTR (9, 5);
3061 unsigned vd
= INSTR (4, 0);
3063 uint64_t val_m1
= aarch64_get_vec_u64 (cpu
, vm
, 0);
3064 uint64_t val_m2
= aarch64_get_vec_u64 (cpu
, vm
, 1);
3065 uint64_t val_n1
= aarch64_get_vec_u64 (cpu
, vn
, 0);
3066 uint64_t val_n2
= aarch64_get_vec_u64 (cpu
, vn
, 1);
3071 uint64_t input1
= upper
? val_n1
: val_m1
;
3072 uint64_t input2
= upper
? val_n2
: val_m2
;
3074 NYI_assert (29, 24, 0x0E);
3075 NYI_assert (21, 21, 0);
3076 NYI_assert (15, 15, 0);
3077 NYI_assert (13, 10, 0xE);
3079 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3080 switch (INSTR (23, 23))
3084 ((input1
<< 0) & (0xFF << 0))
3085 | ((input2
<< 8) & (0xFF << 8))
3086 | ((input1
<< 8) & (0xFF << 16))
3087 | ((input2
<< 16) & (0xFF << 24))
3088 | ((input1
<< 16) & (0xFFULL
<< 32))
3089 | ((input2
<< 24) & (0xFFULL
<< 40))
3090 | ((input1
<< 24) & (0xFFULL
<< 48))
3091 | ((input2
<< 32) & (0xFFULL
<< 56));
3094 ((input1
>> 32) & (0xFF << 0))
3095 | ((input2
>> 24) & (0xFF << 8))
3096 | ((input1
>> 24) & (0xFF << 16))
3097 | ((input2
>> 16) & (0xFF << 24))
3098 | ((input1
>> 16) & (0xFFULL
<< 32))
3099 | ((input2
>> 8) & (0xFFULL
<< 40))
3100 | ((input1
>> 8) & (0xFFULL
<< 48))
3101 | ((input2
>> 0) & (0xFFULL
<< 56));
3106 ((input1
<< 0) & (0xFFFF << 0))
3107 | ((input2
<< 16) & (0xFFFF << 16))
3108 | ((input1
<< 16) & (0xFFFFULL
<< 32))
3109 | ((input2
<< 32) & (0xFFFFULL
<< 48));
3112 ((input1
>> 32) & (0xFFFF << 0))
3113 | ((input2
>> 16) & (0xFFFF << 16))
3114 | ((input1
>> 16) & (0xFFFFULL
<< 32))
3115 | ((input2
>> 0) & (0xFFFFULL
<< 48));
3119 val1
= (input1
& 0xFFFFFFFFULL
) | (input2
<< 32);
3120 val2
= (input2
& 0xFFFFFFFFULL
) | (input1
<< 32);
3129 aarch64_set_vec_u64 (cpu
, vd
, 0, val1
);
3131 aarch64_set_vec_u64 (cpu
, vd
, 1, val2
);
3134 /* Floating point immediates are encoded in 8 bits.
3135 fpimm[7] = sign bit.
3136 fpimm[6:4] = signed exponent.
3137 fpimm[3:0] = fraction (assuming leading 1).
3138 i.e. F = s * 1.f * 2^(e - b). */
3141 fp_immediate_for_encoding_32 (uint32_t imm8
)
3144 uint32_t s
, e
, f
, i
;
3146 s
= (imm8
>> 7) & 0x1;
3147 e
= (imm8
>> 4) & 0x7;
3150 /* The fp value is s * n/16 * 2r where n is 16+e. */
3151 u
= (16.0 + f
) / 16.0;
3153 /* N.B. exponent is signed. */
3158 for (i
= 0; i
<= epos
; i
++)
3165 for (i
= 0; i
< eneg
; i
++)
3176 fp_immediate_for_encoding_64 (uint32_t imm8
)
3179 uint32_t s
, e
, f
, i
;
3181 s
= (imm8
>> 7) & 0x1;
3182 e
= (imm8
>> 4) & 0x7;
3185 /* The fp value is s * n/16 * 2r where n is 16+e. */
3186 u
= (16.0 + f
) / 16.0;
3188 /* N.B. exponent is signed. */
3193 for (i
= 0; i
<= epos
; i
++)
3200 for (i
= 0; i
< eneg
; i
++)
3211 do_vec_MOV_immediate (sim_cpu
*cpu
)
3214 instr[30] = full/half selector
3215 instr[29,19] = 00111100000
3216 instr[18,16] = high 3 bits of uimm8
3217 instr[15,12] = size & shift:
3219 0010 => 32-bit + LSL#8
3220 0100 => 32-bit + LSL#16
3221 0110 => 32-bit + LSL#24
3222 1010 => 16-bit + LSL#8
3224 1101 => 32-bit + MSL#16
3225 1100 => 32-bit + MSL#8
3229 instr[9,5] = low 5-bits of uimm8
3232 int full
= INSTR (30, 30);
3233 unsigned vd
= INSTR (4, 0);
3234 unsigned val
= (INSTR (18, 16) << 5) | INSTR (9, 5);
3237 NYI_assert (29, 19, 0x1E0);
3238 NYI_assert (11, 10, 1);
3240 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3241 switch (INSTR (15, 12))
3243 case 0x0: /* 32-bit, no shift. */
3244 case 0x2: /* 32-bit, shift by 8. */
3245 case 0x4: /* 32-bit, shift by 16. */
3246 case 0x6: /* 32-bit, shift by 24. */
3247 val
<<= (8 * INSTR (14, 13));
3248 for (i
= 0; i
< (full
? 4 : 2); i
++)
3249 aarch64_set_vec_u32 (cpu
, vd
, i
, val
);
3252 case 0xa: /* 16-bit, shift by 8. */
3255 case 0x8: /* 16-bit, no shift. */
3256 for (i
= 0; i
< (full
? 8 : 4); i
++)
3257 aarch64_set_vec_u16 (cpu
, vd
, i
, val
);
3260 case 0xd: /* 32-bit, mask shift by 16. */
3264 case 0xc: /* 32-bit, mask shift by 8. */
3267 for (i
= 0; i
< (full
? 4 : 2); i
++)
3268 aarch64_set_vec_u32 (cpu
, vd
, i
, val
);
3271 case 0xe: /* 8-bit, no shift. */
3272 for (i
= 0; i
< (full
? 16 : 8); i
++)
3273 aarch64_set_vec_u8 (cpu
, vd
, i
, val
);
3276 case 0xf: /* FMOV Vs.{2|4}S, #fpimm. */
3278 float u
= fp_immediate_for_encoding_32 (val
);
3279 for (i
= 0; i
< (full
? 4 : 2); i
++)
3280 aarch64_set_vec_float (cpu
, vd
, i
, u
);
3290 do_vec_MVNI (sim_cpu
*cpu
)
3293 instr[30] = full/half selector
3294 instr[29,19] = 10111100000
3295 instr[18,16] = high 3 bits of uimm8
3296 instr[15,12] = selector
3298 instr[9,5] = low 5-bits of uimm8
3301 int full
= INSTR (30, 30);
3302 unsigned vd
= INSTR (4, 0);
3303 unsigned val
= (INSTR (18, 16) << 5) | INSTR (9, 5);
3306 NYI_assert (29, 19, 0x5E0);
3307 NYI_assert (11, 10, 1);
3309 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3310 switch (INSTR (15, 12))
3312 case 0x0: /* 32-bit, no shift. */
3313 case 0x2: /* 32-bit, shift by 8. */
3314 case 0x4: /* 32-bit, shift by 16. */
3315 case 0x6: /* 32-bit, shift by 24. */
3316 val
<<= (8 * INSTR (14, 13));
3318 for (i
= 0; i
< (full
? 4 : 2); i
++)
3319 aarch64_set_vec_u32 (cpu
, vd
, i
, val
);
3322 case 0xa: /* 16-bit, 8 bit shift. */
3324 case 0x8: /* 16-bit, no shift. */
3326 for (i
= 0; i
< (full
? 8 : 4); i
++)
3327 aarch64_set_vec_u16 (cpu
, vd
, i
, val
);
3330 case 0xd: /* 32-bit, mask shift by 16. */
3333 case 0xc: /* 32-bit, mask shift by 8. */
3337 for (i
= 0; i
< (full
? 4 : 2); i
++)
3338 aarch64_set_vec_u32 (cpu
, vd
, i
, val
);
3341 case 0xE: /* MOVI Dn, #mask64 */
3345 for (i
= 0; i
< 8; i
++)
3347 mask
|= (0xFFUL
<< (i
* 8));
3348 aarch64_set_vec_u64 (cpu
, vd
, 0, mask
);
3349 aarch64_set_vec_u64 (cpu
, vd
, 1, mask
);
3353 case 0xf: /* FMOV Vd.2D, #fpimm. */
3355 double u
= fp_immediate_for_encoding_64 (val
);
3360 aarch64_set_vec_double (cpu
, vd
, 0, u
);
3361 aarch64_set_vec_double (cpu
, vd
, 1, u
);
3370 #define ABS(A) ((A) < 0 ? - (A) : (A))
3373 do_vec_ABS (sim_cpu
*cpu
)
3376 instr[30] = half(0)/full(1)
3377 instr[29,24] = 00 1110
3378 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3379 instr[21,10] = 10 0000 1011 10
3383 unsigned vn
= INSTR (9, 5);
3384 unsigned vd
= INSTR (4, 0);
3385 unsigned full
= INSTR (30, 30);
3388 NYI_assert (29, 24, 0x0E);
3389 NYI_assert (21, 10, 0x82E);
3391 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3392 switch (INSTR (23, 22))
3395 for (i
= 0; i
< (full
? 16 : 8); i
++)
3396 aarch64_set_vec_s8 (cpu
, vd
, i
,
3397 ABS (aarch64_get_vec_s8 (cpu
, vn
, i
)));
3401 for (i
= 0; i
< (full
? 8 : 4); i
++)
3402 aarch64_set_vec_s16 (cpu
, vd
, i
,
3403 ABS (aarch64_get_vec_s16 (cpu
, vn
, i
)));
3407 for (i
= 0; i
< (full
? 4 : 2); i
++)
3408 aarch64_set_vec_s32 (cpu
, vd
, i
,
3409 ABS (aarch64_get_vec_s32 (cpu
, vn
, i
)));
3415 for (i
= 0; i
< 2; i
++)
3416 aarch64_set_vec_s64 (cpu
, vd
, i
,
3417 ABS (aarch64_get_vec_s64 (cpu
, vn
, i
)));
3423 do_vec_ADDV (sim_cpu
*cpu
)
3426 instr[30] = full/half selector
3427 instr[29,24] = 00 1110
3428 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3429 instr[21,10] = 11 0001 1011 10
3433 unsigned vm
= INSTR (9, 5);
3434 unsigned rd
= INSTR (4, 0);
3436 int full
= INSTR (30, 30);
3438 NYI_assert (29, 24, 0x0E);
3439 NYI_assert (21, 10, 0xC6E);
3441 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3442 switch (INSTR (23, 22))
3447 for (i
= 0; i
< (full
? 16 : 8); i
++)
3448 val
+= aarch64_get_vec_u8 (cpu
, vm
, i
);
3449 aarch64_set_vec_u64 (cpu
, rd
, 0, val
);
3456 for (i
= 0; i
< (full
? 8 : 4); i
++)
3457 val
+= aarch64_get_vec_u16 (cpu
, vm
, i
);
3458 aarch64_set_vec_u64 (cpu
, rd
, 0, val
);
3467 for (i
= 0; i
< 4; i
++)
3468 val
+= aarch64_get_vec_u32 (cpu
, vm
, i
);
3469 aarch64_set_vec_u64 (cpu
, rd
, 0, val
);
3479 do_vec_ins_2 (sim_cpu
*cpu
)
3481 /* instr[31,21] = 01001110000
3482 instr[20,18] = size & element selector
3484 instr[13] = direction: to vec(0), from vec (1)
3490 unsigned vm
= INSTR (9, 5);
3491 unsigned vd
= INSTR (4, 0);
3493 NYI_assert (31, 21, 0x270);
3494 NYI_assert (17, 14, 0);
3495 NYI_assert (12, 10, 7);
3497 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3498 if (INSTR (13, 13) == 1)
3500 if (INSTR (18, 18) == 1)
3503 elem
= INSTR (20, 19);
3504 aarch64_set_reg_u64 (cpu
, vd
, NO_SP
,
3505 aarch64_get_vec_u32 (cpu
, vm
, elem
));
3510 if (INSTR (19, 19) != 1)
3513 elem
= INSTR (20, 20);
3514 aarch64_set_reg_u64 (cpu
, vd
, NO_SP
,
3515 aarch64_get_vec_u64 (cpu
, vm
, elem
));
3520 if (INSTR (18, 18) == 1)
3523 elem
= INSTR (20, 19);
3524 aarch64_set_vec_u32 (cpu
, vd
, elem
,
3525 aarch64_get_reg_u32 (cpu
, vm
, NO_SP
));
3530 if (INSTR (19, 19) != 1)
3533 elem
= INSTR (20, 20);
3534 aarch64_set_vec_u64 (cpu
, vd
, elem
,
3535 aarch64_get_reg_u64 (cpu
, vm
, NO_SP
));
3540 #define DO_VEC_WIDENING_MUL(N, DST_TYPE, READ_TYPE, WRITE_TYPE) \
3543 DST_TYPE a[N], b[N]; \
3545 for (i = 0; i < (N); i++) \
3547 a[i] = aarch64_get_vec_##READ_TYPE (cpu, vn, i + bias); \
3548 b[i] = aarch64_get_vec_##READ_TYPE (cpu, vm, i + bias); \
3550 for (i = 0; i < (N); i++) \
3551 aarch64_set_vec_##WRITE_TYPE (cpu, vd, i, a[i] * b[i]); \
3556 do_vec_mull (sim_cpu
*cpu
)
3559 instr[30] = lower(0)/upper(1) selector
3560 instr[29] = signed(0)/unsigned(1)
3561 instr[28,24] = 0 1110
3562 instr[23,22] = size: 8-bit (00), 16-bit (01), 32-bit (10)
3565 instr[15,10] = 11 0000
3569 int unsign
= INSTR (29, 29);
3570 int bias
= INSTR (30, 30);
3571 unsigned vm
= INSTR (20, 16);
3572 unsigned vn
= INSTR ( 9, 5);
3573 unsigned vd
= INSTR ( 4, 0);
3576 NYI_assert (28, 24, 0x0E);
3577 NYI_assert (15, 10, 0x30);
3579 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3580 /* NB: Read source values before writing results, in case
3581 the source and destination vectors are the same. */
3582 switch (INSTR (23, 22))
3588 DO_VEC_WIDENING_MUL (8, uint16_t, u8
, u16
);
3590 DO_VEC_WIDENING_MUL (8, int16_t, s8
, s16
);
3597 DO_VEC_WIDENING_MUL (4, uint32_t, u16
, u32
);
3599 DO_VEC_WIDENING_MUL (4, int32_t, s16
, s32
);
3606 DO_VEC_WIDENING_MUL (2, uint64_t, u32
, u64
);
3608 DO_VEC_WIDENING_MUL (2, int64_t, s32
, s64
);
3617 do_vec_fadd (sim_cpu
*cpu
)
3620 instr[30] = half(0)/full(1)
3621 instr[29,24] = 001110
3622 instr[23] = FADD(0)/FSUB(1)
3623 instr[22] = float (0)/double(1)
3626 instr[15,10] = 110101
3630 unsigned vm
= INSTR (20, 16);
3631 unsigned vn
= INSTR (9, 5);
3632 unsigned vd
= INSTR (4, 0);
3634 int full
= INSTR (30, 30);
3636 NYI_assert (29, 24, 0x0E);
3637 NYI_assert (21, 21, 1);
3638 NYI_assert (15, 10, 0x35);
3640 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3648 for (i
= 0; i
< 2; i
++)
3649 aarch64_set_vec_double (cpu
, vd
, i
,
3650 aarch64_get_vec_double (cpu
, vn
, i
)
3651 - aarch64_get_vec_double (cpu
, vm
, i
));
3655 for (i
= 0; i
< (full
? 4 : 2); i
++)
3656 aarch64_set_vec_float (cpu
, vd
, i
,
3657 aarch64_get_vec_float (cpu
, vn
, i
)
3658 - aarch64_get_vec_float (cpu
, vm
, i
));
3668 for (i
= 0; i
< 2; i
++)
3669 aarch64_set_vec_double (cpu
, vd
, i
,
3670 aarch64_get_vec_double (cpu
, vm
, i
)
3671 + aarch64_get_vec_double (cpu
, vn
, i
));
3675 for (i
= 0; i
< (full
? 4 : 2); i
++)
3676 aarch64_set_vec_float (cpu
, vd
, i
,
3677 aarch64_get_vec_float (cpu
, vm
, i
)
3678 + aarch64_get_vec_float (cpu
, vn
, i
));
3684 do_vec_add (sim_cpu
*cpu
)
3687 instr[30] = full/half selector
3688 instr[29,24] = 001110
3689 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3692 instr[15,10] = 100001
3696 unsigned vm
= INSTR (20, 16);
3697 unsigned vn
= INSTR (9, 5);
3698 unsigned vd
= INSTR (4, 0);
3700 int full
= INSTR (30, 30);
3702 NYI_assert (29, 24, 0x0E);
3703 NYI_assert (21, 21, 1);
3704 NYI_assert (15, 10, 0x21);
3706 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3707 switch (INSTR (23, 22))
3710 for (i
= 0; i
< (full
? 16 : 8); i
++)
3711 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vn
, i
)
3712 + aarch64_get_vec_u8 (cpu
, vm
, i
));
3716 for (i
= 0; i
< (full
? 8 : 4); i
++)
3717 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vn
, i
)
3718 + aarch64_get_vec_u16 (cpu
, vm
, i
));
3722 for (i
= 0; i
< (full
? 4 : 2); i
++)
3723 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vn
, i
)
3724 + aarch64_get_vec_u32 (cpu
, vm
, i
));
3730 aarch64_set_vec_u64 (cpu
, vd
, 0, aarch64_get_vec_u64 (cpu
, vn
, 0)
3731 + aarch64_get_vec_u64 (cpu
, vm
, 0));
3732 aarch64_set_vec_u64 (cpu
, vd
, 1,
3733 aarch64_get_vec_u64 (cpu
, vn
, 1)
3734 + aarch64_get_vec_u64 (cpu
, vm
, 1));
3740 do_vec_mul (sim_cpu
*cpu
)
3743 instr[30] = full/half selector
3744 instr[29,24] = 00 1110
3745 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3748 instr[15,10] = 10 0111
3752 unsigned vm
= INSTR (20, 16);
3753 unsigned vn
= INSTR (9, 5);
3754 unsigned vd
= INSTR (4, 0);
3756 int full
= INSTR (30, 30);
3759 NYI_assert (29, 24, 0x0E);
3760 NYI_assert (21, 21, 1);
3761 NYI_assert (15, 10, 0x27);
3763 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3764 switch (INSTR (23, 22))
3767 DO_VEC_WIDENING_MUL (full
? 16 : 8, uint8_t, u8
, u8
);
3771 DO_VEC_WIDENING_MUL (full
? 8 : 4, uint16_t, u16
, u16
);
3775 DO_VEC_WIDENING_MUL (full
? 4 : 2, uint32_t, u32
, u32
);
3784 do_vec_MLA (sim_cpu
*cpu
)
3787 instr[30] = full/half selector
3788 instr[29,24] = 00 1110
3789 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3792 instr[15,10] = 1001 01
3796 unsigned vm
= INSTR (20, 16);
3797 unsigned vn
= INSTR (9, 5);
3798 unsigned vd
= INSTR (4, 0);
3800 int full
= INSTR (30, 30);
3802 NYI_assert (29, 24, 0x0E);
3803 NYI_assert (21, 21, 1);
3804 NYI_assert (15, 10, 0x25);
3806 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3807 switch (INSTR (23, 22))
3810 for (i
= 0; i
< (full
? 16 : 8); i
++)
3811 aarch64_set_vec_u8 (cpu
, vd
, i
,
3812 aarch64_get_vec_u8 (cpu
, vd
, i
)
3813 + (aarch64_get_vec_u8 (cpu
, vn
, i
)
3814 * aarch64_get_vec_u8 (cpu
, vm
, i
)));
3818 for (i
= 0; i
< (full
? 8 : 4); i
++)
3819 aarch64_set_vec_u16 (cpu
, vd
, i
,
3820 aarch64_get_vec_u16 (cpu
, vd
, i
)
3821 + (aarch64_get_vec_u16 (cpu
, vn
, i
)
3822 * aarch64_get_vec_u16 (cpu
, vm
, i
)));
3826 for (i
= 0; i
< (full
? 4 : 2); i
++)
3827 aarch64_set_vec_u32 (cpu
, vd
, i
,
3828 aarch64_get_vec_u32 (cpu
, vd
, i
)
3829 + (aarch64_get_vec_u32 (cpu
, vn
, i
)
3830 * aarch64_get_vec_u32 (cpu
, vm
, i
)));
3839 fmaxnm (float a
, float b
)
3844 return a
> b
? a
: b
;
3847 else if (! isnan (b
))
3853 fminnm (float a
, float b
)
3858 return a
< b
? a
: b
;
3861 else if (! isnan (b
))
3867 dmaxnm (double a
, double b
)
3872 return a
> b
? a
: b
;
3875 else if (! isnan (b
))
3881 dminnm (double a
, double b
)
3886 return a
< b
? a
: b
;
3889 else if (! isnan (b
))
3895 do_vec_FminmaxNMP (sim_cpu
*cpu
)
3898 instr [30] = half (0)/full (1)
3899 instr [29,24] = 10 1110
3900 instr [23] = max(0)/min(1)
3901 instr [22] = float (0)/double (1)
3904 instr [15,10] = 1100 01
3906 instr [4.0] = Vd. */
3908 unsigned vm
= INSTR (20, 16);
3909 unsigned vn
= INSTR (9, 5);
3910 unsigned vd
= INSTR (4, 0);
3911 int full
= INSTR (30, 30);
3913 NYI_assert (29, 24, 0x2E);
3914 NYI_assert (21, 21, 1);
3915 NYI_assert (15, 10, 0x31);
3917 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3920 double (* fn
)(double, double) = INSTR (23, 23)
3925 aarch64_set_vec_double (cpu
, vd
, 0,
3926 fn (aarch64_get_vec_double (cpu
, vn
, 0),
3927 aarch64_get_vec_double (cpu
, vn
, 1)));
3928 aarch64_set_vec_double (cpu
, vd
, 0,
3929 fn (aarch64_get_vec_double (cpu
, vm
, 0),
3930 aarch64_get_vec_double (cpu
, vm
, 1)));
3934 float (* fn
)(float, float) = INSTR (23, 23)
3937 aarch64_set_vec_float (cpu
, vd
, 0,
3938 fn (aarch64_get_vec_float (cpu
, vn
, 0),
3939 aarch64_get_vec_float (cpu
, vn
, 1)));
3941 aarch64_set_vec_float (cpu
, vd
, 1,
3942 fn (aarch64_get_vec_float (cpu
, vn
, 2),
3943 aarch64_get_vec_float (cpu
, vn
, 3)));
3945 aarch64_set_vec_float (cpu
, vd
, (full
? 2 : 1),
3946 fn (aarch64_get_vec_float (cpu
, vm
, 0),
3947 aarch64_get_vec_float (cpu
, vm
, 1)));
3949 aarch64_set_vec_float (cpu
, vd
, 3,
3950 fn (aarch64_get_vec_float (cpu
, vm
, 2),
3951 aarch64_get_vec_float (cpu
, vm
, 3)));
3956 do_vec_AND (sim_cpu
*cpu
)
3959 instr[30] = half (0)/full (1)
3960 instr[29,21] = 001110001
3962 instr[15,10] = 000111
3966 unsigned vm
= INSTR (20, 16);
3967 unsigned vn
= INSTR (9, 5);
3968 unsigned vd
= INSTR (4, 0);
3970 int full
= INSTR (30, 30);
3972 NYI_assert (29, 21, 0x071);
3973 NYI_assert (15, 10, 0x07);
3975 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3976 for (i
= 0; i
< (full
? 4 : 2); i
++)
3977 aarch64_set_vec_u32 (cpu
, vd
, i
,
3978 aarch64_get_vec_u32 (cpu
, vn
, i
)
3979 & aarch64_get_vec_u32 (cpu
, vm
, i
));
3983 do_vec_BSL (sim_cpu
*cpu
)
3986 instr[30] = half (0)/full (1)
3987 instr[29,21] = 101110011
3989 instr[15,10] = 000111
3993 unsigned vm
= INSTR (20, 16);
3994 unsigned vn
= INSTR (9, 5);
3995 unsigned vd
= INSTR (4, 0);
3997 int full
= INSTR (30, 30);
3999 NYI_assert (29, 21, 0x173);
4000 NYI_assert (15, 10, 0x07);
4002 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4003 for (i
= 0; i
< (full
? 16 : 8); i
++)
4004 aarch64_set_vec_u8 (cpu
, vd
, i
,
4005 ( aarch64_get_vec_u8 (cpu
, vd
, i
)
4006 & aarch64_get_vec_u8 (cpu
, vn
, i
))
4007 | ((~ aarch64_get_vec_u8 (cpu
, vd
, i
))
4008 & aarch64_get_vec_u8 (cpu
, vm
, i
)));
4012 do_vec_EOR (sim_cpu
*cpu
)
4015 instr[30] = half (0)/full (1)
4016 instr[29,21] = 10 1110 001
4018 instr[15,10] = 000111
4022 unsigned vm
= INSTR (20, 16);
4023 unsigned vn
= INSTR (9, 5);
4024 unsigned vd
= INSTR (4, 0);
4026 int full
= INSTR (30, 30);
4028 NYI_assert (29, 21, 0x171);
4029 NYI_assert (15, 10, 0x07);
4031 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4032 for (i
= 0; i
< (full
? 4 : 2); i
++)
4033 aarch64_set_vec_u32 (cpu
, vd
, i
,
4034 aarch64_get_vec_u32 (cpu
, vn
, i
)
4035 ^ aarch64_get_vec_u32 (cpu
, vm
, i
));
4039 do_vec_bit (sim_cpu
*cpu
)
4042 instr[30] = half (0)/full (1)
4043 instr[29,23] = 10 1110 1
4044 instr[22] = BIT (0) / BIF (1)
4047 instr[15,10] = 0001 11
4051 unsigned vm
= INSTR (20, 16);
4052 unsigned vn
= INSTR (9, 5);
4053 unsigned vd
= INSTR (4, 0);
4054 unsigned full
= INSTR (30, 30);
4055 unsigned test_false
= INSTR (22, 22);
4058 NYI_assert (29, 23, 0x5D);
4059 NYI_assert (21, 21, 1);
4060 NYI_assert (15, 10, 0x07);
4062 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4063 for (i
= 0; i
< (full
? 4 : 2); i
++)
4065 uint32_t vd_val
= aarch64_get_vec_u32 (cpu
, vd
, i
);
4066 uint32_t vn_val
= aarch64_get_vec_u32 (cpu
, vn
, i
);
4067 uint32_t vm_val
= aarch64_get_vec_u32 (cpu
, vm
, i
);
4069 aarch64_set_vec_u32 (cpu
, vd
, i
,
4070 (vd_val
& vm_val
) | (vn_val
& ~vm_val
));
4072 aarch64_set_vec_u32 (cpu
, vd
, i
,
4073 (vd_val
& ~vm_val
) | (vn_val
& vm_val
));
4078 do_vec_ORN (sim_cpu
*cpu
)
4081 instr[30] = half (0)/full (1)
4082 instr[29,21] = 00 1110 111
4084 instr[15,10] = 00 0111
4088 unsigned vm
= INSTR (20, 16);
4089 unsigned vn
= INSTR (9, 5);
4090 unsigned vd
= INSTR (4, 0);
4092 int full
= INSTR (30, 30);
4094 NYI_assert (29, 21, 0x077);
4095 NYI_assert (15, 10, 0x07);
4097 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4098 for (i
= 0; i
< (full
? 16 : 8); i
++)
4099 aarch64_set_vec_u8 (cpu
, vd
, i
,
4100 aarch64_get_vec_u8 (cpu
, vn
, i
)
4101 | ~ aarch64_get_vec_u8 (cpu
, vm
, i
));
4105 do_vec_ORR (sim_cpu
*cpu
)
4108 instr[30] = half (0)/full (1)
4109 instr[29,21] = 00 1110 101
4111 instr[15,10] = 0001 11
4115 unsigned vm
= INSTR (20, 16);
4116 unsigned vn
= INSTR (9, 5);
4117 unsigned vd
= INSTR (4, 0);
4119 int full
= INSTR (30, 30);
4121 NYI_assert (29, 21, 0x075);
4122 NYI_assert (15, 10, 0x07);
4124 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4125 for (i
= 0; i
< (full
? 16 : 8); i
++)
4126 aarch64_set_vec_u8 (cpu
, vd
, i
,
4127 aarch64_get_vec_u8 (cpu
, vn
, i
)
4128 | aarch64_get_vec_u8 (cpu
, vm
, i
));
4132 do_vec_BIC (sim_cpu
*cpu
)
4135 instr[30] = half (0)/full (1)
4136 instr[29,21] = 00 1110 011
4138 instr[15,10] = 00 0111
4142 unsigned vm
= INSTR (20, 16);
4143 unsigned vn
= INSTR (9, 5);
4144 unsigned vd
= INSTR (4, 0);
4146 int full
= INSTR (30, 30);
4148 NYI_assert (29, 21, 0x073);
4149 NYI_assert (15, 10, 0x07);
4151 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4152 for (i
= 0; i
< (full
? 16 : 8); i
++)
4153 aarch64_set_vec_u8 (cpu
, vd
, i
,
4154 aarch64_get_vec_u8 (cpu
, vn
, i
)
4155 & ~ aarch64_get_vec_u8 (cpu
, vm
, i
));
4159 do_vec_XTN (sim_cpu
*cpu
)
4162 instr[30] = first part (0)/ second part (1)
4163 instr[29,24] = 00 1110
4164 instr[23,22] = size: byte(00), half(01), word (10)
4165 instr[21,10] = 1000 0100 1010
4169 unsigned vs
= INSTR (9, 5);
4170 unsigned vd
= INSTR (4, 0);
4171 unsigned bias
= INSTR (30, 30);
4174 NYI_assert (29, 24, 0x0E);
4175 NYI_assert (21, 10, 0x84A);
4177 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4178 switch (INSTR (23, 22))
4181 for (i
= 0; i
< 8; i
++)
4182 aarch64_set_vec_u8 (cpu
, vd
, i
+ (bias
* 8),
4183 aarch64_get_vec_u16 (cpu
, vs
, i
));
4187 for (i
= 0; i
< 4; i
++)
4188 aarch64_set_vec_u16 (cpu
, vd
, i
+ (bias
* 4),
4189 aarch64_get_vec_u32 (cpu
, vs
, i
));
4193 for (i
= 0; i
< 2; i
++)
4194 aarch64_set_vec_u32 (cpu
, vd
, i
+ (bias
* 2),
4195 aarch64_get_vec_u64 (cpu
, vs
, i
));
4201 do_vec_maxv (sim_cpu
*cpu
)
4204 instr[30] = half(0)/full(1)
4205 instr[29] = signed (0)/unsigned(1)
4206 instr[28,24] = 0 1110
4207 instr[23,22] = size: byte(00), half(01), word (10)
4209 instr[20,17] = 1 000
4210 instr[16] = max(0)/min(1)
4211 instr[15,10] = 1010 10
4212 instr[9,5] = V source
4213 instr[4.0] = R dest. */
4215 unsigned vs
= INSTR (9, 5);
4216 unsigned rd
= INSTR (4, 0);
4217 unsigned full
= INSTR (30, 30);
4220 NYI_assert (28, 24, 0x0E);
4221 NYI_assert (21, 21, 1);
4222 NYI_assert (20, 17, 8);
4223 NYI_assert (15, 10, 0x2A);
4225 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4226 switch ((INSTR (29, 29) << 1) | INSTR (16, 16))
4228 case 0: /* SMAXV. */
4231 switch (INSTR (23, 22))
4234 smax
= aarch64_get_vec_s8 (cpu
, vs
, 0);
4235 for (i
= 1; i
< (full
? 16 : 8); i
++)
4236 smax
= max (smax
, aarch64_get_vec_s8 (cpu
, vs
, i
));
4239 smax
= aarch64_get_vec_s16 (cpu
, vs
, 0);
4240 for (i
= 1; i
< (full
? 8 : 4); i
++)
4241 smax
= max (smax
, aarch64_get_vec_s16 (cpu
, vs
, i
));
4244 smax
= aarch64_get_vec_s32 (cpu
, vs
, 0);
4245 for (i
= 1; i
< (full
? 4 : 2); i
++)
4246 smax
= max (smax
, aarch64_get_vec_s32 (cpu
, vs
, i
));
4251 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, smax
);
4255 case 1: /* SMINV. */
4258 switch (INSTR (23, 22))
4261 smin
= aarch64_get_vec_s8 (cpu
, vs
, 0);
4262 for (i
= 1; i
< (full
? 16 : 8); i
++)
4263 smin
= min (smin
, aarch64_get_vec_s8 (cpu
, vs
, i
));
4266 smin
= aarch64_get_vec_s16 (cpu
, vs
, 0);
4267 for (i
= 1; i
< (full
? 8 : 4); i
++)
4268 smin
= min (smin
, aarch64_get_vec_s16 (cpu
, vs
, i
));
4271 smin
= aarch64_get_vec_s32 (cpu
, vs
, 0);
4272 for (i
= 1; i
< (full
? 4 : 2); i
++)
4273 smin
= min (smin
, aarch64_get_vec_s32 (cpu
, vs
, i
));
4279 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, smin
);
4283 case 2: /* UMAXV. */
4286 switch (INSTR (23, 22))
4289 umax
= aarch64_get_vec_u8 (cpu
, vs
, 0);
4290 for (i
= 1; i
< (full
? 16 : 8); i
++)
4291 umax
= max (umax
, aarch64_get_vec_u8 (cpu
, vs
, i
));
4294 umax
= aarch64_get_vec_u16 (cpu
, vs
, 0);
4295 for (i
= 1; i
< (full
? 8 : 4); i
++)
4296 umax
= max (umax
, aarch64_get_vec_u16 (cpu
, vs
, i
));
4299 umax
= aarch64_get_vec_u32 (cpu
, vs
, 0);
4300 for (i
= 1; i
< (full
? 4 : 2); i
++)
4301 umax
= max (umax
, aarch64_get_vec_u32 (cpu
, vs
, i
));
4307 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, umax
);
4311 case 3: /* UMINV. */
4314 switch (INSTR (23, 22))
4317 umin
= aarch64_get_vec_u8 (cpu
, vs
, 0);
4318 for (i
= 1; i
< (full
? 16 : 8); i
++)
4319 umin
= min (umin
, aarch64_get_vec_u8 (cpu
, vs
, i
));
4322 umin
= aarch64_get_vec_u16 (cpu
, vs
, 0);
4323 for (i
= 1; i
< (full
? 8 : 4); i
++)
4324 umin
= min (umin
, aarch64_get_vec_u16 (cpu
, vs
, i
));
4327 umin
= aarch64_get_vec_u32 (cpu
, vs
, 0);
4328 for (i
= 1; i
< (full
? 4 : 2); i
++)
4329 umin
= min (umin
, aarch64_get_vec_u32 (cpu
, vs
, i
));
4335 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, umin
);
4342 do_vec_fminmaxV (sim_cpu
*cpu
)
4344 /* instr[31,24] = 0110 1110
4345 instr[23] = max(0)/min(1)
4346 instr[22,14] = 011 0000 11
4347 instr[13,12] = nm(00)/normal(11)
4349 instr[9,5] = V source
4350 instr[4.0] = R dest. */
4352 unsigned vs
= INSTR (9, 5);
4353 unsigned rd
= INSTR (4, 0);
4355 float res
= aarch64_get_vec_float (cpu
, vs
, 0);
4357 NYI_assert (31, 24, 0x6E);
4358 NYI_assert (22, 14, 0x0C3);
4359 NYI_assert (11, 10, 2);
4361 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4364 switch (INSTR (13, 12))
4366 case 0: /* FMNINNMV. */
4367 for (i
= 1; i
< 4; i
++)
4368 res
= fminnm (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4371 case 3: /* FMINV. */
4372 for (i
= 1; i
< 4; i
++)
4373 res
= min (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4382 switch (INSTR (13, 12))
4384 case 0: /* FMNAXNMV. */
4385 for (i
= 1; i
< 4; i
++)
4386 res
= fmaxnm (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4389 case 3: /* FMAXV. */
4390 for (i
= 1; i
< 4; i
++)
4391 res
= max (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4399 aarch64_set_FP_float (cpu
, rd
, res
);
4403 do_vec_Fminmax (sim_cpu
*cpu
)
4406 instr[30] = half(0)/full(1)
4407 instr[29,24] = 00 1110
4408 instr[23] = max(0)/min(1)
4409 instr[22] = float(0)/double(1)
4413 instr[13,12] = nm(00)/normal(11)
4418 unsigned vm
= INSTR (20, 16);
4419 unsigned vn
= INSTR (9, 5);
4420 unsigned vd
= INSTR (4, 0);
4421 unsigned full
= INSTR (30, 30);
4422 unsigned min
= INSTR (23, 23);
4425 NYI_assert (29, 24, 0x0E);
4426 NYI_assert (21, 21, 1);
4427 NYI_assert (15, 14, 3);
4428 NYI_assert (11, 10, 1);
4430 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4433 double (* func
)(double, double);
4438 if (INSTR (13, 12) == 0)
4439 func
= min
? dminnm
: dmaxnm
;
4440 else if (INSTR (13, 12) == 3)
4441 func
= min
? fmin
: fmax
;
4445 for (i
= 0; i
< 2; i
++)
4446 aarch64_set_vec_double (cpu
, vd
, i
,
4447 func (aarch64_get_vec_double (cpu
, vn
, i
),
4448 aarch64_get_vec_double (cpu
, vm
, i
)));
4452 float (* func
)(float, float);
4454 if (INSTR (13, 12) == 0)
4455 func
= min
? fminnm
: fmaxnm
;
4456 else if (INSTR (13, 12) == 3)
4457 func
= min
? fminf
: fmaxf
;
4461 for (i
= 0; i
< (full
? 4 : 2); i
++)
4462 aarch64_set_vec_float (cpu
, vd
, i
,
4463 func (aarch64_get_vec_float (cpu
, vn
, i
),
4464 aarch64_get_vec_float (cpu
, vm
, i
)));
4469 do_vec_SCVTF (sim_cpu
*cpu
)
4473 instr[29,23] = 00 1110 0
4474 instr[22] = float(0)/double(1)
4475 instr[21,10] = 10 0001 1101 10
4479 unsigned vn
= INSTR (9, 5);
4480 unsigned vd
= INSTR (4, 0);
4481 unsigned full
= INSTR (30, 30);
4482 unsigned size
= INSTR (22, 22);
4485 NYI_assert (29, 23, 0x1C);
4486 NYI_assert (21, 10, 0x876);
4488 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4494 for (i
= 0; i
< 2; i
++)
4496 double val
= (double) aarch64_get_vec_u64 (cpu
, vn
, i
);
4497 aarch64_set_vec_double (cpu
, vd
, i
, val
);
4502 for (i
= 0; i
< (full
? 4 : 2); i
++)
4504 float val
= (float) aarch64_get_vec_u32 (cpu
, vn
, i
);
4505 aarch64_set_vec_float (cpu
, vd
, i
, val
);
4510 #define VEC_CMP(SOURCE, CMP) \
4516 for (i = 0; i < (full ? 16 : 8); i++) \
4517 aarch64_set_vec_u8 (cpu, vd, i, \
4518 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4520 aarch64_get_vec_##SOURCE##8 (cpu, vm, i) \
4524 for (i = 0; i < (full ? 8 : 4); i++) \
4525 aarch64_set_vec_u16 (cpu, vd, i, \
4526 aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4528 aarch64_get_vec_##SOURCE##16 (cpu, vm, i) \
4532 for (i = 0; i < (full ? 4 : 2); i++) \
4533 aarch64_set_vec_u32 (cpu, vd, i, \
4534 aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4536 aarch64_get_vec_##SOURCE##32 (cpu, vm, i) \
4542 for (i = 0; i < 2; i++) \
4543 aarch64_set_vec_u64 (cpu, vd, i, \
4544 aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4546 aarch64_get_vec_##SOURCE##64 (cpu, vm, i) \
4553 #define VEC_CMP0(SOURCE, CMP) \
4559 for (i = 0; i < (full ? 16 : 8); i++) \
4560 aarch64_set_vec_u8 (cpu, vd, i, \
4561 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4565 for (i = 0; i < (full ? 8 : 4); i++) \
4566 aarch64_set_vec_u16 (cpu, vd, i, \
4567 aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4571 for (i = 0; i < (full ? 4 : 2); i++) \
4572 aarch64_set_vec_u32 (cpu, vd, i, \
4573 aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4579 for (i = 0; i < 2; i++) \
4580 aarch64_set_vec_u64 (cpu, vd, i, \
4581 aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4582 CMP 0 ? -1ULL : 0); \
4588 #define VEC_FCMP0(CMP) \
4593 if (INSTR (22, 22)) \
4597 for (i = 0; i < 2; i++) \
4598 aarch64_set_vec_u64 (cpu, vd, i, \
4599 aarch64_get_vec_double (cpu, vn, i) \
4600 CMP 0.0 ? -1 : 0); \
4604 for (i = 0; i < (full ? 4 : 2); i++) \
4605 aarch64_set_vec_u32 (cpu, vd, i, \
4606 aarch64_get_vec_float (cpu, vn, i) \
4607 CMP 0.0 ? -1 : 0); \
4613 #define VEC_FCMP(CMP) \
4616 if (INSTR (22, 22)) \
4620 for (i = 0; i < 2; i++) \
4621 aarch64_set_vec_u64 (cpu, vd, i, \
4622 aarch64_get_vec_double (cpu, vn, i) \
4624 aarch64_get_vec_double (cpu, vm, i) \
4629 for (i = 0; i < (full ? 4 : 2); i++) \
4630 aarch64_set_vec_u32 (cpu, vd, i, \
4631 aarch64_get_vec_float (cpu, vn, i) \
4633 aarch64_get_vec_float (cpu, vm, i) \
4641 do_vec_compare (sim_cpu
*cpu
)
4644 instr[30] = half(0)/full(1)
4645 instr[29] = part-of-comparison-type
4646 instr[28,24] = 0 1110
4647 instr[23,22] = size of integer compares: byte(00), half(01), word (10), long (11)
4648 type of float compares: single (-0) / double (-1)
4650 instr[20,16] = Vm or 00000 (compare vs 0)
4651 instr[15,10] = part-of-comparison-type
4655 int full
= INSTR (30, 30);
4656 int size
= INSTR (23, 22);
4657 unsigned vm
= INSTR (20, 16);
4658 unsigned vn
= INSTR (9, 5);
4659 unsigned vd
= INSTR (4, 0);
4662 NYI_assert (28, 24, 0x0E);
4663 NYI_assert (21, 21, 1);
4665 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4668 || ((INSTR (11, 11) == 0
4669 && INSTR (10, 10) == 0)))
4671 /* A compare vs 0. */
4674 if (INSTR (15, 10) == 0x2A)
4676 else if (INSTR (15, 10) == 0x32
4677 || INSTR (15, 10) == 0x3E)
4678 do_vec_fminmaxV (cpu
);
4679 else if (INSTR (29, 23) == 0x1C
4680 && INSTR (21, 10) == 0x876)
4690 /* A floating point compare. */
4691 unsigned decode
= (INSTR (29, 29) << 5) | (INSTR (23, 23) << 4)
4694 NYI_assert (15, 15, 1);
4698 case /* 0b010010: GT#0 */ 0x12: VEC_FCMP0 (>);
4699 case /* 0b110010: GE#0 */ 0x32: VEC_FCMP0 (>=);
4700 case /* 0b010110: EQ#0 */ 0x16: VEC_FCMP0 (==);
4701 case /* 0b110110: LE#0 */ 0x36: VEC_FCMP0 (<=);
4702 case /* 0b011010: LT#0 */ 0x1A: VEC_FCMP0 (<);
4703 case /* 0b111001: GT */ 0x39: VEC_FCMP (>);
4704 case /* 0b101001: GE */ 0x29: VEC_FCMP (>=);
4705 case /* 0b001001: EQ */ 0x09: VEC_FCMP (==);
4713 unsigned decode
= (INSTR (29, 29) << 6) | INSTR (15, 10);
4717 case 0x0D: /* 0001101 GT */ VEC_CMP (s
, > );
4718 case 0x0F: /* 0001111 GE */ VEC_CMP (s
, >= );
4719 case 0x22: /* 0100010 GT #0 */ VEC_CMP0 (s
, > );
4720 case 0x23: /* 0100011 TST */ VEC_CMP (u
, & );
4721 case 0x26: /* 0100110 EQ #0 */ VEC_CMP0 (s
, == );
4722 case 0x2A: /* 0101010 LT #0 */ VEC_CMP0 (s
, < );
4723 case 0x4D: /* 1001101 HI */ VEC_CMP (u
, > );
4724 case 0x4F: /* 1001111 HS */ VEC_CMP (u
, >= );
4725 case 0x62: /* 1100010 GE #0 */ VEC_CMP0 (s
, >= );
4726 case 0x63: /* 1100011 EQ */ VEC_CMP (u
, == );
4727 case 0x66: /* 1100110 LE #0 */ VEC_CMP0 (s
, <= );
4737 do_vec_SSHL (sim_cpu
*cpu
)
4740 instr[30] = first part (0)/ second part (1)
4741 instr[29,24] = 00 1110
4742 instr[23,22] = size: byte(00), half(01), word (10), long (11)
4745 instr[15,10] = 0100 01
4749 unsigned full
= INSTR (30, 30);
4750 unsigned vm
= INSTR (20, 16);
4751 unsigned vn
= INSTR (9, 5);
4752 unsigned vd
= INSTR (4, 0);
4756 NYI_assert (29, 24, 0x0E);
4757 NYI_assert (21, 21, 1);
4758 NYI_assert (15, 10, 0x11);
4760 /* FIXME: What is a signed shift left in this context ?. */
4762 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4763 switch (INSTR (23, 22))
4766 for (i
= 0; i
< (full
? 16 : 8); i
++)
4768 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
);
4770 aarch64_set_vec_s8 (cpu
, vd
, i
, aarch64_get_vec_s8 (cpu
, vn
, i
)
4773 aarch64_set_vec_s8 (cpu
, vd
, i
, aarch64_get_vec_s8 (cpu
, vn
, i
)
4779 for (i
= 0; i
< (full
? 8 : 4); i
++)
4781 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 2);
4783 aarch64_set_vec_s16 (cpu
, vd
, i
, aarch64_get_vec_s16 (cpu
, vn
, i
)
4786 aarch64_set_vec_s16 (cpu
, vd
, i
, aarch64_get_vec_s16 (cpu
, vn
, i
)
4792 for (i
= 0; i
< (full
? 4 : 2); i
++)
4794 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 4);
4796 aarch64_set_vec_s32 (cpu
, vd
, i
, aarch64_get_vec_s32 (cpu
, vn
, i
)
4799 aarch64_set_vec_s32 (cpu
, vd
, i
, aarch64_get_vec_s32 (cpu
, vn
, i
)
4807 for (i
= 0; i
< 2; i
++)
4809 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 8);
4811 aarch64_set_vec_s64 (cpu
, vd
, i
, aarch64_get_vec_s64 (cpu
, vn
, i
)
4814 aarch64_set_vec_s64 (cpu
, vd
, i
, aarch64_get_vec_s64 (cpu
, vn
, i
)
4822 do_vec_USHL (sim_cpu
*cpu
)
4825 instr[30] = first part (0)/ second part (1)
4826 instr[29,24] = 10 1110
4827 instr[23,22] = size: byte(00), half(01), word (10), long (11)
4830 instr[15,10] = 0100 01
4834 unsigned full
= INSTR (30, 30);
4835 unsigned vm
= INSTR (20, 16);
4836 unsigned vn
= INSTR (9, 5);
4837 unsigned vd
= INSTR (4, 0);
4841 NYI_assert (29, 24, 0x2E);
4842 NYI_assert (15, 10, 0x11);
4844 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4845 switch (INSTR (23, 22))
4848 for (i
= 0; i
< (full
? 16 : 8); i
++)
4850 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
);
4852 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vn
, i
)
4855 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vn
, i
)
4861 for (i
= 0; i
< (full
? 8 : 4); i
++)
4863 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 2);
4865 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vn
, i
)
4868 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vn
, i
)
4874 for (i
= 0; i
< (full
? 4 : 2); i
++)
4876 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 4);
4878 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vn
, i
)
4881 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vn
, i
)
4889 for (i
= 0; i
< 2; i
++)
4891 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 8);
4893 aarch64_set_vec_u64 (cpu
, vd
, i
, aarch64_get_vec_u64 (cpu
, vn
, i
)
4896 aarch64_set_vec_u64 (cpu
, vd
, i
, aarch64_get_vec_u64 (cpu
, vn
, i
)
4904 do_vec_FMLA (sim_cpu
*cpu
)
4907 instr[30] = full/half selector
4908 instr[29,23] = 0011100
4909 instr[22] = size: 0=>float, 1=>double
4912 instr[15,10] = 1100 11
4916 unsigned vm
= INSTR (20, 16);
4917 unsigned vn
= INSTR (9, 5);
4918 unsigned vd
= INSTR (4, 0);
4920 int full
= INSTR (30, 30);
4922 NYI_assert (29, 23, 0x1C);
4923 NYI_assert (21, 21, 1);
4924 NYI_assert (15, 10, 0x33);
4926 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4931 for (i
= 0; i
< 2; i
++)
4932 aarch64_set_vec_double (cpu
, vd
, i
,
4933 aarch64_get_vec_double (cpu
, vn
, i
) *
4934 aarch64_get_vec_double (cpu
, vm
, i
) +
4935 aarch64_get_vec_double (cpu
, vd
, i
));
4939 for (i
= 0; i
< (full
? 4 : 2); i
++)
4940 aarch64_set_vec_float (cpu
, vd
, i
,
4941 aarch64_get_vec_float (cpu
, vn
, i
) *
4942 aarch64_get_vec_float (cpu
, vm
, i
) +
4943 aarch64_get_vec_float (cpu
, vd
, i
));
4948 do_vec_max (sim_cpu
*cpu
)
4951 instr[30] = full/half selector
4952 instr[29] = SMAX (0) / UMAX (1)
4953 instr[28,24] = 0 1110
4954 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
4957 instr[15,10] = 0110 01
4961 unsigned vm
= INSTR (20, 16);
4962 unsigned vn
= INSTR (9, 5);
4963 unsigned vd
= INSTR (4, 0);
4965 int full
= INSTR (30, 30);
4967 NYI_assert (28, 24, 0x0E);
4968 NYI_assert (21, 21, 1);
4969 NYI_assert (15, 10, 0x19);
4971 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4974 switch (INSTR (23, 22))
4977 for (i
= 0; i
< (full
? 16 : 8); i
++)
4978 aarch64_set_vec_u8 (cpu
, vd
, i
,
4979 aarch64_get_vec_u8 (cpu
, vn
, i
)
4980 > aarch64_get_vec_u8 (cpu
, vm
, i
)
4981 ? aarch64_get_vec_u8 (cpu
, vn
, i
)
4982 : aarch64_get_vec_u8 (cpu
, vm
, i
));
4986 for (i
= 0; i
< (full
? 8 : 4); i
++)
4987 aarch64_set_vec_u16 (cpu
, vd
, i
,
4988 aarch64_get_vec_u16 (cpu
, vn
, i
)
4989 > aarch64_get_vec_u16 (cpu
, vm
, i
)
4990 ? aarch64_get_vec_u16 (cpu
, vn
, i
)
4991 : aarch64_get_vec_u16 (cpu
, vm
, i
));
4995 for (i
= 0; i
< (full
? 4 : 2); i
++)
4996 aarch64_set_vec_u32 (cpu
, vd
, i
,
4997 aarch64_get_vec_u32 (cpu
, vn
, i
)
4998 > aarch64_get_vec_u32 (cpu
, vm
, i
)
4999 ? aarch64_get_vec_u32 (cpu
, vn
, i
)
5000 : aarch64_get_vec_u32 (cpu
, vm
, i
));
5009 switch (INSTR (23, 22))
5012 for (i
= 0; i
< (full
? 16 : 8); i
++)
5013 aarch64_set_vec_s8 (cpu
, vd
, i
,
5014 aarch64_get_vec_s8 (cpu
, vn
, i
)
5015 > aarch64_get_vec_s8 (cpu
, vm
, i
)
5016 ? aarch64_get_vec_s8 (cpu
, vn
, i
)
5017 : aarch64_get_vec_s8 (cpu
, vm
, i
));
5021 for (i
= 0; i
< (full
? 8 : 4); i
++)
5022 aarch64_set_vec_s16 (cpu
, vd
, i
,
5023 aarch64_get_vec_s16 (cpu
, vn
, i
)
5024 > aarch64_get_vec_s16 (cpu
, vm
, i
)
5025 ? aarch64_get_vec_s16 (cpu
, vn
, i
)
5026 : aarch64_get_vec_s16 (cpu
, vm
, i
));
5030 for (i
= 0; i
< (full
? 4 : 2); i
++)
5031 aarch64_set_vec_s32 (cpu
, vd
, i
,
5032 aarch64_get_vec_s32 (cpu
, vn
, i
)
5033 > aarch64_get_vec_s32 (cpu
, vm
, i
)
5034 ? aarch64_get_vec_s32 (cpu
, vn
, i
)
5035 : aarch64_get_vec_s32 (cpu
, vm
, i
));
5045 do_vec_min (sim_cpu
*cpu
)
5048 instr[30] = full/half selector
5049 instr[29] = SMIN (0) / UMIN (1)
5050 instr[28,24] = 0 1110
5051 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
5054 instr[15,10] = 0110 11
5058 unsigned vm
= INSTR (20, 16);
5059 unsigned vn
= INSTR (9, 5);
5060 unsigned vd
= INSTR (4, 0);
5062 int full
= INSTR (30, 30);
5064 NYI_assert (28, 24, 0x0E);
5065 NYI_assert (21, 21, 1);
5066 NYI_assert (15, 10, 0x1B);
5068 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5071 switch (INSTR (23, 22))
5074 for (i
= 0; i
< (full
? 16 : 8); i
++)
5075 aarch64_set_vec_u8 (cpu
, vd
, i
,
5076 aarch64_get_vec_u8 (cpu
, vn
, i
)
5077 < aarch64_get_vec_u8 (cpu
, vm
, i
)
5078 ? aarch64_get_vec_u8 (cpu
, vn
, i
)
5079 : aarch64_get_vec_u8 (cpu
, vm
, i
));
5083 for (i
= 0; i
< (full
? 8 : 4); i
++)
5084 aarch64_set_vec_u16 (cpu
, vd
, i
,
5085 aarch64_get_vec_u16 (cpu
, vn
, i
)
5086 < aarch64_get_vec_u16 (cpu
, vm
, i
)
5087 ? aarch64_get_vec_u16 (cpu
, vn
, i
)
5088 : aarch64_get_vec_u16 (cpu
, vm
, i
));
5092 for (i
= 0; i
< (full
? 4 : 2); i
++)
5093 aarch64_set_vec_u32 (cpu
, vd
, i
,
5094 aarch64_get_vec_u32 (cpu
, vn
, i
)
5095 < aarch64_get_vec_u32 (cpu
, vm
, i
)
5096 ? aarch64_get_vec_u32 (cpu
, vn
, i
)
5097 : aarch64_get_vec_u32 (cpu
, vm
, i
));
5106 switch (INSTR (23, 22))
5109 for (i
= 0; i
< (full
? 16 : 8); i
++)
5110 aarch64_set_vec_s8 (cpu
, vd
, i
,
5111 aarch64_get_vec_s8 (cpu
, vn
, i
)
5112 < aarch64_get_vec_s8 (cpu
, vm
, i
)
5113 ? aarch64_get_vec_s8 (cpu
, vn
, i
)
5114 : aarch64_get_vec_s8 (cpu
, vm
, i
));
5118 for (i
= 0; i
< (full
? 8 : 4); i
++)
5119 aarch64_set_vec_s16 (cpu
, vd
, i
,
5120 aarch64_get_vec_s16 (cpu
, vn
, i
)
5121 < aarch64_get_vec_s16 (cpu
, vm
, i
)
5122 ? aarch64_get_vec_s16 (cpu
, vn
, i
)
5123 : aarch64_get_vec_s16 (cpu
, vm
, i
));
5127 for (i
= 0; i
< (full
? 4 : 2); i
++)
5128 aarch64_set_vec_s32 (cpu
, vd
, i
,
5129 aarch64_get_vec_s32 (cpu
, vn
, i
)
5130 < aarch64_get_vec_s32 (cpu
, vm
, i
)
5131 ? aarch64_get_vec_s32 (cpu
, vn
, i
)
5132 : aarch64_get_vec_s32 (cpu
, vm
, i
));
5142 do_vec_sub_long (sim_cpu
*cpu
)
5145 instr[30] = lower (0) / upper (1)
5146 instr[29] = signed (0) / unsigned (1)
5147 instr[28,24] = 0 1110
5148 instr[23,22] = size: bytes (00), half (01), word (10)
5151 instr[15,10] = 0010 00
5153 instr[4,0] = V dest. */
5155 unsigned size
= INSTR (23, 22);
5156 unsigned vm
= INSTR (20, 16);
5157 unsigned vn
= INSTR (9, 5);
5158 unsigned vd
= INSTR (4, 0);
5162 NYI_assert (28, 24, 0x0E);
5163 NYI_assert (21, 21, 1);
5164 NYI_assert (15, 10, 0x08);
5169 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5170 switch (INSTR (30, 29))
5172 case 2: /* SSUBL2. */
5174 case 0: /* SSUBL. */
5179 for (i
= 0; i
< 8; i
++)
5180 aarch64_set_vec_s16 (cpu
, vd
, i
,
5181 aarch64_get_vec_s8 (cpu
, vn
, i
+ bias
)
5182 - aarch64_get_vec_s8 (cpu
, vm
, i
+ bias
));
5187 for (i
= 0; i
< 4; i
++)
5188 aarch64_set_vec_s32 (cpu
, vd
, i
,
5189 aarch64_get_vec_s16 (cpu
, vn
, i
+ bias
)
5190 - aarch64_get_vec_s16 (cpu
, vm
, i
+ bias
));
5194 for (i
= 0; i
< 2; i
++)
5195 aarch64_set_vec_s64 (cpu
, vd
, i
,
5196 aarch64_get_vec_s32 (cpu
, vn
, i
+ bias
)
5197 - aarch64_get_vec_s32 (cpu
, vm
, i
+ bias
));
5205 case 3: /* USUBL2. */
5207 case 1: /* USUBL. */
5212 for (i
= 0; i
< 8; i
++)
5213 aarch64_set_vec_u16 (cpu
, vd
, i
,
5214 aarch64_get_vec_u8 (cpu
, vn
, i
+ bias
)
5215 - aarch64_get_vec_u8 (cpu
, vm
, i
+ bias
));
5220 for (i
= 0; i
< 4; i
++)
5221 aarch64_set_vec_u32 (cpu
, vd
, i
,
5222 aarch64_get_vec_u16 (cpu
, vn
, i
+ bias
)
5223 - aarch64_get_vec_u16 (cpu
, vm
, i
+ bias
));
5227 for (i
= 0; i
< 2; i
++)
5228 aarch64_set_vec_u64 (cpu
, vd
, i
,
5229 aarch64_get_vec_u32 (cpu
, vn
, i
+ bias
)
5230 - aarch64_get_vec_u32 (cpu
, vm
, i
+ bias
));
5241 do_vec_ADDP (sim_cpu
*cpu
)
5244 instr[30] = half(0)/full(1)
5245 instr[29,24] = 00 1110
5246 instr[23,22] = size: bytes (00), half (01), word (10), long (11)
5249 instr[15,10] = 1011 11
5251 instr[4,0] = V dest. */
5255 unsigned full
= INSTR (30, 30);
5256 unsigned size
= INSTR (23, 22);
5257 unsigned vm
= INSTR (20, 16);
5258 unsigned vn
= INSTR (9, 5);
5259 unsigned vd
= INSTR (4, 0);
5262 NYI_assert (29, 24, 0x0E);
5263 NYI_assert (21, 21, 1);
5264 NYI_assert (15, 10, 0x2F);
5266 /* Make copies of the source registers in case vd == vn/vm. */
5267 copy_vn
= cpu
->fr
[vn
];
5268 copy_vm
= cpu
->fr
[vm
];
5270 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5274 range
= full
? 8 : 4;
5275 for (i
= 0; i
< range
; i
++)
5277 aarch64_set_vec_u8 (cpu
, vd
, i
,
5278 copy_vn
.b
[i
* 2] + copy_vn
.b
[i
* 2 + 1]);
5279 aarch64_set_vec_u8 (cpu
, vd
, i
+ range
,
5280 copy_vm
.b
[i
* 2] + copy_vm
.b
[i
* 2 + 1]);
5285 range
= full
? 4 : 2;
5286 for (i
= 0; i
< range
; i
++)
5288 aarch64_set_vec_u16 (cpu
, vd
, i
,
5289 copy_vn
.h
[i
* 2] + copy_vn
.h
[i
* 2 + 1]);
5290 aarch64_set_vec_u16 (cpu
, vd
, i
+ range
,
5291 copy_vm
.h
[i
* 2] + copy_vm
.h
[i
* 2 + 1]);
5296 range
= full
? 2 : 1;
5297 for (i
= 0; i
< range
; i
++)
5299 aarch64_set_vec_u32 (cpu
, vd
, i
,
5300 copy_vn
.w
[i
* 2] + copy_vn
.w
[i
* 2 + 1]);
5301 aarch64_set_vec_u32 (cpu
, vd
, i
+ range
,
5302 copy_vm
.w
[i
* 2] + copy_vm
.w
[i
* 2 + 1]);
5309 aarch64_set_vec_u64 (cpu
, vd
, 0, copy_vn
.v
[0] + copy_vn
.v
[1]);
5310 aarch64_set_vec_u64 (cpu
, vd
, 1, copy_vm
.v
[0] + copy_vm
.v
[1]);
5316 do_vec_UMOV (sim_cpu
*cpu
)
5319 instr[30] = 32-bit(0)/64-bit(1)
5320 instr[29,21] = 00 1110 000
5321 insrt[20,16] = size & index
5322 instr[15,10] = 0011 11
5323 instr[9,5] = V source
5324 instr[4,0] = R dest. */
5326 unsigned vs
= INSTR (9, 5);
5327 unsigned rd
= INSTR (4, 0);
5330 NYI_assert (29, 21, 0x070);
5331 NYI_assert (15, 10, 0x0F);
5333 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5336 /* Byte transfer. */
5337 index
= INSTR (20, 17);
5338 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
5339 aarch64_get_vec_u8 (cpu
, vs
, index
));
5341 else if (INSTR (17, 17))
5343 index
= INSTR (20, 18);
5344 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
5345 aarch64_get_vec_u16 (cpu
, vs
, index
));
5347 else if (INSTR (18, 18))
5349 index
= INSTR (20, 19);
5350 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
5351 aarch64_get_vec_u32 (cpu
, vs
, index
));
5355 if (INSTR (30, 30) != 1)
5358 index
= INSTR (20, 20);
5359 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
5360 aarch64_get_vec_u64 (cpu
, vs
, index
));
5365 do_vec_FABS (sim_cpu
*cpu
)
5368 instr[30] = half(0)/full(1)
5369 instr[29,23] = 00 1110 1
5370 instr[22] = float(0)/double(1)
5371 instr[21,16] = 10 0000
5372 instr[15,10] = 1111 10
5376 unsigned vn
= INSTR (9, 5);
5377 unsigned vd
= INSTR (4, 0);
5378 unsigned full
= INSTR (30, 30);
5381 NYI_assert (29, 23, 0x1D);
5382 NYI_assert (21, 10, 0x83E);
5384 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5390 for (i
= 0; i
< 2; i
++)
5391 aarch64_set_vec_double (cpu
, vd
, i
,
5392 fabs (aarch64_get_vec_double (cpu
, vn
, i
)));
5396 for (i
= 0; i
< (full
? 4 : 2); i
++)
5397 aarch64_set_vec_float (cpu
, vd
, i
,
5398 fabsf (aarch64_get_vec_float (cpu
, vn
, i
)));
5403 do_vec_FCVTZS (sim_cpu
*cpu
)
5406 instr[30] = half (0) / all (1)
5407 instr[29,23] = 00 1110 1
5408 instr[22] = single (0) / double (1)
5409 instr[21,10] = 10 0001 1011 10
5413 unsigned rn
= INSTR (9, 5);
5414 unsigned rd
= INSTR (4, 0);
5415 unsigned full
= INSTR (30, 30);
5418 NYI_assert (31, 31, 0);
5419 NYI_assert (29, 23, 0x1D);
5420 NYI_assert (21, 10, 0x86E);
5422 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5428 for (i
= 0; i
< 2; i
++)
5429 aarch64_set_vec_s64 (cpu
, rd
, i
,
5430 (int64_t) aarch64_get_vec_double (cpu
, rn
, i
));
5433 for (i
= 0; i
< (full
? 4 : 2); i
++)
5434 aarch64_set_vec_s32 (cpu
, rd
, i
,
5435 (int32_t) aarch64_get_vec_float (cpu
, rn
, i
));
5439 do_vec_REV64 (sim_cpu
*cpu
)
5442 instr[30] = full/half
5443 instr[29,24] = 00 1110
5445 instr[21,10] = 10 0000 0000 10
5449 unsigned rn
= INSTR (9, 5);
5450 unsigned rd
= INSTR (4, 0);
5451 unsigned size
= INSTR (23, 22);
5452 unsigned full
= INSTR (30, 30);
5456 NYI_assert (29, 24, 0x0E);
5457 NYI_assert (21, 10, 0x802);
5459 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5463 for (i
= 0; i
< (full
? 16 : 8); i
++)
5464 val
.b
[i
^ 0x7] = aarch64_get_vec_u8 (cpu
, rn
, i
);
5468 for (i
= 0; i
< (full
? 8 : 4); i
++)
5469 val
.h
[i
^ 0x3] = aarch64_get_vec_u16 (cpu
, rn
, i
);
5473 for (i
= 0; i
< (full
? 4 : 2); i
++)
5474 val
.w
[i
^ 0x1] = aarch64_get_vec_u32 (cpu
, rn
, i
);
5481 aarch64_set_vec_u64 (cpu
, rd
, 0, val
.v
[0]);
5483 aarch64_set_vec_u64 (cpu
, rd
, 1, val
.v
[1]);
5487 do_vec_REV16 (sim_cpu
*cpu
)
5490 instr[30] = full/half
5491 instr[29,24] = 00 1110
5493 instr[21,10] = 10 0000 0001 10
5497 unsigned rn
= INSTR (9, 5);
5498 unsigned rd
= INSTR (4, 0);
5499 unsigned size
= INSTR (23, 22);
5500 unsigned full
= INSTR (30, 30);
5504 NYI_assert (29, 24, 0x0E);
5505 NYI_assert (21, 10, 0x806);
5507 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5511 for (i
= 0; i
< (full
? 16 : 8); i
++)
5512 val
.b
[i
^ 0x1] = aarch64_get_vec_u8 (cpu
, rn
, i
);
5519 aarch64_set_vec_u64 (cpu
, rd
, 0, val
.v
[0]);
5521 aarch64_set_vec_u64 (cpu
, rd
, 1, val
.v
[1]);
5525 do_vec_op1 (sim_cpu
*cpu
)
5528 instr[30] = half/full
5529 instr[29,24] = 00 1110
5532 instr[15,10] = sub-opcode
5535 NYI_assert (29, 24, 0x0E);
5537 if (INSTR (21, 21) == 0)
5539 if (INSTR (23, 22) == 0)
5541 if (INSTR (30, 30) == 1
5542 && INSTR (17, 14) == 0
5543 && INSTR (12, 10) == 7)
5544 return do_vec_ins_2 (cpu
);
5546 switch (INSTR (15, 10))
5548 case 0x01: do_vec_DUP_vector_into_vector (cpu
); return;
5549 case 0x03: do_vec_DUP_scalar_into_vector (cpu
); return;
5550 case 0x07: do_vec_INS (cpu
); return;
5551 case 0x0A: do_vec_TRN (cpu
); return;
5554 if (INSTR (17, 16) == 0)
5556 do_vec_MOV_into_scalar (cpu
);
5565 do_vec_TBL (cpu
); return;
5569 do_vec_UZP (cpu
); return;
5573 do_vec_ZIP (cpu
); return;
5580 switch (INSTR (13, 10))
5582 case 0x6: do_vec_UZP (cpu
); return;
5583 case 0xE: do_vec_ZIP (cpu
); return;
5584 case 0xA: do_vec_TRN (cpu
); return;
5585 case 0xF: do_vec_UMOV (cpu
); return;
5590 switch (INSTR (15, 10))
5592 case 0x02: do_vec_REV64 (cpu
); return;
5593 case 0x06: do_vec_REV16 (cpu
); return;
5596 switch (INSTR (23, 21))
5598 case 1: do_vec_AND (cpu
); return;
5599 case 3: do_vec_BIC (cpu
); return;
5600 case 5: do_vec_ORR (cpu
); return;
5601 case 7: do_vec_ORN (cpu
); return;
5605 case 0x08: do_vec_sub_long (cpu
); return;
5606 case 0x0a: do_vec_XTN (cpu
); return;
5607 case 0x11: do_vec_SSHL (cpu
); return;
5608 case 0x19: do_vec_max (cpu
); return;
5609 case 0x1B: do_vec_min (cpu
); return;
5610 case 0x21: do_vec_add (cpu
); return;
5611 case 0x25: do_vec_MLA (cpu
); return;
5612 case 0x27: do_vec_mul (cpu
); return;
5613 case 0x2F: do_vec_ADDP (cpu
); return;
5614 case 0x30: do_vec_mull (cpu
); return;
5615 case 0x33: do_vec_FMLA (cpu
); return;
5616 case 0x35: do_vec_fadd (cpu
); return;
5619 switch (INSTR (20, 16))
5621 case 0x00: do_vec_ABS (cpu
); return;
5622 case 0x01: do_vec_FCVTZS (cpu
); return;
5623 case 0x11: do_vec_ADDV (cpu
); return;
5629 do_vec_Fminmax (cpu
); return;
5641 do_vec_compare (cpu
); return;
5644 do_vec_FABS (cpu
); return;
5652 do_vec_xtl (sim_cpu
*cpu
)
5655 instr[30,29] = SXTL (00), UXTL (01), SXTL2 (10), UXTL2 (11)
5656 instr[28,22] = 0 1111 00
5657 instr[21,16] = size & shift (USHLL, SSHLL, USHLL2, SSHLL2)
5658 instr[15,10] = 1010 01
5659 instr[9,5] = V source
5660 instr[4,0] = V dest. */
5662 unsigned vs
= INSTR (9, 5);
5663 unsigned vd
= INSTR (4, 0);
5664 unsigned i
, shift
, bias
= 0;
5666 NYI_assert (28, 22, 0x3C);
5667 NYI_assert (15, 10, 0x29);
5669 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5670 switch (INSTR (30, 29))
5672 case 2: /* SXTL2, SSHLL2. */
5674 case 0: /* SXTL, SSHLL. */
5679 shift
= INSTR (20, 16);
5680 /* Get the source values before setting the destination values
5681 in case the source and destination are the same. */
5682 val1
= aarch64_get_vec_s32 (cpu
, vs
, bias
) << shift
;
5683 val2
= aarch64_get_vec_s32 (cpu
, vs
, bias
+ 1) << shift
;
5684 aarch64_set_vec_s64 (cpu
, vd
, 0, val1
);
5685 aarch64_set_vec_s64 (cpu
, vd
, 1, val2
);
5687 else if (INSTR (20, 20))
5690 int32_t v1
,v2
,v3
,v4
;
5692 shift
= INSTR (19, 16);
5694 for (i
= 0; i
< 4; i
++)
5695 v
[i
] = aarch64_get_vec_s16 (cpu
, vs
, bias
+ i
) << shift
;
5696 for (i
= 0; i
< 4; i
++)
5697 aarch64_set_vec_s32 (cpu
, vd
, i
, v
[i
]);
5702 NYI_assert (19, 19, 1);
5704 shift
= INSTR (18, 16);
5706 for (i
= 0; i
< 8; i
++)
5707 v
[i
] = aarch64_get_vec_s8 (cpu
, vs
, i
+ bias
) << shift
;
5708 for (i
= 0; i
< 8; i
++)
5709 aarch64_set_vec_s16 (cpu
, vd
, i
, v
[i
]);
5713 case 3: /* UXTL2, USHLL2. */
5715 case 1: /* UXTL, USHLL. */
5719 shift
= INSTR (20, 16);
5720 v1
= aarch64_get_vec_u32 (cpu
, vs
, bias
) << shift
;
5721 v2
= aarch64_get_vec_u32 (cpu
, vs
, bias
+ 1) << shift
;
5722 aarch64_set_vec_u64 (cpu
, vd
, 0, v1
);
5723 aarch64_set_vec_u64 (cpu
, vd
, 1, v2
);
5725 else if (INSTR (20, 20))
5728 shift
= INSTR (19, 16);
5730 for (i
= 0; i
< 4; i
++)
5731 v
[i
] = aarch64_get_vec_u16 (cpu
, vs
, i
+ bias
) << shift
;
5732 for (i
= 0; i
< 4; i
++)
5733 aarch64_set_vec_u32 (cpu
, vd
, i
, v
[i
]);
5738 NYI_assert (19, 19, 1);
5740 shift
= INSTR (18, 16);
5742 for (i
= 0; i
< 8; i
++)
5743 v
[i
] = aarch64_get_vec_u8 (cpu
, vs
, i
+ bias
) << shift
;
5744 for (i
= 0; i
< 8; i
++)
5745 aarch64_set_vec_u16 (cpu
, vd
, i
, v
[i
]);
5752 do_vec_SHL (sim_cpu
*cpu
)
5755 instr [30] = half(0)/full(1)
5756 instr [29,23] = 001 1110
5757 instr [22,16] = size and shift amount
5758 instr [15,10] = 01 0101
5760 instr [4, 0] = Vd. */
5763 int full
= INSTR (30, 30);
5764 unsigned vs
= INSTR (9, 5);
5765 unsigned vd
= INSTR (4, 0);
5768 NYI_assert (29, 23, 0x1E);
5769 NYI_assert (15, 10, 0x15);
5771 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5774 shift
= INSTR (21, 16);
5779 for (i
= 0; i
< 2; i
++)
5781 uint64_t val
= aarch64_get_vec_u64 (cpu
, vs
, i
);
5782 aarch64_set_vec_u64 (cpu
, vd
, i
, val
<< shift
);
5790 shift
= INSTR (20, 16);
5792 for (i
= 0; i
< (full
? 4 : 2); i
++)
5794 uint32_t val
= aarch64_get_vec_u32 (cpu
, vs
, i
);
5795 aarch64_set_vec_u32 (cpu
, vd
, i
, val
<< shift
);
5803 shift
= INSTR (19, 16);
5805 for (i
= 0; i
< (full
? 8 : 4); i
++)
5807 uint16_t val
= aarch64_get_vec_u16 (cpu
, vs
, i
);
5808 aarch64_set_vec_u16 (cpu
, vd
, i
, val
<< shift
);
5814 if (INSTR (19, 19) == 0)
5817 shift
= INSTR (18, 16);
5819 for (i
= 0; i
< (full
? 16 : 8); i
++)
5821 uint8_t val
= aarch64_get_vec_u8 (cpu
, vs
, i
);
5822 aarch64_set_vec_u8 (cpu
, vd
, i
, val
<< shift
);
5827 do_vec_SSHR_USHR (sim_cpu
*cpu
)
5830 instr [30] = half(0)/full(1)
5831 instr [29] = signed(0)/unsigned(1)
5832 instr [28,23] = 0 1111 0
5833 instr [22,16] = size and shift amount
5834 instr [15,10] = 0000 01
5836 instr [4, 0] = Vd. */
5838 int full
= INSTR (30, 30);
5839 int sign
= ! INSTR (29, 29);
5840 unsigned shift
= INSTR (22, 16);
5841 unsigned vs
= INSTR (9, 5);
5842 unsigned vd
= INSTR (4, 0);
5845 NYI_assert (28, 23, 0x1E);
5846 NYI_assert (15, 10, 0x01);
5848 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5851 shift
= 128 - shift
;
5857 for (i
= 0; i
< 2; i
++)
5859 int64_t val
= aarch64_get_vec_s64 (cpu
, vs
, i
);
5860 aarch64_set_vec_s64 (cpu
, vd
, i
, val
>> shift
);
5863 for (i
= 0; i
< 2; i
++)
5865 uint64_t val
= aarch64_get_vec_u64 (cpu
, vs
, i
);
5866 aarch64_set_vec_u64 (cpu
, vd
, i
, val
>> shift
);
5877 for (i
= 0; i
< (full
? 4 : 2); i
++)
5879 int32_t val
= aarch64_get_vec_s32 (cpu
, vs
, i
);
5880 aarch64_set_vec_s32 (cpu
, vd
, i
, val
>> shift
);
5883 for (i
= 0; i
< (full
? 4 : 2); i
++)
5885 uint32_t val
= aarch64_get_vec_u32 (cpu
, vs
, i
);
5886 aarch64_set_vec_u32 (cpu
, vd
, i
, val
>> shift
);
5897 for (i
= 0; i
< (full
? 8 : 4); i
++)
5899 int16_t val
= aarch64_get_vec_s16 (cpu
, vs
, i
);
5900 aarch64_set_vec_s16 (cpu
, vd
, i
, val
>> shift
);
5903 for (i
= 0; i
< (full
? 8 : 4); i
++)
5905 uint16_t val
= aarch64_get_vec_u16 (cpu
, vs
, i
);
5906 aarch64_set_vec_u16 (cpu
, vd
, i
, val
>> shift
);
5912 if (INSTR (19, 19) == 0)
5918 for (i
= 0; i
< (full
? 16 : 8); i
++)
5920 int8_t val
= aarch64_get_vec_s8 (cpu
, vs
, i
);
5921 aarch64_set_vec_s8 (cpu
, vd
, i
, val
>> shift
);
5924 for (i
= 0; i
< (full
? 16 : 8); i
++)
5926 uint8_t val
= aarch64_get_vec_u8 (cpu
, vs
, i
);
5927 aarch64_set_vec_u8 (cpu
, vd
, i
, val
>> shift
);
5932 do_vec_MUL_by_element (sim_cpu
*cpu
)
5935 instr[30] = half/full
5936 instr[29,24] = 00 1111
5947 unsigned full
= INSTR (30, 30);
5948 unsigned L
= INSTR (21, 21);
5949 unsigned H
= INSTR (11, 11);
5950 unsigned vn
= INSTR (9, 5);
5951 unsigned vd
= INSTR (4, 0);
5952 unsigned size
= INSTR (23, 22);
5957 NYI_assert (29, 24, 0x0F);
5958 NYI_assert (15, 12, 0x8);
5959 NYI_assert (10, 10, 0);
5961 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5966 /* 16 bit products. */
5971 index
= (H
<< 2) | (L
<< 1) | INSTR (20, 20);
5972 vm
= INSTR (19, 16);
5973 element2
= aarch64_get_vec_u16 (cpu
, vm
, index
);
5975 for (e
= 0; e
< (full
? 8 : 4); e
++)
5977 element1
= aarch64_get_vec_u16 (cpu
, vn
, e
);
5978 product
= element1
* element2
;
5979 aarch64_set_vec_u16 (cpu
, vd
, e
, product
);
5986 /* 32 bit products. */
5991 index
= (H
<< 1) | L
;
5992 vm
= INSTR (20, 16);
5993 element2
= aarch64_get_vec_u32 (cpu
, vm
, index
);
5995 for (e
= 0; e
< (full
? 4 : 2); e
++)
5997 element1
= aarch64_get_vec_u32 (cpu
, vn
, e
);
5998 product
= element1
* element2
;
5999 aarch64_set_vec_u32 (cpu
, vd
, e
, product
);
6010 do_FMLA_by_element (sim_cpu
*cpu
)
6013 instr[30] = half/full
6014 instr[29,23] = 00 1111 1
6024 unsigned full
= INSTR (30, 30);
6025 unsigned size
= INSTR (22, 22);
6026 unsigned L
= INSTR (21, 21);
6027 unsigned vm
= INSTR (20, 16);
6028 unsigned H
= INSTR (11, 11);
6029 unsigned vn
= INSTR (9, 5);
6030 unsigned vd
= INSTR (4, 0);
6033 NYI_assert (29, 23, 0x1F);
6034 NYI_assert (15, 12, 0x1);
6035 NYI_assert (10, 10, 0);
6037 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6040 double element1
, element2
;
6045 element2
= aarch64_get_vec_double (cpu
, vm
, H
);
6047 for (e
= 0; e
< 2; e
++)
6049 element1
= aarch64_get_vec_double (cpu
, vn
, e
);
6050 element1
*= element2
;
6051 element1
+= aarch64_get_vec_double (cpu
, vd
, e
);
6052 aarch64_set_vec_double (cpu
, vd
, e
, element1
);
6058 float element2
= aarch64_get_vec_float (cpu
, vm
, (H
<< 1) | L
);
6060 for (e
= 0; e
< (full
? 4 : 2); e
++)
6062 element1
= aarch64_get_vec_float (cpu
, vn
, e
);
6063 element1
*= element2
;
6064 element1
+= aarch64_get_vec_float (cpu
, vd
, e
);
6065 aarch64_set_vec_float (cpu
, vd
, e
, element1
);
6071 do_vec_op2 (sim_cpu
*cpu
)
6074 instr[30] = half/full
6075 instr[29,24] = 00 1111
6077 instr[22,16] = element size & index
6078 instr[15,10] = sub-opcode
6082 NYI_assert (29, 24, 0x0F);
6084 if (INSTR (23, 23) != 0)
6086 switch (INSTR (15, 10))
6090 do_FMLA_by_element (cpu
);
6095 do_vec_MUL_by_element (cpu
);
6104 switch (INSTR (15, 10))
6106 case 0x01: do_vec_SSHR_USHR (cpu
); return;
6107 case 0x15: do_vec_SHL (cpu
); return;
6109 case 0x22: do_vec_MUL_by_element (cpu
); return;
6110 case 0x29: do_vec_xtl (cpu
); return;
6117 do_vec_neg (sim_cpu
*cpu
)
6120 instr[30] = full(1)/half(0)
6121 instr[29,24] = 10 1110
6122 instr[23,22] = size: byte(00), half (01), word (10), long (11)
6123 instr[21,10] = 1000 0010 1110
6127 int full
= INSTR (30, 30);
6128 unsigned vs
= INSTR (9, 5);
6129 unsigned vd
= INSTR (4, 0);
6132 NYI_assert (29, 24, 0x2E);
6133 NYI_assert (21, 10, 0x82E);
6135 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6136 switch (INSTR (23, 22))
6139 for (i
= 0; i
< (full
? 16 : 8); i
++)
6140 aarch64_set_vec_s8 (cpu
, vd
, i
, - aarch64_get_vec_s8 (cpu
, vs
, i
));
6144 for (i
= 0; i
< (full
? 8 : 4); i
++)
6145 aarch64_set_vec_s16 (cpu
, vd
, i
, - aarch64_get_vec_s16 (cpu
, vs
, i
));
6149 for (i
= 0; i
< (full
? 4 : 2); i
++)
6150 aarch64_set_vec_s32 (cpu
, vd
, i
, - aarch64_get_vec_s32 (cpu
, vs
, i
));
6156 for (i
= 0; i
< 2; i
++)
6157 aarch64_set_vec_s64 (cpu
, vd
, i
, - aarch64_get_vec_s64 (cpu
, vs
, i
));
6163 do_vec_sqrt (sim_cpu
*cpu
)
6166 instr[30] = full(1)/half(0)
6167 instr[29,23] = 101 1101
6168 instr[22] = single(0)/double(1)
6169 instr[21,10] = 1000 0111 1110
6173 int full
= INSTR (30, 30);
6174 unsigned vs
= INSTR (9, 5);
6175 unsigned vd
= INSTR (4, 0);
6178 NYI_assert (29, 23, 0x5B);
6179 NYI_assert (21, 10, 0x87E);
6181 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6182 if (INSTR (22, 22) == 0)
6183 for (i
= 0; i
< (full
? 4 : 2); i
++)
6184 aarch64_set_vec_float (cpu
, vd
, i
,
6185 sqrtf (aarch64_get_vec_float (cpu
, vs
, i
)));
6187 for (i
= 0; i
< 2; i
++)
6188 aarch64_set_vec_double (cpu
, vd
, i
,
6189 sqrt (aarch64_get_vec_double (cpu
, vs
, i
)));
6193 do_vec_mls_indexed (sim_cpu
*cpu
)
6196 instr[30] = half(0)/full(1)
6197 instr[29,24] = 10 1111
6198 instr[23,22] = 16-bit(01)/32-bit(10)
6199 instr[21,20+11] = index (if 16-bit)
6200 instr[21+11] = index (if 32-bit)
6203 instr[11] = part of index
6208 int full
= INSTR (30, 30);
6209 unsigned vs
= INSTR (9, 5);
6210 unsigned vd
= INSTR (4, 0);
6211 unsigned vm
= INSTR (20, 16);
6214 NYI_assert (15, 12, 4);
6215 NYI_assert (10, 10, 0);
6217 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6218 switch (INSTR (23, 22))
6228 elem
= (INSTR (21, 20) << 1) | INSTR (11, 11);
6229 val
= aarch64_get_vec_u16 (cpu
, vm
, elem
);
6231 for (i
= 0; i
< (full
? 8 : 4); i
++)
6232 aarch64_set_vec_u32 (cpu
, vd
, i
,
6233 aarch64_get_vec_u32 (cpu
, vd
, i
) -
6234 (aarch64_get_vec_u32 (cpu
, vs
, i
) * val
));
6240 unsigned elem
= (INSTR (21, 21) << 1) | INSTR (11, 11);
6241 uint64_t val
= aarch64_get_vec_u32 (cpu
, vm
, elem
);
6243 for (i
= 0; i
< (full
? 4 : 2); i
++)
6244 aarch64_set_vec_u64 (cpu
, vd
, i
,
6245 aarch64_get_vec_u64 (cpu
, vd
, i
) -
6246 (aarch64_get_vec_u64 (cpu
, vs
, i
) * val
));
6258 do_vec_SUB (sim_cpu
*cpu
)
6261 instr [30] = half(0)/full(1)
6262 instr [29,24] = 10 1110
6263 instr [23,22] = size: byte(00, half(01), word (10), long (11)
6266 instr [15,10] = 10 0001
6268 instr [4, 0] = Vd. */
6270 unsigned full
= INSTR (30, 30);
6271 unsigned vm
= INSTR (20, 16);
6272 unsigned vn
= INSTR (9, 5);
6273 unsigned vd
= INSTR (4, 0);
6276 NYI_assert (29, 24, 0x2E);
6277 NYI_assert (21, 21, 1);
6278 NYI_assert (15, 10, 0x21);
6280 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6281 switch (INSTR (23, 22))
6284 for (i
= 0; i
< (full
? 16 : 8); i
++)
6285 aarch64_set_vec_s8 (cpu
, vd
, i
,
6286 aarch64_get_vec_s8 (cpu
, vn
, i
)
6287 - aarch64_get_vec_s8 (cpu
, vm
, i
));
6291 for (i
= 0; i
< (full
? 8 : 4); i
++)
6292 aarch64_set_vec_s16 (cpu
, vd
, i
,
6293 aarch64_get_vec_s16 (cpu
, vn
, i
)
6294 - aarch64_get_vec_s16 (cpu
, vm
, i
));
6298 for (i
= 0; i
< (full
? 4 : 2); i
++)
6299 aarch64_set_vec_s32 (cpu
, vd
, i
,
6300 aarch64_get_vec_s32 (cpu
, vn
, i
)
6301 - aarch64_get_vec_s32 (cpu
, vm
, i
));
6308 for (i
= 0; i
< 2; i
++)
6309 aarch64_set_vec_s64 (cpu
, vd
, i
,
6310 aarch64_get_vec_s64 (cpu
, vn
, i
)
6311 - aarch64_get_vec_s64 (cpu
, vm
, i
));
6317 do_vec_MLS (sim_cpu
*cpu
)
6320 instr [30] = half(0)/full(1)
6321 instr [29,24] = 10 1110
6322 instr [23,22] = size: byte(00, half(01), word (10)
6325 instr [15,10] = 10 0101
6327 instr [4, 0] = Vd. */
6329 unsigned full
= INSTR (30, 30);
6330 unsigned vm
= INSTR (20, 16);
6331 unsigned vn
= INSTR (9, 5);
6332 unsigned vd
= INSTR (4, 0);
6335 NYI_assert (29, 24, 0x2E);
6336 NYI_assert (21, 21, 1);
6337 NYI_assert (15, 10, 0x25);
6339 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6340 switch (INSTR (23, 22))
6343 for (i
= 0; i
< (full
? 16 : 8); i
++)
6344 aarch64_set_vec_u8 (cpu
, vd
, i
,
6345 aarch64_get_vec_u8 (cpu
, vd
, i
)
6346 - (aarch64_get_vec_u8 (cpu
, vn
, i
)
6347 * aarch64_get_vec_u8 (cpu
, vm
, i
)));
6351 for (i
= 0; i
< (full
? 8 : 4); i
++)
6352 aarch64_set_vec_u16 (cpu
, vd
, i
,
6353 aarch64_get_vec_u16 (cpu
, vd
, i
)
6354 - (aarch64_get_vec_u16 (cpu
, vn
, i
)
6355 * aarch64_get_vec_u16 (cpu
, vm
, i
)));
6359 for (i
= 0; i
< (full
? 4 : 2); i
++)
6360 aarch64_set_vec_u32 (cpu
, vd
, i
,
6361 aarch64_get_vec_u32 (cpu
, vd
, i
)
6362 - (aarch64_get_vec_u32 (cpu
, vn
, i
)
6363 * aarch64_get_vec_u32 (cpu
, vm
, i
)));
6372 do_vec_FDIV (sim_cpu
*cpu
)
6375 instr [30] = half(0)/full(1)
6376 instr [29,23] = 10 1110 0
6377 instr [22] = float()/double(1)
6380 instr [15,10] = 1111 11
6382 instr [4, 0] = Vd. */
6384 unsigned full
= INSTR (30, 30);
6385 unsigned vm
= INSTR (20, 16);
6386 unsigned vn
= INSTR (9, 5);
6387 unsigned vd
= INSTR (4, 0);
6390 NYI_assert (29, 23, 0x5C);
6391 NYI_assert (21, 21, 1);
6392 NYI_assert (15, 10, 0x3F);
6394 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6400 for (i
= 0; i
< 2; i
++)
6401 aarch64_set_vec_double (cpu
, vd
, i
,
6402 aarch64_get_vec_double (cpu
, vn
, i
)
6403 / aarch64_get_vec_double (cpu
, vm
, i
));
6406 for (i
= 0; i
< (full
? 4 : 2); i
++)
6407 aarch64_set_vec_float (cpu
, vd
, i
,
6408 aarch64_get_vec_float (cpu
, vn
, i
)
6409 / aarch64_get_vec_float (cpu
, vm
, i
));
6413 do_vec_FMUL (sim_cpu
*cpu
)
6416 instr [30] = half(0)/full(1)
6417 instr [29,23] = 10 1110 0
6418 instr [22] = float(0)/double(1)
6421 instr [15,10] = 1101 11
6423 instr [4, 0] = Vd. */
6425 unsigned full
= INSTR (30, 30);
6426 unsigned vm
= INSTR (20, 16);
6427 unsigned vn
= INSTR (9, 5);
6428 unsigned vd
= INSTR (4, 0);
6431 NYI_assert (29, 23, 0x5C);
6432 NYI_assert (21, 21, 1);
6433 NYI_assert (15, 10, 0x37);
6435 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6441 for (i
= 0; i
< 2; i
++)
6442 aarch64_set_vec_double (cpu
, vd
, i
,
6443 aarch64_get_vec_double (cpu
, vn
, i
)
6444 * aarch64_get_vec_double (cpu
, vm
, i
));
6447 for (i
= 0; i
< (full
? 4 : 2); i
++)
6448 aarch64_set_vec_float (cpu
, vd
, i
,
6449 aarch64_get_vec_float (cpu
, vn
, i
)
6450 * aarch64_get_vec_float (cpu
, vm
, i
));
6454 do_vec_FADDP (sim_cpu
*cpu
)
6457 instr [30] = half(0)/full(1)
6458 instr [29,23] = 10 1110 0
6459 instr [22] = float(0)/double(1)
6462 instr [15,10] = 1101 01
6464 instr [4, 0] = Vd. */
6466 unsigned full
= INSTR (30, 30);
6467 unsigned vm
= INSTR (20, 16);
6468 unsigned vn
= INSTR (9, 5);
6469 unsigned vd
= INSTR (4, 0);
6471 NYI_assert (29, 23, 0x5C);
6472 NYI_assert (21, 21, 1);
6473 NYI_assert (15, 10, 0x35);
6475 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6478 /* Extract values before adding them incase vd == vn/vm. */
6479 double tmp1
= aarch64_get_vec_double (cpu
, vn
, 0);
6480 double tmp2
= aarch64_get_vec_double (cpu
, vn
, 1);
6481 double tmp3
= aarch64_get_vec_double (cpu
, vm
, 0);
6482 double tmp4
= aarch64_get_vec_double (cpu
, vm
, 1);
6487 aarch64_set_vec_double (cpu
, vd
, 0, tmp1
+ tmp2
);
6488 aarch64_set_vec_double (cpu
, vd
, 1, tmp3
+ tmp4
);
6492 /* Extract values before adding them incase vd == vn/vm. */
6493 float tmp1
= aarch64_get_vec_float (cpu
, vn
, 0);
6494 float tmp2
= aarch64_get_vec_float (cpu
, vn
, 1);
6495 float tmp5
= aarch64_get_vec_float (cpu
, vm
, 0);
6496 float tmp6
= aarch64_get_vec_float (cpu
, vm
, 1);
6500 float tmp3
= aarch64_get_vec_float (cpu
, vn
, 2);
6501 float tmp4
= aarch64_get_vec_float (cpu
, vn
, 3);
6502 float tmp7
= aarch64_get_vec_float (cpu
, vm
, 2);
6503 float tmp8
= aarch64_get_vec_float (cpu
, vm
, 3);
6505 aarch64_set_vec_float (cpu
, vd
, 0, tmp1
+ tmp2
);
6506 aarch64_set_vec_float (cpu
, vd
, 1, tmp3
+ tmp4
);
6507 aarch64_set_vec_float (cpu
, vd
, 2, tmp5
+ tmp6
);
6508 aarch64_set_vec_float (cpu
, vd
, 3, tmp7
+ tmp8
);
6512 aarch64_set_vec_float (cpu
, vd
, 0, tmp1
+ tmp2
);
6513 aarch64_set_vec_float (cpu
, vd
, 1, tmp5
+ tmp6
);
6519 do_vec_FSQRT (sim_cpu
*cpu
)
6522 instr[30] = half(0)/full(1)
6523 instr[29,23] = 10 1110 1
6524 instr[22] = single(0)/double(1)
6525 instr[21,10] = 10 0001 1111 10
6527 instr[4,0] = Vdest. */
6529 unsigned vn
= INSTR (9, 5);
6530 unsigned vd
= INSTR (4, 0);
6531 unsigned full
= INSTR (30, 30);
6534 NYI_assert (29, 23, 0x5D);
6535 NYI_assert (21, 10, 0x87E);
6537 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6543 for (i
= 0; i
< 2; i
++)
6544 aarch64_set_vec_double (cpu
, vd
, i
,
6545 sqrt (aarch64_get_vec_double (cpu
, vn
, i
)));
6549 for (i
= 0; i
< (full
? 4 : 2); i
++)
6550 aarch64_set_vec_float (cpu
, vd
, i
,
6551 sqrtf (aarch64_get_vec_float (cpu
, vn
, i
)));
6556 do_vec_FNEG (sim_cpu
*cpu
)
6559 instr[30] = half (0)/full (1)
6560 instr[29,23] = 10 1110 1
6561 instr[22] = single (0)/double (1)
6562 instr[21,10] = 10 0000 1111 10
6564 instr[4,0] = Vdest. */
6566 unsigned vn
= INSTR (9, 5);
6567 unsigned vd
= INSTR (4, 0);
6568 unsigned full
= INSTR (30, 30);
6571 NYI_assert (29, 23, 0x5D);
6572 NYI_assert (21, 10, 0x83E);
6574 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6580 for (i
= 0; i
< 2; i
++)
6581 aarch64_set_vec_double (cpu
, vd
, i
,
6582 - aarch64_get_vec_double (cpu
, vn
, i
));
6586 for (i
= 0; i
< (full
? 4 : 2); i
++)
6587 aarch64_set_vec_float (cpu
, vd
, i
,
6588 - aarch64_get_vec_float (cpu
, vn
, i
));
6593 do_vec_NOT (sim_cpu
*cpu
)
6596 instr[30] = half (0)/full (1)
6597 instr[29,10] = 10 1110 0010 0000 0101 10
6601 unsigned vn
= INSTR (9, 5);
6602 unsigned vd
= INSTR (4, 0);
6604 int full
= INSTR (30, 30);
6606 NYI_assert (29, 10, 0xB8816);
6608 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6609 for (i
= 0; i
< (full
? 16 : 8); i
++)
6610 aarch64_set_vec_u8 (cpu
, vd
, i
, ~ aarch64_get_vec_u8 (cpu
, vn
, i
));
6614 clz (uint64_t val
, unsigned size
)
6619 mask
<<= (size
- 1);
6634 do_vec_CLZ (sim_cpu
*cpu
)
6637 instr[30] = half (0)/full (1)
6638 instr[29,24] = 10 1110
6640 instr[21,10] = 10 0000 0100 10
6644 unsigned vn
= INSTR (9, 5);
6645 unsigned vd
= INSTR (4, 0);
6647 int full
= INSTR (30,30);
6649 NYI_assert (29, 24, 0x2E);
6650 NYI_assert (21, 10, 0x812);
6652 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6653 switch (INSTR (23, 22))
6656 for (i
= 0; i
< (full
? 16 : 8); i
++)
6657 aarch64_set_vec_u8 (cpu
, vd
, i
, clz (aarch64_get_vec_u8 (cpu
, vn
, i
), 8));
6660 for (i
= 0; i
< (full
? 8 : 4); i
++)
6661 aarch64_set_vec_u16 (cpu
, vd
, i
, clz (aarch64_get_vec_u16 (cpu
, vn
, i
), 16));
6664 for (i
= 0; i
< (full
? 4 : 2); i
++)
6665 aarch64_set_vec_u32 (cpu
, vd
, i
, clz (aarch64_get_vec_u32 (cpu
, vn
, i
), 32));
6670 aarch64_set_vec_u64 (cpu
, vd
, 0, clz (aarch64_get_vec_u64 (cpu
, vn
, 0), 64));
6671 aarch64_set_vec_u64 (cpu
, vd
, 1, clz (aarch64_get_vec_u64 (cpu
, vn
, 1), 64));
6677 do_vec_MOV_element (sim_cpu
*cpu
)
6679 /* instr[31,21] = 0110 1110 000
6680 instr[20,16] = size & dest index
6682 instr[14,11] = source index
6687 unsigned vs
= INSTR (9, 5);
6688 unsigned vd
= INSTR (4, 0);
6692 NYI_assert (31, 21, 0x370);
6693 NYI_assert (15, 15, 0);
6694 NYI_assert (10, 10, 1);
6696 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6700 src_index
= INSTR (14, 11);
6701 dst_index
= INSTR (20, 17);
6702 aarch64_set_vec_u8 (cpu
, vd
, dst_index
,
6703 aarch64_get_vec_u8 (cpu
, vs
, src_index
));
6705 else if (INSTR (17, 17))
6708 NYI_assert (11, 11, 0);
6709 src_index
= INSTR (14, 12);
6710 dst_index
= INSTR (20, 18);
6711 aarch64_set_vec_u16 (cpu
, vd
, dst_index
,
6712 aarch64_get_vec_u16 (cpu
, vs
, src_index
));
6714 else if (INSTR (18, 18))
6717 NYI_assert (12, 11, 0);
6718 src_index
= INSTR (14, 13);
6719 dst_index
= INSTR (20, 19);
6720 aarch64_set_vec_u32 (cpu
, vd
, dst_index
,
6721 aarch64_get_vec_u32 (cpu
, vs
, src_index
));
6725 NYI_assert (19, 19, 1);
6726 NYI_assert (13, 11, 0);
6727 src_index
= INSTR (14, 14);
6728 dst_index
= INSTR (20, 20);
6729 aarch64_set_vec_u64 (cpu
, vd
, dst_index
,
6730 aarch64_get_vec_u64 (cpu
, vs
, src_index
));
6735 do_vec_REV32 (sim_cpu
*cpu
)
6738 instr[30] = full/half
6739 instr[29,24] = 10 1110
6741 instr[21,10] = 10 0000 0000 10
6745 unsigned rn
= INSTR (9, 5);
6746 unsigned rd
= INSTR (4, 0);
6747 unsigned size
= INSTR (23, 22);
6748 unsigned full
= INSTR (30, 30);
6752 NYI_assert (29, 24, 0x2E);
6753 NYI_assert (21, 10, 0x802);
6755 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6759 for (i
= 0; i
< (full
? 16 : 8); i
++)
6760 val
.b
[i
^ 0x3] = aarch64_get_vec_u8 (cpu
, rn
, i
);
6764 for (i
= 0; i
< (full
? 8 : 4); i
++)
6765 val
.h
[i
^ 0x1] = aarch64_get_vec_u16 (cpu
, rn
, i
);
6772 aarch64_set_vec_u64 (cpu
, rd
, 0, val
.v
[0]);
6774 aarch64_set_vec_u64 (cpu
, rd
, 1, val
.v
[1]);
6778 do_vec_EXT (sim_cpu
*cpu
)
6781 instr[30] = full/half
6782 instr[29,21] = 10 1110 000
6785 instr[14,11] = source index
6790 unsigned vm
= INSTR (20, 16);
6791 unsigned vn
= INSTR (9, 5);
6792 unsigned vd
= INSTR (4, 0);
6793 unsigned src_index
= INSTR (14, 11);
6794 unsigned full
= INSTR (30, 30);
6799 NYI_assert (31, 21, 0x370);
6800 NYI_assert (15, 15, 0);
6801 NYI_assert (10, 10, 0);
6803 if (!full
&& (src_index
& 0x8))
6808 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6809 for (i
= src_index
; i
< (full
? 16 : 8); i
++)
6810 val
.b
[j
++] = aarch64_get_vec_u8 (cpu
, vn
, i
);
6811 for (i
= 0; i
< src_index
; i
++)
6812 val
.b
[j
++] = aarch64_get_vec_u8 (cpu
, vm
, i
);
6814 aarch64_set_vec_u64 (cpu
, vd
, 0, val
.v
[0]);
6816 aarch64_set_vec_u64 (cpu
, vd
, 1, val
.v
[1]);
6820 dexAdvSIMD0 (sim_cpu
*cpu
)
6822 /* instr [28,25] = 0 111. */
6823 if ( INSTR (15, 10) == 0x07
6827 if (INSTR (31, 21) == 0x075
6828 || INSTR (31, 21) == 0x275)
6830 do_vec_MOV_whole_vector (cpu
);
6835 if (INSTR (29, 19) == 0x1E0)
6837 do_vec_MOV_immediate (cpu
);
6841 if (INSTR (29, 19) == 0x5E0)
6847 if (INSTR (29, 19) == 0x1C0
6848 || INSTR (29, 19) == 0x1C1)
6850 if (INSTR (15, 10) == 0x03)
6852 do_vec_DUP_scalar_into_vector (cpu
);
6857 switch (INSTR (29, 24))
6859 case 0x0E: do_vec_op1 (cpu
); return;
6860 case 0x0F: do_vec_op2 (cpu
); return;
6863 if (INSTR (21, 21) == 1)
6865 switch (INSTR (15, 10))
6872 switch (INSTR (23, 22))
6874 case 0: do_vec_EOR (cpu
); return;
6875 case 1: do_vec_BSL (cpu
); return;
6877 case 3: do_vec_bit (cpu
); return;
6881 case 0x08: do_vec_sub_long (cpu
); return;
6882 case 0x11: do_vec_USHL (cpu
); return;
6883 case 0x12: do_vec_CLZ (cpu
); return;
6884 case 0x16: do_vec_NOT (cpu
); return;
6885 case 0x19: do_vec_max (cpu
); return;
6886 case 0x1B: do_vec_min (cpu
); return;
6887 case 0x21: do_vec_SUB (cpu
); return;
6888 case 0x25: do_vec_MLS (cpu
); return;
6889 case 0x31: do_vec_FminmaxNMP (cpu
); return;
6890 case 0x35: do_vec_FADDP (cpu
); return;
6891 case 0x37: do_vec_FMUL (cpu
); return;
6892 case 0x3F: do_vec_FDIV (cpu
); return;
6895 switch (INSTR (20, 16))
6897 case 0x00: do_vec_FNEG (cpu
); return;
6898 case 0x01: do_vec_FSQRT (cpu
); return;
6912 do_vec_compare (cpu
); return;
6919 if (INSTR (31, 21) == 0x370)
6922 do_vec_MOV_element (cpu
);
6928 switch (INSTR (21, 10))
6930 case 0x82E: do_vec_neg (cpu
); return;
6931 case 0x87E: do_vec_sqrt (cpu
); return;
6933 if (INSTR (15, 10) == 0x30)
6943 switch (INSTR (15, 10))
6945 case 0x01: do_vec_SSHR_USHR (cpu
); return;
6947 case 0x12: do_vec_mls_indexed (cpu
); return;
6948 case 0x29: do_vec_xtl (cpu
); return;
6962 /* Float multiply add. */
6964 fmadds (sim_cpu
*cpu
)
6966 unsigned sa
= INSTR (14, 10);
6967 unsigned sm
= INSTR (20, 16);
6968 unsigned sn
= INSTR ( 9, 5);
6969 unsigned sd
= INSTR ( 4, 0);
6971 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6972 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sa
)
6973 + aarch64_get_FP_float (cpu
, sn
)
6974 * aarch64_get_FP_float (cpu
, sm
));
6977 /* Double multiply add. */
6979 fmaddd (sim_cpu
*cpu
)
6981 unsigned sa
= INSTR (14, 10);
6982 unsigned sm
= INSTR (20, 16);
6983 unsigned sn
= INSTR ( 9, 5);
6984 unsigned sd
= INSTR ( 4, 0);
6986 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6987 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sa
)
6988 + aarch64_get_FP_double (cpu
, sn
)
6989 * aarch64_get_FP_double (cpu
, sm
));
6992 /* Float multiply subtract. */
6994 fmsubs (sim_cpu
*cpu
)
6996 unsigned sa
= INSTR (14, 10);
6997 unsigned sm
= INSTR (20, 16);
6998 unsigned sn
= INSTR ( 9, 5);
6999 unsigned sd
= INSTR ( 4, 0);
7001 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7002 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sa
)
7003 - aarch64_get_FP_float (cpu
, sn
)
7004 * aarch64_get_FP_float (cpu
, sm
));
7007 /* Double multiply subtract. */
7009 fmsubd (sim_cpu
*cpu
)
7011 unsigned sa
= INSTR (14, 10);
7012 unsigned sm
= INSTR (20, 16);
7013 unsigned sn
= INSTR ( 9, 5);
7014 unsigned sd
= INSTR ( 4, 0);
7016 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7017 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sa
)
7018 - aarch64_get_FP_double (cpu
, sn
)
7019 * aarch64_get_FP_double (cpu
, sm
));
7022 /* Float negative multiply add. */
7024 fnmadds (sim_cpu
*cpu
)
7026 unsigned sa
= INSTR (14, 10);
7027 unsigned sm
= INSTR (20, 16);
7028 unsigned sn
= INSTR ( 9, 5);
7029 unsigned sd
= INSTR ( 4, 0);
7031 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7032 aarch64_set_FP_float (cpu
, sd
, - aarch64_get_FP_float (cpu
, sa
)
7033 + (- aarch64_get_FP_float (cpu
, sn
))
7034 * aarch64_get_FP_float (cpu
, sm
));
7037 /* Double negative multiply add. */
7039 fnmaddd (sim_cpu
*cpu
)
7041 unsigned sa
= INSTR (14, 10);
7042 unsigned sm
= INSTR (20, 16);
7043 unsigned sn
= INSTR ( 9, 5);
7044 unsigned sd
= INSTR ( 4, 0);
7046 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7047 aarch64_set_FP_double (cpu
, sd
, - aarch64_get_FP_double (cpu
, sa
)
7048 + (- aarch64_get_FP_double (cpu
, sn
))
7049 * aarch64_get_FP_double (cpu
, sm
));
7052 /* Float negative multiply subtract. */
7054 fnmsubs (sim_cpu
*cpu
)
7056 unsigned sa
= INSTR (14, 10);
7057 unsigned sm
= INSTR (20, 16);
7058 unsigned sn
= INSTR ( 9, 5);
7059 unsigned sd
= INSTR ( 4, 0);
7061 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7062 aarch64_set_FP_float (cpu
, sd
, - aarch64_get_FP_float (cpu
, sa
)
7063 + aarch64_get_FP_float (cpu
, sn
)
7064 * aarch64_get_FP_float (cpu
, sm
));
7067 /* Double negative multiply subtract. */
7069 fnmsubd (sim_cpu
*cpu
)
7071 unsigned sa
= INSTR (14, 10);
7072 unsigned sm
= INSTR (20, 16);
7073 unsigned sn
= INSTR ( 9, 5);
7074 unsigned sd
= INSTR ( 4, 0);
7076 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7077 aarch64_set_FP_double (cpu
, sd
, - aarch64_get_FP_double (cpu
, sa
)
7078 + aarch64_get_FP_double (cpu
, sn
)
7079 * aarch64_get_FP_double (cpu
, sm
));
7083 dexSimpleFPDataProc3Source (sim_cpu
*cpu
)
7085 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
7087 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
7090 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
7091 instr[21] ==> o1 : 0 ==> unnegated, 1 ==> negated
7092 instr[15] ==> o2 : 0 ==> ADD, 1 ==> SUB */
7094 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
7095 /* dispatch on combined type:o1:o2. */
7096 uint32_t dispatch
= (INSTR (23, 21) << 1) | INSTR (15, 15);
7103 case 0: fmadds (cpu
); return;
7104 case 1: fmsubs (cpu
); return;
7105 case 2: fnmadds (cpu
); return;
7106 case 3: fnmsubs (cpu
); return;
7107 case 4: fmaddd (cpu
); return;
7108 case 5: fmsubd (cpu
); return;
7109 case 6: fnmaddd (cpu
); return;
7110 case 7: fnmsubd (cpu
); return;
7112 /* type > 1 is currently unallocated. */
7118 dexSimpleFPFixedConvert (sim_cpu
*cpu
)
7124 dexSimpleFPCondCompare (sim_cpu
*cpu
)
7126 /* instr [31,23] = 0001 1110 0
7130 instr [15,12] = condition
7134 instr [3,0] = nzcv */
7136 unsigned rm
= INSTR (20, 16);
7137 unsigned rn
= INSTR (9, 5);
7139 NYI_assert (31, 23, 0x3C);
7140 NYI_assert (11, 10, 0x1);
7141 NYI_assert (4, 4, 0);
7143 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7144 if (! testConditionCode (cpu
, INSTR (15, 12)))
7146 aarch64_set_CPSR (cpu
, INSTR (3, 0));
7152 /* Double precision. */
7153 double val1
= aarch64_get_vec_double (cpu
, rn
, 0);
7154 double val2
= aarch64_get_vec_double (cpu
, rm
, 0);
7156 /* FIXME: Check for NaNs. */
7158 aarch64_set_CPSR (cpu
, (Z
| C
));
7159 else if (val1
< val2
)
7160 aarch64_set_CPSR (cpu
, N
);
7161 else /* val1 > val2 */
7162 aarch64_set_CPSR (cpu
, C
);
7166 /* Single precision. */
7167 float val1
= aarch64_get_vec_float (cpu
, rn
, 0);
7168 float val2
= aarch64_get_vec_float (cpu
, rm
, 0);
7170 /* FIXME: Check for NaNs. */
7172 aarch64_set_CPSR (cpu
, (Z
| C
));
7173 else if (val1
< val2
)
7174 aarch64_set_CPSR (cpu
, N
);
7175 else /* val1 > val2 */
7176 aarch64_set_CPSR (cpu
, C
);
7184 fadds (sim_cpu
*cpu
)
7186 unsigned sm
= INSTR (20, 16);
7187 unsigned sn
= INSTR ( 9, 5);
7188 unsigned sd
= INSTR ( 4, 0);
7190 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7191 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
7192 + aarch64_get_FP_float (cpu
, sm
));
7197 faddd (sim_cpu
*cpu
)
7199 unsigned sm
= INSTR (20, 16);
7200 unsigned sn
= INSTR ( 9, 5);
7201 unsigned sd
= INSTR ( 4, 0);
7203 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7204 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
7205 + aarch64_get_FP_double (cpu
, sm
));
7210 fdivs (sim_cpu
*cpu
)
7212 unsigned sm
= INSTR (20, 16);
7213 unsigned sn
= INSTR ( 9, 5);
7214 unsigned sd
= INSTR ( 4, 0);
7216 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7217 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
7218 / aarch64_get_FP_float (cpu
, sm
));
7221 /* Double divide. */
7223 fdivd (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_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
7231 / aarch64_get_FP_double (cpu
, sm
));
7234 /* Float multiply. */
7236 fmuls (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_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
7244 * aarch64_get_FP_float (cpu
, sm
));
7247 /* Double multiply. */
7249 fmuld (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_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
7257 * aarch64_get_FP_double (cpu
, sm
));
7260 /* Float negate and multiply. */
7262 fnmuls (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_float (cpu
, sd
, - (aarch64_get_FP_float (cpu
, sn
)
7270 * aarch64_get_FP_float (cpu
, sm
)));
7273 /* Double negate and multiply. */
7275 fnmuld (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_double (cpu
, sd
, - (aarch64_get_FP_double (cpu
, sn
)
7283 * aarch64_get_FP_double (cpu
, sm
)));
7286 /* Float subtract. */
7288 fsubs (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_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
7296 - aarch64_get_FP_float (cpu
, sm
));
7299 /* Double subtract. */
7301 fsubd (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_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
7309 - aarch64_get_FP_double (cpu
, sm
));
7313 do_FMINNM (sim_cpu
*cpu
)
7315 /* instr[31,23] = 0 0011 1100
7316 instr[22] = float(0)/double(1)
7319 instr[15,10] = 01 1110
7323 unsigned sm
= INSTR (20, 16);
7324 unsigned sn
= INSTR ( 9, 5);
7325 unsigned sd
= INSTR ( 4, 0);
7327 NYI_assert (31, 23, 0x03C);
7328 NYI_assert (15, 10, 0x1E);
7330 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7332 aarch64_set_FP_double (cpu
, sd
,
7333 dminnm (aarch64_get_FP_double (cpu
, sn
),
7334 aarch64_get_FP_double (cpu
, sm
)));
7336 aarch64_set_FP_float (cpu
, sd
,
7337 fminnm (aarch64_get_FP_float (cpu
, sn
),
7338 aarch64_get_FP_float (cpu
, sm
)));
7342 do_FMAXNM (sim_cpu
*cpu
)
7344 /* instr[31,23] = 0 0011 1100
7345 instr[22] = float(0)/double(1)
7348 instr[15,10] = 01 1010
7352 unsigned sm
= INSTR (20, 16);
7353 unsigned sn
= INSTR ( 9, 5);
7354 unsigned sd
= INSTR ( 4, 0);
7356 NYI_assert (31, 23, 0x03C);
7357 NYI_assert (15, 10, 0x1A);
7359 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7361 aarch64_set_FP_double (cpu
, sd
,
7362 dmaxnm (aarch64_get_FP_double (cpu
, sn
),
7363 aarch64_get_FP_double (cpu
, sm
)));
7365 aarch64_set_FP_float (cpu
, sd
,
7366 fmaxnm (aarch64_get_FP_float (cpu
, sn
),
7367 aarch64_get_FP_float (cpu
, sm
)));
7371 dexSimpleFPDataProc2Source (sim_cpu
*cpu
)
7373 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
7375 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
7378 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
7381 instr[15,12] ==> opcode : 0000 ==> FMUL, 0001 ==> FDIV
7382 0010 ==> FADD, 0011 ==> FSUB,
7383 0100 ==> FMAX, 0101 ==> FMIN
7384 0110 ==> FMAXNM, 0111 ==> FMINNM
7385 1000 ==> FNMUL, ow ==> UNALLOC
7390 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
7391 uint32_t type
= INSTR (23, 22);
7392 /* Dispatch on opcode. */
7393 uint32_t dispatch
= INSTR (15, 12);
7404 case 0: fmuld (cpu
); return;
7405 case 1: fdivd (cpu
); return;
7406 case 2: faddd (cpu
); return;
7407 case 3: fsubd (cpu
); return;
7408 case 6: do_FMAXNM (cpu
); return;
7409 case 7: do_FMINNM (cpu
); return;
7410 case 8: fnmuld (cpu
); return;
7412 /* Have not yet implemented fmax and fmin. */
7420 else /* type == 0 => floats. */
7423 case 0: fmuls (cpu
); return;
7424 case 1: fdivs (cpu
); return;
7425 case 2: fadds (cpu
); return;
7426 case 3: fsubs (cpu
); return;
7427 case 6: do_FMAXNM (cpu
); return;
7428 case 7: do_FMINNM (cpu
); return;
7429 case 8: fnmuls (cpu
); return;
7441 dexSimpleFPCondSelect (sim_cpu
*cpu
)
7444 instr[31,23] = 0 0011 1100
7445 instr[22] = 0=>single 1=>double
7452 unsigned sm
= INSTR (20, 16);
7453 unsigned sn
= INSTR ( 9, 5);
7454 unsigned sd
= INSTR ( 4, 0);
7455 uint32_t set
= testConditionCode (cpu
, INSTR (15, 12));
7457 NYI_assert (31, 23, 0x03C);
7458 NYI_assert (11, 10, 0x3);
7460 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7462 aarch64_set_FP_double (cpu
, sd
, (set
? aarch64_get_FP_double (cpu
, sn
)
7463 : aarch64_get_FP_double (cpu
, sm
)));
7465 aarch64_set_FP_float (cpu
, sd
, (set
? aarch64_get_FP_float (cpu
, sn
)
7466 : aarch64_get_FP_float (cpu
, sm
)));
7469 /* Store 32 bit unscaled signed 9 bit. */
7471 fsturs (sim_cpu
*cpu
, int32_t offset
)
7473 unsigned int rn
= INSTR (9, 5);
7474 unsigned int st
= INSTR (4, 0);
7476 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7477 aarch64_set_mem_u32 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, 1) + offset
,
7478 aarch64_get_vec_u32 (cpu
, st
, 0));
7481 /* Store 64 bit unscaled signed 9 bit. */
7483 fsturd (sim_cpu
*cpu
, int32_t offset
)
7485 unsigned int rn
= INSTR (9, 5);
7486 unsigned int st
= INSTR (4, 0);
7488 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7489 aarch64_set_mem_u64 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, 1) + offset
,
7490 aarch64_get_vec_u64 (cpu
, st
, 0));
7493 /* Store 128 bit unscaled signed 9 bit. */
7495 fsturq (sim_cpu
*cpu
, int32_t offset
)
7497 unsigned int rn
= INSTR (9, 5);
7498 unsigned int st
= INSTR (4, 0);
7501 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7502 aarch64_get_FP_long_double (cpu
, st
, & a
);
7503 aarch64_set_mem_long_double (cpu
,
7504 aarch64_get_reg_u64 (cpu
, rn
, 1)
7508 /* TODO FP move register. */
7510 /* 32 bit fp to fp move register. */
7512 ffmovs (sim_cpu
*cpu
)
7514 unsigned int rn
= INSTR (9, 5);
7515 unsigned int st
= INSTR (4, 0);
7517 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7518 aarch64_set_FP_float (cpu
, st
, aarch64_get_FP_float (cpu
, rn
));
7521 /* 64 bit fp to fp move register. */
7523 ffmovd (sim_cpu
*cpu
)
7525 unsigned int rn
= INSTR (9, 5);
7526 unsigned int st
= INSTR (4, 0);
7528 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7529 aarch64_set_FP_double (cpu
, st
, aarch64_get_FP_double (cpu
, rn
));
7532 /* 32 bit GReg to Vec move register. */
7534 fgmovs (sim_cpu
*cpu
)
7536 unsigned int rn
= INSTR (9, 5);
7537 unsigned int st
= INSTR (4, 0);
7539 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7540 aarch64_set_vec_u32 (cpu
, st
, 0, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
));
7543 /* 64 bit g to fp move register. */
7545 fgmovd (sim_cpu
*cpu
)
7547 unsigned int rn
= INSTR (9, 5);
7548 unsigned int st
= INSTR (4, 0);
7550 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7551 aarch64_set_vec_u64 (cpu
, st
, 0, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
7554 /* 32 bit fp to g move register. */
7556 gfmovs (sim_cpu
*cpu
)
7558 unsigned int rn
= INSTR (9, 5);
7559 unsigned int st
= INSTR (4, 0);
7561 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7562 aarch64_set_reg_u64 (cpu
, st
, NO_SP
, aarch64_get_vec_u32 (cpu
, rn
, 0));
7565 /* 64 bit fp to g move register. */
7567 gfmovd (sim_cpu
*cpu
)
7569 unsigned int rn
= INSTR (9, 5);
7570 unsigned int st
= INSTR (4, 0);
7572 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7573 aarch64_set_reg_u64 (cpu
, st
, NO_SP
, aarch64_get_vec_u64 (cpu
, rn
, 0));
7576 /* FP move immediate
7578 These install an immediate 8 bit value in the target register
7579 where the 8 bits comprise 1 sign bit, 4 bits of fraction and a 3
7583 fmovs (sim_cpu
*cpu
)
7585 unsigned int sd
= INSTR (4, 0);
7586 uint32_t imm
= INSTR (20, 13);
7587 float f
= fp_immediate_for_encoding_32 (imm
);
7589 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7590 aarch64_set_FP_float (cpu
, sd
, f
);
7594 fmovd (sim_cpu
*cpu
)
7596 unsigned int sd
= INSTR (4, 0);
7597 uint32_t imm
= INSTR (20, 13);
7598 double d
= fp_immediate_for_encoding_64 (imm
);
7600 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7601 aarch64_set_FP_double (cpu
, sd
, d
);
7605 dexSimpleFPImmediate (sim_cpu
*cpu
)
7607 /* instr[31,23] == 00111100
7608 instr[22] == type : single(0)/double(1)
7610 instr[20,13] == imm8
7612 instr[9,5] == imm5 : 00000 ==> PK, ow ==> UNALLOC
7614 uint32_t imm5
= INSTR (9, 5);
7616 NYI_assert (31, 23, 0x3C);
7627 /* TODO specific decode and execute for group Load Store. */
7629 /* TODO FP load/store single register (unscaled offset). */
7631 /* TODO load 8 bit unscaled signed 9 bit. */
7632 /* TODO load 16 bit unscaled signed 9 bit. */
7634 /* Load 32 bit unscaled signed 9 bit. */
7636 fldurs (sim_cpu
*cpu
, int32_t offset
)
7638 unsigned int rn
= INSTR (9, 5);
7639 unsigned int st
= INSTR (4, 0);
7641 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7642 aarch64_set_vec_u32 (cpu
, st
, 0, aarch64_get_mem_u32
7643 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
));
7646 /* Load 64 bit unscaled signed 9 bit. */
7648 fldurd (sim_cpu
*cpu
, int32_t offset
)
7650 unsigned int rn
= INSTR (9, 5);
7651 unsigned int st
= INSTR (4, 0);
7653 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7654 aarch64_set_vec_u64 (cpu
, st
, 0, aarch64_get_mem_u64
7655 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
));
7658 /* Load 128 bit unscaled signed 9 bit. */
7660 fldurq (sim_cpu
*cpu
, int32_t offset
)
7662 unsigned int rn
= INSTR (9, 5);
7663 unsigned int st
= INSTR (4, 0);
7665 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
;
7667 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7668 aarch64_get_mem_long_double (cpu
, addr
, & a
);
7669 aarch64_set_FP_long_double (cpu
, st
, a
);
7672 /* TODO store 8 bit unscaled signed 9 bit. */
7673 /* TODO store 16 bit unscaled signed 9 bit. */
7678 /* Float absolute value. */
7680 fabss (sim_cpu
*cpu
)
7682 unsigned sn
= INSTR (9, 5);
7683 unsigned sd
= INSTR (4, 0);
7684 float value
= aarch64_get_FP_float (cpu
, sn
);
7686 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7687 aarch64_set_FP_float (cpu
, sd
, fabsf (value
));
7690 /* Double absolute value. */
7692 fabcpu (sim_cpu
*cpu
)
7694 unsigned sn
= INSTR (9, 5);
7695 unsigned sd
= INSTR (4, 0);
7696 double value
= aarch64_get_FP_double (cpu
, sn
);
7698 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7699 aarch64_set_FP_double (cpu
, sd
, fabs (value
));
7702 /* Float negative value. */
7704 fnegs (sim_cpu
*cpu
)
7706 unsigned sn
= INSTR (9, 5);
7707 unsigned sd
= INSTR (4, 0);
7709 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7710 aarch64_set_FP_float (cpu
, sd
, - aarch64_get_FP_float (cpu
, sn
));
7713 /* Double negative value. */
7715 fnegd (sim_cpu
*cpu
)
7717 unsigned sn
= INSTR (9, 5);
7718 unsigned sd
= INSTR (4, 0);
7720 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7721 aarch64_set_FP_double (cpu
, sd
, - aarch64_get_FP_double (cpu
, sn
));
7724 /* Float square root. */
7726 fsqrts (sim_cpu
*cpu
)
7728 unsigned sn
= INSTR (9, 5);
7729 unsigned sd
= INSTR (4, 0);
7731 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7732 aarch64_set_FP_float (cpu
, sd
, sqrtf (aarch64_get_FP_float (cpu
, sn
)));
7735 /* Double square root. */
7737 fsqrtd (sim_cpu
*cpu
)
7739 unsigned sn
= INSTR (9, 5);
7740 unsigned sd
= INSTR (4, 0);
7742 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7743 aarch64_set_FP_double (cpu
, sd
,
7744 sqrt (aarch64_get_FP_double (cpu
, sn
)));
7747 /* Convert double to float. */
7749 fcvtds (sim_cpu
*cpu
)
7751 unsigned sn
= INSTR (9, 5);
7752 unsigned sd
= INSTR (4, 0);
7754 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7755 aarch64_set_FP_float (cpu
, sd
, (float) aarch64_get_FP_double (cpu
, sn
));
7758 /* Convert float to double. */
7760 fcvtcpu (sim_cpu
*cpu
)
7762 unsigned sn
= INSTR (9, 5);
7763 unsigned sd
= INSTR (4, 0);
7765 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7766 aarch64_set_FP_double (cpu
, sd
, (double) aarch64_get_FP_float (cpu
, sn
));
7770 do_FRINT (sim_cpu
*cpu
)
7772 /* instr[31,23] = 0001 1110 0
7773 instr[22] = single(0)/double(1)
7775 instr[17,15] = rounding mode
7776 instr[14,10] = 10000
7778 instr[4,0] = dest */
7781 unsigned rs
= INSTR (9, 5);
7782 unsigned rd
= INSTR (4, 0);
7783 unsigned int rmode
= INSTR (17, 15);
7785 NYI_assert (31, 23, 0x03C);
7786 NYI_assert (21, 18, 0x9);
7787 NYI_assert (14, 10, 0x10);
7789 if (rmode
== 6 || rmode
== 7)
7790 /* FIXME: Add support for rmode == 6 exactness check. */
7791 rmode
= uimm (aarch64_get_FPSR (cpu
), 23, 22);
7793 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7796 double val
= aarch64_get_FP_double (cpu
, rs
);
7800 case 0: /* mode N: nearest or even. */
7802 double rval
= round (val
);
7804 if (val
- rval
== 0.5)
7806 if (((rval
/ 2.0) * 2.0) != rval
)
7810 aarch64_set_FP_double (cpu
, rd
, round (val
));
7814 case 1: /* mode P: towards +inf. */
7816 aarch64_set_FP_double (cpu
, rd
, trunc (val
));
7818 aarch64_set_FP_double (cpu
, rd
, round (val
));
7821 case 2: /* mode M: towards -inf. */
7823 aarch64_set_FP_double (cpu
, rd
, round (val
));
7825 aarch64_set_FP_double (cpu
, rd
, trunc (val
));
7828 case 3: /* mode Z: towards 0. */
7829 aarch64_set_FP_double (cpu
, rd
, trunc (val
));
7832 case 4: /* mode A: away from 0. */
7833 aarch64_set_FP_double (cpu
, rd
, round (val
));
7836 case 6: /* mode X: use FPCR with exactness check. */
7837 case 7: /* mode I: use FPCR mode. */
7845 val
= aarch64_get_FP_float (cpu
, rs
);
7849 case 0: /* mode N: nearest or even. */
7851 float rval
= roundf (val
);
7853 if (val
- rval
== 0.5)
7855 if (((rval
/ 2.0) * 2.0) != rval
)
7859 aarch64_set_FP_float (cpu
, rd
, rval
);
7863 case 1: /* mode P: towards +inf. */
7865 aarch64_set_FP_float (cpu
, rd
, truncf (val
));
7867 aarch64_set_FP_float (cpu
, rd
, roundf (val
));
7870 case 2: /* mode M: towards -inf. */
7872 aarch64_set_FP_float (cpu
, rd
, truncf (val
));
7874 aarch64_set_FP_float (cpu
, rd
, roundf (val
));
7877 case 3: /* mode Z: towards 0. */
7878 aarch64_set_FP_float (cpu
, rd
, truncf (val
));
7881 case 4: /* mode A: away from 0. */
7882 aarch64_set_FP_float (cpu
, rd
, roundf (val
));
7885 case 6: /* mode X: use FPCR with exactness check. */
7886 case 7: /* mode I: use FPCR mode. */
7894 /* Convert half to float. */
7896 do_FCVT_half_to_single (sim_cpu
*cpu
)
7898 unsigned rn
= INSTR (9, 5);
7899 unsigned rd
= INSTR (4, 0);
7901 NYI_assert (31, 10, 0x7B890);
7903 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7904 aarch64_set_FP_float (cpu
, rd
, (float) aarch64_get_FP_half (cpu
, rn
));
7907 /* Convert half to double. */
7909 do_FCVT_half_to_double (sim_cpu
*cpu
)
7911 unsigned rn
= INSTR (9, 5);
7912 unsigned rd
= INSTR (4, 0);
7914 NYI_assert (31, 10, 0x7B8B0);
7916 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7917 aarch64_set_FP_double (cpu
, rd
, (double) aarch64_get_FP_half (cpu
, rn
));
7921 do_FCVT_single_to_half (sim_cpu
*cpu
)
7923 unsigned rn
= INSTR (9, 5);
7924 unsigned rd
= INSTR (4, 0);
7926 NYI_assert (31, 10, 0x788F0);
7928 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7929 aarch64_set_FP_half (cpu
, rd
, aarch64_get_FP_float (cpu
, rn
));
7932 /* Convert double to half. */
7934 do_FCVT_double_to_half (sim_cpu
*cpu
)
7936 unsigned rn
= INSTR (9, 5);
7937 unsigned rd
= INSTR (4, 0);
7939 NYI_assert (31, 10, 0x798F0);
7941 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7942 aarch64_set_FP_half (cpu
, rd
, (float) aarch64_get_FP_double (cpu
, rn
));
7946 dexSimpleFPDataProc1Source (sim_cpu
*cpu
)
7948 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
7950 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
7953 instr[23,22] ==> type : 00 ==> source is single,
7954 01 ==> source is double
7956 11 ==> UNALLOC or source is half
7958 instr[20,15] ==> opcode : with type 00 or 01
7959 000000 ==> FMOV, 000001 ==> FABS,
7960 000010 ==> FNEG, 000011 ==> FSQRT,
7961 000100 ==> UNALLOC, 000101 ==> FCVT,(to single/double)
7962 000110 ==> UNALLOC, 000111 ==> FCVT (to half)
7963 001000 ==> FRINTN, 001001 ==> FRINTP,
7964 001010 ==> FRINTM, 001011 ==> FRINTZ,
7965 001100 ==> FRINTA, 001101 ==> UNALLOC
7966 001110 ==> FRINTX, 001111 ==> FRINTI
7968 000100 ==> FCVT (half-to-single)
7969 000101 ==> FCVT (half-to-double)
7970 instr[14,10] = 10000. */
7972 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
7973 uint32_t type
= INSTR (23, 22);
7974 uint32_t opcode
= INSTR (20, 15);
7982 do_FCVT_half_to_single (cpu
);
7983 else if (opcode
== 5)
7984 do_FCVT_half_to_double (cpu
);
8036 case 8: /* FRINTN etc. */
8048 do_FCVT_double_to_half (cpu
);
8050 do_FCVT_single_to_half (cpu
);
8061 /* 32 bit signed int to float. */
8063 scvtf32 (sim_cpu
*cpu
)
8065 unsigned rn
= INSTR (9, 5);
8066 unsigned sd
= INSTR (4, 0);
8068 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8069 aarch64_set_FP_float
8070 (cpu
, sd
, (float) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
));
8073 /* signed int to float. */
8075 scvtf (sim_cpu
*cpu
)
8077 unsigned rn
= INSTR (9, 5);
8078 unsigned sd
= INSTR (4, 0);
8080 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8081 aarch64_set_FP_float
8082 (cpu
, sd
, (float) aarch64_get_reg_s64 (cpu
, rn
, NO_SP
));
8085 /* 32 bit signed int to double. */
8087 scvtd32 (sim_cpu
*cpu
)
8089 unsigned rn
= INSTR (9, 5);
8090 unsigned sd
= INSTR (4, 0);
8092 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8093 aarch64_set_FP_double
8094 (cpu
, sd
, (double) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
));
8097 /* signed int to double. */
8099 scvtd (sim_cpu
*cpu
)
8101 unsigned rn
= INSTR (9, 5);
8102 unsigned sd
= INSTR (4, 0);
8104 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8105 aarch64_set_FP_double
8106 (cpu
, sd
, (double) aarch64_get_reg_s64 (cpu
, rn
, NO_SP
));
8109 static const float FLOAT_INT_MAX
= (float) INT_MAX
;
8110 static const float FLOAT_INT_MIN
= (float) INT_MIN
;
8111 static const double DOUBLE_INT_MAX
= (double) INT_MAX
;
8112 static const double DOUBLE_INT_MIN
= (double) INT_MIN
;
8113 static const float FLOAT_LONG_MAX
= (float) LONG_MAX
;
8114 static const float FLOAT_LONG_MIN
= (float) LONG_MIN
;
8115 static const double DOUBLE_LONG_MAX
= (double) LONG_MAX
;
8116 static const double DOUBLE_LONG_MIN
= (double) LONG_MIN
;
8120 static const float FLOAT_UINT_MAX
= (float) UINT_MAX
;
8121 static const float FLOAT_UINT_MIN
= (float) UINT_MIN
;
8122 static const double DOUBLE_UINT_MAX
= (double) UINT_MAX
;
8123 static const double DOUBLE_UINT_MIN
= (double) UINT_MIN
;
8124 static const float FLOAT_ULONG_MAX
= (float) ULONG_MAX
;
8125 static const float FLOAT_ULONG_MIN
= (float) ULONG_MIN
;
8126 static const double DOUBLE_ULONG_MAX
= (double) ULONG_MAX
;
8127 static const double DOUBLE_ULONG_MIN
= (double) ULONG_MIN
;
8129 /* Check for FP exception conditions:
8132 Out of Range raises IO and IX and saturates value
8133 Denormal raises ID and IX and sets to zero. */
8134 #define RAISE_EXCEPTIONS(F, VALUE, FTYPE, ITYPE) \
8137 switch (fpclassify (F)) \
8141 aarch64_set_FPSR (cpu, IO); \
8143 VALUE = ITYPE##_MAX; \
8145 VALUE = ITYPE##_MIN; \
8149 if (F >= FTYPE##_##ITYPE##_MAX) \
8151 aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX); \
8152 VALUE = ITYPE##_MAX; \
8154 else if (F <= FTYPE##_##ITYPE##_MIN) \
8156 aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX); \
8157 VALUE = ITYPE##_MIN; \
8161 case FP_SUBNORMAL: \
8162 aarch64_set_FPSR_bits (cpu, IO | IX | ID, IX | ID); \
8174 /* 32 bit convert float to signed int truncate towards zero. */
8176 fcvtszs32 (sim_cpu
*cpu
)
8178 unsigned sn
= INSTR (9, 5);
8179 unsigned rd
= INSTR (4, 0);
8180 /* TODO : check that this rounds toward zero. */
8181 float f
= aarch64_get_FP_float (cpu
, sn
);
8182 int32_t value
= (int32_t) f
;
8184 RAISE_EXCEPTIONS (f
, value
, FLOAT
, INT
);
8186 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8187 /* Avoid sign extension to 64 bit. */
8188 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) value
);
8191 /* 64 bit convert float to signed int truncate towards zero. */
8193 fcvtszs (sim_cpu
*cpu
)
8195 unsigned sn
= INSTR (9, 5);
8196 unsigned rd
= INSTR (4, 0);
8197 float f
= aarch64_get_FP_float (cpu
, sn
);
8198 int64_t value
= (int64_t) f
;
8200 RAISE_EXCEPTIONS (f
, value
, FLOAT
, LONG
);
8202 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8203 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, value
);
8206 /* 32 bit convert double to signed int truncate towards zero. */
8208 fcvtszd32 (sim_cpu
*cpu
)
8210 unsigned sn
= INSTR (9, 5);
8211 unsigned rd
= INSTR (4, 0);
8212 /* TODO : check that this rounds toward zero. */
8213 double d
= aarch64_get_FP_double (cpu
, sn
);
8214 int32_t value
= (int32_t) d
;
8216 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, INT
);
8218 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8219 /* Avoid sign extension to 64 bit. */
8220 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) value
);
8223 /* 64 bit convert double to signed int truncate towards zero. */
8225 fcvtszd (sim_cpu
*cpu
)
8227 unsigned sn
= INSTR (9, 5);
8228 unsigned rd
= INSTR (4, 0);
8229 /* TODO : check that this rounds toward zero. */
8230 double d
= aarch64_get_FP_double (cpu
, sn
);
8233 value
= (int64_t) d
;
8235 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, LONG
);
8237 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8238 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, value
);
8242 do_fcvtzu (sim_cpu
*cpu
)
8244 /* instr[31] = size: 32-bit (0), 64-bit (1)
8245 instr[30,23] = 00111100
8246 instr[22] = type: single (0)/ double (1)
8247 instr[21] = enable (0)/disable(1) precision
8248 instr[20,16] = 11001
8249 instr[15,10] = precision
8253 unsigned rs
= INSTR (9, 5);
8254 unsigned rd
= INSTR (4, 0);
8256 NYI_assert (30, 23, 0x3C);
8257 NYI_assert (20, 16, 0x19);
8259 if (INSTR (21, 21) != 1)
8260 /* Convert to fixed point. */
8263 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8266 /* Convert to unsigned 64-bit integer. */
8269 double d
= aarch64_get_FP_double (cpu
, rs
);
8270 uint64_t value
= (uint64_t) d
;
8272 /* Do not raise an exception if we have reached ULONG_MAX. */
8273 if (value
!= (1UL << 63))
8274 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, ULONG
);
8276 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
8280 float f
= aarch64_get_FP_float (cpu
, rs
);
8281 uint64_t value
= (uint64_t) f
;
8283 /* Do not raise an exception if we have reached ULONG_MAX. */
8284 if (value
!= (1UL << 63))
8285 RAISE_EXCEPTIONS (f
, value
, FLOAT
, ULONG
);
8287 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
8294 /* Convert to unsigned 32-bit integer. */
8297 double d
= aarch64_get_FP_double (cpu
, rs
);
8299 value
= (uint32_t) d
;
8300 /* Do not raise an exception if we have reached UINT_MAX. */
8301 if (value
!= (1UL << 31))
8302 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, UINT
);
8306 float f
= aarch64_get_FP_float (cpu
, rs
);
8308 value
= (uint32_t) f
;
8309 /* Do not raise an exception if we have reached UINT_MAX. */
8310 if (value
!= (1UL << 31))
8311 RAISE_EXCEPTIONS (f
, value
, FLOAT
, UINT
);
8314 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
8319 do_UCVTF (sim_cpu
*cpu
)
8321 /* instr[31] = size: 32-bit (0), 64-bit (1)
8322 instr[30,23] = 001 1110 0
8323 instr[22] = type: single (0)/ double (1)
8324 instr[21] = enable (0)/disable(1) precision
8325 instr[20,16] = 0 0011
8326 instr[15,10] = precision
8330 unsigned rs
= INSTR (9, 5);
8331 unsigned rd
= INSTR (4, 0);
8333 NYI_assert (30, 23, 0x3C);
8334 NYI_assert (20, 16, 0x03);
8336 if (INSTR (21, 21) != 1)
8339 /* FIXME: Add exception raising. */
8340 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8343 uint64_t value
= aarch64_get_reg_u64 (cpu
, rs
, NO_SP
);
8346 aarch64_set_FP_double (cpu
, rd
, (double) value
);
8348 aarch64_set_FP_float (cpu
, rd
, (float) value
);
8352 uint32_t value
= aarch64_get_reg_u32 (cpu
, rs
, NO_SP
);
8355 aarch64_set_FP_double (cpu
, rd
, (double) value
);
8357 aarch64_set_FP_float (cpu
, rd
, (float) value
);
8362 float_vector_move (sim_cpu
*cpu
)
8364 /* instr[31,17] == 100 1111 0101 0111
8365 instr[16] ==> direction 0=> to GR, 1=> from GR
8367 instr[9,5] ==> source
8368 instr[4,0] ==> dest. */
8370 unsigned rn
= INSTR (9, 5);
8371 unsigned rd
= INSTR (4, 0);
8373 NYI_assert (31, 17, 0x4F57);
8375 if (INSTR (15, 10) != 0)
8378 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8380 aarch64_set_vec_u64 (cpu
, rd
, 1, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
8382 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, aarch64_get_vec_u64 (cpu
, rn
, 1));
8386 dexSimpleFPIntegerConvert (sim_cpu
*cpu
)
8388 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
8390 instr[29] = S : 0 ==> OK, 1 ==> UNALLOC
8393 instr[23,22] = type : 00 ==> single, 01 ==> double, 1x ==> UNALLOC
8395 instr[20,19] = rmode
8396 instr[18,16] = opcode
8397 instr[15,10] = 10 0000 */
8399 uint32_t rmode_opcode
;
8405 if (INSTR (31, 17) == 0x4F57)
8407 float_vector_move (cpu
);
8411 size
= INSTR (31, 31);
8416 type
= INSTR (23, 22);
8420 rmode_opcode
= INSTR (20, 16);
8421 size_type
= (size
<< 1) | type
; /* 0==32f, 1==32d, 2==64f, 3==64d. */
8423 switch (rmode_opcode
)
8425 case 2: /* SCVTF. */
8428 case 0: scvtf32 (cpu
); return;
8429 case 1: scvtd32 (cpu
); return;
8430 case 2: scvtf (cpu
); return;
8431 case 3: scvtd (cpu
); return;
8434 case 6: /* FMOV GR, Vec. */
8437 case 0: gfmovs (cpu
); return;
8438 case 3: gfmovd (cpu
); return;
8439 default: HALT_UNALLOC
;
8442 case 7: /* FMOV vec, GR. */
8445 case 0: fgmovs (cpu
); return;
8446 case 3: fgmovd (cpu
); return;
8447 default: HALT_UNALLOC
;
8450 case 24: /* FCVTZS. */
8453 case 0: fcvtszs32 (cpu
); return;
8454 case 1: fcvtszd32 (cpu
); return;
8455 case 2: fcvtszs (cpu
); return;
8456 case 3: fcvtszd (cpu
); return;
8459 case 25: do_fcvtzu (cpu
); return;
8460 case 3: do_UCVTF (cpu
); return;
8462 case 0: /* FCVTNS. */
8463 case 1: /* FCVTNU. */
8464 case 4: /* FCVTAS. */
8465 case 5: /* FCVTAU. */
8466 case 8: /* FCVPTS. */
8467 case 9: /* FCVTPU. */
8468 case 16: /* FCVTMS. */
8469 case 17: /* FCVTMU. */
8476 set_flags_for_float_compare (sim_cpu
*cpu
, float fvalue1
, float fvalue2
)
8480 /* FIXME: Add exception raising. */
8481 if (isnan (fvalue1
) || isnan (fvalue2
))
8483 else if (isinf (fvalue1
) && isinf (fvalue2
))
8485 /* Subtracting two infinities may give a NaN. We only need to compare
8486 the signs, which we can get from isinf. */
8487 int result
= isinf (fvalue1
) - isinf (fvalue2
);
8491 else if (result
< 0)
8493 else /* (result > 0). */
8498 float result
= fvalue1
- fvalue2
;
8502 else if (result
< 0)
8504 else /* (result > 0). */
8508 aarch64_set_CPSR (cpu
, flags
);
8512 fcmps (sim_cpu
*cpu
)
8514 unsigned sm
= INSTR (20, 16);
8515 unsigned sn
= INSTR ( 9, 5);
8517 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8518 float fvalue2
= aarch64_get_FP_float (cpu
, sm
);
8520 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8521 set_flags_for_float_compare (cpu
, fvalue1
, fvalue2
);
8524 /* Float compare to zero -- Invalid Operation exception
8525 only on signaling NaNs. */
8527 fcmpzs (sim_cpu
*cpu
)
8529 unsigned sn
= INSTR ( 9, 5);
8530 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8532 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8533 set_flags_for_float_compare (cpu
, fvalue1
, 0.0f
);
8536 /* Float compare -- Invalid Operation exception on all NaNs. */
8538 fcmpes (sim_cpu
*cpu
)
8540 unsigned sm
= INSTR (20, 16);
8541 unsigned sn
= INSTR ( 9, 5);
8543 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8544 float fvalue2
= aarch64_get_FP_float (cpu
, sm
);
8546 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8547 set_flags_for_float_compare (cpu
, fvalue1
, fvalue2
);
8550 /* Float compare to zero -- Invalid Operation exception on all NaNs. */
8552 fcmpzes (sim_cpu
*cpu
)
8554 unsigned sn
= INSTR ( 9, 5);
8555 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8557 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8558 set_flags_for_float_compare (cpu
, fvalue1
, 0.0f
);
8562 set_flags_for_double_compare (sim_cpu
*cpu
, double dval1
, double dval2
)
8566 /* FIXME: Add exception raising. */
8567 if (isnan (dval1
) || isnan (dval2
))
8569 else if (isinf (dval1
) && isinf (dval2
))
8571 /* Subtracting two infinities may give a NaN. We only need to compare
8572 the signs, which we can get from isinf. */
8573 int result
= isinf (dval1
) - isinf (dval2
);
8577 else if (result
< 0)
8579 else /* (result > 0). */
8584 double result
= dval1
- dval2
;
8588 else if (result
< 0)
8590 else /* (result > 0). */
8594 aarch64_set_CPSR (cpu
, flags
);
8597 /* Double compare -- Invalid Operation exception only on signaling NaNs. */
8599 fcmpd (sim_cpu
*cpu
)
8601 unsigned sm
= INSTR (20, 16);
8602 unsigned sn
= INSTR ( 9, 5);
8604 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8605 double dvalue2
= aarch64_get_FP_double (cpu
, sm
);
8607 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8608 set_flags_for_double_compare (cpu
, dvalue1
, dvalue2
);
8611 /* Double compare to zero -- Invalid Operation exception
8612 only on signaling NaNs. */
8614 fcmpzd (sim_cpu
*cpu
)
8616 unsigned sn
= INSTR ( 9, 5);
8617 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8619 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8620 set_flags_for_double_compare (cpu
, dvalue1
, 0.0);
8623 /* Double compare -- Invalid Operation exception on all NaNs. */
8625 fcmped (sim_cpu
*cpu
)
8627 unsigned sm
= INSTR (20, 16);
8628 unsigned sn
= INSTR ( 9, 5);
8630 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8631 double dvalue2
= aarch64_get_FP_double (cpu
, sm
);
8633 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8634 set_flags_for_double_compare (cpu
, dvalue1
, dvalue2
);
8637 /* Double compare to zero -- Invalid Operation exception on all NaNs. */
8639 fcmpzed (sim_cpu
*cpu
)
8641 unsigned sn
= INSTR ( 9, 5);
8642 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8644 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8645 set_flags_for_double_compare (cpu
, dvalue1
, 0.0);
8649 dexSimpleFPCompare (sim_cpu
*cpu
)
8651 /* assert instr[28,25] == 1111
8652 instr[30:24:21:13,10] = 0011000
8653 instr[31] = M : 0 ==> OK, 1 ==> UNALLOC
8654 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
8655 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
8656 instr[15,14] ==> op : 00 ==> OK, ow ==> UNALLOC
8657 instr[4,0] ==> opcode2 : 00000 ==> FCMP, 10000 ==> FCMPE,
8658 01000 ==> FCMPZ, 11000 ==> FCMPEZ,
8661 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
8662 uint32_t type
= INSTR (23, 22);
8663 uint32_t op
= INSTR (15, 14);
8664 uint32_t op2_2_0
= INSTR (2, 0);
8678 /* dispatch on type and top 2 bits of opcode. */
8679 dispatch
= (type
<< 2) | INSTR (4, 3);
8683 case 0: fcmps (cpu
); return;
8684 case 1: fcmpzs (cpu
); return;
8685 case 2: fcmpes (cpu
); return;
8686 case 3: fcmpzes (cpu
); return;
8687 case 4: fcmpd (cpu
); return;
8688 case 5: fcmpzd (cpu
); return;
8689 case 6: fcmped (cpu
); return;
8690 case 7: fcmpzed (cpu
); return;
8695 do_scalar_FADDP (sim_cpu
*cpu
)
8697 /* instr [31,23] = 0111 1110 0
8698 instr [22] = single(0)/double(1)
8699 instr [21,10] = 11 0000 1101 10
8701 instr [4,0] = Fd. */
8703 unsigned Fn
= INSTR (9, 5);
8704 unsigned Fd
= INSTR (4, 0);
8706 NYI_assert (31, 23, 0x0FC);
8707 NYI_assert (21, 10, 0xC36);
8709 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8712 double val1
= aarch64_get_vec_double (cpu
, Fn
, 0);
8713 double val2
= aarch64_get_vec_double (cpu
, Fn
, 1);
8715 aarch64_set_FP_double (cpu
, Fd
, val1
+ val2
);
8719 float val1
= aarch64_get_vec_float (cpu
, Fn
, 0);
8720 float val2
= aarch64_get_vec_float (cpu
, Fn
, 1);
8722 aarch64_set_FP_float (cpu
, Fd
, val1
+ val2
);
8726 /* Floating point absolute difference. */
8729 do_scalar_FABD (sim_cpu
*cpu
)
8731 /* instr [31,23] = 0111 1110 1
8732 instr [22] = float(0)/double(1)
8735 instr [15,10] = 1101 01
8737 instr [4, 0] = Rd. */
8739 unsigned rm
= INSTR (20, 16);
8740 unsigned rn
= INSTR (9, 5);
8741 unsigned rd
= INSTR (4, 0);
8743 NYI_assert (31, 23, 0x0FD);
8744 NYI_assert (21, 21, 1);
8745 NYI_assert (15, 10, 0x35);
8747 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8749 aarch64_set_FP_double (cpu
, rd
,
8750 fabs (aarch64_get_FP_double (cpu
, rn
)
8751 - aarch64_get_FP_double (cpu
, rm
)));
8753 aarch64_set_FP_float (cpu
, rd
,
8754 fabsf (aarch64_get_FP_float (cpu
, rn
)
8755 - aarch64_get_FP_float (cpu
, rm
)));
8759 do_scalar_CMGT (sim_cpu
*cpu
)
8761 /* instr [31,21] = 0101 1110 111
8763 instr [15,10] = 00 1101
8765 instr [4, 0] = Rd. */
8767 unsigned rm
= INSTR (20, 16);
8768 unsigned rn
= INSTR (9, 5);
8769 unsigned rd
= INSTR (4, 0);
8771 NYI_assert (31, 21, 0x2F7);
8772 NYI_assert (15, 10, 0x0D);
8774 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8775 aarch64_set_vec_u64 (cpu
, rd
, 0,
8776 aarch64_get_vec_u64 (cpu
, rn
, 0) >
8777 aarch64_get_vec_u64 (cpu
, rm
, 0) ? -1L : 0L);
8781 do_scalar_USHR (sim_cpu
*cpu
)
8783 /* instr [31,23] = 0111 1111 0
8784 instr [22,16] = shift amount
8785 instr [15,10] = 0000 01
8787 instr [4, 0] = Rd. */
8789 unsigned amount
= 128 - INSTR (22, 16);
8790 unsigned rn
= INSTR (9, 5);
8791 unsigned rd
= INSTR (4, 0);
8793 NYI_assert (31, 23, 0x0FE);
8794 NYI_assert (15, 10, 0x01);
8796 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8797 aarch64_set_vec_u64 (cpu
, rd
, 0,
8798 aarch64_get_vec_u64 (cpu
, rn
, 0) >> amount
);
8802 do_scalar_SSHL (sim_cpu
*cpu
)
8804 /* instr [31,21] = 0101 1110 111
8806 instr [15,10] = 0100 01
8808 instr [4, 0] = Rd. */
8810 unsigned rm
= INSTR (20, 16);
8811 unsigned rn
= INSTR (9, 5);
8812 unsigned rd
= INSTR (4, 0);
8813 signed int shift
= aarch64_get_vec_s8 (cpu
, rm
, 0);
8815 NYI_assert (31, 21, 0x2F7);
8816 NYI_assert (15, 10, 0x11);
8818 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8820 aarch64_set_vec_s64 (cpu
, rd
, 0,
8821 aarch64_get_vec_s64 (cpu
, rn
, 0) << shift
);
8823 aarch64_set_vec_s64 (cpu
, rd
, 0,
8824 aarch64_get_vec_s64 (cpu
, rn
, 0) >> - shift
);
8828 do_scalar_shift (sim_cpu
*cpu
)
8830 /* instr [31,23] = 0101 1111 0
8831 instr [22,16] = shift amount
8832 instr [15,10] = 0101 01 [SHL]
8833 instr [15,10] = 0000 01 [SSHR]
8835 instr [4, 0] = Rd. */
8837 unsigned rn
= INSTR (9, 5);
8838 unsigned rd
= INSTR (4, 0);
8841 NYI_assert (31, 23, 0x0BE);
8843 if (INSTR (22, 22) == 0)
8846 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8847 switch (INSTR (15, 10))
8849 case 0x01: /* SSHR */
8850 amount
= 128 - INSTR (22, 16);
8851 aarch64_set_vec_s64 (cpu
, rd
, 0,
8852 aarch64_get_vec_s64 (cpu
, rn
, 0) >> amount
);
8854 case 0x15: /* SHL */
8855 amount
= INSTR (22, 16) - 64;
8856 aarch64_set_vec_u64 (cpu
, rd
, 0,
8857 aarch64_get_vec_u64 (cpu
, rn
, 0) << amount
);
8864 /* FCMEQ FCMGT FCMGE. */
8866 do_scalar_FCM (sim_cpu
*cpu
)
8868 /* instr [31,30] = 01
8870 instr [28,24] = 1 1110
8875 instr [15,12] = 1110
8879 instr [4, 0] = Rd. */
8881 unsigned rm
= INSTR (20, 16);
8882 unsigned rn
= INSTR (9, 5);
8883 unsigned rd
= INSTR (4, 0);
8884 unsigned EUac
= (INSTR (23, 23) << 2) | (INSTR (29, 29) << 1) | INSTR (11, 11);
8889 NYI_assert (31, 30, 1);
8890 NYI_assert (28, 24, 0x1E);
8891 NYI_assert (21, 21, 1);
8892 NYI_assert (15, 12, 0xE);
8893 NYI_assert (10, 10, 1);
8895 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8898 double val1
= aarch64_get_FP_double (cpu
, rn
);
8899 double val2
= aarch64_get_FP_double (cpu
, rm
);
8904 result
= val1
== val2
;
8912 result
= val1
>= val2
;
8920 result
= val1
> val2
;
8927 aarch64_set_vec_u32 (cpu
, rd
, 0, result
? -1 : 0);
8931 val1
= aarch64_get_FP_float (cpu
, rn
);
8932 val2
= aarch64_get_FP_float (cpu
, rm
);
8937 result
= val1
== val2
;
8941 val1
= fabsf (val1
);
8942 val2
= fabsf (val2
);
8945 result
= val1
>= val2
;
8949 val1
= fabsf (val1
);
8950 val2
= fabsf (val2
);
8953 result
= val1
> val2
;
8960 aarch64_set_vec_u32 (cpu
, rd
, 0, result
? -1 : 0);
8963 /* An alias of DUP. */
8965 do_scalar_MOV (sim_cpu
*cpu
)
8967 /* instr [31,21] = 0101 1110 000
8968 instr [20,16] = imm5
8969 instr [15,10] = 0000 01
8971 instr [4, 0] = Rd. */
8973 unsigned rn
= INSTR (9, 5);
8974 unsigned rd
= INSTR (4, 0);
8977 NYI_assert (31, 21, 0x2F0);
8978 NYI_assert (15, 10, 0x01);
8980 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8984 index
= INSTR (20, 17);
8986 (cpu
, rd
, 0, aarch64_get_vec_u8 (cpu
, rn
, index
));
8988 else if (INSTR (17, 17))
8991 index
= INSTR (20, 18);
8993 (cpu
, rd
, 0, aarch64_get_vec_u16 (cpu
, rn
, index
));
8995 else if (INSTR (18, 18))
8998 index
= INSTR (20, 19);
9000 (cpu
, rd
, 0, aarch64_get_vec_u32 (cpu
, rn
, index
));
9002 else if (INSTR (19, 19))
9005 index
= INSTR (20, 20);
9007 (cpu
, rd
, 0, aarch64_get_vec_u64 (cpu
, rn
, index
));
9014 do_scalar_NEG (sim_cpu
*cpu
)
9016 /* instr [31,10] = 0111 1110 1110 0000 1011 10
9018 instr [4, 0] = Rd. */
9020 unsigned rn
= INSTR (9, 5);
9021 unsigned rd
= INSTR (4, 0);
9023 NYI_assert (31, 10, 0x1FB82E);
9025 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9026 aarch64_set_vec_u64 (cpu
, rd
, 0, - aarch64_get_vec_u64 (cpu
, rn
, 0));
9030 do_scalar_USHL (sim_cpu
*cpu
)
9032 /* instr [31,21] = 0111 1110 111
9034 instr [15,10] = 0100 01
9036 instr [4, 0] = Rd. */
9038 unsigned rm
= INSTR (20, 16);
9039 unsigned rn
= INSTR (9, 5);
9040 unsigned rd
= INSTR (4, 0);
9041 signed int shift
= aarch64_get_vec_s8 (cpu
, rm
, 0);
9043 NYI_assert (31, 21, 0x3F7);
9044 NYI_assert (15, 10, 0x11);
9046 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9048 aarch64_set_vec_u64 (cpu
, rd
, 0, aarch64_get_vec_u64 (cpu
, rn
, 0) << shift
);
9050 aarch64_set_vec_u64 (cpu
, rd
, 0, aarch64_get_vec_u64 (cpu
, rn
, 0) >> - shift
);
9054 do_double_add (sim_cpu
*cpu
)
9056 /* instr [31,21] = 0101 1110 111
9058 instr [15,10] = 1000 01
9060 instr [4,0] = Fd. */
9067 NYI_assert (31, 21, 0x2F7);
9068 NYI_assert (15, 10, 0x21);
9072 Fn
= INSTR (20, 16);
9074 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9075 val1
= aarch64_get_FP_double (cpu
, Fm
);
9076 val2
= aarch64_get_FP_double (cpu
, Fn
);
9078 aarch64_set_FP_double (cpu
, Fd
, val1
+ val2
);
9082 do_scalar_UCVTF (sim_cpu
*cpu
)
9084 /* instr [31,23] = 0111 1110 0
9085 instr [22] = single(0)/double(1)
9086 instr [21,10] = 10 0001 1101 10
9088 instr [4,0] = rd. */
9090 unsigned rn
= INSTR (9, 5);
9091 unsigned rd
= INSTR (4, 0);
9093 NYI_assert (31, 23, 0x0FC);
9094 NYI_assert (21, 10, 0x876);
9096 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9099 uint64_t val
= aarch64_get_vec_u64 (cpu
, rn
, 0);
9101 aarch64_set_vec_double (cpu
, rd
, 0, (double) val
);
9105 uint32_t val
= aarch64_get_vec_u32 (cpu
, rn
, 0);
9107 aarch64_set_vec_float (cpu
, rd
, 0, (float) val
);
9112 do_scalar_vec (sim_cpu
*cpu
)
9114 /* instr [30] = 1. */
9115 /* instr [28,25] = 1111. */
9116 switch (INSTR (31, 23))
9119 switch (INSTR (15, 10))
9121 case 0x01: do_scalar_MOV (cpu
); return;
9122 case 0x39: do_scalar_FCM (cpu
); return;
9123 case 0x3B: do_scalar_FCM (cpu
); return;
9127 case 0xBE: do_scalar_shift (cpu
); return;
9130 switch (INSTR (15, 10))
9133 switch (INSTR (21, 16))
9135 case 0x30: do_scalar_FADDP (cpu
); return;
9136 case 0x21: do_scalar_UCVTF (cpu
); return;
9139 case 0x39: do_scalar_FCM (cpu
); return;
9140 case 0x3B: do_scalar_FCM (cpu
); return;
9145 switch (INSTR (15, 10))
9147 case 0x0D: do_scalar_CMGT (cpu
); return;
9148 case 0x11: do_scalar_USHL (cpu
); return;
9149 case 0x2E: do_scalar_NEG (cpu
); return;
9150 case 0x35: do_scalar_FABD (cpu
); return;
9151 case 0x39: do_scalar_FCM (cpu
); return;
9152 case 0x3B: do_scalar_FCM (cpu
); return;
9157 case 0xFE: do_scalar_USHR (cpu
); return;
9160 switch (INSTR (15, 10))
9162 case 0x21: do_double_add (cpu
); return;
9163 case 0x11: do_scalar_SSHL (cpu
); return;
9174 dexAdvSIMD1 (sim_cpu
*cpu
)
9176 /* instr [28,25] = 1 111. */
9178 /* We are currently only interested in the basic
9179 scalar fp routines which all have bit 30 = 0. */
9181 do_scalar_vec (cpu
);
9183 /* instr[24] is set for FP data processing 3-source and clear for
9184 all other basic scalar fp instruction groups. */
9185 else if (INSTR (24, 24))
9186 dexSimpleFPDataProc3Source (cpu
);
9188 /* instr[21] is clear for floating <-> fixed conversions and set for
9189 all other basic scalar fp instruction groups. */
9190 else if (!INSTR (21, 21))
9191 dexSimpleFPFixedConvert (cpu
);
9193 /* instr[11,10] : 01 ==> cond compare, 10 ==> Data Proc 2 Source
9194 11 ==> cond select, 00 ==> other. */
9196 switch (INSTR (11, 10))
9198 case 1: dexSimpleFPCondCompare (cpu
); return;
9199 case 2: dexSimpleFPDataProc2Source (cpu
); return;
9200 case 3: dexSimpleFPCondSelect (cpu
); return;
9203 /* Now an ordered cascade of tests.
9204 FP immediate has instr [12] == 1.
9205 FP compare has instr [13] == 1.
9206 FP Data Proc 1 Source has instr [14] == 1.
9207 FP floating <--> integer conversions has instr [15] == 0. */
9209 dexSimpleFPImmediate (cpu
);
9211 else if (INSTR (13, 13))
9212 dexSimpleFPCompare (cpu
);
9214 else if (INSTR (14, 14))
9215 dexSimpleFPDataProc1Source (cpu
);
9217 else if (!INSTR (15, 15))
9218 dexSimpleFPIntegerConvert (cpu
);
9221 /* If we get here then instr[15] == 1 which means UNALLOC. */
9226 /* PC relative addressing. */
9229 pcadr (sim_cpu
*cpu
)
9231 /* instr[31] = op : 0 ==> ADR, 1 ==> ADRP
9232 instr[30,29] = immlo
9233 instr[23,5] = immhi. */
9235 unsigned rd
= INSTR (4, 0);
9236 uint32_t isPage
= INSTR (31, 31);
9237 union { int64_t u64
; uint64_t s64
; } imm
;
9240 imm
.s64
= simm64 (aarch64_get_instr (cpu
), 23, 5);
9242 offset
= (offset
<< 2) | INSTR (30, 29);
9244 address
= aarch64_get_PC (cpu
);
9252 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9253 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, address
+ offset
);
9256 /* Specific decode and execute for group Data Processing Immediate. */
9259 dexPCRelAddressing (sim_cpu
*cpu
)
9261 /* assert instr[28,24] = 10000. */
9265 /* Immediate logical.
9266 The bimm32/64 argument is constructed by replicating a 2, 4, 8,
9267 16, 32 or 64 bit sequence pulled out at decode and possibly
9270 N.B. the output register (dest) can normally be Xn or SP
9271 the exception occurs for flag setting instructions which may
9272 only use Xn for the output (dest). The input register can
9275 /* 32 bit and immediate. */
9277 and32 (sim_cpu
*cpu
, uint32_t bimm
)
9279 unsigned rn
= INSTR (9, 5);
9280 unsigned rd
= INSTR (4, 0);
9282 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9283 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9284 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
) & bimm
);
9287 /* 64 bit and immediate. */
9289 and64 (sim_cpu
*cpu
, uint64_t bimm
)
9291 unsigned rn
= INSTR (9, 5);
9292 unsigned rd
= INSTR (4, 0);
9294 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9295 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9296 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) & bimm
);
9299 /* 32 bit and immediate set flags. */
9301 ands32 (sim_cpu
*cpu
, uint32_t bimm
)
9303 unsigned rn
= INSTR (9, 5);
9304 unsigned rd
= INSTR (4, 0);
9306 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9307 uint32_t value2
= bimm
;
9309 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9310 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9311 set_flags_for_binop32 (cpu
, value1
& value2
);
9314 /* 64 bit and immediate set flags. */
9316 ands64 (sim_cpu
*cpu
, uint64_t bimm
)
9318 unsigned rn
= INSTR (9, 5);
9319 unsigned rd
= INSTR (4, 0);
9321 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9322 uint64_t value2
= bimm
;
9324 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9325 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9326 set_flags_for_binop64 (cpu
, value1
& value2
);
9329 /* 32 bit exclusive or immediate. */
9331 eor32 (sim_cpu
*cpu
, uint32_t bimm
)
9333 unsigned rn
= INSTR (9, 5);
9334 unsigned rd
= INSTR (4, 0);
9336 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9337 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9338 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
) ^ bimm
);
9341 /* 64 bit exclusive or immediate. */
9343 eor64 (sim_cpu
*cpu
, uint64_t bimm
)
9345 unsigned rn
= INSTR (9, 5);
9346 unsigned rd
= INSTR (4, 0);
9348 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9349 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9350 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) ^ bimm
);
9353 /* 32 bit or immediate. */
9355 orr32 (sim_cpu
*cpu
, uint32_t bimm
)
9357 unsigned rn
= INSTR (9, 5);
9358 unsigned rd
= INSTR (4, 0);
9360 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9361 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9362 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
) | bimm
);
9365 /* 64 bit or immediate. */
9367 orr64 (sim_cpu
*cpu
, uint64_t bimm
)
9369 unsigned rn
= INSTR (9, 5);
9370 unsigned rd
= INSTR (4, 0);
9372 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9373 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9374 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) | bimm
);
9377 /* Logical shifted register.
9378 These allow an optional LSL, ASR, LSR or ROR to the second source
9379 register with a count up to the register bit count.
9380 N.B register args may not be SP. */
9382 /* 32 bit AND shifted register. */
9384 and32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9386 unsigned rm
= INSTR (20, 16);
9387 unsigned rn
= INSTR (9, 5);
9388 unsigned rd
= INSTR (4, 0);
9390 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9392 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9393 & shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9396 /* 64 bit AND shifted register. */
9398 and64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9400 unsigned rm
= INSTR (20, 16);
9401 unsigned rn
= INSTR (9, 5);
9402 unsigned rd
= INSTR (4, 0);
9404 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9406 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9407 & shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9410 /* 32 bit AND shifted register setting flags. */
9412 ands32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9414 unsigned rm
= INSTR (20, 16);
9415 unsigned rn
= INSTR (9, 5);
9416 unsigned rd
= INSTR (4, 0);
9418 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9419 uint32_t value2
= shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
9422 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9423 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9424 set_flags_for_binop32 (cpu
, value1
& value2
);
9427 /* 64 bit AND shifted register setting flags. */
9429 ands64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9431 unsigned rm
= INSTR (20, 16);
9432 unsigned rn
= INSTR (9, 5);
9433 unsigned rd
= INSTR (4, 0);
9435 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9436 uint64_t value2
= shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
9439 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9440 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9441 set_flags_for_binop64 (cpu
, value1
& value2
);
9444 /* 32 bit BIC shifted register. */
9446 bic32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9448 unsigned rm
= INSTR (20, 16);
9449 unsigned rn
= INSTR (9, 5);
9450 unsigned rd
= INSTR (4, 0);
9452 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9454 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9455 & ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9458 /* 64 bit BIC shifted register. */
9460 bic64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9462 unsigned rm
= INSTR (20, 16);
9463 unsigned rn
= INSTR (9, 5);
9464 unsigned rd
= INSTR (4, 0);
9466 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9468 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9469 & ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9472 /* 32 bit BIC shifted register setting flags. */
9474 bics32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9476 unsigned rm
= INSTR (20, 16);
9477 unsigned rn
= INSTR (9, 5);
9478 unsigned rd
= INSTR (4, 0);
9480 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9481 uint32_t value2
= ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
9484 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9485 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9486 set_flags_for_binop32 (cpu
, value1
& value2
);
9489 /* 64 bit BIC shifted register setting flags. */
9491 bics64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9493 unsigned rm
= INSTR (20, 16);
9494 unsigned rn
= INSTR (9, 5);
9495 unsigned rd
= INSTR (4, 0);
9497 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9498 uint64_t value2
= ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
9501 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9502 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9503 set_flags_for_binop64 (cpu
, value1
& value2
);
9506 /* 32 bit EON shifted register. */
9508 eon32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9510 unsigned rm
= INSTR (20, 16);
9511 unsigned rn
= INSTR (9, 5);
9512 unsigned rd
= INSTR (4, 0);
9514 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9516 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9517 ^ ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9520 /* 64 bit EON shifted register. */
9522 eon64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9524 unsigned rm
= INSTR (20, 16);
9525 unsigned rn
= INSTR (9, 5);
9526 unsigned rd
= INSTR (4, 0);
9528 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9530 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9531 ^ ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9534 /* 32 bit EOR shifted register. */
9536 eor32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9538 unsigned rm
= INSTR (20, 16);
9539 unsigned rn
= INSTR (9, 5);
9540 unsigned rd
= INSTR (4, 0);
9542 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9544 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9545 ^ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9548 /* 64 bit EOR shifted register. */
9550 eor64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9552 unsigned rm
= INSTR (20, 16);
9553 unsigned rn
= INSTR (9, 5);
9554 unsigned rd
= INSTR (4, 0);
9556 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9558 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9559 ^ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9562 /* 32 bit ORR shifted register. */
9564 orr32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9566 unsigned rm
= INSTR (20, 16);
9567 unsigned rn
= INSTR (9, 5);
9568 unsigned rd
= INSTR (4, 0);
9570 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9572 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9573 | shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9576 /* 64 bit ORR shifted register. */
9578 orr64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9580 unsigned rm
= INSTR (20, 16);
9581 unsigned rn
= INSTR (9, 5);
9582 unsigned rd
= INSTR (4, 0);
9584 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9586 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9587 | shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9590 /* 32 bit ORN shifted register. */
9592 orn32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9594 unsigned rm
= INSTR (20, 16);
9595 unsigned rn
= INSTR (9, 5);
9596 unsigned rd
= INSTR (4, 0);
9598 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9600 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9601 | ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9604 /* 64 bit ORN shifted register. */
9606 orn64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9608 unsigned rm
= INSTR (20, 16);
9609 unsigned rn
= INSTR (9, 5);
9610 unsigned rd
= INSTR (4, 0);
9612 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9614 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9615 | ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9619 dexLogicalImmediate (sim_cpu
*cpu
)
9621 /* assert instr[28,23] = 1001000
9622 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9623 instr[30,29] = op : 0 ==> AND, 1 ==> ORR, 2 ==> EOR, 3 ==> ANDS
9624 instr[22] = N : used to construct immediate mask
9630 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
9631 uint32_t size
= INSTR (31, 31);
9632 uint32_t N
= INSTR (22, 22);
9633 /* uint32_t immr = INSTR (21, 16);. */
9634 /* uint32_t imms = INSTR (15, 10);. */
9635 uint32_t index
= INSTR (22, 10);
9636 uint64_t bimm64
= LITable
[index
];
9637 uint32_t dispatch
= INSTR (30, 29);
9647 uint32_t bimm
= (uint32_t) bimm64
;
9651 case 0: and32 (cpu
, bimm
); return;
9652 case 1: orr32 (cpu
, bimm
); return;
9653 case 2: eor32 (cpu
, bimm
); return;
9654 case 3: ands32 (cpu
, bimm
); return;
9661 case 0: and64 (cpu
, bimm64
); return;
9662 case 1: orr64 (cpu
, bimm64
); return;
9663 case 2: eor64 (cpu
, bimm64
); return;
9664 case 3: ands64 (cpu
, bimm64
); return;
9671 The uimm argument is a 16 bit value to be inserted into the
9672 target register the pos argument locates the 16 bit word in the
9673 dest register i.e. it is in {0, 1} for 32 bit and {0, 1, 2,
9675 N.B register arg may not be SP so it should be.
9676 accessed using the setGZRegisterXXX accessors. */
9678 /* 32 bit move 16 bit immediate zero remaining shorts. */
9680 movz32 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9682 unsigned rd
= INSTR (4, 0);
9684 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9685 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val
<< (pos
* 16));
9688 /* 64 bit move 16 bit immediate zero remaining shorts. */
9690 movz64 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9692 unsigned rd
= INSTR (4, 0);
9694 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9695 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, ((uint64_t) val
) << (pos
* 16));
9698 /* 32 bit move 16 bit immediate negated. */
9700 movn32 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9702 unsigned rd
= INSTR (4, 0);
9704 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9705 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, ((val
<< (pos
* 16)) ^ 0xffffffffU
));
9708 /* 64 bit move 16 bit immediate negated. */
9710 movn64 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9712 unsigned rd
= INSTR (4, 0);
9714 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9716 (cpu
, rd
, NO_SP
, ((((uint64_t) val
) << (pos
* 16))
9717 ^ 0xffffffffffffffffULL
));
9720 /* 32 bit move 16 bit immediate keep remaining shorts. */
9722 movk32 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9724 unsigned rd
= INSTR (4, 0);
9725 uint32_t current
= aarch64_get_reg_u32 (cpu
, rd
, NO_SP
);
9726 uint32_t value
= val
<< (pos
* 16);
9727 uint32_t mask
= ~(0xffffU
<< (pos
* 16));
9729 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9730 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (value
| (current
& mask
)));
9733 /* 64 bit move 16 it immediate keep remaining shorts. */
9735 movk64 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9737 unsigned rd
= INSTR (4, 0);
9738 uint64_t current
= aarch64_get_reg_u64 (cpu
, rd
, NO_SP
);
9739 uint64_t value
= (uint64_t) val
<< (pos
* 16);
9740 uint64_t mask
= ~(0xffffULL
<< (pos
* 16));
9742 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9743 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (value
| (current
& mask
)));
9747 dexMoveWideImmediate (sim_cpu
*cpu
)
9749 /* assert instr[28:23] = 100101
9750 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9751 instr[30,29] = op : 0 ==> MOVN, 1 ==> UNALLOC, 2 ==> MOVZ, 3 ==> MOVK
9752 instr[22,21] = shift : 00 == LSL#0, 01 = LSL#16, 10 = LSL#32, 11 = LSL#48
9753 instr[20,5] = uimm16
9756 /* N.B. the (multiple of 16) shift is applied by the called routine,
9757 we just pass the multiplier. */
9760 uint32_t size
= INSTR (31, 31);
9761 uint32_t op
= INSTR (30, 29);
9762 uint32_t shift
= INSTR (22, 21);
9764 /* 32 bit can only shift 0 or 1 lot of 16.
9765 anything else is an unallocated instruction. */
9766 if (size
== 0 && (shift
> 1))
9772 imm
= INSTR (20, 5);
9777 movn32 (cpu
, imm
, shift
);
9779 movz32 (cpu
, imm
, shift
);
9781 movk32 (cpu
, imm
, shift
);
9786 movn64 (cpu
, imm
, shift
);
9788 movz64 (cpu
, imm
, shift
);
9790 movk64 (cpu
, imm
, shift
);
9794 /* Bitfield operations.
9795 These take a pair of bit positions r and s which are in {0..31}
9796 or {0..63} depending on the instruction word size.
9797 N.B register args may not be SP. */
9799 /* OK, we start with ubfm which just needs to pick
9800 some bits out of source zero the rest and write
9801 the result to dest. Just need two logical shifts. */
9803 /* 32 bit bitfield move, left and right of affected zeroed
9804 if r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
9806 ubfm32 (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9809 unsigned rn
= INSTR (9, 5);
9810 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9812 /* Pick either s+1-r or s+1 consecutive bits out of the original word. */
9815 /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
9816 We want only bits s:xxx:r at the bottom of the word
9817 so we LSL bit s up to bit 31 i.e. by 31 - s
9818 and then we LSR to bring bit 31 down to bit s - r
9819 i.e. by 31 + r - s. */
9821 value
>>= 31 + r
- s
;
9825 /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0
9826 We want only bits s:xxx:0 starting at it 31-(r-1)
9827 so we LSL bit s up to bit 31 i.e. by 31 - s
9828 and then we LSL to bring bit 31 down to 31-(r-1)+s
9829 i.e. by r - (s + 1). */
9831 value
>>= r
- (s
+ 1);
9834 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9836 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
9839 /* 64 bit bitfield move, left and right of affected zeroed
9840 if r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
9842 ubfm (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9845 unsigned rn
= INSTR (9, 5);
9846 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9850 /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
9851 We want only bits s:xxx:r at the bottom of the word.
9852 So we LSL bit s up to bit 63 i.e. by 63 - s
9853 and then we LSR to bring bit 63 down to bit s - r
9854 i.e. by 63 + r - s. */
9856 value
>>= 63 + r
- s
;
9860 /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0.
9861 We want only bits s:xxx:0 starting at it 63-(r-1).
9862 So we LSL bit s up to bit 63 i.e. by 63 - s
9863 and then we LSL to bring bit 63 down to 63-(r-1)+s
9864 i.e. by r - (s + 1). */
9866 value
>>= r
- (s
+ 1);
9869 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9871 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
9874 /* The signed versions need to insert sign bits
9875 on the left of the inserted bit field. so we do
9876 much the same as the unsigned version except we
9877 use an arithmetic shift right -- this just means
9878 we need to operate on signed values. */
9880 /* 32 bit bitfield move, left of affected sign-extended, right zeroed. */
9881 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
9883 sbfm32 (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9886 unsigned rn
= INSTR (9, 5);
9887 /* as per ubfm32 but use an ASR instead of an LSR. */
9888 int32_t value
= aarch64_get_reg_s32 (cpu
, rn
, NO_SP
);
9893 value
>>= 31 + r
- s
;
9898 value
>>= r
- (s
+ 1);
9901 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9903 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) value
);
9906 /* 64 bit bitfield move, left of affected sign-extended, right zeroed. */
9907 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
9909 sbfm (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9912 unsigned rn
= INSTR (9, 5);
9913 /* acpu per ubfm but use an ASR instead of an LSR. */
9914 int64_t value
= aarch64_get_reg_s64 (cpu
, rn
, NO_SP
);
9919 value
>>= 63 + r
- s
;
9924 value
>>= r
- (s
+ 1);
9927 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9929 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, value
);
9932 /* Finally, these versions leave non-affected bits
9933 as is. so we need to generate the bits as per
9934 ubfm and also generate a mask to pick the
9935 bits from the original and computed values. */
9937 /* 32 bit bitfield move, non-affected bits left as is.
9938 If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
9940 bfm32 (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9942 unsigned rn
= INSTR (9, 5);
9943 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9948 /* Pick either s+1-r or s+1 consecutive bits out of the original word. */
9951 /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
9952 We want only bits s:xxx:r at the bottom of the word
9953 so we LSL bit s up to bit 31 i.e. by 31 - s
9954 and then we LSR to bring bit 31 down to bit s - r
9955 i.e. by 31 + r - s. */
9957 value
>>= 31 + r
- s
;
9958 /* the mask must include the same bits. */
9960 mask
>>= 31 + r
- s
;
9964 /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0.
9965 We want only bits s:xxx:0 starting at it 31-(r-1)
9966 so we LSL bit s up to bit 31 i.e. by 31 - s
9967 and then we LSL to bring bit 31 down to 31-(r-1)+s
9968 i.e. by r - (s + 1). */
9970 value
>>= r
- (s
+ 1);
9971 /* The mask must include the same bits. */
9973 mask
>>= r
- (s
+ 1);
9977 value2
= aarch64_get_reg_u32 (cpu
, rd
, NO_SP
);
9982 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9984 (cpu
, rd
, NO_SP
, (aarch64_get_reg_u32 (cpu
, rd
, NO_SP
) & ~mask
) | value
);
9987 /* 64 bit bitfield move, non-affected bits left as is.
9988 If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
9990 bfm (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9993 unsigned rn
= INSTR (9, 5);
9994 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9995 uint64_t mask
= 0xffffffffffffffffULL
;
9999 /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
10000 We want only bits s:xxx:r at the bottom of the word
10001 so we LSL bit s up to bit 63 i.e. by 63 - s
10002 and then we LSR to bring bit 63 down to bit s - r
10003 i.e. by 63 + r - s. */
10005 value
>>= 63 + r
- s
;
10006 /* The mask must include the same bits. */
10008 mask
>>= 63 + r
- s
;
10012 /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0
10013 We want only bits s:xxx:0 starting at it 63-(r-1)
10014 so we LSL bit s up to bit 63 i.e. by 63 - s
10015 and then we LSL to bring bit 63 down to 63-(r-1)+s
10016 i.e. by r - (s + 1). */
10018 value
>>= r
- (s
+ 1);
10019 /* The mask must include the same bits. */
10021 mask
>>= r
- (s
+ 1);
10024 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10026 aarch64_set_reg_u64
10027 (cpu
, rd
, NO_SP
, (aarch64_get_reg_u64 (cpu
, rd
, NO_SP
) & ~mask
) | value
);
10031 dexBitfieldImmediate (sim_cpu
*cpu
)
10033 /* assert instr[28:23] = 100110
10034 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
10035 instr[30,29] = op : 0 ==> SBFM, 1 ==> BFM, 2 ==> UBFM, 3 ==> UNALLOC
10036 instr[22] = N : must be 0 for 32 bit, 1 for 64 bit ow UNALLOC
10037 instr[21,16] = immr : 0xxxxx for 32 bit, xxxxxx for 64 bit
10038 instr[15,10] = imms : 0xxxxx for 32 bit, xxxxxx for 64 bit
10042 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
10045 uint32_t size
= INSTR (31, 31);
10046 uint32_t N
= INSTR (22, 22);
10047 /* 32 bit operations must have immr[5] = 0 and imms[5] = 0. */
10048 /* or else we have an UNALLOC. */
10049 uint32_t immr
= INSTR (21, 16);
10054 if (!size
&& uimm (immr
, 5, 5))
10057 imms
= INSTR (15, 10);
10058 if (!size
&& uimm (imms
, 5, 5))
10061 /* Switch on combined size and op. */
10062 dispatch
= INSTR (31, 29);
10065 case 0: sbfm32 (cpu
, immr
, imms
); return;
10066 case 1: bfm32 (cpu
, immr
, imms
); return;
10067 case 2: ubfm32 (cpu
, immr
, imms
); return;
10068 case 4: sbfm (cpu
, immr
, imms
); return;
10069 case 5: bfm (cpu
, immr
, imms
); return;
10070 case 6: ubfm (cpu
, immr
, imms
); return;
10071 default: HALT_UNALLOC
;
10076 do_EXTR_32 (sim_cpu
*cpu
)
10078 /* instr[31:21] = 00010011100
10080 instr[15,10] = imms : 0xxxxx for 32 bit
10083 unsigned rm
= INSTR (20, 16);
10084 unsigned imms
= INSTR (15, 10) & 31;
10085 unsigned rn
= INSTR ( 9, 5);
10086 unsigned rd
= INSTR ( 4, 0);
10090 val1
= aarch64_get_reg_u32 (cpu
, rm
, NO_SP
);
10092 val2
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
10093 val2
<<= (32 - imms
);
10095 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10096 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val1
| val2
);
10100 do_EXTR_64 (sim_cpu
*cpu
)
10102 /* instr[31:21] = 10010011100
10104 instr[15,10] = imms
10107 unsigned rm
= INSTR (20, 16);
10108 unsigned imms
= INSTR (15, 10) & 63;
10109 unsigned rn
= INSTR ( 9, 5);
10110 unsigned rd
= INSTR ( 4, 0);
10113 val
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
10115 val
|= (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) << (64 - imms
));
10117 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val
);
10121 dexExtractImmediate (sim_cpu
*cpu
)
10123 /* assert instr[28:23] = 100111
10124 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
10125 instr[30,29] = op21 : 0 ==> EXTR, 1,2,3 ==> UNALLOC
10126 instr[22] = N : must be 0 for 32 bit, 1 for 64 bit or UNALLOC
10127 instr[21] = op0 : must be 0 or UNALLOC
10129 instr[15,10] = imms : 0xxxxx for 32 bit, xxxxxx for 64 bit
10133 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
10134 /* 64 bit operations must have N = 1 or else we have an UNALLOC. */
10136 uint32_t size
= INSTR (31, 31);
10137 uint32_t N
= INSTR (22, 22);
10138 /* 32 bit operations must have imms[5] = 0
10139 or else we have an UNALLOC. */
10140 uint32_t imms
= INSTR (15, 10);
10145 if (!size
&& uimm (imms
, 5, 5))
10148 /* Switch on combined size and op. */
10149 dispatch
= INSTR (31, 29);
10154 else if (dispatch
== 4)
10157 else if (dispatch
== 1)
10164 dexDPImm (sim_cpu
*cpu
)
10166 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
10167 assert group == GROUP_DPIMM_1000 || grpoup == GROUP_DPIMM_1001
10168 bits [25,23] of a DPImm are the secondary dispatch vector. */
10169 uint32_t group2
= dispatchDPImm (aarch64_get_instr (cpu
));
10173 case DPIMM_PCADR_000
:
10174 case DPIMM_PCADR_001
:
10175 dexPCRelAddressing (cpu
);
10178 case DPIMM_ADDSUB_010
:
10179 case DPIMM_ADDSUB_011
:
10180 dexAddSubtractImmediate (cpu
);
10183 case DPIMM_LOG_100
:
10184 dexLogicalImmediate (cpu
);
10187 case DPIMM_MOV_101
:
10188 dexMoveWideImmediate (cpu
);
10191 case DPIMM_BITF_110
:
10192 dexBitfieldImmediate (cpu
);
10195 case DPIMM_EXTR_111
:
10196 dexExtractImmediate (cpu
);
10200 /* Should never reach here. */
10206 dexLoadUnscaledImmediate (sim_cpu
*cpu
)
10208 /* instr[29,24] == 111_00
10211 instr[31,30] = size
10214 instr[20,12] = simm9
10215 instr[9,5] = rn may be SP. */
10216 /* unsigned rt = INSTR (4, 0); */
10217 uint32_t V
= INSTR (26, 26);
10218 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
10219 int32_t imm
= simm32 (aarch64_get_instr (cpu
), 20, 12);
10223 /* GReg operations. */
10226 case 0: sturb (cpu
, imm
); return;
10227 case 1: ldurb32 (cpu
, imm
); return;
10228 case 2: ldursb64 (cpu
, imm
); return;
10229 case 3: ldursb32 (cpu
, imm
); return;
10230 case 4: sturh (cpu
, imm
); return;
10231 case 5: ldurh32 (cpu
, imm
); return;
10232 case 6: ldursh64 (cpu
, imm
); return;
10233 case 7: ldursh32 (cpu
, imm
); return;
10234 case 8: stur32 (cpu
, imm
); return;
10235 case 9: ldur32 (cpu
, imm
); return;
10236 case 10: ldursw (cpu
, imm
); return;
10237 case 12: stur64 (cpu
, imm
); return;
10238 case 13: ldur64 (cpu
, imm
); return;
10251 /* FReg operations. */
10254 case 2: fsturq (cpu
, imm
); return;
10255 case 3: fldurq (cpu
, imm
); return;
10256 case 8: fsturs (cpu
, imm
); return;
10257 case 9: fldurs (cpu
, imm
); return;
10258 case 12: fsturd (cpu
, imm
); return;
10259 case 13: fldurd (cpu
, imm
); return;
10261 case 0: /* STUR 8 bit FP. */
10262 case 1: /* LDUR 8 bit FP. */
10263 case 4: /* STUR 16 bit FP. */
10264 case 5: /* LDUR 8 bit FP. */
10278 /* N.B. A preliminary note regarding all the ldrs<x>32
10281 The signed value loaded by these instructions is cast to unsigned
10282 before being assigned to aarch64_get_reg_u64 (cpu, N) i.e. to the
10283 64 bit element of the GReg union. this performs a 32 bit sign extension
10284 (as required) but avoids 64 bit sign extension, thus ensuring that the
10285 top half of the register word is zero. this is what the spec demands
10286 when a 32 bit load occurs. */
10288 /* 32 bit load sign-extended byte scaled unsigned 12 bit. */
10290 ldrsb32_abs (sim_cpu
*cpu
, uint32_t offset
)
10292 unsigned int rn
= INSTR (9, 5);
10293 unsigned int rt
= INSTR (4, 0);
10295 /* The target register may not be SP but the source may be
10296 there is no scaling required for a byte load. */
10297 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
;
10298 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
10299 (int64_t) aarch64_get_mem_s8 (cpu
, address
));
10302 /* 32 bit load sign-extended byte scaled or unscaled zero-
10303 or sign-extended 32-bit register offset. */
10305 ldrsb32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10307 unsigned int rm
= INSTR (20, 16);
10308 unsigned int rn
= INSTR (9, 5);
10309 unsigned int rt
= INSTR (4, 0);
10311 /* rn may reference SP, rm and rt must reference ZR. */
10313 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10314 int64_t displacement
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10317 /* There is no scaling required for a byte load. */
10318 aarch64_set_reg_u64
10319 (cpu
, rt
, NO_SP
, (int64_t) aarch64_get_mem_s8 (cpu
, address
10323 /* 32 bit load sign-extended byte unscaled signed 9 bit with
10324 pre- or post-writeback. */
10326 ldrsb32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10329 unsigned int rn
= INSTR (9, 5);
10330 unsigned int rt
= INSTR (4, 0);
10332 if (rn
== rt
&& wb
!= NoWriteBack
)
10335 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10340 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
10341 (int64_t) aarch64_get_mem_s8 (cpu
, address
));
10346 if (wb
!= NoWriteBack
)
10347 aarch64_set_reg_u64 (cpu
, rn
, NO_SP
, address
);
10350 /* 8 bit store scaled. */
10352 fstrb_abs (sim_cpu
*cpu
, uint32_t offset
)
10354 unsigned st
= INSTR (4, 0);
10355 unsigned rn
= INSTR (9, 5);
10357 aarch64_set_mem_u8 (cpu
,
10358 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
10359 aarch64_get_vec_u8 (cpu
, st
, 0));
10362 /* 8 bit store scaled or unscaled zero- or
10363 sign-extended 8-bit register offset. */
10365 fstrb_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10367 unsigned rm
= INSTR (20, 16);
10368 unsigned rn
= INSTR (9, 5);
10369 unsigned st
= INSTR (4, 0);
10371 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10372 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10374 uint64_t displacement
= scaling
== Scaled
? extended
: 0;
10377 (cpu
, address
+ displacement
, aarch64_get_vec_u8 (cpu
, st
, 0));
10380 /* 16 bit store scaled. */
10382 fstrh_abs (sim_cpu
*cpu
, uint32_t offset
)
10384 unsigned st
= INSTR (4, 0);
10385 unsigned rn
= INSTR (9, 5);
10387 aarch64_set_mem_u16
10389 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 16),
10390 aarch64_get_vec_u16 (cpu
, st
, 0));
10393 /* 16 bit store scaled or unscaled zero-
10394 or sign-extended 16-bit register offset. */
10396 fstrh_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10398 unsigned rm
= INSTR (20, 16);
10399 unsigned rn
= INSTR (9, 5);
10400 unsigned st
= INSTR (4, 0);
10402 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10403 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10405 uint64_t displacement
= OPT_SCALE (extended
, 16, scaling
);
10407 aarch64_set_mem_u16
10408 (cpu
, address
+ displacement
, aarch64_get_vec_u16 (cpu
, st
, 0));
10411 /* 32 bit store scaled unsigned 12 bit. */
10413 fstrs_abs (sim_cpu
*cpu
, uint32_t offset
)
10415 unsigned st
= INSTR (4, 0);
10416 unsigned rn
= INSTR (9, 5);
10418 aarch64_set_mem_u32
10420 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 32),
10421 aarch64_get_vec_u32 (cpu
, st
, 0));
10424 /* 32 bit store unscaled signed 9 bit with pre- or post-writeback. */
10426 fstrs_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10428 unsigned rn
= INSTR (9, 5);
10429 unsigned st
= INSTR (4, 0);
10431 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10436 aarch64_set_mem_u32 (cpu
, address
, aarch64_get_vec_u32 (cpu
, st
, 0));
10441 if (wb
!= NoWriteBack
)
10442 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
10445 /* 32 bit store scaled or unscaled zero-
10446 or sign-extended 32-bit register offset. */
10448 fstrs_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10450 unsigned rm
= INSTR (20, 16);
10451 unsigned rn
= INSTR (9, 5);
10452 unsigned st
= INSTR (4, 0);
10454 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10455 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10457 uint64_t displacement
= OPT_SCALE (extended
, 32, scaling
);
10459 aarch64_set_mem_u32
10460 (cpu
, address
+ displacement
, aarch64_get_vec_u32 (cpu
, st
, 0));
10463 /* 64 bit store scaled unsigned 12 bit. */
10465 fstrd_abs (sim_cpu
*cpu
, uint32_t offset
)
10467 unsigned st
= INSTR (4, 0);
10468 unsigned rn
= INSTR (9, 5);
10470 aarch64_set_mem_u64
10472 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 64),
10473 aarch64_get_vec_u64 (cpu
, st
, 0));
10476 /* 64 bit store unscaled signed 9 bit with pre- or post-writeback. */
10478 fstrd_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10480 unsigned rn
= INSTR (9, 5);
10481 unsigned st
= INSTR (4, 0);
10483 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10488 aarch64_set_mem_u64 (cpu
, address
, aarch64_get_vec_u64 (cpu
, st
, 0));
10493 if (wb
!= NoWriteBack
)
10494 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
10497 /* 64 bit store scaled or unscaled zero-
10498 or sign-extended 32-bit register offset. */
10500 fstrd_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10502 unsigned rm
= INSTR (20, 16);
10503 unsigned rn
= INSTR (9, 5);
10504 unsigned st
= INSTR (4, 0);
10506 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10507 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10509 uint64_t displacement
= OPT_SCALE (extended
, 64, scaling
);
10511 aarch64_set_mem_u64
10512 (cpu
, address
+ displacement
, aarch64_get_vec_u64 (cpu
, st
, 0));
10515 /* 128 bit store scaled unsigned 12 bit. */
10517 fstrq_abs (sim_cpu
*cpu
, uint32_t offset
)
10520 unsigned st
= INSTR (4, 0);
10521 unsigned rn
= INSTR (9, 5);
10524 aarch64_get_FP_long_double (cpu
, st
, & a
);
10526 addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 128);
10527 aarch64_set_mem_long_double (cpu
, addr
, a
);
10530 /* 128 bit store unscaled signed 9 bit with pre- or post-writeback. */
10532 fstrq_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10535 unsigned rn
= INSTR (9, 5);
10536 unsigned st
= INSTR (4, 0);
10537 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10542 aarch64_get_FP_long_double (cpu
, st
, & a
);
10543 aarch64_set_mem_long_double (cpu
, address
, a
);
10548 if (wb
!= NoWriteBack
)
10549 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
10552 /* 128 bit store scaled or unscaled zero-
10553 or sign-extended 32-bit register offset. */
10555 fstrq_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10557 unsigned rm
= INSTR (20, 16);
10558 unsigned rn
= INSTR (9, 5);
10559 unsigned st
= INSTR (4, 0);
10561 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10562 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10564 uint64_t displacement
= OPT_SCALE (extended
, 128, scaling
);
10568 aarch64_get_FP_long_double (cpu
, st
, & a
);
10569 aarch64_set_mem_long_double (cpu
, address
+ displacement
, a
);
10573 dexLoadImmediatePrePost (sim_cpu
*cpu
)
10575 /* instr[31,30] = size
10581 instr[20,12] = simm9
10582 instr[11] = wb : 0 ==> Post, 1 ==> Pre
10584 instr[9,5] = Rn may be SP.
10587 uint32_t V
= INSTR (26, 26);
10588 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
10589 int32_t imm
= simm32 (aarch64_get_instr (cpu
), 20, 12);
10590 WriteBack wb
= INSTR (11, 11);
10594 /* GReg operations. */
10597 case 0: strb_wb (cpu
, imm
, wb
); return;
10598 case 1: ldrb32_wb (cpu
, imm
, wb
); return;
10599 case 2: ldrsb_wb (cpu
, imm
, wb
); return;
10600 case 3: ldrsb32_wb (cpu
, imm
, wb
); return;
10601 case 4: strh_wb (cpu
, imm
, wb
); return;
10602 case 5: ldrh32_wb (cpu
, imm
, wb
); return;
10603 case 6: ldrsh64_wb (cpu
, imm
, wb
); return;
10604 case 7: ldrsh32_wb (cpu
, imm
, wb
); return;
10605 case 8: str32_wb (cpu
, imm
, wb
); return;
10606 case 9: ldr32_wb (cpu
, imm
, wb
); return;
10607 case 10: ldrsw_wb (cpu
, imm
, wb
); return;
10608 case 12: str_wb (cpu
, imm
, wb
); return;
10609 case 13: ldr_wb (cpu
, imm
, wb
); return;
10619 /* FReg operations. */
10622 case 2: fstrq_wb (cpu
, imm
, wb
); return;
10623 case 3: fldrq_wb (cpu
, imm
, wb
); return;
10624 case 8: fstrs_wb (cpu
, imm
, wb
); return;
10625 case 9: fldrs_wb (cpu
, imm
, wb
); return;
10626 case 12: fstrd_wb (cpu
, imm
, wb
); return;
10627 case 13: fldrd_wb (cpu
, imm
, wb
); return;
10629 case 0: /* STUR 8 bit FP. */
10630 case 1: /* LDUR 8 bit FP. */
10631 case 4: /* STUR 16 bit FP. */
10632 case 5: /* LDUR 8 bit FP. */
10647 dexLoadRegisterOffset (sim_cpu
*cpu
)
10649 /* instr[31,30] = size
10656 instr[15,13] = option : 010 ==> UXTW, 011 ==> UXTX/LSL,
10657 110 ==> SXTW, 111 ==> SXTX,
10662 instr[4,0] = rt. */
10664 uint32_t V
= INSTR (26, 26);
10665 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
10666 Scaling scale
= INSTR (12, 12);
10667 Extension extensionType
= INSTR (15, 13);
10669 /* Check for illegal extension types. */
10670 if (uimm (extensionType
, 1, 1) == 0)
10673 if (extensionType
== UXTX
|| extensionType
== SXTX
)
10674 extensionType
= NoExtension
;
10678 /* GReg operations. */
10681 case 0: strb_scale_ext (cpu
, scale
, extensionType
); return;
10682 case 1: ldrb32_scale_ext (cpu
, scale
, extensionType
); return;
10683 case 2: ldrsb_scale_ext (cpu
, scale
, extensionType
); return;
10684 case 3: ldrsb32_scale_ext (cpu
, scale
, extensionType
); return;
10685 case 4: strh_scale_ext (cpu
, scale
, extensionType
); return;
10686 case 5: ldrh32_scale_ext (cpu
, scale
, extensionType
); return;
10687 case 6: ldrsh_scale_ext (cpu
, scale
, extensionType
); return;
10688 case 7: ldrsh32_scale_ext (cpu
, scale
, extensionType
); return;
10689 case 8: str32_scale_ext (cpu
, scale
, extensionType
); return;
10690 case 9: ldr32_scale_ext (cpu
, scale
, extensionType
); return;
10691 case 10: ldrsw_scale_ext (cpu
, scale
, extensionType
); return;
10692 case 12: str_scale_ext (cpu
, scale
, extensionType
); return;
10693 case 13: ldr_scale_ext (cpu
, scale
, extensionType
); return;
10694 case 14: prfm_scale_ext (cpu
, scale
, extensionType
); return;
10703 /* FReg operations. */
10706 case 1: /* LDUR 8 bit FP. */
10708 case 3: fldrq_scale_ext (cpu
, scale
, extensionType
); return;
10709 case 5: /* LDUR 8 bit FP. */
10711 case 9: fldrs_scale_ext (cpu
, scale
, extensionType
); return;
10712 case 13: fldrd_scale_ext (cpu
, scale
, extensionType
); return;
10714 case 0: fstrb_scale_ext (cpu
, scale
, extensionType
); return;
10715 case 2: fstrq_scale_ext (cpu
, scale
, extensionType
); return;
10716 case 4: fstrh_scale_ext (cpu
, scale
, extensionType
); return;
10717 case 8: fstrs_scale_ext (cpu
, scale
, extensionType
); return;
10718 case 12: fstrd_scale_ext (cpu
, scale
, extensionType
); return;
10732 dexLoadUnsignedImmediate (sim_cpu
*cpu
)
10734 /* instr[29,24] == 111_01
10735 instr[31,30] = size
10738 instr[21,10] = uimm12 : unsigned immediate offset
10739 instr[9,5] = rn may be SP.
10740 instr[4,0] = rt. */
10742 uint32_t V
= INSTR (26,26);
10743 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
10744 uint32_t imm
= INSTR (21, 10);
10748 /* GReg operations. */
10751 case 0: strb_abs (cpu
, imm
); return;
10752 case 1: ldrb32_abs (cpu
, imm
); return;
10753 case 2: ldrsb_abs (cpu
, imm
); return;
10754 case 3: ldrsb32_abs (cpu
, imm
); return;
10755 case 4: strh_abs (cpu
, imm
); return;
10756 case 5: ldrh32_abs (cpu
, imm
); return;
10757 case 6: ldrsh_abs (cpu
, imm
); return;
10758 case 7: ldrsh32_abs (cpu
, imm
); return;
10759 case 8: str32_abs (cpu
, imm
); return;
10760 case 9: ldr32_abs (cpu
, imm
); return;
10761 case 10: ldrsw_abs (cpu
, imm
); return;
10762 case 12: str_abs (cpu
, imm
); return;
10763 case 13: ldr_abs (cpu
, imm
); return;
10764 case 14: prfm_abs (cpu
, imm
); return;
10773 /* FReg operations. */
10776 case 0: fstrb_abs (cpu
, imm
); return;
10777 case 4: fstrh_abs (cpu
, imm
); return;
10778 case 8: fstrs_abs (cpu
, imm
); return;
10779 case 12: fstrd_abs (cpu
, imm
); return;
10780 case 2: fstrq_abs (cpu
, imm
); return;
10782 case 1: fldrb_abs (cpu
, imm
); return;
10783 case 5: fldrh_abs (cpu
, imm
); return;
10784 case 9: fldrs_abs (cpu
, imm
); return;
10785 case 13: fldrd_abs (cpu
, imm
); return;
10786 case 3: fldrq_abs (cpu
, imm
); return;
10800 dexLoadExclusive (sim_cpu
*cpu
)
10802 /* assert instr[29:24] = 001000;
10803 instr[31,30] = size
10804 instr[23] = 0 if exclusive
10805 instr[22] = L : 1 if load, 0 if store
10806 instr[21] = 1 if pair
10808 instr[15] = o0 : 1 if ordered
10811 instr[4.0] = Rt. */
10813 switch (INSTR (22, 21))
10815 case 2: ldxr (cpu
); return;
10816 case 0: stxr (cpu
); return;
10822 dexLoadOther (sim_cpu
*cpu
)
10826 /* instr[29,25] = 111_0
10827 instr[24] == 0 ==> dispatch, 1 ==> ldst reg unsigned immediate
10828 instr[21:11,10] is the secondary dispatch. */
10829 if (INSTR (24, 24))
10831 dexLoadUnsignedImmediate (cpu
);
10835 dispatch
= ((INSTR (21, 21) << 2) | INSTR (11, 10));
10838 case 0: dexLoadUnscaledImmediate (cpu
); return;
10839 case 1: dexLoadImmediatePrePost (cpu
); return;
10840 case 3: dexLoadImmediatePrePost (cpu
); return;
10841 case 6: dexLoadRegisterOffset (cpu
); return;
10853 store_pair_u32 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10855 unsigned rn
= INSTR (14, 10);
10856 unsigned rd
= INSTR (9, 5);
10857 unsigned rm
= INSTR (4, 0);
10858 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10860 if ((rn
== rd
|| rm
== rd
) && wb
!= NoWriteBack
)
10861 HALT_UNALLOC
; /* ??? */
10868 aarch64_set_mem_u32 (cpu
, address
,
10869 aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
10870 aarch64_set_mem_u32 (cpu
, address
+ 4,
10871 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
));
10876 if (wb
!= NoWriteBack
)
10877 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10881 store_pair_u64 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10883 unsigned rn
= INSTR (14, 10);
10884 unsigned rd
= INSTR (9, 5);
10885 unsigned rm
= INSTR (4, 0);
10886 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10888 if ((rn
== rd
|| rm
== rd
) && wb
!= NoWriteBack
)
10889 HALT_UNALLOC
; /* ??? */
10896 aarch64_set_mem_u64 (cpu
, address
,
10897 aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
10898 aarch64_set_mem_u64 (cpu
, address
+ 8,
10899 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
10904 if (wb
!= NoWriteBack
)
10905 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10909 load_pair_u32 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10911 unsigned rn
= INSTR (14, 10);
10912 unsigned rd
= INSTR (9, 5);
10913 unsigned rm
= INSTR (4, 0);
10914 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10916 /* Treat this as unalloc to make sure we don't do it. */
10925 aarch64_set_reg_u64 (cpu
, rm
, SP_OK
, aarch64_get_mem_u32 (cpu
, address
));
10926 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, aarch64_get_mem_u32 (cpu
, address
+ 4));
10931 if (wb
!= NoWriteBack
)
10932 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10936 load_pair_s32 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10938 unsigned rn
= INSTR (14, 10);
10939 unsigned rd
= INSTR (9, 5);
10940 unsigned rm
= INSTR (4, 0);
10941 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10943 /* Treat this as unalloc to make sure we don't do it. */
10952 aarch64_set_reg_s64 (cpu
, rm
, SP_OK
, aarch64_get_mem_s32 (cpu
, address
));
10953 aarch64_set_reg_s64 (cpu
, rn
, SP_OK
, aarch64_get_mem_s32 (cpu
, address
+ 4));
10958 if (wb
!= NoWriteBack
)
10959 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10963 load_pair_u64 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10965 unsigned rn
= INSTR (14, 10);
10966 unsigned rd
= INSTR (9, 5);
10967 unsigned rm
= INSTR (4, 0);
10968 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10970 /* Treat this as unalloc to make sure we don't do it. */
10979 aarch64_set_reg_u64 (cpu
, rm
, SP_OK
, aarch64_get_mem_u64 (cpu
, address
));
10980 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, aarch64_get_mem_u64 (cpu
, address
+ 8));
10985 if (wb
!= NoWriteBack
)
10986 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10990 dex_load_store_pair_gr (sim_cpu
*cpu
)
10992 /* instr[31,30] = size (10=> 64-bit, 01=> signed 32-bit, 00=> 32-bit)
10993 instr[29,25] = instruction encoding: 101_0
10994 instr[26] = V : 1 if fp 0 if gp
10995 instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
10996 instr[22] = load/store (1=> load)
10997 instr[21,15] = signed, scaled, offset
11000 instr[ 4, 0] = Rm. */
11002 uint32_t dispatch
= ((INSTR (31, 30) << 3) | INSTR (24, 22));
11003 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 21, 15);
11007 case 2: store_pair_u32 (cpu
, offset
, Post
); return;
11008 case 3: load_pair_u32 (cpu
, offset
, Post
); return;
11009 case 4: store_pair_u32 (cpu
, offset
, NoWriteBack
); return;
11010 case 5: load_pair_u32 (cpu
, offset
, NoWriteBack
); return;
11011 case 6: store_pair_u32 (cpu
, offset
, Pre
); return;
11012 case 7: load_pair_u32 (cpu
, offset
, Pre
); return;
11014 case 11: load_pair_s32 (cpu
, offset
, Post
); return;
11015 case 13: load_pair_s32 (cpu
, offset
, NoWriteBack
); return;
11016 case 15: load_pair_s32 (cpu
, offset
, Pre
); return;
11018 case 18: store_pair_u64 (cpu
, offset
, Post
); return;
11019 case 19: load_pair_u64 (cpu
, offset
, Post
); return;
11020 case 20: store_pair_u64 (cpu
, offset
, NoWriteBack
); return;
11021 case 21: load_pair_u64 (cpu
, offset
, NoWriteBack
); return;
11022 case 22: store_pair_u64 (cpu
, offset
, Pre
); return;
11023 case 23: load_pair_u64 (cpu
, offset
, Pre
); return;
11031 store_pair_float (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11033 unsigned rn
= INSTR (14, 10);
11034 unsigned rd
= INSTR (9, 5);
11035 unsigned rm
= INSTR (4, 0);
11036 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11043 aarch64_set_mem_u32 (cpu
, address
, aarch64_get_vec_u32 (cpu
, rm
, 0));
11044 aarch64_set_mem_u32 (cpu
, address
+ 4, aarch64_get_vec_u32 (cpu
, rn
, 0));
11049 if (wb
!= NoWriteBack
)
11050 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11054 store_pair_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11056 unsigned rn
= INSTR (14, 10);
11057 unsigned rd
= INSTR (9, 5);
11058 unsigned rm
= INSTR (4, 0);
11059 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11066 aarch64_set_mem_u64 (cpu
, address
, aarch64_get_vec_u64 (cpu
, rm
, 0));
11067 aarch64_set_mem_u64 (cpu
, address
+ 8, aarch64_get_vec_u64 (cpu
, rn
, 0));
11072 if (wb
!= NoWriteBack
)
11073 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11077 store_pair_long_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11080 unsigned rn
= INSTR (14, 10);
11081 unsigned rd
= INSTR (9, 5);
11082 unsigned rm
= INSTR (4, 0);
11083 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11090 aarch64_get_FP_long_double (cpu
, rm
, & a
);
11091 aarch64_set_mem_long_double (cpu
, address
, a
);
11092 aarch64_get_FP_long_double (cpu
, rn
, & a
);
11093 aarch64_set_mem_long_double (cpu
, address
+ 16, a
);
11098 if (wb
!= NoWriteBack
)
11099 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11103 load_pair_float (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11105 unsigned rn
= INSTR (14, 10);
11106 unsigned rd
= INSTR (9, 5);
11107 unsigned rm
= INSTR (4, 0);
11108 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11118 aarch64_set_vec_u32 (cpu
, rm
, 0, aarch64_get_mem_u32 (cpu
, address
));
11119 aarch64_set_vec_u32 (cpu
, rn
, 0, aarch64_get_mem_u32 (cpu
, address
+ 4));
11124 if (wb
!= NoWriteBack
)
11125 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11129 load_pair_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11131 unsigned rn
= INSTR (14, 10);
11132 unsigned rd
= INSTR (9, 5);
11133 unsigned rm
= INSTR (4, 0);
11134 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11144 aarch64_set_vec_u64 (cpu
, rm
, 0, aarch64_get_mem_u64 (cpu
, address
));
11145 aarch64_set_vec_u64 (cpu
, rn
, 0, aarch64_get_mem_u64 (cpu
, address
+ 8));
11150 if (wb
!= NoWriteBack
)
11151 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11155 load_pair_long_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11158 unsigned rn
= INSTR (14, 10);
11159 unsigned rd
= INSTR (9, 5);
11160 unsigned rm
= INSTR (4, 0);
11161 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11171 aarch64_get_mem_long_double (cpu
, address
, & a
);
11172 aarch64_set_FP_long_double (cpu
, rm
, a
);
11173 aarch64_get_mem_long_double (cpu
, address
+ 16, & a
);
11174 aarch64_set_FP_long_double (cpu
, rn
, a
);
11179 if (wb
!= NoWriteBack
)
11180 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11184 dex_load_store_pair_fp (sim_cpu
*cpu
)
11186 /* instr[31,30] = size (10=> 128-bit, 01=> 64-bit, 00=> 32-bit)
11187 instr[29,25] = instruction encoding
11188 instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
11189 instr[22] = load/store (1=> load)
11190 instr[21,15] = signed, scaled, offset
11193 instr[ 4, 0] = Rm */
11195 uint32_t dispatch
= ((INSTR (31, 30) << 3) | INSTR (24, 22));
11196 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 21, 15);
11200 case 2: store_pair_float (cpu
, offset
, Post
); return;
11201 case 3: load_pair_float (cpu
, offset
, Post
); return;
11202 case 4: store_pair_float (cpu
, offset
, NoWriteBack
); return;
11203 case 5: load_pair_float (cpu
, offset
, NoWriteBack
); return;
11204 case 6: store_pair_float (cpu
, offset
, Pre
); return;
11205 case 7: load_pair_float (cpu
, offset
, Pre
); return;
11207 case 10: store_pair_double (cpu
, offset
, Post
); return;
11208 case 11: load_pair_double (cpu
, offset
, Post
); return;
11209 case 12: store_pair_double (cpu
, offset
, NoWriteBack
); return;
11210 case 13: load_pair_double (cpu
, offset
, NoWriteBack
); return;
11211 case 14: store_pair_double (cpu
, offset
, Pre
); return;
11212 case 15: load_pair_double (cpu
, offset
, Pre
); return;
11214 case 18: store_pair_long_double (cpu
, offset
, Post
); return;
11215 case 19: load_pair_long_double (cpu
, offset
, Post
); return;
11216 case 20: store_pair_long_double (cpu
, offset
, NoWriteBack
); return;
11217 case 21: load_pair_long_double (cpu
, offset
, NoWriteBack
); return;
11218 case 22: store_pair_long_double (cpu
, offset
, Pre
); return;
11219 case 23: load_pair_long_double (cpu
, offset
, Pre
); return;
11226 static inline unsigned
11227 vec_reg (unsigned v
, unsigned o
)
11229 return (v
+ o
) & 0x3F;
11232 /* Load multiple N-element structures to N consecutive registers. */
11234 vec_load (sim_cpu
*cpu
, uint64_t address
, unsigned N
)
11236 int all
= INSTR (30, 30);
11237 unsigned size
= INSTR (11, 10);
11238 unsigned vd
= INSTR (4, 0);
11243 case 0: /* 8-bit operations. */
11245 for (i
= 0; i
< (16 * N
); i
++)
11246 aarch64_set_vec_u8 (cpu
, vec_reg (vd
, i
>> 4), i
& 15,
11247 aarch64_get_mem_u8 (cpu
, address
+ i
));
11249 for (i
= 0; i
< (8 * N
); i
++)
11250 aarch64_set_vec_u8 (cpu
, vec_reg (vd
, i
>> 3), i
& 7,
11251 aarch64_get_mem_u8 (cpu
, address
+ i
));
11254 case 1: /* 16-bit operations. */
11256 for (i
= 0; i
< (8 * N
); i
++)
11257 aarch64_set_vec_u16 (cpu
, vec_reg (vd
, i
>> 3), i
& 7,
11258 aarch64_get_mem_u16 (cpu
, address
+ i
* 2));
11260 for (i
= 0; i
< (4 * N
); i
++)
11261 aarch64_set_vec_u16 (cpu
, vec_reg (vd
, i
>> 2), i
& 3,
11262 aarch64_get_mem_u16 (cpu
, address
+ i
* 2));
11265 case 2: /* 32-bit operations. */
11267 for (i
= 0; i
< (4 * N
); i
++)
11268 aarch64_set_vec_u32 (cpu
, vec_reg (vd
, i
>> 2), i
& 3,
11269 aarch64_get_mem_u32 (cpu
, address
+ i
* 4));
11271 for (i
= 0; i
< (2 * N
); i
++)
11272 aarch64_set_vec_u32 (cpu
, vec_reg (vd
, i
>> 1), i
& 1,
11273 aarch64_get_mem_u32 (cpu
, address
+ i
* 4));
11276 case 3: /* 64-bit operations. */
11278 for (i
= 0; i
< (2 * N
); i
++)
11279 aarch64_set_vec_u64 (cpu
, vec_reg (vd
, i
>> 1), i
& 1,
11280 aarch64_get_mem_u64 (cpu
, address
+ i
* 8));
11282 for (i
= 0; i
< N
; i
++)
11283 aarch64_set_vec_u64 (cpu
, vec_reg (vd
, i
), 0,
11284 aarch64_get_mem_u64 (cpu
, address
+ i
* 8));
11289 /* LD4: load multiple 4-element to four consecutive registers. */
11291 LD4 (sim_cpu
*cpu
, uint64_t address
)
11293 vec_load (cpu
, address
, 4);
11296 /* LD3: load multiple 3-element structures to three consecutive registers. */
11298 LD3 (sim_cpu
*cpu
, uint64_t address
)
11300 vec_load (cpu
, address
, 3);
11303 /* LD2: load multiple 2-element structures to two consecutive registers. */
11305 LD2 (sim_cpu
*cpu
, uint64_t address
)
11307 vec_load (cpu
, address
, 2);
11310 /* Load multiple 1-element structures into one register. */
11312 LD1_1 (sim_cpu
*cpu
, uint64_t address
)
11314 int all
= INSTR (30, 30);
11315 unsigned size
= INSTR (11, 10);
11316 unsigned vd
= INSTR (4, 0);
11322 /* LD1 {Vd.16b}, addr, #16 */
11323 /* LD1 {Vd.8b}, addr, #8 */
11324 for (i
= 0; i
< (all
? 16 : 8); i
++)
11325 aarch64_set_vec_u8 (cpu
, vd
, i
,
11326 aarch64_get_mem_u8 (cpu
, address
+ i
));
11330 /* LD1 {Vd.8h}, addr, #16 */
11331 /* LD1 {Vd.4h}, addr, #8 */
11332 for (i
= 0; i
< (all
? 8 : 4); i
++)
11333 aarch64_set_vec_u16 (cpu
, vd
, i
,
11334 aarch64_get_mem_u16 (cpu
, address
+ i
* 2));
11338 /* LD1 {Vd.4s}, addr, #16 */
11339 /* LD1 {Vd.2s}, addr, #8 */
11340 for (i
= 0; i
< (all
? 4 : 2); i
++)
11341 aarch64_set_vec_u32 (cpu
, vd
, i
,
11342 aarch64_get_mem_u32 (cpu
, address
+ i
* 4));
11346 /* LD1 {Vd.2d}, addr, #16 */
11347 /* LD1 {Vd.1d}, addr, #8 */
11348 for (i
= 0; i
< (all
? 2 : 1); i
++)
11349 aarch64_set_vec_u64 (cpu
, vd
, i
,
11350 aarch64_get_mem_u64 (cpu
, address
+ i
* 8));
11355 /* Load multiple 1-element structures into two registers. */
11357 LD1_2 (sim_cpu
*cpu
, uint64_t address
)
11359 /* FIXME: This algorithm is *exactly* the same as the LD2 version.
11360 So why have two different instructions ? There must be something
11361 wrong somewhere. */
11362 vec_load (cpu
, address
, 2);
11365 /* Load multiple 1-element structures into three registers. */
11367 LD1_3 (sim_cpu
*cpu
, uint64_t address
)
11369 /* FIXME: This algorithm is *exactly* the same as the LD3 version.
11370 So why have two different instructions ? There must be something
11371 wrong somewhere. */
11372 vec_load (cpu
, address
, 3);
11375 /* Load multiple 1-element structures into four registers. */
11377 LD1_4 (sim_cpu
*cpu
, uint64_t address
)
11379 /* FIXME: This algorithm is *exactly* the same as the LD4 version.
11380 So why have two different instructions ? There must be something
11381 wrong somewhere. */
11382 vec_load (cpu
, address
, 4);
11385 /* Store multiple N-element structures to N consecutive registers. */
11387 vec_store (sim_cpu
*cpu
, uint64_t address
, unsigned N
)
11389 int all
= INSTR (30, 30);
11390 unsigned size
= INSTR (11, 10);
11391 unsigned vd
= INSTR (4, 0);
11396 case 0: /* 8-bit operations. */
11398 for (i
= 0; i
< (16 * N
); i
++)
11401 aarch64_get_vec_u8 (cpu
, vec_reg (vd
, i
>> 4), i
& 15));
11403 for (i
= 0; i
< (8 * N
); i
++)
11406 aarch64_get_vec_u8 (cpu
, vec_reg (vd
, i
>> 3), i
& 7));
11409 case 1: /* 16-bit operations. */
11411 for (i
= 0; i
< (8 * N
); i
++)
11412 aarch64_set_mem_u16
11413 (cpu
, address
+ i
* 2,
11414 aarch64_get_vec_u16 (cpu
, vec_reg (vd
, i
>> 3), i
& 7));
11416 for (i
= 0; i
< (4 * N
); i
++)
11417 aarch64_set_mem_u16
11418 (cpu
, address
+ i
* 2,
11419 aarch64_get_vec_u16 (cpu
, vec_reg (vd
, i
>> 2), i
& 3));
11422 case 2: /* 32-bit operations. */
11424 for (i
= 0; i
< (4 * N
); i
++)
11425 aarch64_set_mem_u32
11426 (cpu
, address
+ i
* 4,
11427 aarch64_get_vec_u32 (cpu
, vec_reg (vd
, i
>> 2), i
& 3));
11429 for (i
= 0; i
< (2 * N
); i
++)
11430 aarch64_set_mem_u32
11431 (cpu
, address
+ i
* 4,
11432 aarch64_get_vec_u32 (cpu
, vec_reg (vd
, i
>> 1), i
& 1));
11435 case 3: /* 64-bit operations. */
11437 for (i
= 0; i
< (2 * N
); i
++)
11438 aarch64_set_mem_u64
11439 (cpu
, address
+ i
* 8,
11440 aarch64_get_vec_u64 (cpu
, vec_reg (vd
, i
>> 1), i
& 1));
11442 for (i
= 0; i
< N
; i
++)
11443 aarch64_set_mem_u64
11444 (cpu
, address
+ i
* 8,
11445 aarch64_get_vec_u64 (cpu
, vec_reg (vd
, i
), 0));
11450 /* Store multiple 4-element structure to four consecutive registers. */
11452 ST4 (sim_cpu
*cpu
, uint64_t address
)
11454 vec_store (cpu
, address
, 4);
11457 /* Store multiple 3-element structures to three consecutive registers. */
11459 ST3 (sim_cpu
*cpu
, uint64_t address
)
11461 vec_store (cpu
, address
, 3);
11464 /* Store multiple 2-element structures to two consecutive registers. */
11466 ST2 (sim_cpu
*cpu
, uint64_t address
)
11468 vec_store (cpu
, address
, 2);
11471 /* Store multiple 1-element structures into one register. */
11473 ST1_1 (sim_cpu
*cpu
, uint64_t address
)
11475 int all
= INSTR (30, 30);
11476 unsigned size
= INSTR (11, 10);
11477 unsigned vd
= INSTR (4, 0);
11483 for (i
= 0; i
< (all
? 16 : 8); i
++)
11484 aarch64_set_mem_u8 (cpu
, address
+ i
,
11485 aarch64_get_vec_u8 (cpu
, vd
, i
));
11489 for (i
= 0; i
< (all
? 8 : 4); i
++)
11490 aarch64_set_mem_u16 (cpu
, address
+ i
* 2,
11491 aarch64_get_vec_u16 (cpu
, vd
, i
));
11495 for (i
= 0; i
< (all
? 4 : 2); i
++)
11496 aarch64_set_mem_u32 (cpu
, address
+ i
* 4,
11497 aarch64_get_vec_u32 (cpu
, vd
, i
));
11501 for (i
= 0; i
< (all
? 2 : 1); i
++)
11502 aarch64_set_mem_u64 (cpu
, address
+ i
* 8,
11503 aarch64_get_vec_u64 (cpu
, vd
, i
));
11508 /* Store multiple 1-element structures into two registers. */
11510 ST1_2 (sim_cpu
*cpu
, uint64_t address
)
11512 /* FIXME: This algorithm is *exactly* the same as the ST2 version.
11513 So why have two different instructions ? There must be
11514 something wrong somewhere. */
11515 vec_store (cpu
, address
, 2);
11518 /* Store multiple 1-element structures into three registers. */
11520 ST1_3 (sim_cpu
*cpu
, uint64_t address
)
11522 /* FIXME: This algorithm is *exactly* the same as the ST3 version.
11523 So why have two different instructions ? There must be
11524 something wrong somewhere. */
11525 vec_store (cpu
, address
, 3);
11528 /* Store multiple 1-element structures into four registers. */
11530 ST1_4 (sim_cpu
*cpu
, uint64_t address
)
11532 /* FIXME: This algorithm is *exactly* the same as the ST4 version.
11533 So why have two different instructions ? There must be
11534 something wrong somewhere. */
11535 vec_store (cpu
, address
, 4);
11538 #define LDn_STn_SINGLE_LANE_AND_SIZE() \
11541 switch (INSTR (15, 14)) \
11544 lane = (full << 3) | (s << 2) | size; \
11549 if ((size & 1) == 1) \
11551 lane = (full << 2) | (s << 1) | (size >> 1); \
11556 if ((size & 2) == 2) \
11559 if ((size & 1) == 0) \
11561 lane = (full << 1) | s; \
11579 /* Load single structure into one lane of N registers. */
11581 do_vec_LDn_single (sim_cpu
*cpu
, uint64_t address
)
11584 instr[30] = element selector 0=>half, 1=>all elements
11585 instr[29,24] = 00 1101
11586 instr[23] = 0=>simple, 1=>post
11588 instr[21] = width: LD1-or-LD3 (0) / LD2-or-LD4 (1)
11589 instr[20,16] = 0 0000 (simple), Vinc (reg-post-inc, no SP),
11590 11111 (immediate post inc)
11591 instr[15,13] = opcode
11592 instr[12] = S, used for lane number
11593 instr[11,10] = size, also used for lane number
11594 instr[9,5] = address
11597 unsigned full
= INSTR (30, 30);
11598 unsigned vd
= INSTR (4, 0);
11599 unsigned size
= INSTR (11, 10);
11600 unsigned s
= INSTR (12, 12);
11601 int nregs
= ((INSTR (13, 13) << 1) | INSTR (21, 21)) + 1;
11605 NYI_assert (29, 24, 0x0D);
11606 NYI_assert (22, 22, 1);
11608 /* Compute the lane number first (using size), and then compute size. */
11609 LDn_STn_SINGLE_LANE_AND_SIZE ();
11611 for (i
= 0; i
< nregs
; i
++)
11616 uint8_t val
= aarch64_get_mem_u8 (cpu
, address
+ i
);
11617 aarch64_set_vec_u8 (cpu
, vd
+ i
, lane
, val
);
11623 uint16_t val
= aarch64_get_mem_u16 (cpu
, address
+ (i
* 2));
11624 aarch64_set_vec_u16 (cpu
, vd
+ i
, lane
, val
);
11630 uint32_t val
= aarch64_get_mem_u32 (cpu
, address
+ (i
* 4));
11631 aarch64_set_vec_u32 (cpu
, vd
+ i
, lane
, val
);
11637 uint64_t val
= aarch64_get_mem_u64 (cpu
, address
+ (i
* 8));
11638 aarch64_set_vec_u64 (cpu
, vd
+ i
, lane
, val
);
11644 /* Store single structure from one lane from N registers. */
11646 do_vec_STn_single (sim_cpu
*cpu
, uint64_t address
)
11649 instr[30] = element selector 0=>half, 1=>all elements
11650 instr[29,24] = 00 1101
11651 instr[23] = 0=>simple, 1=>post
11653 instr[21] = width: LD1-or-LD3 (0) / LD2-or-LD4 (1)
11654 instr[20,16] = 0 0000 (simple), Vinc (reg-post-inc, no SP),
11655 11111 (immediate post inc)
11656 instr[15,13] = opcode
11657 instr[12] = S, used for lane number
11658 instr[11,10] = size, also used for lane number
11659 instr[9,5] = address
11662 unsigned full
= INSTR (30, 30);
11663 unsigned vd
= INSTR (4, 0);
11664 unsigned size
= INSTR (11, 10);
11665 unsigned s
= INSTR (12, 12);
11666 int nregs
= ((INSTR (13, 13) << 1) | INSTR (21, 21)) + 1;
11670 NYI_assert (29, 24, 0x0D);
11671 NYI_assert (22, 22, 0);
11673 /* Compute the lane number first (using size), and then compute size. */
11674 LDn_STn_SINGLE_LANE_AND_SIZE ();
11676 for (i
= 0; i
< nregs
; i
++)
11681 uint8_t val
= aarch64_get_vec_u8 (cpu
, vd
+ i
, lane
);
11682 aarch64_set_mem_u8 (cpu
, address
+ i
, val
);
11688 uint16_t val
= aarch64_get_vec_u16 (cpu
, vd
+ i
, lane
);
11689 aarch64_set_mem_u16 (cpu
, address
+ (i
* 2), val
);
11695 uint32_t val
= aarch64_get_vec_u32 (cpu
, vd
+ i
, lane
);
11696 aarch64_set_mem_u32 (cpu
, address
+ (i
* 4), val
);
11702 uint64_t val
= aarch64_get_vec_u64 (cpu
, vd
+ i
, lane
);
11703 aarch64_set_mem_u64 (cpu
, address
+ (i
* 8), val
);
11709 /* Load single structure into all lanes of N registers. */
11711 do_vec_LDnR (sim_cpu
*cpu
, uint64_t address
)
11714 instr[30] = element selector 0=>half, 1=>all elements
11715 instr[29,24] = 00 1101
11716 instr[23] = 0=>simple, 1=>post
11718 instr[21] = width: LD1R-or-LD3R (0) / LD2R-or-LD4R (1)
11719 instr[20,16] = 0 0000 (simple), Vinc (reg-post-inc, no SP),
11720 11111 (immediate post inc)
11722 instr[13] = width: LD1R-or-LD2R (0) / LD3R-or-LD4R (1)
11724 instr[11,10] = element size 00=> byte(b), 01=> half(h),
11725 10=> word(s), 11=> double(d)
11726 instr[9,5] = address
11729 unsigned full
= INSTR (30, 30);
11730 unsigned vd
= INSTR (4, 0);
11731 unsigned size
= INSTR (11, 10);
11732 int nregs
= ((INSTR (13, 13) << 1) | INSTR (21, 21)) + 1;
11735 NYI_assert (29, 24, 0x0D);
11736 NYI_assert (22, 22, 1);
11737 NYI_assert (15, 14, 3);
11738 NYI_assert (12, 12, 0);
11740 for (n
= 0; n
< nregs
; n
++)
11745 uint8_t val
= aarch64_get_mem_u8 (cpu
, address
+ n
);
11746 for (i
= 0; i
< (full
? 16 : 8); i
++)
11747 aarch64_set_vec_u8 (cpu
, vd
+ n
, i
, val
);
11753 uint16_t val
= aarch64_get_mem_u16 (cpu
, address
+ (n
* 2));
11754 for (i
= 0; i
< (full
? 8 : 4); i
++)
11755 aarch64_set_vec_u16 (cpu
, vd
+ n
, i
, val
);
11761 uint32_t val
= aarch64_get_mem_u32 (cpu
, address
+ (n
* 4));
11762 for (i
= 0; i
< (full
? 4 : 2); i
++)
11763 aarch64_set_vec_u32 (cpu
, vd
+ n
, i
, val
);
11769 uint64_t val
= aarch64_get_mem_u64 (cpu
, address
+ (n
* 8));
11770 for (i
= 0; i
< (full
? 2 : 1); i
++)
11771 aarch64_set_vec_u64 (cpu
, vd
+ n
, i
, val
);
11781 do_vec_load_store (sim_cpu
*cpu
)
11783 /* {LD|ST}<N> {Vd..Vd+N}, vaddr
11786 instr[30] = element selector 0=>half, 1=>all elements
11787 instr[29,25] = 00110
11788 instr[24] = 0=>multiple struct, 1=>single struct
11789 instr[23] = 0=>simple, 1=>post
11790 instr[22] = 0=>store, 1=>load
11791 instr[21] = 0 (LDn) / small(0)-large(1) selector (LDnR)
11792 instr[20,16] = 00000 (simple), Vinc (reg-post-inc, no SP),
11793 11111 (immediate post inc)
11794 instr[15,12] = elements and destinations. eg for load:
11795 0000=>LD4 => load multiple 4-element to
11796 four consecutive registers
11797 0100=>LD3 => load multiple 3-element to
11798 three consecutive registers
11799 1000=>LD2 => load multiple 2-element to
11800 two consecutive registers
11801 0010=>LD1 => load multiple 1-element to
11802 four consecutive registers
11803 0110=>LD1 => load multiple 1-element to
11804 three consecutive registers
11805 1010=>LD1 => load multiple 1-element to
11806 two consecutive registers
11807 0111=>LD1 => load multiple 1-element to
11811 instr[11,10] = element size 00=> byte(b), 01=> half(h),
11812 10=> word(s), 11=> double(d)
11813 instr[9,5] = Vn, can be SP
11823 if (INSTR (31, 31) != 0 || INSTR (29, 25) != 0x06)
11826 single
= INSTR (24, 24);
11827 post
= INSTR (23, 23);
11828 load
= INSTR (22, 22);
11829 type
= INSTR (15, 12);
11831 address
= aarch64_get_reg_u64 (cpu
, vn
, SP_OK
);
11833 if (! single
&& INSTR (21, 21) != 0)
11838 unsigned vm
= INSTR (20, 16);
11842 unsigned sizeof_operation
;
11846 if ((type
>= 0) && (type
<= 11))
11848 int nregs
= ((INSTR (13, 13) << 1) | INSTR (21, 21)) + 1;
11849 switch (INSTR (15, 14))
11852 sizeof_operation
= nregs
* 1;
11855 sizeof_operation
= nregs
* 2;
11858 if (INSTR (10, 10) == 0)
11859 sizeof_operation
= nregs
* 4;
11861 sizeof_operation
= nregs
* 8;
11867 else if (type
== 0xC)
11869 sizeof_operation
= INSTR (21, 21) ? 2 : 1;
11870 sizeof_operation
<<= INSTR (11, 10);
11872 else if (type
== 0xE)
11874 sizeof_operation
= INSTR (21, 21) ? 4 : 3;
11875 sizeof_operation
<<= INSTR (11, 10);
11884 case 0: sizeof_operation
= 32; break;
11885 case 4: sizeof_operation
= 24; break;
11886 case 8: sizeof_operation
= 16; break;
11889 /* One register, immediate offset variant. */
11890 sizeof_operation
= 8;
11894 /* Two registers, immediate offset variant. */
11895 sizeof_operation
= 16;
11899 /* Three registers, immediate offset variant. */
11900 sizeof_operation
= 24;
11904 /* Four registers, immediate offset variant. */
11905 sizeof_operation
= 32;
11912 if (INSTR (30, 30))
11913 sizeof_operation
*= 2;
11916 aarch64_set_reg_u64 (cpu
, vn
, SP_OK
, address
+ sizeof_operation
);
11919 aarch64_set_reg_u64 (cpu
, vn
, SP_OK
,
11920 address
+ aarch64_get_reg_u64 (cpu
, vm
, NO_SP
));
11924 NYI_assert (20, 16, 0);
11931 if ((type
>= 0) && (type
<= 11))
11932 do_vec_LDn_single (cpu
, address
);
11933 else if ((type
== 0xC) || (type
== 0xE))
11934 do_vec_LDnR (cpu
, address
);
11941 if ((type
>= 0) && (type
<= 11))
11943 do_vec_STn_single (cpu
, address
);
11954 case 0: LD4 (cpu
, address
); return;
11955 case 4: LD3 (cpu
, address
); return;
11956 case 8: LD2 (cpu
, address
); return;
11957 case 2: LD1_4 (cpu
, address
); return;
11958 case 6: LD1_3 (cpu
, address
); return;
11959 case 10: LD1_2 (cpu
, address
); return;
11960 case 7: LD1_1 (cpu
, address
); return;
11970 case 0: ST4 (cpu
, address
); return;
11971 case 4: ST3 (cpu
, address
); return;
11972 case 8: ST2 (cpu
, address
); return;
11973 case 2: ST1_4 (cpu
, address
); return;
11974 case 6: ST1_3 (cpu
, address
); return;
11975 case 10: ST1_2 (cpu
, address
); return;
11976 case 7: ST1_1 (cpu
, address
); return;
11983 dexLdSt (sim_cpu
*cpu
)
11985 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
11986 assert group == GROUP_LDST_0100 || group == GROUP_LDST_0110 ||
11987 group == GROUP_LDST_1100 || group == GROUP_LDST_1110
11988 bits [29,28:26] of a LS are the secondary dispatch vector. */
11989 uint32_t group2
= dispatchLS (aarch64_get_instr (cpu
));
11994 dexLoadExclusive (cpu
); return;
11998 dexLoadLiteral (cpu
); return;
12002 dexLoadOther (cpu
); return;
12004 case LS_ADVSIMD_001
:
12005 do_vec_load_store (cpu
); return;
12008 dex_load_store_pair_gr (cpu
); return;
12011 dex_load_store_pair_fp (cpu
); return;
12014 /* Should never reach here. */
12019 /* Specific decode and execute for group Data Processing Register. */
12022 dexLogicalShiftedRegister (sim_cpu
*cpu
)
12024 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12026 instr[28:24] = 01010
12027 instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> ROR
12030 instr[15,10] = count : must be 0xxxxx for 32 bit
12034 uint32_t size
= INSTR (31, 31);
12035 Shift shiftType
= INSTR (23, 22);
12036 uint32_t count
= INSTR (15, 10);
12038 /* 32 bit operations must have count[5] = 0.
12039 or else we have an UNALLOC. */
12040 if (size
== 0 && uimm (count
, 5, 5))
12043 /* Dispatch on size:op:N. */
12044 switch ((INSTR (31, 29) << 1) | INSTR (21, 21))
12046 case 0: and32_shift (cpu
, shiftType
, count
); return;
12047 case 1: bic32_shift (cpu
, shiftType
, count
); return;
12048 case 2: orr32_shift (cpu
, shiftType
, count
); return;
12049 case 3: orn32_shift (cpu
, shiftType
, count
); return;
12050 case 4: eor32_shift (cpu
, shiftType
, count
); return;
12051 case 5: eon32_shift (cpu
, shiftType
, count
); return;
12052 case 6: ands32_shift (cpu
, shiftType
, count
); return;
12053 case 7: bics32_shift (cpu
, shiftType
, count
); return;
12054 case 8: and64_shift (cpu
, shiftType
, count
); return;
12055 case 9: bic64_shift (cpu
, shiftType
, count
); return;
12056 case 10:orr64_shift (cpu
, shiftType
, count
); return;
12057 case 11:orn64_shift (cpu
, shiftType
, count
); return;
12058 case 12:eor64_shift (cpu
, shiftType
, count
); return;
12059 case 13:eon64_shift (cpu
, shiftType
, count
); return;
12060 case 14:ands64_shift (cpu
, shiftType
, count
); return;
12061 case 15:bics64_shift (cpu
, shiftType
, count
); return;
12065 /* 32 bit conditional select. */
12067 csel32 (sim_cpu
*cpu
, CondCode cc
)
12069 unsigned rm
= INSTR (20, 16);
12070 unsigned rn
= INSTR (9, 5);
12071 unsigned rd
= INSTR (4, 0);
12073 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12074 testConditionCode (cpu
, cc
)
12075 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12076 : aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12079 /* 64 bit conditional select. */
12081 csel64 (sim_cpu
*cpu
, CondCode cc
)
12083 unsigned rm
= INSTR (20, 16);
12084 unsigned rn
= INSTR (9, 5);
12085 unsigned rd
= INSTR (4, 0);
12087 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12088 testConditionCode (cpu
, cc
)
12089 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12090 : aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
12093 /* 32 bit conditional increment. */
12095 csinc32 (sim_cpu
*cpu
, CondCode cc
)
12097 unsigned rm
= INSTR (20, 16);
12098 unsigned rn
= INSTR (9, 5);
12099 unsigned rd
= INSTR (4, 0);
12101 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12102 testConditionCode (cpu
, cc
)
12103 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12104 : aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) + 1);
12107 /* 64 bit conditional increment. */
12109 csinc64 (sim_cpu
*cpu
, CondCode cc
)
12111 unsigned rm
= INSTR (20, 16);
12112 unsigned rn
= INSTR (9, 5);
12113 unsigned rd
= INSTR (4, 0);
12115 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12116 testConditionCode (cpu
, cc
)
12117 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12118 : aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) + 1);
12121 /* 32 bit conditional invert. */
12123 csinv32 (sim_cpu
*cpu
, CondCode cc
)
12125 unsigned rm
= INSTR (20, 16);
12126 unsigned rn
= INSTR (9, 5);
12127 unsigned rd
= INSTR (4, 0);
12129 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12130 testConditionCode (cpu
, cc
)
12131 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12132 : ~ aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12135 /* 64 bit conditional invert. */
12137 csinv64 (sim_cpu
*cpu
, CondCode cc
)
12139 unsigned rm
= INSTR (20, 16);
12140 unsigned rn
= INSTR (9, 5);
12141 unsigned rd
= INSTR (4, 0);
12143 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12144 testConditionCode (cpu
, cc
)
12145 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12146 : ~ aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
12149 /* 32 bit conditional negate. */
12151 csneg32 (sim_cpu
*cpu
, CondCode cc
)
12153 unsigned rm
= INSTR (20, 16);
12154 unsigned rn
= INSTR (9, 5);
12155 unsigned rd
= INSTR (4, 0);
12157 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12158 testConditionCode (cpu
, cc
)
12159 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12160 : - aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12163 /* 64 bit conditional negate. */
12165 csneg64 (sim_cpu
*cpu
, CondCode cc
)
12167 unsigned rm
= INSTR (20, 16);
12168 unsigned rn
= INSTR (9, 5);
12169 unsigned rd
= INSTR (4, 0);
12171 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12172 testConditionCode (cpu
, cc
)
12173 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12174 : - aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
12178 dexCondSelect (sim_cpu
*cpu
)
12180 /* instr[28,21] = 11011011
12181 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12182 instr[30:11,10] = op : 000 ==> CSEL, 001 ==> CSINC,
12183 100 ==> CSINV, 101 ==> CSNEG,
12185 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
12186 instr[15,12] = cond
12187 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC */
12189 CondCode cc
= INSTR (15, 12);
12190 uint32_t S
= INSTR (29, 29);
12191 uint32_t op2
= INSTR (11, 10);
12199 switch ((INSTR (31, 30) << 1) | op2
)
12201 case 0: csel32 (cpu
, cc
); return;
12202 case 1: csinc32 (cpu
, cc
); return;
12203 case 2: csinv32 (cpu
, cc
); return;
12204 case 3: csneg32 (cpu
, cc
); return;
12205 case 4: csel64 (cpu
, cc
); return;
12206 case 5: csinc64 (cpu
, cc
); return;
12207 case 6: csinv64 (cpu
, cc
); return;
12208 case 7: csneg64 (cpu
, cc
); return;
12212 /* Some helpers for counting leading 1 or 0 bits. */
12214 /* Counts the number of leading bits which are the same
12215 in a 32 bit value in the range 1 to 32. */
12217 leading32 (uint32_t value
)
12219 int32_t mask
= 0xffff0000;
12220 uint32_t count
= 16; /* Counts number of bits set in mask. */
12221 uint32_t lo
= 1; /* Lower bound for number of sign bits. */
12222 uint32_t hi
= 32; /* Upper bound for number of sign bits. */
12224 while (lo
+ 1 < hi
)
12226 int32_t test
= (value
& mask
);
12228 if (test
== 0 || test
== mask
)
12231 count
= (lo
+ hi
) / 2;
12232 mask
>>= (count
- lo
);
12237 count
= (lo
+ hi
) / 2;
12238 mask
<<= hi
- count
;
12247 test
= (value
& mask
);
12249 if (test
== 0 || test
== mask
)
12258 /* Counts the number of leading bits which are the same
12259 in a 64 bit value in the range 1 to 64. */
12261 leading64 (uint64_t value
)
12263 int64_t mask
= 0xffffffff00000000LL
;
12264 uint64_t count
= 32; /* Counts number of bits set in mask. */
12265 uint64_t lo
= 1; /* Lower bound for number of sign bits. */
12266 uint64_t hi
= 64; /* Upper bound for number of sign bits. */
12268 while (lo
+ 1 < hi
)
12270 int64_t test
= (value
& mask
);
12272 if (test
== 0 || test
== mask
)
12275 count
= (lo
+ hi
) / 2;
12276 mask
>>= (count
- lo
);
12281 count
= (lo
+ hi
) / 2;
12282 mask
<<= hi
- count
;
12291 test
= (value
& mask
);
12293 if (test
== 0 || test
== mask
)
12302 /* Bit operations. */
12303 /* N.B register args may not be SP. */
12305 /* 32 bit count leading sign bits. */
12307 cls32 (sim_cpu
*cpu
)
12309 unsigned rn
= INSTR (9, 5);
12310 unsigned rd
= INSTR (4, 0);
12312 /* N.B. the result needs to exclude the leading bit. */
12313 aarch64_set_reg_u64
12314 (cpu
, rd
, NO_SP
, leading32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)) - 1);
12317 /* 64 bit count leading sign bits. */
12319 cls64 (sim_cpu
*cpu
)
12321 unsigned rn
= INSTR (9, 5);
12322 unsigned rd
= INSTR (4, 0);
12324 /* N.B. the result needs to exclude the leading bit. */
12325 aarch64_set_reg_u64
12326 (cpu
, rd
, NO_SP
, leading64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)) - 1);
12329 /* 32 bit count leading zero bits. */
12331 clz32 (sim_cpu
*cpu
)
12333 unsigned rn
= INSTR (9, 5);
12334 unsigned rd
= INSTR (4, 0);
12335 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12337 /* if the sign (top) bit is set then the count is 0. */
12338 if (pick32 (value
, 31, 31))
12339 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, 0L);
12341 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, leading32 (value
));
12344 /* 64 bit count leading zero bits. */
12346 clz64 (sim_cpu
*cpu
)
12348 unsigned rn
= INSTR (9, 5);
12349 unsigned rd
= INSTR (4, 0);
12350 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12352 /* if the sign (top) bit is set then the count is 0. */
12353 if (pick64 (value
, 63, 63))
12354 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, 0L);
12356 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, leading64 (value
));
12359 /* 32 bit reverse bits. */
12361 rbit32 (sim_cpu
*cpu
)
12363 unsigned rn
= INSTR (9, 5);
12364 unsigned rd
= INSTR (4, 0);
12365 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12366 uint32_t result
= 0;
12369 for (i
= 0; i
< 32; i
++)
12372 result
|= (value
& 1);
12375 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12378 /* 64 bit reverse bits. */
12380 rbit64 (sim_cpu
*cpu
)
12382 unsigned rn
= INSTR (9, 5);
12383 unsigned rd
= INSTR (4, 0);
12384 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12385 uint64_t result
= 0;
12388 for (i
= 0; i
< 64; i
++)
12391 result
|= (value
& 1UL);
12394 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12397 /* 32 bit reverse bytes. */
12399 rev32 (sim_cpu
*cpu
)
12401 unsigned rn
= INSTR (9, 5);
12402 unsigned rd
= INSTR (4, 0);
12403 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12404 uint32_t result
= 0;
12407 for (i
= 0; i
< 4; i
++)
12410 result
|= (value
& 0xff);
12413 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12416 /* 64 bit reverse bytes. */
12418 rev64 (sim_cpu
*cpu
)
12420 unsigned rn
= INSTR (9, 5);
12421 unsigned rd
= INSTR (4, 0);
12422 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12423 uint64_t result
= 0;
12426 for (i
= 0; i
< 8; i
++)
12429 result
|= (value
& 0xffULL
);
12432 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12435 /* 32 bit reverse shorts. */
12436 /* N.B.this reverses the order of the bytes in each half word. */
12438 revh32 (sim_cpu
*cpu
)
12440 unsigned rn
= INSTR (9, 5);
12441 unsigned rd
= INSTR (4, 0);
12442 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12443 uint32_t result
= 0;
12446 for (i
= 0; i
< 2; i
++)
12449 result
|= (value
& 0x00ff00ff);
12452 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12455 /* 64 bit reverse shorts. */
12456 /* N.B.this reverses the order of the bytes in each half word. */
12458 revh64 (sim_cpu
*cpu
)
12460 unsigned rn
= INSTR (9, 5);
12461 unsigned rd
= INSTR (4, 0);
12462 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12463 uint64_t result
= 0;
12466 for (i
= 0; i
< 2; i
++)
12469 result
|= (value
& 0x00ff00ff00ff00ffULL
);
12472 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12476 dexDataProc1Source (sim_cpu
*cpu
)
12479 instr[28,21] = 111010110
12480 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12481 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
12482 instr[20,16] = opcode2 : 00000 ==> ok, ow ==> UNALLOC
12483 instr[15,10] = opcode : 000000 ==> RBIT, 000001 ==> REV16,
12484 000010 ==> REV, 000011 ==> UNALLOC
12485 000100 ==> CLZ, 000101 ==> CLS
12487 instr[9,5] = rn : may not be SP
12488 instr[4,0] = rd : may not be SP. */
12490 uint32_t S
= INSTR (29, 29);
12491 uint32_t opcode2
= INSTR (20, 16);
12492 uint32_t opcode
= INSTR (15, 10);
12493 uint32_t dispatch
= ((INSTR (31, 31) << 3) | opcode
);
12506 case 0: rbit32 (cpu
); return;
12507 case 1: revh32 (cpu
); return;
12508 case 2: rev32 (cpu
); return;
12509 case 4: clz32 (cpu
); return;
12510 case 5: cls32 (cpu
); return;
12511 case 8: rbit64 (cpu
); return;
12512 case 9: revh64 (cpu
); return;
12513 case 10:rev32 (cpu
); return;
12514 case 11:rev64 (cpu
); return;
12515 case 12:clz64 (cpu
); return;
12516 case 13:cls64 (cpu
); return;
12517 default: HALT_UNALLOC
;
12522 Shifts by count supplied in register.
12523 N.B register args may not be SP.
12524 These all use the shifted auxiliary function for
12525 simplicity and clarity. Writing the actual shift
12526 inline would avoid a branch and so be faster but
12527 would also necessitate getting signs right. */
12529 /* 32 bit arithmetic shift right. */
12531 asrv32 (sim_cpu
*cpu
)
12533 unsigned rm
= INSTR (20, 16);
12534 unsigned rn
= INSTR (9, 5);
12535 unsigned rd
= INSTR (4, 0);
12537 aarch64_set_reg_u64
12539 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), ASR
,
12540 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12543 /* 64 bit arithmetic shift right. */
12545 asrv64 (sim_cpu
*cpu
)
12547 unsigned rm
= INSTR (20, 16);
12548 unsigned rn
= INSTR (9, 5);
12549 unsigned rd
= INSTR (4, 0);
12551 aarch64_set_reg_u64
12553 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), ASR
,
12554 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12557 /* 32 bit logical shift left. */
12559 lslv32 (sim_cpu
*cpu
)
12561 unsigned rm
= INSTR (20, 16);
12562 unsigned rn
= INSTR (9, 5);
12563 unsigned rd
= INSTR (4, 0);
12565 aarch64_set_reg_u64
12567 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), LSL
,
12568 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12571 /* 64 bit arithmetic shift left. */
12573 lslv64 (sim_cpu
*cpu
)
12575 unsigned rm
= INSTR (20, 16);
12576 unsigned rn
= INSTR (9, 5);
12577 unsigned rd
= INSTR (4, 0);
12579 aarch64_set_reg_u64
12581 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), LSL
,
12582 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12585 /* 32 bit logical shift right. */
12587 lsrv32 (sim_cpu
*cpu
)
12589 unsigned rm
= INSTR (20, 16);
12590 unsigned rn
= INSTR (9, 5);
12591 unsigned rd
= INSTR (4, 0);
12593 aarch64_set_reg_u64
12595 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), LSR
,
12596 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12599 /* 64 bit logical shift right. */
12601 lsrv64 (sim_cpu
*cpu
)
12603 unsigned rm
= INSTR (20, 16);
12604 unsigned rn
= INSTR (9, 5);
12605 unsigned rd
= INSTR (4, 0);
12607 aarch64_set_reg_u64
12609 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), LSR
,
12610 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12613 /* 32 bit rotate right. */
12615 rorv32 (sim_cpu
*cpu
)
12617 unsigned rm
= INSTR (20, 16);
12618 unsigned rn
= INSTR (9, 5);
12619 unsigned rd
= INSTR (4, 0);
12621 aarch64_set_reg_u64
12623 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), ROR
,
12624 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12627 /* 64 bit rotate right. */
12629 rorv64 (sim_cpu
*cpu
)
12631 unsigned rm
= INSTR (20, 16);
12632 unsigned rn
= INSTR (9, 5);
12633 unsigned rd
= INSTR (4, 0);
12635 aarch64_set_reg_u64
12637 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), ROR
,
12638 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12644 /* 32 bit signed divide. */
12646 cpuiv32 (sim_cpu
*cpu
)
12648 unsigned rm
= INSTR (20, 16);
12649 unsigned rn
= INSTR (9, 5);
12650 unsigned rd
= INSTR (4, 0);
12651 /* N.B. the pseudo-code does the divide using 64 bit data. */
12652 /* TODO : check that this rounds towards zero as required. */
12653 int64_t dividend
= aarch64_get_reg_s32 (cpu
, rn
, NO_SP
);
12654 int64_t divisor
= aarch64_get_reg_s32 (cpu
, rm
, NO_SP
);
12656 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
,
12657 divisor
? ((int32_t) (dividend
/ divisor
)) : 0);
12660 /* 64 bit signed divide. */
12662 cpuiv64 (sim_cpu
*cpu
)
12664 unsigned rm
= INSTR (20, 16);
12665 unsigned rn
= INSTR (9, 5);
12666 unsigned rd
= INSTR (4, 0);
12668 /* TODO : check that this rounds towards zero as required. */
12669 int64_t divisor
= aarch64_get_reg_s64 (cpu
, rm
, NO_SP
);
12671 aarch64_set_reg_s64
12673 divisor
? (aarch64_get_reg_s64 (cpu
, rn
, NO_SP
) / divisor
) : 0);
12676 /* 32 bit unsigned divide. */
12678 udiv32 (sim_cpu
*cpu
)
12680 unsigned rm
= INSTR (20, 16);
12681 unsigned rn
= INSTR (9, 5);
12682 unsigned rd
= INSTR (4, 0);
12684 /* N.B. the pseudo-code does the divide using 64 bit data. */
12685 uint64_t dividend
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12686 uint64_t divisor
= aarch64_get_reg_u32 (cpu
, rm
, NO_SP
);
12688 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12689 divisor
? (uint32_t) (dividend
/ divisor
) : 0);
12692 /* 64 bit unsigned divide. */
12694 udiv64 (sim_cpu
*cpu
)
12696 unsigned rm
= INSTR (20, 16);
12697 unsigned rn
= INSTR (9, 5);
12698 unsigned rd
= INSTR (4, 0);
12700 /* TODO : check that this rounds towards zero as required. */
12701 uint64_t divisor
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
12703 aarch64_set_reg_u64
12705 divisor
? (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) / divisor
) : 0);
12709 dexDataProc2Source (sim_cpu
*cpu
)
12711 /* assert instr[30] == 0
12712 instr[28,21] == 11010110
12713 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12714 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
12715 instr[15,10] = opcode : 000010 ==> UDIV, 000011 ==> CPUIV,
12716 001000 ==> LSLV, 001001 ==> LSRV
12717 001010 ==> ASRV, 001011 ==> RORV
12721 uint32_t S
= INSTR (29, 29);
12722 uint32_t opcode
= INSTR (15, 10);
12730 dispatch
= ( (INSTR (31, 31) << 3)
12731 | (uimm (opcode
, 3, 3) << 2)
12732 | uimm (opcode
, 1, 0));
12735 case 2: udiv32 (cpu
); return;
12736 case 3: cpuiv32 (cpu
); return;
12737 case 4: lslv32 (cpu
); return;
12738 case 5: lsrv32 (cpu
); return;
12739 case 6: asrv32 (cpu
); return;
12740 case 7: rorv32 (cpu
); return;
12741 case 10: udiv64 (cpu
); return;
12742 case 11: cpuiv64 (cpu
); return;
12743 case 12: lslv64 (cpu
); return;
12744 case 13: lsrv64 (cpu
); return;
12745 case 14: asrv64 (cpu
); return;
12746 case 15: rorv64 (cpu
); return;
12747 default: HALT_UNALLOC
;
12754 /* 32 bit multiply and add. */
12756 madd32 (sim_cpu
*cpu
)
12758 unsigned rm
= INSTR (20, 16);
12759 unsigned ra
= INSTR (14, 10);
12760 unsigned rn
= INSTR (9, 5);
12761 unsigned rd
= INSTR (4, 0);
12763 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12764 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12765 aarch64_get_reg_u32 (cpu
, ra
, NO_SP
)
12766 + aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12767 * aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12770 /* 64 bit multiply and add. */
12772 madd64 (sim_cpu
*cpu
)
12774 unsigned rm
= INSTR (20, 16);
12775 unsigned ra
= INSTR (14, 10);
12776 unsigned rn
= INSTR (9, 5);
12777 unsigned rd
= INSTR (4, 0);
12779 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12780 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12781 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
12782 + (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12783 * aarch64_get_reg_u64 (cpu
, rm
, NO_SP
)));
12786 /* 32 bit multiply and sub. */
12788 msub32 (sim_cpu
*cpu
)
12790 unsigned rm
= INSTR (20, 16);
12791 unsigned ra
= INSTR (14, 10);
12792 unsigned rn
= INSTR (9, 5);
12793 unsigned rd
= INSTR (4, 0);
12795 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12796 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12797 aarch64_get_reg_u32 (cpu
, ra
, NO_SP
)
12798 - aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12799 * aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12802 /* 64 bit multiply and sub. */
12804 msub64 (sim_cpu
*cpu
)
12806 unsigned rm
= INSTR (20, 16);
12807 unsigned ra
= INSTR (14, 10);
12808 unsigned rn
= INSTR (9, 5);
12809 unsigned rd
= INSTR (4, 0);
12811 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12812 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12813 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
12814 - aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12815 * aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
12818 /* Signed multiply add long -- source, source2 : 32 bit, source3 : 64 bit. */
12820 smaddl (sim_cpu
*cpu
)
12822 unsigned rm
= INSTR (20, 16);
12823 unsigned ra
= INSTR (14, 10);
12824 unsigned rn
= INSTR (9, 5);
12825 unsigned rd
= INSTR (4, 0);
12827 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12828 obtain a 64 bit product. */
12829 aarch64_set_reg_s64
12831 aarch64_get_reg_s64 (cpu
, ra
, NO_SP
)
12832 + ((int64_t) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
))
12833 * ((int64_t) aarch64_get_reg_s32 (cpu
, rm
, NO_SP
)));
12836 /* Signed multiply sub long -- source, source2 : 32 bit, source3 : 64 bit. */
12838 smsubl (sim_cpu
*cpu
)
12840 unsigned rm
= INSTR (20, 16);
12841 unsigned ra
= INSTR (14, 10);
12842 unsigned rn
= INSTR (9, 5);
12843 unsigned rd
= INSTR (4, 0);
12845 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12846 obtain a 64 bit product. */
12847 aarch64_set_reg_s64
12849 aarch64_get_reg_s64 (cpu
, ra
, NO_SP
)
12850 - ((int64_t) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
))
12851 * ((int64_t) aarch64_get_reg_s32 (cpu
, rm
, NO_SP
)));
12854 /* Integer Multiply/Divide. */
12856 /* First some macros and a helper function. */
12857 /* Macros to test or access elements of 64 bit words. */
12859 /* Mask used to access lo 32 bits of 64 bit unsigned int. */
12860 #define LOW_WORD_MASK ((1ULL << 32) - 1)
12861 /* Return the lo 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int. */
12862 #define lowWordToU64(_value_u64) ((_value_u64) & LOW_WORD_MASK)
12863 /* Return the hi 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int. */
12864 #define highWordToU64(_value_u64) ((_value_u64) >> 32)
12866 /* Offset of sign bit in 64 bit signed integger. */
12867 #define SIGN_SHIFT_U64 63
12868 /* The sign bit itself -- also identifies the minimum negative int value. */
12869 #define SIGN_BIT_U64 (1UL << SIGN_SHIFT_U64)
12870 /* Return true if a 64 bit signed int presented as an unsigned int is the
12871 most negative value. */
12872 #define isMinimumU64(_value_u64) ((_value_u64) == SIGN_BIT_U64)
12873 /* Return true (non-zero) if a 64 bit signed int presented as an unsigned
12874 int has its sign bit set to false. */
12875 #define isSignSetU64(_value_u64) ((_value_u64) & SIGN_BIT_U64)
12876 /* Return 1L or -1L according to whether a 64 bit signed int presented as
12877 an unsigned int has its sign bit set or not. */
12878 #define signOfU64(_value_u64) (1L + (((value_u64) >> SIGN_SHIFT_U64) * -2L)
12879 /* Clear the sign bit of a 64 bit signed int presented as an unsigned int. */
12880 #define clearSignU64(_value_u64) ((_value_u64) &= ~SIGN_BIT_U64)
12882 /* Multiply two 64 bit ints and return.
12883 the hi 64 bits of the 128 bit product. */
12886 mul64hi (uint64_t value1
, uint64_t value2
)
12888 uint64_t resultmid1
;
12890 uint64_t value1_lo
= lowWordToU64 (value1
);
12891 uint64_t value1_hi
= highWordToU64 (value1
) ;
12892 uint64_t value2_lo
= lowWordToU64 (value2
);
12893 uint64_t value2_hi
= highWordToU64 (value2
);
12895 /* Cross-multiply and collect results. */
12896 uint64_t xproductlo
= value1_lo
* value2_lo
;
12897 uint64_t xproductmid1
= value1_lo
* value2_hi
;
12898 uint64_t xproductmid2
= value1_hi
* value2_lo
;
12899 uint64_t xproducthi
= value1_hi
* value2_hi
;
12900 uint64_t carry
= 0;
12901 /* Start accumulating 64 bit results. */
12902 /* Drop bottom half of lowest cross-product. */
12903 uint64_t resultmid
= xproductlo
>> 32;
12904 /* Add in middle products. */
12905 resultmid
= resultmid
+ xproductmid1
;
12907 /* Check for overflow. */
12908 if (resultmid
< xproductmid1
)
12909 /* Carry over 1 into top cross-product. */
12912 resultmid1
= resultmid
+ xproductmid2
;
12914 /* Check for overflow. */
12915 if (resultmid1
< xproductmid2
)
12916 /* Carry over 1 into top cross-product. */
12919 /* Drop lowest 32 bits of middle cross-product. */
12920 result
= resultmid1
>> 32;
12922 /* Add top cross-product plus and any carry. */
12923 result
+= xproducthi
+ carry
;
12928 /* Signed multiply high, source, source2 :
12929 64 bit, dest <-- high 64-bit of result. */
12931 smulh (sim_cpu
*cpu
)
12935 unsigned rm
= INSTR (20, 16);
12936 unsigned rn
= INSTR (9, 5);
12937 unsigned rd
= INSTR (4, 0);
12938 GReg ra
= INSTR (14, 10);
12939 int64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12940 int64_t value2
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
12943 int64_t signum
= 1;
12948 /* Convert to unsigned and use the unsigned mul64hi routine
12949 the fix the sign up afterwards. */
12970 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12971 uresult
= mul64hi (uvalue1
, uvalue2
);
12975 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, result
);
12978 /* Unsigned multiply add long -- source, source2 :
12979 32 bit, source3 : 64 bit. */
12981 umaddl (sim_cpu
*cpu
)
12983 unsigned rm
= INSTR (20, 16);
12984 unsigned ra
= INSTR (14, 10);
12985 unsigned rn
= INSTR (9, 5);
12986 unsigned rd
= INSTR (4, 0);
12988 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12989 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12990 obtain a 64 bit product. */
12991 aarch64_set_reg_u64
12993 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
12994 + ((uint64_t) aarch64_get_reg_u32 (cpu
, rn
, NO_SP
))
12995 * ((uint64_t) aarch64_get_reg_u32 (cpu
, rm
, NO_SP
)));
12998 /* Unsigned multiply sub long -- source, source2 : 32 bit, source3 : 64 bit. */
13000 umsubl (sim_cpu
*cpu
)
13002 unsigned rm
= INSTR (20, 16);
13003 unsigned ra
= INSTR (14, 10);
13004 unsigned rn
= INSTR (9, 5);
13005 unsigned rd
= INSTR (4, 0);
13007 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13008 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
13009 obtain a 64 bit product. */
13010 aarch64_set_reg_u64
13012 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
13013 - ((uint64_t) aarch64_get_reg_u32 (cpu
, rn
, NO_SP
))
13014 * ((uint64_t) aarch64_get_reg_u32 (cpu
, rm
, NO_SP
)));
13017 /* Unsigned multiply high, source, source2 :
13018 64 bit, dest <-- high 64-bit of result. */
13020 umulh (sim_cpu
*cpu
)
13022 unsigned rm
= INSTR (20, 16);
13023 unsigned rn
= INSTR (9, 5);
13024 unsigned rd
= INSTR (4, 0);
13025 GReg ra
= INSTR (14, 10);
13030 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13031 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
13032 mul64hi (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
),
13033 aarch64_get_reg_u64 (cpu
, rm
, NO_SP
)));
13037 dexDataProc3Source (sim_cpu
*cpu
)
13039 /* assert instr[28,24] == 11011. */
13040 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit (for rd at least)
13041 instr[30,29] = op54 : 00 ==> ok, ow ==> UNALLOC
13042 instr[23,21] = op31 : 111 ==> UNALLOC, o2 ==> ok
13043 instr[15] = o0 : 0/1 ==> ok
13044 instr[23,21:15] ==> op : 0000 ==> MADD, 0001 ==> MSUB, (32/64 bit)
13045 0010 ==> SMADDL, 0011 ==> SMSUBL, (64 bit only)
13046 0100 ==> SMULH, (64 bit only)
13047 1010 ==> UMADDL, 1011 ==> UNSUBL, (64 bit only)
13048 1100 ==> UMULH (64 bit only)
13052 uint32_t size
= INSTR (31, 31);
13053 uint32_t op54
= INSTR (30, 29);
13054 uint32_t op31
= INSTR (23, 21);
13055 uint32_t o0
= INSTR (15, 15);
13072 dispatch
= (op31
<< 1) | o0
;
13076 case 0: madd64 (cpu
); return;
13077 case 1: msub64 (cpu
); return;
13078 case 2: smaddl (cpu
); return;
13079 case 3: smsubl (cpu
); return;
13080 case 4: smulh (cpu
); return;
13081 case 10: umaddl (cpu
); return;
13082 case 11: umsubl (cpu
); return;
13083 case 12: umulh (cpu
); return;
13084 default: HALT_UNALLOC
;
13089 dexDPReg (sim_cpu
*cpu
)
13091 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
13092 assert group == GROUP_DPREG_0101 || group == GROUP_DPREG_1101
13093 bits [28:24:21] of a DPReg are the secondary dispatch vector. */
13094 uint32_t group2
= dispatchDPReg (aarch64_get_instr (cpu
));
13098 case DPREG_LOG_000
:
13099 case DPREG_LOG_001
:
13100 dexLogicalShiftedRegister (cpu
); return;
13102 case DPREG_ADDSHF_010
:
13103 dexAddSubtractShiftedRegister (cpu
); return;
13105 case DPREG_ADDEXT_011
:
13106 dexAddSubtractExtendedRegister (cpu
); return;
13108 case DPREG_ADDCOND_100
:
13110 /* This set bundles a variety of different operations. */
13112 /* 1) add/sub w carry. */
13113 uint32_t mask1
= 0x1FE00000U
;
13114 uint32_t val1
= 0x1A000000U
;
13115 /* 2) cond compare register/immediate. */
13116 uint32_t mask2
= 0x1FE00000U
;
13117 uint32_t val2
= 0x1A400000U
;
13118 /* 3) cond select. */
13119 uint32_t mask3
= 0x1FE00000U
;
13120 uint32_t val3
= 0x1A800000U
;
13121 /* 4) data proc 1/2 source. */
13122 uint32_t mask4
= 0x1FE00000U
;
13123 uint32_t val4
= 0x1AC00000U
;
13125 if ((aarch64_get_instr (cpu
) & mask1
) == val1
)
13126 dexAddSubtractWithCarry (cpu
);
13128 else if ((aarch64_get_instr (cpu
) & mask2
) == val2
)
13131 else if ((aarch64_get_instr (cpu
) & mask3
) == val3
)
13132 dexCondSelect (cpu
);
13134 else if ((aarch64_get_instr (cpu
) & mask4
) == val4
)
13136 /* Bit 30 is clear for data proc 2 source
13137 and set for data proc 1 source. */
13138 if (aarch64_get_instr (cpu
) & (1U << 30))
13139 dexDataProc1Source (cpu
);
13141 dexDataProc2Source (cpu
);
13145 /* Should not reach here. */
13151 case DPREG_3SRC_110
:
13152 dexDataProc3Source (cpu
); return;
13154 case DPREG_UNALLOC_101
:
13157 case DPREG_3SRC_111
:
13158 dexDataProc3Source (cpu
); return;
13161 /* Should never reach here. */
13166 /* Unconditional Branch immediate.
13167 Offset is a PC-relative byte offset in the range +/- 128MiB.
13168 The offset is assumed to be raw from the decode i.e. the
13169 simulator is expected to scale them from word offsets to byte. */
13171 /* Unconditional branch. */
13173 buc (sim_cpu
*cpu
, int32_t offset
)
13175 aarch64_set_next_PC_by_offset (cpu
, offset
);
13178 static unsigned stack_depth
= 0;
13180 /* Unconditional branch and link -- writes return PC to LR. */
13182 bl (sim_cpu
*cpu
, int32_t offset
)
13184 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13185 aarch64_save_LR (cpu
);
13186 aarch64_set_next_PC_by_offset (cpu
, offset
);
13188 if (TRACE_BRANCH_P (cpu
))
13192 " %*scall %" PRIx64
" [%s]"
13193 " [args: %" PRIx64
" %" PRIx64
" %" PRIx64
"]",
13194 stack_depth
, " ", aarch64_get_next_PC (cpu
),
13195 aarch64_get_func (CPU_STATE (cpu
),
13196 aarch64_get_next_PC (cpu
)),
13197 aarch64_get_reg_u64 (cpu
, 0, NO_SP
),
13198 aarch64_get_reg_u64 (cpu
, 1, NO_SP
),
13199 aarch64_get_reg_u64 (cpu
, 2, NO_SP
)
13204 /* Unconditional Branch register.
13205 Branch/return address is in source register. */
13207 /* Unconditional branch. */
13211 unsigned rn
= INSTR (9, 5);
13212 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13213 aarch64_set_next_PC (cpu
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
13216 /* Unconditional branch and link -- writes return PC to LR. */
13220 unsigned rn
= INSTR (9, 5);
13222 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13223 /* The pseudo code in the spec says we update LR before fetching.
13224 the value from the rn. */
13225 aarch64_save_LR (cpu
);
13226 aarch64_set_next_PC (cpu
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
13228 if (TRACE_BRANCH_P (cpu
))
13232 " %*scall %" PRIx64
" [%s]"
13233 " [args: %" PRIx64
" %" PRIx64
" %" PRIx64
"]",
13234 stack_depth
, " ", aarch64_get_next_PC (cpu
),
13235 aarch64_get_func (CPU_STATE (cpu
),
13236 aarch64_get_next_PC (cpu
)),
13237 aarch64_get_reg_u64 (cpu
, 0, NO_SP
),
13238 aarch64_get_reg_u64 (cpu
, 1, NO_SP
),
13239 aarch64_get_reg_u64 (cpu
, 2, NO_SP
)
13244 /* Return -- assembler will default source to LR this is functionally
13245 equivalent to br but, presumably, unlike br it side effects the
13246 branch predictor. */
13250 unsigned rn
= INSTR (9, 5);
13251 aarch64_set_next_PC (cpu
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
13253 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13254 if (TRACE_BRANCH_P (cpu
))
13257 " %*sreturn [result: %" PRIx64
"]",
13258 stack_depth
, " ", aarch64_get_reg_u64 (cpu
, 0, NO_SP
));
13263 /* NOP -- we implement this and call it from the decode in case we
13264 want to intercept it later. */
13269 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13272 /* Data synchronization barrier. */
13277 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13280 /* Data memory barrier. */
13285 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13288 /* Instruction synchronization barrier. */
13293 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13297 dexBranchImmediate (sim_cpu
*cpu
)
13299 /* assert instr[30,26] == 00101
13300 instr[31] ==> 0 == B, 1 == BL
13301 instr[25,0] == imm26 branch offset counted in words. */
13303 uint32_t top
= INSTR (31, 31);
13304 /* We have a 26 byte signed word offset which we need to pass to the
13305 execute routine as a signed byte offset. */
13306 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 25, 0) << 2;
13314 /* Control Flow. */
13316 /* Conditional branch
13318 Offset is a PC-relative byte offset in the range +/- 1MiB pos is
13319 a bit position in the range 0 .. 63
13321 cc is a CondCode enum value as pulled out of the decode
13323 N.B. any offset register (source) can only be Xn or Wn. */
13326 bcc (sim_cpu
*cpu
, int32_t offset
, CondCode cc
)
13328 /* The test returns TRUE if CC is met. */
13329 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13330 if (testConditionCode (cpu
, cc
))
13331 aarch64_set_next_PC_by_offset (cpu
, offset
);
13334 /* 32 bit branch on register non-zero. */
13336 cbnz32 (sim_cpu
*cpu
, int32_t offset
)
13338 unsigned rt
= INSTR (4, 0);
13340 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13341 if (aarch64_get_reg_u32 (cpu
, rt
, NO_SP
) != 0)
13342 aarch64_set_next_PC_by_offset (cpu
, offset
);
13345 /* 64 bit branch on register zero. */
13347 cbnz (sim_cpu
*cpu
, int32_t offset
)
13349 unsigned rt
= INSTR (4, 0);
13351 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13352 if (aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) != 0)
13353 aarch64_set_next_PC_by_offset (cpu
, offset
);
13356 /* 32 bit branch on register non-zero. */
13358 cbz32 (sim_cpu
*cpu
, int32_t offset
)
13360 unsigned rt
= INSTR (4, 0);
13362 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13363 if (aarch64_get_reg_u32 (cpu
, rt
, NO_SP
) == 0)
13364 aarch64_set_next_PC_by_offset (cpu
, offset
);
13367 /* 64 bit branch on register zero. */
13369 cbz (sim_cpu
*cpu
, int32_t offset
)
13371 unsigned rt
= INSTR (4, 0);
13373 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13374 if (aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) == 0)
13375 aarch64_set_next_PC_by_offset (cpu
, offset
);
13378 /* Branch on register bit test non-zero -- one size fits all. */
13380 tbnz (sim_cpu
*cpu
, uint32_t pos
, int32_t offset
)
13382 unsigned rt
= INSTR (4, 0);
13384 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13385 if (aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) & (((uint64_t) 1) << pos
))
13386 aarch64_set_next_PC_by_offset (cpu
, offset
);
13389 /* Branch on register bit test zero -- one size fits all. */
13391 tbz (sim_cpu
*cpu
, uint32_t pos
, int32_t offset
)
13393 unsigned rt
= INSTR (4, 0);
13395 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13396 if (!(aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) & (((uint64_t) 1) << pos
)))
13397 aarch64_set_next_PC_by_offset (cpu
, offset
);
13401 dexCompareBranchImmediate (sim_cpu
*cpu
)
13403 /* instr[30,25] = 01 1010
13404 instr[31] = size : 0 ==> 32, 1 ==> 64
13405 instr[24] = op : 0 ==> CBZ, 1 ==> CBNZ
13406 instr[23,5] = simm19 branch offset counted in words
13409 uint32_t size
= INSTR (31, 31);
13410 uint32_t op
= INSTR (24, 24);
13411 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 23, 5) << 2;
13416 cbz32 (cpu
, offset
);
13418 cbnz32 (cpu
, offset
);
13425 cbnz (cpu
, offset
);
13430 dexTestBranchImmediate (sim_cpu
*cpu
)
13432 /* instr[31] = b5 : bit 5 of test bit idx
13433 instr[30,25] = 01 1011
13434 instr[24] = op : 0 ==> TBZ, 1 == TBNZ
13435 instr[23,19] = b40 : bits 4 to 0 of test bit idx
13436 instr[18,5] = simm14 : signed offset counted in words
13437 instr[4,0] = uimm5 */
13439 uint32_t pos
= ((INSTR (31, 31) << 5) | INSTR (23, 19));
13440 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 18, 5) << 2;
13442 NYI_assert (30, 25, 0x1b);
13444 if (INSTR (24, 24) == 0)
13445 tbz (cpu
, pos
, offset
);
13447 tbnz (cpu
, pos
, offset
);
13451 dexCondBranchImmediate (sim_cpu
*cpu
)
13453 /* instr[31,25] = 010 1010
13454 instr[24] = op1; op => 00 ==> B.cond
13455 instr[23,5] = simm19 : signed offset counted in words
13457 instr[3,0] = cond */
13460 uint32_t op
= ((INSTR (24, 24) << 1) | INSTR (4, 4));
13462 NYI_assert (31, 25, 0x2a);
13467 offset
= simm32 (aarch64_get_instr (cpu
), 23, 5) << 2;
13469 bcc (cpu
, offset
, INSTR (3, 0));
13473 dexBranchRegister (sim_cpu
*cpu
)
13475 /* instr[31,25] = 110 1011
13476 instr[24,21] = op : 0 ==> BR, 1 => BLR, 2 => RET, 3 => ERET, 4 => DRPS
13477 instr[20,16] = op2 : must be 11111
13478 instr[15,10] = op3 : must be 000000
13479 instr[4,0] = op2 : must be 11111. */
13481 uint32_t op
= INSTR (24, 21);
13482 uint32_t op2
= INSTR (20, 16);
13483 uint32_t op3
= INSTR (15, 10);
13484 uint32_t op4
= INSTR (4, 0);
13486 NYI_assert (31, 25, 0x6b);
13488 if (op2
!= 0x1F || op3
!= 0 || op4
!= 0)
13502 /* ERET and DRPS accept 0b11111 for rn = instr [4,0]. */
13503 /* anything else is unallocated. */
13504 uint32_t rn
= INSTR (4, 0);
13509 if (op
== 4 || op
== 5)
13516 /* FIXME: We should get the Angel SWI values from ../../libgloss/aarch64/svc.h
13517 but this may not be available. So instead we define the values we need
13519 #define AngelSVC_Reason_Open 0x01
13520 #define AngelSVC_Reason_Close 0x02
13521 #define AngelSVC_Reason_Write 0x05
13522 #define AngelSVC_Reason_Read 0x06
13523 #define AngelSVC_Reason_IsTTY 0x09
13524 #define AngelSVC_Reason_Seek 0x0A
13525 #define AngelSVC_Reason_FLen 0x0C
13526 #define AngelSVC_Reason_Remove 0x0E
13527 #define AngelSVC_Reason_Rename 0x0F
13528 #define AngelSVC_Reason_Clock 0x10
13529 #define AngelSVC_Reason_Time 0x11
13530 #define AngelSVC_Reason_System 0x12
13531 #define AngelSVC_Reason_Errno 0x13
13532 #define AngelSVC_Reason_GetCmdLine 0x15
13533 #define AngelSVC_Reason_HeapInfo 0x16
13534 #define AngelSVC_Reason_ReportException 0x18
13535 #define AngelSVC_Reason_Elapsed 0x30
13539 handle_halt (sim_cpu
*cpu
, uint32_t val
)
13541 uint64_t result
= 0;
13543 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13546 TRACE_SYSCALL (cpu
, " HLT [0x%x]", val
);
13547 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13548 sim_stopped
, SIM_SIGTRAP
);
13551 /* We have encountered an Angel SVC call. See if we can process it. */
13552 switch (aarch64_get_reg_u32 (cpu
, 0, NO_SP
))
13554 case AngelSVC_Reason_HeapInfo
:
13556 /* Get the values. */
13557 uint64_t stack_top
= aarch64_get_stack_start (cpu
);
13558 uint64_t heap_base
= aarch64_get_heap_start (cpu
);
13560 /* Get the pointer */
13561 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13562 ptr
= aarch64_get_mem_u64 (cpu
, ptr
);
13564 /* Fill in the memory block. */
13565 /* Start addr of heap. */
13566 aarch64_set_mem_u64 (cpu
, ptr
+ 0, heap_base
);
13567 /* End addr of heap. */
13568 aarch64_set_mem_u64 (cpu
, ptr
+ 8, stack_top
);
13569 /* Lowest stack addr. */
13570 aarch64_set_mem_u64 (cpu
, ptr
+ 16, heap_base
);
13571 /* Initial stack addr. */
13572 aarch64_set_mem_u64 (cpu
, ptr
+ 24, stack_top
);
13574 TRACE_SYSCALL (cpu
, " AngelSVC: Get Heap Info");
13578 case AngelSVC_Reason_Open
:
13580 /* Get the pointer */
13581 /* uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);. */
13582 /* FIXME: For now we just assume that we will only be asked
13583 to open the standard file descriptors. */
13587 TRACE_SYSCALL (cpu
, " AngelSVC: Open file %d", fd
- 1);
13591 case AngelSVC_Reason_Close
:
13593 uint64_t fh
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13594 TRACE_SYSCALL (cpu
, " AngelSVC: Close file %d", (int) fh
);
13599 case AngelSVC_Reason_Errno
:
13601 TRACE_SYSCALL (cpu
, " AngelSVC: Get Errno");
13604 case AngelSVC_Reason_Clock
:
13606 #ifdef CLOCKS_PER_SEC
13607 (CLOCKS_PER_SEC
>= 100)
13608 ? (clock () / (CLOCKS_PER_SEC
/ 100))
13609 : ((clock () * 100) / CLOCKS_PER_SEC
)
13611 /* Presume unix... clock() returns microseconds. */
13615 TRACE_SYSCALL (cpu
, " AngelSVC: Get Clock");
13618 case AngelSVC_Reason_GetCmdLine
:
13620 /* Get the pointer */
13621 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13622 ptr
= aarch64_get_mem_u64 (cpu
, ptr
);
13624 /* FIXME: No command line for now. */
13625 aarch64_set_mem_u64 (cpu
, ptr
, 0);
13626 TRACE_SYSCALL (cpu
, " AngelSVC: Get Command Line");
13630 case AngelSVC_Reason_IsTTY
:
13632 TRACE_SYSCALL (cpu
, " AngelSVC: IsTTY ?");
13635 case AngelSVC_Reason_Write
:
13637 /* Get the pointer */
13638 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13639 /* Get the write control block. */
13640 uint64_t fd
= aarch64_get_mem_u64 (cpu
, ptr
);
13641 uint64_t buf
= aarch64_get_mem_u64 (cpu
, ptr
+ 8);
13642 uint64_t len
= aarch64_get_mem_u64 (cpu
, ptr
+ 16);
13644 TRACE_SYSCALL (cpu
, "write of %" PRIx64
" bytes from %"
13645 PRIx64
" on descriptor %" PRIx64
,
13650 TRACE_SYSCALL (cpu
,
13651 " AngelSVC: Write: Suspiciously long write: %ld",
13653 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13654 sim_stopped
, SIM_SIGBUS
);
13658 printf ("%.*s", (int) len
, aarch64_get_mem_ptr (cpu
, buf
));
13662 TRACE (cpu
, 0, "\n");
13663 sim_io_eprintf (CPU_STATE (cpu
), "%.*s",
13664 (int) len
, aarch64_get_mem_ptr (cpu
, buf
));
13665 TRACE (cpu
, 0, "\n");
13669 TRACE_SYSCALL (cpu
,
13670 " AngelSVC: Write: Unexpected file handle: %d",
13672 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13673 sim_stopped
, SIM_SIGABRT
);
13678 case AngelSVC_Reason_ReportException
:
13680 /* Get the pointer */
13681 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13682 /*ptr = aarch64_get_mem_u64 (cpu, ptr);. */
13683 uint64_t type
= aarch64_get_mem_u64 (cpu
, ptr
);
13684 uint64_t state
= aarch64_get_mem_u64 (cpu
, ptr
+ 8);
13686 TRACE_SYSCALL (cpu
,
13687 "Angel Exception: type 0x%" PRIx64
" state %" PRIx64
,
13690 if (type
== 0x20026)
13691 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13692 sim_exited
, state
);
13694 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13695 sim_stopped
, SIM_SIGINT
);
13699 case AngelSVC_Reason_Read
:
13700 case AngelSVC_Reason_FLen
:
13701 case AngelSVC_Reason_Seek
:
13702 case AngelSVC_Reason_Remove
:
13703 case AngelSVC_Reason_Time
:
13704 case AngelSVC_Reason_System
:
13705 case AngelSVC_Reason_Rename
:
13706 case AngelSVC_Reason_Elapsed
:
13708 TRACE_SYSCALL (cpu
, " HLT [Unknown angel %x]",
13709 aarch64_get_reg_u32 (cpu
, 0, NO_SP
));
13710 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13711 sim_stopped
, SIM_SIGTRAP
);
13714 aarch64_set_reg_u64 (cpu
, 0, NO_SP
, result
);
13718 dexExcpnGen (sim_cpu
*cpu
)
13720 /* instr[31:24] = 11010100
13721 instr[23,21] = opc : 000 ==> GEN EXCPN, 001 ==> BRK
13722 010 ==> HLT, 101 ==> DBG GEN EXCPN
13723 instr[20,5] = imm16
13724 instr[4,2] = opc2 000 ==> OK, ow ==> UNALLOC
13725 instr[1,0] = LL : discriminates opc */
13727 uint32_t opc
= INSTR (23, 21);
13728 uint32_t imm16
= INSTR (20, 5);
13729 uint32_t opc2
= INSTR (4, 2);
13732 NYI_assert (31, 24, 0xd4);
13739 /* We only implement HLT and BRK for now. */
13740 if (opc
== 1 && LL
== 0)
13742 TRACE_EVENTS (cpu
, " BRK [0x%x]", imm16
);
13743 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13744 sim_exited
, aarch64_get_reg_s32 (cpu
, R0
, SP_OK
));
13747 if (opc
== 2 && LL
== 0)
13748 handle_halt (cpu
, imm16
);
13750 else if (opc
== 0 || opc
== 5)
13757 /* Stub for accessing system registers. */
13760 system_get (sim_cpu
*cpu
, unsigned op0
, unsigned op1
, unsigned crn
,
13761 unsigned crm
, unsigned op2
)
13763 if (crn
== 0 && op1
== 3 && crm
== 0 && op2
== 7)
13764 /* DCZID_EL0 - the Data Cache Zero ID register.
13765 We do not support DC ZVA at the moment, so
13766 we return a value with the disable bit set.
13767 We implement support for the DCZID register since
13768 it is used by the C library's memset function. */
13769 return ((uint64_t) 1) << 4;
13771 if (crn
== 0 && op1
== 3 && crm
== 0 && op2
== 1)
13772 /* Cache Type Register. */
13773 return 0x80008000UL
;
13775 if (crn
== 13 && op1
== 3 && crm
== 0 && op2
== 2)
13776 /* TPIDR_EL0 - thread pointer id. */
13777 return aarch64_get_thread_id (cpu
);
13779 if (op1
== 3 && crm
== 4 && op2
== 0)
13780 return aarch64_get_FPCR (cpu
);
13782 if (op1
== 3 && crm
== 4 && op2
== 1)
13783 return aarch64_get_FPSR (cpu
);
13785 else if (op1
== 3 && crm
== 2 && op2
== 0)
13786 return aarch64_get_CPSR (cpu
);
13792 system_set (sim_cpu
*cpu
, unsigned op0
, unsigned op1
, unsigned crn
,
13793 unsigned crm
, unsigned op2
, uint64_t val
)
13795 if (op1
== 3 && crm
== 4 && op2
== 0)
13796 aarch64_set_FPCR (cpu
, val
);
13798 else if (op1
== 3 && crm
== 4 && op2
== 1)
13799 aarch64_set_FPSR (cpu
, val
);
13801 else if (op1
== 3 && crm
== 2 && op2
== 0)
13802 aarch64_set_CPSR (cpu
, val
);
13809 do_mrs (sim_cpu
*cpu
)
13811 /* instr[31:20] = 1101 0101 0001 1
13818 unsigned sys_op0
= INSTR (19, 19) + 2;
13819 unsigned sys_op1
= INSTR (18, 16);
13820 unsigned sys_crn
= INSTR (15, 12);
13821 unsigned sys_crm
= INSTR (11, 8);
13822 unsigned sys_op2
= INSTR (7, 5);
13823 unsigned rt
= INSTR (4, 0);
13825 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13826 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
13827 system_get (cpu
, sys_op0
, sys_op1
, sys_crn
, sys_crm
, sys_op2
));
13831 do_MSR_immediate (sim_cpu
*cpu
)
13833 /* instr[31:19] = 1101 0101 0000 0
13835 instr[15,12] = 0100
13838 instr[4,0] = 1 1111 */
13840 unsigned op1
= INSTR (18, 16);
13841 /*unsigned crm = INSTR (11, 8);*/
13842 unsigned op2
= INSTR (7, 5);
13844 NYI_assert (31, 19, 0x1AA0);
13845 NYI_assert (15, 12, 0x4);
13846 NYI_assert (4, 0, 0x1F);
13851 HALT_NYI
; /* set SPSel. */
13858 HALT_NYI
; /* set DAIFset. */
13860 HALT_NYI
; /* set DAIFclr. */
13869 do_MSR_reg (sim_cpu
*cpu
)
13871 /* instr[31:20] = 1101 0101 0001
13879 unsigned sys_op0
= INSTR (19, 19) + 2;
13880 unsigned sys_op1
= INSTR (18, 16);
13881 unsigned sys_crn
= INSTR (15, 12);
13882 unsigned sys_crm
= INSTR (11, 8);
13883 unsigned sys_op2
= INSTR (7, 5);
13884 unsigned rt
= INSTR (4, 0);
13886 NYI_assert (31, 20, 0xD51);
13888 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13889 system_set (cpu
, sys_op0
, sys_op1
, sys_crn
, sys_crm
, sys_op2
,
13890 aarch64_get_reg_u64 (cpu
, rt
, NO_SP
));
13894 do_SYS (sim_cpu
*cpu
)
13896 /* instr[31,19] = 1101 0101 0000 1
13902 NYI_assert (31, 19, 0x1AA1);
13904 /* FIXME: For now we just silently accept system ops. */
13908 dexSystem (sim_cpu
*cpu
)
13910 /* instr[31:22] = 1101 01010 0
13917 instr[4,0] = uimm5 */
13919 /* We are interested in HINT, DSB, DMB and ISB
13921 Hint #0 encodes NOOP (this is the only hint we care about)
13922 L == 0, op0 == 0, op1 = 011, CRn = 0010, Rt = 11111,
13923 CRm op2 != 0000 000 OR CRm op2 == 0000 000 || CRm op > 0000 101
13925 DSB, DMB, ISB are data store barrier, data memory barrier and
13926 instruction store barrier, respectively, where
13928 L == 0, op0 == 0, op1 = 011, CRn = 0011, Rt = 11111,
13929 op2 : DSB ==> 100, DMB ==> 101, ISB ==> 110
13930 CRm<3:2> ==> domain, CRm<1:0> ==> types,
13931 domain : 00 ==> OuterShareable, 01 ==> Nonshareable,
13932 10 ==> InerShareable, 11 ==> FullSystem
13933 types : 01 ==> Reads, 10 ==> Writes,
13934 11 ==> All, 00 ==> All (domain == FullSystem). */
13936 unsigned rt
= INSTR (4, 0);
13938 NYI_assert (31, 22, 0x354);
13940 switch (INSTR (21, 12))
13945 /* NOP has CRm != 0000 OR. */
13946 /* (CRm == 0000 AND (op2 == 000 OR op2 > 101)). */
13947 uint32_t crm
= INSTR (11, 8);
13948 uint32_t op2
= INSTR (7, 5);
13950 if (crm
!= 0 || (op2
== 0 || op2
> 5))
13952 /* Actually call nop method so we can reimplement it later. */
13961 uint32_t op2
= INSTR (7, 5);
13966 case 4: dsb (cpu
); return;
13967 case 5: dmb (cpu
); return;
13968 case 6: isb (cpu
); return;
13969 default: HALT_UNALLOC
;
13980 do_SYS (cpu
); /* DC is an alias of SYS. */
13984 if (INSTR (21, 20) == 0x1)
13986 else if (INSTR (21, 19) == 0 && INSTR (15, 12) == 0x4)
13987 do_MSR_immediate (cpu
);
13995 dexBr (sim_cpu
*cpu
)
13997 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
13998 assert group == GROUP_BREXSYS_1010 || group == GROUP_BREXSYS_1011
13999 bits [31,29] of a BrExSys are the secondary dispatch vector. */
14000 uint32_t group2
= dispatchBrExSys (aarch64_get_instr (cpu
));
14005 return dexBranchImmediate (cpu
);
14007 case BR_IMMCMP_001
:
14008 /* Compare has bit 25 clear while test has it set. */
14009 if (!INSTR (25, 25))
14010 dexCompareBranchImmediate (cpu
);
14012 dexTestBranchImmediate (cpu
);
14015 case BR_IMMCOND_010
:
14016 /* This is a conditional branch if bit 25 is clear otherwise
14018 if (!INSTR (25, 25))
14019 dexCondBranchImmediate (cpu
);
14024 case BR_UNALLOC_011
:
14028 dexBranchImmediate (cpu
);
14031 case BR_IMMCMP_101
:
14032 /* Compare has bit 25 clear while test has it set. */
14033 if (!INSTR (25, 25))
14034 dexCompareBranchImmediate (cpu
);
14036 dexTestBranchImmediate (cpu
);
14040 /* Unconditional branch reg has bit 25 set. */
14041 if (INSTR (25, 25))
14042 dexBranchRegister (cpu
);
14044 /* This includes both Excpn Gen, System and unalloc operations.
14045 We need to decode the Excpn Gen operation BRK so we can plant
14046 debugger entry points.
14047 Excpn Gen operations have instr [24] = 0.
14048 we need to decode at least one of the System operations NOP
14049 which is an alias for HINT #0.
14050 System operations have instr [24,22] = 100. */
14051 else if (INSTR (24, 24) == 0)
14054 else if (INSTR (24, 22) == 4)
14062 case BR_UNALLOC_111
:
14066 /* Should never reach here. */
14072 aarch64_decode_and_execute (sim_cpu
*cpu
, uint64_t pc
)
14074 /* We need to check if gdb wants an in here. */
14075 /* checkBreak (cpu);. */
14077 uint64_t group
= dispatchGroup (aarch64_get_instr (cpu
));
14081 case GROUP_PSEUDO_0000
: dexPseudo (cpu
); break;
14082 case GROUP_LDST_0100
: dexLdSt (cpu
); break;
14083 case GROUP_DPREG_0101
: dexDPReg (cpu
); break;
14084 case GROUP_LDST_0110
: dexLdSt (cpu
); break;
14085 case GROUP_ADVSIMD_0111
: dexAdvSIMD0 (cpu
); break;
14086 case GROUP_DPIMM_1000
: dexDPImm (cpu
); break;
14087 case GROUP_DPIMM_1001
: dexDPImm (cpu
); break;
14088 case GROUP_BREXSYS_1010
: dexBr (cpu
); break;
14089 case GROUP_BREXSYS_1011
: dexBr (cpu
); break;
14090 case GROUP_LDST_1100
: dexLdSt (cpu
); break;
14091 case GROUP_DPREG_1101
: dexDPReg (cpu
); break;
14092 case GROUP_LDST_1110
: dexLdSt (cpu
); break;
14093 case GROUP_ADVSIMD_1111
: dexAdvSIMD1 (cpu
); break;
14095 case GROUP_UNALLOC_0001
:
14096 case GROUP_UNALLOC_0010
:
14097 case GROUP_UNALLOC_0011
:
14101 /* Should never reach here. */
14107 aarch64_step (sim_cpu
*cpu
)
14109 uint64_t pc
= aarch64_get_PC (cpu
);
14111 if (pc
== TOP_LEVEL_RETURN_PC
)
14114 aarch64_set_next_PC (cpu
, pc
+ 4);
14116 /* Code is always little-endian. */
14117 sim_core_read_buffer (CPU_STATE (cpu
), cpu
, read_map
,
14118 & aarch64_get_instr (cpu
), pc
, 4);
14119 aarch64_get_instr (cpu
) = endian_le2h_4 (aarch64_get_instr (cpu
));
14121 TRACE_INSN (cpu
, " pc = %" PRIx64
" instr = %08x", pc
,
14122 aarch64_get_instr (cpu
));
14123 TRACE_DISASM (cpu
, pc
);
14125 aarch64_decode_and_execute (cpu
, pc
);
14131 aarch64_run (SIM_DESC sd
)
14133 sim_cpu
*cpu
= STATE_CPU (sd
, 0);
14135 while (aarch64_step (cpu
))
14137 aarch64_update_PC (cpu
);
14139 if (sim_events_tick (sd
))
14140 sim_events_process (sd
);
14143 sim_engine_halt (sd
, cpu
, NULL
, aarch64_get_PC (cpu
),
14144 sim_exited
, aarch64_get_reg_s32 (cpu
, R0
, NO_SP
));
14148 aarch64_init (sim_cpu
*cpu
, uint64_t pc
)
14150 uint64_t sp
= aarch64_get_stack_start (cpu
);
14152 /* Install SP, FP and PC and set LR to -20
14153 so we can detect a top-level return. */
14154 aarch64_set_reg_u64 (cpu
, SP
, SP_OK
, sp
);
14155 aarch64_set_reg_u64 (cpu
, FP
, SP_OK
, sp
);
14156 aarch64_set_reg_u64 (cpu
, LR
, SP_OK
, TOP_LEVEL_RETURN_PC
);
14157 aarch64_set_next_PC (cpu
, pc
);
14158 aarch64_update_PC (cpu
);
14159 aarch64_init_LIT_table ();