1 /* simulator.c -- Interface for the AArch64 simulator.
3 Copyright (C) 2015-2016 Free Software Foundation, Inc.
5 Contributed by Red Hat.
7 This file is part of GDB.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
26 #include <sys/types.h>
31 #include "simulator.h"
38 #define TST(_flag) (aarch64_test_CPSR_bit (cpu, _flag))
39 #define IS_SET(_X) (TST (( _X )) ? 1 : 0)
40 #define IS_CLEAR(_X) (TST (( _X )) ? 0 : 1)
42 /* Space saver macro. */
43 #define INSTR(HIGH, LOW) uimm (aarch64_get_instr (cpu), (HIGH), (LOW))
45 #define HALT_UNALLOC \
48 TRACE_DISASM (cpu, aarch64_get_PC (cpu)); \
50 "Unallocated instruction detected at sim line %d," \
51 " exe addr %" PRIx64, \
52 __LINE__, aarch64_get_PC (cpu)); \
53 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),\
54 sim_stopped, SIM_SIGILL); \
61 TRACE_DISASM (cpu, aarch64_get_PC (cpu)); \
63 "Unimplemented instruction detected at sim line %d," \
64 " exe addr %" PRIx64, \
65 __LINE__, aarch64_get_PC (cpu)); \
66 if (! TRACE_ANY_P (cpu)) \
68 sim_io_eprintf (CPU_STATE (cpu), "SIM Error: Unimplemented instruction: "); \
69 trace_disasm (CPU_STATE (cpu), cpu, aarch64_get_PC (cpu)); \
71 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),\
72 sim_stopped, SIM_SIGABRT); \
76 #define NYI_assert(HI, LO, EXPECTED) \
79 if (INSTR ((HI), (LO)) != (EXPECTED)) \
84 /* Helper functions used by expandLogicalImmediate. */
86 /* for i = 1, ... N result<i-1> = 1 other bits are zero */
87 static inline uint64_t
90 return (N
== 64 ? (uint64_t)-1UL : ((1UL << N
) - 1));
93 /* result<0> to val<N> */
94 static inline uint64_t
95 pickbit (uint64_t val
, int N
)
97 return pickbits64 (val
, N
, N
);
101 expand_logical_immediate (uint32_t S
, uint32_t R
, uint32_t N
)
107 /* The immediate value is S+1 bits to 1, left rotated by SIMDsize - R
108 (in other words, right rotated by R), then replicated. */
112 mask
= 0xffffffffffffffffull
;
118 case 0x00 ... 0x1f: /* 0xxxxx */ simd_size
= 32; break;
119 case 0x20 ... 0x2f: /* 10xxxx */ simd_size
= 16; S
&= 0xf; break;
120 case 0x30 ... 0x37: /* 110xxx */ simd_size
= 8; S
&= 0x7; break;
121 case 0x38 ... 0x3b: /* 1110xx */ simd_size
= 4; S
&= 0x3; break;
122 case 0x3c ... 0x3d: /* 11110x */ simd_size
= 2; S
&= 0x1; break;
125 mask
= (1ull << simd_size
) - 1;
126 /* Top bits are IGNORED. */
130 /* NOTE: if S = simd_size - 1 we get 0xf..f which is rejected. */
131 if (S
== simd_size
- 1)
134 /* S+1 consecutive bits to 1. */
135 /* NOTE: S can't be 63 due to detection above. */
136 imm
= (1ull << (S
+ 1)) - 1;
138 /* Rotate to the left by simd_size - R. */
140 imm
= ((imm
<< (simd_size
- R
)) & mask
) | (imm
>> R
);
142 /* Replicate the value according to SIMD size. */
145 case 2: imm
= (imm
<< 2) | imm
;
146 case 4: imm
= (imm
<< 4) | imm
;
147 case 8: imm
= (imm
<< 8) | imm
;
148 case 16: imm
= (imm
<< 16) | imm
;
149 case 32: imm
= (imm
<< 32) | imm
;
157 /* Instr[22,10] encodes N immr and imms. we want a lookup table
158 for each possible combination i.e. 13 bits worth of int entries. */
159 #define LI_TABLE_SIZE (1 << 13)
160 static uint64_t LITable
[LI_TABLE_SIZE
];
163 aarch64_init_LIT_table (void)
167 for (index
= 0; index
< LI_TABLE_SIZE
; index
++)
169 uint32_t N
= uimm (index
, 12, 12);
170 uint32_t immr
= uimm (index
, 11, 6);
171 uint32_t imms
= uimm (index
, 5, 0);
173 LITable
[index
] = expand_logical_immediate (imms
, immr
, N
);
178 dexNotify (sim_cpu
*cpu
)
180 /* instr[14,0] == type : 0 ==> method entry, 1 ==> method reentry
181 2 ==> exit Java, 3 ==> start next bytecode. */
182 uint32_t type
= INSTR (14, 0);
184 TRACE_EVENTS (cpu
, "Notify Insn encountered, type = 0x%x", type
);
189 /* aarch64_notifyMethodEntry (aarch64_get_reg_u64 (cpu, R23, 0),
190 aarch64_get_reg_u64 (cpu, R22, 0)); */
193 /* aarch64_notifyMethodReentry (aarch64_get_reg_u64 (cpu, R23, 0),
194 aarch64_get_reg_u64 (cpu, R22, 0)); */
197 /* aarch64_notifyMethodExit (); */
200 /* aarch64_notifyBCStart (aarch64_get_reg_u64 (cpu, R23, 0),
201 aarch64_get_reg_u64 (cpu, R22, 0)); */
206 /* secondary decode within top level groups */
209 dexPseudo (sim_cpu
*cpu
)
211 /* assert instr[28,27] = 00
213 We provide 2 pseudo instructions:
215 HALT stops execution of the simulator causing an immediate
216 return to the x86 code which entered it.
218 CALLOUT initiates recursive entry into x86 code. A register
219 argument holds the address of the x86 routine. Immediate
220 values in the instruction identify the number of general
221 purpose and floating point register arguments to be passed
222 and the type of any value to be returned. */
224 uint32_t PSEUDO_HALT
= 0xE0000000U
;
225 uint32_t PSEUDO_CALLOUT
= 0x00018000U
;
226 uint32_t PSEUDO_CALLOUTR
= 0x00018001U
;
227 uint32_t PSEUDO_NOTIFY
= 0x00014000U
;
230 if (aarch64_get_instr (cpu
) == PSEUDO_HALT
)
232 TRACE_EVENTS (cpu
, " Pseudo Halt Instruction");
233 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
234 sim_stopped
, SIM_SIGTRAP
);
237 dispatch
= INSTR (31, 15);
239 /* We do not handle callouts at the moment. */
240 if (dispatch
== PSEUDO_CALLOUT
|| dispatch
== PSEUDO_CALLOUTR
)
242 TRACE_EVENTS (cpu
, " Callout");
243 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
244 sim_stopped
, SIM_SIGABRT
);
247 else if (dispatch
== PSEUDO_NOTIFY
)
254 /* Load-store single register (unscaled offset)
255 These instructions employ a base register plus an unscaled signed
258 N.B. the base register (source) can be Xn or SP. all other
259 registers may not be SP. */
261 /* 32 bit load 32 bit unscaled signed 9 bit. */
263 ldur32 (sim_cpu
*cpu
, int32_t offset
)
265 unsigned rn
= INSTR (9, 5);
266 unsigned rt
= INSTR (4, 0);
268 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
269 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u32
270 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
274 /* 64 bit load 64 bit unscaled signed 9 bit. */
276 ldur64 (sim_cpu
*cpu
, int32_t offset
)
278 unsigned rn
= INSTR (9, 5);
279 unsigned rt
= INSTR (4, 0);
281 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
282 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u64
283 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
287 /* 32 bit load zero-extended byte unscaled signed 9 bit. */
289 ldurb32 (sim_cpu
*cpu
, int32_t offset
)
291 unsigned rn
= INSTR (9, 5);
292 unsigned rt
= INSTR (4, 0);
294 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
295 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u8
296 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
300 /* 32 bit load sign-extended byte unscaled signed 9 bit. */
302 ldursb32 (sim_cpu
*cpu
, int32_t offset
)
304 unsigned rn
= INSTR (9, 5);
305 unsigned rt
= INSTR (4, 0);
307 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
308 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, (uint32_t) aarch64_get_mem_s8
309 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
313 /* 64 bit load sign-extended byte unscaled signed 9 bit. */
315 ldursb64 (sim_cpu
*cpu
, int32_t offset
)
317 unsigned rn
= INSTR (9, 5);
318 unsigned rt
= INSTR (4, 0);
320 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
321 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, aarch64_get_mem_s8
322 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
326 /* 32 bit load zero-extended short unscaled signed 9 bit */
328 ldurh32 (sim_cpu
*cpu
, int32_t offset
)
330 unsigned rn
= INSTR (9, 5);
331 unsigned rd
= INSTR (4, 0);
333 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
334 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, aarch64_get_mem_u16
335 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
339 /* 32 bit load sign-extended short unscaled signed 9 bit */
341 ldursh32 (sim_cpu
*cpu
, int32_t offset
)
343 unsigned rn
= INSTR (9, 5);
344 unsigned rd
= INSTR (4, 0);
346 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
347 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) aarch64_get_mem_s16
348 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
352 /* 64 bit load sign-extended short unscaled signed 9 bit */
354 ldursh64 (sim_cpu
*cpu
, int32_t offset
)
356 unsigned rn
= INSTR (9, 5);
357 unsigned rt
= INSTR (4, 0);
359 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
360 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, aarch64_get_mem_s16
361 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
365 /* 64 bit load sign-extended word unscaled signed 9 bit */
367 ldursw (sim_cpu
*cpu
, int32_t offset
)
369 unsigned rn
= INSTR (9, 5);
370 unsigned rd
= INSTR (4, 0);
372 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
373 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) aarch64_get_mem_s32
374 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
378 /* N.B. with stores the value in source is written to the address
379 identified by source2 modified by offset. */
381 /* 32 bit store 32 bit unscaled signed 9 bit. */
383 stur32 (sim_cpu
*cpu
, int32_t offset
)
385 unsigned rn
= INSTR (9, 5);
386 unsigned rd
= INSTR (4, 0);
388 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
389 aarch64_set_mem_u32 (cpu
,
390 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
391 aarch64_get_reg_u32 (cpu
, rd
, NO_SP
));
394 /* 64 bit store 64 bit unscaled signed 9 bit */
396 stur64 (sim_cpu
*cpu
, int32_t offset
)
398 unsigned rn
= INSTR (9, 5);
399 unsigned rd
= INSTR (4, 0);
401 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
402 aarch64_set_mem_u64 (cpu
,
403 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
404 aarch64_get_reg_u64 (cpu
, rd
, NO_SP
));
407 /* 32 bit store byte unscaled signed 9 bit */
409 sturb (sim_cpu
*cpu
, int32_t offset
)
411 unsigned rn
= INSTR (9, 5);
412 unsigned rd
= INSTR (4, 0);
414 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
415 aarch64_set_mem_u8 (cpu
,
416 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
417 aarch64_get_reg_u8 (cpu
, rd
, NO_SP
));
420 /* 32 bit store short unscaled signed 9 bit */
422 sturh (sim_cpu
*cpu
, int32_t offset
)
424 unsigned rn
= INSTR (9, 5);
425 unsigned rd
= INSTR (4, 0);
427 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
428 aarch64_set_mem_u16 (cpu
,
429 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
430 aarch64_get_reg_u16 (cpu
, rd
, NO_SP
));
433 /* Load single register pc-relative label
434 Offset is a signed 19 bit immediate count in words
437 /* 32 bit pc-relative load */
439 ldr32_pcrel (sim_cpu
*cpu
, int32_t offset
)
441 unsigned rd
= INSTR (4, 0);
443 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
444 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
446 (cpu
, aarch64_get_PC (cpu
) + offset
* 4));
449 /* 64 bit pc-relative load */
451 ldr_pcrel (sim_cpu
*cpu
, int32_t offset
)
453 unsigned rd
= INSTR (4, 0);
455 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
456 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
458 (cpu
, aarch64_get_PC (cpu
) + offset
* 4));
461 /* sign extended 32 bit pc-relative load */
463 ldrsw_pcrel (sim_cpu
*cpu
, int32_t offset
)
465 unsigned rd
= INSTR (4, 0);
467 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
468 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
470 (cpu
, aarch64_get_PC (cpu
) + offset
* 4));
473 /* float pc-relative load */
475 fldrs_pcrel (sim_cpu
*cpu
, int32_t offset
)
477 unsigned int rd
= INSTR (4, 0);
479 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
480 aarch64_set_vec_u32 (cpu
, rd
, 0,
482 (cpu
, aarch64_get_PC (cpu
) + offset
* 4));
485 /* double pc-relative load */
487 fldrd_pcrel (sim_cpu
*cpu
, int32_t offset
)
489 unsigned int st
= INSTR (4, 0);
491 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
492 aarch64_set_vec_u64 (cpu
, st
, 0,
494 (cpu
, aarch64_get_PC (cpu
) + offset
* 4));
497 /* long double pc-relative load. */
499 fldrq_pcrel (sim_cpu
*cpu
, int32_t offset
)
501 unsigned int st
= INSTR (4, 0);
502 uint64_t addr
= aarch64_get_PC (cpu
) + offset
* 4;
505 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
506 aarch64_get_mem_long_double (cpu
, addr
, & a
);
507 aarch64_set_FP_long_double (cpu
, st
, a
);
510 /* This can be used to scale an offset by applying
511 the requisite shift. the second argument is either
514 #define SCALE(_offset, _elementSize) \
515 ((_offset) << ScaleShift ## _elementSize)
517 /* This can be used to optionally scale a register derived offset
518 by applying the requisite shift as indicated by the Scaling
519 argument. The second argument is either Byte, Short, Word
520 or Long. The third argument is either Scaled or Unscaled.
521 N.B. when _Scaling is Scaled the shift gets ANDed with
522 all 1s while when it is Unscaled it gets ANDed with 0. */
524 #define OPT_SCALE(_offset, _elementType, _Scaling) \
525 ((_offset) << (_Scaling ? ScaleShift ## _elementType : 0))
527 /* This can be used to zero or sign extend a 32 bit register derived
528 value to a 64 bit value. the first argument must be the value as
529 a uint32_t and the second must be either UXTW or SXTW. The result
530 is returned as an int64_t. */
532 static inline int64_t
533 extend (uint32_t value
, Extension extension
)
541 /* A branchless variant of this ought to be possible. */
542 if (extension
== UXTW
|| extension
== NoExtension
)
549 /* Scalar Floating Point
551 FP load/store single register (4 addressing modes)
553 N.B. the base register (source) can be the stack pointer.
554 The secondary source register (source2) can only be an Xn register. */
556 /* Load 32 bit unscaled signed 9 bit with pre- or post-writeback. */
558 fldrs_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
560 unsigned rn
= INSTR (9, 5);
561 unsigned st
= INSTR (4, 0);
562 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
567 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
568 aarch64_set_vec_u32 (cpu
, st
, 0, aarch64_get_mem_u32 (cpu
, address
));
572 if (wb
!= NoWriteBack
)
573 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
576 /* Load 8 bit with unsigned 12 bit offset. */
578 fldrb_abs (sim_cpu
*cpu
, uint32_t offset
)
580 unsigned rd
= INSTR (4, 0);
581 unsigned rn
= INSTR (9, 5);
582 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
;
584 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
585 aarch64_set_vec_u8 (cpu
, rd
, 0, aarch64_get_mem_u32 (cpu
, addr
));
588 /* Load 16 bit scaled unsigned 12 bit. */
590 fldrh_abs (sim_cpu
*cpu
, uint32_t offset
)
592 unsigned rd
= INSTR (4, 0);
593 unsigned rn
= INSTR (9, 5);
594 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 16);
596 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
597 aarch64_set_vec_u16 (cpu
, rd
, 0, aarch64_get_mem_u16 (cpu
, addr
));
600 /* Load 32 bit scaled unsigned 12 bit. */
602 fldrs_abs (sim_cpu
*cpu
, uint32_t offset
)
604 unsigned rd
= INSTR (4, 0);
605 unsigned rn
= INSTR (9, 5);
606 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 32);
608 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
609 aarch64_set_vec_u32 (cpu
, rd
, 0, aarch64_get_mem_u32 (cpu
, addr
));
612 /* Load 64 bit scaled unsigned 12 bit. */
614 fldrd_abs (sim_cpu
*cpu
, uint32_t offset
)
616 unsigned rd
= INSTR (4, 0);
617 unsigned rn
= INSTR (9, 5);
618 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 64);
620 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
621 aarch64_set_vec_u64 (cpu
, rd
, 0, aarch64_get_mem_u64 (cpu
, addr
));
624 /* Load 128 bit scaled unsigned 12 bit. */
626 fldrq_abs (sim_cpu
*cpu
, uint32_t offset
)
628 unsigned rd
= INSTR (4, 0);
629 unsigned rn
= INSTR (9, 5);
630 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 128);
632 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
633 aarch64_set_vec_u64 (cpu
, rd
, 0, aarch64_get_mem_u64 (cpu
, addr
));
634 aarch64_set_vec_u64 (cpu
, rd
, 1, aarch64_get_mem_u64 (cpu
, addr
+ 8));
637 /* Load 32 bit scaled or unscaled zero- or sign-extended
638 32-bit register offset. */
640 fldrs_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
642 unsigned rm
= INSTR (20, 16);
643 unsigned rn
= INSTR (9, 5);
644 unsigned st
= INSTR (4, 0);
645 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
646 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
647 uint64_t displacement
= OPT_SCALE (extended
, 32, scaling
);
649 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
650 aarch64_set_vec_u32 (cpu
, st
, 0, aarch64_get_mem_u32
651 (cpu
, address
+ displacement
));
654 /* Load 64 bit unscaled signed 9 bit with pre- or post-writeback. */
656 fldrd_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
658 unsigned rn
= INSTR (9, 5);
659 unsigned st
= INSTR (4, 0);
660 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
665 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
666 aarch64_set_vec_u64 (cpu
, st
, 0, aarch64_get_mem_u64 (cpu
, address
));
671 if (wb
!= NoWriteBack
)
672 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
675 /* Load 64 bit scaled or unscaled zero- or sign-extended 32-bit register offset. */
677 fldrd_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
679 unsigned rm
= INSTR (20, 16);
680 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
681 uint64_t displacement
= OPT_SCALE (extended
, 64, scaling
);
683 fldrd_wb (cpu
, displacement
, NoWriteBack
);
686 /* Load 128 bit unscaled signed 9 bit with pre- or post-writeback. */
688 fldrq_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
691 unsigned rn
= INSTR (9, 5);
692 unsigned st
= INSTR (4, 0);
693 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
698 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
699 aarch64_get_mem_long_double (cpu
, address
, & a
);
700 aarch64_set_FP_long_double (cpu
, st
, a
);
705 if (wb
!= NoWriteBack
)
706 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
709 /* Load 128 bit scaled or unscaled zero- or sign-extended 32-bit register offset */
711 fldrq_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
713 unsigned rm
= INSTR (20, 16);
714 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
715 uint64_t displacement
= OPT_SCALE (extended
, 128, scaling
);
717 fldrq_wb (cpu
, displacement
, NoWriteBack
);
722 load-store single register
723 There are four addressing modes available here which all employ a
724 64 bit source (base) register.
726 N.B. the base register (source) can be the stack pointer.
727 The secondary source register (source2)can only be an Xn register.
729 Scaled, 12-bit, unsigned immediate offset, without pre- and
731 Unscaled, 9-bit, signed immediate offset with pre- or post-index
733 scaled or unscaled 64-bit register offset.
734 scaled or unscaled 32-bit extended register offset.
736 All offsets are assumed to be raw from the decode i.e. the
737 simulator is expected to adjust scaled offsets based on the
738 accessed data size with register or extended register offset
739 versions the same applies except that in the latter case the
740 operation may also require a sign extend.
742 A separate method is provided for each possible addressing mode. */
744 /* 32 bit load 32 bit scaled unsigned 12 bit */
746 ldr32_abs (sim_cpu
*cpu
, uint32_t offset
)
748 unsigned rn
= INSTR (9, 5);
749 unsigned rt
= INSTR (4, 0);
751 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
752 /* The target register may not be SP but the source may be. */
753 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u32
754 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
755 + SCALE (offset
, 32)));
758 /* 32 bit load 32 bit unscaled signed 9 bit with pre- or post-writeback. */
760 ldr32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
762 unsigned rn
= INSTR (9, 5);
763 unsigned rt
= INSTR (4, 0);
766 if (rn
== rt
&& wb
!= NoWriteBack
)
769 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
774 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
775 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u32 (cpu
, address
));
780 if (wb
!= NoWriteBack
)
781 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
784 /* 32 bit load 32 bit scaled or unscaled
785 zero- or sign-extended 32-bit register offset */
787 ldr32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
789 unsigned rm
= INSTR (20, 16);
790 unsigned rn
= INSTR (9, 5);
791 unsigned rt
= INSTR (4, 0);
792 /* rn may reference SP, rm and rt must reference ZR */
794 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
795 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
796 uint64_t displacement
= OPT_SCALE (extended
, 32, scaling
);
798 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
799 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
800 aarch64_get_mem_u32 (cpu
, address
+ displacement
));
803 /* 64 bit load 64 bit scaled unsigned 12 bit */
805 ldr_abs (sim_cpu
*cpu
, uint32_t offset
)
807 unsigned rn
= INSTR (9, 5);
808 unsigned rt
= INSTR (4, 0);
810 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
811 /* The target register may not be SP but the source may be. */
812 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u64
813 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
814 + SCALE (offset
, 64)));
817 /* 64 bit load 64 bit unscaled signed 9 bit with pre- or post-writeback. */
819 ldr_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
821 unsigned rn
= INSTR (9, 5);
822 unsigned rt
= INSTR (4, 0);
825 if (rn
== rt
&& wb
!= NoWriteBack
)
828 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
833 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
834 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u64 (cpu
, address
));
839 if (wb
!= NoWriteBack
)
840 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
843 /* 64 bit load 64 bit scaled or unscaled zero-
844 or sign-extended 32-bit register offset. */
846 ldr_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
848 unsigned rm
= INSTR (20, 16);
849 unsigned rn
= INSTR (9, 5);
850 unsigned rt
= INSTR (4, 0);
851 /* rn may reference SP, rm and rt must reference ZR */
853 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
854 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
855 uint64_t displacement
= OPT_SCALE (extended
, 64, scaling
);
857 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
858 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
859 aarch64_get_mem_u64 (cpu
, address
+ displacement
));
862 /* 32 bit load zero-extended byte scaled unsigned 12 bit. */
864 ldrb32_abs (sim_cpu
*cpu
, uint32_t offset
)
866 unsigned rn
= INSTR (9, 5);
867 unsigned rt
= INSTR (4, 0);
869 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
870 /* The target register may not be SP but the source may be
871 there is no scaling required for a byte load. */
872 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
874 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
));
877 /* 32 bit load zero-extended byte unscaled signed 9 bit with pre- or post-writeback. */
879 ldrb32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
881 unsigned rn
= INSTR (9, 5);
882 unsigned rt
= INSTR (4, 0);
885 if (rn
== rt
&& wb
!= NoWriteBack
)
888 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
893 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
894 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u8 (cpu
, address
));
899 if (wb
!= NoWriteBack
)
900 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
903 /* 32 bit load zero-extended byte scaled or unscaled zero-
904 or sign-extended 32-bit register offset. */
906 ldrb32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
908 unsigned rm
= INSTR (20, 16);
909 unsigned rn
= INSTR (9, 5);
910 unsigned rt
= INSTR (4, 0);
911 /* rn may reference SP, rm and rt must reference ZR */
913 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
914 int64_t displacement
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
917 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
918 /* There is no scaling required for a byte load. */
919 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
920 aarch64_get_mem_u8 (cpu
, address
+ displacement
));
923 /* 64 bit load sign-extended byte unscaled signed 9 bit
924 with pre- or post-writeback. */
926 ldrsb_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
928 unsigned rn
= INSTR (9, 5);
929 unsigned rt
= INSTR (4, 0);
933 if (rn
== rt
&& wb
!= NoWriteBack
)
936 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
941 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
942 val
= aarch64_get_mem_s8 (cpu
, address
);
943 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, val
);
948 if (wb
!= NoWriteBack
)
949 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
952 /* 64 bit load sign-extended byte scaled unsigned 12 bit. */
954 ldrsb_abs (sim_cpu
*cpu
, uint32_t offset
)
956 ldrsb_wb (cpu
, offset
, NoWriteBack
);
959 /* 64 bit load sign-extended byte scaled or unscaled zero-
960 or sign-extended 32-bit register offset. */
962 ldrsb_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
964 unsigned rm
= INSTR (20, 16);
965 unsigned rn
= INSTR (9, 5);
966 unsigned rt
= INSTR (4, 0);
967 /* rn may reference SP, rm and rt must reference ZR */
969 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
970 int64_t displacement
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
972 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
973 /* There is no scaling required for a byte load. */
974 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
,
975 aarch64_get_mem_s8 (cpu
, address
+ displacement
));
978 /* 32 bit load zero-extended short scaled unsigned 12 bit. */
980 ldrh32_abs (sim_cpu
*cpu
, uint32_t offset
)
982 unsigned rn
= INSTR (9, 5);
983 unsigned rt
= INSTR (4, 0);
986 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
987 /* The target register may not be SP but the source may be. */
988 val
= aarch64_get_mem_u16 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
989 + SCALE (offset
, 16));
990 aarch64_set_reg_u32 (cpu
, rt
, NO_SP
, val
);
993 /* 32 bit load zero-extended short unscaled signed 9 bit
994 with pre- or post-writeback. */
996 ldrh32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
998 unsigned rn
= INSTR (9, 5);
999 unsigned rt
= INSTR (4, 0);
1002 if (rn
== rt
&& wb
!= NoWriteBack
)
1005 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1010 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1011 aarch64_set_reg_u32 (cpu
, rt
, NO_SP
, aarch64_get_mem_u16 (cpu
, address
));
1016 if (wb
!= NoWriteBack
)
1017 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1020 /* 32 bit load zero-extended short scaled or unscaled zero-
1021 or sign-extended 32-bit register offset. */
1023 ldrh32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1025 unsigned rm
= INSTR (20, 16);
1026 unsigned rn
= INSTR (9, 5);
1027 unsigned rt
= INSTR (4, 0);
1028 /* rn may reference SP, rm and rt must reference ZR */
1030 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1031 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
1032 uint64_t displacement
= OPT_SCALE (extended
, 16, scaling
);
1034 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1035 aarch64_set_reg_u32 (cpu
, rt
, NO_SP
,
1036 aarch64_get_mem_u16 (cpu
, address
+ displacement
));
1039 /* 32 bit load sign-extended short scaled unsigned 12 bit. */
1041 ldrsh32_abs (sim_cpu
*cpu
, uint32_t offset
)
1043 unsigned rn
= INSTR (9, 5);
1044 unsigned rt
= INSTR (4, 0);
1047 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1048 /* The target register may not be SP but the source may be. */
1049 val
= aarch64_get_mem_s16 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
1050 + SCALE (offset
, 16));
1051 aarch64_set_reg_s32 (cpu
, rt
, NO_SP
, val
);
1054 /* 32 bit load sign-extended short unscaled signed 9 bit
1055 with pre- or post-writeback. */
1057 ldrsh32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1059 unsigned rn
= INSTR (9, 5);
1060 unsigned rt
= INSTR (4, 0);
1063 if (rn
== rt
&& wb
!= NoWriteBack
)
1066 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1071 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1072 aarch64_set_reg_s32 (cpu
, rt
, NO_SP
,
1073 (int32_t) aarch64_get_mem_s16 (cpu
, address
));
1078 if (wb
!= NoWriteBack
)
1079 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1082 /* 32 bit load sign-extended short scaled or unscaled zero-
1083 or sign-extended 32-bit register offset. */
1085 ldrsh32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1087 unsigned rm
= INSTR (20, 16);
1088 unsigned rn
= INSTR (9, 5);
1089 unsigned rt
= INSTR (4, 0);
1090 /* rn may reference SP, rm and rt must reference ZR */
1092 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1093 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
1094 uint64_t displacement
= OPT_SCALE (extended
, 16, scaling
);
1096 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1097 aarch64_set_reg_s32 (cpu
, rt
, NO_SP
,
1098 (int32_t) aarch64_get_mem_s16
1099 (cpu
, address
+ displacement
));
1102 /* 64 bit load sign-extended short scaled unsigned 12 bit. */
1104 ldrsh_abs (sim_cpu
*cpu
, uint32_t offset
)
1106 unsigned rn
= INSTR (9, 5);
1107 unsigned rt
= INSTR (4, 0);
1110 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1111 /* The target register may not be SP but the source may be. */
1112 val
= aarch64_get_mem_s16 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
1113 + SCALE (offset
, 16));
1114 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, val
);
1117 /* 64 bit load sign-extended short unscaled signed 9 bit
1118 with pre- or post-writeback. */
1120 ldrsh64_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1122 unsigned rn
= INSTR (9, 5);
1123 unsigned rt
= INSTR (4, 0);
1127 if (rn
== rt
&& wb
!= NoWriteBack
)
1130 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1131 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1136 val
= aarch64_get_mem_s16 (cpu
, address
);
1137 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, val
);
1142 if (wb
!= NoWriteBack
)
1143 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1146 /* 64 bit load sign-extended short scaled or unscaled zero-
1147 or sign-extended 32-bit register offset. */
1149 ldrsh_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1151 unsigned rm
= INSTR (20, 16);
1152 unsigned rn
= INSTR (9, 5);
1153 unsigned rt
= INSTR (4, 0);
1155 /* rn may reference SP, rm and rt must reference ZR */
1157 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1158 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
1159 uint64_t displacement
= OPT_SCALE (extended
, 16, scaling
);
1162 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1163 val
= aarch64_get_mem_s16 (cpu
, address
+ displacement
);
1164 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, val
);
1167 /* 64 bit load sign-extended 32 bit scaled unsigned 12 bit. */
1169 ldrsw_abs (sim_cpu
*cpu
, uint32_t offset
)
1171 unsigned rn
= INSTR (9, 5);
1172 unsigned rt
= INSTR (4, 0);
1175 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1176 val
= aarch64_get_mem_s32 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
1177 + SCALE (offset
, 32));
1178 /* The target register may not be SP but the source may be. */
1179 return aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, val
);
1182 /* 64 bit load sign-extended 32 bit unscaled signed 9 bit
1183 with pre- or post-writeback. */
1185 ldrsw_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1187 unsigned rn
= INSTR (9, 5);
1188 unsigned rt
= INSTR (4, 0);
1191 if (rn
== rt
&& wb
!= NoWriteBack
)
1194 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1199 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1200 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, aarch64_get_mem_s32 (cpu
, address
));
1205 if (wb
!= NoWriteBack
)
1206 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1209 /* 64 bit load sign-extended 32 bit scaled or unscaled zero-
1210 or sign-extended 32-bit register offset. */
1212 ldrsw_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1214 unsigned rm
= INSTR (20, 16);
1215 unsigned rn
= INSTR (9, 5);
1216 unsigned rt
= INSTR (4, 0);
1217 /* rn may reference SP, rm and rt must reference ZR */
1219 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1220 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
1221 uint64_t displacement
= OPT_SCALE (extended
, 32, scaling
);
1223 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1224 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
,
1225 aarch64_get_mem_s32 (cpu
, address
+ displacement
));
1228 /* N.B. with stores the value in source is written to the
1229 address identified by source2 modified by source3/offset. */
1231 /* 32 bit store scaled unsigned 12 bit. */
1233 str32_abs (sim_cpu
*cpu
, uint32_t offset
)
1235 unsigned rn
= INSTR (9, 5);
1236 unsigned rt
= INSTR (4, 0);
1238 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1239 /* The target register may not be SP but the source may be. */
1240 aarch64_set_mem_u32 (cpu
, (aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
1241 + SCALE (offset
, 32)),
1242 aarch64_get_reg_u32 (cpu
, rt
, NO_SP
));
1245 /* 32 bit store unscaled signed 9 bit with pre- or post-writeback. */
1247 str32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1249 unsigned rn
= INSTR (9, 5);
1250 unsigned rt
= INSTR (4, 0);
1253 if (rn
== rt
&& wb
!= NoWriteBack
)
1256 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1260 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1261 aarch64_set_mem_u32 (cpu
, address
, aarch64_get_reg_u32 (cpu
, rt
, NO_SP
));
1266 if (wb
!= NoWriteBack
)
1267 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1270 /* 32 bit store scaled or unscaled zero- or
1271 sign-extended 32-bit register offset. */
1273 str32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1275 unsigned rm
= INSTR (20, 16);
1276 unsigned rn
= INSTR (9, 5);
1277 unsigned rt
= INSTR (4, 0);
1279 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1280 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
1281 uint64_t displacement
= OPT_SCALE (extended
, 32, scaling
);
1283 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1284 aarch64_set_mem_u32 (cpu
, address
+ displacement
,
1285 aarch64_get_reg_u64 (cpu
, rt
, NO_SP
));
1288 /* 64 bit store scaled unsigned 12 bit. */
1290 str_abs (sim_cpu
*cpu
, uint32_t offset
)
1292 unsigned rn
= INSTR (9, 5);
1293 unsigned rt
= INSTR (4, 0);
1295 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1296 aarch64_set_mem_u64 (cpu
,
1297 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
1298 + SCALE (offset
, 64),
1299 aarch64_get_reg_u64 (cpu
, rt
, NO_SP
));
1302 /* 64 bit store unscaled signed 9 bit with pre- or post-writeback. */
1304 str_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1306 unsigned rn
= INSTR (9, 5);
1307 unsigned rt
= INSTR (4, 0);
1310 if (rn
== rt
&& wb
!= NoWriteBack
)
1313 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1318 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1319 aarch64_set_mem_u64 (cpu
, address
, aarch64_get_reg_u64 (cpu
, rt
, NO_SP
));
1324 if (wb
!= NoWriteBack
)
1325 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1328 /* 64 bit store scaled or unscaled zero-
1329 or sign-extended 32-bit register offset. */
1331 str_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1333 unsigned rm
= INSTR (20, 16);
1334 unsigned rn
= INSTR (9, 5);
1335 unsigned rt
= INSTR (4, 0);
1336 /* rn may reference SP, rm and rt must reference ZR */
1338 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1339 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
1341 uint64_t displacement
= OPT_SCALE (extended
, 64, scaling
);
1343 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1344 aarch64_set_mem_u64 (cpu
, address
+ displacement
,
1345 aarch64_get_reg_u64 (cpu
, rt
, NO_SP
));
1348 /* 32 bit store byte scaled unsigned 12 bit. */
1350 strb_abs (sim_cpu
*cpu
, uint32_t offset
)
1352 unsigned rn
= INSTR (9, 5);
1353 unsigned rt
= INSTR (4, 0);
1355 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1356 /* The target register may not be SP but the source may be.
1357 There is no scaling required for a byte load. */
1358 aarch64_set_mem_u8 (cpu
,
1359 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
1360 aarch64_get_reg_u8 (cpu
, rt
, NO_SP
));
1363 /* 32 bit store byte unscaled signed 9 bit with pre- or post-writeback. */
1365 strb_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1367 unsigned rn
= INSTR (9, 5);
1368 unsigned rt
= INSTR (4, 0);
1371 if (rn
== rt
&& wb
!= NoWriteBack
)
1374 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1379 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1380 aarch64_set_mem_u8 (cpu
, address
, aarch64_get_reg_u8 (cpu
, rt
, NO_SP
));
1385 if (wb
!= NoWriteBack
)
1386 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1389 /* 32 bit store byte scaled or unscaled zero-
1390 or sign-extended 32-bit register offset. */
1392 strb_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1394 unsigned rm
= INSTR (20, 16);
1395 unsigned rn
= INSTR (9, 5);
1396 unsigned rt
= INSTR (4, 0);
1397 /* rn may reference SP, rm and rt must reference ZR */
1399 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1400 int64_t displacement
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
1403 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1404 /* There is no scaling required for a byte load. */
1405 aarch64_set_mem_u8 (cpu
, address
+ displacement
,
1406 aarch64_get_reg_u8 (cpu
, rt
, NO_SP
));
1409 /* 32 bit store short scaled unsigned 12 bit. */
1411 strh_abs (sim_cpu
*cpu
, uint32_t offset
)
1413 unsigned rn
= INSTR (9, 5);
1414 unsigned rt
= INSTR (4, 0);
1416 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1417 /* The target register may not be SP but the source may be. */
1418 aarch64_set_mem_u16 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
1419 + SCALE (offset
, 16),
1420 aarch64_get_reg_u16 (cpu
, rt
, NO_SP
));
1423 /* 32 bit store short unscaled signed 9 bit with pre- or post-writeback. */
1425 strh_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1427 unsigned rn
= INSTR (9, 5);
1428 unsigned rt
= INSTR (4, 0);
1431 if (rn
== rt
&& wb
!= NoWriteBack
)
1434 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1439 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1440 aarch64_set_mem_u16 (cpu
, address
, aarch64_get_reg_u16 (cpu
, rt
, NO_SP
));
1445 if (wb
!= NoWriteBack
)
1446 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1449 /* 32 bit store short scaled or unscaled zero-
1450 or sign-extended 32-bit register offset. */
1452 strh_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1454 unsigned rm
= INSTR (20, 16);
1455 unsigned rn
= INSTR (9, 5);
1456 unsigned rt
= INSTR (4, 0);
1457 /* rn may reference SP, rm and rt must reference ZR */
1459 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1460 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
1461 uint64_t displacement
= OPT_SCALE (extended
, 16, scaling
);
1463 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1464 aarch64_set_mem_u16 (cpu
, address
+ displacement
,
1465 aarch64_get_reg_u16 (cpu
, rt
, NO_SP
));
1468 /* Prefetch unsigned 12 bit. */
1470 prfm_abs (sim_cpu
*cpu
, uint32_t offset
)
1472 /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1473 00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1474 00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1475 10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1476 10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1477 10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1479 PrfOp prfop = prfop (instr, 4, 0);
1480 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK)
1481 + SCALE (offset, 64). */
1483 /* TODO : implement prefetch of address. */
1486 /* Prefetch scaled or unscaled zero- or sign-extended 32-bit register offset. */
1488 prfm_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1490 /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1491 00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1492 00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1493 10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1494 10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1495 10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1497 rn may reference SP, rm may only reference ZR
1498 PrfOp prfop = prfop (instr, 4, 0);
1499 uint64_t base = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1500 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1502 uint64_t displacement = OPT_SCALE (extended, 64, scaling);
1503 uint64_t address = base + displacement. */
1505 /* TODO : implement prefetch of address */
1508 /* 64 bit pc-relative prefetch. */
1510 prfm_pcrel (sim_cpu
*cpu
, int32_t offset
)
1512 /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1513 00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1514 00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1515 10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1516 10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1517 10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1519 PrfOp prfop = prfop (instr, 4, 0);
1520 uint64_t address = aarch64_get_PC (cpu) + offset. */
1522 /* TODO : implement this */
1525 /* Load-store exclusive. */
1530 unsigned rn
= INSTR (9, 5);
1531 unsigned rt
= INSTR (4, 0);
1532 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1533 int size
= INSTR (31, 30);
1534 /* int ordered = INSTR (15, 15); */
1535 /* int exclusive = ! INSTR (23, 23); */
1537 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1541 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u8 (cpu
, address
));
1544 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u16 (cpu
, address
));
1547 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u32 (cpu
, address
));
1550 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u64 (cpu
, address
));
1558 unsigned rn
= INSTR (9, 5);
1559 unsigned rt
= INSTR (4, 0);
1560 unsigned rs
= INSTR (20, 16);
1561 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1562 int size
= INSTR (31, 30);
1563 uint64_t data
= aarch64_get_reg_u64 (cpu
, rt
, NO_SP
);
1567 case 0: aarch64_set_mem_u8 (cpu
, address
, data
); break;
1568 case 1: aarch64_set_mem_u16 (cpu
, address
, data
); break;
1569 case 2: aarch64_set_mem_u32 (cpu
, address
, data
); break;
1570 case 3: aarch64_set_mem_u64 (cpu
, address
, data
); break;
1573 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1574 aarch64_set_reg_u64 (cpu
, rs
, NO_SP
, 0); /* Always exclusive... */
1578 dexLoadLiteral (sim_cpu
*cpu
)
1580 /* instr[29,27] == 011
1582 instr[31,30:26] = opc: 000 ==> LDRW, 001 ==> FLDRS
1583 010 ==> LDRX, 011 ==> FLDRD
1584 100 ==> LDRSW, 101 ==> FLDRQ
1585 110 ==> PRFM, 111 ==> UNALLOC
1586 instr[26] ==> V : 0 ==> GReg, 1 ==> FReg
1587 instr[23, 5] == simm19 */
1589 /* unsigned rt = INSTR (4, 0); */
1590 uint32_t dispatch
= (INSTR (31, 30) << 1) | INSTR (26, 26);
1591 int32_t imm
= simm32 (aarch64_get_instr (cpu
), 23, 5);
1595 case 0: ldr32_pcrel (cpu
, imm
); break;
1596 case 1: fldrs_pcrel (cpu
, imm
); break;
1597 case 2: ldr_pcrel (cpu
, imm
); break;
1598 case 3: fldrd_pcrel (cpu
, imm
); break;
1599 case 4: ldrsw_pcrel (cpu
, imm
); break;
1600 case 5: fldrq_pcrel (cpu
, imm
); break;
1601 case 6: prfm_pcrel (cpu
, imm
); break;
1608 /* Immediate arithmetic
1609 The aimm argument is a 12 bit unsigned value or a 12 bit unsigned
1610 value left shifted by 12 bits (done at decode).
1612 N.B. the register args (dest, source) can normally be Xn or SP.
1613 the exception occurs for flag setting instructions which may
1614 only use Xn for the output (dest). */
1616 /* 32 bit add immediate. */
1618 add32 (sim_cpu
*cpu
, uint32_t aimm
)
1620 unsigned rn
= INSTR (9, 5);
1621 unsigned rd
= INSTR (4, 0);
1623 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1624 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
1625 aarch64_get_reg_u32 (cpu
, rn
, SP_OK
) + aimm
);
1628 /* 64 bit add immediate. */
1630 add64 (sim_cpu
*cpu
, uint32_t aimm
)
1632 unsigned rn
= INSTR (9, 5);
1633 unsigned rd
= INSTR (4, 0);
1635 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1636 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
1637 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + aimm
);
1641 set_flags_for_add32 (sim_cpu
*cpu
, int32_t value1
, int32_t value2
)
1643 int32_t result
= value1
+ value2
;
1644 int64_t sresult
= (int64_t) value1
+ (int64_t) value2
;
1645 uint64_t uresult
= (uint64_t)(uint32_t) value1
1646 + (uint64_t)(uint32_t) value2
;
1652 if (result
& (1 << 31))
1655 if (uresult
!= result
)
1658 if (sresult
!= result
)
1661 aarch64_set_CPSR (cpu
, flags
);
1665 set_flags_for_add64 (sim_cpu
*cpu
, uint64_t value1
, uint64_t value2
)
1667 int64_t sval1
= value1
;
1668 int64_t sval2
= value2
;
1669 uint64_t result
= value1
+ value2
;
1670 int64_t sresult
= sval1
+ sval2
;
1676 if (result
& (1ULL << 63))
1683 /* Negative plus a negative. Overflow happens if
1684 the result is greater than either of the operands. */
1685 if (sresult
> sval1
|| sresult
> sval2
)
1688 /* else Negative plus a positive. Overflow cannot happen. */
1690 else /* value1 is +ve. */
1694 /* Overflow can only occur if we computed "0 - MININT". */
1695 if (sval1
== 0 && sval2
== (1LL << 63))
1700 /* Postive plus positive - overflow has happened if the
1701 result is smaller than either of the operands. */
1702 if (result
< value1
|| result
< value2
)
1707 aarch64_set_CPSR (cpu
, flags
);
1710 #define NEG(a) (((a) & signbit) == signbit)
1711 #define POS(a) (((a) & signbit) == 0)
1714 set_flags_for_sub32 (sim_cpu
*cpu
, uint32_t value1
, uint32_t value2
)
1716 uint32_t result
= value1
- value2
;
1718 uint32_t signbit
= 1U << 31;
1726 if ( (NEG (value1
) && POS (value2
))
1727 || (NEG (value1
) && POS (result
))
1728 || (POS (value2
) && POS (result
)))
1731 if ( (NEG (value1
) && POS (value2
) && POS (result
))
1732 || (POS (value1
) && NEG (value2
) && NEG (result
)))
1735 aarch64_set_CPSR (cpu
, flags
);
1739 set_flags_for_sub64 (sim_cpu
*cpu
, uint64_t value1
, uint64_t value2
)
1741 uint64_t result
= value1
- value2
;
1743 uint64_t signbit
= 1ULL << 63;
1751 if ( (NEG (value1
) && POS (value2
))
1752 || (NEG (value1
) && POS (result
))
1753 || (POS (value2
) && POS (result
)))
1756 if ( (NEG (value1
) && POS (value2
) && POS (result
))
1757 || (POS (value1
) && NEG (value2
) && NEG (result
)))
1760 aarch64_set_CPSR (cpu
, flags
);
1764 set_flags_for_binop32 (sim_cpu
*cpu
, uint32_t result
)
1773 if (result
& (1 << 31))
1778 aarch64_set_CPSR (cpu
, flags
);
1782 set_flags_for_binop64 (sim_cpu
*cpu
, uint64_t result
)
1791 if (result
& (1ULL << 63))
1796 aarch64_set_CPSR (cpu
, flags
);
1799 /* 32 bit add immediate set flags. */
1801 adds32 (sim_cpu
*cpu
, uint32_t aimm
)
1803 unsigned rn
= INSTR (9, 5);
1804 unsigned rd
= INSTR (4, 0);
1805 /* TODO : do we need to worry about signs here? */
1806 int32_t value1
= aarch64_get_reg_s32 (cpu
, rn
, SP_OK
);
1808 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1809 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ aimm
);
1810 set_flags_for_add32 (cpu
, value1
, aimm
);
1813 /* 64 bit add immediate set flags. */
1815 adds64 (sim_cpu
*cpu
, uint32_t aimm
)
1817 unsigned rn
= INSTR (9, 5);
1818 unsigned rd
= INSTR (4, 0);
1819 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1820 uint64_t value2
= aimm
;
1822 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1823 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
);
1824 set_flags_for_add64 (cpu
, value1
, value2
);
1827 /* 32 bit sub immediate. */
1829 sub32 (sim_cpu
*cpu
, uint32_t aimm
)
1831 unsigned rn
= INSTR (9, 5);
1832 unsigned rd
= INSTR (4, 0);
1834 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1835 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
1836 aarch64_get_reg_u32 (cpu
, rn
, SP_OK
) - aimm
);
1839 /* 64 bit sub immediate. */
1841 sub64 (sim_cpu
*cpu
, uint32_t aimm
)
1843 unsigned rn
= INSTR (9, 5);
1844 unsigned rd
= INSTR (4, 0);
1846 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1847 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
1848 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) - aimm
);
1851 /* 32 bit sub immediate set flags. */
1853 subs32 (sim_cpu
*cpu
, uint32_t aimm
)
1855 unsigned rn
= INSTR (9, 5);
1856 unsigned rd
= INSTR (4, 0);
1857 uint32_t value1
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1858 uint32_t value2
= aimm
;
1860 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1861 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
1862 set_flags_for_sub32 (cpu
, value1
, value2
);
1865 /* 64 bit sub immediate set flags. */
1867 subs64 (sim_cpu
*cpu
, uint32_t aimm
)
1869 unsigned rn
= INSTR (9, 5);
1870 unsigned rd
= INSTR (4, 0);
1871 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1872 uint32_t value2
= aimm
;
1874 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1875 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
1876 set_flags_for_sub64 (cpu
, value1
, value2
);
1879 /* Data Processing Register. */
1881 /* First two helpers to perform the shift operations. */
1883 static inline uint32_t
1884 shifted32 (uint32_t value
, Shift shift
, uint32_t count
)
1890 return (value
<< count
);
1892 return (value
>> count
);
1895 int32_t svalue
= value
;
1896 return (svalue
>> count
);
1900 uint32_t top
= value
>> count
;
1901 uint32_t bottom
= value
<< (32 - count
);
1902 return (bottom
| top
);
1907 static inline uint64_t
1908 shifted64 (uint64_t value
, Shift shift
, uint32_t count
)
1914 return (value
<< count
);
1916 return (value
>> count
);
1919 int64_t svalue
= value
;
1920 return (svalue
>> count
);
1924 uint64_t top
= value
>> count
;
1925 uint64_t bottom
= value
<< (64 - count
);
1926 return (bottom
| top
);
1931 /* Arithmetic shifted register.
1932 These allow an optional LSL, ASR or LSR to the second source
1933 register with a count up to the register bit count.
1935 N.B register args may not be SP. */
1937 /* 32 bit ADD shifted register. */
1939 add32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1941 unsigned rm
= INSTR (20, 16);
1942 unsigned rn
= INSTR (9, 5);
1943 unsigned rd
= INSTR (4, 0);
1945 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1946 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
1947 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
1948 + shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
1952 /* 64 bit ADD shifted register. */
1954 add64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1956 unsigned rm
= INSTR (20, 16);
1957 unsigned rn
= INSTR (9, 5);
1958 unsigned rd
= INSTR (4, 0);
1960 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1961 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
1962 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
1963 + shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
1967 /* 32 bit ADD shifted register setting flags. */
1969 adds32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1971 unsigned rm
= INSTR (20, 16);
1972 unsigned rn
= INSTR (9, 5);
1973 unsigned rd
= INSTR (4, 0);
1975 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
1976 uint32_t value2
= shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
1979 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1980 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
);
1981 set_flags_for_add32 (cpu
, value1
, value2
);
1984 /* 64 bit ADD shifted register setting flags. */
1986 adds64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1988 unsigned rm
= INSTR (20, 16);
1989 unsigned rn
= INSTR (9, 5);
1990 unsigned rd
= INSTR (4, 0);
1992 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
1993 uint64_t value2
= shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
1996 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1997 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
);
1998 set_flags_for_add64 (cpu
, value1
, value2
);
2001 /* 32 bit SUB shifted register. */
2003 sub32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
2005 unsigned rm
= INSTR (20, 16);
2006 unsigned rn
= INSTR (9, 5);
2007 unsigned rd
= INSTR (4, 0);
2009 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2010 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
2011 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
2012 - shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
2016 /* 64 bit SUB shifted register. */
2018 sub64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
2020 unsigned rm
= INSTR (20, 16);
2021 unsigned rn
= INSTR (9, 5);
2022 unsigned rd
= INSTR (4, 0);
2024 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2025 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
2026 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
2027 - shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
2031 /* 32 bit SUB shifted register setting flags. */
2033 subs32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
2035 unsigned rm
= INSTR (20, 16);
2036 unsigned rn
= INSTR (9, 5);
2037 unsigned rd
= INSTR (4, 0);
2039 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
2040 uint32_t value2
= shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
2043 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2044 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
2045 set_flags_for_sub32 (cpu
, value1
, value2
);
2048 /* 64 bit SUB shifted register setting flags. */
2050 subs64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
2052 unsigned rm
= INSTR (20, 16);
2053 unsigned rn
= INSTR (9, 5);
2054 unsigned rd
= INSTR (4, 0);
2056 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
2057 uint64_t value2
= shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
2060 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2061 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
2062 set_flags_for_sub64 (cpu
, value1
, value2
);
2065 /* First a couple more helpers to fetch the
2066 relevant source register element either
2067 sign or zero extended as required by the
2071 extreg32 (sim_cpu
*cpu
, unsigned int lo
, Extension extension
)
2075 case UXTB
: return aarch64_get_reg_u8 (cpu
, lo
, NO_SP
);
2076 case UXTH
: return aarch64_get_reg_u16 (cpu
, lo
, NO_SP
);
2077 case UXTW
: /* Fall through. */
2078 case UXTX
: return aarch64_get_reg_u32 (cpu
, lo
, NO_SP
);
2079 case SXTB
: return aarch64_get_reg_s8 (cpu
, lo
, NO_SP
);
2080 case SXTH
: return aarch64_get_reg_s16 (cpu
, lo
, NO_SP
);
2081 case SXTW
: /* Fall through. */
2082 case SXTX
: /* Fall through. */
2083 default: return aarch64_get_reg_s32 (cpu
, lo
, NO_SP
);
2088 extreg64 (sim_cpu
*cpu
, unsigned int lo
, Extension extension
)
2092 case UXTB
: return aarch64_get_reg_u8 (cpu
, lo
, NO_SP
);
2093 case UXTH
: return aarch64_get_reg_u16 (cpu
, lo
, NO_SP
);
2094 case UXTW
: return aarch64_get_reg_u32 (cpu
, lo
, NO_SP
);
2095 case UXTX
: return aarch64_get_reg_u64 (cpu
, lo
, NO_SP
);
2096 case SXTB
: return aarch64_get_reg_s8 (cpu
, lo
, NO_SP
);
2097 case SXTH
: return aarch64_get_reg_s16 (cpu
, lo
, NO_SP
);
2098 case SXTW
: return aarch64_get_reg_s32 (cpu
, lo
, NO_SP
);
2100 default: return aarch64_get_reg_s64 (cpu
, lo
, NO_SP
);
2104 /* Arithmetic extending register
2105 These allow an optional sign extension of some portion of the
2106 second source register followed by an optional left shift of
2107 between 1 and 4 bits (i.e. a shift of 0-4 bits???)
2109 N.B output (dest) and first input arg (source) may normally be Xn
2110 or SP. However, for flag setting operations dest can only be
2111 Xn. Second input registers are always Xn. */
2113 /* 32 bit ADD extending register. */
2115 add32_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2117 unsigned rm
= INSTR (20, 16);
2118 unsigned rn
= INSTR (9, 5);
2119 unsigned rd
= INSTR (4, 0);
2121 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2122 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
2123 aarch64_get_reg_u32 (cpu
, rn
, SP_OK
)
2124 + (extreg32 (cpu
, rm
, extension
) << shift
));
2127 /* 64 bit ADD extending register.
2128 N.B. This subsumes the case with 64 bit source2 and UXTX #n or LSL #0. */
2130 add64_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2132 unsigned rm
= INSTR (20, 16);
2133 unsigned rn
= INSTR (9, 5);
2134 unsigned rd
= INSTR (4, 0);
2136 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2137 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
2138 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
2139 + (extreg64 (cpu
, rm
, extension
) << shift
));
2142 /* 32 bit ADD extending register setting flags. */
2144 adds32_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2146 unsigned rm
= INSTR (20, 16);
2147 unsigned rn
= INSTR (9, 5);
2148 unsigned rd
= INSTR (4, 0);
2150 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, SP_OK
);
2151 uint32_t value2
= extreg32 (cpu
, rm
, extension
) << shift
;
2153 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2154 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
);
2155 set_flags_for_add32 (cpu
, value1
, value2
);
2158 /* 64 bit ADD extending register setting flags */
2159 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0 */
2161 adds64_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2163 unsigned rm
= INSTR (20, 16);
2164 unsigned rn
= INSTR (9, 5);
2165 unsigned rd
= INSTR (4, 0);
2167 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
2168 uint64_t value2
= extreg64 (cpu
, rm
, extension
) << shift
;
2170 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2171 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
);
2172 set_flags_for_add64 (cpu
, value1
, value2
);
2175 /* 32 bit SUB extending register. */
2177 sub32_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2179 unsigned rm
= INSTR (20, 16);
2180 unsigned rn
= INSTR (9, 5);
2181 unsigned rd
= INSTR (4, 0);
2183 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2184 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
2185 aarch64_get_reg_u32 (cpu
, rn
, SP_OK
)
2186 - (extreg32 (cpu
, rm
, extension
) << shift
));
2189 /* 64 bit SUB extending register. */
2190 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0. */
2192 sub64_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2194 unsigned rm
= INSTR (20, 16);
2195 unsigned rn
= INSTR (9, 5);
2196 unsigned rd
= INSTR (4, 0);
2198 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2199 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
2200 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
2201 - (extreg64 (cpu
, rm
, extension
) << shift
));
2204 /* 32 bit SUB extending register setting flags. */
2206 subs32_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2208 unsigned rm
= INSTR (20, 16);
2209 unsigned rn
= INSTR (9, 5);
2210 unsigned rd
= INSTR (4, 0);
2212 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, SP_OK
);
2213 uint32_t value2
= extreg32 (cpu
, rm
, extension
) << shift
;
2215 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2216 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
2217 set_flags_for_sub32 (cpu
, value1
, value2
);
2220 /* 64 bit SUB extending register setting flags */
2221 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0 */
2223 subs64_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2225 unsigned rm
= INSTR (20, 16);
2226 unsigned rn
= INSTR (9, 5);
2227 unsigned rd
= INSTR (4, 0);
2229 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
2230 uint64_t value2
= extreg64 (cpu
, rm
, extension
) << shift
;
2232 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2233 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
2234 set_flags_for_sub64 (cpu
, value1
, value2
);
2238 dexAddSubtractImmediate (sim_cpu
*cpu
)
2240 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2241 instr[30] = op : 0 ==> ADD, 1 ==> SUB
2242 instr[29] = set : 0 ==> no flags, 1 ==> set flags
2243 instr[28,24] = 10001
2244 instr[23,22] = shift : 00 == LSL#0, 01 = LSL#12 1x = UNALLOC
2245 instr[21,10] = uimm12
2249 /* N.B. the shift is applied at decode before calling the add/sub routine. */
2250 uint32_t shift
= INSTR (23, 22);
2251 uint32_t imm
= INSTR (21, 10);
2252 uint32_t dispatch
= INSTR (31, 29);
2254 NYI_assert (28, 24, 0x11);
2264 case 0: add32 (cpu
, imm
); break;
2265 case 1: adds32 (cpu
, imm
); break;
2266 case 2: sub32 (cpu
, imm
); break;
2267 case 3: subs32 (cpu
, imm
); break;
2268 case 4: add64 (cpu
, imm
); break;
2269 case 5: adds64 (cpu
, imm
); break;
2270 case 6: sub64 (cpu
, imm
); break;
2271 case 7: subs64 (cpu
, imm
); break;
2276 dexAddSubtractShiftedRegister (sim_cpu
*cpu
)
2278 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2279 instr[30,29] = op : 00 ==> ADD, 01 ==> ADDS, 10 ==> SUB, 11 ==> SUBS
2280 instr[28,24] = 01011
2281 instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> UNALLOC
2284 instr[15,10] = count : must be 0xxxxx for 32 bit
2288 uint32_t size
= INSTR (31, 31);
2289 uint32_t count
= INSTR (15, 10);
2290 Shift shiftType
= INSTR (23, 22);
2292 NYI_assert (28, 24, 0x0B);
2293 NYI_assert (21, 21, 0);
2295 /* Shift encoded as ROR is unallocated. */
2296 if (shiftType
== ROR
)
2299 /* 32 bit operations must have count[5] = 0
2300 or else we have an UNALLOC. */
2301 if (size
== 0 && uimm (count
, 5, 5))
2304 /* Dispatch on size:op i.e instr [31,29]. */
2305 switch (INSTR (31, 29))
2307 case 0: add32_shift (cpu
, shiftType
, count
); break;
2308 case 1: adds32_shift (cpu
, shiftType
, count
); break;
2309 case 2: sub32_shift (cpu
, shiftType
, count
); break;
2310 case 3: subs32_shift (cpu
, shiftType
, count
); break;
2311 case 4: add64_shift (cpu
, shiftType
, count
); break;
2312 case 5: adds64_shift (cpu
, shiftType
, count
); break;
2313 case 6: sub64_shift (cpu
, shiftType
, count
); break;
2314 case 7: subs64_shift (cpu
, shiftType
, count
); break;
2319 dexAddSubtractExtendedRegister (sim_cpu
*cpu
)
2321 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2322 instr[30] = op : 0 ==> ADD, 1 ==> SUB
2323 instr[29] = set? : 0 ==> no flags, 1 ==> set flags
2324 instr[28,24] = 01011
2325 instr[23,22] = opt : 0 ==> ok, 1,2,3 ==> UNALLOC
2328 instr[15,13] = option : 000 ==> UXTB, 001 ==> UXTH,
2329 000 ==> LSL|UXTW, 001 ==> UXTZ,
2330 000 ==> SXTB, 001 ==> SXTH,
2331 000 ==> SXTW, 001 ==> SXTX,
2332 instr[12,10] = shift : 0,1,2,3,4 ==> ok, 5,6,7 ==> UNALLOC
2336 Extension extensionType
= INSTR (15, 13);
2337 uint32_t shift
= INSTR (12, 10);
2339 NYI_assert (28, 24, 0x0B);
2340 NYI_assert (21, 21, 1);
2342 /* Shift may not exceed 4. */
2346 /* Dispatch on size:op:set?. */
2347 switch (INSTR (31, 29))
2349 case 0: add32_ext (cpu
, extensionType
, shift
); break;
2350 case 1: adds32_ext (cpu
, extensionType
, shift
); break;
2351 case 2: sub32_ext (cpu
, extensionType
, shift
); break;
2352 case 3: subs32_ext (cpu
, extensionType
, shift
); break;
2353 case 4: add64_ext (cpu
, extensionType
, shift
); break;
2354 case 5: adds64_ext (cpu
, extensionType
, shift
); break;
2355 case 6: sub64_ext (cpu
, extensionType
, shift
); break;
2356 case 7: subs64_ext (cpu
, extensionType
, shift
); break;
2360 /* Conditional data processing
2361 Condition register is implicit 3rd source. */
2363 /* 32 bit add with carry. */
2364 /* N.B register args may not be SP. */
2367 adc32 (sim_cpu
*cpu
)
2369 unsigned rm
= INSTR (20, 16);
2370 unsigned rn
= INSTR (9, 5);
2371 unsigned rd
= INSTR (4, 0);
2373 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2374 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
2375 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
2376 + aarch64_get_reg_u32 (cpu
, rm
, NO_SP
)
2380 /* 64 bit add with carry */
2382 adc64 (sim_cpu
*cpu
)
2384 unsigned rm
= INSTR (20, 16);
2385 unsigned rn
= INSTR (9, 5);
2386 unsigned rd
= INSTR (4, 0);
2388 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2389 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
2390 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
2391 + aarch64_get_reg_u64 (cpu
, rm
, NO_SP
)
2395 /* 32 bit add with carry setting flags. */
2397 adcs32 (sim_cpu
*cpu
)
2399 unsigned rm
= INSTR (20, 16);
2400 unsigned rn
= INSTR (9, 5);
2401 unsigned rd
= INSTR (4, 0);
2403 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
2404 uint32_t value2
= aarch64_get_reg_u32 (cpu
, rm
, NO_SP
);
2405 uint32_t carry
= IS_SET (C
);
2407 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2408 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
+ carry
);
2409 set_flags_for_add32 (cpu
, value1
, value2
+ carry
);
2412 /* 64 bit add with carry setting flags. */
2414 adcs64 (sim_cpu
*cpu
)
2416 unsigned rm
= INSTR (20, 16);
2417 unsigned rn
= INSTR (9, 5);
2418 unsigned rd
= INSTR (4, 0);
2420 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
2421 uint64_t value2
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
2422 uint64_t carry
= IS_SET (C
);
2424 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2425 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
+ carry
);
2426 set_flags_for_add64 (cpu
, value1
, value2
+ carry
);
2429 /* 32 bit sub with carry. */
2431 sbc32 (sim_cpu
*cpu
)
2433 unsigned rm
= INSTR (20, 16);
2434 unsigned rn
= INSTR (9, 5); /* ngc iff rn == 31. */
2435 unsigned rd
= INSTR (4, 0);
2437 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2438 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
2439 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
2440 - aarch64_get_reg_u32 (cpu
, rm
, NO_SP
)
2444 /* 64 bit sub with carry */
2446 sbc64 (sim_cpu
*cpu
)
2448 unsigned rm
= INSTR (20, 16);
2449 unsigned rn
= INSTR (9, 5);
2450 unsigned rd
= INSTR (4, 0);
2452 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2453 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
2454 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
2455 - aarch64_get_reg_u64 (cpu
, rm
, NO_SP
)
2459 /* 32 bit sub with carry setting flags */
2461 sbcs32 (sim_cpu
*cpu
)
2463 unsigned rm
= INSTR (20, 16);
2464 unsigned rn
= INSTR (9, 5);
2465 unsigned rd
= INSTR (4, 0);
2467 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
2468 uint32_t value2
= aarch64_get_reg_u32 (cpu
, rm
, NO_SP
);
2469 uint32_t carry
= IS_SET (C
);
2470 uint32_t result
= value1
- value2
+ 1 - carry
;
2472 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2473 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
2474 set_flags_for_sub32 (cpu
, value1
, value2
+ 1 - carry
);
2477 /* 64 bit sub with carry setting flags */
2479 sbcs64 (sim_cpu
*cpu
)
2481 unsigned rm
= INSTR (20, 16);
2482 unsigned rn
= INSTR (9, 5);
2483 unsigned rd
= INSTR (4, 0);
2485 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
2486 uint64_t value2
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
2487 uint64_t carry
= IS_SET (C
);
2488 uint64_t result
= value1
- value2
+ 1 - carry
;
2490 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2491 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
2492 set_flags_for_sub64 (cpu
, value1
, value2
+ 1 - carry
);
2496 dexAddSubtractWithCarry (sim_cpu
*cpu
)
2498 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2499 instr[30] = op : 0 ==> ADC, 1 ==> SBC
2500 instr[29] = set? : 0 ==> no flags, 1 ==> set flags
2501 instr[28,21] = 1 1010 000
2503 instr[15,10] = op2 : 00000 ==> ok, ow ==> UNALLOC
2507 uint32_t op2
= INSTR (15, 10);
2509 NYI_assert (28, 21, 0xD0);
2514 /* Dispatch on size:op:set?. */
2515 switch (INSTR (31, 29))
2517 case 0: adc32 (cpu
); break;
2518 case 1: adcs32 (cpu
); break;
2519 case 2: sbc32 (cpu
); break;
2520 case 3: sbcs32 (cpu
); break;
2521 case 4: adc64 (cpu
); break;
2522 case 5: adcs64 (cpu
); break;
2523 case 6: sbc64 (cpu
); break;
2524 case 7: sbcs64 (cpu
); break;
2529 testConditionCode (sim_cpu
*cpu
, CondCode cc
)
2531 /* This should be reduceable to branchless logic
2532 by some careful testing of bits in CC followed
2533 by the requisite masking and combining of bits
2534 from the flag register.
2536 For now we do it with a switch. */
2541 case EQ
: res
= IS_SET (Z
); break;
2542 case NE
: res
= IS_CLEAR (Z
); break;
2543 case CS
: res
= IS_SET (C
); break;
2544 case CC
: res
= IS_CLEAR (C
); break;
2545 case MI
: res
= IS_SET (N
); break;
2546 case PL
: res
= IS_CLEAR (N
); break;
2547 case VS
: res
= IS_SET (V
); break;
2548 case VC
: res
= IS_CLEAR (V
); break;
2549 case HI
: res
= IS_SET (C
) && IS_CLEAR (Z
); break;
2550 case LS
: res
= IS_CLEAR (C
) || IS_SET (Z
); break;
2551 case GE
: res
= IS_SET (N
) == IS_SET (V
); break;
2552 case LT
: res
= IS_SET (N
) != IS_SET (V
); break;
2553 case GT
: res
= IS_CLEAR (Z
) && (IS_SET (N
) == IS_SET (V
)); break;
2554 case LE
: res
= IS_SET (Z
) || (IS_SET (N
) != IS_SET (V
)); break;
2565 CondCompare (sim_cpu
*cpu
) /* aka: ccmp and ccmn */
2567 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2568 instr[30] = compare with positive (1) or negative value (0)
2569 instr[29,21] = 1 1101 0010
2570 instr[20,16] = Rm or const
2572 instr[11] = compare reg (0) or const (1)
2576 instr[3,0] = value for CPSR bits if the comparison does not take place. */
2581 NYI_assert (29, 21, 0x1d2);
2582 NYI_assert (10, 10, 0);
2583 NYI_assert (4, 4, 0);
2585 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2586 if (! testConditionCode (cpu
, INSTR (15, 12)))
2588 aarch64_set_CPSR (cpu
, INSTR (3, 0));
2592 negate
= INSTR (30, 30) ? 1 : -1;
2593 rm
= INSTR (20, 16);
2599 set_flags_for_sub64 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
),
2600 negate
* (uint64_t) rm
);
2602 set_flags_for_sub64 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
),
2603 negate
* aarch64_get_reg_u64 (cpu
, rm
, SP_OK
));
2608 set_flags_for_sub32 (cpu
, aarch64_get_reg_u32 (cpu
, rn
, SP_OK
),
2611 set_flags_for_sub32 (cpu
, aarch64_get_reg_u32 (cpu
, rn
, SP_OK
),
2612 negate
* aarch64_get_reg_u32 (cpu
, rm
, SP_OK
));
2617 do_vec_MOV_whole_vector (sim_cpu
*cpu
)
2619 /* MOV Vd.T, Vs.T (alias for ORR Vd.T, Vn.T, Vm.T where Vn == Vm)
2622 instr[30] = half(0)/full(1)
2623 instr[29,21] = 001110101
2625 instr[15,10] = 000111
2629 unsigned vs
= INSTR (9, 5);
2630 unsigned vd
= INSTR (4, 0);
2632 NYI_assert (29, 21, 0x075);
2633 NYI_assert (15, 10, 0x07);
2635 if (INSTR (20, 16) != vs
)
2638 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2640 aarch64_set_vec_u64 (cpu
, vd
, 1, aarch64_get_vec_u64 (cpu
, vs
, 1));
2642 aarch64_set_vec_u64 (cpu
, vd
, 0, aarch64_get_vec_u64 (cpu
, vs
, 0));
2646 do_vec_MOV_into_scalar (sim_cpu
*cpu
)
2649 instr[30] = word(0)/long(1)
2650 instr[29,21] = 00 1110 000
2651 instr[20,18] = element size and index
2652 instr[17,10] = 00 0011 11
2653 instr[9,5] = V source
2654 instr[4,0] = R dest */
2656 unsigned vs
= INSTR (9, 5);
2657 unsigned rd
= INSTR (4, 0);
2659 NYI_assert (29, 21, 0x070);
2660 NYI_assert (17, 10, 0x0F);
2662 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2663 switch (INSTR (20, 18))
2666 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, aarch64_get_vec_u64 (cpu
, vs
, 0));
2670 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, aarch64_get_vec_u64 (cpu
, vs
, 1));
2677 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, aarch64_get_vec_u32
2678 (cpu
, vs
, INSTR (20, 19)));
2687 do_vec_INS (sim_cpu
*cpu
)
2689 /* instr[31,21] = 01001110000
2690 instr[20,16] = element size and index
2691 instr[15,10] = 000111
2692 instr[9,5] = W source
2693 instr[4,0] = V dest */
2696 unsigned rs
= INSTR (9, 5);
2697 unsigned vd
= INSTR (4, 0);
2699 NYI_assert (31, 21, 0x270);
2700 NYI_assert (15, 10, 0x07);
2702 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2705 index
= INSTR (20, 17);
2706 aarch64_set_vec_u8 (cpu
, vd
, index
,
2707 aarch64_get_reg_u8 (cpu
, rs
, NO_SP
));
2709 else if (INSTR (17, 17))
2711 index
= INSTR (20, 18);
2712 aarch64_set_vec_u16 (cpu
, vd
, index
,
2713 aarch64_get_reg_u16 (cpu
, rs
, NO_SP
));
2715 else if (INSTR (18, 18))
2717 index
= INSTR (20, 19);
2718 aarch64_set_vec_u32 (cpu
, vd
, index
,
2719 aarch64_get_reg_u32 (cpu
, rs
, NO_SP
));
2721 else if (INSTR (19, 19))
2723 index
= INSTR (20, 20);
2724 aarch64_set_vec_u64 (cpu
, vd
, index
,
2725 aarch64_get_reg_u64 (cpu
, rs
, NO_SP
));
2732 do_vec_DUP_vector_into_vector (sim_cpu
*cpu
)
2735 instr[30] = half(0)/full(1)
2736 instr[29,21] = 00 1110 000
2737 instr[20,16] = element size and index
2738 instr[15,10] = 0000 01
2739 instr[9,5] = V source
2740 instr[4,0] = V dest. */
2742 unsigned full
= INSTR (30, 30);
2743 unsigned vs
= INSTR (9, 5);
2744 unsigned vd
= INSTR (4, 0);
2747 NYI_assert (29, 21, 0x070);
2748 NYI_assert (15, 10, 0x01);
2750 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2753 index
= INSTR (20, 17);
2755 for (i
= 0; i
< (full
? 16 : 8); i
++)
2756 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vs
, index
));
2758 else if (INSTR (17, 17))
2760 index
= INSTR (20, 18);
2762 for (i
= 0; i
< (full
? 8 : 4); i
++)
2763 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vs
, index
));
2765 else if (INSTR (18, 18))
2767 index
= INSTR (20, 19);
2769 for (i
= 0; i
< (full
? 4 : 2); i
++)
2770 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vs
, index
));
2774 if (INSTR (19, 19) == 0)
2780 index
= INSTR (20, 20);
2782 for (i
= 0; i
< 2; i
++)
2783 aarch64_set_vec_u64 (cpu
, vd
, i
, aarch64_get_vec_u64 (cpu
, vs
, index
));
2788 do_vec_TBL (sim_cpu
*cpu
)
2791 instr[30] = half(0)/full(1)
2792 instr[29,21] = 00 1110 000
2795 instr[14,13] = vec length
2797 instr[9,5] = V start
2798 instr[4,0] = V dest */
2800 int full
= INSTR (30, 30);
2801 int len
= INSTR (14, 13) + 1;
2802 unsigned vm
= INSTR (20, 16);
2803 unsigned vn
= INSTR (9, 5);
2804 unsigned vd
= INSTR (4, 0);
2807 NYI_assert (29, 21, 0x070);
2808 NYI_assert (12, 10, 0);
2810 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2811 for (i
= 0; i
< (full
? 16 : 8); i
++)
2813 unsigned int selector
= aarch64_get_vec_u8 (cpu
, vm
, i
);
2817 val
= aarch64_get_vec_u8 (cpu
, vn
, selector
);
2818 else if (selector
< 32)
2819 val
= len
< 2 ? 0 : aarch64_get_vec_u8 (cpu
, vn
+ 1, selector
- 16);
2820 else if (selector
< 48)
2821 val
= len
< 3 ? 0 : aarch64_get_vec_u8 (cpu
, vn
+ 2, selector
- 32);
2822 else if (selector
< 64)
2823 val
= len
< 4 ? 0 : aarch64_get_vec_u8 (cpu
, vn
+ 3, selector
- 48);
2827 aarch64_set_vec_u8 (cpu
, vd
, i
, val
);
2832 do_vec_TRN (sim_cpu
*cpu
)
2835 instr[30] = half(0)/full(1)
2836 instr[29,24] = 00 1110
2841 instr[14] = TRN1 (0) / TRN2 (1)
2843 instr[9,5] = V source
2844 instr[4,0] = V dest. */
2846 int full
= INSTR (30, 30);
2847 int second
= INSTR (14, 14);
2848 unsigned vm
= INSTR (20, 16);
2849 unsigned vn
= INSTR (9, 5);
2850 unsigned vd
= INSTR (4, 0);
2853 NYI_assert (29, 24, 0x0E);
2854 NYI_assert (13, 10, 0xA);
2856 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2857 switch (INSTR (23, 22))
2860 for (i
= 0; i
< (full
? 8 : 4); i
++)
2864 aarch64_get_vec_u8 (cpu
, second
? vm
: vn
, i
* 2));
2866 (cpu
, vd
, 1 * 2 + 1,
2867 aarch64_get_vec_u8 (cpu
, second
? vn
: vm
, i
* 2 + 1));
2872 for (i
= 0; i
< (full
? 4 : 2); i
++)
2876 aarch64_get_vec_u16 (cpu
, second
? vm
: vn
, i
* 2));
2878 (cpu
, vd
, 1 * 2 + 1,
2879 aarch64_get_vec_u16 (cpu
, second
? vn
: vm
, i
* 2 + 1));
2885 (cpu
, vd
, 0, aarch64_get_vec_u32 (cpu
, second
? vm
: vn
, 0));
2887 (cpu
, vd
, 1, aarch64_get_vec_u32 (cpu
, second
? vn
: vm
, 1));
2889 (cpu
, vd
, 2, aarch64_get_vec_u32 (cpu
, second
? vm
: vn
, 2));
2891 (cpu
, vd
, 3, aarch64_get_vec_u32 (cpu
, second
? vn
: vm
, 3));
2898 aarch64_set_vec_u64 (cpu
, vd
, 0,
2899 aarch64_get_vec_u64 (cpu
, second
? vm
: vn
, 0));
2900 aarch64_set_vec_u64 (cpu
, vd
, 1,
2901 aarch64_get_vec_u64 (cpu
, second
? vn
: vm
, 1));
2907 do_vec_DUP_scalar_into_vector (sim_cpu
*cpu
)
2910 instr[30] = 0=> zero top 64-bits, 1=> duplicate into top 64-bits
2911 [must be 1 for 64-bit xfer]
2912 instr[29,20] = 00 1110 0000
2913 instr[19,16] = element size: 0001=> 8-bits, 0010=> 16-bits,
2914 0100=> 32-bits. 1000=>64-bits
2915 instr[15,10] = 0000 11
2916 instr[9,5] = W source
2917 instr[4,0] = V dest. */
2920 unsigned Vd
= INSTR (4, 0);
2921 unsigned Rs
= INSTR (9, 5);
2922 int both
= INSTR (30, 30);
2924 NYI_assert (29, 20, 0x0E0);
2925 NYI_assert (15, 10, 0x03);
2927 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2928 switch (INSTR (19, 16))
2931 for (i
= 0; i
< (both
? 16 : 8); i
++)
2932 aarch64_set_vec_u8 (cpu
, Vd
, i
, aarch64_get_reg_u8 (cpu
, Rs
, NO_SP
));
2936 for (i
= 0; i
< (both
? 8 : 4); i
++)
2937 aarch64_set_vec_u16 (cpu
, Vd
, i
, aarch64_get_reg_u16 (cpu
, Rs
, NO_SP
));
2941 for (i
= 0; i
< (both
? 4 : 2); i
++)
2942 aarch64_set_vec_u32 (cpu
, Vd
, i
, aarch64_get_reg_u32 (cpu
, Rs
, NO_SP
));
2948 aarch64_set_vec_u64 (cpu
, Vd
, 0, aarch64_get_reg_u64 (cpu
, Rs
, NO_SP
));
2949 aarch64_set_vec_u64 (cpu
, Vd
, 1, aarch64_get_reg_u64 (cpu
, Rs
, NO_SP
));
2958 do_vec_UZP (sim_cpu
*cpu
)
2961 instr[30] = half(0)/full(1)
2962 instr[29,24] = 00 1110
2963 instr[23,22] = size: byte(00), half(01), word (10), long (11)
2967 instr[14] = lower (0) / upper (1)
2972 int full
= INSTR (30, 30);
2973 int upper
= INSTR (14, 14);
2975 unsigned vm
= INSTR (20, 16);
2976 unsigned vn
= INSTR (9, 5);
2977 unsigned vd
= INSTR (4, 0);
2979 uint64_t val_m1
= aarch64_get_vec_u64 (cpu
, vm
, 0);
2980 uint64_t val_m2
= aarch64_get_vec_u64 (cpu
, vm
, 1);
2981 uint64_t val_n1
= aarch64_get_vec_u64 (cpu
, vn
, 0);
2982 uint64_t val_n2
= aarch64_get_vec_u64 (cpu
, vn
, 1);
2987 uint64_t input1
= upper
? val_n1
: val_m1
;
2988 uint64_t input2
= upper
? val_n2
: val_m2
;
2991 NYI_assert (29, 24, 0x0E);
2992 NYI_assert (21, 21, 0);
2993 NYI_assert (15, 15, 0);
2994 NYI_assert (13, 10, 6);
2996 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2997 switch (INSTR (23, 23))
3000 for (i
= 0; i
< 8; i
++)
3002 val1
|= (input1
>> (i
* 8)) & (0xFFULL
<< (i
* 8));
3003 val2
|= (input2
>> (i
* 8)) & (0xFFULL
<< (i
* 8));
3008 for (i
= 0; i
< 4; i
++)
3010 val1
|= (input1
>> (i
* 16)) & (0xFFFFULL
<< (i
* 16));
3011 val2
|= (input2
>> (i
* 16)) & (0xFFFFULL
<< (i
* 16));
3016 val1
= ((input1
& 0xFFFFFFFF) | ((input1
>> 32) & 0xFFFFFFFF00000000ULL
));
3017 val2
= ((input2
& 0xFFFFFFFF) | ((input2
>> 32) & 0xFFFFFFFF00000000ULL
));
3025 aarch64_set_vec_u64 (cpu
, vd
, 0, val1
);
3027 aarch64_set_vec_u64 (cpu
, vd
, 1, val2
);
3031 do_vec_ZIP (sim_cpu
*cpu
)
3034 instr[30] = half(0)/full(1)
3035 instr[29,24] = 00 1110
3036 instr[23,22] = size: byte(00), hald(01), word (10), long (11)
3040 instr[14] = lower (0) / upper (1)
3045 int full
= INSTR (30, 30);
3046 int upper
= INSTR (14, 14);
3048 unsigned vm
= INSTR (20, 16);
3049 unsigned vn
= INSTR (9, 5);
3050 unsigned vd
= INSTR (4, 0);
3052 uint64_t val_m1
= aarch64_get_vec_u64 (cpu
, vm
, 0);
3053 uint64_t val_m2
= aarch64_get_vec_u64 (cpu
, vm
, 1);
3054 uint64_t val_n1
= aarch64_get_vec_u64 (cpu
, vn
, 0);
3055 uint64_t val_n2
= aarch64_get_vec_u64 (cpu
, vn
, 1);
3060 uint64_t input1
= upper
? val_n1
: val_m1
;
3061 uint64_t input2
= upper
? val_n2
: val_m2
;
3063 NYI_assert (29, 24, 0x0E);
3064 NYI_assert (21, 21, 0);
3065 NYI_assert (15, 15, 0);
3066 NYI_assert (13, 10, 0xE);
3068 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3069 switch (INSTR (23, 23))
3073 ((input1
<< 0) & (0xFF << 0))
3074 | ((input2
<< 8) & (0xFF << 8))
3075 | ((input1
<< 8) & (0xFF << 16))
3076 | ((input2
<< 16) & (0xFF << 24))
3077 | ((input1
<< 16) & (0xFFULL
<< 32))
3078 | ((input2
<< 24) & (0xFFULL
<< 40))
3079 | ((input1
<< 24) & (0xFFULL
<< 48))
3080 | ((input2
<< 32) & (0xFFULL
<< 56));
3083 ((input1
>> 32) & (0xFF << 0))
3084 | ((input2
>> 24) & (0xFF << 8))
3085 | ((input1
>> 24) & (0xFF << 16))
3086 | ((input2
>> 16) & (0xFF << 24))
3087 | ((input1
>> 16) & (0xFFULL
<< 32))
3088 | ((input2
>> 8) & (0xFFULL
<< 40))
3089 | ((input1
>> 8) & (0xFFULL
<< 48))
3090 | ((input2
>> 0) & (0xFFULL
<< 56));
3095 ((input1
<< 0) & (0xFFFF << 0))
3096 | ((input2
<< 16) & (0xFFFF << 16))
3097 | ((input1
<< 16) & (0xFFFFULL
<< 32))
3098 | ((input2
<< 32) & (0xFFFFULL
<< 48));
3101 ((input1
>> 32) & (0xFFFF << 0))
3102 | ((input2
>> 16) & (0xFFFF << 16))
3103 | ((input1
>> 16) & (0xFFFFULL
<< 32))
3104 | ((input2
>> 0) & (0xFFFFULL
<< 48));
3108 val1
= (input1
& 0xFFFFFFFFULL
) | (input2
<< 32);
3109 val2
= (input2
& 0xFFFFFFFFULL
) | (input1
<< 32);
3118 aarch64_set_vec_u64 (cpu
, vd
, 0, val1
);
3120 aarch64_set_vec_u64 (cpu
, vd
, 1, val2
);
3123 /* Floating point immediates are encoded in 8 bits.
3124 fpimm[7] = sign bit.
3125 fpimm[6:4] = signed exponent.
3126 fpimm[3:0] = fraction (assuming leading 1).
3127 i.e. F = s * 1.f * 2^(e - b). */
3130 fp_immediate_for_encoding_32 (uint32_t imm8
)
3133 uint32_t s
, e
, f
, i
;
3135 s
= (imm8
>> 7) & 0x1;
3136 e
= (imm8
>> 4) & 0x7;
3139 /* The fp value is s * n/16 * 2r where n is 16+e. */
3140 u
= (16.0 + f
) / 16.0;
3142 /* N.B. exponent is signed. */
3147 for (i
= 0; i
<= epos
; i
++)
3154 for (i
= 0; i
< eneg
; i
++)
3165 fp_immediate_for_encoding_64 (uint32_t imm8
)
3168 uint32_t s
, e
, f
, i
;
3170 s
= (imm8
>> 7) & 0x1;
3171 e
= (imm8
>> 4) & 0x7;
3174 /* The fp value is s * n/16 * 2r where n is 16+e. */
3175 u
= (16.0 + f
) / 16.0;
3177 /* N.B. exponent is signed. */
3182 for (i
= 0; i
<= epos
; i
++)
3189 for (i
= 0; i
< eneg
; i
++)
3200 do_vec_MOV_immediate (sim_cpu
*cpu
)
3203 instr[30] = full/half selector
3204 instr[29,19] = 00111100000
3205 instr[18,16] = high 3 bits of uimm8
3206 instr[15,12] = size & shift:
3208 0010 => 32-bit + LSL#8
3209 0100 => 32-bit + LSL#16
3210 0110 => 32-bit + LSL#24
3211 1010 => 16-bit + LSL#8
3213 1101 => 32-bit + MSL#16
3214 1100 => 32-bit + MSL#8
3218 instr[9,5] = low 5-bits of uimm8
3221 int full
= INSTR (30, 30);
3222 unsigned vd
= INSTR (4, 0);
3223 unsigned val
= (INSTR (18, 16) << 5) | INSTR (9, 5);
3226 NYI_assert (29, 19, 0x1E0);
3227 NYI_assert (11, 10, 1);
3229 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3230 switch (INSTR (15, 12))
3232 case 0x0: /* 32-bit, no shift. */
3233 case 0x2: /* 32-bit, shift by 8. */
3234 case 0x4: /* 32-bit, shift by 16. */
3235 case 0x6: /* 32-bit, shift by 24. */
3236 val
<<= (8 * INSTR (14, 13));
3237 for (i
= 0; i
< (full
? 4 : 2); i
++)
3238 aarch64_set_vec_u32 (cpu
, vd
, i
, val
);
3241 case 0xa: /* 16-bit, shift by 8. */
3244 case 0x8: /* 16-bit, no shift. */
3245 for (i
= 0; i
< (full
? 8 : 4); i
++)
3246 aarch64_set_vec_u16 (cpu
, vd
, i
, val
);
3248 case 0xd: /* 32-bit, mask shift by 16. */
3252 case 0xc: /* 32-bit, mask shift by 8. */
3255 for (i
= 0; i
< (full
? 4 : 2); i
++)
3256 aarch64_set_vec_u32 (cpu
, vd
, i
, val
);
3259 case 0xe: /* 8-bit, no shift. */
3260 for (i
= 0; i
< (full
? 16 : 8); i
++)
3261 aarch64_set_vec_u8 (cpu
, vd
, i
, val
);
3264 case 0xf: /* FMOV Vs.{2|4}S, #fpimm. */
3266 float u
= fp_immediate_for_encoding_32 (val
);
3267 for (i
= 0; i
< (full
? 4 : 2); i
++)
3268 aarch64_set_vec_float (cpu
, vd
, i
, u
);
3278 do_vec_MVNI (sim_cpu
*cpu
)
3281 instr[30] = full/half selector
3282 instr[29,19] = 10111100000
3283 instr[18,16] = high 3 bits of uimm8
3284 instr[15,12] = selector
3286 instr[9,5] = low 5-bits of uimm8
3289 int full
= INSTR (30, 30);
3290 unsigned vd
= INSTR (4, 0);
3291 unsigned val
= (INSTR (18, 16) << 5) | INSTR (9, 5);
3294 NYI_assert (29, 19, 0x5E0);
3295 NYI_assert (11, 10, 1);
3297 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3298 switch (INSTR (15, 12))
3300 case 0x0: /* 32-bit, no shift. */
3301 case 0x2: /* 32-bit, shift by 8. */
3302 case 0x4: /* 32-bit, shift by 16. */
3303 case 0x6: /* 32-bit, shift by 24. */
3304 val
<<= (8 * INSTR (14, 13));
3306 for (i
= 0; i
< (full
? 4 : 2); i
++)
3307 aarch64_set_vec_u32 (cpu
, vd
, i
, val
);
3310 case 0xa: /* 16-bit, 8 bit shift. */
3312 case 0x8: /* 16-bit, no shift. */
3314 for (i
= 0; i
< (full
? 8 : 4); i
++)
3315 aarch64_set_vec_u16 (cpu
, vd
, i
, val
);
3318 case 0xd: /* 32-bit, mask shift by 16. */
3321 case 0xc: /* 32-bit, mask shift by 8. */
3325 for (i
= 0; i
< (full
? 4 : 2); i
++)
3326 aarch64_set_vec_u32 (cpu
, vd
, i
, val
);
3329 case 0xE: /* MOVI Dn, #mask64 */
3333 for (i
= 0; i
< 8; i
++)
3335 mask
|= (0xFFUL
<< (i
* 8));
3336 aarch64_set_vec_u64 (cpu
, vd
, 0, mask
);
3337 aarch64_set_vec_u64 (cpu
, vd
, 1, mask
);
3341 case 0xf: /* FMOV Vd.2D, #fpimm. */
3343 double u
= fp_immediate_for_encoding_64 (val
);
3348 aarch64_set_vec_double (cpu
, vd
, 0, u
);
3349 aarch64_set_vec_double (cpu
, vd
, 1, u
);
3358 #define ABS(A) ((A) < 0 ? - (A) : (A))
3361 do_vec_ABS (sim_cpu
*cpu
)
3364 instr[30] = half(0)/full(1)
3365 instr[29,24] = 00 1110
3366 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3367 instr[21,10] = 10 0000 1011 10
3371 unsigned vn
= INSTR (9, 5);
3372 unsigned vd
= INSTR (4, 0);
3373 unsigned full
= INSTR (30, 30);
3376 NYI_assert (29, 24, 0x0E);
3377 NYI_assert (21, 10, 0x82E);
3379 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3380 switch (INSTR (23, 22))
3383 for (i
= 0; i
< (full
? 16 : 8); i
++)
3384 aarch64_set_vec_s8 (cpu
, vd
, i
,
3385 ABS (aarch64_get_vec_s8 (cpu
, vn
, i
)));
3389 for (i
= 0; i
< (full
? 8 : 4); i
++)
3390 aarch64_set_vec_s16 (cpu
, vd
, i
,
3391 ABS (aarch64_get_vec_s16 (cpu
, vn
, i
)));
3395 for (i
= 0; i
< (full
? 4 : 2); i
++)
3396 aarch64_set_vec_s32 (cpu
, vd
, i
,
3397 ABS (aarch64_get_vec_s32 (cpu
, vn
, i
)));
3403 for (i
= 0; i
< 2; i
++)
3404 aarch64_set_vec_s64 (cpu
, vd
, i
,
3405 ABS (aarch64_get_vec_s64 (cpu
, vn
, i
)));
3411 do_vec_ADDV (sim_cpu
*cpu
)
3414 instr[30] = full/half selector
3415 instr[29,24] = 00 1110
3416 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3417 instr[21,10] = 11 0001 1011 10
3421 unsigned vm
= INSTR (9, 5);
3422 unsigned rd
= INSTR (4, 0);
3425 int full
= INSTR (30, 30);
3427 NYI_assert (29, 24, 0x0E);
3428 NYI_assert (21, 10, 0xC6E);
3430 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3431 switch (INSTR (23, 22))
3434 for (i
= 0; i
< (full
? 16 : 8); i
++)
3435 val
+= aarch64_get_vec_u8 (cpu
, vm
, i
);
3436 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val
);
3440 for (i
= 0; i
< (full
? 8 : 4); i
++)
3441 val
+= aarch64_get_vec_u16 (cpu
, vm
, i
);
3442 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val
);
3446 for (i
= 0; i
< (full
? 4 : 2); i
++)
3447 val
+= aarch64_get_vec_u32 (cpu
, vm
, i
);
3448 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val
);
3454 val
= aarch64_get_vec_u64 (cpu
, vm
, 0);
3455 val
+= aarch64_get_vec_u64 (cpu
, vm
, 1);
3456 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val
);
3462 do_vec_ins_2 (sim_cpu
*cpu
)
3464 /* instr[31,21] = 01001110000
3465 instr[20,18] = size & element selector
3467 instr[13] = direction: to vec(0), from vec (1)
3473 unsigned vm
= INSTR (9, 5);
3474 unsigned vd
= INSTR (4, 0);
3476 NYI_assert (31, 21, 0x270);
3477 NYI_assert (17, 14, 0);
3478 NYI_assert (12, 10, 7);
3480 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3481 if (INSTR (13, 13) == 1)
3483 if (INSTR (18, 18) == 1)
3486 elem
= INSTR (20, 19);
3487 aarch64_set_reg_u64 (cpu
, vd
, NO_SP
,
3488 aarch64_get_vec_u32 (cpu
, vm
, elem
));
3493 if (INSTR (19, 19) != 1)
3496 elem
= INSTR (20, 20);
3497 aarch64_set_reg_u64 (cpu
, vd
, NO_SP
,
3498 aarch64_get_vec_u64 (cpu
, vm
, elem
));
3503 if (INSTR (18, 18) == 1)
3506 elem
= INSTR (20, 19);
3507 aarch64_set_vec_u32 (cpu
, vd
, elem
,
3508 aarch64_get_reg_u32 (cpu
, vm
, NO_SP
));
3513 if (INSTR (19, 19) != 1)
3516 elem
= INSTR (20, 20);
3517 aarch64_set_vec_u64 (cpu
, vd
, elem
,
3518 aarch64_get_reg_u64 (cpu
, vm
, NO_SP
));
3523 #define DO_VEC_WIDENING_MUL(N, DST_TYPE, READ_TYPE, WRITE_TYPE) \
3526 DST_TYPE a[N], b[N]; \
3528 for (i = 0; i < (N); i++) \
3530 a[i] = aarch64_get_vec_##READ_TYPE (cpu, vn, i + bias); \
3531 b[i] = aarch64_get_vec_##READ_TYPE (cpu, vm, i + bias); \
3533 for (i = 0; i < (N); i++) \
3534 aarch64_set_vec_##WRITE_TYPE (cpu, vd, i, a[i] * b[i]); \
3539 do_vec_mull (sim_cpu
*cpu
)
3542 instr[30] = lower(0)/upper(1) selector
3543 instr[29] = signed(0)/unsigned(1)
3544 instr[28,24] = 0 1110
3545 instr[23,22] = size: 8-bit (00), 16-bit (01), 32-bit (10)
3548 instr[15,10] = 11 0000
3552 int unsign
= INSTR (29, 29);
3553 int bias
= INSTR (30, 30);
3554 unsigned vm
= INSTR (20, 16);
3555 unsigned vn
= INSTR ( 9, 5);
3556 unsigned vd
= INSTR ( 4, 0);
3559 NYI_assert (28, 24, 0x0E);
3560 NYI_assert (15, 10, 0x30);
3562 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3563 /* NB: Read source values before writing results, in case
3564 the source and destination vectors are the same. */
3565 switch (INSTR (23, 22))
3571 DO_VEC_WIDENING_MUL (8, uint16_t, u8
, u16
);
3573 DO_VEC_WIDENING_MUL (8, int16_t, s8
, s16
);
3580 DO_VEC_WIDENING_MUL (4, uint32_t, u16
, u32
);
3582 DO_VEC_WIDENING_MUL (4, int32_t, s16
, s32
);
3589 DO_VEC_WIDENING_MUL (2, uint64_t, u32
, u64
);
3591 DO_VEC_WIDENING_MUL (2, int64_t, s32
, s64
);
3600 do_vec_fadd (sim_cpu
*cpu
)
3603 instr[30] = half(0)/full(1)
3604 instr[29,24] = 001110
3605 instr[23] = FADD(0)/FSUB(1)
3606 instr[22] = float (0)/double(1)
3609 instr[15,10] = 110101
3613 unsigned vm
= INSTR (20, 16);
3614 unsigned vn
= INSTR (9, 5);
3615 unsigned vd
= INSTR (4, 0);
3617 int full
= INSTR (30, 30);
3619 NYI_assert (29, 24, 0x0E);
3620 NYI_assert (21, 21, 1);
3621 NYI_assert (15, 10, 0x35);
3623 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3631 for (i
= 0; i
< 2; i
++)
3632 aarch64_set_vec_double (cpu
, vd
, i
,
3633 aarch64_get_vec_double (cpu
, vn
, i
)
3634 - aarch64_get_vec_double (cpu
, vm
, i
));
3638 for (i
= 0; i
< (full
? 4 : 2); i
++)
3639 aarch64_set_vec_float (cpu
, vd
, i
,
3640 aarch64_get_vec_float (cpu
, vn
, i
)
3641 - aarch64_get_vec_float (cpu
, vm
, i
));
3651 for (i
= 0; i
< 2; i
++)
3652 aarch64_set_vec_double (cpu
, vd
, i
,
3653 aarch64_get_vec_double (cpu
, vm
, i
)
3654 + aarch64_get_vec_double (cpu
, vn
, i
));
3658 for (i
= 0; i
< (full
? 4 : 2); i
++)
3659 aarch64_set_vec_float (cpu
, vd
, i
,
3660 aarch64_get_vec_float (cpu
, vm
, i
)
3661 + aarch64_get_vec_float (cpu
, vn
, i
));
3667 do_vec_add (sim_cpu
*cpu
)
3670 instr[30] = full/half selector
3671 instr[29,24] = 001110
3672 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3675 instr[15,10] = 100001
3679 unsigned vm
= INSTR (20, 16);
3680 unsigned vn
= INSTR (9, 5);
3681 unsigned vd
= INSTR (4, 0);
3683 int full
= INSTR (30, 30);
3685 NYI_assert (29, 24, 0x0E);
3686 NYI_assert (21, 21, 1);
3687 NYI_assert (15, 10, 0x21);
3689 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3690 switch (INSTR (23, 22))
3693 for (i
= 0; i
< (full
? 16 : 8); i
++)
3694 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vn
, i
)
3695 + aarch64_get_vec_u8 (cpu
, vm
, i
));
3699 for (i
= 0; i
< (full
? 8 : 4); i
++)
3700 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vn
, i
)
3701 + aarch64_get_vec_u16 (cpu
, vm
, i
));
3705 for (i
= 0; i
< (full
? 4 : 2); i
++)
3706 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vn
, i
)
3707 + aarch64_get_vec_u32 (cpu
, vm
, i
));
3713 aarch64_set_vec_u64 (cpu
, vd
, 0, aarch64_get_vec_u64 (cpu
, vn
, 0)
3714 + aarch64_get_vec_u64 (cpu
, vm
, 0));
3715 aarch64_set_vec_u64 (cpu
, vd
, 1,
3716 aarch64_get_vec_u64 (cpu
, vn
, 1)
3717 + aarch64_get_vec_u64 (cpu
, vm
, 1));
3723 do_vec_mul (sim_cpu
*cpu
)
3726 instr[30] = full/half selector
3727 instr[29,24] = 00 1110
3728 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3731 instr[15,10] = 10 0111
3735 unsigned vm
= INSTR (20, 16);
3736 unsigned vn
= INSTR (9, 5);
3737 unsigned vd
= INSTR (4, 0);
3739 int full
= INSTR (30, 30);
3742 NYI_assert (29, 24, 0x0E);
3743 NYI_assert (21, 21, 1);
3744 NYI_assert (15, 10, 0x27);
3746 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3747 switch (INSTR (23, 22))
3750 DO_VEC_WIDENING_MUL (full
? 16 : 8, uint16_t, u8
, u16
);
3754 DO_VEC_WIDENING_MUL (full
? 8 : 4, uint32_t, u16
, u32
);
3758 DO_VEC_WIDENING_MUL (full
? 4 : 2, uint64_t, u32
, u64
);
3767 do_vec_MLA (sim_cpu
*cpu
)
3770 instr[30] = full/half selector
3771 instr[29,24] = 00 1110
3772 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3775 instr[15,10] = 1001 01
3779 unsigned vm
= INSTR (20, 16);
3780 unsigned vn
= INSTR (9, 5);
3781 unsigned vd
= INSTR (4, 0);
3783 int full
= INSTR (30, 30);
3785 NYI_assert (29, 24, 0x0E);
3786 NYI_assert (21, 21, 1);
3787 NYI_assert (15, 10, 0x25);
3789 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3790 switch (INSTR (23, 22))
3794 uint16_t a
[16], b
[16];
3796 for (i
= 0; i
< (full
? 16 : 8); i
++)
3798 a
[i
] = aarch64_get_vec_u8 (cpu
, vn
, i
);
3799 b
[i
] = aarch64_get_vec_u8 (cpu
, vm
, i
);
3802 for (i
= 0; i
< (full
? 16 : 8); i
++)
3804 uint16_t v
= aarch64_get_vec_u8 (cpu
, vd
, i
);
3806 aarch64_set_vec_u16 (cpu
, vd
, i
, v
+ (a
[i
] * b
[i
]));
3813 uint32_t a
[8], b
[8];
3815 for (i
= 0; i
< (full
? 8 : 4); i
++)
3817 a
[i
] = aarch64_get_vec_u16 (cpu
, vn
, i
);
3818 b
[i
] = aarch64_get_vec_u16 (cpu
, vm
, i
);
3821 for (i
= 0; i
< (full
? 8 : 4); i
++)
3823 uint32_t v
= aarch64_get_vec_u16 (cpu
, vd
, i
);
3825 aarch64_set_vec_u32 (cpu
, vd
, i
, v
+ (a
[i
] * b
[i
]));
3832 uint64_t a
[4], b
[4];
3834 for (i
= 0; i
< (full
? 4 : 2); i
++)
3836 a
[i
] = aarch64_get_vec_u32 (cpu
, vn
, i
);
3837 b
[i
] = aarch64_get_vec_u32 (cpu
, vm
, i
);
3840 for (i
= 0; i
< (full
? 4 : 2); i
++)
3842 uint64_t v
= aarch64_get_vec_u32 (cpu
, vd
, i
);
3844 aarch64_set_vec_u64 (cpu
, vd
, i
, v
+ (a
[i
] * b
[i
]));
3855 fmaxnm (float a
, float b
)
3857 if (fpclassify (a
) == FP_NORMAL
)
3859 if (fpclassify (b
) == FP_NORMAL
)
3860 return a
> b
? a
: b
;
3863 else if (fpclassify (b
) == FP_NORMAL
)
3869 fminnm (float a
, float b
)
3871 if (fpclassify (a
) == FP_NORMAL
)
3873 if (fpclassify (b
) == FP_NORMAL
)
3874 return a
< b
? a
: b
;
3877 else if (fpclassify (b
) == FP_NORMAL
)
3883 dmaxnm (double a
, double b
)
3885 if (fpclassify (a
) == FP_NORMAL
)
3887 if (fpclassify (b
) == FP_NORMAL
)
3888 return a
> b
? a
: b
;
3891 else if (fpclassify (b
) == FP_NORMAL
)
3897 dminnm (double a
, double b
)
3899 if (fpclassify (a
) == FP_NORMAL
)
3901 if (fpclassify (b
) == FP_NORMAL
)
3902 return a
< b
? a
: b
;
3905 else if (fpclassify (b
) == FP_NORMAL
)
3911 do_vec_FminmaxNMP (sim_cpu
*cpu
)
3914 instr [30] = half (0)/full (1)
3915 instr [29,24] = 10 1110
3916 instr [23] = max(0)/min(1)
3917 instr [22] = float (0)/double (1)
3920 instr [15,10] = 1100 01
3922 instr [4.0] = Vd. */
3924 unsigned vm
= INSTR (20, 16);
3925 unsigned vn
= INSTR (9, 5);
3926 unsigned vd
= INSTR (4, 0);
3927 int full
= INSTR (30, 30);
3929 NYI_assert (29, 24, 0x2E);
3930 NYI_assert (21, 21, 1);
3931 NYI_assert (15, 10, 0x31);
3933 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3936 double (* fn
)(double, double) = INSTR (23, 23)
3941 aarch64_set_vec_double (cpu
, vd
, 0,
3942 fn (aarch64_get_vec_double (cpu
, vn
, 0),
3943 aarch64_get_vec_double (cpu
, vn
, 1)));
3944 aarch64_set_vec_double (cpu
, vd
, 0,
3945 fn (aarch64_get_vec_double (cpu
, vm
, 0),
3946 aarch64_get_vec_double (cpu
, vm
, 1)));
3950 float (* fn
)(float, float) = INSTR (23, 23)
3953 aarch64_set_vec_float (cpu
, vd
, 0,
3954 fn (aarch64_get_vec_float (cpu
, vn
, 0),
3955 aarch64_get_vec_float (cpu
, vn
, 1)));
3957 aarch64_set_vec_float (cpu
, vd
, 1,
3958 fn (aarch64_get_vec_float (cpu
, vn
, 2),
3959 aarch64_get_vec_float (cpu
, vn
, 3)));
3961 aarch64_set_vec_float (cpu
, vd
, (full
? 2 : 1),
3962 fn (aarch64_get_vec_float (cpu
, vm
, 0),
3963 aarch64_get_vec_float (cpu
, vm
, 1)));
3965 aarch64_set_vec_float (cpu
, vd
, 3,
3966 fn (aarch64_get_vec_float (cpu
, vm
, 2),
3967 aarch64_get_vec_float (cpu
, vm
, 3)));
3972 do_vec_AND (sim_cpu
*cpu
)
3975 instr[30] = half (0)/full (1)
3976 instr[29,21] = 001110001
3978 instr[15,10] = 000111
3982 unsigned vm
= INSTR (20, 16);
3983 unsigned vn
= INSTR (9, 5);
3984 unsigned vd
= INSTR (4, 0);
3986 int full
= INSTR (30, 30);
3988 NYI_assert (29, 21, 0x071);
3989 NYI_assert (15, 10, 0x07);
3991 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3992 for (i
= 0; i
< (full
? 4 : 2); i
++)
3993 aarch64_set_vec_u32 (cpu
, vd
, i
,
3994 aarch64_get_vec_u32 (cpu
, vn
, i
)
3995 & aarch64_get_vec_u32 (cpu
, vm
, i
));
3999 do_vec_BSL (sim_cpu
*cpu
)
4002 instr[30] = half (0)/full (1)
4003 instr[29,21] = 101110011
4005 instr[15,10] = 000111
4009 unsigned vm
= INSTR (20, 16);
4010 unsigned vn
= INSTR (9, 5);
4011 unsigned vd
= INSTR (4, 0);
4013 int full
= INSTR (30, 30);
4015 NYI_assert (29, 21, 0x173);
4016 NYI_assert (15, 10, 0x07);
4018 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4019 for (i
= 0; i
< (full
? 16 : 8); i
++)
4020 aarch64_set_vec_u8 (cpu
, vd
, i
,
4021 ( aarch64_get_vec_u8 (cpu
, vd
, i
)
4022 & aarch64_get_vec_u8 (cpu
, vn
, i
))
4023 | ((~ aarch64_get_vec_u8 (cpu
, vd
, i
))
4024 & aarch64_get_vec_u8 (cpu
, vm
, i
)));
4028 do_vec_EOR (sim_cpu
*cpu
)
4031 instr[30] = half (0)/full (1)
4032 instr[29,21] = 10 1110 001
4034 instr[15,10] = 000111
4038 unsigned vm
= INSTR (20, 16);
4039 unsigned vn
= INSTR (9, 5);
4040 unsigned vd
= INSTR (4, 0);
4042 int full
= INSTR (30, 30);
4044 NYI_assert (29, 21, 0x171);
4045 NYI_assert (15, 10, 0x07);
4047 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4048 for (i
= 0; i
< (full
? 4 : 2); i
++)
4049 aarch64_set_vec_u32 (cpu
, vd
, i
,
4050 aarch64_get_vec_u32 (cpu
, vn
, i
)
4051 ^ aarch64_get_vec_u32 (cpu
, vm
, i
));
4055 do_vec_bit (sim_cpu
*cpu
)
4058 instr[30] = half (0)/full (1)
4059 instr[29,23] = 10 1110 1
4060 instr[22] = BIT (0) / BIF (1)
4063 instr[15,10] = 0001 11
4067 unsigned vm
= INSTR (20, 16);
4068 unsigned vn
= INSTR (9, 5);
4069 unsigned vd
= INSTR (4, 0);
4070 unsigned full
= INSTR (30, 30);
4071 unsigned test_false
= INSTR (22, 22);
4074 NYI_assert (29, 23, 0x5D);
4075 NYI_assert (21, 21, 1);
4076 NYI_assert (15, 10, 0x07);
4078 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4081 for (i
= 0; i
< (full
? 16 : 8); i
++)
4082 if (aarch64_get_vec_u32 (cpu
, vn
, i
) == 0)
4083 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vm
, i
));
4087 for (i
= 0; i
< (full
? 16 : 8); i
++)
4088 if (aarch64_get_vec_u32 (cpu
, vn
, i
) != 0)
4089 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vm
, i
));
4094 do_vec_ORN (sim_cpu
*cpu
)
4097 instr[30] = half (0)/full (1)
4098 instr[29,21] = 00 1110 111
4100 instr[15,10] = 00 0111
4104 unsigned vm
= INSTR (20, 16);
4105 unsigned vn
= INSTR (9, 5);
4106 unsigned vd
= INSTR (4, 0);
4108 int full
= INSTR (30, 30);
4110 NYI_assert (29, 21, 0x077);
4111 NYI_assert (15, 10, 0x07);
4113 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4114 for (i
= 0; i
< (full
? 16 : 8); i
++)
4115 aarch64_set_vec_u8 (cpu
, vd
, i
,
4116 aarch64_get_vec_u8 (cpu
, vn
, i
)
4117 | ~ aarch64_get_vec_u8 (cpu
, vm
, i
));
4121 do_vec_ORR (sim_cpu
*cpu
)
4124 instr[30] = half (0)/full (1)
4125 instr[29,21] = 00 1110 101
4127 instr[15,10] = 0001 11
4131 unsigned vm
= INSTR (20, 16);
4132 unsigned vn
= INSTR (9, 5);
4133 unsigned vd
= INSTR (4, 0);
4135 int full
= INSTR (30, 30);
4137 NYI_assert (29, 21, 0x075);
4138 NYI_assert (15, 10, 0x07);
4140 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4141 for (i
= 0; i
< (full
? 16 : 8); i
++)
4142 aarch64_set_vec_u8 (cpu
, vd
, i
,
4143 aarch64_get_vec_u8 (cpu
, vn
, i
)
4144 | aarch64_get_vec_u8 (cpu
, vm
, i
));
4148 do_vec_BIC (sim_cpu
*cpu
)
4151 instr[30] = half (0)/full (1)
4152 instr[29,21] = 00 1110 011
4154 instr[15,10] = 00 0111
4158 unsigned vm
= INSTR (20, 16);
4159 unsigned vn
= INSTR (9, 5);
4160 unsigned vd
= INSTR (4, 0);
4162 int full
= INSTR (30, 30);
4164 NYI_assert (29, 21, 0x073);
4165 NYI_assert (15, 10, 0x07);
4167 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4168 for (i
= 0; i
< (full
? 16 : 8); i
++)
4169 aarch64_set_vec_u8 (cpu
, vd
, i
,
4170 aarch64_get_vec_u8 (cpu
, vn
, i
)
4171 & ~ aarch64_get_vec_u8 (cpu
, vm
, i
));
4175 do_vec_XTN (sim_cpu
*cpu
)
4178 instr[30] = first part (0)/ second part (1)
4179 instr[29,24] = 00 1110
4180 instr[23,22] = size: byte(00), half(01), word (10)
4181 instr[21,10] = 1000 0100 1010
4185 unsigned vs
= INSTR (9, 5);
4186 unsigned vd
= INSTR (4, 0);
4187 unsigned bias
= INSTR (30, 30);
4190 NYI_assert (29, 24, 0x0E);
4191 NYI_assert (21, 10, 0x84A);
4193 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4194 switch (INSTR (23, 22))
4198 for (i
= 0; i
< 8; i
++)
4199 aarch64_set_vec_u8 (cpu
, vd
, i
+ 8,
4200 aarch64_get_vec_u16 (cpu
, vs
, i
) >> 8);
4202 for (i
= 0; i
< 8; i
++)
4203 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vs
, i
));
4208 for (i
= 0; i
< 4; i
++)
4209 aarch64_set_vec_u16 (cpu
, vd
, i
+ 4,
4210 aarch64_get_vec_u32 (cpu
, vs
, i
) >> 16);
4212 for (i
= 0; i
< 4; i
++)
4213 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vs
, i
));
4218 for (i
= 0; i
< 2; i
++)
4219 aarch64_set_vec_u32 (cpu
, vd
, i
+ 4,
4220 aarch64_get_vec_u64 (cpu
, vs
, i
) >> 32);
4222 for (i
= 0; i
< 2; i
++)
4223 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u64 (cpu
, vs
, i
));
4229 do_vec_maxv (sim_cpu
*cpu
)
4232 instr[30] = half(0)/full(1)
4233 instr[29] = signed (0)/unsigned(1)
4234 instr[28,24] = 0 1110
4235 instr[23,22] = size: byte(00), half(01), word (10)
4237 instr[20,17] = 1 000
4238 instr[16] = max(0)/min(1)
4239 instr[15,10] = 1010 10
4240 instr[9,5] = V source
4241 instr[4.0] = R dest. */
4243 unsigned vs
= INSTR (9, 5);
4244 unsigned rd
= INSTR (4, 0);
4245 unsigned full
= INSTR (30, 30);
4248 NYI_assert (28, 24, 0x0E);
4249 NYI_assert (21, 21, 1);
4250 NYI_assert (20, 17, 8);
4251 NYI_assert (15, 10, 0x2A);
4253 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4254 switch ((INSTR (29, 29) << 1) | INSTR (16, 16))
4256 case 0: /* SMAXV. */
4259 switch (INSTR (23, 22))
4262 smax
= aarch64_get_vec_s8 (cpu
, vs
, 0);
4263 for (i
= 1; i
< (full
? 16 : 8); i
++)
4264 smax
= max (smax
, aarch64_get_vec_s8 (cpu
, vs
, i
));
4267 smax
= aarch64_get_vec_s16 (cpu
, vs
, 0);
4268 for (i
= 1; i
< (full
? 8 : 4); i
++)
4269 smax
= max (smax
, aarch64_get_vec_s16 (cpu
, vs
, i
));
4272 smax
= aarch64_get_vec_s32 (cpu
, vs
, 0);
4273 for (i
= 1; i
< (full
? 4 : 2); i
++)
4274 smax
= max (smax
, aarch64_get_vec_s32 (cpu
, vs
, i
));
4279 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, smax
);
4283 case 1: /* SMINV. */
4286 switch (INSTR (23, 22))
4289 smin
= aarch64_get_vec_s8 (cpu
, vs
, 0);
4290 for (i
= 1; i
< (full
? 16 : 8); i
++)
4291 smin
= min (smin
, aarch64_get_vec_s8 (cpu
, vs
, i
));
4294 smin
= aarch64_get_vec_s16 (cpu
, vs
, 0);
4295 for (i
= 1; i
< (full
? 8 : 4); i
++)
4296 smin
= min (smin
, aarch64_get_vec_s16 (cpu
, vs
, i
));
4299 smin
= aarch64_get_vec_s32 (cpu
, vs
, 0);
4300 for (i
= 1; i
< (full
? 4 : 2); i
++)
4301 smin
= min (smin
, aarch64_get_vec_s32 (cpu
, vs
, i
));
4307 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, smin
);
4311 case 2: /* UMAXV. */
4314 switch (INSTR (23, 22))
4317 umax
= aarch64_get_vec_u8 (cpu
, vs
, 0);
4318 for (i
= 1; i
< (full
? 16 : 8); i
++)
4319 umax
= max (umax
, aarch64_get_vec_u8 (cpu
, vs
, i
));
4322 umax
= aarch64_get_vec_u16 (cpu
, vs
, 0);
4323 for (i
= 1; i
< (full
? 8 : 4); i
++)
4324 umax
= max (umax
, aarch64_get_vec_u16 (cpu
, vs
, i
));
4327 umax
= aarch64_get_vec_u32 (cpu
, vs
, 0);
4328 for (i
= 1; i
< (full
? 4 : 2); i
++)
4329 umax
= max (umax
, aarch64_get_vec_u32 (cpu
, vs
, i
));
4335 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, umax
);
4339 case 3: /* UMINV. */
4342 switch (INSTR (23, 22))
4345 umin
= aarch64_get_vec_u8 (cpu
, vs
, 0);
4346 for (i
= 1; i
< (full
? 16 : 8); i
++)
4347 umin
= min (umin
, aarch64_get_vec_u8 (cpu
, vs
, i
));
4350 umin
= aarch64_get_vec_u16 (cpu
, vs
, 0);
4351 for (i
= 1; i
< (full
? 8 : 4); i
++)
4352 umin
= min (umin
, aarch64_get_vec_u16 (cpu
, vs
, i
));
4355 umin
= aarch64_get_vec_u32 (cpu
, vs
, 0);
4356 for (i
= 1; i
< (full
? 4 : 2); i
++)
4357 umin
= min (umin
, aarch64_get_vec_u32 (cpu
, vs
, i
));
4363 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, umin
);
4370 do_vec_fminmaxV (sim_cpu
*cpu
)
4372 /* instr[31,24] = 0110 1110
4373 instr[23] = max(0)/min(1)
4374 instr[22,14] = 011 0000 11
4375 instr[13,12] = nm(00)/normal(11)
4377 instr[9,5] = V source
4378 instr[4.0] = R dest. */
4380 unsigned vs
= INSTR (9, 5);
4381 unsigned rd
= INSTR (4, 0);
4383 float res
= aarch64_get_vec_float (cpu
, vs
, 0);
4385 NYI_assert (31, 24, 0x6E);
4386 NYI_assert (22, 14, 0x0C3);
4387 NYI_assert (11, 10, 2);
4389 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4392 switch (INSTR (13, 12))
4394 case 0: /* FMNINNMV. */
4395 for (i
= 1; i
< 4; i
++)
4396 res
= fminnm (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4399 case 3: /* FMINV. */
4400 for (i
= 1; i
< 4; i
++)
4401 res
= min (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4410 switch (INSTR (13, 12))
4412 case 0: /* FMNAXNMV. */
4413 for (i
= 1; i
< 4; i
++)
4414 res
= fmaxnm (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4417 case 3: /* FMAXV. */
4418 for (i
= 1; i
< 4; i
++)
4419 res
= max (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4427 aarch64_set_FP_float (cpu
, rd
, res
);
4431 do_vec_Fminmax (sim_cpu
*cpu
)
4434 instr[30] = half(0)/full(1)
4435 instr[29,24] = 00 1110
4436 instr[23] = max(0)/min(1)
4437 instr[22] = float(0)/double(1)
4441 instr[13,12] = nm(00)/normal(11)
4446 unsigned vm
= INSTR (20, 16);
4447 unsigned vn
= INSTR (9, 5);
4448 unsigned vd
= INSTR (4, 0);
4449 unsigned full
= INSTR (30, 30);
4450 unsigned min
= INSTR (23, 23);
4453 NYI_assert (29, 24, 0x0E);
4454 NYI_assert (21, 21, 1);
4455 NYI_assert (15, 14, 3);
4456 NYI_assert (11, 10, 1);
4458 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4461 double (* func
)(double, double);
4466 if (INSTR (13, 12) == 0)
4467 func
= min
? dminnm
: dmaxnm
;
4468 else if (INSTR (13, 12) == 3)
4469 func
= min
? fmin
: fmax
;
4473 for (i
= 0; i
< 2; i
++)
4474 aarch64_set_vec_double (cpu
, vd
, i
,
4475 func (aarch64_get_vec_double (cpu
, vn
, i
),
4476 aarch64_get_vec_double (cpu
, vm
, i
)));
4480 float (* func
)(float, float);
4482 if (INSTR (13, 12) == 0)
4483 func
= min
? fminnm
: fmaxnm
;
4484 else if (INSTR (13, 12) == 3)
4485 func
= min
? fminf
: fmaxf
;
4489 for (i
= 0; i
< (full
? 4 : 2); i
++)
4490 aarch64_set_vec_float (cpu
, vd
, i
,
4491 func (aarch64_get_vec_float (cpu
, vn
, i
),
4492 aarch64_get_vec_float (cpu
, vm
, i
)));
4497 do_vec_SCVTF (sim_cpu
*cpu
)
4501 instr[29,23] = 00 1110 0
4502 instr[22] = float(0)/double(1)
4503 instr[21,10] = 10 0001 1101 10
4507 unsigned vn
= INSTR (9, 5);
4508 unsigned vd
= INSTR (4, 0);
4509 unsigned full
= INSTR (30, 30);
4510 unsigned size
= INSTR (22, 22);
4513 NYI_assert (29, 23, 0x1C);
4514 NYI_assert (21, 10, 0x876);
4516 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4522 for (i
= 0; i
< 2; i
++)
4524 double val
= (double) aarch64_get_vec_u64 (cpu
, vn
, i
);
4525 aarch64_set_vec_double (cpu
, vd
, i
, val
);
4530 for (i
= 0; i
< (full
? 4 : 2); i
++)
4532 float val
= (float) aarch64_get_vec_u32 (cpu
, vn
, i
);
4533 aarch64_set_vec_float (cpu
, vd
, i
, val
);
4538 #define VEC_CMP(SOURCE, CMP) \
4544 for (i = 0; i < (full ? 16 : 8); i++) \
4545 aarch64_set_vec_u8 (cpu, vd, i, \
4546 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4548 aarch64_get_vec_##SOURCE##8 (cpu, vm, i) \
4552 for (i = 0; i < (full ? 8 : 4); i++) \
4553 aarch64_set_vec_u16 (cpu, vd, i, \
4554 aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4556 aarch64_get_vec_##SOURCE##16 (cpu, vm, i) \
4560 for (i = 0; i < (full ? 4 : 2); i++) \
4561 aarch64_set_vec_u32 (cpu, vd, i, \
4562 aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4564 aarch64_get_vec_##SOURCE##32 (cpu, vm, i) \
4570 for (i = 0; i < 2; i++) \
4571 aarch64_set_vec_u64 (cpu, vd, i, \
4572 aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4574 aarch64_get_vec_##SOURCE##64 (cpu, vm, i) \
4581 #define VEC_CMP0(SOURCE, CMP) \
4587 for (i = 0; i < (full ? 16 : 8); i++) \
4588 aarch64_set_vec_u8 (cpu, vd, i, \
4589 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4593 for (i = 0; i < (full ? 8 : 4); i++) \
4594 aarch64_set_vec_u16 (cpu, vd, i, \
4595 aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4599 for (i = 0; i < (full ? 4 : 2); i++) \
4600 aarch64_set_vec_u32 (cpu, vd, i, \
4601 aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4607 for (i = 0; i < 2; i++) \
4608 aarch64_set_vec_u64 (cpu, vd, i, \
4609 aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4610 CMP 0 ? -1ULL : 0); \
4616 #define VEC_FCMP0(CMP) \
4621 if (INSTR (22, 22)) \
4625 for (i = 0; i < 2; i++) \
4626 aarch64_set_vec_u64 (cpu, vd, i, \
4627 aarch64_get_vec_double (cpu, vn, i) \
4628 CMP 0.0 ? -1 : 0); \
4632 for (i = 0; i < (full ? 4 : 2); i++) \
4633 aarch64_set_vec_u32 (cpu, vd, i, \
4634 aarch64_get_vec_float (cpu, vn, i) \
4635 CMP 0.0 ? -1 : 0); \
4641 #define VEC_FCMP(CMP) \
4644 if (INSTR (22, 22)) \
4648 for (i = 0; i < 2; i++) \
4649 aarch64_set_vec_u64 (cpu, vd, i, \
4650 aarch64_get_vec_double (cpu, vn, i) \
4652 aarch64_get_vec_double (cpu, vm, i) \
4657 for (i = 0; i < (full ? 4 : 2); i++) \
4658 aarch64_set_vec_u32 (cpu, vd, i, \
4659 aarch64_get_vec_float (cpu, vn, i) \
4661 aarch64_get_vec_float (cpu, vm, i) \
4669 do_vec_compare (sim_cpu
*cpu
)
4672 instr[30] = half(0)/full(1)
4673 instr[29] = part-of-comparison-type
4674 instr[28,24] = 0 1110
4675 instr[23,22] = size of integer compares: byte(00), half(01), word (10), long (11)
4676 type of float compares: single (-0) / double (-1)
4678 instr[20,16] = Vm or 00000 (compare vs 0)
4679 instr[15,10] = part-of-comparison-type
4683 int full
= INSTR (30, 30);
4684 int size
= INSTR (23, 22);
4685 unsigned vm
= INSTR (20, 16);
4686 unsigned vn
= INSTR (9, 5);
4687 unsigned vd
= INSTR (4, 0);
4690 NYI_assert (28, 24, 0x0E);
4691 NYI_assert (21, 21, 1);
4693 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4696 || ((INSTR (11, 11) == 0
4697 && INSTR (10, 10) == 0)))
4699 /* A compare vs 0. */
4702 if (INSTR (15, 10) == 0x2A)
4704 else if (INSTR (15, 10) == 0x32
4705 || INSTR (15, 10) == 0x3E)
4706 do_vec_fminmaxV (cpu
);
4707 else if (INSTR (29, 23) == 0x1C
4708 && INSTR (21, 10) == 0x876)
4718 /* A floating point compare. */
4719 unsigned decode
= (INSTR (29, 29) << 5) | (INSTR (23, 23) << 4)
4722 NYI_assert (15, 15, 1);
4726 case /* 0b010010: GT#0 */ 0x12: VEC_FCMP0 (>);
4727 case /* 0b110010: GE#0 */ 0x32: VEC_FCMP0 (>=);
4728 case /* 0b010110: EQ#0 */ 0x16: VEC_FCMP0 (==);
4729 case /* 0b110110: LE#0 */ 0x36: VEC_FCMP0 (<=);
4730 case /* 0b011010: LT#0 */ 0x1A: VEC_FCMP0 (<);
4731 case /* 0b111001: GT */ 0x39: VEC_FCMP (>);
4732 case /* 0b101001: GE */ 0x29: VEC_FCMP (>=);
4733 case /* 0b001001: EQ */ 0x09: VEC_FCMP (==);
4741 unsigned decode
= (INSTR (29, 29) << 6) | INSTR (15, 10);
4745 case 0x0D: /* 0001101 GT */ VEC_CMP (s
, > );
4746 case 0x0F: /* 0001111 GE */ VEC_CMP (s
, >= );
4747 case 0x22: /* 0100010 GT #0 */ VEC_CMP0 (s
, > );
4748 case 0x26: /* 0100110 EQ #0 */ VEC_CMP0 (s
, == );
4749 case 0x2A: /* 0101010 LT #0 */ VEC_CMP0 (s
, < );
4750 case 0x4D: /* 1001101 HI */ VEC_CMP (u
, > );
4751 case 0x4F: /* 1001111 HS */ VEC_CMP (u
, >= );
4752 case 0x62: /* 1100010 GE #0 */ VEC_CMP0 (s
, >= );
4753 case 0x63: /* 1100011 EQ */ VEC_CMP (u
, == );
4754 case 0x66: /* 1100110 LE #0 */ VEC_CMP0 (s
, <= );
4764 do_vec_SSHL (sim_cpu
*cpu
)
4767 instr[30] = first part (0)/ second part (1)
4768 instr[29,24] = 00 1110
4769 instr[23,22] = size: byte(00), half(01), word (10), long (11)
4772 instr[15,10] = 0100 01
4776 unsigned full
= INSTR (30, 30);
4777 unsigned vm
= INSTR (20, 16);
4778 unsigned vn
= INSTR (9, 5);
4779 unsigned vd
= INSTR (4, 0);
4783 NYI_assert (29, 24, 0x0E);
4784 NYI_assert (21, 21, 1);
4785 NYI_assert (15, 10, 0x11);
4787 /* FIXME: What is a signed shift left in this context ?. */
4789 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4790 switch (INSTR (23, 22))
4793 for (i
= 0; i
< (full
? 16 : 8); i
++)
4795 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
);
4797 aarch64_set_vec_s8 (cpu
, vd
, i
, aarch64_get_vec_s8 (cpu
, vn
, i
)
4800 aarch64_set_vec_s8 (cpu
, vd
, i
, aarch64_get_vec_s8 (cpu
, vn
, i
)
4806 for (i
= 0; i
< (full
? 8 : 4); i
++)
4808 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 2);
4810 aarch64_set_vec_s16 (cpu
, vd
, i
, aarch64_get_vec_s16 (cpu
, vn
, i
)
4813 aarch64_set_vec_s16 (cpu
, vd
, i
, aarch64_get_vec_s16 (cpu
, vn
, i
)
4819 for (i
= 0; i
< (full
? 4 : 2); i
++)
4821 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 4);
4823 aarch64_set_vec_s32 (cpu
, vd
, i
, aarch64_get_vec_s32 (cpu
, vn
, i
)
4826 aarch64_set_vec_s32 (cpu
, vd
, i
, aarch64_get_vec_s32 (cpu
, vn
, i
)
4834 for (i
= 0; i
< 2; i
++)
4836 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 8);
4838 aarch64_set_vec_s64 (cpu
, vd
, i
, aarch64_get_vec_s64 (cpu
, vn
, i
)
4841 aarch64_set_vec_s64 (cpu
, vd
, i
, aarch64_get_vec_s64 (cpu
, vn
, i
)
4849 do_vec_USHL (sim_cpu
*cpu
)
4852 instr[30] = first part (0)/ second part (1)
4853 instr[29,24] = 10 1110
4854 instr[23,22] = size: byte(00), half(01), word (10), long (11)
4857 instr[15,10] = 0100 01
4861 unsigned full
= INSTR (30, 30);
4862 unsigned vm
= INSTR (20, 16);
4863 unsigned vn
= INSTR (9, 5);
4864 unsigned vd
= INSTR (4, 0);
4868 NYI_assert (29, 24, 0x2E);
4869 NYI_assert (15, 10, 0x11);
4871 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4872 switch (INSTR (23, 22))
4875 for (i
= 0; i
< (full
? 16 : 8); i
++)
4877 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
);
4879 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vn
, i
)
4882 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vn
, i
)
4888 for (i
= 0; i
< (full
? 8 : 4); i
++)
4890 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 2);
4892 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vn
, i
)
4895 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vn
, i
)
4901 for (i
= 0; i
< (full
? 4 : 2); i
++)
4903 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 4);
4905 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vn
, i
)
4908 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vn
, i
)
4916 for (i
= 0; i
< 2; i
++)
4918 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 8);
4920 aarch64_set_vec_u64 (cpu
, vd
, i
, aarch64_get_vec_u64 (cpu
, vn
, i
)
4923 aarch64_set_vec_u64 (cpu
, vd
, i
, aarch64_get_vec_u64 (cpu
, vn
, i
)
4931 do_vec_FMLA (sim_cpu
*cpu
)
4934 instr[30] = full/half selector
4935 instr[29,23] = 0011100
4936 instr[22] = size: 0=>float, 1=>double
4939 instr[15,10] = 1100 11
4943 unsigned vm
= INSTR (20, 16);
4944 unsigned vn
= INSTR (9, 5);
4945 unsigned vd
= INSTR (4, 0);
4947 int full
= INSTR (30, 30);
4949 NYI_assert (29, 23, 0x1C);
4950 NYI_assert (21, 21, 1);
4951 NYI_assert (15, 10, 0x33);
4953 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4958 for (i
= 0; i
< 2; i
++)
4959 aarch64_set_vec_double (cpu
, vd
, i
,
4960 aarch64_get_vec_double (cpu
, vn
, i
) *
4961 aarch64_get_vec_double (cpu
, vm
, i
) +
4962 aarch64_get_vec_double (cpu
, vd
, i
));
4966 for (i
= 0; i
< (full
? 4 : 2); i
++)
4967 aarch64_set_vec_float (cpu
, vd
, i
,
4968 aarch64_get_vec_float (cpu
, vn
, i
) *
4969 aarch64_get_vec_float (cpu
, vm
, i
) +
4970 aarch64_get_vec_float (cpu
, vd
, i
));
4975 do_vec_max (sim_cpu
*cpu
)
4978 instr[30] = full/half selector
4979 instr[29] = SMAX (0) / UMAX (1)
4980 instr[28,24] = 0 1110
4981 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
4984 instr[15,10] = 0110 01
4988 unsigned vm
= INSTR (20, 16);
4989 unsigned vn
= INSTR (9, 5);
4990 unsigned vd
= INSTR (4, 0);
4992 int full
= INSTR (30, 30);
4994 NYI_assert (28, 24, 0x0E);
4995 NYI_assert (21, 21, 1);
4996 NYI_assert (15, 10, 0x19);
4998 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5001 switch (INSTR (23, 22))
5004 for (i
= 0; i
< (full
? 16 : 8); i
++)
5005 aarch64_set_vec_u8 (cpu
, vd
, i
,
5006 aarch64_get_vec_u8 (cpu
, vn
, i
)
5007 > aarch64_get_vec_u8 (cpu
, vm
, i
)
5008 ? aarch64_get_vec_u8 (cpu
, vn
, i
)
5009 : aarch64_get_vec_u8 (cpu
, vm
, i
));
5013 for (i
= 0; i
< (full
? 8 : 4); i
++)
5014 aarch64_set_vec_u16 (cpu
, vd
, i
,
5015 aarch64_get_vec_u16 (cpu
, vn
, i
)
5016 > aarch64_get_vec_u16 (cpu
, vm
, i
)
5017 ? aarch64_get_vec_u16 (cpu
, vn
, i
)
5018 : aarch64_get_vec_u16 (cpu
, vm
, i
));
5022 for (i
= 0; i
< (full
? 4 : 2); i
++)
5023 aarch64_set_vec_u32 (cpu
, vd
, i
,
5024 aarch64_get_vec_u32 (cpu
, vn
, i
)
5025 > aarch64_get_vec_u32 (cpu
, vm
, i
)
5026 ? aarch64_get_vec_u32 (cpu
, vn
, i
)
5027 : aarch64_get_vec_u32 (cpu
, vm
, i
));
5036 switch (INSTR (23, 22))
5039 for (i
= 0; i
< (full
? 16 : 8); i
++)
5040 aarch64_set_vec_s8 (cpu
, vd
, i
,
5041 aarch64_get_vec_s8 (cpu
, vn
, i
)
5042 > aarch64_get_vec_s8 (cpu
, vm
, i
)
5043 ? aarch64_get_vec_s8 (cpu
, vn
, i
)
5044 : aarch64_get_vec_s8 (cpu
, vm
, i
));
5048 for (i
= 0; i
< (full
? 8 : 4); i
++)
5049 aarch64_set_vec_s16 (cpu
, vd
, i
,
5050 aarch64_get_vec_s16 (cpu
, vn
, i
)
5051 > aarch64_get_vec_s16 (cpu
, vm
, i
)
5052 ? aarch64_get_vec_s16 (cpu
, vn
, i
)
5053 : aarch64_get_vec_s16 (cpu
, vm
, i
));
5057 for (i
= 0; i
< (full
? 4 : 2); i
++)
5058 aarch64_set_vec_s32 (cpu
, vd
, i
,
5059 aarch64_get_vec_s32 (cpu
, vn
, i
)
5060 > aarch64_get_vec_s32 (cpu
, vm
, i
)
5061 ? aarch64_get_vec_s32 (cpu
, vn
, i
)
5062 : aarch64_get_vec_s32 (cpu
, vm
, i
));
5072 do_vec_min (sim_cpu
*cpu
)
5075 instr[30] = full/half selector
5076 instr[29] = SMIN (0) / UMIN (1)
5077 instr[28,24] = 0 1110
5078 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
5081 instr[15,10] = 0110 11
5085 unsigned vm
= INSTR (20, 16);
5086 unsigned vn
= INSTR (9, 5);
5087 unsigned vd
= INSTR (4, 0);
5089 int full
= INSTR (30, 30);
5091 NYI_assert (28, 24, 0x0E);
5092 NYI_assert (21, 21, 1);
5093 NYI_assert (15, 10, 0x1B);
5095 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5098 switch (INSTR (23, 22))
5101 for (i
= 0; i
< (full
? 16 : 8); i
++)
5102 aarch64_set_vec_u8 (cpu
, vd
, i
,
5103 aarch64_get_vec_u8 (cpu
, vn
, i
)
5104 < aarch64_get_vec_u8 (cpu
, vm
, i
)
5105 ? aarch64_get_vec_u8 (cpu
, vn
, i
)
5106 : aarch64_get_vec_u8 (cpu
, vm
, i
));
5110 for (i
= 0; i
< (full
? 8 : 4); i
++)
5111 aarch64_set_vec_u16 (cpu
, vd
, i
,
5112 aarch64_get_vec_u16 (cpu
, vn
, i
)
5113 < aarch64_get_vec_u16 (cpu
, vm
, i
)
5114 ? aarch64_get_vec_u16 (cpu
, vn
, i
)
5115 : aarch64_get_vec_u16 (cpu
, vm
, i
));
5119 for (i
= 0; i
< (full
? 4 : 2); i
++)
5120 aarch64_set_vec_u32 (cpu
, vd
, i
,
5121 aarch64_get_vec_u32 (cpu
, vn
, i
)
5122 < aarch64_get_vec_u32 (cpu
, vm
, i
)
5123 ? aarch64_get_vec_u32 (cpu
, vn
, i
)
5124 : aarch64_get_vec_u32 (cpu
, vm
, i
));
5133 switch (INSTR (23, 22))
5136 for (i
= 0; i
< (full
? 16 : 8); i
++)
5137 aarch64_set_vec_s8 (cpu
, vd
, i
,
5138 aarch64_get_vec_s8 (cpu
, vn
, i
)
5139 < aarch64_get_vec_s8 (cpu
, vm
, i
)
5140 ? aarch64_get_vec_s8 (cpu
, vn
, i
)
5141 : aarch64_get_vec_s8 (cpu
, vm
, i
));
5145 for (i
= 0; i
< (full
? 8 : 4); i
++)
5146 aarch64_set_vec_s16 (cpu
, vd
, i
,
5147 aarch64_get_vec_s16 (cpu
, vn
, i
)
5148 < aarch64_get_vec_s16 (cpu
, vm
, i
)
5149 ? aarch64_get_vec_s16 (cpu
, vn
, i
)
5150 : aarch64_get_vec_s16 (cpu
, vm
, i
));
5154 for (i
= 0; i
< (full
? 4 : 2); i
++)
5155 aarch64_set_vec_s32 (cpu
, vd
, i
,
5156 aarch64_get_vec_s32 (cpu
, vn
, i
)
5157 < aarch64_get_vec_s32 (cpu
, vm
, i
)
5158 ? aarch64_get_vec_s32 (cpu
, vn
, i
)
5159 : aarch64_get_vec_s32 (cpu
, vm
, i
));
5169 do_vec_sub_long (sim_cpu
*cpu
)
5172 instr[30] = lower (0) / upper (1)
5173 instr[29] = signed (0) / unsigned (1)
5174 instr[28,24] = 0 1110
5175 instr[23,22] = size: bytes (00), half (01), word (10)
5178 instr[15,10] = 0010 00
5180 instr[4,0] = V dest. */
5182 unsigned size
= INSTR (23, 22);
5183 unsigned vm
= INSTR (20, 16);
5184 unsigned vn
= INSTR (9, 5);
5185 unsigned vd
= INSTR (4, 0);
5189 NYI_assert (28, 24, 0x0E);
5190 NYI_assert (21, 21, 1);
5191 NYI_assert (15, 10, 0x08);
5196 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5197 switch (INSTR (30, 29))
5199 case 2: /* SSUBL2. */
5201 case 0: /* SSUBL. */
5206 for (i
= 0; i
< 8; i
++)
5207 aarch64_set_vec_s16 (cpu
, vd
, i
,
5208 aarch64_get_vec_s8 (cpu
, vn
, i
+ bias
)
5209 - aarch64_get_vec_s8 (cpu
, vm
, i
+ bias
));
5214 for (i
= 0; i
< 4; i
++)
5215 aarch64_set_vec_s32 (cpu
, vd
, i
,
5216 aarch64_get_vec_s16 (cpu
, vn
, i
+ bias
)
5217 - aarch64_get_vec_s16 (cpu
, vm
, i
+ bias
));
5221 for (i
= 0; i
< 2; i
++)
5222 aarch64_set_vec_s64 (cpu
, vd
, i
,
5223 aarch64_get_vec_s32 (cpu
, vn
, i
+ bias
)
5224 - aarch64_get_vec_s32 (cpu
, vm
, i
+ bias
));
5232 case 3: /* USUBL2. */
5234 case 1: /* USUBL. */
5239 for (i
= 0; i
< 8; i
++)
5240 aarch64_set_vec_u16 (cpu
, vd
, i
,
5241 aarch64_get_vec_u8 (cpu
, vn
, i
+ bias
)
5242 - aarch64_get_vec_u8 (cpu
, vm
, i
+ bias
));
5247 for (i
= 0; i
< 4; i
++)
5248 aarch64_set_vec_u32 (cpu
, vd
, i
,
5249 aarch64_get_vec_u16 (cpu
, vn
, i
+ bias
)
5250 - aarch64_get_vec_u16 (cpu
, vm
, i
+ bias
));
5254 for (i
= 0; i
< 2; i
++)
5255 aarch64_set_vec_u64 (cpu
, vd
, i
,
5256 aarch64_get_vec_u32 (cpu
, vn
, i
+ bias
)
5257 - aarch64_get_vec_u32 (cpu
, vm
, i
+ bias
));
5268 do_vec_ADDP (sim_cpu
*cpu
)
5271 instr[30] = half(0)/full(1)
5272 instr[29,24] = 00 1110
5273 instr[23,22] = size: bytes (00), half (01), word (10), long (11)
5276 instr[15,10] = 1011 11
5278 instr[4,0] = V dest. */
5282 unsigned full
= INSTR (30, 30);
5283 unsigned size
= INSTR (23, 22);
5284 unsigned vm
= INSTR (20, 16);
5285 unsigned vn
= INSTR (9, 5);
5286 unsigned vd
= INSTR (4, 0);
5289 NYI_assert (29, 24, 0x0E);
5290 NYI_assert (21, 21, 1);
5291 NYI_assert (15, 10, 0x2F);
5293 /* Make copies of the source registers in case vd == vn/vm. */
5294 copy_vn
= cpu
->fr
[vn
];
5295 copy_vm
= cpu
->fr
[vm
];
5297 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5301 range
= full
? 8 : 4;
5302 for (i
= 0; i
< range
; i
++)
5304 aarch64_set_vec_u8 (cpu
, vd
, i
,
5305 copy_vn
.b
[i
* 2] + copy_vn
.b
[i
* 2 + 1]);
5306 aarch64_set_vec_u8 (cpu
, vd
, i
+ range
,
5307 copy_vm
.b
[i
* 2] + copy_vm
.b
[i
* 2 + 1]);
5312 range
= full
? 4 : 2;
5313 for (i
= 0; i
< range
; i
++)
5315 aarch64_set_vec_u16 (cpu
, vd
, i
,
5316 copy_vn
.h
[i
* 2] + copy_vn
.h
[i
* 2 + 1]);
5317 aarch64_set_vec_u16 (cpu
, vd
, i
+ range
,
5318 copy_vm
.h
[i
* 2] + copy_vm
.h
[i
* 2 + 1]);
5323 range
= full
? 2 : 1;
5324 for (i
= 0; i
< range
; i
++)
5326 aarch64_set_vec_u32 (cpu
, vd
, i
,
5327 copy_vn
.w
[i
* 2] + copy_vn
.w
[i
* 2 + 1]);
5328 aarch64_set_vec_u32 (cpu
, vd
, i
+ range
,
5329 copy_vm
.w
[i
* 2] + copy_vm
.w
[i
* 2 + 1]);
5336 aarch64_set_vec_u64 (cpu
, vd
, 0, copy_vn
.v
[0] + copy_vn
.v
[1]);
5337 aarch64_set_vec_u64 (cpu
, vd
, 1, copy_vm
.v
[0] + copy_vm
.v
[1]);
5343 do_vec_UMOV (sim_cpu
*cpu
)
5346 instr[30] = 32-bit(0)/64-bit(1)
5347 instr[29,21] = 00 1110 000
5348 insrt[20,16] = size & index
5349 instr[15,10] = 0011 11
5350 instr[9,5] = V source
5351 instr[4,0] = R dest. */
5353 unsigned vs
= INSTR (9, 5);
5354 unsigned rd
= INSTR (4, 0);
5357 NYI_assert (29, 21, 0x070);
5358 NYI_assert (15, 10, 0x0F);
5360 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5363 /* Byte transfer. */
5364 index
= INSTR (20, 17);
5365 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
5366 aarch64_get_vec_u8 (cpu
, vs
, index
));
5368 else if (INSTR (17, 17))
5370 index
= INSTR (20, 18);
5371 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
5372 aarch64_get_vec_u16 (cpu
, vs
, index
));
5374 else if (INSTR (18, 18))
5376 index
= INSTR (20, 19);
5377 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
5378 aarch64_get_vec_u32 (cpu
, vs
, index
));
5382 if (INSTR (30, 30) != 1)
5385 index
= INSTR (20, 20);
5386 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
5387 aarch64_get_vec_u64 (cpu
, vs
, index
));
5392 do_vec_FABS (sim_cpu
*cpu
)
5395 instr[30] = half(0)/full(1)
5396 instr[29,23] = 00 1110 1
5397 instr[22] = float(0)/double(1)
5398 instr[21,16] = 10 0000
5399 instr[15,10] = 1111 10
5403 unsigned vn
= INSTR (9, 5);
5404 unsigned vd
= INSTR (4, 0);
5405 unsigned full
= INSTR (30, 30);
5408 NYI_assert (29, 23, 0x1D);
5409 NYI_assert (21, 10, 0x83E);
5411 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5417 for (i
= 0; i
< 2; i
++)
5418 aarch64_set_vec_double (cpu
, vd
, i
,
5419 fabs (aarch64_get_vec_double (cpu
, vn
, i
)));
5423 for (i
= 0; i
< (full
? 4 : 2); i
++)
5424 aarch64_set_vec_float (cpu
, vd
, i
,
5425 fabsf (aarch64_get_vec_float (cpu
, vn
, i
)));
5430 do_vec_FCVTZS (sim_cpu
*cpu
)
5433 instr[30] = half (0) / all (1)
5434 instr[29,23] = 00 1110 1
5435 instr[22] = single (0) / double (1)
5436 instr[21,10] = 10 0001 1011 10
5440 unsigned rn
= INSTR (9, 5);
5441 unsigned rd
= INSTR (4, 0);
5442 unsigned full
= INSTR (30, 30);
5445 NYI_assert (31, 31, 0);
5446 NYI_assert (29, 23, 0x1D);
5447 NYI_assert (21, 10, 0x86E);
5449 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5455 for (i
= 0; i
< 2; i
++)
5456 aarch64_set_vec_s64 (cpu
, rd
, i
,
5457 (int64_t) aarch64_get_vec_double (cpu
, rn
, i
));
5460 for (i
= 0; i
< (full
? 4 : 2); i
++)
5461 aarch64_set_vec_s32 (cpu
, rd
, i
,
5462 (int32_t) aarch64_get_vec_float (cpu
, rn
, i
));
5466 do_vec_REV64 (sim_cpu
*cpu
)
5469 instr[30] = full/half
5470 instr[29,24] = 00 1110
5472 instr[21,10] = 10 0000 0000 10
5476 unsigned rn
= INSTR (9, 5);
5477 unsigned rd
= INSTR (4, 0);
5478 unsigned size
= INSTR (23, 22);
5479 unsigned full
= INSTR (30, 30);
5483 NYI_assert (29, 24, 0x0E);
5484 NYI_assert (21, 10, 0x802);
5486 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5490 for (i
= 0; i
< (full
? 16 : 8); i
++)
5491 val
.b
[i
^ 0x7] = aarch64_get_vec_u8 (cpu
, rn
, i
);
5495 for (i
= 0; i
< (full
? 8 : 4); i
++)
5496 val
.h
[i
^ 0x3] = aarch64_get_vec_u16 (cpu
, rn
, i
);
5500 for (i
= 0; i
< (full
? 4 : 2); i
++)
5501 val
.w
[i
^ 0x1] = aarch64_get_vec_u32 (cpu
, rn
, i
);
5508 aarch64_set_vec_u64 (cpu
, rd
, 0, val
.v
[0]);
5510 aarch64_set_vec_u64 (cpu
, rd
, 1, val
.v
[1]);
5514 do_vec_REV16 (sim_cpu
*cpu
)
5517 instr[30] = full/half
5518 instr[29,24] = 00 1110
5520 instr[21,10] = 10 0000 0001 10
5524 unsigned rn
= INSTR (9, 5);
5525 unsigned rd
= INSTR (4, 0);
5526 unsigned size
= INSTR (23, 22);
5527 unsigned full
= INSTR (30, 30);
5531 NYI_assert (29, 24, 0x0E);
5532 NYI_assert (21, 10, 0x806);
5534 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5538 for (i
= 0; i
< (full
? 16 : 8); i
++)
5539 val
.b
[i
^ 0x1] = aarch64_get_vec_u8 (cpu
, rn
, i
);
5546 aarch64_set_vec_u64 (cpu
, rd
, 0, val
.v
[0]);
5548 aarch64_set_vec_u64 (cpu
, rd
, 1, val
.v
[1]);
5552 do_vec_op1 (sim_cpu
*cpu
)
5555 instr[30] = half/full
5556 instr[29,24] = 00 1110
5559 instr[15,10] = sub-opcode
5562 NYI_assert (29, 24, 0x0E);
5564 if (INSTR (21, 21) == 0)
5566 if (INSTR (23, 22) == 0)
5568 if (INSTR (30, 30) == 1
5569 && INSTR (17, 14) == 0
5570 && INSTR (12, 10) == 7)
5571 return do_vec_ins_2 (cpu
);
5573 switch (INSTR (15, 10))
5575 case 0x01: do_vec_DUP_vector_into_vector (cpu
); return;
5576 case 0x03: do_vec_DUP_scalar_into_vector (cpu
); return;
5577 case 0x07: do_vec_INS (cpu
); return;
5578 case 0x0A: do_vec_TRN (cpu
); return;
5581 if (INSTR (17, 16) == 0)
5583 do_vec_MOV_into_scalar (cpu
);
5592 do_vec_TBL (cpu
); return;
5596 do_vec_UZP (cpu
); return;
5600 do_vec_ZIP (cpu
); return;
5607 switch (INSTR (13, 10))
5609 case 0x6: do_vec_UZP (cpu
); return;
5610 case 0xE: do_vec_ZIP (cpu
); return;
5611 case 0xA: do_vec_TRN (cpu
); return;
5612 case 0xF: do_vec_UMOV (cpu
); return;
5617 switch (INSTR (15, 10))
5619 case 0x02: do_vec_REV64 (cpu
); return;
5620 case 0x06: do_vec_REV16 (cpu
); return;
5623 switch (INSTR (23, 21))
5625 case 1: do_vec_AND (cpu
); return;
5626 case 3: do_vec_BIC (cpu
); return;
5627 case 5: do_vec_ORR (cpu
); return;
5628 case 7: do_vec_ORN (cpu
); return;
5632 case 0x08: do_vec_sub_long (cpu
); return;
5633 case 0x0a: do_vec_XTN (cpu
); return;
5634 case 0x11: do_vec_SSHL (cpu
); return;
5635 case 0x19: do_vec_max (cpu
); return;
5636 case 0x1B: do_vec_min (cpu
); return;
5637 case 0x21: do_vec_add (cpu
); return;
5638 case 0x25: do_vec_MLA (cpu
); return;
5639 case 0x27: do_vec_mul (cpu
); return;
5640 case 0x2F: do_vec_ADDP (cpu
); return;
5641 case 0x30: do_vec_mull (cpu
); return;
5642 case 0x33: do_vec_FMLA (cpu
); return;
5643 case 0x35: do_vec_fadd (cpu
); return;
5646 switch (INSTR (20, 16))
5648 case 0x00: do_vec_ABS (cpu
); return;
5649 case 0x01: do_vec_FCVTZS (cpu
); return;
5650 case 0x11: do_vec_ADDV (cpu
); return;
5656 do_vec_Fminmax (cpu
); return;
5668 do_vec_compare (cpu
); return;
5671 do_vec_FABS (cpu
); return;
5679 do_vec_xtl (sim_cpu
*cpu
)
5682 instr[30,29] = SXTL (00), UXTL (01), SXTL2 (10), UXTL2 (11)
5683 instr[28,22] = 0 1111 00
5684 instr[21,16] = size & shift (USHLL, SSHLL, USHLL2, SSHLL2)
5685 instr[15,10] = 1010 01
5686 instr[9,5] = V source
5687 instr[4,0] = V dest. */
5689 unsigned vs
= INSTR (9, 5);
5690 unsigned vd
= INSTR (4, 0);
5691 unsigned i
, shift
, bias
= 0;
5693 NYI_assert (28, 22, 0x3C);
5694 NYI_assert (15, 10, 0x29);
5696 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5697 switch (INSTR (30, 29))
5699 case 2: /* SXTL2, SSHLL2. */
5701 case 0: /* SXTL, SSHLL. */
5706 shift
= INSTR (20, 16);
5707 /* Get the source values before setting the destination values
5708 in case the source and destination are the same. */
5709 val1
= aarch64_get_vec_s32 (cpu
, vs
, bias
) << shift
;
5710 val2
= aarch64_get_vec_s32 (cpu
, vs
, bias
+ 1) << shift
;
5711 aarch64_set_vec_s64 (cpu
, vd
, 0, val1
);
5712 aarch64_set_vec_s64 (cpu
, vd
, 1, val2
);
5714 else if (INSTR (20, 20))
5717 int32_t v1
,v2
,v3
,v4
;
5719 shift
= INSTR (19, 16);
5721 for (i
= 0; i
< 4; i
++)
5722 v
[i
] = aarch64_get_vec_s16 (cpu
, vs
, bias
+ i
) << shift
;
5723 for (i
= 0; i
< 4; i
++)
5724 aarch64_set_vec_s32 (cpu
, vd
, i
, v
[i
]);
5729 NYI_assert (19, 19, 1);
5731 shift
= INSTR (18, 16);
5733 for (i
= 0; i
< 8; i
++)
5734 v
[i
] = aarch64_get_vec_s8 (cpu
, vs
, i
+ bias
) << shift
;
5735 for (i
= 0; i
< 8; i
++)
5736 aarch64_set_vec_s16 (cpu
, vd
, i
, v
[i
]);
5740 case 3: /* UXTL2, USHLL2. */
5742 case 1: /* UXTL, USHLL. */
5746 shift
= INSTR (20, 16);
5747 v1
= aarch64_get_vec_u32 (cpu
, vs
, bias
) << shift
;
5748 v2
= aarch64_get_vec_u32 (cpu
, vs
, bias
+ 1) << shift
;
5749 aarch64_set_vec_u64 (cpu
, vd
, 0, v1
);
5750 aarch64_set_vec_u64 (cpu
, vd
, 1, v2
);
5752 else if (INSTR (20, 20))
5755 shift
= INSTR (19, 16);
5757 for (i
= 0; i
< 4; i
++)
5758 v
[i
] = aarch64_get_vec_u16 (cpu
, vs
, i
+ bias
) << shift
;
5759 for (i
= 0; i
< 4; i
++)
5760 aarch64_set_vec_u32 (cpu
, vd
, i
, v
[i
]);
5765 NYI_assert (19, 19, 1);
5767 shift
= INSTR (18, 16);
5769 for (i
= 0; i
< 8; i
++)
5770 v
[i
] = aarch64_get_vec_u8 (cpu
, vs
, i
+ bias
) << shift
;
5771 for (i
= 0; i
< 8; i
++)
5772 aarch64_set_vec_u16 (cpu
, vd
, i
, v
[i
]);
5779 do_vec_SHL (sim_cpu
*cpu
)
5782 instr [30] = half(0)/full(1)
5783 instr [29,23] = 001 1110
5784 instr [22,16] = size and shift amount
5785 instr [15,10] = 01 0101
5787 instr [4, 0] = Vd. */
5790 int full
= INSTR (30, 30);
5791 unsigned vs
= INSTR (9, 5);
5792 unsigned vd
= INSTR (4, 0);
5795 NYI_assert (29, 23, 0x1E);
5796 NYI_assert (15, 10, 0x15);
5798 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5801 shift
= INSTR (21, 16);
5806 for (i
= 0; i
< 2; i
++)
5808 uint64_t val
= aarch64_get_vec_u64 (cpu
, vs
, i
);
5809 aarch64_set_vec_u64 (cpu
, vd
, i
, val
<< shift
);
5817 shift
= INSTR (20, 16);
5819 for (i
= 0; i
< (full
? 4 : 2); i
++)
5821 uint32_t val
= aarch64_get_vec_u32 (cpu
, vs
, i
);
5822 aarch64_set_vec_u32 (cpu
, vd
, i
, val
<< shift
);
5830 shift
= INSTR (19, 16);
5832 for (i
= 0; i
< (full
? 8 : 4); i
++)
5834 uint16_t val
= aarch64_get_vec_u16 (cpu
, vs
, i
);
5835 aarch64_set_vec_u16 (cpu
, vd
, i
, val
<< shift
);
5841 if (INSTR (19, 19) == 0)
5844 shift
= INSTR (18, 16);
5846 for (i
= 0; i
< (full
? 16 : 8); i
++)
5848 uint8_t val
= aarch64_get_vec_u8 (cpu
, vs
, i
);
5849 aarch64_set_vec_u8 (cpu
, vd
, i
, val
<< shift
);
5854 do_vec_SSHR_USHR (sim_cpu
*cpu
)
5857 instr [30] = half(0)/full(1)
5858 instr [29] = signed(0)/unsigned(1)
5859 instr [28,23] = 0 1111 0
5860 instr [22,16] = size and shift amount
5861 instr [15,10] = 0000 01
5863 instr [4, 0] = Vd. */
5865 int full
= INSTR (30, 30);
5866 int sign
= ! INSTR (29, 29);
5867 unsigned shift
= INSTR (22, 16);
5868 unsigned vs
= INSTR (9, 5);
5869 unsigned vd
= INSTR (4, 0);
5872 NYI_assert (28, 23, 0x1E);
5873 NYI_assert (15, 10, 0x01);
5875 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5878 shift
= 128 - shift
;
5884 for (i
= 0; i
< 2; i
++)
5886 int64_t val
= aarch64_get_vec_s64 (cpu
, vs
, i
);
5887 aarch64_set_vec_s64 (cpu
, vd
, i
, val
>> shift
);
5890 for (i
= 0; i
< 2; i
++)
5892 uint64_t val
= aarch64_get_vec_u64 (cpu
, vs
, i
);
5893 aarch64_set_vec_u64 (cpu
, vd
, i
, val
>> shift
);
5904 for (i
= 0; i
< (full
? 4 : 2); i
++)
5906 int32_t val
= aarch64_get_vec_s32 (cpu
, vs
, i
);
5907 aarch64_set_vec_s32 (cpu
, vd
, i
, val
>> shift
);
5910 for (i
= 0; i
< (full
? 4 : 2); i
++)
5912 uint32_t val
= aarch64_get_vec_u32 (cpu
, vs
, i
);
5913 aarch64_set_vec_u32 (cpu
, vd
, i
, val
>> shift
);
5924 for (i
= 0; i
< (full
? 8 : 4); i
++)
5926 int16_t val
= aarch64_get_vec_s16 (cpu
, vs
, i
);
5927 aarch64_set_vec_s16 (cpu
, vd
, i
, val
>> shift
);
5930 for (i
= 0; i
< (full
? 8 : 4); i
++)
5932 uint16_t val
= aarch64_get_vec_u16 (cpu
, vs
, i
);
5933 aarch64_set_vec_u16 (cpu
, vd
, i
, val
>> shift
);
5939 if (INSTR (19, 19) == 0)
5945 for (i
= 0; i
< (full
? 16 : 8); i
++)
5947 int8_t val
= aarch64_get_vec_s8 (cpu
, vs
, i
);
5948 aarch64_set_vec_s8 (cpu
, vd
, i
, val
>> shift
);
5951 for (i
= 0; i
< (full
? 16 : 8); i
++)
5953 uint8_t val
= aarch64_get_vec_u8 (cpu
, vs
, i
);
5954 aarch64_set_vec_u8 (cpu
, vd
, i
, val
>> shift
);
5959 do_vec_MUL_by_element (sim_cpu
*cpu
)
5962 instr[30] = half/full
5963 instr[29,24] = 00 1111
5974 unsigned full
= INSTR (30, 30);
5975 unsigned L
= INSTR (21, 21);
5976 unsigned H
= INSTR (11, 11);
5977 unsigned vn
= INSTR (9, 5);
5978 unsigned vd
= INSTR (4, 0);
5979 unsigned size
= INSTR (23, 22);
5984 NYI_assert (29, 24, 0x0F);
5985 NYI_assert (15, 12, 0x8);
5986 NYI_assert (10, 10, 0);
5988 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5993 /* 16 bit products. */
5998 index
= (H
<< 2) | (L
<< 1) | INSTR (20, 20);
5999 vm
= INSTR (19, 16);
6000 element2
= aarch64_get_vec_u16 (cpu
, vm
, index
);
6002 for (e
= 0; e
< (full
? 8 : 4); e
++)
6004 element1
= aarch64_get_vec_u16 (cpu
, vn
, e
);
6005 product
= element1
* element2
;
6006 aarch64_set_vec_u16 (cpu
, vd
, e
, product
);
6013 /* 32 bit products. */
6018 index
= (H
<< 1) | L
;
6019 vm
= INSTR (20, 16);
6020 element2
= aarch64_get_vec_u32 (cpu
, vm
, index
);
6022 for (e
= 0; e
< (full
? 4 : 2); e
++)
6024 element1
= aarch64_get_vec_u32 (cpu
, vn
, e
);
6025 product
= element1
* element2
;
6026 aarch64_set_vec_u32 (cpu
, vd
, e
, product
);
6037 do_FMLA_by_element (sim_cpu
*cpu
)
6040 instr[30] = half/full
6041 instr[29,23] = 00 1111 1
6051 unsigned full
= INSTR (30, 30);
6052 unsigned size
= INSTR (22, 22);
6053 unsigned L
= INSTR (21, 21);
6054 unsigned vm
= INSTR (20, 16);
6055 unsigned H
= INSTR (11, 11);
6056 unsigned vn
= INSTR (9, 5);
6057 unsigned vd
= INSTR (4, 0);
6060 NYI_assert (29, 23, 0x1F);
6061 NYI_assert (15, 12, 0x1);
6062 NYI_assert (10, 10, 0);
6064 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6067 double element1
, element2
;
6072 element2
= aarch64_get_vec_double (cpu
, vm
, H
);
6074 for (e
= 0; e
< 2; e
++)
6076 element1
= aarch64_get_vec_double (cpu
, vn
, e
);
6077 element1
*= element2
;
6078 element1
+= aarch64_get_vec_double (cpu
, vd
, e
);
6079 aarch64_set_vec_double (cpu
, vd
, e
, element1
);
6085 float element2
= aarch64_get_vec_float (cpu
, vm
, (H
<< 1) | L
);
6087 for (e
= 0; e
< (full
? 4 : 2); e
++)
6089 element1
= aarch64_get_vec_float (cpu
, vn
, e
);
6090 element1
*= element2
;
6091 element1
+= aarch64_get_vec_float (cpu
, vd
, e
);
6092 aarch64_set_vec_float (cpu
, vd
, e
, element1
);
6098 do_vec_op2 (sim_cpu
*cpu
)
6101 instr[30] = half/full
6102 instr[29,24] = 00 1111
6104 instr[22,16] = element size & index
6105 instr[15,10] = sub-opcode
6109 NYI_assert (29, 24, 0x0F);
6111 if (INSTR (23, 23) != 0)
6113 switch (INSTR (15, 10))
6117 do_FMLA_by_element (cpu
);
6122 do_vec_MUL_by_element (cpu
);
6131 switch (INSTR (15, 10))
6133 case 0x01: do_vec_SSHR_USHR (cpu
); return;
6134 case 0x15: do_vec_SHL (cpu
); return;
6136 case 0x22: do_vec_MUL_by_element (cpu
); return;
6137 case 0x29: do_vec_xtl (cpu
); return;
6144 do_vec_neg (sim_cpu
*cpu
)
6147 instr[30] = full(1)/half(0)
6148 instr[29,24] = 10 1110
6149 instr[23,22] = size: byte(00), half (01), word (10), long (11)
6150 instr[21,10] = 1000 0010 1110
6154 int full
= INSTR (30, 30);
6155 unsigned vs
= INSTR (9, 5);
6156 unsigned vd
= INSTR (4, 0);
6159 NYI_assert (29, 24, 0x2E);
6160 NYI_assert (21, 10, 0x82E);
6162 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6163 switch (INSTR (23, 22))
6166 for (i
= 0; i
< (full
? 16 : 8); i
++)
6167 aarch64_set_vec_s8 (cpu
, vd
, i
, - aarch64_get_vec_s8 (cpu
, vs
, i
));
6171 for (i
= 0; i
< (full
? 8 : 4); i
++)
6172 aarch64_set_vec_s16 (cpu
, vd
, i
, - aarch64_get_vec_s16 (cpu
, vs
, i
));
6176 for (i
= 0; i
< (full
? 4 : 2); i
++)
6177 aarch64_set_vec_s32 (cpu
, vd
, i
, - aarch64_get_vec_s32 (cpu
, vs
, i
));
6183 for (i
= 0; i
< 2; i
++)
6184 aarch64_set_vec_s64 (cpu
, vd
, i
, - aarch64_get_vec_s64 (cpu
, vs
, i
));
6190 do_vec_sqrt (sim_cpu
*cpu
)
6193 instr[30] = full(1)/half(0)
6194 instr[29,23] = 101 1101
6195 instr[22] = single(0)/double(1)
6196 instr[21,10] = 1000 0111 1110
6200 int full
= INSTR (30, 30);
6201 unsigned vs
= INSTR (9, 5);
6202 unsigned vd
= INSTR (4, 0);
6205 NYI_assert (29, 23, 0x5B);
6206 NYI_assert (21, 10, 0x87E);
6208 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6209 if (INSTR (22, 22) == 0)
6210 for (i
= 0; i
< (full
? 4 : 2); i
++)
6211 aarch64_set_vec_float (cpu
, vd
, i
,
6212 sqrtf (aarch64_get_vec_float (cpu
, vs
, i
)));
6214 for (i
= 0; i
< 2; i
++)
6215 aarch64_set_vec_double (cpu
, vd
, i
,
6216 sqrt (aarch64_get_vec_double (cpu
, vs
, i
)));
6220 do_vec_mls_indexed (sim_cpu
*cpu
)
6223 instr[30] = half(0)/full(1)
6224 instr[29,24] = 10 1111
6225 instr[23,22] = 16-bit(01)/32-bit(10)
6226 instr[21,20+11] = index (if 16-bit)
6227 instr[21+11] = index (if 32-bit)
6230 instr[11] = part of index
6235 int full
= INSTR (30, 30);
6236 unsigned vs
= INSTR (9, 5);
6237 unsigned vd
= INSTR (4, 0);
6238 unsigned vm
= INSTR (20, 16);
6241 NYI_assert (15, 12, 4);
6242 NYI_assert (10, 10, 0);
6244 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6245 switch (INSTR (23, 22))
6255 elem
= (INSTR (21, 20) << 1) | INSTR (11, 11);
6256 val
= aarch64_get_vec_u16 (cpu
, vm
, elem
);
6258 for (i
= 0; i
< (full
? 8 : 4); i
++)
6259 aarch64_set_vec_u32 (cpu
, vd
, i
,
6260 aarch64_get_vec_u32 (cpu
, vd
, i
) -
6261 (aarch64_get_vec_u32 (cpu
, vs
, i
) * val
));
6267 unsigned elem
= (INSTR (21, 21) << 1) | INSTR (11, 11);
6268 uint64_t val
= aarch64_get_vec_u32 (cpu
, vm
, elem
);
6270 for (i
= 0; i
< (full
? 4 : 2); i
++)
6271 aarch64_set_vec_u64 (cpu
, vd
, i
,
6272 aarch64_get_vec_u64 (cpu
, vd
, i
) -
6273 (aarch64_get_vec_u64 (cpu
, vs
, i
) * val
));
6285 do_vec_SUB (sim_cpu
*cpu
)
6288 instr [30] = half(0)/full(1)
6289 instr [29,24] = 10 1110
6290 instr [23,22] = size: byte(00, half(01), word (10), long (11)
6293 instr [15,10] = 10 0001
6295 instr [4, 0] = Vd. */
6297 unsigned full
= INSTR (30, 30);
6298 unsigned vm
= INSTR (20, 16);
6299 unsigned vn
= INSTR (9, 5);
6300 unsigned vd
= INSTR (4, 0);
6303 NYI_assert (29, 24, 0x2E);
6304 NYI_assert (21, 21, 1);
6305 NYI_assert (15, 10, 0x21);
6307 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6308 switch (INSTR (23, 22))
6311 for (i
= 0; i
< (full
? 16 : 8); i
++)
6312 aarch64_set_vec_s8 (cpu
, vd
, i
,
6313 aarch64_get_vec_s8 (cpu
, vn
, i
)
6314 - aarch64_get_vec_s8 (cpu
, vm
, i
));
6318 for (i
= 0; i
< (full
? 8 : 4); i
++)
6319 aarch64_set_vec_s16 (cpu
, vd
, i
,
6320 aarch64_get_vec_s16 (cpu
, vn
, i
)
6321 - aarch64_get_vec_s16 (cpu
, vm
, i
));
6325 for (i
= 0; i
< (full
? 4 : 2); i
++)
6326 aarch64_set_vec_s32 (cpu
, vd
, i
,
6327 aarch64_get_vec_s32 (cpu
, vn
, i
)
6328 - aarch64_get_vec_s32 (cpu
, vm
, i
));
6335 for (i
= 0; i
< 2; i
++)
6336 aarch64_set_vec_s64 (cpu
, vd
, i
,
6337 aarch64_get_vec_s64 (cpu
, vn
, i
)
6338 - aarch64_get_vec_s64 (cpu
, vm
, i
));
6344 do_vec_MLS (sim_cpu
*cpu
)
6347 instr [30] = half(0)/full(1)
6348 instr [29,24] = 10 1110
6349 instr [23,22] = size: byte(00, half(01), word (10)
6352 instr [15,10] = 10 0101
6354 instr [4, 0] = Vd. */
6356 unsigned full
= INSTR (30, 30);
6357 unsigned vm
= INSTR (20, 16);
6358 unsigned vn
= INSTR (9, 5);
6359 unsigned vd
= INSTR (4, 0);
6362 NYI_assert (29, 24, 0x2E);
6363 NYI_assert (21, 21, 1);
6364 NYI_assert (15, 10, 0x25);
6366 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6367 switch (INSTR (23, 22))
6370 for (i
= 0; i
< (full
? 16 : 8); i
++)
6371 aarch64_set_vec_u8 (cpu
, vd
, i
,
6372 (aarch64_get_vec_u8 (cpu
, vn
, i
)
6373 * aarch64_get_vec_u8 (cpu
, vm
, i
))
6374 - aarch64_get_vec_u8 (cpu
, vd
, i
));
6378 for (i
= 0; i
< (full
? 8 : 4); i
++)
6379 aarch64_set_vec_u16 (cpu
, vd
, i
,
6380 (aarch64_get_vec_u16 (cpu
, vn
, i
)
6381 * aarch64_get_vec_u16 (cpu
, vm
, i
))
6382 - aarch64_get_vec_u16 (cpu
, vd
, i
));
6386 for (i
= 0; i
< (full
? 4 : 2); i
++)
6387 aarch64_set_vec_u32 (cpu
, vd
, i
,
6388 (aarch64_get_vec_u32 (cpu
, vn
, i
)
6389 * aarch64_get_vec_u32 (cpu
, vm
, i
))
6390 - aarch64_get_vec_u32 (cpu
, vd
, i
));
6399 do_vec_FDIV (sim_cpu
*cpu
)
6402 instr [30] = half(0)/full(1)
6403 instr [29,23] = 10 1110 0
6404 instr [22] = float()/double(1)
6407 instr [15,10] = 1111 11
6409 instr [4, 0] = Vd. */
6411 unsigned full
= INSTR (30, 30);
6412 unsigned vm
= INSTR (20, 16);
6413 unsigned vn
= INSTR (9, 5);
6414 unsigned vd
= INSTR (4, 0);
6417 NYI_assert (29, 23, 0x5C);
6418 NYI_assert (21, 21, 1);
6419 NYI_assert (15, 10, 0x3F);
6421 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6427 for (i
= 0; i
< 2; i
++)
6428 aarch64_set_vec_double (cpu
, vd
, i
,
6429 aarch64_get_vec_double (cpu
, vn
, i
)
6430 / aarch64_get_vec_double (cpu
, vm
, i
));
6433 for (i
= 0; i
< (full
? 4 : 2); i
++)
6434 aarch64_set_vec_float (cpu
, vd
, i
,
6435 aarch64_get_vec_float (cpu
, vn
, i
)
6436 / aarch64_get_vec_float (cpu
, vm
, i
));
6440 do_vec_FMUL (sim_cpu
*cpu
)
6443 instr [30] = half(0)/full(1)
6444 instr [29,23] = 10 1110 0
6445 instr [22] = float(0)/double(1)
6448 instr [15,10] = 1101 11
6450 instr [4, 0] = Vd. */
6452 unsigned full
= INSTR (30, 30);
6453 unsigned vm
= INSTR (20, 16);
6454 unsigned vn
= INSTR (9, 5);
6455 unsigned vd
= INSTR (4, 0);
6458 NYI_assert (29, 23, 0x5C);
6459 NYI_assert (21, 21, 1);
6460 NYI_assert (15, 10, 0x37);
6462 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6468 for (i
= 0; i
< 2; i
++)
6469 aarch64_set_vec_double (cpu
, vd
, i
,
6470 aarch64_get_vec_double (cpu
, vn
, i
)
6471 * aarch64_get_vec_double (cpu
, vm
, i
));
6474 for (i
= 0; i
< (full
? 4 : 2); i
++)
6475 aarch64_set_vec_float (cpu
, vd
, i
,
6476 aarch64_get_vec_float (cpu
, vn
, i
)
6477 * aarch64_get_vec_float (cpu
, vm
, i
));
6481 do_vec_FADDP (sim_cpu
*cpu
)
6484 instr [30] = half(0)/full(1)
6485 instr [29,23] = 10 1110 0
6486 instr [22] = float(0)/double(1)
6489 instr [15,10] = 1101 01
6491 instr [4, 0] = Vd. */
6493 unsigned full
= INSTR (30, 30);
6494 unsigned vm
= INSTR (20, 16);
6495 unsigned vn
= INSTR (9, 5);
6496 unsigned vd
= INSTR (4, 0);
6498 NYI_assert (29, 23, 0x5C);
6499 NYI_assert (21, 21, 1);
6500 NYI_assert (15, 10, 0x35);
6502 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6505 /* Extract values before adding them incase vd == vn/vm. */
6506 double tmp1
= aarch64_get_vec_double (cpu
, vn
, 0);
6507 double tmp2
= aarch64_get_vec_double (cpu
, vn
, 1);
6508 double tmp3
= aarch64_get_vec_double (cpu
, vm
, 0);
6509 double tmp4
= aarch64_get_vec_double (cpu
, vm
, 1);
6514 aarch64_set_vec_double (cpu
, vd
, 0, tmp1
+ tmp2
);
6515 aarch64_set_vec_double (cpu
, vd
, 1, tmp3
+ tmp4
);
6519 /* Extract values before adding them incase vd == vn/vm. */
6520 float tmp1
= aarch64_get_vec_float (cpu
, vn
, 0);
6521 float tmp2
= aarch64_get_vec_float (cpu
, vn
, 1);
6522 float tmp5
= aarch64_get_vec_float (cpu
, vm
, 0);
6523 float tmp6
= aarch64_get_vec_float (cpu
, vm
, 1);
6527 float tmp3
= aarch64_get_vec_float (cpu
, vn
, 2);
6528 float tmp4
= aarch64_get_vec_float (cpu
, vn
, 3);
6529 float tmp7
= aarch64_get_vec_float (cpu
, vm
, 2);
6530 float tmp8
= aarch64_get_vec_float (cpu
, vm
, 3);
6532 aarch64_set_vec_float (cpu
, vd
, 0, tmp1
+ tmp2
);
6533 aarch64_set_vec_float (cpu
, vd
, 1, tmp3
+ tmp4
);
6534 aarch64_set_vec_float (cpu
, vd
, 2, tmp5
+ tmp6
);
6535 aarch64_set_vec_float (cpu
, vd
, 3, tmp7
+ tmp8
);
6539 aarch64_set_vec_float (cpu
, vd
, 0, tmp1
+ tmp2
);
6540 aarch64_set_vec_float (cpu
, vd
, 1, tmp5
+ tmp6
);
6546 do_vec_FSQRT (sim_cpu
*cpu
)
6549 instr[30] = half(0)/full(1)
6550 instr[29,23] = 10 1110 1
6551 instr[22] = single(0)/double(1)
6552 instr[21,10] = 10 0001 1111 10
6554 instr[4,0] = Vdest. */
6556 unsigned vn
= INSTR (9, 5);
6557 unsigned vd
= INSTR (4, 0);
6558 unsigned full
= INSTR (30, 30);
6561 NYI_assert (29, 23, 0x5D);
6562 NYI_assert (21, 10, 0x87E);
6564 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6570 for (i
= 0; i
< 2; i
++)
6571 aarch64_set_vec_double (cpu
, vd
, i
,
6572 sqrt (aarch64_get_vec_double (cpu
, vn
, i
)));
6576 for (i
= 0; i
< (full
? 4 : 2); i
++)
6577 aarch64_set_vec_float (cpu
, vd
, i
,
6578 sqrtf (aarch64_get_vec_float (cpu
, vn
, i
)));
6583 do_vec_FNEG (sim_cpu
*cpu
)
6586 instr[30] = half (0)/full (1)
6587 instr[29,23] = 10 1110 1
6588 instr[22] = single (0)/double (1)
6589 instr[21,10] = 10 0000 1111 10
6591 instr[4,0] = Vdest. */
6593 unsigned vn
= INSTR (9, 5);
6594 unsigned vd
= INSTR (4, 0);
6595 unsigned full
= INSTR (30, 30);
6598 NYI_assert (29, 23, 0x5D);
6599 NYI_assert (21, 10, 0x83E);
6601 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6607 for (i
= 0; i
< 2; i
++)
6608 aarch64_set_vec_double (cpu
, vd
, i
,
6609 - aarch64_get_vec_double (cpu
, vn
, i
));
6613 for (i
= 0; i
< (full
? 4 : 2); i
++)
6614 aarch64_set_vec_float (cpu
, vd
, i
,
6615 - aarch64_get_vec_float (cpu
, vn
, i
));
6620 do_vec_NOT (sim_cpu
*cpu
)
6623 instr[30] = half (0)/full (1)
6624 instr[29,10] = 10 1110 0010 0000 0101 10
6628 unsigned vn
= INSTR (9, 5);
6629 unsigned vd
= INSTR (4, 0);
6631 int full
= INSTR (30, 30);
6633 NYI_assert (29, 10, 0xB8816);
6635 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6636 for (i
= 0; i
< (full
? 16 : 8); i
++)
6637 aarch64_set_vec_u8 (cpu
, vd
, i
, ~ aarch64_get_vec_u8 (cpu
, vn
, i
));
6641 clz (uint64_t val
, unsigned size
)
6646 mask
<<= (size
- 1);
6661 do_vec_CLZ (sim_cpu
*cpu
)
6664 instr[30] = half (0)/full (1)
6665 instr[29,24] = 10 1110
6667 instr[21,10] = 10 0000 0100 10
6671 unsigned vn
= INSTR (9, 5);
6672 unsigned vd
= INSTR (4, 0);
6674 int full
= INSTR (30,30);
6676 NYI_assert (29, 24, 0x2E);
6677 NYI_assert (21, 10, 0x812);
6679 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6680 switch (INSTR (23, 22))
6683 for (i
= 0; i
< (full
? 16 : 8); i
++)
6684 aarch64_set_vec_u8 (cpu
, vd
, i
, clz (aarch64_get_vec_u8 (cpu
, vn
, i
), 8));
6687 for (i
= 0; i
< (full
? 8 : 4); i
++)
6688 aarch64_set_vec_u16 (cpu
, vd
, i
, clz (aarch64_get_vec_u16 (cpu
, vn
, i
), 16));
6691 for (i
= 0; i
< (full
? 4 : 2); i
++)
6692 aarch64_set_vec_u32 (cpu
, vd
, i
, clz (aarch64_get_vec_u32 (cpu
, vn
, i
), 32));
6697 aarch64_set_vec_u64 (cpu
, vd
, 0, clz (aarch64_get_vec_u64 (cpu
, vn
, 0), 64));
6698 aarch64_set_vec_u64 (cpu
, vd
, 1, clz (aarch64_get_vec_u64 (cpu
, vn
, 1), 64));
6704 do_vec_MOV_element (sim_cpu
*cpu
)
6706 /* instr[31,21] = 0110 1110 000
6707 instr[20,16] = size & dest index
6709 instr[14,11] = source index
6714 unsigned vs
= INSTR (9, 5);
6715 unsigned vd
= INSTR (4, 0);
6719 NYI_assert (31, 21, 0x370);
6720 NYI_assert (15, 15, 0);
6721 NYI_assert (10, 10, 1);
6723 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6727 src_index
= INSTR (14, 11);
6728 dst_index
= INSTR (20, 17);
6729 aarch64_set_vec_u8 (cpu
, vd
, dst_index
,
6730 aarch64_get_vec_u8 (cpu
, vs
, src_index
));
6732 else if (INSTR (17, 17))
6735 NYI_assert (11, 11, 0);
6736 src_index
= INSTR (14, 12);
6737 dst_index
= INSTR (20, 18);
6738 aarch64_set_vec_u16 (cpu
, vd
, dst_index
,
6739 aarch64_get_vec_u16 (cpu
, vs
, src_index
));
6741 else if (INSTR (18, 18))
6744 NYI_assert (12, 11, 0);
6745 src_index
= INSTR (14, 13);
6746 dst_index
= INSTR (20, 19);
6747 aarch64_set_vec_u32 (cpu
, vd
, dst_index
,
6748 aarch64_get_vec_u32 (cpu
, vs
, src_index
));
6752 NYI_assert (19, 19, 1);
6753 NYI_assert (13, 11, 0);
6754 src_index
= INSTR (14, 14);
6755 dst_index
= INSTR (20, 20);
6756 aarch64_set_vec_u64 (cpu
, vd
, dst_index
,
6757 aarch64_get_vec_u64 (cpu
, vs
, src_index
));
6762 do_vec_REV32 (sim_cpu
*cpu
)
6765 instr[30] = full/half
6766 instr[29,24] = 10 1110
6768 instr[21,10] = 10 0000 0000 10
6772 unsigned rn
= INSTR (9, 5);
6773 unsigned rd
= INSTR (4, 0);
6774 unsigned size
= INSTR (23, 22);
6775 unsigned full
= INSTR (30, 30);
6779 NYI_assert (29, 24, 0x2E);
6780 NYI_assert (21, 10, 0x802);
6782 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6786 for (i
= 0; i
< (full
? 16 : 8); i
++)
6787 val
.b
[i
^ 0x3] = aarch64_get_vec_u8 (cpu
, rn
, i
);
6791 for (i
= 0; i
< (full
? 8 : 4); i
++)
6792 val
.h
[i
^ 0x1] = aarch64_get_vec_u16 (cpu
, rn
, i
);
6799 aarch64_set_vec_u64 (cpu
, rd
, 0, val
.v
[0]);
6801 aarch64_set_vec_u64 (cpu
, rd
, 1, val
.v
[1]);
6805 do_vec_EXT (sim_cpu
*cpu
)
6808 instr[30] = full/half
6809 instr[29,21] = 10 1110 000
6812 instr[14,11] = source index
6817 unsigned vm
= INSTR (20, 16);
6818 unsigned vn
= INSTR (9, 5);
6819 unsigned vd
= INSTR (4, 0);
6820 unsigned src_index
= INSTR (14, 11);
6821 unsigned full
= INSTR (30, 30);
6826 NYI_assert (31, 21, 0x370);
6827 NYI_assert (15, 15, 0);
6828 NYI_assert (10, 10, 0);
6830 if (!full
&& (src_index
& 0x8))
6835 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6836 for (i
= src_index
; i
< (full
? 16 : 8); i
++)
6837 val
.b
[j
++] = aarch64_get_vec_u8 (cpu
, vn
, i
);
6838 for (i
= 0; i
< src_index
; i
++)
6839 val
.b
[j
++] = aarch64_get_vec_u8 (cpu
, vm
, i
);
6841 aarch64_set_vec_u64 (cpu
, vd
, 0, val
.v
[0]);
6843 aarch64_set_vec_u64 (cpu
, vd
, 1, val
.v
[1]);
6847 dexAdvSIMD0 (sim_cpu
*cpu
)
6849 /* instr [28,25] = 0 111. */
6850 if ( INSTR (15, 10) == 0x07
6854 if (INSTR (31, 21) == 0x075
6855 || INSTR (31, 21) == 0x275)
6857 do_vec_MOV_whole_vector (cpu
);
6862 if (INSTR (29, 19) == 0x1E0)
6864 do_vec_MOV_immediate (cpu
);
6868 if (INSTR (29, 19) == 0x5E0)
6874 if (INSTR (29, 19) == 0x1C0
6875 || INSTR (29, 19) == 0x1C1)
6877 if (INSTR (15, 10) == 0x03)
6879 do_vec_DUP_scalar_into_vector (cpu
);
6884 switch (INSTR (29, 24))
6886 case 0x0E: do_vec_op1 (cpu
); return;
6887 case 0x0F: do_vec_op2 (cpu
); return;
6890 if (INSTR (21, 21) == 1)
6892 switch (INSTR (15, 10))
6899 switch (INSTR (23, 22))
6901 case 0: do_vec_EOR (cpu
); return;
6902 case 1: do_vec_BSL (cpu
); return;
6904 case 3: do_vec_bit (cpu
); return;
6908 case 0x08: do_vec_sub_long (cpu
); return;
6909 case 0x11: do_vec_USHL (cpu
); return;
6910 case 0x12: do_vec_CLZ (cpu
); return;
6911 case 0x16: do_vec_NOT (cpu
); return;
6912 case 0x19: do_vec_max (cpu
); return;
6913 case 0x1B: do_vec_min (cpu
); return;
6914 case 0x21: do_vec_SUB (cpu
); return;
6915 case 0x25: do_vec_MLS (cpu
); return;
6916 case 0x31: do_vec_FminmaxNMP (cpu
); return;
6917 case 0x35: do_vec_FADDP (cpu
); return;
6918 case 0x37: do_vec_FMUL (cpu
); return;
6919 case 0x3F: do_vec_FDIV (cpu
); return;
6922 switch (INSTR (20, 16))
6924 case 0x00: do_vec_FNEG (cpu
); return;
6925 case 0x01: do_vec_FSQRT (cpu
); return;
6939 do_vec_compare (cpu
); return;
6946 if (INSTR (31, 21) == 0x370)
6949 do_vec_MOV_element (cpu
);
6955 switch (INSTR (21, 10))
6957 case 0x82E: do_vec_neg (cpu
); return;
6958 case 0x87E: do_vec_sqrt (cpu
); return;
6960 if (INSTR (15, 10) == 0x30)
6970 switch (INSTR (15, 10))
6972 case 0x01: do_vec_SSHR_USHR (cpu
); return;
6974 case 0x12: do_vec_mls_indexed (cpu
); return;
6975 case 0x29: do_vec_xtl (cpu
); return;
6989 /* Float multiply add. */
6991 fmadds (sim_cpu
*cpu
)
6993 unsigned sa
= INSTR (14, 10);
6994 unsigned sm
= INSTR (20, 16);
6995 unsigned sn
= INSTR ( 9, 5);
6996 unsigned sd
= INSTR ( 4, 0);
6998 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6999 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sa
)
7000 + aarch64_get_FP_float (cpu
, sn
)
7001 * aarch64_get_FP_float (cpu
, sm
));
7004 /* Double multiply add. */
7006 fmaddd (sim_cpu
*cpu
)
7008 unsigned sa
= INSTR (14, 10);
7009 unsigned sm
= INSTR (20, 16);
7010 unsigned sn
= INSTR ( 9, 5);
7011 unsigned sd
= INSTR ( 4, 0);
7013 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7014 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sa
)
7015 + aarch64_get_FP_double (cpu
, sn
)
7016 * aarch64_get_FP_double (cpu
, sm
));
7019 /* Float multiply subtract. */
7021 fmsubs (sim_cpu
*cpu
)
7023 unsigned sa
= INSTR (14, 10);
7024 unsigned sm
= INSTR (20, 16);
7025 unsigned sn
= INSTR ( 9, 5);
7026 unsigned sd
= INSTR ( 4, 0);
7028 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7029 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sa
)
7030 - aarch64_get_FP_float (cpu
, sn
)
7031 * aarch64_get_FP_float (cpu
, sm
));
7034 /* Double multiply subtract. */
7036 fmsubd (sim_cpu
*cpu
)
7038 unsigned sa
= INSTR (14, 10);
7039 unsigned sm
= INSTR (20, 16);
7040 unsigned sn
= INSTR ( 9, 5);
7041 unsigned sd
= INSTR ( 4, 0);
7043 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7044 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sa
)
7045 - aarch64_get_FP_double (cpu
, sn
)
7046 * aarch64_get_FP_double (cpu
, sm
));
7049 /* Float negative multiply add. */
7051 fnmadds (sim_cpu
*cpu
)
7053 unsigned sa
= INSTR (14, 10);
7054 unsigned sm
= INSTR (20, 16);
7055 unsigned sn
= INSTR ( 9, 5);
7056 unsigned sd
= INSTR ( 4, 0);
7058 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7059 aarch64_set_FP_float (cpu
, sd
, - aarch64_get_FP_float (cpu
, sa
)
7060 + (- aarch64_get_FP_float (cpu
, sn
))
7061 * aarch64_get_FP_float (cpu
, sm
));
7064 /* Double negative multiply add. */
7066 fnmaddd (sim_cpu
*cpu
)
7068 unsigned sa
= INSTR (14, 10);
7069 unsigned sm
= INSTR (20, 16);
7070 unsigned sn
= INSTR ( 9, 5);
7071 unsigned sd
= INSTR ( 4, 0);
7073 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7074 aarch64_set_FP_double (cpu
, sd
, - aarch64_get_FP_double (cpu
, sa
)
7075 + (- aarch64_get_FP_double (cpu
, sn
))
7076 * aarch64_get_FP_double (cpu
, sm
));
7079 /* Float negative multiply subtract. */
7081 fnmsubs (sim_cpu
*cpu
)
7083 unsigned sa
= INSTR (14, 10);
7084 unsigned sm
= INSTR (20, 16);
7085 unsigned sn
= INSTR ( 9, 5);
7086 unsigned sd
= INSTR ( 4, 0);
7088 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7089 aarch64_set_FP_float (cpu
, sd
, - aarch64_get_FP_float (cpu
, sa
)
7090 + aarch64_get_FP_float (cpu
, sn
)
7091 * aarch64_get_FP_float (cpu
, sm
));
7094 /* Double negative multiply subtract. */
7096 fnmsubd (sim_cpu
*cpu
)
7098 unsigned sa
= INSTR (14, 10);
7099 unsigned sm
= INSTR (20, 16);
7100 unsigned sn
= INSTR ( 9, 5);
7101 unsigned sd
= INSTR ( 4, 0);
7103 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7104 aarch64_set_FP_double (cpu
, sd
, - aarch64_get_FP_double (cpu
, sa
)
7105 + aarch64_get_FP_double (cpu
, sn
)
7106 * aarch64_get_FP_double (cpu
, sm
));
7110 dexSimpleFPDataProc3Source (sim_cpu
*cpu
)
7112 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
7114 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
7117 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
7118 instr[21] ==> o1 : 0 ==> unnegated, 1 ==> negated
7119 instr[15] ==> o2 : 0 ==> ADD, 1 ==> SUB */
7121 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
7122 /* dispatch on combined type:o1:o2. */
7123 uint32_t dispatch
= (INSTR (23, 21) << 1) | INSTR (15, 15);
7130 case 0: fmadds (cpu
); return;
7131 case 1: fmsubs (cpu
); return;
7132 case 2: fnmadds (cpu
); return;
7133 case 3: fnmsubs (cpu
); return;
7134 case 4: fmaddd (cpu
); return;
7135 case 5: fmsubd (cpu
); return;
7136 case 6: fnmaddd (cpu
); return;
7137 case 7: fnmsubd (cpu
); return;
7139 /* type > 1 is currently unallocated. */
7145 dexSimpleFPFixedConvert (sim_cpu
*cpu
)
7151 dexSimpleFPCondCompare (sim_cpu
*cpu
)
7153 /* instr [31,23] = 0001 1110 0
7157 instr [15,12] = condition
7161 instr [3,0] = nzcv */
7163 unsigned rm
= INSTR (20, 16);
7164 unsigned rn
= INSTR (9, 5);
7166 NYI_assert (31, 23, 0x3C);
7167 NYI_assert (11, 10, 0x1);
7168 NYI_assert (4, 4, 0);
7170 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7171 if (! testConditionCode (cpu
, INSTR (15, 12)))
7173 aarch64_set_CPSR (cpu
, INSTR (3, 0));
7179 /* Double precision. */
7180 double val1
= aarch64_get_vec_double (cpu
, rn
, 0);
7181 double val2
= aarch64_get_vec_double (cpu
, rm
, 0);
7183 /* FIXME: Check for NaNs. */
7185 aarch64_set_CPSR (cpu
, (Z
| C
));
7186 else if (val1
< val2
)
7187 aarch64_set_CPSR (cpu
, N
);
7188 else /* val1 > val2 */
7189 aarch64_set_CPSR (cpu
, C
);
7193 /* Single precision. */
7194 float val1
= aarch64_get_vec_float (cpu
, rn
, 0);
7195 float val2
= aarch64_get_vec_float (cpu
, rm
, 0);
7197 /* FIXME: Check for NaNs. */
7199 aarch64_set_CPSR (cpu
, (Z
| C
));
7200 else if (val1
< val2
)
7201 aarch64_set_CPSR (cpu
, N
);
7202 else /* val1 > val2 */
7203 aarch64_set_CPSR (cpu
, C
);
7211 fadds (sim_cpu
*cpu
)
7213 unsigned sm
= INSTR (20, 16);
7214 unsigned sn
= INSTR ( 9, 5);
7215 unsigned sd
= INSTR ( 4, 0);
7217 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7218 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
7219 + aarch64_get_FP_float (cpu
, sm
));
7224 faddd (sim_cpu
*cpu
)
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
, sn
)
7232 + aarch64_get_FP_double (cpu
, sm
));
7237 fdivs (sim_cpu
*cpu
)
7239 unsigned sm
= INSTR (20, 16);
7240 unsigned sn
= INSTR ( 9, 5);
7241 unsigned sd
= INSTR ( 4, 0);
7243 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7244 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
7245 / aarch64_get_FP_float (cpu
, sm
));
7248 /* Double divide. */
7250 fdivd (sim_cpu
*cpu
)
7252 unsigned sm
= INSTR (20, 16);
7253 unsigned sn
= INSTR ( 9, 5);
7254 unsigned sd
= INSTR ( 4, 0);
7256 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7257 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
7258 / aarch64_get_FP_double (cpu
, sm
));
7261 /* Float multiply. */
7263 fmuls (sim_cpu
*cpu
)
7265 unsigned sm
= INSTR (20, 16);
7266 unsigned sn
= INSTR ( 9, 5);
7267 unsigned sd
= INSTR ( 4, 0);
7269 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7270 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
7271 * aarch64_get_FP_float (cpu
, sm
));
7274 /* Double multiply. */
7276 fmuld (sim_cpu
*cpu
)
7278 unsigned sm
= INSTR (20, 16);
7279 unsigned sn
= INSTR ( 9, 5);
7280 unsigned sd
= INSTR ( 4, 0);
7282 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7283 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
7284 * aarch64_get_FP_double (cpu
, sm
));
7287 /* Float negate and multiply. */
7289 fnmuls (sim_cpu
*cpu
)
7291 unsigned sm
= INSTR (20, 16);
7292 unsigned sn
= INSTR ( 9, 5);
7293 unsigned sd
= INSTR ( 4, 0);
7295 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7296 aarch64_set_FP_float (cpu
, sd
, - (aarch64_get_FP_float (cpu
, sn
)
7297 * aarch64_get_FP_float (cpu
, sm
)));
7300 /* Double negate and multiply. */
7302 fnmuld (sim_cpu
*cpu
)
7304 unsigned sm
= INSTR (20, 16);
7305 unsigned sn
= INSTR ( 9, 5);
7306 unsigned sd
= INSTR ( 4, 0);
7308 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7309 aarch64_set_FP_double (cpu
, sd
, - (aarch64_get_FP_double (cpu
, sn
)
7310 * aarch64_get_FP_double (cpu
, sm
)));
7313 /* Float subtract. */
7315 fsubs (sim_cpu
*cpu
)
7317 unsigned sm
= INSTR (20, 16);
7318 unsigned sn
= INSTR ( 9, 5);
7319 unsigned sd
= INSTR ( 4, 0);
7321 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7322 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
7323 - aarch64_get_FP_float (cpu
, sm
));
7326 /* Double subtract. */
7328 fsubd (sim_cpu
*cpu
)
7330 unsigned sm
= INSTR (20, 16);
7331 unsigned sn
= INSTR ( 9, 5);
7332 unsigned sd
= INSTR ( 4, 0);
7334 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7335 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
7336 - aarch64_get_FP_double (cpu
, sm
));
7340 do_FMINNM (sim_cpu
*cpu
)
7342 /* instr[31,23] = 0 0011 1100
7343 instr[22] = float(0)/double(1)
7346 instr[15,10] = 01 1110
7350 unsigned sm
= INSTR (20, 16);
7351 unsigned sn
= INSTR ( 9, 5);
7352 unsigned sd
= INSTR ( 4, 0);
7354 NYI_assert (31, 23, 0x03C);
7355 NYI_assert (15, 10, 0x1E);
7357 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7359 aarch64_set_FP_double (cpu
, sd
,
7360 dminnm (aarch64_get_FP_double (cpu
, sn
),
7361 aarch64_get_FP_double (cpu
, sm
)));
7363 aarch64_set_FP_float (cpu
, sd
,
7364 fminnm (aarch64_get_FP_float (cpu
, sn
),
7365 aarch64_get_FP_float (cpu
, sm
)));
7369 do_FMAXNM (sim_cpu
*cpu
)
7371 /* instr[31,23] = 0 0011 1100
7372 instr[22] = float(0)/double(1)
7375 instr[15,10] = 01 1010
7379 unsigned sm
= INSTR (20, 16);
7380 unsigned sn
= INSTR ( 9, 5);
7381 unsigned sd
= INSTR ( 4, 0);
7383 NYI_assert (31, 23, 0x03C);
7384 NYI_assert (15, 10, 0x1A);
7386 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7388 aarch64_set_FP_double (cpu
, sd
,
7389 dmaxnm (aarch64_get_FP_double (cpu
, sn
),
7390 aarch64_get_FP_double (cpu
, sm
)));
7392 aarch64_set_FP_float (cpu
, sd
,
7393 fmaxnm (aarch64_get_FP_float (cpu
, sn
),
7394 aarch64_get_FP_float (cpu
, sm
)));
7398 dexSimpleFPDataProc2Source (sim_cpu
*cpu
)
7400 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
7402 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
7405 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
7408 instr[15,12] ==> opcode : 0000 ==> FMUL, 0001 ==> FDIV
7409 0010 ==> FADD, 0011 ==> FSUB,
7410 0100 ==> FMAX, 0101 ==> FMIN
7411 0110 ==> FMAXNM, 0111 ==> FMINNM
7412 1000 ==> FNMUL, ow ==> UNALLOC
7417 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
7418 uint32_t type
= INSTR (23, 22);
7419 /* Dispatch on opcode. */
7420 uint32_t dispatch
= INSTR (15, 12);
7431 case 0: fmuld (cpu
); return;
7432 case 1: fdivd (cpu
); return;
7433 case 2: faddd (cpu
); return;
7434 case 3: fsubd (cpu
); return;
7435 case 6: do_FMAXNM (cpu
); return;
7436 case 7: do_FMINNM (cpu
); return;
7437 case 8: fnmuld (cpu
); return;
7439 /* Have not yet implemented fmax and fmin. */
7447 else /* type == 0 => floats. */
7450 case 0: fmuls (cpu
); return;
7451 case 1: fdivs (cpu
); return;
7452 case 2: fadds (cpu
); return;
7453 case 3: fsubs (cpu
); return;
7454 case 6: do_FMAXNM (cpu
); return;
7455 case 7: do_FMINNM (cpu
); return;
7456 case 8: fnmuls (cpu
); return;
7468 dexSimpleFPCondSelect (sim_cpu
*cpu
)
7471 instr[31,23] = 0 0011 1100
7472 instr[22] = 0=>single 1=>double
7479 unsigned sm
= INSTR (20, 16);
7480 unsigned sn
= INSTR ( 9, 5);
7481 unsigned sd
= INSTR ( 4, 0);
7482 uint32_t set
= testConditionCode (cpu
, INSTR (15, 12));
7484 NYI_assert (31, 23, 0x03C);
7485 NYI_assert (11, 10, 0x3);
7487 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7489 aarch64_set_FP_double (cpu
, sd
, set
? sn
: sm
);
7491 aarch64_set_FP_float (cpu
, sd
, set
? sn
: sm
);
7494 /* Store 32 bit unscaled signed 9 bit. */
7496 fsturs (sim_cpu
*cpu
, int32_t offset
)
7498 unsigned int rn
= INSTR (9, 5);
7499 unsigned int st
= INSTR (4, 0);
7501 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7502 aarch64_set_mem_u32 (cpu
, aarch64_get_reg_u64 (cpu
, st
, 1) + offset
,
7503 aarch64_get_vec_u32 (cpu
, rn
, 0));
7506 /* Store 64 bit unscaled signed 9 bit. */
7508 fsturd (sim_cpu
*cpu
, int32_t offset
)
7510 unsigned int rn
= INSTR (9, 5);
7511 unsigned int st
= INSTR (4, 0);
7513 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7514 aarch64_set_mem_u64 (cpu
, aarch64_get_reg_u64 (cpu
, st
, 1) + offset
,
7515 aarch64_get_vec_u64 (cpu
, rn
, 0));
7518 /* Store 128 bit unscaled signed 9 bit. */
7520 fsturq (sim_cpu
*cpu
, int32_t offset
)
7522 unsigned int rn
= INSTR (9, 5);
7523 unsigned int st
= INSTR (4, 0);
7526 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7527 aarch64_get_FP_long_double (cpu
, rn
, & a
);
7528 aarch64_set_mem_long_double (cpu
,
7529 aarch64_get_reg_u64 (cpu
, st
, 1)
7533 /* TODO FP move register. */
7535 /* 32 bit fp to fp move register. */
7537 ffmovs (sim_cpu
*cpu
)
7539 unsigned int rn
= INSTR (9, 5);
7540 unsigned int st
= INSTR (4, 0);
7542 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7543 aarch64_set_FP_float (cpu
, st
, aarch64_get_FP_float (cpu
, rn
));
7546 /* 64 bit fp to fp move register. */
7548 ffmovd (sim_cpu
*cpu
)
7550 unsigned int rn
= INSTR (9, 5);
7551 unsigned int st
= INSTR (4, 0);
7553 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7554 aarch64_set_FP_double (cpu
, st
, aarch64_get_FP_double (cpu
, rn
));
7557 /* 32 bit GReg to Vec move register. */
7559 fgmovs (sim_cpu
*cpu
)
7561 unsigned int rn
= INSTR (9, 5);
7562 unsigned int st
= INSTR (4, 0);
7564 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7565 aarch64_set_vec_u32 (cpu
, st
, 0, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
));
7568 /* 64 bit g to fp move register. */
7570 fgmovd (sim_cpu
*cpu
)
7572 unsigned int rn
= INSTR (9, 5);
7573 unsigned int st
= INSTR (4, 0);
7575 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7576 aarch64_set_vec_u64 (cpu
, st
, 0, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
7579 /* 32 bit fp to g move register. */
7581 gfmovs (sim_cpu
*cpu
)
7583 unsigned int rn
= INSTR (9, 5);
7584 unsigned int st
= INSTR (4, 0);
7586 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7587 aarch64_set_reg_u64 (cpu
, st
, NO_SP
, aarch64_get_vec_u32 (cpu
, rn
, 0));
7590 /* 64 bit fp to g move register. */
7592 gfmovd (sim_cpu
*cpu
)
7594 unsigned int rn
= INSTR (9, 5);
7595 unsigned int st
= INSTR (4, 0);
7597 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7598 aarch64_set_reg_u64 (cpu
, st
, NO_SP
, aarch64_get_vec_u64 (cpu
, rn
, 0));
7601 /* FP move immediate
7603 These install an immediate 8 bit value in the target register
7604 where the 8 bits comprise 1 sign bit, 4 bits of fraction and a 3
7608 fmovs (sim_cpu
*cpu
)
7610 unsigned int sd
= INSTR (4, 0);
7611 uint32_t imm
= INSTR (20, 13);
7612 float f
= fp_immediate_for_encoding_32 (imm
);
7614 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7615 aarch64_set_FP_float (cpu
, sd
, f
);
7619 fmovd (sim_cpu
*cpu
)
7621 unsigned int sd
= INSTR (4, 0);
7622 uint32_t imm
= INSTR (20, 13);
7623 double d
= fp_immediate_for_encoding_64 (imm
);
7625 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7626 aarch64_set_FP_double (cpu
, sd
, d
);
7630 dexSimpleFPImmediate (sim_cpu
*cpu
)
7632 /* instr[31,23] == 00111100
7633 instr[22] == type : single(0)/double(1)
7635 instr[20,13] == imm8
7637 instr[9,5] == imm5 : 00000 ==> PK, ow ==> UNALLOC
7639 uint32_t imm5
= INSTR (9, 5);
7641 NYI_assert (31, 23, 0x3C);
7652 /* TODO specific decode and execute for group Load Store. */
7654 /* TODO FP load/store single register (unscaled offset). */
7656 /* TODO load 8 bit unscaled signed 9 bit. */
7657 /* TODO load 16 bit unscaled signed 9 bit. */
7659 /* Load 32 bit unscaled signed 9 bit. */
7661 fldurs (sim_cpu
*cpu
, int32_t offset
)
7663 unsigned int rn
= INSTR (9, 5);
7664 unsigned int st
= INSTR (4, 0);
7666 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7667 aarch64_set_vec_u32 (cpu
, st
, 0, aarch64_get_mem_u32
7668 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
));
7671 /* Load 64 bit unscaled signed 9 bit. */
7673 fldurd (sim_cpu
*cpu
, int32_t offset
)
7675 unsigned int rn
= INSTR (9, 5);
7676 unsigned int st
= INSTR (4, 0);
7678 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7679 aarch64_set_vec_u64 (cpu
, st
, 0, aarch64_get_mem_u64
7680 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
));
7683 /* Load 128 bit unscaled signed 9 bit. */
7685 fldurq (sim_cpu
*cpu
, int32_t offset
)
7687 unsigned int rn
= INSTR (9, 5);
7688 unsigned int st
= INSTR (4, 0);
7690 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
;
7692 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7693 aarch64_get_mem_long_double (cpu
, addr
, & a
);
7694 aarch64_set_FP_long_double (cpu
, st
, a
);
7697 /* TODO store 8 bit unscaled signed 9 bit. */
7698 /* TODO store 16 bit unscaled signed 9 bit. */
7703 /* Float absolute value. */
7705 fabss (sim_cpu
*cpu
)
7707 unsigned sn
= INSTR (9, 5);
7708 unsigned sd
= INSTR (4, 0);
7709 float value
= aarch64_get_FP_float (cpu
, sn
);
7711 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7712 aarch64_set_FP_float (cpu
, sd
, fabsf (value
));
7715 /* Double absolute value. */
7717 fabcpu (sim_cpu
*cpu
)
7719 unsigned sn
= INSTR (9, 5);
7720 unsigned sd
= INSTR (4, 0);
7721 double value
= aarch64_get_FP_double (cpu
, sn
);
7723 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7724 aarch64_set_FP_double (cpu
, sd
, fabs (value
));
7727 /* Float negative value. */
7729 fnegs (sim_cpu
*cpu
)
7731 unsigned sn
= INSTR (9, 5);
7732 unsigned sd
= INSTR (4, 0);
7734 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7735 aarch64_set_FP_float (cpu
, sd
, - aarch64_get_FP_float (cpu
, sn
));
7738 /* Double negative value. */
7740 fnegd (sim_cpu
*cpu
)
7742 unsigned sn
= INSTR (9, 5);
7743 unsigned sd
= INSTR (4, 0);
7745 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7746 aarch64_set_FP_double (cpu
, sd
, - aarch64_get_FP_double (cpu
, sn
));
7749 /* Float square root. */
7751 fsqrts (sim_cpu
*cpu
)
7753 unsigned sn
= INSTR (9, 5);
7754 unsigned sd
= INSTR (4, 0);
7756 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7757 aarch64_set_FP_float (cpu
, sd
, sqrt (aarch64_get_FP_float (cpu
, sn
)));
7760 /* Double square root. */
7762 fsqrtd (sim_cpu
*cpu
)
7764 unsigned sn
= INSTR (9, 5);
7765 unsigned sd
= INSTR (4, 0);
7767 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7768 aarch64_set_FP_double (cpu
, sd
,
7769 sqrt (aarch64_get_FP_double (cpu
, sn
)));
7772 /* Convert double to float. */
7774 fcvtds (sim_cpu
*cpu
)
7776 unsigned sn
= INSTR (9, 5);
7777 unsigned sd
= INSTR (4, 0);
7779 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7780 aarch64_set_FP_float (cpu
, sd
, (float) aarch64_get_FP_double (cpu
, sn
));
7783 /* Convert float to double. */
7785 fcvtcpu (sim_cpu
*cpu
)
7787 unsigned sn
= INSTR (9, 5);
7788 unsigned sd
= INSTR (4, 0);
7790 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7791 aarch64_set_FP_double (cpu
, sd
, (double) aarch64_get_FP_float (cpu
, sn
));
7795 do_FRINT (sim_cpu
*cpu
)
7797 /* instr[31,23] = 0001 1110 0
7798 instr[22] = single(0)/double(1)
7800 instr[17,15] = rounding mode
7801 instr[14,10] = 10000
7803 instr[4,0] = dest */
7806 unsigned rs
= INSTR (9, 5);
7807 unsigned rd
= INSTR (4, 0);
7808 unsigned int rmode
= INSTR (17, 15);
7810 NYI_assert (31, 23, 0x03C);
7811 NYI_assert (21, 18, 0x9);
7812 NYI_assert (14, 10, 0x10);
7814 if (rmode
== 6 || rmode
== 7)
7815 /* FIXME: Add support for rmode == 6 exactness check. */
7816 rmode
= uimm (aarch64_get_FPSR (cpu
), 23, 22);
7818 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7821 double val
= aarch64_get_FP_double (cpu
, rs
);
7825 case 0: /* mode N: nearest or even. */
7827 double rval
= round (val
);
7829 if (val
- rval
== 0.5)
7831 if (((rval
/ 2.0) * 2.0) != rval
)
7835 aarch64_set_FP_double (cpu
, rd
, round (val
));
7839 case 1: /* mode P: towards +inf. */
7841 aarch64_set_FP_double (cpu
, rd
, trunc (val
));
7843 aarch64_set_FP_double (cpu
, rd
, round (val
));
7846 case 2: /* mode M: towards -inf. */
7848 aarch64_set_FP_double (cpu
, rd
, round (val
));
7850 aarch64_set_FP_double (cpu
, rd
, trunc (val
));
7853 case 3: /* mode Z: towards 0. */
7854 aarch64_set_FP_double (cpu
, rd
, trunc (val
));
7857 case 4: /* mode A: away from 0. */
7858 aarch64_set_FP_double (cpu
, rd
, round (val
));
7861 case 6: /* mode X: use FPCR with exactness check. */
7862 case 7: /* mode I: use FPCR mode. */
7870 val
= aarch64_get_FP_float (cpu
, rs
);
7874 case 0: /* mode N: nearest or even. */
7876 float rval
= roundf (val
);
7878 if (val
- rval
== 0.5)
7880 if (((rval
/ 2.0) * 2.0) != rval
)
7884 aarch64_set_FP_float (cpu
, rd
, rval
);
7888 case 1: /* mode P: towards +inf. */
7890 aarch64_set_FP_float (cpu
, rd
, truncf (val
));
7892 aarch64_set_FP_float (cpu
, rd
, roundf (val
));
7895 case 2: /* mode M: towards -inf. */
7897 aarch64_set_FP_float (cpu
, rd
, truncf (val
));
7899 aarch64_set_FP_float (cpu
, rd
, roundf (val
));
7902 case 3: /* mode Z: towards 0. */
7903 aarch64_set_FP_float (cpu
, rd
, truncf (val
));
7906 case 4: /* mode A: away from 0. */
7907 aarch64_set_FP_float (cpu
, rd
, roundf (val
));
7910 case 6: /* mode X: use FPCR with exactness check. */
7911 case 7: /* mode I: use FPCR mode. */
7919 /* Convert half to float. */
7921 do_FCVT_half_to_single (sim_cpu
*cpu
)
7923 unsigned rn
= INSTR (9, 5);
7924 unsigned rd
= INSTR (4, 0);
7926 NYI_assert (31, 10, 0x7B890);
7928 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7929 aarch64_set_FP_float (cpu
, rd
, (float) aarch64_get_FP_half (cpu
, rn
));
7932 /* Convert half to double. */
7934 do_FCVT_half_to_double (sim_cpu
*cpu
)
7936 unsigned rn
= INSTR (9, 5);
7937 unsigned rd
= INSTR (4, 0);
7939 NYI_assert (31, 10, 0x7B8B0);
7941 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7942 aarch64_set_FP_double (cpu
, rd
, (double) aarch64_get_FP_half (cpu
, rn
));
7946 do_FCVT_single_to_half (sim_cpu
*cpu
)
7948 unsigned rn
= INSTR (9, 5);
7949 unsigned rd
= INSTR (4, 0);
7951 NYI_assert (31, 10, 0x788F0);
7953 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7954 aarch64_set_FP_half (cpu
, rd
, aarch64_get_FP_float (cpu
, rn
));
7957 /* Convert double to half. */
7959 do_FCVT_double_to_half (sim_cpu
*cpu
)
7961 unsigned rn
= INSTR (9, 5);
7962 unsigned rd
= INSTR (4, 0);
7964 NYI_assert (31, 10, 0x798F0);
7966 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7967 aarch64_set_FP_half (cpu
, rd
, (float) aarch64_get_FP_double (cpu
, rn
));
7971 dexSimpleFPDataProc1Source (sim_cpu
*cpu
)
7973 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
7975 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
7978 instr[23,22] ==> type : 00 ==> source is single,
7979 01 ==> source is double
7981 11 ==> UNALLOC or source is half
7983 instr[20,15] ==> opcode : with type 00 or 01
7984 000000 ==> FMOV, 000001 ==> FABS,
7985 000010 ==> FNEG, 000011 ==> FSQRT,
7986 000100 ==> UNALLOC, 000101 ==> FCVT,(to single/double)
7987 000110 ==> UNALLOC, 000111 ==> FCVT (to half)
7988 001000 ==> FRINTN, 001001 ==> FRINTP,
7989 001010 ==> FRINTM, 001011 ==> FRINTZ,
7990 001100 ==> FRINTA, 001101 ==> UNALLOC
7991 001110 ==> FRINTX, 001111 ==> FRINTI
7993 000100 ==> FCVT (half-to-single)
7994 000101 ==> FCVT (half-to-double)
7995 instr[14,10] = 10000. */
7997 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
7998 uint32_t type
= INSTR (23, 22);
7999 uint32_t opcode
= INSTR (20, 15);
8007 do_FCVT_half_to_single (cpu
);
8008 else if (opcode
== 5)
8009 do_FCVT_half_to_double (cpu
);
8061 case 8: /* FRINTN etc. */
8073 do_FCVT_double_to_half (cpu
);
8075 do_FCVT_single_to_half (cpu
);
8086 /* 32 bit signed int to float. */
8088 scvtf32 (sim_cpu
*cpu
)
8090 unsigned rn
= INSTR (9, 5);
8091 unsigned sd
= INSTR (4, 0);
8093 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8094 aarch64_set_FP_float
8095 (cpu
, sd
, (float) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
));
8098 /* signed int to float. */
8100 scvtf (sim_cpu
*cpu
)
8102 unsigned rn
= INSTR (9, 5);
8103 unsigned sd
= INSTR (4, 0);
8105 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8106 aarch64_set_FP_float
8107 (cpu
, sd
, (float) aarch64_get_reg_s64 (cpu
, rn
, NO_SP
));
8110 /* 32 bit signed int to double. */
8112 scvtd32 (sim_cpu
*cpu
)
8114 unsigned rn
= INSTR (9, 5);
8115 unsigned sd
= INSTR (4, 0);
8117 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8118 aarch64_set_FP_double
8119 (cpu
, sd
, (double) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
));
8122 /* signed int to double. */
8124 scvtd (sim_cpu
*cpu
)
8126 unsigned rn
= INSTR (9, 5);
8127 unsigned sd
= INSTR (4, 0);
8129 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8130 aarch64_set_FP_double
8131 (cpu
, sd
, (double) aarch64_get_reg_s64 (cpu
, rn
, NO_SP
));
8134 static const float FLOAT_INT_MAX
= (float) INT_MAX
;
8135 static const float FLOAT_INT_MIN
= (float) INT_MIN
;
8136 static const double DOUBLE_INT_MAX
= (double) INT_MAX
;
8137 static const double DOUBLE_INT_MIN
= (double) INT_MIN
;
8138 static const float FLOAT_LONG_MAX
= (float) LONG_MAX
;
8139 static const float FLOAT_LONG_MIN
= (float) LONG_MIN
;
8140 static const double DOUBLE_LONG_MAX
= (double) LONG_MAX
;
8141 static const double DOUBLE_LONG_MIN
= (double) LONG_MIN
;
8143 /* Check for FP exception conditions:
8146 Out of Range raises IO and IX and saturates value
8147 Denormal raises ID and IX and sets to zero. */
8148 #define RAISE_EXCEPTIONS(F, VALUE, FTYPE, ITYPE) \
8151 switch (fpclassify (F)) \
8155 aarch64_set_FPSR (cpu, IO); \
8157 VALUE = ITYPE##_MAX; \
8159 VALUE = ITYPE##_MIN; \
8163 if (F >= FTYPE##_##ITYPE##_MAX) \
8165 aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX); \
8166 VALUE = ITYPE##_MAX; \
8168 else if (F <= FTYPE##_##ITYPE##_MIN) \
8170 aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX); \
8171 VALUE = ITYPE##_MIN; \
8175 case FP_SUBNORMAL: \
8176 aarch64_set_FPSR_bits (cpu, IO | IX | ID, IX | ID); \
8188 /* 32 bit convert float to signed int truncate towards zero. */
8190 fcvtszs32 (sim_cpu
*cpu
)
8192 unsigned sn
= INSTR (9, 5);
8193 unsigned rd
= INSTR (4, 0);
8194 /* TODO : check that this rounds toward zero. */
8195 float f
= aarch64_get_FP_float (cpu
, sn
);
8196 int32_t value
= (int32_t) f
;
8198 RAISE_EXCEPTIONS (f
, value
, FLOAT
, INT
);
8200 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8201 /* Avoid sign extension to 64 bit. */
8202 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) value
);
8205 /* 64 bit convert float to signed int truncate towards zero. */
8207 fcvtszs (sim_cpu
*cpu
)
8209 unsigned sn
= INSTR (9, 5);
8210 unsigned rd
= INSTR (4, 0);
8211 float f
= aarch64_get_FP_float (cpu
, sn
);
8212 int64_t value
= (int64_t) f
;
8214 RAISE_EXCEPTIONS (f
, value
, FLOAT
, LONG
);
8216 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8217 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, value
);
8220 /* 32 bit convert double to signed int truncate towards zero. */
8222 fcvtszd32 (sim_cpu
*cpu
)
8224 unsigned sn
= INSTR (9, 5);
8225 unsigned rd
= INSTR (4, 0);
8226 /* TODO : check that this rounds toward zero. */
8227 double d
= aarch64_get_FP_double (cpu
, sn
);
8228 int32_t value
= (int32_t) d
;
8230 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, INT
);
8232 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8233 /* Avoid sign extension to 64 bit. */
8234 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) value
);
8237 /* 64 bit convert double to signed int truncate towards zero. */
8239 fcvtszd (sim_cpu
*cpu
)
8241 unsigned sn
= INSTR (9, 5);
8242 unsigned rd
= INSTR (4, 0);
8243 /* TODO : check that this rounds toward zero. */
8244 double d
= aarch64_get_FP_double (cpu
, sn
);
8247 value
= (int64_t) d
;
8249 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, LONG
);
8251 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8252 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, value
);
8256 do_fcvtzu (sim_cpu
*cpu
)
8258 /* instr[31] = size: 32-bit (0), 64-bit (1)
8259 instr[30,23] = 00111100
8260 instr[22] = type: single (0)/ double (1)
8261 instr[21] = enable (0)/disable(1) precision
8262 instr[20,16] = 11001
8263 instr[15,10] = precision
8267 unsigned rs
= INSTR (9, 5);
8268 unsigned rd
= INSTR (4, 0);
8270 NYI_assert (30, 23, 0x3C);
8271 NYI_assert (20, 16, 0x19);
8273 if (INSTR (21, 21) != 1)
8274 /* Convert to fixed point. */
8277 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8280 /* Convert to unsigned 64-bit integer. */
8283 double d
= aarch64_get_FP_double (cpu
, rs
);
8284 uint64_t value
= (uint64_t) d
;
8286 /* Do not raise an exception if we have reached ULONG_MAX. */
8287 if (value
!= (1UL << 63))
8288 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, LONG
);
8290 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
8294 float f
= aarch64_get_FP_float (cpu
, rs
);
8295 uint64_t value
= (uint64_t) f
;
8297 /* Do not raise an exception if we have reached ULONG_MAX. */
8298 if (value
!= (1UL << 63))
8299 RAISE_EXCEPTIONS (f
, value
, FLOAT
, LONG
);
8301 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
8308 /* Convert to unsigned 32-bit integer. */
8311 double d
= aarch64_get_FP_double (cpu
, rs
);
8313 value
= (uint32_t) d
;
8314 /* Do not raise an exception if we have reached UINT_MAX. */
8315 if (value
!= (1UL << 31))
8316 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, INT
);
8320 float f
= aarch64_get_FP_float (cpu
, rs
);
8322 value
= (uint32_t) f
;
8323 /* Do not raise an exception if we have reached UINT_MAX. */
8324 if (value
!= (1UL << 31))
8325 RAISE_EXCEPTIONS (f
, value
, FLOAT
, INT
);
8328 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
8333 do_UCVTF (sim_cpu
*cpu
)
8335 /* instr[31] = size: 32-bit (0), 64-bit (1)
8336 instr[30,23] = 001 1110 0
8337 instr[22] = type: single (0)/ double (1)
8338 instr[21] = enable (0)/disable(1) precision
8339 instr[20,16] = 0 0011
8340 instr[15,10] = precision
8344 unsigned rs
= INSTR (9, 5);
8345 unsigned rd
= INSTR (4, 0);
8347 NYI_assert (30, 23, 0x3C);
8348 NYI_assert (20, 16, 0x03);
8350 if (INSTR (21, 21) != 1)
8353 /* FIXME: Add exception raising. */
8354 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8357 uint64_t value
= aarch64_get_reg_u64 (cpu
, rs
, NO_SP
);
8360 aarch64_set_FP_double (cpu
, rd
, (double) value
);
8362 aarch64_set_FP_float (cpu
, rd
, (float) value
);
8366 uint32_t value
= aarch64_get_reg_u32 (cpu
, rs
, NO_SP
);
8369 aarch64_set_FP_double (cpu
, rd
, (double) value
);
8371 aarch64_set_FP_float (cpu
, rd
, (float) value
);
8376 float_vector_move (sim_cpu
*cpu
)
8378 /* instr[31,17] == 100 1111 0101 0111
8379 instr[16] ==> direction 0=> to GR, 1=> from GR
8381 instr[9,5] ==> source
8382 instr[4,0] ==> dest. */
8384 unsigned rn
= INSTR (9, 5);
8385 unsigned rd
= INSTR (4, 0);
8387 NYI_assert (31, 17, 0x4F57);
8389 if (INSTR (15, 10) != 0)
8392 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8394 aarch64_set_vec_u64 (cpu
, rd
, 1, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
8396 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, aarch64_get_vec_u64 (cpu
, rn
, 1));
8400 dexSimpleFPIntegerConvert (sim_cpu
*cpu
)
8402 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
8404 instr[29] = S : 0 ==> OK, 1 ==> UNALLOC
8407 instr[23,22] = type : 00 ==> single, 01 ==> double, 1x ==> UNALLOC
8409 instr[20,19] = rmode
8410 instr[18,16] = opcode
8411 instr[15,10] = 10 0000 */
8413 uint32_t rmode_opcode
;
8419 if (INSTR (31, 17) == 0x4F57)
8421 float_vector_move (cpu
);
8425 size
= INSTR (31, 31);
8430 type
= INSTR (23, 22);
8434 rmode_opcode
= INSTR (20, 16);
8435 size_type
= (size
<< 1) | type
; /* 0==32f, 1==32d, 2==64f, 3==64d. */
8437 switch (rmode_opcode
)
8439 case 2: /* SCVTF. */
8442 case 0: scvtf32 (cpu
); return;
8443 case 1: scvtd32 (cpu
); return;
8444 case 2: scvtf (cpu
); return;
8445 case 3: scvtd (cpu
); return;
8448 case 6: /* FMOV GR, Vec. */
8451 case 0: gfmovs (cpu
); return;
8452 case 3: gfmovd (cpu
); return;
8453 default: HALT_UNALLOC
;
8456 case 7: /* FMOV vec, GR. */
8459 case 0: fgmovs (cpu
); return;
8460 case 3: fgmovd (cpu
); return;
8461 default: HALT_UNALLOC
;
8464 case 24: /* FCVTZS. */
8467 case 0: fcvtszs32 (cpu
); return;
8468 case 1: fcvtszd32 (cpu
); return;
8469 case 2: fcvtszs (cpu
); return;
8470 case 3: fcvtszd (cpu
); return;
8473 case 25: do_fcvtzu (cpu
); return;
8474 case 3: do_UCVTF (cpu
); return;
8476 case 0: /* FCVTNS. */
8477 case 1: /* FCVTNU. */
8478 case 4: /* FCVTAS. */
8479 case 5: /* FCVTAU. */
8480 case 8: /* FCVPTS. */
8481 case 9: /* FCVTPU. */
8482 case 16: /* FCVTMS. */
8483 case 17: /* FCVTMU. */
8490 set_flags_for_float_compare (sim_cpu
*cpu
, float fvalue1
, float fvalue2
)
8494 if (isnan (fvalue1
) || isnan (fvalue2
))
8498 float result
= fvalue1
- fvalue2
;
8502 else if (result
< 0)
8504 else /* (result > 0). */
8508 aarch64_set_CPSR (cpu
, flags
);
8512 fcmps (sim_cpu
*cpu
)
8514 unsigned sm
= INSTR (20, 16);
8515 unsigned sn
= INSTR ( 9, 5);
8517 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8518 float fvalue2
= aarch64_get_FP_float (cpu
, sm
);
8520 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8521 set_flags_for_float_compare (cpu
, fvalue1
, fvalue2
);
8524 /* Float compare to zero -- Invalid Operation exception
8525 only on signaling NaNs. */
8527 fcmpzs (sim_cpu
*cpu
)
8529 unsigned sn
= INSTR ( 9, 5);
8530 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8532 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8533 set_flags_for_float_compare (cpu
, fvalue1
, 0.0f
);
8536 /* Float compare -- Invalid Operation exception on all NaNs. */
8538 fcmpes (sim_cpu
*cpu
)
8540 unsigned sm
= INSTR (20, 16);
8541 unsigned sn
= INSTR ( 9, 5);
8543 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8544 float fvalue2
= aarch64_get_FP_float (cpu
, sm
);
8546 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8547 set_flags_for_float_compare (cpu
, fvalue1
, fvalue2
);
8550 /* Float compare to zero -- Invalid Operation exception on all NaNs. */
8552 fcmpzes (sim_cpu
*cpu
)
8554 unsigned sn
= INSTR ( 9, 5);
8555 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8557 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8558 set_flags_for_float_compare (cpu
, fvalue1
, 0.0f
);
8562 set_flags_for_double_compare (sim_cpu
*cpu
, double dval1
, double dval2
)
8566 if (isnan (dval1
) || isnan (dval2
))
8570 double result
= dval1
- dval2
;
8574 else if (result
< 0)
8576 else /* (result > 0). */
8580 aarch64_set_CPSR (cpu
, flags
);
8583 /* Double compare -- Invalid Operation exception only on signaling NaNs. */
8585 fcmpd (sim_cpu
*cpu
)
8587 unsigned sm
= INSTR (20, 16);
8588 unsigned sn
= INSTR ( 9, 5);
8590 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8591 double dvalue2
= aarch64_get_FP_double (cpu
, sm
);
8593 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8594 set_flags_for_double_compare (cpu
, dvalue1
, dvalue2
);
8597 /* Double compare to zero -- Invalid Operation exception
8598 only on signaling NaNs. */
8600 fcmpzd (sim_cpu
*cpu
)
8602 unsigned sn
= INSTR ( 9, 5);
8603 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8605 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8606 set_flags_for_double_compare (cpu
, dvalue1
, 0.0);
8609 /* Double compare -- Invalid Operation exception on all NaNs. */
8611 fcmped (sim_cpu
*cpu
)
8613 unsigned sm
= INSTR (20, 16);
8614 unsigned sn
= INSTR ( 9, 5);
8616 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8617 double dvalue2
= aarch64_get_FP_double (cpu
, sm
);
8619 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8620 set_flags_for_double_compare (cpu
, dvalue1
, dvalue2
);
8623 /* Double compare to zero -- Invalid Operation exception on all NaNs. */
8625 fcmpzed (sim_cpu
*cpu
)
8627 unsigned sn
= INSTR ( 9, 5);
8628 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8630 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8631 set_flags_for_double_compare (cpu
, dvalue1
, 0.0);
8635 dexSimpleFPCompare (sim_cpu
*cpu
)
8637 /* assert instr[28,25] == 1111
8638 instr[30:24:21:13,10] = 0011000
8639 instr[31] = M : 0 ==> OK, 1 ==> UNALLOC
8640 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
8641 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
8642 instr[15,14] ==> op : 00 ==> OK, ow ==> UNALLOC
8643 instr[4,0] ==> opcode2 : 00000 ==> FCMP, 10000 ==> FCMPE,
8644 01000 ==> FCMPZ, 11000 ==> FCMPEZ,
8647 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
8648 uint32_t type
= INSTR (23, 22);
8649 uint32_t op
= INSTR (15, 14);
8650 uint32_t op2_2_0
= INSTR (2, 0);
8664 /* dispatch on type and top 2 bits of opcode. */
8665 dispatch
= (type
<< 2) | INSTR (4, 3);
8669 case 0: fcmps (cpu
); return;
8670 case 1: fcmpzs (cpu
); return;
8671 case 2: fcmpes (cpu
); return;
8672 case 3: fcmpzes (cpu
); return;
8673 case 4: fcmpd (cpu
); return;
8674 case 5: fcmpzd (cpu
); return;
8675 case 6: fcmped (cpu
); return;
8676 case 7: fcmpzed (cpu
); return;
8681 do_scalar_FADDP (sim_cpu
*cpu
)
8683 /* instr [31,23] = 0111 1110 0
8684 instr [22] = single(0)/double(1)
8685 instr [21,10] = 11 0000 1101 10
8687 instr [4,0] = Fd. */
8689 unsigned Fn
= INSTR (9, 5);
8690 unsigned Fd
= INSTR (4, 0);
8692 NYI_assert (31, 23, 0x0FC);
8693 NYI_assert (21, 10, 0xC36);
8695 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8698 double val1
= aarch64_get_vec_double (cpu
, Fn
, 0);
8699 double val2
= aarch64_get_vec_double (cpu
, Fn
, 1);
8701 aarch64_set_FP_double (cpu
, Fd
, val1
+ val2
);
8705 float val1
= aarch64_get_vec_float (cpu
, Fn
, 0);
8706 float val2
= aarch64_get_vec_float (cpu
, Fn
, 1);
8708 aarch64_set_FP_float (cpu
, Fd
, val1
+ val2
);
8712 /* Floating point absolute difference. */
8715 do_scalar_FABD (sim_cpu
*cpu
)
8717 /* instr [31,23] = 0111 1110 1
8718 instr [22] = float(0)/double(1)
8721 instr [15,10] = 1101 01
8723 instr [4, 0] = Rd. */
8725 unsigned rm
= INSTR (20, 16);
8726 unsigned rn
= INSTR (9, 5);
8727 unsigned rd
= INSTR (4, 0);
8729 NYI_assert (31, 23, 0x0FD);
8730 NYI_assert (21, 21, 1);
8731 NYI_assert (15, 10, 0x35);
8733 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8735 aarch64_set_FP_double (cpu
, rd
,
8736 fabs (aarch64_get_FP_double (cpu
, rn
)
8737 - aarch64_get_FP_double (cpu
, rm
)));
8739 aarch64_set_FP_float (cpu
, rd
,
8740 fabsf (aarch64_get_FP_float (cpu
, rn
)
8741 - aarch64_get_FP_float (cpu
, rm
)));
8745 do_scalar_CMGT (sim_cpu
*cpu
)
8747 /* instr [31,21] = 0101 1110 111
8749 instr [15,10] = 00 1101
8751 instr [4, 0] = Rd. */
8753 unsigned rm
= INSTR (20, 16);
8754 unsigned rn
= INSTR (9, 5);
8755 unsigned rd
= INSTR (4, 0);
8757 NYI_assert (31, 21, 0x2F7);
8758 NYI_assert (15, 10, 0x0D);
8760 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8761 aarch64_set_vec_u64 (cpu
, rd
, 0,
8762 aarch64_get_vec_u64 (cpu
, rn
, 0) >
8763 aarch64_get_vec_u64 (cpu
, rm
, 0) ? -1L : 0L);
8767 do_scalar_USHR (sim_cpu
*cpu
)
8769 /* instr [31,23] = 0111 1111 0
8770 instr [22,16] = shift amount
8771 instr [15,10] = 0000 01
8773 instr [4, 0] = Rd. */
8775 unsigned amount
= 128 - INSTR (22, 16);
8776 unsigned rn
= INSTR (9, 5);
8777 unsigned rd
= INSTR (4, 0);
8779 NYI_assert (31, 23, 0x0FE);
8780 NYI_assert (15, 10, 0x01);
8782 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8783 aarch64_set_vec_u64 (cpu
, rd
, 0,
8784 aarch64_get_vec_u64 (cpu
, rn
, 0) >> amount
);
8788 do_scalar_SSHL (sim_cpu
*cpu
)
8790 /* instr [31,21] = 0101 1110 111
8792 instr [15,10] = 0100 01
8794 instr [4, 0] = Rd. */
8796 unsigned rm
= INSTR (20, 16);
8797 unsigned rn
= INSTR (9, 5);
8798 unsigned rd
= INSTR (4, 0);
8799 signed int shift
= aarch64_get_vec_s8 (cpu
, rm
, 0);
8801 NYI_assert (31, 21, 0x2F7);
8802 NYI_assert (15, 10, 0x11);
8804 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8806 aarch64_set_vec_s64 (cpu
, rd
, 0,
8807 aarch64_get_vec_s64 (cpu
, rn
, 0) << shift
);
8809 aarch64_set_vec_s64 (cpu
, rd
, 0,
8810 aarch64_get_vec_s64 (cpu
, rn
, 0) >> - shift
);
8814 do_scalar_shift (sim_cpu
*cpu
)
8816 /* instr [31,23] = 0101 1111 0
8817 instr [22,16] = shift amount
8818 instr [15,10] = 0101 01 [SHL]
8819 instr [15,10] = 0000 01 [SSHR]
8821 instr [4, 0] = Rd. */
8823 unsigned rn
= INSTR (9, 5);
8824 unsigned rd
= INSTR (4, 0);
8827 NYI_assert (31, 23, 0x0BE);
8829 if (INSTR (22, 22) == 0)
8832 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8833 switch (INSTR (15, 10))
8835 case 0x01: /* SSHR */
8836 amount
= 128 - INSTR (22, 16);
8837 aarch64_set_vec_s64 (cpu
, rd
, 0,
8838 aarch64_get_vec_s64 (cpu
, rn
, 0) >> amount
);
8840 case 0x15: /* SHL */
8841 amount
= INSTR (22, 16) - 64;
8842 aarch64_set_vec_u64 (cpu
, rd
, 0,
8843 aarch64_get_vec_u64 (cpu
, rn
, 0) << amount
);
8850 /* FCMEQ FCMGT FCMGE. */
8852 do_scalar_FCM (sim_cpu
*cpu
)
8854 /* instr [31,30] = 01
8856 instr [28,24] = 1 1110
8861 instr [15,12] = 1110
8865 instr [4, 0] = Rd. */
8867 unsigned rm
= INSTR (20, 16);
8868 unsigned rn
= INSTR (9, 5);
8869 unsigned rd
= INSTR (4, 0);
8870 unsigned EUac
= (INSTR (23, 23) << 2) | (INSTR (29, 29) << 1) | INSTR (11, 11);
8875 NYI_assert (31, 30, 1);
8876 NYI_assert (28, 24, 0x1E);
8877 NYI_assert (21, 21, 1);
8878 NYI_assert (15, 12, 0xE);
8879 NYI_assert (10, 10, 1);
8881 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8884 double val1
= aarch64_get_FP_double (cpu
, rn
);
8885 double val2
= aarch64_get_FP_double (cpu
, rm
);
8890 result
= val1
== val2
;
8898 result
= val1
>= val2
;
8906 result
= val1
> val2
;
8913 aarch64_set_vec_u32 (cpu
, rd
, 0, result
? -1 : 0);
8917 val1
= aarch64_get_FP_float (cpu
, rn
);
8918 val2
= aarch64_get_FP_float (cpu
, rm
);
8923 result
= val1
== val2
;
8927 val1
= fabsf (val1
);
8928 val2
= fabsf (val2
);
8931 result
= val1
>= val2
;
8935 val1
= fabsf (val1
);
8936 val2
= fabsf (val2
);
8939 result
= val1
> val2
;
8946 aarch64_set_vec_u32 (cpu
, rd
, 0, result
? -1 : 0);
8949 /* An alias of DUP. */
8951 do_scalar_MOV (sim_cpu
*cpu
)
8953 /* instr [31,21] = 0101 1110 000
8954 instr [20,16] = imm5
8955 instr [15,10] = 0000 01
8957 instr [4, 0] = Rd. */
8959 unsigned rn
= INSTR (9, 5);
8960 unsigned rd
= INSTR (4, 0);
8963 NYI_assert (31, 21, 0x2F0);
8964 NYI_assert (15, 10, 0x01);
8966 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8970 index
= INSTR (20, 17);
8972 (cpu
, rd
, 0, aarch64_get_vec_u8 (cpu
, rn
, index
));
8974 else if (INSTR (17, 17))
8977 index
= INSTR (20, 18);
8979 (cpu
, rd
, 0, aarch64_get_vec_u16 (cpu
, rn
, index
));
8981 else if (INSTR (18, 18))
8984 index
= INSTR (20, 19);
8986 (cpu
, rd
, 0, aarch64_get_vec_u32 (cpu
, rn
, index
));
8988 else if (INSTR (19, 19))
8991 index
= INSTR (20, 20);
8993 (cpu
, rd
, 0, aarch64_get_vec_u64 (cpu
, rn
, index
));
9000 do_scalar_NEG (sim_cpu
*cpu
)
9002 /* instr [31,10] = 0111 1110 1110 0000 1011 10
9004 instr [4, 0] = Rd. */
9006 unsigned rn
= INSTR (9, 5);
9007 unsigned rd
= INSTR (4, 0);
9009 NYI_assert (31, 10, 0x1FB82E);
9011 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9012 aarch64_set_vec_u64 (cpu
, rd
, 0, - aarch64_get_vec_u64 (cpu
, rn
, 0));
9016 do_scalar_USHL (sim_cpu
*cpu
)
9018 /* instr [31,21] = 0111 1110 111
9020 instr [15,10] = 0100 01
9022 instr [4, 0] = Rd. */
9024 unsigned rm
= INSTR (20, 16);
9025 unsigned rn
= INSTR (9, 5);
9026 unsigned rd
= INSTR (4, 0);
9027 signed int shift
= aarch64_get_vec_s8 (cpu
, rm
, 0);
9029 NYI_assert (31, 21, 0x3F7);
9030 NYI_assert (15, 10, 0x11);
9032 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9034 aarch64_set_vec_u64 (cpu
, rd
, 0, aarch64_get_vec_u64 (cpu
, rn
, 0) << shift
);
9036 aarch64_set_vec_u64 (cpu
, rd
, 0, aarch64_get_vec_u64 (cpu
, rn
, 0) >> - shift
);
9040 do_double_add (sim_cpu
*cpu
)
9042 /* instr [31,21] = 0101 1110 111
9044 instr [15,10] = 1000 01
9046 instr [4,0] = Fd. */
9053 NYI_assert (31, 21, 0x2F7);
9054 NYI_assert (15, 10, 0x21);
9058 Fn
= INSTR (20, 16);
9060 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9061 val1
= aarch64_get_FP_double (cpu
, Fm
);
9062 val2
= aarch64_get_FP_double (cpu
, Fn
);
9064 aarch64_set_FP_double (cpu
, Fd
, val1
+ val2
);
9068 do_scalar_UCVTF (sim_cpu
*cpu
)
9070 /* instr [31,23] = 0111 1110 0
9071 instr [22] = single(0)/double(1)
9072 instr [21,10] = 10 0001 1101 10
9074 instr [4,0] = rd. */
9076 unsigned rn
= INSTR (9, 5);
9077 unsigned rd
= INSTR (4, 0);
9079 NYI_assert (31, 23, 0x0FC);
9080 NYI_assert (21, 10, 0x876);
9082 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9085 uint64_t val
= aarch64_get_vec_u64 (cpu
, rn
, 0);
9087 aarch64_set_vec_double (cpu
, rd
, 0, (double) val
);
9091 uint32_t val
= aarch64_get_vec_u32 (cpu
, rn
, 0);
9093 aarch64_set_vec_float (cpu
, rd
, 0, (float) val
);
9098 do_scalar_vec (sim_cpu
*cpu
)
9100 /* instr [30] = 1. */
9101 /* instr [28,25] = 1111. */
9102 switch (INSTR (31, 23))
9105 switch (INSTR (15, 10))
9107 case 0x01: do_scalar_MOV (cpu
); return;
9108 case 0x39: do_scalar_FCM (cpu
); return;
9109 case 0x3B: do_scalar_FCM (cpu
); return;
9113 case 0xBE: do_scalar_shift (cpu
); return;
9116 switch (INSTR (15, 10))
9119 switch (INSTR (21, 16))
9121 case 0x30: do_scalar_FADDP (cpu
); return;
9122 case 0x21: do_scalar_UCVTF (cpu
); return;
9125 case 0x39: do_scalar_FCM (cpu
); return;
9126 case 0x3B: do_scalar_FCM (cpu
); return;
9131 switch (INSTR (15, 10))
9133 case 0x0D: do_scalar_CMGT (cpu
); return;
9134 case 0x11: do_scalar_USHL (cpu
); return;
9135 case 0x2E: do_scalar_NEG (cpu
); return;
9136 case 0x35: do_scalar_FABD (cpu
); return;
9137 case 0x39: do_scalar_FCM (cpu
); return;
9138 case 0x3B: do_scalar_FCM (cpu
); return;
9143 case 0xFE: do_scalar_USHR (cpu
); return;
9146 switch (INSTR (15, 10))
9148 case 0x21: do_double_add (cpu
); return;
9149 case 0x11: do_scalar_SSHL (cpu
); return;
9160 dexAdvSIMD1 (sim_cpu
*cpu
)
9162 /* instr [28,25] = 1 111. */
9164 /* We are currently only interested in the basic
9165 scalar fp routines which all have bit 30 = 0. */
9167 do_scalar_vec (cpu
);
9169 /* instr[24] is set for FP data processing 3-source and clear for
9170 all other basic scalar fp instruction groups. */
9171 else if (INSTR (24, 24))
9172 dexSimpleFPDataProc3Source (cpu
);
9174 /* instr[21] is clear for floating <-> fixed conversions and set for
9175 all other basic scalar fp instruction groups. */
9176 else if (!INSTR (21, 21))
9177 dexSimpleFPFixedConvert (cpu
);
9179 /* instr[11,10] : 01 ==> cond compare, 10 ==> Data Proc 2 Source
9180 11 ==> cond select, 00 ==> other. */
9182 switch (INSTR (11, 10))
9184 case 1: dexSimpleFPCondCompare (cpu
); return;
9185 case 2: dexSimpleFPDataProc2Source (cpu
); return;
9186 case 3: dexSimpleFPCondSelect (cpu
); return;
9189 /* Now an ordered cascade of tests.
9190 FP immediate has instr [12] == 1.
9191 FP compare has instr [13] == 1.
9192 FP Data Proc 1 Source has instr [14] == 1.
9193 FP floating <--> integer conversions has instr [15] == 0. */
9195 dexSimpleFPImmediate (cpu
);
9197 else if (INSTR (13, 13))
9198 dexSimpleFPCompare (cpu
);
9200 else if (INSTR (14, 14))
9201 dexSimpleFPDataProc1Source (cpu
);
9203 else if (!INSTR (15, 15))
9204 dexSimpleFPIntegerConvert (cpu
);
9207 /* If we get here then instr[15] == 1 which means UNALLOC. */
9212 /* PC relative addressing. */
9215 pcadr (sim_cpu
*cpu
)
9217 /* instr[31] = op : 0 ==> ADR, 1 ==> ADRP
9218 instr[30,29] = immlo
9219 instr[23,5] = immhi. */
9221 unsigned rd
= INSTR (4, 0);
9222 uint32_t isPage
= INSTR (31, 31);
9223 union { int64_t u64
; uint64_t s64
; } imm
;
9226 imm
.s64
= simm64 (aarch64_get_instr (cpu
), 23, 5);
9228 offset
= (offset
<< 2) | INSTR (30, 29);
9230 address
= aarch64_get_PC (cpu
);
9238 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9239 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, address
+ offset
);
9242 /* Specific decode and execute for group Data Processing Immediate. */
9245 dexPCRelAddressing (sim_cpu
*cpu
)
9247 /* assert instr[28,24] = 10000. */
9251 /* Immediate logical.
9252 The bimm32/64 argument is constructed by replicating a 2, 4, 8,
9253 16, 32 or 64 bit sequence pulled out at decode and possibly
9256 N.B. the output register (dest) can normally be Xn or SP
9257 the exception occurs for flag setting instructions which may
9258 only use Xn for the output (dest). The input register can
9261 /* 32 bit and immediate. */
9263 and32 (sim_cpu
*cpu
, uint32_t bimm
)
9265 unsigned rn
= INSTR (9, 5);
9266 unsigned rd
= INSTR (4, 0);
9268 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9269 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9270 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
) & bimm
);
9273 /* 64 bit and immediate. */
9275 and64 (sim_cpu
*cpu
, uint64_t bimm
)
9277 unsigned rn
= INSTR (9, 5);
9278 unsigned rd
= INSTR (4, 0);
9280 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9281 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9282 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) & bimm
);
9285 /* 32 bit and immediate set flags. */
9287 ands32 (sim_cpu
*cpu
, uint32_t bimm
)
9289 unsigned rn
= INSTR (9, 5);
9290 unsigned rd
= INSTR (4, 0);
9292 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9293 uint32_t value2
= bimm
;
9295 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9296 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9297 set_flags_for_binop32 (cpu
, value1
& value2
);
9300 /* 64 bit and immediate set flags. */
9302 ands64 (sim_cpu
*cpu
, uint64_t bimm
)
9304 unsigned rn
= INSTR (9, 5);
9305 unsigned rd
= INSTR (4, 0);
9307 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9308 uint64_t value2
= bimm
;
9310 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9311 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9312 set_flags_for_binop64 (cpu
, value1
& value2
);
9315 /* 32 bit exclusive or immediate. */
9317 eor32 (sim_cpu
*cpu
, uint32_t bimm
)
9319 unsigned rn
= INSTR (9, 5);
9320 unsigned rd
= INSTR (4, 0);
9322 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9323 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9324 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
) ^ bimm
);
9327 /* 64 bit exclusive or immediate. */
9329 eor64 (sim_cpu
*cpu
, uint64_t bimm
)
9331 unsigned rn
= INSTR (9, 5);
9332 unsigned rd
= INSTR (4, 0);
9334 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9335 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9336 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) ^ bimm
);
9339 /* 32 bit or immediate. */
9341 orr32 (sim_cpu
*cpu
, uint32_t bimm
)
9343 unsigned rn
= INSTR (9, 5);
9344 unsigned rd
= INSTR (4, 0);
9346 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9347 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9348 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
) | bimm
);
9351 /* 64 bit or immediate. */
9353 orr64 (sim_cpu
*cpu
, uint64_t bimm
)
9355 unsigned rn
= INSTR (9, 5);
9356 unsigned rd
= INSTR (4, 0);
9358 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9359 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9360 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) | bimm
);
9363 /* Logical shifted register.
9364 These allow an optional LSL, ASR, LSR or ROR to the second source
9365 register with a count up to the register bit count.
9366 N.B register args may not be SP. */
9368 /* 32 bit AND shifted register. */
9370 and32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9372 unsigned rm
= INSTR (20, 16);
9373 unsigned rn
= INSTR (9, 5);
9374 unsigned rd
= INSTR (4, 0);
9376 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9378 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9379 & shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9382 /* 64 bit AND shifted register. */
9384 and64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9386 unsigned rm
= INSTR (20, 16);
9387 unsigned rn
= INSTR (9, 5);
9388 unsigned rd
= INSTR (4, 0);
9390 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9392 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9393 & shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9396 /* 32 bit AND shifted register setting flags. */
9398 ands32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9400 unsigned rm
= INSTR (20, 16);
9401 unsigned rn
= INSTR (9, 5);
9402 unsigned rd
= INSTR (4, 0);
9404 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9405 uint32_t value2
= shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
9408 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9409 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9410 set_flags_for_binop32 (cpu
, value1
& value2
);
9413 /* 64 bit AND shifted register setting flags. */
9415 ands64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9417 unsigned rm
= INSTR (20, 16);
9418 unsigned rn
= INSTR (9, 5);
9419 unsigned rd
= INSTR (4, 0);
9421 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9422 uint64_t value2
= shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
9425 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9426 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9427 set_flags_for_binop64 (cpu
, value1
& value2
);
9430 /* 32 bit BIC shifted register. */
9432 bic32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9434 unsigned rm
= INSTR (20, 16);
9435 unsigned rn
= INSTR (9, 5);
9436 unsigned rd
= INSTR (4, 0);
9438 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9440 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9441 & ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9444 /* 64 bit BIC shifted register. */
9446 bic64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9448 unsigned rm
= INSTR (20, 16);
9449 unsigned rn
= INSTR (9, 5);
9450 unsigned rd
= INSTR (4, 0);
9452 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9454 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9455 & ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9458 /* 32 bit BIC shifted register setting flags. */
9460 bics32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9462 unsigned rm
= INSTR (20, 16);
9463 unsigned rn
= INSTR (9, 5);
9464 unsigned rd
= INSTR (4, 0);
9466 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9467 uint32_t value2
= ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
9470 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9471 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9472 set_flags_for_binop32 (cpu
, value1
& value2
);
9475 /* 64 bit BIC shifted register setting flags. */
9477 bics64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9479 unsigned rm
= INSTR (20, 16);
9480 unsigned rn
= INSTR (9, 5);
9481 unsigned rd
= INSTR (4, 0);
9483 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9484 uint64_t value2
= ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
9487 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9488 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9489 set_flags_for_binop64 (cpu
, value1
& value2
);
9492 /* 32 bit EON shifted register. */
9494 eon32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9496 unsigned rm
= INSTR (20, 16);
9497 unsigned rn
= INSTR (9, 5);
9498 unsigned rd
= INSTR (4, 0);
9500 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9502 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9503 ^ ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9506 /* 64 bit EON shifted register. */
9508 eon64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9510 unsigned rm
= INSTR (20, 16);
9511 unsigned rn
= INSTR (9, 5);
9512 unsigned rd
= INSTR (4, 0);
9514 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9516 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9517 ^ ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9520 /* 32 bit EOR shifted register. */
9522 eor32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9524 unsigned rm
= INSTR (20, 16);
9525 unsigned rn
= INSTR (9, 5);
9526 unsigned rd
= INSTR (4, 0);
9528 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9530 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9531 ^ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9534 /* 64 bit EOR shifted register. */
9536 eor64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9538 unsigned rm
= INSTR (20, 16);
9539 unsigned rn
= INSTR (9, 5);
9540 unsigned rd
= INSTR (4, 0);
9542 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9544 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9545 ^ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9548 /* 32 bit ORR shifted register. */
9550 orr32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9552 unsigned rm
= INSTR (20, 16);
9553 unsigned rn
= INSTR (9, 5);
9554 unsigned rd
= INSTR (4, 0);
9556 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9558 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9559 | shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9562 /* 64 bit ORR shifted register. */
9564 orr64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9566 unsigned rm
= INSTR (20, 16);
9567 unsigned rn
= INSTR (9, 5);
9568 unsigned rd
= INSTR (4, 0);
9570 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9572 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9573 | shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9576 /* 32 bit ORN shifted register. */
9578 orn32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9580 unsigned rm
= INSTR (20, 16);
9581 unsigned rn
= INSTR (9, 5);
9582 unsigned rd
= INSTR (4, 0);
9584 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9586 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9587 | ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9590 /* 64 bit ORN shifted register. */
9592 orn64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9594 unsigned rm
= INSTR (20, 16);
9595 unsigned rn
= INSTR (9, 5);
9596 unsigned rd
= INSTR (4, 0);
9598 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9600 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9601 | ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9605 dexLogicalImmediate (sim_cpu
*cpu
)
9607 /* assert instr[28,23] = 1001000
9608 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9609 instr[30,29] = op : 0 ==> AND, 1 ==> ORR, 2 ==> EOR, 3 ==> ANDS
9610 instr[22] = N : used to construct immediate mask
9616 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
9617 uint32_t size
= INSTR (31, 31);
9618 uint32_t N
= INSTR (22, 22);
9619 /* uint32_t immr = INSTR (21, 16);. */
9620 /* uint32_t imms = INSTR (15, 10);. */
9621 uint32_t index
= INSTR (22, 10);
9622 uint64_t bimm64
= LITable
[index
];
9623 uint32_t dispatch
= INSTR (30, 29);
9633 uint32_t bimm
= (uint32_t) bimm64
;
9637 case 0: and32 (cpu
, bimm
); return;
9638 case 1: orr32 (cpu
, bimm
); return;
9639 case 2: eor32 (cpu
, bimm
); return;
9640 case 3: ands32 (cpu
, bimm
); return;
9647 case 0: and64 (cpu
, bimm64
); return;
9648 case 1: orr64 (cpu
, bimm64
); return;
9649 case 2: eor64 (cpu
, bimm64
); return;
9650 case 3: ands64 (cpu
, bimm64
); return;
9657 The uimm argument is a 16 bit value to be inserted into the
9658 target register the pos argument locates the 16 bit word in the
9659 dest register i.e. it is in {0, 1} for 32 bit and {0, 1, 2,
9661 N.B register arg may not be SP so it should be.
9662 accessed using the setGZRegisterXXX accessors. */
9664 /* 32 bit move 16 bit immediate zero remaining shorts. */
9666 movz32 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9668 unsigned rd
= INSTR (4, 0);
9670 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9671 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val
<< (pos
* 16));
9674 /* 64 bit move 16 bit immediate zero remaining shorts. */
9676 movz64 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9678 unsigned rd
= INSTR (4, 0);
9680 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9681 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, ((uint64_t) val
) << (pos
* 16));
9684 /* 32 bit move 16 bit immediate negated. */
9686 movn32 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9688 unsigned rd
= INSTR (4, 0);
9690 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9691 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, ((val
<< (pos
* 16)) ^ 0xffffffffU
));
9694 /* 64 bit move 16 bit immediate negated. */
9696 movn64 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9698 unsigned rd
= INSTR (4, 0);
9700 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9702 (cpu
, rd
, NO_SP
, ((((uint64_t) val
) << (pos
* 16))
9703 ^ 0xffffffffffffffffULL
));
9706 /* 32 bit move 16 bit immediate keep remaining shorts. */
9708 movk32 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9710 unsigned rd
= INSTR (4, 0);
9711 uint32_t current
= aarch64_get_reg_u32 (cpu
, rd
, NO_SP
);
9712 uint32_t value
= val
<< (pos
* 16);
9713 uint32_t mask
= ~(0xffffU
<< (pos
* 16));
9715 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9716 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (value
| (current
& mask
)));
9719 /* 64 bit move 16 it immediate keep remaining shorts. */
9721 movk64 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9723 unsigned rd
= INSTR (4, 0);
9724 uint64_t current
= aarch64_get_reg_u64 (cpu
, rd
, NO_SP
);
9725 uint64_t value
= (uint64_t) val
<< (pos
* 16);
9726 uint64_t mask
= ~(0xffffULL
<< (pos
* 16));
9728 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9729 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (value
| (current
& mask
)));
9733 dexMoveWideImmediate (sim_cpu
*cpu
)
9735 /* assert instr[28:23] = 100101
9736 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9737 instr[30,29] = op : 0 ==> MOVN, 1 ==> UNALLOC, 2 ==> MOVZ, 3 ==> MOVK
9738 instr[22,21] = shift : 00 == LSL#0, 01 = LSL#16, 10 = LSL#32, 11 = LSL#48
9739 instr[20,5] = uimm16
9742 /* N.B. the (multiple of 16) shift is applied by the called routine,
9743 we just pass the multiplier. */
9746 uint32_t size
= INSTR (31, 31);
9747 uint32_t op
= INSTR (30, 29);
9748 uint32_t shift
= INSTR (22, 21);
9750 /* 32 bit can only shift 0 or 1 lot of 16.
9751 anything else is an unallocated instruction. */
9752 if (size
== 0 && (shift
> 1))
9758 imm
= INSTR (20, 5);
9763 movn32 (cpu
, imm
, shift
);
9765 movz32 (cpu
, imm
, shift
);
9767 movk32 (cpu
, imm
, shift
);
9772 movn64 (cpu
, imm
, shift
);
9774 movz64 (cpu
, imm
, shift
);
9776 movk64 (cpu
, imm
, shift
);
9780 /* Bitfield operations.
9781 These take a pair of bit positions r and s which are in {0..31}
9782 or {0..63} depending on the instruction word size.
9783 N.B register args may not be SP. */
9785 /* OK, we start with ubfm which just needs to pick
9786 some bits out of source zero the rest and write
9787 the result to dest. Just need two logical shifts. */
9789 /* 32 bit bitfield move, left and right of affected zeroed
9790 if r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
9792 ubfm32 (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9795 unsigned rn
= INSTR (9, 5);
9796 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9798 /* Pick either s+1-r or s+1 consecutive bits out of the original word. */
9801 /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
9802 We want only bits s:xxx:r at the bottom of the word
9803 so we LSL bit s up to bit 31 i.e. by 31 - s
9804 and then we LSR to bring bit 31 down to bit s - r
9805 i.e. by 31 + r - s. */
9807 value
>>= 31 + r
- s
;
9811 /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0
9812 We want only bits s:xxx:0 starting at it 31-(r-1)
9813 so we LSL bit s up to bit 31 i.e. by 31 - s
9814 and then we LSL to bring bit 31 down to 31-(r-1)+s
9815 i.e. by r - (s + 1). */
9817 value
>>= r
- (s
+ 1);
9820 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9822 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
9825 /* 64 bit bitfield move, left and right of affected zeroed
9826 if r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
9828 ubfm (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9831 unsigned rn
= INSTR (9, 5);
9832 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9836 /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
9837 We want only bits s:xxx:r at the bottom of the word.
9838 So we LSL bit s up to bit 63 i.e. by 63 - s
9839 and then we LSR to bring bit 63 down to bit s - r
9840 i.e. by 63 + r - s. */
9842 value
>>= 63 + r
- s
;
9846 /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0.
9847 We want only bits s:xxx:0 starting at it 63-(r-1).
9848 So we LSL bit s up to bit 63 i.e. by 63 - s
9849 and then we LSL to bring bit 63 down to 63-(r-1)+s
9850 i.e. by r - (s + 1). */
9852 value
>>= r
- (s
+ 1);
9855 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9857 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
9860 /* The signed versions need to insert sign bits
9861 on the left of the inserted bit field. so we do
9862 much the same as the unsigned version except we
9863 use an arithmetic shift right -- this just means
9864 we need to operate on signed values. */
9866 /* 32 bit bitfield move, left of affected sign-extended, right zeroed. */
9867 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
9869 sbfm32 (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9872 unsigned rn
= INSTR (9, 5);
9873 /* as per ubfm32 but use an ASR instead of an LSR. */
9874 int32_t value
= aarch64_get_reg_s32 (cpu
, rn
, NO_SP
);
9879 value
>>= 31 + r
- s
;
9884 value
>>= r
- (s
+ 1);
9887 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9889 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) value
);
9892 /* 64 bit bitfield move, left of affected sign-extended, right zeroed. */
9893 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
9895 sbfm (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9898 unsigned rn
= INSTR (9, 5);
9899 /* acpu per ubfm but use an ASR instead of an LSR. */
9900 int64_t value
= aarch64_get_reg_s64 (cpu
, rn
, NO_SP
);
9905 value
>>= 63 + r
- s
;
9910 value
>>= r
- (s
+ 1);
9913 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9915 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, value
);
9918 /* Finally, these versions leave non-affected bits
9919 as is. so we need to generate the bits as per
9920 ubfm and also generate a mask to pick the
9921 bits from the original and computed values. */
9923 /* 32 bit bitfield move, non-affected bits left as is.
9924 If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
9926 bfm32 (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9928 unsigned rn
= INSTR (9, 5);
9929 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9934 /* Pick either s+1-r or s+1 consecutive bits out of the original word. */
9937 /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
9938 We want only bits s:xxx:r at the bottom of the word
9939 so we LSL bit s up to bit 31 i.e. by 31 - s
9940 and then we LSR to bring bit 31 down to bit s - r
9941 i.e. by 31 + r - s. */
9943 value
>>= 31 + r
- s
;
9944 /* the mask must include the same bits. */
9946 mask
>>= 31 + r
- s
;
9950 /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0.
9951 We want only bits s:xxx:0 starting at it 31-(r-1)
9952 so we LSL bit s up to bit 31 i.e. by 31 - s
9953 and then we LSL to bring bit 31 down to 31-(r-1)+s
9954 i.e. by r - (s + 1). */
9956 value
>>= r
- (s
+ 1);
9957 /* The mask must include the same bits. */
9959 mask
>>= r
- (s
+ 1);
9963 value2
= aarch64_get_reg_u32 (cpu
, rd
, NO_SP
);
9968 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9970 (cpu
, rd
, NO_SP
, (aarch64_get_reg_u32 (cpu
, rd
, NO_SP
) & ~mask
) | value
);
9973 /* 64 bit bitfield move, non-affected bits left as is.
9974 If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
9976 bfm (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
9979 unsigned rn
= INSTR (9, 5);
9980 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9981 uint64_t mask
= 0xffffffffffffffffULL
;
9985 /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
9986 We want only bits s:xxx:r at the bottom of the word
9987 so we LSL bit s up to bit 63 i.e. by 63 - s
9988 and then we LSR to bring bit 63 down to bit s - r
9989 i.e. by 63 + r - s. */
9991 value
>>= 63 + r
- s
;
9992 /* The mask must include the same bits. */
9994 mask
>>= 63 + r
- s
;
9998 /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0
9999 We want only bits s:xxx:0 starting at it 63-(r-1)
10000 so we LSL bit s up to bit 63 i.e. by 63 - s
10001 and then we LSL to bring bit 63 down to 63-(r-1)+s
10002 i.e. by r - (s + 1). */
10004 value
>>= r
- (s
+ 1);
10005 /* The mask must include the same bits. */
10007 mask
>>= r
- (s
+ 1);
10010 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10012 aarch64_set_reg_u64
10013 (cpu
, rd
, NO_SP
, (aarch64_get_reg_u64 (cpu
, rd
, NO_SP
) & ~mask
) | value
);
10017 dexBitfieldImmediate (sim_cpu
*cpu
)
10019 /* assert instr[28:23] = 100110
10020 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
10021 instr[30,29] = op : 0 ==> SBFM, 1 ==> BFM, 2 ==> UBFM, 3 ==> UNALLOC
10022 instr[22] = N : must be 0 for 32 bit, 1 for 64 bit ow UNALLOC
10023 instr[21,16] = immr : 0xxxxx for 32 bit, xxxxxx for 64 bit
10024 instr[15,10] = imms : 0xxxxx for 32 bit, xxxxxx for 64 bit
10028 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
10031 uint32_t size
= INSTR (31, 31);
10032 uint32_t N
= INSTR (22, 22);
10033 /* 32 bit operations must have immr[5] = 0 and imms[5] = 0. */
10034 /* or else we have an UNALLOC. */
10035 uint32_t immr
= INSTR (21, 16);
10040 if (!size
&& uimm (immr
, 5, 5))
10043 imms
= INSTR (15, 10);
10044 if (!size
&& uimm (imms
, 5, 5))
10047 /* Switch on combined size and op. */
10048 dispatch
= INSTR (31, 29);
10051 case 0: sbfm32 (cpu
, immr
, imms
); return;
10052 case 1: bfm32 (cpu
, immr
, imms
); return;
10053 case 2: ubfm32 (cpu
, immr
, imms
); return;
10054 case 4: sbfm (cpu
, immr
, imms
); return;
10055 case 5: bfm (cpu
, immr
, imms
); return;
10056 case 6: ubfm (cpu
, immr
, imms
); return;
10057 default: HALT_UNALLOC
;
10062 do_EXTR_32 (sim_cpu
*cpu
)
10064 /* instr[31:21] = 00010011100
10066 instr[15,10] = imms : 0xxxxx for 32 bit
10069 unsigned rm
= INSTR (20, 16);
10070 unsigned imms
= INSTR (15, 10) & 31;
10071 unsigned rn
= INSTR ( 9, 5);
10072 unsigned rd
= INSTR ( 4, 0);
10076 val1
= aarch64_get_reg_u32 (cpu
, rm
, NO_SP
);
10078 val2
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
10079 val2
<<= (32 - imms
);
10081 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10082 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val1
| val2
);
10086 do_EXTR_64 (sim_cpu
*cpu
)
10088 /* instr[31:21] = 10010011100
10090 instr[15,10] = imms
10093 unsigned rm
= INSTR (20, 16);
10094 unsigned imms
= INSTR (15, 10) & 63;
10095 unsigned rn
= INSTR ( 9, 5);
10096 unsigned rd
= INSTR ( 4, 0);
10099 val
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
10101 val
|= (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) << (64 - imms
));
10103 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val
);
10107 dexExtractImmediate (sim_cpu
*cpu
)
10109 /* assert instr[28:23] = 100111
10110 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
10111 instr[30,29] = op21 : 0 ==> EXTR, 1,2,3 ==> UNALLOC
10112 instr[22] = N : must be 0 for 32 bit, 1 for 64 bit or UNALLOC
10113 instr[21] = op0 : must be 0 or UNALLOC
10115 instr[15,10] = imms : 0xxxxx for 32 bit, xxxxxx for 64 bit
10119 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
10120 /* 64 bit operations must have N = 1 or else we have an UNALLOC. */
10122 uint32_t size
= INSTR (31, 31);
10123 uint32_t N
= INSTR (22, 22);
10124 /* 32 bit operations must have imms[5] = 0
10125 or else we have an UNALLOC. */
10126 uint32_t imms
= INSTR (15, 10);
10131 if (!size
&& uimm (imms
, 5, 5))
10134 /* Switch on combined size and op. */
10135 dispatch
= INSTR (31, 29);
10140 else if (dispatch
== 4)
10143 else if (dispatch
== 1)
10150 dexDPImm (sim_cpu
*cpu
)
10152 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
10153 assert group == GROUP_DPIMM_1000 || grpoup == GROUP_DPIMM_1001
10154 bits [25,23] of a DPImm are the secondary dispatch vector. */
10155 uint32_t group2
= dispatchDPImm (aarch64_get_instr (cpu
));
10159 case DPIMM_PCADR_000
:
10160 case DPIMM_PCADR_001
:
10161 dexPCRelAddressing (cpu
);
10164 case DPIMM_ADDSUB_010
:
10165 case DPIMM_ADDSUB_011
:
10166 dexAddSubtractImmediate (cpu
);
10169 case DPIMM_LOG_100
:
10170 dexLogicalImmediate (cpu
);
10173 case DPIMM_MOV_101
:
10174 dexMoveWideImmediate (cpu
);
10177 case DPIMM_BITF_110
:
10178 dexBitfieldImmediate (cpu
);
10181 case DPIMM_EXTR_111
:
10182 dexExtractImmediate (cpu
);
10186 /* Should never reach here. */
10192 dexLoadUnscaledImmediate (sim_cpu
*cpu
)
10194 /* instr[29,24] == 111_00
10197 instr[31,30] = size
10200 instr[20,12] = simm9
10201 instr[9,5] = rn may be SP. */
10202 /* unsigned rt = INSTR (4, 0); */
10203 uint32_t V
= INSTR (26, 26);
10204 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
10205 int32_t imm
= simm32 (aarch64_get_instr (cpu
), 20, 12);
10209 /* GReg operations. */
10212 case 0: sturb (cpu
, imm
); return;
10213 case 1: ldurb32 (cpu
, imm
); return;
10214 case 2: ldursb64 (cpu
, imm
); return;
10215 case 3: ldursb32 (cpu
, imm
); return;
10216 case 4: sturh (cpu
, imm
); return;
10217 case 5: ldurh32 (cpu
, imm
); return;
10218 case 6: ldursh64 (cpu
, imm
); return;
10219 case 7: ldursh32 (cpu
, imm
); return;
10220 case 8: stur32 (cpu
, imm
); return;
10221 case 9: ldur32 (cpu
, imm
); return;
10222 case 10: ldursw (cpu
, imm
); return;
10223 case 12: stur64 (cpu
, imm
); return;
10224 case 13: ldur64 (cpu
, imm
); return;
10237 /* FReg operations. */
10240 case 2: fsturq (cpu
, imm
); return;
10241 case 3: fldurq (cpu
, imm
); return;
10242 case 8: fsturs (cpu
, imm
); return;
10243 case 9: fldurs (cpu
, imm
); return;
10244 case 12: fsturd (cpu
, imm
); return;
10245 case 13: fldurd (cpu
, imm
); return;
10247 case 0: /* STUR 8 bit FP. */
10248 case 1: /* LDUR 8 bit FP. */
10249 case 4: /* STUR 16 bit FP. */
10250 case 5: /* LDUR 8 bit FP. */
10264 /* N.B. A preliminary note regarding all the ldrs<x>32
10267 The signed value loaded by these instructions is cast to unsigned
10268 before being assigned to aarch64_get_reg_u64 (cpu, N) i.e. to the
10269 64 bit element of the GReg union. this performs a 32 bit sign extension
10270 (as required) but avoids 64 bit sign extension, thus ensuring that the
10271 top half of the register word is zero. this is what the spec demands
10272 when a 32 bit load occurs. */
10274 /* 32 bit load sign-extended byte scaled unsigned 12 bit. */
10276 ldrsb32_abs (sim_cpu
*cpu
, uint32_t offset
)
10278 unsigned int rn
= INSTR (9, 5);
10279 unsigned int rt
= INSTR (4, 0);
10281 /* The target register may not be SP but the source may be
10282 there is no scaling required for a byte load. */
10283 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
;
10284 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
10285 (int64_t) aarch64_get_mem_s8 (cpu
, address
));
10288 /* 32 bit load sign-extended byte scaled or unscaled zero-
10289 or sign-extended 32-bit register offset. */
10291 ldrsb32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10293 unsigned int rm
= INSTR (20, 16);
10294 unsigned int rn
= INSTR (9, 5);
10295 unsigned int rt
= INSTR (4, 0);
10297 /* rn may reference SP, rm and rt must reference ZR. */
10299 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10300 int64_t displacement
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10303 /* There is no scaling required for a byte load. */
10304 aarch64_set_reg_u64
10305 (cpu
, rt
, NO_SP
, (int64_t) aarch64_get_mem_s8 (cpu
, address
10309 /* 32 bit load sign-extended byte unscaled signed 9 bit with
10310 pre- or post-writeback. */
10312 ldrsb32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10315 unsigned int rn
= INSTR (9, 5);
10316 unsigned int rt
= INSTR (4, 0);
10318 if (rn
== rt
&& wb
!= NoWriteBack
)
10321 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10326 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
10327 (int64_t) aarch64_get_mem_s8 (cpu
, address
));
10332 if (wb
!= NoWriteBack
)
10333 aarch64_set_reg_u64 (cpu
, rn
, NO_SP
, address
);
10336 /* 8 bit store scaled. */
10338 fstrb_abs (sim_cpu
*cpu
, uint32_t offset
)
10340 unsigned st
= INSTR (4, 0);
10341 unsigned rn
= INSTR (9, 5);
10343 aarch64_set_mem_u8 (cpu
,
10344 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
10345 aarch64_get_vec_u8 (cpu
, st
, 0));
10348 /* 8 bit store scaled or unscaled zero- or
10349 sign-extended 8-bit register offset. */
10351 fstrb_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10353 unsigned rm
= INSTR (20, 16);
10354 unsigned rn
= INSTR (9, 5);
10355 unsigned st
= INSTR (4, 0);
10357 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10358 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10360 uint64_t displacement
= scaling
== Scaled
? extended
: 0;
10363 (cpu
, address
+ displacement
, aarch64_get_vec_u8 (cpu
, st
, 0));
10366 /* 16 bit store scaled. */
10368 fstrh_abs (sim_cpu
*cpu
, uint32_t offset
)
10370 unsigned st
= INSTR (4, 0);
10371 unsigned rn
= INSTR (9, 5);
10373 aarch64_set_mem_u16
10375 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 16),
10376 aarch64_get_vec_u16 (cpu
, st
, 0));
10379 /* 16 bit store scaled or unscaled zero-
10380 or sign-extended 16-bit register offset. */
10382 fstrh_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10384 unsigned rm
= INSTR (20, 16);
10385 unsigned rn
= INSTR (9, 5);
10386 unsigned st
= INSTR (4, 0);
10388 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10389 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10391 uint64_t displacement
= OPT_SCALE (extended
, 16, scaling
);
10393 aarch64_set_mem_u16
10394 (cpu
, address
+ displacement
, aarch64_get_vec_u16 (cpu
, st
, 0));
10397 /* 32 bit store scaled unsigned 12 bit. */
10399 fstrs_abs (sim_cpu
*cpu
, uint32_t offset
)
10401 unsigned st
= INSTR (4, 0);
10402 unsigned rn
= INSTR (9, 5);
10404 aarch64_set_mem_u32
10406 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 32),
10407 aarch64_get_vec_u32 (cpu
, st
, 0));
10410 /* 32 bit store unscaled signed 9 bit with pre- or post-writeback. */
10412 fstrs_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10414 unsigned rn
= INSTR (9, 5);
10415 unsigned st
= INSTR (4, 0);
10417 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10422 aarch64_set_mem_u32 (cpu
, address
, aarch64_get_vec_u32 (cpu
, st
, 0));
10427 if (wb
!= NoWriteBack
)
10428 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
10431 /* 32 bit store scaled or unscaled zero-
10432 or sign-extended 32-bit register offset. */
10434 fstrs_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10436 unsigned rm
= INSTR (20, 16);
10437 unsigned rn
= INSTR (9, 5);
10438 unsigned st
= INSTR (4, 0);
10440 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10441 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10443 uint64_t displacement
= OPT_SCALE (extended
, 32, scaling
);
10445 aarch64_set_mem_u32
10446 (cpu
, address
+ displacement
, aarch64_get_vec_u32 (cpu
, st
, 0));
10449 /* 64 bit store scaled unsigned 12 bit. */
10451 fstrd_abs (sim_cpu
*cpu
, uint32_t offset
)
10453 unsigned st
= INSTR (4, 0);
10454 unsigned rn
= INSTR (9, 5);
10456 aarch64_set_mem_u64
10458 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 64),
10459 aarch64_get_vec_u64 (cpu
, st
, 0));
10462 /* 64 bit store unscaled signed 9 bit with pre- or post-writeback. */
10464 fstrd_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10466 unsigned rn
= INSTR (9, 5);
10467 unsigned st
= INSTR (4, 0);
10469 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10474 aarch64_set_mem_u64 (cpu
, address
, aarch64_get_vec_u64 (cpu
, st
, 0));
10479 if (wb
!= NoWriteBack
)
10480 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
10483 /* 64 bit store scaled or unscaled zero-
10484 or sign-extended 32-bit register offset. */
10486 fstrd_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10488 unsigned rm
= INSTR (20, 16);
10489 unsigned rn
= INSTR (9, 5);
10490 unsigned st
= INSTR (4, 0);
10492 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10493 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10495 uint64_t displacement
= OPT_SCALE (extended
, 64, scaling
);
10497 aarch64_set_mem_u64
10498 (cpu
, address
+ displacement
, aarch64_get_vec_u64 (cpu
, st
, 0));
10501 /* 128 bit store scaled unsigned 12 bit. */
10503 fstrq_abs (sim_cpu
*cpu
, uint32_t offset
)
10506 unsigned st
= INSTR (4, 0);
10507 unsigned rn
= INSTR (9, 5);
10510 aarch64_get_FP_long_double (cpu
, st
, & a
);
10512 addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 128);
10513 aarch64_set_mem_long_double (cpu
, addr
, a
);
10516 /* 128 bit store unscaled signed 9 bit with pre- or post-writeback. */
10518 fstrq_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10521 unsigned rn
= INSTR (9, 5);
10522 unsigned st
= INSTR (4, 0);
10523 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10528 aarch64_get_FP_long_double (cpu
, st
, & a
);
10529 aarch64_set_mem_long_double (cpu
, address
, a
);
10534 if (wb
!= NoWriteBack
)
10535 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
10538 /* 128 bit store scaled or unscaled zero-
10539 or sign-extended 32-bit register offset. */
10541 fstrq_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10543 unsigned rm
= INSTR (20, 16);
10544 unsigned rn
= INSTR (9, 5);
10545 unsigned st
= INSTR (4, 0);
10547 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10548 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10550 uint64_t displacement
= OPT_SCALE (extended
, 128, scaling
);
10554 aarch64_get_FP_long_double (cpu
, st
, & a
);
10555 aarch64_set_mem_long_double (cpu
, address
+ displacement
, a
);
10559 dexLoadImmediatePrePost (sim_cpu
*cpu
)
10561 /* instr[31,30] = size
10567 instr[20,12] = simm9
10568 instr[11] = wb : 0 ==> Post, 1 ==> Pre
10570 instr[9,5] = Rn may be SP.
10573 uint32_t V
= INSTR (26, 26);
10574 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
10575 int32_t imm
= simm32 (aarch64_get_instr (cpu
), 20, 12);
10576 WriteBack wb
= INSTR (11, 11);
10580 /* GReg operations. */
10583 case 0: strb_wb (cpu
, imm
, wb
); return;
10584 case 1: ldrb32_wb (cpu
, imm
, wb
); return;
10585 case 2: ldrsb_wb (cpu
, imm
, wb
); return;
10586 case 3: ldrsb32_wb (cpu
, imm
, wb
); return;
10587 case 4: strh_wb (cpu
, imm
, wb
); return;
10588 case 5: ldrh32_wb (cpu
, imm
, wb
); return;
10589 case 6: ldrsh64_wb (cpu
, imm
, wb
); return;
10590 case 7: ldrsh32_wb (cpu
, imm
, wb
); return;
10591 case 8: str32_wb (cpu
, imm
, wb
); return;
10592 case 9: ldr32_wb (cpu
, imm
, wb
); return;
10593 case 10: ldrsw_wb (cpu
, imm
, wb
); return;
10594 case 12: str_wb (cpu
, imm
, wb
); return;
10595 case 13: ldr_wb (cpu
, imm
, wb
); return;
10605 /* FReg operations. */
10608 case 2: fstrq_wb (cpu
, imm
, wb
); return;
10609 case 3: fldrq_wb (cpu
, imm
, wb
); return;
10610 case 8: fstrs_wb (cpu
, imm
, wb
); return;
10611 case 9: fldrs_wb (cpu
, imm
, wb
); return;
10612 case 12: fstrd_wb (cpu
, imm
, wb
); return;
10613 case 13: fldrd_wb (cpu
, imm
, wb
); return;
10615 case 0: /* STUR 8 bit FP. */
10616 case 1: /* LDUR 8 bit FP. */
10617 case 4: /* STUR 16 bit FP. */
10618 case 5: /* LDUR 8 bit FP. */
10633 dexLoadRegisterOffset (sim_cpu
*cpu
)
10635 /* instr[31,30] = size
10642 instr[15,13] = option : 010 ==> UXTW, 011 ==> UXTX/LSL,
10643 110 ==> SXTW, 111 ==> SXTX,
10648 instr[4,0] = rt. */
10650 uint32_t V
= INSTR (26, 26);
10651 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
10652 Scaling scale
= INSTR (12, 12);
10653 Extension extensionType
= INSTR (15, 13);
10655 /* Check for illegal extension types. */
10656 if (uimm (extensionType
, 1, 1) == 0)
10659 if (extensionType
== UXTX
|| extensionType
== SXTX
)
10660 extensionType
= NoExtension
;
10664 /* GReg operations. */
10667 case 0: strb_scale_ext (cpu
, scale
, extensionType
); return;
10668 case 1: ldrb32_scale_ext (cpu
, scale
, extensionType
); return;
10669 case 2: ldrsb_scale_ext (cpu
, scale
, extensionType
); return;
10670 case 3: ldrsb32_scale_ext (cpu
, scale
, extensionType
); return;
10671 case 4: strh_scale_ext (cpu
, scale
, extensionType
); return;
10672 case 5: ldrh32_scale_ext (cpu
, scale
, extensionType
); return;
10673 case 6: ldrsh_scale_ext (cpu
, scale
, extensionType
); return;
10674 case 7: ldrsh32_scale_ext (cpu
, scale
, extensionType
); return;
10675 case 8: str32_scale_ext (cpu
, scale
, extensionType
); return;
10676 case 9: ldr32_scale_ext (cpu
, scale
, extensionType
); return;
10677 case 10: ldrsw_scale_ext (cpu
, scale
, extensionType
); return;
10678 case 12: str_scale_ext (cpu
, scale
, extensionType
); return;
10679 case 13: ldr_scale_ext (cpu
, scale
, extensionType
); return;
10680 case 14: prfm_scale_ext (cpu
, scale
, extensionType
); return;
10689 /* FReg operations. */
10692 case 1: /* LDUR 8 bit FP. */
10694 case 3: fldrq_scale_ext (cpu
, scale
, extensionType
); return;
10695 case 5: /* LDUR 8 bit FP. */
10697 case 9: fldrs_scale_ext (cpu
, scale
, extensionType
); return;
10698 case 13: fldrd_scale_ext (cpu
, scale
, extensionType
); return;
10700 case 0: fstrb_scale_ext (cpu
, scale
, extensionType
); return;
10701 case 2: fstrq_scale_ext (cpu
, scale
, extensionType
); return;
10702 case 4: fstrh_scale_ext (cpu
, scale
, extensionType
); return;
10703 case 8: fstrs_scale_ext (cpu
, scale
, extensionType
); return;
10704 case 12: fstrd_scale_ext (cpu
, scale
, extensionType
); return;
10718 dexLoadUnsignedImmediate (sim_cpu
*cpu
)
10720 /* instr[29,24] == 111_01
10721 instr[31,30] = size
10724 instr[21,10] = uimm12 : unsigned immediate offset
10725 instr[9,5] = rn may be SP.
10726 instr[4,0] = rt. */
10728 uint32_t V
= INSTR (26,26);
10729 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
10730 uint32_t imm
= INSTR (21, 10);
10734 /* GReg operations. */
10737 case 0: strb_abs (cpu
, imm
); return;
10738 case 1: ldrb32_abs (cpu
, imm
); return;
10739 case 2: ldrsb_abs (cpu
, imm
); return;
10740 case 3: ldrsb32_abs (cpu
, imm
); return;
10741 case 4: strh_abs (cpu
, imm
); return;
10742 case 5: ldrh32_abs (cpu
, imm
); return;
10743 case 6: ldrsh_abs (cpu
, imm
); return;
10744 case 7: ldrsh32_abs (cpu
, imm
); return;
10745 case 8: str32_abs (cpu
, imm
); return;
10746 case 9: ldr32_abs (cpu
, imm
); return;
10747 case 10: ldrsw_abs (cpu
, imm
); return;
10748 case 12: str_abs (cpu
, imm
); return;
10749 case 13: ldr_abs (cpu
, imm
); return;
10750 case 14: prfm_abs (cpu
, imm
); return;
10759 /* FReg operations. */
10762 case 0: fstrb_abs (cpu
, imm
); return;
10763 case 4: fstrh_abs (cpu
, imm
); return;
10764 case 8: fstrs_abs (cpu
, imm
); return;
10765 case 12: fstrd_abs (cpu
, imm
); return;
10766 case 2: fstrq_abs (cpu
, imm
); return;
10768 case 1: fldrb_abs (cpu
, imm
); return;
10769 case 5: fldrh_abs (cpu
, imm
); return;
10770 case 9: fldrs_abs (cpu
, imm
); return;
10771 case 13: fldrd_abs (cpu
, imm
); return;
10772 case 3: fldrq_abs (cpu
, imm
); return;
10786 dexLoadExclusive (sim_cpu
*cpu
)
10788 /* assert instr[29:24] = 001000;
10789 instr[31,30] = size
10790 instr[23] = 0 if exclusive
10791 instr[22] = L : 1 if load, 0 if store
10792 instr[21] = 1 if pair
10794 instr[15] = o0 : 1 if ordered
10797 instr[4.0] = Rt. */
10799 switch (INSTR (22, 21))
10801 case 2: ldxr (cpu
); return;
10802 case 0: stxr (cpu
); return;
10808 dexLoadOther (sim_cpu
*cpu
)
10812 /* instr[29,25] = 111_0
10813 instr[24] == 0 ==> dispatch, 1 ==> ldst reg unsigned immediate
10814 instr[21:11,10] is the secondary dispatch. */
10815 if (INSTR (24, 24))
10817 dexLoadUnsignedImmediate (cpu
);
10821 dispatch
= ((INSTR (21, 21) << 2) | INSTR (11, 10));
10824 case 0: dexLoadUnscaledImmediate (cpu
); return;
10825 case 1: dexLoadImmediatePrePost (cpu
); return;
10826 case 3: dexLoadImmediatePrePost (cpu
); return;
10827 case 6: dexLoadRegisterOffset (cpu
); return;
10839 store_pair_u32 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10841 unsigned rn
= INSTR (14, 10);
10842 unsigned rd
= INSTR (9, 5);
10843 unsigned rm
= INSTR (4, 0);
10844 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10846 if ((rn
== rd
|| rm
== rd
) && wb
!= NoWriteBack
)
10847 HALT_UNALLOC
; /* ??? */
10854 aarch64_set_mem_u32 (cpu
, address
,
10855 aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
10856 aarch64_set_mem_u32 (cpu
, address
+ 4,
10857 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
));
10862 if (wb
!= NoWriteBack
)
10863 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10867 store_pair_u64 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10869 unsigned rn
= INSTR (14, 10);
10870 unsigned rd
= INSTR (9, 5);
10871 unsigned rm
= INSTR (4, 0);
10872 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10874 if ((rn
== rd
|| rm
== rd
) && wb
!= NoWriteBack
)
10875 HALT_UNALLOC
; /* ??? */
10882 aarch64_set_mem_u64 (cpu
, address
,
10883 aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
10884 aarch64_set_mem_u64 (cpu
, address
+ 8,
10885 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
10890 if (wb
!= NoWriteBack
)
10891 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10895 load_pair_u32 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10897 unsigned rn
= INSTR (14, 10);
10898 unsigned rd
= INSTR (9, 5);
10899 unsigned rm
= INSTR (4, 0);
10900 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10902 /* Treat this as unalloc to make sure we don't do it. */
10911 aarch64_set_reg_u64 (cpu
, rm
, SP_OK
, aarch64_get_mem_u32 (cpu
, address
));
10912 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, aarch64_get_mem_u32 (cpu
, address
+ 4));
10917 if (wb
!= NoWriteBack
)
10918 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10922 load_pair_s32 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10924 unsigned rn
= INSTR (14, 10);
10925 unsigned rd
= INSTR (9, 5);
10926 unsigned rm
= INSTR (4, 0);
10927 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10929 /* Treat this as unalloc to make sure we don't do it. */
10938 aarch64_set_reg_s64 (cpu
, rm
, SP_OK
, aarch64_get_mem_s32 (cpu
, address
));
10939 aarch64_set_reg_s64 (cpu
, rn
, SP_OK
, aarch64_get_mem_s32 (cpu
, address
+ 4));
10944 if (wb
!= NoWriteBack
)
10945 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10949 load_pair_u64 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10951 unsigned rn
= INSTR (14, 10);
10952 unsigned rd
= INSTR (9, 5);
10953 unsigned rm
= INSTR (4, 0);
10954 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
10956 /* Treat this as unalloc to make sure we don't do it. */
10965 aarch64_set_reg_u64 (cpu
, rm
, SP_OK
, aarch64_get_mem_u64 (cpu
, address
));
10966 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, aarch64_get_mem_u64 (cpu
, address
+ 8));
10971 if (wb
!= NoWriteBack
)
10972 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
10976 dex_load_store_pair_gr (sim_cpu
*cpu
)
10978 /* instr[31,30] = size (10=> 64-bit, 01=> signed 32-bit, 00=> 32-bit)
10979 instr[29,25] = instruction encoding: 101_0
10980 instr[26] = V : 1 if fp 0 if gp
10981 instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
10982 instr[22] = load/store (1=> load)
10983 instr[21,15] = signed, scaled, offset
10986 instr[ 4, 0] = Rm. */
10988 uint32_t dispatch
= ((INSTR (31, 30) << 3) | INSTR (24, 22));
10989 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 21, 15);
10993 case 2: store_pair_u32 (cpu
, offset
, Post
); return;
10994 case 3: load_pair_u32 (cpu
, offset
, Post
); return;
10995 case 4: store_pair_u32 (cpu
, offset
, NoWriteBack
); return;
10996 case 5: load_pair_u32 (cpu
, offset
, NoWriteBack
); return;
10997 case 6: store_pair_u32 (cpu
, offset
, Pre
); return;
10998 case 7: load_pair_u32 (cpu
, offset
, Pre
); return;
11000 case 11: load_pair_s32 (cpu
, offset
, Post
); return;
11001 case 13: load_pair_s32 (cpu
, offset
, NoWriteBack
); return;
11002 case 15: load_pair_s32 (cpu
, offset
, Pre
); return;
11004 case 18: store_pair_u64 (cpu
, offset
, Post
); return;
11005 case 19: load_pair_u64 (cpu
, offset
, Post
); return;
11006 case 20: store_pair_u64 (cpu
, offset
, NoWriteBack
); return;
11007 case 21: load_pair_u64 (cpu
, offset
, NoWriteBack
); return;
11008 case 22: store_pair_u64 (cpu
, offset
, Pre
); return;
11009 case 23: load_pair_u64 (cpu
, offset
, Pre
); return;
11017 store_pair_float (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11019 unsigned rn
= INSTR (14, 10);
11020 unsigned rd
= INSTR (9, 5);
11021 unsigned rm
= INSTR (4, 0);
11022 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11029 aarch64_set_mem_u32 (cpu
, address
, aarch64_get_vec_u32 (cpu
, rm
, 0));
11030 aarch64_set_mem_u32 (cpu
, address
+ 4, aarch64_get_vec_u32 (cpu
, rn
, 0));
11035 if (wb
!= NoWriteBack
)
11036 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11040 store_pair_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11042 unsigned rn
= INSTR (14, 10);
11043 unsigned rd
= INSTR (9, 5);
11044 unsigned rm
= INSTR (4, 0);
11045 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11052 aarch64_set_mem_u64 (cpu
, address
, aarch64_get_vec_u64 (cpu
, rm
, 0));
11053 aarch64_set_mem_u64 (cpu
, address
+ 8, aarch64_get_vec_u64 (cpu
, rn
, 0));
11058 if (wb
!= NoWriteBack
)
11059 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11063 store_pair_long_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11066 unsigned rn
= INSTR (14, 10);
11067 unsigned rd
= INSTR (9, 5);
11068 unsigned rm
= INSTR (4, 0);
11069 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11076 aarch64_get_FP_long_double (cpu
, rm
, & a
);
11077 aarch64_set_mem_long_double (cpu
, address
, a
);
11078 aarch64_get_FP_long_double (cpu
, rn
, & a
);
11079 aarch64_set_mem_long_double (cpu
, address
+ 16, a
);
11084 if (wb
!= NoWriteBack
)
11085 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11089 load_pair_float (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11091 unsigned rn
= INSTR (14, 10);
11092 unsigned rd
= INSTR (9, 5);
11093 unsigned rm
= INSTR (4, 0);
11094 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11104 aarch64_set_vec_u32 (cpu
, rm
, 0, aarch64_get_mem_u32 (cpu
, address
));
11105 aarch64_set_vec_u32 (cpu
, rn
, 0, aarch64_get_mem_u32 (cpu
, address
+ 4));
11110 if (wb
!= NoWriteBack
)
11111 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11115 load_pair_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11117 unsigned rn
= INSTR (14, 10);
11118 unsigned rd
= INSTR (9, 5);
11119 unsigned rm
= INSTR (4, 0);
11120 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11130 aarch64_set_vec_u64 (cpu
, rm
, 0, aarch64_get_mem_u64 (cpu
, address
));
11131 aarch64_set_vec_u64 (cpu
, rn
, 0, aarch64_get_mem_u64 (cpu
, address
+ 8));
11136 if (wb
!= NoWriteBack
)
11137 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11141 load_pair_long_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11144 unsigned rn
= INSTR (14, 10);
11145 unsigned rd
= INSTR (9, 5);
11146 unsigned rm
= INSTR (4, 0);
11147 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11157 aarch64_get_mem_long_double (cpu
, address
, & a
);
11158 aarch64_set_FP_long_double (cpu
, rm
, a
);
11159 aarch64_get_mem_long_double (cpu
, address
+ 16, & a
);
11160 aarch64_set_FP_long_double (cpu
, rn
, a
);
11165 if (wb
!= NoWriteBack
)
11166 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11170 dex_load_store_pair_fp (sim_cpu
*cpu
)
11172 /* instr[31,30] = size (10=> 128-bit, 01=> 64-bit, 00=> 32-bit)
11173 instr[29,25] = instruction encoding
11174 instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
11175 instr[22] = load/store (1=> load)
11176 instr[21,15] = signed, scaled, offset
11179 instr[ 4, 0] = Rm */
11181 uint32_t dispatch
= ((INSTR (31, 30) << 3) | INSTR (24, 22));
11182 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 21, 15);
11186 case 2: store_pair_float (cpu
, offset
, Post
); return;
11187 case 3: load_pair_float (cpu
, offset
, Post
); return;
11188 case 4: store_pair_float (cpu
, offset
, NoWriteBack
); return;
11189 case 5: load_pair_float (cpu
, offset
, NoWriteBack
); return;
11190 case 6: store_pair_float (cpu
, offset
, Pre
); return;
11191 case 7: load_pair_float (cpu
, offset
, Pre
); return;
11193 case 10: store_pair_double (cpu
, offset
, Post
); return;
11194 case 11: load_pair_double (cpu
, offset
, Post
); return;
11195 case 12: store_pair_double (cpu
, offset
, NoWriteBack
); return;
11196 case 13: load_pair_double (cpu
, offset
, NoWriteBack
); return;
11197 case 14: store_pair_double (cpu
, offset
, Pre
); return;
11198 case 15: load_pair_double (cpu
, offset
, Pre
); return;
11200 case 18: store_pair_long_double (cpu
, offset
, Post
); return;
11201 case 19: load_pair_long_double (cpu
, offset
, Post
); return;
11202 case 20: store_pair_long_double (cpu
, offset
, NoWriteBack
); return;
11203 case 21: load_pair_long_double (cpu
, offset
, NoWriteBack
); return;
11204 case 22: store_pair_long_double (cpu
, offset
, Pre
); return;
11205 case 23: load_pair_long_double (cpu
, offset
, Pre
); return;
11212 static inline unsigned
11213 vec_reg (unsigned v
, unsigned o
)
11215 return (v
+ o
) & 0x3F;
11218 /* Load multiple N-element structures to N consecutive registers. */
11220 vec_load (sim_cpu
*cpu
, uint64_t address
, unsigned N
)
11222 int all
= INSTR (30, 30);
11223 unsigned size
= INSTR (11, 10);
11224 unsigned vd
= INSTR (4, 0);
11229 case 0: /* 8-bit operations. */
11231 for (i
= 0; i
< (16 * N
); i
++)
11232 aarch64_set_vec_u8 (cpu
, vec_reg (vd
, i
>> 4), i
& 15,
11233 aarch64_get_mem_u8 (cpu
, address
+ i
));
11235 for (i
= 0; i
< (8 * N
); i
++)
11236 aarch64_set_vec_u8 (cpu
, vec_reg (vd
, i
>> 3), i
& 7,
11237 aarch64_get_mem_u8 (cpu
, address
+ i
));
11240 case 1: /* 16-bit operations. */
11242 for (i
= 0; i
< (8 * N
); i
++)
11243 aarch64_set_vec_u16 (cpu
, vec_reg (vd
, i
>> 3), i
& 7,
11244 aarch64_get_mem_u16 (cpu
, address
+ i
* 2));
11246 for (i
= 0; i
< (4 * N
); i
++)
11247 aarch64_set_vec_u16 (cpu
, vec_reg (vd
, i
>> 2), i
& 3,
11248 aarch64_get_mem_u16 (cpu
, address
+ i
* 2));
11251 case 2: /* 32-bit operations. */
11253 for (i
= 0; i
< (4 * N
); i
++)
11254 aarch64_set_vec_u32 (cpu
, vec_reg (vd
, i
>> 2), i
& 3,
11255 aarch64_get_mem_u32 (cpu
, address
+ i
* 4));
11257 for (i
= 0; i
< (2 * N
); i
++)
11258 aarch64_set_vec_u32 (cpu
, vec_reg (vd
, i
>> 1), i
& 1,
11259 aarch64_get_mem_u32 (cpu
, address
+ i
* 4));
11262 case 3: /* 64-bit operations. */
11264 for (i
= 0; i
< (2 * N
); i
++)
11265 aarch64_set_vec_u64 (cpu
, vec_reg (vd
, i
>> 1), i
& 1,
11266 aarch64_get_mem_u64 (cpu
, address
+ i
* 8));
11268 for (i
= 0; i
< N
; i
++)
11269 aarch64_set_vec_u64 (cpu
, vec_reg (vd
, i
), 0,
11270 aarch64_get_mem_u64 (cpu
, address
+ i
* 8));
11275 /* LD4: load multiple 4-element to four consecutive registers. */
11277 LD4 (sim_cpu
*cpu
, uint64_t address
)
11279 vec_load (cpu
, address
, 4);
11282 /* LD3: load multiple 3-element structures to three consecutive registers. */
11284 LD3 (sim_cpu
*cpu
, uint64_t address
)
11286 vec_load (cpu
, address
, 3);
11289 /* LD2: load multiple 2-element structures to two consecutive registers. */
11291 LD2 (sim_cpu
*cpu
, uint64_t address
)
11293 vec_load (cpu
, address
, 2);
11296 /* Load multiple 1-element structures into one register. */
11298 LD1_1 (sim_cpu
*cpu
, uint64_t address
)
11300 int all
= INSTR (30, 30);
11301 unsigned size
= INSTR (11, 10);
11302 unsigned vd
= INSTR (4, 0);
11308 /* LD1 {Vd.16b}, addr, #16 */
11309 /* LD1 {Vd.8b}, addr, #8 */
11310 for (i
= 0; i
< (all
? 16 : 8); i
++)
11311 aarch64_set_vec_u8 (cpu
, vd
, i
,
11312 aarch64_get_mem_u8 (cpu
, address
+ i
));
11316 /* LD1 {Vd.8h}, addr, #16 */
11317 /* LD1 {Vd.4h}, addr, #8 */
11318 for (i
= 0; i
< (all
? 8 : 4); i
++)
11319 aarch64_set_vec_u16 (cpu
, vd
, i
,
11320 aarch64_get_mem_u16 (cpu
, address
+ i
* 2));
11324 /* LD1 {Vd.4s}, addr, #16 */
11325 /* LD1 {Vd.2s}, addr, #8 */
11326 for (i
= 0; i
< (all
? 4 : 2); i
++)
11327 aarch64_set_vec_u32 (cpu
, vd
, i
,
11328 aarch64_get_mem_u32 (cpu
, address
+ i
* 4));
11332 /* LD1 {Vd.2d}, addr, #16 */
11333 /* LD1 {Vd.1d}, addr, #8 */
11334 for (i
= 0; i
< (all
? 2 : 1); i
++)
11335 aarch64_set_vec_u64 (cpu
, vd
, i
,
11336 aarch64_get_mem_u64 (cpu
, address
+ i
* 8));
11341 /* Load multiple 1-element structures into two registers. */
11343 LD1_2 (sim_cpu
*cpu
, uint64_t address
)
11345 /* FIXME: This algorithm is *exactly* the same as the LD2 version.
11346 So why have two different instructions ? There must be something
11347 wrong somewhere. */
11348 vec_load (cpu
, address
, 2);
11351 /* Load multiple 1-element structures into three registers. */
11353 LD1_3 (sim_cpu
*cpu
, uint64_t address
)
11355 /* FIXME: This algorithm is *exactly* the same as the LD3 version.
11356 So why have two different instructions ? There must be something
11357 wrong somewhere. */
11358 vec_load (cpu
, address
, 3);
11361 /* Load multiple 1-element structures into four registers. */
11363 LD1_4 (sim_cpu
*cpu
, uint64_t address
)
11365 /* FIXME: This algorithm is *exactly* the same as the LD4 version.
11366 So why have two different instructions ? There must be something
11367 wrong somewhere. */
11368 vec_load (cpu
, address
, 4);
11371 /* Store multiple N-element structures to N consecutive registers. */
11373 vec_store (sim_cpu
*cpu
, uint64_t address
, unsigned N
)
11375 int all
= INSTR (30, 30);
11376 unsigned size
= INSTR (11, 10);
11377 unsigned vd
= INSTR (4, 0);
11382 case 0: /* 8-bit operations. */
11384 for (i
= 0; i
< (16 * N
); i
++)
11387 aarch64_get_vec_u8 (cpu
, vec_reg (vd
, i
>> 4), i
& 15));
11389 for (i
= 0; i
< (8 * N
); i
++)
11392 aarch64_get_vec_u8 (cpu
, vec_reg (vd
, i
>> 3), i
& 7));
11395 case 1: /* 16-bit operations. */
11397 for (i
= 0; i
< (8 * N
); i
++)
11398 aarch64_set_mem_u16
11399 (cpu
, address
+ i
* 2,
11400 aarch64_get_vec_u16 (cpu
, vec_reg (vd
, i
>> 3), i
& 7));
11402 for (i
= 0; i
< (4 * N
); i
++)
11403 aarch64_set_mem_u16
11404 (cpu
, address
+ i
* 2,
11405 aarch64_get_vec_u16 (cpu
, vec_reg (vd
, i
>> 2), i
& 3));
11408 case 2: /* 32-bit operations. */
11410 for (i
= 0; i
< (4 * N
); i
++)
11411 aarch64_set_mem_u32
11412 (cpu
, address
+ i
* 4,
11413 aarch64_get_vec_u32 (cpu
, vec_reg (vd
, i
>> 2), i
& 3));
11415 for (i
= 0; i
< (2 * N
); i
++)
11416 aarch64_set_mem_u32
11417 (cpu
, address
+ i
* 4,
11418 aarch64_get_vec_u32 (cpu
, vec_reg (vd
, i
>> 1), i
& 1));
11421 case 3: /* 64-bit operations. */
11423 for (i
= 0; i
< (2 * N
); i
++)
11424 aarch64_set_mem_u64
11425 (cpu
, address
+ i
* 8,
11426 aarch64_get_vec_u64 (cpu
, vec_reg (vd
, i
>> 1), i
& 1));
11428 for (i
= 0; i
< N
; i
++)
11429 aarch64_set_mem_u64
11430 (cpu
, address
+ i
* 8,
11431 aarch64_get_vec_u64 (cpu
, vec_reg (vd
, i
), 0));
11436 /* Store multiple 4-element structure to four consecutive registers. */
11438 ST4 (sim_cpu
*cpu
, uint64_t address
)
11440 vec_store (cpu
, address
, 4);
11443 /* Store multiple 3-element structures to three consecutive registers. */
11445 ST3 (sim_cpu
*cpu
, uint64_t address
)
11447 vec_store (cpu
, address
, 3);
11450 /* Store multiple 2-element structures to two consecutive registers. */
11452 ST2 (sim_cpu
*cpu
, uint64_t address
)
11454 vec_store (cpu
, address
, 2);
11457 /* Store multiple 1-element structures into one register. */
11459 ST1_1 (sim_cpu
*cpu
, uint64_t address
)
11461 int all
= INSTR (30, 30);
11462 unsigned size
= INSTR (11, 10);
11463 unsigned vd
= INSTR (4, 0);
11469 for (i
= 0; i
< (all
? 16 : 8); i
++)
11470 aarch64_set_mem_u8 (cpu
, address
+ i
,
11471 aarch64_get_vec_u8 (cpu
, vd
, i
));
11475 for (i
= 0; i
< (all
? 8 : 4); i
++)
11476 aarch64_set_mem_u16 (cpu
, address
+ i
* 2,
11477 aarch64_get_vec_u16 (cpu
, vd
, i
));
11481 for (i
= 0; i
< (all
? 4 : 2); i
++)
11482 aarch64_set_mem_u32 (cpu
, address
+ i
* 4,
11483 aarch64_get_vec_u32 (cpu
, vd
, i
));
11487 for (i
= 0; i
< (all
? 2 : 1); i
++)
11488 aarch64_set_mem_u64 (cpu
, address
+ i
* 8,
11489 aarch64_get_vec_u64 (cpu
, vd
, i
));
11494 /* Store multiple 1-element structures into two registers. */
11496 ST1_2 (sim_cpu
*cpu
, uint64_t address
)
11498 /* FIXME: This algorithm is *exactly* the same as the ST2 version.
11499 So why have two different instructions ? There must be
11500 something wrong somewhere. */
11501 vec_store (cpu
, address
, 2);
11504 /* Store multiple 1-element structures into three registers. */
11506 ST1_3 (sim_cpu
*cpu
, uint64_t address
)
11508 /* FIXME: This algorithm is *exactly* the same as the ST3 version.
11509 So why have two different instructions ? There must be
11510 something wrong somewhere. */
11511 vec_store (cpu
, address
, 3);
11514 /* Store multiple 1-element structures into four registers. */
11516 ST1_4 (sim_cpu
*cpu
, uint64_t address
)
11518 /* FIXME: This algorithm is *exactly* the same as the ST4 version.
11519 So why have two different instructions ? There must be
11520 something wrong somewhere. */
11521 vec_store (cpu
, address
, 4);
11525 do_vec_LDnR (sim_cpu
*cpu
, uint64_t address
)
11528 instr[30] = element selector 0=>half, 1=>all elements
11529 instr[29,24] = 00 1101
11530 instr[23] = 0=>simple, 1=>post
11532 instr[21] = width: LD1R-or-LD3R (0) / LD2R-or-LD4R (1)
11533 instr[20,16] = 0 0000 (simple), Vinc (reg-post-inc, no SP),
11534 11111 (immediate post inc)
11536 instr[13] = width: LD1R-or-LD2R (0) / LD3R-or-LD4R (1)
11538 instr[11,10] = element size 00=> byte(b), 01=> half(h),
11539 10=> word(s), 11=> double(d)
11540 instr[9,5] = address
11543 unsigned full
= INSTR (30, 30);
11544 unsigned vd
= INSTR (4, 0);
11545 unsigned size
= INSTR (11, 10);
11548 NYI_assert (29, 24, 0x0D);
11549 NYI_assert (22, 22, 1);
11550 NYI_assert (15, 14, 3);
11551 NYI_assert (12, 12, 0);
11553 switch ((INSTR (13, 13) << 1) | INSTR (21, 21))
11555 case 0: /* LD1R. */
11560 uint8_t val
= aarch64_get_mem_u8 (cpu
, address
);
11561 for (i
= 0; i
< (full
? 16 : 8); i
++)
11562 aarch64_set_vec_u8 (cpu
, vd
, i
, val
);
11568 uint16_t val
= aarch64_get_mem_u16 (cpu
, address
);
11569 for (i
= 0; i
< (full
? 8 : 4); i
++)
11570 aarch64_set_vec_u16 (cpu
, vd
, i
, val
);
11576 uint32_t val
= aarch64_get_mem_u32 (cpu
, address
);
11577 for (i
= 0; i
< (full
? 4 : 2); i
++)
11578 aarch64_set_vec_u32 (cpu
, vd
, i
, val
);
11584 uint64_t val
= aarch64_get_mem_u64 (cpu
, address
);
11585 for (i
= 0; i
< (full
? 2 : 1); i
++)
11586 aarch64_set_vec_u64 (cpu
, vd
, i
, val
);
11595 case 1: /* LD2R. */
11600 uint8_t val1
= aarch64_get_mem_u8 (cpu
, address
);
11601 uint8_t val2
= aarch64_get_mem_u8 (cpu
, address
+ 1);
11603 for (i
= 0; i
< (full
? 16 : 8); i
++)
11605 aarch64_set_vec_u8 (cpu
, vd
, 0, val1
);
11606 aarch64_set_vec_u8 (cpu
, vd
+ 1, 0, val2
);
11613 uint16_t val1
= aarch64_get_mem_u16 (cpu
, address
);
11614 uint16_t val2
= aarch64_get_mem_u16 (cpu
, address
+ 2);
11616 for (i
= 0; i
< (full
? 8 : 4); i
++)
11618 aarch64_set_vec_u16 (cpu
, vd
, 0, val1
);
11619 aarch64_set_vec_u16 (cpu
, vd
+ 1, 0, val2
);
11626 uint32_t val1
= aarch64_get_mem_u32 (cpu
, address
);
11627 uint32_t val2
= aarch64_get_mem_u32 (cpu
, address
+ 4);
11629 for (i
= 0; i
< (full
? 4 : 2); i
++)
11631 aarch64_set_vec_u32 (cpu
, vd
, 0, val1
);
11632 aarch64_set_vec_u32 (cpu
, vd
+ 1, 0, val2
);
11639 uint64_t val1
= aarch64_get_mem_u64 (cpu
, address
);
11640 uint64_t val2
= aarch64_get_mem_u64 (cpu
, address
+ 8);
11642 for (i
= 0; i
< (full
? 2 : 1); i
++)
11644 aarch64_set_vec_u64 (cpu
, vd
, 0, val1
);
11645 aarch64_set_vec_u64 (cpu
, vd
+ 1, 0, val2
);
11655 case 2: /* LD3R. */
11660 uint8_t val1
= aarch64_get_mem_u8 (cpu
, address
);
11661 uint8_t val2
= aarch64_get_mem_u8 (cpu
, address
+ 1);
11662 uint8_t val3
= aarch64_get_mem_u8 (cpu
, address
+ 2);
11664 for (i
= 0; i
< (full
? 16 : 8); i
++)
11666 aarch64_set_vec_u8 (cpu
, vd
, 0, val1
);
11667 aarch64_set_vec_u8 (cpu
, vd
+ 1, 0, val2
);
11668 aarch64_set_vec_u8 (cpu
, vd
+ 2, 0, val3
);
11675 uint32_t val1
= aarch64_get_mem_u16 (cpu
, address
);
11676 uint32_t val2
= aarch64_get_mem_u16 (cpu
, address
+ 2);
11677 uint32_t val3
= aarch64_get_mem_u16 (cpu
, address
+ 4);
11679 for (i
= 0; i
< (full
? 8 : 4); i
++)
11681 aarch64_set_vec_u16 (cpu
, vd
, 0, val1
);
11682 aarch64_set_vec_u16 (cpu
, vd
+ 1, 0, val2
);
11683 aarch64_set_vec_u16 (cpu
, vd
+ 2, 0, val3
);
11690 uint32_t val1
= aarch64_get_mem_u32 (cpu
, address
);
11691 uint32_t val2
= aarch64_get_mem_u32 (cpu
, address
+ 4);
11692 uint32_t val3
= aarch64_get_mem_u32 (cpu
, address
+ 8);
11694 for (i
= 0; i
< (full
? 4 : 2); i
++)
11696 aarch64_set_vec_u32 (cpu
, vd
, 0, val1
);
11697 aarch64_set_vec_u32 (cpu
, vd
+ 1, 0, val2
);
11698 aarch64_set_vec_u32 (cpu
, vd
+ 2, 0, val3
);
11705 uint64_t val1
= aarch64_get_mem_u64 (cpu
, address
);
11706 uint64_t val2
= aarch64_get_mem_u64 (cpu
, address
+ 8);
11707 uint64_t val3
= aarch64_get_mem_u64 (cpu
, address
+ 16);
11709 for (i
= 0; i
< (full
? 2 : 1); i
++)
11711 aarch64_set_vec_u64 (cpu
, vd
, 0, val1
);
11712 aarch64_set_vec_u64 (cpu
, vd
+ 1, 0, val2
);
11713 aarch64_set_vec_u64 (cpu
, vd
+ 2, 0, val3
);
11723 case 3: /* LD4R. */
11728 uint8_t val1
= aarch64_get_mem_u8 (cpu
, address
);
11729 uint8_t val2
= aarch64_get_mem_u8 (cpu
, address
+ 1);
11730 uint8_t val3
= aarch64_get_mem_u8 (cpu
, address
+ 2);
11731 uint8_t val4
= aarch64_get_mem_u8 (cpu
, address
+ 3);
11733 for (i
= 0; i
< (full
? 16 : 8); i
++)
11735 aarch64_set_vec_u8 (cpu
, vd
, 0, val1
);
11736 aarch64_set_vec_u8 (cpu
, vd
+ 1, 0, val2
);
11737 aarch64_set_vec_u8 (cpu
, vd
+ 2, 0, val3
);
11738 aarch64_set_vec_u8 (cpu
, vd
+ 3, 0, val4
);
11745 uint32_t val1
= aarch64_get_mem_u16 (cpu
, address
);
11746 uint32_t val2
= aarch64_get_mem_u16 (cpu
, address
+ 2);
11747 uint32_t val3
= aarch64_get_mem_u16 (cpu
, address
+ 4);
11748 uint32_t val4
= aarch64_get_mem_u16 (cpu
, address
+ 6);
11750 for (i
= 0; i
< (full
? 8 : 4); i
++)
11752 aarch64_set_vec_u16 (cpu
, vd
, 0, val1
);
11753 aarch64_set_vec_u16 (cpu
, vd
+ 1, 0, val2
);
11754 aarch64_set_vec_u16 (cpu
, vd
+ 2, 0, val3
);
11755 aarch64_set_vec_u16 (cpu
, vd
+ 3, 0, val4
);
11762 uint32_t val1
= aarch64_get_mem_u32 (cpu
, address
);
11763 uint32_t val2
= aarch64_get_mem_u32 (cpu
, address
+ 4);
11764 uint32_t val3
= aarch64_get_mem_u32 (cpu
, address
+ 8);
11765 uint32_t val4
= aarch64_get_mem_u32 (cpu
, address
+ 12);
11767 for (i
= 0; i
< (full
? 4 : 2); i
++)
11769 aarch64_set_vec_u32 (cpu
, vd
, 0, val1
);
11770 aarch64_set_vec_u32 (cpu
, vd
+ 1, 0, val2
);
11771 aarch64_set_vec_u32 (cpu
, vd
+ 2, 0, val3
);
11772 aarch64_set_vec_u32 (cpu
, vd
+ 3, 0, val4
);
11779 uint64_t val1
= aarch64_get_mem_u64 (cpu
, address
);
11780 uint64_t val2
= aarch64_get_mem_u64 (cpu
, address
+ 8);
11781 uint64_t val3
= aarch64_get_mem_u64 (cpu
, address
+ 16);
11782 uint64_t val4
= aarch64_get_mem_u64 (cpu
, address
+ 24);
11784 for (i
= 0; i
< (full
? 2 : 1); i
++)
11786 aarch64_set_vec_u64 (cpu
, vd
, 0, val1
);
11787 aarch64_set_vec_u64 (cpu
, vd
+ 1, 0, val2
);
11788 aarch64_set_vec_u64 (cpu
, vd
+ 2, 0, val3
);
11789 aarch64_set_vec_u64 (cpu
, vd
+ 3, 0, val4
);
11805 do_vec_load_store (sim_cpu
*cpu
)
11807 /* {LD|ST}<N> {Vd..Vd+N}, vaddr
11810 instr[30] = element selector 0=>half, 1=>all elements
11811 instr[29,25] = 00110
11813 instr[23] = 0=>simple, 1=>post
11814 instr[22] = 0=>store, 1=>load
11815 instr[21] = 0 (LDn) / small(0)-large(1) selector (LDnR)
11816 instr[20,16] = 00000 (simple), Vinc (reg-post-inc, no SP),
11817 11111 (immediate post inc)
11818 instr[15,12] = elements and destinations. eg for load:
11819 0000=>LD4 => load multiple 4-element to
11820 four consecutive registers
11821 0100=>LD3 => load multiple 3-element to
11822 three consecutive registers
11823 1000=>LD2 => load multiple 2-element to
11824 two consecutive registers
11825 0010=>LD1 => load multiple 1-element to
11826 four consecutive registers
11827 0110=>LD1 => load multiple 1-element to
11828 three consecutive registers
11829 1010=>LD1 => load multiple 1-element to
11830 two consecutive registers
11831 0111=>LD1 => load multiple 1-element to
11835 instr[11,10] = element size 00=> byte(b), 01=> half(h),
11836 10=> word(s), 11=> double(d)
11837 instr[9,5] = Vn, can be SP
11846 if (INSTR (31, 31) != 0 || INSTR (29, 25) != 0x06)
11849 type
= INSTR (15, 12);
11850 if (type
!= 0xE && type
!= 0xE && INSTR (21, 21) != 0)
11853 post
= INSTR (23, 23);
11854 load
= INSTR (22, 22);
11856 address
= aarch64_get_reg_u64 (cpu
, vn
, SP_OK
);
11860 unsigned vm
= INSTR (20, 16);
11864 unsigned sizeof_operation
;
11868 case 0: sizeof_operation
= 32; break;
11869 case 4: sizeof_operation
= 24; break;
11870 case 8: sizeof_operation
= 16; break;
11873 sizeof_operation
= INSTR (21, 21) ? 2 : 1;
11874 sizeof_operation
<<= INSTR (11, 10);
11878 sizeof_operation
= INSTR (21, 21) ? 8 : 4;
11879 sizeof_operation
<<= INSTR (11, 10);
11883 /* One register, immediate offset variant. */
11884 sizeof_operation
= 8;
11888 /* Two registers, immediate offset variant. */
11889 sizeof_operation
= 16;
11893 /* Three registers, immediate offset variant. */
11894 sizeof_operation
= 24;
11898 /* Four registers, immediate offset variant. */
11899 sizeof_operation
= 32;
11906 if (INSTR (30, 30))
11907 sizeof_operation
*= 2;
11909 aarch64_set_reg_u64 (cpu
, vn
, SP_OK
, address
+ sizeof_operation
);
11912 aarch64_set_reg_u64 (cpu
, vn
, SP_OK
,
11913 address
+ aarch64_get_reg_u64 (cpu
, vm
, NO_SP
));
11917 NYI_assert (20, 16, 0);
11924 case 0: LD4 (cpu
, address
); return;
11925 case 4: LD3 (cpu
, address
); return;
11926 case 8: LD2 (cpu
, address
); return;
11927 case 2: LD1_4 (cpu
, address
); return;
11928 case 6: LD1_3 (cpu
, address
); return;
11929 case 10: LD1_2 (cpu
, address
); return;
11930 case 7: LD1_1 (cpu
, address
); return;
11933 case 0xC: do_vec_LDnR (cpu
, address
); return;
11943 case 0: ST4 (cpu
, address
); return;
11944 case 4: ST3 (cpu
, address
); return;
11945 case 8: ST2 (cpu
, address
); return;
11946 case 2: ST1_4 (cpu
, address
); return;
11947 case 6: ST1_3 (cpu
, address
); return;
11948 case 10: ST1_2 (cpu
, address
); return;
11949 case 7: ST1_1 (cpu
, address
); return;
11956 dexLdSt (sim_cpu
*cpu
)
11958 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
11959 assert group == GROUP_LDST_0100 || group == GROUP_LDST_0110 ||
11960 group == GROUP_LDST_1100 || group == GROUP_LDST_1110
11961 bits [29,28:26] of a LS are the secondary dispatch vector. */
11962 uint32_t group2
= dispatchLS (aarch64_get_instr (cpu
));
11967 dexLoadExclusive (cpu
); return;
11971 dexLoadLiteral (cpu
); return;
11975 dexLoadOther (cpu
); return;
11977 case LS_ADVSIMD_001
:
11978 do_vec_load_store (cpu
); return;
11981 dex_load_store_pair_gr (cpu
); return;
11984 dex_load_store_pair_fp (cpu
); return;
11987 /* Should never reach here. */
11992 /* Specific decode and execute for group Data Processing Register. */
11995 dexLogicalShiftedRegister (sim_cpu
*cpu
)
11997 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11999 instr[28:24] = 01010
12000 instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> ROR
12003 instr[15,10] = count : must be 0xxxxx for 32 bit
12007 uint32_t size
= INSTR (31, 31);
12008 Shift shiftType
= INSTR (23, 22);
12009 uint32_t count
= INSTR (15, 10);
12011 /* 32 bit operations must have count[5] = 0.
12012 or else we have an UNALLOC. */
12013 if (size
== 0 && uimm (count
, 5, 5))
12016 /* Dispatch on size:op:N. */
12017 switch ((INSTR (31, 29) << 1) | INSTR (21, 21))
12019 case 0: and32_shift (cpu
, shiftType
, count
); return;
12020 case 1: bic32_shift (cpu
, shiftType
, count
); return;
12021 case 2: orr32_shift (cpu
, shiftType
, count
); return;
12022 case 3: orn32_shift (cpu
, shiftType
, count
); return;
12023 case 4: eor32_shift (cpu
, shiftType
, count
); return;
12024 case 5: eon32_shift (cpu
, shiftType
, count
); return;
12025 case 6: ands32_shift (cpu
, shiftType
, count
); return;
12026 case 7: bics32_shift (cpu
, shiftType
, count
); return;
12027 case 8: and64_shift (cpu
, shiftType
, count
); return;
12028 case 9: bic64_shift (cpu
, shiftType
, count
); return;
12029 case 10:orr64_shift (cpu
, shiftType
, count
); return;
12030 case 11:orn64_shift (cpu
, shiftType
, count
); return;
12031 case 12:eor64_shift (cpu
, shiftType
, count
); return;
12032 case 13:eon64_shift (cpu
, shiftType
, count
); return;
12033 case 14:ands64_shift (cpu
, shiftType
, count
); return;
12034 case 15:bics64_shift (cpu
, shiftType
, count
); return;
12038 /* 32 bit conditional select. */
12040 csel32 (sim_cpu
*cpu
, CondCode cc
)
12042 unsigned rm
= INSTR (20, 16);
12043 unsigned rn
= INSTR (9, 5);
12044 unsigned rd
= INSTR (4, 0);
12046 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12047 testConditionCode (cpu
, cc
)
12048 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12049 : aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12052 /* 64 bit conditional select. */
12054 csel64 (sim_cpu
*cpu
, CondCode cc
)
12056 unsigned rm
= INSTR (20, 16);
12057 unsigned rn
= INSTR (9, 5);
12058 unsigned rd
= INSTR (4, 0);
12060 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12061 testConditionCode (cpu
, cc
)
12062 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12063 : aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
12066 /* 32 bit conditional increment. */
12068 csinc32 (sim_cpu
*cpu
, CondCode cc
)
12070 unsigned rm
= INSTR (20, 16);
12071 unsigned rn
= INSTR (9, 5);
12072 unsigned rd
= INSTR (4, 0);
12074 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12075 testConditionCode (cpu
, cc
)
12076 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12077 : aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) + 1);
12080 /* 64 bit conditional increment. */
12082 csinc64 (sim_cpu
*cpu
, CondCode cc
)
12084 unsigned rm
= INSTR (20, 16);
12085 unsigned rn
= INSTR (9, 5);
12086 unsigned rd
= INSTR (4, 0);
12088 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12089 testConditionCode (cpu
, cc
)
12090 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12091 : aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) + 1);
12094 /* 32 bit conditional invert. */
12096 csinv32 (sim_cpu
*cpu
, CondCode cc
)
12098 unsigned rm
= INSTR (20, 16);
12099 unsigned rn
= INSTR (9, 5);
12100 unsigned rd
= INSTR (4, 0);
12102 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12103 testConditionCode (cpu
, cc
)
12104 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12105 : ~ aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12108 /* 64 bit conditional invert. */
12110 csinv64 (sim_cpu
*cpu
, CondCode cc
)
12112 unsigned rm
= INSTR (20, 16);
12113 unsigned rn
= INSTR (9, 5);
12114 unsigned rd
= INSTR (4, 0);
12116 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12117 testConditionCode (cpu
, cc
)
12118 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12119 : ~ aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
12122 /* 32 bit conditional negate. */
12124 csneg32 (sim_cpu
*cpu
, CondCode cc
)
12126 unsigned rm
= INSTR (20, 16);
12127 unsigned rn
= INSTR (9, 5);
12128 unsigned rd
= INSTR (4, 0);
12130 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12131 testConditionCode (cpu
, cc
)
12132 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12133 : - aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12136 /* 64 bit conditional negate. */
12138 csneg64 (sim_cpu
*cpu
, CondCode cc
)
12140 unsigned rm
= INSTR (20, 16);
12141 unsigned rn
= INSTR (9, 5);
12142 unsigned rd
= INSTR (4, 0);
12144 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12145 testConditionCode (cpu
, cc
)
12146 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12147 : - aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
12151 dexCondSelect (sim_cpu
*cpu
)
12153 /* instr[28,21] = 11011011
12154 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12155 instr[30:11,10] = op : 000 ==> CSEL, 001 ==> CSINC,
12156 100 ==> CSINV, 101 ==> CSNEG,
12158 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
12159 instr[15,12] = cond
12160 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC */
12162 CondCode cc
= INSTR (15, 12);
12163 uint32_t S
= INSTR (29, 29);
12164 uint32_t op2
= INSTR (11, 10);
12172 switch ((INSTR (31, 30) << 1) | op2
)
12174 case 0: csel32 (cpu
, cc
); return;
12175 case 1: csinc32 (cpu
, cc
); return;
12176 case 2: csinv32 (cpu
, cc
); return;
12177 case 3: csneg32 (cpu
, cc
); return;
12178 case 4: csel64 (cpu
, cc
); return;
12179 case 5: csinc64 (cpu
, cc
); return;
12180 case 6: csinv64 (cpu
, cc
); return;
12181 case 7: csneg64 (cpu
, cc
); return;
12185 /* Some helpers for counting leading 1 or 0 bits. */
12187 /* Counts the number of leading bits which are the same
12188 in a 32 bit value in the range 1 to 32. */
12190 leading32 (uint32_t value
)
12192 int32_t mask
= 0xffff0000;
12193 uint32_t count
= 16; /* Counts number of bits set in mask. */
12194 uint32_t lo
= 1; /* Lower bound for number of sign bits. */
12195 uint32_t hi
= 32; /* Upper bound for number of sign bits. */
12197 while (lo
+ 1 < hi
)
12199 int32_t test
= (value
& mask
);
12201 if (test
== 0 || test
== mask
)
12204 count
= (lo
+ hi
) / 2;
12205 mask
>>= (count
- lo
);
12210 count
= (lo
+ hi
) / 2;
12211 mask
<<= hi
- count
;
12220 test
= (value
& mask
);
12222 if (test
== 0 || test
== mask
)
12231 /* Counts the number of leading bits which are the same
12232 in a 64 bit value in the range 1 to 64. */
12234 leading64 (uint64_t value
)
12236 int64_t mask
= 0xffffffff00000000LL
;
12237 uint64_t count
= 32; /* Counts number of bits set in mask. */
12238 uint64_t lo
= 1; /* Lower bound for number of sign bits. */
12239 uint64_t hi
= 64; /* Upper bound for number of sign bits. */
12241 while (lo
+ 1 < hi
)
12243 int64_t test
= (value
& mask
);
12245 if (test
== 0 || test
== mask
)
12248 count
= (lo
+ hi
) / 2;
12249 mask
>>= (count
- lo
);
12254 count
= (lo
+ hi
) / 2;
12255 mask
<<= hi
- count
;
12264 test
= (value
& mask
);
12266 if (test
== 0 || test
== mask
)
12275 /* Bit operations. */
12276 /* N.B register args may not be SP. */
12278 /* 32 bit count leading sign bits. */
12280 cls32 (sim_cpu
*cpu
)
12282 unsigned rn
= INSTR (9, 5);
12283 unsigned rd
= INSTR (4, 0);
12285 /* N.B. the result needs to exclude the leading bit. */
12286 aarch64_set_reg_u64
12287 (cpu
, rd
, NO_SP
, leading32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)) - 1);
12290 /* 64 bit count leading sign bits. */
12292 cls64 (sim_cpu
*cpu
)
12294 unsigned rn
= INSTR (9, 5);
12295 unsigned rd
= INSTR (4, 0);
12297 /* N.B. the result needs to exclude the leading bit. */
12298 aarch64_set_reg_u64
12299 (cpu
, rd
, NO_SP
, leading64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)) - 1);
12302 /* 32 bit count leading zero bits. */
12304 clz32 (sim_cpu
*cpu
)
12306 unsigned rn
= INSTR (9, 5);
12307 unsigned rd
= INSTR (4, 0);
12308 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12310 /* if the sign (top) bit is set then the count is 0. */
12311 if (pick32 (value
, 31, 31))
12312 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, 0L);
12314 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, leading32 (value
));
12317 /* 64 bit count leading zero bits. */
12319 clz64 (sim_cpu
*cpu
)
12321 unsigned rn
= INSTR (9, 5);
12322 unsigned rd
= INSTR (4, 0);
12323 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12325 /* if the sign (top) bit is set then the count is 0. */
12326 if (pick64 (value
, 63, 63))
12327 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, 0L);
12329 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, leading64 (value
));
12332 /* 32 bit reverse bits. */
12334 rbit32 (sim_cpu
*cpu
)
12336 unsigned rn
= INSTR (9, 5);
12337 unsigned rd
= INSTR (4, 0);
12338 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12339 uint32_t result
= 0;
12342 for (i
= 0; i
< 32; i
++)
12345 result
|= (value
& 1);
12348 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12351 /* 64 bit reverse bits. */
12353 rbit64 (sim_cpu
*cpu
)
12355 unsigned rn
= INSTR (9, 5);
12356 unsigned rd
= INSTR (4, 0);
12357 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12358 uint64_t result
= 0;
12361 for (i
= 0; i
< 64; i
++)
12364 result
|= (value
& 1UL);
12367 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12370 /* 32 bit reverse bytes. */
12372 rev32 (sim_cpu
*cpu
)
12374 unsigned rn
= INSTR (9, 5);
12375 unsigned rd
= INSTR (4, 0);
12376 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12377 uint32_t result
= 0;
12380 for (i
= 0; i
< 4; i
++)
12383 result
|= (value
& 0xff);
12386 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12389 /* 64 bit reverse bytes. */
12391 rev64 (sim_cpu
*cpu
)
12393 unsigned rn
= INSTR (9, 5);
12394 unsigned rd
= INSTR (4, 0);
12395 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12396 uint64_t result
= 0;
12399 for (i
= 0; i
< 8; i
++)
12402 result
|= (value
& 0xffULL
);
12405 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12408 /* 32 bit reverse shorts. */
12409 /* N.B.this reverses the order of the bytes in each half word. */
12411 revh32 (sim_cpu
*cpu
)
12413 unsigned rn
= INSTR (9, 5);
12414 unsigned rd
= INSTR (4, 0);
12415 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12416 uint32_t result
= 0;
12419 for (i
= 0; i
< 2; i
++)
12422 result
|= (value
& 0x00ff00ff);
12425 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12428 /* 64 bit reverse shorts. */
12429 /* N.B.this reverses the order of the bytes in each half word. */
12431 revh64 (sim_cpu
*cpu
)
12433 unsigned rn
= INSTR (9, 5);
12434 unsigned rd
= INSTR (4, 0);
12435 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12436 uint64_t result
= 0;
12439 for (i
= 0; i
< 2; i
++)
12442 result
|= (value
& 0x00ff00ff00ff00ffULL
);
12445 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12449 dexDataProc1Source (sim_cpu
*cpu
)
12452 instr[28,21] = 111010110
12453 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12454 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
12455 instr[20,16] = opcode2 : 00000 ==> ok, ow ==> UNALLOC
12456 instr[15,10] = opcode : 000000 ==> RBIT, 000001 ==> REV16,
12457 000010 ==> REV, 000011 ==> UNALLOC
12458 000100 ==> CLZ, 000101 ==> CLS
12460 instr[9,5] = rn : may not be SP
12461 instr[4,0] = rd : may not be SP. */
12463 uint32_t S
= INSTR (29, 29);
12464 uint32_t opcode2
= INSTR (20, 16);
12465 uint32_t opcode
= INSTR (15, 10);
12466 uint32_t dispatch
= ((INSTR (31, 31) << 3) | opcode
);
12479 case 0: rbit32 (cpu
); return;
12480 case 1: revh32 (cpu
); return;
12481 case 2: rev32 (cpu
); return;
12482 case 4: clz32 (cpu
); return;
12483 case 5: cls32 (cpu
); return;
12484 case 8: rbit64 (cpu
); return;
12485 case 9: revh64 (cpu
); return;
12486 case 10:rev32 (cpu
); return;
12487 case 11:rev64 (cpu
); return;
12488 case 12:clz64 (cpu
); return;
12489 case 13:cls64 (cpu
); return;
12490 default: HALT_UNALLOC
;
12495 Shifts by count supplied in register.
12496 N.B register args may not be SP.
12497 These all use the shifted auxiliary function for
12498 simplicity and clarity. Writing the actual shift
12499 inline would avoid a branch and so be faster but
12500 would also necessitate getting signs right. */
12502 /* 32 bit arithmetic shift right. */
12504 asrv32 (sim_cpu
*cpu
)
12506 unsigned rm
= INSTR (20, 16);
12507 unsigned rn
= INSTR (9, 5);
12508 unsigned rd
= INSTR (4, 0);
12510 aarch64_set_reg_u64
12512 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), ASR
,
12513 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12516 /* 64 bit arithmetic shift right. */
12518 asrv64 (sim_cpu
*cpu
)
12520 unsigned rm
= INSTR (20, 16);
12521 unsigned rn
= INSTR (9, 5);
12522 unsigned rd
= INSTR (4, 0);
12524 aarch64_set_reg_u64
12526 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), ASR
,
12527 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12530 /* 32 bit logical shift left. */
12532 lslv32 (sim_cpu
*cpu
)
12534 unsigned rm
= INSTR (20, 16);
12535 unsigned rn
= INSTR (9, 5);
12536 unsigned rd
= INSTR (4, 0);
12538 aarch64_set_reg_u64
12540 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), LSL
,
12541 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12544 /* 64 bit arithmetic shift left. */
12546 lslv64 (sim_cpu
*cpu
)
12548 unsigned rm
= INSTR (20, 16);
12549 unsigned rn
= INSTR (9, 5);
12550 unsigned rd
= INSTR (4, 0);
12552 aarch64_set_reg_u64
12554 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), LSL
,
12555 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12558 /* 32 bit logical shift right. */
12560 lsrv32 (sim_cpu
*cpu
)
12562 unsigned rm
= INSTR (20, 16);
12563 unsigned rn
= INSTR (9, 5);
12564 unsigned rd
= INSTR (4, 0);
12566 aarch64_set_reg_u64
12568 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), LSR
,
12569 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12572 /* 64 bit logical shift right. */
12574 lsrv64 (sim_cpu
*cpu
)
12576 unsigned rm
= INSTR (20, 16);
12577 unsigned rn
= INSTR (9, 5);
12578 unsigned rd
= INSTR (4, 0);
12580 aarch64_set_reg_u64
12582 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), LSR
,
12583 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12586 /* 32 bit rotate right. */
12588 rorv32 (sim_cpu
*cpu
)
12590 unsigned rm
= INSTR (20, 16);
12591 unsigned rn
= INSTR (9, 5);
12592 unsigned rd
= INSTR (4, 0);
12594 aarch64_set_reg_u64
12596 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), ROR
,
12597 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12600 /* 64 bit rotate right. */
12602 rorv64 (sim_cpu
*cpu
)
12604 unsigned rm
= INSTR (20, 16);
12605 unsigned rn
= INSTR (9, 5);
12606 unsigned rd
= INSTR (4, 0);
12608 aarch64_set_reg_u64
12610 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), ROR
,
12611 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12617 /* 32 bit signed divide. */
12619 cpuiv32 (sim_cpu
*cpu
)
12621 unsigned rm
= INSTR (20, 16);
12622 unsigned rn
= INSTR (9, 5);
12623 unsigned rd
= INSTR (4, 0);
12624 /* N.B. the pseudo-code does the divide using 64 bit data. */
12625 /* TODO : check that this rounds towards zero as required. */
12626 int64_t dividend
= aarch64_get_reg_s32 (cpu
, rn
, NO_SP
);
12627 int64_t divisor
= aarch64_get_reg_s32 (cpu
, rm
, NO_SP
);
12629 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
,
12630 divisor
? ((int32_t) (dividend
/ divisor
)) : 0);
12633 /* 64 bit signed divide. */
12635 cpuiv64 (sim_cpu
*cpu
)
12637 unsigned rm
= INSTR (20, 16);
12638 unsigned rn
= INSTR (9, 5);
12639 unsigned rd
= INSTR (4, 0);
12641 /* TODO : check that this rounds towards zero as required. */
12642 int64_t divisor
= aarch64_get_reg_s64 (cpu
, rm
, NO_SP
);
12644 aarch64_set_reg_s64
12646 divisor
? (aarch64_get_reg_s64 (cpu
, rn
, NO_SP
) / divisor
) : 0);
12649 /* 32 bit unsigned divide. */
12651 udiv32 (sim_cpu
*cpu
)
12653 unsigned rm
= INSTR (20, 16);
12654 unsigned rn
= INSTR (9, 5);
12655 unsigned rd
= INSTR (4, 0);
12657 /* N.B. the pseudo-code does the divide using 64 bit data. */
12658 uint64_t dividend
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12659 uint64_t divisor
= aarch64_get_reg_u32 (cpu
, rm
, NO_SP
);
12661 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12662 divisor
? (uint32_t) (dividend
/ divisor
) : 0);
12665 /* 64 bit unsigned divide. */
12667 udiv64 (sim_cpu
*cpu
)
12669 unsigned rm
= INSTR (20, 16);
12670 unsigned rn
= INSTR (9, 5);
12671 unsigned rd
= INSTR (4, 0);
12673 /* TODO : check that this rounds towards zero as required. */
12674 uint64_t divisor
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
12676 aarch64_set_reg_u64
12678 divisor
? (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) / divisor
) : 0);
12682 dexDataProc2Source (sim_cpu
*cpu
)
12684 /* assert instr[30] == 0
12685 instr[28,21] == 11010110
12686 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12687 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
12688 instr[15,10] = opcode : 000010 ==> UDIV, 000011 ==> CPUIV,
12689 001000 ==> LSLV, 001001 ==> LSRV
12690 001010 ==> ASRV, 001011 ==> RORV
12694 uint32_t S
= INSTR (29, 29);
12695 uint32_t opcode
= INSTR (15, 10);
12703 dispatch
= ( (INSTR (31, 31) << 3)
12704 | (uimm (opcode
, 3, 3) << 2)
12705 | uimm (opcode
, 1, 0));
12708 case 2: udiv32 (cpu
); return;
12709 case 3: cpuiv32 (cpu
); return;
12710 case 4: lslv32 (cpu
); return;
12711 case 5: lsrv32 (cpu
); return;
12712 case 6: asrv32 (cpu
); return;
12713 case 7: rorv32 (cpu
); return;
12714 case 10: udiv64 (cpu
); return;
12715 case 11: cpuiv64 (cpu
); return;
12716 case 12: lslv64 (cpu
); return;
12717 case 13: lsrv64 (cpu
); return;
12718 case 14: asrv64 (cpu
); return;
12719 case 15: rorv64 (cpu
); return;
12720 default: HALT_UNALLOC
;
12727 /* 32 bit multiply and add. */
12729 madd32 (sim_cpu
*cpu
)
12731 unsigned rm
= INSTR (20, 16);
12732 unsigned ra
= INSTR (14, 10);
12733 unsigned rn
= INSTR (9, 5);
12734 unsigned rd
= INSTR (4, 0);
12736 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12737 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12738 aarch64_get_reg_u32 (cpu
, ra
, NO_SP
)
12739 + aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12740 * aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12743 /* 64 bit multiply and add. */
12745 madd64 (sim_cpu
*cpu
)
12747 unsigned rm
= INSTR (20, 16);
12748 unsigned ra
= INSTR (14, 10);
12749 unsigned rn
= INSTR (9, 5);
12750 unsigned rd
= INSTR (4, 0);
12752 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12753 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12754 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
12755 + (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12756 * aarch64_get_reg_u64 (cpu
, rm
, NO_SP
)));
12759 /* 32 bit multiply and sub. */
12761 msub32 (sim_cpu
*cpu
)
12763 unsigned rm
= INSTR (20, 16);
12764 unsigned ra
= INSTR (14, 10);
12765 unsigned rn
= INSTR (9, 5);
12766 unsigned rd
= INSTR (4, 0);
12768 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12769 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12770 aarch64_get_reg_u32 (cpu
, ra
, NO_SP
)
12771 - aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12772 * aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12775 /* 64 bit multiply and sub. */
12777 msub64 (sim_cpu
*cpu
)
12779 unsigned rm
= INSTR (20, 16);
12780 unsigned ra
= INSTR (14, 10);
12781 unsigned rn
= INSTR (9, 5);
12782 unsigned rd
= INSTR (4, 0);
12784 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12785 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12786 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
12787 - aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12788 * aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
12791 /* Signed multiply add long -- source, source2 : 32 bit, source3 : 64 bit. */
12793 smaddl (sim_cpu
*cpu
)
12795 unsigned rm
= INSTR (20, 16);
12796 unsigned ra
= INSTR (14, 10);
12797 unsigned rn
= INSTR (9, 5);
12798 unsigned rd
= INSTR (4, 0);
12800 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12801 obtain a 64 bit product. */
12802 aarch64_set_reg_s64
12804 aarch64_get_reg_s64 (cpu
, ra
, NO_SP
)
12805 + ((int64_t) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
))
12806 * ((int64_t) aarch64_get_reg_s32 (cpu
, rm
, NO_SP
)));
12809 /* Signed multiply sub long -- source, source2 : 32 bit, source3 : 64 bit. */
12811 smsubl (sim_cpu
*cpu
)
12813 unsigned rm
= INSTR (20, 16);
12814 unsigned ra
= INSTR (14, 10);
12815 unsigned rn
= INSTR (9, 5);
12816 unsigned rd
= INSTR (4, 0);
12818 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12819 obtain a 64 bit product. */
12820 aarch64_set_reg_s64
12822 aarch64_get_reg_s64 (cpu
, ra
, NO_SP
)
12823 - ((int64_t) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
))
12824 * ((int64_t) aarch64_get_reg_s32 (cpu
, rm
, NO_SP
)));
12827 /* Integer Multiply/Divide. */
12829 /* First some macros and a helper function. */
12830 /* Macros to test or access elements of 64 bit words. */
12832 /* Mask used to access lo 32 bits of 64 bit unsigned int. */
12833 #define LOW_WORD_MASK ((1ULL << 32) - 1)
12834 /* Return the lo 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int. */
12835 #define lowWordToU64(_value_u64) ((_value_u64) & LOW_WORD_MASK)
12836 /* Return the hi 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int. */
12837 #define highWordToU64(_value_u64) ((_value_u64) >> 32)
12839 /* Offset of sign bit in 64 bit signed integger. */
12840 #define SIGN_SHIFT_U64 63
12841 /* The sign bit itself -- also identifies the minimum negative int value. */
12842 #define SIGN_BIT_U64 (1UL << SIGN_SHIFT_U64)
12843 /* Return true if a 64 bit signed int presented as an unsigned int is the
12844 most negative value. */
12845 #define isMinimumU64(_value_u64) ((_value_u64) == SIGN_BIT_U64)
12846 /* Return true (non-zero) if a 64 bit signed int presented as an unsigned
12847 int has its sign bit set to false. */
12848 #define isSignSetU64(_value_u64) ((_value_u64) & SIGN_BIT_U64)
12849 /* Return 1L or -1L according to whether a 64 bit signed int presented as
12850 an unsigned int has its sign bit set or not. */
12851 #define signOfU64(_value_u64) (1L + (((value_u64) >> SIGN_SHIFT_U64) * -2L)
12852 /* Clear the sign bit of a 64 bit signed int presented as an unsigned int. */
12853 #define clearSignU64(_value_u64) ((_value_u64) &= ~SIGN_BIT_U64)
12855 /* Multiply two 64 bit ints and return.
12856 the hi 64 bits of the 128 bit product. */
12859 mul64hi (uint64_t value1
, uint64_t value2
)
12861 uint64_t resultmid1
;
12863 uint64_t value1_lo
= lowWordToU64 (value1
);
12864 uint64_t value1_hi
= highWordToU64 (value1
) ;
12865 uint64_t value2_lo
= lowWordToU64 (value2
);
12866 uint64_t value2_hi
= highWordToU64 (value2
);
12868 /* Cross-multiply and collect results. */
12869 uint64_t xproductlo
= value1_lo
* value2_lo
;
12870 uint64_t xproductmid1
= value1_lo
* value2_hi
;
12871 uint64_t xproductmid2
= value1_hi
* value2_lo
;
12872 uint64_t xproducthi
= value1_hi
* value2_hi
;
12873 uint64_t carry
= 0;
12874 /* Start accumulating 64 bit results. */
12875 /* Drop bottom half of lowest cross-product. */
12876 uint64_t resultmid
= xproductlo
>> 32;
12877 /* Add in middle products. */
12878 resultmid
= resultmid
+ xproductmid1
;
12880 /* Check for overflow. */
12881 if (resultmid
< xproductmid1
)
12882 /* Carry over 1 into top cross-product. */
12885 resultmid1
= resultmid
+ xproductmid2
;
12887 /* Check for overflow. */
12888 if (resultmid1
< xproductmid2
)
12889 /* Carry over 1 into top cross-product. */
12892 /* Drop lowest 32 bits of middle cross-product. */
12893 result
= resultmid1
>> 32;
12895 /* Add top cross-product plus and any carry. */
12896 result
+= xproducthi
+ carry
;
12901 /* Signed multiply high, source, source2 :
12902 64 bit, dest <-- high 64-bit of result. */
12904 smulh (sim_cpu
*cpu
)
12908 unsigned rm
= INSTR (20, 16);
12909 unsigned rn
= INSTR (9, 5);
12910 unsigned rd
= INSTR (4, 0);
12911 GReg ra
= INSTR (14, 10);
12912 int64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12913 int64_t value2
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
12916 int64_t signum
= 1;
12921 /* Convert to unsigned and use the unsigned mul64hi routine
12922 the fix the sign up afterwards. */
12943 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12944 uresult
= mul64hi (uvalue1
, uvalue2
);
12948 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, result
);
12951 /* Unsigned multiply add long -- source, source2 :
12952 32 bit, source3 : 64 bit. */
12954 umaddl (sim_cpu
*cpu
)
12956 unsigned rm
= INSTR (20, 16);
12957 unsigned ra
= INSTR (14, 10);
12958 unsigned rn
= INSTR (9, 5);
12959 unsigned rd
= INSTR (4, 0);
12961 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12962 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12963 obtain a 64 bit product. */
12964 aarch64_set_reg_u64
12966 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
12967 + ((uint64_t) aarch64_get_reg_u32 (cpu
, rn
, NO_SP
))
12968 * ((uint64_t) aarch64_get_reg_u32 (cpu
, rm
, NO_SP
)));
12971 /* Unsigned multiply sub long -- source, source2 : 32 bit, source3 : 64 bit. */
12973 umsubl (sim_cpu
*cpu
)
12975 unsigned rm
= INSTR (20, 16);
12976 unsigned ra
= INSTR (14, 10);
12977 unsigned rn
= INSTR (9, 5);
12978 unsigned rd
= INSTR (4, 0);
12980 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12981 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12982 obtain a 64 bit product. */
12983 aarch64_set_reg_u64
12985 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
12986 - ((uint64_t) aarch64_get_reg_u32 (cpu
, rn
, NO_SP
))
12987 * ((uint64_t) aarch64_get_reg_u32 (cpu
, rm
, NO_SP
)));
12990 /* Unsigned multiply high, source, source2 :
12991 64 bit, dest <-- high 64-bit of result. */
12993 umulh (sim_cpu
*cpu
)
12995 unsigned rm
= INSTR (20, 16);
12996 unsigned rn
= INSTR (9, 5);
12997 unsigned rd
= INSTR (4, 0);
12998 GReg ra
= INSTR (14, 10);
13003 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13004 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
13005 mul64hi (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
),
13006 aarch64_get_reg_u64 (cpu
, rm
, NO_SP
)));
13010 dexDataProc3Source (sim_cpu
*cpu
)
13012 /* assert instr[28,24] == 11011. */
13013 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit (for rd at least)
13014 instr[30,29] = op54 : 00 ==> ok, ow ==> UNALLOC
13015 instr[23,21] = op31 : 111 ==> UNALLOC, o2 ==> ok
13016 instr[15] = o0 : 0/1 ==> ok
13017 instr[23,21:15] ==> op : 0000 ==> MADD, 0001 ==> MSUB, (32/64 bit)
13018 0010 ==> SMADDL, 0011 ==> SMSUBL, (64 bit only)
13019 0100 ==> SMULH, (64 bit only)
13020 1010 ==> UMADDL, 1011 ==> UNSUBL, (64 bit only)
13021 1100 ==> UMULH (64 bit only)
13025 uint32_t size
= INSTR (31, 31);
13026 uint32_t op54
= INSTR (30, 29);
13027 uint32_t op31
= INSTR (23, 21);
13028 uint32_t o0
= INSTR (15, 15);
13045 dispatch
= (op31
<< 1) | o0
;
13049 case 0: madd64 (cpu
); return;
13050 case 1: msub64 (cpu
); return;
13051 case 2: smaddl (cpu
); return;
13052 case 3: smsubl (cpu
); return;
13053 case 4: smulh (cpu
); return;
13054 case 10: umaddl (cpu
); return;
13055 case 11: umsubl (cpu
); return;
13056 case 12: umulh (cpu
); return;
13057 default: HALT_UNALLOC
;
13062 dexDPReg (sim_cpu
*cpu
)
13064 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
13065 assert group == GROUP_DPREG_0101 || group == GROUP_DPREG_1101
13066 bits [28:24:21] of a DPReg are the secondary dispatch vector. */
13067 uint32_t group2
= dispatchDPReg (aarch64_get_instr (cpu
));
13071 case DPREG_LOG_000
:
13072 case DPREG_LOG_001
:
13073 dexLogicalShiftedRegister (cpu
); return;
13075 case DPREG_ADDSHF_010
:
13076 dexAddSubtractShiftedRegister (cpu
); return;
13078 case DPREG_ADDEXT_011
:
13079 dexAddSubtractExtendedRegister (cpu
); return;
13081 case DPREG_ADDCOND_100
:
13083 /* This set bundles a variety of different operations. */
13085 /* 1) add/sub w carry. */
13086 uint32_t mask1
= 0x1FE00000U
;
13087 uint32_t val1
= 0x1A000000U
;
13088 /* 2) cond compare register/immediate. */
13089 uint32_t mask2
= 0x1FE00000U
;
13090 uint32_t val2
= 0x1A400000U
;
13091 /* 3) cond select. */
13092 uint32_t mask3
= 0x1FE00000U
;
13093 uint32_t val3
= 0x1A800000U
;
13094 /* 4) data proc 1/2 source. */
13095 uint32_t mask4
= 0x1FE00000U
;
13096 uint32_t val4
= 0x1AC00000U
;
13098 if ((aarch64_get_instr (cpu
) & mask1
) == val1
)
13099 dexAddSubtractWithCarry (cpu
);
13101 else if ((aarch64_get_instr (cpu
) & mask2
) == val2
)
13104 else if ((aarch64_get_instr (cpu
) & mask3
) == val3
)
13105 dexCondSelect (cpu
);
13107 else if ((aarch64_get_instr (cpu
) & mask4
) == val4
)
13109 /* Bit 30 is clear for data proc 2 source
13110 and set for data proc 1 source. */
13111 if (aarch64_get_instr (cpu
) & (1U << 30))
13112 dexDataProc1Source (cpu
);
13114 dexDataProc2Source (cpu
);
13118 /* Should not reach here. */
13124 case DPREG_3SRC_110
:
13125 dexDataProc3Source (cpu
); return;
13127 case DPREG_UNALLOC_101
:
13130 case DPREG_3SRC_111
:
13131 dexDataProc3Source (cpu
); return;
13134 /* Should never reach here. */
13139 /* Unconditional Branch immediate.
13140 Offset is a PC-relative byte offset in the range +/- 128MiB.
13141 The offset is assumed to be raw from the decode i.e. the
13142 simulator is expected to scale them from word offsets to byte. */
13144 /* Unconditional branch. */
13146 buc (sim_cpu
*cpu
, int32_t offset
)
13148 aarch64_set_next_PC_by_offset (cpu
, offset
);
13151 static unsigned stack_depth
= 0;
13153 /* Unconditional branch and link -- writes return PC to LR. */
13155 bl (sim_cpu
*cpu
, int32_t offset
)
13157 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13158 aarch64_save_LR (cpu
);
13159 aarch64_set_next_PC_by_offset (cpu
, offset
);
13161 if (TRACE_BRANCH_P (cpu
))
13165 " %*scall %" PRIx64
" [%s]"
13166 " [args: %" PRIx64
" %" PRIx64
" %" PRIx64
"]",
13167 stack_depth
, " ", aarch64_get_next_PC (cpu
),
13168 aarch64_get_func (aarch64_get_next_PC (cpu
)),
13169 aarch64_get_reg_u64 (cpu
, 0, NO_SP
),
13170 aarch64_get_reg_u64 (cpu
, 1, NO_SP
),
13171 aarch64_get_reg_u64 (cpu
, 2, NO_SP
)
13176 /* Unconditional Branch register.
13177 Branch/return address is in source register. */
13179 /* Unconditional branch. */
13183 unsigned rn
= INSTR (9, 5);
13184 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13185 aarch64_set_next_PC (cpu
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
13188 /* Unconditional branch and link -- writes return PC to LR. */
13192 unsigned rn
= INSTR (9, 5);
13194 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13195 /* The pseudo code in the spec says we update LR before fetching.
13196 the value from the rn. */
13197 aarch64_save_LR (cpu
);
13198 aarch64_set_next_PC (cpu
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
13200 if (TRACE_BRANCH_P (cpu
))
13204 " %*scall %" PRIx64
" [%s]"
13205 " [args: %" PRIx64
" %" PRIx64
" %" PRIx64
"]",
13206 stack_depth
, " ", aarch64_get_next_PC (cpu
),
13207 aarch64_get_func (aarch64_get_next_PC (cpu
)),
13208 aarch64_get_reg_u64 (cpu
, 0, NO_SP
),
13209 aarch64_get_reg_u64 (cpu
, 1, NO_SP
),
13210 aarch64_get_reg_u64 (cpu
, 2, NO_SP
)
13215 /* Return -- assembler will default source to LR this is functionally
13216 equivalent to br but, presumably, unlike br it side effects the
13217 branch predictor. */
13221 unsigned rn
= INSTR (9, 5);
13222 aarch64_set_next_PC (cpu
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
13224 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13225 if (TRACE_BRANCH_P (cpu
))
13228 " %*sreturn [result: %" PRIx64
"]",
13229 stack_depth
, " ", aarch64_get_reg_u64 (cpu
, 0, NO_SP
));
13234 /* NOP -- we implement this and call it from the decode in case we
13235 want to intercept it later. */
13240 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13243 /* Data synchronization barrier. */
13248 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13251 /* Data memory barrier. */
13256 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13259 /* Instruction synchronization barrier. */
13264 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13268 dexBranchImmediate (sim_cpu
*cpu
)
13270 /* assert instr[30,26] == 00101
13271 instr[31] ==> 0 == B, 1 == BL
13272 instr[25,0] == imm26 branch offset counted in words. */
13274 uint32_t top
= INSTR (31, 31);
13275 /* We have a 26 byte signed word offset which we need to pass to the
13276 execute routine as a signed byte offset. */
13277 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 25, 0) << 2;
13285 /* Control Flow. */
13287 /* Conditional branch
13289 Offset is a PC-relative byte offset in the range +/- 1MiB pos is
13290 a bit position in the range 0 .. 63
13292 cc is a CondCode enum value as pulled out of the decode
13294 N.B. any offset register (source) can only be Xn or Wn. */
13297 bcc (sim_cpu
*cpu
, int32_t offset
, CondCode cc
)
13299 /* The test returns TRUE if CC is met. */
13300 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13301 if (testConditionCode (cpu
, cc
))
13302 aarch64_set_next_PC_by_offset (cpu
, offset
);
13305 /* 32 bit branch on register non-zero. */
13307 cbnz32 (sim_cpu
*cpu
, int32_t offset
)
13309 unsigned rt
= INSTR (4, 0);
13311 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13312 if (aarch64_get_reg_u32 (cpu
, rt
, NO_SP
) != 0)
13313 aarch64_set_next_PC_by_offset (cpu
, offset
);
13316 /* 64 bit branch on register zero. */
13318 cbnz (sim_cpu
*cpu
, int32_t offset
)
13320 unsigned rt
= INSTR (4, 0);
13322 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13323 if (aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) != 0)
13324 aarch64_set_next_PC_by_offset (cpu
, offset
);
13327 /* 32 bit branch on register non-zero. */
13329 cbz32 (sim_cpu
*cpu
, int32_t offset
)
13331 unsigned rt
= INSTR (4, 0);
13333 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13334 if (aarch64_get_reg_u32 (cpu
, rt
, NO_SP
) == 0)
13335 aarch64_set_next_PC_by_offset (cpu
, offset
);
13338 /* 64 bit branch on register zero. */
13340 cbz (sim_cpu
*cpu
, int32_t offset
)
13342 unsigned rt
= INSTR (4, 0);
13344 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13345 if (aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) == 0)
13346 aarch64_set_next_PC_by_offset (cpu
, offset
);
13349 /* Branch on register bit test non-zero -- one size fits all. */
13351 tbnz (sim_cpu
*cpu
, uint32_t pos
, int32_t offset
)
13353 unsigned rt
= INSTR (4, 0);
13355 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13356 if (aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) & (1 << pos
))
13357 aarch64_set_next_PC_by_offset (cpu
, offset
);
13360 /* Branch on register bit test zero -- one size fits all. */
13362 tbz (sim_cpu
*cpu
, uint32_t pos
, int32_t offset
)
13364 unsigned rt
= INSTR (4, 0);
13366 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13367 if (!(aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) & (1 << pos
)))
13368 aarch64_set_next_PC_by_offset (cpu
, offset
);
13372 dexCompareBranchImmediate (sim_cpu
*cpu
)
13374 /* instr[30,25] = 01 1010
13375 instr[31] = size : 0 ==> 32, 1 ==> 64
13376 instr[24] = op : 0 ==> CBZ, 1 ==> CBNZ
13377 instr[23,5] = simm19 branch offset counted in words
13380 uint32_t size
= INSTR (31, 31);
13381 uint32_t op
= INSTR (24, 24);
13382 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 23, 5) << 2;
13387 cbz32 (cpu
, offset
);
13389 cbnz32 (cpu
, offset
);
13396 cbnz (cpu
, offset
);
13401 dexTestBranchImmediate (sim_cpu
*cpu
)
13403 /* instr[31] = b5 : bit 5 of test bit idx
13404 instr[30,25] = 01 1011
13405 instr[24] = op : 0 ==> TBZ, 1 == TBNZ
13406 instr[23,19] = b40 : bits 4 to 0 of test bit idx
13407 instr[18,5] = simm14 : signed offset counted in words
13408 instr[4,0] = uimm5 */
13410 uint32_t pos
= ((INSTR (31, 31) << 4) | INSTR (23, 19));
13411 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 18, 5) << 2;
13413 NYI_assert (30, 25, 0x1b);
13415 if (INSTR (24, 24) == 0)
13416 tbz (cpu
, pos
, offset
);
13418 tbnz (cpu
, pos
, offset
);
13422 dexCondBranchImmediate (sim_cpu
*cpu
)
13424 /* instr[31,25] = 010 1010
13425 instr[24] = op1; op => 00 ==> B.cond
13426 instr[23,5] = simm19 : signed offset counted in words
13428 instr[3,0] = cond */
13431 uint32_t op
= ((INSTR (24, 24) << 1) | INSTR (4, 4));
13433 NYI_assert (31, 25, 0x2a);
13438 offset
= simm32 (aarch64_get_instr (cpu
), 23, 5) << 2;
13440 bcc (cpu
, offset
, INSTR (3, 0));
13444 dexBranchRegister (sim_cpu
*cpu
)
13446 /* instr[31,25] = 110 1011
13447 instr[24,21] = op : 0 ==> BR, 1 => BLR, 2 => RET, 3 => ERET, 4 => DRPS
13448 instr[20,16] = op2 : must be 11111
13449 instr[15,10] = op3 : must be 000000
13450 instr[4,0] = op2 : must be 11111. */
13452 uint32_t op
= INSTR (24, 21);
13453 uint32_t op2
= INSTR (20, 16);
13454 uint32_t op3
= INSTR (15, 10);
13455 uint32_t op4
= INSTR (4, 0);
13457 NYI_assert (31, 25, 0x6b);
13459 if (op2
!= 0x1F || op3
!= 0 || op4
!= 0)
13473 /* ERET and DRPS accept 0b11111 for rn = instr [4,0]. */
13474 /* anything else is unallocated. */
13475 uint32_t rn
= INSTR (4, 0);
13480 if (op
== 4 || op
== 5)
13487 /* FIXME: We should get the Angel SWI values from ../../libgloss/aarch64/svc.h
13488 but this may not be available. So instead we define the values we need
13490 #define AngelSVC_Reason_Open 0x01
13491 #define AngelSVC_Reason_Close 0x02
13492 #define AngelSVC_Reason_Write 0x05
13493 #define AngelSVC_Reason_Read 0x06
13494 #define AngelSVC_Reason_IsTTY 0x09
13495 #define AngelSVC_Reason_Seek 0x0A
13496 #define AngelSVC_Reason_FLen 0x0C
13497 #define AngelSVC_Reason_Remove 0x0E
13498 #define AngelSVC_Reason_Rename 0x0F
13499 #define AngelSVC_Reason_Clock 0x10
13500 #define AngelSVC_Reason_Time 0x11
13501 #define AngelSVC_Reason_System 0x12
13502 #define AngelSVC_Reason_Errno 0x13
13503 #define AngelSVC_Reason_GetCmdLine 0x15
13504 #define AngelSVC_Reason_HeapInfo 0x16
13505 #define AngelSVC_Reason_ReportException 0x18
13506 #define AngelSVC_Reason_Elapsed 0x30
13510 handle_halt (sim_cpu
*cpu
, uint32_t val
)
13512 uint64_t result
= 0;
13514 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13517 TRACE_SYSCALL (cpu
, " HLT [0x%x]", val
);
13518 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13519 sim_stopped
, SIM_SIGTRAP
);
13522 /* We have encountered an Angel SVC call. See if we can process it. */
13523 switch (aarch64_get_reg_u32 (cpu
, 0, NO_SP
))
13525 case AngelSVC_Reason_HeapInfo
:
13527 /* Get the values. */
13528 uint64_t stack_top
= aarch64_get_stack_start (cpu
);
13529 uint64_t heap_base
= aarch64_get_heap_start (cpu
);
13531 /* Get the pointer */
13532 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13533 ptr
= aarch64_get_mem_u64 (cpu
, ptr
);
13535 /* Fill in the memory block. */
13536 /* Start addr of heap. */
13537 aarch64_set_mem_u64 (cpu
, ptr
+ 0, heap_base
);
13538 /* End addr of heap. */
13539 aarch64_set_mem_u64 (cpu
, ptr
+ 8, stack_top
);
13540 /* Lowest stack addr. */
13541 aarch64_set_mem_u64 (cpu
, ptr
+ 16, heap_base
);
13542 /* Initial stack addr. */
13543 aarch64_set_mem_u64 (cpu
, ptr
+ 24, stack_top
);
13545 TRACE_SYSCALL (cpu
, " AngelSVC: Get Heap Info");
13549 case AngelSVC_Reason_Open
:
13551 /* Get the pointer */
13552 /* uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);. */
13553 /* FIXME: For now we just assume that we will only be asked
13554 to open the standard file descriptors. */
13558 TRACE_SYSCALL (cpu
, " AngelSVC: Open file %d", fd
- 1);
13562 case AngelSVC_Reason_Close
:
13564 uint64_t fh
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13565 TRACE_SYSCALL (cpu
, " AngelSVC: Close file %d", (int) fh
);
13570 case AngelSVC_Reason_Errno
:
13572 TRACE_SYSCALL (cpu
, " AngelSVC: Get Errno");
13575 case AngelSVC_Reason_Clock
:
13577 #ifdef CLOCKS_PER_SEC
13578 (CLOCKS_PER_SEC
>= 100)
13579 ? (clock () / (CLOCKS_PER_SEC
/ 100))
13580 : ((clock () * 100) / CLOCKS_PER_SEC
)
13582 /* Presume unix... clock() returns microseconds. */
13586 TRACE_SYSCALL (cpu
, " AngelSVC: Get Clock");
13589 case AngelSVC_Reason_GetCmdLine
:
13591 /* Get the pointer */
13592 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13593 ptr
= aarch64_get_mem_u64 (cpu
, ptr
);
13595 /* FIXME: No command line for now. */
13596 aarch64_set_mem_u64 (cpu
, ptr
, 0);
13597 TRACE_SYSCALL (cpu
, " AngelSVC: Get Command Line");
13601 case AngelSVC_Reason_IsTTY
:
13603 TRACE_SYSCALL (cpu
, " AngelSVC: IsTTY ?");
13606 case AngelSVC_Reason_Write
:
13608 /* Get the pointer */
13609 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13610 /* Get the write control block. */
13611 uint64_t fd
= aarch64_get_mem_u64 (cpu
, ptr
);
13612 uint64_t buf
= aarch64_get_mem_u64 (cpu
, ptr
+ 8);
13613 uint64_t len
= aarch64_get_mem_u64 (cpu
, ptr
+ 16);
13615 TRACE_SYSCALL (cpu
, "write of %" PRIx64
" bytes from %"
13616 PRIx64
" on descriptor %" PRIx64
,
13621 TRACE_SYSCALL (cpu
,
13622 " AngelSVC: Write: Suspiciously long write: %ld",
13624 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13625 sim_stopped
, SIM_SIGBUS
);
13629 printf ("%.*s", (int) len
, aarch64_get_mem_ptr (cpu
, buf
));
13633 TRACE (cpu
, 0, "\n");
13634 sim_io_eprintf (CPU_STATE (cpu
), "%.*s",
13635 (int) len
, aarch64_get_mem_ptr (cpu
, buf
));
13636 TRACE (cpu
, 0, "\n");
13640 TRACE_SYSCALL (cpu
,
13641 " AngelSVC: Write: Unexpected file handle: %d",
13643 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13644 sim_stopped
, SIM_SIGABRT
);
13649 case AngelSVC_Reason_ReportException
:
13651 /* Get the pointer */
13652 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13653 /*ptr = aarch64_get_mem_u64 (cpu, ptr);. */
13654 uint64_t type
= aarch64_get_mem_u64 (cpu
, ptr
);
13655 uint64_t state
= aarch64_get_mem_u64 (cpu
, ptr
+ 8);
13657 TRACE_SYSCALL (cpu
,
13658 "Angel Exception: type 0x%" PRIx64
" state %" PRIx64
,
13661 if (type
== 0x20026)
13662 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13663 sim_exited
, state
);
13665 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13666 sim_stopped
, SIM_SIGINT
);
13670 case AngelSVC_Reason_Read
:
13671 case AngelSVC_Reason_FLen
:
13672 case AngelSVC_Reason_Seek
:
13673 case AngelSVC_Reason_Remove
:
13674 case AngelSVC_Reason_Time
:
13675 case AngelSVC_Reason_System
:
13676 case AngelSVC_Reason_Rename
:
13677 case AngelSVC_Reason_Elapsed
:
13679 TRACE_SYSCALL (cpu
, " HLT [Unknown angel %x]",
13680 aarch64_get_reg_u32 (cpu
, 0, NO_SP
));
13681 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13682 sim_stopped
, SIM_SIGTRAP
);
13685 aarch64_set_reg_u64 (cpu
, 0, NO_SP
, result
);
13689 dexExcpnGen (sim_cpu
*cpu
)
13691 /* instr[31:24] = 11010100
13692 instr[23,21] = opc : 000 ==> GEN EXCPN, 001 ==> BRK
13693 010 ==> HLT, 101 ==> DBG GEN EXCPN
13694 instr[20,5] = imm16
13695 instr[4,2] = opc2 000 ==> OK, ow ==> UNALLOC
13696 instr[1,0] = LL : discriminates opc */
13698 uint32_t opc
= INSTR (23, 21);
13699 uint32_t imm16
= INSTR (20, 5);
13700 uint32_t opc2
= INSTR (4, 2);
13703 NYI_assert (31, 24, 0xd4);
13710 /* We only implement HLT and BRK for now. */
13711 if (opc
== 1 && LL
== 0)
13713 TRACE_EVENTS (cpu
, " BRK [0x%x]", imm16
);
13714 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13715 sim_exited
, aarch64_get_reg_s32 (cpu
, R0
, SP_OK
));
13718 if (opc
== 2 && LL
== 0)
13719 handle_halt (cpu
, imm16
);
13721 else if (opc
== 0 || opc
== 5)
13728 /* Stub for accessing system registers. */
13731 system_get (sim_cpu
*cpu
, unsigned op0
, unsigned op1
, unsigned crn
,
13732 unsigned crm
, unsigned op2
)
13734 if (crn
== 0 && op1
== 3 && crm
== 0 && op2
== 7)
13735 /* DCZID_EL0 - the Data Cache Zero ID register.
13736 We do not support DC ZVA at the moment, so
13737 we return a value with the disable bit set.
13738 We implement support for the DCZID register since
13739 it is used by the C library's memset function. */
13740 return ((uint64_t) 1) << 4;
13742 if (crn
== 0 && op1
== 3 && crm
== 0 && op2
== 1)
13743 /* Cache Type Register. */
13744 return 0x80008000UL
;
13746 if (crn
== 13 && op1
== 3 && crm
== 0 && op2
== 2)
13747 /* TPIDR_EL0 - thread pointer id. */
13748 return aarch64_get_thread_id (cpu
);
13750 if (op1
== 3 && crm
== 4 && op2
== 0)
13751 return aarch64_get_FPCR (cpu
);
13753 if (op1
== 3 && crm
== 4 && op2
== 1)
13754 return aarch64_get_FPSR (cpu
);
13756 else if (op1
== 3 && crm
== 2 && op2
== 0)
13757 return aarch64_get_CPSR (cpu
);
13763 system_set (sim_cpu
*cpu
, unsigned op0
, unsigned op1
, unsigned crn
,
13764 unsigned crm
, unsigned op2
, uint64_t val
)
13766 if (op1
== 3 && crm
== 4 && op2
== 0)
13767 aarch64_set_FPCR (cpu
, val
);
13769 else if (op1
== 3 && crm
== 4 && op2
== 1)
13770 aarch64_set_FPSR (cpu
, val
);
13772 else if (op1
== 3 && crm
== 2 && op2
== 0)
13773 aarch64_set_CPSR (cpu
, val
);
13780 do_mrs (sim_cpu
*cpu
)
13782 /* instr[31:20] = 1101 0101 0001 1
13789 unsigned sys_op0
= INSTR (19, 19) + 2;
13790 unsigned sys_op1
= INSTR (18, 16);
13791 unsigned sys_crn
= INSTR (15, 12);
13792 unsigned sys_crm
= INSTR (11, 8);
13793 unsigned sys_op2
= INSTR (7, 5);
13794 unsigned rt
= INSTR (4, 0);
13796 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13797 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
13798 system_get (cpu
, sys_op0
, sys_op1
, sys_crn
, sys_crm
, sys_op2
));
13802 do_MSR_immediate (sim_cpu
*cpu
)
13804 /* instr[31:19] = 1101 0101 0000 0
13806 instr[15,12] = 0100
13809 instr[4,0] = 1 1111 */
13811 unsigned op1
= INSTR (18, 16);
13812 /*unsigned crm = INSTR (11, 8);*/
13813 unsigned op2
= INSTR (7, 5);
13815 NYI_assert (31, 19, 0x1AA0);
13816 NYI_assert (15, 12, 0x4);
13817 NYI_assert (4, 0, 0x1F);
13822 HALT_NYI
; /* set SPSel. */
13829 HALT_NYI
; /* set DAIFset. */
13831 HALT_NYI
; /* set DAIFclr. */
13840 do_MSR_reg (sim_cpu
*cpu
)
13842 /* instr[31:20] = 1101 0101 0001
13850 unsigned sys_op0
= INSTR (19, 19) + 2;
13851 unsigned sys_op1
= INSTR (18, 16);
13852 unsigned sys_crn
= INSTR (15, 12);
13853 unsigned sys_crm
= INSTR (11, 8);
13854 unsigned sys_op2
= INSTR (7, 5);
13855 unsigned rt
= INSTR (4, 0);
13857 NYI_assert (31, 20, 0xD51);
13859 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13860 system_set (cpu
, sys_op0
, sys_op1
, sys_crn
, sys_crm
, sys_op2
,
13861 aarch64_get_reg_u64 (cpu
, rt
, NO_SP
));
13865 do_SYS (sim_cpu
*cpu
)
13867 /* instr[31,19] = 1101 0101 0000 1
13873 NYI_assert (31, 19, 0x1AA1);
13875 /* FIXME: For now we just silently accept system ops. */
13879 dexSystem (sim_cpu
*cpu
)
13881 /* instr[31:22] = 1101 01010 0
13888 instr[4,0] = uimm5 */
13890 /* We are interested in HINT, DSB, DMB and ISB
13892 Hint #0 encodes NOOP (this is the only hint we care about)
13893 L == 0, op0 == 0, op1 = 011, CRn = 0010, Rt = 11111,
13894 CRm op2 != 0000 000 OR CRm op2 == 0000 000 || CRm op > 0000 101
13896 DSB, DMB, ISB are data store barrier, data memory barrier and
13897 instruction store barrier, respectively, where
13899 L == 0, op0 == 0, op1 = 011, CRn = 0011, Rt = 11111,
13900 op2 : DSB ==> 100, DMB ==> 101, ISB ==> 110
13901 CRm<3:2> ==> domain, CRm<1:0> ==> types,
13902 domain : 00 ==> OuterShareable, 01 ==> Nonshareable,
13903 10 ==> InerShareable, 11 ==> FullSystem
13904 types : 01 ==> Reads, 10 ==> Writes,
13905 11 ==> All, 00 ==> All (domain == FullSystem). */
13907 unsigned rt
= INSTR (4, 0);
13909 NYI_assert (31, 22, 0x354);
13911 switch (INSTR (21, 12))
13916 /* NOP has CRm != 0000 OR. */
13917 /* (CRm == 0000 AND (op2 == 000 OR op2 > 101)). */
13918 uint32_t crm
= INSTR (11, 8);
13919 uint32_t op2
= INSTR (7, 5);
13921 if (crm
!= 0 || (op2
== 0 || op2
> 5))
13923 /* Actually call nop method so we can reimplement it later. */
13932 uint32_t op2
= INSTR (7, 5);
13937 case 4: dsb (cpu
); return;
13938 case 5: dmb (cpu
); return;
13939 case 6: isb (cpu
); return;
13940 default: HALT_UNALLOC
;
13951 do_SYS (cpu
); /* DC is an alias of SYS. */
13955 if (INSTR (21, 20) == 0x1)
13957 else if (INSTR (21, 19) == 0 && INSTR (15, 12) == 0x4)
13958 do_MSR_immediate (cpu
);
13966 dexBr (sim_cpu
*cpu
)
13968 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
13969 assert group == GROUP_BREXSYS_1010 || group == GROUP_BREXSYS_1011
13970 bits [31,29] of a BrExSys are the secondary dispatch vector. */
13971 uint32_t group2
= dispatchBrExSys (aarch64_get_instr (cpu
));
13976 return dexBranchImmediate (cpu
);
13978 case BR_IMMCMP_001
:
13979 /* Compare has bit 25 clear while test has it set. */
13980 if (!INSTR (25, 25))
13981 dexCompareBranchImmediate (cpu
);
13983 dexTestBranchImmediate (cpu
);
13986 case BR_IMMCOND_010
:
13987 /* This is a conditional branch if bit 25 is clear otherwise
13989 if (!INSTR (25, 25))
13990 dexCondBranchImmediate (cpu
);
13995 case BR_UNALLOC_011
:
13999 dexBranchImmediate (cpu
);
14002 case BR_IMMCMP_101
:
14003 /* Compare has bit 25 clear while test has it set. */
14004 if (!INSTR (25, 25))
14005 dexCompareBranchImmediate (cpu
);
14007 dexTestBranchImmediate (cpu
);
14011 /* Unconditional branch reg has bit 25 set. */
14012 if (INSTR (25, 25))
14013 dexBranchRegister (cpu
);
14015 /* This includes both Excpn Gen, System and unalloc operations.
14016 We need to decode the Excpn Gen operation BRK so we can plant
14017 debugger entry points.
14018 Excpn Gen operations have instr [24] = 0.
14019 we need to decode at least one of the System operations NOP
14020 which is an alias for HINT #0.
14021 System operations have instr [24,22] = 100. */
14022 else if (INSTR (24, 24) == 0)
14025 else if (INSTR (24, 22) == 4)
14033 case BR_UNALLOC_111
:
14037 /* Should never reach here. */
14043 aarch64_decode_and_execute (sim_cpu
*cpu
, uint64_t pc
)
14045 /* We need to check if gdb wants an in here. */
14046 /* checkBreak (cpu);. */
14048 uint64_t group
= dispatchGroup (aarch64_get_instr (cpu
));
14052 case GROUP_PSEUDO_0000
: dexPseudo (cpu
); break;
14053 case GROUP_LDST_0100
: dexLdSt (cpu
); break;
14054 case GROUP_DPREG_0101
: dexDPReg (cpu
); break;
14055 case GROUP_LDST_0110
: dexLdSt (cpu
); break;
14056 case GROUP_ADVSIMD_0111
: dexAdvSIMD0 (cpu
); break;
14057 case GROUP_DPIMM_1000
: dexDPImm (cpu
); break;
14058 case GROUP_DPIMM_1001
: dexDPImm (cpu
); break;
14059 case GROUP_BREXSYS_1010
: dexBr (cpu
); break;
14060 case GROUP_BREXSYS_1011
: dexBr (cpu
); break;
14061 case GROUP_LDST_1100
: dexLdSt (cpu
); break;
14062 case GROUP_DPREG_1101
: dexDPReg (cpu
); break;
14063 case GROUP_LDST_1110
: dexLdSt (cpu
); break;
14064 case GROUP_ADVSIMD_1111
: dexAdvSIMD1 (cpu
); break;
14066 case GROUP_UNALLOC_0001
:
14067 case GROUP_UNALLOC_0010
:
14068 case GROUP_UNALLOC_0011
:
14072 /* Should never reach here. */
14078 aarch64_step (sim_cpu
*cpu
)
14080 uint64_t pc
= aarch64_get_PC (cpu
);
14082 if (pc
== TOP_LEVEL_RETURN_PC
)
14085 aarch64_set_next_PC (cpu
, pc
+ 4);
14087 /* Code is always little-endian. */
14088 sim_core_read_buffer (CPU_STATE (cpu
), cpu
, read_map
,
14089 & aarch64_get_instr (cpu
), pc
, 4);
14090 aarch64_get_instr (cpu
) = endian_le2h_4 (aarch64_get_instr (cpu
));
14092 TRACE_INSN (cpu
, " pc = %" PRIx64
" instr = %08x", pc
,
14093 aarch64_get_instr (cpu
));
14094 TRACE_DISASM (cpu
, pc
);
14096 aarch64_decode_and_execute (cpu
, pc
);
14102 aarch64_run (SIM_DESC sd
)
14104 sim_cpu
*cpu
= STATE_CPU (sd
, 0);
14106 while (aarch64_step (cpu
))
14107 aarch64_update_PC (cpu
);
14109 sim_engine_halt (sd
, NULL
, NULL
, aarch64_get_PC (cpu
),
14110 sim_exited
, aarch64_get_reg_s32 (cpu
, R0
, SP_OK
));
14114 aarch64_init (sim_cpu
*cpu
, uint64_t pc
)
14116 uint64_t sp
= aarch64_get_stack_start (cpu
);
14118 /* Install SP, FP and PC and set LR to -20
14119 so we can detect a top-level return. */
14120 aarch64_set_reg_u64 (cpu
, SP
, SP_OK
, sp
);
14121 aarch64_set_reg_u64 (cpu
, FP
, SP_OK
, sp
);
14122 aarch64_set_reg_u64 (cpu
, LR
, SP_OK
, TOP_LEVEL_RETURN_PC
);
14123 aarch64_set_next_PC (cpu
, pc
);
14124 aarch64_update_PC (cpu
);
14125 aarch64_init_LIT_table ();