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 input1
= upper
? val_n1
: val_m1
;
2965 uint64_t input2
= upper
? val_n2
: val_m2
;
2968 NYI_assert (29, 24, 0x0E);
2969 NYI_assert (21, 21, 0);
2970 NYI_assert (15, 15, 0);
2971 NYI_assert (13, 10, 6);
2973 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2974 switch (INSTR (23, 23))
2977 for (i
= 0; i
< 8; i
++)
2979 val1
|= (input1
>> (i
* 8)) & (0xFFULL
<< (i
* 8));
2980 val2
|= (input2
>> (i
* 8)) & (0xFFULL
<< (i
* 8));
2985 for (i
= 0; i
< 4; i
++)
2987 val1
|= (input1
>> (i
* 16)) & (0xFFFFULL
<< (i
* 16));
2988 val2
|= (input2
>> (i
* 16)) & (0xFFFFULL
<< (i
* 16));
2993 val1
= ((input1
& 0xFFFFFFFF) | ((input1
>> 32) & 0xFFFFFFFF00000000ULL
));
2994 val2
= ((input2
& 0xFFFFFFFF) | ((input2
>> 32) & 0xFFFFFFFF00000000ULL
));
3002 aarch64_set_vec_u64 (cpu
, vd
, 0, val1
);
3004 aarch64_set_vec_u64 (cpu
, vd
, 1, val2
);
3008 do_vec_ZIP (sim_cpu
*cpu
)
3011 instr[30] = half(0)/full(1)
3012 instr[29,24] = 00 1110
3013 instr[23,22] = size: byte(00), hald(01), word (10), long (11)
3017 instr[14] = lower (0) / upper (1)
3022 int full
= INSTR (30, 30);
3023 int upper
= INSTR (14, 14);
3025 unsigned vm
= INSTR (20, 16);
3026 unsigned vn
= INSTR (9, 5);
3027 unsigned vd
= INSTR (4, 0);
3029 uint64_t val_m1
= aarch64_get_vec_u64 (cpu
, vm
, 0);
3030 uint64_t val_m2
= aarch64_get_vec_u64 (cpu
, vm
, 1);
3031 uint64_t val_n1
= aarch64_get_vec_u64 (cpu
, vn
, 0);
3032 uint64_t val_n2
= aarch64_get_vec_u64 (cpu
, vn
, 1);
3037 uint64_t input1
= upper
? val_n1
: val_m1
;
3038 uint64_t input2
= upper
? val_n2
: val_m2
;
3040 NYI_assert (29, 24, 0x0E);
3041 NYI_assert (21, 21, 0);
3042 NYI_assert (15, 15, 0);
3043 NYI_assert (13, 10, 0xE);
3045 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3046 switch (INSTR (23, 23))
3050 ((input1
<< 0) & (0xFF << 0))
3051 | ((input2
<< 8) & (0xFF << 8))
3052 | ((input1
<< 8) & (0xFF << 16))
3053 | ((input2
<< 16) & (0xFF << 24))
3054 | ((input1
<< 16) & (0xFFULL
<< 32))
3055 | ((input2
<< 24) & (0xFFULL
<< 40))
3056 | ((input1
<< 24) & (0xFFULL
<< 48))
3057 | ((input2
<< 32) & (0xFFULL
<< 56));
3060 ((input1
>> 32) & (0xFF << 0))
3061 | ((input2
>> 24) & (0xFF << 8))
3062 | ((input1
>> 24) & (0xFF << 16))
3063 | ((input2
>> 16) & (0xFF << 24))
3064 | ((input1
>> 16) & (0xFFULL
<< 32))
3065 | ((input2
>> 8) & (0xFFULL
<< 40))
3066 | ((input1
>> 8) & (0xFFULL
<< 48))
3067 | ((input2
>> 0) & (0xFFULL
<< 56));
3072 ((input1
<< 0) & (0xFFFF << 0))
3073 | ((input2
<< 16) & (0xFFFF << 16))
3074 | ((input1
<< 16) & (0xFFFFULL
<< 32))
3075 | ((input2
<< 32) & (0xFFFFULL
<< 48));
3078 ((input1
>> 32) & (0xFFFF << 0))
3079 | ((input2
>> 16) & (0xFFFF << 16))
3080 | ((input1
>> 16) & (0xFFFFULL
<< 32))
3081 | ((input2
>> 0) & (0xFFFFULL
<< 48));
3085 val1
= (input1
& 0xFFFFFFFFULL
) | (input2
<< 32);
3086 val2
= (input2
& 0xFFFFFFFFULL
) | (input1
<< 32);
3095 aarch64_set_vec_u64 (cpu
, vd
, 0, val1
);
3097 aarch64_set_vec_u64 (cpu
, vd
, 1, val2
);
3100 /* Floating point immediates are encoded in 8 bits.
3101 fpimm[7] = sign bit.
3102 fpimm[6:4] = signed exponent.
3103 fpimm[3:0] = fraction (assuming leading 1).
3104 i.e. F = s * 1.f * 2^(e - b). */
3107 fp_immediate_for_encoding_32 (uint32_t imm8
)
3110 uint32_t s
, e
, f
, i
;
3112 s
= (imm8
>> 7) & 0x1;
3113 e
= (imm8
>> 4) & 0x7;
3116 /* The fp value is s * n/16 * 2r where n is 16+e. */
3117 u
= (16.0 + f
) / 16.0;
3119 /* N.B. exponent is signed. */
3124 for (i
= 0; i
<= epos
; i
++)
3131 for (i
= 0; i
< eneg
; i
++)
3142 fp_immediate_for_encoding_64 (uint32_t imm8
)
3145 uint32_t s
, e
, f
, i
;
3147 s
= (imm8
>> 7) & 0x1;
3148 e
= (imm8
>> 4) & 0x7;
3151 /* The fp value is s * n/16 * 2r where n is 16+e. */
3152 u
= (16.0 + f
) / 16.0;
3154 /* N.B. exponent is signed. */
3159 for (i
= 0; i
<= epos
; i
++)
3166 for (i
= 0; i
< eneg
; i
++)
3177 do_vec_MOV_immediate (sim_cpu
*cpu
)
3180 instr[30] = full/half selector
3181 instr[29,19] = 00111100000
3182 instr[18,16] = high 3 bits of uimm8
3183 instr[15,12] = size & shift:
3185 0010 => 32-bit + LSL#8
3186 0100 => 32-bit + LSL#16
3187 0110 => 32-bit + LSL#24
3188 1010 => 16-bit + LSL#8
3190 1101 => 32-bit + MSL#16
3191 1100 => 32-bit + MSL#8
3195 instr[9,5] = low 5-bits of uimm8
3198 int full
= INSTR (30, 30);
3199 unsigned vd
= INSTR (4, 0);
3200 unsigned val
= (INSTR (18, 16) << 5) | INSTR (9, 5);
3203 NYI_assert (29, 19, 0x1E0);
3204 NYI_assert (11, 10, 1);
3206 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3207 switch (INSTR (15, 12))
3209 case 0x0: /* 32-bit, no shift. */
3210 case 0x2: /* 32-bit, shift by 8. */
3211 case 0x4: /* 32-bit, shift by 16. */
3212 case 0x6: /* 32-bit, shift by 24. */
3213 val
<<= (8 * INSTR (14, 13));
3214 for (i
= 0; i
< (full
? 4 : 2); i
++)
3215 aarch64_set_vec_u32 (cpu
, vd
, i
, val
);
3218 case 0xa: /* 16-bit, shift by 8. */
3221 case 0x8: /* 16-bit, no shift. */
3222 for (i
= 0; i
< (full
? 8 : 4); i
++)
3223 aarch64_set_vec_u16 (cpu
, vd
, i
, val
);
3225 case 0xd: /* 32-bit, mask shift by 16. */
3229 case 0xc: /* 32-bit, mask shift by 8. */
3232 for (i
= 0; i
< (full
? 4 : 2); i
++)
3233 aarch64_set_vec_u32 (cpu
, vd
, i
, val
);
3236 case 0xe: /* 8-bit, no shift. */
3237 for (i
= 0; i
< (full
? 16 : 8); i
++)
3238 aarch64_set_vec_u8 (cpu
, vd
, i
, val
);
3241 case 0xf: /* FMOV Vs.{2|4}S, #fpimm. */
3243 float u
= fp_immediate_for_encoding_32 (val
);
3244 for (i
= 0; i
< (full
? 4 : 2); i
++)
3245 aarch64_set_vec_float (cpu
, vd
, i
, u
);
3255 do_vec_MVNI (sim_cpu
*cpu
)
3258 instr[30] = full/half selector
3259 instr[29,19] = 10111100000
3260 instr[18,16] = high 3 bits of uimm8
3261 instr[15,12] = selector
3263 instr[9,5] = low 5-bits of uimm8
3266 int full
= INSTR (30, 30);
3267 unsigned vd
= INSTR (4, 0);
3268 unsigned val
= (INSTR (18, 16) << 5) | INSTR (9, 5);
3271 NYI_assert (29, 19, 0x5E0);
3272 NYI_assert (11, 10, 1);
3274 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3275 switch (INSTR (15, 12))
3277 case 0x0: /* 32-bit, no shift. */
3278 case 0x2: /* 32-bit, shift by 8. */
3279 case 0x4: /* 32-bit, shift by 16. */
3280 case 0x6: /* 32-bit, shift by 24. */
3281 val
<<= (8 * INSTR (14, 13));
3283 for (i
= 0; i
< (full
? 4 : 2); i
++)
3284 aarch64_set_vec_u32 (cpu
, vd
, i
, val
);
3287 case 0xa: /* 16-bit, 8 bit shift. */
3289 case 0x8: /* 16-bit, no shift. */
3291 for (i
= 0; i
< (full
? 8 : 4); i
++)
3292 aarch64_set_vec_u16 (cpu
, vd
, i
, val
);
3295 case 0xd: /* 32-bit, mask shift by 16. */
3298 case 0xc: /* 32-bit, mask shift by 8. */
3302 for (i
= 0; i
< (full
? 4 : 2); i
++)
3303 aarch64_set_vec_u32 (cpu
, vd
, i
, val
);
3306 case 0xE: /* MOVI Dn, #mask64 */
3310 for (i
= 0; i
< 8; i
++)
3312 mask
|= (0xFFUL
<< (i
* 8));
3313 aarch64_set_vec_u64 (cpu
, vd
, 0, mask
);
3314 aarch64_set_vec_u64 (cpu
, vd
, 1, mask
);
3318 case 0xf: /* FMOV Vd.2D, #fpimm. */
3320 double u
= fp_immediate_for_encoding_64 (val
);
3325 aarch64_set_vec_double (cpu
, vd
, 0, u
);
3326 aarch64_set_vec_double (cpu
, vd
, 1, u
);
3335 #define ABS(A) ((A) < 0 ? - (A) : (A))
3338 do_vec_ABS (sim_cpu
*cpu
)
3341 instr[30] = half(0)/full(1)
3342 instr[29,24] = 00 1110
3343 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3344 instr[21,10] = 10 0000 1011 10
3348 unsigned vn
= INSTR (9, 5);
3349 unsigned vd
= INSTR (4, 0);
3350 unsigned full
= INSTR (30, 30);
3353 NYI_assert (29, 24, 0x0E);
3354 NYI_assert (21, 10, 0x82E);
3356 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3357 switch (INSTR (23, 22))
3360 for (i
= 0; i
< (full
? 16 : 8); i
++)
3361 aarch64_set_vec_s8 (cpu
, vd
, i
,
3362 ABS (aarch64_get_vec_s8 (cpu
, vn
, i
)));
3366 for (i
= 0; i
< (full
? 8 : 4); i
++)
3367 aarch64_set_vec_s16 (cpu
, vd
, i
,
3368 ABS (aarch64_get_vec_s16 (cpu
, vn
, i
)));
3372 for (i
= 0; i
< (full
? 4 : 2); i
++)
3373 aarch64_set_vec_s32 (cpu
, vd
, i
,
3374 ABS (aarch64_get_vec_s32 (cpu
, vn
, i
)));
3380 for (i
= 0; i
< 2; i
++)
3381 aarch64_set_vec_s64 (cpu
, vd
, i
,
3382 ABS (aarch64_get_vec_s64 (cpu
, vn
, i
)));
3388 do_vec_ADDV (sim_cpu
*cpu
)
3391 instr[30] = full/half selector
3392 instr[29,24] = 00 1110
3393 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3394 instr[21,10] = 11 0001 1011 10
3398 unsigned vm
= INSTR (9, 5);
3399 unsigned rd
= INSTR (4, 0);
3402 int full
= INSTR (30, 30);
3404 NYI_assert (29, 24, 0x0E);
3405 NYI_assert (21, 10, 0xC6E);
3407 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3408 switch (INSTR (23, 22))
3411 for (i
= 0; i
< (full
? 16 : 8); i
++)
3412 val
+= aarch64_get_vec_u8 (cpu
, vm
, i
);
3413 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val
);
3417 for (i
= 0; i
< (full
? 8 : 4); i
++)
3418 val
+= aarch64_get_vec_u16 (cpu
, vm
, i
);
3419 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val
);
3423 for (i
= 0; i
< (full
? 4 : 2); i
++)
3424 val
+= aarch64_get_vec_u32 (cpu
, vm
, i
);
3425 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val
);
3431 val
= aarch64_get_vec_u64 (cpu
, vm
, 0);
3432 val
+= aarch64_get_vec_u64 (cpu
, vm
, 1);
3433 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val
);
3439 do_vec_ins_2 (sim_cpu
*cpu
)
3441 /* instr[31,21] = 01001110000
3442 instr[20,18] = size & element selector
3444 instr[13] = direction: to vec(0), from vec (1)
3450 unsigned vm
= INSTR (9, 5);
3451 unsigned vd
= INSTR (4, 0);
3453 NYI_assert (31, 21, 0x270);
3454 NYI_assert (17, 14, 0);
3455 NYI_assert (12, 10, 7);
3457 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3458 if (INSTR (13, 13) == 1)
3460 if (INSTR (18, 18) == 1)
3463 elem
= INSTR (20, 19);
3464 aarch64_set_reg_u64 (cpu
, vd
, NO_SP
,
3465 aarch64_get_vec_u32 (cpu
, vm
, elem
));
3470 if (INSTR (19, 19) != 1)
3473 elem
= INSTR (20, 20);
3474 aarch64_set_reg_u64 (cpu
, vd
, NO_SP
,
3475 aarch64_get_vec_u64 (cpu
, vm
, elem
));
3480 if (INSTR (18, 18) == 1)
3483 elem
= INSTR (20, 19);
3484 aarch64_set_vec_u32 (cpu
, vd
, elem
,
3485 aarch64_get_reg_u32 (cpu
, vm
, NO_SP
));
3490 if (INSTR (19, 19) != 1)
3493 elem
= INSTR (20, 20);
3494 aarch64_set_vec_u64 (cpu
, vd
, elem
,
3495 aarch64_get_reg_u64 (cpu
, vm
, NO_SP
));
3500 #define DO_VEC_WIDENING_MUL(N, DST_TYPE, READ_TYPE, WRITE_TYPE) \
3503 DST_TYPE a[N], b[N]; \
3505 for (i = 0; i < (N); i++) \
3507 a[i] = aarch64_get_vec_##READ_TYPE (cpu, vn, i + bias); \
3508 b[i] = aarch64_get_vec_##READ_TYPE (cpu, vm, i + bias); \
3510 for (i = 0; i < (N); i++) \
3511 aarch64_set_vec_##WRITE_TYPE (cpu, vd, i, a[i] * b[i]); \
3516 do_vec_mull (sim_cpu
*cpu
)
3519 instr[30] = lower(0)/upper(1) selector
3520 instr[29] = signed(0)/unsigned(1)
3521 instr[28,24] = 0 1110
3522 instr[23,22] = size: 8-bit (00), 16-bit (01), 32-bit (10)
3525 instr[15,10] = 11 0000
3529 int unsign
= INSTR (29, 29);
3530 int bias
= INSTR (30, 30);
3531 unsigned vm
= INSTR (20, 16);
3532 unsigned vn
= INSTR ( 9, 5);
3533 unsigned vd
= INSTR ( 4, 0);
3536 NYI_assert (28, 24, 0x0E);
3537 NYI_assert (15, 10, 0x30);
3539 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3540 /* NB: Read source values before writing results, in case
3541 the source and destination vectors are the same. */
3542 switch (INSTR (23, 22))
3548 DO_VEC_WIDENING_MUL (8, uint16_t, u8
, u16
);
3550 DO_VEC_WIDENING_MUL (8, int16_t, s8
, s16
);
3557 DO_VEC_WIDENING_MUL (4, uint32_t, u16
, u32
);
3559 DO_VEC_WIDENING_MUL (4, int32_t, s16
, s32
);
3566 DO_VEC_WIDENING_MUL (2, uint64_t, u32
, u64
);
3568 DO_VEC_WIDENING_MUL (2, int64_t, s32
, s64
);
3577 do_vec_fadd (sim_cpu
*cpu
)
3580 instr[30] = half(0)/full(1)
3581 instr[29,24] = 001110
3582 instr[23] = FADD(0)/FSUB(1)
3583 instr[22] = float (0)/double(1)
3586 instr[15,10] = 110101
3590 unsigned vm
= INSTR (20, 16);
3591 unsigned vn
= INSTR (9, 5);
3592 unsigned vd
= INSTR (4, 0);
3594 int full
= INSTR (30, 30);
3596 NYI_assert (29, 24, 0x0E);
3597 NYI_assert (21, 21, 1);
3598 NYI_assert (15, 10, 0x35);
3600 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3608 for (i
= 0; i
< 2; i
++)
3609 aarch64_set_vec_double (cpu
, vd
, i
,
3610 aarch64_get_vec_double (cpu
, vn
, i
)
3611 - aarch64_get_vec_double (cpu
, vm
, i
));
3615 for (i
= 0; i
< (full
? 4 : 2); i
++)
3616 aarch64_set_vec_float (cpu
, vd
, i
,
3617 aarch64_get_vec_float (cpu
, vn
, i
)
3618 - aarch64_get_vec_float (cpu
, vm
, i
));
3628 for (i
= 0; i
< 2; i
++)
3629 aarch64_set_vec_double (cpu
, vd
, i
,
3630 aarch64_get_vec_double (cpu
, vm
, i
)
3631 + aarch64_get_vec_double (cpu
, vn
, i
));
3635 for (i
= 0; i
< (full
? 4 : 2); i
++)
3636 aarch64_set_vec_float (cpu
, vd
, i
,
3637 aarch64_get_vec_float (cpu
, vm
, i
)
3638 + aarch64_get_vec_float (cpu
, vn
, i
));
3644 do_vec_add (sim_cpu
*cpu
)
3647 instr[30] = full/half selector
3648 instr[29,24] = 001110
3649 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3652 instr[15,10] = 100001
3656 unsigned vm
= INSTR (20, 16);
3657 unsigned vn
= INSTR (9, 5);
3658 unsigned vd
= INSTR (4, 0);
3660 int full
= INSTR (30, 30);
3662 NYI_assert (29, 24, 0x0E);
3663 NYI_assert (21, 21, 1);
3664 NYI_assert (15, 10, 0x21);
3666 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3667 switch (INSTR (23, 22))
3670 for (i
= 0; i
< (full
? 16 : 8); i
++)
3671 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vn
, i
)
3672 + aarch64_get_vec_u8 (cpu
, vm
, i
));
3676 for (i
= 0; i
< (full
? 8 : 4); i
++)
3677 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vn
, i
)
3678 + aarch64_get_vec_u16 (cpu
, vm
, i
));
3682 for (i
= 0; i
< (full
? 4 : 2); i
++)
3683 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vn
, i
)
3684 + aarch64_get_vec_u32 (cpu
, vm
, i
));
3690 aarch64_set_vec_u64 (cpu
, vd
, 0, aarch64_get_vec_u64 (cpu
, vn
, 0)
3691 + aarch64_get_vec_u64 (cpu
, vm
, 0));
3692 aarch64_set_vec_u64 (cpu
, vd
, 1,
3693 aarch64_get_vec_u64 (cpu
, vn
, 1)
3694 + aarch64_get_vec_u64 (cpu
, vm
, 1));
3700 do_vec_mul (sim_cpu
*cpu
)
3703 instr[30] = full/half selector
3704 instr[29,24] = 00 1110
3705 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3708 instr[15,10] = 10 0111
3712 unsigned vm
= INSTR (20, 16);
3713 unsigned vn
= INSTR (9, 5);
3714 unsigned vd
= INSTR (4, 0);
3716 int full
= INSTR (30, 30);
3719 NYI_assert (29, 24, 0x0E);
3720 NYI_assert (21, 21, 1);
3721 NYI_assert (15, 10, 0x27);
3723 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3724 switch (INSTR (23, 22))
3727 DO_VEC_WIDENING_MUL (full
? 16 : 8, uint16_t, u8
, u16
);
3731 DO_VEC_WIDENING_MUL (full
? 8 : 4, uint32_t, u16
, u32
);
3735 DO_VEC_WIDENING_MUL (full
? 4 : 2, uint64_t, u32
, u64
);
3744 do_vec_MLA (sim_cpu
*cpu
)
3747 instr[30] = full/half selector
3748 instr[29,24] = 00 1110
3749 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3752 instr[15,10] = 1001 01
3756 unsigned vm
= INSTR (20, 16);
3757 unsigned vn
= INSTR (9, 5);
3758 unsigned vd
= INSTR (4, 0);
3760 int full
= INSTR (30, 30);
3762 NYI_assert (29, 24, 0x0E);
3763 NYI_assert (21, 21, 1);
3764 NYI_assert (15, 10, 0x25);
3766 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3767 switch (INSTR (23, 22))
3771 uint16_t a
[16], b
[16];
3773 for (i
= 0; i
< (full
? 16 : 8); i
++)
3775 a
[i
] = aarch64_get_vec_u8 (cpu
, vn
, i
);
3776 b
[i
] = aarch64_get_vec_u8 (cpu
, vm
, i
);
3779 for (i
= 0; i
< (full
? 16 : 8); i
++)
3781 uint16_t v
= aarch64_get_vec_u8 (cpu
, vd
, i
);
3783 aarch64_set_vec_u16 (cpu
, vd
, i
, v
+ (a
[i
] * b
[i
]));
3790 uint32_t a
[8], b
[8];
3792 for (i
= 0; i
< (full
? 8 : 4); i
++)
3794 a
[i
] = aarch64_get_vec_u16 (cpu
, vn
, i
);
3795 b
[i
] = aarch64_get_vec_u16 (cpu
, vm
, i
);
3798 for (i
= 0; i
< (full
? 8 : 4); i
++)
3800 uint32_t v
= aarch64_get_vec_u16 (cpu
, vd
, i
);
3802 aarch64_set_vec_u32 (cpu
, vd
, i
, v
+ (a
[i
] * b
[i
]));
3809 uint64_t a
[4], b
[4];
3811 for (i
= 0; i
< (full
? 4 : 2); i
++)
3813 a
[i
] = aarch64_get_vec_u32 (cpu
, vn
, i
);
3814 b
[i
] = aarch64_get_vec_u32 (cpu
, vm
, i
);
3817 for (i
= 0; i
< (full
? 4 : 2); i
++)
3819 uint64_t v
= aarch64_get_vec_u32 (cpu
, vd
, i
);
3821 aarch64_set_vec_u64 (cpu
, vd
, i
, v
+ (a
[i
] * b
[i
]));
3832 fmaxnm (float a
, float b
)
3834 if (fpclassify (a
) == FP_NORMAL
)
3836 if (fpclassify (b
) == FP_NORMAL
)
3837 return a
> b
? a
: b
;
3840 else if (fpclassify (b
) == FP_NORMAL
)
3846 fminnm (float a
, float b
)
3848 if (fpclassify (a
) == FP_NORMAL
)
3850 if (fpclassify (b
) == FP_NORMAL
)
3851 return a
< b
? a
: b
;
3854 else if (fpclassify (b
) == FP_NORMAL
)
3860 dmaxnm (double a
, double b
)
3862 if (fpclassify (a
) == FP_NORMAL
)
3864 if (fpclassify (b
) == FP_NORMAL
)
3865 return a
> b
? a
: b
;
3868 else if (fpclassify (b
) == FP_NORMAL
)
3874 dminnm (double a
, double b
)
3876 if (fpclassify (a
) == FP_NORMAL
)
3878 if (fpclassify (b
) == FP_NORMAL
)
3879 return a
< b
? a
: b
;
3882 else if (fpclassify (b
) == FP_NORMAL
)
3888 do_vec_FminmaxNMP (sim_cpu
*cpu
)
3891 instr [30] = half (0)/full (1)
3892 instr [29,24] = 10 1110
3893 instr [23] = max(0)/min(1)
3894 instr [22] = float (0)/double (1)
3897 instr [15,10] = 1100 01
3899 instr [4.0] = Vd. */
3901 unsigned vm
= INSTR (20, 16);
3902 unsigned vn
= INSTR (9, 5);
3903 unsigned vd
= INSTR (4, 0);
3904 int full
= INSTR (30, 30);
3906 NYI_assert (29, 24, 0x2E);
3907 NYI_assert (21, 21, 1);
3908 NYI_assert (15, 10, 0x31);
3910 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3913 double (* fn
)(double, double) = INSTR (23, 23)
3918 aarch64_set_vec_double (cpu
, vd
, 0,
3919 fn (aarch64_get_vec_double (cpu
, vn
, 0),
3920 aarch64_get_vec_double (cpu
, vn
, 1)));
3921 aarch64_set_vec_double (cpu
, vd
, 0,
3922 fn (aarch64_get_vec_double (cpu
, vm
, 0),
3923 aarch64_get_vec_double (cpu
, vm
, 1)));
3927 float (* fn
)(float, float) = INSTR (23, 23)
3930 aarch64_set_vec_float (cpu
, vd
, 0,
3931 fn (aarch64_get_vec_float (cpu
, vn
, 0),
3932 aarch64_get_vec_float (cpu
, vn
, 1)));
3934 aarch64_set_vec_float (cpu
, vd
, 1,
3935 fn (aarch64_get_vec_float (cpu
, vn
, 2),
3936 aarch64_get_vec_float (cpu
, vn
, 3)));
3938 aarch64_set_vec_float (cpu
, vd
, (full
? 2 : 1),
3939 fn (aarch64_get_vec_float (cpu
, vm
, 0),
3940 aarch64_get_vec_float (cpu
, vm
, 1)));
3942 aarch64_set_vec_float (cpu
, vd
, 3,
3943 fn (aarch64_get_vec_float (cpu
, vm
, 2),
3944 aarch64_get_vec_float (cpu
, vm
, 3)));
3949 do_vec_AND (sim_cpu
*cpu
)
3952 instr[30] = half (0)/full (1)
3953 instr[29,21] = 001110001
3955 instr[15,10] = 000111
3959 unsigned vm
= INSTR (20, 16);
3960 unsigned vn
= INSTR (9, 5);
3961 unsigned vd
= INSTR (4, 0);
3963 int full
= INSTR (30, 30);
3965 NYI_assert (29, 21, 0x071);
3966 NYI_assert (15, 10, 0x07);
3968 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3969 for (i
= 0; i
< (full
? 4 : 2); i
++)
3970 aarch64_set_vec_u32 (cpu
, vd
, i
,
3971 aarch64_get_vec_u32 (cpu
, vn
, i
)
3972 & aarch64_get_vec_u32 (cpu
, vm
, i
));
3976 do_vec_BSL (sim_cpu
*cpu
)
3979 instr[30] = half (0)/full (1)
3980 instr[29,21] = 101110011
3982 instr[15,10] = 000111
3986 unsigned vm
= INSTR (20, 16);
3987 unsigned vn
= INSTR (9, 5);
3988 unsigned vd
= INSTR (4, 0);
3990 int full
= INSTR (30, 30);
3992 NYI_assert (29, 21, 0x173);
3993 NYI_assert (15, 10, 0x07);
3995 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3996 for (i
= 0; i
< (full
? 16 : 8); i
++)
3997 aarch64_set_vec_u8 (cpu
, vd
, i
,
3998 ( aarch64_get_vec_u8 (cpu
, vd
, i
)
3999 & aarch64_get_vec_u8 (cpu
, vn
, i
))
4000 | ((~ aarch64_get_vec_u8 (cpu
, vd
, i
))
4001 & aarch64_get_vec_u8 (cpu
, vm
, i
)));
4005 do_vec_EOR (sim_cpu
*cpu
)
4008 instr[30] = half (0)/full (1)
4009 instr[29,21] = 10 1110 001
4011 instr[15,10] = 000111
4015 unsigned vm
= INSTR (20, 16);
4016 unsigned vn
= INSTR (9, 5);
4017 unsigned vd
= INSTR (4, 0);
4019 int full
= INSTR (30, 30);
4021 NYI_assert (29, 21, 0x171);
4022 NYI_assert (15, 10, 0x07);
4024 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4025 for (i
= 0; i
< (full
? 4 : 2); i
++)
4026 aarch64_set_vec_u32 (cpu
, vd
, i
,
4027 aarch64_get_vec_u32 (cpu
, vn
, i
)
4028 ^ aarch64_get_vec_u32 (cpu
, vm
, i
));
4032 do_vec_bit (sim_cpu
*cpu
)
4035 instr[30] = half (0)/full (1)
4036 instr[29,23] = 10 1110 1
4037 instr[22] = BIT (0) / BIF (1)
4040 instr[15,10] = 0001 11
4044 unsigned vm
= INSTR (20, 16);
4045 unsigned vn
= INSTR (9, 5);
4046 unsigned vd
= INSTR (4, 0);
4047 unsigned full
= INSTR (30, 30);
4048 unsigned test_false
= INSTR (22, 22);
4051 NYI_assert (29, 23, 0x5D);
4052 NYI_assert (21, 21, 1);
4053 NYI_assert (15, 10, 0x07);
4055 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4058 for (i
= 0; i
< (full
? 16 : 8); i
++)
4059 if (aarch64_get_vec_u32 (cpu
, vn
, i
) == 0)
4060 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vm
, i
));
4064 for (i
= 0; i
< (full
? 16 : 8); i
++)
4065 if (aarch64_get_vec_u32 (cpu
, vn
, i
) != 0)
4066 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vm
, i
));
4071 do_vec_ORN (sim_cpu
*cpu
)
4074 instr[30] = half (0)/full (1)
4075 instr[29,21] = 00 1110 111
4077 instr[15,10] = 00 0111
4081 unsigned vm
= INSTR (20, 16);
4082 unsigned vn
= INSTR (9, 5);
4083 unsigned vd
= INSTR (4, 0);
4085 int full
= INSTR (30, 30);
4087 NYI_assert (29, 21, 0x077);
4088 NYI_assert (15, 10, 0x07);
4090 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4091 for (i
= 0; i
< (full
? 16 : 8); i
++)
4092 aarch64_set_vec_u8 (cpu
, vd
, i
,
4093 aarch64_get_vec_u8 (cpu
, vn
, i
)
4094 | ~ aarch64_get_vec_u8 (cpu
, vm
, i
));
4098 do_vec_ORR (sim_cpu
*cpu
)
4101 instr[30] = half (0)/full (1)
4102 instr[29,21] = 00 1110 101
4104 instr[15,10] = 0001 11
4108 unsigned vm
= INSTR (20, 16);
4109 unsigned vn
= INSTR (9, 5);
4110 unsigned vd
= INSTR (4, 0);
4112 int full
= INSTR (30, 30);
4114 NYI_assert (29, 21, 0x075);
4115 NYI_assert (15, 10, 0x07);
4117 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4118 for (i
= 0; i
< (full
? 16 : 8); i
++)
4119 aarch64_set_vec_u8 (cpu
, vd
, i
,
4120 aarch64_get_vec_u8 (cpu
, vn
, i
)
4121 | aarch64_get_vec_u8 (cpu
, vm
, i
));
4125 do_vec_BIC (sim_cpu
*cpu
)
4128 instr[30] = half (0)/full (1)
4129 instr[29,21] = 00 1110 011
4131 instr[15,10] = 00 0111
4135 unsigned vm
= INSTR (20, 16);
4136 unsigned vn
= INSTR (9, 5);
4137 unsigned vd
= INSTR (4, 0);
4139 int full
= INSTR (30, 30);
4141 NYI_assert (29, 21, 0x073);
4142 NYI_assert (15, 10, 0x07);
4144 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4145 for (i
= 0; i
< (full
? 16 : 8); i
++)
4146 aarch64_set_vec_u8 (cpu
, vd
, i
,
4147 aarch64_get_vec_u8 (cpu
, vn
, i
)
4148 & ~ aarch64_get_vec_u8 (cpu
, vm
, i
));
4152 do_vec_XTN (sim_cpu
*cpu
)
4155 instr[30] = first part (0)/ second part (1)
4156 instr[29,24] = 00 1110
4157 instr[23,22] = size: byte(00), half(01), word (10)
4158 instr[21,10] = 1000 0100 1010
4162 unsigned vs
= INSTR (9, 5);
4163 unsigned vd
= INSTR (4, 0);
4164 unsigned bias
= INSTR (30, 30);
4167 NYI_assert (29, 24, 0x0E);
4168 NYI_assert (21, 10, 0x84A);
4170 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4171 switch (INSTR (23, 22))
4175 for (i
= 0; i
< 8; i
++)
4176 aarch64_set_vec_u8 (cpu
, vd
, i
+ 8,
4177 aarch64_get_vec_u16 (cpu
, vs
, i
) >> 8);
4179 for (i
= 0; i
< 8; i
++)
4180 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vs
, i
));
4185 for (i
= 0; i
< 4; i
++)
4186 aarch64_set_vec_u16 (cpu
, vd
, i
+ 4,
4187 aarch64_get_vec_u32 (cpu
, vs
, i
) >> 16);
4189 for (i
= 0; i
< 4; i
++)
4190 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vs
, i
));
4195 for (i
= 0; i
< 2; i
++)
4196 aarch64_set_vec_u32 (cpu
, vd
, i
+ 4,
4197 aarch64_get_vec_u64 (cpu
, vs
, i
) >> 32);
4199 for (i
= 0; i
< 2; i
++)
4200 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u64 (cpu
, vs
, i
));
4206 do_vec_maxv (sim_cpu
*cpu
)
4209 instr[30] = half(0)/full(1)
4210 instr[29] = signed (0)/unsigned(1)
4211 instr[28,24] = 0 1110
4212 instr[23,22] = size: byte(00), half(01), word (10)
4214 instr[20,17] = 1 000
4215 instr[16] = max(0)/min(1)
4216 instr[15,10] = 1010 10
4217 instr[9,5] = V source
4218 instr[4.0] = R dest. */
4220 unsigned vs
= INSTR (9, 5);
4221 unsigned rd
= INSTR (4, 0);
4222 unsigned full
= INSTR (30, 30);
4225 NYI_assert (28, 24, 0x0E);
4226 NYI_assert (21, 21, 1);
4227 NYI_assert (20, 17, 8);
4228 NYI_assert (15, 10, 0x2A);
4230 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4231 switch ((INSTR (29, 29) << 1) | INSTR (16, 16))
4233 case 0: /* SMAXV. */
4236 switch (INSTR (23, 22))
4239 smax
= aarch64_get_vec_s8 (cpu
, vs
, 0);
4240 for (i
= 1; i
< (full
? 16 : 8); i
++)
4241 smax
= max (smax
, aarch64_get_vec_s8 (cpu
, vs
, i
));
4244 smax
= aarch64_get_vec_s16 (cpu
, vs
, 0);
4245 for (i
= 1; i
< (full
? 8 : 4); i
++)
4246 smax
= max (smax
, aarch64_get_vec_s16 (cpu
, vs
, i
));
4249 smax
= aarch64_get_vec_s32 (cpu
, vs
, 0);
4250 for (i
= 1; i
< (full
? 4 : 2); i
++)
4251 smax
= max (smax
, aarch64_get_vec_s32 (cpu
, vs
, i
));
4256 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, smax
);
4260 case 1: /* SMINV. */
4263 switch (INSTR (23, 22))
4266 smin
= aarch64_get_vec_s8 (cpu
, vs
, 0);
4267 for (i
= 1; i
< (full
? 16 : 8); i
++)
4268 smin
= min (smin
, aarch64_get_vec_s8 (cpu
, vs
, i
));
4271 smin
= aarch64_get_vec_s16 (cpu
, vs
, 0);
4272 for (i
= 1; i
< (full
? 8 : 4); i
++)
4273 smin
= min (smin
, aarch64_get_vec_s16 (cpu
, vs
, i
));
4276 smin
= aarch64_get_vec_s32 (cpu
, vs
, 0);
4277 for (i
= 1; i
< (full
? 4 : 2); i
++)
4278 smin
= min (smin
, aarch64_get_vec_s32 (cpu
, vs
, i
));
4284 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, smin
);
4288 case 2: /* UMAXV. */
4291 switch (INSTR (23, 22))
4294 umax
= aarch64_get_vec_u8 (cpu
, vs
, 0);
4295 for (i
= 1; i
< (full
? 16 : 8); i
++)
4296 umax
= max (umax
, aarch64_get_vec_u8 (cpu
, vs
, i
));
4299 umax
= aarch64_get_vec_u16 (cpu
, vs
, 0);
4300 for (i
= 1; i
< (full
? 8 : 4); i
++)
4301 umax
= max (umax
, aarch64_get_vec_u16 (cpu
, vs
, i
));
4304 umax
= aarch64_get_vec_u32 (cpu
, vs
, 0);
4305 for (i
= 1; i
< (full
? 4 : 2); i
++)
4306 umax
= max (umax
, aarch64_get_vec_u32 (cpu
, vs
, i
));
4312 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, umax
);
4316 case 3: /* UMINV. */
4319 switch (INSTR (23, 22))
4322 umin
= aarch64_get_vec_u8 (cpu
, vs
, 0);
4323 for (i
= 1; i
< (full
? 16 : 8); i
++)
4324 umin
= min (umin
, aarch64_get_vec_u8 (cpu
, vs
, i
));
4327 umin
= aarch64_get_vec_u16 (cpu
, vs
, 0);
4328 for (i
= 1; i
< (full
? 8 : 4); i
++)
4329 umin
= min (umin
, aarch64_get_vec_u16 (cpu
, vs
, i
));
4332 umin
= aarch64_get_vec_u32 (cpu
, vs
, 0);
4333 for (i
= 1; i
< (full
? 4 : 2); i
++)
4334 umin
= min (umin
, aarch64_get_vec_u32 (cpu
, vs
, i
));
4340 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, umin
);
4347 do_vec_fminmaxV (sim_cpu
*cpu
)
4349 /* instr[31,24] = 0110 1110
4350 instr[23] = max(0)/min(1)
4351 instr[22,14] = 011 0000 11
4352 instr[13,12] = nm(00)/normal(11)
4354 instr[9,5] = V source
4355 instr[4.0] = R dest. */
4357 unsigned vs
= INSTR (9, 5);
4358 unsigned rd
= INSTR (4, 0);
4360 float res
= aarch64_get_vec_float (cpu
, vs
, 0);
4362 NYI_assert (31, 24, 0x6E);
4363 NYI_assert (22, 14, 0x0C3);
4364 NYI_assert (11, 10, 2);
4366 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4369 switch (INSTR (13, 12))
4371 case 0: /* FMNINNMV. */
4372 for (i
= 1; i
< 4; i
++)
4373 res
= fminnm (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4376 case 3: /* FMINV. */
4377 for (i
= 1; i
< 4; i
++)
4378 res
= min (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4387 switch (INSTR (13, 12))
4389 case 0: /* FMNAXNMV. */
4390 for (i
= 1; i
< 4; i
++)
4391 res
= fmaxnm (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4394 case 3: /* FMAXV. */
4395 for (i
= 1; i
< 4; i
++)
4396 res
= max (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4404 aarch64_set_FP_float (cpu
, rd
, res
);
4408 do_vec_Fminmax (sim_cpu
*cpu
)
4411 instr[30] = half(0)/full(1)
4412 instr[29,24] = 00 1110
4413 instr[23] = max(0)/min(1)
4414 instr[22] = float(0)/double(1)
4418 instr[13,12] = nm(00)/normal(11)
4423 unsigned vm
= INSTR (20, 16);
4424 unsigned vn
= INSTR (9, 5);
4425 unsigned vd
= INSTR (4, 0);
4426 unsigned full
= INSTR (30, 30);
4427 unsigned min
= INSTR (23, 23);
4430 NYI_assert (29, 24, 0x0E);
4431 NYI_assert (21, 21, 1);
4432 NYI_assert (15, 14, 3);
4433 NYI_assert (11, 10, 1);
4435 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4438 double (* func
)(double, double);
4443 if (INSTR (13, 12) == 0)
4444 func
= min
? dminnm
: dmaxnm
;
4445 else if (INSTR (13, 12) == 3)
4446 func
= min
? fmin
: fmax
;
4450 for (i
= 0; i
< 2; i
++)
4451 aarch64_set_vec_double (cpu
, vd
, i
,
4452 func (aarch64_get_vec_double (cpu
, vn
, i
),
4453 aarch64_get_vec_double (cpu
, vm
, i
)));
4457 float (* func
)(float, float);
4459 if (INSTR (13, 12) == 0)
4460 func
= min
? fminnm
: fmaxnm
;
4461 else if (INSTR (13, 12) == 3)
4462 func
= min
? fminf
: fmaxf
;
4466 for (i
= 0; i
< (full
? 4 : 2); i
++)
4467 aarch64_set_vec_float (cpu
, vd
, i
,
4468 func (aarch64_get_vec_float (cpu
, vn
, i
),
4469 aarch64_get_vec_float (cpu
, vm
, i
)));
4474 do_vec_SCVTF (sim_cpu
*cpu
)
4478 instr[29,23] = 00 1110 0
4479 instr[22] = float(0)/double(1)
4480 instr[21,10] = 10 0001 1101 10
4484 unsigned vn
= INSTR (9, 5);
4485 unsigned vd
= INSTR (4, 0);
4486 unsigned full
= INSTR (30, 30);
4487 unsigned size
= INSTR (22, 22);
4490 NYI_assert (29, 23, 0x1C);
4491 NYI_assert (21, 10, 0x876);
4493 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4499 for (i
= 0; i
< 2; i
++)
4501 double val
= (double) aarch64_get_vec_u64 (cpu
, vn
, i
);
4502 aarch64_set_vec_double (cpu
, vd
, i
, val
);
4507 for (i
= 0; i
< (full
? 4 : 2); i
++)
4509 float val
= (float) aarch64_get_vec_u32 (cpu
, vn
, i
);
4510 aarch64_set_vec_float (cpu
, vd
, i
, val
);
4515 #define VEC_CMP(SOURCE, CMP) \
4521 for (i = 0; i < (full ? 16 : 8); i++) \
4522 aarch64_set_vec_u8 (cpu, vd, i, \
4523 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4525 aarch64_get_vec_##SOURCE##8 (cpu, vm, i) \
4529 for (i = 0; i < (full ? 8 : 4); i++) \
4530 aarch64_set_vec_u16 (cpu, vd, i, \
4531 aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4533 aarch64_get_vec_##SOURCE##16 (cpu, vm, i) \
4537 for (i = 0; i < (full ? 4 : 2); i++) \
4538 aarch64_set_vec_u32 (cpu, vd, i, \
4539 aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4541 aarch64_get_vec_##SOURCE##32 (cpu, vm, i) \
4547 for (i = 0; i < 2; i++) \
4548 aarch64_set_vec_u64 (cpu, vd, i, \
4549 aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4551 aarch64_get_vec_##SOURCE##64 (cpu, vm, i) \
4558 #define VEC_CMP0(SOURCE, CMP) \
4564 for (i = 0; i < (full ? 16 : 8); i++) \
4565 aarch64_set_vec_u8 (cpu, vd, i, \
4566 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4570 for (i = 0; i < (full ? 8 : 4); i++) \
4571 aarch64_set_vec_u16 (cpu, vd, i, \
4572 aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4576 for (i = 0; i < (full ? 4 : 2); i++) \
4577 aarch64_set_vec_u32 (cpu, vd, i, \
4578 aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4584 for (i = 0; i < 2; i++) \
4585 aarch64_set_vec_u64 (cpu, vd, i, \
4586 aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4587 CMP 0 ? -1ULL : 0); \
4593 #define VEC_FCMP0(CMP) \
4598 if (INSTR (22, 22)) \
4602 for (i = 0; i < 2; i++) \
4603 aarch64_set_vec_u64 (cpu, vd, i, \
4604 aarch64_get_vec_double (cpu, vn, i) \
4605 CMP 0.0 ? -1 : 0); \
4609 for (i = 0; i < (full ? 4 : 2); i++) \
4610 aarch64_set_vec_u32 (cpu, vd, i, \
4611 aarch64_get_vec_float (cpu, vn, i) \
4612 CMP 0.0 ? -1 : 0); \
4618 #define VEC_FCMP(CMP) \
4621 if (INSTR (22, 22)) \
4625 for (i = 0; i < 2; i++) \
4626 aarch64_set_vec_u64 (cpu, vd, i, \
4627 aarch64_get_vec_double (cpu, vn, i) \
4629 aarch64_get_vec_double (cpu, vm, i) \
4634 for (i = 0; i < (full ? 4 : 2); i++) \
4635 aarch64_set_vec_u32 (cpu, vd, i, \
4636 aarch64_get_vec_float (cpu, vn, i) \
4638 aarch64_get_vec_float (cpu, vm, i) \
4646 do_vec_compare (sim_cpu
*cpu
)
4649 instr[30] = half(0)/full(1)
4650 instr[29] = part-of-comparison-type
4651 instr[28,24] = 0 1110
4652 instr[23,22] = size of integer compares: byte(00), half(01), word (10), long (11)
4653 type of float compares: single (-0) / double (-1)
4655 instr[20,16] = Vm or 00000 (compare vs 0)
4656 instr[15,10] = part-of-comparison-type
4660 int full
= INSTR (30, 30);
4661 int size
= INSTR (23, 22);
4662 unsigned vm
= INSTR (20, 16);
4663 unsigned vn
= INSTR (9, 5);
4664 unsigned vd
= INSTR (4, 0);
4667 NYI_assert (28, 24, 0x0E);
4668 NYI_assert (21, 21, 1);
4670 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4673 || ((INSTR (11, 11) == 0
4674 && INSTR (10, 10) == 0)))
4676 /* A compare vs 0. */
4679 if (INSTR (15, 10) == 0x2A)
4681 else if (INSTR (15, 10) == 0x32
4682 || INSTR (15, 10) == 0x3E)
4683 do_vec_fminmaxV (cpu
);
4684 else if (INSTR (29, 23) == 0x1C
4685 && INSTR (21, 10) == 0x876)
4695 /* A floating point compare. */
4696 unsigned decode
= (INSTR (29, 29) << 5) | (INSTR (23, 23) << 4)
4699 NYI_assert (15, 15, 1);
4703 case /* 0b010010: GT#0 */ 0x12: VEC_FCMP0 (>);
4704 case /* 0b110010: GE#0 */ 0x32: VEC_FCMP0 (>=);
4705 case /* 0b010110: EQ#0 */ 0x16: VEC_FCMP0 (==);
4706 case /* 0b110110: LE#0 */ 0x36: VEC_FCMP0 (<=);
4707 case /* 0b011010: LT#0 */ 0x1A: VEC_FCMP0 (<);
4708 case /* 0b111001: GT */ 0x39: VEC_FCMP (>);
4709 case /* 0b101001: GE */ 0x29: VEC_FCMP (>=);
4710 case /* 0b001001: EQ */ 0x09: VEC_FCMP (==);
4718 unsigned decode
= (INSTR (29, 29) << 6) | INSTR (15, 10);
4722 case 0x0D: /* 0001101 GT */ VEC_CMP (s
, > );
4723 case 0x0F: /* 0001111 GE */ VEC_CMP (s
, >= );
4724 case 0x22: /* 0100010 GT #0 */ VEC_CMP0 (s
, > );
4725 case 0x26: /* 0100110 EQ #0 */ VEC_CMP0 (s
, == );
4726 case 0x2A: /* 0101010 LT #0 */ VEC_CMP0 (s
, < );
4727 case 0x4D: /* 1001101 HI */ VEC_CMP (u
, > );
4728 case 0x4F: /* 1001111 HS */ VEC_CMP (u
, >= );
4729 case 0x62: /* 1100010 GE #0 */ VEC_CMP0 (s
, >= );
4730 case 0x63: /* 1100011 EQ */ VEC_CMP (u
, == );
4731 case 0x66: /* 1100110 LE #0 */ VEC_CMP0 (s
, <= );
4741 do_vec_SSHL (sim_cpu
*cpu
)
4744 instr[30] = first part (0)/ second part (1)
4745 instr[29,24] = 00 1110
4746 instr[23,22] = size: byte(00), half(01), word (10), long (11)
4749 instr[15,10] = 0100 01
4753 unsigned full
= INSTR (30, 30);
4754 unsigned vm
= INSTR (20, 16);
4755 unsigned vn
= INSTR (9, 5);
4756 unsigned vd
= INSTR (4, 0);
4760 NYI_assert (29, 24, 0x0E);
4761 NYI_assert (21, 21, 1);
4762 NYI_assert (15, 10, 0x11);
4764 /* FIXME: What is a signed shift left in this context ?. */
4766 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4767 switch (INSTR (23, 22))
4770 for (i
= 0; i
< (full
? 16 : 8); i
++)
4772 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
);
4774 aarch64_set_vec_s8 (cpu
, vd
, i
, aarch64_get_vec_s8 (cpu
, vn
, i
)
4777 aarch64_set_vec_s8 (cpu
, vd
, i
, aarch64_get_vec_s8 (cpu
, vn
, i
)
4783 for (i
= 0; i
< (full
? 8 : 4); i
++)
4785 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 2);
4787 aarch64_set_vec_s16 (cpu
, vd
, i
, aarch64_get_vec_s16 (cpu
, vn
, i
)
4790 aarch64_set_vec_s16 (cpu
, vd
, i
, aarch64_get_vec_s16 (cpu
, vn
, i
)
4796 for (i
= 0; i
< (full
? 4 : 2); i
++)
4798 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 4);
4800 aarch64_set_vec_s32 (cpu
, vd
, i
, aarch64_get_vec_s32 (cpu
, vn
, i
)
4803 aarch64_set_vec_s32 (cpu
, vd
, i
, aarch64_get_vec_s32 (cpu
, vn
, i
)
4811 for (i
= 0; i
< 2; i
++)
4813 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 8);
4815 aarch64_set_vec_s64 (cpu
, vd
, i
, aarch64_get_vec_s64 (cpu
, vn
, i
)
4818 aarch64_set_vec_s64 (cpu
, vd
, i
, aarch64_get_vec_s64 (cpu
, vn
, i
)
4826 do_vec_USHL (sim_cpu
*cpu
)
4829 instr[30] = first part (0)/ second part (1)
4830 instr[29,24] = 10 1110
4831 instr[23,22] = size: byte(00), half(01), word (10), long (11)
4834 instr[15,10] = 0100 01
4838 unsigned full
= INSTR (30, 30);
4839 unsigned vm
= INSTR (20, 16);
4840 unsigned vn
= INSTR (9, 5);
4841 unsigned vd
= INSTR (4, 0);
4845 NYI_assert (29, 24, 0x2E);
4846 NYI_assert (15, 10, 0x11);
4848 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4849 switch (INSTR (23, 22))
4852 for (i
= 0; i
< (full
? 16 : 8); i
++)
4854 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
);
4856 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vn
, i
)
4859 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vn
, i
)
4865 for (i
= 0; i
< (full
? 8 : 4); i
++)
4867 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 2);
4869 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vn
, i
)
4872 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vn
, i
)
4878 for (i
= 0; i
< (full
? 4 : 2); i
++)
4880 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 4);
4882 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vn
, i
)
4885 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vn
, i
)
4893 for (i
= 0; i
< 2; i
++)
4895 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 8);
4897 aarch64_set_vec_u64 (cpu
, vd
, i
, aarch64_get_vec_u64 (cpu
, vn
, i
)
4900 aarch64_set_vec_u64 (cpu
, vd
, i
, aarch64_get_vec_u64 (cpu
, vn
, i
)
4908 do_vec_FMLA (sim_cpu
*cpu
)
4911 instr[30] = full/half selector
4912 instr[29,23] = 0011100
4913 instr[22] = size: 0=>float, 1=>double
4916 instr[15,10] = 1100 11
4920 unsigned vm
= INSTR (20, 16);
4921 unsigned vn
= INSTR (9, 5);
4922 unsigned vd
= INSTR (4, 0);
4924 int full
= INSTR (30, 30);
4926 NYI_assert (29, 23, 0x1C);
4927 NYI_assert (21, 21, 1);
4928 NYI_assert (15, 10, 0x33);
4930 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4935 for (i
= 0; i
< 2; i
++)
4936 aarch64_set_vec_double (cpu
, vd
, i
,
4937 aarch64_get_vec_double (cpu
, vn
, i
) *
4938 aarch64_get_vec_double (cpu
, vm
, i
) +
4939 aarch64_get_vec_double (cpu
, vd
, i
));
4943 for (i
= 0; i
< (full
? 4 : 2); i
++)
4944 aarch64_set_vec_float (cpu
, vd
, i
,
4945 aarch64_get_vec_float (cpu
, vn
, i
) *
4946 aarch64_get_vec_float (cpu
, vm
, i
) +
4947 aarch64_get_vec_float (cpu
, vd
, i
));
4952 do_vec_max (sim_cpu
*cpu
)
4955 instr[30] = full/half selector
4956 instr[29] = SMAX (0) / UMAX (1)
4957 instr[28,24] = 0 1110
4958 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
4961 instr[15,10] = 0110 01
4965 unsigned vm
= INSTR (20, 16);
4966 unsigned vn
= INSTR (9, 5);
4967 unsigned vd
= INSTR (4, 0);
4969 int full
= INSTR (30, 30);
4971 NYI_assert (28, 24, 0x0E);
4972 NYI_assert (21, 21, 1);
4973 NYI_assert (15, 10, 0x19);
4975 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4978 switch (INSTR (23, 22))
4981 for (i
= 0; i
< (full
? 16 : 8); i
++)
4982 aarch64_set_vec_u8 (cpu
, vd
, i
,
4983 aarch64_get_vec_u8 (cpu
, vn
, i
)
4984 > aarch64_get_vec_u8 (cpu
, vm
, i
)
4985 ? aarch64_get_vec_u8 (cpu
, vn
, i
)
4986 : aarch64_get_vec_u8 (cpu
, vm
, i
));
4990 for (i
= 0; i
< (full
? 8 : 4); i
++)
4991 aarch64_set_vec_u16 (cpu
, vd
, i
,
4992 aarch64_get_vec_u16 (cpu
, vn
, i
)
4993 > aarch64_get_vec_u16 (cpu
, vm
, i
)
4994 ? aarch64_get_vec_u16 (cpu
, vn
, i
)
4995 : aarch64_get_vec_u16 (cpu
, vm
, i
));
4999 for (i
= 0; i
< (full
? 4 : 2); i
++)
5000 aarch64_set_vec_u32 (cpu
, vd
, i
,
5001 aarch64_get_vec_u32 (cpu
, vn
, i
)
5002 > aarch64_get_vec_u32 (cpu
, vm
, i
)
5003 ? aarch64_get_vec_u32 (cpu
, vn
, i
)
5004 : aarch64_get_vec_u32 (cpu
, vm
, i
));
5013 switch (INSTR (23, 22))
5016 for (i
= 0; i
< (full
? 16 : 8); i
++)
5017 aarch64_set_vec_s8 (cpu
, vd
, i
,
5018 aarch64_get_vec_s8 (cpu
, vn
, i
)
5019 > aarch64_get_vec_s8 (cpu
, vm
, i
)
5020 ? aarch64_get_vec_s8 (cpu
, vn
, i
)
5021 : aarch64_get_vec_s8 (cpu
, vm
, i
));
5025 for (i
= 0; i
< (full
? 8 : 4); i
++)
5026 aarch64_set_vec_s16 (cpu
, vd
, i
,
5027 aarch64_get_vec_s16 (cpu
, vn
, i
)
5028 > aarch64_get_vec_s16 (cpu
, vm
, i
)
5029 ? aarch64_get_vec_s16 (cpu
, vn
, i
)
5030 : aarch64_get_vec_s16 (cpu
, vm
, i
));
5034 for (i
= 0; i
< (full
? 4 : 2); i
++)
5035 aarch64_set_vec_s32 (cpu
, vd
, i
,
5036 aarch64_get_vec_s32 (cpu
, vn
, i
)
5037 > aarch64_get_vec_s32 (cpu
, vm
, i
)
5038 ? aarch64_get_vec_s32 (cpu
, vn
, i
)
5039 : aarch64_get_vec_s32 (cpu
, vm
, i
));
5049 do_vec_min (sim_cpu
*cpu
)
5052 instr[30] = full/half selector
5053 instr[29] = SMIN (0) / UMIN (1)
5054 instr[28,24] = 0 1110
5055 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
5058 instr[15,10] = 0110 11
5062 unsigned vm
= INSTR (20, 16);
5063 unsigned vn
= INSTR (9, 5);
5064 unsigned vd
= INSTR (4, 0);
5066 int full
= INSTR (30, 30);
5068 NYI_assert (28, 24, 0x0E);
5069 NYI_assert (21, 21, 1);
5070 NYI_assert (15, 10, 0x1B);
5072 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5075 switch (INSTR (23, 22))
5078 for (i
= 0; i
< (full
? 16 : 8); i
++)
5079 aarch64_set_vec_u8 (cpu
, vd
, i
,
5080 aarch64_get_vec_u8 (cpu
, vn
, i
)
5081 < aarch64_get_vec_u8 (cpu
, vm
, i
)
5082 ? aarch64_get_vec_u8 (cpu
, vn
, i
)
5083 : aarch64_get_vec_u8 (cpu
, vm
, i
));
5087 for (i
= 0; i
< (full
? 8 : 4); i
++)
5088 aarch64_set_vec_u16 (cpu
, vd
, i
,
5089 aarch64_get_vec_u16 (cpu
, vn
, i
)
5090 < aarch64_get_vec_u16 (cpu
, vm
, i
)
5091 ? aarch64_get_vec_u16 (cpu
, vn
, i
)
5092 : aarch64_get_vec_u16 (cpu
, vm
, i
));
5096 for (i
= 0; i
< (full
? 4 : 2); i
++)
5097 aarch64_set_vec_u32 (cpu
, vd
, i
,
5098 aarch64_get_vec_u32 (cpu
, vn
, i
)
5099 < aarch64_get_vec_u32 (cpu
, vm
, i
)
5100 ? aarch64_get_vec_u32 (cpu
, vn
, i
)
5101 : aarch64_get_vec_u32 (cpu
, vm
, i
));
5110 switch (INSTR (23, 22))
5113 for (i
= 0; i
< (full
? 16 : 8); i
++)
5114 aarch64_set_vec_s8 (cpu
, vd
, i
,
5115 aarch64_get_vec_s8 (cpu
, vn
, i
)
5116 < aarch64_get_vec_s8 (cpu
, vm
, i
)
5117 ? aarch64_get_vec_s8 (cpu
, vn
, i
)
5118 : aarch64_get_vec_s8 (cpu
, vm
, i
));
5122 for (i
= 0; i
< (full
? 8 : 4); i
++)
5123 aarch64_set_vec_s16 (cpu
, vd
, i
,
5124 aarch64_get_vec_s16 (cpu
, vn
, i
)
5125 < aarch64_get_vec_s16 (cpu
, vm
, i
)
5126 ? aarch64_get_vec_s16 (cpu
, vn
, i
)
5127 : aarch64_get_vec_s16 (cpu
, vm
, i
));
5131 for (i
= 0; i
< (full
? 4 : 2); i
++)
5132 aarch64_set_vec_s32 (cpu
, vd
, i
,
5133 aarch64_get_vec_s32 (cpu
, vn
, i
)
5134 < aarch64_get_vec_s32 (cpu
, vm
, i
)
5135 ? aarch64_get_vec_s32 (cpu
, vn
, i
)
5136 : aarch64_get_vec_s32 (cpu
, vm
, i
));
5146 do_vec_sub_long (sim_cpu
*cpu
)
5149 instr[30] = lower (0) / upper (1)
5150 instr[29] = signed (0) / unsigned (1)
5151 instr[28,24] = 0 1110
5152 instr[23,22] = size: bytes (00), half (01), word (10)
5155 instr[15,10] = 0010 00
5157 instr[4,0] = V dest. */
5159 unsigned size
= INSTR (23, 22);
5160 unsigned vm
= INSTR (20, 16);
5161 unsigned vn
= INSTR (9, 5);
5162 unsigned vd
= INSTR (4, 0);
5166 NYI_assert (28, 24, 0x0E);
5167 NYI_assert (21, 21, 1);
5168 NYI_assert (15, 10, 0x08);
5173 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5174 switch (INSTR (30, 29))
5176 case 2: /* SSUBL2. */
5178 case 0: /* SSUBL. */
5183 for (i
= 0; i
< 8; i
++)
5184 aarch64_set_vec_s16 (cpu
, vd
, i
,
5185 aarch64_get_vec_s8 (cpu
, vn
, i
+ bias
)
5186 - aarch64_get_vec_s8 (cpu
, vm
, i
+ bias
));
5191 for (i
= 0; i
< 4; i
++)
5192 aarch64_set_vec_s32 (cpu
, vd
, i
,
5193 aarch64_get_vec_s16 (cpu
, vn
, i
+ bias
)
5194 - aarch64_get_vec_s16 (cpu
, vm
, i
+ bias
));
5198 for (i
= 0; i
< 2; i
++)
5199 aarch64_set_vec_s64 (cpu
, vd
, i
,
5200 aarch64_get_vec_s32 (cpu
, vn
, i
+ bias
)
5201 - aarch64_get_vec_s32 (cpu
, vm
, i
+ bias
));
5209 case 3: /* USUBL2. */
5211 case 1: /* USUBL. */
5216 for (i
= 0; i
< 8; i
++)
5217 aarch64_set_vec_u16 (cpu
, vd
, i
,
5218 aarch64_get_vec_u8 (cpu
, vn
, i
+ bias
)
5219 - aarch64_get_vec_u8 (cpu
, vm
, i
+ bias
));
5224 for (i
= 0; i
< 4; i
++)
5225 aarch64_set_vec_u32 (cpu
, vd
, i
,
5226 aarch64_get_vec_u16 (cpu
, vn
, i
+ bias
)
5227 - aarch64_get_vec_u16 (cpu
, vm
, i
+ bias
));
5231 for (i
= 0; i
< 2; i
++)
5232 aarch64_set_vec_u64 (cpu
, vd
, i
,
5233 aarch64_get_vec_u32 (cpu
, vn
, i
+ bias
)
5234 - aarch64_get_vec_u32 (cpu
, vm
, i
+ bias
));
5245 do_vec_ADDP (sim_cpu
*cpu
)
5248 instr[30] = half(0)/full(1)
5249 instr[29,24] = 00 1110
5250 instr[23,22] = size: bytes (00), half (01), word (10), long (11)
5253 instr[15,10] = 1011 11
5255 instr[4,0] = V dest. */
5259 unsigned full
= INSTR (30, 30);
5260 unsigned size
= INSTR (23, 22);
5261 unsigned vm
= INSTR (20, 16);
5262 unsigned vn
= INSTR (9, 5);
5263 unsigned vd
= INSTR (4, 0);
5266 NYI_assert (29, 24, 0x0E);
5267 NYI_assert (21, 21, 1);
5268 NYI_assert (15, 10, 0x2F);
5270 /* Make copies of the source registers in case vd == vn/vm. */
5271 copy_vn
= cpu
->fr
[vn
];
5272 copy_vm
= cpu
->fr
[vm
];
5274 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5278 range
= full
? 8 : 4;
5279 for (i
= 0; i
< range
; i
++)
5281 aarch64_set_vec_u8 (cpu
, vd
, i
,
5282 copy_vn
.b
[i
* 2] + copy_vn
.b
[i
* 2 + 1]);
5283 aarch64_set_vec_u8 (cpu
, vd
, i
+ range
,
5284 copy_vm
.b
[i
* 2] + copy_vm
.b
[i
* 2 + 1]);
5289 range
= full
? 4 : 2;
5290 for (i
= 0; i
< range
; i
++)
5292 aarch64_set_vec_u16 (cpu
, vd
, i
,
5293 copy_vn
.h
[i
* 2] + copy_vn
.h
[i
* 2 + 1]);
5294 aarch64_set_vec_u16 (cpu
, vd
, i
+ range
,
5295 copy_vm
.h
[i
* 2] + copy_vm
.h
[i
* 2 + 1]);
5300 range
= full
? 2 : 1;
5301 for (i
= 0; i
< range
; i
++)
5303 aarch64_set_vec_u32 (cpu
, vd
, i
,
5304 copy_vn
.w
[i
* 2] + copy_vn
.w
[i
* 2 + 1]);
5305 aarch64_set_vec_u32 (cpu
, vd
, i
+ range
,
5306 copy_vm
.w
[i
* 2] + copy_vm
.w
[i
* 2 + 1]);
5313 aarch64_set_vec_u64 (cpu
, vd
, 0, copy_vn
.v
[0] + copy_vn
.v
[1]);
5314 aarch64_set_vec_u64 (cpu
, vd
, 1, copy_vm
.v
[0] + copy_vm
.v
[1]);
5320 do_vec_UMOV (sim_cpu
*cpu
)
5323 instr[30] = 32-bit(0)/64-bit(1)
5324 instr[29,21] = 00 1110 000
5325 insrt[20,16] = size & index
5326 instr[15,10] = 0011 11
5327 instr[9,5] = V source
5328 instr[4,0] = R dest. */
5330 unsigned vs
= INSTR (9, 5);
5331 unsigned rd
= INSTR (4, 0);
5334 NYI_assert (29, 21, 0x070);
5335 NYI_assert (15, 10, 0x0F);
5337 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5340 /* Byte transfer. */
5341 index
= INSTR (20, 17);
5342 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
5343 aarch64_get_vec_u8 (cpu
, vs
, index
));
5345 else if (INSTR (17, 17))
5347 index
= INSTR (20, 18);
5348 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
5349 aarch64_get_vec_u16 (cpu
, vs
, index
));
5351 else if (INSTR (18, 18))
5353 index
= INSTR (20, 19);
5354 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
5355 aarch64_get_vec_u32 (cpu
, vs
, index
));
5359 if (INSTR (30, 30) != 1)
5362 index
= INSTR (20, 20);
5363 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
5364 aarch64_get_vec_u64 (cpu
, vs
, index
));
5369 do_vec_FABS (sim_cpu
*cpu
)
5372 instr[30] = half(0)/full(1)
5373 instr[29,23] = 00 1110 1
5374 instr[22] = float(0)/double(1)
5375 instr[21,16] = 10 0000
5376 instr[15,10] = 1111 10
5380 unsigned vn
= INSTR (9, 5);
5381 unsigned vd
= INSTR (4, 0);
5382 unsigned full
= INSTR (30, 30);
5385 NYI_assert (29, 23, 0x1D);
5386 NYI_assert (21, 10, 0x83E);
5388 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5394 for (i
= 0; i
< 2; i
++)
5395 aarch64_set_vec_double (cpu
, vd
, i
,
5396 fabs (aarch64_get_vec_double (cpu
, vn
, i
)));
5400 for (i
= 0; i
< (full
? 4 : 2); i
++)
5401 aarch64_set_vec_float (cpu
, vd
, i
,
5402 fabsf (aarch64_get_vec_float (cpu
, vn
, i
)));
5407 do_vec_FCVTZS (sim_cpu
*cpu
)
5410 instr[30] = half (0) / all (1)
5411 instr[29,23] = 00 1110 1
5412 instr[22] = single (0) / double (1)
5413 instr[21,10] = 10 0001 1011 10
5417 unsigned rn
= INSTR (9, 5);
5418 unsigned rd
= INSTR (4, 0);
5419 unsigned full
= INSTR (30, 30);
5422 NYI_assert (31, 31, 0);
5423 NYI_assert (29, 23, 0x1D);
5424 NYI_assert (21, 10, 0x86E);
5426 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5432 for (i
= 0; i
< 2; i
++)
5433 aarch64_set_vec_s64 (cpu
, rd
, i
,
5434 (int64_t) aarch64_get_vec_double (cpu
, rn
, i
));
5437 for (i
= 0; i
< (full
? 4 : 2); i
++)
5438 aarch64_set_vec_s32 (cpu
, rd
, i
,
5439 (int32_t) aarch64_get_vec_float (cpu
, rn
, i
));
5443 do_vec_REV64 (sim_cpu
*cpu
)
5446 instr[30] = full/half
5447 instr[29,24] = 00 1110
5449 instr[21,10] = 10 0000 0000 10
5453 unsigned rn
= INSTR (9, 5);
5454 unsigned rd
= INSTR (4, 0);
5455 unsigned size
= INSTR (23, 22);
5456 unsigned full
= INSTR (30, 30);
5460 NYI_assert (29, 24, 0x0E);
5461 NYI_assert (21, 10, 0x802);
5463 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5467 for (i
= 0; i
< (full
? 16 : 8); i
++)
5468 val
.b
[i
^ 0x7] = aarch64_get_vec_u8 (cpu
, rn
, i
);
5472 for (i
= 0; i
< (full
? 8 : 4); i
++)
5473 val
.h
[i
^ 0x3] = aarch64_get_vec_u16 (cpu
, rn
, i
);
5477 for (i
= 0; i
< (full
? 4 : 2); i
++)
5478 val
.w
[i
^ 0x1] = aarch64_get_vec_u32 (cpu
, rn
, i
);
5485 aarch64_set_vec_u64 (cpu
, rd
, 0, val
.v
[0]);
5487 aarch64_set_vec_u64 (cpu
, rd
, 1, val
.v
[1]);
5491 do_vec_REV16 (sim_cpu
*cpu
)
5494 instr[30] = full/half
5495 instr[29,24] = 00 1110
5497 instr[21,10] = 10 0000 0001 10
5501 unsigned rn
= INSTR (9, 5);
5502 unsigned rd
= INSTR (4, 0);
5503 unsigned size
= INSTR (23, 22);
5504 unsigned full
= INSTR (30, 30);
5508 NYI_assert (29, 24, 0x0E);
5509 NYI_assert (21, 10, 0x806);
5511 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5515 for (i
= 0; i
< (full
? 16 : 8); i
++)
5516 val
.b
[i
^ 0x1] = aarch64_get_vec_u8 (cpu
, rn
, i
);
5523 aarch64_set_vec_u64 (cpu
, rd
, 0, val
.v
[0]);
5525 aarch64_set_vec_u64 (cpu
, rd
, 1, val
.v
[1]);
5529 do_vec_op1 (sim_cpu
*cpu
)
5532 instr[30] = half/full
5533 instr[29,24] = 00 1110
5536 instr[15,10] = sub-opcode
5539 NYI_assert (29, 24, 0x0E);
5541 if (INSTR (21, 21) == 0)
5543 if (INSTR (23, 22) == 0)
5545 if (INSTR (30, 30) == 1
5546 && INSTR (17, 14) == 0
5547 && INSTR (12, 10) == 7)
5548 return do_vec_ins_2 (cpu
);
5550 switch (INSTR (15, 10))
5552 case 0x01: do_vec_DUP_vector_into_vector (cpu
); return;
5553 case 0x03: do_vec_DUP_scalar_into_vector (cpu
); return;
5554 case 0x07: do_vec_INS (cpu
); return;
5555 case 0x0A: do_vec_TRN (cpu
); return;
5558 if (INSTR (17, 16) == 0)
5560 do_vec_MOV_into_scalar (cpu
);
5569 do_vec_TBL (cpu
); return;
5573 do_vec_UZP (cpu
); return;
5577 do_vec_ZIP (cpu
); return;
5584 switch (INSTR (13, 10))
5586 case 0x6: do_vec_UZP (cpu
); return;
5587 case 0xE: do_vec_ZIP (cpu
); return;
5588 case 0xA: do_vec_TRN (cpu
); return;
5589 case 0xF: do_vec_UMOV (cpu
); return;
5594 switch (INSTR (15, 10))
5596 case 0x02: do_vec_REV64 (cpu
); return;
5597 case 0x06: do_vec_REV16 (cpu
); return;
5600 switch (INSTR (23, 21))
5602 case 1: do_vec_AND (cpu
); return;
5603 case 3: do_vec_BIC (cpu
); return;
5604 case 5: do_vec_ORR (cpu
); return;
5605 case 7: do_vec_ORN (cpu
); return;
5609 case 0x08: do_vec_sub_long (cpu
); return;
5610 case 0x0a: do_vec_XTN (cpu
); return;
5611 case 0x11: do_vec_SSHL (cpu
); return;
5612 case 0x19: do_vec_max (cpu
); return;
5613 case 0x1B: do_vec_min (cpu
); return;
5614 case 0x21: do_vec_add (cpu
); return;
5615 case 0x25: do_vec_MLA (cpu
); return;
5616 case 0x27: do_vec_mul (cpu
); return;
5617 case 0x2F: do_vec_ADDP (cpu
); return;
5618 case 0x30: do_vec_mull (cpu
); return;
5619 case 0x33: do_vec_FMLA (cpu
); return;
5620 case 0x35: do_vec_fadd (cpu
); return;
5623 switch (INSTR (20, 16))
5625 case 0x00: do_vec_ABS (cpu
); return;
5626 case 0x01: do_vec_FCVTZS (cpu
); return;
5627 case 0x11: do_vec_ADDV (cpu
); return;
5633 do_vec_Fminmax (cpu
); return;
5645 do_vec_compare (cpu
); return;
5648 do_vec_FABS (cpu
); return;
5656 do_vec_xtl (sim_cpu
*cpu
)
5659 instr[30,29] = SXTL (00), UXTL (01), SXTL2 (10), UXTL2 (11)
5660 instr[28,22] = 0 1111 00
5661 instr[21,16] = size & shift (USHLL, SSHLL, USHLL2, SSHLL2)
5662 instr[15,10] = 1010 01
5663 instr[9,5] = V source
5664 instr[4,0] = V dest. */
5666 unsigned vs
= INSTR (9, 5);
5667 unsigned vd
= INSTR (4, 0);
5668 unsigned i
, shift
, bias
= 0;
5670 NYI_assert (28, 22, 0x3C);
5671 NYI_assert (15, 10, 0x29);
5673 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5674 switch (INSTR (30, 29))
5676 case 2: /* SXTL2, SSHLL2. */
5678 case 0: /* SXTL, SSHLL. */
5683 shift
= INSTR (20, 16);
5684 /* Get the source values before setting the destination values
5685 in case the source and destination are the same. */
5686 val1
= aarch64_get_vec_s32 (cpu
, vs
, bias
) << shift
;
5687 val2
= aarch64_get_vec_s32 (cpu
, vs
, bias
+ 1) << shift
;
5688 aarch64_set_vec_s64 (cpu
, vd
, 0, val1
);
5689 aarch64_set_vec_s64 (cpu
, vd
, 1, val2
);
5691 else if (INSTR (20, 20))
5694 int32_t v1
,v2
,v3
,v4
;
5696 shift
= INSTR (19, 16);
5698 for (i
= 0; i
< 4; i
++)
5699 v
[i
] = aarch64_get_vec_s16 (cpu
, vs
, bias
+ i
) << shift
;
5700 for (i
= 0; i
< 4; i
++)
5701 aarch64_set_vec_s32 (cpu
, vd
, i
, v
[i
]);
5706 NYI_assert (19, 19, 1);
5708 shift
= INSTR (18, 16);
5710 for (i
= 0; i
< 8; i
++)
5711 v
[i
] = aarch64_get_vec_s8 (cpu
, vs
, i
+ bias
) << shift
;
5712 for (i
= 0; i
< 8; i
++)
5713 aarch64_set_vec_s16 (cpu
, vd
, i
, v
[i
]);
5717 case 3: /* UXTL2, USHLL2. */
5719 case 1: /* UXTL, USHLL. */
5723 shift
= INSTR (20, 16);
5724 v1
= aarch64_get_vec_u32 (cpu
, vs
, bias
) << shift
;
5725 v2
= aarch64_get_vec_u32 (cpu
, vs
, bias
+ 1) << shift
;
5726 aarch64_set_vec_u64 (cpu
, vd
, 0, v1
);
5727 aarch64_set_vec_u64 (cpu
, vd
, 1, v2
);
5729 else if (INSTR (20, 20))
5732 shift
= INSTR (19, 16);
5734 for (i
= 0; i
< 4; i
++)
5735 v
[i
] = aarch64_get_vec_u16 (cpu
, vs
, i
+ bias
) << shift
;
5736 for (i
= 0; i
< 4; i
++)
5737 aarch64_set_vec_u32 (cpu
, vd
, i
, v
[i
]);
5742 NYI_assert (19, 19, 1);
5744 shift
= INSTR (18, 16);
5746 for (i
= 0; i
< 8; i
++)
5747 v
[i
] = aarch64_get_vec_u8 (cpu
, vs
, i
+ bias
) << shift
;
5748 for (i
= 0; i
< 8; i
++)
5749 aarch64_set_vec_u16 (cpu
, vd
, i
, v
[i
]);
5756 do_vec_SHL (sim_cpu
*cpu
)
5759 instr [30] = half(0)/full(1)
5760 instr [29,23] = 001 1110
5761 instr [22,16] = size and shift amount
5762 instr [15,10] = 01 0101
5764 instr [4, 0] = Vd. */
5767 int full
= INSTR (30, 30);
5768 unsigned vs
= INSTR (9, 5);
5769 unsigned vd
= INSTR (4, 0);
5772 NYI_assert (29, 23, 0x1E);
5773 NYI_assert (15, 10, 0x15);
5775 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5778 shift
= INSTR (21, 16);
5783 for (i
= 0; i
< 2; i
++)
5785 uint64_t val
= aarch64_get_vec_u64 (cpu
, vs
, i
);
5786 aarch64_set_vec_u64 (cpu
, vd
, i
, val
<< shift
);
5794 shift
= INSTR (20, 16);
5796 for (i
= 0; i
< (full
? 4 : 2); i
++)
5798 uint32_t val
= aarch64_get_vec_u32 (cpu
, vs
, i
);
5799 aarch64_set_vec_u32 (cpu
, vd
, i
, val
<< shift
);
5807 shift
= INSTR (19, 16);
5809 for (i
= 0; i
< (full
? 8 : 4); i
++)
5811 uint16_t val
= aarch64_get_vec_u16 (cpu
, vs
, i
);
5812 aarch64_set_vec_u16 (cpu
, vd
, i
, val
<< shift
);
5818 if (INSTR (19, 19) == 0)
5821 shift
= INSTR (18, 16);
5823 for (i
= 0; i
< (full
? 16 : 8); i
++)
5825 uint8_t val
= aarch64_get_vec_u8 (cpu
, vs
, i
);
5826 aarch64_set_vec_u8 (cpu
, vd
, i
, val
<< shift
);
5831 do_vec_SSHR_USHR (sim_cpu
*cpu
)
5834 instr [30] = half(0)/full(1)
5835 instr [29] = signed(0)/unsigned(1)
5836 instr [28,23] = 0 1111 0
5837 instr [22,16] = size and shift amount
5838 instr [15,10] = 0000 01
5840 instr [4, 0] = Vd. */
5842 int full
= INSTR (30, 30);
5843 int sign
= ! INSTR (29, 29);
5844 unsigned shift
= INSTR (22, 16);
5845 unsigned vs
= INSTR (9, 5);
5846 unsigned vd
= INSTR (4, 0);
5849 NYI_assert (28, 23, 0x1E);
5850 NYI_assert (15, 10, 0x01);
5852 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5855 shift
= 128 - shift
;
5861 for (i
= 0; i
< 2; i
++)
5863 int64_t val
= aarch64_get_vec_s64 (cpu
, vs
, i
);
5864 aarch64_set_vec_s64 (cpu
, vd
, i
, val
>> shift
);
5867 for (i
= 0; i
< 2; i
++)
5869 uint64_t val
= aarch64_get_vec_u64 (cpu
, vs
, i
);
5870 aarch64_set_vec_u64 (cpu
, vd
, i
, val
>> shift
);
5881 for (i
= 0; i
< (full
? 4 : 2); i
++)
5883 int32_t val
= aarch64_get_vec_s32 (cpu
, vs
, i
);
5884 aarch64_set_vec_s32 (cpu
, vd
, i
, val
>> shift
);
5887 for (i
= 0; i
< (full
? 4 : 2); i
++)
5889 uint32_t val
= aarch64_get_vec_u32 (cpu
, vs
, i
);
5890 aarch64_set_vec_u32 (cpu
, vd
, i
, val
>> shift
);
5901 for (i
= 0; i
< (full
? 8 : 4); i
++)
5903 int16_t val
= aarch64_get_vec_s16 (cpu
, vs
, i
);
5904 aarch64_set_vec_s16 (cpu
, vd
, i
, val
>> shift
);
5907 for (i
= 0; i
< (full
? 8 : 4); i
++)
5909 uint16_t val
= aarch64_get_vec_u16 (cpu
, vs
, i
);
5910 aarch64_set_vec_u16 (cpu
, vd
, i
, val
>> shift
);
5916 if (INSTR (19, 19) == 0)
5922 for (i
= 0; i
< (full
? 16 : 8); i
++)
5924 int8_t val
= aarch64_get_vec_s8 (cpu
, vs
, i
);
5925 aarch64_set_vec_s8 (cpu
, vd
, i
, val
>> shift
);
5928 for (i
= 0; i
< (full
? 16 : 8); i
++)
5930 uint8_t val
= aarch64_get_vec_u8 (cpu
, vs
, i
);
5931 aarch64_set_vec_u8 (cpu
, vd
, i
, val
>> shift
);
5936 do_vec_MUL_by_element (sim_cpu
*cpu
)
5939 instr[30] = half/full
5940 instr[29,24] = 00 1111
5951 unsigned full
= INSTR (30, 30);
5952 unsigned L
= INSTR (21, 21);
5953 unsigned H
= INSTR (11, 11);
5954 unsigned vn
= INSTR (9, 5);
5955 unsigned vd
= INSTR (4, 0);
5956 unsigned size
= INSTR (23, 22);
5961 NYI_assert (29, 24, 0x0F);
5962 NYI_assert (15, 12, 0x8);
5963 NYI_assert (10, 10, 0);
5965 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5970 /* 16 bit products. */
5975 index
= (H
<< 2) | (L
<< 1) | INSTR (20, 20);
5976 vm
= INSTR (19, 16);
5977 element2
= aarch64_get_vec_u16 (cpu
, vm
, index
);
5979 for (e
= 0; e
< (full
? 8 : 4); e
++)
5981 element1
= aarch64_get_vec_u16 (cpu
, vn
, e
);
5982 product
= element1
* element2
;
5983 aarch64_set_vec_u16 (cpu
, vd
, e
, product
);
5990 /* 32 bit products. */
5995 index
= (H
<< 1) | L
;
5996 vm
= INSTR (20, 16);
5997 element2
= aarch64_get_vec_u32 (cpu
, vm
, index
);
5999 for (e
= 0; e
< (full
? 4 : 2); e
++)
6001 element1
= aarch64_get_vec_u32 (cpu
, vn
, e
);
6002 product
= element1
* element2
;
6003 aarch64_set_vec_u32 (cpu
, vd
, e
, product
);
6014 do_FMLA_by_element (sim_cpu
*cpu
)
6017 instr[30] = half/full
6018 instr[29,23] = 00 1111 1
6028 unsigned full
= INSTR (30, 30);
6029 unsigned size
= INSTR (22, 22);
6030 unsigned L
= INSTR (21, 21);
6031 unsigned vm
= INSTR (20, 16);
6032 unsigned H
= INSTR (11, 11);
6033 unsigned vn
= INSTR (9, 5);
6034 unsigned vd
= INSTR (4, 0);
6037 NYI_assert (29, 23, 0x1F);
6038 NYI_assert (15, 12, 0x1);
6039 NYI_assert (10, 10, 0);
6041 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6044 double element1
, element2
;
6049 element2
= aarch64_get_vec_double (cpu
, vm
, H
);
6051 for (e
= 0; e
< 2; e
++)
6053 element1
= aarch64_get_vec_double (cpu
, vn
, e
);
6054 element1
*= element2
;
6055 element1
+= aarch64_get_vec_double (cpu
, vd
, e
);
6056 aarch64_set_vec_double (cpu
, vd
, e
, element1
);
6062 float element2
= aarch64_get_vec_float (cpu
, vm
, (H
<< 1) | L
);
6064 for (e
= 0; e
< (full
? 4 : 2); e
++)
6066 element1
= aarch64_get_vec_float (cpu
, vn
, e
);
6067 element1
*= element2
;
6068 element1
+= aarch64_get_vec_float (cpu
, vd
, e
);
6069 aarch64_set_vec_float (cpu
, vd
, e
, element1
);
6075 do_vec_op2 (sim_cpu
*cpu
)
6078 instr[30] = half/full
6079 instr[29,24] = 00 1111
6081 instr[22,16] = element size & index
6082 instr[15,10] = sub-opcode
6086 NYI_assert (29, 24, 0x0F);
6088 if (INSTR (23, 23) != 0)
6090 switch (INSTR (15, 10))
6094 do_FMLA_by_element (cpu
);
6099 do_vec_MUL_by_element (cpu
);
6108 switch (INSTR (15, 10))
6110 case 0x01: do_vec_SSHR_USHR (cpu
); return;
6111 case 0x15: do_vec_SHL (cpu
); return;
6113 case 0x22: do_vec_MUL_by_element (cpu
); return;
6114 case 0x29: do_vec_xtl (cpu
); return;
6121 do_vec_neg (sim_cpu
*cpu
)
6124 instr[30] = full(1)/half(0)
6125 instr[29,24] = 10 1110
6126 instr[23,22] = size: byte(00), half (01), word (10), long (11)
6127 instr[21,10] = 1000 0010 1110
6131 int full
= INSTR (30, 30);
6132 unsigned vs
= INSTR (9, 5);
6133 unsigned vd
= INSTR (4, 0);
6136 NYI_assert (29, 24, 0x2E);
6137 NYI_assert (21, 10, 0x82E);
6139 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6140 switch (INSTR (23, 22))
6143 for (i
= 0; i
< (full
? 16 : 8); i
++)
6144 aarch64_set_vec_s8 (cpu
, vd
, i
, - aarch64_get_vec_s8 (cpu
, vs
, i
));
6148 for (i
= 0; i
< (full
? 8 : 4); i
++)
6149 aarch64_set_vec_s16 (cpu
, vd
, i
, - aarch64_get_vec_s16 (cpu
, vs
, i
));
6153 for (i
= 0; i
< (full
? 4 : 2); i
++)
6154 aarch64_set_vec_s32 (cpu
, vd
, i
, - aarch64_get_vec_s32 (cpu
, vs
, i
));
6160 for (i
= 0; i
< 2; i
++)
6161 aarch64_set_vec_s64 (cpu
, vd
, i
, - aarch64_get_vec_s64 (cpu
, vs
, i
));
6167 do_vec_sqrt (sim_cpu
*cpu
)
6170 instr[30] = full(1)/half(0)
6171 instr[29,23] = 101 1101
6172 instr[22] = single(0)/double(1)
6173 instr[21,10] = 1000 0111 1110
6177 int full
= INSTR (30, 30);
6178 unsigned vs
= INSTR (9, 5);
6179 unsigned vd
= INSTR (4, 0);
6182 NYI_assert (29, 23, 0x5B);
6183 NYI_assert (21, 10, 0x87E);
6185 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6186 if (INSTR (22, 22) == 0)
6187 for (i
= 0; i
< (full
? 4 : 2); i
++)
6188 aarch64_set_vec_float (cpu
, vd
, i
,
6189 sqrtf (aarch64_get_vec_float (cpu
, vs
, i
)));
6191 for (i
= 0; i
< 2; i
++)
6192 aarch64_set_vec_double (cpu
, vd
, i
,
6193 sqrt (aarch64_get_vec_double (cpu
, vs
, i
)));
6197 do_vec_mls_indexed (sim_cpu
*cpu
)
6200 instr[30] = half(0)/full(1)
6201 instr[29,24] = 10 1111
6202 instr[23,22] = 16-bit(01)/32-bit(10)
6203 instr[21,20+11] = index (if 16-bit)
6204 instr[21+11] = index (if 32-bit)
6207 instr[11] = part of index
6212 int full
= INSTR (30, 30);
6213 unsigned vs
= INSTR (9, 5);
6214 unsigned vd
= INSTR (4, 0);
6215 unsigned vm
= INSTR (20, 16);
6218 NYI_assert (15, 12, 4);
6219 NYI_assert (10, 10, 0);
6221 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6222 switch (INSTR (23, 22))
6232 elem
= (INSTR (21, 20) << 1) | INSTR (11, 11);
6233 val
= aarch64_get_vec_u16 (cpu
, vm
, elem
);
6235 for (i
= 0; i
< (full
? 8 : 4); i
++)
6236 aarch64_set_vec_u32 (cpu
, vd
, i
,
6237 aarch64_get_vec_u32 (cpu
, vd
, i
) -
6238 (aarch64_get_vec_u32 (cpu
, vs
, i
) * val
));
6244 unsigned elem
= (INSTR (21, 21) << 1) | INSTR (11, 11);
6245 uint64_t val
= aarch64_get_vec_u32 (cpu
, vm
, elem
);
6247 for (i
= 0; i
< (full
? 4 : 2); i
++)
6248 aarch64_set_vec_u64 (cpu
, vd
, i
,
6249 aarch64_get_vec_u64 (cpu
, vd
, i
) -
6250 (aarch64_get_vec_u64 (cpu
, vs
, i
) * val
));
6262 do_vec_SUB (sim_cpu
*cpu
)
6265 instr [30] = half(0)/full(1)
6266 instr [29,24] = 10 1110
6267 instr [23,22] = size: byte(00, half(01), word (10), long (11)
6270 instr [15,10] = 10 0001
6272 instr [4, 0] = Vd. */
6274 unsigned full
= INSTR (30, 30);
6275 unsigned vm
= INSTR (20, 16);
6276 unsigned vn
= INSTR (9, 5);
6277 unsigned vd
= INSTR (4, 0);
6280 NYI_assert (29, 24, 0x2E);
6281 NYI_assert (21, 21, 1);
6282 NYI_assert (15, 10, 0x21);
6284 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6285 switch (INSTR (23, 22))
6288 for (i
= 0; i
< (full
? 16 : 8); i
++)
6289 aarch64_set_vec_s8 (cpu
, vd
, i
,
6290 aarch64_get_vec_s8 (cpu
, vn
, i
)
6291 - aarch64_get_vec_s8 (cpu
, vm
, i
));
6295 for (i
= 0; i
< (full
? 8 : 4); i
++)
6296 aarch64_set_vec_s16 (cpu
, vd
, i
,
6297 aarch64_get_vec_s16 (cpu
, vn
, i
)
6298 - aarch64_get_vec_s16 (cpu
, vm
, i
));
6302 for (i
= 0; i
< (full
? 4 : 2); i
++)
6303 aarch64_set_vec_s32 (cpu
, vd
, i
,
6304 aarch64_get_vec_s32 (cpu
, vn
, i
)
6305 - aarch64_get_vec_s32 (cpu
, vm
, i
));
6312 for (i
= 0; i
< 2; i
++)
6313 aarch64_set_vec_s64 (cpu
, vd
, i
,
6314 aarch64_get_vec_s64 (cpu
, vn
, i
)
6315 - aarch64_get_vec_s64 (cpu
, vm
, i
));
6321 do_vec_MLS (sim_cpu
*cpu
)
6324 instr [30] = half(0)/full(1)
6325 instr [29,24] = 10 1110
6326 instr [23,22] = size: byte(00, half(01), word (10)
6329 instr [15,10] = 10 0101
6331 instr [4, 0] = Vd. */
6333 unsigned full
= INSTR (30, 30);
6334 unsigned vm
= INSTR (20, 16);
6335 unsigned vn
= INSTR (9, 5);
6336 unsigned vd
= INSTR (4, 0);
6339 NYI_assert (29, 24, 0x2E);
6340 NYI_assert (21, 21, 1);
6341 NYI_assert (15, 10, 0x25);
6343 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6344 switch (INSTR (23, 22))
6347 for (i
= 0; i
< (full
? 16 : 8); i
++)
6348 aarch64_set_vec_u8 (cpu
, vd
, i
,
6349 (aarch64_get_vec_u8 (cpu
, vn
, i
)
6350 * aarch64_get_vec_u8 (cpu
, vm
, i
))
6351 - aarch64_get_vec_u8 (cpu
, vd
, i
));
6355 for (i
= 0; i
< (full
? 8 : 4); i
++)
6356 aarch64_set_vec_u16 (cpu
, vd
, i
,
6357 (aarch64_get_vec_u16 (cpu
, vn
, i
)
6358 * aarch64_get_vec_u16 (cpu
, vm
, i
))
6359 - aarch64_get_vec_u16 (cpu
, vd
, i
));
6363 for (i
= 0; i
< (full
? 4 : 2); i
++)
6364 aarch64_set_vec_u32 (cpu
, vd
, i
,
6365 (aarch64_get_vec_u32 (cpu
, vn
, i
)
6366 * aarch64_get_vec_u32 (cpu
, vm
, i
))
6367 - aarch64_get_vec_u32 (cpu
, vd
, i
));
6376 do_vec_FDIV (sim_cpu
*cpu
)
6379 instr [30] = half(0)/full(1)
6380 instr [29,23] = 10 1110 0
6381 instr [22] = float()/double(1)
6384 instr [15,10] = 1111 11
6386 instr [4, 0] = Vd. */
6388 unsigned full
= INSTR (30, 30);
6389 unsigned vm
= INSTR (20, 16);
6390 unsigned vn
= INSTR (9, 5);
6391 unsigned vd
= INSTR (4, 0);
6394 NYI_assert (29, 23, 0x5C);
6395 NYI_assert (21, 21, 1);
6396 NYI_assert (15, 10, 0x3F);
6398 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6404 for (i
= 0; i
< 2; i
++)
6405 aarch64_set_vec_double (cpu
, vd
, i
,
6406 aarch64_get_vec_double (cpu
, vn
, i
)
6407 / aarch64_get_vec_double (cpu
, vm
, i
));
6410 for (i
= 0; i
< (full
? 4 : 2); i
++)
6411 aarch64_set_vec_float (cpu
, vd
, i
,
6412 aarch64_get_vec_float (cpu
, vn
, i
)
6413 / aarch64_get_vec_float (cpu
, vm
, i
));
6417 do_vec_FMUL (sim_cpu
*cpu
)
6420 instr [30] = half(0)/full(1)
6421 instr [29,23] = 10 1110 0
6422 instr [22] = float(0)/double(1)
6425 instr [15,10] = 1101 11
6427 instr [4, 0] = Vd. */
6429 unsigned full
= INSTR (30, 30);
6430 unsigned vm
= INSTR (20, 16);
6431 unsigned vn
= INSTR (9, 5);
6432 unsigned vd
= INSTR (4, 0);
6435 NYI_assert (29, 23, 0x5C);
6436 NYI_assert (21, 21, 1);
6437 NYI_assert (15, 10, 0x37);
6439 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6445 for (i
= 0; i
< 2; i
++)
6446 aarch64_set_vec_double (cpu
, vd
, i
,
6447 aarch64_get_vec_double (cpu
, vn
, i
)
6448 * aarch64_get_vec_double (cpu
, vm
, i
));
6451 for (i
= 0; i
< (full
? 4 : 2); i
++)
6452 aarch64_set_vec_float (cpu
, vd
, i
,
6453 aarch64_get_vec_float (cpu
, vn
, i
)
6454 * aarch64_get_vec_float (cpu
, vm
, i
));
6458 do_vec_FADDP (sim_cpu
*cpu
)
6461 instr [30] = half(0)/full(1)
6462 instr [29,23] = 10 1110 0
6463 instr [22] = float(0)/double(1)
6466 instr [15,10] = 1101 01
6468 instr [4, 0] = Vd. */
6470 unsigned full
= INSTR (30, 30);
6471 unsigned vm
= INSTR (20, 16);
6472 unsigned vn
= INSTR (9, 5);
6473 unsigned vd
= INSTR (4, 0);
6475 NYI_assert (29, 23, 0x5C);
6476 NYI_assert (21, 21, 1);
6477 NYI_assert (15, 10, 0x35);
6479 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6482 /* Extract values before adding them incase vd == vn/vm. */
6483 double tmp1
= aarch64_get_vec_double (cpu
, vn
, 0);
6484 double tmp2
= aarch64_get_vec_double (cpu
, vn
, 1);
6485 double tmp3
= aarch64_get_vec_double (cpu
, vm
, 0);
6486 double tmp4
= aarch64_get_vec_double (cpu
, vm
, 1);
6491 aarch64_set_vec_double (cpu
, vd
, 0, tmp1
+ tmp2
);
6492 aarch64_set_vec_double (cpu
, vd
, 1, tmp3
+ tmp4
);
6496 /* Extract values before adding them incase vd == vn/vm. */
6497 float tmp1
= aarch64_get_vec_float (cpu
, vn
, 0);
6498 float tmp2
= aarch64_get_vec_float (cpu
, vn
, 1);
6499 float tmp5
= aarch64_get_vec_float (cpu
, vm
, 0);
6500 float tmp6
= aarch64_get_vec_float (cpu
, vm
, 1);
6504 float tmp3
= aarch64_get_vec_float (cpu
, vn
, 2);
6505 float tmp4
= aarch64_get_vec_float (cpu
, vn
, 3);
6506 float tmp7
= aarch64_get_vec_float (cpu
, vm
, 2);
6507 float tmp8
= aarch64_get_vec_float (cpu
, vm
, 3);
6509 aarch64_set_vec_float (cpu
, vd
, 0, tmp1
+ tmp2
);
6510 aarch64_set_vec_float (cpu
, vd
, 1, tmp3
+ tmp4
);
6511 aarch64_set_vec_float (cpu
, vd
, 2, tmp5
+ tmp6
);
6512 aarch64_set_vec_float (cpu
, vd
, 3, tmp7
+ tmp8
);
6516 aarch64_set_vec_float (cpu
, vd
, 0, tmp1
+ tmp2
);
6517 aarch64_set_vec_float (cpu
, vd
, 1, tmp5
+ tmp6
);
6523 do_vec_FSQRT (sim_cpu
*cpu
)
6526 instr[30] = half(0)/full(1)
6527 instr[29,23] = 10 1110 1
6528 instr[22] = single(0)/double(1)
6529 instr[21,10] = 10 0001 1111 10
6531 instr[4,0] = Vdest. */
6533 unsigned vn
= INSTR (9, 5);
6534 unsigned vd
= INSTR (4, 0);
6535 unsigned full
= INSTR (30, 30);
6538 NYI_assert (29, 23, 0x5D);
6539 NYI_assert (21, 10, 0x87E);
6541 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6547 for (i
= 0; i
< 2; i
++)
6548 aarch64_set_vec_double (cpu
, vd
, i
,
6549 sqrt (aarch64_get_vec_double (cpu
, vn
, i
)));
6553 for (i
= 0; i
< (full
? 4 : 2); i
++)
6554 aarch64_set_vec_float (cpu
, vd
, i
,
6555 sqrtf (aarch64_get_vec_float (cpu
, vn
, i
)));
6560 do_vec_FNEG (sim_cpu
*cpu
)
6563 instr[30] = half (0)/full (1)
6564 instr[29,23] = 10 1110 1
6565 instr[22] = single (0)/double (1)
6566 instr[21,10] = 10 0000 1111 10
6568 instr[4,0] = Vdest. */
6570 unsigned vn
= INSTR (9, 5);
6571 unsigned vd
= INSTR (4, 0);
6572 unsigned full
= INSTR (30, 30);
6575 NYI_assert (29, 23, 0x5D);
6576 NYI_assert (21, 10, 0x83E);
6578 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6584 for (i
= 0; i
< 2; i
++)
6585 aarch64_set_vec_double (cpu
, vd
, i
,
6586 - aarch64_get_vec_double (cpu
, vn
, i
));
6590 for (i
= 0; i
< (full
? 4 : 2); i
++)
6591 aarch64_set_vec_float (cpu
, vd
, i
,
6592 - aarch64_get_vec_float (cpu
, vn
, i
));
6597 do_vec_NOT (sim_cpu
*cpu
)
6600 instr[30] = half (0)/full (1)
6601 instr[29,10] = 10 1110 0010 0000 0101 10
6605 unsigned vn
= INSTR (9, 5);
6606 unsigned vd
= INSTR (4, 0);
6608 int full
= INSTR (30, 30);
6610 NYI_assert (29, 10, 0xB8816);
6612 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6613 for (i
= 0; i
< (full
? 16 : 8); i
++)
6614 aarch64_set_vec_u8 (cpu
, vd
, i
, ~ aarch64_get_vec_u8 (cpu
, vn
, i
));
6618 clz (uint64_t val
, unsigned size
)
6623 mask
<<= (size
- 1);
6638 do_vec_CLZ (sim_cpu
*cpu
)
6641 instr[30] = half (0)/full (1)
6642 instr[29,24] = 10 1110
6644 instr[21,10] = 10 0000 0100 10
6648 unsigned vn
= INSTR (9, 5);
6649 unsigned vd
= INSTR (4, 0);
6651 int full
= INSTR (30,30);
6653 NYI_assert (29, 24, 0x2E);
6654 NYI_assert (21, 10, 0x812);
6656 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6657 switch (INSTR (23, 22))
6660 for (i
= 0; i
< (full
? 16 : 8); i
++)
6661 aarch64_set_vec_u8 (cpu
, vd
, i
, clz (aarch64_get_vec_u8 (cpu
, vn
, i
), 8));
6664 for (i
= 0; i
< (full
? 8 : 4); i
++)
6665 aarch64_set_vec_u16 (cpu
, vd
, i
, clz (aarch64_get_vec_u16 (cpu
, vn
, i
), 16));
6668 for (i
= 0; i
< (full
? 4 : 2); i
++)
6669 aarch64_set_vec_u32 (cpu
, vd
, i
, clz (aarch64_get_vec_u32 (cpu
, vn
, i
), 32));
6674 aarch64_set_vec_u64 (cpu
, vd
, 0, clz (aarch64_get_vec_u64 (cpu
, vn
, 0), 64));
6675 aarch64_set_vec_u64 (cpu
, vd
, 1, clz (aarch64_get_vec_u64 (cpu
, vn
, 1), 64));
6681 do_vec_MOV_element (sim_cpu
*cpu
)
6683 /* instr[31,21] = 0110 1110 000
6684 instr[20,16] = size & dest index
6686 instr[14,11] = source index
6691 unsigned vs
= INSTR (9, 5);
6692 unsigned vd
= INSTR (4, 0);
6696 NYI_assert (31, 21, 0x370);
6697 NYI_assert (15, 15, 0);
6698 NYI_assert (10, 10, 1);
6700 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6704 src_index
= INSTR (14, 11);
6705 dst_index
= INSTR (20, 17);
6706 aarch64_set_vec_u8 (cpu
, vd
, dst_index
,
6707 aarch64_get_vec_u8 (cpu
, vs
, src_index
));
6709 else if (INSTR (17, 17))
6712 NYI_assert (11, 11, 0);
6713 src_index
= INSTR (14, 12);
6714 dst_index
= INSTR (20, 18);
6715 aarch64_set_vec_u16 (cpu
, vd
, dst_index
,
6716 aarch64_get_vec_u16 (cpu
, vs
, src_index
));
6718 else if (INSTR (18, 18))
6721 NYI_assert (12, 11, 0);
6722 src_index
= INSTR (14, 13);
6723 dst_index
= INSTR (20, 19);
6724 aarch64_set_vec_u32 (cpu
, vd
, dst_index
,
6725 aarch64_get_vec_u32 (cpu
, vs
, src_index
));
6729 NYI_assert (19, 19, 1);
6730 NYI_assert (13, 11, 0);
6731 src_index
= INSTR (14, 14);
6732 dst_index
= INSTR (20, 20);
6733 aarch64_set_vec_u64 (cpu
, vd
, dst_index
,
6734 aarch64_get_vec_u64 (cpu
, vs
, src_index
));
6739 do_vec_REV32 (sim_cpu
*cpu
)
6742 instr[30] = full/half
6743 instr[29,24] = 10 1110
6745 instr[21,10] = 10 0000 0000 10
6749 unsigned rn
= INSTR (9, 5);
6750 unsigned rd
= INSTR (4, 0);
6751 unsigned size
= INSTR (23, 22);
6752 unsigned full
= INSTR (30, 30);
6756 NYI_assert (29, 24, 0x2E);
6757 NYI_assert (21, 10, 0x802);
6759 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6763 for (i
= 0; i
< (full
? 16 : 8); i
++)
6764 val
.b
[i
^ 0x3] = aarch64_get_vec_u8 (cpu
, rn
, i
);
6768 for (i
= 0; i
< (full
? 8 : 4); i
++)
6769 val
.h
[i
^ 0x1] = aarch64_get_vec_u16 (cpu
, rn
, i
);
6776 aarch64_set_vec_u64 (cpu
, rd
, 0, val
.v
[0]);
6778 aarch64_set_vec_u64 (cpu
, rd
, 1, val
.v
[1]);
6782 do_vec_EXT (sim_cpu
*cpu
)
6785 instr[30] = full/half
6786 instr[29,21] = 10 1110 000
6789 instr[14,11] = source index
6794 unsigned vm
= INSTR (20, 16);
6795 unsigned vn
= INSTR (9, 5);
6796 unsigned vd
= INSTR (4, 0);
6797 unsigned src_index
= INSTR (14, 11);
6798 unsigned full
= INSTR (30, 30);
6803 NYI_assert (31, 21, 0x370);
6804 NYI_assert (15, 15, 0);
6805 NYI_assert (10, 10, 0);
6807 if (!full
&& (src_index
& 0x8))
6812 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6813 for (i
= src_index
; i
< (full
? 16 : 8); i
++)
6814 val
.b
[j
++] = aarch64_get_vec_u8 (cpu
, vn
, i
);
6815 for (i
= 0; i
< src_index
; i
++)
6816 val
.b
[j
++] = aarch64_get_vec_u8 (cpu
, vm
, i
);
6818 aarch64_set_vec_u64 (cpu
, vd
, 0, val
.v
[0]);
6820 aarch64_set_vec_u64 (cpu
, vd
, 1, val
.v
[1]);
6824 dexAdvSIMD0 (sim_cpu
*cpu
)
6826 /* instr [28,25] = 0 111. */
6827 if ( INSTR (15, 10) == 0x07
6831 if (INSTR (31, 21) == 0x075
6832 || INSTR (31, 21) == 0x275)
6834 do_vec_MOV_whole_vector (cpu
);
6839 if (INSTR (29, 19) == 0x1E0)
6841 do_vec_MOV_immediate (cpu
);
6845 if (INSTR (29, 19) == 0x5E0)
6851 if (INSTR (29, 19) == 0x1C0
6852 || INSTR (29, 19) == 0x1C1)
6854 if (INSTR (15, 10) == 0x03)
6856 do_vec_DUP_scalar_into_vector (cpu
);
6861 switch (INSTR (29, 24))
6863 case 0x0E: do_vec_op1 (cpu
); return;
6864 case 0x0F: do_vec_op2 (cpu
); return;
6867 if (INSTR (21, 21) == 1)
6869 switch (INSTR (15, 10))
6876 switch (INSTR (23, 22))
6878 case 0: do_vec_EOR (cpu
); return;
6879 case 1: do_vec_BSL (cpu
); return;
6881 case 3: do_vec_bit (cpu
); return;
6885 case 0x08: do_vec_sub_long (cpu
); return;
6886 case 0x11: do_vec_USHL (cpu
); return;
6887 case 0x12: do_vec_CLZ (cpu
); return;
6888 case 0x16: do_vec_NOT (cpu
); return;
6889 case 0x19: do_vec_max (cpu
); return;
6890 case 0x1B: do_vec_min (cpu
); return;
6891 case 0x21: do_vec_SUB (cpu
); return;
6892 case 0x25: do_vec_MLS (cpu
); return;
6893 case 0x31: do_vec_FminmaxNMP (cpu
); return;
6894 case 0x35: do_vec_FADDP (cpu
); return;
6895 case 0x37: do_vec_FMUL (cpu
); return;
6896 case 0x3F: do_vec_FDIV (cpu
); return;
6899 switch (INSTR (20, 16))
6901 case 0x00: do_vec_FNEG (cpu
); return;
6902 case 0x01: do_vec_FSQRT (cpu
); return;
6916 do_vec_compare (cpu
); return;
6923 if (INSTR (31, 21) == 0x370)
6926 do_vec_MOV_element (cpu
);
6932 switch (INSTR (21, 10))
6934 case 0x82E: do_vec_neg (cpu
); return;
6935 case 0x87E: do_vec_sqrt (cpu
); return;
6937 if (INSTR (15, 10) == 0x30)
6947 switch (INSTR (15, 10))
6949 case 0x01: do_vec_SSHR_USHR (cpu
); return;
6951 case 0x12: do_vec_mls_indexed (cpu
); return;
6952 case 0x29: do_vec_xtl (cpu
); return;
6966 /* Float multiply add. */
6968 fmadds (sim_cpu
*cpu
)
6970 unsigned sa
= INSTR (14, 10);
6971 unsigned sm
= INSTR (20, 16);
6972 unsigned sn
= INSTR ( 9, 5);
6973 unsigned sd
= INSTR ( 4, 0);
6975 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6976 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sa
)
6977 + aarch64_get_FP_float (cpu
, sn
)
6978 * aarch64_get_FP_float (cpu
, sm
));
6981 /* Double multiply add. */
6983 fmaddd (sim_cpu
*cpu
)
6985 unsigned sa
= INSTR (14, 10);
6986 unsigned sm
= INSTR (20, 16);
6987 unsigned sn
= INSTR ( 9, 5);
6988 unsigned sd
= INSTR ( 4, 0);
6990 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6991 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sa
)
6992 + aarch64_get_FP_double (cpu
, sn
)
6993 * aarch64_get_FP_double (cpu
, sm
));
6996 /* Float multiply subtract. */
6998 fmsubs (sim_cpu
*cpu
)
7000 unsigned sa
= INSTR (14, 10);
7001 unsigned sm
= INSTR (20, 16);
7002 unsigned sn
= INSTR ( 9, 5);
7003 unsigned sd
= INSTR ( 4, 0);
7005 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7006 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sa
)
7007 - aarch64_get_FP_float (cpu
, sn
)
7008 * aarch64_get_FP_float (cpu
, sm
));
7011 /* Double multiply subtract. */
7013 fmsubd (sim_cpu
*cpu
)
7015 unsigned sa
= INSTR (14, 10);
7016 unsigned sm
= INSTR (20, 16);
7017 unsigned sn
= INSTR ( 9, 5);
7018 unsigned sd
= INSTR ( 4, 0);
7020 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7021 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sa
)
7022 - aarch64_get_FP_double (cpu
, sn
)
7023 * aarch64_get_FP_double (cpu
, sm
));
7026 /* Float negative multiply add. */
7028 fnmadds (sim_cpu
*cpu
)
7030 unsigned sa
= INSTR (14, 10);
7031 unsigned sm
= INSTR (20, 16);
7032 unsigned sn
= INSTR ( 9, 5);
7033 unsigned sd
= INSTR ( 4, 0);
7035 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7036 aarch64_set_FP_float (cpu
, sd
, - aarch64_get_FP_float (cpu
, sa
)
7037 + (- aarch64_get_FP_float (cpu
, sn
))
7038 * aarch64_get_FP_float (cpu
, sm
));
7041 /* Double negative multiply add. */
7043 fnmaddd (sim_cpu
*cpu
)
7045 unsigned sa
= INSTR (14, 10);
7046 unsigned sm
= INSTR (20, 16);
7047 unsigned sn
= INSTR ( 9, 5);
7048 unsigned sd
= INSTR ( 4, 0);
7050 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7051 aarch64_set_FP_double (cpu
, sd
, - aarch64_get_FP_double (cpu
, sa
)
7052 + (- aarch64_get_FP_double (cpu
, sn
))
7053 * aarch64_get_FP_double (cpu
, sm
));
7056 /* Float negative multiply subtract. */
7058 fnmsubs (sim_cpu
*cpu
)
7060 unsigned sa
= INSTR (14, 10);
7061 unsigned sm
= INSTR (20, 16);
7062 unsigned sn
= INSTR ( 9, 5);
7063 unsigned sd
= INSTR ( 4, 0);
7065 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7066 aarch64_set_FP_float (cpu
, sd
, - aarch64_get_FP_float (cpu
, sa
)
7067 + aarch64_get_FP_float (cpu
, sn
)
7068 * aarch64_get_FP_float (cpu
, sm
));
7071 /* Double negative multiply subtract. */
7073 fnmsubd (sim_cpu
*cpu
)
7075 unsigned sa
= INSTR (14, 10);
7076 unsigned sm
= INSTR (20, 16);
7077 unsigned sn
= INSTR ( 9, 5);
7078 unsigned sd
= INSTR ( 4, 0);
7080 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7081 aarch64_set_FP_double (cpu
, sd
, - aarch64_get_FP_double (cpu
, sa
)
7082 + aarch64_get_FP_double (cpu
, sn
)
7083 * aarch64_get_FP_double (cpu
, sm
));
7087 dexSimpleFPDataProc3Source (sim_cpu
*cpu
)
7089 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
7091 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
7094 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
7095 instr[21] ==> o1 : 0 ==> unnegated, 1 ==> negated
7096 instr[15] ==> o2 : 0 ==> ADD, 1 ==> SUB */
7098 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
7099 /* dispatch on combined type:o1:o2. */
7100 uint32_t dispatch
= (INSTR (23, 21) << 1) | INSTR (15, 15);
7107 case 0: fmadds (cpu
); return;
7108 case 1: fmsubs (cpu
); return;
7109 case 2: fnmadds (cpu
); return;
7110 case 3: fnmsubs (cpu
); return;
7111 case 4: fmaddd (cpu
); return;
7112 case 5: fmsubd (cpu
); return;
7113 case 6: fnmaddd (cpu
); return;
7114 case 7: fnmsubd (cpu
); return;
7116 /* type > 1 is currently unallocated. */
7122 dexSimpleFPFixedConvert (sim_cpu
*cpu
)
7128 dexSimpleFPCondCompare (sim_cpu
*cpu
)
7130 /* instr [31,23] = 0001 1110 0
7134 instr [15,12] = condition
7138 instr [3,0] = nzcv */
7140 unsigned rm
= INSTR (20, 16);
7141 unsigned rn
= INSTR (9, 5);
7143 NYI_assert (31, 23, 0x3C);
7144 NYI_assert (11, 10, 0x1);
7145 NYI_assert (4, 4, 0);
7147 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7148 if (! testConditionCode (cpu
, INSTR (15, 12)))
7150 aarch64_set_CPSR (cpu
, INSTR (3, 0));
7156 /* Double precision. */
7157 double val1
= aarch64_get_vec_double (cpu
, rn
, 0);
7158 double val2
= aarch64_get_vec_double (cpu
, rm
, 0);
7160 /* FIXME: Check for NaNs. */
7162 aarch64_set_CPSR (cpu
, (Z
| C
));
7163 else if (val1
< val2
)
7164 aarch64_set_CPSR (cpu
, N
);
7165 else /* val1 > val2 */
7166 aarch64_set_CPSR (cpu
, C
);
7170 /* Single precision. */
7171 float val1
= aarch64_get_vec_float (cpu
, rn
, 0);
7172 float val2
= aarch64_get_vec_float (cpu
, rm
, 0);
7174 /* FIXME: Check for NaNs. */
7176 aarch64_set_CPSR (cpu
, (Z
| C
));
7177 else if (val1
< val2
)
7178 aarch64_set_CPSR (cpu
, N
);
7179 else /* val1 > val2 */
7180 aarch64_set_CPSR (cpu
, C
);
7188 fadds (sim_cpu
*cpu
)
7190 unsigned sm
= INSTR (20, 16);
7191 unsigned sn
= INSTR ( 9, 5);
7192 unsigned sd
= INSTR ( 4, 0);
7194 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7195 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
7196 + aarch64_get_FP_float (cpu
, sm
));
7201 faddd (sim_cpu
*cpu
)
7203 unsigned sm
= INSTR (20, 16);
7204 unsigned sn
= INSTR ( 9, 5);
7205 unsigned sd
= INSTR ( 4, 0);
7207 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7208 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
7209 + aarch64_get_FP_double (cpu
, sm
));
7214 fdivs (sim_cpu
*cpu
)
7216 unsigned sm
= INSTR (20, 16);
7217 unsigned sn
= INSTR ( 9, 5);
7218 unsigned sd
= INSTR ( 4, 0);
7220 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7221 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
7222 / aarch64_get_FP_float (cpu
, sm
));
7225 /* Double divide. */
7227 fdivd (sim_cpu
*cpu
)
7229 unsigned sm
= INSTR (20, 16);
7230 unsigned sn
= INSTR ( 9, 5);
7231 unsigned sd
= INSTR ( 4, 0);
7233 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7234 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
7235 / aarch64_get_FP_double (cpu
, sm
));
7238 /* Float multiply. */
7240 fmuls (sim_cpu
*cpu
)
7242 unsigned sm
= INSTR (20, 16);
7243 unsigned sn
= INSTR ( 9, 5);
7244 unsigned sd
= INSTR ( 4, 0);
7246 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7247 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
7248 * aarch64_get_FP_float (cpu
, sm
));
7251 /* Double multiply. */
7253 fmuld (sim_cpu
*cpu
)
7255 unsigned sm
= INSTR (20, 16);
7256 unsigned sn
= INSTR ( 9, 5);
7257 unsigned sd
= INSTR ( 4, 0);
7259 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7260 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
7261 * aarch64_get_FP_double (cpu
, sm
));
7264 /* Float negate and multiply. */
7266 fnmuls (sim_cpu
*cpu
)
7268 unsigned sm
= INSTR (20, 16);
7269 unsigned sn
= INSTR ( 9, 5);
7270 unsigned sd
= INSTR ( 4, 0);
7272 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7273 aarch64_set_FP_float (cpu
, sd
, - (aarch64_get_FP_float (cpu
, sn
)
7274 * aarch64_get_FP_float (cpu
, sm
)));
7277 /* Double negate and multiply. */
7279 fnmuld (sim_cpu
*cpu
)
7281 unsigned sm
= INSTR (20, 16);
7282 unsigned sn
= INSTR ( 9, 5);
7283 unsigned sd
= INSTR ( 4, 0);
7285 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7286 aarch64_set_FP_double (cpu
, sd
, - (aarch64_get_FP_double (cpu
, sn
)
7287 * aarch64_get_FP_double (cpu
, sm
)));
7290 /* Float subtract. */
7292 fsubs (sim_cpu
*cpu
)
7294 unsigned sm
= INSTR (20, 16);
7295 unsigned sn
= INSTR ( 9, 5);
7296 unsigned sd
= INSTR ( 4, 0);
7298 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7299 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
7300 - aarch64_get_FP_float (cpu
, sm
));
7303 /* Double subtract. */
7305 fsubd (sim_cpu
*cpu
)
7307 unsigned sm
= INSTR (20, 16);
7308 unsigned sn
= INSTR ( 9, 5);
7309 unsigned sd
= INSTR ( 4, 0);
7311 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7312 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
7313 - aarch64_get_FP_double (cpu
, sm
));
7317 do_FMINNM (sim_cpu
*cpu
)
7319 /* instr[31,23] = 0 0011 1100
7320 instr[22] = float(0)/double(1)
7323 instr[15,10] = 01 1110
7327 unsigned sm
= INSTR (20, 16);
7328 unsigned sn
= INSTR ( 9, 5);
7329 unsigned sd
= INSTR ( 4, 0);
7331 NYI_assert (31, 23, 0x03C);
7332 NYI_assert (15, 10, 0x1E);
7334 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7336 aarch64_set_FP_double (cpu
, sd
,
7337 dminnm (aarch64_get_FP_double (cpu
, sn
),
7338 aarch64_get_FP_double (cpu
, sm
)));
7340 aarch64_set_FP_float (cpu
, sd
,
7341 fminnm (aarch64_get_FP_float (cpu
, sn
),
7342 aarch64_get_FP_float (cpu
, sm
)));
7346 do_FMAXNM (sim_cpu
*cpu
)
7348 /* instr[31,23] = 0 0011 1100
7349 instr[22] = float(0)/double(1)
7352 instr[15,10] = 01 1010
7356 unsigned sm
= INSTR (20, 16);
7357 unsigned sn
= INSTR ( 9, 5);
7358 unsigned sd
= INSTR ( 4, 0);
7360 NYI_assert (31, 23, 0x03C);
7361 NYI_assert (15, 10, 0x1A);
7363 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7365 aarch64_set_FP_double (cpu
, sd
,
7366 dmaxnm (aarch64_get_FP_double (cpu
, sn
),
7367 aarch64_get_FP_double (cpu
, sm
)));
7369 aarch64_set_FP_float (cpu
, sd
,
7370 fmaxnm (aarch64_get_FP_float (cpu
, sn
),
7371 aarch64_get_FP_float (cpu
, sm
)));
7375 dexSimpleFPDataProc2Source (sim_cpu
*cpu
)
7377 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
7379 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
7382 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
7385 instr[15,12] ==> opcode : 0000 ==> FMUL, 0001 ==> FDIV
7386 0010 ==> FADD, 0011 ==> FSUB,
7387 0100 ==> FMAX, 0101 ==> FMIN
7388 0110 ==> FMAXNM, 0111 ==> FMINNM
7389 1000 ==> FNMUL, ow ==> UNALLOC
7394 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
7395 uint32_t type
= INSTR (23, 22);
7396 /* Dispatch on opcode. */
7397 uint32_t dispatch
= INSTR (15, 12);
7408 case 0: fmuld (cpu
); return;
7409 case 1: fdivd (cpu
); return;
7410 case 2: faddd (cpu
); return;
7411 case 3: fsubd (cpu
); return;
7412 case 6: do_FMAXNM (cpu
); return;
7413 case 7: do_FMINNM (cpu
); return;
7414 case 8: fnmuld (cpu
); return;
7416 /* Have not yet implemented fmax and fmin. */
7424 else /* type == 0 => floats. */
7427 case 0: fmuls (cpu
); return;
7428 case 1: fdivs (cpu
); return;
7429 case 2: fadds (cpu
); return;
7430 case 3: fsubs (cpu
); return;
7431 case 6: do_FMAXNM (cpu
); return;
7432 case 7: do_FMINNM (cpu
); return;
7433 case 8: fnmuls (cpu
); return;
7445 dexSimpleFPCondSelect (sim_cpu
*cpu
)
7448 instr[31,23] = 0 0011 1100
7449 instr[22] = 0=>single 1=>double
7456 unsigned sm
= INSTR (20, 16);
7457 unsigned sn
= INSTR ( 9, 5);
7458 unsigned sd
= INSTR ( 4, 0);
7459 uint32_t set
= testConditionCode (cpu
, INSTR (15, 12));
7461 NYI_assert (31, 23, 0x03C);
7462 NYI_assert (11, 10, 0x3);
7464 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7466 aarch64_set_FP_double (cpu
, sd
, set
? sn
: sm
);
7468 aarch64_set_FP_float (cpu
, sd
, set
? sn
: sm
);
7471 /* Store 32 bit unscaled signed 9 bit. */
7473 fsturs (sim_cpu
*cpu
, int32_t offset
)
7475 unsigned int rn
= INSTR (9, 5);
7476 unsigned int st
= INSTR (4, 0);
7478 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7479 aarch64_set_mem_u32 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, 1) + offset
,
7480 aarch64_get_vec_u32 (cpu
, st
, 0));
7483 /* Store 64 bit unscaled signed 9 bit. */
7485 fsturd (sim_cpu
*cpu
, int32_t offset
)
7487 unsigned int rn
= INSTR (9, 5);
7488 unsigned int st
= INSTR (4, 0);
7490 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7491 aarch64_set_mem_u64 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, 1) + offset
,
7492 aarch64_get_vec_u64 (cpu
, st
, 0));
7495 /* Store 128 bit unscaled signed 9 bit. */
7497 fsturq (sim_cpu
*cpu
, int32_t offset
)
7499 unsigned int rn
= INSTR (9, 5);
7500 unsigned int st
= INSTR (4, 0);
7503 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7504 aarch64_get_FP_long_double (cpu
, st
, & a
);
7505 aarch64_set_mem_long_double (cpu
,
7506 aarch64_get_reg_u64 (cpu
, rn
, 1)
7510 /* TODO FP move register. */
7512 /* 32 bit fp to fp move register. */
7514 ffmovs (sim_cpu
*cpu
)
7516 unsigned int rn
= INSTR (9, 5);
7517 unsigned int st
= INSTR (4, 0);
7519 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7520 aarch64_set_FP_float (cpu
, st
, aarch64_get_FP_float (cpu
, rn
));
7523 /* 64 bit fp to fp move register. */
7525 ffmovd (sim_cpu
*cpu
)
7527 unsigned int rn
= INSTR (9, 5);
7528 unsigned int st
= INSTR (4, 0);
7530 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7531 aarch64_set_FP_double (cpu
, st
, aarch64_get_FP_double (cpu
, rn
));
7534 /* 32 bit GReg to Vec move register. */
7536 fgmovs (sim_cpu
*cpu
)
7538 unsigned int rn
= INSTR (9, 5);
7539 unsigned int st
= INSTR (4, 0);
7541 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7542 aarch64_set_vec_u32 (cpu
, st
, 0, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
));
7545 /* 64 bit g to fp move register. */
7547 fgmovd (sim_cpu
*cpu
)
7549 unsigned int rn
= INSTR (9, 5);
7550 unsigned int st
= INSTR (4, 0);
7552 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7553 aarch64_set_vec_u64 (cpu
, st
, 0, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
7556 /* 32 bit fp to g move register. */
7558 gfmovs (sim_cpu
*cpu
)
7560 unsigned int rn
= INSTR (9, 5);
7561 unsigned int st
= INSTR (4, 0);
7563 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7564 aarch64_set_reg_u64 (cpu
, st
, NO_SP
, aarch64_get_vec_u32 (cpu
, rn
, 0));
7567 /* 64 bit fp to g move register. */
7569 gfmovd (sim_cpu
*cpu
)
7571 unsigned int rn
= INSTR (9, 5);
7572 unsigned int st
= INSTR (4, 0);
7574 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7575 aarch64_set_reg_u64 (cpu
, st
, NO_SP
, aarch64_get_vec_u64 (cpu
, rn
, 0));
7578 /* FP move immediate
7580 These install an immediate 8 bit value in the target register
7581 where the 8 bits comprise 1 sign bit, 4 bits of fraction and a 3
7585 fmovs (sim_cpu
*cpu
)
7587 unsigned int sd
= INSTR (4, 0);
7588 uint32_t imm
= INSTR (20, 13);
7589 float f
= fp_immediate_for_encoding_32 (imm
);
7591 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7592 aarch64_set_FP_float (cpu
, sd
, f
);
7596 fmovd (sim_cpu
*cpu
)
7598 unsigned int sd
= INSTR (4, 0);
7599 uint32_t imm
= INSTR (20, 13);
7600 double d
= fp_immediate_for_encoding_64 (imm
);
7602 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7603 aarch64_set_FP_double (cpu
, sd
, d
);
7607 dexSimpleFPImmediate (sim_cpu
*cpu
)
7609 /* instr[31,23] == 00111100
7610 instr[22] == type : single(0)/double(1)
7612 instr[20,13] == imm8
7614 instr[9,5] == imm5 : 00000 ==> PK, ow ==> UNALLOC
7616 uint32_t imm5
= INSTR (9, 5);
7618 NYI_assert (31, 23, 0x3C);
7629 /* TODO specific decode and execute for group Load Store. */
7631 /* TODO FP load/store single register (unscaled offset). */
7633 /* TODO load 8 bit unscaled signed 9 bit. */
7634 /* TODO load 16 bit unscaled signed 9 bit. */
7636 /* Load 32 bit unscaled signed 9 bit. */
7638 fldurs (sim_cpu
*cpu
, int32_t offset
)
7640 unsigned int rn
= INSTR (9, 5);
7641 unsigned int st
= INSTR (4, 0);
7643 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7644 aarch64_set_vec_u32 (cpu
, st
, 0, aarch64_get_mem_u32
7645 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
));
7648 /* Load 64 bit unscaled signed 9 bit. */
7650 fldurd (sim_cpu
*cpu
, int32_t offset
)
7652 unsigned int rn
= INSTR (9, 5);
7653 unsigned int st
= INSTR (4, 0);
7655 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7656 aarch64_set_vec_u64 (cpu
, st
, 0, aarch64_get_mem_u64
7657 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
));
7660 /* Load 128 bit unscaled signed 9 bit. */
7662 fldurq (sim_cpu
*cpu
, int32_t offset
)
7664 unsigned int rn
= INSTR (9, 5);
7665 unsigned int st
= INSTR (4, 0);
7667 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
;
7669 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7670 aarch64_get_mem_long_double (cpu
, addr
, & a
);
7671 aarch64_set_FP_long_double (cpu
, st
, a
);
7674 /* TODO store 8 bit unscaled signed 9 bit. */
7675 /* TODO store 16 bit unscaled signed 9 bit. */
7680 /* Float absolute value. */
7682 fabss (sim_cpu
*cpu
)
7684 unsigned sn
= INSTR (9, 5);
7685 unsigned sd
= INSTR (4, 0);
7686 float value
= aarch64_get_FP_float (cpu
, sn
);
7688 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7689 aarch64_set_FP_float (cpu
, sd
, fabsf (value
));
7692 /* Double absolute value. */
7694 fabcpu (sim_cpu
*cpu
)
7696 unsigned sn
= INSTR (9, 5);
7697 unsigned sd
= INSTR (4, 0);
7698 double value
= aarch64_get_FP_double (cpu
, sn
);
7700 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7701 aarch64_set_FP_double (cpu
, sd
, fabs (value
));
7704 /* Float negative value. */
7706 fnegs (sim_cpu
*cpu
)
7708 unsigned sn
= INSTR (9, 5);
7709 unsigned sd
= INSTR (4, 0);
7711 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7712 aarch64_set_FP_float (cpu
, sd
, - aarch64_get_FP_float (cpu
, sn
));
7715 /* Double negative value. */
7717 fnegd (sim_cpu
*cpu
)
7719 unsigned sn
= INSTR (9, 5);
7720 unsigned sd
= INSTR (4, 0);
7722 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7723 aarch64_set_FP_double (cpu
, sd
, - aarch64_get_FP_double (cpu
, sn
));
7726 /* Float square root. */
7728 fsqrts (sim_cpu
*cpu
)
7730 unsigned sn
= INSTR (9, 5);
7731 unsigned sd
= INSTR (4, 0);
7733 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7734 aarch64_set_FP_float (cpu
, sd
, sqrtf (aarch64_get_FP_float (cpu
, sn
)));
7737 /* Double square root. */
7739 fsqrtd (sim_cpu
*cpu
)
7741 unsigned sn
= INSTR (9, 5);
7742 unsigned sd
= INSTR (4, 0);
7744 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7745 aarch64_set_FP_double (cpu
, sd
,
7746 sqrt (aarch64_get_FP_double (cpu
, sn
)));
7749 /* Convert double to float. */
7751 fcvtds (sim_cpu
*cpu
)
7753 unsigned sn
= INSTR (9, 5);
7754 unsigned sd
= INSTR (4, 0);
7756 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7757 aarch64_set_FP_float (cpu
, sd
, (float) aarch64_get_FP_double (cpu
, sn
));
7760 /* Convert float to double. */
7762 fcvtcpu (sim_cpu
*cpu
)
7764 unsigned sn
= INSTR (9, 5);
7765 unsigned sd
= INSTR (4, 0);
7767 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7768 aarch64_set_FP_double (cpu
, sd
, (double) aarch64_get_FP_float (cpu
, sn
));
7772 do_FRINT (sim_cpu
*cpu
)
7774 /* instr[31,23] = 0001 1110 0
7775 instr[22] = single(0)/double(1)
7777 instr[17,15] = rounding mode
7778 instr[14,10] = 10000
7780 instr[4,0] = dest */
7783 unsigned rs
= INSTR (9, 5);
7784 unsigned rd
= INSTR (4, 0);
7785 unsigned int rmode
= INSTR (17, 15);
7787 NYI_assert (31, 23, 0x03C);
7788 NYI_assert (21, 18, 0x9);
7789 NYI_assert (14, 10, 0x10);
7791 if (rmode
== 6 || rmode
== 7)
7792 /* FIXME: Add support for rmode == 6 exactness check. */
7793 rmode
= uimm (aarch64_get_FPSR (cpu
), 23, 22);
7795 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7798 double val
= aarch64_get_FP_double (cpu
, rs
);
7802 case 0: /* mode N: nearest or even. */
7804 double rval
= round (val
);
7806 if (val
- rval
== 0.5)
7808 if (((rval
/ 2.0) * 2.0) != rval
)
7812 aarch64_set_FP_double (cpu
, rd
, round (val
));
7816 case 1: /* mode P: towards +inf. */
7818 aarch64_set_FP_double (cpu
, rd
, trunc (val
));
7820 aarch64_set_FP_double (cpu
, rd
, round (val
));
7823 case 2: /* mode M: towards -inf. */
7825 aarch64_set_FP_double (cpu
, rd
, round (val
));
7827 aarch64_set_FP_double (cpu
, rd
, trunc (val
));
7830 case 3: /* mode Z: towards 0. */
7831 aarch64_set_FP_double (cpu
, rd
, trunc (val
));
7834 case 4: /* mode A: away from 0. */
7835 aarch64_set_FP_double (cpu
, rd
, round (val
));
7838 case 6: /* mode X: use FPCR with exactness check. */
7839 case 7: /* mode I: use FPCR mode. */
7847 val
= aarch64_get_FP_float (cpu
, rs
);
7851 case 0: /* mode N: nearest or even. */
7853 float rval
= roundf (val
);
7855 if (val
- rval
== 0.5)
7857 if (((rval
/ 2.0) * 2.0) != rval
)
7861 aarch64_set_FP_float (cpu
, rd
, rval
);
7865 case 1: /* mode P: towards +inf. */
7867 aarch64_set_FP_float (cpu
, rd
, truncf (val
));
7869 aarch64_set_FP_float (cpu
, rd
, roundf (val
));
7872 case 2: /* mode M: towards -inf. */
7874 aarch64_set_FP_float (cpu
, rd
, truncf (val
));
7876 aarch64_set_FP_float (cpu
, rd
, roundf (val
));
7879 case 3: /* mode Z: towards 0. */
7880 aarch64_set_FP_float (cpu
, rd
, truncf (val
));
7883 case 4: /* mode A: away from 0. */
7884 aarch64_set_FP_float (cpu
, rd
, roundf (val
));
7887 case 6: /* mode X: use FPCR with exactness check. */
7888 case 7: /* mode I: use FPCR mode. */
7896 /* Convert half to float. */
7898 do_FCVT_half_to_single (sim_cpu
*cpu
)
7900 unsigned rn
= INSTR (9, 5);
7901 unsigned rd
= INSTR (4, 0);
7903 NYI_assert (31, 10, 0x7B890);
7905 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7906 aarch64_set_FP_float (cpu
, rd
, (float) aarch64_get_FP_half (cpu
, rn
));
7909 /* Convert half to double. */
7911 do_FCVT_half_to_double (sim_cpu
*cpu
)
7913 unsigned rn
= INSTR (9, 5);
7914 unsigned rd
= INSTR (4, 0);
7916 NYI_assert (31, 10, 0x7B8B0);
7918 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7919 aarch64_set_FP_double (cpu
, rd
, (double) aarch64_get_FP_half (cpu
, rn
));
7923 do_FCVT_single_to_half (sim_cpu
*cpu
)
7925 unsigned rn
= INSTR (9, 5);
7926 unsigned rd
= INSTR (4, 0);
7928 NYI_assert (31, 10, 0x788F0);
7930 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7931 aarch64_set_FP_half (cpu
, rd
, aarch64_get_FP_float (cpu
, rn
));
7934 /* Convert double to half. */
7936 do_FCVT_double_to_half (sim_cpu
*cpu
)
7938 unsigned rn
= INSTR (9, 5);
7939 unsigned rd
= INSTR (4, 0);
7941 NYI_assert (31, 10, 0x798F0);
7943 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7944 aarch64_set_FP_half (cpu
, rd
, (float) aarch64_get_FP_double (cpu
, rn
));
7948 dexSimpleFPDataProc1Source (sim_cpu
*cpu
)
7950 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
7952 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
7955 instr[23,22] ==> type : 00 ==> source is single,
7956 01 ==> source is double
7958 11 ==> UNALLOC or source is half
7960 instr[20,15] ==> opcode : with type 00 or 01
7961 000000 ==> FMOV, 000001 ==> FABS,
7962 000010 ==> FNEG, 000011 ==> FSQRT,
7963 000100 ==> UNALLOC, 000101 ==> FCVT,(to single/double)
7964 000110 ==> UNALLOC, 000111 ==> FCVT (to half)
7965 001000 ==> FRINTN, 001001 ==> FRINTP,
7966 001010 ==> FRINTM, 001011 ==> FRINTZ,
7967 001100 ==> FRINTA, 001101 ==> UNALLOC
7968 001110 ==> FRINTX, 001111 ==> FRINTI
7970 000100 ==> FCVT (half-to-single)
7971 000101 ==> FCVT (half-to-double)
7972 instr[14,10] = 10000. */
7974 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
7975 uint32_t type
= INSTR (23, 22);
7976 uint32_t opcode
= INSTR (20, 15);
7984 do_FCVT_half_to_single (cpu
);
7985 else if (opcode
== 5)
7986 do_FCVT_half_to_double (cpu
);
8038 case 8: /* FRINTN etc. */
8050 do_FCVT_double_to_half (cpu
);
8052 do_FCVT_single_to_half (cpu
);
8063 /* 32 bit signed int to float. */
8065 scvtf32 (sim_cpu
*cpu
)
8067 unsigned rn
= INSTR (9, 5);
8068 unsigned sd
= INSTR (4, 0);
8070 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8071 aarch64_set_FP_float
8072 (cpu
, sd
, (float) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
));
8075 /* signed int to float. */
8077 scvtf (sim_cpu
*cpu
)
8079 unsigned rn
= INSTR (9, 5);
8080 unsigned sd
= INSTR (4, 0);
8082 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8083 aarch64_set_FP_float
8084 (cpu
, sd
, (float) aarch64_get_reg_s64 (cpu
, rn
, NO_SP
));
8087 /* 32 bit signed int to double. */
8089 scvtd32 (sim_cpu
*cpu
)
8091 unsigned rn
= INSTR (9, 5);
8092 unsigned sd
= INSTR (4, 0);
8094 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8095 aarch64_set_FP_double
8096 (cpu
, sd
, (double) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
));
8099 /* signed int to double. */
8101 scvtd (sim_cpu
*cpu
)
8103 unsigned rn
= INSTR (9, 5);
8104 unsigned sd
= INSTR (4, 0);
8106 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8107 aarch64_set_FP_double
8108 (cpu
, sd
, (double) aarch64_get_reg_s64 (cpu
, rn
, NO_SP
));
8111 static const float FLOAT_INT_MAX
= (float) INT_MAX
;
8112 static const float FLOAT_INT_MIN
= (float) INT_MIN
;
8113 static const double DOUBLE_INT_MAX
= (double) INT_MAX
;
8114 static const double DOUBLE_INT_MIN
= (double) INT_MIN
;
8115 static const float FLOAT_LONG_MAX
= (float) LONG_MAX
;
8116 static const float FLOAT_LONG_MIN
= (float) LONG_MIN
;
8117 static const double DOUBLE_LONG_MAX
= (double) LONG_MAX
;
8118 static const double DOUBLE_LONG_MIN
= (double) LONG_MIN
;
8120 /* Check for FP exception conditions:
8123 Out of Range raises IO and IX and saturates value
8124 Denormal raises ID and IX and sets to zero. */
8125 #define RAISE_EXCEPTIONS(F, VALUE, FTYPE, ITYPE) \
8128 switch (fpclassify (F)) \
8132 aarch64_set_FPSR (cpu, IO); \
8134 VALUE = ITYPE##_MAX; \
8136 VALUE = ITYPE##_MIN; \
8140 if (F >= FTYPE##_##ITYPE##_MAX) \
8142 aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX); \
8143 VALUE = ITYPE##_MAX; \
8145 else if (F <= FTYPE##_##ITYPE##_MIN) \
8147 aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX); \
8148 VALUE = ITYPE##_MIN; \
8152 case FP_SUBNORMAL: \
8153 aarch64_set_FPSR_bits (cpu, IO | IX | ID, IX | ID); \
8165 /* 32 bit convert float to signed int truncate towards zero. */
8167 fcvtszs32 (sim_cpu
*cpu
)
8169 unsigned sn
= INSTR (9, 5);
8170 unsigned rd
= INSTR (4, 0);
8171 /* TODO : check that this rounds toward zero. */
8172 float f
= aarch64_get_FP_float (cpu
, sn
);
8173 int32_t value
= (int32_t) f
;
8175 RAISE_EXCEPTIONS (f
, value
, FLOAT
, INT
);
8177 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8178 /* Avoid sign extension to 64 bit. */
8179 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) value
);
8182 /* 64 bit convert float to signed int truncate towards zero. */
8184 fcvtszs (sim_cpu
*cpu
)
8186 unsigned sn
= INSTR (9, 5);
8187 unsigned rd
= INSTR (4, 0);
8188 float f
= aarch64_get_FP_float (cpu
, sn
);
8189 int64_t value
= (int64_t) f
;
8191 RAISE_EXCEPTIONS (f
, value
, FLOAT
, LONG
);
8193 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8194 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, value
);
8197 /* 32 bit convert double to signed int truncate towards zero. */
8199 fcvtszd32 (sim_cpu
*cpu
)
8201 unsigned sn
= INSTR (9, 5);
8202 unsigned rd
= INSTR (4, 0);
8203 /* TODO : check that this rounds toward zero. */
8204 double d
= aarch64_get_FP_double (cpu
, sn
);
8205 int32_t value
= (int32_t) d
;
8207 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, INT
);
8209 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8210 /* Avoid sign extension to 64 bit. */
8211 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) value
);
8214 /* 64 bit convert double to signed int truncate towards zero. */
8216 fcvtszd (sim_cpu
*cpu
)
8218 unsigned sn
= INSTR (9, 5);
8219 unsigned rd
= INSTR (4, 0);
8220 /* TODO : check that this rounds toward zero. */
8221 double d
= aarch64_get_FP_double (cpu
, sn
);
8224 value
= (int64_t) d
;
8226 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, LONG
);
8228 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8229 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, value
);
8233 do_fcvtzu (sim_cpu
*cpu
)
8235 /* instr[31] = size: 32-bit (0), 64-bit (1)
8236 instr[30,23] = 00111100
8237 instr[22] = type: single (0)/ double (1)
8238 instr[21] = enable (0)/disable(1) precision
8239 instr[20,16] = 11001
8240 instr[15,10] = precision
8244 unsigned rs
= INSTR (9, 5);
8245 unsigned rd
= INSTR (4, 0);
8247 NYI_assert (30, 23, 0x3C);
8248 NYI_assert (20, 16, 0x19);
8250 if (INSTR (21, 21) != 1)
8251 /* Convert to fixed point. */
8254 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8257 /* Convert to unsigned 64-bit integer. */
8260 double d
= aarch64_get_FP_double (cpu
, rs
);
8261 uint64_t value
= (uint64_t) d
;
8263 /* Do not raise an exception if we have reached ULONG_MAX. */
8264 if (value
!= (1UL << 63))
8265 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, LONG
);
8267 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
8271 float f
= aarch64_get_FP_float (cpu
, rs
);
8272 uint64_t value
= (uint64_t) f
;
8274 /* Do not raise an exception if we have reached ULONG_MAX. */
8275 if (value
!= (1UL << 63))
8276 RAISE_EXCEPTIONS (f
, value
, FLOAT
, LONG
);
8278 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
8285 /* Convert to unsigned 32-bit integer. */
8288 double d
= aarch64_get_FP_double (cpu
, rs
);
8290 value
= (uint32_t) d
;
8291 /* Do not raise an exception if we have reached UINT_MAX. */
8292 if (value
!= (1UL << 31))
8293 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, INT
);
8297 float f
= aarch64_get_FP_float (cpu
, rs
);
8299 value
= (uint32_t) f
;
8300 /* Do not raise an exception if we have reached UINT_MAX. */
8301 if (value
!= (1UL << 31))
8302 RAISE_EXCEPTIONS (f
, value
, FLOAT
, INT
);
8305 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
8310 do_UCVTF (sim_cpu
*cpu
)
8312 /* instr[31] = size: 32-bit (0), 64-bit (1)
8313 instr[30,23] = 001 1110 0
8314 instr[22] = type: single (0)/ double (1)
8315 instr[21] = enable (0)/disable(1) precision
8316 instr[20,16] = 0 0011
8317 instr[15,10] = precision
8321 unsigned rs
= INSTR (9, 5);
8322 unsigned rd
= INSTR (4, 0);
8324 NYI_assert (30, 23, 0x3C);
8325 NYI_assert (20, 16, 0x03);
8327 if (INSTR (21, 21) != 1)
8330 /* FIXME: Add exception raising. */
8331 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8334 uint64_t value
= aarch64_get_reg_u64 (cpu
, rs
, NO_SP
);
8337 aarch64_set_FP_double (cpu
, rd
, (double) value
);
8339 aarch64_set_FP_float (cpu
, rd
, (float) value
);
8343 uint32_t value
= aarch64_get_reg_u32 (cpu
, rs
, NO_SP
);
8346 aarch64_set_FP_double (cpu
, rd
, (double) value
);
8348 aarch64_set_FP_float (cpu
, rd
, (float) value
);
8353 float_vector_move (sim_cpu
*cpu
)
8355 /* instr[31,17] == 100 1111 0101 0111
8356 instr[16] ==> direction 0=> to GR, 1=> from GR
8358 instr[9,5] ==> source
8359 instr[4,0] ==> dest. */
8361 unsigned rn
= INSTR (9, 5);
8362 unsigned rd
= INSTR (4, 0);
8364 NYI_assert (31, 17, 0x4F57);
8366 if (INSTR (15, 10) != 0)
8369 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8371 aarch64_set_vec_u64 (cpu
, rd
, 1, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
8373 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, aarch64_get_vec_u64 (cpu
, rn
, 1));
8377 dexSimpleFPIntegerConvert (sim_cpu
*cpu
)
8379 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
8381 instr[29] = S : 0 ==> OK, 1 ==> UNALLOC
8384 instr[23,22] = type : 00 ==> single, 01 ==> double, 1x ==> UNALLOC
8386 instr[20,19] = rmode
8387 instr[18,16] = opcode
8388 instr[15,10] = 10 0000 */
8390 uint32_t rmode_opcode
;
8396 if (INSTR (31, 17) == 0x4F57)
8398 float_vector_move (cpu
);
8402 size
= INSTR (31, 31);
8407 type
= INSTR (23, 22);
8411 rmode_opcode
= INSTR (20, 16);
8412 size_type
= (size
<< 1) | type
; /* 0==32f, 1==32d, 2==64f, 3==64d. */
8414 switch (rmode_opcode
)
8416 case 2: /* SCVTF. */
8419 case 0: scvtf32 (cpu
); return;
8420 case 1: scvtd32 (cpu
); return;
8421 case 2: scvtf (cpu
); return;
8422 case 3: scvtd (cpu
); return;
8425 case 6: /* FMOV GR, Vec. */
8428 case 0: gfmovs (cpu
); return;
8429 case 3: gfmovd (cpu
); return;
8430 default: HALT_UNALLOC
;
8433 case 7: /* FMOV vec, GR. */
8436 case 0: fgmovs (cpu
); return;
8437 case 3: fgmovd (cpu
); return;
8438 default: HALT_UNALLOC
;
8441 case 24: /* FCVTZS. */
8444 case 0: fcvtszs32 (cpu
); return;
8445 case 1: fcvtszd32 (cpu
); return;
8446 case 2: fcvtszs (cpu
); return;
8447 case 3: fcvtszd (cpu
); return;
8450 case 25: do_fcvtzu (cpu
); return;
8451 case 3: do_UCVTF (cpu
); return;
8453 case 0: /* FCVTNS. */
8454 case 1: /* FCVTNU. */
8455 case 4: /* FCVTAS. */
8456 case 5: /* FCVTAU. */
8457 case 8: /* FCVPTS. */
8458 case 9: /* FCVTPU. */
8459 case 16: /* FCVTMS. */
8460 case 17: /* FCVTMU. */
8467 set_flags_for_float_compare (sim_cpu
*cpu
, float fvalue1
, float fvalue2
)
8471 /* FIXME: Add exception raising. */
8472 if (isnan (fvalue1
) || isnan (fvalue2
))
8474 else if (isinf (fvalue1
) && isinf (fvalue2
))
8476 /* Subtracting two infinities may give a NaN. We only need to compare
8477 the signs, which we can get from isinf. */
8478 int result
= isinf (fvalue1
) - isinf (fvalue2
);
8482 else if (result
< 0)
8484 else /* (result > 0). */
8489 float result
= fvalue1
- fvalue2
;
8493 else if (result
< 0)
8495 else /* (result > 0). */
8499 aarch64_set_CPSR (cpu
, flags
);
8503 fcmps (sim_cpu
*cpu
)
8505 unsigned sm
= INSTR (20, 16);
8506 unsigned sn
= INSTR ( 9, 5);
8508 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8509 float fvalue2
= aarch64_get_FP_float (cpu
, sm
);
8511 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8512 set_flags_for_float_compare (cpu
, fvalue1
, fvalue2
);
8515 /* Float compare to zero -- Invalid Operation exception
8516 only on signaling NaNs. */
8518 fcmpzs (sim_cpu
*cpu
)
8520 unsigned sn
= INSTR ( 9, 5);
8521 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8523 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8524 set_flags_for_float_compare (cpu
, fvalue1
, 0.0f
);
8527 /* Float compare -- Invalid Operation exception on all NaNs. */
8529 fcmpes (sim_cpu
*cpu
)
8531 unsigned sm
= INSTR (20, 16);
8532 unsigned sn
= INSTR ( 9, 5);
8534 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8535 float fvalue2
= aarch64_get_FP_float (cpu
, sm
);
8537 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8538 set_flags_for_float_compare (cpu
, fvalue1
, fvalue2
);
8541 /* Float compare to zero -- Invalid Operation exception on all NaNs. */
8543 fcmpzes (sim_cpu
*cpu
)
8545 unsigned sn
= INSTR ( 9, 5);
8546 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8548 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8549 set_flags_for_float_compare (cpu
, fvalue1
, 0.0f
);
8553 set_flags_for_double_compare (sim_cpu
*cpu
, double dval1
, double dval2
)
8557 /* FIXME: Add exception raising. */
8558 if (isnan (dval1
) || isnan (dval2
))
8560 else if (isinf (dval1
) && isinf (dval2
))
8562 /* Subtracting two infinities may give a NaN. We only need to compare
8563 the signs, which we can get from isinf. */
8564 int result
= isinf (dval1
) - isinf (dval2
);
8568 else if (result
< 0)
8570 else /* (result > 0). */
8575 double result
= dval1
- dval2
;
8579 else if (result
< 0)
8581 else /* (result > 0). */
8585 aarch64_set_CPSR (cpu
, flags
);
8588 /* Double compare -- Invalid Operation exception only on signaling NaNs. */
8590 fcmpd (sim_cpu
*cpu
)
8592 unsigned sm
= INSTR (20, 16);
8593 unsigned sn
= INSTR ( 9, 5);
8595 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8596 double dvalue2
= aarch64_get_FP_double (cpu
, sm
);
8598 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8599 set_flags_for_double_compare (cpu
, dvalue1
, dvalue2
);
8602 /* Double compare to zero -- Invalid Operation exception
8603 only on signaling NaNs. */
8605 fcmpzd (sim_cpu
*cpu
)
8607 unsigned sn
= INSTR ( 9, 5);
8608 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8610 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8611 set_flags_for_double_compare (cpu
, dvalue1
, 0.0);
8614 /* Double compare -- Invalid Operation exception on all NaNs. */
8616 fcmped (sim_cpu
*cpu
)
8618 unsigned sm
= INSTR (20, 16);
8619 unsigned sn
= INSTR ( 9, 5);
8621 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8622 double dvalue2
= aarch64_get_FP_double (cpu
, sm
);
8624 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8625 set_flags_for_double_compare (cpu
, dvalue1
, dvalue2
);
8628 /* Double compare to zero -- Invalid Operation exception on all NaNs. */
8630 fcmpzed (sim_cpu
*cpu
)
8632 unsigned sn
= INSTR ( 9, 5);
8633 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8635 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8636 set_flags_for_double_compare (cpu
, dvalue1
, 0.0);
8640 dexSimpleFPCompare (sim_cpu
*cpu
)
8642 /* assert instr[28,25] == 1111
8643 instr[30:24:21:13,10] = 0011000
8644 instr[31] = M : 0 ==> OK, 1 ==> UNALLOC
8645 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
8646 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
8647 instr[15,14] ==> op : 00 ==> OK, ow ==> UNALLOC
8648 instr[4,0] ==> opcode2 : 00000 ==> FCMP, 10000 ==> FCMPE,
8649 01000 ==> FCMPZ, 11000 ==> FCMPEZ,
8652 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
8653 uint32_t type
= INSTR (23, 22);
8654 uint32_t op
= INSTR (15, 14);
8655 uint32_t op2_2_0
= INSTR (2, 0);
8669 /* dispatch on type and top 2 bits of opcode. */
8670 dispatch
= (type
<< 2) | INSTR (4, 3);
8674 case 0: fcmps (cpu
); return;
8675 case 1: fcmpzs (cpu
); return;
8676 case 2: fcmpes (cpu
); return;
8677 case 3: fcmpzes (cpu
); return;
8678 case 4: fcmpd (cpu
); return;
8679 case 5: fcmpzd (cpu
); return;
8680 case 6: fcmped (cpu
); return;
8681 case 7: fcmpzed (cpu
); return;
8686 do_scalar_FADDP (sim_cpu
*cpu
)
8688 /* instr [31,23] = 0111 1110 0
8689 instr [22] = single(0)/double(1)
8690 instr [21,10] = 11 0000 1101 10
8692 instr [4,0] = Fd. */
8694 unsigned Fn
= INSTR (9, 5);
8695 unsigned Fd
= INSTR (4, 0);
8697 NYI_assert (31, 23, 0x0FC);
8698 NYI_assert (21, 10, 0xC36);
8700 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8703 double val1
= aarch64_get_vec_double (cpu
, Fn
, 0);
8704 double val2
= aarch64_get_vec_double (cpu
, Fn
, 1);
8706 aarch64_set_FP_double (cpu
, Fd
, val1
+ val2
);
8710 float val1
= aarch64_get_vec_float (cpu
, Fn
, 0);
8711 float val2
= aarch64_get_vec_float (cpu
, Fn
, 1);
8713 aarch64_set_FP_float (cpu
, Fd
, val1
+ val2
);
8717 /* Floating point absolute difference. */
8720 do_scalar_FABD (sim_cpu
*cpu
)
8722 /* instr [31,23] = 0111 1110 1
8723 instr [22] = float(0)/double(1)
8726 instr [15,10] = 1101 01
8728 instr [4, 0] = Rd. */
8730 unsigned rm
= INSTR (20, 16);
8731 unsigned rn
= INSTR (9, 5);
8732 unsigned rd
= INSTR (4, 0);
8734 NYI_assert (31, 23, 0x0FD);
8735 NYI_assert (21, 21, 1);
8736 NYI_assert (15, 10, 0x35);
8738 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8740 aarch64_set_FP_double (cpu
, rd
,
8741 fabs (aarch64_get_FP_double (cpu
, rn
)
8742 - aarch64_get_FP_double (cpu
, rm
)));
8744 aarch64_set_FP_float (cpu
, rd
,
8745 fabsf (aarch64_get_FP_float (cpu
, rn
)
8746 - aarch64_get_FP_float (cpu
, rm
)));
8750 do_scalar_CMGT (sim_cpu
*cpu
)
8752 /* instr [31,21] = 0101 1110 111
8754 instr [15,10] = 00 1101
8756 instr [4, 0] = Rd. */
8758 unsigned rm
= INSTR (20, 16);
8759 unsigned rn
= INSTR (9, 5);
8760 unsigned rd
= INSTR (4, 0);
8762 NYI_assert (31, 21, 0x2F7);
8763 NYI_assert (15, 10, 0x0D);
8765 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8766 aarch64_set_vec_u64 (cpu
, rd
, 0,
8767 aarch64_get_vec_u64 (cpu
, rn
, 0) >
8768 aarch64_get_vec_u64 (cpu
, rm
, 0) ? -1L : 0L);
8772 do_scalar_USHR (sim_cpu
*cpu
)
8774 /* instr [31,23] = 0111 1111 0
8775 instr [22,16] = shift amount
8776 instr [15,10] = 0000 01
8778 instr [4, 0] = Rd. */
8780 unsigned amount
= 128 - INSTR (22, 16);
8781 unsigned rn
= INSTR (9, 5);
8782 unsigned rd
= INSTR (4, 0);
8784 NYI_assert (31, 23, 0x0FE);
8785 NYI_assert (15, 10, 0x01);
8787 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8788 aarch64_set_vec_u64 (cpu
, rd
, 0,
8789 aarch64_get_vec_u64 (cpu
, rn
, 0) >> amount
);
8793 do_scalar_SSHL (sim_cpu
*cpu
)
8795 /* instr [31,21] = 0101 1110 111
8797 instr [15,10] = 0100 01
8799 instr [4, 0] = Rd. */
8801 unsigned rm
= INSTR (20, 16);
8802 unsigned rn
= INSTR (9, 5);
8803 unsigned rd
= INSTR (4, 0);
8804 signed int shift
= aarch64_get_vec_s8 (cpu
, rm
, 0);
8806 NYI_assert (31, 21, 0x2F7);
8807 NYI_assert (15, 10, 0x11);
8809 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8811 aarch64_set_vec_s64 (cpu
, rd
, 0,
8812 aarch64_get_vec_s64 (cpu
, rn
, 0) << shift
);
8814 aarch64_set_vec_s64 (cpu
, rd
, 0,
8815 aarch64_get_vec_s64 (cpu
, rn
, 0) >> - shift
);
8819 do_scalar_shift (sim_cpu
*cpu
)
8821 /* instr [31,23] = 0101 1111 0
8822 instr [22,16] = shift amount
8823 instr [15,10] = 0101 01 [SHL]
8824 instr [15,10] = 0000 01 [SSHR]
8826 instr [4, 0] = Rd. */
8828 unsigned rn
= INSTR (9, 5);
8829 unsigned rd
= INSTR (4, 0);
8832 NYI_assert (31, 23, 0x0BE);
8834 if (INSTR (22, 22) == 0)
8837 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8838 switch (INSTR (15, 10))
8840 case 0x01: /* SSHR */
8841 amount
= 128 - INSTR (22, 16);
8842 aarch64_set_vec_s64 (cpu
, rd
, 0,
8843 aarch64_get_vec_s64 (cpu
, rn
, 0) >> amount
);
8845 case 0x15: /* SHL */
8846 amount
= INSTR (22, 16) - 64;
8847 aarch64_set_vec_u64 (cpu
, rd
, 0,
8848 aarch64_get_vec_u64 (cpu
, rn
, 0) << amount
);
8855 /* FCMEQ FCMGT FCMGE. */
8857 do_scalar_FCM (sim_cpu
*cpu
)
8859 /* instr [31,30] = 01
8861 instr [28,24] = 1 1110
8866 instr [15,12] = 1110
8870 instr [4, 0] = Rd. */
8872 unsigned rm
= INSTR (20, 16);
8873 unsigned rn
= INSTR (9, 5);
8874 unsigned rd
= INSTR (4, 0);
8875 unsigned EUac
= (INSTR (23, 23) << 2) | (INSTR (29, 29) << 1) | INSTR (11, 11);
8880 NYI_assert (31, 30, 1);
8881 NYI_assert (28, 24, 0x1E);
8882 NYI_assert (21, 21, 1);
8883 NYI_assert (15, 12, 0xE);
8884 NYI_assert (10, 10, 1);
8886 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8889 double val1
= aarch64_get_FP_double (cpu
, rn
);
8890 double val2
= aarch64_get_FP_double (cpu
, rm
);
8895 result
= val1
== val2
;
8903 result
= val1
>= val2
;
8911 result
= val1
> val2
;
8918 aarch64_set_vec_u32 (cpu
, rd
, 0, result
? -1 : 0);
8922 val1
= aarch64_get_FP_float (cpu
, rn
);
8923 val2
= aarch64_get_FP_float (cpu
, rm
);
8928 result
= val1
== val2
;
8932 val1
= fabsf (val1
);
8933 val2
= fabsf (val2
);
8936 result
= val1
>= val2
;
8940 val1
= fabsf (val1
);
8941 val2
= fabsf (val2
);
8944 result
= val1
> val2
;
8951 aarch64_set_vec_u32 (cpu
, rd
, 0, result
? -1 : 0);
8954 /* An alias of DUP. */
8956 do_scalar_MOV (sim_cpu
*cpu
)
8958 /* instr [31,21] = 0101 1110 000
8959 instr [20,16] = imm5
8960 instr [15,10] = 0000 01
8962 instr [4, 0] = Rd. */
8964 unsigned rn
= INSTR (9, 5);
8965 unsigned rd
= INSTR (4, 0);
8968 NYI_assert (31, 21, 0x2F0);
8969 NYI_assert (15, 10, 0x01);
8971 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8975 index
= INSTR (20, 17);
8977 (cpu
, rd
, 0, aarch64_get_vec_u8 (cpu
, rn
, index
));
8979 else if (INSTR (17, 17))
8982 index
= INSTR (20, 18);
8984 (cpu
, rd
, 0, aarch64_get_vec_u16 (cpu
, rn
, index
));
8986 else if (INSTR (18, 18))
8989 index
= INSTR (20, 19);
8991 (cpu
, rd
, 0, aarch64_get_vec_u32 (cpu
, rn
, index
));
8993 else if (INSTR (19, 19))
8996 index
= INSTR (20, 20);
8998 (cpu
, rd
, 0, aarch64_get_vec_u64 (cpu
, rn
, index
));
9005 do_scalar_NEG (sim_cpu
*cpu
)
9007 /* instr [31,10] = 0111 1110 1110 0000 1011 10
9009 instr [4, 0] = Rd. */
9011 unsigned rn
= INSTR (9, 5);
9012 unsigned rd
= INSTR (4, 0);
9014 NYI_assert (31, 10, 0x1FB82E);
9016 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9017 aarch64_set_vec_u64 (cpu
, rd
, 0, - aarch64_get_vec_u64 (cpu
, rn
, 0));
9021 do_scalar_USHL (sim_cpu
*cpu
)
9023 /* instr [31,21] = 0111 1110 111
9025 instr [15,10] = 0100 01
9027 instr [4, 0] = Rd. */
9029 unsigned rm
= INSTR (20, 16);
9030 unsigned rn
= INSTR (9, 5);
9031 unsigned rd
= INSTR (4, 0);
9032 signed int shift
= aarch64_get_vec_s8 (cpu
, rm
, 0);
9034 NYI_assert (31, 21, 0x3F7);
9035 NYI_assert (15, 10, 0x11);
9037 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9039 aarch64_set_vec_u64 (cpu
, rd
, 0, aarch64_get_vec_u64 (cpu
, rn
, 0) << shift
);
9041 aarch64_set_vec_u64 (cpu
, rd
, 0, aarch64_get_vec_u64 (cpu
, rn
, 0) >> - shift
);
9045 do_double_add (sim_cpu
*cpu
)
9047 /* instr [31,21] = 0101 1110 111
9049 instr [15,10] = 1000 01
9051 instr [4,0] = Fd. */
9058 NYI_assert (31, 21, 0x2F7);
9059 NYI_assert (15, 10, 0x21);
9063 Fn
= INSTR (20, 16);
9065 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9066 val1
= aarch64_get_FP_double (cpu
, Fm
);
9067 val2
= aarch64_get_FP_double (cpu
, Fn
);
9069 aarch64_set_FP_double (cpu
, Fd
, val1
+ val2
);
9073 do_scalar_UCVTF (sim_cpu
*cpu
)
9075 /* instr [31,23] = 0111 1110 0
9076 instr [22] = single(0)/double(1)
9077 instr [21,10] = 10 0001 1101 10
9079 instr [4,0] = rd. */
9081 unsigned rn
= INSTR (9, 5);
9082 unsigned rd
= INSTR (4, 0);
9084 NYI_assert (31, 23, 0x0FC);
9085 NYI_assert (21, 10, 0x876);
9087 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9090 uint64_t val
= aarch64_get_vec_u64 (cpu
, rn
, 0);
9092 aarch64_set_vec_double (cpu
, rd
, 0, (double) val
);
9096 uint32_t val
= aarch64_get_vec_u32 (cpu
, rn
, 0);
9098 aarch64_set_vec_float (cpu
, rd
, 0, (float) val
);
9103 do_scalar_vec (sim_cpu
*cpu
)
9105 /* instr [30] = 1. */
9106 /* instr [28,25] = 1111. */
9107 switch (INSTR (31, 23))
9110 switch (INSTR (15, 10))
9112 case 0x01: do_scalar_MOV (cpu
); return;
9113 case 0x39: do_scalar_FCM (cpu
); return;
9114 case 0x3B: do_scalar_FCM (cpu
); return;
9118 case 0xBE: do_scalar_shift (cpu
); return;
9121 switch (INSTR (15, 10))
9124 switch (INSTR (21, 16))
9126 case 0x30: do_scalar_FADDP (cpu
); return;
9127 case 0x21: do_scalar_UCVTF (cpu
); return;
9130 case 0x39: do_scalar_FCM (cpu
); return;
9131 case 0x3B: do_scalar_FCM (cpu
); return;
9136 switch (INSTR (15, 10))
9138 case 0x0D: do_scalar_CMGT (cpu
); return;
9139 case 0x11: do_scalar_USHL (cpu
); return;
9140 case 0x2E: do_scalar_NEG (cpu
); return;
9141 case 0x35: do_scalar_FABD (cpu
); return;
9142 case 0x39: do_scalar_FCM (cpu
); return;
9143 case 0x3B: do_scalar_FCM (cpu
); return;
9148 case 0xFE: do_scalar_USHR (cpu
); return;
9151 switch (INSTR (15, 10))
9153 case 0x21: do_double_add (cpu
); return;
9154 case 0x11: do_scalar_SSHL (cpu
); return;
9165 dexAdvSIMD1 (sim_cpu
*cpu
)
9167 /* instr [28,25] = 1 111. */
9169 /* We are currently only interested in the basic
9170 scalar fp routines which all have bit 30 = 0. */
9172 do_scalar_vec (cpu
);
9174 /* instr[24] is set for FP data processing 3-source and clear for
9175 all other basic scalar fp instruction groups. */
9176 else if (INSTR (24, 24))
9177 dexSimpleFPDataProc3Source (cpu
);
9179 /* instr[21] is clear for floating <-> fixed conversions and set for
9180 all other basic scalar fp instruction groups. */
9181 else if (!INSTR (21, 21))
9182 dexSimpleFPFixedConvert (cpu
);
9184 /* instr[11,10] : 01 ==> cond compare, 10 ==> Data Proc 2 Source
9185 11 ==> cond select, 00 ==> other. */
9187 switch (INSTR (11, 10))
9189 case 1: dexSimpleFPCondCompare (cpu
); return;
9190 case 2: dexSimpleFPDataProc2Source (cpu
); return;
9191 case 3: dexSimpleFPCondSelect (cpu
); return;
9194 /* Now an ordered cascade of tests.
9195 FP immediate has instr [12] == 1.
9196 FP compare has instr [13] == 1.
9197 FP Data Proc 1 Source has instr [14] == 1.
9198 FP floating <--> integer conversions has instr [15] == 0. */
9200 dexSimpleFPImmediate (cpu
);
9202 else if (INSTR (13, 13))
9203 dexSimpleFPCompare (cpu
);
9205 else if (INSTR (14, 14))
9206 dexSimpleFPDataProc1Source (cpu
);
9208 else if (!INSTR (15, 15))
9209 dexSimpleFPIntegerConvert (cpu
);
9212 /* If we get here then instr[15] == 1 which means UNALLOC. */
9217 /* PC relative addressing. */
9220 pcadr (sim_cpu
*cpu
)
9222 /* instr[31] = op : 0 ==> ADR, 1 ==> ADRP
9223 instr[30,29] = immlo
9224 instr[23,5] = immhi. */
9226 unsigned rd
= INSTR (4, 0);
9227 uint32_t isPage
= INSTR (31, 31);
9228 union { int64_t u64
; uint64_t s64
; } imm
;
9231 imm
.s64
= simm64 (aarch64_get_instr (cpu
), 23, 5);
9233 offset
= (offset
<< 2) | INSTR (30, 29);
9235 address
= aarch64_get_PC (cpu
);
9243 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9244 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, address
+ offset
);
9247 /* Specific decode and execute for group Data Processing Immediate. */
9250 dexPCRelAddressing (sim_cpu
*cpu
)
9252 /* assert instr[28,24] = 10000. */
9256 /* Immediate logical.
9257 The bimm32/64 argument is constructed by replicating a 2, 4, 8,
9258 16, 32 or 64 bit sequence pulled out at decode and possibly
9261 N.B. the output register (dest) can normally be Xn or SP
9262 the exception occurs for flag setting instructions which may
9263 only use Xn for the output (dest). The input register can
9266 /* 32 bit and immediate. */
9268 and32 (sim_cpu
*cpu
, uint32_t bimm
)
9270 unsigned rn
= INSTR (9, 5);
9271 unsigned rd
= INSTR (4, 0);
9273 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9274 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9275 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
) & bimm
);
9278 /* 64 bit and immediate. */
9280 and64 (sim_cpu
*cpu
, uint64_t bimm
)
9282 unsigned rn
= INSTR (9, 5);
9283 unsigned rd
= INSTR (4, 0);
9285 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9286 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9287 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) & bimm
);
9290 /* 32 bit and immediate set flags. */
9292 ands32 (sim_cpu
*cpu
, uint32_t bimm
)
9294 unsigned rn
= INSTR (9, 5);
9295 unsigned rd
= INSTR (4, 0);
9297 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9298 uint32_t value2
= bimm
;
9300 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9301 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9302 set_flags_for_binop32 (cpu
, value1
& value2
);
9305 /* 64 bit and immediate set flags. */
9307 ands64 (sim_cpu
*cpu
, uint64_t bimm
)
9309 unsigned rn
= INSTR (9, 5);
9310 unsigned rd
= INSTR (4, 0);
9312 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9313 uint64_t value2
= bimm
;
9315 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9316 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9317 set_flags_for_binop64 (cpu
, value1
& value2
);
9320 /* 32 bit exclusive or immediate. */
9322 eor32 (sim_cpu
*cpu
, uint32_t bimm
)
9324 unsigned rn
= INSTR (9, 5);
9325 unsigned rd
= INSTR (4, 0);
9327 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9328 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9329 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
) ^ bimm
);
9332 /* 64 bit exclusive or immediate. */
9334 eor64 (sim_cpu
*cpu
, uint64_t bimm
)
9336 unsigned rn
= INSTR (9, 5);
9337 unsigned rd
= INSTR (4, 0);
9339 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9340 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9341 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) ^ bimm
);
9344 /* 32 bit or immediate. */
9346 orr32 (sim_cpu
*cpu
, uint32_t bimm
)
9348 unsigned rn
= INSTR (9, 5);
9349 unsigned rd
= INSTR (4, 0);
9351 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9352 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9353 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
) | bimm
);
9356 /* 64 bit or immediate. */
9358 orr64 (sim_cpu
*cpu
, uint64_t bimm
)
9360 unsigned rn
= INSTR (9, 5);
9361 unsigned rd
= INSTR (4, 0);
9363 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9364 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9365 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) | bimm
);
9368 /* Logical shifted register.
9369 These allow an optional LSL, ASR, LSR or ROR to the second source
9370 register with a count up to the register bit count.
9371 N.B register args may not be SP. */
9373 /* 32 bit AND shifted register. */
9375 and32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9377 unsigned rm
= INSTR (20, 16);
9378 unsigned rn
= INSTR (9, 5);
9379 unsigned rd
= INSTR (4, 0);
9381 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9383 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9384 & shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9387 /* 64 bit AND shifted register. */
9389 and64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9391 unsigned rm
= INSTR (20, 16);
9392 unsigned rn
= INSTR (9, 5);
9393 unsigned rd
= INSTR (4, 0);
9395 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9397 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9398 & shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9401 /* 32 bit AND shifted register setting flags. */
9403 ands32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9405 unsigned rm
= INSTR (20, 16);
9406 unsigned rn
= INSTR (9, 5);
9407 unsigned rd
= INSTR (4, 0);
9409 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9410 uint32_t value2
= shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
9413 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9414 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9415 set_flags_for_binop32 (cpu
, value1
& value2
);
9418 /* 64 bit AND shifted register setting flags. */
9420 ands64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9422 unsigned rm
= INSTR (20, 16);
9423 unsigned rn
= INSTR (9, 5);
9424 unsigned rd
= INSTR (4, 0);
9426 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9427 uint64_t value2
= shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
9430 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9431 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9432 set_flags_for_binop64 (cpu
, value1
& value2
);
9435 /* 32 bit BIC shifted register. */
9437 bic32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9439 unsigned rm
= INSTR (20, 16);
9440 unsigned rn
= INSTR (9, 5);
9441 unsigned rd
= INSTR (4, 0);
9443 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9445 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9446 & ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9449 /* 64 bit BIC shifted register. */
9451 bic64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9453 unsigned rm
= INSTR (20, 16);
9454 unsigned rn
= INSTR (9, 5);
9455 unsigned rd
= INSTR (4, 0);
9457 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9459 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9460 & ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9463 /* 32 bit BIC shifted register setting flags. */
9465 bics32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9467 unsigned rm
= INSTR (20, 16);
9468 unsigned rn
= INSTR (9, 5);
9469 unsigned rd
= INSTR (4, 0);
9471 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9472 uint32_t value2
= ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
9475 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9476 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9477 set_flags_for_binop32 (cpu
, value1
& value2
);
9480 /* 64 bit BIC shifted register setting flags. */
9482 bics64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9484 unsigned rm
= INSTR (20, 16);
9485 unsigned rn
= INSTR (9, 5);
9486 unsigned rd
= INSTR (4, 0);
9488 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9489 uint64_t value2
= ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
9492 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9493 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9494 set_flags_for_binop64 (cpu
, value1
& value2
);
9497 /* 32 bit EON shifted register. */
9499 eon32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9501 unsigned rm
= INSTR (20, 16);
9502 unsigned rn
= INSTR (9, 5);
9503 unsigned rd
= INSTR (4, 0);
9505 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9507 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9508 ^ ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9511 /* 64 bit EON shifted register. */
9513 eon64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9515 unsigned rm
= INSTR (20, 16);
9516 unsigned rn
= INSTR (9, 5);
9517 unsigned rd
= INSTR (4, 0);
9519 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9521 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9522 ^ ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9525 /* 32 bit EOR shifted register. */
9527 eor32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9529 unsigned rm
= INSTR (20, 16);
9530 unsigned rn
= INSTR (9, 5);
9531 unsigned rd
= INSTR (4, 0);
9533 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9535 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9536 ^ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9539 /* 64 bit EOR shifted register. */
9541 eor64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9543 unsigned rm
= INSTR (20, 16);
9544 unsigned rn
= INSTR (9, 5);
9545 unsigned rd
= INSTR (4, 0);
9547 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9549 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9550 ^ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9553 /* 32 bit ORR shifted register. */
9555 orr32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9557 unsigned rm
= INSTR (20, 16);
9558 unsigned rn
= INSTR (9, 5);
9559 unsigned rd
= INSTR (4, 0);
9561 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9563 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9564 | shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9567 /* 64 bit ORR shifted register. */
9569 orr64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9571 unsigned rm
= INSTR (20, 16);
9572 unsigned rn
= INSTR (9, 5);
9573 unsigned rd
= INSTR (4, 0);
9575 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9577 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9578 | shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9581 /* 32 bit ORN shifted register. */
9583 orn32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9585 unsigned rm
= INSTR (20, 16);
9586 unsigned rn
= INSTR (9, 5);
9587 unsigned rd
= INSTR (4, 0);
9589 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9591 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9592 | ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9595 /* 64 bit ORN shifted register. */
9597 orn64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9599 unsigned rm
= INSTR (20, 16);
9600 unsigned rn
= INSTR (9, 5);
9601 unsigned rd
= INSTR (4, 0);
9603 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9605 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9606 | ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9610 dexLogicalImmediate (sim_cpu
*cpu
)
9612 /* assert instr[28,23] = 1001000
9613 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9614 instr[30,29] = op : 0 ==> AND, 1 ==> ORR, 2 ==> EOR, 3 ==> ANDS
9615 instr[22] = N : used to construct immediate mask
9621 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
9622 uint32_t size
= INSTR (31, 31);
9623 uint32_t N
= INSTR (22, 22);
9624 /* uint32_t immr = INSTR (21, 16);. */
9625 /* uint32_t imms = INSTR (15, 10);. */
9626 uint32_t index
= INSTR (22, 10);
9627 uint64_t bimm64
= LITable
[index
];
9628 uint32_t dispatch
= INSTR (30, 29);
9638 uint32_t bimm
= (uint32_t) bimm64
;
9642 case 0: and32 (cpu
, bimm
); return;
9643 case 1: orr32 (cpu
, bimm
); return;
9644 case 2: eor32 (cpu
, bimm
); return;
9645 case 3: ands32 (cpu
, bimm
); return;
9652 case 0: and64 (cpu
, bimm64
); return;
9653 case 1: orr64 (cpu
, bimm64
); return;
9654 case 2: eor64 (cpu
, bimm64
); return;
9655 case 3: ands64 (cpu
, bimm64
); return;
9662 The uimm argument is a 16 bit value to be inserted into the
9663 target register the pos argument locates the 16 bit word in the
9664 dest register i.e. it is in {0, 1} for 32 bit and {0, 1, 2,
9666 N.B register arg may not be SP so it should be.
9667 accessed using the setGZRegisterXXX accessors. */
9669 /* 32 bit move 16 bit immediate zero remaining shorts. */
9671 movz32 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9673 unsigned rd
= INSTR (4, 0);
9675 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9676 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val
<< (pos
* 16));
9679 /* 64 bit move 16 bit immediate zero remaining shorts. */
9681 movz64 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9683 unsigned rd
= INSTR (4, 0);
9685 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9686 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, ((uint64_t) val
) << (pos
* 16));
9689 /* 32 bit move 16 bit immediate negated. */
9691 movn32 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9693 unsigned rd
= INSTR (4, 0);
9695 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9696 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, ((val
<< (pos
* 16)) ^ 0xffffffffU
));
9699 /* 64 bit move 16 bit immediate negated. */
9701 movn64 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9703 unsigned rd
= INSTR (4, 0);
9705 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9707 (cpu
, rd
, NO_SP
, ((((uint64_t) val
) << (pos
* 16))
9708 ^ 0xffffffffffffffffULL
));
9711 /* 32 bit move 16 bit immediate keep remaining shorts. */
9713 movk32 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9715 unsigned rd
= INSTR (4, 0);
9716 uint32_t current
= aarch64_get_reg_u32 (cpu
, rd
, NO_SP
);
9717 uint32_t value
= val
<< (pos
* 16);
9718 uint32_t mask
= ~(0xffffU
<< (pos
* 16));
9720 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9721 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (value
| (current
& mask
)));
9724 /* 64 bit move 16 it immediate keep remaining shorts. */
9726 movk64 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9728 unsigned rd
= INSTR (4, 0);
9729 uint64_t current
= aarch64_get_reg_u64 (cpu
, rd
, NO_SP
);
9730 uint64_t value
= (uint64_t) val
<< (pos
* 16);
9731 uint64_t mask
= ~(0xffffULL
<< (pos
* 16));
9733 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9734 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (value
| (current
& mask
)));
9738 dexMoveWideImmediate (sim_cpu
*cpu
)
9740 /* assert instr[28:23] = 100101
9741 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9742 instr[30,29] = op : 0 ==> MOVN, 1 ==> UNALLOC, 2 ==> MOVZ, 3 ==> MOVK
9743 instr[22,21] = shift : 00 == LSL#0, 01 = LSL#16, 10 = LSL#32, 11 = LSL#48
9744 instr[20,5] = uimm16
9747 /* N.B. the (multiple of 16) shift is applied by the called routine,
9748 we just pass the multiplier. */
9751 uint32_t size
= INSTR (31, 31);
9752 uint32_t op
= INSTR (30, 29);
9753 uint32_t shift
= INSTR (22, 21);
9755 /* 32 bit can only shift 0 or 1 lot of 16.
9756 anything else is an unallocated instruction. */
9757 if (size
== 0 && (shift
> 1))
9763 imm
= INSTR (20, 5);
9768 movn32 (cpu
, imm
, shift
);
9770 movz32 (cpu
, imm
, shift
);
9772 movk32 (cpu
, imm
, shift
);
9777 movn64 (cpu
, imm
, shift
);
9779 movz64 (cpu
, imm
, shift
);
9781 movk64 (cpu
, imm
, shift
);
9785 /* Bitfield operations.
9786 These take a pair of bit positions r and s which are in {0..31}
9787 or {0..63} depending on the instruction word size.
9788 N.B register args may not be SP. */
9790 /* OK, we start with ubfm which just needs to pick
9791 some bits out of source zero the rest and write
9792 the result to dest. Just need two logical shifts. */
9794 /* 32 bit bitfield move, left and right of affected zeroed
9795 if r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
9797 ubfm32 (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9800 unsigned rn
= INSTR (9, 5);
9801 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9803 /* Pick either s+1-r or s+1 consecutive bits out of the original word. */
9806 /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
9807 We want only bits s:xxx:r at the bottom of the word
9808 so we LSL bit s up to bit 31 i.e. by 31 - s
9809 and then we LSR to bring bit 31 down to bit s - r
9810 i.e. by 31 + r - s. */
9812 value
>>= 31 + r
- s
;
9816 /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0
9817 We want only bits s:xxx:0 starting at it 31-(r-1)
9818 so we LSL bit s up to bit 31 i.e. by 31 - s
9819 and then we LSL to bring bit 31 down to 31-(r-1)+s
9820 i.e. by r - (s + 1). */
9822 value
>>= r
- (s
+ 1);
9825 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9827 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
9830 /* 64 bit bitfield move, left and right of affected zeroed
9831 if r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
9833 ubfm (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9836 unsigned rn
= INSTR (9, 5);
9837 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9841 /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
9842 We want only bits s:xxx:r at the bottom of the word.
9843 So we LSL bit s up to bit 63 i.e. by 63 - s
9844 and then we LSR to bring bit 63 down to bit s - r
9845 i.e. by 63 + r - s. */
9847 value
>>= 63 + r
- s
;
9851 /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0.
9852 We want only bits s:xxx:0 starting at it 63-(r-1).
9853 So we LSL bit s up to bit 63 i.e. by 63 - s
9854 and then we LSL to bring bit 63 down to 63-(r-1)+s
9855 i.e. by r - (s + 1). */
9857 value
>>= r
- (s
+ 1);
9860 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9862 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
9865 /* The signed versions need to insert sign bits
9866 on the left of the inserted bit field. so we do
9867 much the same as the unsigned version except we
9868 use an arithmetic shift right -- this just means
9869 we need to operate on signed values. */
9871 /* 32 bit bitfield move, left of affected sign-extended, right zeroed. */
9872 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
9874 sbfm32 (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9877 unsigned rn
= INSTR (9, 5);
9878 /* as per ubfm32 but use an ASR instead of an LSR. */
9879 int32_t value
= aarch64_get_reg_s32 (cpu
, rn
, NO_SP
);
9884 value
>>= 31 + r
- s
;
9889 value
>>= r
- (s
+ 1);
9892 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9894 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) value
);
9897 /* 64 bit bitfield move, left of affected sign-extended, right zeroed. */
9898 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
9900 sbfm (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9903 unsigned rn
= INSTR (9, 5);
9904 /* acpu per ubfm but use an ASR instead of an LSR. */
9905 int64_t value
= aarch64_get_reg_s64 (cpu
, rn
, NO_SP
);
9910 value
>>= 63 + r
- s
;
9915 value
>>= r
- (s
+ 1);
9918 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9920 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, value
);
9923 /* Finally, these versions leave non-affected bits
9924 as is. so we need to generate the bits as per
9925 ubfm and also generate a mask to pick the
9926 bits from the original and computed values. */
9928 /* 32 bit bitfield move, non-affected bits left as is.
9929 If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
9931 bfm32 (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9933 unsigned rn
= INSTR (9, 5);
9934 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9939 /* Pick either s+1-r or s+1 consecutive bits out of the original word. */
9942 /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
9943 We want only bits s:xxx:r at the bottom of the word
9944 so we LSL bit s up to bit 31 i.e. by 31 - s
9945 and then we LSR to bring bit 31 down to bit s - r
9946 i.e. by 31 + r - s. */
9948 value
>>= 31 + r
- s
;
9949 /* the mask must include the same bits. */
9951 mask
>>= 31 + r
- s
;
9955 /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0.
9956 We want only bits s:xxx:0 starting at it 31-(r-1)
9957 so we LSL bit s up to bit 31 i.e. by 31 - s
9958 and then we LSL to bring bit 31 down to 31-(r-1)+s
9959 i.e. by r - (s + 1). */
9961 value
>>= r
- (s
+ 1);
9962 /* The mask must include the same bits. */
9964 mask
>>= r
- (s
+ 1);
9968 value2
= aarch64_get_reg_u32 (cpu
, rd
, NO_SP
);
9973 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9975 (cpu
, rd
, NO_SP
, (aarch64_get_reg_u32 (cpu
, rd
, NO_SP
) & ~mask
) | value
);
9978 /* 64 bit bitfield move, non-affected bits left as is.
9979 If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
9981 bfm (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9984 unsigned rn
= INSTR (9, 5);
9985 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9986 uint64_t mask
= 0xffffffffffffffffULL
;
9990 /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
9991 We want only bits s:xxx:r at the bottom of the word
9992 so we LSL bit s up to bit 63 i.e. by 63 - s
9993 and then we LSR to bring bit 63 down to bit s - r
9994 i.e. by 63 + r - s. */
9996 value
>>= 63 + r
- s
;
9997 /* The mask must include the same bits. */
9999 mask
>>= 63 + r
- s
;
10003 /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0
10004 We want only bits s:xxx:0 starting at it 63-(r-1)
10005 so we LSL bit s up to bit 63 i.e. by 63 - s
10006 and then we LSL to bring bit 63 down to 63-(r-1)+s
10007 i.e. by r - (s + 1). */
10009 value
>>= r
- (s
+ 1);
10010 /* The mask must include the same bits. */
10012 mask
>>= r
- (s
+ 1);
10015 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10017 aarch64_set_reg_u64
10018 (cpu
, rd
, NO_SP
, (aarch64_get_reg_u64 (cpu
, rd
, NO_SP
) & ~mask
) | value
);
10022 dexBitfieldImmediate (sim_cpu
*cpu
)
10024 /* assert instr[28:23] = 100110
10025 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
10026 instr[30,29] = op : 0 ==> SBFM, 1 ==> BFM, 2 ==> UBFM, 3 ==> UNALLOC
10027 instr[22] = N : must be 0 for 32 bit, 1 for 64 bit ow UNALLOC
10028 instr[21,16] = immr : 0xxxxx for 32 bit, xxxxxx for 64 bit
10029 instr[15,10] = imms : 0xxxxx for 32 bit, xxxxxx for 64 bit
10033 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
10036 uint32_t size
= INSTR (31, 31);
10037 uint32_t N
= INSTR (22, 22);
10038 /* 32 bit operations must have immr[5] = 0 and imms[5] = 0. */
10039 /* or else we have an UNALLOC. */
10040 uint32_t immr
= INSTR (21, 16);
10045 if (!size
&& uimm (immr
, 5, 5))
10048 imms
= INSTR (15, 10);
10049 if (!size
&& uimm (imms
, 5, 5))
10052 /* Switch on combined size and op. */
10053 dispatch
= INSTR (31, 29);
10056 case 0: sbfm32 (cpu
, immr
, imms
); return;
10057 case 1: bfm32 (cpu
, immr
, imms
); return;
10058 case 2: ubfm32 (cpu
, immr
, imms
); return;
10059 case 4: sbfm (cpu
, immr
, imms
); return;
10060 case 5: bfm (cpu
, immr
, imms
); return;
10061 case 6: ubfm (cpu
, immr
, imms
); return;
10062 default: HALT_UNALLOC
;
10067 do_EXTR_32 (sim_cpu
*cpu
)
10069 /* instr[31:21] = 00010011100
10071 instr[15,10] = imms : 0xxxxx for 32 bit
10074 unsigned rm
= INSTR (20, 16);
10075 unsigned imms
= INSTR (15, 10) & 31;
10076 unsigned rn
= INSTR ( 9, 5);
10077 unsigned rd
= INSTR ( 4, 0);
10081 val1
= aarch64_get_reg_u32 (cpu
, rm
, NO_SP
);
10083 val2
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
10084 val2
<<= (32 - imms
);
10086 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10087 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val1
| val2
);
10091 do_EXTR_64 (sim_cpu
*cpu
)
10093 /* instr[31:21] = 10010011100
10095 instr[15,10] = imms
10098 unsigned rm
= INSTR (20, 16);
10099 unsigned imms
= INSTR (15, 10) & 63;
10100 unsigned rn
= INSTR ( 9, 5);
10101 unsigned rd
= INSTR ( 4, 0);
10104 val
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
10106 val
|= (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) << (64 - imms
));
10108 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val
);
10112 dexExtractImmediate (sim_cpu
*cpu
)
10114 /* assert instr[28:23] = 100111
10115 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
10116 instr[30,29] = op21 : 0 ==> EXTR, 1,2,3 ==> UNALLOC
10117 instr[22] = N : must be 0 for 32 bit, 1 for 64 bit or UNALLOC
10118 instr[21] = op0 : must be 0 or UNALLOC
10120 instr[15,10] = imms : 0xxxxx for 32 bit, xxxxxx for 64 bit
10124 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
10125 /* 64 bit operations must have N = 1 or else we have an UNALLOC. */
10127 uint32_t size
= INSTR (31, 31);
10128 uint32_t N
= INSTR (22, 22);
10129 /* 32 bit operations must have imms[5] = 0
10130 or else we have an UNALLOC. */
10131 uint32_t imms
= INSTR (15, 10);
10136 if (!size
&& uimm (imms
, 5, 5))
10139 /* Switch on combined size and op. */
10140 dispatch
= INSTR (31, 29);
10145 else if (dispatch
== 4)
10148 else if (dispatch
== 1)
10155 dexDPImm (sim_cpu
*cpu
)
10157 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
10158 assert group == GROUP_DPIMM_1000 || grpoup == GROUP_DPIMM_1001
10159 bits [25,23] of a DPImm are the secondary dispatch vector. */
10160 uint32_t group2
= dispatchDPImm (aarch64_get_instr (cpu
));
10164 case DPIMM_PCADR_000
:
10165 case DPIMM_PCADR_001
:
10166 dexPCRelAddressing (cpu
);
10169 case DPIMM_ADDSUB_010
:
10170 case DPIMM_ADDSUB_011
:
10171 dexAddSubtractImmediate (cpu
);
10174 case DPIMM_LOG_100
:
10175 dexLogicalImmediate (cpu
);
10178 case DPIMM_MOV_101
:
10179 dexMoveWideImmediate (cpu
);
10182 case DPIMM_BITF_110
:
10183 dexBitfieldImmediate (cpu
);
10186 case DPIMM_EXTR_111
:
10187 dexExtractImmediate (cpu
);
10191 /* Should never reach here. */
10197 dexLoadUnscaledImmediate (sim_cpu
*cpu
)
10199 /* instr[29,24] == 111_00
10202 instr[31,30] = size
10205 instr[20,12] = simm9
10206 instr[9,5] = rn may be SP. */
10207 /* unsigned rt = INSTR (4, 0); */
10208 uint32_t V
= INSTR (26, 26);
10209 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
10210 int32_t imm
= simm32 (aarch64_get_instr (cpu
), 20, 12);
10214 /* GReg operations. */
10217 case 0: sturb (cpu
, imm
); return;
10218 case 1: ldurb32 (cpu
, imm
); return;
10219 case 2: ldursb64 (cpu
, imm
); return;
10220 case 3: ldursb32 (cpu
, imm
); return;
10221 case 4: sturh (cpu
, imm
); return;
10222 case 5: ldurh32 (cpu
, imm
); return;
10223 case 6: ldursh64 (cpu
, imm
); return;
10224 case 7: ldursh32 (cpu
, imm
); return;
10225 case 8: stur32 (cpu
, imm
); return;
10226 case 9: ldur32 (cpu
, imm
); return;
10227 case 10: ldursw (cpu
, imm
); return;
10228 case 12: stur64 (cpu
, imm
); return;
10229 case 13: ldur64 (cpu
, imm
); return;
10242 /* FReg operations. */
10245 case 2: fsturq (cpu
, imm
); return;
10246 case 3: fldurq (cpu
, imm
); return;
10247 case 8: fsturs (cpu
, imm
); return;
10248 case 9: fldurs (cpu
, imm
); return;
10249 case 12: fsturd (cpu
, imm
); return;
10250 case 13: fldurd (cpu
, imm
); return;
10252 case 0: /* STUR 8 bit FP. */
10253 case 1: /* LDUR 8 bit FP. */
10254 case 4: /* STUR 16 bit FP. */
10255 case 5: /* LDUR 8 bit FP. */
10269 /* N.B. A preliminary note regarding all the ldrs<x>32
10272 The signed value loaded by these instructions is cast to unsigned
10273 before being assigned to aarch64_get_reg_u64 (cpu, N) i.e. to the
10274 64 bit element of the GReg union. this performs a 32 bit sign extension
10275 (as required) but avoids 64 bit sign extension, thus ensuring that the
10276 top half of the register word is zero. this is what the spec demands
10277 when a 32 bit load occurs. */
10279 /* 32 bit load sign-extended byte scaled unsigned 12 bit. */
10281 ldrsb32_abs (sim_cpu
*cpu
, uint32_t offset
)
10283 unsigned int rn
= INSTR (9, 5);
10284 unsigned int rt
= INSTR (4, 0);
10286 /* The target register may not be SP but the source may be
10287 there is no scaling required for a byte load. */
10288 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
;
10289 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
10290 (int64_t) aarch64_get_mem_s8 (cpu
, address
));
10293 /* 32 bit load sign-extended byte scaled or unscaled zero-
10294 or sign-extended 32-bit register offset. */
10296 ldrsb32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10298 unsigned int rm
= INSTR (20, 16);
10299 unsigned int rn
= INSTR (9, 5);
10300 unsigned int rt
= INSTR (4, 0);
10302 /* rn may reference SP, rm and rt must reference ZR. */
10304 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10305 int64_t displacement
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10308 /* There is no scaling required for a byte load. */
10309 aarch64_set_reg_u64
10310 (cpu
, rt
, NO_SP
, (int64_t) aarch64_get_mem_s8 (cpu
, address
10314 /* 32 bit load sign-extended byte unscaled signed 9 bit with
10315 pre- or post-writeback. */
10317 ldrsb32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10320 unsigned int rn
= INSTR (9, 5);
10321 unsigned int rt
= INSTR (4, 0);
10323 if (rn
== rt
&& wb
!= NoWriteBack
)
10326 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10331 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
10332 (int64_t) aarch64_get_mem_s8 (cpu
, address
));
10337 if (wb
!= NoWriteBack
)
10338 aarch64_set_reg_u64 (cpu
, rn
, NO_SP
, address
);
10341 /* 8 bit store scaled. */
10343 fstrb_abs (sim_cpu
*cpu
, uint32_t offset
)
10345 unsigned st
= INSTR (4, 0);
10346 unsigned rn
= INSTR (9, 5);
10348 aarch64_set_mem_u8 (cpu
,
10349 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
10350 aarch64_get_vec_u8 (cpu
, st
, 0));
10353 /* 8 bit store scaled or unscaled zero- or
10354 sign-extended 8-bit register offset. */
10356 fstrb_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10358 unsigned rm
= INSTR (20, 16);
10359 unsigned rn
= INSTR (9, 5);
10360 unsigned st
= INSTR (4, 0);
10362 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10363 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10365 uint64_t displacement
= scaling
== Scaled
? extended
: 0;
10368 (cpu
, address
+ displacement
, aarch64_get_vec_u8 (cpu
, st
, 0));
10371 /* 16 bit store scaled. */
10373 fstrh_abs (sim_cpu
*cpu
, uint32_t offset
)
10375 unsigned st
= INSTR (4, 0);
10376 unsigned rn
= INSTR (9, 5);
10378 aarch64_set_mem_u16
10380 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 16),
10381 aarch64_get_vec_u16 (cpu
, st
, 0));
10384 /* 16 bit store scaled or unscaled zero-
10385 or sign-extended 16-bit register offset. */
10387 fstrh_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10389 unsigned rm
= INSTR (20, 16);
10390 unsigned rn
= INSTR (9, 5);
10391 unsigned st
= INSTR (4, 0);
10393 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10394 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10396 uint64_t displacement
= OPT_SCALE (extended
, 16, scaling
);
10398 aarch64_set_mem_u16
10399 (cpu
, address
+ displacement
, aarch64_get_vec_u16 (cpu
, st
, 0));
10402 /* 32 bit store scaled unsigned 12 bit. */
10404 fstrs_abs (sim_cpu
*cpu
, uint32_t offset
)
10406 unsigned st
= INSTR (4, 0);
10407 unsigned rn
= INSTR (9, 5);
10409 aarch64_set_mem_u32
10411 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 32),
10412 aarch64_get_vec_u32 (cpu
, st
, 0));
10415 /* 32 bit store unscaled signed 9 bit with pre- or post-writeback. */
10417 fstrs_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10419 unsigned rn
= INSTR (9, 5);
10420 unsigned st
= INSTR (4, 0);
10422 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10427 aarch64_set_mem_u32 (cpu
, address
, aarch64_get_vec_u32 (cpu
, st
, 0));
10432 if (wb
!= NoWriteBack
)
10433 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
10436 /* 32 bit store scaled or unscaled zero-
10437 or sign-extended 32-bit register offset. */
10439 fstrs_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10441 unsigned rm
= INSTR (20, 16);
10442 unsigned rn
= INSTR (9, 5);
10443 unsigned st
= INSTR (4, 0);
10445 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10446 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10448 uint64_t displacement
= OPT_SCALE (extended
, 32, scaling
);
10450 aarch64_set_mem_u32
10451 (cpu
, address
+ displacement
, aarch64_get_vec_u32 (cpu
, st
, 0));
10454 /* 64 bit store scaled unsigned 12 bit. */
10456 fstrd_abs (sim_cpu
*cpu
, uint32_t offset
)
10458 unsigned st
= INSTR (4, 0);
10459 unsigned rn
= INSTR (9, 5);
10461 aarch64_set_mem_u64
10463 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 64),
10464 aarch64_get_vec_u64 (cpu
, st
, 0));
10467 /* 64 bit store unscaled signed 9 bit with pre- or post-writeback. */
10469 fstrd_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10471 unsigned rn
= INSTR (9, 5);
10472 unsigned st
= INSTR (4, 0);
10474 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10479 aarch64_set_mem_u64 (cpu
, address
, aarch64_get_vec_u64 (cpu
, st
, 0));
10484 if (wb
!= NoWriteBack
)
10485 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
10488 /* 64 bit store scaled or unscaled zero-
10489 or sign-extended 32-bit register offset. */
10491 fstrd_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10493 unsigned rm
= INSTR (20, 16);
10494 unsigned rn
= INSTR (9, 5);
10495 unsigned st
= INSTR (4, 0);
10497 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10498 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10500 uint64_t displacement
= OPT_SCALE (extended
, 64, scaling
);
10502 aarch64_set_mem_u64
10503 (cpu
, address
+ displacement
, aarch64_get_vec_u64 (cpu
, st
, 0));
10506 /* 128 bit store scaled unsigned 12 bit. */
10508 fstrq_abs (sim_cpu
*cpu
, uint32_t offset
)
10511 unsigned st
= INSTR (4, 0);
10512 unsigned rn
= INSTR (9, 5);
10515 aarch64_get_FP_long_double (cpu
, st
, & a
);
10517 addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 128);
10518 aarch64_set_mem_long_double (cpu
, addr
, a
);
10521 /* 128 bit store unscaled signed 9 bit with pre- or post-writeback. */
10523 fstrq_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10526 unsigned rn
= INSTR (9, 5);
10527 unsigned st
= INSTR (4, 0);
10528 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10533 aarch64_get_FP_long_double (cpu
, st
, & a
);
10534 aarch64_set_mem_long_double (cpu
, address
, a
);
10539 if (wb
!= NoWriteBack
)
10540 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
10543 /* 128 bit store scaled or unscaled zero-
10544 or sign-extended 32-bit register offset. */
10546 fstrq_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10548 unsigned rm
= INSTR (20, 16);
10549 unsigned rn
= INSTR (9, 5);
10550 unsigned st
= INSTR (4, 0);
10552 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10553 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10555 uint64_t displacement
= OPT_SCALE (extended
, 128, scaling
);
10559 aarch64_get_FP_long_double (cpu
, st
, & a
);
10560 aarch64_set_mem_long_double (cpu
, address
+ displacement
, a
);
10564 dexLoadImmediatePrePost (sim_cpu
*cpu
)
10566 /* instr[31,30] = size
10572 instr[20,12] = simm9
10573 instr[11] = wb : 0 ==> Post, 1 ==> Pre
10575 instr[9,5] = Rn may be SP.
10578 uint32_t V
= INSTR (26, 26);
10579 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
10580 int32_t imm
= simm32 (aarch64_get_instr (cpu
), 20, 12);
10581 WriteBack wb
= INSTR (11, 11);
10585 /* GReg operations. */
10588 case 0: strb_wb (cpu
, imm
, wb
); return;
10589 case 1: ldrb32_wb (cpu
, imm
, wb
); return;
10590 case 2: ldrsb_wb (cpu
, imm
, wb
); return;
10591 case 3: ldrsb32_wb (cpu
, imm
, wb
); return;
10592 case 4: strh_wb (cpu
, imm
, wb
); return;
10593 case 5: ldrh32_wb (cpu
, imm
, wb
); return;
10594 case 6: ldrsh64_wb (cpu
, imm
, wb
); return;
10595 case 7: ldrsh32_wb (cpu
, imm
, wb
); return;
10596 case 8: str32_wb (cpu
, imm
, wb
); return;
10597 case 9: ldr32_wb (cpu
, imm
, wb
); return;
10598 case 10: ldrsw_wb (cpu
, imm
, wb
); return;
10599 case 12: str_wb (cpu
, imm
, wb
); return;
10600 case 13: ldr_wb (cpu
, imm
, wb
); return;
10610 /* FReg operations. */
10613 case 2: fstrq_wb (cpu
, imm
, wb
); return;
10614 case 3: fldrq_wb (cpu
, imm
, wb
); return;
10615 case 8: fstrs_wb (cpu
, imm
, wb
); return;
10616 case 9: fldrs_wb (cpu
, imm
, wb
); return;
10617 case 12: fstrd_wb (cpu
, imm
, wb
); return;
10618 case 13: fldrd_wb (cpu
, imm
, wb
); return;
10620 case 0: /* STUR 8 bit FP. */
10621 case 1: /* LDUR 8 bit FP. */
10622 case 4: /* STUR 16 bit FP. */
10623 case 5: /* LDUR 8 bit FP. */
10638 dexLoadRegisterOffset (sim_cpu
*cpu
)
10640 /* instr[31,30] = size
10647 instr[15,13] = option : 010 ==> UXTW, 011 ==> UXTX/LSL,
10648 110 ==> SXTW, 111 ==> SXTX,
10653 instr[4,0] = rt. */
10655 uint32_t V
= INSTR (26, 26);
10656 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
10657 Scaling scale
= INSTR (12, 12);
10658 Extension extensionType
= INSTR (15, 13);
10660 /* Check for illegal extension types. */
10661 if (uimm (extensionType
, 1, 1) == 0)
10664 if (extensionType
== UXTX
|| extensionType
== SXTX
)
10665 extensionType
= NoExtension
;
10669 /* GReg operations. */
10672 case 0: strb_scale_ext (cpu
, scale
, extensionType
); return;
10673 case 1: ldrb32_scale_ext (cpu
, scale
, extensionType
); return;
10674 case 2: ldrsb_scale_ext (cpu
, scale
, extensionType
); return;
10675 case 3: ldrsb32_scale_ext (cpu
, scale
, extensionType
); return;
10676 case 4: strh_scale_ext (cpu
, scale
, extensionType
); return;
10677 case 5: ldrh32_scale_ext (cpu
, scale
, extensionType
); return;
10678 case 6: ldrsh_scale_ext (cpu
, scale
, extensionType
); return;
10679 case 7: ldrsh32_scale_ext (cpu
, scale
, extensionType
); return;
10680 case 8: str32_scale_ext (cpu
, scale
, extensionType
); return;
10681 case 9: ldr32_scale_ext (cpu
, scale
, extensionType
); return;
10682 case 10: ldrsw_scale_ext (cpu
, scale
, extensionType
); return;
10683 case 12: str_scale_ext (cpu
, scale
, extensionType
); return;
10684 case 13: ldr_scale_ext (cpu
, scale
, extensionType
); return;
10685 case 14: prfm_scale_ext (cpu
, scale
, extensionType
); return;
10694 /* FReg operations. */
10697 case 1: /* LDUR 8 bit FP. */
10699 case 3: fldrq_scale_ext (cpu
, scale
, extensionType
); return;
10700 case 5: /* LDUR 8 bit FP. */
10702 case 9: fldrs_scale_ext (cpu
, scale
, extensionType
); return;
10703 case 13: fldrd_scale_ext (cpu
, scale
, extensionType
); return;
10705 case 0: fstrb_scale_ext (cpu
, scale
, extensionType
); return;
10706 case 2: fstrq_scale_ext (cpu
, scale
, extensionType
); return;
10707 case 4: fstrh_scale_ext (cpu
, scale
, extensionType
); return;
10708 case 8: fstrs_scale_ext (cpu
, scale
, extensionType
); return;
10709 case 12: fstrd_scale_ext (cpu
, scale
, extensionType
); return;
10723 dexLoadUnsignedImmediate (sim_cpu
*cpu
)
10725 /* instr[29,24] == 111_01
10726 instr[31,30] = size
10729 instr[21,10] = uimm12 : unsigned immediate offset
10730 instr[9,5] = rn may be SP.
10731 instr[4,0] = rt. */
10733 uint32_t V
= INSTR (26,26);
10734 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
10735 uint32_t imm
= INSTR (21, 10);
10739 /* GReg operations. */
10742 case 0: strb_abs (cpu
, imm
); return;
10743 case 1: ldrb32_abs (cpu
, imm
); return;
10744 case 2: ldrsb_abs (cpu
, imm
); return;
10745 case 3: ldrsb32_abs (cpu
, imm
); return;
10746 case 4: strh_abs (cpu
, imm
); return;
10747 case 5: ldrh32_abs (cpu
, imm
); return;
10748 case 6: ldrsh_abs (cpu
, imm
); return;
10749 case 7: ldrsh32_abs (cpu
, imm
); return;
10750 case 8: str32_abs (cpu
, imm
); return;
10751 case 9: ldr32_abs (cpu
, imm
); return;
10752 case 10: ldrsw_abs (cpu
, imm
); return;
10753 case 12: str_abs (cpu
, imm
); return;
10754 case 13: ldr_abs (cpu
, imm
); return;
10755 case 14: prfm_abs (cpu
, imm
); return;
10764 /* FReg operations. */
10767 case 0: fstrb_abs (cpu
, imm
); return;
10768 case 4: fstrh_abs (cpu
, imm
); return;
10769 case 8: fstrs_abs (cpu
, imm
); return;
10770 case 12: fstrd_abs (cpu
, imm
); return;
10771 case 2: fstrq_abs (cpu
, imm
); return;
10773 case 1: fldrb_abs (cpu
, imm
); return;
10774 case 5: fldrh_abs (cpu
, imm
); return;
10775 case 9: fldrs_abs (cpu
, imm
); return;
10776 case 13: fldrd_abs (cpu
, imm
); return;
10777 case 3: fldrq_abs (cpu
, imm
); return;
10791 dexLoadExclusive (sim_cpu
*cpu
)
10793 /* assert instr[29:24] = 001000;
10794 instr[31,30] = size
10795 instr[23] = 0 if exclusive
10796 instr[22] = L : 1 if load, 0 if store
10797 instr[21] = 1 if pair
10799 instr[15] = o0 : 1 if ordered
10802 instr[4.0] = Rt. */
10804 switch (INSTR (22, 21))
10806 case 2: ldxr (cpu
); return;
10807 case 0: stxr (cpu
); return;
10813 dexLoadOther (sim_cpu
*cpu
)
10817 /* instr[29,25] = 111_0
10818 instr[24] == 0 ==> dispatch, 1 ==> ldst reg unsigned immediate
10819 instr[21:11,10] is the secondary dispatch. */
10820 if (INSTR (24, 24))
10822 dexLoadUnsignedImmediate (cpu
);
10826 dispatch
= ((INSTR (21, 21) << 2) | INSTR (11, 10));
10829 case 0: dexLoadUnscaledImmediate (cpu
); return;
10830 case 1: dexLoadImmediatePrePost (cpu
); return;
10831 case 3: dexLoadImmediatePrePost (cpu
); return;
10832 case 6: dexLoadRegisterOffset (cpu
); return;
10844 store_pair_u32 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10846 unsigned rn
= INSTR (14, 10);
10847 unsigned rd
= INSTR (9, 5);
10848 unsigned rm
= INSTR (4, 0);
10849 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10851 if ((rn
== rd
|| rm
== rd
) && wb
!= NoWriteBack
)
10852 HALT_UNALLOC
; /* ??? */
10859 aarch64_set_mem_u32 (cpu
, address
,
10860 aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
10861 aarch64_set_mem_u32 (cpu
, address
+ 4,
10862 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
));
10867 if (wb
!= NoWriteBack
)
10868 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10872 store_pair_u64 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10874 unsigned rn
= INSTR (14, 10);
10875 unsigned rd
= INSTR (9, 5);
10876 unsigned rm
= INSTR (4, 0);
10877 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10879 if ((rn
== rd
|| rm
== rd
) && wb
!= NoWriteBack
)
10880 HALT_UNALLOC
; /* ??? */
10887 aarch64_set_mem_u64 (cpu
, address
,
10888 aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
10889 aarch64_set_mem_u64 (cpu
, address
+ 8,
10890 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
10895 if (wb
!= NoWriteBack
)
10896 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10900 load_pair_u32 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10902 unsigned rn
= INSTR (14, 10);
10903 unsigned rd
= INSTR (9, 5);
10904 unsigned rm
= INSTR (4, 0);
10905 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10907 /* Treat this as unalloc to make sure we don't do it. */
10916 aarch64_set_reg_u64 (cpu
, rm
, SP_OK
, aarch64_get_mem_u32 (cpu
, address
));
10917 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, aarch64_get_mem_u32 (cpu
, address
+ 4));
10922 if (wb
!= NoWriteBack
)
10923 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10927 load_pair_s32 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10929 unsigned rn
= INSTR (14, 10);
10930 unsigned rd
= INSTR (9, 5);
10931 unsigned rm
= INSTR (4, 0);
10932 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10934 /* Treat this as unalloc to make sure we don't do it. */
10943 aarch64_set_reg_s64 (cpu
, rm
, SP_OK
, aarch64_get_mem_s32 (cpu
, address
));
10944 aarch64_set_reg_s64 (cpu
, rn
, SP_OK
, aarch64_get_mem_s32 (cpu
, address
+ 4));
10949 if (wb
!= NoWriteBack
)
10950 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10954 load_pair_u64 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10956 unsigned rn
= INSTR (14, 10);
10957 unsigned rd
= INSTR (9, 5);
10958 unsigned rm
= INSTR (4, 0);
10959 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10961 /* Treat this as unalloc to make sure we don't do it. */
10970 aarch64_set_reg_u64 (cpu
, rm
, SP_OK
, aarch64_get_mem_u64 (cpu
, address
));
10971 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, aarch64_get_mem_u64 (cpu
, address
+ 8));
10976 if (wb
!= NoWriteBack
)
10977 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10981 dex_load_store_pair_gr (sim_cpu
*cpu
)
10983 /* instr[31,30] = size (10=> 64-bit, 01=> signed 32-bit, 00=> 32-bit)
10984 instr[29,25] = instruction encoding: 101_0
10985 instr[26] = V : 1 if fp 0 if gp
10986 instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
10987 instr[22] = load/store (1=> load)
10988 instr[21,15] = signed, scaled, offset
10991 instr[ 4, 0] = Rm. */
10993 uint32_t dispatch
= ((INSTR (31, 30) << 3) | INSTR (24, 22));
10994 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 21, 15);
10998 case 2: store_pair_u32 (cpu
, offset
, Post
); return;
10999 case 3: load_pair_u32 (cpu
, offset
, Post
); return;
11000 case 4: store_pair_u32 (cpu
, offset
, NoWriteBack
); return;
11001 case 5: load_pair_u32 (cpu
, offset
, NoWriteBack
); return;
11002 case 6: store_pair_u32 (cpu
, offset
, Pre
); return;
11003 case 7: load_pair_u32 (cpu
, offset
, Pre
); return;
11005 case 11: load_pair_s32 (cpu
, offset
, Post
); return;
11006 case 13: load_pair_s32 (cpu
, offset
, NoWriteBack
); return;
11007 case 15: load_pair_s32 (cpu
, offset
, Pre
); return;
11009 case 18: store_pair_u64 (cpu
, offset
, Post
); return;
11010 case 19: load_pair_u64 (cpu
, offset
, Post
); return;
11011 case 20: store_pair_u64 (cpu
, offset
, NoWriteBack
); return;
11012 case 21: load_pair_u64 (cpu
, offset
, NoWriteBack
); return;
11013 case 22: store_pair_u64 (cpu
, offset
, Pre
); return;
11014 case 23: load_pair_u64 (cpu
, offset
, Pre
); return;
11022 store_pair_float (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11024 unsigned rn
= INSTR (14, 10);
11025 unsigned rd
= INSTR (9, 5);
11026 unsigned rm
= INSTR (4, 0);
11027 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11034 aarch64_set_mem_u32 (cpu
, address
, aarch64_get_vec_u32 (cpu
, rm
, 0));
11035 aarch64_set_mem_u32 (cpu
, address
+ 4, aarch64_get_vec_u32 (cpu
, rn
, 0));
11040 if (wb
!= NoWriteBack
)
11041 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11045 store_pair_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11047 unsigned rn
= INSTR (14, 10);
11048 unsigned rd
= INSTR (9, 5);
11049 unsigned rm
= INSTR (4, 0);
11050 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11057 aarch64_set_mem_u64 (cpu
, address
, aarch64_get_vec_u64 (cpu
, rm
, 0));
11058 aarch64_set_mem_u64 (cpu
, address
+ 8, aarch64_get_vec_u64 (cpu
, rn
, 0));
11063 if (wb
!= NoWriteBack
)
11064 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11068 store_pair_long_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11071 unsigned rn
= INSTR (14, 10);
11072 unsigned rd
= INSTR (9, 5);
11073 unsigned rm
= INSTR (4, 0);
11074 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11081 aarch64_get_FP_long_double (cpu
, rm
, & a
);
11082 aarch64_set_mem_long_double (cpu
, address
, a
);
11083 aarch64_get_FP_long_double (cpu
, rn
, & a
);
11084 aarch64_set_mem_long_double (cpu
, address
+ 16, a
);
11089 if (wb
!= NoWriteBack
)
11090 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11094 load_pair_float (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11096 unsigned rn
= INSTR (14, 10);
11097 unsigned rd
= INSTR (9, 5);
11098 unsigned rm
= INSTR (4, 0);
11099 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11109 aarch64_set_vec_u32 (cpu
, rm
, 0, aarch64_get_mem_u32 (cpu
, address
));
11110 aarch64_set_vec_u32 (cpu
, rn
, 0, aarch64_get_mem_u32 (cpu
, address
+ 4));
11115 if (wb
!= NoWriteBack
)
11116 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11120 load_pair_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11122 unsigned rn
= INSTR (14, 10);
11123 unsigned rd
= INSTR (9, 5);
11124 unsigned rm
= INSTR (4, 0);
11125 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11135 aarch64_set_vec_u64 (cpu
, rm
, 0, aarch64_get_mem_u64 (cpu
, address
));
11136 aarch64_set_vec_u64 (cpu
, rn
, 0, aarch64_get_mem_u64 (cpu
, address
+ 8));
11141 if (wb
!= NoWriteBack
)
11142 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11146 load_pair_long_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11149 unsigned rn
= INSTR (14, 10);
11150 unsigned rd
= INSTR (9, 5);
11151 unsigned rm
= INSTR (4, 0);
11152 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11162 aarch64_get_mem_long_double (cpu
, address
, & a
);
11163 aarch64_set_FP_long_double (cpu
, rm
, a
);
11164 aarch64_get_mem_long_double (cpu
, address
+ 16, & a
);
11165 aarch64_set_FP_long_double (cpu
, rn
, a
);
11170 if (wb
!= NoWriteBack
)
11171 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11175 dex_load_store_pair_fp (sim_cpu
*cpu
)
11177 /* instr[31,30] = size (10=> 128-bit, 01=> 64-bit, 00=> 32-bit)
11178 instr[29,25] = instruction encoding
11179 instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
11180 instr[22] = load/store (1=> load)
11181 instr[21,15] = signed, scaled, offset
11184 instr[ 4, 0] = Rm */
11186 uint32_t dispatch
= ((INSTR (31, 30) << 3) | INSTR (24, 22));
11187 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 21, 15);
11191 case 2: store_pair_float (cpu
, offset
, Post
); return;
11192 case 3: load_pair_float (cpu
, offset
, Post
); return;
11193 case 4: store_pair_float (cpu
, offset
, NoWriteBack
); return;
11194 case 5: load_pair_float (cpu
, offset
, NoWriteBack
); return;
11195 case 6: store_pair_float (cpu
, offset
, Pre
); return;
11196 case 7: load_pair_float (cpu
, offset
, Pre
); return;
11198 case 10: store_pair_double (cpu
, offset
, Post
); return;
11199 case 11: load_pair_double (cpu
, offset
, Post
); return;
11200 case 12: store_pair_double (cpu
, offset
, NoWriteBack
); return;
11201 case 13: load_pair_double (cpu
, offset
, NoWriteBack
); return;
11202 case 14: store_pair_double (cpu
, offset
, Pre
); return;
11203 case 15: load_pair_double (cpu
, offset
, Pre
); return;
11205 case 18: store_pair_long_double (cpu
, offset
, Post
); return;
11206 case 19: load_pair_long_double (cpu
, offset
, Post
); return;
11207 case 20: store_pair_long_double (cpu
, offset
, NoWriteBack
); return;
11208 case 21: load_pair_long_double (cpu
, offset
, NoWriteBack
); return;
11209 case 22: store_pair_long_double (cpu
, offset
, Pre
); return;
11210 case 23: load_pair_long_double (cpu
, offset
, Pre
); return;
11217 static inline unsigned
11218 vec_reg (unsigned v
, unsigned o
)
11220 return (v
+ o
) & 0x3F;
11223 /* Load multiple N-element structures to N consecutive registers. */
11225 vec_load (sim_cpu
*cpu
, uint64_t address
, unsigned N
)
11227 int all
= INSTR (30, 30);
11228 unsigned size
= INSTR (11, 10);
11229 unsigned vd
= INSTR (4, 0);
11234 case 0: /* 8-bit operations. */
11236 for (i
= 0; i
< (16 * N
); i
++)
11237 aarch64_set_vec_u8 (cpu
, vec_reg (vd
, i
>> 4), i
& 15,
11238 aarch64_get_mem_u8 (cpu
, address
+ i
));
11240 for (i
= 0; i
< (8 * N
); i
++)
11241 aarch64_set_vec_u8 (cpu
, vec_reg (vd
, i
>> 3), i
& 7,
11242 aarch64_get_mem_u8 (cpu
, address
+ i
));
11245 case 1: /* 16-bit operations. */
11247 for (i
= 0; i
< (8 * N
); i
++)
11248 aarch64_set_vec_u16 (cpu
, vec_reg (vd
, i
>> 3), i
& 7,
11249 aarch64_get_mem_u16 (cpu
, address
+ i
* 2));
11251 for (i
= 0; i
< (4 * N
); i
++)
11252 aarch64_set_vec_u16 (cpu
, vec_reg (vd
, i
>> 2), i
& 3,
11253 aarch64_get_mem_u16 (cpu
, address
+ i
* 2));
11256 case 2: /* 32-bit operations. */
11258 for (i
= 0; i
< (4 * N
); i
++)
11259 aarch64_set_vec_u32 (cpu
, vec_reg (vd
, i
>> 2), i
& 3,
11260 aarch64_get_mem_u32 (cpu
, address
+ i
* 4));
11262 for (i
= 0; i
< (2 * N
); i
++)
11263 aarch64_set_vec_u32 (cpu
, vec_reg (vd
, i
>> 1), i
& 1,
11264 aarch64_get_mem_u32 (cpu
, address
+ i
* 4));
11267 case 3: /* 64-bit operations. */
11269 for (i
= 0; i
< (2 * N
); i
++)
11270 aarch64_set_vec_u64 (cpu
, vec_reg (vd
, i
>> 1), i
& 1,
11271 aarch64_get_mem_u64 (cpu
, address
+ i
* 8));
11273 for (i
= 0; i
< N
; i
++)
11274 aarch64_set_vec_u64 (cpu
, vec_reg (vd
, i
), 0,
11275 aarch64_get_mem_u64 (cpu
, address
+ i
* 8));
11280 /* LD4: load multiple 4-element to four consecutive registers. */
11282 LD4 (sim_cpu
*cpu
, uint64_t address
)
11284 vec_load (cpu
, address
, 4);
11287 /* LD3: load multiple 3-element structures to three consecutive registers. */
11289 LD3 (sim_cpu
*cpu
, uint64_t address
)
11291 vec_load (cpu
, address
, 3);
11294 /* LD2: load multiple 2-element structures to two consecutive registers. */
11296 LD2 (sim_cpu
*cpu
, uint64_t address
)
11298 vec_load (cpu
, address
, 2);
11301 /* Load multiple 1-element structures into one register. */
11303 LD1_1 (sim_cpu
*cpu
, uint64_t address
)
11305 int all
= INSTR (30, 30);
11306 unsigned size
= INSTR (11, 10);
11307 unsigned vd
= INSTR (4, 0);
11313 /* LD1 {Vd.16b}, addr, #16 */
11314 /* LD1 {Vd.8b}, addr, #8 */
11315 for (i
= 0; i
< (all
? 16 : 8); i
++)
11316 aarch64_set_vec_u8 (cpu
, vd
, i
,
11317 aarch64_get_mem_u8 (cpu
, address
+ i
));
11321 /* LD1 {Vd.8h}, addr, #16 */
11322 /* LD1 {Vd.4h}, addr, #8 */
11323 for (i
= 0; i
< (all
? 8 : 4); i
++)
11324 aarch64_set_vec_u16 (cpu
, vd
, i
,
11325 aarch64_get_mem_u16 (cpu
, address
+ i
* 2));
11329 /* LD1 {Vd.4s}, addr, #16 */
11330 /* LD1 {Vd.2s}, addr, #8 */
11331 for (i
= 0; i
< (all
? 4 : 2); i
++)
11332 aarch64_set_vec_u32 (cpu
, vd
, i
,
11333 aarch64_get_mem_u32 (cpu
, address
+ i
* 4));
11337 /* LD1 {Vd.2d}, addr, #16 */
11338 /* LD1 {Vd.1d}, addr, #8 */
11339 for (i
= 0; i
< (all
? 2 : 1); i
++)
11340 aarch64_set_vec_u64 (cpu
, vd
, i
,
11341 aarch64_get_mem_u64 (cpu
, address
+ i
* 8));
11346 /* Load multiple 1-element structures into two registers. */
11348 LD1_2 (sim_cpu
*cpu
, uint64_t address
)
11350 /* FIXME: This algorithm is *exactly* the same as the LD2 version.
11351 So why have two different instructions ? There must be something
11352 wrong somewhere. */
11353 vec_load (cpu
, address
, 2);
11356 /* Load multiple 1-element structures into three registers. */
11358 LD1_3 (sim_cpu
*cpu
, uint64_t address
)
11360 /* FIXME: This algorithm is *exactly* the same as the LD3 version.
11361 So why have two different instructions ? There must be something
11362 wrong somewhere. */
11363 vec_load (cpu
, address
, 3);
11366 /* Load multiple 1-element structures into four registers. */
11368 LD1_4 (sim_cpu
*cpu
, uint64_t address
)
11370 /* FIXME: This algorithm is *exactly* the same as the LD4 version.
11371 So why have two different instructions ? There must be something
11372 wrong somewhere. */
11373 vec_load (cpu
, address
, 4);
11376 /* Store multiple N-element structures to N consecutive registers. */
11378 vec_store (sim_cpu
*cpu
, uint64_t address
, unsigned N
)
11380 int all
= INSTR (30, 30);
11381 unsigned size
= INSTR (11, 10);
11382 unsigned vd
= INSTR (4, 0);
11387 case 0: /* 8-bit operations. */
11389 for (i
= 0; i
< (16 * N
); i
++)
11392 aarch64_get_vec_u8 (cpu
, vec_reg (vd
, i
>> 4), i
& 15));
11394 for (i
= 0; i
< (8 * N
); i
++)
11397 aarch64_get_vec_u8 (cpu
, vec_reg (vd
, i
>> 3), i
& 7));
11400 case 1: /* 16-bit operations. */
11402 for (i
= 0; i
< (8 * N
); i
++)
11403 aarch64_set_mem_u16
11404 (cpu
, address
+ i
* 2,
11405 aarch64_get_vec_u16 (cpu
, vec_reg (vd
, i
>> 3), i
& 7));
11407 for (i
= 0; i
< (4 * N
); i
++)
11408 aarch64_set_mem_u16
11409 (cpu
, address
+ i
* 2,
11410 aarch64_get_vec_u16 (cpu
, vec_reg (vd
, i
>> 2), i
& 3));
11413 case 2: /* 32-bit operations. */
11415 for (i
= 0; i
< (4 * N
); i
++)
11416 aarch64_set_mem_u32
11417 (cpu
, address
+ i
* 4,
11418 aarch64_get_vec_u32 (cpu
, vec_reg (vd
, i
>> 2), i
& 3));
11420 for (i
= 0; i
< (2 * N
); i
++)
11421 aarch64_set_mem_u32
11422 (cpu
, address
+ i
* 4,
11423 aarch64_get_vec_u32 (cpu
, vec_reg (vd
, i
>> 1), i
& 1));
11426 case 3: /* 64-bit operations. */
11428 for (i
= 0; i
< (2 * N
); i
++)
11429 aarch64_set_mem_u64
11430 (cpu
, address
+ i
* 8,
11431 aarch64_get_vec_u64 (cpu
, vec_reg (vd
, i
>> 1), i
& 1));
11433 for (i
= 0; i
< N
; i
++)
11434 aarch64_set_mem_u64
11435 (cpu
, address
+ i
* 8,
11436 aarch64_get_vec_u64 (cpu
, vec_reg (vd
, i
), 0));
11441 /* Store multiple 4-element structure to four consecutive registers. */
11443 ST4 (sim_cpu
*cpu
, uint64_t address
)
11445 vec_store (cpu
, address
, 4);
11448 /* Store multiple 3-element structures to three consecutive registers. */
11450 ST3 (sim_cpu
*cpu
, uint64_t address
)
11452 vec_store (cpu
, address
, 3);
11455 /* Store multiple 2-element structures to two consecutive registers. */
11457 ST2 (sim_cpu
*cpu
, uint64_t address
)
11459 vec_store (cpu
, address
, 2);
11462 /* Store multiple 1-element structures into one register. */
11464 ST1_1 (sim_cpu
*cpu
, uint64_t address
)
11466 int all
= INSTR (30, 30);
11467 unsigned size
= INSTR (11, 10);
11468 unsigned vd
= INSTR (4, 0);
11474 for (i
= 0; i
< (all
? 16 : 8); i
++)
11475 aarch64_set_mem_u8 (cpu
, address
+ i
,
11476 aarch64_get_vec_u8 (cpu
, vd
, i
));
11480 for (i
= 0; i
< (all
? 8 : 4); i
++)
11481 aarch64_set_mem_u16 (cpu
, address
+ i
* 2,
11482 aarch64_get_vec_u16 (cpu
, vd
, i
));
11486 for (i
= 0; i
< (all
? 4 : 2); i
++)
11487 aarch64_set_mem_u32 (cpu
, address
+ i
* 4,
11488 aarch64_get_vec_u32 (cpu
, vd
, i
));
11492 for (i
= 0; i
< (all
? 2 : 1); i
++)
11493 aarch64_set_mem_u64 (cpu
, address
+ i
* 8,
11494 aarch64_get_vec_u64 (cpu
, vd
, i
));
11499 /* Store multiple 1-element structures into two registers. */
11501 ST1_2 (sim_cpu
*cpu
, uint64_t address
)
11503 /* FIXME: This algorithm is *exactly* the same as the ST2 version.
11504 So why have two different instructions ? There must be
11505 something wrong somewhere. */
11506 vec_store (cpu
, address
, 2);
11509 /* Store multiple 1-element structures into three registers. */
11511 ST1_3 (sim_cpu
*cpu
, uint64_t address
)
11513 /* FIXME: This algorithm is *exactly* the same as the ST3 version.
11514 So why have two different instructions ? There must be
11515 something wrong somewhere. */
11516 vec_store (cpu
, address
, 3);
11519 /* Store multiple 1-element structures into four registers. */
11521 ST1_4 (sim_cpu
*cpu
, uint64_t address
)
11523 /* FIXME: This algorithm is *exactly* the same as the ST4 version.
11524 So why have two different instructions ? There must be
11525 something wrong somewhere. */
11526 vec_store (cpu
, address
, 4);
11530 do_vec_LDnR (sim_cpu
*cpu
, uint64_t address
)
11533 instr[30] = element selector 0=>half, 1=>all elements
11534 instr[29,24] = 00 1101
11535 instr[23] = 0=>simple, 1=>post
11537 instr[21] = width: LD1R-or-LD3R (0) / LD2R-or-LD4R (1)
11538 instr[20,16] = 0 0000 (simple), Vinc (reg-post-inc, no SP),
11539 11111 (immediate post inc)
11541 instr[13] = width: LD1R-or-LD2R (0) / LD3R-or-LD4R (1)
11543 instr[11,10] = element size 00=> byte(b), 01=> half(h),
11544 10=> word(s), 11=> double(d)
11545 instr[9,5] = address
11548 unsigned full
= INSTR (30, 30);
11549 unsigned vd
= INSTR (4, 0);
11550 unsigned size
= INSTR (11, 10);
11553 NYI_assert (29, 24, 0x0D);
11554 NYI_assert (22, 22, 1);
11555 NYI_assert (15, 14, 3);
11556 NYI_assert (12, 12, 0);
11558 switch ((INSTR (13, 13) << 1) | INSTR (21, 21))
11560 case 0: /* LD1R. */
11565 uint8_t val
= aarch64_get_mem_u8 (cpu
, address
);
11566 for (i
= 0; i
< (full
? 16 : 8); i
++)
11567 aarch64_set_vec_u8 (cpu
, vd
, i
, val
);
11573 uint16_t val
= aarch64_get_mem_u16 (cpu
, address
);
11574 for (i
= 0; i
< (full
? 8 : 4); i
++)
11575 aarch64_set_vec_u16 (cpu
, vd
, i
, val
);
11581 uint32_t val
= aarch64_get_mem_u32 (cpu
, address
);
11582 for (i
= 0; i
< (full
? 4 : 2); i
++)
11583 aarch64_set_vec_u32 (cpu
, vd
, i
, val
);
11589 uint64_t val
= aarch64_get_mem_u64 (cpu
, address
);
11590 for (i
= 0; i
< (full
? 2 : 1); i
++)
11591 aarch64_set_vec_u64 (cpu
, vd
, i
, val
);
11600 case 1: /* LD2R. */
11605 uint8_t val1
= aarch64_get_mem_u8 (cpu
, address
);
11606 uint8_t val2
= aarch64_get_mem_u8 (cpu
, address
+ 1);
11608 for (i
= 0; i
< (full
? 16 : 8); i
++)
11610 aarch64_set_vec_u8 (cpu
, vd
, 0, val1
);
11611 aarch64_set_vec_u8 (cpu
, vd
+ 1, 0, val2
);
11618 uint16_t val1
= aarch64_get_mem_u16 (cpu
, address
);
11619 uint16_t val2
= aarch64_get_mem_u16 (cpu
, address
+ 2);
11621 for (i
= 0; i
< (full
? 8 : 4); i
++)
11623 aarch64_set_vec_u16 (cpu
, vd
, 0, val1
);
11624 aarch64_set_vec_u16 (cpu
, vd
+ 1, 0, val2
);
11631 uint32_t val1
= aarch64_get_mem_u32 (cpu
, address
);
11632 uint32_t val2
= aarch64_get_mem_u32 (cpu
, address
+ 4);
11634 for (i
= 0; i
< (full
? 4 : 2); i
++)
11636 aarch64_set_vec_u32 (cpu
, vd
, 0, val1
);
11637 aarch64_set_vec_u32 (cpu
, vd
+ 1, 0, val2
);
11644 uint64_t val1
= aarch64_get_mem_u64 (cpu
, address
);
11645 uint64_t val2
= aarch64_get_mem_u64 (cpu
, address
+ 8);
11647 for (i
= 0; i
< (full
? 2 : 1); i
++)
11649 aarch64_set_vec_u64 (cpu
, vd
, 0, val1
);
11650 aarch64_set_vec_u64 (cpu
, vd
+ 1, 0, val2
);
11660 case 2: /* LD3R. */
11665 uint8_t val1
= aarch64_get_mem_u8 (cpu
, address
);
11666 uint8_t val2
= aarch64_get_mem_u8 (cpu
, address
+ 1);
11667 uint8_t val3
= aarch64_get_mem_u8 (cpu
, address
+ 2);
11669 for (i
= 0; i
< (full
? 16 : 8); i
++)
11671 aarch64_set_vec_u8 (cpu
, vd
, 0, val1
);
11672 aarch64_set_vec_u8 (cpu
, vd
+ 1, 0, val2
);
11673 aarch64_set_vec_u8 (cpu
, vd
+ 2, 0, val3
);
11680 uint32_t val1
= aarch64_get_mem_u16 (cpu
, address
);
11681 uint32_t val2
= aarch64_get_mem_u16 (cpu
, address
+ 2);
11682 uint32_t val3
= aarch64_get_mem_u16 (cpu
, address
+ 4);
11684 for (i
= 0; i
< (full
? 8 : 4); i
++)
11686 aarch64_set_vec_u16 (cpu
, vd
, 0, val1
);
11687 aarch64_set_vec_u16 (cpu
, vd
+ 1, 0, val2
);
11688 aarch64_set_vec_u16 (cpu
, vd
+ 2, 0, val3
);
11695 uint32_t val1
= aarch64_get_mem_u32 (cpu
, address
);
11696 uint32_t val2
= aarch64_get_mem_u32 (cpu
, address
+ 4);
11697 uint32_t val3
= aarch64_get_mem_u32 (cpu
, address
+ 8);
11699 for (i
= 0; i
< (full
? 4 : 2); i
++)
11701 aarch64_set_vec_u32 (cpu
, vd
, 0, val1
);
11702 aarch64_set_vec_u32 (cpu
, vd
+ 1, 0, val2
);
11703 aarch64_set_vec_u32 (cpu
, vd
+ 2, 0, val3
);
11710 uint64_t val1
= aarch64_get_mem_u64 (cpu
, address
);
11711 uint64_t val2
= aarch64_get_mem_u64 (cpu
, address
+ 8);
11712 uint64_t val3
= aarch64_get_mem_u64 (cpu
, address
+ 16);
11714 for (i
= 0; i
< (full
? 2 : 1); i
++)
11716 aarch64_set_vec_u64 (cpu
, vd
, 0, val1
);
11717 aarch64_set_vec_u64 (cpu
, vd
+ 1, 0, val2
);
11718 aarch64_set_vec_u64 (cpu
, vd
+ 2, 0, val3
);
11728 case 3: /* LD4R. */
11733 uint8_t val1
= aarch64_get_mem_u8 (cpu
, address
);
11734 uint8_t val2
= aarch64_get_mem_u8 (cpu
, address
+ 1);
11735 uint8_t val3
= aarch64_get_mem_u8 (cpu
, address
+ 2);
11736 uint8_t val4
= aarch64_get_mem_u8 (cpu
, address
+ 3);
11738 for (i
= 0; i
< (full
? 16 : 8); i
++)
11740 aarch64_set_vec_u8 (cpu
, vd
, 0, val1
);
11741 aarch64_set_vec_u8 (cpu
, vd
+ 1, 0, val2
);
11742 aarch64_set_vec_u8 (cpu
, vd
+ 2, 0, val3
);
11743 aarch64_set_vec_u8 (cpu
, vd
+ 3, 0, val4
);
11750 uint32_t val1
= aarch64_get_mem_u16 (cpu
, address
);
11751 uint32_t val2
= aarch64_get_mem_u16 (cpu
, address
+ 2);
11752 uint32_t val3
= aarch64_get_mem_u16 (cpu
, address
+ 4);
11753 uint32_t val4
= aarch64_get_mem_u16 (cpu
, address
+ 6);
11755 for (i
= 0; i
< (full
? 8 : 4); i
++)
11757 aarch64_set_vec_u16 (cpu
, vd
, 0, val1
);
11758 aarch64_set_vec_u16 (cpu
, vd
+ 1, 0, val2
);
11759 aarch64_set_vec_u16 (cpu
, vd
+ 2, 0, val3
);
11760 aarch64_set_vec_u16 (cpu
, vd
+ 3, 0, val4
);
11767 uint32_t val1
= aarch64_get_mem_u32 (cpu
, address
);
11768 uint32_t val2
= aarch64_get_mem_u32 (cpu
, address
+ 4);
11769 uint32_t val3
= aarch64_get_mem_u32 (cpu
, address
+ 8);
11770 uint32_t val4
= aarch64_get_mem_u32 (cpu
, address
+ 12);
11772 for (i
= 0; i
< (full
? 4 : 2); i
++)
11774 aarch64_set_vec_u32 (cpu
, vd
, 0, val1
);
11775 aarch64_set_vec_u32 (cpu
, vd
+ 1, 0, val2
);
11776 aarch64_set_vec_u32 (cpu
, vd
+ 2, 0, val3
);
11777 aarch64_set_vec_u32 (cpu
, vd
+ 3, 0, val4
);
11784 uint64_t val1
= aarch64_get_mem_u64 (cpu
, address
);
11785 uint64_t val2
= aarch64_get_mem_u64 (cpu
, address
+ 8);
11786 uint64_t val3
= aarch64_get_mem_u64 (cpu
, address
+ 16);
11787 uint64_t val4
= aarch64_get_mem_u64 (cpu
, address
+ 24);
11789 for (i
= 0; i
< (full
? 2 : 1); i
++)
11791 aarch64_set_vec_u64 (cpu
, vd
, 0, val1
);
11792 aarch64_set_vec_u64 (cpu
, vd
+ 1, 0, val2
);
11793 aarch64_set_vec_u64 (cpu
, vd
+ 2, 0, val3
);
11794 aarch64_set_vec_u64 (cpu
, vd
+ 3, 0, val4
);
11810 do_vec_load_store (sim_cpu
*cpu
)
11812 /* {LD|ST}<N> {Vd..Vd+N}, vaddr
11815 instr[30] = element selector 0=>half, 1=>all elements
11816 instr[29,25] = 00110
11818 instr[23] = 0=>simple, 1=>post
11819 instr[22] = 0=>store, 1=>load
11820 instr[21] = 0 (LDn) / small(0)-large(1) selector (LDnR)
11821 instr[20,16] = 00000 (simple), Vinc (reg-post-inc, no SP),
11822 11111 (immediate post inc)
11823 instr[15,12] = elements and destinations. eg for load:
11824 0000=>LD4 => load multiple 4-element to
11825 four consecutive registers
11826 0100=>LD3 => load multiple 3-element to
11827 three consecutive registers
11828 1000=>LD2 => load multiple 2-element to
11829 two consecutive registers
11830 0010=>LD1 => load multiple 1-element to
11831 four consecutive registers
11832 0110=>LD1 => load multiple 1-element to
11833 three consecutive registers
11834 1010=>LD1 => load multiple 1-element to
11835 two consecutive registers
11836 0111=>LD1 => load multiple 1-element to
11840 instr[11,10] = element size 00=> byte(b), 01=> half(h),
11841 10=> word(s), 11=> double(d)
11842 instr[9,5] = Vn, can be SP
11851 if (INSTR (31, 31) != 0 || INSTR (29, 25) != 0x06)
11854 type
= INSTR (15, 12);
11855 if (type
!= 0xE && type
!= 0xE && INSTR (21, 21) != 0)
11858 post
= INSTR (23, 23);
11859 load
= INSTR (22, 22);
11861 address
= aarch64_get_reg_u64 (cpu
, vn
, SP_OK
);
11865 unsigned vm
= INSTR (20, 16);
11869 unsigned sizeof_operation
;
11873 case 0: sizeof_operation
= 32; break;
11874 case 4: sizeof_operation
= 24; break;
11875 case 8: sizeof_operation
= 16; break;
11878 sizeof_operation
= INSTR (21, 21) ? 2 : 1;
11879 sizeof_operation
<<= INSTR (11, 10);
11883 sizeof_operation
= INSTR (21, 21) ? 8 : 4;
11884 sizeof_operation
<<= INSTR (11, 10);
11888 /* One register, immediate offset variant. */
11889 sizeof_operation
= 8;
11893 /* Two registers, immediate offset variant. */
11894 sizeof_operation
= 16;
11898 /* Three registers, immediate offset variant. */
11899 sizeof_operation
= 24;
11903 /* Four registers, immediate offset variant. */
11904 sizeof_operation
= 32;
11911 if (INSTR (30, 30))
11912 sizeof_operation
*= 2;
11914 aarch64_set_reg_u64 (cpu
, vn
, SP_OK
, address
+ sizeof_operation
);
11917 aarch64_set_reg_u64 (cpu
, vn
, SP_OK
,
11918 address
+ aarch64_get_reg_u64 (cpu
, vm
, NO_SP
));
11922 NYI_assert (20, 16, 0);
11929 case 0: LD4 (cpu
, address
); return;
11930 case 4: LD3 (cpu
, address
); return;
11931 case 8: LD2 (cpu
, address
); return;
11932 case 2: LD1_4 (cpu
, address
); return;
11933 case 6: LD1_3 (cpu
, address
); return;
11934 case 10: LD1_2 (cpu
, address
); return;
11935 case 7: LD1_1 (cpu
, address
); return;
11938 case 0xC: do_vec_LDnR (cpu
, address
); return;
11948 case 0: ST4 (cpu
, address
); return;
11949 case 4: ST3 (cpu
, address
); return;
11950 case 8: ST2 (cpu
, address
); return;
11951 case 2: ST1_4 (cpu
, address
); return;
11952 case 6: ST1_3 (cpu
, address
); return;
11953 case 10: ST1_2 (cpu
, address
); return;
11954 case 7: ST1_1 (cpu
, address
); return;
11961 dexLdSt (sim_cpu
*cpu
)
11963 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
11964 assert group == GROUP_LDST_0100 || group == GROUP_LDST_0110 ||
11965 group == GROUP_LDST_1100 || group == GROUP_LDST_1110
11966 bits [29,28:26] of a LS are the secondary dispatch vector. */
11967 uint32_t group2
= dispatchLS (aarch64_get_instr (cpu
));
11972 dexLoadExclusive (cpu
); return;
11976 dexLoadLiteral (cpu
); return;
11980 dexLoadOther (cpu
); return;
11982 case LS_ADVSIMD_001
:
11983 do_vec_load_store (cpu
); return;
11986 dex_load_store_pair_gr (cpu
); return;
11989 dex_load_store_pair_fp (cpu
); return;
11992 /* Should never reach here. */
11997 /* Specific decode and execute for group Data Processing Register. */
12000 dexLogicalShiftedRegister (sim_cpu
*cpu
)
12002 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12004 instr[28:24] = 01010
12005 instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> ROR
12008 instr[15,10] = count : must be 0xxxxx for 32 bit
12012 uint32_t size
= INSTR (31, 31);
12013 Shift shiftType
= INSTR (23, 22);
12014 uint32_t count
= INSTR (15, 10);
12016 /* 32 bit operations must have count[5] = 0.
12017 or else we have an UNALLOC. */
12018 if (size
== 0 && uimm (count
, 5, 5))
12021 /* Dispatch on size:op:N. */
12022 switch ((INSTR (31, 29) << 1) | INSTR (21, 21))
12024 case 0: and32_shift (cpu
, shiftType
, count
); return;
12025 case 1: bic32_shift (cpu
, shiftType
, count
); return;
12026 case 2: orr32_shift (cpu
, shiftType
, count
); return;
12027 case 3: orn32_shift (cpu
, shiftType
, count
); return;
12028 case 4: eor32_shift (cpu
, shiftType
, count
); return;
12029 case 5: eon32_shift (cpu
, shiftType
, count
); return;
12030 case 6: ands32_shift (cpu
, shiftType
, count
); return;
12031 case 7: bics32_shift (cpu
, shiftType
, count
); return;
12032 case 8: and64_shift (cpu
, shiftType
, count
); return;
12033 case 9: bic64_shift (cpu
, shiftType
, count
); return;
12034 case 10:orr64_shift (cpu
, shiftType
, count
); return;
12035 case 11:orn64_shift (cpu
, shiftType
, count
); return;
12036 case 12:eor64_shift (cpu
, shiftType
, count
); return;
12037 case 13:eon64_shift (cpu
, shiftType
, count
); return;
12038 case 14:ands64_shift (cpu
, shiftType
, count
); return;
12039 case 15:bics64_shift (cpu
, shiftType
, count
); return;
12043 /* 32 bit conditional select. */
12045 csel32 (sim_cpu
*cpu
, CondCode cc
)
12047 unsigned rm
= INSTR (20, 16);
12048 unsigned rn
= INSTR (9, 5);
12049 unsigned rd
= INSTR (4, 0);
12051 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12052 testConditionCode (cpu
, cc
)
12053 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12054 : aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12057 /* 64 bit conditional select. */
12059 csel64 (sim_cpu
*cpu
, CondCode cc
)
12061 unsigned rm
= INSTR (20, 16);
12062 unsigned rn
= INSTR (9, 5);
12063 unsigned rd
= INSTR (4, 0);
12065 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12066 testConditionCode (cpu
, cc
)
12067 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12068 : aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
12071 /* 32 bit conditional increment. */
12073 csinc32 (sim_cpu
*cpu
, CondCode cc
)
12075 unsigned rm
= INSTR (20, 16);
12076 unsigned rn
= INSTR (9, 5);
12077 unsigned rd
= INSTR (4, 0);
12079 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12080 testConditionCode (cpu
, cc
)
12081 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12082 : aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) + 1);
12085 /* 64 bit conditional increment. */
12087 csinc64 (sim_cpu
*cpu
, CondCode cc
)
12089 unsigned rm
= INSTR (20, 16);
12090 unsigned rn
= INSTR (9, 5);
12091 unsigned rd
= INSTR (4, 0);
12093 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12094 testConditionCode (cpu
, cc
)
12095 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12096 : aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) + 1);
12099 /* 32 bit conditional invert. */
12101 csinv32 (sim_cpu
*cpu
, CondCode cc
)
12103 unsigned rm
= INSTR (20, 16);
12104 unsigned rn
= INSTR (9, 5);
12105 unsigned rd
= INSTR (4, 0);
12107 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12108 testConditionCode (cpu
, cc
)
12109 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12110 : ~ aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12113 /* 64 bit conditional invert. */
12115 csinv64 (sim_cpu
*cpu
, CondCode cc
)
12117 unsigned rm
= INSTR (20, 16);
12118 unsigned rn
= INSTR (9, 5);
12119 unsigned rd
= INSTR (4, 0);
12121 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12122 testConditionCode (cpu
, cc
)
12123 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12124 : ~ aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
12127 /* 32 bit conditional negate. */
12129 csneg32 (sim_cpu
*cpu
, CondCode cc
)
12131 unsigned rm
= INSTR (20, 16);
12132 unsigned rn
= INSTR (9, 5);
12133 unsigned rd
= INSTR (4, 0);
12135 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12136 testConditionCode (cpu
, cc
)
12137 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12138 : - aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12141 /* 64 bit conditional negate. */
12143 csneg64 (sim_cpu
*cpu
, CondCode cc
)
12145 unsigned rm
= INSTR (20, 16);
12146 unsigned rn
= INSTR (9, 5);
12147 unsigned rd
= INSTR (4, 0);
12149 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12150 testConditionCode (cpu
, cc
)
12151 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12152 : - aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
12156 dexCondSelect (sim_cpu
*cpu
)
12158 /* instr[28,21] = 11011011
12159 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12160 instr[30:11,10] = op : 000 ==> CSEL, 001 ==> CSINC,
12161 100 ==> CSINV, 101 ==> CSNEG,
12163 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
12164 instr[15,12] = cond
12165 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC */
12167 CondCode cc
= INSTR (15, 12);
12168 uint32_t S
= INSTR (29, 29);
12169 uint32_t op2
= INSTR (11, 10);
12177 switch ((INSTR (31, 30) << 1) | op2
)
12179 case 0: csel32 (cpu
, cc
); return;
12180 case 1: csinc32 (cpu
, cc
); return;
12181 case 2: csinv32 (cpu
, cc
); return;
12182 case 3: csneg32 (cpu
, cc
); return;
12183 case 4: csel64 (cpu
, cc
); return;
12184 case 5: csinc64 (cpu
, cc
); return;
12185 case 6: csinv64 (cpu
, cc
); return;
12186 case 7: csneg64 (cpu
, cc
); return;
12190 /* Some helpers for counting leading 1 or 0 bits. */
12192 /* Counts the number of leading bits which are the same
12193 in a 32 bit value in the range 1 to 32. */
12195 leading32 (uint32_t value
)
12197 int32_t mask
= 0xffff0000;
12198 uint32_t count
= 16; /* Counts number of bits set in mask. */
12199 uint32_t lo
= 1; /* Lower bound for number of sign bits. */
12200 uint32_t hi
= 32; /* Upper bound for number of sign bits. */
12202 while (lo
+ 1 < hi
)
12204 int32_t test
= (value
& mask
);
12206 if (test
== 0 || test
== mask
)
12209 count
= (lo
+ hi
) / 2;
12210 mask
>>= (count
- lo
);
12215 count
= (lo
+ hi
) / 2;
12216 mask
<<= hi
- count
;
12225 test
= (value
& mask
);
12227 if (test
== 0 || test
== mask
)
12236 /* Counts the number of leading bits which are the same
12237 in a 64 bit value in the range 1 to 64. */
12239 leading64 (uint64_t value
)
12241 int64_t mask
= 0xffffffff00000000LL
;
12242 uint64_t count
= 32; /* Counts number of bits set in mask. */
12243 uint64_t lo
= 1; /* Lower bound for number of sign bits. */
12244 uint64_t hi
= 64; /* Upper bound for number of sign bits. */
12246 while (lo
+ 1 < hi
)
12248 int64_t test
= (value
& mask
);
12250 if (test
== 0 || test
== mask
)
12253 count
= (lo
+ hi
) / 2;
12254 mask
>>= (count
- lo
);
12259 count
= (lo
+ hi
) / 2;
12260 mask
<<= hi
- count
;
12269 test
= (value
& mask
);
12271 if (test
== 0 || test
== mask
)
12280 /* Bit operations. */
12281 /* N.B register args may not be SP. */
12283 /* 32 bit count leading sign bits. */
12285 cls32 (sim_cpu
*cpu
)
12287 unsigned rn
= INSTR (9, 5);
12288 unsigned rd
= INSTR (4, 0);
12290 /* N.B. the result needs to exclude the leading bit. */
12291 aarch64_set_reg_u64
12292 (cpu
, rd
, NO_SP
, leading32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)) - 1);
12295 /* 64 bit count leading sign bits. */
12297 cls64 (sim_cpu
*cpu
)
12299 unsigned rn
= INSTR (9, 5);
12300 unsigned rd
= INSTR (4, 0);
12302 /* N.B. the result needs to exclude the leading bit. */
12303 aarch64_set_reg_u64
12304 (cpu
, rd
, NO_SP
, leading64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)) - 1);
12307 /* 32 bit count leading zero bits. */
12309 clz32 (sim_cpu
*cpu
)
12311 unsigned rn
= INSTR (9, 5);
12312 unsigned rd
= INSTR (4, 0);
12313 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12315 /* if the sign (top) bit is set then the count is 0. */
12316 if (pick32 (value
, 31, 31))
12317 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, 0L);
12319 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, leading32 (value
));
12322 /* 64 bit count leading zero bits. */
12324 clz64 (sim_cpu
*cpu
)
12326 unsigned rn
= INSTR (9, 5);
12327 unsigned rd
= INSTR (4, 0);
12328 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12330 /* if the sign (top) bit is set then the count is 0. */
12331 if (pick64 (value
, 63, 63))
12332 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, 0L);
12334 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, leading64 (value
));
12337 /* 32 bit reverse bits. */
12339 rbit32 (sim_cpu
*cpu
)
12341 unsigned rn
= INSTR (9, 5);
12342 unsigned rd
= INSTR (4, 0);
12343 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12344 uint32_t result
= 0;
12347 for (i
= 0; i
< 32; i
++)
12350 result
|= (value
& 1);
12353 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12356 /* 64 bit reverse bits. */
12358 rbit64 (sim_cpu
*cpu
)
12360 unsigned rn
= INSTR (9, 5);
12361 unsigned rd
= INSTR (4, 0);
12362 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12363 uint64_t result
= 0;
12366 for (i
= 0; i
< 64; i
++)
12369 result
|= (value
& 1UL);
12372 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12375 /* 32 bit reverse bytes. */
12377 rev32 (sim_cpu
*cpu
)
12379 unsigned rn
= INSTR (9, 5);
12380 unsigned rd
= INSTR (4, 0);
12381 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12382 uint32_t result
= 0;
12385 for (i
= 0; i
< 4; i
++)
12388 result
|= (value
& 0xff);
12391 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12394 /* 64 bit reverse bytes. */
12396 rev64 (sim_cpu
*cpu
)
12398 unsigned rn
= INSTR (9, 5);
12399 unsigned rd
= INSTR (4, 0);
12400 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12401 uint64_t result
= 0;
12404 for (i
= 0; i
< 8; i
++)
12407 result
|= (value
& 0xffULL
);
12410 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12413 /* 32 bit reverse shorts. */
12414 /* N.B.this reverses the order of the bytes in each half word. */
12416 revh32 (sim_cpu
*cpu
)
12418 unsigned rn
= INSTR (9, 5);
12419 unsigned rd
= INSTR (4, 0);
12420 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12421 uint32_t result
= 0;
12424 for (i
= 0; i
< 2; i
++)
12427 result
|= (value
& 0x00ff00ff);
12430 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12433 /* 64 bit reverse shorts. */
12434 /* N.B.this reverses the order of the bytes in each half word. */
12436 revh64 (sim_cpu
*cpu
)
12438 unsigned rn
= INSTR (9, 5);
12439 unsigned rd
= INSTR (4, 0);
12440 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12441 uint64_t result
= 0;
12444 for (i
= 0; i
< 2; i
++)
12447 result
|= (value
& 0x00ff00ff00ff00ffULL
);
12450 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12454 dexDataProc1Source (sim_cpu
*cpu
)
12457 instr[28,21] = 111010110
12458 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12459 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
12460 instr[20,16] = opcode2 : 00000 ==> ok, ow ==> UNALLOC
12461 instr[15,10] = opcode : 000000 ==> RBIT, 000001 ==> REV16,
12462 000010 ==> REV, 000011 ==> UNALLOC
12463 000100 ==> CLZ, 000101 ==> CLS
12465 instr[9,5] = rn : may not be SP
12466 instr[4,0] = rd : may not be SP. */
12468 uint32_t S
= INSTR (29, 29);
12469 uint32_t opcode2
= INSTR (20, 16);
12470 uint32_t opcode
= INSTR (15, 10);
12471 uint32_t dispatch
= ((INSTR (31, 31) << 3) | opcode
);
12484 case 0: rbit32 (cpu
); return;
12485 case 1: revh32 (cpu
); return;
12486 case 2: rev32 (cpu
); return;
12487 case 4: clz32 (cpu
); return;
12488 case 5: cls32 (cpu
); return;
12489 case 8: rbit64 (cpu
); return;
12490 case 9: revh64 (cpu
); return;
12491 case 10:rev32 (cpu
); return;
12492 case 11:rev64 (cpu
); return;
12493 case 12:clz64 (cpu
); return;
12494 case 13:cls64 (cpu
); return;
12495 default: HALT_UNALLOC
;
12500 Shifts by count supplied in register.
12501 N.B register args may not be SP.
12502 These all use the shifted auxiliary function for
12503 simplicity and clarity. Writing the actual shift
12504 inline would avoid a branch and so be faster but
12505 would also necessitate getting signs right. */
12507 /* 32 bit arithmetic shift right. */
12509 asrv32 (sim_cpu
*cpu
)
12511 unsigned rm
= INSTR (20, 16);
12512 unsigned rn
= INSTR (9, 5);
12513 unsigned rd
= INSTR (4, 0);
12515 aarch64_set_reg_u64
12517 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), ASR
,
12518 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12521 /* 64 bit arithmetic shift right. */
12523 asrv64 (sim_cpu
*cpu
)
12525 unsigned rm
= INSTR (20, 16);
12526 unsigned rn
= INSTR (9, 5);
12527 unsigned rd
= INSTR (4, 0);
12529 aarch64_set_reg_u64
12531 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), ASR
,
12532 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12535 /* 32 bit logical shift left. */
12537 lslv32 (sim_cpu
*cpu
)
12539 unsigned rm
= INSTR (20, 16);
12540 unsigned rn
= INSTR (9, 5);
12541 unsigned rd
= INSTR (4, 0);
12543 aarch64_set_reg_u64
12545 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), LSL
,
12546 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12549 /* 64 bit arithmetic shift left. */
12551 lslv64 (sim_cpu
*cpu
)
12553 unsigned rm
= INSTR (20, 16);
12554 unsigned rn
= INSTR (9, 5);
12555 unsigned rd
= INSTR (4, 0);
12557 aarch64_set_reg_u64
12559 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), LSL
,
12560 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12563 /* 32 bit logical shift right. */
12565 lsrv32 (sim_cpu
*cpu
)
12567 unsigned rm
= INSTR (20, 16);
12568 unsigned rn
= INSTR (9, 5);
12569 unsigned rd
= INSTR (4, 0);
12571 aarch64_set_reg_u64
12573 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), LSR
,
12574 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12577 /* 64 bit logical shift right. */
12579 lsrv64 (sim_cpu
*cpu
)
12581 unsigned rm
= INSTR (20, 16);
12582 unsigned rn
= INSTR (9, 5);
12583 unsigned rd
= INSTR (4, 0);
12585 aarch64_set_reg_u64
12587 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), LSR
,
12588 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12591 /* 32 bit rotate right. */
12593 rorv32 (sim_cpu
*cpu
)
12595 unsigned rm
= INSTR (20, 16);
12596 unsigned rn
= INSTR (9, 5);
12597 unsigned rd
= INSTR (4, 0);
12599 aarch64_set_reg_u64
12601 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), ROR
,
12602 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12605 /* 64 bit rotate right. */
12607 rorv64 (sim_cpu
*cpu
)
12609 unsigned rm
= INSTR (20, 16);
12610 unsigned rn
= INSTR (9, 5);
12611 unsigned rd
= INSTR (4, 0);
12613 aarch64_set_reg_u64
12615 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), ROR
,
12616 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12622 /* 32 bit signed divide. */
12624 cpuiv32 (sim_cpu
*cpu
)
12626 unsigned rm
= INSTR (20, 16);
12627 unsigned rn
= INSTR (9, 5);
12628 unsigned rd
= INSTR (4, 0);
12629 /* N.B. the pseudo-code does the divide using 64 bit data. */
12630 /* TODO : check that this rounds towards zero as required. */
12631 int64_t dividend
= aarch64_get_reg_s32 (cpu
, rn
, NO_SP
);
12632 int64_t divisor
= aarch64_get_reg_s32 (cpu
, rm
, NO_SP
);
12634 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
,
12635 divisor
? ((int32_t) (dividend
/ divisor
)) : 0);
12638 /* 64 bit signed divide. */
12640 cpuiv64 (sim_cpu
*cpu
)
12642 unsigned rm
= INSTR (20, 16);
12643 unsigned rn
= INSTR (9, 5);
12644 unsigned rd
= INSTR (4, 0);
12646 /* TODO : check that this rounds towards zero as required. */
12647 int64_t divisor
= aarch64_get_reg_s64 (cpu
, rm
, NO_SP
);
12649 aarch64_set_reg_s64
12651 divisor
? (aarch64_get_reg_s64 (cpu
, rn
, NO_SP
) / divisor
) : 0);
12654 /* 32 bit unsigned divide. */
12656 udiv32 (sim_cpu
*cpu
)
12658 unsigned rm
= INSTR (20, 16);
12659 unsigned rn
= INSTR (9, 5);
12660 unsigned rd
= INSTR (4, 0);
12662 /* N.B. the pseudo-code does the divide using 64 bit data. */
12663 uint64_t dividend
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12664 uint64_t divisor
= aarch64_get_reg_u32 (cpu
, rm
, NO_SP
);
12666 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12667 divisor
? (uint32_t) (dividend
/ divisor
) : 0);
12670 /* 64 bit unsigned divide. */
12672 udiv64 (sim_cpu
*cpu
)
12674 unsigned rm
= INSTR (20, 16);
12675 unsigned rn
= INSTR (9, 5);
12676 unsigned rd
= INSTR (4, 0);
12678 /* TODO : check that this rounds towards zero as required. */
12679 uint64_t divisor
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
12681 aarch64_set_reg_u64
12683 divisor
? (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) / divisor
) : 0);
12687 dexDataProc2Source (sim_cpu
*cpu
)
12689 /* assert instr[30] == 0
12690 instr[28,21] == 11010110
12691 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12692 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
12693 instr[15,10] = opcode : 000010 ==> UDIV, 000011 ==> CPUIV,
12694 001000 ==> LSLV, 001001 ==> LSRV
12695 001010 ==> ASRV, 001011 ==> RORV
12699 uint32_t S
= INSTR (29, 29);
12700 uint32_t opcode
= INSTR (15, 10);
12708 dispatch
= ( (INSTR (31, 31) << 3)
12709 | (uimm (opcode
, 3, 3) << 2)
12710 | uimm (opcode
, 1, 0));
12713 case 2: udiv32 (cpu
); return;
12714 case 3: cpuiv32 (cpu
); return;
12715 case 4: lslv32 (cpu
); return;
12716 case 5: lsrv32 (cpu
); return;
12717 case 6: asrv32 (cpu
); return;
12718 case 7: rorv32 (cpu
); return;
12719 case 10: udiv64 (cpu
); return;
12720 case 11: cpuiv64 (cpu
); return;
12721 case 12: lslv64 (cpu
); return;
12722 case 13: lsrv64 (cpu
); return;
12723 case 14: asrv64 (cpu
); return;
12724 case 15: rorv64 (cpu
); return;
12725 default: HALT_UNALLOC
;
12732 /* 32 bit multiply and add. */
12734 madd32 (sim_cpu
*cpu
)
12736 unsigned rm
= INSTR (20, 16);
12737 unsigned ra
= INSTR (14, 10);
12738 unsigned rn
= INSTR (9, 5);
12739 unsigned rd
= INSTR (4, 0);
12741 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12742 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12743 aarch64_get_reg_u32 (cpu
, ra
, NO_SP
)
12744 + aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12745 * aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12748 /* 64 bit multiply and add. */
12750 madd64 (sim_cpu
*cpu
)
12752 unsigned rm
= INSTR (20, 16);
12753 unsigned ra
= INSTR (14, 10);
12754 unsigned rn
= INSTR (9, 5);
12755 unsigned rd
= INSTR (4, 0);
12757 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12758 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12759 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
12760 + (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12761 * aarch64_get_reg_u64 (cpu
, rm
, NO_SP
)));
12764 /* 32 bit multiply and sub. */
12766 msub32 (sim_cpu
*cpu
)
12768 unsigned rm
= INSTR (20, 16);
12769 unsigned ra
= INSTR (14, 10);
12770 unsigned rn
= INSTR (9, 5);
12771 unsigned rd
= INSTR (4, 0);
12773 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12774 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12775 aarch64_get_reg_u32 (cpu
, ra
, NO_SP
)
12776 - aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12777 * aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12780 /* 64 bit multiply and sub. */
12782 msub64 (sim_cpu
*cpu
)
12784 unsigned rm
= INSTR (20, 16);
12785 unsigned ra
= INSTR (14, 10);
12786 unsigned rn
= INSTR (9, 5);
12787 unsigned rd
= INSTR (4, 0);
12789 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12790 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12791 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
12792 - aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12793 * aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
12796 /* Signed multiply add long -- source, source2 : 32 bit, source3 : 64 bit. */
12798 smaddl (sim_cpu
*cpu
)
12800 unsigned rm
= INSTR (20, 16);
12801 unsigned ra
= INSTR (14, 10);
12802 unsigned rn
= INSTR (9, 5);
12803 unsigned rd
= INSTR (4, 0);
12805 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12806 obtain a 64 bit product. */
12807 aarch64_set_reg_s64
12809 aarch64_get_reg_s64 (cpu
, ra
, NO_SP
)
12810 + ((int64_t) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
))
12811 * ((int64_t) aarch64_get_reg_s32 (cpu
, rm
, NO_SP
)));
12814 /* Signed multiply sub long -- source, source2 : 32 bit, source3 : 64 bit. */
12816 smsubl (sim_cpu
*cpu
)
12818 unsigned rm
= INSTR (20, 16);
12819 unsigned ra
= INSTR (14, 10);
12820 unsigned rn
= INSTR (9, 5);
12821 unsigned rd
= INSTR (4, 0);
12823 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12824 obtain a 64 bit product. */
12825 aarch64_set_reg_s64
12827 aarch64_get_reg_s64 (cpu
, ra
, NO_SP
)
12828 - ((int64_t) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
))
12829 * ((int64_t) aarch64_get_reg_s32 (cpu
, rm
, NO_SP
)));
12832 /* Integer Multiply/Divide. */
12834 /* First some macros and a helper function. */
12835 /* Macros to test or access elements of 64 bit words. */
12837 /* Mask used to access lo 32 bits of 64 bit unsigned int. */
12838 #define LOW_WORD_MASK ((1ULL << 32) - 1)
12839 /* Return the lo 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int. */
12840 #define lowWordToU64(_value_u64) ((_value_u64) & LOW_WORD_MASK)
12841 /* Return the hi 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int. */
12842 #define highWordToU64(_value_u64) ((_value_u64) >> 32)
12844 /* Offset of sign bit in 64 bit signed integger. */
12845 #define SIGN_SHIFT_U64 63
12846 /* The sign bit itself -- also identifies the minimum negative int value. */
12847 #define SIGN_BIT_U64 (1UL << SIGN_SHIFT_U64)
12848 /* Return true if a 64 bit signed int presented as an unsigned int is the
12849 most negative value. */
12850 #define isMinimumU64(_value_u64) ((_value_u64) == SIGN_BIT_U64)
12851 /* Return true (non-zero) if a 64 bit signed int presented as an unsigned
12852 int has its sign bit set to false. */
12853 #define isSignSetU64(_value_u64) ((_value_u64) & SIGN_BIT_U64)
12854 /* Return 1L or -1L according to whether a 64 bit signed int presented as
12855 an unsigned int has its sign bit set or not. */
12856 #define signOfU64(_value_u64) (1L + (((value_u64) >> SIGN_SHIFT_U64) * -2L)
12857 /* Clear the sign bit of a 64 bit signed int presented as an unsigned int. */
12858 #define clearSignU64(_value_u64) ((_value_u64) &= ~SIGN_BIT_U64)
12860 /* Multiply two 64 bit ints and return.
12861 the hi 64 bits of the 128 bit product. */
12864 mul64hi (uint64_t value1
, uint64_t value2
)
12866 uint64_t resultmid1
;
12868 uint64_t value1_lo
= lowWordToU64 (value1
);
12869 uint64_t value1_hi
= highWordToU64 (value1
) ;
12870 uint64_t value2_lo
= lowWordToU64 (value2
);
12871 uint64_t value2_hi
= highWordToU64 (value2
);
12873 /* Cross-multiply and collect results. */
12874 uint64_t xproductlo
= value1_lo
* value2_lo
;
12875 uint64_t xproductmid1
= value1_lo
* value2_hi
;
12876 uint64_t xproductmid2
= value1_hi
* value2_lo
;
12877 uint64_t xproducthi
= value1_hi
* value2_hi
;
12878 uint64_t carry
= 0;
12879 /* Start accumulating 64 bit results. */
12880 /* Drop bottom half of lowest cross-product. */
12881 uint64_t resultmid
= xproductlo
>> 32;
12882 /* Add in middle products. */
12883 resultmid
= resultmid
+ xproductmid1
;
12885 /* Check for overflow. */
12886 if (resultmid
< xproductmid1
)
12887 /* Carry over 1 into top cross-product. */
12890 resultmid1
= resultmid
+ xproductmid2
;
12892 /* Check for overflow. */
12893 if (resultmid1
< xproductmid2
)
12894 /* Carry over 1 into top cross-product. */
12897 /* Drop lowest 32 bits of middle cross-product. */
12898 result
= resultmid1
>> 32;
12900 /* Add top cross-product plus and any carry. */
12901 result
+= xproducthi
+ carry
;
12906 /* Signed multiply high, source, source2 :
12907 64 bit, dest <-- high 64-bit of result. */
12909 smulh (sim_cpu
*cpu
)
12913 unsigned rm
= INSTR (20, 16);
12914 unsigned rn
= INSTR (9, 5);
12915 unsigned rd
= INSTR (4, 0);
12916 GReg ra
= INSTR (14, 10);
12917 int64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12918 int64_t value2
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
12921 int64_t signum
= 1;
12926 /* Convert to unsigned and use the unsigned mul64hi routine
12927 the fix the sign up afterwards. */
12948 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12949 uresult
= mul64hi (uvalue1
, uvalue2
);
12953 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, result
);
12956 /* Unsigned multiply add long -- source, source2 :
12957 32 bit, source3 : 64 bit. */
12959 umaddl (sim_cpu
*cpu
)
12961 unsigned rm
= INSTR (20, 16);
12962 unsigned ra
= INSTR (14, 10);
12963 unsigned rn
= INSTR (9, 5);
12964 unsigned rd
= INSTR (4, 0);
12966 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12967 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12968 obtain a 64 bit product. */
12969 aarch64_set_reg_u64
12971 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
12972 + ((uint64_t) aarch64_get_reg_u32 (cpu
, rn
, NO_SP
))
12973 * ((uint64_t) aarch64_get_reg_u32 (cpu
, rm
, NO_SP
)));
12976 /* Unsigned multiply sub long -- source, source2 : 32 bit, source3 : 64 bit. */
12978 umsubl (sim_cpu
*cpu
)
12980 unsigned rm
= INSTR (20, 16);
12981 unsigned ra
= INSTR (14, 10);
12982 unsigned rn
= INSTR (9, 5);
12983 unsigned rd
= INSTR (4, 0);
12985 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12986 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12987 obtain a 64 bit product. */
12988 aarch64_set_reg_u64
12990 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
12991 - ((uint64_t) aarch64_get_reg_u32 (cpu
, rn
, NO_SP
))
12992 * ((uint64_t) aarch64_get_reg_u32 (cpu
, rm
, NO_SP
)));
12995 /* Unsigned multiply high, source, source2 :
12996 64 bit, dest <-- high 64-bit of result. */
12998 umulh (sim_cpu
*cpu
)
13000 unsigned rm
= INSTR (20, 16);
13001 unsigned rn
= INSTR (9, 5);
13002 unsigned rd
= INSTR (4, 0);
13003 GReg ra
= INSTR (14, 10);
13008 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13009 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
13010 mul64hi (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
),
13011 aarch64_get_reg_u64 (cpu
, rm
, NO_SP
)));
13015 dexDataProc3Source (sim_cpu
*cpu
)
13017 /* assert instr[28,24] == 11011. */
13018 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit (for rd at least)
13019 instr[30,29] = op54 : 00 ==> ok, ow ==> UNALLOC
13020 instr[23,21] = op31 : 111 ==> UNALLOC, o2 ==> ok
13021 instr[15] = o0 : 0/1 ==> ok
13022 instr[23,21:15] ==> op : 0000 ==> MADD, 0001 ==> MSUB, (32/64 bit)
13023 0010 ==> SMADDL, 0011 ==> SMSUBL, (64 bit only)
13024 0100 ==> SMULH, (64 bit only)
13025 1010 ==> UMADDL, 1011 ==> UNSUBL, (64 bit only)
13026 1100 ==> UMULH (64 bit only)
13030 uint32_t size
= INSTR (31, 31);
13031 uint32_t op54
= INSTR (30, 29);
13032 uint32_t op31
= INSTR (23, 21);
13033 uint32_t o0
= INSTR (15, 15);
13050 dispatch
= (op31
<< 1) | o0
;
13054 case 0: madd64 (cpu
); return;
13055 case 1: msub64 (cpu
); return;
13056 case 2: smaddl (cpu
); return;
13057 case 3: smsubl (cpu
); return;
13058 case 4: smulh (cpu
); return;
13059 case 10: umaddl (cpu
); return;
13060 case 11: umsubl (cpu
); return;
13061 case 12: umulh (cpu
); return;
13062 default: HALT_UNALLOC
;
13067 dexDPReg (sim_cpu
*cpu
)
13069 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
13070 assert group == GROUP_DPREG_0101 || group == GROUP_DPREG_1101
13071 bits [28:24:21] of a DPReg are the secondary dispatch vector. */
13072 uint32_t group2
= dispatchDPReg (aarch64_get_instr (cpu
));
13076 case DPREG_LOG_000
:
13077 case DPREG_LOG_001
:
13078 dexLogicalShiftedRegister (cpu
); return;
13080 case DPREG_ADDSHF_010
:
13081 dexAddSubtractShiftedRegister (cpu
); return;
13083 case DPREG_ADDEXT_011
:
13084 dexAddSubtractExtendedRegister (cpu
); return;
13086 case DPREG_ADDCOND_100
:
13088 /* This set bundles a variety of different operations. */
13090 /* 1) add/sub w carry. */
13091 uint32_t mask1
= 0x1FE00000U
;
13092 uint32_t val1
= 0x1A000000U
;
13093 /* 2) cond compare register/immediate. */
13094 uint32_t mask2
= 0x1FE00000U
;
13095 uint32_t val2
= 0x1A400000U
;
13096 /* 3) cond select. */
13097 uint32_t mask3
= 0x1FE00000U
;
13098 uint32_t val3
= 0x1A800000U
;
13099 /* 4) data proc 1/2 source. */
13100 uint32_t mask4
= 0x1FE00000U
;
13101 uint32_t val4
= 0x1AC00000U
;
13103 if ((aarch64_get_instr (cpu
) & mask1
) == val1
)
13104 dexAddSubtractWithCarry (cpu
);
13106 else if ((aarch64_get_instr (cpu
) & mask2
) == val2
)
13109 else if ((aarch64_get_instr (cpu
) & mask3
) == val3
)
13110 dexCondSelect (cpu
);
13112 else if ((aarch64_get_instr (cpu
) & mask4
) == val4
)
13114 /* Bit 30 is clear for data proc 2 source
13115 and set for data proc 1 source. */
13116 if (aarch64_get_instr (cpu
) & (1U << 30))
13117 dexDataProc1Source (cpu
);
13119 dexDataProc2Source (cpu
);
13123 /* Should not reach here. */
13129 case DPREG_3SRC_110
:
13130 dexDataProc3Source (cpu
); return;
13132 case DPREG_UNALLOC_101
:
13135 case DPREG_3SRC_111
:
13136 dexDataProc3Source (cpu
); return;
13139 /* Should never reach here. */
13144 /* Unconditional Branch immediate.
13145 Offset is a PC-relative byte offset in the range +/- 128MiB.
13146 The offset is assumed to be raw from the decode i.e. the
13147 simulator is expected to scale them from word offsets to byte. */
13149 /* Unconditional branch. */
13151 buc (sim_cpu
*cpu
, int32_t offset
)
13153 aarch64_set_next_PC_by_offset (cpu
, offset
);
13156 static unsigned stack_depth
= 0;
13158 /* Unconditional branch and link -- writes return PC to LR. */
13160 bl (sim_cpu
*cpu
, int32_t offset
)
13162 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13163 aarch64_save_LR (cpu
);
13164 aarch64_set_next_PC_by_offset (cpu
, offset
);
13166 if (TRACE_BRANCH_P (cpu
))
13170 " %*scall %" PRIx64
" [%s]"
13171 " [args: %" PRIx64
" %" PRIx64
" %" PRIx64
"]",
13172 stack_depth
, " ", aarch64_get_next_PC (cpu
),
13173 aarch64_get_func (CPU_STATE (cpu
),
13174 aarch64_get_next_PC (cpu
)),
13175 aarch64_get_reg_u64 (cpu
, 0, NO_SP
),
13176 aarch64_get_reg_u64 (cpu
, 1, NO_SP
),
13177 aarch64_get_reg_u64 (cpu
, 2, NO_SP
)
13182 /* Unconditional Branch register.
13183 Branch/return address is in source register. */
13185 /* Unconditional branch. */
13189 unsigned rn
= INSTR (9, 5);
13190 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13191 aarch64_set_next_PC (cpu
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
13194 /* Unconditional branch and link -- writes return PC to LR. */
13198 unsigned rn
= INSTR (9, 5);
13200 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13201 /* The pseudo code in the spec says we update LR before fetching.
13202 the value from the rn. */
13203 aarch64_save_LR (cpu
);
13204 aarch64_set_next_PC (cpu
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
13206 if (TRACE_BRANCH_P (cpu
))
13210 " %*scall %" PRIx64
" [%s]"
13211 " [args: %" PRIx64
" %" PRIx64
" %" PRIx64
"]",
13212 stack_depth
, " ", aarch64_get_next_PC (cpu
),
13213 aarch64_get_func (CPU_STATE (cpu
),
13214 aarch64_get_next_PC (cpu
)),
13215 aarch64_get_reg_u64 (cpu
, 0, NO_SP
),
13216 aarch64_get_reg_u64 (cpu
, 1, NO_SP
),
13217 aarch64_get_reg_u64 (cpu
, 2, NO_SP
)
13222 /* Return -- assembler will default source to LR this is functionally
13223 equivalent to br but, presumably, unlike br it side effects the
13224 branch predictor. */
13228 unsigned rn
= INSTR (9, 5);
13229 aarch64_set_next_PC (cpu
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
13231 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13232 if (TRACE_BRANCH_P (cpu
))
13235 " %*sreturn [result: %" PRIx64
"]",
13236 stack_depth
, " ", aarch64_get_reg_u64 (cpu
, 0, NO_SP
));
13241 /* NOP -- we implement this and call it from the decode in case we
13242 want to intercept it later. */
13247 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13250 /* Data synchronization barrier. */
13255 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13258 /* Data memory barrier. */
13263 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13266 /* Instruction synchronization barrier. */
13271 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13275 dexBranchImmediate (sim_cpu
*cpu
)
13277 /* assert instr[30,26] == 00101
13278 instr[31] ==> 0 == B, 1 == BL
13279 instr[25,0] == imm26 branch offset counted in words. */
13281 uint32_t top
= INSTR (31, 31);
13282 /* We have a 26 byte signed word offset which we need to pass to the
13283 execute routine as a signed byte offset. */
13284 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 25, 0) << 2;
13292 /* Control Flow. */
13294 /* Conditional branch
13296 Offset is a PC-relative byte offset in the range +/- 1MiB pos is
13297 a bit position in the range 0 .. 63
13299 cc is a CondCode enum value as pulled out of the decode
13301 N.B. any offset register (source) can only be Xn or Wn. */
13304 bcc (sim_cpu
*cpu
, int32_t offset
, CondCode cc
)
13306 /* The test returns TRUE if CC is met. */
13307 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13308 if (testConditionCode (cpu
, cc
))
13309 aarch64_set_next_PC_by_offset (cpu
, offset
);
13312 /* 32 bit branch on register non-zero. */
13314 cbnz32 (sim_cpu
*cpu
, int32_t offset
)
13316 unsigned rt
= INSTR (4, 0);
13318 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13319 if (aarch64_get_reg_u32 (cpu
, rt
, NO_SP
) != 0)
13320 aarch64_set_next_PC_by_offset (cpu
, offset
);
13323 /* 64 bit branch on register zero. */
13325 cbnz (sim_cpu
*cpu
, int32_t offset
)
13327 unsigned rt
= INSTR (4, 0);
13329 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13330 if (aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) != 0)
13331 aarch64_set_next_PC_by_offset (cpu
, offset
);
13334 /* 32 bit branch on register non-zero. */
13336 cbz32 (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 cbz (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 /* Branch on register bit test non-zero -- one size fits all. */
13358 tbnz (sim_cpu
*cpu
, uint32_t pos
, int32_t offset
)
13360 unsigned rt
= INSTR (4, 0);
13362 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13363 if (aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) & (((uint64_t) 1) << pos
))
13364 aarch64_set_next_PC_by_offset (cpu
, offset
);
13367 /* Branch on register bit test zero -- one size fits all. */
13369 tbz (sim_cpu
*cpu
, uint32_t pos
, 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
) & (((uint64_t) 1) << pos
)))
13375 aarch64_set_next_PC_by_offset (cpu
, offset
);
13379 dexCompareBranchImmediate (sim_cpu
*cpu
)
13381 /* instr[30,25] = 01 1010
13382 instr[31] = size : 0 ==> 32, 1 ==> 64
13383 instr[24] = op : 0 ==> CBZ, 1 ==> CBNZ
13384 instr[23,5] = simm19 branch offset counted in words
13387 uint32_t size
= INSTR (31, 31);
13388 uint32_t op
= INSTR (24, 24);
13389 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 23, 5) << 2;
13394 cbz32 (cpu
, offset
);
13396 cbnz32 (cpu
, offset
);
13403 cbnz (cpu
, offset
);
13408 dexTestBranchImmediate (sim_cpu
*cpu
)
13410 /* instr[31] = b5 : bit 5 of test bit idx
13411 instr[30,25] = 01 1011
13412 instr[24] = op : 0 ==> TBZ, 1 == TBNZ
13413 instr[23,19] = b40 : bits 4 to 0 of test bit idx
13414 instr[18,5] = simm14 : signed offset counted in words
13415 instr[4,0] = uimm5 */
13417 uint32_t pos
= ((INSTR (31, 31) << 5) | INSTR (23, 19));
13418 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 18, 5) << 2;
13420 NYI_assert (30, 25, 0x1b);
13422 if (INSTR (24, 24) == 0)
13423 tbz (cpu
, pos
, offset
);
13425 tbnz (cpu
, pos
, offset
);
13429 dexCondBranchImmediate (sim_cpu
*cpu
)
13431 /* instr[31,25] = 010 1010
13432 instr[24] = op1; op => 00 ==> B.cond
13433 instr[23,5] = simm19 : signed offset counted in words
13435 instr[3,0] = cond */
13438 uint32_t op
= ((INSTR (24, 24) << 1) | INSTR (4, 4));
13440 NYI_assert (31, 25, 0x2a);
13445 offset
= simm32 (aarch64_get_instr (cpu
), 23, 5) << 2;
13447 bcc (cpu
, offset
, INSTR (3, 0));
13451 dexBranchRegister (sim_cpu
*cpu
)
13453 /* instr[31,25] = 110 1011
13454 instr[24,21] = op : 0 ==> BR, 1 => BLR, 2 => RET, 3 => ERET, 4 => DRPS
13455 instr[20,16] = op2 : must be 11111
13456 instr[15,10] = op3 : must be 000000
13457 instr[4,0] = op2 : must be 11111. */
13459 uint32_t op
= INSTR (24, 21);
13460 uint32_t op2
= INSTR (20, 16);
13461 uint32_t op3
= INSTR (15, 10);
13462 uint32_t op4
= INSTR (4, 0);
13464 NYI_assert (31, 25, 0x6b);
13466 if (op2
!= 0x1F || op3
!= 0 || op4
!= 0)
13480 /* ERET and DRPS accept 0b11111 for rn = instr [4,0]. */
13481 /* anything else is unallocated. */
13482 uint32_t rn
= INSTR (4, 0);
13487 if (op
== 4 || op
== 5)
13494 /* FIXME: We should get the Angel SWI values from ../../libgloss/aarch64/svc.h
13495 but this may not be available. So instead we define the values we need
13497 #define AngelSVC_Reason_Open 0x01
13498 #define AngelSVC_Reason_Close 0x02
13499 #define AngelSVC_Reason_Write 0x05
13500 #define AngelSVC_Reason_Read 0x06
13501 #define AngelSVC_Reason_IsTTY 0x09
13502 #define AngelSVC_Reason_Seek 0x0A
13503 #define AngelSVC_Reason_FLen 0x0C
13504 #define AngelSVC_Reason_Remove 0x0E
13505 #define AngelSVC_Reason_Rename 0x0F
13506 #define AngelSVC_Reason_Clock 0x10
13507 #define AngelSVC_Reason_Time 0x11
13508 #define AngelSVC_Reason_System 0x12
13509 #define AngelSVC_Reason_Errno 0x13
13510 #define AngelSVC_Reason_GetCmdLine 0x15
13511 #define AngelSVC_Reason_HeapInfo 0x16
13512 #define AngelSVC_Reason_ReportException 0x18
13513 #define AngelSVC_Reason_Elapsed 0x30
13517 handle_halt (sim_cpu
*cpu
, uint32_t val
)
13519 uint64_t result
= 0;
13521 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13524 TRACE_SYSCALL (cpu
, " HLT [0x%x]", val
);
13525 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13526 sim_stopped
, SIM_SIGTRAP
);
13529 /* We have encountered an Angel SVC call. See if we can process it. */
13530 switch (aarch64_get_reg_u32 (cpu
, 0, NO_SP
))
13532 case AngelSVC_Reason_HeapInfo
:
13534 /* Get the values. */
13535 uint64_t stack_top
= aarch64_get_stack_start (cpu
);
13536 uint64_t heap_base
= aarch64_get_heap_start (cpu
);
13538 /* Get the pointer */
13539 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13540 ptr
= aarch64_get_mem_u64 (cpu
, ptr
);
13542 /* Fill in the memory block. */
13543 /* Start addr of heap. */
13544 aarch64_set_mem_u64 (cpu
, ptr
+ 0, heap_base
);
13545 /* End addr of heap. */
13546 aarch64_set_mem_u64 (cpu
, ptr
+ 8, stack_top
);
13547 /* Lowest stack addr. */
13548 aarch64_set_mem_u64 (cpu
, ptr
+ 16, heap_base
);
13549 /* Initial stack addr. */
13550 aarch64_set_mem_u64 (cpu
, ptr
+ 24, stack_top
);
13552 TRACE_SYSCALL (cpu
, " AngelSVC: Get Heap Info");
13556 case AngelSVC_Reason_Open
:
13558 /* Get the pointer */
13559 /* uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);. */
13560 /* FIXME: For now we just assume that we will only be asked
13561 to open the standard file descriptors. */
13565 TRACE_SYSCALL (cpu
, " AngelSVC: Open file %d", fd
- 1);
13569 case AngelSVC_Reason_Close
:
13571 uint64_t fh
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13572 TRACE_SYSCALL (cpu
, " AngelSVC: Close file %d", (int) fh
);
13577 case AngelSVC_Reason_Errno
:
13579 TRACE_SYSCALL (cpu
, " AngelSVC: Get Errno");
13582 case AngelSVC_Reason_Clock
:
13584 #ifdef CLOCKS_PER_SEC
13585 (CLOCKS_PER_SEC
>= 100)
13586 ? (clock () / (CLOCKS_PER_SEC
/ 100))
13587 : ((clock () * 100) / CLOCKS_PER_SEC
)
13589 /* Presume unix... clock() returns microseconds. */
13593 TRACE_SYSCALL (cpu
, " AngelSVC: Get Clock");
13596 case AngelSVC_Reason_GetCmdLine
:
13598 /* Get the pointer */
13599 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13600 ptr
= aarch64_get_mem_u64 (cpu
, ptr
);
13602 /* FIXME: No command line for now. */
13603 aarch64_set_mem_u64 (cpu
, ptr
, 0);
13604 TRACE_SYSCALL (cpu
, " AngelSVC: Get Command Line");
13608 case AngelSVC_Reason_IsTTY
:
13610 TRACE_SYSCALL (cpu
, " AngelSVC: IsTTY ?");
13613 case AngelSVC_Reason_Write
:
13615 /* Get the pointer */
13616 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13617 /* Get the write control block. */
13618 uint64_t fd
= aarch64_get_mem_u64 (cpu
, ptr
);
13619 uint64_t buf
= aarch64_get_mem_u64 (cpu
, ptr
+ 8);
13620 uint64_t len
= aarch64_get_mem_u64 (cpu
, ptr
+ 16);
13622 TRACE_SYSCALL (cpu
, "write of %" PRIx64
" bytes from %"
13623 PRIx64
" on descriptor %" PRIx64
,
13628 TRACE_SYSCALL (cpu
,
13629 " AngelSVC: Write: Suspiciously long write: %ld",
13631 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13632 sim_stopped
, SIM_SIGBUS
);
13636 printf ("%.*s", (int) len
, aarch64_get_mem_ptr (cpu
, buf
));
13640 TRACE (cpu
, 0, "\n");
13641 sim_io_eprintf (CPU_STATE (cpu
), "%.*s",
13642 (int) len
, aarch64_get_mem_ptr (cpu
, buf
));
13643 TRACE (cpu
, 0, "\n");
13647 TRACE_SYSCALL (cpu
,
13648 " AngelSVC: Write: Unexpected file handle: %d",
13650 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13651 sim_stopped
, SIM_SIGABRT
);
13656 case AngelSVC_Reason_ReportException
:
13658 /* Get the pointer */
13659 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13660 /*ptr = aarch64_get_mem_u64 (cpu, ptr);. */
13661 uint64_t type
= aarch64_get_mem_u64 (cpu
, ptr
);
13662 uint64_t state
= aarch64_get_mem_u64 (cpu
, ptr
+ 8);
13664 TRACE_SYSCALL (cpu
,
13665 "Angel Exception: type 0x%" PRIx64
" state %" PRIx64
,
13668 if (type
== 0x20026)
13669 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13670 sim_exited
, state
);
13672 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13673 sim_stopped
, SIM_SIGINT
);
13677 case AngelSVC_Reason_Read
:
13678 case AngelSVC_Reason_FLen
:
13679 case AngelSVC_Reason_Seek
:
13680 case AngelSVC_Reason_Remove
:
13681 case AngelSVC_Reason_Time
:
13682 case AngelSVC_Reason_System
:
13683 case AngelSVC_Reason_Rename
:
13684 case AngelSVC_Reason_Elapsed
:
13686 TRACE_SYSCALL (cpu
, " HLT [Unknown angel %x]",
13687 aarch64_get_reg_u32 (cpu
, 0, NO_SP
));
13688 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13689 sim_stopped
, SIM_SIGTRAP
);
13692 aarch64_set_reg_u64 (cpu
, 0, NO_SP
, result
);
13696 dexExcpnGen (sim_cpu
*cpu
)
13698 /* instr[31:24] = 11010100
13699 instr[23,21] = opc : 000 ==> GEN EXCPN, 001 ==> BRK
13700 010 ==> HLT, 101 ==> DBG GEN EXCPN
13701 instr[20,5] = imm16
13702 instr[4,2] = opc2 000 ==> OK, ow ==> UNALLOC
13703 instr[1,0] = LL : discriminates opc */
13705 uint32_t opc
= INSTR (23, 21);
13706 uint32_t imm16
= INSTR (20, 5);
13707 uint32_t opc2
= INSTR (4, 2);
13710 NYI_assert (31, 24, 0xd4);
13717 /* We only implement HLT and BRK for now. */
13718 if (opc
== 1 && LL
== 0)
13720 TRACE_EVENTS (cpu
, " BRK [0x%x]", imm16
);
13721 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13722 sim_exited
, aarch64_get_reg_s32 (cpu
, R0
, SP_OK
));
13725 if (opc
== 2 && LL
== 0)
13726 handle_halt (cpu
, imm16
);
13728 else if (opc
== 0 || opc
== 5)
13735 /* Stub for accessing system registers. */
13738 system_get (sim_cpu
*cpu
, unsigned op0
, unsigned op1
, unsigned crn
,
13739 unsigned crm
, unsigned op2
)
13741 if (crn
== 0 && op1
== 3 && crm
== 0 && op2
== 7)
13742 /* DCZID_EL0 - the Data Cache Zero ID register.
13743 We do not support DC ZVA at the moment, so
13744 we return a value with the disable bit set.
13745 We implement support for the DCZID register since
13746 it is used by the C library's memset function. */
13747 return ((uint64_t) 1) << 4;
13749 if (crn
== 0 && op1
== 3 && crm
== 0 && op2
== 1)
13750 /* Cache Type Register. */
13751 return 0x80008000UL
;
13753 if (crn
== 13 && op1
== 3 && crm
== 0 && op2
== 2)
13754 /* TPIDR_EL0 - thread pointer id. */
13755 return aarch64_get_thread_id (cpu
);
13757 if (op1
== 3 && crm
== 4 && op2
== 0)
13758 return aarch64_get_FPCR (cpu
);
13760 if (op1
== 3 && crm
== 4 && op2
== 1)
13761 return aarch64_get_FPSR (cpu
);
13763 else if (op1
== 3 && crm
== 2 && op2
== 0)
13764 return aarch64_get_CPSR (cpu
);
13770 system_set (sim_cpu
*cpu
, unsigned op0
, unsigned op1
, unsigned crn
,
13771 unsigned crm
, unsigned op2
, uint64_t val
)
13773 if (op1
== 3 && crm
== 4 && op2
== 0)
13774 aarch64_set_FPCR (cpu
, val
);
13776 else if (op1
== 3 && crm
== 4 && op2
== 1)
13777 aarch64_set_FPSR (cpu
, val
);
13779 else if (op1
== 3 && crm
== 2 && op2
== 0)
13780 aarch64_set_CPSR (cpu
, val
);
13787 do_mrs (sim_cpu
*cpu
)
13789 /* instr[31:20] = 1101 0101 0001 1
13796 unsigned sys_op0
= INSTR (19, 19) + 2;
13797 unsigned sys_op1
= INSTR (18, 16);
13798 unsigned sys_crn
= INSTR (15, 12);
13799 unsigned sys_crm
= INSTR (11, 8);
13800 unsigned sys_op2
= INSTR (7, 5);
13801 unsigned rt
= INSTR (4, 0);
13803 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13804 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
13805 system_get (cpu
, sys_op0
, sys_op1
, sys_crn
, sys_crm
, sys_op2
));
13809 do_MSR_immediate (sim_cpu
*cpu
)
13811 /* instr[31:19] = 1101 0101 0000 0
13813 instr[15,12] = 0100
13816 instr[4,0] = 1 1111 */
13818 unsigned op1
= INSTR (18, 16);
13819 /*unsigned crm = INSTR (11, 8);*/
13820 unsigned op2
= INSTR (7, 5);
13822 NYI_assert (31, 19, 0x1AA0);
13823 NYI_assert (15, 12, 0x4);
13824 NYI_assert (4, 0, 0x1F);
13829 HALT_NYI
; /* set SPSel. */
13836 HALT_NYI
; /* set DAIFset. */
13838 HALT_NYI
; /* set DAIFclr. */
13847 do_MSR_reg (sim_cpu
*cpu
)
13849 /* instr[31:20] = 1101 0101 0001
13857 unsigned sys_op0
= INSTR (19, 19) + 2;
13858 unsigned sys_op1
= INSTR (18, 16);
13859 unsigned sys_crn
= INSTR (15, 12);
13860 unsigned sys_crm
= INSTR (11, 8);
13861 unsigned sys_op2
= INSTR (7, 5);
13862 unsigned rt
= INSTR (4, 0);
13864 NYI_assert (31, 20, 0xD51);
13866 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13867 system_set (cpu
, sys_op0
, sys_op1
, sys_crn
, sys_crm
, sys_op2
,
13868 aarch64_get_reg_u64 (cpu
, rt
, NO_SP
));
13872 do_SYS (sim_cpu
*cpu
)
13874 /* instr[31,19] = 1101 0101 0000 1
13880 NYI_assert (31, 19, 0x1AA1);
13882 /* FIXME: For now we just silently accept system ops. */
13886 dexSystem (sim_cpu
*cpu
)
13888 /* instr[31:22] = 1101 01010 0
13895 instr[4,0] = uimm5 */
13897 /* We are interested in HINT, DSB, DMB and ISB
13899 Hint #0 encodes NOOP (this is the only hint we care about)
13900 L == 0, op0 == 0, op1 = 011, CRn = 0010, Rt = 11111,
13901 CRm op2 != 0000 000 OR CRm op2 == 0000 000 || CRm op > 0000 101
13903 DSB, DMB, ISB are data store barrier, data memory barrier and
13904 instruction store barrier, respectively, where
13906 L == 0, op0 == 0, op1 = 011, CRn = 0011, Rt = 11111,
13907 op2 : DSB ==> 100, DMB ==> 101, ISB ==> 110
13908 CRm<3:2> ==> domain, CRm<1:0> ==> types,
13909 domain : 00 ==> OuterShareable, 01 ==> Nonshareable,
13910 10 ==> InerShareable, 11 ==> FullSystem
13911 types : 01 ==> Reads, 10 ==> Writes,
13912 11 ==> All, 00 ==> All (domain == FullSystem). */
13914 unsigned rt
= INSTR (4, 0);
13916 NYI_assert (31, 22, 0x354);
13918 switch (INSTR (21, 12))
13923 /* NOP has CRm != 0000 OR. */
13924 /* (CRm == 0000 AND (op2 == 000 OR op2 > 101)). */
13925 uint32_t crm
= INSTR (11, 8);
13926 uint32_t op2
= INSTR (7, 5);
13928 if (crm
!= 0 || (op2
== 0 || op2
> 5))
13930 /* Actually call nop method so we can reimplement it later. */
13939 uint32_t op2
= INSTR (7, 5);
13944 case 4: dsb (cpu
); return;
13945 case 5: dmb (cpu
); return;
13946 case 6: isb (cpu
); return;
13947 default: HALT_UNALLOC
;
13958 do_SYS (cpu
); /* DC is an alias of SYS. */
13962 if (INSTR (21, 20) == 0x1)
13964 else if (INSTR (21, 19) == 0 && INSTR (15, 12) == 0x4)
13965 do_MSR_immediate (cpu
);
13973 dexBr (sim_cpu
*cpu
)
13975 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
13976 assert group == GROUP_BREXSYS_1010 || group == GROUP_BREXSYS_1011
13977 bits [31,29] of a BrExSys are the secondary dispatch vector. */
13978 uint32_t group2
= dispatchBrExSys (aarch64_get_instr (cpu
));
13983 return dexBranchImmediate (cpu
);
13985 case BR_IMMCMP_001
:
13986 /* Compare has bit 25 clear while test has it set. */
13987 if (!INSTR (25, 25))
13988 dexCompareBranchImmediate (cpu
);
13990 dexTestBranchImmediate (cpu
);
13993 case BR_IMMCOND_010
:
13994 /* This is a conditional branch if bit 25 is clear otherwise
13996 if (!INSTR (25, 25))
13997 dexCondBranchImmediate (cpu
);
14002 case BR_UNALLOC_011
:
14006 dexBranchImmediate (cpu
);
14009 case BR_IMMCMP_101
:
14010 /* Compare has bit 25 clear while test has it set. */
14011 if (!INSTR (25, 25))
14012 dexCompareBranchImmediate (cpu
);
14014 dexTestBranchImmediate (cpu
);
14018 /* Unconditional branch reg has bit 25 set. */
14019 if (INSTR (25, 25))
14020 dexBranchRegister (cpu
);
14022 /* This includes both Excpn Gen, System and unalloc operations.
14023 We need to decode the Excpn Gen operation BRK so we can plant
14024 debugger entry points.
14025 Excpn Gen operations have instr [24] = 0.
14026 we need to decode at least one of the System operations NOP
14027 which is an alias for HINT #0.
14028 System operations have instr [24,22] = 100. */
14029 else if (INSTR (24, 24) == 0)
14032 else if (INSTR (24, 22) == 4)
14040 case BR_UNALLOC_111
:
14044 /* Should never reach here. */
14050 aarch64_decode_and_execute (sim_cpu
*cpu
, uint64_t pc
)
14052 /* We need to check if gdb wants an in here. */
14053 /* checkBreak (cpu);. */
14055 uint64_t group
= dispatchGroup (aarch64_get_instr (cpu
));
14059 case GROUP_PSEUDO_0000
: dexPseudo (cpu
); break;
14060 case GROUP_LDST_0100
: dexLdSt (cpu
); break;
14061 case GROUP_DPREG_0101
: dexDPReg (cpu
); break;
14062 case GROUP_LDST_0110
: dexLdSt (cpu
); break;
14063 case GROUP_ADVSIMD_0111
: dexAdvSIMD0 (cpu
); break;
14064 case GROUP_DPIMM_1000
: dexDPImm (cpu
); break;
14065 case GROUP_DPIMM_1001
: dexDPImm (cpu
); break;
14066 case GROUP_BREXSYS_1010
: dexBr (cpu
); break;
14067 case GROUP_BREXSYS_1011
: dexBr (cpu
); break;
14068 case GROUP_LDST_1100
: dexLdSt (cpu
); break;
14069 case GROUP_DPREG_1101
: dexDPReg (cpu
); break;
14070 case GROUP_LDST_1110
: dexLdSt (cpu
); break;
14071 case GROUP_ADVSIMD_1111
: dexAdvSIMD1 (cpu
); break;
14073 case GROUP_UNALLOC_0001
:
14074 case GROUP_UNALLOC_0010
:
14075 case GROUP_UNALLOC_0011
:
14079 /* Should never reach here. */
14085 aarch64_step (sim_cpu
*cpu
)
14087 uint64_t pc
= aarch64_get_PC (cpu
);
14089 if (pc
== TOP_LEVEL_RETURN_PC
)
14092 aarch64_set_next_PC (cpu
, pc
+ 4);
14094 /* Code is always little-endian. */
14095 sim_core_read_buffer (CPU_STATE (cpu
), cpu
, read_map
,
14096 & aarch64_get_instr (cpu
), pc
, 4);
14097 aarch64_get_instr (cpu
) = endian_le2h_4 (aarch64_get_instr (cpu
));
14099 TRACE_INSN (cpu
, " pc = %" PRIx64
" instr = %08x", pc
,
14100 aarch64_get_instr (cpu
));
14101 TRACE_DISASM (cpu
, pc
);
14103 aarch64_decode_and_execute (cpu
, pc
);
14109 aarch64_run (SIM_DESC sd
)
14111 sim_cpu
*cpu
= STATE_CPU (sd
, 0);
14113 while (aarch64_step (cpu
))
14115 aarch64_update_PC (cpu
);
14117 if (sim_events_tick (sd
))
14118 sim_events_process (sd
);
14121 sim_engine_halt (sd
, cpu
, NULL
, aarch64_get_PC (cpu
),
14122 sim_exited
, aarch64_get_reg_s32 (cpu
, R0
, NO_SP
));
14126 aarch64_init (sim_cpu
*cpu
, uint64_t pc
)
14128 uint64_t sp
= aarch64_get_stack_start (cpu
);
14130 /* Install SP, FP and PC and set LR to -20
14131 so we can detect a top-level return. */
14132 aarch64_set_reg_u64 (cpu
, SP
, SP_OK
, sp
);
14133 aarch64_set_reg_u64 (cpu
, FP
, SP_OK
, sp
);
14134 aarch64_set_reg_u64 (cpu
, LR
, SP_OK
, TOP_LEVEL_RETURN_PC
);
14135 aarch64_set_next_PC (cpu
, pc
);
14136 aarch64_update_PC (cpu
);
14137 aarch64_init_LIT_table ();