1 /* simulator.c -- Interface for the AArch64 simulator.
3 Copyright (C) 2015-2021 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/>. */
22 /* This must come before any other includes. */
28 #include <sys/types.h>
33 #include "simulator.h"
37 #include "sim-signal.h"
42 #define TST(_flag) (aarch64_test_CPSR_bit (cpu, _flag))
43 #define IS_SET(_X) (TST (( _X )) ? 1 : 0)
44 #define IS_CLEAR(_X) (TST (( _X )) ? 0 : 1)
46 /* Space saver macro. */
47 #define INSTR(HIGH, LOW) uimm (aarch64_get_instr (cpu), (HIGH), (LOW))
49 #define HALT_UNALLOC \
52 TRACE_DISASM (cpu, aarch64_get_PC (cpu)); \
54 "Unallocated instruction detected at sim line %d," \
55 " exe addr %" PRIx64, \
56 __LINE__, aarch64_get_PC (cpu)); \
57 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),\
58 sim_stopped, SIM_SIGILL); \
65 TRACE_DISASM (cpu, aarch64_get_PC (cpu)); \
67 "Unimplemented instruction detected at sim line %d," \
68 " exe addr %" PRIx64, \
69 __LINE__, aarch64_get_PC (cpu)); \
70 if (! TRACE_ANY_P (cpu)) \
71 sim_io_eprintf (CPU_STATE (cpu), "SIM Error: Unimplemented instruction: %#08x\n", \
72 aarch64_get_instr (cpu)); \
73 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),\
74 sim_stopped, SIM_SIGABRT); \
78 #define NYI_assert(HI, LO, EXPECTED) \
81 if (INSTR ((HI), (LO)) != (EXPECTED)) \
86 /* Helper functions used by expandLogicalImmediate. */
88 /* for i = 1, ... N result<i-1> = 1 other bits are zero */
89 static inline uint64_t
92 return (N
== 64 ? (uint64_t)-1UL : ((1UL << N
) - 1));
95 /* result<0> to val<N> */
96 static inline uint64_t
97 pickbit (uint64_t val
, int N
)
99 return pickbits64 (val
, N
, N
);
103 expand_logical_immediate (uint32_t S
, uint32_t R
, uint32_t N
)
109 /* The immediate value is S+1 bits to 1, left rotated by SIMDsize - R
110 (in other words, right rotated by R), then replicated. */
114 mask
= 0xffffffffffffffffull
;
120 case 0x00 ... 0x1f: /* 0xxxxx */ simd_size
= 32; break;
121 case 0x20 ... 0x2f: /* 10xxxx */ simd_size
= 16; S
&= 0xf; break;
122 case 0x30 ... 0x37: /* 110xxx */ simd_size
= 8; S
&= 0x7; break;
123 case 0x38 ... 0x3b: /* 1110xx */ simd_size
= 4; S
&= 0x3; break;
124 case 0x3c ... 0x3d: /* 11110x */ simd_size
= 2; S
&= 0x1; break;
127 mask
= (1ull << simd_size
) - 1;
128 /* Top bits are IGNORED. */
132 /* NOTE: if S = simd_size - 1 we get 0xf..f which is rejected. */
133 if (S
== simd_size
- 1)
136 /* S+1 consecutive bits to 1. */
137 /* NOTE: S can't be 63 due to detection above. */
138 imm
= (1ull << (S
+ 1)) - 1;
140 /* Rotate to the left by simd_size - R. */
142 imm
= ((imm
<< (simd_size
- R
)) & mask
) | (imm
>> R
);
144 /* Replicate the value according to SIMD size. */
147 case 2: imm
= (imm
<< 2) | imm
;
148 case 4: imm
= (imm
<< 4) | imm
;
149 case 8: imm
= (imm
<< 8) | imm
;
150 case 16: imm
= (imm
<< 16) | imm
;
151 case 32: imm
= (imm
<< 32) | imm
;
159 /* Instr[22,10] encodes N immr and imms. we want a lookup table
160 for each possible combination i.e. 13 bits worth of int entries. */
161 #define LI_TABLE_SIZE (1 << 13)
162 static uint64_t LITable
[LI_TABLE_SIZE
];
165 aarch64_init_LIT_table (void)
169 for (index
= 0; index
< LI_TABLE_SIZE
; index
++)
171 uint32_t N
= uimm (index
, 12, 12);
172 uint32_t immr
= uimm (index
, 11, 6);
173 uint32_t imms
= uimm (index
, 5, 0);
175 LITable
[index
] = expand_logical_immediate (imms
, immr
, N
);
180 dexNotify (sim_cpu
*cpu
)
182 /* instr[14,0] == type : 0 ==> method entry, 1 ==> method reentry
183 2 ==> exit Java, 3 ==> start next bytecode. */
184 uint32_t type
= INSTR (14, 0);
186 TRACE_EVENTS (cpu
, "Notify Insn encountered, type = 0x%x", type
);
191 /* aarch64_notifyMethodEntry (aarch64_get_reg_u64 (cpu, R23, 0),
192 aarch64_get_reg_u64 (cpu, R22, 0)); */
195 /* aarch64_notifyMethodReentry (aarch64_get_reg_u64 (cpu, R23, 0),
196 aarch64_get_reg_u64 (cpu, R22, 0)); */
199 /* aarch64_notifyMethodExit (); */
202 /* aarch64_notifyBCStart (aarch64_get_reg_u64 (cpu, R23, 0),
203 aarch64_get_reg_u64 (cpu, R22, 0)); */
208 /* secondary decode within top level groups */
211 dexPseudo (sim_cpu
*cpu
)
213 /* assert instr[28,27] = 00
215 We provide 2 pseudo instructions:
217 HALT stops execution of the simulator causing an immediate
218 return to the x86 code which entered it.
220 CALLOUT initiates recursive entry into x86 code. A register
221 argument holds the address of the x86 routine. Immediate
222 values in the instruction identify the number of general
223 purpose and floating point register arguments to be passed
224 and the type of any value to be returned. */
226 uint32_t PSEUDO_HALT
= 0xE0000000U
;
227 uint32_t PSEUDO_CALLOUT
= 0x00018000U
;
228 uint32_t PSEUDO_CALLOUTR
= 0x00018001U
;
229 uint32_t PSEUDO_NOTIFY
= 0x00014000U
;
232 if (aarch64_get_instr (cpu
) == PSEUDO_HALT
)
234 TRACE_EVENTS (cpu
, " Pseudo Halt Instruction");
235 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
236 sim_stopped
, SIM_SIGTRAP
);
239 dispatch
= INSTR (31, 15);
241 /* We do not handle callouts at the moment. */
242 if (dispatch
== PSEUDO_CALLOUT
|| dispatch
== PSEUDO_CALLOUTR
)
244 TRACE_EVENTS (cpu
, " Callout");
245 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
246 sim_stopped
, SIM_SIGABRT
);
249 else if (dispatch
== PSEUDO_NOTIFY
)
256 /* Load-store single register (unscaled offset)
257 These instructions employ a base register plus an unscaled signed
260 N.B. the base register (source) can be Xn or SP. all other
261 registers may not be SP. */
263 /* 32 bit load 32 bit unscaled signed 9 bit. */
265 ldur32 (sim_cpu
*cpu
, int32_t offset
)
267 unsigned rn
= INSTR (9, 5);
268 unsigned rt
= INSTR (4, 0);
270 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
271 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u32
272 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
276 /* 64 bit load 64 bit unscaled signed 9 bit. */
278 ldur64 (sim_cpu
*cpu
, int32_t offset
)
280 unsigned rn
= INSTR (9, 5);
281 unsigned rt
= INSTR (4, 0);
283 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
284 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u64
285 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
289 /* 32 bit load zero-extended byte unscaled signed 9 bit. */
291 ldurb32 (sim_cpu
*cpu
, int32_t offset
)
293 unsigned rn
= INSTR (9, 5);
294 unsigned rt
= INSTR (4, 0);
296 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
297 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u8
298 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
302 /* 32 bit load sign-extended byte unscaled signed 9 bit. */
304 ldursb32 (sim_cpu
*cpu
, int32_t offset
)
306 unsigned rn
= INSTR (9, 5);
307 unsigned rt
= INSTR (4, 0);
309 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
310 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, (uint32_t) aarch64_get_mem_s8
311 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
315 /* 64 bit load sign-extended byte unscaled signed 9 bit. */
317 ldursb64 (sim_cpu
*cpu
, int32_t offset
)
319 unsigned rn
= INSTR (9, 5);
320 unsigned rt
= INSTR (4, 0);
322 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
323 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, aarch64_get_mem_s8
324 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
328 /* 32 bit load zero-extended short unscaled signed 9 bit */
330 ldurh32 (sim_cpu
*cpu
, int32_t offset
)
332 unsigned rn
= INSTR (9, 5);
333 unsigned rd
= INSTR (4, 0);
335 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
336 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, aarch64_get_mem_u16
337 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
341 /* 32 bit load sign-extended short unscaled signed 9 bit */
343 ldursh32 (sim_cpu
*cpu
, int32_t offset
)
345 unsigned rn
= INSTR (9, 5);
346 unsigned rd
= INSTR (4, 0);
348 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
349 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) aarch64_get_mem_s16
350 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
354 /* 64 bit load sign-extended short unscaled signed 9 bit */
356 ldursh64 (sim_cpu
*cpu
, int32_t offset
)
358 unsigned rn
= INSTR (9, 5);
359 unsigned rt
= INSTR (4, 0);
361 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
362 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, aarch64_get_mem_s16
363 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
367 /* 64 bit load sign-extended word unscaled signed 9 bit */
369 ldursw (sim_cpu
*cpu
, int32_t offset
)
371 unsigned rn
= INSTR (9, 5);
372 unsigned rd
= INSTR (4, 0);
374 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
375 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) aarch64_get_mem_s32
376 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
380 /* N.B. with stores the value in source is written to the address
381 identified by source2 modified by offset. */
383 /* 32 bit store 32 bit unscaled signed 9 bit. */
385 stur32 (sim_cpu
*cpu
, int32_t offset
)
387 unsigned rn
= INSTR (9, 5);
388 unsigned rd
= INSTR (4, 0);
390 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
391 aarch64_set_mem_u32 (cpu
,
392 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
393 aarch64_get_reg_u32 (cpu
, rd
, NO_SP
));
396 /* 64 bit store 64 bit unscaled signed 9 bit */
398 stur64 (sim_cpu
*cpu
, int32_t offset
)
400 unsigned rn
= INSTR (9, 5);
401 unsigned rd
= INSTR (4, 0);
403 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
404 aarch64_set_mem_u64 (cpu
,
405 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
406 aarch64_get_reg_u64 (cpu
, rd
, NO_SP
));
409 /* 32 bit store byte unscaled signed 9 bit */
411 sturb (sim_cpu
*cpu
, int32_t offset
)
413 unsigned rn
= INSTR (9, 5);
414 unsigned rd
= INSTR (4, 0);
416 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
417 aarch64_set_mem_u8 (cpu
,
418 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
419 aarch64_get_reg_u8 (cpu
, rd
, NO_SP
));
422 /* 32 bit store short unscaled signed 9 bit */
424 sturh (sim_cpu
*cpu
, int32_t offset
)
426 unsigned rn
= INSTR (9, 5);
427 unsigned rd
= INSTR (4, 0);
429 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
430 aarch64_set_mem_u16 (cpu
,
431 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
432 aarch64_get_reg_u16 (cpu
, rd
, NO_SP
));
435 /* Load single register pc-relative label
436 Offset is a signed 19 bit immediate count in words
439 /* 32 bit pc-relative load */
441 ldr32_pcrel (sim_cpu
*cpu
, int32_t offset
)
443 unsigned rd
= INSTR (4, 0);
445 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
446 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
448 (cpu
, aarch64_get_PC (cpu
) + offset
* 4));
451 /* 64 bit pc-relative load */
453 ldr_pcrel (sim_cpu
*cpu
, int32_t offset
)
455 unsigned rd
= INSTR (4, 0);
457 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
458 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
460 (cpu
, aarch64_get_PC (cpu
) + offset
* 4));
463 /* sign extended 32 bit pc-relative load */
465 ldrsw_pcrel (sim_cpu
*cpu
, int32_t offset
)
467 unsigned rd
= INSTR (4, 0);
469 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
470 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
472 (cpu
, aarch64_get_PC (cpu
) + offset
* 4));
475 /* float pc-relative load */
477 fldrs_pcrel (sim_cpu
*cpu
, int32_t offset
)
479 unsigned int rd
= INSTR (4, 0);
481 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
482 aarch64_set_vec_u32 (cpu
, rd
, 0,
484 (cpu
, aarch64_get_PC (cpu
) + offset
* 4));
487 /* double pc-relative load */
489 fldrd_pcrel (sim_cpu
*cpu
, int32_t offset
)
491 unsigned int st
= INSTR (4, 0);
493 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
494 aarch64_set_vec_u64 (cpu
, st
, 0,
496 (cpu
, aarch64_get_PC (cpu
) + offset
* 4));
499 /* long double pc-relative load. */
501 fldrq_pcrel (sim_cpu
*cpu
, int32_t offset
)
503 unsigned int st
= INSTR (4, 0);
504 uint64_t addr
= aarch64_get_PC (cpu
) + offset
* 4;
507 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
508 aarch64_get_mem_long_double (cpu
, addr
, & a
);
509 aarch64_set_FP_long_double (cpu
, st
, a
);
512 /* This can be used to scale an offset by applying
513 the requisite shift. the second argument is either
516 #define SCALE(_offset, _elementSize) \
517 ((_offset) << ScaleShift ## _elementSize)
519 /* This can be used to optionally scale a register derived offset
520 by applying the requisite shift as indicated by the Scaling
521 argument. The second argument is either Byte, Short, Word
522 or Long. The third argument is either Scaled or Unscaled.
523 N.B. when _Scaling is Scaled the shift gets ANDed with
524 all 1s while when it is Unscaled it gets ANDed with 0. */
526 #define OPT_SCALE(_offset, _elementType, _Scaling) \
527 ((_offset) << (_Scaling ? ScaleShift ## _elementType : 0))
529 /* This can be used to zero or sign extend a 32 bit register derived
530 value to a 64 bit value. the first argument must be the value as
531 a uint32_t and the second must be either UXTW or SXTW. The result
532 is returned as an int64_t. */
534 static inline int64_t
535 extend (uint32_t value
, Extension extension
)
543 /* A branchless variant of this ought to be possible. */
544 if (extension
== UXTW
|| extension
== NoExtension
)
551 /* Scalar Floating Point
553 FP load/store single register (4 addressing modes)
555 N.B. the base register (source) can be the stack pointer.
556 The secondary source register (source2) can only be an Xn register. */
558 /* Load 32 bit unscaled signed 9 bit with pre- or post-writeback. */
560 fldrs_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
562 unsigned rn
= INSTR (9, 5);
563 unsigned st
= INSTR (4, 0);
564 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
569 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
570 aarch64_set_vec_u32 (cpu
, st
, 0, aarch64_get_mem_u32 (cpu
, address
));
574 if (wb
!= NoWriteBack
)
575 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
578 /* Load 8 bit with unsigned 12 bit offset. */
580 fldrb_abs (sim_cpu
*cpu
, uint32_t offset
)
582 unsigned rd
= INSTR (4, 0);
583 unsigned rn
= INSTR (9, 5);
584 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
;
586 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
587 aarch64_set_vec_u8 (cpu
, rd
, 0, aarch64_get_mem_u32 (cpu
, addr
));
590 /* Load 16 bit scaled unsigned 12 bit. */
592 fldrh_abs (sim_cpu
*cpu
, uint32_t offset
)
594 unsigned rd
= INSTR (4, 0);
595 unsigned rn
= INSTR (9, 5);
596 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 16);
598 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
599 aarch64_set_vec_u16 (cpu
, rd
, 0, aarch64_get_mem_u16 (cpu
, addr
));
602 /* Load 32 bit scaled unsigned 12 bit. */
604 fldrs_abs (sim_cpu
*cpu
, uint32_t offset
)
606 unsigned rd
= INSTR (4, 0);
607 unsigned rn
= INSTR (9, 5);
608 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 32);
610 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
611 aarch64_set_vec_u32 (cpu
, rd
, 0, aarch64_get_mem_u32 (cpu
, addr
));
614 /* Load 64 bit scaled unsigned 12 bit. */
616 fldrd_abs (sim_cpu
*cpu
, uint32_t offset
)
618 unsigned rd
= INSTR (4, 0);
619 unsigned rn
= INSTR (9, 5);
620 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 64);
622 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
623 aarch64_set_vec_u64 (cpu
, rd
, 0, aarch64_get_mem_u64 (cpu
, addr
));
626 /* Load 128 bit scaled unsigned 12 bit. */
628 fldrq_abs (sim_cpu
*cpu
, uint32_t offset
)
630 unsigned rd
= INSTR (4, 0);
631 unsigned rn
= INSTR (9, 5);
632 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 128);
634 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
635 aarch64_set_vec_u64 (cpu
, rd
, 0, aarch64_get_mem_u64 (cpu
, addr
));
636 aarch64_set_vec_u64 (cpu
, rd
, 1, aarch64_get_mem_u64 (cpu
, addr
+ 8));
639 /* Load 32 bit scaled or unscaled zero- or sign-extended
640 32-bit register offset. */
642 fldrs_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
644 unsigned rm
= INSTR (20, 16);
645 unsigned rn
= INSTR (9, 5);
646 unsigned st
= INSTR (4, 0);
647 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
648 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
649 uint64_t displacement
= OPT_SCALE (extended
, 32, scaling
);
651 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
652 aarch64_set_vec_u32 (cpu
, st
, 0, aarch64_get_mem_u32
653 (cpu
, address
+ displacement
));
656 /* Load 64 bit unscaled signed 9 bit with pre- or post-writeback. */
658 fldrd_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
660 unsigned rn
= INSTR (9, 5);
661 unsigned st
= INSTR (4, 0);
662 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
667 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
668 aarch64_set_vec_u64 (cpu
, st
, 0, aarch64_get_mem_u64 (cpu
, address
));
673 if (wb
!= NoWriteBack
)
674 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
677 /* Load 64 bit scaled or unscaled zero- or sign-extended 32-bit register offset. */
679 fldrd_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
681 unsigned rm
= INSTR (20, 16);
682 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
683 uint64_t displacement
= OPT_SCALE (extended
, 64, scaling
);
685 fldrd_wb (cpu
, displacement
, NoWriteBack
);
688 /* Load 128 bit unscaled signed 9 bit with pre- or post-writeback. */
690 fldrq_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
693 unsigned rn
= INSTR (9, 5);
694 unsigned st
= INSTR (4, 0);
695 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
700 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
701 aarch64_get_mem_long_double (cpu
, address
, & a
);
702 aarch64_set_FP_long_double (cpu
, st
, a
);
707 if (wb
!= NoWriteBack
)
708 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
711 /* Load 128 bit scaled or unscaled zero- or sign-extended 32-bit register offset */
713 fldrq_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
715 unsigned rm
= INSTR (20, 16);
716 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
717 uint64_t displacement
= OPT_SCALE (extended
, 128, scaling
);
719 fldrq_wb (cpu
, displacement
, NoWriteBack
);
724 load-store single register
725 There are four addressing modes available here which all employ a
726 64 bit source (base) register.
728 N.B. the base register (source) can be the stack pointer.
729 The secondary source register (source2)can only be an Xn register.
731 Scaled, 12-bit, unsigned immediate offset, without pre- and
733 Unscaled, 9-bit, signed immediate offset with pre- or post-index
735 scaled or unscaled 64-bit register offset.
736 scaled or unscaled 32-bit extended register offset.
738 All offsets are assumed to be raw from the decode i.e. the
739 simulator is expected to adjust scaled offsets based on the
740 accessed data size with register or extended register offset
741 versions the same applies except that in the latter case the
742 operation may also require a sign extend.
744 A separate method is provided for each possible addressing mode. */
746 /* 32 bit load 32 bit scaled unsigned 12 bit */
748 ldr32_abs (sim_cpu
*cpu
, uint32_t offset
)
750 unsigned rn
= INSTR (9, 5);
751 unsigned rt
= INSTR (4, 0);
753 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
754 /* The target register may not be SP but the source may be. */
755 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u32
756 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
757 + SCALE (offset
, 32)));
760 /* 32 bit load 32 bit unscaled signed 9 bit with pre- or post-writeback. */
762 ldr32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
764 unsigned rn
= INSTR (9, 5);
765 unsigned rt
= INSTR (4, 0);
768 if (rn
== rt
&& wb
!= NoWriteBack
)
771 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
776 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
777 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u32 (cpu
, address
));
782 if (wb
!= NoWriteBack
)
783 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
786 /* 32 bit load 32 bit scaled or unscaled
787 zero- or sign-extended 32-bit register offset */
789 ldr32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
791 unsigned rm
= INSTR (20, 16);
792 unsigned rn
= INSTR (9, 5);
793 unsigned rt
= INSTR (4, 0);
794 /* rn may reference SP, rm and rt must reference ZR */
796 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
797 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
798 uint64_t displacement
= OPT_SCALE (extended
, 32, scaling
);
800 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
801 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
802 aarch64_get_mem_u32 (cpu
, address
+ displacement
));
805 /* 64 bit load 64 bit scaled unsigned 12 bit */
807 ldr_abs (sim_cpu
*cpu
, uint32_t offset
)
809 unsigned rn
= INSTR (9, 5);
810 unsigned rt
= INSTR (4, 0);
812 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
813 /* The target register may not be SP but the source may be. */
814 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u64
815 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
816 + SCALE (offset
, 64)));
819 /* 64 bit load 64 bit unscaled signed 9 bit with pre- or post-writeback. */
821 ldr_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
823 unsigned rn
= INSTR (9, 5);
824 unsigned rt
= INSTR (4, 0);
827 if (rn
== rt
&& wb
!= NoWriteBack
)
830 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
835 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
836 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u64 (cpu
, address
));
841 if (wb
!= NoWriteBack
)
842 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
845 /* 64 bit load 64 bit scaled or unscaled zero-
846 or sign-extended 32-bit register offset. */
848 ldr_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
850 unsigned rm
= INSTR (20, 16);
851 unsigned rn
= INSTR (9, 5);
852 unsigned rt
= INSTR (4, 0);
853 /* rn may reference SP, rm and rt must reference ZR */
855 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
856 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
857 uint64_t displacement
= OPT_SCALE (extended
, 64, scaling
);
859 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
860 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
861 aarch64_get_mem_u64 (cpu
, address
+ displacement
));
864 /* 32 bit load zero-extended byte scaled unsigned 12 bit. */
866 ldrb32_abs (sim_cpu
*cpu
, uint32_t offset
)
868 unsigned rn
= INSTR (9, 5);
869 unsigned rt
= INSTR (4, 0);
871 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
872 /* The target register may not be SP but the source may be
873 there is no scaling required for a byte load. */
874 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
876 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
));
879 /* 32 bit load zero-extended byte unscaled signed 9 bit with pre- or post-writeback. */
881 ldrb32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
883 unsigned rn
= INSTR (9, 5);
884 unsigned rt
= INSTR (4, 0);
887 if (rn
== rt
&& wb
!= NoWriteBack
)
890 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
895 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
896 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u8 (cpu
, address
));
901 if (wb
!= NoWriteBack
)
902 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
905 /* 32 bit load zero-extended byte scaled or unscaled zero-
906 or sign-extended 32-bit register offset. */
908 ldrb32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
910 unsigned rm
= INSTR (20, 16);
911 unsigned rn
= INSTR (9, 5);
912 unsigned rt
= INSTR (4, 0);
913 /* rn may reference SP, rm and rt must reference ZR */
915 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
916 int64_t displacement
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
919 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
920 /* There is no scaling required for a byte load. */
921 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
922 aarch64_get_mem_u8 (cpu
, address
+ displacement
));
925 /* 64 bit load sign-extended byte unscaled signed 9 bit
926 with pre- or post-writeback. */
928 ldrsb_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
930 unsigned rn
= INSTR (9, 5);
931 unsigned rt
= INSTR (4, 0);
935 if (rn
== rt
&& wb
!= NoWriteBack
)
938 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
943 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
944 val
= aarch64_get_mem_s8 (cpu
, address
);
945 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, val
);
950 if (wb
!= NoWriteBack
)
951 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
954 /* 64 bit load sign-extended byte scaled unsigned 12 bit. */
956 ldrsb_abs (sim_cpu
*cpu
, uint32_t offset
)
958 ldrsb_wb (cpu
, offset
, NoWriteBack
);
961 /* 64 bit load sign-extended byte scaled or unscaled zero-
962 or sign-extended 32-bit register offset. */
964 ldrsb_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
966 unsigned rm
= INSTR (20, 16);
967 unsigned rn
= INSTR (9, 5);
968 unsigned rt
= INSTR (4, 0);
969 /* rn may reference SP, rm and rt must reference ZR */
971 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
972 int64_t displacement
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
974 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
975 /* There is no scaling required for a byte load. */
976 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
,
977 aarch64_get_mem_s8 (cpu
, address
+ displacement
));
980 /* 32 bit load zero-extended short scaled unsigned 12 bit. */
982 ldrh32_abs (sim_cpu
*cpu
, uint32_t offset
)
984 unsigned rn
= INSTR (9, 5);
985 unsigned rt
= INSTR (4, 0);
988 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
989 /* The target register may not be SP but the source may be. */
990 val
= aarch64_get_mem_u16 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
991 + SCALE (offset
, 16));
992 aarch64_set_reg_u32 (cpu
, rt
, NO_SP
, val
);
995 /* 32 bit load zero-extended short unscaled signed 9 bit
996 with pre- or post-writeback. */
998 ldrh32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1000 unsigned rn
= INSTR (9, 5);
1001 unsigned rt
= INSTR (4, 0);
1004 if (rn
== rt
&& wb
!= NoWriteBack
)
1007 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1012 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1013 aarch64_set_reg_u32 (cpu
, rt
, NO_SP
, aarch64_get_mem_u16 (cpu
, address
));
1018 if (wb
!= NoWriteBack
)
1019 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1022 /* 32 bit load zero-extended short scaled or unscaled zero-
1023 or sign-extended 32-bit register offset. */
1025 ldrh32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1027 unsigned rm
= INSTR (20, 16);
1028 unsigned rn
= INSTR (9, 5);
1029 unsigned rt
= INSTR (4, 0);
1030 /* rn may reference SP, rm and rt must reference ZR */
1032 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1033 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
1034 uint64_t displacement
= OPT_SCALE (extended
, 16, scaling
);
1036 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1037 aarch64_set_reg_u32 (cpu
, rt
, NO_SP
,
1038 aarch64_get_mem_u16 (cpu
, address
+ displacement
));
1041 /* 32 bit load sign-extended short scaled unsigned 12 bit. */
1043 ldrsh32_abs (sim_cpu
*cpu
, uint32_t offset
)
1045 unsigned rn
= INSTR (9, 5);
1046 unsigned rt
= INSTR (4, 0);
1049 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1050 /* The target register may not be SP but the source may be. */
1051 val
= aarch64_get_mem_s16 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
1052 + SCALE (offset
, 16));
1053 aarch64_set_reg_s32 (cpu
, rt
, NO_SP
, val
);
1056 /* 32 bit load sign-extended short unscaled signed 9 bit
1057 with pre- or post-writeback. */
1059 ldrsh32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1061 unsigned rn
= INSTR (9, 5);
1062 unsigned rt
= INSTR (4, 0);
1065 if (rn
== rt
&& wb
!= NoWriteBack
)
1068 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1073 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1074 aarch64_set_reg_s32 (cpu
, rt
, NO_SP
,
1075 (int32_t) aarch64_get_mem_s16 (cpu
, address
));
1080 if (wb
!= NoWriteBack
)
1081 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1084 /* 32 bit load sign-extended short scaled or unscaled zero-
1085 or sign-extended 32-bit register offset. */
1087 ldrsh32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1089 unsigned rm
= INSTR (20, 16);
1090 unsigned rn
= INSTR (9, 5);
1091 unsigned rt
= INSTR (4, 0);
1092 /* rn may reference SP, rm and rt must reference ZR */
1094 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1095 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
1096 uint64_t displacement
= OPT_SCALE (extended
, 16, scaling
);
1098 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1099 aarch64_set_reg_s32 (cpu
, rt
, NO_SP
,
1100 (int32_t) aarch64_get_mem_s16
1101 (cpu
, address
+ displacement
));
1104 /* 64 bit load sign-extended short scaled unsigned 12 bit. */
1106 ldrsh_abs (sim_cpu
*cpu
, uint32_t offset
)
1108 unsigned rn
= INSTR (9, 5);
1109 unsigned rt
= INSTR (4, 0);
1112 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1113 /* The target register may not be SP but the source may be. */
1114 val
= aarch64_get_mem_s16 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
1115 + SCALE (offset
, 16));
1116 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, val
);
1119 /* 64 bit load sign-extended short unscaled signed 9 bit
1120 with pre- or post-writeback. */
1122 ldrsh64_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1124 unsigned rn
= INSTR (9, 5);
1125 unsigned rt
= INSTR (4, 0);
1129 if (rn
== rt
&& wb
!= NoWriteBack
)
1132 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1133 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1138 val
= aarch64_get_mem_s16 (cpu
, address
);
1139 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, val
);
1144 if (wb
!= NoWriteBack
)
1145 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1148 /* 64 bit load sign-extended short scaled or unscaled zero-
1149 or sign-extended 32-bit register offset. */
1151 ldrsh_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1153 unsigned rm
= INSTR (20, 16);
1154 unsigned rn
= INSTR (9, 5);
1155 unsigned rt
= INSTR (4, 0);
1157 /* rn may reference SP, rm and rt must reference ZR */
1159 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1160 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
1161 uint64_t displacement
= OPT_SCALE (extended
, 16, scaling
);
1164 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1165 val
= aarch64_get_mem_s16 (cpu
, address
+ displacement
);
1166 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, val
);
1169 /* 64 bit load sign-extended 32 bit scaled unsigned 12 bit. */
1171 ldrsw_abs (sim_cpu
*cpu
, uint32_t offset
)
1173 unsigned rn
= INSTR (9, 5);
1174 unsigned rt
= INSTR (4, 0);
1177 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1178 val
= aarch64_get_mem_s32 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
1179 + SCALE (offset
, 32));
1180 /* The target register may not be SP but the source may be. */
1181 return aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, val
);
1184 /* 64 bit load sign-extended 32 bit unscaled signed 9 bit
1185 with pre- or post-writeback. */
1187 ldrsw_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1189 unsigned rn
= INSTR (9, 5);
1190 unsigned rt
= INSTR (4, 0);
1193 if (rn
== rt
&& wb
!= NoWriteBack
)
1196 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1201 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1202 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, aarch64_get_mem_s32 (cpu
, address
));
1207 if (wb
!= NoWriteBack
)
1208 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1211 /* 64 bit load sign-extended 32 bit scaled or unscaled zero-
1212 or sign-extended 32-bit register offset. */
1214 ldrsw_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1216 unsigned rm
= INSTR (20, 16);
1217 unsigned rn
= INSTR (9, 5);
1218 unsigned rt
= INSTR (4, 0);
1219 /* rn may reference SP, rm and rt must reference ZR */
1221 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1222 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
1223 uint64_t displacement
= OPT_SCALE (extended
, 32, scaling
);
1225 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1226 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
,
1227 aarch64_get_mem_s32 (cpu
, address
+ displacement
));
1230 /* N.B. with stores the value in source is written to the
1231 address identified by source2 modified by source3/offset. */
1233 /* 32 bit store scaled unsigned 12 bit. */
1235 str32_abs (sim_cpu
*cpu
, uint32_t offset
)
1237 unsigned rn
= INSTR (9, 5);
1238 unsigned rt
= INSTR (4, 0);
1240 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1241 /* The target register may not be SP but the source may be. */
1242 aarch64_set_mem_u32 (cpu
, (aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
1243 + SCALE (offset
, 32)),
1244 aarch64_get_reg_u32 (cpu
, rt
, NO_SP
));
1247 /* 32 bit store unscaled signed 9 bit with pre- or post-writeback. */
1249 str32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1251 unsigned rn
= INSTR (9, 5);
1252 unsigned rt
= INSTR (4, 0);
1255 if (rn
== rt
&& wb
!= NoWriteBack
)
1258 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1262 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1263 aarch64_set_mem_u32 (cpu
, address
, aarch64_get_reg_u32 (cpu
, rt
, NO_SP
));
1268 if (wb
!= NoWriteBack
)
1269 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1272 /* 32 bit store scaled or unscaled zero- or
1273 sign-extended 32-bit register offset. */
1275 str32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1277 unsigned rm
= INSTR (20, 16);
1278 unsigned rn
= INSTR (9, 5);
1279 unsigned rt
= INSTR (4, 0);
1281 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1282 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
1283 uint64_t displacement
= OPT_SCALE (extended
, 32, scaling
);
1285 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1286 aarch64_set_mem_u32 (cpu
, address
+ displacement
,
1287 aarch64_get_reg_u64 (cpu
, rt
, NO_SP
));
1290 /* 64 bit store scaled unsigned 12 bit. */
1292 str_abs (sim_cpu
*cpu
, uint32_t offset
)
1294 unsigned rn
= INSTR (9, 5);
1295 unsigned rt
= INSTR (4, 0);
1297 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1298 aarch64_set_mem_u64 (cpu
,
1299 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
1300 + SCALE (offset
, 64),
1301 aarch64_get_reg_u64 (cpu
, rt
, NO_SP
));
1304 /* 64 bit store unscaled signed 9 bit with pre- or post-writeback. */
1306 str_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1308 unsigned rn
= INSTR (9, 5);
1309 unsigned rt
= INSTR (4, 0);
1312 if (rn
== rt
&& wb
!= NoWriteBack
)
1315 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1320 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1321 aarch64_set_mem_u64 (cpu
, address
, aarch64_get_reg_u64 (cpu
, rt
, NO_SP
));
1326 if (wb
!= NoWriteBack
)
1327 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1330 /* 64 bit store scaled or unscaled zero-
1331 or sign-extended 32-bit register offset. */
1333 str_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1335 unsigned rm
= INSTR (20, 16);
1336 unsigned rn
= INSTR (9, 5);
1337 unsigned rt
= INSTR (4, 0);
1338 /* rn may reference SP, rm and rt must reference ZR */
1340 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1341 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
1343 uint64_t displacement
= OPT_SCALE (extended
, 64, scaling
);
1345 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1346 aarch64_set_mem_u64 (cpu
, address
+ displacement
,
1347 aarch64_get_reg_u64 (cpu
, rt
, NO_SP
));
1350 /* 32 bit store byte scaled unsigned 12 bit. */
1352 strb_abs (sim_cpu
*cpu
, uint32_t offset
)
1354 unsigned rn
= INSTR (9, 5);
1355 unsigned rt
= INSTR (4, 0);
1357 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1358 /* The target register may not be SP but the source may be.
1359 There is no scaling required for a byte load. */
1360 aarch64_set_mem_u8 (cpu
,
1361 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
1362 aarch64_get_reg_u8 (cpu
, rt
, NO_SP
));
1365 /* 32 bit store byte unscaled signed 9 bit with pre- or post-writeback. */
1367 strb_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1369 unsigned rn
= INSTR (9, 5);
1370 unsigned rt
= INSTR (4, 0);
1373 if (rn
== rt
&& wb
!= NoWriteBack
)
1376 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1381 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1382 aarch64_set_mem_u8 (cpu
, address
, aarch64_get_reg_u8 (cpu
, rt
, NO_SP
));
1387 if (wb
!= NoWriteBack
)
1388 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1391 /* 32 bit store byte scaled or unscaled zero-
1392 or sign-extended 32-bit register offset. */
1394 strb_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1396 unsigned rm
= INSTR (20, 16);
1397 unsigned rn
= INSTR (9, 5);
1398 unsigned rt
= INSTR (4, 0);
1399 /* rn may reference SP, rm and rt must reference ZR */
1401 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1402 int64_t displacement
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
1405 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1406 /* There is no scaling required for a byte load. */
1407 aarch64_set_mem_u8 (cpu
, address
+ displacement
,
1408 aarch64_get_reg_u8 (cpu
, rt
, NO_SP
));
1411 /* 32 bit store short scaled unsigned 12 bit. */
1413 strh_abs (sim_cpu
*cpu
, uint32_t offset
)
1415 unsigned rn
= INSTR (9, 5);
1416 unsigned rt
= INSTR (4, 0);
1418 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1419 /* The target register may not be SP but the source may be. */
1420 aarch64_set_mem_u16 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
1421 + SCALE (offset
, 16),
1422 aarch64_get_reg_u16 (cpu
, rt
, NO_SP
));
1425 /* 32 bit store short unscaled signed 9 bit with pre- or post-writeback. */
1427 strh_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1429 unsigned rn
= INSTR (9, 5);
1430 unsigned rt
= INSTR (4, 0);
1433 if (rn
== rt
&& wb
!= NoWriteBack
)
1436 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1441 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1442 aarch64_set_mem_u16 (cpu
, address
, aarch64_get_reg_u16 (cpu
, rt
, NO_SP
));
1447 if (wb
!= NoWriteBack
)
1448 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1451 /* 32 bit store short scaled or unscaled zero-
1452 or sign-extended 32-bit register offset. */
1454 strh_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1456 unsigned rm
= INSTR (20, 16);
1457 unsigned rn
= INSTR (9, 5);
1458 unsigned rt
= INSTR (4, 0);
1459 /* rn may reference SP, rm and rt must reference ZR */
1461 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1462 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
1463 uint64_t displacement
= OPT_SCALE (extended
, 16, scaling
);
1465 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1466 aarch64_set_mem_u16 (cpu
, address
+ displacement
,
1467 aarch64_get_reg_u16 (cpu
, rt
, NO_SP
));
1470 /* Prefetch unsigned 12 bit. */
1472 prfm_abs (sim_cpu
*cpu
, uint32_t offset
)
1474 /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1475 00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1476 00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1477 10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1478 10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1479 10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1481 PrfOp prfop = prfop (instr, 4, 0);
1482 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK)
1483 + SCALE (offset, 64). */
1485 /* TODO : implement prefetch of address. */
1488 /* Prefetch scaled or unscaled zero- or sign-extended 32-bit register offset. */
1490 prfm_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1492 /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1493 00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1494 00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1495 10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1496 10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1497 10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1499 rn may reference SP, rm may only reference ZR
1500 PrfOp prfop = prfop (instr, 4, 0);
1501 uint64_t base = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1502 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1504 uint64_t displacement = OPT_SCALE (extended, 64, scaling);
1505 uint64_t address = base + displacement. */
1507 /* TODO : implement prefetch of address */
1510 /* 64 bit pc-relative prefetch. */
1512 prfm_pcrel (sim_cpu
*cpu
, int32_t offset
)
1514 /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1515 00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1516 00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1517 10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1518 10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1519 10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1521 PrfOp prfop = prfop (instr, 4, 0);
1522 uint64_t address = aarch64_get_PC (cpu) + offset. */
1524 /* TODO : implement this */
1527 /* Load-store exclusive. */
1532 unsigned rn
= INSTR (9, 5);
1533 unsigned rt
= INSTR (4, 0);
1534 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1535 int size
= INSTR (31, 30);
1536 /* int ordered = INSTR (15, 15); */
1537 /* int exclusive = ! INSTR (23, 23); */
1539 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1543 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u8 (cpu
, address
));
1546 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u16 (cpu
, address
));
1549 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u32 (cpu
, address
));
1552 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u64 (cpu
, address
));
1560 unsigned rn
= INSTR (9, 5);
1561 unsigned rt
= INSTR (4, 0);
1562 unsigned rs
= INSTR (20, 16);
1563 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1564 int size
= INSTR (31, 30);
1565 uint64_t data
= aarch64_get_reg_u64 (cpu
, rt
, NO_SP
);
1569 case 0: aarch64_set_mem_u8 (cpu
, address
, data
); break;
1570 case 1: aarch64_set_mem_u16 (cpu
, address
, data
); break;
1571 case 2: aarch64_set_mem_u32 (cpu
, address
, data
); break;
1572 case 3: aarch64_set_mem_u64 (cpu
, address
, data
); break;
1575 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1576 aarch64_set_reg_u64 (cpu
, rs
, NO_SP
, 0); /* Always exclusive... */
1580 dexLoadLiteral (sim_cpu
*cpu
)
1582 /* instr[29,27] == 011
1584 instr[31,30:26] = opc: 000 ==> LDRW, 001 ==> FLDRS
1585 010 ==> LDRX, 011 ==> FLDRD
1586 100 ==> LDRSW, 101 ==> FLDRQ
1587 110 ==> PRFM, 111 ==> UNALLOC
1588 instr[26] ==> V : 0 ==> GReg, 1 ==> FReg
1589 instr[23, 5] == simm19 */
1591 /* unsigned rt = INSTR (4, 0); */
1592 uint32_t dispatch
= (INSTR (31, 30) << 1) | INSTR (26, 26);
1593 int32_t imm
= simm32 (aarch64_get_instr (cpu
), 23, 5);
1597 case 0: ldr32_pcrel (cpu
, imm
); break;
1598 case 1: fldrs_pcrel (cpu
, imm
); break;
1599 case 2: ldr_pcrel (cpu
, imm
); break;
1600 case 3: fldrd_pcrel (cpu
, imm
); break;
1601 case 4: ldrsw_pcrel (cpu
, imm
); break;
1602 case 5: fldrq_pcrel (cpu
, imm
); break;
1603 case 6: prfm_pcrel (cpu
, imm
); break;
1610 /* Immediate arithmetic
1611 The aimm argument is a 12 bit unsigned value or a 12 bit unsigned
1612 value left shifted by 12 bits (done at decode).
1614 N.B. the register args (dest, source) can normally be Xn or SP.
1615 the exception occurs for flag setting instructions which may
1616 only use Xn for the output (dest). */
1618 /* 32 bit add immediate. */
1620 add32 (sim_cpu
*cpu
, uint32_t aimm
)
1622 unsigned rn
= INSTR (9, 5);
1623 unsigned rd
= INSTR (4, 0);
1625 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1626 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
1627 aarch64_get_reg_u32 (cpu
, rn
, SP_OK
) + aimm
);
1630 /* 64 bit add immediate. */
1632 add64 (sim_cpu
*cpu
, uint32_t aimm
)
1634 unsigned rn
= INSTR (9, 5);
1635 unsigned rd
= INSTR (4, 0);
1637 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1638 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
1639 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + aimm
);
1643 set_flags_for_add32 (sim_cpu
*cpu
, int32_t value1
, int32_t value2
)
1645 int32_t result
= value1
+ value2
;
1646 int64_t sresult
= (int64_t) value1
+ (int64_t) value2
;
1647 uint64_t uresult
= (uint64_t)(uint32_t) value1
1648 + (uint64_t)(uint32_t) value2
;
1654 if (result
& (1 << 31))
1657 if (uresult
!= (uint32_t)uresult
)
1660 if (sresult
!= (int32_t)sresult
)
1663 aarch64_set_CPSR (cpu
, flags
);
1666 #define NEG(a) (((a) & signbit) == signbit)
1667 #define POS(a) (((a) & signbit) == 0)
1670 set_flags_for_add64 (sim_cpu
*cpu
, uint64_t value1
, uint64_t value2
)
1672 uint64_t result
= value1
+ value2
;
1674 uint64_t signbit
= 1ULL << 63;
1682 if ( (NEG (value1
) && NEG (value2
))
1683 || (NEG (value1
) && POS (result
))
1684 || (NEG (value2
) && POS (result
)))
1687 if ( (NEG (value1
) && NEG (value2
) && POS (result
))
1688 || (POS (value1
) && POS (value2
) && NEG (result
)))
1691 aarch64_set_CPSR (cpu
, flags
);
1695 set_flags_for_sub32 (sim_cpu
*cpu
, uint32_t value1
, uint32_t value2
)
1697 uint32_t result
= value1
- value2
;
1699 uint32_t signbit
= 1U << 31;
1707 if ( (NEG (value1
) && POS (value2
))
1708 || (NEG (value1
) && POS (result
))
1709 || (POS (value2
) && POS (result
)))
1712 if ( (NEG (value1
) && POS (value2
) && POS (result
))
1713 || (POS (value1
) && NEG (value2
) && NEG (result
)))
1716 aarch64_set_CPSR (cpu
, flags
);
1720 set_flags_for_sub64 (sim_cpu
*cpu
, uint64_t value1
, uint64_t value2
)
1722 uint64_t result
= value1
- value2
;
1724 uint64_t signbit
= 1ULL << 63;
1732 if ( (NEG (value1
) && POS (value2
))
1733 || (NEG (value1
) && POS (result
))
1734 || (POS (value2
) && POS (result
)))
1737 if ( (NEG (value1
) && POS (value2
) && POS (result
))
1738 || (POS (value1
) && NEG (value2
) && NEG (result
)))
1741 aarch64_set_CPSR (cpu
, flags
);
1745 set_flags_for_binop32 (sim_cpu
*cpu
, uint32_t result
)
1754 if (result
& (1 << 31))
1759 aarch64_set_CPSR (cpu
, flags
);
1763 set_flags_for_binop64 (sim_cpu
*cpu
, uint64_t result
)
1772 if (result
& (1ULL << 63))
1777 aarch64_set_CPSR (cpu
, flags
);
1780 /* 32 bit add immediate set flags. */
1782 adds32 (sim_cpu
*cpu
, uint32_t aimm
)
1784 unsigned rn
= INSTR (9, 5);
1785 unsigned rd
= INSTR (4, 0);
1786 /* TODO : do we need to worry about signs here? */
1787 int32_t value1
= aarch64_get_reg_s32 (cpu
, rn
, SP_OK
);
1789 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1790 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ aimm
);
1791 set_flags_for_add32 (cpu
, value1
, aimm
);
1794 /* 64 bit add immediate set flags. */
1796 adds64 (sim_cpu
*cpu
, uint32_t aimm
)
1798 unsigned rn
= INSTR (9, 5);
1799 unsigned rd
= INSTR (4, 0);
1800 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1801 uint64_t value2
= aimm
;
1803 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1804 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
);
1805 set_flags_for_add64 (cpu
, value1
, value2
);
1808 /* 32 bit sub immediate. */
1810 sub32 (sim_cpu
*cpu
, uint32_t aimm
)
1812 unsigned rn
= INSTR (9, 5);
1813 unsigned rd
= INSTR (4, 0);
1815 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1816 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
1817 aarch64_get_reg_u32 (cpu
, rn
, SP_OK
) - aimm
);
1820 /* 64 bit sub immediate. */
1822 sub64 (sim_cpu
*cpu
, uint32_t aimm
)
1824 unsigned rn
= INSTR (9, 5);
1825 unsigned rd
= INSTR (4, 0);
1827 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1828 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
1829 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) - aimm
);
1832 /* 32 bit sub immediate set flags. */
1834 subs32 (sim_cpu
*cpu
, uint32_t aimm
)
1836 unsigned rn
= INSTR (9, 5);
1837 unsigned rd
= INSTR (4, 0);
1838 uint32_t value1
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1839 uint32_t value2
= aimm
;
1841 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1842 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
1843 set_flags_for_sub32 (cpu
, value1
, value2
);
1846 /* 64 bit sub immediate set flags. */
1848 subs64 (sim_cpu
*cpu
, uint32_t aimm
)
1850 unsigned rn
= INSTR (9, 5);
1851 unsigned rd
= INSTR (4, 0);
1852 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1853 uint32_t value2
= aimm
;
1855 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1856 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
1857 set_flags_for_sub64 (cpu
, value1
, value2
);
1860 /* Data Processing Register. */
1862 /* First two helpers to perform the shift operations. */
1864 static inline uint32_t
1865 shifted32 (uint32_t value
, Shift shift
, uint32_t count
)
1871 return (value
<< count
);
1873 return (value
>> count
);
1876 int32_t svalue
= value
;
1877 return (svalue
>> count
);
1881 uint32_t top
= value
>> count
;
1882 uint32_t bottom
= value
<< (32 - count
);
1883 return (bottom
| top
);
1888 static inline uint64_t
1889 shifted64 (uint64_t value
, Shift shift
, uint32_t count
)
1895 return (value
<< count
);
1897 return (value
>> count
);
1900 int64_t svalue
= value
;
1901 return (svalue
>> count
);
1905 uint64_t top
= value
>> count
;
1906 uint64_t bottom
= value
<< (64 - count
);
1907 return (bottom
| top
);
1912 /* Arithmetic shifted register.
1913 These allow an optional LSL, ASR or LSR to the second source
1914 register with a count up to the register bit count.
1916 N.B register args may not be SP. */
1918 /* 32 bit ADD shifted register. */
1920 add32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1922 unsigned rm
= INSTR (20, 16);
1923 unsigned rn
= INSTR (9, 5);
1924 unsigned rd
= INSTR (4, 0);
1926 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1927 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
1928 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
1929 + shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
1933 /* 64 bit ADD shifted register. */
1935 add64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1937 unsigned rm
= INSTR (20, 16);
1938 unsigned rn
= INSTR (9, 5);
1939 unsigned rd
= INSTR (4, 0);
1941 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1942 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
1943 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
1944 + shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
1948 /* 32 bit ADD shifted register setting flags. */
1950 adds32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1952 unsigned rm
= INSTR (20, 16);
1953 unsigned rn
= INSTR (9, 5);
1954 unsigned rd
= INSTR (4, 0);
1956 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
1957 uint32_t value2
= shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
1960 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1961 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
);
1962 set_flags_for_add32 (cpu
, value1
, value2
);
1965 /* 64 bit ADD shifted register setting flags. */
1967 adds64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1969 unsigned rm
= INSTR (20, 16);
1970 unsigned rn
= INSTR (9, 5);
1971 unsigned rd
= INSTR (4, 0);
1973 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
1974 uint64_t value2
= shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
1977 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1978 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
);
1979 set_flags_for_add64 (cpu
, value1
, value2
);
1982 /* 32 bit SUB shifted register. */
1984 sub32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1986 unsigned rm
= INSTR (20, 16);
1987 unsigned rn
= INSTR (9, 5);
1988 unsigned rd
= INSTR (4, 0);
1990 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1991 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
1992 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
1993 - shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
1997 /* 64 bit SUB shifted register. */
1999 sub64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
2001 unsigned rm
= INSTR (20, 16);
2002 unsigned rn
= INSTR (9, 5);
2003 unsigned rd
= INSTR (4, 0);
2005 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2006 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
2007 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
2008 - shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
2012 /* 32 bit SUB shifted register setting flags. */
2014 subs32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
2016 unsigned rm
= INSTR (20, 16);
2017 unsigned rn
= INSTR (9, 5);
2018 unsigned rd
= INSTR (4, 0);
2020 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
2021 uint32_t value2
= shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
2024 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2025 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
2026 set_flags_for_sub32 (cpu
, value1
, value2
);
2029 /* 64 bit SUB shifted register setting flags. */
2031 subs64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
2033 unsigned rm
= INSTR (20, 16);
2034 unsigned rn
= INSTR (9, 5);
2035 unsigned rd
= INSTR (4, 0);
2037 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
2038 uint64_t value2
= shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
2041 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2042 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
2043 set_flags_for_sub64 (cpu
, value1
, value2
);
2046 /* First a couple more helpers to fetch the
2047 relevant source register element either
2048 sign or zero extended as required by the
2052 extreg32 (sim_cpu
*cpu
, unsigned int lo
, Extension extension
)
2056 case UXTB
: return aarch64_get_reg_u8 (cpu
, lo
, NO_SP
);
2057 case UXTH
: return aarch64_get_reg_u16 (cpu
, lo
, NO_SP
);
2058 case UXTW
: /* Fall through. */
2059 case UXTX
: return aarch64_get_reg_u32 (cpu
, lo
, NO_SP
);
2060 case SXTB
: return aarch64_get_reg_s8 (cpu
, lo
, NO_SP
);
2061 case SXTH
: return aarch64_get_reg_s16 (cpu
, lo
, NO_SP
);
2062 case SXTW
: /* Fall through. */
2063 case SXTX
: /* Fall through. */
2064 default: return aarch64_get_reg_s32 (cpu
, lo
, NO_SP
);
2069 extreg64 (sim_cpu
*cpu
, unsigned int lo
, Extension extension
)
2073 case UXTB
: return aarch64_get_reg_u8 (cpu
, lo
, NO_SP
);
2074 case UXTH
: return aarch64_get_reg_u16 (cpu
, lo
, NO_SP
);
2075 case UXTW
: return aarch64_get_reg_u32 (cpu
, lo
, NO_SP
);
2076 case UXTX
: return aarch64_get_reg_u64 (cpu
, lo
, NO_SP
);
2077 case SXTB
: return aarch64_get_reg_s8 (cpu
, lo
, NO_SP
);
2078 case SXTH
: return aarch64_get_reg_s16 (cpu
, lo
, NO_SP
);
2079 case SXTW
: return aarch64_get_reg_s32 (cpu
, lo
, NO_SP
);
2081 default: return aarch64_get_reg_s64 (cpu
, lo
, NO_SP
);
2085 /* Arithmetic extending register
2086 These allow an optional sign extension of some portion of the
2087 second source register followed by an optional left shift of
2088 between 1 and 4 bits (i.e. a shift of 0-4 bits???)
2090 N.B output (dest) and first input arg (source) may normally be Xn
2091 or SP. However, for flag setting operations dest can only be
2092 Xn. Second input registers are always Xn. */
2094 /* 32 bit ADD extending register. */
2096 add32_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2098 unsigned rm
= INSTR (20, 16);
2099 unsigned rn
= INSTR (9, 5);
2100 unsigned rd
= INSTR (4, 0);
2102 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2103 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
2104 aarch64_get_reg_u32 (cpu
, rn
, SP_OK
)
2105 + (extreg32 (cpu
, rm
, extension
) << shift
));
2108 /* 64 bit ADD extending register.
2109 N.B. This subsumes the case with 64 bit source2 and UXTX #n or LSL #0. */
2111 add64_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2113 unsigned rm
= INSTR (20, 16);
2114 unsigned rn
= INSTR (9, 5);
2115 unsigned rd
= INSTR (4, 0);
2117 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2118 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
2119 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
2120 + (extreg64 (cpu
, rm
, extension
) << shift
));
2123 /* 32 bit ADD extending register setting flags. */
2125 adds32_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2127 unsigned rm
= INSTR (20, 16);
2128 unsigned rn
= INSTR (9, 5);
2129 unsigned rd
= INSTR (4, 0);
2131 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, SP_OK
);
2132 uint32_t value2
= extreg32 (cpu
, rm
, extension
) << shift
;
2134 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2135 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
);
2136 set_flags_for_add32 (cpu
, value1
, value2
);
2139 /* 64 bit ADD extending register setting flags */
2140 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0 */
2142 adds64_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2144 unsigned rm
= INSTR (20, 16);
2145 unsigned rn
= INSTR (9, 5);
2146 unsigned rd
= INSTR (4, 0);
2148 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
2149 uint64_t value2
= extreg64 (cpu
, rm
, extension
) << shift
;
2151 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2152 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
);
2153 set_flags_for_add64 (cpu
, value1
, value2
);
2156 /* 32 bit SUB extending register. */
2158 sub32_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2160 unsigned rm
= INSTR (20, 16);
2161 unsigned rn
= INSTR (9, 5);
2162 unsigned rd
= INSTR (4, 0);
2164 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2165 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
2166 aarch64_get_reg_u32 (cpu
, rn
, SP_OK
)
2167 - (extreg32 (cpu
, rm
, extension
) << shift
));
2170 /* 64 bit SUB extending register. */
2171 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0. */
2173 sub64_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2175 unsigned rm
= INSTR (20, 16);
2176 unsigned rn
= INSTR (9, 5);
2177 unsigned rd
= INSTR (4, 0);
2179 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2180 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
2181 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
2182 - (extreg64 (cpu
, rm
, extension
) << shift
));
2185 /* 32 bit SUB extending register setting flags. */
2187 subs32_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2189 unsigned rm
= INSTR (20, 16);
2190 unsigned rn
= INSTR (9, 5);
2191 unsigned rd
= INSTR (4, 0);
2193 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, SP_OK
);
2194 uint32_t value2
= extreg32 (cpu
, rm
, extension
) << shift
;
2196 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2197 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
2198 set_flags_for_sub32 (cpu
, value1
, value2
);
2201 /* 64 bit SUB extending register setting flags */
2202 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0 */
2204 subs64_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2206 unsigned rm
= INSTR (20, 16);
2207 unsigned rn
= INSTR (9, 5);
2208 unsigned rd
= INSTR (4, 0);
2210 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
2211 uint64_t value2
= extreg64 (cpu
, rm
, extension
) << shift
;
2213 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2214 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
2215 set_flags_for_sub64 (cpu
, value1
, value2
);
2219 dexAddSubtractImmediate (sim_cpu
*cpu
)
2221 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2222 instr[30] = op : 0 ==> ADD, 1 ==> SUB
2223 instr[29] = set : 0 ==> no flags, 1 ==> set flags
2224 instr[28,24] = 10001
2225 instr[23,22] = shift : 00 == LSL#0, 01 = LSL#12 1x = UNALLOC
2226 instr[21,10] = uimm12
2230 /* N.B. the shift is applied at decode before calling the add/sub routine. */
2231 uint32_t shift
= INSTR (23, 22);
2232 uint32_t imm
= INSTR (21, 10);
2233 uint32_t dispatch
= INSTR (31, 29);
2235 NYI_assert (28, 24, 0x11);
2245 case 0: add32 (cpu
, imm
); break;
2246 case 1: adds32 (cpu
, imm
); break;
2247 case 2: sub32 (cpu
, imm
); break;
2248 case 3: subs32 (cpu
, imm
); break;
2249 case 4: add64 (cpu
, imm
); break;
2250 case 5: adds64 (cpu
, imm
); break;
2251 case 6: sub64 (cpu
, imm
); break;
2252 case 7: subs64 (cpu
, imm
); break;
2257 dexAddSubtractShiftedRegister (sim_cpu
*cpu
)
2259 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2260 instr[30,29] = op : 00 ==> ADD, 01 ==> ADDS, 10 ==> SUB, 11 ==> SUBS
2261 instr[28,24] = 01011
2262 instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> UNALLOC
2265 instr[15,10] = count : must be 0xxxxx for 32 bit
2269 uint32_t size
= INSTR (31, 31);
2270 uint32_t count
= INSTR (15, 10);
2271 Shift shiftType
= INSTR (23, 22);
2273 NYI_assert (28, 24, 0x0B);
2274 NYI_assert (21, 21, 0);
2276 /* Shift encoded as ROR is unallocated. */
2277 if (shiftType
== ROR
)
2280 /* 32 bit operations must have count[5] = 0
2281 or else we have an UNALLOC. */
2282 if (size
== 0 && uimm (count
, 5, 5))
2285 /* Dispatch on size:op i.e instr [31,29]. */
2286 switch (INSTR (31, 29))
2288 case 0: add32_shift (cpu
, shiftType
, count
); break;
2289 case 1: adds32_shift (cpu
, shiftType
, count
); break;
2290 case 2: sub32_shift (cpu
, shiftType
, count
); break;
2291 case 3: subs32_shift (cpu
, shiftType
, count
); break;
2292 case 4: add64_shift (cpu
, shiftType
, count
); break;
2293 case 5: adds64_shift (cpu
, shiftType
, count
); break;
2294 case 6: sub64_shift (cpu
, shiftType
, count
); break;
2295 case 7: subs64_shift (cpu
, shiftType
, count
); break;
2300 dexAddSubtractExtendedRegister (sim_cpu
*cpu
)
2302 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2303 instr[30] = op : 0 ==> ADD, 1 ==> SUB
2304 instr[29] = set? : 0 ==> no flags, 1 ==> set flags
2305 instr[28,24] = 01011
2306 instr[23,22] = opt : 0 ==> ok, 1,2,3 ==> UNALLOC
2309 instr[15,13] = option : 000 ==> UXTB, 001 ==> UXTH,
2310 000 ==> LSL|UXTW, 001 ==> UXTZ,
2311 000 ==> SXTB, 001 ==> SXTH,
2312 000 ==> SXTW, 001 ==> SXTX,
2313 instr[12,10] = shift : 0,1,2,3,4 ==> ok, 5,6,7 ==> UNALLOC
2317 Extension extensionType
= INSTR (15, 13);
2318 uint32_t shift
= INSTR (12, 10);
2320 NYI_assert (28, 24, 0x0B);
2321 NYI_assert (21, 21, 1);
2323 /* Shift may not exceed 4. */
2327 /* Dispatch on size:op:set?. */
2328 switch (INSTR (31, 29))
2330 case 0: add32_ext (cpu
, extensionType
, shift
); break;
2331 case 1: adds32_ext (cpu
, extensionType
, shift
); break;
2332 case 2: sub32_ext (cpu
, extensionType
, shift
); break;
2333 case 3: subs32_ext (cpu
, extensionType
, shift
); break;
2334 case 4: add64_ext (cpu
, extensionType
, shift
); break;
2335 case 5: adds64_ext (cpu
, extensionType
, shift
); break;
2336 case 6: sub64_ext (cpu
, extensionType
, shift
); break;
2337 case 7: subs64_ext (cpu
, extensionType
, shift
); break;
2341 /* Conditional data processing
2342 Condition register is implicit 3rd source. */
2344 /* 32 bit add with carry. */
2345 /* N.B register args may not be SP. */
2348 adc32 (sim_cpu
*cpu
)
2350 unsigned rm
= INSTR (20, 16);
2351 unsigned rn
= INSTR (9, 5);
2352 unsigned rd
= INSTR (4, 0);
2354 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2355 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
2356 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
2357 + aarch64_get_reg_u32 (cpu
, rm
, NO_SP
)
2361 /* 64 bit add with carry */
2363 adc64 (sim_cpu
*cpu
)
2365 unsigned rm
= INSTR (20, 16);
2366 unsigned rn
= INSTR (9, 5);
2367 unsigned rd
= INSTR (4, 0);
2369 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2370 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
2371 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
2372 + aarch64_get_reg_u64 (cpu
, rm
, NO_SP
)
2376 /* 32 bit add with carry setting flags. */
2378 adcs32 (sim_cpu
*cpu
)
2380 unsigned rm
= INSTR (20, 16);
2381 unsigned rn
= INSTR (9, 5);
2382 unsigned rd
= INSTR (4, 0);
2384 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
2385 uint32_t value2
= aarch64_get_reg_u32 (cpu
, rm
, NO_SP
);
2386 uint32_t carry
= IS_SET (C
);
2388 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2389 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
+ carry
);
2390 set_flags_for_add32 (cpu
, value1
, value2
+ carry
);
2393 /* 64 bit add with carry setting flags. */
2395 adcs64 (sim_cpu
*cpu
)
2397 unsigned rm
= INSTR (20, 16);
2398 unsigned rn
= INSTR (9, 5);
2399 unsigned rd
= INSTR (4, 0);
2401 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
2402 uint64_t value2
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
2403 uint64_t carry
= IS_SET (C
);
2405 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2406 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
+ carry
);
2407 set_flags_for_add64 (cpu
, value1
, value2
+ carry
);
2410 /* 32 bit sub with carry. */
2412 sbc32 (sim_cpu
*cpu
)
2414 unsigned rm
= INSTR (20, 16);
2415 unsigned rn
= INSTR (9, 5); /* ngc iff rn == 31. */
2416 unsigned rd
= INSTR (4, 0);
2418 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2419 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
2420 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
2421 - aarch64_get_reg_u32 (cpu
, rm
, NO_SP
)
2425 /* 64 bit sub with carry */
2427 sbc64 (sim_cpu
*cpu
)
2429 unsigned rm
= INSTR (20, 16);
2430 unsigned rn
= INSTR (9, 5);
2431 unsigned rd
= INSTR (4, 0);
2433 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2434 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
2435 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
2436 - aarch64_get_reg_u64 (cpu
, rm
, NO_SP
)
2440 /* 32 bit sub with carry setting flags */
2442 sbcs32 (sim_cpu
*cpu
)
2444 unsigned rm
= INSTR (20, 16);
2445 unsigned rn
= INSTR (9, 5);
2446 unsigned rd
= INSTR (4, 0);
2448 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
2449 uint32_t value2
= aarch64_get_reg_u32 (cpu
, rm
, NO_SP
);
2450 uint32_t carry
= IS_SET (C
);
2451 uint32_t result
= value1
- value2
+ 1 - carry
;
2453 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2454 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
2455 set_flags_for_sub32 (cpu
, value1
, value2
+ 1 - carry
);
2458 /* 64 bit sub with carry setting flags */
2460 sbcs64 (sim_cpu
*cpu
)
2462 unsigned rm
= INSTR (20, 16);
2463 unsigned rn
= INSTR (9, 5);
2464 unsigned rd
= INSTR (4, 0);
2466 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
2467 uint64_t value2
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
2468 uint64_t carry
= IS_SET (C
);
2469 uint64_t result
= value1
- value2
+ 1 - carry
;
2471 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2472 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
2473 set_flags_for_sub64 (cpu
, value1
, value2
+ 1 - carry
);
2477 dexAddSubtractWithCarry (sim_cpu
*cpu
)
2479 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2480 instr[30] = op : 0 ==> ADC, 1 ==> SBC
2481 instr[29] = set? : 0 ==> no flags, 1 ==> set flags
2482 instr[28,21] = 1 1010 000
2484 instr[15,10] = op2 : 00000 ==> ok, ow ==> UNALLOC
2488 uint32_t op2
= INSTR (15, 10);
2490 NYI_assert (28, 21, 0xD0);
2495 /* Dispatch on size:op:set?. */
2496 switch (INSTR (31, 29))
2498 case 0: adc32 (cpu
); break;
2499 case 1: adcs32 (cpu
); break;
2500 case 2: sbc32 (cpu
); break;
2501 case 3: sbcs32 (cpu
); break;
2502 case 4: adc64 (cpu
); break;
2503 case 5: adcs64 (cpu
); break;
2504 case 6: sbc64 (cpu
); break;
2505 case 7: sbcs64 (cpu
); break;
2510 testConditionCode (sim_cpu
*cpu
, CondCode cc
)
2512 /* This should be reduceable to branchless logic
2513 by some careful testing of bits in CC followed
2514 by the requisite masking and combining of bits
2515 from the flag register.
2517 For now we do it with a switch. */
2522 case EQ
: res
= IS_SET (Z
); break;
2523 case NE
: res
= IS_CLEAR (Z
); break;
2524 case CS
: res
= IS_SET (C
); break;
2525 case CC
: res
= IS_CLEAR (C
); break;
2526 case MI
: res
= IS_SET (N
); break;
2527 case PL
: res
= IS_CLEAR (N
); break;
2528 case VS
: res
= IS_SET (V
); break;
2529 case VC
: res
= IS_CLEAR (V
); break;
2530 case HI
: res
= IS_SET (C
) && IS_CLEAR (Z
); break;
2531 case LS
: res
= IS_CLEAR (C
) || IS_SET (Z
); break;
2532 case GE
: res
= IS_SET (N
) == IS_SET (V
); break;
2533 case LT
: res
= IS_SET (N
) != IS_SET (V
); break;
2534 case GT
: res
= IS_CLEAR (Z
) && (IS_SET (N
) == IS_SET (V
)); break;
2535 case LE
: res
= IS_SET (Z
) || (IS_SET (N
) != IS_SET (V
)); break;
2546 CondCompare (sim_cpu
*cpu
) /* aka: ccmp and ccmn */
2548 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2549 instr[30] = compare with positive (1) or negative value (0)
2550 instr[29,21] = 1 1101 0010
2551 instr[20,16] = Rm or const
2553 instr[11] = compare reg (0) or const (1)
2557 instr[3,0] = value for CPSR bits if the comparison does not take place. */
2562 NYI_assert (29, 21, 0x1d2);
2563 NYI_assert (10, 10, 0);
2564 NYI_assert (4, 4, 0);
2566 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2567 if (! testConditionCode (cpu
, INSTR (15, 12)))
2569 aarch64_set_CPSR (cpu
, INSTR (3, 0));
2573 negate
= INSTR (30, 30) ? 1 : -1;
2574 rm
= INSTR (20, 16);
2580 set_flags_for_sub64 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
),
2581 negate
* (uint64_t) rm
);
2583 set_flags_for_sub64 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
),
2584 negate
* aarch64_get_reg_u64 (cpu
, rm
, SP_OK
));
2589 set_flags_for_sub32 (cpu
, aarch64_get_reg_u32 (cpu
, rn
, SP_OK
),
2592 set_flags_for_sub32 (cpu
, aarch64_get_reg_u32 (cpu
, rn
, SP_OK
),
2593 negate
* aarch64_get_reg_u32 (cpu
, rm
, SP_OK
));
2598 do_vec_MOV_whole_vector (sim_cpu
*cpu
)
2600 /* MOV Vd.T, Vs.T (alias for ORR Vd.T, Vn.T, Vm.T where Vn == Vm)
2603 instr[30] = half(0)/full(1)
2604 instr[29,21] = 001110101
2606 instr[15,10] = 000111
2610 unsigned vs
= INSTR (9, 5);
2611 unsigned vd
= INSTR (4, 0);
2613 NYI_assert (29, 21, 0x075);
2614 NYI_assert (15, 10, 0x07);
2616 if (INSTR (20, 16) != vs
)
2619 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2621 aarch64_set_vec_u64 (cpu
, vd
, 1, aarch64_get_vec_u64 (cpu
, vs
, 1));
2623 aarch64_set_vec_u64 (cpu
, vd
, 0, aarch64_get_vec_u64 (cpu
, vs
, 0));
2627 do_vec_SMOV_into_scalar (sim_cpu
*cpu
)
2630 instr[30] = word(0)/long(1)
2631 instr[29,21] = 00 1110 000
2632 instr[20,16] = element size and index
2633 instr[15,10] = 00 0010 11
2634 instr[9,5] = V source
2635 instr[4,0] = R dest */
2637 unsigned vs
= INSTR (9, 5);
2638 unsigned rd
= INSTR (4, 0);
2639 unsigned imm5
= INSTR (20, 16);
2640 unsigned full
= INSTR (30, 30);
2643 NYI_assert (29, 21, 0x070);
2644 NYI_assert (15, 10, 0x0B);
2646 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2651 index
= (imm5
>> 1) & 0xF;
2653 else if (imm5
& 0x2)
2656 index
= (imm5
>> 2) & 0x7;
2658 else if (full
&& (imm5
& 0x4))
2661 index
= (imm5
>> 3) & 0x3;
2670 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
,
2671 aarch64_get_vec_s8 (cpu
, vs
, index
));
2673 aarch64_set_reg_s32 (cpu
, rd
, NO_SP
,
2674 aarch64_get_vec_s8 (cpu
, vs
, index
));
2679 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
,
2680 aarch64_get_vec_s16 (cpu
, vs
, index
));
2682 aarch64_set_reg_s32 (cpu
, rd
, NO_SP
,
2683 aarch64_get_vec_s16 (cpu
, vs
, index
));
2687 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
,
2688 aarch64_get_vec_s32 (cpu
, vs
, index
));
2697 do_vec_UMOV_into_scalar (sim_cpu
*cpu
)
2700 instr[30] = word(0)/long(1)
2701 instr[29,21] = 00 1110 000
2702 instr[20,16] = element size and index
2703 instr[15,10] = 00 0011 11
2704 instr[9,5] = V source
2705 instr[4,0] = R dest */
2707 unsigned vs
= INSTR (9, 5);
2708 unsigned rd
= INSTR (4, 0);
2709 unsigned imm5
= INSTR (20, 16);
2710 unsigned full
= INSTR (30, 30);
2713 NYI_assert (29, 21, 0x070);
2714 NYI_assert (15, 10, 0x0F);
2716 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2723 index
= (imm5
>> 1) & 0xF;
2725 else if (imm5
& 0x2)
2728 index
= (imm5
>> 2) & 0x7;
2730 else if (imm5
& 0x4)
2733 index
= (imm5
>> 3) & 0x3;
2738 else if (imm5
& 0x8)
2741 index
= (imm5
>> 4) & 0x1;
2749 aarch64_set_reg_u32 (cpu
, rd
, NO_SP
,
2750 aarch64_get_vec_u8 (cpu
, vs
, index
));
2754 aarch64_set_reg_u32 (cpu
, rd
, NO_SP
,
2755 aarch64_get_vec_u16 (cpu
, vs
, index
));
2759 aarch64_set_reg_u32 (cpu
, rd
, NO_SP
,
2760 aarch64_get_vec_u32 (cpu
, vs
, index
));
2764 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
2765 aarch64_get_vec_u64 (cpu
, vs
, index
));
2774 do_vec_INS (sim_cpu
*cpu
)
2776 /* instr[31,21] = 01001110000
2777 instr[20,16] = element size and index
2778 instr[15,10] = 000111
2779 instr[9,5] = W source
2780 instr[4,0] = V dest */
2783 unsigned rs
= INSTR (9, 5);
2784 unsigned vd
= INSTR (4, 0);
2786 NYI_assert (31, 21, 0x270);
2787 NYI_assert (15, 10, 0x07);
2789 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2792 index
= INSTR (20, 17);
2793 aarch64_set_vec_u8 (cpu
, vd
, index
,
2794 aarch64_get_reg_u8 (cpu
, rs
, NO_SP
));
2796 else if (INSTR (17, 17))
2798 index
= INSTR (20, 18);
2799 aarch64_set_vec_u16 (cpu
, vd
, index
,
2800 aarch64_get_reg_u16 (cpu
, rs
, NO_SP
));
2802 else if (INSTR (18, 18))
2804 index
= INSTR (20, 19);
2805 aarch64_set_vec_u32 (cpu
, vd
, index
,
2806 aarch64_get_reg_u32 (cpu
, rs
, NO_SP
));
2808 else if (INSTR (19, 19))
2810 index
= INSTR (20, 20);
2811 aarch64_set_vec_u64 (cpu
, vd
, index
,
2812 aarch64_get_reg_u64 (cpu
, rs
, NO_SP
));
2819 do_vec_DUP_vector_into_vector (sim_cpu
*cpu
)
2822 instr[30] = half(0)/full(1)
2823 instr[29,21] = 00 1110 000
2824 instr[20,16] = element size and index
2825 instr[15,10] = 0000 01
2826 instr[9,5] = V source
2827 instr[4,0] = V dest. */
2829 unsigned full
= INSTR (30, 30);
2830 unsigned vs
= INSTR (9, 5);
2831 unsigned vd
= INSTR (4, 0);
2834 NYI_assert (29, 21, 0x070);
2835 NYI_assert (15, 10, 0x01);
2837 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2840 index
= INSTR (20, 17);
2842 for (i
= 0; i
< (full
? 16 : 8); i
++)
2843 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vs
, index
));
2845 else if (INSTR (17, 17))
2847 index
= INSTR (20, 18);
2849 for (i
= 0; i
< (full
? 8 : 4); i
++)
2850 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vs
, index
));
2852 else if (INSTR (18, 18))
2854 index
= INSTR (20, 19);
2856 for (i
= 0; i
< (full
? 4 : 2); i
++)
2857 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vs
, index
));
2861 if (INSTR (19, 19) == 0)
2867 index
= INSTR (20, 20);
2869 for (i
= 0; i
< 2; i
++)
2870 aarch64_set_vec_u64 (cpu
, vd
, i
, aarch64_get_vec_u64 (cpu
, vs
, index
));
2875 do_vec_TBL (sim_cpu
*cpu
)
2878 instr[30] = half(0)/full(1)
2879 instr[29,21] = 00 1110 000
2882 instr[14,13] = vec length
2884 instr[9,5] = V start
2885 instr[4,0] = V dest */
2887 int full
= INSTR (30, 30);
2888 int len
= INSTR (14, 13) + 1;
2889 unsigned vm
= INSTR (20, 16);
2890 unsigned vn
= INSTR (9, 5);
2891 unsigned vd
= INSTR (4, 0);
2894 NYI_assert (29, 21, 0x070);
2895 NYI_assert (12, 10, 0);
2897 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2898 for (i
= 0; i
< (full
? 16 : 8); i
++)
2900 unsigned int selector
= aarch64_get_vec_u8 (cpu
, vm
, i
);
2904 val
= aarch64_get_vec_u8 (cpu
, vn
, selector
);
2905 else if (selector
< 32)
2906 val
= len
< 2 ? 0 : aarch64_get_vec_u8 (cpu
, vn
+ 1, selector
- 16);
2907 else if (selector
< 48)
2908 val
= len
< 3 ? 0 : aarch64_get_vec_u8 (cpu
, vn
+ 2, selector
- 32);
2909 else if (selector
< 64)
2910 val
= len
< 4 ? 0 : aarch64_get_vec_u8 (cpu
, vn
+ 3, selector
- 48);
2914 aarch64_set_vec_u8 (cpu
, vd
, i
, val
);
2919 do_vec_TRN (sim_cpu
*cpu
)
2922 instr[30] = half(0)/full(1)
2923 instr[29,24] = 00 1110
2928 instr[14] = TRN1 (0) / TRN2 (1)
2930 instr[9,5] = V source
2931 instr[4,0] = V dest. */
2933 int full
= INSTR (30, 30);
2934 int second
= INSTR (14, 14);
2935 unsigned vm
= INSTR (20, 16);
2936 unsigned vn
= INSTR (9, 5);
2937 unsigned vd
= INSTR (4, 0);
2940 NYI_assert (29, 24, 0x0E);
2941 NYI_assert (13, 10, 0xA);
2943 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2944 switch (INSTR (23, 22))
2947 for (i
= 0; i
< (full
? 8 : 4); i
++)
2951 aarch64_get_vec_u8 (cpu
, second
? vm
: vn
, i
* 2));
2953 (cpu
, vd
, 1 * 2 + 1,
2954 aarch64_get_vec_u8 (cpu
, second
? vn
: vm
, i
* 2 + 1));
2959 for (i
= 0; i
< (full
? 4 : 2); i
++)
2963 aarch64_get_vec_u16 (cpu
, second
? vm
: vn
, i
* 2));
2965 (cpu
, vd
, 1 * 2 + 1,
2966 aarch64_get_vec_u16 (cpu
, second
? vn
: vm
, i
* 2 + 1));
2972 (cpu
, vd
, 0, aarch64_get_vec_u32 (cpu
, second
? vm
: vn
, 0));
2974 (cpu
, vd
, 1, aarch64_get_vec_u32 (cpu
, second
? vn
: vm
, 1));
2976 (cpu
, vd
, 2, aarch64_get_vec_u32 (cpu
, second
? vm
: vn
, 2));
2978 (cpu
, vd
, 3, aarch64_get_vec_u32 (cpu
, second
? vn
: vm
, 3));
2985 aarch64_set_vec_u64 (cpu
, vd
, 0,
2986 aarch64_get_vec_u64 (cpu
, second
? vm
: vn
, 0));
2987 aarch64_set_vec_u64 (cpu
, vd
, 1,
2988 aarch64_get_vec_u64 (cpu
, second
? vn
: vm
, 1));
2994 do_vec_DUP_scalar_into_vector (sim_cpu
*cpu
)
2997 instr[30] = 0=> zero top 64-bits, 1=> duplicate into top 64-bits
2998 [must be 1 for 64-bit xfer]
2999 instr[29,20] = 00 1110 0000
3000 instr[19,16] = element size: 0001=> 8-bits, 0010=> 16-bits,
3001 0100=> 32-bits. 1000=>64-bits
3002 instr[15,10] = 0000 11
3003 instr[9,5] = W source
3004 instr[4,0] = V dest. */
3007 unsigned Vd
= INSTR (4, 0);
3008 unsigned Rs
= INSTR (9, 5);
3009 int both
= INSTR (30, 30);
3011 NYI_assert (29, 20, 0x0E0);
3012 NYI_assert (15, 10, 0x03);
3014 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3015 switch (INSTR (19, 16))
3018 for (i
= 0; i
< (both
? 16 : 8); i
++)
3019 aarch64_set_vec_u8 (cpu
, Vd
, i
, aarch64_get_reg_u8 (cpu
, Rs
, NO_SP
));
3023 for (i
= 0; i
< (both
? 8 : 4); i
++)
3024 aarch64_set_vec_u16 (cpu
, Vd
, i
, aarch64_get_reg_u16 (cpu
, Rs
, NO_SP
));
3028 for (i
= 0; i
< (both
? 4 : 2); i
++)
3029 aarch64_set_vec_u32 (cpu
, Vd
, i
, aarch64_get_reg_u32 (cpu
, Rs
, NO_SP
));
3035 aarch64_set_vec_u64 (cpu
, Vd
, 0, aarch64_get_reg_u64 (cpu
, Rs
, NO_SP
));
3036 aarch64_set_vec_u64 (cpu
, Vd
, 1, aarch64_get_reg_u64 (cpu
, Rs
, NO_SP
));
3045 do_vec_UZP (sim_cpu
*cpu
)
3048 instr[30] = half(0)/full(1)
3049 instr[29,24] = 00 1110
3050 instr[23,22] = size: byte(00), half(01), word (10), long (11)
3054 instr[14] = lower (0) / upper (1)
3059 int full
= INSTR (30, 30);
3060 int upper
= INSTR (14, 14);
3062 unsigned vm
= INSTR (20, 16);
3063 unsigned vn
= INSTR (9, 5);
3064 unsigned vd
= INSTR (4, 0);
3066 uint64_t val_m1
= aarch64_get_vec_u64 (cpu
, vm
, 0);
3067 uint64_t val_m2
= aarch64_get_vec_u64 (cpu
, vm
, 1);
3068 uint64_t val_n1
= aarch64_get_vec_u64 (cpu
, vn
, 0);
3069 uint64_t val_n2
= aarch64_get_vec_u64 (cpu
, vn
, 1);
3074 uint64_t input2
= full
? val_n2
: val_m1
;
3076 NYI_assert (29, 24, 0x0E);
3077 NYI_assert (21, 21, 0);
3078 NYI_assert (15, 15, 0);
3079 NYI_assert (13, 10, 6);
3081 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3082 switch (INSTR (23, 22))
3085 val1
= (val_n1
>> (upper
* 8)) & 0xFFULL
;
3086 val1
|= (val_n1
>> ((upper
* 8) + 8)) & 0xFF00ULL
;
3087 val1
|= (val_n1
>> ((upper
* 8) + 16)) & 0xFF0000ULL
;
3088 val1
|= (val_n1
>> ((upper
* 8) + 24)) & 0xFF000000ULL
;
3090 val1
|= (input2
<< (32 - (upper
* 8))) & 0xFF00000000ULL
;
3091 val1
|= (input2
<< (24 - (upper
* 8))) & 0xFF0000000000ULL
;
3092 val1
|= (input2
<< (16 - (upper
* 8))) & 0xFF000000000000ULL
;
3093 val1
|= (input2
<< (8 - (upper
* 8))) & 0xFF00000000000000ULL
;
3097 val2
= (val_m1
>> (upper
* 8)) & 0xFFULL
;
3098 val2
|= (val_m1
>> ((upper
* 8) + 8)) & 0xFF00ULL
;
3099 val2
|= (val_m1
>> ((upper
* 8) + 16)) & 0xFF0000ULL
;
3100 val2
|= (val_m1
>> ((upper
* 8) + 24)) & 0xFF000000ULL
;
3102 val2
|= (val_m2
<< (32 - (upper
* 8))) & 0xFF00000000ULL
;
3103 val2
|= (val_m2
<< (24 - (upper
* 8))) & 0xFF0000000000ULL
;
3104 val2
|= (val_m2
<< (16 - (upper
* 8))) & 0xFF000000000000ULL
;
3105 val2
|= (val_m2
<< (8 - (upper
* 8))) & 0xFF00000000000000ULL
;
3110 val1
= (val_n1
>> (upper
* 16)) & 0xFFFFULL
;
3111 val1
|= (val_n1
>> ((upper
* 16) + 16)) & 0xFFFF0000ULL
;
3113 val1
|= (input2
<< (32 - (upper
* 16))) & 0xFFFF00000000ULL
;;
3114 val1
|= (input2
<< (16 - (upper
* 16))) & 0xFFFF000000000000ULL
;
3118 val2
= (val_m1
>> (upper
* 16)) & 0xFFFFULL
;
3119 val2
|= (val_m1
>> ((upper
* 16) + 16)) & 0xFFFF0000ULL
;
3121 val2
|= (val_m2
<< (32 - (upper
* 16))) & 0xFFFF00000000ULL
;
3122 val2
|= (val_m2
<< (16 - (upper
* 16))) & 0xFFFF000000000000ULL
;
3127 val1
= (val_n1
>> (upper
* 32)) & 0xFFFFFFFF;
3128 val1
|= (input2
<< (32 - (upper
* 32))) & 0xFFFFFFFF00000000ULL
;
3132 val2
= (val_m1
>> (upper
* 32)) & 0xFFFFFFFF;
3133 val2
|= (val_m2
<< (32 - (upper
* 32))) & 0xFFFFFFFF00000000ULL
;
3141 val1
= upper
? val_n2
: val_n1
;
3142 val2
= upper
? val_m2
: val_m1
;
3146 aarch64_set_vec_u64 (cpu
, vd
, 0, val1
);
3148 aarch64_set_vec_u64 (cpu
, vd
, 1, val2
);
3152 do_vec_ZIP (sim_cpu
*cpu
)
3155 instr[30] = half(0)/full(1)
3156 instr[29,24] = 00 1110
3157 instr[23,22] = size: byte(00), hald(01), word (10), long (11)
3161 instr[14] = lower (0) / upper (1)
3166 int full
= INSTR (30, 30);
3167 int upper
= INSTR (14, 14);
3169 unsigned vm
= INSTR (20, 16);
3170 unsigned vn
= INSTR (9, 5);
3171 unsigned vd
= INSTR (4, 0);
3173 uint64_t val_m1
= aarch64_get_vec_u64 (cpu
, vm
, 0);
3174 uint64_t val_m2
= aarch64_get_vec_u64 (cpu
, vm
, 1);
3175 uint64_t val_n1
= aarch64_get_vec_u64 (cpu
, vn
, 0);
3176 uint64_t val_n2
= aarch64_get_vec_u64 (cpu
, vn
, 1);
3181 uint64_t input1
= upper
? val_n1
: val_m1
;
3182 uint64_t input2
= upper
? val_n2
: val_m2
;
3184 NYI_assert (29, 24, 0x0E);
3185 NYI_assert (21, 21, 0);
3186 NYI_assert (15, 15, 0);
3187 NYI_assert (13, 10, 0xE);
3189 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3190 switch (INSTR (23, 23))
3194 ((input1
<< 0) & (0xFF << 0))
3195 | ((input2
<< 8) & (0xFF << 8))
3196 | ((input1
<< 8) & (0xFF << 16))
3197 | ((input2
<< 16) & (0xFF << 24))
3198 | ((input1
<< 16) & (0xFFULL
<< 32))
3199 | ((input2
<< 24) & (0xFFULL
<< 40))
3200 | ((input1
<< 24) & (0xFFULL
<< 48))
3201 | ((input2
<< 32) & (0xFFULL
<< 56));
3204 ((input1
>> 32) & (0xFF << 0))
3205 | ((input2
>> 24) & (0xFF << 8))
3206 | ((input1
>> 24) & (0xFF << 16))
3207 | ((input2
>> 16) & (0xFF << 24))
3208 | ((input1
>> 16) & (0xFFULL
<< 32))
3209 | ((input2
>> 8) & (0xFFULL
<< 40))
3210 | ((input1
>> 8) & (0xFFULL
<< 48))
3211 | ((input2
>> 0) & (0xFFULL
<< 56));
3216 ((input1
<< 0) & (0xFFFF << 0))
3217 | ((input2
<< 16) & (0xFFFF << 16))
3218 | ((input1
<< 16) & (0xFFFFULL
<< 32))
3219 | ((input2
<< 32) & (0xFFFFULL
<< 48));
3222 ((input1
>> 32) & (0xFFFF << 0))
3223 | ((input2
>> 16) & (0xFFFF << 16))
3224 | ((input1
>> 16) & (0xFFFFULL
<< 32))
3225 | ((input2
>> 0) & (0xFFFFULL
<< 48));
3229 val1
= (input1
& 0xFFFFFFFFULL
) | (input2
<< 32);
3230 val2
= (input2
& 0xFFFFFFFFULL
) | (input1
<< 32);
3239 aarch64_set_vec_u64 (cpu
, vd
, 0, val1
);
3241 aarch64_set_vec_u64 (cpu
, vd
, 1, val2
);
3244 /* Floating point immediates are encoded in 8 bits.
3245 fpimm[7] = sign bit.
3246 fpimm[6:4] = signed exponent.
3247 fpimm[3:0] = fraction (assuming leading 1).
3248 i.e. F = s * 1.f * 2^(e - b). */
3251 fp_immediate_for_encoding_32 (uint32_t imm8
)
3254 uint32_t s
, e
, f
, i
;
3256 s
= (imm8
>> 7) & 0x1;
3257 e
= (imm8
>> 4) & 0x7;
3260 /* The fp value is s * n/16 * 2r where n is 16+e. */
3261 u
= (16.0 + f
) / 16.0;
3263 /* N.B. exponent is signed. */
3268 for (i
= 0; i
<= epos
; i
++)
3275 for (i
= 0; i
< eneg
; i
++)
3286 fp_immediate_for_encoding_64 (uint32_t imm8
)
3289 uint32_t s
, e
, f
, i
;
3291 s
= (imm8
>> 7) & 0x1;
3292 e
= (imm8
>> 4) & 0x7;
3295 /* The fp value is s * n/16 * 2r where n is 16+e. */
3296 u
= (16.0 + f
) / 16.0;
3298 /* N.B. exponent is signed. */
3303 for (i
= 0; i
<= epos
; i
++)
3310 for (i
= 0; i
< eneg
; i
++)
3321 do_vec_MOV_immediate (sim_cpu
*cpu
)
3324 instr[30] = full/half selector
3325 instr[29,19] = 00111100000
3326 instr[18,16] = high 3 bits of uimm8
3327 instr[15,12] = size & shift:
3329 0010 => 32-bit + LSL#8
3330 0100 => 32-bit + LSL#16
3331 0110 => 32-bit + LSL#24
3332 1010 => 16-bit + LSL#8
3334 1101 => 32-bit + MSL#16
3335 1100 => 32-bit + MSL#8
3339 instr[9,5] = low 5-bits of uimm8
3342 int full
= INSTR (30, 30);
3343 unsigned vd
= INSTR (4, 0);
3344 unsigned val
= (INSTR (18, 16) << 5) | INSTR (9, 5);
3347 NYI_assert (29, 19, 0x1E0);
3348 NYI_assert (11, 10, 1);
3350 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3351 switch (INSTR (15, 12))
3353 case 0x0: /* 32-bit, no shift. */
3354 case 0x2: /* 32-bit, shift by 8. */
3355 case 0x4: /* 32-bit, shift by 16. */
3356 case 0x6: /* 32-bit, shift by 24. */
3357 val
<<= (8 * INSTR (14, 13));
3358 for (i
= 0; i
< (full
? 4 : 2); i
++)
3359 aarch64_set_vec_u32 (cpu
, vd
, i
, val
);
3362 case 0xa: /* 16-bit, shift by 8. */
3365 case 0x8: /* 16-bit, no shift. */
3366 for (i
= 0; i
< (full
? 8 : 4); i
++)
3367 aarch64_set_vec_u16 (cpu
, vd
, i
, val
);
3370 case 0xd: /* 32-bit, mask shift by 16. */
3374 case 0xc: /* 32-bit, mask shift by 8. */
3377 for (i
= 0; i
< (full
? 4 : 2); i
++)
3378 aarch64_set_vec_u32 (cpu
, vd
, i
, val
);
3381 case 0xe: /* 8-bit, no shift. */
3382 for (i
= 0; i
< (full
? 16 : 8); i
++)
3383 aarch64_set_vec_u8 (cpu
, vd
, i
, val
);
3386 case 0xf: /* FMOV Vs.{2|4}S, #fpimm. */
3388 float u
= fp_immediate_for_encoding_32 (val
);
3389 for (i
= 0; i
< (full
? 4 : 2); i
++)
3390 aarch64_set_vec_float (cpu
, vd
, i
, u
);
3400 do_vec_MVNI (sim_cpu
*cpu
)
3403 instr[30] = full/half selector
3404 instr[29,19] = 10111100000
3405 instr[18,16] = high 3 bits of uimm8
3406 instr[15,12] = selector
3408 instr[9,5] = low 5-bits of uimm8
3411 int full
= INSTR (30, 30);
3412 unsigned vd
= INSTR (4, 0);
3413 unsigned val
= (INSTR (18, 16) << 5) | INSTR (9, 5);
3416 NYI_assert (29, 19, 0x5E0);
3417 NYI_assert (11, 10, 1);
3419 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3420 switch (INSTR (15, 12))
3422 case 0x0: /* 32-bit, no shift. */
3423 case 0x2: /* 32-bit, shift by 8. */
3424 case 0x4: /* 32-bit, shift by 16. */
3425 case 0x6: /* 32-bit, shift by 24. */
3426 val
<<= (8 * INSTR (14, 13));
3428 for (i
= 0; i
< (full
? 4 : 2); i
++)
3429 aarch64_set_vec_u32 (cpu
, vd
, i
, val
);
3432 case 0xa: /* 16-bit, 8 bit shift. */
3434 case 0x8: /* 16-bit, no shift. */
3436 for (i
= 0; i
< (full
? 8 : 4); i
++)
3437 aarch64_set_vec_u16 (cpu
, vd
, i
, val
);
3440 case 0xd: /* 32-bit, mask shift by 16. */
3443 case 0xc: /* 32-bit, mask shift by 8. */
3447 for (i
= 0; i
< (full
? 4 : 2); i
++)
3448 aarch64_set_vec_u32 (cpu
, vd
, i
, val
);
3451 case 0xE: /* MOVI Dn, #mask64 */
3455 for (i
= 0; i
< 8; i
++)
3457 mask
|= (0xFFUL
<< (i
* 8));
3458 aarch64_set_vec_u64 (cpu
, vd
, 0, mask
);
3459 aarch64_set_vec_u64 (cpu
, vd
, 1, mask
);
3463 case 0xf: /* FMOV Vd.2D, #fpimm. */
3465 double u
= fp_immediate_for_encoding_64 (val
);
3470 aarch64_set_vec_double (cpu
, vd
, 0, u
);
3471 aarch64_set_vec_double (cpu
, vd
, 1, u
);
3480 #define ABS(A) ((A) < 0 ? - (A) : (A))
3483 do_vec_ABS (sim_cpu
*cpu
)
3486 instr[30] = half(0)/full(1)
3487 instr[29,24] = 00 1110
3488 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3489 instr[21,10] = 10 0000 1011 10
3493 unsigned vn
= INSTR (9, 5);
3494 unsigned vd
= INSTR (4, 0);
3495 unsigned full
= INSTR (30, 30);
3498 NYI_assert (29, 24, 0x0E);
3499 NYI_assert (21, 10, 0x82E);
3501 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3502 switch (INSTR (23, 22))
3505 for (i
= 0; i
< (full
? 16 : 8); i
++)
3506 aarch64_set_vec_s8 (cpu
, vd
, i
,
3507 ABS (aarch64_get_vec_s8 (cpu
, vn
, i
)));
3511 for (i
= 0; i
< (full
? 8 : 4); i
++)
3512 aarch64_set_vec_s16 (cpu
, vd
, i
,
3513 ABS (aarch64_get_vec_s16 (cpu
, vn
, i
)));
3517 for (i
= 0; i
< (full
? 4 : 2); i
++)
3518 aarch64_set_vec_s32 (cpu
, vd
, i
,
3519 ABS (aarch64_get_vec_s32 (cpu
, vn
, i
)));
3525 for (i
= 0; i
< 2; i
++)
3526 aarch64_set_vec_s64 (cpu
, vd
, i
,
3527 ABS (aarch64_get_vec_s64 (cpu
, vn
, i
)));
3533 do_vec_ADDV (sim_cpu
*cpu
)
3536 instr[30] = full/half selector
3537 instr[29,24] = 00 1110
3538 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3539 instr[21,10] = 11 0001 1011 10
3543 unsigned vm
= INSTR (9, 5);
3544 unsigned rd
= INSTR (4, 0);
3546 int full
= INSTR (30, 30);
3548 NYI_assert (29, 24, 0x0E);
3549 NYI_assert (21, 10, 0xC6E);
3551 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3552 switch (INSTR (23, 22))
3557 for (i
= 0; i
< (full
? 16 : 8); i
++)
3558 val
+= aarch64_get_vec_u8 (cpu
, vm
, i
);
3559 aarch64_set_vec_u64 (cpu
, rd
, 0, val
);
3566 for (i
= 0; i
< (full
? 8 : 4); i
++)
3567 val
+= aarch64_get_vec_u16 (cpu
, vm
, i
);
3568 aarch64_set_vec_u64 (cpu
, rd
, 0, val
);
3577 for (i
= 0; i
< 4; i
++)
3578 val
+= aarch64_get_vec_u32 (cpu
, vm
, i
);
3579 aarch64_set_vec_u64 (cpu
, rd
, 0, val
);
3589 do_vec_ins_2 (sim_cpu
*cpu
)
3591 /* instr[31,21] = 01001110000
3592 instr[20,18] = size & element selector
3594 instr[13] = direction: to vec(0), from vec (1)
3600 unsigned vm
= INSTR (9, 5);
3601 unsigned vd
= INSTR (4, 0);
3603 NYI_assert (31, 21, 0x270);
3604 NYI_assert (17, 14, 0);
3605 NYI_assert (12, 10, 7);
3607 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3608 if (INSTR (13, 13) == 1)
3610 if (INSTR (18, 18) == 1)
3613 elem
= INSTR (20, 19);
3614 aarch64_set_reg_u64 (cpu
, vd
, NO_SP
,
3615 aarch64_get_vec_u32 (cpu
, vm
, elem
));
3620 if (INSTR (19, 19) != 1)
3623 elem
= INSTR (20, 20);
3624 aarch64_set_reg_u64 (cpu
, vd
, NO_SP
,
3625 aarch64_get_vec_u64 (cpu
, vm
, elem
));
3630 if (INSTR (18, 18) == 1)
3633 elem
= INSTR (20, 19);
3634 aarch64_set_vec_u32 (cpu
, vd
, elem
,
3635 aarch64_get_reg_u32 (cpu
, vm
, NO_SP
));
3640 if (INSTR (19, 19) != 1)
3643 elem
= INSTR (20, 20);
3644 aarch64_set_vec_u64 (cpu
, vd
, elem
,
3645 aarch64_get_reg_u64 (cpu
, vm
, NO_SP
));
3650 #define DO_VEC_WIDENING_MUL(N, DST_TYPE, READ_TYPE, WRITE_TYPE) \
3653 DST_TYPE a[N], b[N]; \
3655 for (i = 0; i < (N); i++) \
3657 a[i] = aarch64_get_vec_##READ_TYPE (cpu, vn, i + bias); \
3658 b[i] = aarch64_get_vec_##READ_TYPE (cpu, vm, i + bias); \
3660 for (i = 0; i < (N); i++) \
3661 aarch64_set_vec_##WRITE_TYPE (cpu, vd, i, a[i] * b[i]); \
3666 do_vec_mull (sim_cpu
*cpu
)
3669 instr[30] = lower(0)/upper(1) selector
3670 instr[29] = signed(0)/unsigned(1)
3671 instr[28,24] = 0 1110
3672 instr[23,22] = size: 8-bit (00), 16-bit (01), 32-bit (10)
3675 instr[15,10] = 11 0000
3679 int unsign
= INSTR (29, 29);
3680 int bias
= INSTR (30, 30);
3681 unsigned vm
= INSTR (20, 16);
3682 unsigned vn
= INSTR ( 9, 5);
3683 unsigned vd
= INSTR ( 4, 0);
3686 NYI_assert (28, 24, 0x0E);
3687 NYI_assert (15, 10, 0x30);
3689 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3690 /* NB: Read source values before writing results, in case
3691 the source and destination vectors are the same. */
3692 switch (INSTR (23, 22))
3698 DO_VEC_WIDENING_MUL (8, uint16_t, u8
, u16
);
3700 DO_VEC_WIDENING_MUL (8, int16_t, s8
, s16
);
3707 DO_VEC_WIDENING_MUL (4, uint32_t, u16
, u32
);
3709 DO_VEC_WIDENING_MUL (4, int32_t, s16
, s32
);
3716 DO_VEC_WIDENING_MUL (2, uint64_t, u32
, u64
);
3718 DO_VEC_WIDENING_MUL (2, int64_t, s32
, s64
);
3727 do_vec_fadd (sim_cpu
*cpu
)
3730 instr[30] = half(0)/full(1)
3731 instr[29,24] = 001110
3732 instr[23] = FADD(0)/FSUB(1)
3733 instr[22] = float (0)/double(1)
3736 instr[15,10] = 110101
3740 unsigned vm
= INSTR (20, 16);
3741 unsigned vn
= INSTR (9, 5);
3742 unsigned vd
= INSTR (4, 0);
3744 int full
= INSTR (30, 30);
3746 NYI_assert (29, 24, 0x0E);
3747 NYI_assert (21, 21, 1);
3748 NYI_assert (15, 10, 0x35);
3750 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3758 for (i
= 0; i
< 2; i
++)
3759 aarch64_set_vec_double (cpu
, vd
, i
,
3760 aarch64_get_vec_double (cpu
, vn
, i
)
3761 - aarch64_get_vec_double (cpu
, vm
, i
));
3765 for (i
= 0; i
< (full
? 4 : 2); i
++)
3766 aarch64_set_vec_float (cpu
, vd
, i
,
3767 aarch64_get_vec_float (cpu
, vn
, i
)
3768 - aarch64_get_vec_float (cpu
, vm
, i
));
3778 for (i
= 0; i
< 2; i
++)
3779 aarch64_set_vec_double (cpu
, vd
, i
,
3780 aarch64_get_vec_double (cpu
, vm
, i
)
3781 + aarch64_get_vec_double (cpu
, vn
, i
));
3785 for (i
= 0; i
< (full
? 4 : 2); i
++)
3786 aarch64_set_vec_float (cpu
, vd
, i
,
3787 aarch64_get_vec_float (cpu
, vm
, i
)
3788 + aarch64_get_vec_float (cpu
, vn
, i
));
3794 do_vec_add (sim_cpu
*cpu
)
3797 instr[30] = full/half selector
3798 instr[29,24] = 001110
3799 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3802 instr[15,10] = 100001
3806 unsigned vm
= INSTR (20, 16);
3807 unsigned vn
= INSTR (9, 5);
3808 unsigned vd
= INSTR (4, 0);
3810 int full
= INSTR (30, 30);
3812 NYI_assert (29, 24, 0x0E);
3813 NYI_assert (21, 21, 1);
3814 NYI_assert (15, 10, 0x21);
3816 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3817 switch (INSTR (23, 22))
3820 for (i
= 0; i
< (full
? 16 : 8); i
++)
3821 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vn
, i
)
3822 + aarch64_get_vec_u8 (cpu
, vm
, i
));
3826 for (i
= 0; i
< (full
? 8 : 4); i
++)
3827 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vn
, i
)
3828 + aarch64_get_vec_u16 (cpu
, vm
, i
));
3832 for (i
= 0; i
< (full
? 4 : 2); i
++)
3833 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vn
, i
)
3834 + aarch64_get_vec_u32 (cpu
, vm
, i
));
3840 aarch64_set_vec_u64 (cpu
, vd
, 0, aarch64_get_vec_u64 (cpu
, vn
, 0)
3841 + aarch64_get_vec_u64 (cpu
, vm
, 0));
3842 aarch64_set_vec_u64 (cpu
, vd
, 1,
3843 aarch64_get_vec_u64 (cpu
, vn
, 1)
3844 + aarch64_get_vec_u64 (cpu
, vm
, 1));
3850 do_vec_mul (sim_cpu
*cpu
)
3853 instr[30] = full/half selector
3854 instr[29,24] = 00 1110
3855 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3858 instr[15,10] = 10 0111
3862 unsigned vm
= INSTR (20, 16);
3863 unsigned vn
= INSTR (9, 5);
3864 unsigned vd
= INSTR (4, 0);
3866 int full
= INSTR (30, 30);
3869 NYI_assert (29, 24, 0x0E);
3870 NYI_assert (21, 21, 1);
3871 NYI_assert (15, 10, 0x27);
3873 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3874 switch (INSTR (23, 22))
3877 DO_VEC_WIDENING_MUL (full
? 16 : 8, uint8_t, u8
, u8
);
3881 DO_VEC_WIDENING_MUL (full
? 8 : 4, uint16_t, u16
, u16
);
3885 DO_VEC_WIDENING_MUL (full
? 4 : 2, uint32_t, u32
, u32
);
3894 do_vec_MLA (sim_cpu
*cpu
)
3897 instr[30] = full/half selector
3898 instr[29,24] = 00 1110
3899 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3902 instr[15,10] = 1001 01
3906 unsigned vm
= INSTR (20, 16);
3907 unsigned vn
= INSTR (9, 5);
3908 unsigned vd
= INSTR (4, 0);
3910 int full
= INSTR (30, 30);
3912 NYI_assert (29, 24, 0x0E);
3913 NYI_assert (21, 21, 1);
3914 NYI_assert (15, 10, 0x25);
3916 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3917 switch (INSTR (23, 22))
3920 for (i
= 0; i
< (full
? 16 : 8); i
++)
3921 aarch64_set_vec_u8 (cpu
, vd
, i
,
3922 aarch64_get_vec_u8 (cpu
, vd
, i
)
3923 + (aarch64_get_vec_u8 (cpu
, vn
, i
)
3924 * aarch64_get_vec_u8 (cpu
, vm
, i
)));
3928 for (i
= 0; i
< (full
? 8 : 4); i
++)
3929 aarch64_set_vec_u16 (cpu
, vd
, i
,
3930 aarch64_get_vec_u16 (cpu
, vd
, i
)
3931 + (aarch64_get_vec_u16 (cpu
, vn
, i
)
3932 * aarch64_get_vec_u16 (cpu
, vm
, i
)));
3936 for (i
= 0; i
< (full
? 4 : 2); i
++)
3937 aarch64_set_vec_u32 (cpu
, vd
, i
,
3938 aarch64_get_vec_u32 (cpu
, vd
, i
)
3939 + (aarch64_get_vec_u32 (cpu
, vn
, i
)
3940 * aarch64_get_vec_u32 (cpu
, vm
, i
)));
3949 fmaxnm (float a
, float b
)
3954 return a
> b
? a
: b
;
3957 else if (! isnan (b
))
3963 fminnm (float a
, float b
)
3968 return a
< b
? a
: b
;
3971 else if (! isnan (b
))
3977 dmaxnm (double a
, double b
)
3982 return a
> b
? a
: b
;
3985 else if (! isnan (b
))
3991 dminnm (double a
, double b
)
3996 return a
< b
? a
: b
;
3999 else if (! isnan (b
))
4005 do_vec_FminmaxNMP (sim_cpu
*cpu
)
4008 instr [30] = half (0)/full (1)
4009 instr [29,24] = 10 1110
4010 instr [23] = max(0)/min(1)
4011 instr [22] = float (0)/double (1)
4014 instr [15,10] = 1100 01
4016 instr [4.0] = Vd. */
4018 unsigned vm
= INSTR (20, 16);
4019 unsigned vn
= INSTR (9, 5);
4020 unsigned vd
= INSTR (4, 0);
4021 int full
= INSTR (30, 30);
4023 NYI_assert (29, 24, 0x2E);
4024 NYI_assert (21, 21, 1);
4025 NYI_assert (15, 10, 0x31);
4027 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4030 double (* fn
)(double, double) = INSTR (23, 23)
4035 aarch64_set_vec_double (cpu
, vd
, 0,
4036 fn (aarch64_get_vec_double (cpu
, vn
, 0),
4037 aarch64_get_vec_double (cpu
, vn
, 1)));
4038 aarch64_set_vec_double (cpu
, vd
, 0,
4039 fn (aarch64_get_vec_double (cpu
, vm
, 0),
4040 aarch64_get_vec_double (cpu
, vm
, 1)));
4044 float (* fn
)(float, float) = INSTR (23, 23)
4047 aarch64_set_vec_float (cpu
, vd
, 0,
4048 fn (aarch64_get_vec_float (cpu
, vn
, 0),
4049 aarch64_get_vec_float (cpu
, vn
, 1)));
4051 aarch64_set_vec_float (cpu
, vd
, 1,
4052 fn (aarch64_get_vec_float (cpu
, vn
, 2),
4053 aarch64_get_vec_float (cpu
, vn
, 3)));
4055 aarch64_set_vec_float (cpu
, vd
, (full
? 2 : 1),
4056 fn (aarch64_get_vec_float (cpu
, vm
, 0),
4057 aarch64_get_vec_float (cpu
, vm
, 1)));
4059 aarch64_set_vec_float (cpu
, vd
, 3,
4060 fn (aarch64_get_vec_float (cpu
, vm
, 2),
4061 aarch64_get_vec_float (cpu
, vm
, 3)));
4066 do_vec_AND (sim_cpu
*cpu
)
4069 instr[30] = half (0)/full (1)
4070 instr[29,21] = 001110001
4072 instr[15,10] = 000111
4076 unsigned vm
= INSTR (20, 16);
4077 unsigned vn
= INSTR (9, 5);
4078 unsigned vd
= INSTR (4, 0);
4080 int full
= INSTR (30, 30);
4082 NYI_assert (29, 21, 0x071);
4083 NYI_assert (15, 10, 0x07);
4085 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4086 for (i
= 0; i
< (full
? 4 : 2); i
++)
4087 aarch64_set_vec_u32 (cpu
, vd
, i
,
4088 aarch64_get_vec_u32 (cpu
, vn
, i
)
4089 & aarch64_get_vec_u32 (cpu
, vm
, i
));
4093 do_vec_BSL (sim_cpu
*cpu
)
4096 instr[30] = half (0)/full (1)
4097 instr[29,21] = 101110011
4099 instr[15,10] = 000111
4103 unsigned vm
= INSTR (20, 16);
4104 unsigned vn
= INSTR (9, 5);
4105 unsigned vd
= INSTR (4, 0);
4107 int full
= INSTR (30, 30);
4109 NYI_assert (29, 21, 0x173);
4110 NYI_assert (15, 10, 0x07);
4112 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4113 for (i
= 0; i
< (full
? 16 : 8); i
++)
4114 aarch64_set_vec_u8 (cpu
, vd
, i
,
4115 ( aarch64_get_vec_u8 (cpu
, vd
, i
)
4116 & aarch64_get_vec_u8 (cpu
, vn
, i
))
4117 | ((~ aarch64_get_vec_u8 (cpu
, vd
, i
))
4118 & aarch64_get_vec_u8 (cpu
, vm
, i
)));
4122 do_vec_EOR (sim_cpu
*cpu
)
4125 instr[30] = half (0)/full (1)
4126 instr[29,21] = 10 1110 001
4128 instr[15,10] = 000111
4132 unsigned vm
= INSTR (20, 16);
4133 unsigned vn
= INSTR (9, 5);
4134 unsigned vd
= INSTR (4, 0);
4136 int full
= INSTR (30, 30);
4138 NYI_assert (29, 21, 0x171);
4139 NYI_assert (15, 10, 0x07);
4141 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4142 for (i
= 0; i
< (full
? 4 : 2); i
++)
4143 aarch64_set_vec_u32 (cpu
, vd
, i
,
4144 aarch64_get_vec_u32 (cpu
, vn
, i
)
4145 ^ aarch64_get_vec_u32 (cpu
, vm
, i
));
4149 do_vec_bit (sim_cpu
*cpu
)
4152 instr[30] = half (0)/full (1)
4153 instr[29,23] = 10 1110 1
4154 instr[22] = BIT (0) / BIF (1)
4157 instr[15,10] = 0001 11
4161 unsigned vm
= INSTR (20, 16);
4162 unsigned vn
= INSTR (9, 5);
4163 unsigned vd
= INSTR (4, 0);
4164 unsigned full
= INSTR (30, 30);
4165 unsigned test_false
= INSTR (22, 22);
4168 NYI_assert (29, 23, 0x5D);
4169 NYI_assert (21, 21, 1);
4170 NYI_assert (15, 10, 0x07);
4172 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4173 for (i
= 0; i
< (full
? 4 : 2); i
++)
4175 uint32_t vd_val
= aarch64_get_vec_u32 (cpu
, vd
, i
);
4176 uint32_t vn_val
= aarch64_get_vec_u32 (cpu
, vn
, i
);
4177 uint32_t vm_val
= aarch64_get_vec_u32 (cpu
, vm
, i
);
4179 aarch64_set_vec_u32 (cpu
, vd
, i
,
4180 (vd_val
& vm_val
) | (vn_val
& ~vm_val
));
4182 aarch64_set_vec_u32 (cpu
, vd
, i
,
4183 (vd_val
& ~vm_val
) | (vn_val
& vm_val
));
4188 do_vec_ORN (sim_cpu
*cpu
)
4191 instr[30] = half (0)/full (1)
4192 instr[29,21] = 00 1110 111
4194 instr[15,10] = 00 0111
4198 unsigned vm
= INSTR (20, 16);
4199 unsigned vn
= INSTR (9, 5);
4200 unsigned vd
= INSTR (4, 0);
4202 int full
= INSTR (30, 30);
4204 NYI_assert (29, 21, 0x077);
4205 NYI_assert (15, 10, 0x07);
4207 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4208 for (i
= 0; i
< (full
? 16 : 8); i
++)
4209 aarch64_set_vec_u8 (cpu
, vd
, i
,
4210 aarch64_get_vec_u8 (cpu
, vn
, i
)
4211 | ~ aarch64_get_vec_u8 (cpu
, vm
, i
));
4215 do_vec_ORR (sim_cpu
*cpu
)
4218 instr[30] = half (0)/full (1)
4219 instr[29,21] = 00 1110 101
4221 instr[15,10] = 0001 11
4225 unsigned vm
= INSTR (20, 16);
4226 unsigned vn
= INSTR (9, 5);
4227 unsigned vd
= INSTR (4, 0);
4229 int full
= INSTR (30, 30);
4231 NYI_assert (29, 21, 0x075);
4232 NYI_assert (15, 10, 0x07);
4234 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4235 for (i
= 0; i
< (full
? 16 : 8); i
++)
4236 aarch64_set_vec_u8 (cpu
, vd
, i
,
4237 aarch64_get_vec_u8 (cpu
, vn
, i
)
4238 | aarch64_get_vec_u8 (cpu
, vm
, i
));
4242 do_vec_BIC (sim_cpu
*cpu
)
4245 instr[30] = half (0)/full (1)
4246 instr[29,21] = 00 1110 011
4248 instr[15,10] = 00 0111
4252 unsigned vm
= INSTR (20, 16);
4253 unsigned vn
= INSTR (9, 5);
4254 unsigned vd
= INSTR (4, 0);
4256 int full
= INSTR (30, 30);
4258 NYI_assert (29, 21, 0x073);
4259 NYI_assert (15, 10, 0x07);
4261 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4262 for (i
= 0; i
< (full
? 16 : 8); i
++)
4263 aarch64_set_vec_u8 (cpu
, vd
, i
,
4264 aarch64_get_vec_u8 (cpu
, vn
, i
)
4265 & ~ aarch64_get_vec_u8 (cpu
, vm
, i
));
4269 do_vec_XTN (sim_cpu
*cpu
)
4272 instr[30] = first part (0)/ second part (1)
4273 instr[29,24] = 00 1110
4274 instr[23,22] = size: byte(00), half(01), word (10)
4275 instr[21,10] = 1000 0100 1010
4279 unsigned vs
= INSTR (9, 5);
4280 unsigned vd
= INSTR (4, 0);
4281 unsigned bias
= INSTR (30, 30);
4284 NYI_assert (29, 24, 0x0E);
4285 NYI_assert (21, 10, 0x84A);
4287 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4288 switch (INSTR (23, 22))
4291 for (i
= 0; i
< 8; i
++)
4292 aarch64_set_vec_u8 (cpu
, vd
, i
+ (bias
* 8),
4293 aarch64_get_vec_u16 (cpu
, vs
, i
));
4297 for (i
= 0; i
< 4; i
++)
4298 aarch64_set_vec_u16 (cpu
, vd
, i
+ (bias
* 4),
4299 aarch64_get_vec_u32 (cpu
, vs
, i
));
4303 for (i
= 0; i
< 2; i
++)
4304 aarch64_set_vec_u32 (cpu
, vd
, i
+ (bias
* 2),
4305 aarch64_get_vec_u64 (cpu
, vs
, i
));
4310 /* Return the number of bits set in the input value. */
4311 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
4312 # define popcount __builtin_popcount
4315 popcount (unsigned char x
)
4317 static const unsigned char popcnt
[16] =
4325 /* Only counts the low 8 bits of the input as that is all we need. */
4326 return popcnt
[x
% 16] + popcnt
[x
/ 16];
4331 do_vec_CNT (sim_cpu
*cpu
)
4334 instr[30] = half (0)/ full (1)
4335 instr[29,24] = 00 1110
4336 instr[23,22] = size: byte(00)
4337 instr[21,10] = 1000 0001 0110
4341 unsigned vs
= INSTR (9, 5);
4342 unsigned vd
= INSTR (4, 0);
4343 int full
= INSTR (30, 30);
4344 int size
= INSTR (23, 22);
4347 NYI_assert (29, 24, 0x0E);
4348 NYI_assert (21, 10, 0x816);
4353 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4355 for (i
= 0; i
< (full
? 16 : 8); i
++)
4356 aarch64_set_vec_u8 (cpu
, vd
, i
,
4357 popcount (aarch64_get_vec_u8 (cpu
, vs
, i
)));
4361 do_vec_maxv (sim_cpu
*cpu
)
4364 instr[30] = half(0)/full(1)
4365 instr[29] = signed (0)/unsigned(1)
4366 instr[28,24] = 0 1110
4367 instr[23,22] = size: byte(00), half(01), word (10)
4369 instr[20,17] = 1 000
4370 instr[16] = max(0)/min(1)
4371 instr[15,10] = 1010 10
4372 instr[9,5] = V source
4373 instr[4.0] = R dest. */
4375 unsigned vs
= INSTR (9, 5);
4376 unsigned rd
= INSTR (4, 0);
4377 unsigned full
= INSTR (30, 30);
4380 NYI_assert (28, 24, 0x0E);
4381 NYI_assert (21, 21, 1);
4382 NYI_assert (20, 17, 8);
4383 NYI_assert (15, 10, 0x2A);
4385 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4386 switch ((INSTR (29, 29) << 1) | INSTR (16, 16))
4388 case 0: /* SMAXV. */
4391 switch (INSTR (23, 22))
4394 smax
= aarch64_get_vec_s8 (cpu
, vs
, 0);
4395 for (i
= 1; i
< (full
? 16 : 8); i
++)
4396 smax
= max (smax
, aarch64_get_vec_s8 (cpu
, vs
, i
));
4399 smax
= aarch64_get_vec_s16 (cpu
, vs
, 0);
4400 for (i
= 1; i
< (full
? 8 : 4); i
++)
4401 smax
= max (smax
, aarch64_get_vec_s16 (cpu
, vs
, i
));
4404 smax
= aarch64_get_vec_s32 (cpu
, vs
, 0);
4405 for (i
= 1; i
< (full
? 4 : 2); i
++)
4406 smax
= max (smax
, aarch64_get_vec_s32 (cpu
, vs
, i
));
4411 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, smax
);
4415 case 1: /* SMINV. */
4418 switch (INSTR (23, 22))
4421 smin
= aarch64_get_vec_s8 (cpu
, vs
, 0);
4422 for (i
= 1; i
< (full
? 16 : 8); i
++)
4423 smin
= min (smin
, aarch64_get_vec_s8 (cpu
, vs
, i
));
4426 smin
= aarch64_get_vec_s16 (cpu
, vs
, 0);
4427 for (i
= 1; i
< (full
? 8 : 4); i
++)
4428 smin
= min (smin
, aarch64_get_vec_s16 (cpu
, vs
, i
));
4431 smin
= aarch64_get_vec_s32 (cpu
, vs
, 0);
4432 for (i
= 1; i
< (full
? 4 : 2); i
++)
4433 smin
= min (smin
, aarch64_get_vec_s32 (cpu
, vs
, i
));
4439 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, smin
);
4443 case 2: /* UMAXV. */
4446 switch (INSTR (23, 22))
4449 umax
= aarch64_get_vec_u8 (cpu
, vs
, 0);
4450 for (i
= 1; i
< (full
? 16 : 8); i
++)
4451 umax
= max (umax
, aarch64_get_vec_u8 (cpu
, vs
, i
));
4454 umax
= aarch64_get_vec_u16 (cpu
, vs
, 0);
4455 for (i
= 1; i
< (full
? 8 : 4); i
++)
4456 umax
= max (umax
, aarch64_get_vec_u16 (cpu
, vs
, i
));
4459 umax
= aarch64_get_vec_u32 (cpu
, vs
, 0);
4460 for (i
= 1; i
< (full
? 4 : 2); i
++)
4461 umax
= max (umax
, aarch64_get_vec_u32 (cpu
, vs
, i
));
4467 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, umax
);
4471 case 3: /* UMINV. */
4474 switch (INSTR (23, 22))
4477 umin
= aarch64_get_vec_u8 (cpu
, vs
, 0);
4478 for (i
= 1; i
< (full
? 16 : 8); i
++)
4479 umin
= min (umin
, aarch64_get_vec_u8 (cpu
, vs
, i
));
4482 umin
= aarch64_get_vec_u16 (cpu
, vs
, 0);
4483 for (i
= 1; i
< (full
? 8 : 4); i
++)
4484 umin
= min (umin
, aarch64_get_vec_u16 (cpu
, vs
, i
));
4487 umin
= aarch64_get_vec_u32 (cpu
, vs
, 0);
4488 for (i
= 1; i
< (full
? 4 : 2); i
++)
4489 umin
= min (umin
, aarch64_get_vec_u32 (cpu
, vs
, i
));
4495 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, umin
);
4502 do_vec_fminmaxV (sim_cpu
*cpu
)
4504 /* instr[31,24] = 0110 1110
4505 instr[23] = max(0)/min(1)
4506 instr[22,14] = 011 0000 11
4507 instr[13,12] = nm(00)/normal(11)
4509 instr[9,5] = V source
4510 instr[4.0] = R dest. */
4512 unsigned vs
= INSTR (9, 5);
4513 unsigned rd
= INSTR (4, 0);
4515 float res
= aarch64_get_vec_float (cpu
, vs
, 0);
4517 NYI_assert (31, 24, 0x6E);
4518 NYI_assert (22, 14, 0x0C3);
4519 NYI_assert (11, 10, 2);
4521 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4524 switch (INSTR (13, 12))
4526 case 0: /* FMNINNMV. */
4527 for (i
= 1; i
< 4; i
++)
4528 res
= fminnm (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4531 case 3: /* FMINV. */
4532 for (i
= 1; i
< 4; i
++)
4533 res
= min (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4542 switch (INSTR (13, 12))
4544 case 0: /* FMNAXNMV. */
4545 for (i
= 1; i
< 4; i
++)
4546 res
= fmaxnm (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4549 case 3: /* FMAXV. */
4550 for (i
= 1; i
< 4; i
++)
4551 res
= max (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4559 aarch64_set_FP_float (cpu
, rd
, res
);
4563 do_vec_Fminmax (sim_cpu
*cpu
)
4566 instr[30] = half(0)/full(1)
4567 instr[29,24] = 00 1110
4568 instr[23] = max(0)/min(1)
4569 instr[22] = float(0)/double(1)
4573 instr[13,12] = nm(00)/normal(11)
4578 unsigned vm
= INSTR (20, 16);
4579 unsigned vn
= INSTR (9, 5);
4580 unsigned vd
= INSTR (4, 0);
4581 unsigned full
= INSTR (30, 30);
4582 unsigned min
= INSTR (23, 23);
4585 NYI_assert (29, 24, 0x0E);
4586 NYI_assert (21, 21, 1);
4587 NYI_assert (15, 14, 3);
4588 NYI_assert (11, 10, 1);
4590 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4593 double (* func
)(double, double);
4598 if (INSTR (13, 12) == 0)
4599 func
= min
? dminnm
: dmaxnm
;
4600 else if (INSTR (13, 12) == 3)
4601 func
= min
? fmin
: fmax
;
4605 for (i
= 0; i
< 2; i
++)
4606 aarch64_set_vec_double (cpu
, vd
, i
,
4607 func (aarch64_get_vec_double (cpu
, vn
, i
),
4608 aarch64_get_vec_double (cpu
, vm
, i
)));
4612 float (* func
)(float, float);
4614 if (INSTR (13, 12) == 0)
4615 func
= min
? fminnm
: fmaxnm
;
4616 else if (INSTR (13, 12) == 3)
4617 func
= min
? fminf
: fmaxf
;
4621 for (i
= 0; i
< (full
? 4 : 2); i
++)
4622 aarch64_set_vec_float (cpu
, vd
, i
,
4623 func (aarch64_get_vec_float (cpu
, vn
, i
),
4624 aarch64_get_vec_float (cpu
, vm
, i
)));
4629 do_vec_SCVTF (sim_cpu
*cpu
)
4633 instr[29,23] = 00 1110 0
4634 instr[22] = float(0)/double(1)
4635 instr[21,10] = 10 0001 1101 10
4639 unsigned vn
= INSTR (9, 5);
4640 unsigned vd
= INSTR (4, 0);
4641 unsigned full
= INSTR (30, 30);
4642 unsigned size
= INSTR (22, 22);
4645 NYI_assert (29, 23, 0x1C);
4646 NYI_assert (21, 10, 0x876);
4648 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4654 for (i
= 0; i
< 2; i
++)
4656 double val
= (double) aarch64_get_vec_u64 (cpu
, vn
, i
);
4657 aarch64_set_vec_double (cpu
, vd
, i
, val
);
4662 for (i
= 0; i
< (full
? 4 : 2); i
++)
4664 float val
= (float) aarch64_get_vec_u32 (cpu
, vn
, i
);
4665 aarch64_set_vec_float (cpu
, vd
, i
, val
);
4670 #define VEC_CMP(SOURCE, CMP) \
4676 for (i = 0; i < (full ? 16 : 8); i++) \
4677 aarch64_set_vec_u8 (cpu, vd, i, \
4678 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4680 aarch64_get_vec_##SOURCE##8 (cpu, vm, i) \
4684 for (i = 0; i < (full ? 8 : 4); i++) \
4685 aarch64_set_vec_u16 (cpu, vd, i, \
4686 aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4688 aarch64_get_vec_##SOURCE##16 (cpu, vm, i) \
4692 for (i = 0; i < (full ? 4 : 2); i++) \
4693 aarch64_set_vec_u32 (cpu, vd, i, \
4694 aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4696 aarch64_get_vec_##SOURCE##32 (cpu, vm, i) \
4702 for (i = 0; i < 2; i++) \
4703 aarch64_set_vec_u64 (cpu, vd, i, \
4704 aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4706 aarch64_get_vec_##SOURCE##64 (cpu, vm, i) \
4713 #define VEC_CMP0(SOURCE, CMP) \
4719 for (i = 0; i < (full ? 16 : 8); i++) \
4720 aarch64_set_vec_u8 (cpu, vd, i, \
4721 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4725 for (i = 0; i < (full ? 8 : 4); i++) \
4726 aarch64_set_vec_u16 (cpu, vd, i, \
4727 aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4731 for (i = 0; i < (full ? 4 : 2); i++) \
4732 aarch64_set_vec_u32 (cpu, vd, i, \
4733 aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4739 for (i = 0; i < 2; i++) \
4740 aarch64_set_vec_u64 (cpu, vd, i, \
4741 aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4742 CMP 0 ? -1ULL : 0); \
4748 #define VEC_FCMP0(CMP) \
4753 if (INSTR (22, 22)) \
4757 for (i = 0; i < 2; i++) \
4758 aarch64_set_vec_u64 (cpu, vd, i, \
4759 aarch64_get_vec_double (cpu, vn, i) \
4760 CMP 0.0 ? -1 : 0); \
4764 for (i = 0; i < (full ? 4 : 2); i++) \
4765 aarch64_set_vec_u32 (cpu, vd, i, \
4766 aarch64_get_vec_float (cpu, vn, i) \
4767 CMP 0.0 ? -1 : 0); \
4773 #define VEC_FCMP(CMP) \
4776 if (INSTR (22, 22)) \
4780 for (i = 0; i < 2; i++) \
4781 aarch64_set_vec_u64 (cpu, vd, i, \
4782 aarch64_get_vec_double (cpu, vn, i) \
4784 aarch64_get_vec_double (cpu, vm, i) \
4789 for (i = 0; i < (full ? 4 : 2); i++) \
4790 aarch64_set_vec_u32 (cpu, vd, i, \
4791 aarch64_get_vec_float (cpu, vn, i) \
4793 aarch64_get_vec_float (cpu, vm, i) \
4801 do_vec_compare (sim_cpu
*cpu
)
4804 instr[30] = half(0)/full(1)
4805 instr[29] = part-of-comparison-type
4806 instr[28,24] = 0 1110
4807 instr[23,22] = size of integer compares: byte(00), half(01), word (10), long (11)
4808 type of float compares: single (-0) / double (-1)
4810 instr[20,16] = Vm or 00000 (compare vs 0)
4811 instr[15,10] = part-of-comparison-type
4815 int full
= INSTR (30, 30);
4816 int size
= INSTR (23, 22);
4817 unsigned vm
= INSTR (20, 16);
4818 unsigned vn
= INSTR (9, 5);
4819 unsigned vd
= INSTR (4, 0);
4822 NYI_assert (28, 24, 0x0E);
4823 NYI_assert (21, 21, 1);
4825 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4828 || ((INSTR (11, 11) == 0
4829 && INSTR (10, 10) == 0)))
4831 /* A compare vs 0. */
4834 if (INSTR (15, 10) == 0x2A)
4836 else if (INSTR (15, 10) == 0x32
4837 || INSTR (15, 10) == 0x3E)
4838 do_vec_fminmaxV (cpu
);
4839 else if (INSTR (29, 23) == 0x1C
4840 && INSTR (21, 10) == 0x876)
4850 /* A floating point compare. */
4851 unsigned decode
= (INSTR (29, 29) << 5) | (INSTR (23, 23) << 4)
4854 NYI_assert (15, 15, 1);
4858 case /* 0b010010: GT#0 */ 0x12: VEC_FCMP0 (>);
4859 case /* 0b110010: GE#0 */ 0x32: VEC_FCMP0 (>=);
4860 case /* 0b010110: EQ#0 */ 0x16: VEC_FCMP0 (==);
4861 case /* 0b110110: LE#0 */ 0x36: VEC_FCMP0 (<=);
4862 case /* 0b011010: LT#0 */ 0x1A: VEC_FCMP0 (<);
4863 case /* 0b111001: GT */ 0x39: VEC_FCMP (>);
4864 case /* 0b101001: GE */ 0x29: VEC_FCMP (>=);
4865 case /* 0b001001: EQ */ 0x09: VEC_FCMP (==);
4873 unsigned decode
= (INSTR (29, 29) << 6) | INSTR (15, 10);
4877 case 0x0D: /* 0001101 GT */ VEC_CMP (s
, > );
4878 case 0x0F: /* 0001111 GE */ VEC_CMP (s
, >= );
4879 case 0x22: /* 0100010 GT #0 */ VEC_CMP0 (s
, > );
4880 case 0x23: /* 0100011 TST */ VEC_CMP (u
, & );
4881 case 0x26: /* 0100110 EQ #0 */ VEC_CMP0 (s
, == );
4882 case 0x2A: /* 0101010 LT #0 */ VEC_CMP0 (s
, < );
4883 case 0x4D: /* 1001101 HI */ VEC_CMP (u
, > );
4884 case 0x4F: /* 1001111 HS */ VEC_CMP (u
, >= );
4885 case 0x62: /* 1100010 GE #0 */ VEC_CMP0 (s
, >= );
4886 case 0x63: /* 1100011 EQ */ VEC_CMP (u
, == );
4887 case 0x66: /* 1100110 LE #0 */ VEC_CMP0 (s
, <= );
4897 do_vec_SSHL (sim_cpu
*cpu
)
4900 instr[30] = first part (0)/ second part (1)
4901 instr[29,24] = 00 1110
4902 instr[23,22] = size: byte(00), half(01), word (10), long (11)
4905 instr[15,10] = 0100 01
4909 unsigned full
= INSTR (30, 30);
4910 unsigned vm
= INSTR (20, 16);
4911 unsigned vn
= INSTR (9, 5);
4912 unsigned vd
= INSTR (4, 0);
4916 NYI_assert (29, 24, 0x0E);
4917 NYI_assert (21, 21, 1);
4918 NYI_assert (15, 10, 0x11);
4920 /* FIXME: What is a signed shift left in this context ?. */
4922 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4923 switch (INSTR (23, 22))
4926 for (i
= 0; i
< (full
? 16 : 8); i
++)
4928 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
);
4930 aarch64_set_vec_s8 (cpu
, vd
, i
, aarch64_get_vec_s8 (cpu
, vn
, i
)
4933 aarch64_set_vec_s8 (cpu
, vd
, i
, aarch64_get_vec_s8 (cpu
, vn
, i
)
4939 for (i
= 0; i
< (full
? 8 : 4); i
++)
4941 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 2);
4943 aarch64_set_vec_s16 (cpu
, vd
, i
, aarch64_get_vec_s16 (cpu
, vn
, i
)
4946 aarch64_set_vec_s16 (cpu
, vd
, i
, aarch64_get_vec_s16 (cpu
, vn
, i
)
4952 for (i
= 0; i
< (full
? 4 : 2); i
++)
4954 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 4);
4956 aarch64_set_vec_s32 (cpu
, vd
, i
, aarch64_get_vec_s32 (cpu
, vn
, i
)
4959 aarch64_set_vec_s32 (cpu
, vd
, i
, aarch64_get_vec_s32 (cpu
, vn
, i
)
4967 for (i
= 0; i
< 2; i
++)
4969 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 8);
4971 aarch64_set_vec_s64 (cpu
, vd
, i
, aarch64_get_vec_s64 (cpu
, vn
, i
)
4974 aarch64_set_vec_s64 (cpu
, vd
, i
, aarch64_get_vec_s64 (cpu
, vn
, i
)
4982 do_vec_USHL (sim_cpu
*cpu
)
4985 instr[30] = first part (0)/ second part (1)
4986 instr[29,24] = 10 1110
4987 instr[23,22] = size: byte(00), half(01), word (10), long (11)
4990 instr[15,10] = 0100 01
4994 unsigned full
= INSTR (30, 30);
4995 unsigned vm
= INSTR (20, 16);
4996 unsigned vn
= INSTR (9, 5);
4997 unsigned vd
= INSTR (4, 0);
5001 NYI_assert (29, 24, 0x2E);
5002 NYI_assert (15, 10, 0x11);
5004 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5005 switch (INSTR (23, 22))
5008 for (i
= 0; i
< (full
? 16 : 8); i
++)
5010 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
);
5012 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vn
, i
)
5015 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vn
, i
)
5021 for (i
= 0; i
< (full
? 8 : 4); i
++)
5023 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 2);
5025 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vn
, i
)
5028 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vn
, i
)
5034 for (i
= 0; i
< (full
? 4 : 2); i
++)
5036 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 4);
5038 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vn
, i
)
5041 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vn
, i
)
5049 for (i
= 0; i
< 2; i
++)
5051 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 8);
5053 aarch64_set_vec_u64 (cpu
, vd
, i
, aarch64_get_vec_u64 (cpu
, vn
, i
)
5056 aarch64_set_vec_u64 (cpu
, vd
, i
, aarch64_get_vec_u64 (cpu
, vn
, i
)
5064 do_vec_FMLA (sim_cpu
*cpu
)
5067 instr[30] = full/half selector
5068 instr[29,23] = 0011100
5069 instr[22] = size: 0=>float, 1=>double
5072 instr[15,10] = 1100 11
5076 unsigned vm
= INSTR (20, 16);
5077 unsigned vn
= INSTR (9, 5);
5078 unsigned vd
= INSTR (4, 0);
5080 int full
= INSTR (30, 30);
5082 NYI_assert (29, 23, 0x1C);
5083 NYI_assert (21, 21, 1);
5084 NYI_assert (15, 10, 0x33);
5086 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5091 for (i
= 0; i
< 2; i
++)
5092 aarch64_set_vec_double (cpu
, vd
, i
,
5093 aarch64_get_vec_double (cpu
, vn
, i
) *
5094 aarch64_get_vec_double (cpu
, vm
, i
) +
5095 aarch64_get_vec_double (cpu
, vd
, i
));
5099 for (i
= 0; i
< (full
? 4 : 2); i
++)
5100 aarch64_set_vec_float (cpu
, vd
, i
,
5101 aarch64_get_vec_float (cpu
, vn
, i
) *
5102 aarch64_get_vec_float (cpu
, vm
, i
) +
5103 aarch64_get_vec_float (cpu
, vd
, i
));
5108 do_vec_max (sim_cpu
*cpu
)
5111 instr[30] = full/half selector
5112 instr[29] = SMAX (0) / UMAX (1)
5113 instr[28,24] = 0 1110
5114 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
5117 instr[15,10] = 0110 01
5121 unsigned vm
= INSTR (20, 16);
5122 unsigned vn
= INSTR (9, 5);
5123 unsigned vd
= INSTR (4, 0);
5125 int full
= INSTR (30, 30);
5127 NYI_assert (28, 24, 0x0E);
5128 NYI_assert (21, 21, 1);
5129 NYI_assert (15, 10, 0x19);
5131 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5134 switch (INSTR (23, 22))
5137 for (i
= 0; i
< (full
? 16 : 8); i
++)
5138 aarch64_set_vec_u8 (cpu
, vd
, i
,
5139 aarch64_get_vec_u8 (cpu
, vn
, i
)
5140 > aarch64_get_vec_u8 (cpu
, vm
, i
)
5141 ? aarch64_get_vec_u8 (cpu
, vn
, i
)
5142 : aarch64_get_vec_u8 (cpu
, vm
, i
));
5146 for (i
= 0; i
< (full
? 8 : 4); i
++)
5147 aarch64_set_vec_u16 (cpu
, vd
, i
,
5148 aarch64_get_vec_u16 (cpu
, vn
, i
)
5149 > aarch64_get_vec_u16 (cpu
, vm
, i
)
5150 ? aarch64_get_vec_u16 (cpu
, vn
, i
)
5151 : aarch64_get_vec_u16 (cpu
, vm
, i
));
5155 for (i
= 0; i
< (full
? 4 : 2); i
++)
5156 aarch64_set_vec_u32 (cpu
, vd
, i
,
5157 aarch64_get_vec_u32 (cpu
, vn
, i
)
5158 > aarch64_get_vec_u32 (cpu
, vm
, i
)
5159 ? aarch64_get_vec_u32 (cpu
, vn
, i
)
5160 : aarch64_get_vec_u32 (cpu
, vm
, i
));
5169 switch (INSTR (23, 22))
5172 for (i
= 0; i
< (full
? 16 : 8); i
++)
5173 aarch64_set_vec_s8 (cpu
, vd
, i
,
5174 aarch64_get_vec_s8 (cpu
, vn
, i
)
5175 > aarch64_get_vec_s8 (cpu
, vm
, i
)
5176 ? aarch64_get_vec_s8 (cpu
, vn
, i
)
5177 : aarch64_get_vec_s8 (cpu
, vm
, i
));
5181 for (i
= 0; i
< (full
? 8 : 4); i
++)
5182 aarch64_set_vec_s16 (cpu
, vd
, i
,
5183 aarch64_get_vec_s16 (cpu
, vn
, i
)
5184 > aarch64_get_vec_s16 (cpu
, vm
, i
)
5185 ? aarch64_get_vec_s16 (cpu
, vn
, i
)
5186 : aarch64_get_vec_s16 (cpu
, vm
, i
));
5190 for (i
= 0; i
< (full
? 4 : 2); i
++)
5191 aarch64_set_vec_s32 (cpu
, vd
, i
,
5192 aarch64_get_vec_s32 (cpu
, vn
, i
)
5193 > aarch64_get_vec_s32 (cpu
, vm
, i
)
5194 ? aarch64_get_vec_s32 (cpu
, vn
, i
)
5195 : aarch64_get_vec_s32 (cpu
, vm
, i
));
5205 do_vec_min (sim_cpu
*cpu
)
5208 instr[30] = full/half selector
5209 instr[29] = SMIN (0) / UMIN (1)
5210 instr[28,24] = 0 1110
5211 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
5214 instr[15,10] = 0110 11
5218 unsigned vm
= INSTR (20, 16);
5219 unsigned vn
= INSTR (9, 5);
5220 unsigned vd
= INSTR (4, 0);
5222 int full
= INSTR (30, 30);
5224 NYI_assert (28, 24, 0x0E);
5225 NYI_assert (21, 21, 1);
5226 NYI_assert (15, 10, 0x1B);
5228 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5231 switch (INSTR (23, 22))
5234 for (i
= 0; i
< (full
? 16 : 8); i
++)
5235 aarch64_set_vec_u8 (cpu
, vd
, i
,
5236 aarch64_get_vec_u8 (cpu
, vn
, i
)
5237 < aarch64_get_vec_u8 (cpu
, vm
, i
)
5238 ? aarch64_get_vec_u8 (cpu
, vn
, i
)
5239 : aarch64_get_vec_u8 (cpu
, vm
, i
));
5243 for (i
= 0; i
< (full
? 8 : 4); i
++)
5244 aarch64_set_vec_u16 (cpu
, vd
, i
,
5245 aarch64_get_vec_u16 (cpu
, vn
, i
)
5246 < aarch64_get_vec_u16 (cpu
, vm
, i
)
5247 ? aarch64_get_vec_u16 (cpu
, vn
, i
)
5248 : aarch64_get_vec_u16 (cpu
, vm
, i
));
5252 for (i
= 0; i
< (full
? 4 : 2); i
++)
5253 aarch64_set_vec_u32 (cpu
, vd
, i
,
5254 aarch64_get_vec_u32 (cpu
, vn
, i
)
5255 < aarch64_get_vec_u32 (cpu
, vm
, i
)
5256 ? aarch64_get_vec_u32 (cpu
, vn
, i
)
5257 : aarch64_get_vec_u32 (cpu
, vm
, i
));
5266 switch (INSTR (23, 22))
5269 for (i
= 0; i
< (full
? 16 : 8); i
++)
5270 aarch64_set_vec_s8 (cpu
, vd
, i
,
5271 aarch64_get_vec_s8 (cpu
, vn
, i
)
5272 < aarch64_get_vec_s8 (cpu
, vm
, i
)
5273 ? aarch64_get_vec_s8 (cpu
, vn
, i
)
5274 : aarch64_get_vec_s8 (cpu
, vm
, i
));
5278 for (i
= 0; i
< (full
? 8 : 4); i
++)
5279 aarch64_set_vec_s16 (cpu
, vd
, i
,
5280 aarch64_get_vec_s16 (cpu
, vn
, i
)
5281 < aarch64_get_vec_s16 (cpu
, vm
, i
)
5282 ? aarch64_get_vec_s16 (cpu
, vn
, i
)
5283 : aarch64_get_vec_s16 (cpu
, vm
, i
));
5287 for (i
= 0; i
< (full
? 4 : 2); i
++)
5288 aarch64_set_vec_s32 (cpu
, vd
, i
,
5289 aarch64_get_vec_s32 (cpu
, vn
, i
)
5290 < aarch64_get_vec_s32 (cpu
, vm
, i
)
5291 ? aarch64_get_vec_s32 (cpu
, vn
, i
)
5292 : aarch64_get_vec_s32 (cpu
, vm
, i
));
5302 do_vec_sub_long (sim_cpu
*cpu
)
5305 instr[30] = lower (0) / upper (1)
5306 instr[29] = signed (0) / unsigned (1)
5307 instr[28,24] = 0 1110
5308 instr[23,22] = size: bytes (00), half (01), word (10)
5311 instr[15,10] = 0010 00
5313 instr[4,0] = V dest. */
5315 unsigned size
= INSTR (23, 22);
5316 unsigned vm
= INSTR (20, 16);
5317 unsigned vn
= INSTR (9, 5);
5318 unsigned vd
= INSTR (4, 0);
5322 NYI_assert (28, 24, 0x0E);
5323 NYI_assert (21, 21, 1);
5324 NYI_assert (15, 10, 0x08);
5329 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5330 switch (INSTR (30, 29))
5332 case 2: /* SSUBL2. */
5334 case 0: /* SSUBL. */
5339 for (i
= 0; i
< 8; i
++)
5340 aarch64_set_vec_s16 (cpu
, vd
, i
,
5341 aarch64_get_vec_s8 (cpu
, vn
, i
+ bias
)
5342 - aarch64_get_vec_s8 (cpu
, vm
, i
+ bias
));
5347 for (i
= 0; i
< 4; i
++)
5348 aarch64_set_vec_s32 (cpu
, vd
, i
,
5349 aarch64_get_vec_s16 (cpu
, vn
, i
+ bias
)
5350 - aarch64_get_vec_s16 (cpu
, vm
, i
+ bias
));
5354 for (i
= 0; i
< 2; i
++)
5355 aarch64_set_vec_s64 (cpu
, vd
, i
,
5356 aarch64_get_vec_s32 (cpu
, vn
, i
+ bias
)
5357 - aarch64_get_vec_s32 (cpu
, vm
, i
+ bias
));
5365 case 3: /* USUBL2. */
5367 case 1: /* USUBL. */
5372 for (i
= 0; i
< 8; i
++)
5373 aarch64_set_vec_u16 (cpu
, vd
, i
,
5374 aarch64_get_vec_u8 (cpu
, vn
, i
+ bias
)
5375 - aarch64_get_vec_u8 (cpu
, vm
, i
+ bias
));
5380 for (i
= 0; i
< 4; i
++)
5381 aarch64_set_vec_u32 (cpu
, vd
, i
,
5382 aarch64_get_vec_u16 (cpu
, vn
, i
+ bias
)
5383 - aarch64_get_vec_u16 (cpu
, vm
, i
+ bias
));
5387 for (i
= 0; i
< 2; i
++)
5388 aarch64_set_vec_u64 (cpu
, vd
, i
,
5389 aarch64_get_vec_u32 (cpu
, vn
, i
+ bias
)
5390 - aarch64_get_vec_u32 (cpu
, vm
, i
+ bias
));
5401 do_vec_ADDP (sim_cpu
*cpu
)
5404 instr[30] = half(0)/full(1)
5405 instr[29,24] = 00 1110
5406 instr[23,22] = size: bytes (00), half (01), word (10), long (11)
5409 instr[15,10] = 1011 11
5411 instr[4,0] = V dest. */
5415 unsigned full
= INSTR (30, 30);
5416 unsigned size
= INSTR (23, 22);
5417 unsigned vm
= INSTR (20, 16);
5418 unsigned vn
= INSTR (9, 5);
5419 unsigned vd
= INSTR (4, 0);
5422 NYI_assert (29, 24, 0x0E);
5423 NYI_assert (21, 21, 1);
5424 NYI_assert (15, 10, 0x2F);
5426 /* Make copies of the source registers in case vd == vn/vm. */
5427 copy_vn
= cpu
->fr
[vn
];
5428 copy_vm
= cpu
->fr
[vm
];
5430 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5434 range
= full
? 8 : 4;
5435 for (i
= 0; i
< range
; i
++)
5437 aarch64_set_vec_u8 (cpu
, vd
, i
,
5438 copy_vn
.b
[i
* 2] + copy_vn
.b
[i
* 2 + 1]);
5439 aarch64_set_vec_u8 (cpu
, vd
, i
+ range
,
5440 copy_vm
.b
[i
* 2] + copy_vm
.b
[i
* 2 + 1]);
5445 range
= full
? 4 : 2;
5446 for (i
= 0; i
< range
; i
++)
5448 aarch64_set_vec_u16 (cpu
, vd
, i
,
5449 copy_vn
.h
[i
* 2] + copy_vn
.h
[i
* 2 + 1]);
5450 aarch64_set_vec_u16 (cpu
, vd
, i
+ range
,
5451 copy_vm
.h
[i
* 2] + copy_vm
.h
[i
* 2 + 1]);
5456 range
= full
? 2 : 1;
5457 for (i
= 0; i
< range
; i
++)
5459 aarch64_set_vec_u32 (cpu
, vd
, i
,
5460 copy_vn
.w
[i
* 2] + copy_vn
.w
[i
* 2 + 1]);
5461 aarch64_set_vec_u32 (cpu
, vd
, i
+ range
,
5462 copy_vm
.w
[i
* 2] + copy_vm
.w
[i
* 2 + 1]);
5469 aarch64_set_vec_u64 (cpu
, vd
, 0, copy_vn
.v
[0] + copy_vn
.v
[1]);
5470 aarch64_set_vec_u64 (cpu
, vd
, 1, copy_vm
.v
[0] + copy_vm
.v
[1]);
5475 /* Float point vector convert to longer (precision). */
5477 do_vec_FCVTL (sim_cpu
*cpu
)
5480 instr[30] = half (0) / all (1)
5481 instr[29,23] = 00 1110 0
5482 instr[22] = single (0) / double (1)
5483 instr[21,10] = 10 0001 0111 10
5487 unsigned rn
= INSTR (9, 5);
5488 unsigned rd
= INSTR (4, 0);
5489 unsigned full
= INSTR (30, 30);
5492 NYI_assert (31, 31, 0);
5493 NYI_assert (29, 23, 0x1C);
5494 NYI_assert (21, 10, 0x85E);
5496 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5499 for (i
= 0; i
< 2; i
++)
5500 aarch64_set_vec_double (cpu
, rd
, i
,
5501 aarch64_get_vec_float (cpu
, rn
, i
+ 2*full
));
5508 /* TODO: Implement missing half-float support. */
5509 for (i
= 0; i
< 4; i
++)
5510 aarch64_set_vec_float (cpu
, rd
, i
,
5511 aarch64_get_vec_halffloat (cpu
, rn
, i
+ 4*full
));
5517 do_vec_FABS (sim_cpu
*cpu
)
5520 instr[30] = half(0)/full(1)
5521 instr[29,23] = 00 1110 1
5522 instr[22] = float(0)/double(1)
5523 instr[21,16] = 10 0000
5524 instr[15,10] = 1111 10
5528 unsigned vn
= INSTR (9, 5);
5529 unsigned vd
= INSTR (4, 0);
5530 unsigned full
= INSTR (30, 30);
5533 NYI_assert (29, 23, 0x1D);
5534 NYI_assert (21, 10, 0x83E);
5536 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5542 for (i
= 0; i
< 2; i
++)
5543 aarch64_set_vec_double (cpu
, vd
, i
,
5544 fabs (aarch64_get_vec_double (cpu
, vn
, i
)));
5548 for (i
= 0; i
< (full
? 4 : 2); i
++)
5549 aarch64_set_vec_float (cpu
, vd
, i
,
5550 fabsf (aarch64_get_vec_float (cpu
, vn
, i
)));
5555 do_vec_FCVTZS (sim_cpu
*cpu
)
5558 instr[30] = half (0) / all (1)
5559 instr[29,23] = 00 1110 1
5560 instr[22] = single (0) / double (1)
5561 instr[21,10] = 10 0001 1011 10
5565 unsigned rn
= INSTR (9, 5);
5566 unsigned rd
= INSTR (4, 0);
5567 unsigned full
= INSTR (30, 30);
5570 NYI_assert (31, 31, 0);
5571 NYI_assert (29, 23, 0x1D);
5572 NYI_assert (21, 10, 0x86E);
5574 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5580 for (i
= 0; i
< 2; i
++)
5581 aarch64_set_vec_s64 (cpu
, rd
, i
,
5582 (int64_t) aarch64_get_vec_double (cpu
, rn
, i
));
5585 for (i
= 0; i
< (full
? 4 : 2); i
++)
5586 aarch64_set_vec_s32 (cpu
, rd
, i
,
5587 (int32_t) aarch64_get_vec_float (cpu
, rn
, i
));
5591 do_vec_REV64 (sim_cpu
*cpu
)
5594 instr[30] = full/half
5595 instr[29,24] = 00 1110
5597 instr[21,10] = 10 0000 0000 10
5601 unsigned rn
= INSTR (9, 5);
5602 unsigned rd
= INSTR (4, 0);
5603 unsigned size
= INSTR (23, 22);
5604 unsigned full
= INSTR (30, 30);
5608 NYI_assert (29, 24, 0x0E);
5609 NYI_assert (21, 10, 0x802);
5611 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5615 for (i
= 0; i
< (full
? 16 : 8); i
++)
5616 val
.b
[i
^ 0x7] = aarch64_get_vec_u8 (cpu
, rn
, i
);
5620 for (i
= 0; i
< (full
? 8 : 4); i
++)
5621 val
.h
[i
^ 0x3] = aarch64_get_vec_u16 (cpu
, rn
, i
);
5625 for (i
= 0; i
< (full
? 4 : 2); i
++)
5626 val
.w
[i
^ 0x1] = aarch64_get_vec_u32 (cpu
, rn
, i
);
5633 aarch64_set_vec_u64 (cpu
, rd
, 0, val
.v
[0]);
5635 aarch64_set_vec_u64 (cpu
, rd
, 1, val
.v
[1]);
5639 do_vec_REV16 (sim_cpu
*cpu
)
5642 instr[30] = full/half
5643 instr[29,24] = 00 1110
5645 instr[21,10] = 10 0000 0001 10
5649 unsigned rn
= INSTR (9, 5);
5650 unsigned rd
= INSTR (4, 0);
5651 unsigned size
= INSTR (23, 22);
5652 unsigned full
= INSTR (30, 30);
5656 NYI_assert (29, 24, 0x0E);
5657 NYI_assert (21, 10, 0x806);
5659 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5663 for (i
= 0; i
< (full
? 16 : 8); i
++)
5664 val
.b
[i
^ 0x1] = aarch64_get_vec_u8 (cpu
, rn
, i
);
5671 aarch64_set_vec_u64 (cpu
, rd
, 0, val
.v
[0]);
5673 aarch64_set_vec_u64 (cpu
, rd
, 1, val
.v
[1]);
5677 do_vec_op1 (sim_cpu
*cpu
)
5680 instr[30] = half/full
5681 instr[29,24] = 00 1110
5684 instr[15,10] = sub-opcode
5687 NYI_assert (29, 24, 0x0E);
5689 if (INSTR (21, 21) == 0)
5691 if (INSTR (23, 22) == 0)
5693 if (INSTR (30, 30) == 1
5694 && INSTR (17, 14) == 0
5695 && INSTR (12, 10) == 7)
5696 return do_vec_ins_2 (cpu
);
5698 switch (INSTR (15, 10))
5700 case 0x01: do_vec_DUP_vector_into_vector (cpu
); return;
5701 case 0x03: do_vec_DUP_scalar_into_vector (cpu
); return;
5702 case 0x07: do_vec_INS (cpu
); return;
5703 case 0x0B: do_vec_SMOV_into_scalar (cpu
); return;
5704 case 0x0F: do_vec_UMOV_into_scalar (cpu
); return;
5710 do_vec_TBL (cpu
); return;
5714 do_vec_UZP (cpu
); return;
5716 case 0x0A: do_vec_TRN (cpu
); return;
5720 do_vec_ZIP (cpu
); return;
5727 switch (INSTR (13, 10))
5729 case 0x6: do_vec_UZP (cpu
); return;
5730 case 0xE: do_vec_ZIP (cpu
); return;
5731 case 0xA: do_vec_TRN (cpu
); return;
5736 switch (INSTR (15, 10))
5738 case 0x02: do_vec_REV64 (cpu
); return;
5739 case 0x06: do_vec_REV16 (cpu
); return;
5742 switch (INSTR (23, 21))
5744 case 1: do_vec_AND (cpu
); return;
5745 case 3: do_vec_BIC (cpu
); return;
5746 case 5: do_vec_ORR (cpu
); return;
5747 case 7: do_vec_ORN (cpu
); return;
5751 case 0x08: do_vec_sub_long (cpu
); return;
5752 case 0x0a: do_vec_XTN (cpu
); return;
5753 case 0x11: do_vec_SSHL (cpu
); return;
5754 case 0x16: do_vec_CNT (cpu
); return;
5755 case 0x19: do_vec_max (cpu
); return;
5756 case 0x1B: do_vec_min (cpu
); return;
5757 case 0x21: do_vec_add (cpu
); return;
5758 case 0x25: do_vec_MLA (cpu
); return;
5759 case 0x27: do_vec_mul (cpu
); return;
5760 case 0x2F: do_vec_ADDP (cpu
); return;
5761 case 0x30: do_vec_mull (cpu
); return;
5762 case 0x33: do_vec_FMLA (cpu
); return;
5763 case 0x35: do_vec_fadd (cpu
); return;
5766 switch (INSTR (20, 16))
5768 case 0x01: do_vec_FCVTL (cpu
); return;
5773 switch (INSTR (20, 16))
5775 case 0x00: do_vec_ABS (cpu
); return;
5776 case 0x01: do_vec_FCVTZS (cpu
); return;
5777 case 0x11: do_vec_ADDV (cpu
); return;
5783 do_vec_Fminmax (cpu
); return;
5795 do_vec_compare (cpu
); return;
5798 do_vec_FABS (cpu
); return;
5806 do_vec_xtl (sim_cpu
*cpu
)
5809 instr[30,29] = SXTL (00), UXTL (01), SXTL2 (10), UXTL2 (11)
5810 instr[28,22] = 0 1111 00
5811 instr[21,16] = size & shift (USHLL, SSHLL, USHLL2, SSHLL2)
5812 instr[15,10] = 1010 01
5813 instr[9,5] = V source
5814 instr[4,0] = V dest. */
5816 unsigned vs
= INSTR (9, 5);
5817 unsigned vd
= INSTR (4, 0);
5818 unsigned i
, shift
, bias
= 0;
5820 NYI_assert (28, 22, 0x3C);
5821 NYI_assert (15, 10, 0x29);
5823 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5824 switch (INSTR (30, 29))
5826 case 2: /* SXTL2, SSHLL2. */
5828 case 0: /* SXTL, SSHLL. */
5833 shift
= INSTR (20, 16);
5834 /* Get the source values before setting the destination values
5835 in case the source and destination are the same. */
5836 val1
= aarch64_get_vec_s32 (cpu
, vs
, bias
) << shift
;
5837 val2
= aarch64_get_vec_s32 (cpu
, vs
, bias
+ 1) << shift
;
5838 aarch64_set_vec_s64 (cpu
, vd
, 0, val1
);
5839 aarch64_set_vec_s64 (cpu
, vd
, 1, val2
);
5841 else if (INSTR (20, 20))
5844 int32_t v1
,v2
,v3
,v4
;
5846 shift
= INSTR (19, 16);
5848 for (i
= 0; i
< 4; i
++)
5849 v
[i
] = aarch64_get_vec_s16 (cpu
, vs
, bias
+ i
) << shift
;
5850 for (i
= 0; i
< 4; i
++)
5851 aarch64_set_vec_s32 (cpu
, vd
, i
, v
[i
]);
5856 NYI_assert (19, 19, 1);
5858 shift
= INSTR (18, 16);
5860 for (i
= 0; i
< 8; i
++)
5861 v
[i
] = aarch64_get_vec_s8 (cpu
, vs
, i
+ bias
) << shift
;
5862 for (i
= 0; i
< 8; i
++)
5863 aarch64_set_vec_s16 (cpu
, vd
, i
, v
[i
]);
5867 case 3: /* UXTL2, USHLL2. */
5869 case 1: /* UXTL, USHLL. */
5873 shift
= INSTR (20, 16);
5874 v1
= aarch64_get_vec_u32 (cpu
, vs
, bias
) << shift
;
5875 v2
= aarch64_get_vec_u32 (cpu
, vs
, bias
+ 1) << shift
;
5876 aarch64_set_vec_u64 (cpu
, vd
, 0, v1
);
5877 aarch64_set_vec_u64 (cpu
, vd
, 1, v2
);
5879 else if (INSTR (20, 20))
5882 shift
= INSTR (19, 16);
5884 for (i
= 0; i
< 4; i
++)
5885 v
[i
] = aarch64_get_vec_u16 (cpu
, vs
, i
+ bias
) << shift
;
5886 for (i
= 0; i
< 4; i
++)
5887 aarch64_set_vec_u32 (cpu
, vd
, i
, v
[i
]);
5892 NYI_assert (19, 19, 1);
5894 shift
= INSTR (18, 16);
5896 for (i
= 0; i
< 8; i
++)
5897 v
[i
] = aarch64_get_vec_u8 (cpu
, vs
, i
+ bias
) << shift
;
5898 for (i
= 0; i
< 8; i
++)
5899 aarch64_set_vec_u16 (cpu
, vd
, i
, v
[i
]);
5906 do_vec_SHL (sim_cpu
*cpu
)
5909 instr [30] = half(0)/full(1)
5910 instr [29,23] = 001 1110
5911 instr [22,16] = size and shift amount
5912 instr [15,10] = 01 0101
5914 instr [4, 0] = Vd. */
5917 int full
= INSTR (30, 30);
5918 unsigned vs
= INSTR (9, 5);
5919 unsigned vd
= INSTR (4, 0);
5922 NYI_assert (29, 23, 0x1E);
5923 NYI_assert (15, 10, 0x15);
5925 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5928 shift
= INSTR (21, 16);
5933 for (i
= 0; i
< 2; i
++)
5935 uint64_t val
= aarch64_get_vec_u64 (cpu
, vs
, i
);
5936 aarch64_set_vec_u64 (cpu
, vd
, i
, val
<< shift
);
5944 shift
= INSTR (20, 16);
5946 for (i
= 0; i
< (full
? 4 : 2); i
++)
5948 uint32_t val
= aarch64_get_vec_u32 (cpu
, vs
, i
);
5949 aarch64_set_vec_u32 (cpu
, vd
, i
, val
<< shift
);
5957 shift
= INSTR (19, 16);
5959 for (i
= 0; i
< (full
? 8 : 4); i
++)
5961 uint16_t val
= aarch64_get_vec_u16 (cpu
, vs
, i
);
5962 aarch64_set_vec_u16 (cpu
, vd
, i
, val
<< shift
);
5968 if (INSTR (19, 19) == 0)
5971 shift
= INSTR (18, 16);
5973 for (i
= 0; i
< (full
? 16 : 8); i
++)
5975 uint8_t val
= aarch64_get_vec_u8 (cpu
, vs
, i
);
5976 aarch64_set_vec_u8 (cpu
, vd
, i
, val
<< shift
);
5981 do_vec_SSHR_USHR (sim_cpu
*cpu
)
5984 instr [30] = half(0)/full(1)
5985 instr [29] = signed(0)/unsigned(1)
5986 instr [28,23] = 0 1111 0
5987 instr [22,16] = size and shift amount
5988 instr [15,10] = 0000 01
5990 instr [4, 0] = Vd. */
5992 int full
= INSTR (30, 30);
5993 int sign
= ! INSTR (29, 29);
5994 unsigned shift
= INSTR (22, 16);
5995 unsigned vs
= INSTR (9, 5);
5996 unsigned vd
= INSTR (4, 0);
5999 NYI_assert (28, 23, 0x1E);
6000 NYI_assert (15, 10, 0x01);
6002 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6005 shift
= 128 - shift
;
6011 for (i
= 0; i
< 2; i
++)
6013 int64_t val
= aarch64_get_vec_s64 (cpu
, vs
, i
);
6014 aarch64_set_vec_s64 (cpu
, vd
, i
, val
>> shift
);
6017 for (i
= 0; i
< 2; i
++)
6019 uint64_t val
= aarch64_get_vec_u64 (cpu
, vs
, i
);
6020 aarch64_set_vec_u64 (cpu
, vd
, i
, val
>> shift
);
6031 for (i
= 0; i
< (full
? 4 : 2); i
++)
6033 int32_t val
= aarch64_get_vec_s32 (cpu
, vs
, i
);
6034 aarch64_set_vec_s32 (cpu
, vd
, i
, val
>> shift
);
6037 for (i
= 0; i
< (full
? 4 : 2); i
++)
6039 uint32_t val
= aarch64_get_vec_u32 (cpu
, vs
, i
);
6040 aarch64_set_vec_u32 (cpu
, vd
, i
, val
>> shift
);
6051 for (i
= 0; i
< (full
? 8 : 4); i
++)
6053 int16_t val
= aarch64_get_vec_s16 (cpu
, vs
, i
);
6054 aarch64_set_vec_s16 (cpu
, vd
, i
, val
>> shift
);
6057 for (i
= 0; i
< (full
? 8 : 4); i
++)
6059 uint16_t val
= aarch64_get_vec_u16 (cpu
, vs
, i
);
6060 aarch64_set_vec_u16 (cpu
, vd
, i
, val
>> shift
);
6066 if (INSTR (19, 19) == 0)
6072 for (i
= 0; i
< (full
? 16 : 8); i
++)
6074 int8_t val
= aarch64_get_vec_s8 (cpu
, vs
, i
);
6075 aarch64_set_vec_s8 (cpu
, vd
, i
, val
>> shift
);
6078 for (i
= 0; i
< (full
? 16 : 8); i
++)
6080 uint8_t val
= aarch64_get_vec_u8 (cpu
, vs
, i
);
6081 aarch64_set_vec_u8 (cpu
, vd
, i
, val
>> shift
);
6086 do_vec_MUL_by_element (sim_cpu
*cpu
)
6089 instr[30] = half/full
6090 instr[29,24] = 00 1111
6101 unsigned full
= INSTR (30, 30);
6102 unsigned L
= INSTR (21, 21);
6103 unsigned H
= INSTR (11, 11);
6104 unsigned vn
= INSTR (9, 5);
6105 unsigned vd
= INSTR (4, 0);
6106 unsigned size
= INSTR (23, 22);
6111 NYI_assert (29, 24, 0x0F);
6112 NYI_assert (15, 12, 0x8);
6113 NYI_assert (10, 10, 0);
6115 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6120 /* 16 bit products. */
6125 index
= (H
<< 2) | (L
<< 1) | INSTR (20, 20);
6126 vm
= INSTR (19, 16);
6127 element2
= aarch64_get_vec_u16 (cpu
, vm
, index
);
6129 for (e
= 0; e
< (full
? 8 : 4); e
++)
6131 element1
= aarch64_get_vec_u16 (cpu
, vn
, e
);
6132 product
= element1
* element2
;
6133 aarch64_set_vec_u16 (cpu
, vd
, e
, product
);
6140 /* 32 bit products. */
6145 index
= (H
<< 1) | L
;
6146 vm
= INSTR (20, 16);
6147 element2
= aarch64_get_vec_u32 (cpu
, vm
, index
);
6149 for (e
= 0; e
< (full
? 4 : 2); e
++)
6151 element1
= aarch64_get_vec_u32 (cpu
, vn
, e
);
6152 product
= element1
* element2
;
6153 aarch64_set_vec_u32 (cpu
, vd
, e
, product
);
6164 do_FMLA_by_element (sim_cpu
*cpu
)
6167 instr[30] = half/full
6168 instr[29,23] = 00 1111 1
6178 unsigned full
= INSTR (30, 30);
6179 unsigned size
= INSTR (22, 22);
6180 unsigned L
= INSTR (21, 21);
6181 unsigned vm
= INSTR (20, 16);
6182 unsigned H
= INSTR (11, 11);
6183 unsigned vn
= INSTR (9, 5);
6184 unsigned vd
= INSTR (4, 0);
6187 NYI_assert (29, 23, 0x1F);
6188 NYI_assert (15, 12, 0x1);
6189 NYI_assert (10, 10, 0);
6191 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6194 double element1
, element2
;
6199 element2
= aarch64_get_vec_double (cpu
, vm
, H
);
6201 for (e
= 0; e
< 2; e
++)
6203 element1
= aarch64_get_vec_double (cpu
, vn
, e
);
6204 element1
*= element2
;
6205 element1
+= aarch64_get_vec_double (cpu
, vd
, e
);
6206 aarch64_set_vec_double (cpu
, vd
, e
, element1
);
6212 float element2
= aarch64_get_vec_float (cpu
, vm
, (H
<< 1) | L
);
6214 for (e
= 0; e
< (full
? 4 : 2); e
++)
6216 element1
= aarch64_get_vec_float (cpu
, vn
, e
);
6217 element1
*= element2
;
6218 element1
+= aarch64_get_vec_float (cpu
, vd
, e
);
6219 aarch64_set_vec_float (cpu
, vd
, e
, element1
);
6225 do_vec_op2 (sim_cpu
*cpu
)
6228 instr[30] = half/full
6229 instr[29,24] = 00 1111
6231 instr[22,16] = element size & index
6232 instr[15,10] = sub-opcode
6236 NYI_assert (29, 24, 0x0F);
6238 if (INSTR (23, 23) != 0)
6240 switch (INSTR (15, 10))
6244 do_FMLA_by_element (cpu
);
6249 do_vec_MUL_by_element (cpu
);
6258 switch (INSTR (15, 10))
6260 case 0x01: do_vec_SSHR_USHR (cpu
); return;
6261 case 0x15: do_vec_SHL (cpu
); return;
6263 case 0x22: do_vec_MUL_by_element (cpu
); return;
6264 case 0x29: do_vec_xtl (cpu
); return;
6271 do_vec_neg (sim_cpu
*cpu
)
6274 instr[30] = full(1)/half(0)
6275 instr[29,24] = 10 1110
6276 instr[23,22] = size: byte(00), half (01), word (10), long (11)
6277 instr[21,10] = 1000 0010 1110
6281 int full
= INSTR (30, 30);
6282 unsigned vs
= INSTR (9, 5);
6283 unsigned vd
= INSTR (4, 0);
6286 NYI_assert (29, 24, 0x2E);
6287 NYI_assert (21, 10, 0x82E);
6289 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6290 switch (INSTR (23, 22))
6293 for (i
= 0; i
< (full
? 16 : 8); i
++)
6294 aarch64_set_vec_s8 (cpu
, vd
, i
, - aarch64_get_vec_s8 (cpu
, vs
, i
));
6298 for (i
= 0; i
< (full
? 8 : 4); i
++)
6299 aarch64_set_vec_s16 (cpu
, vd
, i
, - aarch64_get_vec_s16 (cpu
, vs
, i
));
6303 for (i
= 0; i
< (full
? 4 : 2); i
++)
6304 aarch64_set_vec_s32 (cpu
, vd
, i
, - aarch64_get_vec_s32 (cpu
, vs
, i
));
6310 for (i
= 0; i
< 2; i
++)
6311 aarch64_set_vec_s64 (cpu
, vd
, i
, - aarch64_get_vec_s64 (cpu
, vs
, i
));
6317 do_vec_sqrt (sim_cpu
*cpu
)
6320 instr[30] = full(1)/half(0)
6321 instr[29,23] = 101 1101
6322 instr[22] = single(0)/double(1)
6323 instr[21,10] = 1000 0111 1110
6327 int full
= INSTR (30, 30);
6328 unsigned vs
= INSTR (9, 5);
6329 unsigned vd
= INSTR (4, 0);
6332 NYI_assert (29, 23, 0x5B);
6333 NYI_assert (21, 10, 0x87E);
6335 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6336 if (INSTR (22, 22) == 0)
6337 for (i
= 0; i
< (full
? 4 : 2); i
++)
6338 aarch64_set_vec_float (cpu
, vd
, i
,
6339 sqrtf (aarch64_get_vec_float (cpu
, vs
, i
)));
6341 for (i
= 0; i
< 2; i
++)
6342 aarch64_set_vec_double (cpu
, vd
, i
,
6343 sqrt (aarch64_get_vec_double (cpu
, vs
, i
)));
6347 do_vec_mls_indexed (sim_cpu
*cpu
)
6350 instr[30] = half(0)/full(1)
6351 instr[29,24] = 10 1111
6352 instr[23,22] = 16-bit(01)/32-bit(10)
6353 instr[21,20+11] = index (if 16-bit)
6354 instr[21+11] = index (if 32-bit)
6357 instr[11] = part of index
6362 int full
= INSTR (30, 30);
6363 unsigned vs
= INSTR (9, 5);
6364 unsigned vd
= INSTR (4, 0);
6365 unsigned vm
= INSTR (20, 16);
6368 NYI_assert (15, 12, 4);
6369 NYI_assert (10, 10, 0);
6371 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6372 switch (INSTR (23, 22))
6382 elem
= (INSTR (21, 20) << 1) | INSTR (11, 11);
6383 val
= aarch64_get_vec_u16 (cpu
, vm
, elem
);
6385 for (i
= 0; i
< (full
? 8 : 4); i
++)
6386 aarch64_set_vec_u32 (cpu
, vd
, i
,
6387 aarch64_get_vec_u32 (cpu
, vd
, i
) -
6388 (aarch64_get_vec_u32 (cpu
, vs
, i
) * val
));
6394 unsigned elem
= (INSTR (21, 21) << 1) | INSTR (11, 11);
6395 uint64_t val
= aarch64_get_vec_u32 (cpu
, vm
, elem
);
6397 for (i
= 0; i
< (full
? 4 : 2); i
++)
6398 aarch64_set_vec_u64 (cpu
, vd
, i
,
6399 aarch64_get_vec_u64 (cpu
, vd
, i
) -
6400 (aarch64_get_vec_u64 (cpu
, vs
, i
) * val
));
6412 do_vec_SUB (sim_cpu
*cpu
)
6415 instr [30] = half(0)/full(1)
6416 instr [29,24] = 10 1110
6417 instr [23,22] = size: byte(00, half(01), word (10), long (11)
6420 instr [15,10] = 10 0001
6422 instr [4, 0] = Vd. */
6424 unsigned full
= INSTR (30, 30);
6425 unsigned vm
= INSTR (20, 16);
6426 unsigned vn
= INSTR (9, 5);
6427 unsigned vd
= INSTR (4, 0);
6430 NYI_assert (29, 24, 0x2E);
6431 NYI_assert (21, 21, 1);
6432 NYI_assert (15, 10, 0x21);
6434 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6435 switch (INSTR (23, 22))
6438 for (i
= 0; i
< (full
? 16 : 8); i
++)
6439 aarch64_set_vec_s8 (cpu
, vd
, i
,
6440 aarch64_get_vec_s8 (cpu
, vn
, i
)
6441 - aarch64_get_vec_s8 (cpu
, vm
, i
));
6445 for (i
= 0; i
< (full
? 8 : 4); i
++)
6446 aarch64_set_vec_s16 (cpu
, vd
, i
,
6447 aarch64_get_vec_s16 (cpu
, vn
, i
)
6448 - aarch64_get_vec_s16 (cpu
, vm
, i
));
6452 for (i
= 0; i
< (full
? 4 : 2); i
++)
6453 aarch64_set_vec_s32 (cpu
, vd
, i
,
6454 aarch64_get_vec_s32 (cpu
, vn
, i
)
6455 - aarch64_get_vec_s32 (cpu
, vm
, i
));
6462 for (i
= 0; i
< 2; i
++)
6463 aarch64_set_vec_s64 (cpu
, vd
, i
,
6464 aarch64_get_vec_s64 (cpu
, vn
, i
)
6465 - aarch64_get_vec_s64 (cpu
, vm
, i
));
6471 do_vec_MLS (sim_cpu
*cpu
)
6474 instr [30] = half(0)/full(1)
6475 instr [29,24] = 10 1110
6476 instr [23,22] = size: byte(00, half(01), word (10)
6479 instr [15,10] = 10 0101
6481 instr [4, 0] = Vd. */
6483 unsigned full
= INSTR (30, 30);
6484 unsigned vm
= INSTR (20, 16);
6485 unsigned vn
= INSTR (9, 5);
6486 unsigned vd
= INSTR (4, 0);
6489 NYI_assert (29, 24, 0x2E);
6490 NYI_assert (21, 21, 1);
6491 NYI_assert (15, 10, 0x25);
6493 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6494 switch (INSTR (23, 22))
6497 for (i
= 0; i
< (full
? 16 : 8); i
++)
6498 aarch64_set_vec_u8 (cpu
, vd
, i
,
6499 aarch64_get_vec_u8 (cpu
, vd
, i
)
6500 - (aarch64_get_vec_u8 (cpu
, vn
, i
)
6501 * aarch64_get_vec_u8 (cpu
, vm
, i
)));
6505 for (i
= 0; i
< (full
? 8 : 4); i
++)
6506 aarch64_set_vec_u16 (cpu
, vd
, i
,
6507 aarch64_get_vec_u16 (cpu
, vd
, i
)
6508 - (aarch64_get_vec_u16 (cpu
, vn
, i
)
6509 * aarch64_get_vec_u16 (cpu
, vm
, i
)));
6513 for (i
= 0; i
< (full
? 4 : 2); i
++)
6514 aarch64_set_vec_u32 (cpu
, vd
, i
,
6515 aarch64_get_vec_u32 (cpu
, vd
, i
)
6516 - (aarch64_get_vec_u32 (cpu
, vn
, i
)
6517 * aarch64_get_vec_u32 (cpu
, vm
, i
)));
6526 do_vec_FDIV (sim_cpu
*cpu
)
6529 instr [30] = half(0)/full(1)
6530 instr [29,23] = 10 1110 0
6531 instr [22] = float()/double(1)
6534 instr [15,10] = 1111 11
6536 instr [4, 0] = Vd. */
6538 unsigned full
= INSTR (30, 30);
6539 unsigned vm
= INSTR (20, 16);
6540 unsigned vn
= INSTR (9, 5);
6541 unsigned vd
= INSTR (4, 0);
6544 NYI_assert (29, 23, 0x5C);
6545 NYI_assert (21, 21, 1);
6546 NYI_assert (15, 10, 0x3F);
6548 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6554 for (i
= 0; i
< 2; i
++)
6555 aarch64_set_vec_double (cpu
, vd
, i
,
6556 aarch64_get_vec_double (cpu
, vn
, i
)
6557 / aarch64_get_vec_double (cpu
, vm
, i
));
6560 for (i
= 0; i
< (full
? 4 : 2); i
++)
6561 aarch64_set_vec_float (cpu
, vd
, i
,
6562 aarch64_get_vec_float (cpu
, vn
, i
)
6563 / aarch64_get_vec_float (cpu
, vm
, i
));
6567 do_vec_FMUL (sim_cpu
*cpu
)
6570 instr [30] = half(0)/full(1)
6571 instr [29,23] = 10 1110 0
6572 instr [22] = float(0)/double(1)
6575 instr [15,10] = 1101 11
6577 instr [4, 0] = Vd. */
6579 unsigned full
= INSTR (30, 30);
6580 unsigned vm
= INSTR (20, 16);
6581 unsigned vn
= INSTR (9, 5);
6582 unsigned vd
= INSTR (4, 0);
6585 NYI_assert (29, 23, 0x5C);
6586 NYI_assert (21, 21, 1);
6587 NYI_assert (15, 10, 0x37);
6589 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6595 for (i
= 0; i
< 2; i
++)
6596 aarch64_set_vec_double (cpu
, vd
, i
,
6597 aarch64_get_vec_double (cpu
, vn
, i
)
6598 * aarch64_get_vec_double (cpu
, vm
, i
));
6601 for (i
= 0; i
< (full
? 4 : 2); i
++)
6602 aarch64_set_vec_float (cpu
, vd
, i
,
6603 aarch64_get_vec_float (cpu
, vn
, i
)
6604 * aarch64_get_vec_float (cpu
, vm
, i
));
6608 do_vec_FADDP (sim_cpu
*cpu
)
6611 instr [30] = half(0)/full(1)
6612 instr [29,23] = 10 1110 0
6613 instr [22] = float(0)/double(1)
6616 instr [15,10] = 1101 01
6618 instr [4, 0] = Vd. */
6620 unsigned full
= INSTR (30, 30);
6621 unsigned vm
= INSTR (20, 16);
6622 unsigned vn
= INSTR (9, 5);
6623 unsigned vd
= INSTR (4, 0);
6625 NYI_assert (29, 23, 0x5C);
6626 NYI_assert (21, 21, 1);
6627 NYI_assert (15, 10, 0x35);
6629 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6632 /* Extract values before adding them incase vd == vn/vm. */
6633 double tmp1
= aarch64_get_vec_double (cpu
, vn
, 0);
6634 double tmp2
= aarch64_get_vec_double (cpu
, vn
, 1);
6635 double tmp3
= aarch64_get_vec_double (cpu
, vm
, 0);
6636 double tmp4
= aarch64_get_vec_double (cpu
, vm
, 1);
6641 aarch64_set_vec_double (cpu
, vd
, 0, tmp1
+ tmp2
);
6642 aarch64_set_vec_double (cpu
, vd
, 1, tmp3
+ tmp4
);
6646 /* Extract values before adding them incase vd == vn/vm. */
6647 float tmp1
= aarch64_get_vec_float (cpu
, vn
, 0);
6648 float tmp2
= aarch64_get_vec_float (cpu
, vn
, 1);
6649 float tmp5
= aarch64_get_vec_float (cpu
, vm
, 0);
6650 float tmp6
= aarch64_get_vec_float (cpu
, vm
, 1);
6654 float tmp3
= aarch64_get_vec_float (cpu
, vn
, 2);
6655 float tmp4
= aarch64_get_vec_float (cpu
, vn
, 3);
6656 float tmp7
= aarch64_get_vec_float (cpu
, vm
, 2);
6657 float tmp8
= aarch64_get_vec_float (cpu
, vm
, 3);
6659 aarch64_set_vec_float (cpu
, vd
, 0, tmp1
+ tmp2
);
6660 aarch64_set_vec_float (cpu
, vd
, 1, tmp3
+ tmp4
);
6661 aarch64_set_vec_float (cpu
, vd
, 2, tmp5
+ tmp6
);
6662 aarch64_set_vec_float (cpu
, vd
, 3, tmp7
+ tmp8
);
6666 aarch64_set_vec_float (cpu
, vd
, 0, tmp1
+ tmp2
);
6667 aarch64_set_vec_float (cpu
, vd
, 1, tmp5
+ tmp6
);
6673 do_vec_FSQRT (sim_cpu
*cpu
)
6676 instr[30] = half(0)/full(1)
6677 instr[29,23] = 10 1110 1
6678 instr[22] = single(0)/double(1)
6679 instr[21,10] = 10 0001 1111 10
6681 instr[4,0] = Vdest. */
6683 unsigned vn
= INSTR (9, 5);
6684 unsigned vd
= INSTR (4, 0);
6685 unsigned full
= INSTR (30, 30);
6688 NYI_assert (29, 23, 0x5D);
6689 NYI_assert (21, 10, 0x87E);
6691 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6697 for (i
= 0; i
< 2; i
++)
6698 aarch64_set_vec_double (cpu
, vd
, i
,
6699 sqrt (aarch64_get_vec_double (cpu
, vn
, i
)));
6703 for (i
= 0; i
< (full
? 4 : 2); i
++)
6704 aarch64_set_vec_float (cpu
, vd
, i
,
6705 sqrtf (aarch64_get_vec_float (cpu
, vn
, i
)));
6710 do_vec_FNEG (sim_cpu
*cpu
)
6713 instr[30] = half (0)/full (1)
6714 instr[29,23] = 10 1110 1
6715 instr[22] = single (0)/double (1)
6716 instr[21,10] = 10 0000 1111 10
6718 instr[4,0] = Vdest. */
6720 unsigned vn
= INSTR (9, 5);
6721 unsigned vd
= INSTR (4, 0);
6722 unsigned full
= INSTR (30, 30);
6725 NYI_assert (29, 23, 0x5D);
6726 NYI_assert (21, 10, 0x83E);
6728 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6734 for (i
= 0; i
< 2; i
++)
6735 aarch64_set_vec_double (cpu
, vd
, i
,
6736 - aarch64_get_vec_double (cpu
, vn
, i
));
6740 for (i
= 0; i
< (full
? 4 : 2); i
++)
6741 aarch64_set_vec_float (cpu
, vd
, i
,
6742 - aarch64_get_vec_float (cpu
, vn
, i
));
6747 do_vec_NOT (sim_cpu
*cpu
)
6750 instr[30] = half (0)/full (1)
6751 instr[29,10] = 10 1110 0010 0000 0101 10
6755 unsigned vn
= INSTR (9, 5);
6756 unsigned vd
= INSTR (4, 0);
6758 int full
= INSTR (30, 30);
6760 NYI_assert (29, 10, 0xB8816);
6762 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6763 for (i
= 0; i
< (full
? 16 : 8); i
++)
6764 aarch64_set_vec_u8 (cpu
, vd
, i
, ~ aarch64_get_vec_u8 (cpu
, vn
, i
));
6768 clz (uint64_t val
, unsigned size
)
6773 mask
<<= (size
- 1);
6788 do_vec_CLZ (sim_cpu
*cpu
)
6791 instr[30] = half (0)/full (1)
6792 instr[29,24] = 10 1110
6794 instr[21,10] = 10 0000 0100 10
6798 unsigned vn
= INSTR (9, 5);
6799 unsigned vd
= INSTR (4, 0);
6801 int full
= INSTR (30,30);
6803 NYI_assert (29, 24, 0x2E);
6804 NYI_assert (21, 10, 0x812);
6806 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6807 switch (INSTR (23, 22))
6810 for (i
= 0; i
< (full
? 16 : 8); i
++)
6811 aarch64_set_vec_u8 (cpu
, vd
, i
, clz (aarch64_get_vec_u8 (cpu
, vn
, i
), 8));
6814 for (i
= 0; i
< (full
? 8 : 4); i
++)
6815 aarch64_set_vec_u16 (cpu
, vd
, i
, clz (aarch64_get_vec_u16 (cpu
, vn
, i
), 16));
6818 for (i
= 0; i
< (full
? 4 : 2); i
++)
6819 aarch64_set_vec_u32 (cpu
, vd
, i
, clz (aarch64_get_vec_u32 (cpu
, vn
, i
), 32));
6824 aarch64_set_vec_u64 (cpu
, vd
, 0, clz (aarch64_get_vec_u64 (cpu
, vn
, 0), 64));
6825 aarch64_set_vec_u64 (cpu
, vd
, 1, clz (aarch64_get_vec_u64 (cpu
, vn
, 1), 64));
6831 do_vec_MOV_element (sim_cpu
*cpu
)
6833 /* instr[31,21] = 0110 1110 000
6834 instr[20,16] = size & dest index
6836 instr[14,11] = source index
6841 unsigned vs
= INSTR (9, 5);
6842 unsigned vd
= INSTR (4, 0);
6846 NYI_assert (31, 21, 0x370);
6847 NYI_assert (15, 15, 0);
6848 NYI_assert (10, 10, 1);
6850 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6854 src_index
= INSTR (14, 11);
6855 dst_index
= INSTR (20, 17);
6856 aarch64_set_vec_u8 (cpu
, vd
, dst_index
,
6857 aarch64_get_vec_u8 (cpu
, vs
, src_index
));
6859 else if (INSTR (17, 17))
6862 NYI_assert (11, 11, 0);
6863 src_index
= INSTR (14, 12);
6864 dst_index
= INSTR (20, 18);
6865 aarch64_set_vec_u16 (cpu
, vd
, dst_index
,
6866 aarch64_get_vec_u16 (cpu
, vs
, src_index
));
6868 else if (INSTR (18, 18))
6871 NYI_assert (12, 11, 0);
6872 src_index
= INSTR (14, 13);
6873 dst_index
= INSTR (20, 19);
6874 aarch64_set_vec_u32 (cpu
, vd
, dst_index
,
6875 aarch64_get_vec_u32 (cpu
, vs
, src_index
));
6879 NYI_assert (19, 19, 1);
6880 NYI_assert (13, 11, 0);
6881 src_index
= INSTR (14, 14);
6882 dst_index
= INSTR (20, 20);
6883 aarch64_set_vec_u64 (cpu
, vd
, dst_index
,
6884 aarch64_get_vec_u64 (cpu
, vs
, src_index
));
6889 do_vec_REV32 (sim_cpu
*cpu
)
6892 instr[30] = full/half
6893 instr[29,24] = 10 1110
6895 instr[21,10] = 10 0000 0000 10
6899 unsigned rn
= INSTR (9, 5);
6900 unsigned rd
= INSTR (4, 0);
6901 unsigned size
= INSTR (23, 22);
6902 unsigned full
= INSTR (30, 30);
6906 NYI_assert (29, 24, 0x2E);
6907 NYI_assert (21, 10, 0x802);
6909 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6913 for (i
= 0; i
< (full
? 16 : 8); i
++)
6914 val
.b
[i
^ 0x3] = aarch64_get_vec_u8 (cpu
, rn
, i
);
6918 for (i
= 0; i
< (full
? 8 : 4); i
++)
6919 val
.h
[i
^ 0x1] = aarch64_get_vec_u16 (cpu
, rn
, i
);
6926 aarch64_set_vec_u64 (cpu
, rd
, 0, val
.v
[0]);
6928 aarch64_set_vec_u64 (cpu
, rd
, 1, val
.v
[1]);
6932 do_vec_EXT (sim_cpu
*cpu
)
6935 instr[30] = full/half
6936 instr[29,21] = 10 1110 000
6939 instr[14,11] = source index
6944 unsigned vm
= INSTR (20, 16);
6945 unsigned vn
= INSTR (9, 5);
6946 unsigned vd
= INSTR (4, 0);
6947 unsigned src_index
= INSTR (14, 11);
6948 unsigned full
= INSTR (30, 30);
6953 NYI_assert (31, 21, 0x370);
6954 NYI_assert (15, 15, 0);
6955 NYI_assert (10, 10, 0);
6957 if (!full
&& (src_index
& 0x8))
6962 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6963 for (i
= src_index
; i
< (full
? 16 : 8); i
++)
6964 val
.b
[j
++] = aarch64_get_vec_u8 (cpu
, vn
, i
);
6965 for (i
= 0; i
< src_index
; i
++)
6966 val
.b
[j
++] = aarch64_get_vec_u8 (cpu
, vm
, i
);
6968 aarch64_set_vec_u64 (cpu
, vd
, 0, val
.v
[0]);
6970 aarch64_set_vec_u64 (cpu
, vd
, 1, val
.v
[1]);
6974 dexAdvSIMD0 (sim_cpu
*cpu
)
6976 /* instr [28,25] = 0 111. */
6977 if ( INSTR (15, 10) == 0x07
6981 if (INSTR (31, 21) == 0x075
6982 || INSTR (31, 21) == 0x275)
6984 do_vec_MOV_whole_vector (cpu
);
6989 if (INSTR (29, 19) == 0x1E0)
6991 do_vec_MOV_immediate (cpu
);
6995 if (INSTR (29, 19) == 0x5E0)
7001 if (INSTR (29, 19) == 0x1C0
7002 || INSTR (29, 19) == 0x1C1)
7004 if (INSTR (15, 10) == 0x03)
7006 do_vec_DUP_scalar_into_vector (cpu
);
7011 switch (INSTR (29, 24))
7013 case 0x0E: do_vec_op1 (cpu
); return;
7014 case 0x0F: do_vec_op2 (cpu
); return;
7017 if (INSTR (21, 21) == 1)
7019 switch (INSTR (15, 10))
7026 switch (INSTR (23, 22))
7028 case 0: do_vec_EOR (cpu
); return;
7029 case 1: do_vec_BSL (cpu
); return;
7031 case 3: do_vec_bit (cpu
); return;
7035 case 0x08: do_vec_sub_long (cpu
); return;
7036 case 0x11: do_vec_USHL (cpu
); return;
7037 case 0x12: do_vec_CLZ (cpu
); return;
7038 case 0x16: do_vec_NOT (cpu
); return;
7039 case 0x19: do_vec_max (cpu
); return;
7040 case 0x1B: do_vec_min (cpu
); return;
7041 case 0x21: do_vec_SUB (cpu
); return;
7042 case 0x25: do_vec_MLS (cpu
); return;
7043 case 0x31: do_vec_FminmaxNMP (cpu
); return;
7044 case 0x35: do_vec_FADDP (cpu
); return;
7045 case 0x37: do_vec_FMUL (cpu
); return;
7046 case 0x3F: do_vec_FDIV (cpu
); return;
7049 switch (INSTR (20, 16))
7051 case 0x00: do_vec_FNEG (cpu
); return;
7052 case 0x01: do_vec_FSQRT (cpu
); return;
7066 do_vec_compare (cpu
); return;
7073 if (INSTR (31, 21) == 0x370)
7076 do_vec_MOV_element (cpu
);
7082 switch (INSTR (21, 10))
7084 case 0x82E: do_vec_neg (cpu
); return;
7085 case 0x87E: do_vec_sqrt (cpu
); return;
7087 if (INSTR (15, 10) == 0x30)
7097 switch (INSTR (15, 10))
7099 case 0x01: do_vec_SSHR_USHR (cpu
); return;
7101 case 0x12: do_vec_mls_indexed (cpu
); return;
7102 case 0x29: do_vec_xtl (cpu
); return;
7116 /* Float multiply add. */
7118 fmadds (sim_cpu
*cpu
)
7120 unsigned sa
= INSTR (14, 10);
7121 unsigned sm
= INSTR (20, 16);
7122 unsigned sn
= INSTR ( 9, 5);
7123 unsigned sd
= INSTR ( 4, 0);
7125 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7126 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sa
)
7127 + aarch64_get_FP_float (cpu
, sn
)
7128 * aarch64_get_FP_float (cpu
, sm
));
7131 /* Double multiply add. */
7133 fmaddd (sim_cpu
*cpu
)
7135 unsigned sa
= INSTR (14, 10);
7136 unsigned sm
= INSTR (20, 16);
7137 unsigned sn
= INSTR ( 9, 5);
7138 unsigned sd
= INSTR ( 4, 0);
7140 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7141 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sa
)
7142 + aarch64_get_FP_double (cpu
, sn
)
7143 * aarch64_get_FP_double (cpu
, sm
));
7146 /* Float multiply subtract. */
7148 fmsubs (sim_cpu
*cpu
)
7150 unsigned sa
= INSTR (14, 10);
7151 unsigned sm
= INSTR (20, 16);
7152 unsigned sn
= INSTR ( 9, 5);
7153 unsigned sd
= INSTR ( 4, 0);
7155 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7156 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sa
)
7157 - aarch64_get_FP_float (cpu
, sn
)
7158 * aarch64_get_FP_float (cpu
, sm
));
7161 /* Double multiply subtract. */
7163 fmsubd (sim_cpu
*cpu
)
7165 unsigned sa
= INSTR (14, 10);
7166 unsigned sm
= INSTR (20, 16);
7167 unsigned sn
= INSTR ( 9, 5);
7168 unsigned sd
= INSTR ( 4, 0);
7170 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7171 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sa
)
7172 - aarch64_get_FP_double (cpu
, sn
)
7173 * aarch64_get_FP_double (cpu
, sm
));
7176 /* Float negative multiply add. */
7178 fnmadds (sim_cpu
*cpu
)
7180 unsigned sa
= INSTR (14, 10);
7181 unsigned sm
= INSTR (20, 16);
7182 unsigned sn
= INSTR ( 9, 5);
7183 unsigned sd
= INSTR ( 4, 0);
7185 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7186 aarch64_set_FP_float (cpu
, sd
, - aarch64_get_FP_float (cpu
, sa
)
7187 + (- aarch64_get_FP_float (cpu
, sn
))
7188 * aarch64_get_FP_float (cpu
, sm
));
7191 /* Double negative multiply add. */
7193 fnmaddd (sim_cpu
*cpu
)
7195 unsigned sa
= INSTR (14, 10);
7196 unsigned sm
= INSTR (20, 16);
7197 unsigned sn
= INSTR ( 9, 5);
7198 unsigned sd
= INSTR ( 4, 0);
7200 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7201 aarch64_set_FP_double (cpu
, sd
, - aarch64_get_FP_double (cpu
, sa
)
7202 + (- aarch64_get_FP_double (cpu
, sn
))
7203 * aarch64_get_FP_double (cpu
, sm
));
7206 /* Float negative multiply subtract. */
7208 fnmsubs (sim_cpu
*cpu
)
7210 unsigned sa
= INSTR (14, 10);
7211 unsigned sm
= INSTR (20, 16);
7212 unsigned sn
= INSTR ( 9, 5);
7213 unsigned sd
= INSTR ( 4, 0);
7215 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7216 aarch64_set_FP_float (cpu
, sd
, - aarch64_get_FP_float (cpu
, sa
)
7217 + aarch64_get_FP_float (cpu
, sn
)
7218 * aarch64_get_FP_float (cpu
, sm
));
7221 /* Double negative multiply subtract. */
7223 fnmsubd (sim_cpu
*cpu
)
7225 unsigned sa
= INSTR (14, 10);
7226 unsigned sm
= INSTR (20, 16);
7227 unsigned sn
= INSTR ( 9, 5);
7228 unsigned sd
= INSTR ( 4, 0);
7230 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7231 aarch64_set_FP_double (cpu
, sd
, - aarch64_get_FP_double (cpu
, sa
)
7232 + aarch64_get_FP_double (cpu
, sn
)
7233 * aarch64_get_FP_double (cpu
, sm
));
7237 dexSimpleFPDataProc3Source (sim_cpu
*cpu
)
7239 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
7241 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
7244 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
7245 instr[21] ==> o1 : 0 ==> unnegated, 1 ==> negated
7246 instr[15] ==> o2 : 0 ==> ADD, 1 ==> SUB */
7248 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
7249 /* dispatch on combined type:o1:o2. */
7250 uint32_t dispatch
= (INSTR (23, 21) << 1) | INSTR (15, 15);
7257 case 0: fmadds (cpu
); return;
7258 case 1: fmsubs (cpu
); return;
7259 case 2: fnmadds (cpu
); return;
7260 case 3: fnmsubs (cpu
); return;
7261 case 4: fmaddd (cpu
); return;
7262 case 5: fmsubd (cpu
); return;
7263 case 6: fnmaddd (cpu
); return;
7264 case 7: fnmsubd (cpu
); return;
7266 /* type > 1 is currently unallocated. */
7272 dexSimpleFPFixedConvert (sim_cpu
*cpu
)
7278 dexSimpleFPCondCompare (sim_cpu
*cpu
)
7280 /* instr [31,23] = 0001 1110 0
7284 instr [15,12] = condition
7288 instr [3,0] = nzcv */
7290 unsigned rm
= INSTR (20, 16);
7291 unsigned rn
= INSTR (9, 5);
7293 NYI_assert (31, 23, 0x3C);
7294 NYI_assert (11, 10, 0x1);
7295 NYI_assert (4, 4, 0);
7297 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7298 if (! testConditionCode (cpu
, INSTR (15, 12)))
7300 aarch64_set_CPSR (cpu
, INSTR (3, 0));
7306 /* Double precision. */
7307 double val1
= aarch64_get_vec_double (cpu
, rn
, 0);
7308 double val2
= aarch64_get_vec_double (cpu
, rm
, 0);
7310 /* FIXME: Check for NaNs. */
7312 aarch64_set_CPSR (cpu
, (Z
| C
));
7313 else if (val1
< val2
)
7314 aarch64_set_CPSR (cpu
, N
);
7315 else /* val1 > val2 */
7316 aarch64_set_CPSR (cpu
, C
);
7320 /* Single precision. */
7321 float val1
= aarch64_get_vec_float (cpu
, rn
, 0);
7322 float val2
= aarch64_get_vec_float (cpu
, rm
, 0);
7324 /* FIXME: Check for NaNs. */
7326 aarch64_set_CPSR (cpu
, (Z
| C
));
7327 else if (val1
< val2
)
7328 aarch64_set_CPSR (cpu
, N
);
7329 else /* val1 > val2 */
7330 aarch64_set_CPSR (cpu
, C
);
7338 fadds (sim_cpu
*cpu
)
7340 unsigned sm
= INSTR (20, 16);
7341 unsigned sn
= INSTR ( 9, 5);
7342 unsigned sd
= INSTR ( 4, 0);
7344 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7345 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
7346 + aarch64_get_FP_float (cpu
, sm
));
7351 faddd (sim_cpu
*cpu
)
7353 unsigned sm
= INSTR (20, 16);
7354 unsigned sn
= INSTR ( 9, 5);
7355 unsigned sd
= INSTR ( 4, 0);
7357 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7358 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
7359 + aarch64_get_FP_double (cpu
, sm
));
7364 fdivs (sim_cpu
*cpu
)
7366 unsigned sm
= INSTR (20, 16);
7367 unsigned sn
= INSTR ( 9, 5);
7368 unsigned sd
= INSTR ( 4, 0);
7370 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7371 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
7372 / aarch64_get_FP_float (cpu
, sm
));
7375 /* Double divide. */
7377 fdivd (sim_cpu
*cpu
)
7379 unsigned sm
= INSTR (20, 16);
7380 unsigned sn
= INSTR ( 9, 5);
7381 unsigned sd
= INSTR ( 4, 0);
7383 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7384 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
7385 / aarch64_get_FP_double (cpu
, sm
));
7388 /* Float multiply. */
7390 fmuls (sim_cpu
*cpu
)
7392 unsigned sm
= INSTR (20, 16);
7393 unsigned sn
= INSTR ( 9, 5);
7394 unsigned sd
= INSTR ( 4, 0);
7396 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7397 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
7398 * aarch64_get_FP_float (cpu
, sm
));
7401 /* Double multiply. */
7403 fmuld (sim_cpu
*cpu
)
7405 unsigned sm
= INSTR (20, 16);
7406 unsigned sn
= INSTR ( 9, 5);
7407 unsigned sd
= INSTR ( 4, 0);
7409 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7410 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
7411 * aarch64_get_FP_double (cpu
, sm
));
7414 /* Float negate and multiply. */
7416 fnmuls (sim_cpu
*cpu
)
7418 unsigned sm
= INSTR (20, 16);
7419 unsigned sn
= INSTR ( 9, 5);
7420 unsigned sd
= INSTR ( 4, 0);
7422 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7423 aarch64_set_FP_float (cpu
, sd
, - (aarch64_get_FP_float (cpu
, sn
)
7424 * aarch64_get_FP_float (cpu
, sm
)));
7427 /* Double negate and multiply. */
7429 fnmuld (sim_cpu
*cpu
)
7431 unsigned sm
= INSTR (20, 16);
7432 unsigned sn
= INSTR ( 9, 5);
7433 unsigned sd
= INSTR ( 4, 0);
7435 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7436 aarch64_set_FP_double (cpu
, sd
, - (aarch64_get_FP_double (cpu
, sn
)
7437 * aarch64_get_FP_double (cpu
, sm
)));
7440 /* Float subtract. */
7442 fsubs (sim_cpu
*cpu
)
7444 unsigned sm
= INSTR (20, 16);
7445 unsigned sn
= INSTR ( 9, 5);
7446 unsigned sd
= INSTR ( 4, 0);
7448 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7449 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
7450 - aarch64_get_FP_float (cpu
, sm
));
7453 /* Double subtract. */
7455 fsubd (sim_cpu
*cpu
)
7457 unsigned sm
= INSTR (20, 16);
7458 unsigned sn
= INSTR ( 9, 5);
7459 unsigned sd
= INSTR ( 4, 0);
7461 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7462 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
7463 - aarch64_get_FP_double (cpu
, sm
));
7467 do_FMINNM (sim_cpu
*cpu
)
7469 /* instr[31,23] = 0 0011 1100
7470 instr[22] = float(0)/double(1)
7473 instr[15,10] = 01 1110
7477 unsigned sm
= INSTR (20, 16);
7478 unsigned sn
= INSTR ( 9, 5);
7479 unsigned sd
= INSTR ( 4, 0);
7481 NYI_assert (31, 23, 0x03C);
7482 NYI_assert (15, 10, 0x1E);
7484 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7486 aarch64_set_FP_double (cpu
, sd
,
7487 dminnm (aarch64_get_FP_double (cpu
, sn
),
7488 aarch64_get_FP_double (cpu
, sm
)));
7490 aarch64_set_FP_float (cpu
, sd
,
7491 fminnm (aarch64_get_FP_float (cpu
, sn
),
7492 aarch64_get_FP_float (cpu
, sm
)));
7496 do_FMAXNM (sim_cpu
*cpu
)
7498 /* instr[31,23] = 0 0011 1100
7499 instr[22] = float(0)/double(1)
7502 instr[15,10] = 01 1010
7506 unsigned sm
= INSTR (20, 16);
7507 unsigned sn
= INSTR ( 9, 5);
7508 unsigned sd
= INSTR ( 4, 0);
7510 NYI_assert (31, 23, 0x03C);
7511 NYI_assert (15, 10, 0x1A);
7513 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7515 aarch64_set_FP_double (cpu
, sd
,
7516 dmaxnm (aarch64_get_FP_double (cpu
, sn
),
7517 aarch64_get_FP_double (cpu
, sm
)));
7519 aarch64_set_FP_float (cpu
, sd
,
7520 fmaxnm (aarch64_get_FP_float (cpu
, sn
),
7521 aarch64_get_FP_float (cpu
, sm
)));
7525 dexSimpleFPDataProc2Source (sim_cpu
*cpu
)
7527 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
7529 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
7532 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
7535 instr[15,12] ==> opcode : 0000 ==> FMUL, 0001 ==> FDIV
7536 0010 ==> FADD, 0011 ==> FSUB,
7537 0100 ==> FMAX, 0101 ==> FMIN
7538 0110 ==> FMAXNM, 0111 ==> FMINNM
7539 1000 ==> FNMUL, ow ==> UNALLOC
7544 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
7545 uint32_t type
= INSTR (23, 22);
7546 /* Dispatch on opcode. */
7547 uint32_t dispatch
= INSTR (15, 12);
7558 case 0: fmuld (cpu
); return;
7559 case 1: fdivd (cpu
); return;
7560 case 2: faddd (cpu
); return;
7561 case 3: fsubd (cpu
); return;
7562 case 6: do_FMAXNM (cpu
); return;
7563 case 7: do_FMINNM (cpu
); return;
7564 case 8: fnmuld (cpu
); return;
7566 /* Have not yet implemented fmax and fmin. */
7574 else /* type == 0 => floats. */
7577 case 0: fmuls (cpu
); return;
7578 case 1: fdivs (cpu
); return;
7579 case 2: fadds (cpu
); return;
7580 case 3: fsubs (cpu
); return;
7581 case 6: do_FMAXNM (cpu
); return;
7582 case 7: do_FMINNM (cpu
); return;
7583 case 8: fnmuls (cpu
); return;
7595 dexSimpleFPCondSelect (sim_cpu
*cpu
)
7598 instr[31,23] = 0 0011 1100
7599 instr[22] = 0=>single 1=>double
7606 unsigned sm
= INSTR (20, 16);
7607 unsigned sn
= INSTR ( 9, 5);
7608 unsigned sd
= INSTR ( 4, 0);
7609 uint32_t set
= testConditionCode (cpu
, INSTR (15, 12));
7611 NYI_assert (31, 23, 0x03C);
7612 NYI_assert (11, 10, 0x3);
7614 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7616 aarch64_set_FP_double (cpu
, sd
, (set
? aarch64_get_FP_double (cpu
, sn
)
7617 : aarch64_get_FP_double (cpu
, sm
)));
7619 aarch64_set_FP_float (cpu
, sd
, (set
? aarch64_get_FP_float (cpu
, sn
)
7620 : aarch64_get_FP_float (cpu
, sm
)));
7623 /* Store 32 bit unscaled signed 9 bit. */
7625 fsturs (sim_cpu
*cpu
, int32_t offset
)
7627 unsigned int rn
= INSTR (9, 5);
7628 unsigned int st
= INSTR (4, 0);
7630 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7631 aarch64_set_mem_u32 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, 1) + offset
,
7632 aarch64_get_vec_u32 (cpu
, st
, 0));
7635 /* Store 64 bit unscaled signed 9 bit. */
7637 fsturd (sim_cpu
*cpu
, int32_t offset
)
7639 unsigned int rn
= INSTR (9, 5);
7640 unsigned int st
= INSTR (4, 0);
7642 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7643 aarch64_set_mem_u64 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, 1) + offset
,
7644 aarch64_get_vec_u64 (cpu
, st
, 0));
7647 /* Store 128 bit unscaled signed 9 bit. */
7649 fsturq (sim_cpu
*cpu
, int32_t offset
)
7651 unsigned int rn
= INSTR (9, 5);
7652 unsigned int st
= INSTR (4, 0);
7655 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7656 aarch64_get_FP_long_double (cpu
, st
, & a
);
7657 aarch64_set_mem_long_double (cpu
,
7658 aarch64_get_reg_u64 (cpu
, rn
, 1)
7662 /* TODO FP move register. */
7664 /* 32 bit fp to fp move register. */
7666 ffmovs (sim_cpu
*cpu
)
7668 unsigned int rn
= INSTR (9, 5);
7669 unsigned int st
= INSTR (4, 0);
7671 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7672 aarch64_set_FP_float (cpu
, st
, aarch64_get_FP_float (cpu
, rn
));
7675 /* 64 bit fp to fp move register. */
7677 ffmovd (sim_cpu
*cpu
)
7679 unsigned int rn
= INSTR (9, 5);
7680 unsigned int st
= INSTR (4, 0);
7682 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7683 aarch64_set_FP_double (cpu
, st
, aarch64_get_FP_double (cpu
, rn
));
7686 /* 32 bit GReg to Vec move register. */
7688 fgmovs (sim_cpu
*cpu
)
7690 unsigned int rn
= INSTR (9, 5);
7691 unsigned int st
= INSTR (4, 0);
7693 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7694 aarch64_set_vec_u32 (cpu
, st
, 0, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
));
7697 /* 64 bit g to fp move register. */
7699 fgmovd (sim_cpu
*cpu
)
7701 unsigned int rn
= INSTR (9, 5);
7702 unsigned int st
= INSTR (4, 0);
7704 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7705 aarch64_set_vec_u64 (cpu
, st
, 0, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
7708 /* 32 bit fp to g move register. */
7710 gfmovs (sim_cpu
*cpu
)
7712 unsigned int rn
= INSTR (9, 5);
7713 unsigned int st
= INSTR (4, 0);
7715 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7716 aarch64_set_reg_u64 (cpu
, st
, NO_SP
, aarch64_get_vec_u32 (cpu
, rn
, 0));
7719 /* 64 bit fp to g move register. */
7721 gfmovd (sim_cpu
*cpu
)
7723 unsigned int rn
= INSTR (9, 5);
7724 unsigned int st
= INSTR (4, 0);
7726 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7727 aarch64_set_reg_u64 (cpu
, st
, NO_SP
, aarch64_get_vec_u64 (cpu
, rn
, 0));
7730 /* FP move immediate
7732 These install an immediate 8 bit value in the target register
7733 where the 8 bits comprise 1 sign bit, 4 bits of fraction and a 3
7737 fmovs (sim_cpu
*cpu
)
7739 unsigned int sd
= INSTR (4, 0);
7740 uint32_t imm
= INSTR (20, 13);
7741 float f
= fp_immediate_for_encoding_32 (imm
);
7743 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7744 aarch64_set_FP_float (cpu
, sd
, f
);
7748 fmovd (sim_cpu
*cpu
)
7750 unsigned int sd
= INSTR (4, 0);
7751 uint32_t imm
= INSTR (20, 13);
7752 double d
= fp_immediate_for_encoding_64 (imm
);
7754 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7755 aarch64_set_FP_double (cpu
, sd
, d
);
7759 dexSimpleFPImmediate (sim_cpu
*cpu
)
7761 /* instr[31,23] == 00111100
7762 instr[22] == type : single(0)/double(1)
7764 instr[20,13] == imm8
7766 instr[9,5] == imm5 : 00000 ==> PK, ow ==> UNALLOC
7768 uint32_t imm5
= INSTR (9, 5);
7770 NYI_assert (31, 23, 0x3C);
7781 /* TODO specific decode and execute for group Load Store. */
7783 /* TODO FP load/store single register (unscaled offset). */
7785 /* TODO load 8 bit unscaled signed 9 bit. */
7786 /* TODO load 16 bit unscaled signed 9 bit. */
7788 /* Load 32 bit unscaled signed 9 bit. */
7790 fldurs (sim_cpu
*cpu
, int32_t offset
)
7792 unsigned int rn
= INSTR (9, 5);
7793 unsigned int st
= INSTR (4, 0);
7795 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7796 aarch64_set_vec_u32 (cpu
, st
, 0, aarch64_get_mem_u32
7797 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
));
7800 /* Load 64 bit unscaled signed 9 bit. */
7802 fldurd (sim_cpu
*cpu
, int32_t offset
)
7804 unsigned int rn
= INSTR (9, 5);
7805 unsigned int st
= INSTR (4, 0);
7807 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7808 aarch64_set_vec_u64 (cpu
, st
, 0, aarch64_get_mem_u64
7809 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
));
7812 /* Load 128 bit unscaled signed 9 bit. */
7814 fldurq (sim_cpu
*cpu
, int32_t offset
)
7816 unsigned int rn
= INSTR (9, 5);
7817 unsigned int st
= INSTR (4, 0);
7819 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
;
7821 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7822 aarch64_get_mem_long_double (cpu
, addr
, & a
);
7823 aarch64_set_FP_long_double (cpu
, st
, a
);
7826 /* TODO store 8 bit unscaled signed 9 bit. */
7827 /* TODO store 16 bit unscaled signed 9 bit. */
7832 /* Float absolute value. */
7834 fabss (sim_cpu
*cpu
)
7836 unsigned sn
= INSTR (9, 5);
7837 unsigned sd
= INSTR (4, 0);
7838 float value
= aarch64_get_FP_float (cpu
, sn
);
7840 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7841 aarch64_set_FP_float (cpu
, sd
, fabsf (value
));
7844 /* Double absolute value. */
7846 fabcpu (sim_cpu
*cpu
)
7848 unsigned sn
= INSTR (9, 5);
7849 unsigned sd
= INSTR (4, 0);
7850 double value
= aarch64_get_FP_double (cpu
, sn
);
7852 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7853 aarch64_set_FP_double (cpu
, sd
, fabs (value
));
7856 /* Float negative value. */
7858 fnegs (sim_cpu
*cpu
)
7860 unsigned sn
= INSTR (9, 5);
7861 unsigned sd
= INSTR (4, 0);
7863 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7864 aarch64_set_FP_float (cpu
, sd
, - aarch64_get_FP_float (cpu
, sn
));
7867 /* Double negative value. */
7869 fnegd (sim_cpu
*cpu
)
7871 unsigned sn
= INSTR (9, 5);
7872 unsigned sd
= INSTR (4, 0);
7874 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7875 aarch64_set_FP_double (cpu
, sd
, - aarch64_get_FP_double (cpu
, sn
));
7878 /* Float square root. */
7880 fsqrts (sim_cpu
*cpu
)
7882 unsigned sn
= INSTR (9, 5);
7883 unsigned sd
= INSTR (4, 0);
7885 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7886 aarch64_set_FP_float (cpu
, sd
, sqrtf (aarch64_get_FP_float (cpu
, sn
)));
7889 /* Double square root. */
7891 fsqrtd (sim_cpu
*cpu
)
7893 unsigned sn
= INSTR (9, 5);
7894 unsigned sd
= INSTR (4, 0);
7896 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7897 aarch64_set_FP_double (cpu
, sd
,
7898 sqrt (aarch64_get_FP_double (cpu
, sn
)));
7901 /* Convert double to float. */
7903 fcvtds (sim_cpu
*cpu
)
7905 unsigned sn
= INSTR (9, 5);
7906 unsigned sd
= INSTR (4, 0);
7908 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7909 aarch64_set_FP_float (cpu
, sd
, (float) aarch64_get_FP_double (cpu
, sn
));
7912 /* Convert float to double. */
7914 fcvtcpu (sim_cpu
*cpu
)
7916 unsigned sn
= INSTR (9, 5);
7917 unsigned sd
= INSTR (4, 0);
7919 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7920 aarch64_set_FP_double (cpu
, sd
, (double) aarch64_get_FP_float (cpu
, sn
));
7924 do_FRINT (sim_cpu
*cpu
)
7926 /* instr[31,23] = 0001 1110 0
7927 instr[22] = single(0)/double(1)
7929 instr[17,15] = rounding mode
7930 instr[14,10] = 10000
7932 instr[4,0] = dest */
7935 unsigned rs
= INSTR (9, 5);
7936 unsigned rd
= INSTR (4, 0);
7937 unsigned int rmode
= INSTR (17, 15);
7939 NYI_assert (31, 23, 0x03C);
7940 NYI_assert (21, 18, 0x9);
7941 NYI_assert (14, 10, 0x10);
7943 if (rmode
== 6 || rmode
== 7)
7944 /* FIXME: Add support for rmode == 6 exactness check. */
7945 rmode
= uimm (aarch64_get_FPSR (cpu
), 23, 22);
7947 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7950 double val
= aarch64_get_FP_double (cpu
, rs
);
7954 case 0: /* mode N: nearest or even. */
7956 double rval
= round (val
);
7958 if (val
- rval
== 0.5)
7960 if (((rval
/ 2.0) * 2.0) != rval
)
7964 aarch64_set_FP_double (cpu
, rd
, round (val
));
7968 case 1: /* mode P: towards +inf. */
7970 aarch64_set_FP_double (cpu
, rd
, trunc (val
));
7972 aarch64_set_FP_double (cpu
, rd
, round (val
));
7975 case 2: /* mode M: towards -inf. */
7977 aarch64_set_FP_double (cpu
, rd
, round (val
));
7979 aarch64_set_FP_double (cpu
, rd
, trunc (val
));
7982 case 3: /* mode Z: towards 0. */
7983 aarch64_set_FP_double (cpu
, rd
, trunc (val
));
7986 case 4: /* mode A: away from 0. */
7987 aarch64_set_FP_double (cpu
, rd
, round (val
));
7990 case 6: /* mode X: use FPCR with exactness check. */
7991 case 7: /* mode I: use FPCR mode. */
7999 val
= aarch64_get_FP_float (cpu
, rs
);
8003 case 0: /* mode N: nearest or even. */
8005 float rval
= roundf (val
);
8007 if (val
- rval
== 0.5)
8009 if (((rval
/ 2.0) * 2.0) != rval
)
8013 aarch64_set_FP_float (cpu
, rd
, rval
);
8017 case 1: /* mode P: towards +inf. */
8019 aarch64_set_FP_float (cpu
, rd
, truncf (val
));
8021 aarch64_set_FP_float (cpu
, rd
, roundf (val
));
8024 case 2: /* mode M: towards -inf. */
8026 aarch64_set_FP_float (cpu
, rd
, truncf (val
));
8028 aarch64_set_FP_float (cpu
, rd
, roundf (val
));
8031 case 3: /* mode Z: towards 0. */
8032 aarch64_set_FP_float (cpu
, rd
, truncf (val
));
8035 case 4: /* mode A: away from 0. */
8036 aarch64_set_FP_float (cpu
, rd
, roundf (val
));
8039 case 6: /* mode X: use FPCR with exactness check. */
8040 case 7: /* mode I: use FPCR mode. */
8048 /* Convert half to float. */
8050 do_FCVT_half_to_single (sim_cpu
*cpu
)
8052 unsigned rn
= INSTR (9, 5);
8053 unsigned rd
= INSTR (4, 0);
8055 NYI_assert (31, 10, 0x7B890);
8057 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8058 aarch64_set_FP_float (cpu
, rd
, (float) aarch64_get_FP_half (cpu
, rn
));
8061 /* Convert half to double. */
8063 do_FCVT_half_to_double (sim_cpu
*cpu
)
8065 unsigned rn
= INSTR (9, 5);
8066 unsigned rd
= INSTR (4, 0);
8068 NYI_assert (31, 10, 0x7B8B0);
8070 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8071 aarch64_set_FP_double (cpu
, rd
, (double) aarch64_get_FP_half (cpu
, rn
));
8075 do_FCVT_single_to_half (sim_cpu
*cpu
)
8077 unsigned rn
= INSTR (9, 5);
8078 unsigned rd
= INSTR (4, 0);
8080 NYI_assert (31, 10, 0x788F0);
8082 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8083 aarch64_set_FP_half (cpu
, rd
, aarch64_get_FP_float (cpu
, rn
));
8086 /* Convert double to half. */
8088 do_FCVT_double_to_half (sim_cpu
*cpu
)
8090 unsigned rn
= INSTR (9, 5);
8091 unsigned rd
= INSTR (4, 0);
8093 NYI_assert (31, 10, 0x798F0);
8095 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8096 aarch64_set_FP_half (cpu
, rd
, (float) aarch64_get_FP_double (cpu
, rn
));
8100 dexSimpleFPDataProc1Source (sim_cpu
*cpu
)
8102 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
8104 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
8107 instr[23,22] ==> type : 00 ==> source is single,
8108 01 ==> source is double
8110 11 ==> UNALLOC or source is half
8112 instr[20,15] ==> opcode : with type 00 or 01
8113 000000 ==> FMOV, 000001 ==> FABS,
8114 000010 ==> FNEG, 000011 ==> FSQRT,
8115 000100 ==> UNALLOC, 000101 ==> FCVT,(to single/double)
8116 000110 ==> UNALLOC, 000111 ==> FCVT (to half)
8117 001000 ==> FRINTN, 001001 ==> FRINTP,
8118 001010 ==> FRINTM, 001011 ==> FRINTZ,
8119 001100 ==> FRINTA, 001101 ==> UNALLOC
8120 001110 ==> FRINTX, 001111 ==> FRINTI
8122 000100 ==> FCVT (half-to-single)
8123 000101 ==> FCVT (half-to-double)
8124 instr[14,10] = 10000. */
8126 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
8127 uint32_t type
= INSTR (23, 22);
8128 uint32_t opcode
= INSTR (20, 15);
8136 do_FCVT_half_to_single (cpu
);
8137 else if (opcode
== 5)
8138 do_FCVT_half_to_double (cpu
);
8190 case 8: /* FRINTN etc. */
8202 do_FCVT_double_to_half (cpu
);
8204 do_FCVT_single_to_half (cpu
);
8215 /* 32 bit signed int to float. */
8217 scvtf32 (sim_cpu
*cpu
)
8219 unsigned rn
= INSTR (9, 5);
8220 unsigned sd
= INSTR (4, 0);
8222 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8223 aarch64_set_FP_float
8224 (cpu
, sd
, (float) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
));
8227 /* signed int to float. */
8229 scvtf (sim_cpu
*cpu
)
8231 unsigned rn
= INSTR (9, 5);
8232 unsigned sd
= INSTR (4, 0);
8234 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8235 aarch64_set_FP_float
8236 (cpu
, sd
, (float) aarch64_get_reg_s64 (cpu
, rn
, NO_SP
));
8239 /* 32 bit signed int to double. */
8241 scvtd32 (sim_cpu
*cpu
)
8243 unsigned rn
= INSTR (9, 5);
8244 unsigned sd
= INSTR (4, 0);
8246 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8247 aarch64_set_FP_double
8248 (cpu
, sd
, (double) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
));
8251 /* signed int to double. */
8253 scvtd (sim_cpu
*cpu
)
8255 unsigned rn
= INSTR (9, 5);
8256 unsigned sd
= INSTR (4, 0);
8258 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8259 aarch64_set_FP_double
8260 (cpu
, sd
, (double) aarch64_get_reg_s64 (cpu
, rn
, NO_SP
));
8263 static const float FLOAT_INT_MAX
= (float) INT_MAX
;
8264 static const float FLOAT_INT_MIN
= (float) INT_MIN
;
8265 static const double DOUBLE_INT_MAX
= (double) INT_MAX
;
8266 static const double DOUBLE_INT_MIN
= (double) INT_MIN
;
8267 static const float FLOAT_LONG_MAX
= (float) LONG_MAX
;
8268 static const float FLOAT_LONG_MIN
= (float) LONG_MIN
;
8269 static const double DOUBLE_LONG_MAX
= (double) LONG_MAX
;
8270 static const double DOUBLE_LONG_MIN
= (double) LONG_MIN
;
8274 static const float FLOAT_UINT_MAX
= (float) UINT_MAX
;
8275 static const float FLOAT_UINT_MIN
= (float) UINT_MIN
;
8276 static const double DOUBLE_UINT_MAX
= (double) UINT_MAX
;
8277 static const double DOUBLE_UINT_MIN
= (double) UINT_MIN
;
8278 static const float FLOAT_ULONG_MAX
= (float) ULONG_MAX
;
8279 static const float FLOAT_ULONG_MIN
= (float) ULONG_MIN
;
8280 static const double DOUBLE_ULONG_MAX
= (double) ULONG_MAX
;
8281 static const double DOUBLE_ULONG_MIN
= (double) ULONG_MIN
;
8283 /* Check for FP exception conditions:
8286 Out of Range raises IO and IX and saturates value
8287 Denormal raises ID and IX and sets to zero. */
8288 #define RAISE_EXCEPTIONS(F, VALUE, FTYPE, ITYPE) \
8291 switch (fpclassify (F)) \
8295 aarch64_set_FPSR (cpu, IO); \
8297 VALUE = ITYPE##_MAX; \
8299 VALUE = ITYPE##_MIN; \
8303 if (F >= FTYPE##_##ITYPE##_MAX) \
8305 aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX); \
8306 VALUE = ITYPE##_MAX; \
8308 else if (F <= FTYPE##_##ITYPE##_MIN) \
8310 aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX); \
8311 VALUE = ITYPE##_MIN; \
8315 case FP_SUBNORMAL: \
8316 aarch64_set_FPSR_bits (cpu, IO | IX | ID, IX | ID); \
8328 /* 32 bit convert float to signed int truncate towards zero. */
8330 fcvtszs32 (sim_cpu
*cpu
)
8332 unsigned sn
= INSTR (9, 5);
8333 unsigned rd
= INSTR (4, 0);
8334 /* TODO : check that this rounds toward zero. */
8335 float f
= aarch64_get_FP_float (cpu
, sn
);
8336 int32_t value
= (int32_t) f
;
8338 RAISE_EXCEPTIONS (f
, value
, FLOAT
, INT
);
8340 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8341 /* Avoid sign extension to 64 bit. */
8342 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) value
);
8345 /* 64 bit convert float to signed int truncate towards zero. */
8347 fcvtszs (sim_cpu
*cpu
)
8349 unsigned sn
= INSTR (9, 5);
8350 unsigned rd
= INSTR (4, 0);
8351 float f
= aarch64_get_FP_float (cpu
, sn
);
8352 int64_t value
= (int64_t) f
;
8354 RAISE_EXCEPTIONS (f
, value
, FLOAT
, LONG
);
8356 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8357 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, value
);
8360 /* 32 bit convert double to signed int truncate towards zero. */
8362 fcvtszd32 (sim_cpu
*cpu
)
8364 unsigned sn
= INSTR (9, 5);
8365 unsigned rd
= INSTR (4, 0);
8366 /* TODO : check that this rounds toward zero. */
8367 double d
= aarch64_get_FP_double (cpu
, sn
);
8368 int32_t value
= (int32_t) d
;
8370 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, INT
);
8372 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8373 /* Avoid sign extension to 64 bit. */
8374 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) value
);
8377 /* 64 bit convert double to signed int truncate towards zero. */
8379 fcvtszd (sim_cpu
*cpu
)
8381 unsigned sn
= INSTR (9, 5);
8382 unsigned rd
= INSTR (4, 0);
8383 /* TODO : check that this rounds toward zero. */
8384 double d
= aarch64_get_FP_double (cpu
, sn
);
8387 value
= (int64_t) d
;
8389 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, LONG
);
8391 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8392 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, value
);
8396 do_fcvtzu (sim_cpu
*cpu
)
8398 /* instr[31] = size: 32-bit (0), 64-bit (1)
8399 instr[30,23] = 00111100
8400 instr[22] = type: single (0)/ double (1)
8401 instr[21] = enable (0)/disable(1) precision
8402 instr[20,16] = 11001
8403 instr[15,10] = precision
8407 unsigned rs
= INSTR (9, 5);
8408 unsigned rd
= INSTR (4, 0);
8410 NYI_assert (30, 23, 0x3C);
8411 NYI_assert (20, 16, 0x19);
8413 if (INSTR (21, 21) != 1)
8414 /* Convert to fixed point. */
8417 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8420 /* Convert to unsigned 64-bit integer. */
8423 double d
= aarch64_get_FP_double (cpu
, rs
);
8424 uint64_t value
= (uint64_t) d
;
8426 /* Do not raise an exception if we have reached ULONG_MAX. */
8427 if (value
!= (1ULL << 63))
8428 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, ULONG
);
8430 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
8434 float f
= aarch64_get_FP_float (cpu
, rs
);
8435 uint64_t value
= (uint64_t) f
;
8437 /* Do not raise an exception if we have reached ULONG_MAX. */
8438 if (value
!= (1ULL << 63))
8439 RAISE_EXCEPTIONS (f
, value
, FLOAT
, ULONG
);
8441 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
8448 /* Convert to unsigned 32-bit integer. */
8451 double d
= aarch64_get_FP_double (cpu
, rs
);
8453 value
= (uint32_t) d
;
8454 /* Do not raise an exception if we have reached UINT_MAX. */
8455 if (value
!= (1UL << 31))
8456 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, UINT
);
8460 float f
= aarch64_get_FP_float (cpu
, rs
);
8462 value
= (uint32_t) f
;
8463 /* Do not raise an exception if we have reached UINT_MAX. */
8464 if (value
!= (1UL << 31))
8465 RAISE_EXCEPTIONS (f
, value
, FLOAT
, UINT
);
8468 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
8473 do_UCVTF (sim_cpu
*cpu
)
8475 /* instr[31] = size: 32-bit (0), 64-bit (1)
8476 instr[30,23] = 001 1110 0
8477 instr[22] = type: single (0)/ double (1)
8478 instr[21] = enable (0)/disable(1) precision
8479 instr[20,16] = 0 0011
8480 instr[15,10] = precision
8484 unsigned rs
= INSTR (9, 5);
8485 unsigned rd
= INSTR (4, 0);
8487 NYI_assert (30, 23, 0x3C);
8488 NYI_assert (20, 16, 0x03);
8490 if (INSTR (21, 21) != 1)
8493 /* FIXME: Add exception raising. */
8494 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8497 uint64_t value
= aarch64_get_reg_u64 (cpu
, rs
, NO_SP
);
8500 aarch64_set_FP_double (cpu
, rd
, (double) value
);
8502 aarch64_set_FP_float (cpu
, rd
, (float) value
);
8506 uint32_t value
= aarch64_get_reg_u32 (cpu
, rs
, NO_SP
);
8509 aarch64_set_FP_double (cpu
, rd
, (double) value
);
8511 aarch64_set_FP_float (cpu
, rd
, (float) value
);
8516 float_vector_move (sim_cpu
*cpu
)
8518 /* instr[31,17] == 100 1111 0101 0111
8519 instr[16] ==> direction 0=> to GR, 1=> from GR
8521 instr[9,5] ==> source
8522 instr[4,0] ==> dest. */
8524 unsigned rn
= INSTR (9, 5);
8525 unsigned rd
= INSTR (4, 0);
8527 NYI_assert (31, 17, 0x4F57);
8529 if (INSTR (15, 10) != 0)
8532 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8534 aarch64_set_vec_u64 (cpu
, rd
, 1, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
8536 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, aarch64_get_vec_u64 (cpu
, rn
, 1));
8540 dexSimpleFPIntegerConvert (sim_cpu
*cpu
)
8542 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
8544 instr[29] = S : 0 ==> OK, 1 ==> UNALLOC
8547 instr[23,22] = type : 00 ==> single, 01 ==> double, 1x ==> UNALLOC
8549 instr[20,19] = rmode
8550 instr[18,16] = opcode
8551 instr[15,10] = 10 0000 */
8553 uint32_t rmode_opcode
;
8559 if (INSTR (31, 17) == 0x4F57)
8561 float_vector_move (cpu
);
8565 size
= INSTR (31, 31);
8570 type
= INSTR (23, 22);
8574 rmode_opcode
= INSTR (20, 16);
8575 size_type
= (size
<< 1) | type
; /* 0==32f, 1==32d, 2==64f, 3==64d. */
8577 switch (rmode_opcode
)
8579 case 2: /* SCVTF. */
8582 case 0: scvtf32 (cpu
); return;
8583 case 1: scvtd32 (cpu
); return;
8584 case 2: scvtf (cpu
); return;
8585 case 3: scvtd (cpu
); return;
8588 case 6: /* FMOV GR, Vec. */
8591 case 0: gfmovs (cpu
); return;
8592 case 3: gfmovd (cpu
); return;
8593 default: HALT_UNALLOC
;
8596 case 7: /* FMOV vec, GR. */
8599 case 0: fgmovs (cpu
); return;
8600 case 3: fgmovd (cpu
); return;
8601 default: HALT_UNALLOC
;
8604 case 24: /* FCVTZS. */
8607 case 0: fcvtszs32 (cpu
); return;
8608 case 1: fcvtszd32 (cpu
); return;
8609 case 2: fcvtszs (cpu
); return;
8610 case 3: fcvtszd (cpu
); return;
8613 case 25: do_fcvtzu (cpu
); return;
8614 case 3: do_UCVTF (cpu
); return;
8616 case 0: /* FCVTNS. */
8617 case 1: /* FCVTNU. */
8618 case 4: /* FCVTAS. */
8619 case 5: /* FCVTAU. */
8620 case 8: /* FCVPTS. */
8621 case 9: /* FCVTPU. */
8622 case 16: /* FCVTMS. */
8623 case 17: /* FCVTMU. */
8630 set_flags_for_float_compare (sim_cpu
*cpu
, float fvalue1
, float fvalue2
)
8634 /* FIXME: Add exception raising. */
8635 if (isnan (fvalue1
) || isnan (fvalue2
))
8637 else if (isinf (fvalue1
) && isinf (fvalue2
))
8639 /* Subtracting two infinities may give a NaN. We only need to compare
8640 the signs, which we can get from isinf. */
8641 int result
= isinf (fvalue1
) - isinf (fvalue2
);
8645 else if (result
< 0)
8647 else /* (result > 0). */
8652 float result
= fvalue1
- fvalue2
;
8656 else if (result
< 0)
8658 else /* (result > 0). */
8662 aarch64_set_CPSR (cpu
, flags
);
8666 fcmps (sim_cpu
*cpu
)
8668 unsigned sm
= INSTR (20, 16);
8669 unsigned sn
= INSTR ( 9, 5);
8671 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8672 float fvalue2
= aarch64_get_FP_float (cpu
, sm
);
8674 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8675 set_flags_for_float_compare (cpu
, fvalue1
, fvalue2
);
8678 /* Float compare to zero -- Invalid Operation exception
8679 only on signaling NaNs. */
8681 fcmpzs (sim_cpu
*cpu
)
8683 unsigned sn
= INSTR ( 9, 5);
8684 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8686 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8687 set_flags_for_float_compare (cpu
, fvalue1
, 0.0f
);
8690 /* Float compare -- Invalid Operation exception on all NaNs. */
8692 fcmpes (sim_cpu
*cpu
)
8694 unsigned sm
= INSTR (20, 16);
8695 unsigned sn
= INSTR ( 9, 5);
8697 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8698 float fvalue2
= aarch64_get_FP_float (cpu
, sm
);
8700 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8701 set_flags_for_float_compare (cpu
, fvalue1
, fvalue2
);
8704 /* Float compare to zero -- Invalid Operation exception on all NaNs. */
8706 fcmpzes (sim_cpu
*cpu
)
8708 unsigned sn
= INSTR ( 9, 5);
8709 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8711 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8712 set_flags_for_float_compare (cpu
, fvalue1
, 0.0f
);
8716 set_flags_for_double_compare (sim_cpu
*cpu
, double dval1
, double dval2
)
8720 /* FIXME: Add exception raising. */
8721 if (isnan (dval1
) || isnan (dval2
))
8723 else if (isinf (dval1
) && isinf (dval2
))
8725 /* Subtracting two infinities may give a NaN. We only need to compare
8726 the signs, which we can get from isinf. */
8727 int result
= isinf (dval1
) - isinf (dval2
);
8731 else if (result
< 0)
8733 else /* (result > 0). */
8738 double result
= dval1
- dval2
;
8742 else if (result
< 0)
8744 else /* (result > 0). */
8748 aarch64_set_CPSR (cpu
, flags
);
8751 /* Double compare -- Invalid Operation exception only on signaling NaNs. */
8753 fcmpd (sim_cpu
*cpu
)
8755 unsigned sm
= INSTR (20, 16);
8756 unsigned sn
= INSTR ( 9, 5);
8758 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8759 double dvalue2
= aarch64_get_FP_double (cpu
, sm
);
8761 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8762 set_flags_for_double_compare (cpu
, dvalue1
, dvalue2
);
8765 /* Double compare to zero -- Invalid Operation exception
8766 only on signaling NaNs. */
8768 fcmpzd (sim_cpu
*cpu
)
8770 unsigned sn
= INSTR ( 9, 5);
8771 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8773 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8774 set_flags_for_double_compare (cpu
, dvalue1
, 0.0);
8777 /* Double compare -- Invalid Operation exception on all NaNs. */
8779 fcmped (sim_cpu
*cpu
)
8781 unsigned sm
= INSTR (20, 16);
8782 unsigned sn
= INSTR ( 9, 5);
8784 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8785 double dvalue2
= aarch64_get_FP_double (cpu
, sm
);
8787 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8788 set_flags_for_double_compare (cpu
, dvalue1
, dvalue2
);
8791 /* Double compare to zero -- Invalid Operation exception on all NaNs. */
8793 fcmpzed (sim_cpu
*cpu
)
8795 unsigned sn
= INSTR ( 9, 5);
8796 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8798 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8799 set_flags_for_double_compare (cpu
, dvalue1
, 0.0);
8803 dexSimpleFPCompare (sim_cpu
*cpu
)
8805 /* assert instr[28,25] == 1111
8806 instr[30:24:21:13,10] = 0011000
8807 instr[31] = M : 0 ==> OK, 1 ==> UNALLOC
8808 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
8809 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
8810 instr[15,14] ==> op : 00 ==> OK, ow ==> UNALLOC
8811 instr[4,0] ==> opcode2 : 00000 ==> FCMP, 10000 ==> FCMPE,
8812 01000 ==> FCMPZ, 11000 ==> FCMPEZ,
8815 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
8816 uint32_t type
= INSTR (23, 22);
8817 uint32_t op
= INSTR (15, 14);
8818 uint32_t op2_2_0
= INSTR (2, 0);
8832 /* dispatch on type and top 2 bits of opcode. */
8833 dispatch
= (type
<< 2) | INSTR (4, 3);
8837 case 0: fcmps (cpu
); return;
8838 case 1: fcmpzs (cpu
); return;
8839 case 2: fcmpes (cpu
); return;
8840 case 3: fcmpzes (cpu
); return;
8841 case 4: fcmpd (cpu
); return;
8842 case 5: fcmpzd (cpu
); return;
8843 case 6: fcmped (cpu
); return;
8844 case 7: fcmpzed (cpu
); return;
8849 do_scalar_FADDP (sim_cpu
*cpu
)
8851 /* instr [31,23] = 0111 1110 0
8852 instr [22] = single(0)/double(1)
8853 instr [21,10] = 11 0000 1101 10
8855 instr [4,0] = Fd. */
8857 unsigned Fn
= INSTR (9, 5);
8858 unsigned Fd
= INSTR (4, 0);
8860 NYI_assert (31, 23, 0x0FC);
8861 NYI_assert (21, 10, 0xC36);
8863 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8866 double val1
= aarch64_get_vec_double (cpu
, Fn
, 0);
8867 double val2
= aarch64_get_vec_double (cpu
, Fn
, 1);
8869 aarch64_set_FP_double (cpu
, Fd
, val1
+ val2
);
8873 float val1
= aarch64_get_vec_float (cpu
, Fn
, 0);
8874 float val2
= aarch64_get_vec_float (cpu
, Fn
, 1);
8876 aarch64_set_FP_float (cpu
, Fd
, val1
+ val2
);
8880 /* Floating point absolute difference. */
8883 do_scalar_FABD (sim_cpu
*cpu
)
8885 /* instr [31,23] = 0111 1110 1
8886 instr [22] = float(0)/double(1)
8889 instr [15,10] = 1101 01
8891 instr [4, 0] = Rd. */
8893 unsigned rm
= INSTR (20, 16);
8894 unsigned rn
= INSTR (9, 5);
8895 unsigned rd
= INSTR (4, 0);
8897 NYI_assert (31, 23, 0x0FD);
8898 NYI_assert (21, 21, 1);
8899 NYI_assert (15, 10, 0x35);
8901 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8903 aarch64_set_FP_double (cpu
, rd
,
8904 fabs (aarch64_get_FP_double (cpu
, rn
)
8905 - aarch64_get_FP_double (cpu
, rm
)));
8907 aarch64_set_FP_float (cpu
, rd
,
8908 fabsf (aarch64_get_FP_float (cpu
, rn
)
8909 - aarch64_get_FP_float (cpu
, rm
)));
8913 do_scalar_CMGT (sim_cpu
*cpu
)
8915 /* instr [31,21] = 0101 1110 111
8917 instr [15,10] = 00 1101
8919 instr [4, 0] = Rd. */
8921 unsigned rm
= INSTR (20, 16);
8922 unsigned rn
= INSTR (9, 5);
8923 unsigned rd
= INSTR (4, 0);
8925 NYI_assert (31, 21, 0x2F7);
8926 NYI_assert (15, 10, 0x0D);
8928 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8929 aarch64_set_vec_u64 (cpu
, rd
, 0,
8930 aarch64_get_vec_u64 (cpu
, rn
, 0) >
8931 aarch64_get_vec_u64 (cpu
, rm
, 0) ? -1L : 0L);
8935 do_scalar_USHR (sim_cpu
*cpu
)
8937 /* instr [31,23] = 0111 1111 0
8938 instr [22,16] = shift amount
8939 instr [15,10] = 0000 01
8941 instr [4, 0] = Rd. */
8943 unsigned amount
= 128 - INSTR (22, 16);
8944 unsigned rn
= INSTR (9, 5);
8945 unsigned rd
= INSTR (4, 0);
8947 NYI_assert (31, 23, 0x0FE);
8948 NYI_assert (15, 10, 0x01);
8950 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8951 aarch64_set_vec_u64 (cpu
, rd
, 0,
8952 aarch64_get_vec_u64 (cpu
, rn
, 0) >> amount
);
8956 do_scalar_SSHL (sim_cpu
*cpu
)
8958 /* instr [31,21] = 0101 1110 111
8960 instr [15,10] = 0100 01
8962 instr [4, 0] = Rd. */
8964 unsigned rm
= INSTR (20, 16);
8965 unsigned rn
= INSTR (9, 5);
8966 unsigned rd
= INSTR (4, 0);
8967 signed int shift
= aarch64_get_vec_s8 (cpu
, rm
, 0);
8969 NYI_assert (31, 21, 0x2F7);
8970 NYI_assert (15, 10, 0x11);
8972 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8974 aarch64_set_vec_s64 (cpu
, rd
, 0,
8975 aarch64_get_vec_s64 (cpu
, rn
, 0) << shift
);
8977 aarch64_set_vec_s64 (cpu
, rd
, 0,
8978 aarch64_get_vec_s64 (cpu
, rn
, 0) >> - shift
);
8981 /* Floating point scalar compare greater than or equal to 0. */
8983 do_scalar_FCMGE_zero (sim_cpu
*cpu
)
8985 /* instr [31,23] = 0111 1110 1
8986 instr [22,22] = size
8987 instr [21,16] = 1000 00
8988 instr [15,10] = 1100 10
8990 instr [4, 0] = Rd. */
8992 unsigned size
= INSTR (22, 22);
8993 unsigned rn
= INSTR (9, 5);
8994 unsigned rd
= INSTR (4, 0);
8996 NYI_assert (31, 23, 0x0FD);
8997 NYI_assert (21, 16, 0x20);
8998 NYI_assert (15, 10, 0x32);
9000 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9002 aarch64_set_vec_u64 (cpu
, rd
, 0,
9003 aarch64_get_vec_double (cpu
, rn
, 0) >= 0.0 ? -1 : 0);
9005 aarch64_set_vec_u32 (cpu
, rd
, 0,
9006 aarch64_get_vec_float (cpu
, rn
, 0) >= 0.0 ? -1 : 0);
9009 /* Floating point scalar compare less than or equal to 0. */
9011 do_scalar_FCMLE_zero (sim_cpu
*cpu
)
9013 /* instr [31,23] = 0111 1110 1
9014 instr [22,22] = size
9015 instr [21,16] = 1000 00
9016 instr [15,10] = 1101 10
9018 instr [4, 0] = Rd. */
9020 unsigned size
= INSTR (22, 22);
9021 unsigned rn
= INSTR (9, 5);
9022 unsigned rd
= INSTR (4, 0);
9024 NYI_assert (31, 23, 0x0FD);
9025 NYI_assert (21, 16, 0x20);
9026 NYI_assert (15, 10, 0x36);
9028 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9030 aarch64_set_vec_u64 (cpu
, rd
, 0,
9031 aarch64_get_vec_double (cpu
, rn
, 0) <= 0.0 ? -1 : 0);
9033 aarch64_set_vec_u32 (cpu
, rd
, 0,
9034 aarch64_get_vec_float (cpu
, rn
, 0) <= 0.0 ? -1 : 0);
9037 /* Floating point scalar compare greater than 0. */
9039 do_scalar_FCMGT_zero (sim_cpu
*cpu
)
9041 /* instr [31,23] = 0101 1110 1
9042 instr [22,22] = size
9043 instr [21,16] = 1000 00
9044 instr [15,10] = 1100 10
9046 instr [4, 0] = Rd. */
9048 unsigned size
= INSTR (22, 22);
9049 unsigned rn
= INSTR (9, 5);
9050 unsigned rd
= INSTR (4, 0);
9052 NYI_assert (31, 23, 0x0BD);
9053 NYI_assert (21, 16, 0x20);
9054 NYI_assert (15, 10, 0x32);
9056 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9058 aarch64_set_vec_u64 (cpu
, rd
, 0,
9059 aarch64_get_vec_double (cpu
, rn
, 0) > 0.0 ? -1 : 0);
9061 aarch64_set_vec_u32 (cpu
, rd
, 0,
9062 aarch64_get_vec_float (cpu
, rn
, 0) > 0.0 ? -1 : 0);
9065 /* Floating point scalar compare equal to 0. */
9067 do_scalar_FCMEQ_zero (sim_cpu
*cpu
)
9069 /* instr [31,23] = 0101 1110 1
9070 instr [22,22] = size
9071 instr [21,16] = 1000 00
9072 instr [15,10] = 1101 10
9074 instr [4, 0] = Rd. */
9076 unsigned size
= INSTR (22, 22);
9077 unsigned rn
= INSTR (9, 5);
9078 unsigned rd
= INSTR (4, 0);
9080 NYI_assert (31, 23, 0x0BD);
9081 NYI_assert (21, 16, 0x20);
9082 NYI_assert (15, 10, 0x36);
9084 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9086 aarch64_set_vec_u64 (cpu
, rd
, 0,
9087 aarch64_get_vec_double (cpu
, rn
, 0) == 0.0 ? -1 : 0);
9089 aarch64_set_vec_u32 (cpu
, rd
, 0,
9090 aarch64_get_vec_float (cpu
, rn
, 0) == 0.0 ? -1 : 0);
9093 /* Floating point scalar compare less than 0. */
9095 do_scalar_FCMLT_zero (sim_cpu
*cpu
)
9097 /* instr [31,23] = 0101 1110 1
9098 instr [22,22] = size
9099 instr [21,16] = 1000 00
9100 instr [15,10] = 1110 10
9102 instr [4, 0] = Rd. */
9104 unsigned size
= INSTR (22, 22);
9105 unsigned rn
= INSTR (9, 5);
9106 unsigned rd
= INSTR (4, 0);
9108 NYI_assert (31, 23, 0x0BD);
9109 NYI_assert (21, 16, 0x20);
9110 NYI_assert (15, 10, 0x3A);
9112 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9114 aarch64_set_vec_u64 (cpu
, rd
, 0,
9115 aarch64_get_vec_double (cpu
, rn
, 0) < 0.0 ? -1 : 0);
9117 aarch64_set_vec_u32 (cpu
, rd
, 0,
9118 aarch64_get_vec_float (cpu
, rn
, 0) < 0.0 ? -1 : 0);
9122 do_scalar_shift (sim_cpu
*cpu
)
9124 /* instr [31,23] = 0101 1111 0
9125 instr [22,16] = shift amount
9126 instr [15,10] = 0101 01 [SHL]
9127 instr [15,10] = 0000 01 [SSHR]
9129 instr [4, 0] = Rd. */
9131 unsigned rn
= INSTR (9, 5);
9132 unsigned rd
= INSTR (4, 0);
9135 NYI_assert (31, 23, 0x0BE);
9137 if (INSTR (22, 22) == 0)
9140 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9141 switch (INSTR (15, 10))
9143 case 0x01: /* SSHR */
9144 amount
= 128 - INSTR (22, 16);
9145 aarch64_set_vec_s64 (cpu
, rd
, 0,
9146 aarch64_get_vec_s64 (cpu
, rn
, 0) >> amount
);
9148 case 0x15: /* SHL */
9149 amount
= INSTR (22, 16) - 64;
9150 aarch64_set_vec_u64 (cpu
, rd
, 0,
9151 aarch64_get_vec_u64 (cpu
, rn
, 0) << amount
);
9158 /* FCMEQ FCMGT FCMGE. */
9160 do_scalar_FCM (sim_cpu
*cpu
)
9162 /* instr [31,30] = 01
9164 instr [28,24] = 1 1110
9169 instr [15,12] = 1110
9173 instr [4, 0] = Rd. */
9175 unsigned rm
= INSTR (20, 16);
9176 unsigned rn
= INSTR (9, 5);
9177 unsigned rd
= INSTR (4, 0);
9178 unsigned EUac
= (INSTR (23, 23) << 2) | (INSTR (29, 29) << 1) | INSTR (11, 11);
9183 NYI_assert (31, 30, 1);
9184 NYI_assert (28, 24, 0x1E);
9185 NYI_assert (21, 21, 1);
9186 NYI_assert (15, 12, 0xE);
9187 NYI_assert (10, 10, 1);
9189 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9192 double val1
= aarch64_get_FP_double (cpu
, rn
);
9193 double val2
= aarch64_get_FP_double (cpu
, rm
);
9198 result
= val1
== val2
;
9206 result
= val1
>= val2
;
9214 result
= val1
> val2
;
9221 aarch64_set_vec_u32 (cpu
, rd
, 0, result
? -1 : 0);
9225 val1
= aarch64_get_FP_float (cpu
, rn
);
9226 val2
= aarch64_get_FP_float (cpu
, rm
);
9231 result
= val1
== val2
;
9235 val1
= fabsf (val1
);
9236 val2
= fabsf (val2
);
9239 result
= val1
>= val2
;
9243 val1
= fabsf (val1
);
9244 val2
= fabsf (val2
);
9247 result
= val1
> val2
;
9254 aarch64_set_vec_u32 (cpu
, rd
, 0, result
? -1 : 0);
9257 /* An alias of DUP. */
9259 do_scalar_MOV (sim_cpu
*cpu
)
9261 /* instr [31,21] = 0101 1110 000
9262 instr [20,16] = imm5
9263 instr [15,10] = 0000 01
9265 instr [4, 0] = Rd. */
9267 unsigned rn
= INSTR (9, 5);
9268 unsigned rd
= INSTR (4, 0);
9271 NYI_assert (31, 21, 0x2F0);
9272 NYI_assert (15, 10, 0x01);
9274 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9278 index
= INSTR (20, 17);
9280 (cpu
, rd
, 0, aarch64_get_vec_u8 (cpu
, rn
, index
));
9282 else if (INSTR (17, 17))
9285 index
= INSTR (20, 18);
9287 (cpu
, rd
, 0, aarch64_get_vec_u16 (cpu
, rn
, index
));
9289 else if (INSTR (18, 18))
9292 index
= INSTR (20, 19);
9294 (cpu
, rd
, 0, aarch64_get_vec_u32 (cpu
, rn
, index
));
9296 else if (INSTR (19, 19))
9299 index
= INSTR (20, 20);
9301 (cpu
, rd
, 0, aarch64_get_vec_u64 (cpu
, rn
, index
));
9308 do_scalar_NEG (sim_cpu
*cpu
)
9310 /* instr [31,10] = 0111 1110 1110 0000 1011 10
9312 instr [4, 0] = Rd. */
9314 unsigned rn
= INSTR (9, 5);
9315 unsigned rd
= INSTR (4, 0);
9317 NYI_assert (31, 10, 0x1FB82E);
9319 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9320 aarch64_set_vec_u64 (cpu
, rd
, 0, - aarch64_get_vec_u64 (cpu
, rn
, 0));
9324 do_scalar_USHL (sim_cpu
*cpu
)
9326 /* instr [31,21] = 0111 1110 111
9328 instr [15,10] = 0100 01
9330 instr [4, 0] = Rd. */
9332 unsigned rm
= INSTR (20, 16);
9333 unsigned rn
= INSTR (9, 5);
9334 unsigned rd
= INSTR (4, 0);
9335 signed int shift
= aarch64_get_vec_s8 (cpu
, rm
, 0);
9337 NYI_assert (31, 21, 0x3F7);
9338 NYI_assert (15, 10, 0x11);
9340 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9342 aarch64_set_vec_u64 (cpu
, rd
, 0, aarch64_get_vec_u64 (cpu
, rn
, 0) << shift
);
9344 aarch64_set_vec_u64 (cpu
, rd
, 0, aarch64_get_vec_u64 (cpu
, rn
, 0) >> - shift
);
9348 do_double_add (sim_cpu
*cpu
)
9350 /* instr [31,21] = 0101 1110 111
9352 instr [15,10] = 1000 01
9354 instr [4,0] = Fd. */
9361 NYI_assert (31, 21, 0x2F7);
9362 NYI_assert (15, 10, 0x21);
9366 Fn
= INSTR (20, 16);
9368 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9369 val1
= aarch64_get_FP_double (cpu
, Fm
);
9370 val2
= aarch64_get_FP_double (cpu
, Fn
);
9372 aarch64_set_FP_double (cpu
, Fd
, val1
+ val2
);
9376 do_scalar_UCVTF (sim_cpu
*cpu
)
9378 /* instr [31,23] = 0111 1110 0
9379 instr [22] = single(0)/double(1)
9380 instr [21,10] = 10 0001 1101 10
9382 instr [4,0] = rd. */
9384 unsigned rn
= INSTR (9, 5);
9385 unsigned rd
= INSTR (4, 0);
9387 NYI_assert (31, 23, 0x0FC);
9388 NYI_assert (21, 10, 0x876);
9390 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9393 uint64_t val
= aarch64_get_vec_u64 (cpu
, rn
, 0);
9395 aarch64_set_vec_double (cpu
, rd
, 0, (double) val
);
9399 uint32_t val
= aarch64_get_vec_u32 (cpu
, rn
, 0);
9401 aarch64_set_vec_float (cpu
, rd
, 0, (float) val
);
9406 do_scalar_vec (sim_cpu
*cpu
)
9408 /* instr [30] = 1. */
9409 /* instr [28,25] = 1111. */
9410 switch (INSTR (31, 23))
9413 switch (INSTR (15, 10))
9415 case 0x01: do_scalar_MOV (cpu
); return;
9416 case 0x39: do_scalar_FCM (cpu
); return;
9417 case 0x3B: do_scalar_FCM (cpu
); return;
9421 case 0xBE: do_scalar_shift (cpu
); return;
9424 switch (INSTR (15, 10))
9427 switch (INSTR (21, 16))
9429 case 0x30: do_scalar_FADDP (cpu
); return;
9430 case 0x21: do_scalar_UCVTF (cpu
); return;
9433 case 0x39: do_scalar_FCM (cpu
); return;
9434 case 0x3B: do_scalar_FCM (cpu
); return;
9439 switch (INSTR (15, 10))
9441 case 0x0D: do_scalar_CMGT (cpu
); return;
9442 case 0x11: do_scalar_USHL (cpu
); return;
9443 case 0x2E: do_scalar_NEG (cpu
); return;
9444 case 0x32: do_scalar_FCMGE_zero (cpu
); return;
9445 case 0x35: do_scalar_FABD (cpu
); return;
9446 case 0x36: do_scalar_FCMLE_zero (cpu
); return;
9447 case 0x39: do_scalar_FCM (cpu
); return;
9448 case 0x3B: do_scalar_FCM (cpu
); return;
9453 case 0xFE: do_scalar_USHR (cpu
); return;
9456 switch (INSTR (15, 10))
9458 case 0x21: do_double_add (cpu
); return;
9459 case 0x11: do_scalar_SSHL (cpu
); return;
9460 case 0x32: do_scalar_FCMGT_zero (cpu
); return;
9461 case 0x36: do_scalar_FCMEQ_zero (cpu
); return;
9462 case 0x3A: do_scalar_FCMLT_zero (cpu
); return;
9473 dexAdvSIMD1 (sim_cpu
*cpu
)
9475 /* instr [28,25] = 1 111. */
9477 /* We are currently only interested in the basic
9478 scalar fp routines which all have bit 30 = 0. */
9480 do_scalar_vec (cpu
);
9482 /* instr[24] is set for FP data processing 3-source and clear for
9483 all other basic scalar fp instruction groups. */
9484 else if (INSTR (24, 24))
9485 dexSimpleFPDataProc3Source (cpu
);
9487 /* instr[21] is clear for floating <-> fixed conversions and set for
9488 all other basic scalar fp instruction groups. */
9489 else if (!INSTR (21, 21))
9490 dexSimpleFPFixedConvert (cpu
);
9492 /* instr[11,10] : 01 ==> cond compare, 10 ==> Data Proc 2 Source
9493 11 ==> cond select, 00 ==> other. */
9495 switch (INSTR (11, 10))
9497 case 1: dexSimpleFPCondCompare (cpu
); return;
9498 case 2: dexSimpleFPDataProc2Source (cpu
); return;
9499 case 3: dexSimpleFPCondSelect (cpu
); return;
9502 /* Now an ordered cascade of tests.
9503 FP immediate has instr [12] == 1.
9504 FP compare has instr [13] == 1.
9505 FP Data Proc 1 Source has instr [14] == 1.
9506 FP floating <--> integer conversions has instr [15] == 0. */
9508 dexSimpleFPImmediate (cpu
);
9510 else if (INSTR (13, 13))
9511 dexSimpleFPCompare (cpu
);
9513 else if (INSTR (14, 14))
9514 dexSimpleFPDataProc1Source (cpu
);
9516 else if (!INSTR (15, 15))
9517 dexSimpleFPIntegerConvert (cpu
);
9520 /* If we get here then instr[15] == 1 which means UNALLOC. */
9525 /* PC relative addressing. */
9528 pcadr (sim_cpu
*cpu
)
9530 /* instr[31] = op : 0 ==> ADR, 1 ==> ADRP
9531 instr[30,29] = immlo
9532 instr[23,5] = immhi. */
9534 unsigned rd
= INSTR (4, 0);
9535 uint32_t isPage
= INSTR (31, 31);
9536 union { int64_t u64
; uint64_t s64
; } imm
;
9539 imm
.s64
= simm64 (aarch64_get_instr (cpu
), 23, 5);
9541 offset
= (offset
<< 2) | INSTR (30, 29);
9543 address
= aarch64_get_PC (cpu
);
9551 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9552 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, address
+ offset
);
9555 /* Specific decode and execute for group Data Processing Immediate. */
9558 dexPCRelAddressing (sim_cpu
*cpu
)
9560 /* assert instr[28,24] = 10000. */
9564 /* Immediate logical.
9565 The bimm32/64 argument is constructed by replicating a 2, 4, 8,
9566 16, 32 or 64 bit sequence pulled out at decode and possibly
9569 N.B. the output register (dest) can normally be Xn or SP
9570 the exception occurs for flag setting instructions which may
9571 only use Xn for the output (dest). The input register can
9574 /* 32 bit and immediate. */
9576 and32 (sim_cpu
*cpu
, uint32_t bimm
)
9578 unsigned rn
= INSTR (9, 5);
9579 unsigned rd
= INSTR (4, 0);
9581 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9582 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9583 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
) & bimm
);
9586 /* 64 bit and immediate. */
9588 and64 (sim_cpu
*cpu
, uint64_t bimm
)
9590 unsigned rn
= INSTR (9, 5);
9591 unsigned rd
= INSTR (4, 0);
9593 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9594 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9595 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) & bimm
);
9598 /* 32 bit and immediate set flags. */
9600 ands32 (sim_cpu
*cpu
, uint32_t bimm
)
9602 unsigned rn
= INSTR (9, 5);
9603 unsigned rd
= INSTR (4, 0);
9605 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9606 uint32_t value2
= bimm
;
9608 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9609 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9610 set_flags_for_binop32 (cpu
, value1
& value2
);
9613 /* 64 bit and immediate set flags. */
9615 ands64 (sim_cpu
*cpu
, uint64_t bimm
)
9617 unsigned rn
= INSTR (9, 5);
9618 unsigned rd
= INSTR (4, 0);
9620 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9621 uint64_t value2
= bimm
;
9623 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9624 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9625 set_flags_for_binop64 (cpu
, value1
& value2
);
9628 /* 32 bit exclusive or immediate. */
9630 eor32 (sim_cpu
*cpu
, uint32_t bimm
)
9632 unsigned rn
= INSTR (9, 5);
9633 unsigned rd
= INSTR (4, 0);
9635 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9636 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9637 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
) ^ bimm
);
9640 /* 64 bit exclusive or immediate. */
9642 eor64 (sim_cpu
*cpu
, uint64_t bimm
)
9644 unsigned rn
= INSTR (9, 5);
9645 unsigned rd
= INSTR (4, 0);
9647 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9648 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9649 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) ^ bimm
);
9652 /* 32 bit or immediate. */
9654 orr32 (sim_cpu
*cpu
, uint32_t bimm
)
9656 unsigned rn
= INSTR (9, 5);
9657 unsigned rd
= INSTR (4, 0);
9659 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9660 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9661 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
) | bimm
);
9664 /* 64 bit or immediate. */
9666 orr64 (sim_cpu
*cpu
, uint64_t bimm
)
9668 unsigned rn
= INSTR (9, 5);
9669 unsigned rd
= INSTR (4, 0);
9671 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9672 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9673 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) | bimm
);
9676 /* Logical shifted register.
9677 These allow an optional LSL, ASR, LSR or ROR to the second source
9678 register with a count up to the register bit count.
9679 N.B register args may not be SP. */
9681 /* 32 bit AND shifted register. */
9683 and32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9685 unsigned rm
= INSTR (20, 16);
9686 unsigned rn
= INSTR (9, 5);
9687 unsigned rd
= INSTR (4, 0);
9689 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9691 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9692 & shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9695 /* 64 bit AND shifted register. */
9697 and64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9699 unsigned rm
= INSTR (20, 16);
9700 unsigned rn
= INSTR (9, 5);
9701 unsigned rd
= INSTR (4, 0);
9703 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9705 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9706 & shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9709 /* 32 bit AND shifted register setting flags. */
9711 ands32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9713 unsigned rm
= INSTR (20, 16);
9714 unsigned rn
= INSTR (9, 5);
9715 unsigned rd
= INSTR (4, 0);
9717 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9718 uint32_t value2
= shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
9721 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9722 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9723 set_flags_for_binop32 (cpu
, value1
& value2
);
9726 /* 64 bit AND shifted register setting flags. */
9728 ands64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9730 unsigned rm
= INSTR (20, 16);
9731 unsigned rn
= INSTR (9, 5);
9732 unsigned rd
= INSTR (4, 0);
9734 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9735 uint64_t value2
= shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
9738 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9739 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9740 set_flags_for_binop64 (cpu
, value1
& value2
);
9743 /* 32 bit BIC shifted register. */
9745 bic32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9747 unsigned rm
= INSTR (20, 16);
9748 unsigned rn
= INSTR (9, 5);
9749 unsigned rd
= INSTR (4, 0);
9751 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9753 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9754 & ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9757 /* 64 bit BIC shifted register. */
9759 bic64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9761 unsigned rm
= INSTR (20, 16);
9762 unsigned rn
= INSTR (9, 5);
9763 unsigned rd
= INSTR (4, 0);
9765 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9767 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9768 & ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9771 /* 32 bit BIC shifted register setting flags. */
9773 bics32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9775 unsigned rm
= INSTR (20, 16);
9776 unsigned rn
= INSTR (9, 5);
9777 unsigned rd
= INSTR (4, 0);
9779 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9780 uint32_t value2
= ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
9783 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9784 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9785 set_flags_for_binop32 (cpu
, value1
& value2
);
9788 /* 64 bit BIC shifted register setting flags. */
9790 bics64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9792 unsigned rm
= INSTR (20, 16);
9793 unsigned rn
= INSTR (9, 5);
9794 unsigned rd
= INSTR (4, 0);
9796 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9797 uint64_t value2
= ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
9800 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9801 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9802 set_flags_for_binop64 (cpu
, value1
& value2
);
9805 /* 32 bit EON shifted register. */
9807 eon32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9809 unsigned rm
= INSTR (20, 16);
9810 unsigned rn
= INSTR (9, 5);
9811 unsigned rd
= INSTR (4, 0);
9813 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9815 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9816 ^ ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9819 /* 64 bit EON shifted register. */
9821 eon64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9823 unsigned rm
= INSTR (20, 16);
9824 unsigned rn
= INSTR (9, 5);
9825 unsigned rd
= INSTR (4, 0);
9827 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9829 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9830 ^ ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9833 /* 32 bit EOR shifted register. */
9835 eor32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9837 unsigned rm
= INSTR (20, 16);
9838 unsigned rn
= INSTR (9, 5);
9839 unsigned rd
= INSTR (4, 0);
9841 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9843 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9844 ^ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9847 /* 64 bit EOR shifted register. */
9849 eor64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9851 unsigned rm
= INSTR (20, 16);
9852 unsigned rn
= INSTR (9, 5);
9853 unsigned rd
= INSTR (4, 0);
9855 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9857 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9858 ^ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9861 /* 32 bit ORR shifted register. */
9863 orr32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9865 unsigned rm
= INSTR (20, 16);
9866 unsigned rn
= INSTR (9, 5);
9867 unsigned rd
= INSTR (4, 0);
9869 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9871 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9872 | shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9875 /* 64 bit ORR shifted register. */
9877 orr64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9879 unsigned rm
= INSTR (20, 16);
9880 unsigned rn
= INSTR (9, 5);
9881 unsigned rd
= INSTR (4, 0);
9883 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9885 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9886 | shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9889 /* 32 bit ORN shifted register. */
9891 orn32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9893 unsigned rm
= INSTR (20, 16);
9894 unsigned rn
= INSTR (9, 5);
9895 unsigned rd
= INSTR (4, 0);
9897 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9899 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9900 | ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9903 /* 64 bit ORN shifted register. */
9905 orn64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9907 unsigned rm
= INSTR (20, 16);
9908 unsigned rn
= INSTR (9, 5);
9909 unsigned rd
= INSTR (4, 0);
9911 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9913 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9914 | ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9918 dexLogicalImmediate (sim_cpu
*cpu
)
9920 /* assert instr[28,23] = 1001000
9921 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9922 instr[30,29] = op : 0 ==> AND, 1 ==> ORR, 2 ==> EOR, 3 ==> ANDS
9923 instr[22] = N : used to construct immediate mask
9929 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
9930 uint32_t size
= INSTR (31, 31);
9931 uint32_t N
= INSTR (22, 22);
9932 /* uint32_t immr = INSTR (21, 16);. */
9933 /* uint32_t imms = INSTR (15, 10);. */
9934 uint32_t index
= INSTR (22, 10);
9935 uint64_t bimm64
= LITable
[index
];
9936 uint32_t dispatch
= INSTR (30, 29);
9946 uint32_t bimm
= (uint32_t) bimm64
;
9950 case 0: and32 (cpu
, bimm
); return;
9951 case 1: orr32 (cpu
, bimm
); return;
9952 case 2: eor32 (cpu
, bimm
); return;
9953 case 3: ands32 (cpu
, bimm
); return;
9960 case 0: and64 (cpu
, bimm64
); return;
9961 case 1: orr64 (cpu
, bimm64
); return;
9962 case 2: eor64 (cpu
, bimm64
); return;
9963 case 3: ands64 (cpu
, bimm64
); return;
9970 The uimm argument is a 16 bit value to be inserted into the
9971 target register the pos argument locates the 16 bit word in the
9972 dest register i.e. it is in {0, 1} for 32 bit and {0, 1, 2,
9974 N.B register arg may not be SP so it should be.
9975 accessed using the setGZRegisterXXX accessors. */
9977 /* 32 bit move 16 bit immediate zero remaining shorts. */
9979 movz32 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9981 unsigned rd
= INSTR (4, 0);
9983 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9984 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val
<< (pos
* 16));
9987 /* 64 bit move 16 bit immediate zero remaining shorts. */
9989 movz64 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9991 unsigned rd
= INSTR (4, 0);
9993 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9994 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, ((uint64_t) val
) << (pos
* 16));
9997 /* 32 bit move 16 bit immediate negated. */
9999 movn32 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
10001 unsigned rd
= INSTR (4, 0);
10003 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10004 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, ((val
<< (pos
* 16)) ^ 0xffffffffU
));
10007 /* 64 bit move 16 bit immediate negated. */
10009 movn64 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
10011 unsigned rd
= INSTR (4, 0);
10013 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10014 aarch64_set_reg_u64
10015 (cpu
, rd
, NO_SP
, ((((uint64_t) val
) << (pos
* 16))
10016 ^ 0xffffffffffffffffULL
));
10019 /* 32 bit move 16 bit immediate keep remaining shorts. */
10021 movk32 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
10023 unsigned rd
= INSTR (4, 0);
10024 uint32_t current
= aarch64_get_reg_u32 (cpu
, rd
, NO_SP
);
10025 uint32_t value
= val
<< (pos
* 16);
10026 uint32_t mask
= ~(0xffffU
<< (pos
* 16));
10028 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10029 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (value
| (current
& mask
)));
10032 /* 64 bit move 16 it immediate keep remaining shorts. */
10034 movk64 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
10036 unsigned rd
= INSTR (4, 0);
10037 uint64_t current
= aarch64_get_reg_u64 (cpu
, rd
, NO_SP
);
10038 uint64_t value
= (uint64_t) val
<< (pos
* 16);
10039 uint64_t mask
= ~(0xffffULL
<< (pos
* 16));
10041 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10042 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (value
| (current
& mask
)));
10046 dexMoveWideImmediate (sim_cpu
*cpu
)
10048 /* assert instr[28:23] = 100101
10049 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
10050 instr[30,29] = op : 0 ==> MOVN, 1 ==> UNALLOC, 2 ==> MOVZ, 3 ==> MOVK
10051 instr[22,21] = shift : 00 == LSL#0, 01 = LSL#16, 10 = LSL#32, 11 = LSL#48
10052 instr[20,5] = uimm16
10055 /* N.B. the (multiple of 16) shift is applied by the called routine,
10056 we just pass the multiplier. */
10059 uint32_t size
= INSTR (31, 31);
10060 uint32_t op
= INSTR (30, 29);
10061 uint32_t shift
= INSTR (22, 21);
10063 /* 32 bit can only shift 0 or 1 lot of 16.
10064 anything else is an unallocated instruction. */
10065 if (size
== 0 && (shift
> 1))
10071 imm
= INSTR (20, 5);
10076 movn32 (cpu
, imm
, shift
);
10078 movz32 (cpu
, imm
, shift
);
10080 movk32 (cpu
, imm
, shift
);
10085 movn64 (cpu
, imm
, shift
);
10087 movz64 (cpu
, imm
, shift
);
10089 movk64 (cpu
, imm
, shift
);
10093 /* Bitfield operations.
10094 These take a pair of bit positions r and s which are in {0..31}
10095 or {0..63} depending on the instruction word size.
10096 N.B register args may not be SP. */
10098 /* OK, we start with ubfm which just needs to pick
10099 some bits out of source zero the rest and write
10100 the result to dest. Just need two logical shifts. */
10102 /* 32 bit bitfield move, left and right of affected zeroed
10103 if r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
10105 ubfm32 (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
10108 unsigned rn
= INSTR (9, 5);
10109 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
10111 /* Pick either s+1-r or s+1 consecutive bits out of the original word. */
10114 /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
10115 We want only bits s:xxx:r at the bottom of the word
10116 so we LSL bit s up to bit 31 i.e. by 31 - s
10117 and then we LSR to bring bit 31 down to bit s - r
10118 i.e. by 31 + r - s. */
10120 value
>>= 31 + r
- s
;
10124 /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0
10125 We want only bits s:xxx:0 starting at it 31-(r-1)
10126 so we LSL bit s up to bit 31 i.e. by 31 - s
10127 and then we LSL to bring bit 31 down to 31-(r-1)+s
10128 i.e. by r - (s + 1). */
10130 value
>>= r
- (s
+ 1);
10133 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10135 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
10138 /* 64 bit bitfield move, left and right of affected zeroed
10139 if r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
10141 ubfm (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
10144 unsigned rn
= INSTR (9, 5);
10145 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
10149 /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
10150 We want only bits s:xxx:r at the bottom of the word.
10151 So we LSL bit s up to bit 63 i.e. by 63 - s
10152 and then we LSR to bring bit 63 down to bit s - r
10153 i.e. by 63 + r - s. */
10155 value
>>= 63 + r
- s
;
10159 /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0.
10160 We want only bits s:xxx:0 starting at it 63-(r-1).
10161 So we LSL bit s up to bit 63 i.e. by 63 - s
10162 and then we LSL to bring bit 63 down to 63-(r-1)+s
10163 i.e. by r - (s + 1). */
10165 value
>>= r
- (s
+ 1);
10168 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10170 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
10173 /* The signed versions need to insert sign bits
10174 on the left of the inserted bit field. so we do
10175 much the same as the unsigned version except we
10176 use an arithmetic shift right -- this just means
10177 we need to operate on signed values. */
10179 /* 32 bit bitfield move, left of affected sign-extended, right zeroed. */
10180 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
10182 sbfm32 (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
10185 unsigned rn
= INSTR (9, 5);
10186 /* as per ubfm32 but use an ASR instead of an LSR. */
10187 int32_t value
= aarch64_get_reg_s32 (cpu
, rn
, NO_SP
);
10192 value
>>= 31 + r
- s
;
10197 value
>>= r
- (s
+ 1);
10200 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10202 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) value
);
10205 /* 64 bit bitfield move, left of affected sign-extended, right zeroed. */
10206 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
10208 sbfm (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
10211 unsigned rn
= INSTR (9, 5);
10212 /* acpu per ubfm but use an ASR instead of an LSR. */
10213 int64_t value
= aarch64_get_reg_s64 (cpu
, rn
, NO_SP
);
10218 value
>>= 63 + r
- s
;
10223 value
>>= r
- (s
+ 1);
10226 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10228 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, value
);
10231 /* Finally, these versions leave non-affected bits
10232 as is. so we need to generate the bits as per
10233 ubfm and also generate a mask to pick the
10234 bits from the original and computed values. */
10236 /* 32 bit bitfield move, non-affected bits left as is.
10237 If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
10239 bfm32 (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
10241 unsigned rn
= INSTR (9, 5);
10242 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
10243 uint32_t mask
= -1;
10247 /* Pick either s+1-r or s+1 consecutive bits out of the original word. */
10250 /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
10251 We want only bits s:xxx:r at the bottom of the word
10252 so we LSL bit s up to bit 31 i.e. by 31 - s
10253 and then we LSR to bring bit 31 down to bit s - r
10254 i.e. by 31 + r - s. */
10256 value
>>= 31 + r
- s
;
10257 /* the mask must include the same bits. */
10259 mask
>>= 31 + r
- s
;
10263 /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0.
10264 We want only bits s:xxx:0 starting at it 31-(r-1)
10265 so we LSL bit s up to bit 31 i.e. by 31 - s
10266 and then we LSL to bring bit 31 down to 31-(r-1)+s
10267 i.e. by r - (s + 1). */
10269 value
>>= r
- (s
+ 1);
10270 /* The mask must include the same bits. */
10272 mask
>>= r
- (s
+ 1);
10276 value2
= aarch64_get_reg_u32 (cpu
, rd
, NO_SP
);
10281 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10282 aarch64_set_reg_u64
10283 (cpu
, rd
, NO_SP
, (aarch64_get_reg_u32 (cpu
, rd
, NO_SP
) & ~mask
) | value
);
10286 /* 64 bit bitfield move, non-affected bits left as is.
10287 If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
10289 bfm (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
10292 unsigned rn
= INSTR (9, 5);
10293 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
10294 uint64_t mask
= 0xffffffffffffffffULL
;
10298 /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
10299 We want only bits s:xxx:r at the bottom of the word
10300 so we LSL bit s up to bit 63 i.e. by 63 - s
10301 and then we LSR to bring bit 63 down to bit s - r
10302 i.e. by 63 + r - s. */
10304 value
>>= 63 + r
- s
;
10305 /* The mask must include the same bits. */
10307 mask
>>= 63 + r
- s
;
10311 /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0
10312 We want only bits s:xxx:0 starting at it 63-(r-1)
10313 so we LSL bit s up to bit 63 i.e. by 63 - s
10314 and then we LSL to bring bit 63 down to 63-(r-1)+s
10315 i.e. by r - (s + 1). */
10317 value
>>= r
- (s
+ 1);
10318 /* The mask must include the same bits. */
10320 mask
>>= r
- (s
+ 1);
10323 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10325 aarch64_set_reg_u64
10326 (cpu
, rd
, NO_SP
, (aarch64_get_reg_u64 (cpu
, rd
, NO_SP
) & ~mask
) | value
);
10330 dexBitfieldImmediate (sim_cpu
*cpu
)
10332 /* assert instr[28:23] = 100110
10333 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
10334 instr[30,29] = op : 0 ==> SBFM, 1 ==> BFM, 2 ==> UBFM, 3 ==> UNALLOC
10335 instr[22] = N : must be 0 for 32 bit, 1 for 64 bit ow UNALLOC
10336 instr[21,16] = immr : 0xxxxx for 32 bit, xxxxxx for 64 bit
10337 instr[15,10] = imms : 0xxxxx for 32 bit, xxxxxx for 64 bit
10341 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
10344 uint32_t size
= INSTR (31, 31);
10345 uint32_t N
= INSTR (22, 22);
10346 /* 32 bit operations must have immr[5] = 0 and imms[5] = 0. */
10347 /* or else we have an UNALLOC. */
10348 uint32_t immr
= INSTR (21, 16);
10353 if (!size
&& uimm (immr
, 5, 5))
10356 imms
= INSTR (15, 10);
10357 if (!size
&& uimm (imms
, 5, 5))
10360 /* Switch on combined size and op. */
10361 dispatch
= INSTR (31, 29);
10364 case 0: sbfm32 (cpu
, immr
, imms
); return;
10365 case 1: bfm32 (cpu
, immr
, imms
); return;
10366 case 2: ubfm32 (cpu
, immr
, imms
); return;
10367 case 4: sbfm (cpu
, immr
, imms
); return;
10368 case 5: bfm (cpu
, immr
, imms
); return;
10369 case 6: ubfm (cpu
, immr
, imms
); return;
10370 default: HALT_UNALLOC
;
10375 do_EXTR_32 (sim_cpu
*cpu
)
10377 /* instr[31:21] = 00010011100
10379 instr[15,10] = imms : 0xxxxx for 32 bit
10382 unsigned rm
= INSTR (20, 16);
10383 unsigned imms
= INSTR (15, 10) & 31;
10384 unsigned rn
= INSTR ( 9, 5);
10385 unsigned rd
= INSTR ( 4, 0);
10389 val1
= aarch64_get_reg_u32 (cpu
, rm
, NO_SP
);
10391 val2
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
10392 val2
<<= (32 - imms
);
10394 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10395 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val1
| val2
);
10399 do_EXTR_64 (sim_cpu
*cpu
)
10401 /* instr[31:21] = 10010011100
10403 instr[15,10] = imms
10406 unsigned rm
= INSTR (20, 16);
10407 unsigned imms
= INSTR (15, 10) & 63;
10408 unsigned rn
= INSTR ( 9, 5);
10409 unsigned rd
= INSTR ( 4, 0);
10412 val
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
10414 val
|= (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) << (64 - imms
));
10416 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val
);
10420 dexExtractImmediate (sim_cpu
*cpu
)
10422 /* assert instr[28:23] = 100111
10423 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
10424 instr[30,29] = op21 : 0 ==> EXTR, 1,2,3 ==> UNALLOC
10425 instr[22] = N : must be 0 for 32 bit, 1 for 64 bit or UNALLOC
10426 instr[21] = op0 : must be 0 or UNALLOC
10428 instr[15,10] = imms : 0xxxxx for 32 bit, xxxxxx for 64 bit
10432 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
10433 /* 64 bit operations must have N = 1 or else we have an UNALLOC. */
10435 uint32_t size
= INSTR (31, 31);
10436 uint32_t N
= INSTR (22, 22);
10437 /* 32 bit operations must have imms[5] = 0
10438 or else we have an UNALLOC. */
10439 uint32_t imms
= INSTR (15, 10);
10444 if (!size
&& uimm (imms
, 5, 5))
10447 /* Switch on combined size and op. */
10448 dispatch
= INSTR (31, 29);
10453 else if (dispatch
== 4)
10456 else if (dispatch
== 1)
10463 dexDPImm (sim_cpu
*cpu
)
10465 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
10466 assert group == GROUP_DPIMM_1000 || grpoup == GROUP_DPIMM_1001
10467 bits [25,23] of a DPImm are the secondary dispatch vector. */
10468 uint32_t group2
= dispatchDPImm (aarch64_get_instr (cpu
));
10472 case DPIMM_PCADR_000
:
10473 case DPIMM_PCADR_001
:
10474 dexPCRelAddressing (cpu
);
10477 case DPIMM_ADDSUB_010
:
10478 case DPIMM_ADDSUB_011
:
10479 dexAddSubtractImmediate (cpu
);
10482 case DPIMM_LOG_100
:
10483 dexLogicalImmediate (cpu
);
10486 case DPIMM_MOV_101
:
10487 dexMoveWideImmediate (cpu
);
10490 case DPIMM_BITF_110
:
10491 dexBitfieldImmediate (cpu
);
10494 case DPIMM_EXTR_111
:
10495 dexExtractImmediate (cpu
);
10499 /* Should never reach here. */
10505 dexLoadUnscaledImmediate (sim_cpu
*cpu
)
10507 /* instr[29,24] == 111_00
10510 instr[31,30] = size
10513 instr[20,12] = simm9
10514 instr[9,5] = rn may be SP. */
10515 /* unsigned rt = INSTR (4, 0); */
10516 uint32_t V
= INSTR (26, 26);
10517 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
10518 int32_t imm
= simm32 (aarch64_get_instr (cpu
), 20, 12);
10522 /* GReg operations. */
10525 case 0: sturb (cpu
, imm
); return;
10526 case 1: ldurb32 (cpu
, imm
); return;
10527 case 2: ldursb64 (cpu
, imm
); return;
10528 case 3: ldursb32 (cpu
, imm
); return;
10529 case 4: sturh (cpu
, imm
); return;
10530 case 5: ldurh32 (cpu
, imm
); return;
10531 case 6: ldursh64 (cpu
, imm
); return;
10532 case 7: ldursh32 (cpu
, imm
); return;
10533 case 8: stur32 (cpu
, imm
); return;
10534 case 9: ldur32 (cpu
, imm
); return;
10535 case 10: ldursw (cpu
, imm
); return;
10536 case 12: stur64 (cpu
, imm
); return;
10537 case 13: ldur64 (cpu
, imm
); return;
10550 /* FReg operations. */
10553 case 2: fsturq (cpu
, imm
); return;
10554 case 3: fldurq (cpu
, imm
); return;
10555 case 8: fsturs (cpu
, imm
); return;
10556 case 9: fldurs (cpu
, imm
); return;
10557 case 12: fsturd (cpu
, imm
); return;
10558 case 13: fldurd (cpu
, imm
); return;
10560 case 0: /* STUR 8 bit FP. */
10561 case 1: /* LDUR 8 bit FP. */
10562 case 4: /* STUR 16 bit FP. */
10563 case 5: /* LDUR 8 bit FP. */
10577 /* N.B. A preliminary note regarding all the ldrs<x>32
10580 The signed value loaded by these instructions is cast to unsigned
10581 before being assigned to aarch64_get_reg_u64 (cpu, N) i.e. to the
10582 64 bit element of the GReg union. this performs a 32 bit sign extension
10583 (as required) but avoids 64 bit sign extension, thus ensuring that the
10584 top half of the register word is zero. this is what the spec demands
10585 when a 32 bit load occurs. */
10587 /* 32 bit load sign-extended byte scaled unsigned 12 bit. */
10589 ldrsb32_abs (sim_cpu
*cpu
, uint32_t offset
)
10591 unsigned int rn
= INSTR (9, 5);
10592 unsigned int rt
= INSTR (4, 0);
10594 /* The target register may not be SP but the source may be
10595 there is no scaling required for a byte load. */
10596 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
;
10597 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
10598 (int64_t) aarch64_get_mem_s8 (cpu
, address
));
10601 /* 32 bit load sign-extended byte scaled or unscaled zero-
10602 or sign-extended 32-bit register offset. */
10604 ldrsb32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10606 unsigned int rm
= INSTR (20, 16);
10607 unsigned int rn
= INSTR (9, 5);
10608 unsigned int rt
= INSTR (4, 0);
10610 /* rn may reference SP, rm and rt must reference ZR. */
10612 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10613 int64_t displacement
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10616 /* There is no scaling required for a byte load. */
10617 aarch64_set_reg_u64
10618 (cpu
, rt
, NO_SP
, (int64_t) aarch64_get_mem_s8 (cpu
, address
10622 /* 32 bit load sign-extended byte unscaled signed 9 bit with
10623 pre- or post-writeback. */
10625 ldrsb32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10628 unsigned int rn
= INSTR (9, 5);
10629 unsigned int rt
= INSTR (4, 0);
10631 if (rn
== rt
&& wb
!= NoWriteBack
)
10634 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10639 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
10640 (int64_t) aarch64_get_mem_s8 (cpu
, address
));
10645 if (wb
!= NoWriteBack
)
10646 aarch64_set_reg_u64 (cpu
, rn
, NO_SP
, address
);
10649 /* 8 bit store scaled. */
10651 fstrb_abs (sim_cpu
*cpu
, uint32_t offset
)
10653 unsigned st
= INSTR (4, 0);
10654 unsigned rn
= INSTR (9, 5);
10656 aarch64_set_mem_u8 (cpu
,
10657 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
10658 aarch64_get_vec_u8 (cpu
, st
, 0));
10661 /* 8 bit store scaled or unscaled zero- or
10662 sign-extended 8-bit register offset. */
10664 fstrb_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10666 unsigned rm
= INSTR (20, 16);
10667 unsigned rn
= INSTR (9, 5);
10668 unsigned st
= INSTR (4, 0);
10670 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10671 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10673 uint64_t displacement
= scaling
== Scaled
? extended
: 0;
10676 (cpu
, address
+ displacement
, aarch64_get_vec_u8 (cpu
, st
, 0));
10679 /* 16 bit store scaled. */
10681 fstrh_abs (sim_cpu
*cpu
, uint32_t offset
)
10683 unsigned st
= INSTR (4, 0);
10684 unsigned rn
= INSTR (9, 5);
10686 aarch64_set_mem_u16
10688 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 16),
10689 aarch64_get_vec_u16 (cpu
, st
, 0));
10692 /* 16 bit store scaled or unscaled zero-
10693 or sign-extended 16-bit register offset. */
10695 fstrh_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10697 unsigned rm
= INSTR (20, 16);
10698 unsigned rn
= INSTR (9, 5);
10699 unsigned st
= INSTR (4, 0);
10701 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10702 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10704 uint64_t displacement
= OPT_SCALE (extended
, 16, scaling
);
10706 aarch64_set_mem_u16
10707 (cpu
, address
+ displacement
, aarch64_get_vec_u16 (cpu
, st
, 0));
10710 /* 32 bit store scaled unsigned 12 bit. */
10712 fstrs_abs (sim_cpu
*cpu
, uint32_t offset
)
10714 unsigned st
= INSTR (4, 0);
10715 unsigned rn
= INSTR (9, 5);
10717 aarch64_set_mem_u32
10719 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 32),
10720 aarch64_get_vec_u32 (cpu
, st
, 0));
10723 /* 32 bit store unscaled signed 9 bit with pre- or post-writeback. */
10725 fstrs_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10727 unsigned rn
= INSTR (9, 5);
10728 unsigned st
= INSTR (4, 0);
10730 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10735 aarch64_set_mem_u32 (cpu
, address
, aarch64_get_vec_u32 (cpu
, st
, 0));
10740 if (wb
!= NoWriteBack
)
10741 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
10744 /* 32 bit store scaled or unscaled zero-
10745 or sign-extended 32-bit register offset. */
10747 fstrs_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10749 unsigned rm
= INSTR (20, 16);
10750 unsigned rn
= INSTR (9, 5);
10751 unsigned st
= INSTR (4, 0);
10753 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10754 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10756 uint64_t displacement
= OPT_SCALE (extended
, 32, scaling
);
10758 aarch64_set_mem_u32
10759 (cpu
, address
+ displacement
, aarch64_get_vec_u32 (cpu
, st
, 0));
10762 /* 64 bit store scaled unsigned 12 bit. */
10764 fstrd_abs (sim_cpu
*cpu
, uint32_t offset
)
10766 unsigned st
= INSTR (4, 0);
10767 unsigned rn
= INSTR (9, 5);
10769 aarch64_set_mem_u64
10771 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 64),
10772 aarch64_get_vec_u64 (cpu
, st
, 0));
10775 /* 64 bit store unscaled signed 9 bit with pre- or post-writeback. */
10777 fstrd_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10779 unsigned rn
= INSTR (9, 5);
10780 unsigned st
= INSTR (4, 0);
10782 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10787 aarch64_set_mem_u64 (cpu
, address
, aarch64_get_vec_u64 (cpu
, st
, 0));
10792 if (wb
!= NoWriteBack
)
10793 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
10796 /* 64 bit store scaled or unscaled zero-
10797 or sign-extended 32-bit register offset. */
10799 fstrd_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10801 unsigned rm
= INSTR (20, 16);
10802 unsigned rn
= INSTR (9, 5);
10803 unsigned st
= INSTR (4, 0);
10805 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10806 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10808 uint64_t displacement
= OPT_SCALE (extended
, 64, scaling
);
10810 aarch64_set_mem_u64
10811 (cpu
, address
+ displacement
, aarch64_get_vec_u64 (cpu
, st
, 0));
10814 /* 128 bit store scaled unsigned 12 bit. */
10816 fstrq_abs (sim_cpu
*cpu
, uint32_t offset
)
10819 unsigned st
= INSTR (4, 0);
10820 unsigned rn
= INSTR (9, 5);
10823 aarch64_get_FP_long_double (cpu
, st
, & a
);
10825 addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 128);
10826 aarch64_set_mem_long_double (cpu
, addr
, a
);
10829 /* 128 bit store unscaled signed 9 bit with pre- or post-writeback. */
10831 fstrq_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10834 unsigned rn
= INSTR (9, 5);
10835 unsigned st
= INSTR (4, 0);
10836 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10841 aarch64_get_FP_long_double (cpu
, st
, & a
);
10842 aarch64_set_mem_long_double (cpu
, address
, a
);
10847 if (wb
!= NoWriteBack
)
10848 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
10851 /* 128 bit store scaled or unscaled zero-
10852 or sign-extended 32-bit register offset. */
10854 fstrq_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10856 unsigned rm
= INSTR (20, 16);
10857 unsigned rn
= INSTR (9, 5);
10858 unsigned st
= INSTR (4, 0);
10860 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10861 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10863 uint64_t displacement
= OPT_SCALE (extended
, 128, scaling
);
10867 aarch64_get_FP_long_double (cpu
, st
, & a
);
10868 aarch64_set_mem_long_double (cpu
, address
+ displacement
, a
);
10872 dexLoadImmediatePrePost (sim_cpu
*cpu
)
10874 /* instr[31,30] = size
10880 instr[20,12] = simm9
10881 instr[11] = wb : 0 ==> Post, 1 ==> Pre
10883 instr[9,5] = Rn may be SP.
10886 uint32_t V
= INSTR (26, 26);
10887 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
10888 int32_t imm
= simm32 (aarch64_get_instr (cpu
), 20, 12);
10889 WriteBack wb
= INSTR (11, 11);
10893 /* GReg operations. */
10896 case 0: strb_wb (cpu
, imm
, wb
); return;
10897 case 1: ldrb32_wb (cpu
, imm
, wb
); return;
10898 case 2: ldrsb_wb (cpu
, imm
, wb
); return;
10899 case 3: ldrsb32_wb (cpu
, imm
, wb
); return;
10900 case 4: strh_wb (cpu
, imm
, wb
); return;
10901 case 5: ldrh32_wb (cpu
, imm
, wb
); return;
10902 case 6: ldrsh64_wb (cpu
, imm
, wb
); return;
10903 case 7: ldrsh32_wb (cpu
, imm
, wb
); return;
10904 case 8: str32_wb (cpu
, imm
, wb
); return;
10905 case 9: ldr32_wb (cpu
, imm
, wb
); return;
10906 case 10: ldrsw_wb (cpu
, imm
, wb
); return;
10907 case 12: str_wb (cpu
, imm
, wb
); return;
10908 case 13: ldr_wb (cpu
, imm
, wb
); return;
10918 /* FReg operations. */
10921 case 2: fstrq_wb (cpu
, imm
, wb
); return;
10922 case 3: fldrq_wb (cpu
, imm
, wb
); return;
10923 case 8: fstrs_wb (cpu
, imm
, wb
); return;
10924 case 9: fldrs_wb (cpu
, imm
, wb
); return;
10925 case 12: fstrd_wb (cpu
, imm
, wb
); return;
10926 case 13: fldrd_wb (cpu
, imm
, wb
); return;
10928 case 0: /* STUR 8 bit FP. */
10929 case 1: /* LDUR 8 bit FP. */
10930 case 4: /* STUR 16 bit FP. */
10931 case 5: /* LDUR 8 bit FP. */
10946 dexLoadRegisterOffset (sim_cpu
*cpu
)
10948 /* instr[31,30] = size
10955 instr[15,13] = option : 010 ==> UXTW, 011 ==> UXTX/LSL,
10956 110 ==> SXTW, 111 ==> SXTX,
10961 instr[4,0] = rt. */
10963 uint32_t V
= INSTR (26, 26);
10964 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
10965 Scaling scale
= INSTR (12, 12);
10966 Extension extensionType
= INSTR (15, 13);
10968 /* Check for illegal extension types. */
10969 if (uimm (extensionType
, 1, 1) == 0)
10972 if (extensionType
== UXTX
|| extensionType
== SXTX
)
10973 extensionType
= NoExtension
;
10977 /* GReg operations. */
10980 case 0: strb_scale_ext (cpu
, scale
, extensionType
); return;
10981 case 1: ldrb32_scale_ext (cpu
, scale
, extensionType
); return;
10982 case 2: ldrsb_scale_ext (cpu
, scale
, extensionType
); return;
10983 case 3: ldrsb32_scale_ext (cpu
, scale
, extensionType
); return;
10984 case 4: strh_scale_ext (cpu
, scale
, extensionType
); return;
10985 case 5: ldrh32_scale_ext (cpu
, scale
, extensionType
); return;
10986 case 6: ldrsh_scale_ext (cpu
, scale
, extensionType
); return;
10987 case 7: ldrsh32_scale_ext (cpu
, scale
, extensionType
); return;
10988 case 8: str32_scale_ext (cpu
, scale
, extensionType
); return;
10989 case 9: ldr32_scale_ext (cpu
, scale
, extensionType
); return;
10990 case 10: ldrsw_scale_ext (cpu
, scale
, extensionType
); return;
10991 case 12: str_scale_ext (cpu
, scale
, extensionType
); return;
10992 case 13: ldr_scale_ext (cpu
, scale
, extensionType
); return;
10993 case 14: prfm_scale_ext (cpu
, scale
, extensionType
); return;
11002 /* FReg operations. */
11005 case 1: /* LDUR 8 bit FP. */
11007 case 3: fldrq_scale_ext (cpu
, scale
, extensionType
); return;
11008 case 5: /* LDUR 8 bit FP. */
11010 case 9: fldrs_scale_ext (cpu
, scale
, extensionType
); return;
11011 case 13: fldrd_scale_ext (cpu
, scale
, extensionType
); return;
11013 case 0: fstrb_scale_ext (cpu
, scale
, extensionType
); return;
11014 case 2: fstrq_scale_ext (cpu
, scale
, extensionType
); return;
11015 case 4: fstrh_scale_ext (cpu
, scale
, extensionType
); return;
11016 case 8: fstrs_scale_ext (cpu
, scale
, extensionType
); return;
11017 case 12: fstrd_scale_ext (cpu
, scale
, extensionType
); return;
11031 dexLoadUnsignedImmediate (sim_cpu
*cpu
)
11033 /* instr[29,24] == 111_01
11034 instr[31,30] = size
11037 instr[21,10] = uimm12 : unsigned immediate offset
11038 instr[9,5] = rn may be SP.
11039 instr[4,0] = rt. */
11041 uint32_t V
= INSTR (26,26);
11042 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
11043 uint32_t imm
= INSTR (21, 10);
11047 /* GReg operations. */
11050 case 0: strb_abs (cpu
, imm
); return;
11051 case 1: ldrb32_abs (cpu
, imm
); return;
11052 case 2: ldrsb_abs (cpu
, imm
); return;
11053 case 3: ldrsb32_abs (cpu
, imm
); return;
11054 case 4: strh_abs (cpu
, imm
); return;
11055 case 5: ldrh32_abs (cpu
, imm
); return;
11056 case 6: ldrsh_abs (cpu
, imm
); return;
11057 case 7: ldrsh32_abs (cpu
, imm
); return;
11058 case 8: str32_abs (cpu
, imm
); return;
11059 case 9: ldr32_abs (cpu
, imm
); return;
11060 case 10: ldrsw_abs (cpu
, imm
); return;
11061 case 12: str_abs (cpu
, imm
); return;
11062 case 13: ldr_abs (cpu
, imm
); return;
11063 case 14: prfm_abs (cpu
, imm
); return;
11072 /* FReg operations. */
11075 case 0: fstrb_abs (cpu
, imm
); return;
11076 case 4: fstrh_abs (cpu
, imm
); return;
11077 case 8: fstrs_abs (cpu
, imm
); return;
11078 case 12: fstrd_abs (cpu
, imm
); return;
11079 case 2: fstrq_abs (cpu
, imm
); return;
11081 case 1: fldrb_abs (cpu
, imm
); return;
11082 case 5: fldrh_abs (cpu
, imm
); return;
11083 case 9: fldrs_abs (cpu
, imm
); return;
11084 case 13: fldrd_abs (cpu
, imm
); return;
11085 case 3: fldrq_abs (cpu
, imm
); return;
11099 dexLoadExclusive (sim_cpu
*cpu
)
11101 /* assert instr[29:24] = 001000;
11102 instr[31,30] = size
11103 instr[23] = 0 if exclusive
11104 instr[22] = L : 1 if load, 0 if store
11105 instr[21] = 1 if pair
11107 instr[15] = o0 : 1 if ordered
11110 instr[4.0] = Rt. */
11112 switch (INSTR (22, 21))
11114 case 2: ldxr (cpu
); return;
11115 case 0: stxr (cpu
); return;
11121 dexLoadOther (sim_cpu
*cpu
)
11125 /* instr[29,25] = 111_0
11126 instr[24] == 0 ==> dispatch, 1 ==> ldst reg unsigned immediate
11127 instr[21:11,10] is the secondary dispatch. */
11128 if (INSTR (24, 24))
11130 dexLoadUnsignedImmediate (cpu
);
11134 dispatch
= ((INSTR (21, 21) << 2) | INSTR (11, 10));
11137 case 0: dexLoadUnscaledImmediate (cpu
); return;
11138 case 1: dexLoadImmediatePrePost (cpu
); return;
11139 case 3: dexLoadImmediatePrePost (cpu
); return;
11140 case 6: dexLoadRegisterOffset (cpu
); return;
11152 store_pair_u32 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11154 unsigned rn
= INSTR (14, 10);
11155 unsigned rd
= INSTR (9, 5);
11156 unsigned rm
= INSTR (4, 0);
11157 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11159 if ((rn
== rd
|| rm
== rd
) && wb
!= NoWriteBack
)
11160 HALT_UNALLOC
; /* ??? */
11167 aarch64_set_mem_u32 (cpu
, address
,
11168 aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
11169 aarch64_set_mem_u32 (cpu
, address
+ 4,
11170 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
));
11175 if (wb
!= NoWriteBack
)
11176 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11180 store_pair_u64 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11182 unsigned rn
= INSTR (14, 10);
11183 unsigned rd
= INSTR (9, 5);
11184 unsigned rm
= INSTR (4, 0);
11185 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11187 if ((rn
== rd
|| rm
== rd
) && wb
!= NoWriteBack
)
11188 HALT_UNALLOC
; /* ??? */
11195 aarch64_set_mem_u64 (cpu
, address
,
11196 aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
11197 aarch64_set_mem_u64 (cpu
, address
+ 8,
11198 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
11203 if (wb
!= NoWriteBack
)
11204 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11208 load_pair_u32 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11210 unsigned rn
= INSTR (14, 10);
11211 unsigned rd
= INSTR (9, 5);
11212 unsigned rm
= INSTR (4, 0);
11213 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11215 /* Treat this as unalloc to make sure we don't do it. */
11224 aarch64_set_reg_u64 (cpu
, rm
, SP_OK
, aarch64_get_mem_u32 (cpu
, address
));
11225 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, aarch64_get_mem_u32 (cpu
, address
+ 4));
11230 if (wb
!= NoWriteBack
)
11231 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11235 load_pair_s32 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11237 unsigned rn
= INSTR (14, 10);
11238 unsigned rd
= INSTR (9, 5);
11239 unsigned rm
= INSTR (4, 0);
11240 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11242 /* Treat this as unalloc to make sure we don't do it. */
11251 aarch64_set_reg_s64 (cpu
, rm
, SP_OK
, aarch64_get_mem_s32 (cpu
, address
));
11252 aarch64_set_reg_s64 (cpu
, rn
, SP_OK
, aarch64_get_mem_s32 (cpu
, address
+ 4));
11257 if (wb
!= NoWriteBack
)
11258 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11262 load_pair_u64 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11264 unsigned rn
= INSTR (14, 10);
11265 unsigned rd
= INSTR (9, 5);
11266 unsigned rm
= INSTR (4, 0);
11267 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11269 /* Treat this as unalloc to make sure we don't do it. */
11278 aarch64_set_reg_u64 (cpu
, rm
, SP_OK
, aarch64_get_mem_u64 (cpu
, address
));
11279 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, aarch64_get_mem_u64 (cpu
, address
+ 8));
11284 if (wb
!= NoWriteBack
)
11285 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11289 dex_load_store_pair_gr (sim_cpu
*cpu
)
11291 /* instr[31,30] = size (10=> 64-bit, 01=> signed 32-bit, 00=> 32-bit)
11292 instr[29,25] = instruction encoding: 101_0
11293 instr[26] = V : 1 if fp 0 if gp
11294 instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
11295 instr[22] = load/store (1=> load)
11296 instr[21,15] = signed, scaled, offset
11299 instr[ 4, 0] = Rm. */
11301 uint32_t dispatch
= ((INSTR (31, 30) << 3) | INSTR (24, 22));
11302 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 21, 15);
11306 case 2: store_pair_u32 (cpu
, offset
, Post
); return;
11307 case 3: load_pair_u32 (cpu
, offset
, Post
); return;
11308 case 4: store_pair_u32 (cpu
, offset
, NoWriteBack
); return;
11309 case 5: load_pair_u32 (cpu
, offset
, NoWriteBack
); return;
11310 case 6: store_pair_u32 (cpu
, offset
, Pre
); return;
11311 case 7: load_pair_u32 (cpu
, offset
, Pre
); return;
11313 case 11: load_pair_s32 (cpu
, offset
, Post
); return;
11314 case 13: load_pair_s32 (cpu
, offset
, NoWriteBack
); return;
11315 case 15: load_pair_s32 (cpu
, offset
, Pre
); return;
11317 case 18: store_pair_u64 (cpu
, offset
, Post
); return;
11318 case 19: load_pair_u64 (cpu
, offset
, Post
); return;
11319 case 20: store_pair_u64 (cpu
, offset
, NoWriteBack
); return;
11320 case 21: load_pair_u64 (cpu
, offset
, NoWriteBack
); return;
11321 case 22: store_pair_u64 (cpu
, offset
, Pre
); return;
11322 case 23: load_pair_u64 (cpu
, offset
, Pre
); return;
11330 store_pair_float (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11332 unsigned rn
= INSTR (14, 10);
11333 unsigned rd
= INSTR (9, 5);
11334 unsigned rm
= INSTR (4, 0);
11335 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11342 aarch64_set_mem_u32 (cpu
, address
, aarch64_get_vec_u32 (cpu
, rm
, 0));
11343 aarch64_set_mem_u32 (cpu
, address
+ 4, aarch64_get_vec_u32 (cpu
, rn
, 0));
11348 if (wb
!= NoWriteBack
)
11349 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11353 store_pair_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11355 unsigned rn
= INSTR (14, 10);
11356 unsigned rd
= INSTR (9, 5);
11357 unsigned rm
= INSTR (4, 0);
11358 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11365 aarch64_set_mem_u64 (cpu
, address
, aarch64_get_vec_u64 (cpu
, rm
, 0));
11366 aarch64_set_mem_u64 (cpu
, address
+ 8, aarch64_get_vec_u64 (cpu
, rn
, 0));
11371 if (wb
!= NoWriteBack
)
11372 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11376 store_pair_long_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11379 unsigned rn
= INSTR (14, 10);
11380 unsigned rd
= INSTR (9, 5);
11381 unsigned rm
= INSTR (4, 0);
11382 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11389 aarch64_get_FP_long_double (cpu
, rm
, & a
);
11390 aarch64_set_mem_long_double (cpu
, address
, a
);
11391 aarch64_get_FP_long_double (cpu
, rn
, & a
);
11392 aarch64_set_mem_long_double (cpu
, address
+ 16, a
);
11397 if (wb
!= NoWriteBack
)
11398 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11402 load_pair_float (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11404 unsigned rn
= INSTR (14, 10);
11405 unsigned rd
= INSTR (9, 5);
11406 unsigned rm
= INSTR (4, 0);
11407 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11417 aarch64_set_vec_u32 (cpu
, rm
, 0, aarch64_get_mem_u32 (cpu
, address
));
11418 aarch64_set_vec_u32 (cpu
, rn
, 0, aarch64_get_mem_u32 (cpu
, address
+ 4));
11423 if (wb
!= NoWriteBack
)
11424 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11428 load_pair_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11430 unsigned rn
= INSTR (14, 10);
11431 unsigned rd
= INSTR (9, 5);
11432 unsigned rm
= INSTR (4, 0);
11433 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11443 aarch64_set_vec_u64 (cpu
, rm
, 0, aarch64_get_mem_u64 (cpu
, address
));
11444 aarch64_set_vec_u64 (cpu
, rn
, 0, aarch64_get_mem_u64 (cpu
, address
+ 8));
11449 if (wb
!= NoWriteBack
)
11450 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11454 load_pair_long_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11457 unsigned rn
= INSTR (14, 10);
11458 unsigned rd
= INSTR (9, 5);
11459 unsigned rm
= INSTR (4, 0);
11460 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11470 aarch64_get_mem_long_double (cpu
, address
, & a
);
11471 aarch64_set_FP_long_double (cpu
, rm
, a
);
11472 aarch64_get_mem_long_double (cpu
, address
+ 16, & a
);
11473 aarch64_set_FP_long_double (cpu
, rn
, a
);
11478 if (wb
!= NoWriteBack
)
11479 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11483 dex_load_store_pair_fp (sim_cpu
*cpu
)
11485 /* instr[31,30] = size (10=> 128-bit, 01=> 64-bit, 00=> 32-bit)
11486 instr[29,25] = instruction encoding
11487 instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
11488 instr[22] = load/store (1=> load)
11489 instr[21,15] = signed, scaled, offset
11492 instr[ 4, 0] = Rm */
11494 uint32_t dispatch
= ((INSTR (31, 30) << 3) | INSTR (24, 22));
11495 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 21, 15);
11499 case 2: store_pair_float (cpu
, offset
, Post
); return;
11500 case 3: load_pair_float (cpu
, offset
, Post
); return;
11501 case 4: store_pair_float (cpu
, offset
, NoWriteBack
); return;
11502 case 5: load_pair_float (cpu
, offset
, NoWriteBack
); return;
11503 case 6: store_pair_float (cpu
, offset
, Pre
); return;
11504 case 7: load_pair_float (cpu
, offset
, Pre
); return;
11506 case 10: store_pair_double (cpu
, offset
, Post
); return;
11507 case 11: load_pair_double (cpu
, offset
, Post
); return;
11508 case 12: store_pair_double (cpu
, offset
, NoWriteBack
); return;
11509 case 13: load_pair_double (cpu
, offset
, NoWriteBack
); return;
11510 case 14: store_pair_double (cpu
, offset
, Pre
); return;
11511 case 15: load_pair_double (cpu
, offset
, Pre
); return;
11513 case 18: store_pair_long_double (cpu
, offset
, Post
); return;
11514 case 19: load_pair_long_double (cpu
, offset
, Post
); return;
11515 case 20: store_pair_long_double (cpu
, offset
, NoWriteBack
); return;
11516 case 21: load_pair_long_double (cpu
, offset
, NoWriteBack
); return;
11517 case 22: store_pair_long_double (cpu
, offset
, Pre
); return;
11518 case 23: load_pair_long_double (cpu
, offset
, Pre
); return;
11525 static inline unsigned
11526 vec_reg (unsigned v
, unsigned o
)
11528 return (v
+ o
) & 0x3F;
11531 /* Load multiple N-element structures to M consecutive registers. */
11533 vec_load (sim_cpu
*cpu
, uint64_t address
, unsigned N
, unsigned M
)
11535 int all
= INSTR (30, 30);
11536 unsigned size
= INSTR (11, 10);
11537 unsigned vd
= INSTR (4, 0);
11538 unsigned rpt
= (N
== M
) ? 1 : M
;
11539 unsigned selem
= N
;
11544 case 0: /* 8-bit operations. */
11545 for (i
= 0; i
< rpt
; i
++)
11546 for (j
= 0; j
< (8 + (8 * all
)); j
++)
11547 for (k
= 0; k
< selem
; k
++)
11549 aarch64_set_vec_u8 (cpu
, vec_reg (vd
, i
+ k
), j
,
11550 aarch64_get_mem_u8 (cpu
, address
));
11555 case 1: /* 16-bit operations. */
11556 for (i
= 0; i
< rpt
; i
++)
11557 for (j
= 0; j
< (4 + (4 * all
)); j
++)
11558 for (k
= 0; k
< selem
; k
++)
11560 aarch64_set_vec_u16 (cpu
, vec_reg (vd
, i
+ k
), j
,
11561 aarch64_get_mem_u16 (cpu
, address
));
11566 case 2: /* 32-bit operations. */
11567 for (i
= 0; i
< rpt
; i
++)
11568 for (j
= 0; j
< (2 + (2 * all
)); j
++)
11569 for (k
= 0; k
< selem
; k
++)
11571 aarch64_set_vec_u32 (cpu
, vec_reg (vd
, i
+ k
), j
,
11572 aarch64_get_mem_u32 (cpu
, address
));
11577 case 3: /* 64-bit operations. */
11578 for (i
= 0; i
< rpt
; i
++)
11579 for (j
= 0; j
< (1 + all
); j
++)
11580 for (k
= 0; k
< selem
; k
++)
11582 aarch64_set_vec_u64 (cpu
, vec_reg (vd
, i
+ k
), j
,
11583 aarch64_get_mem_u64 (cpu
, address
));
11590 /* Load multiple 4-element structures into four consecutive registers. */
11592 LD4 (sim_cpu
*cpu
, uint64_t address
)
11594 vec_load (cpu
, address
, 4, 4);
11597 /* Load multiple 3-element structures into three consecutive registers. */
11599 LD3 (sim_cpu
*cpu
, uint64_t address
)
11601 vec_load (cpu
, address
, 3, 3);
11604 /* Load multiple 2-element structures into two consecutive registers. */
11606 LD2 (sim_cpu
*cpu
, uint64_t address
)
11608 vec_load (cpu
, address
, 2, 2);
11611 /* Load multiple 1-element structures into one register. */
11613 LD1_1 (sim_cpu
*cpu
, uint64_t address
)
11615 vec_load (cpu
, address
, 1, 1);
11618 /* Load multiple 1-element structures into two registers. */
11620 LD1_2 (sim_cpu
*cpu
, uint64_t address
)
11622 vec_load (cpu
, address
, 1, 2);
11625 /* Load multiple 1-element structures into three registers. */
11627 LD1_3 (sim_cpu
*cpu
, uint64_t address
)
11629 vec_load (cpu
, address
, 1, 3);
11632 /* Load multiple 1-element structures into four registers. */
11634 LD1_4 (sim_cpu
*cpu
, uint64_t address
)
11636 vec_load (cpu
, address
, 1, 4);
11639 /* Store multiple N-element structures from M consecutive registers. */
11641 vec_store (sim_cpu
*cpu
, uint64_t address
, unsigned N
, unsigned M
)
11643 int all
= INSTR (30, 30);
11644 unsigned size
= INSTR (11, 10);
11645 unsigned vd
= INSTR (4, 0);
11646 unsigned rpt
= (N
== M
) ? 1 : M
;
11647 unsigned selem
= N
;
11652 case 0: /* 8-bit operations. */
11653 for (i
= 0; i
< rpt
; i
++)
11654 for (j
= 0; j
< (8 + (8 * all
)); j
++)
11655 for (k
= 0; k
< selem
; k
++)
11659 aarch64_get_vec_u8 (cpu
, vec_reg (vd
, i
+ k
), j
));
11664 case 1: /* 16-bit operations. */
11665 for (i
= 0; i
< rpt
; i
++)
11666 for (j
= 0; j
< (4 + (4 * all
)); j
++)
11667 for (k
= 0; k
< selem
; k
++)
11669 aarch64_set_mem_u16
11671 aarch64_get_vec_u16 (cpu
, vec_reg (vd
, i
+ k
), j
));
11676 case 2: /* 32-bit operations. */
11677 for (i
= 0; i
< rpt
; i
++)
11678 for (j
= 0; j
< (2 + (2 * all
)); j
++)
11679 for (k
= 0; k
< selem
; k
++)
11681 aarch64_set_mem_u32
11683 aarch64_get_vec_u32 (cpu
, vec_reg (vd
, i
+ k
), j
));
11688 case 3: /* 64-bit operations. */
11689 for (i
= 0; i
< rpt
; i
++)
11690 for (j
= 0; j
< (1 + all
); j
++)
11691 for (k
= 0; k
< selem
; k
++)
11693 aarch64_set_mem_u64
11695 aarch64_get_vec_u64 (cpu
, vec_reg (vd
, i
+ k
), j
));
11702 /* Store multiple 4-element structure from four consecutive registers. */
11704 ST4 (sim_cpu
*cpu
, uint64_t address
)
11706 vec_store (cpu
, address
, 4, 4);
11709 /* Store multiple 3-element structures from three consecutive registers. */
11711 ST3 (sim_cpu
*cpu
, uint64_t address
)
11713 vec_store (cpu
, address
, 3, 3);
11716 /* Store multiple 2-element structures from two consecutive registers. */
11718 ST2 (sim_cpu
*cpu
, uint64_t address
)
11720 vec_store (cpu
, address
, 2, 2);
11723 /* Store multiple 1-element structures from one register. */
11725 ST1_1 (sim_cpu
*cpu
, uint64_t address
)
11727 vec_store (cpu
, address
, 1, 1);
11730 /* Store multiple 1-element structures from two registers. */
11732 ST1_2 (sim_cpu
*cpu
, uint64_t address
)
11734 vec_store (cpu
, address
, 1, 2);
11737 /* Store multiple 1-element structures from three registers. */
11739 ST1_3 (sim_cpu
*cpu
, uint64_t address
)
11741 vec_store (cpu
, address
, 1, 3);
11744 /* Store multiple 1-element structures from four registers. */
11746 ST1_4 (sim_cpu
*cpu
, uint64_t address
)
11748 vec_store (cpu
, address
, 1, 4);
11751 #define LDn_STn_SINGLE_LANE_AND_SIZE() \
11754 switch (INSTR (15, 14)) \
11757 lane = (full << 3) | (s << 2) | size; \
11762 if ((size & 1) == 1) \
11764 lane = (full << 2) | (s << 1) | (size >> 1); \
11769 if ((size & 2) == 2) \
11772 if ((size & 1) == 0) \
11774 lane = (full << 1) | s; \
11792 /* Load single structure into one lane of N registers. */
11794 do_vec_LDn_single (sim_cpu
*cpu
, uint64_t address
)
11797 instr[30] = element selector 0=>half, 1=>all elements
11798 instr[29,24] = 00 1101
11799 instr[23] = 0=>simple, 1=>post
11801 instr[21] = width: LD1-or-LD3 (0) / LD2-or-LD4 (1)
11802 instr[20,16] = 0 0000 (simple), Vinc (reg-post-inc, no SP),
11803 11111 (immediate post inc)
11804 instr[15,13] = opcode
11805 instr[12] = S, used for lane number
11806 instr[11,10] = size, also used for lane number
11807 instr[9,5] = address
11810 unsigned full
= INSTR (30, 30);
11811 unsigned vd
= INSTR (4, 0);
11812 unsigned size
= INSTR (11, 10);
11813 unsigned s
= INSTR (12, 12);
11814 int nregs
= ((INSTR (13, 13) << 1) | INSTR (21, 21)) + 1;
11818 NYI_assert (29, 24, 0x0D);
11819 NYI_assert (22, 22, 1);
11821 /* Compute the lane number first (using size), and then compute size. */
11822 LDn_STn_SINGLE_LANE_AND_SIZE ();
11824 for (i
= 0; i
< nregs
; i
++)
11829 uint8_t val
= aarch64_get_mem_u8 (cpu
, address
+ i
);
11830 aarch64_set_vec_u8 (cpu
, vd
+ i
, lane
, val
);
11836 uint16_t val
= aarch64_get_mem_u16 (cpu
, address
+ (i
* 2));
11837 aarch64_set_vec_u16 (cpu
, vd
+ i
, lane
, val
);
11843 uint32_t val
= aarch64_get_mem_u32 (cpu
, address
+ (i
* 4));
11844 aarch64_set_vec_u32 (cpu
, vd
+ i
, lane
, val
);
11850 uint64_t val
= aarch64_get_mem_u64 (cpu
, address
+ (i
* 8));
11851 aarch64_set_vec_u64 (cpu
, vd
+ i
, lane
, val
);
11857 /* Store single structure from one lane from N registers. */
11859 do_vec_STn_single (sim_cpu
*cpu
, uint64_t address
)
11862 instr[30] = element selector 0=>half, 1=>all elements
11863 instr[29,24] = 00 1101
11864 instr[23] = 0=>simple, 1=>post
11866 instr[21] = width: LD1-or-LD3 (0) / LD2-or-LD4 (1)
11867 instr[20,16] = 0 0000 (simple), Vinc (reg-post-inc, no SP),
11868 11111 (immediate post inc)
11869 instr[15,13] = opcode
11870 instr[12] = S, used for lane number
11871 instr[11,10] = size, also used for lane number
11872 instr[9,5] = address
11875 unsigned full
= INSTR (30, 30);
11876 unsigned vd
= INSTR (4, 0);
11877 unsigned size
= INSTR (11, 10);
11878 unsigned s
= INSTR (12, 12);
11879 int nregs
= ((INSTR (13, 13) << 1) | INSTR (21, 21)) + 1;
11883 NYI_assert (29, 24, 0x0D);
11884 NYI_assert (22, 22, 0);
11886 /* Compute the lane number first (using size), and then compute size. */
11887 LDn_STn_SINGLE_LANE_AND_SIZE ();
11889 for (i
= 0; i
< nregs
; i
++)
11894 uint8_t val
= aarch64_get_vec_u8 (cpu
, vd
+ i
, lane
);
11895 aarch64_set_mem_u8 (cpu
, address
+ i
, val
);
11901 uint16_t val
= aarch64_get_vec_u16 (cpu
, vd
+ i
, lane
);
11902 aarch64_set_mem_u16 (cpu
, address
+ (i
* 2), val
);
11908 uint32_t val
= aarch64_get_vec_u32 (cpu
, vd
+ i
, lane
);
11909 aarch64_set_mem_u32 (cpu
, address
+ (i
* 4), val
);
11915 uint64_t val
= aarch64_get_vec_u64 (cpu
, vd
+ i
, lane
);
11916 aarch64_set_mem_u64 (cpu
, address
+ (i
* 8), val
);
11922 /* Load single structure into all lanes of N registers. */
11924 do_vec_LDnR (sim_cpu
*cpu
, uint64_t address
)
11927 instr[30] = element selector 0=>half, 1=>all elements
11928 instr[29,24] = 00 1101
11929 instr[23] = 0=>simple, 1=>post
11931 instr[21] = width: LD1R-or-LD3R (0) / LD2R-or-LD4R (1)
11932 instr[20,16] = 0 0000 (simple), Vinc (reg-post-inc, no SP),
11933 11111 (immediate post inc)
11935 instr[13] = width: LD1R-or-LD2R (0) / LD3R-or-LD4R (1)
11937 instr[11,10] = element size 00=> byte(b), 01=> half(h),
11938 10=> word(s), 11=> double(d)
11939 instr[9,5] = address
11942 unsigned full
= INSTR (30, 30);
11943 unsigned vd
= INSTR (4, 0);
11944 unsigned size
= INSTR (11, 10);
11945 int nregs
= ((INSTR (13, 13) << 1) | INSTR (21, 21)) + 1;
11948 NYI_assert (29, 24, 0x0D);
11949 NYI_assert (22, 22, 1);
11950 NYI_assert (15, 14, 3);
11951 NYI_assert (12, 12, 0);
11953 for (n
= 0; n
< nregs
; n
++)
11958 uint8_t val
= aarch64_get_mem_u8 (cpu
, address
+ n
);
11959 for (i
= 0; i
< (full
? 16 : 8); i
++)
11960 aarch64_set_vec_u8 (cpu
, vd
+ n
, i
, val
);
11966 uint16_t val
= aarch64_get_mem_u16 (cpu
, address
+ (n
* 2));
11967 for (i
= 0; i
< (full
? 8 : 4); i
++)
11968 aarch64_set_vec_u16 (cpu
, vd
+ n
, i
, val
);
11974 uint32_t val
= aarch64_get_mem_u32 (cpu
, address
+ (n
* 4));
11975 for (i
= 0; i
< (full
? 4 : 2); i
++)
11976 aarch64_set_vec_u32 (cpu
, vd
+ n
, i
, val
);
11982 uint64_t val
= aarch64_get_mem_u64 (cpu
, address
+ (n
* 8));
11983 for (i
= 0; i
< (full
? 2 : 1); i
++)
11984 aarch64_set_vec_u64 (cpu
, vd
+ n
, i
, val
);
11994 do_vec_load_store (sim_cpu
*cpu
)
11996 /* {LD|ST}<N> {Vd..Vd+N}, vaddr
11999 instr[30] = element selector 0=>half, 1=>all elements
12000 instr[29,25] = 00110
12001 instr[24] = 0=>multiple struct, 1=>single struct
12002 instr[23] = 0=>simple, 1=>post
12003 instr[22] = 0=>store, 1=>load
12004 instr[21] = 0 (LDn) / small(0)-large(1) selector (LDnR)
12005 instr[20,16] = 00000 (simple), Vinc (reg-post-inc, no SP),
12006 11111 (immediate post inc)
12007 instr[15,12] = elements and destinations. eg for load:
12008 0000=>LD4 => load multiple 4-element to
12009 four consecutive registers
12010 0100=>LD3 => load multiple 3-element to
12011 three consecutive registers
12012 1000=>LD2 => load multiple 2-element to
12013 two consecutive registers
12014 0010=>LD1 => load multiple 1-element to
12015 four consecutive registers
12016 0110=>LD1 => load multiple 1-element to
12017 three consecutive registers
12018 1010=>LD1 => load multiple 1-element to
12019 two consecutive registers
12020 0111=>LD1 => load multiple 1-element to
12024 instr[11,10] = element size 00=> byte(b), 01=> half(h),
12025 10=> word(s), 11=> double(d)
12026 instr[9,5] = Vn, can be SP
12036 if (INSTR (31, 31) != 0 || INSTR (29, 25) != 0x06)
12039 single
= INSTR (24, 24);
12040 post
= INSTR (23, 23);
12041 load
= INSTR (22, 22);
12042 type
= INSTR (15, 12);
12044 address
= aarch64_get_reg_u64 (cpu
, vn
, SP_OK
);
12046 if (! single
&& INSTR (21, 21) != 0)
12051 unsigned vm
= INSTR (20, 16);
12055 unsigned sizeof_operation
;
12059 if ((type
>= 0) && (type
<= 11))
12061 int nregs
= ((INSTR (13, 13) << 1) | INSTR (21, 21)) + 1;
12062 switch (INSTR (15, 14))
12065 sizeof_operation
= nregs
* 1;
12068 sizeof_operation
= nregs
* 2;
12071 if (INSTR (10, 10) == 0)
12072 sizeof_operation
= nregs
* 4;
12074 sizeof_operation
= nregs
* 8;
12080 else if (type
== 0xC)
12082 sizeof_operation
= INSTR (21, 21) ? 2 : 1;
12083 sizeof_operation
<<= INSTR (11, 10);
12085 else if (type
== 0xE)
12087 sizeof_operation
= INSTR (21, 21) ? 4 : 3;
12088 sizeof_operation
<<= INSTR (11, 10);
12097 case 0: sizeof_operation
= 32; break;
12098 case 4: sizeof_operation
= 24; break;
12099 case 8: sizeof_operation
= 16; break;
12102 /* One register, immediate offset variant. */
12103 sizeof_operation
= 8;
12107 /* Two registers, immediate offset variant. */
12108 sizeof_operation
= 16;
12112 /* Three registers, immediate offset variant. */
12113 sizeof_operation
= 24;
12117 /* Four registers, immediate offset variant. */
12118 sizeof_operation
= 32;
12125 if (INSTR (30, 30))
12126 sizeof_operation
*= 2;
12129 aarch64_set_reg_u64 (cpu
, vn
, SP_OK
, address
+ sizeof_operation
);
12132 aarch64_set_reg_u64 (cpu
, vn
, SP_OK
,
12133 address
+ aarch64_get_reg_u64 (cpu
, vm
, NO_SP
));
12137 NYI_assert (20, 16, 0);
12144 if ((type
>= 0) && (type
<= 11))
12145 do_vec_LDn_single (cpu
, address
);
12146 else if ((type
== 0xC) || (type
== 0xE))
12147 do_vec_LDnR (cpu
, address
);
12154 if ((type
>= 0) && (type
<= 11))
12156 do_vec_STn_single (cpu
, address
);
12167 case 0: LD4 (cpu
, address
); return;
12168 case 4: LD3 (cpu
, address
); return;
12169 case 8: LD2 (cpu
, address
); return;
12170 case 2: LD1_4 (cpu
, address
); return;
12171 case 6: LD1_3 (cpu
, address
); return;
12172 case 10: LD1_2 (cpu
, address
); return;
12173 case 7: LD1_1 (cpu
, address
); return;
12183 case 0: ST4 (cpu
, address
); return;
12184 case 4: ST3 (cpu
, address
); return;
12185 case 8: ST2 (cpu
, address
); return;
12186 case 2: ST1_4 (cpu
, address
); return;
12187 case 6: ST1_3 (cpu
, address
); return;
12188 case 10: ST1_2 (cpu
, address
); return;
12189 case 7: ST1_1 (cpu
, address
); return;
12196 dexLdSt (sim_cpu
*cpu
)
12198 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
12199 assert group == GROUP_LDST_0100 || group == GROUP_LDST_0110 ||
12200 group == GROUP_LDST_1100 || group == GROUP_LDST_1110
12201 bits [29,28:26] of a LS are the secondary dispatch vector. */
12202 uint32_t group2
= dispatchLS (aarch64_get_instr (cpu
));
12207 dexLoadExclusive (cpu
); return;
12211 dexLoadLiteral (cpu
); return;
12215 dexLoadOther (cpu
); return;
12217 case LS_ADVSIMD_001
:
12218 do_vec_load_store (cpu
); return;
12221 dex_load_store_pair_gr (cpu
); return;
12224 dex_load_store_pair_fp (cpu
); return;
12227 /* Should never reach here. */
12232 /* Specific decode and execute for group Data Processing Register. */
12235 dexLogicalShiftedRegister (sim_cpu
*cpu
)
12237 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12239 instr[28:24] = 01010
12240 instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> ROR
12243 instr[15,10] = count : must be 0xxxxx for 32 bit
12247 uint32_t size
= INSTR (31, 31);
12248 Shift shiftType
= INSTR (23, 22);
12249 uint32_t count
= INSTR (15, 10);
12251 /* 32 bit operations must have count[5] = 0.
12252 or else we have an UNALLOC. */
12253 if (size
== 0 && uimm (count
, 5, 5))
12256 /* Dispatch on size:op:N. */
12257 switch ((INSTR (31, 29) << 1) | INSTR (21, 21))
12259 case 0: and32_shift (cpu
, shiftType
, count
); return;
12260 case 1: bic32_shift (cpu
, shiftType
, count
); return;
12261 case 2: orr32_shift (cpu
, shiftType
, count
); return;
12262 case 3: orn32_shift (cpu
, shiftType
, count
); return;
12263 case 4: eor32_shift (cpu
, shiftType
, count
); return;
12264 case 5: eon32_shift (cpu
, shiftType
, count
); return;
12265 case 6: ands32_shift (cpu
, shiftType
, count
); return;
12266 case 7: bics32_shift (cpu
, shiftType
, count
); return;
12267 case 8: and64_shift (cpu
, shiftType
, count
); return;
12268 case 9: bic64_shift (cpu
, shiftType
, count
); return;
12269 case 10:orr64_shift (cpu
, shiftType
, count
); return;
12270 case 11:orn64_shift (cpu
, shiftType
, count
); return;
12271 case 12:eor64_shift (cpu
, shiftType
, count
); return;
12272 case 13:eon64_shift (cpu
, shiftType
, count
); return;
12273 case 14:ands64_shift (cpu
, shiftType
, count
); return;
12274 case 15:bics64_shift (cpu
, shiftType
, count
); return;
12278 /* 32 bit conditional select. */
12280 csel32 (sim_cpu
*cpu
, CondCode cc
)
12282 unsigned rm
= INSTR (20, 16);
12283 unsigned rn
= INSTR (9, 5);
12284 unsigned rd
= INSTR (4, 0);
12286 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12287 testConditionCode (cpu
, cc
)
12288 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12289 : aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12292 /* 64 bit conditional select. */
12294 csel64 (sim_cpu
*cpu
, CondCode cc
)
12296 unsigned rm
= INSTR (20, 16);
12297 unsigned rn
= INSTR (9, 5);
12298 unsigned rd
= INSTR (4, 0);
12300 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12301 testConditionCode (cpu
, cc
)
12302 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12303 : aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
12306 /* 32 bit conditional increment. */
12308 csinc32 (sim_cpu
*cpu
, CondCode cc
)
12310 unsigned rm
= INSTR (20, 16);
12311 unsigned rn
= INSTR (9, 5);
12312 unsigned rd
= INSTR (4, 0);
12314 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12315 testConditionCode (cpu
, cc
)
12316 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12317 : aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) + 1);
12320 /* 64 bit conditional increment. */
12322 csinc64 (sim_cpu
*cpu
, CondCode cc
)
12324 unsigned rm
= INSTR (20, 16);
12325 unsigned rn
= INSTR (9, 5);
12326 unsigned rd
= INSTR (4, 0);
12328 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12329 testConditionCode (cpu
, cc
)
12330 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12331 : aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) + 1);
12334 /* 32 bit conditional invert. */
12336 csinv32 (sim_cpu
*cpu
, CondCode cc
)
12338 unsigned rm
= INSTR (20, 16);
12339 unsigned rn
= INSTR (9, 5);
12340 unsigned rd
= INSTR (4, 0);
12342 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12343 testConditionCode (cpu
, cc
)
12344 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12345 : ~ aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12348 /* 64 bit conditional invert. */
12350 csinv64 (sim_cpu
*cpu
, CondCode cc
)
12352 unsigned rm
= INSTR (20, 16);
12353 unsigned rn
= INSTR (9, 5);
12354 unsigned rd
= INSTR (4, 0);
12356 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12357 testConditionCode (cpu
, cc
)
12358 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12359 : ~ aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
12362 /* 32 bit conditional negate. */
12364 csneg32 (sim_cpu
*cpu
, CondCode cc
)
12366 unsigned rm
= INSTR (20, 16);
12367 unsigned rn
= INSTR (9, 5);
12368 unsigned rd
= INSTR (4, 0);
12370 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12371 testConditionCode (cpu
, cc
)
12372 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12373 : - aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12376 /* 64 bit conditional negate. */
12378 csneg64 (sim_cpu
*cpu
, CondCode cc
)
12380 unsigned rm
= INSTR (20, 16);
12381 unsigned rn
= INSTR (9, 5);
12382 unsigned rd
= INSTR (4, 0);
12384 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12385 testConditionCode (cpu
, cc
)
12386 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12387 : - aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
12391 dexCondSelect (sim_cpu
*cpu
)
12393 /* instr[28,21] = 11011011
12394 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12395 instr[30:11,10] = op : 000 ==> CSEL, 001 ==> CSINC,
12396 100 ==> CSINV, 101 ==> CSNEG,
12398 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
12399 instr[15,12] = cond
12400 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC */
12402 CondCode cc
= INSTR (15, 12);
12403 uint32_t S
= INSTR (29, 29);
12404 uint32_t op2
= INSTR (11, 10);
12412 switch ((INSTR (31, 30) << 1) | op2
)
12414 case 0: csel32 (cpu
, cc
); return;
12415 case 1: csinc32 (cpu
, cc
); return;
12416 case 2: csinv32 (cpu
, cc
); return;
12417 case 3: csneg32 (cpu
, cc
); return;
12418 case 4: csel64 (cpu
, cc
); return;
12419 case 5: csinc64 (cpu
, cc
); return;
12420 case 6: csinv64 (cpu
, cc
); return;
12421 case 7: csneg64 (cpu
, cc
); return;
12425 /* Some helpers for counting leading 1 or 0 bits. */
12427 /* Counts the number of leading bits which are the same
12428 in a 32 bit value in the range 1 to 32. */
12430 leading32 (uint32_t value
)
12432 int32_t mask
= 0xffff0000;
12433 uint32_t count
= 16; /* Counts number of bits set in mask. */
12434 uint32_t lo
= 1; /* Lower bound for number of sign bits. */
12435 uint32_t hi
= 32; /* Upper bound for number of sign bits. */
12437 while (lo
+ 1 < hi
)
12439 int32_t test
= (value
& mask
);
12441 if (test
== 0 || test
== mask
)
12444 count
= (lo
+ hi
) / 2;
12445 mask
>>= (count
- lo
);
12450 count
= (lo
+ hi
) / 2;
12451 mask
<<= hi
- count
;
12460 test
= (value
& mask
);
12462 if (test
== 0 || test
== mask
)
12471 /* Counts the number of leading bits which are the same
12472 in a 64 bit value in the range 1 to 64. */
12474 leading64 (uint64_t value
)
12476 int64_t mask
= 0xffffffff00000000LL
;
12477 uint64_t count
= 32; /* Counts number of bits set in mask. */
12478 uint64_t lo
= 1; /* Lower bound for number of sign bits. */
12479 uint64_t hi
= 64; /* Upper bound for number of sign bits. */
12481 while (lo
+ 1 < hi
)
12483 int64_t test
= (value
& mask
);
12485 if (test
== 0 || test
== mask
)
12488 count
= (lo
+ hi
) / 2;
12489 mask
>>= (count
- lo
);
12494 count
= (lo
+ hi
) / 2;
12495 mask
<<= hi
- count
;
12504 test
= (value
& mask
);
12506 if (test
== 0 || test
== mask
)
12515 /* Bit operations. */
12516 /* N.B register args may not be SP. */
12518 /* 32 bit count leading sign bits. */
12520 cls32 (sim_cpu
*cpu
)
12522 unsigned rn
= INSTR (9, 5);
12523 unsigned rd
= INSTR (4, 0);
12525 /* N.B. the result needs to exclude the leading bit. */
12526 aarch64_set_reg_u64
12527 (cpu
, rd
, NO_SP
, leading32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)) - 1);
12530 /* 64 bit count leading sign bits. */
12532 cls64 (sim_cpu
*cpu
)
12534 unsigned rn
= INSTR (9, 5);
12535 unsigned rd
= INSTR (4, 0);
12537 /* N.B. the result needs to exclude the leading bit. */
12538 aarch64_set_reg_u64
12539 (cpu
, rd
, NO_SP
, leading64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)) - 1);
12542 /* 32 bit count leading zero bits. */
12544 clz32 (sim_cpu
*cpu
)
12546 unsigned rn
= INSTR (9, 5);
12547 unsigned rd
= INSTR (4, 0);
12548 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12550 /* if the sign (top) bit is set then the count is 0. */
12551 if (pick32 (value
, 31, 31))
12552 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, 0L);
12554 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, leading32 (value
));
12557 /* 64 bit count leading zero bits. */
12559 clz64 (sim_cpu
*cpu
)
12561 unsigned rn
= INSTR (9, 5);
12562 unsigned rd
= INSTR (4, 0);
12563 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12565 /* if the sign (top) bit is set then the count is 0. */
12566 if (pick64 (value
, 63, 63))
12567 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, 0L);
12569 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, leading64 (value
));
12572 /* 32 bit reverse bits. */
12574 rbit32 (sim_cpu
*cpu
)
12576 unsigned rn
= INSTR (9, 5);
12577 unsigned rd
= INSTR (4, 0);
12578 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12579 uint32_t result
= 0;
12582 for (i
= 0; i
< 32; i
++)
12585 result
|= (value
& 1);
12588 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12591 /* 64 bit reverse bits. */
12593 rbit64 (sim_cpu
*cpu
)
12595 unsigned rn
= INSTR (9, 5);
12596 unsigned rd
= INSTR (4, 0);
12597 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12598 uint64_t result
= 0;
12601 for (i
= 0; i
< 64; i
++)
12604 result
|= (value
& 1UL);
12607 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12610 /* 32 bit reverse bytes. */
12612 rev32 (sim_cpu
*cpu
)
12614 unsigned rn
= INSTR (9, 5);
12615 unsigned rd
= INSTR (4, 0);
12616 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12617 uint32_t result
= 0;
12620 for (i
= 0; i
< 4; i
++)
12623 result
|= (value
& 0xff);
12626 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12629 /* 64 bit reverse bytes. */
12631 rev64 (sim_cpu
*cpu
)
12633 unsigned rn
= INSTR (9, 5);
12634 unsigned rd
= INSTR (4, 0);
12635 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12636 uint64_t result
= 0;
12639 for (i
= 0; i
< 8; i
++)
12642 result
|= (value
& 0xffULL
);
12645 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12648 /* 32 bit reverse shorts. */
12649 /* N.B.this reverses the order of the bytes in each half word. */
12651 revh32 (sim_cpu
*cpu
)
12653 unsigned rn
= INSTR (9, 5);
12654 unsigned rd
= INSTR (4, 0);
12655 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12656 uint32_t result
= 0;
12659 for (i
= 0; i
< 2; i
++)
12662 result
|= (value
& 0x00ff00ff);
12665 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12668 /* 64 bit reverse shorts. */
12669 /* N.B.this reverses the order of the bytes in each half word. */
12671 revh64 (sim_cpu
*cpu
)
12673 unsigned rn
= INSTR (9, 5);
12674 unsigned rd
= INSTR (4, 0);
12675 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12676 uint64_t result
= 0;
12679 for (i
= 0; i
< 2; i
++)
12682 result
|= (value
& 0x00ff00ff00ff00ffULL
);
12685 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12689 dexDataProc1Source (sim_cpu
*cpu
)
12692 instr[28,21] = 111010110
12693 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12694 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
12695 instr[20,16] = opcode2 : 00000 ==> ok, ow ==> UNALLOC
12696 instr[15,10] = opcode : 000000 ==> RBIT, 000001 ==> REV16,
12697 000010 ==> REV, 000011 ==> UNALLOC
12698 000100 ==> CLZ, 000101 ==> CLS
12700 instr[9,5] = rn : may not be SP
12701 instr[4,0] = rd : may not be SP. */
12703 uint32_t S
= INSTR (29, 29);
12704 uint32_t opcode2
= INSTR (20, 16);
12705 uint32_t opcode
= INSTR (15, 10);
12706 uint32_t dispatch
= ((INSTR (31, 31) << 3) | opcode
);
12719 case 0: rbit32 (cpu
); return;
12720 case 1: revh32 (cpu
); return;
12721 case 2: rev32 (cpu
); return;
12722 case 4: clz32 (cpu
); return;
12723 case 5: cls32 (cpu
); return;
12724 case 8: rbit64 (cpu
); return;
12725 case 9: revh64 (cpu
); return;
12726 case 10:rev32 (cpu
); return;
12727 case 11:rev64 (cpu
); return;
12728 case 12:clz64 (cpu
); return;
12729 case 13:cls64 (cpu
); return;
12730 default: HALT_UNALLOC
;
12735 Shifts by count supplied in register.
12736 N.B register args may not be SP.
12737 These all use the shifted auxiliary function for
12738 simplicity and clarity. Writing the actual shift
12739 inline would avoid a branch and so be faster but
12740 would also necessitate getting signs right. */
12742 /* 32 bit arithmetic shift right. */
12744 asrv32 (sim_cpu
*cpu
)
12746 unsigned rm
= INSTR (20, 16);
12747 unsigned rn
= INSTR (9, 5);
12748 unsigned rd
= INSTR (4, 0);
12750 aarch64_set_reg_u64
12752 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), ASR
,
12753 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12756 /* 64 bit arithmetic shift right. */
12758 asrv64 (sim_cpu
*cpu
)
12760 unsigned rm
= INSTR (20, 16);
12761 unsigned rn
= INSTR (9, 5);
12762 unsigned rd
= INSTR (4, 0);
12764 aarch64_set_reg_u64
12766 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), ASR
,
12767 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12770 /* 32 bit logical shift left. */
12772 lslv32 (sim_cpu
*cpu
)
12774 unsigned rm
= INSTR (20, 16);
12775 unsigned rn
= INSTR (9, 5);
12776 unsigned rd
= INSTR (4, 0);
12778 aarch64_set_reg_u64
12780 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), LSL
,
12781 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12784 /* 64 bit arithmetic shift left. */
12786 lslv64 (sim_cpu
*cpu
)
12788 unsigned rm
= INSTR (20, 16);
12789 unsigned rn
= INSTR (9, 5);
12790 unsigned rd
= INSTR (4, 0);
12792 aarch64_set_reg_u64
12794 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), LSL
,
12795 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12798 /* 32 bit logical shift right. */
12800 lsrv32 (sim_cpu
*cpu
)
12802 unsigned rm
= INSTR (20, 16);
12803 unsigned rn
= INSTR (9, 5);
12804 unsigned rd
= INSTR (4, 0);
12806 aarch64_set_reg_u64
12808 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), LSR
,
12809 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12812 /* 64 bit logical shift right. */
12814 lsrv64 (sim_cpu
*cpu
)
12816 unsigned rm
= INSTR (20, 16);
12817 unsigned rn
= INSTR (9, 5);
12818 unsigned rd
= INSTR (4, 0);
12820 aarch64_set_reg_u64
12822 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), LSR
,
12823 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12826 /* 32 bit rotate right. */
12828 rorv32 (sim_cpu
*cpu
)
12830 unsigned rm
= INSTR (20, 16);
12831 unsigned rn
= INSTR (9, 5);
12832 unsigned rd
= INSTR (4, 0);
12834 aarch64_set_reg_u64
12836 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), ROR
,
12837 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12840 /* 64 bit rotate right. */
12842 rorv64 (sim_cpu
*cpu
)
12844 unsigned rm
= INSTR (20, 16);
12845 unsigned rn
= INSTR (9, 5);
12846 unsigned rd
= INSTR (4, 0);
12848 aarch64_set_reg_u64
12850 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), ROR
,
12851 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12857 /* 32 bit signed divide. */
12859 cpuiv32 (sim_cpu
*cpu
)
12861 unsigned rm
= INSTR (20, 16);
12862 unsigned rn
= INSTR (9, 5);
12863 unsigned rd
= INSTR (4, 0);
12864 /* N.B. the pseudo-code does the divide using 64 bit data. */
12865 /* TODO : check that this rounds towards zero as required. */
12866 int64_t dividend
= aarch64_get_reg_s32 (cpu
, rn
, NO_SP
);
12867 int64_t divisor
= aarch64_get_reg_s32 (cpu
, rm
, NO_SP
);
12869 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
,
12870 divisor
? ((int32_t) (dividend
/ divisor
)) : 0);
12873 /* 64 bit signed divide. */
12875 cpuiv64 (sim_cpu
*cpu
)
12877 unsigned rm
= INSTR (20, 16);
12878 unsigned rn
= INSTR (9, 5);
12879 unsigned rd
= INSTR (4, 0);
12881 /* TODO : check that this rounds towards zero as required. */
12882 int64_t divisor
= aarch64_get_reg_s64 (cpu
, rm
, NO_SP
);
12884 aarch64_set_reg_s64
12886 divisor
? (aarch64_get_reg_s64 (cpu
, rn
, NO_SP
) / divisor
) : 0);
12889 /* 32 bit unsigned divide. */
12891 udiv32 (sim_cpu
*cpu
)
12893 unsigned rm
= INSTR (20, 16);
12894 unsigned rn
= INSTR (9, 5);
12895 unsigned rd
= INSTR (4, 0);
12897 /* N.B. the pseudo-code does the divide using 64 bit data. */
12898 uint64_t dividend
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12899 uint64_t divisor
= aarch64_get_reg_u32 (cpu
, rm
, NO_SP
);
12901 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12902 divisor
? (uint32_t) (dividend
/ divisor
) : 0);
12905 /* 64 bit unsigned divide. */
12907 udiv64 (sim_cpu
*cpu
)
12909 unsigned rm
= INSTR (20, 16);
12910 unsigned rn
= INSTR (9, 5);
12911 unsigned rd
= INSTR (4, 0);
12913 /* TODO : check that this rounds towards zero as required. */
12914 uint64_t divisor
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
12916 aarch64_set_reg_u64
12918 divisor
? (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) / divisor
) : 0);
12922 dexDataProc2Source (sim_cpu
*cpu
)
12924 /* assert instr[30] == 0
12925 instr[28,21] == 11010110
12926 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12927 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
12928 instr[15,10] = opcode : 000010 ==> UDIV, 000011 ==> CPUIV,
12929 001000 ==> LSLV, 001001 ==> LSRV
12930 001010 ==> ASRV, 001011 ==> RORV
12934 uint32_t S
= INSTR (29, 29);
12935 uint32_t opcode
= INSTR (15, 10);
12943 dispatch
= ( (INSTR (31, 31) << 3)
12944 | (uimm (opcode
, 3, 3) << 2)
12945 | uimm (opcode
, 1, 0));
12948 case 2: udiv32 (cpu
); return;
12949 case 3: cpuiv32 (cpu
); return;
12950 case 4: lslv32 (cpu
); return;
12951 case 5: lsrv32 (cpu
); return;
12952 case 6: asrv32 (cpu
); return;
12953 case 7: rorv32 (cpu
); return;
12954 case 10: udiv64 (cpu
); return;
12955 case 11: cpuiv64 (cpu
); return;
12956 case 12: lslv64 (cpu
); return;
12957 case 13: lsrv64 (cpu
); return;
12958 case 14: asrv64 (cpu
); return;
12959 case 15: rorv64 (cpu
); return;
12960 default: HALT_UNALLOC
;
12967 /* 32 bit multiply and add. */
12969 madd32 (sim_cpu
*cpu
)
12971 unsigned rm
= INSTR (20, 16);
12972 unsigned ra
= INSTR (14, 10);
12973 unsigned rn
= INSTR (9, 5);
12974 unsigned rd
= INSTR (4, 0);
12976 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12977 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12978 aarch64_get_reg_u32 (cpu
, ra
, NO_SP
)
12979 + aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12980 * aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12983 /* 64 bit multiply and add. */
12985 madd64 (sim_cpu
*cpu
)
12987 unsigned rm
= INSTR (20, 16);
12988 unsigned ra
= INSTR (14, 10);
12989 unsigned rn
= INSTR (9, 5);
12990 unsigned rd
= INSTR (4, 0);
12992 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12993 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12994 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
12995 + (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12996 * aarch64_get_reg_u64 (cpu
, rm
, NO_SP
)));
12999 /* 32 bit multiply and sub. */
13001 msub32 (sim_cpu
*cpu
)
13003 unsigned rm
= INSTR (20, 16);
13004 unsigned ra
= INSTR (14, 10);
13005 unsigned rn
= INSTR (9, 5);
13006 unsigned rd
= INSTR (4, 0);
13008 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13009 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
13010 aarch64_get_reg_u32 (cpu
, ra
, NO_SP
)
13011 - aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
13012 * aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
13015 /* 64 bit multiply and sub. */
13017 msub64 (sim_cpu
*cpu
)
13019 unsigned rm
= INSTR (20, 16);
13020 unsigned ra
= INSTR (14, 10);
13021 unsigned rn
= INSTR (9, 5);
13022 unsigned rd
= INSTR (4, 0);
13024 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13025 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
13026 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
13027 - aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
13028 * aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
13031 /* Signed multiply add long -- source, source2 : 32 bit, source3 : 64 bit. */
13033 smaddl (sim_cpu
*cpu
)
13035 unsigned rm
= INSTR (20, 16);
13036 unsigned ra
= INSTR (14, 10);
13037 unsigned rn
= INSTR (9, 5);
13038 unsigned rd
= INSTR (4, 0);
13040 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
13041 obtain a 64 bit product. */
13042 aarch64_set_reg_s64
13044 aarch64_get_reg_s64 (cpu
, ra
, NO_SP
)
13045 + ((int64_t) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
))
13046 * ((int64_t) aarch64_get_reg_s32 (cpu
, rm
, NO_SP
)));
13049 /* Signed multiply sub long -- source, source2 : 32 bit, source3 : 64 bit. */
13051 smsubl (sim_cpu
*cpu
)
13053 unsigned rm
= INSTR (20, 16);
13054 unsigned ra
= INSTR (14, 10);
13055 unsigned rn
= INSTR (9, 5);
13056 unsigned rd
= INSTR (4, 0);
13058 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
13059 obtain a 64 bit product. */
13060 aarch64_set_reg_s64
13062 aarch64_get_reg_s64 (cpu
, ra
, NO_SP
)
13063 - ((int64_t) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
))
13064 * ((int64_t) aarch64_get_reg_s32 (cpu
, rm
, NO_SP
)));
13067 /* Integer Multiply/Divide. */
13069 /* First some macros and a helper function. */
13070 /* Macros to test or access elements of 64 bit words. */
13072 /* Mask used to access lo 32 bits of 64 bit unsigned int. */
13073 #define LOW_WORD_MASK ((1ULL << 32) - 1)
13074 /* Return the lo 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int. */
13075 #define lowWordToU64(_value_u64) ((_value_u64) & LOW_WORD_MASK)
13076 /* Return the hi 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int. */
13077 #define highWordToU64(_value_u64) ((_value_u64) >> 32)
13079 /* Offset of sign bit in 64 bit signed integger. */
13080 #define SIGN_SHIFT_U64 63
13081 /* The sign bit itself -- also identifies the minimum negative int value. */
13082 #define SIGN_BIT_U64 (1UL << SIGN_SHIFT_U64)
13083 /* Return true if a 64 bit signed int presented as an unsigned int is the
13084 most negative value. */
13085 #define isMinimumU64(_value_u64) ((_value_u64) == SIGN_BIT_U64)
13086 /* Return true (non-zero) if a 64 bit signed int presented as an unsigned
13087 int has its sign bit set to false. */
13088 #define isSignSetU64(_value_u64) ((_value_u64) & SIGN_BIT_U64)
13089 /* Return 1L or -1L according to whether a 64 bit signed int presented as
13090 an unsigned int has its sign bit set or not. */
13091 #define signOfU64(_value_u64) (1L + (((value_u64) >> SIGN_SHIFT_U64) * -2L)
13092 /* Clear the sign bit of a 64 bit signed int presented as an unsigned int. */
13093 #define clearSignU64(_value_u64) ((_value_u64) &= ~SIGN_BIT_U64)
13095 /* Multiply two 64 bit ints and return.
13096 the hi 64 bits of the 128 bit product. */
13099 mul64hi (uint64_t value1
, uint64_t value2
)
13101 uint64_t resultmid1
;
13103 uint64_t value1_lo
= lowWordToU64 (value1
);
13104 uint64_t value1_hi
= highWordToU64 (value1
) ;
13105 uint64_t value2_lo
= lowWordToU64 (value2
);
13106 uint64_t value2_hi
= highWordToU64 (value2
);
13108 /* Cross-multiply and collect results. */
13109 uint64_t xproductlo
= value1_lo
* value2_lo
;
13110 uint64_t xproductmid1
= value1_lo
* value2_hi
;
13111 uint64_t xproductmid2
= value1_hi
* value2_lo
;
13112 uint64_t xproducthi
= value1_hi
* value2_hi
;
13113 uint64_t carry
= 0;
13114 /* Start accumulating 64 bit results. */
13115 /* Drop bottom half of lowest cross-product. */
13116 uint64_t resultmid
= xproductlo
>> 32;
13117 /* Add in middle products. */
13118 resultmid
= resultmid
+ xproductmid1
;
13120 /* Check for overflow. */
13121 if (resultmid
< xproductmid1
)
13122 /* Carry over 1 into top cross-product. */
13125 resultmid1
= resultmid
+ xproductmid2
;
13127 /* Check for overflow. */
13128 if (resultmid1
< xproductmid2
)
13129 /* Carry over 1 into top cross-product. */
13132 /* Drop lowest 32 bits of middle cross-product. */
13133 result
= resultmid1
>> 32;
13134 /* Move carry bit to just above middle cross-product highest bit. */
13135 carry
= carry
<< 32;
13137 /* Add top cross-product plus and any carry. */
13138 result
+= xproducthi
+ carry
;
13143 /* Signed multiply high, source, source2 :
13144 64 bit, dest <-- high 64-bit of result. */
13146 smulh (sim_cpu
*cpu
)
13150 unsigned rm
= INSTR (20, 16);
13151 unsigned rn
= INSTR (9, 5);
13152 unsigned rd
= INSTR (4, 0);
13153 GReg ra
= INSTR (14, 10);
13154 int64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
13155 int64_t value2
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
13163 /* Convert to unsigned and use the unsigned mul64hi routine
13164 the fix the sign up afterwards. */
13185 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13187 uresult
= mul64hi (uvalue1
, uvalue2
);
13192 /* Multiply 128-bit result by -1, which means highpart gets inverted,
13193 and has carry in added only if low part is 0. */
13195 if ((uvalue1
* uvalue2
) == 0)
13199 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, result
);
13202 /* Unsigned multiply add long -- source, source2 :
13203 32 bit, source3 : 64 bit. */
13205 umaddl (sim_cpu
*cpu
)
13207 unsigned rm
= INSTR (20, 16);
13208 unsigned ra
= INSTR (14, 10);
13209 unsigned rn
= INSTR (9, 5);
13210 unsigned rd
= INSTR (4, 0);
13212 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13213 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
13214 obtain a 64 bit product. */
13215 aarch64_set_reg_u64
13217 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
13218 + ((uint64_t) aarch64_get_reg_u32 (cpu
, rn
, NO_SP
))
13219 * ((uint64_t) aarch64_get_reg_u32 (cpu
, rm
, NO_SP
)));
13222 /* Unsigned multiply sub long -- source, source2 : 32 bit, source3 : 64 bit. */
13224 umsubl (sim_cpu
*cpu
)
13226 unsigned rm
= INSTR (20, 16);
13227 unsigned ra
= INSTR (14, 10);
13228 unsigned rn
= INSTR (9, 5);
13229 unsigned rd
= INSTR (4, 0);
13231 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13232 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
13233 obtain a 64 bit product. */
13234 aarch64_set_reg_u64
13236 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
13237 - ((uint64_t) aarch64_get_reg_u32 (cpu
, rn
, NO_SP
))
13238 * ((uint64_t) aarch64_get_reg_u32 (cpu
, rm
, NO_SP
)));
13241 /* Unsigned multiply high, source, source2 :
13242 64 bit, dest <-- high 64-bit of result. */
13244 umulh (sim_cpu
*cpu
)
13246 unsigned rm
= INSTR (20, 16);
13247 unsigned rn
= INSTR (9, 5);
13248 unsigned rd
= INSTR (4, 0);
13249 GReg ra
= INSTR (14, 10);
13254 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13255 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
13256 mul64hi (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
),
13257 aarch64_get_reg_u64 (cpu
, rm
, NO_SP
)));
13261 dexDataProc3Source (sim_cpu
*cpu
)
13263 /* assert instr[28,24] == 11011. */
13264 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit (for rd at least)
13265 instr[30,29] = op54 : 00 ==> ok, ow ==> UNALLOC
13266 instr[23,21] = op31 : 111 ==> UNALLOC, o2 ==> ok
13267 instr[15] = o0 : 0/1 ==> ok
13268 instr[23,21:15] ==> op : 0000 ==> MADD, 0001 ==> MSUB, (32/64 bit)
13269 0010 ==> SMADDL, 0011 ==> SMSUBL, (64 bit only)
13270 0100 ==> SMULH, (64 bit only)
13271 1010 ==> UMADDL, 1011 ==> UNSUBL, (64 bit only)
13272 1100 ==> UMULH (64 bit only)
13276 uint32_t size
= INSTR (31, 31);
13277 uint32_t op54
= INSTR (30, 29);
13278 uint32_t op31
= INSTR (23, 21);
13279 uint32_t o0
= INSTR (15, 15);
13296 dispatch
= (op31
<< 1) | o0
;
13300 case 0: madd64 (cpu
); return;
13301 case 1: msub64 (cpu
); return;
13302 case 2: smaddl (cpu
); return;
13303 case 3: smsubl (cpu
); return;
13304 case 4: smulh (cpu
); return;
13305 case 10: umaddl (cpu
); return;
13306 case 11: umsubl (cpu
); return;
13307 case 12: umulh (cpu
); return;
13308 default: HALT_UNALLOC
;
13313 dexDPReg (sim_cpu
*cpu
)
13315 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
13316 assert group == GROUP_DPREG_0101 || group == GROUP_DPREG_1101
13317 bits [28:24:21] of a DPReg are the secondary dispatch vector. */
13318 uint32_t group2
= dispatchDPReg (aarch64_get_instr (cpu
));
13322 case DPREG_LOG_000
:
13323 case DPREG_LOG_001
:
13324 dexLogicalShiftedRegister (cpu
); return;
13326 case DPREG_ADDSHF_010
:
13327 dexAddSubtractShiftedRegister (cpu
); return;
13329 case DPREG_ADDEXT_011
:
13330 dexAddSubtractExtendedRegister (cpu
); return;
13332 case DPREG_ADDCOND_100
:
13334 /* This set bundles a variety of different operations. */
13336 /* 1) add/sub w carry. */
13337 uint32_t mask1
= 0x1FE00000U
;
13338 uint32_t val1
= 0x1A000000U
;
13339 /* 2) cond compare register/immediate. */
13340 uint32_t mask2
= 0x1FE00000U
;
13341 uint32_t val2
= 0x1A400000U
;
13342 /* 3) cond select. */
13343 uint32_t mask3
= 0x1FE00000U
;
13344 uint32_t val3
= 0x1A800000U
;
13345 /* 4) data proc 1/2 source. */
13346 uint32_t mask4
= 0x1FE00000U
;
13347 uint32_t val4
= 0x1AC00000U
;
13349 if ((aarch64_get_instr (cpu
) & mask1
) == val1
)
13350 dexAddSubtractWithCarry (cpu
);
13352 else if ((aarch64_get_instr (cpu
) & mask2
) == val2
)
13355 else if ((aarch64_get_instr (cpu
) & mask3
) == val3
)
13356 dexCondSelect (cpu
);
13358 else if ((aarch64_get_instr (cpu
) & mask4
) == val4
)
13360 /* Bit 30 is clear for data proc 2 source
13361 and set for data proc 1 source. */
13362 if (aarch64_get_instr (cpu
) & (1U << 30))
13363 dexDataProc1Source (cpu
);
13365 dexDataProc2Source (cpu
);
13369 /* Should not reach here. */
13375 case DPREG_3SRC_110
:
13376 dexDataProc3Source (cpu
); return;
13378 case DPREG_UNALLOC_101
:
13381 case DPREG_3SRC_111
:
13382 dexDataProc3Source (cpu
); return;
13385 /* Should never reach here. */
13390 /* Unconditional Branch immediate.
13391 Offset is a PC-relative byte offset in the range +/- 128MiB.
13392 The offset is assumed to be raw from the decode i.e. the
13393 simulator is expected to scale them from word offsets to byte. */
13395 /* Unconditional branch. */
13397 buc (sim_cpu
*cpu
, int32_t offset
)
13399 aarch64_set_next_PC_by_offset (cpu
, offset
);
13402 static unsigned stack_depth
= 0;
13404 /* Unconditional branch and link -- writes return PC to LR. */
13406 bl (sim_cpu
*cpu
, int32_t offset
)
13408 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13409 aarch64_save_LR (cpu
);
13410 aarch64_set_next_PC_by_offset (cpu
, offset
);
13412 if (TRACE_BRANCH_P (cpu
))
13416 " %*scall %" PRIx64
" [%s]"
13417 " [args: %" PRIx64
" %" PRIx64
" %" PRIx64
"]",
13418 stack_depth
, " ", aarch64_get_next_PC (cpu
),
13419 aarch64_get_func (CPU_STATE (cpu
),
13420 aarch64_get_next_PC (cpu
)),
13421 aarch64_get_reg_u64 (cpu
, 0, NO_SP
),
13422 aarch64_get_reg_u64 (cpu
, 1, NO_SP
),
13423 aarch64_get_reg_u64 (cpu
, 2, NO_SP
)
13428 /* Unconditional Branch register.
13429 Branch/return address is in source register. */
13431 /* Unconditional branch. */
13435 unsigned rn
= INSTR (9, 5);
13436 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13437 aarch64_set_next_PC (cpu
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
13440 /* Unconditional branch and link -- writes return PC to LR. */
13444 /* Ensure we read the destination before we write LR. */
13445 uint64_t target
= aarch64_get_reg_u64 (cpu
, INSTR (9, 5), NO_SP
);
13447 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13448 aarch64_save_LR (cpu
);
13449 aarch64_set_next_PC (cpu
, target
);
13451 if (TRACE_BRANCH_P (cpu
))
13455 " %*scall %" PRIx64
" [%s]"
13456 " [args: %" PRIx64
" %" PRIx64
" %" PRIx64
"]",
13457 stack_depth
, " ", aarch64_get_next_PC (cpu
),
13458 aarch64_get_func (CPU_STATE (cpu
),
13459 aarch64_get_next_PC (cpu
)),
13460 aarch64_get_reg_u64 (cpu
, 0, NO_SP
),
13461 aarch64_get_reg_u64 (cpu
, 1, NO_SP
),
13462 aarch64_get_reg_u64 (cpu
, 2, NO_SP
)
13467 /* Return -- assembler will default source to LR this is functionally
13468 equivalent to br but, presumably, unlike br it side effects the
13469 branch predictor. */
13473 unsigned rn
= INSTR (9, 5);
13474 aarch64_set_next_PC (cpu
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
13476 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13477 if (TRACE_BRANCH_P (cpu
))
13480 " %*sreturn [result: %" PRIx64
"]",
13481 stack_depth
, " ", aarch64_get_reg_u64 (cpu
, 0, NO_SP
));
13486 /* NOP -- we implement this and call it from the decode in case we
13487 want to intercept it later. */
13492 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13495 /* Data synchronization barrier. */
13500 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13503 /* Data memory barrier. */
13508 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13511 /* Instruction synchronization barrier. */
13516 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13520 dexBranchImmediate (sim_cpu
*cpu
)
13522 /* assert instr[30,26] == 00101
13523 instr[31] ==> 0 == B, 1 == BL
13524 instr[25,0] == imm26 branch offset counted in words. */
13526 uint32_t top
= INSTR (31, 31);
13527 /* We have a 26 byte signed word offset which we need to pass to the
13528 execute routine as a signed byte offset. */
13529 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 25, 0) << 2;
13537 /* Control Flow. */
13539 /* Conditional branch
13541 Offset is a PC-relative byte offset in the range +/- 1MiB pos is
13542 a bit position in the range 0 .. 63
13544 cc is a CondCode enum value as pulled out of the decode
13546 N.B. any offset register (source) can only be Xn or Wn. */
13549 bcc (sim_cpu
*cpu
, int32_t offset
, CondCode cc
)
13551 /* The test returns TRUE if CC is met. */
13552 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13553 if (testConditionCode (cpu
, cc
))
13554 aarch64_set_next_PC_by_offset (cpu
, offset
);
13557 /* 32 bit branch on register non-zero. */
13559 cbnz32 (sim_cpu
*cpu
, int32_t offset
)
13561 unsigned rt
= INSTR (4, 0);
13563 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13564 if (aarch64_get_reg_u32 (cpu
, rt
, NO_SP
) != 0)
13565 aarch64_set_next_PC_by_offset (cpu
, offset
);
13568 /* 64 bit branch on register zero. */
13570 cbnz (sim_cpu
*cpu
, int32_t offset
)
13572 unsigned rt
= INSTR (4, 0);
13574 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13575 if (aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) != 0)
13576 aarch64_set_next_PC_by_offset (cpu
, offset
);
13579 /* 32 bit branch on register non-zero. */
13581 cbz32 (sim_cpu
*cpu
, int32_t offset
)
13583 unsigned rt
= INSTR (4, 0);
13585 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13586 if (aarch64_get_reg_u32 (cpu
, rt
, NO_SP
) == 0)
13587 aarch64_set_next_PC_by_offset (cpu
, offset
);
13590 /* 64 bit branch on register zero. */
13592 cbz (sim_cpu
*cpu
, int32_t offset
)
13594 unsigned rt
= INSTR (4, 0);
13596 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13597 if (aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) == 0)
13598 aarch64_set_next_PC_by_offset (cpu
, offset
);
13601 /* Branch on register bit test non-zero -- one size fits all. */
13603 tbnz (sim_cpu
*cpu
, uint32_t pos
, int32_t offset
)
13605 unsigned rt
= INSTR (4, 0);
13607 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13608 if (aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) & (((uint64_t) 1) << pos
))
13609 aarch64_set_next_PC_by_offset (cpu
, offset
);
13612 /* Branch on register bit test zero -- one size fits all. */
13614 tbz (sim_cpu
*cpu
, uint32_t pos
, int32_t offset
)
13616 unsigned rt
= INSTR (4, 0);
13618 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13619 if (!(aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) & (((uint64_t) 1) << pos
)))
13620 aarch64_set_next_PC_by_offset (cpu
, offset
);
13624 dexCompareBranchImmediate (sim_cpu
*cpu
)
13626 /* instr[30,25] = 01 1010
13627 instr[31] = size : 0 ==> 32, 1 ==> 64
13628 instr[24] = op : 0 ==> CBZ, 1 ==> CBNZ
13629 instr[23,5] = simm19 branch offset counted in words
13632 uint32_t size
= INSTR (31, 31);
13633 uint32_t op
= INSTR (24, 24);
13634 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 23, 5) << 2;
13639 cbz32 (cpu
, offset
);
13641 cbnz32 (cpu
, offset
);
13648 cbnz (cpu
, offset
);
13653 dexTestBranchImmediate (sim_cpu
*cpu
)
13655 /* instr[31] = b5 : bit 5 of test bit idx
13656 instr[30,25] = 01 1011
13657 instr[24] = op : 0 ==> TBZ, 1 == TBNZ
13658 instr[23,19] = b40 : bits 4 to 0 of test bit idx
13659 instr[18,5] = simm14 : signed offset counted in words
13660 instr[4,0] = uimm5 */
13662 uint32_t pos
= ((INSTR (31, 31) << 5) | INSTR (23, 19));
13663 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 18, 5) << 2;
13665 NYI_assert (30, 25, 0x1b);
13667 if (INSTR (24, 24) == 0)
13668 tbz (cpu
, pos
, offset
);
13670 tbnz (cpu
, pos
, offset
);
13674 dexCondBranchImmediate (sim_cpu
*cpu
)
13676 /* instr[31,25] = 010 1010
13677 instr[24] = op1; op => 00 ==> B.cond
13678 instr[23,5] = simm19 : signed offset counted in words
13680 instr[3,0] = cond */
13683 uint32_t op
= ((INSTR (24, 24) << 1) | INSTR (4, 4));
13685 NYI_assert (31, 25, 0x2a);
13690 offset
= simm32 (aarch64_get_instr (cpu
), 23, 5) << 2;
13692 bcc (cpu
, offset
, INSTR (3, 0));
13696 dexBranchRegister (sim_cpu
*cpu
)
13698 /* instr[31,25] = 110 1011
13699 instr[24,21] = op : 0 ==> BR, 1 => BLR, 2 => RET, 3 => ERET, 4 => DRPS
13700 instr[20,16] = op2 : must be 11111
13701 instr[15,10] = op3 : must be 000000
13702 instr[4,0] = op2 : must be 11111. */
13704 uint32_t op
= INSTR (24, 21);
13705 uint32_t op2
= INSTR (20, 16);
13706 uint32_t op3
= INSTR (15, 10);
13707 uint32_t op4
= INSTR (4, 0);
13709 NYI_assert (31, 25, 0x6b);
13711 if (op2
!= 0x1F || op3
!= 0 || op4
!= 0)
13725 /* ERET and DRPS accept 0b11111 for rn = instr [4,0]. */
13726 /* anything else is unallocated. */
13727 uint32_t rn
= INSTR (4, 0);
13732 if (op
== 4 || op
== 5)
13739 /* FIXME: We should get the Angel SWI values from ../../libgloss/aarch64/svc.h
13740 but this may not be available. So instead we define the values we need
13742 #define AngelSVC_Reason_Open 0x01
13743 #define AngelSVC_Reason_Close 0x02
13744 #define AngelSVC_Reason_Write 0x05
13745 #define AngelSVC_Reason_Read 0x06
13746 #define AngelSVC_Reason_IsTTY 0x09
13747 #define AngelSVC_Reason_Seek 0x0A
13748 #define AngelSVC_Reason_FLen 0x0C
13749 #define AngelSVC_Reason_Remove 0x0E
13750 #define AngelSVC_Reason_Rename 0x0F
13751 #define AngelSVC_Reason_Clock 0x10
13752 #define AngelSVC_Reason_Time 0x11
13753 #define AngelSVC_Reason_System 0x12
13754 #define AngelSVC_Reason_Errno 0x13
13755 #define AngelSVC_Reason_GetCmdLine 0x15
13756 #define AngelSVC_Reason_HeapInfo 0x16
13757 #define AngelSVC_Reason_ReportException 0x18
13758 #define AngelSVC_Reason_Elapsed 0x30
13762 handle_halt (sim_cpu
*cpu
, uint32_t val
)
13764 uint64_t result
= 0;
13766 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13769 TRACE_SYSCALL (cpu
, " HLT [0x%x]", val
);
13770 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13771 sim_stopped
, SIM_SIGTRAP
);
13774 /* We have encountered an Angel SVC call. See if we can process it. */
13775 switch (aarch64_get_reg_u32 (cpu
, 0, NO_SP
))
13777 case AngelSVC_Reason_HeapInfo
:
13779 /* Get the values. */
13780 uint64_t stack_top
= aarch64_get_stack_start (cpu
);
13781 uint64_t heap_base
= aarch64_get_heap_start (cpu
);
13783 /* Get the pointer */
13784 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13785 ptr
= aarch64_get_mem_u64 (cpu
, ptr
);
13787 /* Fill in the memory block. */
13788 /* Start addr of heap. */
13789 aarch64_set_mem_u64 (cpu
, ptr
+ 0, heap_base
);
13790 /* End addr of heap. */
13791 aarch64_set_mem_u64 (cpu
, ptr
+ 8, stack_top
);
13792 /* Lowest stack addr. */
13793 aarch64_set_mem_u64 (cpu
, ptr
+ 16, heap_base
);
13794 /* Initial stack addr. */
13795 aarch64_set_mem_u64 (cpu
, ptr
+ 24, stack_top
);
13797 TRACE_SYSCALL (cpu
, " AngelSVC: Get Heap Info");
13801 case AngelSVC_Reason_Open
:
13803 /* Get the pointer */
13804 /* uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);. */
13805 /* FIXME: For now we just assume that we will only be asked
13806 to open the standard file descriptors. */
13810 TRACE_SYSCALL (cpu
, " AngelSVC: Open file %d", fd
- 1);
13814 case AngelSVC_Reason_Close
:
13816 uint64_t fh
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13817 TRACE_SYSCALL (cpu
, " AngelSVC: Close file %d", (int) fh
);
13822 case AngelSVC_Reason_Errno
:
13824 TRACE_SYSCALL (cpu
, " AngelSVC: Get Errno");
13827 case AngelSVC_Reason_Clock
:
13829 #ifdef CLOCKS_PER_SEC
13830 (CLOCKS_PER_SEC
>= 100)
13831 ? (clock () / (CLOCKS_PER_SEC
/ 100))
13832 : ((clock () * 100) / CLOCKS_PER_SEC
)
13834 /* Presume unix... clock() returns microseconds. */
13838 TRACE_SYSCALL (cpu
, " AngelSVC: Get Clock");
13841 case AngelSVC_Reason_GetCmdLine
:
13843 /* Get the pointer */
13844 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13845 ptr
= aarch64_get_mem_u64 (cpu
, ptr
);
13847 /* FIXME: No command line for now. */
13848 aarch64_set_mem_u64 (cpu
, ptr
, 0);
13849 TRACE_SYSCALL (cpu
, " AngelSVC: Get Command Line");
13853 case AngelSVC_Reason_IsTTY
:
13855 TRACE_SYSCALL (cpu
, " AngelSVC: IsTTY ?");
13858 case AngelSVC_Reason_Write
:
13860 /* Get the pointer */
13861 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13862 /* Get the write control block. */
13863 uint64_t fd
= aarch64_get_mem_u64 (cpu
, ptr
);
13864 uint64_t buf
= aarch64_get_mem_u64 (cpu
, ptr
+ 8);
13865 uint64_t len
= aarch64_get_mem_u64 (cpu
, ptr
+ 16);
13867 TRACE_SYSCALL (cpu
, "write of %" PRIx64
" bytes from %"
13868 PRIx64
" on descriptor %" PRIx64
,
13873 TRACE_SYSCALL (cpu
,
13874 " AngelSVC: Write: Suspiciously long write: %ld",
13876 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13877 sim_stopped
, SIM_SIGBUS
);
13881 printf ("%.*s", (int) len
, aarch64_get_mem_ptr (cpu
, buf
));
13885 TRACE (cpu
, 0, "\n");
13886 sim_io_eprintf (CPU_STATE (cpu
), "%.*s",
13887 (int) len
, aarch64_get_mem_ptr (cpu
, buf
));
13888 TRACE (cpu
, 0, "\n");
13892 TRACE_SYSCALL (cpu
,
13893 " AngelSVC: Write: Unexpected file handle: %d",
13895 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13896 sim_stopped
, SIM_SIGABRT
);
13901 case AngelSVC_Reason_ReportException
:
13903 /* Get the pointer */
13904 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13905 /*ptr = aarch64_get_mem_u64 (cpu, ptr);. */
13906 uint64_t type
= aarch64_get_mem_u64 (cpu
, ptr
);
13907 uint64_t state
= aarch64_get_mem_u64 (cpu
, ptr
+ 8);
13909 TRACE_SYSCALL (cpu
,
13910 "Angel Exception: type 0x%" PRIx64
" state %" PRIx64
,
13913 if (type
== 0x20026)
13914 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13915 sim_exited
, state
);
13917 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13918 sim_stopped
, SIM_SIGINT
);
13922 case AngelSVC_Reason_Read
:
13923 case AngelSVC_Reason_FLen
:
13924 case AngelSVC_Reason_Seek
:
13925 case AngelSVC_Reason_Remove
:
13926 case AngelSVC_Reason_Time
:
13927 case AngelSVC_Reason_System
:
13928 case AngelSVC_Reason_Rename
:
13929 case AngelSVC_Reason_Elapsed
:
13931 TRACE_SYSCALL (cpu
, " HLT [Unknown angel %x]",
13932 aarch64_get_reg_u32 (cpu
, 0, NO_SP
));
13933 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13934 sim_stopped
, SIM_SIGTRAP
);
13937 aarch64_set_reg_u64 (cpu
, 0, NO_SP
, result
);
13941 dexExcpnGen (sim_cpu
*cpu
)
13943 /* instr[31:24] = 11010100
13944 instr[23,21] = opc : 000 ==> GEN EXCPN, 001 ==> BRK
13945 010 ==> HLT, 101 ==> DBG GEN EXCPN
13946 instr[20,5] = imm16
13947 instr[4,2] = opc2 000 ==> OK, ow ==> UNALLOC
13948 instr[1,0] = LL : discriminates opc */
13950 uint32_t opc
= INSTR (23, 21);
13951 uint32_t imm16
= INSTR (20, 5);
13952 uint32_t opc2
= INSTR (4, 2);
13955 NYI_assert (31, 24, 0xd4);
13962 /* We only implement HLT and BRK for now. */
13963 if (opc
== 1 && LL
== 0)
13965 TRACE_EVENTS (cpu
, " BRK [0x%x]", imm16
);
13966 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13967 sim_exited
, aarch64_get_reg_s32 (cpu
, R0
, SP_OK
));
13970 if (opc
== 2 && LL
== 0)
13971 handle_halt (cpu
, imm16
);
13973 else if (opc
== 0 || opc
== 5)
13980 /* Stub for accessing system registers. */
13983 system_get (sim_cpu
*cpu
, unsigned op0
, unsigned op1
, unsigned crn
,
13984 unsigned crm
, unsigned op2
)
13986 if (crn
== 0 && op1
== 3 && crm
== 0 && op2
== 7)
13987 /* DCZID_EL0 - the Data Cache Zero ID register.
13988 We do not support DC ZVA at the moment, so
13989 we return a value with the disable bit set.
13990 We implement support for the DCZID register since
13991 it is used by the C library's memset function. */
13992 return ((uint64_t) 1) << 4;
13994 if (crn
== 0 && op1
== 3 && crm
== 0 && op2
== 1)
13995 /* Cache Type Register. */
13996 return 0x80008000UL
;
13998 if (crn
== 13 && op1
== 3 && crm
== 0 && op2
== 2)
13999 /* TPIDR_EL0 - thread pointer id. */
14000 return aarch64_get_thread_id (cpu
);
14002 if (op1
== 3 && crm
== 4 && op2
== 0)
14003 return aarch64_get_FPCR (cpu
);
14005 if (op1
== 3 && crm
== 4 && op2
== 1)
14006 return aarch64_get_FPSR (cpu
);
14008 else if (op1
== 3 && crm
== 2 && op2
== 0)
14009 return aarch64_get_CPSR (cpu
);
14015 system_set (sim_cpu
*cpu
, unsigned op0
, unsigned op1
, unsigned crn
,
14016 unsigned crm
, unsigned op2
, uint64_t val
)
14018 if (op1
== 3 && crm
== 4 && op2
== 0)
14019 aarch64_set_FPCR (cpu
, val
);
14021 else if (op1
== 3 && crm
== 4 && op2
== 1)
14022 aarch64_set_FPSR (cpu
, val
);
14024 else if (op1
== 3 && crm
== 2 && op2
== 0)
14025 aarch64_set_CPSR (cpu
, val
);
14032 do_mrs (sim_cpu
*cpu
)
14034 /* instr[31:20] = 1101 0101 0001 1
14041 unsigned sys_op0
= INSTR (19, 19) + 2;
14042 unsigned sys_op1
= INSTR (18, 16);
14043 unsigned sys_crn
= INSTR (15, 12);
14044 unsigned sys_crm
= INSTR (11, 8);
14045 unsigned sys_op2
= INSTR (7, 5);
14046 unsigned rt
= INSTR (4, 0);
14048 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
14049 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
14050 system_get (cpu
, sys_op0
, sys_op1
, sys_crn
, sys_crm
, sys_op2
));
14054 do_MSR_immediate (sim_cpu
*cpu
)
14056 /* instr[31:19] = 1101 0101 0000 0
14058 instr[15,12] = 0100
14061 instr[4,0] = 1 1111 */
14063 unsigned op1
= INSTR (18, 16);
14064 /*unsigned crm = INSTR (11, 8);*/
14065 unsigned op2
= INSTR (7, 5);
14067 NYI_assert (31, 19, 0x1AA0);
14068 NYI_assert (15, 12, 0x4);
14069 NYI_assert (4, 0, 0x1F);
14074 HALT_NYI
; /* set SPSel. */
14081 HALT_NYI
; /* set DAIFset. */
14083 HALT_NYI
; /* set DAIFclr. */
14092 do_MSR_reg (sim_cpu
*cpu
)
14094 /* instr[31:20] = 1101 0101 0001
14102 unsigned sys_op0
= INSTR (19, 19) + 2;
14103 unsigned sys_op1
= INSTR (18, 16);
14104 unsigned sys_crn
= INSTR (15, 12);
14105 unsigned sys_crm
= INSTR (11, 8);
14106 unsigned sys_op2
= INSTR (7, 5);
14107 unsigned rt
= INSTR (4, 0);
14109 NYI_assert (31, 20, 0xD51);
14111 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
14112 system_set (cpu
, sys_op0
, sys_op1
, sys_crn
, sys_crm
, sys_op2
,
14113 aarch64_get_reg_u64 (cpu
, rt
, NO_SP
));
14117 do_SYS (sim_cpu
*cpu
)
14119 /* instr[31,19] = 1101 0101 0000 1
14125 NYI_assert (31, 19, 0x1AA1);
14127 /* FIXME: For now we just silently accept system ops. */
14131 dexSystem (sim_cpu
*cpu
)
14133 /* instr[31:22] = 1101 01010 0
14140 instr[4,0] = uimm5 */
14142 /* We are interested in HINT, DSB, DMB and ISB
14144 Hint #0 encodes NOOP (this is the only hint we care about)
14145 L == 0, op0 == 0, op1 = 011, CRn = 0010, Rt = 11111,
14146 CRm op2 != 0000 000 OR CRm op2 == 0000 000 || CRm op > 0000 101
14148 DSB, DMB, ISB are data store barrier, data memory barrier and
14149 instruction store barrier, respectively, where
14151 L == 0, op0 == 0, op1 = 011, CRn = 0011, Rt = 11111,
14152 op2 : DSB ==> 100, DMB ==> 101, ISB ==> 110
14153 CRm<3:2> ==> domain, CRm<1:0> ==> types,
14154 domain : 00 ==> OuterShareable, 01 ==> Nonshareable,
14155 10 ==> InerShareable, 11 ==> FullSystem
14156 types : 01 ==> Reads, 10 ==> Writes,
14157 11 ==> All, 00 ==> All (domain == FullSystem). */
14159 unsigned rt
= INSTR (4, 0);
14161 NYI_assert (31, 22, 0x354);
14163 switch (INSTR (21, 12))
14168 /* NOP has CRm != 0000 OR. */
14169 /* (CRm == 0000 AND (op2 == 000 OR op2 > 101)). */
14170 uint32_t crm
= INSTR (11, 8);
14171 uint32_t op2
= INSTR (7, 5);
14173 if (crm
!= 0 || (op2
== 0 || op2
> 5))
14175 /* Actually call nop method so we can reimplement it later. */
14184 uint32_t op2
= INSTR (7, 5);
14189 case 4: dsb (cpu
); return;
14190 case 5: dmb (cpu
); return;
14191 case 6: isb (cpu
); return;
14192 default: HALT_UNALLOC
;
14203 do_SYS (cpu
); /* DC is an alias of SYS. */
14207 if (INSTR (21, 20) == 0x1)
14209 else if (INSTR (21, 19) == 0 && INSTR (15, 12) == 0x4)
14210 do_MSR_immediate (cpu
);
14218 dexBr (sim_cpu
*cpu
)
14220 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
14221 assert group == GROUP_BREXSYS_1010 || group == GROUP_BREXSYS_1011
14222 bits [31,29] of a BrExSys are the secondary dispatch vector. */
14223 uint32_t group2
= dispatchBrExSys (aarch64_get_instr (cpu
));
14228 return dexBranchImmediate (cpu
);
14230 case BR_IMMCMP_001
:
14231 /* Compare has bit 25 clear while test has it set. */
14232 if (!INSTR (25, 25))
14233 dexCompareBranchImmediate (cpu
);
14235 dexTestBranchImmediate (cpu
);
14238 case BR_IMMCOND_010
:
14239 /* This is a conditional branch if bit 25 is clear otherwise
14241 if (!INSTR (25, 25))
14242 dexCondBranchImmediate (cpu
);
14247 case BR_UNALLOC_011
:
14251 dexBranchImmediate (cpu
);
14254 case BR_IMMCMP_101
:
14255 /* Compare has bit 25 clear while test has it set. */
14256 if (!INSTR (25, 25))
14257 dexCompareBranchImmediate (cpu
);
14259 dexTestBranchImmediate (cpu
);
14263 /* Unconditional branch reg has bit 25 set. */
14264 if (INSTR (25, 25))
14265 dexBranchRegister (cpu
);
14267 /* This includes both Excpn Gen, System and unalloc operations.
14268 We need to decode the Excpn Gen operation BRK so we can plant
14269 debugger entry points.
14270 Excpn Gen operations have instr [24] = 0.
14271 we need to decode at least one of the System operations NOP
14272 which is an alias for HINT #0.
14273 System operations have instr [24,22] = 100. */
14274 else if (INSTR (24, 24) == 0)
14277 else if (INSTR (24, 22) == 4)
14285 case BR_UNALLOC_111
:
14289 /* Should never reach here. */
14295 aarch64_decode_and_execute (sim_cpu
*cpu
, uint64_t pc
)
14297 /* We need to check if gdb wants an in here. */
14298 /* checkBreak (cpu);. */
14300 uint64_t group
= dispatchGroup (aarch64_get_instr (cpu
));
14304 case GROUP_PSEUDO_0000
: dexPseudo (cpu
); break;
14305 case GROUP_LDST_0100
: dexLdSt (cpu
); break;
14306 case GROUP_DPREG_0101
: dexDPReg (cpu
); break;
14307 case GROUP_LDST_0110
: dexLdSt (cpu
); break;
14308 case GROUP_ADVSIMD_0111
: dexAdvSIMD0 (cpu
); break;
14309 case GROUP_DPIMM_1000
: dexDPImm (cpu
); break;
14310 case GROUP_DPIMM_1001
: dexDPImm (cpu
); break;
14311 case GROUP_BREXSYS_1010
: dexBr (cpu
); break;
14312 case GROUP_BREXSYS_1011
: dexBr (cpu
); break;
14313 case GROUP_LDST_1100
: dexLdSt (cpu
); break;
14314 case GROUP_DPREG_1101
: dexDPReg (cpu
); break;
14315 case GROUP_LDST_1110
: dexLdSt (cpu
); break;
14316 case GROUP_ADVSIMD_1111
: dexAdvSIMD1 (cpu
); break;
14318 case GROUP_UNALLOC_0001
:
14319 case GROUP_UNALLOC_0010
:
14320 case GROUP_UNALLOC_0011
:
14324 /* Should never reach here. */
14330 aarch64_step (sim_cpu
*cpu
)
14332 uint64_t pc
= aarch64_get_PC (cpu
);
14334 if (pc
== TOP_LEVEL_RETURN_PC
)
14337 aarch64_set_next_PC (cpu
, pc
+ 4);
14339 /* Code is always little-endian. */
14340 sim_core_read_buffer (CPU_STATE (cpu
), cpu
, read_map
,
14341 & aarch64_get_instr (cpu
), pc
, 4);
14342 aarch64_get_instr (cpu
) = endian_le2h_4 (aarch64_get_instr (cpu
));
14344 TRACE_INSN (cpu
, " pc = %" PRIx64
" instr = %08x", pc
,
14345 aarch64_get_instr (cpu
));
14346 TRACE_DISASM (cpu
, pc
);
14348 aarch64_decode_and_execute (cpu
, pc
);
14354 aarch64_run (SIM_DESC sd
)
14356 sim_cpu
*cpu
= STATE_CPU (sd
, 0);
14358 while (aarch64_step (cpu
))
14360 aarch64_update_PC (cpu
);
14362 if (sim_events_tick (sd
))
14363 sim_events_process (sd
);
14366 sim_engine_halt (sd
, cpu
, NULL
, aarch64_get_PC (cpu
),
14367 sim_exited
, aarch64_get_reg_s32 (cpu
, R0
, NO_SP
));
14371 aarch64_init (sim_cpu
*cpu
, uint64_t pc
)
14373 uint64_t sp
= aarch64_get_stack_start (cpu
);
14375 /* Install SP, FP and PC and set LR to -20
14376 so we can detect a top-level return. */
14377 aarch64_set_reg_u64 (cpu
, SP
, SP_OK
, sp
);
14378 aarch64_set_reg_u64 (cpu
, FP
, SP_OK
, sp
);
14379 aarch64_set_reg_u64 (cpu
, LR
, SP_OK
, TOP_LEVEL_RETURN_PC
);
14380 aarch64_set_next_PC (cpu
, pc
);
14381 aarch64_update_PC (cpu
);
14382 aarch64_init_LIT_table ();