1 /* simulator.c -- Interface for the AArch64 simulator.
3 Copyright (C) 2015-2021 Free Software Foundation, Inc.
5 Contributed by Red Hat.
7 This file is part of GDB.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
22 /* This must come before any other includes. */
28 #include <sys/types.h>
33 #include "simulator.h"
40 #define TST(_flag) (aarch64_test_CPSR_bit (cpu, _flag))
41 #define IS_SET(_X) (TST (( _X )) ? 1 : 0)
42 #define IS_CLEAR(_X) (TST (( _X )) ? 0 : 1)
44 /* Space saver macro. */
45 #define INSTR(HIGH, LOW) uimm (aarch64_get_instr (cpu), (HIGH), (LOW))
47 #define HALT_UNALLOC \
50 TRACE_DISASM (cpu, aarch64_get_PC (cpu)); \
52 "Unallocated instruction detected at sim line %d," \
53 " exe addr %" PRIx64, \
54 __LINE__, aarch64_get_PC (cpu)); \
55 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),\
56 sim_stopped, SIM_SIGILL); \
63 TRACE_DISASM (cpu, aarch64_get_PC (cpu)); \
65 "Unimplemented instruction detected at sim line %d," \
66 " exe addr %" PRIx64, \
67 __LINE__, aarch64_get_PC (cpu)); \
68 if (! TRACE_ANY_P (cpu)) \
69 sim_io_eprintf (CPU_STATE (cpu), "SIM Error: Unimplemented instruction: %#08x\n", \
70 aarch64_get_instr (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
!= (uint32_t)uresult
)
1658 if (sresult
!= (int32_t)sresult
)
1661 aarch64_set_CPSR (cpu
, flags
);
1664 #define NEG(a) (((a) & signbit) == signbit)
1665 #define POS(a) (((a) & signbit) == 0)
1668 set_flags_for_add64 (sim_cpu
*cpu
, uint64_t value1
, uint64_t value2
)
1670 uint64_t result
= value1
+ value2
;
1672 uint64_t signbit
= 1ULL << 63;
1680 if ( (NEG (value1
) && NEG (value2
))
1681 || (NEG (value1
) && POS (result
))
1682 || (NEG (value2
) && POS (result
)))
1685 if ( (NEG (value1
) && NEG (value2
) && POS (result
))
1686 || (POS (value1
) && POS (value2
) && NEG (result
)))
1689 aarch64_set_CPSR (cpu
, flags
);
1693 set_flags_for_sub32 (sim_cpu
*cpu
, uint32_t value1
, uint32_t value2
)
1695 uint32_t result
= value1
- value2
;
1697 uint32_t signbit
= 1U << 31;
1705 if ( (NEG (value1
) && POS (value2
))
1706 || (NEG (value1
) && POS (result
))
1707 || (POS (value2
) && POS (result
)))
1710 if ( (NEG (value1
) && POS (value2
) && POS (result
))
1711 || (POS (value1
) && NEG (value2
) && NEG (result
)))
1714 aarch64_set_CPSR (cpu
, flags
);
1718 set_flags_for_sub64 (sim_cpu
*cpu
, uint64_t value1
, uint64_t value2
)
1720 uint64_t result
= value1
- value2
;
1722 uint64_t signbit
= 1ULL << 63;
1730 if ( (NEG (value1
) && POS (value2
))
1731 || (NEG (value1
) && POS (result
))
1732 || (POS (value2
) && POS (result
)))
1735 if ( (NEG (value1
) && POS (value2
) && POS (result
))
1736 || (POS (value1
) && NEG (value2
) && NEG (result
)))
1739 aarch64_set_CPSR (cpu
, flags
);
1743 set_flags_for_binop32 (sim_cpu
*cpu
, uint32_t result
)
1752 if (result
& (1 << 31))
1757 aarch64_set_CPSR (cpu
, flags
);
1761 set_flags_for_binop64 (sim_cpu
*cpu
, uint64_t result
)
1770 if (result
& (1ULL << 63))
1775 aarch64_set_CPSR (cpu
, flags
);
1778 /* 32 bit add immediate set flags. */
1780 adds32 (sim_cpu
*cpu
, uint32_t aimm
)
1782 unsigned rn
= INSTR (9, 5);
1783 unsigned rd
= INSTR (4, 0);
1784 /* TODO : do we need to worry about signs here? */
1785 int32_t value1
= aarch64_get_reg_s32 (cpu
, rn
, SP_OK
);
1787 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1788 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ aimm
);
1789 set_flags_for_add32 (cpu
, value1
, aimm
);
1792 /* 64 bit add immediate set flags. */
1794 adds64 (sim_cpu
*cpu
, uint32_t aimm
)
1796 unsigned rn
= INSTR (9, 5);
1797 unsigned rd
= INSTR (4, 0);
1798 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1799 uint64_t value2
= aimm
;
1801 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1802 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
);
1803 set_flags_for_add64 (cpu
, value1
, value2
);
1806 /* 32 bit sub immediate. */
1808 sub32 (sim_cpu
*cpu
, uint32_t aimm
)
1810 unsigned rn
= INSTR (9, 5);
1811 unsigned rd
= INSTR (4, 0);
1813 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1814 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
1815 aarch64_get_reg_u32 (cpu
, rn
, SP_OK
) - aimm
);
1818 /* 64 bit sub immediate. */
1820 sub64 (sim_cpu
*cpu
, uint32_t aimm
)
1822 unsigned rn
= INSTR (9, 5);
1823 unsigned rd
= INSTR (4, 0);
1825 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1826 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
1827 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) - aimm
);
1830 /* 32 bit sub immediate set flags. */
1832 subs32 (sim_cpu
*cpu
, uint32_t aimm
)
1834 unsigned rn
= INSTR (9, 5);
1835 unsigned rd
= INSTR (4, 0);
1836 uint32_t value1
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1837 uint32_t value2
= aimm
;
1839 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1840 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
1841 set_flags_for_sub32 (cpu
, value1
, value2
);
1844 /* 64 bit sub immediate set flags. */
1846 subs64 (sim_cpu
*cpu
, uint32_t aimm
)
1848 unsigned rn
= INSTR (9, 5);
1849 unsigned rd
= INSTR (4, 0);
1850 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1851 uint32_t value2
= aimm
;
1853 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1854 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
1855 set_flags_for_sub64 (cpu
, value1
, value2
);
1858 /* Data Processing Register. */
1860 /* First two helpers to perform the shift operations. */
1862 static inline uint32_t
1863 shifted32 (uint32_t value
, Shift shift
, uint32_t count
)
1869 return (value
<< count
);
1871 return (value
>> count
);
1874 int32_t svalue
= value
;
1875 return (svalue
>> count
);
1879 uint32_t top
= value
>> count
;
1880 uint32_t bottom
= value
<< (32 - count
);
1881 return (bottom
| top
);
1886 static inline uint64_t
1887 shifted64 (uint64_t value
, Shift shift
, uint32_t count
)
1893 return (value
<< count
);
1895 return (value
>> count
);
1898 int64_t svalue
= value
;
1899 return (svalue
>> count
);
1903 uint64_t top
= value
>> count
;
1904 uint64_t bottom
= value
<< (64 - count
);
1905 return (bottom
| top
);
1910 /* Arithmetic shifted register.
1911 These allow an optional LSL, ASR or LSR to the second source
1912 register with a count up to the register bit count.
1914 N.B register args may not be SP. */
1916 /* 32 bit ADD shifted register. */
1918 add32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1920 unsigned rm
= INSTR (20, 16);
1921 unsigned rn
= INSTR (9, 5);
1922 unsigned rd
= INSTR (4, 0);
1924 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1925 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
1926 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
1927 + shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
1931 /* 64 bit ADD shifted register. */
1933 add64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1935 unsigned rm
= INSTR (20, 16);
1936 unsigned rn
= INSTR (9, 5);
1937 unsigned rd
= INSTR (4, 0);
1939 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1940 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
1941 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
1942 + shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
1946 /* 32 bit ADD shifted register setting flags. */
1948 adds32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1950 unsigned rm
= INSTR (20, 16);
1951 unsigned rn
= INSTR (9, 5);
1952 unsigned rd
= INSTR (4, 0);
1954 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
1955 uint32_t value2
= shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
1958 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1959 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
);
1960 set_flags_for_add32 (cpu
, value1
, value2
);
1963 /* 64 bit ADD shifted register setting flags. */
1965 adds64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1967 unsigned rm
= INSTR (20, 16);
1968 unsigned rn
= INSTR (9, 5);
1969 unsigned rd
= INSTR (4, 0);
1971 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
1972 uint64_t value2
= shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
1975 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1976 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
);
1977 set_flags_for_add64 (cpu
, value1
, value2
);
1980 /* 32 bit SUB shifted register. */
1982 sub32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1984 unsigned rm
= INSTR (20, 16);
1985 unsigned rn
= INSTR (9, 5);
1986 unsigned rd
= INSTR (4, 0);
1988 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1989 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
1990 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
1991 - shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
1995 /* 64 bit SUB shifted register. */
1997 sub64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1999 unsigned rm
= INSTR (20, 16);
2000 unsigned rn
= INSTR (9, 5);
2001 unsigned rd
= INSTR (4, 0);
2003 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2004 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
2005 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
2006 - shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
2010 /* 32 bit SUB shifted register setting flags. */
2012 subs32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
2014 unsigned rm
= INSTR (20, 16);
2015 unsigned rn
= INSTR (9, 5);
2016 unsigned rd
= INSTR (4, 0);
2018 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
2019 uint32_t value2
= shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
2022 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2023 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
2024 set_flags_for_sub32 (cpu
, value1
, value2
);
2027 /* 64 bit SUB shifted register setting flags. */
2029 subs64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
2031 unsigned rm
= INSTR (20, 16);
2032 unsigned rn
= INSTR (9, 5);
2033 unsigned rd
= INSTR (4, 0);
2035 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
2036 uint64_t value2
= shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
2039 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2040 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
2041 set_flags_for_sub64 (cpu
, value1
, value2
);
2044 /* First a couple more helpers to fetch the
2045 relevant source register element either
2046 sign or zero extended as required by the
2050 extreg32 (sim_cpu
*cpu
, unsigned int lo
, Extension extension
)
2054 case UXTB
: return aarch64_get_reg_u8 (cpu
, lo
, NO_SP
);
2055 case UXTH
: return aarch64_get_reg_u16 (cpu
, lo
, NO_SP
);
2056 case UXTW
: /* Fall through. */
2057 case UXTX
: return aarch64_get_reg_u32 (cpu
, lo
, NO_SP
);
2058 case SXTB
: return aarch64_get_reg_s8 (cpu
, lo
, NO_SP
);
2059 case SXTH
: return aarch64_get_reg_s16 (cpu
, lo
, NO_SP
);
2060 case SXTW
: /* Fall through. */
2061 case SXTX
: /* Fall through. */
2062 default: return aarch64_get_reg_s32 (cpu
, lo
, NO_SP
);
2067 extreg64 (sim_cpu
*cpu
, unsigned int lo
, Extension extension
)
2071 case UXTB
: return aarch64_get_reg_u8 (cpu
, lo
, NO_SP
);
2072 case UXTH
: return aarch64_get_reg_u16 (cpu
, lo
, NO_SP
);
2073 case UXTW
: return aarch64_get_reg_u32 (cpu
, lo
, NO_SP
);
2074 case UXTX
: return aarch64_get_reg_u64 (cpu
, lo
, NO_SP
);
2075 case SXTB
: return aarch64_get_reg_s8 (cpu
, lo
, NO_SP
);
2076 case SXTH
: return aarch64_get_reg_s16 (cpu
, lo
, NO_SP
);
2077 case SXTW
: return aarch64_get_reg_s32 (cpu
, lo
, NO_SP
);
2079 default: return aarch64_get_reg_s64 (cpu
, lo
, NO_SP
);
2083 /* Arithmetic extending register
2084 These allow an optional sign extension of some portion of the
2085 second source register followed by an optional left shift of
2086 between 1 and 4 bits (i.e. a shift of 0-4 bits???)
2088 N.B output (dest) and first input arg (source) may normally be Xn
2089 or SP. However, for flag setting operations dest can only be
2090 Xn. Second input registers are always Xn. */
2092 /* 32 bit ADD extending register. */
2094 add32_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2096 unsigned rm
= INSTR (20, 16);
2097 unsigned rn
= INSTR (9, 5);
2098 unsigned rd
= INSTR (4, 0);
2100 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2101 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
2102 aarch64_get_reg_u32 (cpu
, rn
, SP_OK
)
2103 + (extreg32 (cpu
, rm
, extension
) << shift
));
2106 /* 64 bit ADD extending register.
2107 N.B. This subsumes the case with 64 bit source2 and UXTX #n or LSL #0. */
2109 add64_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2111 unsigned rm
= INSTR (20, 16);
2112 unsigned rn
= INSTR (9, 5);
2113 unsigned rd
= INSTR (4, 0);
2115 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2116 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
2117 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
2118 + (extreg64 (cpu
, rm
, extension
) << shift
));
2121 /* 32 bit ADD extending register setting flags. */
2123 adds32_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2125 unsigned rm
= INSTR (20, 16);
2126 unsigned rn
= INSTR (9, 5);
2127 unsigned rd
= INSTR (4, 0);
2129 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, SP_OK
);
2130 uint32_t value2
= extreg32 (cpu
, rm
, extension
) << shift
;
2132 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2133 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
);
2134 set_flags_for_add32 (cpu
, value1
, value2
);
2137 /* 64 bit ADD extending register setting flags */
2138 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0 */
2140 adds64_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2142 unsigned rm
= INSTR (20, 16);
2143 unsigned rn
= INSTR (9, 5);
2144 unsigned rd
= INSTR (4, 0);
2146 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
2147 uint64_t value2
= extreg64 (cpu
, rm
, extension
) << shift
;
2149 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2150 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
);
2151 set_flags_for_add64 (cpu
, value1
, value2
);
2154 /* 32 bit SUB extending register. */
2156 sub32_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2158 unsigned rm
= INSTR (20, 16);
2159 unsigned rn
= INSTR (9, 5);
2160 unsigned rd
= INSTR (4, 0);
2162 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2163 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
2164 aarch64_get_reg_u32 (cpu
, rn
, SP_OK
)
2165 - (extreg32 (cpu
, rm
, extension
) << shift
));
2168 /* 64 bit SUB extending register. */
2169 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0. */
2171 sub64_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2173 unsigned rm
= INSTR (20, 16);
2174 unsigned rn
= INSTR (9, 5);
2175 unsigned rd
= INSTR (4, 0);
2177 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2178 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
2179 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
2180 - (extreg64 (cpu
, rm
, extension
) << shift
));
2183 /* 32 bit SUB extending register setting flags. */
2185 subs32_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2187 unsigned rm
= INSTR (20, 16);
2188 unsigned rn
= INSTR (9, 5);
2189 unsigned rd
= INSTR (4, 0);
2191 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, SP_OK
);
2192 uint32_t value2
= extreg32 (cpu
, rm
, extension
) << shift
;
2194 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2195 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
2196 set_flags_for_sub32 (cpu
, value1
, value2
);
2199 /* 64 bit SUB extending register setting flags */
2200 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0 */
2202 subs64_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2204 unsigned rm
= INSTR (20, 16);
2205 unsigned rn
= INSTR (9, 5);
2206 unsigned rd
= INSTR (4, 0);
2208 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
2209 uint64_t value2
= extreg64 (cpu
, rm
, extension
) << shift
;
2211 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2212 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
2213 set_flags_for_sub64 (cpu
, value1
, value2
);
2217 dexAddSubtractImmediate (sim_cpu
*cpu
)
2219 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2220 instr[30] = op : 0 ==> ADD, 1 ==> SUB
2221 instr[29] = set : 0 ==> no flags, 1 ==> set flags
2222 instr[28,24] = 10001
2223 instr[23,22] = shift : 00 == LSL#0, 01 = LSL#12 1x = UNALLOC
2224 instr[21,10] = uimm12
2228 /* N.B. the shift is applied at decode before calling the add/sub routine. */
2229 uint32_t shift
= INSTR (23, 22);
2230 uint32_t imm
= INSTR (21, 10);
2231 uint32_t dispatch
= INSTR (31, 29);
2233 NYI_assert (28, 24, 0x11);
2243 case 0: add32 (cpu
, imm
); break;
2244 case 1: adds32 (cpu
, imm
); break;
2245 case 2: sub32 (cpu
, imm
); break;
2246 case 3: subs32 (cpu
, imm
); break;
2247 case 4: add64 (cpu
, imm
); break;
2248 case 5: adds64 (cpu
, imm
); break;
2249 case 6: sub64 (cpu
, imm
); break;
2250 case 7: subs64 (cpu
, imm
); break;
2255 dexAddSubtractShiftedRegister (sim_cpu
*cpu
)
2257 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2258 instr[30,29] = op : 00 ==> ADD, 01 ==> ADDS, 10 ==> SUB, 11 ==> SUBS
2259 instr[28,24] = 01011
2260 instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> UNALLOC
2263 instr[15,10] = count : must be 0xxxxx for 32 bit
2267 uint32_t size
= INSTR (31, 31);
2268 uint32_t count
= INSTR (15, 10);
2269 Shift shiftType
= INSTR (23, 22);
2271 NYI_assert (28, 24, 0x0B);
2272 NYI_assert (21, 21, 0);
2274 /* Shift encoded as ROR is unallocated. */
2275 if (shiftType
== ROR
)
2278 /* 32 bit operations must have count[5] = 0
2279 or else we have an UNALLOC. */
2280 if (size
== 0 && uimm (count
, 5, 5))
2283 /* Dispatch on size:op i.e instr [31,29]. */
2284 switch (INSTR (31, 29))
2286 case 0: add32_shift (cpu
, shiftType
, count
); break;
2287 case 1: adds32_shift (cpu
, shiftType
, count
); break;
2288 case 2: sub32_shift (cpu
, shiftType
, count
); break;
2289 case 3: subs32_shift (cpu
, shiftType
, count
); break;
2290 case 4: add64_shift (cpu
, shiftType
, count
); break;
2291 case 5: adds64_shift (cpu
, shiftType
, count
); break;
2292 case 6: sub64_shift (cpu
, shiftType
, count
); break;
2293 case 7: subs64_shift (cpu
, shiftType
, count
); break;
2298 dexAddSubtractExtendedRegister (sim_cpu
*cpu
)
2300 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2301 instr[30] = op : 0 ==> ADD, 1 ==> SUB
2302 instr[29] = set? : 0 ==> no flags, 1 ==> set flags
2303 instr[28,24] = 01011
2304 instr[23,22] = opt : 0 ==> ok, 1,2,3 ==> UNALLOC
2307 instr[15,13] = option : 000 ==> UXTB, 001 ==> UXTH,
2308 000 ==> LSL|UXTW, 001 ==> UXTZ,
2309 000 ==> SXTB, 001 ==> SXTH,
2310 000 ==> SXTW, 001 ==> SXTX,
2311 instr[12,10] = shift : 0,1,2,3,4 ==> ok, 5,6,7 ==> UNALLOC
2315 Extension extensionType
= INSTR (15, 13);
2316 uint32_t shift
= INSTR (12, 10);
2318 NYI_assert (28, 24, 0x0B);
2319 NYI_assert (21, 21, 1);
2321 /* Shift may not exceed 4. */
2325 /* Dispatch on size:op:set?. */
2326 switch (INSTR (31, 29))
2328 case 0: add32_ext (cpu
, extensionType
, shift
); break;
2329 case 1: adds32_ext (cpu
, extensionType
, shift
); break;
2330 case 2: sub32_ext (cpu
, extensionType
, shift
); break;
2331 case 3: subs32_ext (cpu
, extensionType
, shift
); break;
2332 case 4: add64_ext (cpu
, extensionType
, shift
); break;
2333 case 5: adds64_ext (cpu
, extensionType
, shift
); break;
2334 case 6: sub64_ext (cpu
, extensionType
, shift
); break;
2335 case 7: subs64_ext (cpu
, extensionType
, shift
); break;
2339 /* Conditional data processing
2340 Condition register is implicit 3rd source. */
2342 /* 32 bit add with carry. */
2343 /* N.B register args may not be SP. */
2346 adc32 (sim_cpu
*cpu
)
2348 unsigned rm
= INSTR (20, 16);
2349 unsigned rn
= INSTR (9, 5);
2350 unsigned rd
= INSTR (4, 0);
2352 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2353 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
2354 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
2355 + aarch64_get_reg_u32 (cpu
, rm
, NO_SP
)
2359 /* 64 bit add with carry */
2361 adc64 (sim_cpu
*cpu
)
2363 unsigned rm
= INSTR (20, 16);
2364 unsigned rn
= INSTR (9, 5);
2365 unsigned rd
= INSTR (4, 0);
2367 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2368 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
2369 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
2370 + aarch64_get_reg_u64 (cpu
, rm
, NO_SP
)
2374 /* 32 bit add with carry setting flags. */
2376 adcs32 (sim_cpu
*cpu
)
2378 unsigned rm
= INSTR (20, 16);
2379 unsigned rn
= INSTR (9, 5);
2380 unsigned rd
= INSTR (4, 0);
2382 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
2383 uint32_t value2
= aarch64_get_reg_u32 (cpu
, rm
, NO_SP
);
2384 uint32_t carry
= IS_SET (C
);
2386 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2387 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
+ carry
);
2388 set_flags_for_add32 (cpu
, value1
, value2
+ carry
);
2391 /* 64 bit add with carry setting flags. */
2393 adcs64 (sim_cpu
*cpu
)
2395 unsigned rm
= INSTR (20, 16);
2396 unsigned rn
= INSTR (9, 5);
2397 unsigned rd
= INSTR (4, 0);
2399 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
2400 uint64_t value2
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
2401 uint64_t carry
= IS_SET (C
);
2403 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2404 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
+ carry
);
2405 set_flags_for_add64 (cpu
, value1
, value2
+ carry
);
2408 /* 32 bit sub with carry. */
2410 sbc32 (sim_cpu
*cpu
)
2412 unsigned rm
= INSTR (20, 16);
2413 unsigned rn
= INSTR (9, 5); /* ngc iff rn == 31. */
2414 unsigned rd
= INSTR (4, 0);
2416 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2417 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
2418 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
2419 - aarch64_get_reg_u32 (cpu
, rm
, NO_SP
)
2423 /* 64 bit sub with carry */
2425 sbc64 (sim_cpu
*cpu
)
2427 unsigned rm
= INSTR (20, 16);
2428 unsigned rn
= INSTR (9, 5);
2429 unsigned rd
= INSTR (4, 0);
2431 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2432 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
2433 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
2434 - aarch64_get_reg_u64 (cpu
, rm
, NO_SP
)
2438 /* 32 bit sub with carry setting flags */
2440 sbcs32 (sim_cpu
*cpu
)
2442 unsigned rm
= INSTR (20, 16);
2443 unsigned rn
= INSTR (9, 5);
2444 unsigned rd
= INSTR (4, 0);
2446 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
2447 uint32_t value2
= aarch64_get_reg_u32 (cpu
, rm
, NO_SP
);
2448 uint32_t carry
= IS_SET (C
);
2449 uint32_t result
= value1
- value2
+ 1 - carry
;
2451 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2452 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
2453 set_flags_for_sub32 (cpu
, value1
, value2
+ 1 - carry
);
2456 /* 64 bit sub with carry setting flags */
2458 sbcs64 (sim_cpu
*cpu
)
2460 unsigned rm
= INSTR (20, 16);
2461 unsigned rn
= INSTR (9, 5);
2462 unsigned rd
= INSTR (4, 0);
2464 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
2465 uint64_t value2
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
2466 uint64_t carry
= IS_SET (C
);
2467 uint64_t result
= value1
- value2
+ 1 - carry
;
2469 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2470 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
2471 set_flags_for_sub64 (cpu
, value1
, value2
+ 1 - carry
);
2475 dexAddSubtractWithCarry (sim_cpu
*cpu
)
2477 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2478 instr[30] = op : 0 ==> ADC, 1 ==> SBC
2479 instr[29] = set? : 0 ==> no flags, 1 ==> set flags
2480 instr[28,21] = 1 1010 000
2482 instr[15,10] = op2 : 00000 ==> ok, ow ==> UNALLOC
2486 uint32_t op2
= INSTR (15, 10);
2488 NYI_assert (28, 21, 0xD0);
2493 /* Dispatch on size:op:set?. */
2494 switch (INSTR (31, 29))
2496 case 0: adc32 (cpu
); break;
2497 case 1: adcs32 (cpu
); break;
2498 case 2: sbc32 (cpu
); break;
2499 case 3: sbcs32 (cpu
); break;
2500 case 4: adc64 (cpu
); break;
2501 case 5: adcs64 (cpu
); break;
2502 case 6: sbc64 (cpu
); break;
2503 case 7: sbcs64 (cpu
); break;
2508 testConditionCode (sim_cpu
*cpu
, CondCode cc
)
2510 /* This should be reduceable to branchless logic
2511 by some careful testing of bits in CC followed
2512 by the requisite masking and combining of bits
2513 from the flag register.
2515 For now we do it with a switch. */
2520 case EQ
: res
= IS_SET (Z
); break;
2521 case NE
: res
= IS_CLEAR (Z
); break;
2522 case CS
: res
= IS_SET (C
); break;
2523 case CC
: res
= IS_CLEAR (C
); break;
2524 case MI
: res
= IS_SET (N
); break;
2525 case PL
: res
= IS_CLEAR (N
); break;
2526 case VS
: res
= IS_SET (V
); break;
2527 case VC
: res
= IS_CLEAR (V
); break;
2528 case HI
: res
= IS_SET (C
) && IS_CLEAR (Z
); break;
2529 case LS
: res
= IS_CLEAR (C
) || IS_SET (Z
); break;
2530 case GE
: res
= IS_SET (N
) == IS_SET (V
); break;
2531 case LT
: res
= IS_SET (N
) != IS_SET (V
); break;
2532 case GT
: res
= IS_CLEAR (Z
) && (IS_SET (N
) == IS_SET (V
)); break;
2533 case LE
: res
= IS_SET (Z
) || (IS_SET (N
) != IS_SET (V
)); break;
2544 CondCompare (sim_cpu
*cpu
) /* aka: ccmp and ccmn */
2546 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2547 instr[30] = compare with positive (1) or negative value (0)
2548 instr[29,21] = 1 1101 0010
2549 instr[20,16] = Rm or const
2551 instr[11] = compare reg (0) or const (1)
2555 instr[3,0] = value for CPSR bits if the comparison does not take place. */
2560 NYI_assert (29, 21, 0x1d2);
2561 NYI_assert (10, 10, 0);
2562 NYI_assert (4, 4, 0);
2564 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2565 if (! testConditionCode (cpu
, INSTR (15, 12)))
2567 aarch64_set_CPSR (cpu
, INSTR (3, 0));
2571 negate
= INSTR (30, 30) ? 1 : -1;
2572 rm
= INSTR (20, 16);
2578 set_flags_for_sub64 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
),
2579 negate
* (uint64_t) rm
);
2581 set_flags_for_sub64 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
),
2582 negate
* aarch64_get_reg_u64 (cpu
, rm
, SP_OK
));
2587 set_flags_for_sub32 (cpu
, aarch64_get_reg_u32 (cpu
, rn
, SP_OK
),
2590 set_flags_for_sub32 (cpu
, aarch64_get_reg_u32 (cpu
, rn
, SP_OK
),
2591 negate
* aarch64_get_reg_u32 (cpu
, rm
, SP_OK
));
2596 do_vec_MOV_whole_vector (sim_cpu
*cpu
)
2598 /* MOV Vd.T, Vs.T (alias for ORR Vd.T, Vn.T, Vm.T where Vn == Vm)
2601 instr[30] = half(0)/full(1)
2602 instr[29,21] = 001110101
2604 instr[15,10] = 000111
2608 unsigned vs
= INSTR (9, 5);
2609 unsigned vd
= INSTR (4, 0);
2611 NYI_assert (29, 21, 0x075);
2612 NYI_assert (15, 10, 0x07);
2614 if (INSTR (20, 16) != vs
)
2617 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2619 aarch64_set_vec_u64 (cpu
, vd
, 1, aarch64_get_vec_u64 (cpu
, vs
, 1));
2621 aarch64_set_vec_u64 (cpu
, vd
, 0, aarch64_get_vec_u64 (cpu
, vs
, 0));
2625 do_vec_SMOV_into_scalar (sim_cpu
*cpu
)
2628 instr[30] = word(0)/long(1)
2629 instr[29,21] = 00 1110 000
2630 instr[20,16] = element size and index
2631 instr[15,10] = 00 0010 11
2632 instr[9,5] = V source
2633 instr[4,0] = R dest */
2635 unsigned vs
= INSTR (9, 5);
2636 unsigned rd
= INSTR (4, 0);
2637 unsigned imm5
= INSTR (20, 16);
2638 unsigned full
= INSTR (30, 30);
2641 NYI_assert (29, 21, 0x070);
2642 NYI_assert (15, 10, 0x0B);
2644 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2649 index
= (imm5
>> 1) & 0xF;
2651 else if (imm5
& 0x2)
2654 index
= (imm5
>> 2) & 0x7;
2656 else if (full
&& (imm5
& 0x4))
2659 index
= (imm5
>> 3) & 0x3;
2668 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
,
2669 aarch64_get_vec_s8 (cpu
, vs
, index
));
2671 aarch64_set_reg_s32 (cpu
, rd
, NO_SP
,
2672 aarch64_get_vec_s8 (cpu
, vs
, index
));
2677 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
,
2678 aarch64_get_vec_s16 (cpu
, vs
, index
));
2680 aarch64_set_reg_s32 (cpu
, rd
, NO_SP
,
2681 aarch64_get_vec_s16 (cpu
, vs
, index
));
2685 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
,
2686 aarch64_get_vec_s32 (cpu
, vs
, index
));
2695 do_vec_UMOV_into_scalar (sim_cpu
*cpu
)
2698 instr[30] = word(0)/long(1)
2699 instr[29,21] = 00 1110 000
2700 instr[20,16] = element size and index
2701 instr[15,10] = 00 0011 11
2702 instr[9,5] = V source
2703 instr[4,0] = R dest */
2705 unsigned vs
= INSTR (9, 5);
2706 unsigned rd
= INSTR (4, 0);
2707 unsigned imm5
= INSTR (20, 16);
2708 unsigned full
= INSTR (30, 30);
2711 NYI_assert (29, 21, 0x070);
2712 NYI_assert (15, 10, 0x0F);
2714 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2721 index
= (imm5
>> 1) & 0xF;
2723 else if (imm5
& 0x2)
2726 index
= (imm5
>> 2) & 0x7;
2728 else if (imm5
& 0x4)
2731 index
= (imm5
>> 3) & 0x3;
2736 else if (imm5
& 0x8)
2739 index
= (imm5
>> 4) & 0x1;
2747 aarch64_set_reg_u32 (cpu
, rd
, NO_SP
,
2748 aarch64_get_vec_u8 (cpu
, vs
, index
));
2752 aarch64_set_reg_u32 (cpu
, rd
, NO_SP
,
2753 aarch64_get_vec_u16 (cpu
, vs
, index
));
2757 aarch64_set_reg_u32 (cpu
, rd
, NO_SP
,
2758 aarch64_get_vec_u32 (cpu
, vs
, index
));
2762 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
2763 aarch64_get_vec_u64 (cpu
, vs
, index
));
2772 do_vec_INS (sim_cpu
*cpu
)
2774 /* instr[31,21] = 01001110000
2775 instr[20,16] = element size and index
2776 instr[15,10] = 000111
2777 instr[9,5] = W source
2778 instr[4,0] = V dest */
2781 unsigned rs
= INSTR (9, 5);
2782 unsigned vd
= INSTR (4, 0);
2784 NYI_assert (31, 21, 0x270);
2785 NYI_assert (15, 10, 0x07);
2787 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2790 index
= INSTR (20, 17);
2791 aarch64_set_vec_u8 (cpu
, vd
, index
,
2792 aarch64_get_reg_u8 (cpu
, rs
, NO_SP
));
2794 else if (INSTR (17, 17))
2796 index
= INSTR (20, 18);
2797 aarch64_set_vec_u16 (cpu
, vd
, index
,
2798 aarch64_get_reg_u16 (cpu
, rs
, NO_SP
));
2800 else if (INSTR (18, 18))
2802 index
= INSTR (20, 19);
2803 aarch64_set_vec_u32 (cpu
, vd
, index
,
2804 aarch64_get_reg_u32 (cpu
, rs
, NO_SP
));
2806 else if (INSTR (19, 19))
2808 index
= INSTR (20, 20);
2809 aarch64_set_vec_u64 (cpu
, vd
, index
,
2810 aarch64_get_reg_u64 (cpu
, rs
, NO_SP
));
2817 do_vec_DUP_vector_into_vector (sim_cpu
*cpu
)
2820 instr[30] = half(0)/full(1)
2821 instr[29,21] = 00 1110 000
2822 instr[20,16] = element size and index
2823 instr[15,10] = 0000 01
2824 instr[9,5] = V source
2825 instr[4,0] = V dest. */
2827 unsigned full
= INSTR (30, 30);
2828 unsigned vs
= INSTR (9, 5);
2829 unsigned vd
= INSTR (4, 0);
2832 NYI_assert (29, 21, 0x070);
2833 NYI_assert (15, 10, 0x01);
2835 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2838 index
= INSTR (20, 17);
2840 for (i
= 0; i
< (full
? 16 : 8); i
++)
2841 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vs
, index
));
2843 else if (INSTR (17, 17))
2845 index
= INSTR (20, 18);
2847 for (i
= 0; i
< (full
? 8 : 4); i
++)
2848 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vs
, index
));
2850 else if (INSTR (18, 18))
2852 index
= INSTR (20, 19);
2854 for (i
= 0; i
< (full
? 4 : 2); i
++)
2855 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vs
, index
));
2859 if (INSTR (19, 19) == 0)
2865 index
= INSTR (20, 20);
2867 for (i
= 0; i
< 2; i
++)
2868 aarch64_set_vec_u64 (cpu
, vd
, i
, aarch64_get_vec_u64 (cpu
, vs
, index
));
2873 do_vec_TBL (sim_cpu
*cpu
)
2876 instr[30] = half(0)/full(1)
2877 instr[29,21] = 00 1110 000
2880 instr[14,13] = vec length
2882 instr[9,5] = V start
2883 instr[4,0] = V dest */
2885 int full
= INSTR (30, 30);
2886 int len
= INSTR (14, 13) + 1;
2887 unsigned vm
= INSTR (20, 16);
2888 unsigned vn
= INSTR (9, 5);
2889 unsigned vd
= INSTR (4, 0);
2892 NYI_assert (29, 21, 0x070);
2893 NYI_assert (12, 10, 0);
2895 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2896 for (i
= 0; i
< (full
? 16 : 8); i
++)
2898 unsigned int selector
= aarch64_get_vec_u8 (cpu
, vm
, i
);
2902 val
= aarch64_get_vec_u8 (cpu
, vn
, selector
);
2903 else if (selector
< 32)
2904 val
= len
< 2 ? 0 : aarch64_get_vec_u8 (cpu
, vn
+ 1, selector
- 16);
2905 else if (selector
< 48)
2906 val
= len
< 3 ? 0 : aarch64_get_vec_u8 (cpu
, vn
+ 2, selector
- 32);
2907 else if (selector
< 64)
2908 val
= len
< 4 ? 0 : aarch64_get_vec_u8 (cpu
, vn
+ 3, selector
- 48);
2912 aarch64_set_vec_u8 (cpu
, vd
, i
, val
);
2917 do_vec_TRN (sim_cpu
*cpu
)
2920 instr[30] = half(0)/full(1)
2921 instr[29,24] = 00 1110
2926 instr[14] = TRN1 (0) / TRN2 (1)
2928 instr[9,5] = V source
2929 instr[4,0] = V dest. */
2931 int full
= INSTR (30, 30);
2932 int second
= INSTR (14, 14);
2933 unsigned vm
= INSTR (20, 16);
2934 unsigned vn
= INSTR (9, 5);
2935 unsigned vd
= INSTR (4, 0);
2938 NYI_assert (29, 24, 0x0E);
2939 NYI_assert (13, 10, 0xA);
2941 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2942 switch (INSTR (23, 22))
2945 for (i
= 0; i
< (full
? 8 : 4); i
++)
2949 aarch64_get_vec_u8 (cpu
, second
? vm
: vn
, i
* 2));
2951 (cpu
, vd
, 1 * 2 + 1,
2952 aarch64_get_vec_u8 (cpu
, second
? vn
: vm
, i
* 2 + 1));
2957 for (i
= 0; i
< (full
? 4 : 2); i
++)
2961 aarch64_get_vec_u16 (cpu
, second
? vm
: vn
, i
* 2));
2963 (cpu
, vd
, 1 * 2 + 1,
2964 aarch64_get_vec_u16 (cpu
, second
? vn
: vm
, i
* 2 + 1));
2970 (cpu
, vd
, 0, aarch64_get_vec_u32 (cpu
, second
? vm
: vn
, 0));
2972 (cpu
, vd
, 1, aarch64_get_vec_u32 (cpu
, second
? vn
: vm
, 1));
2974 (cpu
, vd
, 2, aarch64_get_vec_u32 (cpu
, second
? vm
: vn
, 2));
2976 (cpu
, vd
, 3, aarch64_get_vec_u32 (cpu
, second
? vn
: vm
, 3));
2983 aarch64_set_vec_u64 (cpu
, vd
, 0,
2984 aarch64_get_vec_u64 (cpu
, second
? vm
: vn
, 0));
2985 aarch64_set_vec_u64 (cpu
, vd
, 1,
2986 aarch64_get_vec_u64 (cpu
, second
? vn
: vm
, 1));
2992 do_vec_DUP_scalar_into_vector (sim_cpu
*cpu
)
2995 instr[30] = 0=> zero top 64-bits, 1=> duplicate into top 64-bits
2996 [must be 1 for 64-bit xfer]
2997 instr[29,20] = 00 1110 0000
2998 instr[19,16] = element size: 0001=> 8-bits, 0010=> 16-bits,
2999 0100=> 32-bits. 1000=>64-bits
3000 instr[15,10] = 0000 11
3001 instr[9,5] = W source
3002 instr[4,0] = V dest. */
3005 unsigned Vd
= INSTR (4, 0);
3006 unsigned Rs
= INSTR (9, 5);
3007 int both
= INSTR (30, 30);
3009 NYI_assert (29, 20, 0x0E0);
3010 NYI_assert (15, 10, 0x03);
3012 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3013 switch (INSTR (19, 16))
3016 for (i
= 0; i
< (both
? 16 : 8); i
++)
3017 aarch64_set_vec_u8 (cpu
, Vd
, i
, aarch64_get_reg_u8 (cpu
, Rs
, NO_SP
));
3021 for (i
= 0; i
< (both
? 8 : 4); i
++)
3022 aarch64_set_vec_u16 (cpu
, Vd
, i
, aarch64_get_reg_u16 (cpu
, Rs
, NO_SP
));
3026 for (i
= 0; i
< (both
? 4 : 2); i
++)
3027 aarch64_set_vec_u32 (cpu
, Vd
, i
, aarch64_get_reg_u32 (cpu
, Rs
, NO_SP
));
3033 aarch64_set_vec_u64 (cpu
, Vd
, 0, aarch64_get_reg_u64 (cpu
, Rs
, NO_SP
));
3034 aarch64_set_vec_u64 (cpu
, Vd
, 1, aarch64_get_reg_u64 (cpu
, Rs
, NO_SP
));
3043 do_vec_UZP (sim_cpu
*cpu
)
3046 instr[30] = half(0)/full(1)
3047 instr[29,24] = 00 1110
3048 instr[23,22] = size: byte(00), half(01), word (10), long (11)
3052 instr[14] = lower (0) / upper (1)
3057 int full
= INSTR (30, 30);
3058 int upper
= INSTR (14, 14);
3060 unsigned vm
= INSTR (20, 16);
3061 unsigned vn
= INSTR (9, 5);
3062 unsigned vd
= INSTR (4, 0);
3064 uint64_t val_m1
= aarch64_get_vec_u64 (cpu
, vm
, 0);
3065 uint64_t val_m2
= aarch64_get_vec_u64 (cpu
, vm
, 1);
3066 uint64_t val_n1
= aarch64_get_vec_u64 (cpu
, vn
, 0);
3067 uint64_t val_n2
= aarch64_get_vec_u64 (cpu
, vn
, 1);
3072 uint64_t input2
= full
? val_n2
: val_m1
;
3074 NYI_assert (29, 24, 0x0E);
3075 NYI_assert (21, 21, 0);
3076 NYI_assert (15, 15, 0);
3077 NYI_assert (13, 10, 6);
3079 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3080 switch (INSTR (23, 22))
3083 val1
= (val_n1
>> (upper
* 8)) & 0xFFULL
;
3084 val1
|= (val_n1
>> ((upper
* 8) + 8)) & 0xFF00ULL
;
3085 val1
|= (val_n1
>> ((upper
* 8) + 16)) & 0xFF0000ULL
;
3086 val1
|= (val_n1
>> ((upper
* 8) + 24)) & 0xFF000000ULL
;
3088 val1
|= (input2
<< (32 - (upper
* 8))) & 0xFF00000000ULL
;
3089 val1
|= (input2
<< (24 - (upper
* 8))) & 0xFF0000000000ULL
;
3090 val1
|= (input2
<< (16 - (upper
* 8))) & 0xFF000000000000ULL
;
3091 val1
|= (input2
<< (8 - (upper
* 8))) & 0xFF00000000000000ULL
;
3095 val2
= (val_m1
>> (upper
* 8)) & 0xFFULL
;
3096 val2
|= (val_m1
>> ((upper
* 8) + 8)) & 0xFF00ULL
;
3097 val2
|= (val_m1
>> ((upper
* 8) + 16)) & 0xFF0000ULL
;
3098 val2
|= (val_m1
>> ((upper
* 8) + 24)) & 0xFF000000ULL
;
3100 val2
|= (val_m2
<< (32 - (upper
* 8))) & 0xFF00000000ULL
;
3101 val2
|= (val_m2
<< (24 - (upper
* 8))) & 0xFF0000000000ULL
;
3102 val2
|= (val_m2
<< (16 - (upper
* 8))) & 0xFF000000000000ULL
;
3103 val2
|= (val_m2
<< (8 - (upper
* 8))) & 0xFF00000000000000ULL
;
3108 val1
= (val_n1
>> (upper
* 16)) & 0xFFFFULL
;
3109 val1
|= (val_n1
>> ((upper
* 16) + 16)) & 0xFFFF0000ULL
;
3111 val1
|= (input2
<< (32 - (upper
* 16))) & 0xFFFF00000000ULL
;;
3112 val1
|= (input2
<< (16 - (upper
* 16))) & 0xFFFF000000000000ULL
;
3116 val2
= (val_m1
>> (upper
* 16)) & 0xFFFFULL
;
3117 val2
|= (val_m1
>> ((upper
* 16) + 16)) & 0xFFFF0000ULL
;
3119 val2
|= (val_m2
<< (32 - (upper
* 16))) & 0xFFFF00000000ULL
;
3120 val2
|= (val_m2
<< (16 - (upper
* 16))) & 0xFFFF000000000000ULL
;
3125 val1
= (val_n1
>> (upper
* 32)) & 0xFFFFFFFF;
3126 val1
|= (input2
<< (32 - (upper
* 32))) & 0xFFFFFFFF00000000ULL
;
3130 val2
= (val_m1
>> (upper
* 32)) & 0xFFFFFFFF;
3131 val2
|= (val_m2
<< (32 - (upper
* 32))) & 0xFFFFFFFF00000000ULL
;
3139 val1
= upper
? val_n2
: val_n1
;
3140 val2
= upper
? val_m2
: val_m1
;
3144 aarch64_set_vec_u64 (cpu
, vd
, 0, val1
);
3146 aarch64_set_vec_u64 (cpu
, vd
, 1, val2
);
3150 do_vec_ZIP (sim_cpu
*cpu
)
3153 instr[30] = half(0)/full(1)
3154 instr[29,24] = 00 1110
3155 instr[23,22] = size: byte(00), hald(01), word (10), long (11)
3159 instr[14] = lower (0) / upper (1)
3164 int full
= INSTR (30, 30);
3165 int upper
= INSTR (14, 14);
3167 unsigned vm
= INSTR (20, 16);
3168 unsigned vn
= INSTR (9, 5);
3169 unsigned vd
= INSTR (4, 0);
3171 uint64_t val_m1
= aarch64_get_vec_u64 (cpu
, vm
, 0);
3172 uint64_t val_m2
= aarch64_get_vec_u64 (cpu
, vm
, 1);
3173 uint64_t val_n1
= aarch64_get_vec_u64 (cpu
, vn
, 0);
3174 uint64_t val_n2
= aarch64_get_vec_u64 (cpu
, vn
, 1);
3179 uint64_t input1
= upper
? val_n1
: val_m1
;
3180 uint64_t input2
= upper
? val_n2
: val_m2
;
3182 NYI_assert (29, 24, 0x0E);
3183 NYI_assert (21, 21, 0);
3184 NYI_assert (15, 15, 0);
3185 NYI_assert (13, 10, 0xE);
3187 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3188 switch (INSTR (23, 23))
3192 ((input1
<< 0) & (0xFF << 0))
3193 | ((input2
<< 8) & (0xFF << 8))
3194 | ((input1
<< 8) & (0xFF << 16))
3195 | ((input2
<< 16) & (0xFF << 24))
3196 | ((input1
<< 16) & (0xFFULL
<< 32))
3197 | ((input2
<< 24) & (0xFFULL
<< 40))
3198 | ((input1
<< 24) & (0xFFULL
<< 48))
3199 | ((input2
<< 32) & (0xFFULL
<< 56));
3202 ((input1
>> 32) & (0xFF << 0))
3203 | ((input2
>> 24) & (0xFF << 8))
3204 | ((input1
>> 24) & (0xFF << 16))
3205 | ((input2
>> 16) & (0xFF << 24))
3206 | ((input1
>> 16) & (0xFFULL
<< 32))
3207 | ((input2
>> 8) & (0xFFULL
<< 40))
3208 | ((input1
>> 8) & (0xFFULL
<< 48))
3209 | ((input2
>> 0) & (0xFFULL
<< 56));
3214 ((input1
<< 0) & (0xFFFF << 0))
3215 | ((input2
<< 16) & (0xFFFF << 16))
3216 | ((input1
<< 16) & (0xFFFFULL
<< 32))
3217 | ((input2
<< 32) & (0xFFFFULL
<< 48));
3220 ((input1
>> 32) & (0xFFFF << 0))
3221 | ((input2
>> 16) & (0xFFFF << 16))
3222 | ((input1
>> 16) & (0xFFFFULL
<< 32))
3223 | ((input2
>> 0) & (0xFFFFULL
<< 48));
3227 val1
= (input1
& 0xFFFFFFFFULL
) | (input2
<< 32);
3228 val2
= (input2
& 0xFFFFFFFFULL
) | (input1
<< 32);
3237 aarch64_set_vec_u64 (cpu
, vd
, 0, val1
);
3239 aarch64_set_vec_u64 (cpu
, vd
, 1, val2
);
3242 /* Floating point immediates are encoded in 8 bits.
3243 fpimm[7] = sign bit.
3244 fpimm[6:4] = signed exponent.
3245 fpimm[3:0] = fraction (assuming leading 1).
3246 i.e. F = s * 1.f * 2^(e - b). */
3249 fp_immediate_for_encoding_32 (uint32_t imm8
)
3252 uint32_t s
, e
, f
, i
;
3254 s
= (imm8
>> 7) & 0x1;
3255 e
= (imm8
>> 4) & 0x7;
3258 /* The fp value is s * n/16 * 2r where n is 16+e. */
3259 u
= (16.0 + f
) / 16.0;
3261 /* N.B. exponent is signed. */
3266 for (i
= 0; i
<= epos
; i
++)
3273 for (i
= 0; i
< eneg
; i
++)
3284 fp_immediate_for_encoding_64 (uint32_t imm8
)
3287 uint32_t s
, e
, f
, i
;
3289 s
= (imm8
>> 7) & 0x1;
3290 e
= (imm8
>> 4) & 0x7;
3293 /* The fp value is s * n/16 * 2r where n is 16+e. */
3294 u
= (16.0 + f
) / 16.0;
3296 /* N.B. exponent is signed. */
3301 for (i
= 0; i
<= epos
; i
++)
3308 for (i
= 0; i
< eneg
; i
++)
3319 do_vec_MOV_immediate (sim_cpu
*cpu
)
3322 instr[30] = full/half selector
3323 instr[29,19] = 00111100000
3324 instr[18,16] = high 3 bits of uimm8
3325 instr[15,12] = size & shift:
3327 0010 => 32-bit + LSL#8
3328 0100 => 32-bit + LSL#16
3329 0110 => 32-bit + LSL#24
3330 1010 => 16-bit + LSL#8
3332 1101 => 32-bit + MSL#16
3333 1100 => 32-bit + MSL#8
3337 instr[9,5] = low 5-bits of uimm8
3340 int full
= INSTR (30, 30);
3341 unsigned vd
= INSTR (4, 0);
3342 unsigned val
= (INSTR (18, 16) << 5) | INSTR (9, 5);
3345 NYI_assert (29, 19, 0x1E0);
3346 NYI_assert (11, 10, 1);
3348 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3349 switch (INSTR (15, 12))
3351 case 0x0: /* 32-bit, no shift. */
3352 case 0x2: /* 32-bit, shift by 8. */
3353 case 0x4: /* 32-bit, shift by 16. */
3354 case 0x6: /* 32-bit, shift by 24. */
3355 val
<<= (8 * INSTR (14, 13));
3356 for (i
= 0; i
< (full
? 4 : 2); i
++)
3357 aarch64_set_vec_u32 (cpu
, vd
, i
, val
);
3360 case 0xa: /* 16-bit, shift by 8. */
3363 case 0x8: /* 16-bit, no shift. */
3364 for (i
= 0; i
< (full
? 8 : 4); i
++)
3365 aarch64_set_vec_u16 (cpu
, vd
, i
, val
);
3368 case 0xd: /* 32-bit, mask shift by 16. */
3372 case 0xc: /* 32-bit, mask shift by 8. */
3375 for (i
= 0; i
< (full
? 4 : 2); i
++)
3376 aarch64_set_vec_u32 (cpu
, vd
, i
, val
);
3379 case 0xe: /* 8-bit, no shift. */
3380 for (i
= 0; i
< (full
? 16 : 8); i
++)
3381 aarch64_set_vec_u8 (cpu
, vd
, i
, val
);
3384 case 0xf: /* FMOV Vs.{2|4}S, #fpimm. */
3386 float u
= fp_immediate_for_encoding_32 (val
);
3387 for (i
= 0; i
< (full
? 4 : 2); i
++)
3388 aarch64_set_vec_float (cpu
, vd
, i
, u
);
3398 do_vec_MVNI (sim_cpu
*cpu
)
3401 instr[30] = full/half selector
3402 instr[29,19] = 10111100000
3403 instr[18,16] = high 3 bits of uimm8
3404 instr[15,12] = selector
3406 instr[9,5] = low 5-bits of uimm8
3409 int full
= INSTR (30, 30);
3410 unsigned vd
= INSTR (4, 0);
3411 unsigned val
= (INSTR (18, 16) << 5) | INSTR (9, 5);
3414 NYI_assert (29, 19, 0x5E0);
3415 NYI_assert (11, 10, 1);
3417 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3418 switch (INSTR (15, 12))
3420 case 0x0: /* 32-bit, no shift. */
3421 case 0x2: /* 32-bit, shift by 8. */
3422 case 0x4: /* 32-bit, shift by 16. */
3423 case 0x6: /* 32-bit, shift by 24. */
3424 val
<<= (8 * INSTR (14, 13));
3426 for (i
= 0; i
< (full
? 4 : 2); i
++)
3427 aarch64_set_vec_u32 (cpu
, vd
, i
, val
);
3430 case 0xa: /* 16-bit, 8 bit shift. */
3432 case 0x8: /* 16-bit, no shift. */
3434 for (i
= 0; i
< (full
? 8 : 4); i
++)
3435 aarch64_set_vec_u16 (cpu
, vd
, i
, val
);
3438 case 0xd: /* 32-bit, mask shift by 16. */
3441 case 0xc: /* 32-bit, mask shift by 8. */
3445 for (i
= 0; i
< (full
? 4 : 2); i
++)
3446 aarch64_set_vec_u32 (cpu
, vd
, i
, val
);
3449 case 0xE: /* MOVI Dn, #mask64 */
3453 for (i
= 0; i
< 8; i
++)
3455 mask
|= (0xFFUL
<< (i
* 8));
3456 aarch64_set_vec_u64 (cpu
, vd
, 0, mask
);
3457 aarch64_set_vec_u64 (cpu
, vd
, 1, mask
);
3461 case 0xf: /* FMOV Vd.2D, #fpimm. */
3463 double u
= fp_immediate_for_encoding_64 (val
);
3468 aarch64_set_vec_double (cpu
, vd
, 0, u
);
3469 aarch64_set_vec_double (cpu
, vd
, 1, u
);
3478 #define ABS(A) ((A) < 0 ? - (A) : (A))
3481 do_vec_ABS (sim_cpu
*cpu
)
3484 instr[30] = half(0)/full(1)
3485 instr[29,24] = 00 1110
3486 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3487 instr[21,10] = 10 0000 1011 10
3491 unsigned vn
= INSTR (9, 5);
3492 unsigned vd
= INSTR (4, 0);
3493 unsigned full
= INSTR (30, 30);
3496 NYI_assert (29, 24, 0x0E);
3497 NYI_assert (21, 10, 0x82E);
3499 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3500 switch (INSTR (23, 22))
3503 for (i
= 0; i
< (full
? 16 : 8); i
++)
3504 aarch64_set_vec_s8 (cpu
, vd
, i
,
3505 ABS (aarch64_get_vec_s8 (cpu
, vn
, i
)));
3509 for (i
= 0; i
< (full
? 8 : 4); i
++)
3510 aarch64_set_vec_s16 (cpu
, vd
, i
,
3511 ABS (aarch64_get_vec_s16 (cpu
, vn
, i
)));
3515 for (i
= 0; i
< (full
? 4 : 2); i
++)
3516 aarch64_set_vec_s32 (cpu
, vd
, i
,
3517 ABS (aarch64_get_vec_s32 (cpu
, vn
, i
)));
3523 for (i
= 0; i
< 2; i
++)
3524 aarch64_set_vec_s64 (cpu
, vd
, i
,
3525 ABS (aarch64_get_vec_s64 (cpu
, vn
, i
)));
3531 do_vec_ADDV (sim_cpu
*cpu
)
3534 instr[30] = full/half selector
3535 instr[29,24] = 00 1110
3536 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3537 instr[21,10] = 11 0001 1011 10
3541 unsigned vm
= INSTR (9, 5);
3542 unsigned rd
= INSTR (4, 0);
3544 int full
= INSTR (30, 30);
3546 NYI_assert (29, 24, 0x0E);
3547 NYI_assert (21, 10, 0xC6E);
3549 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3550 switch (INSTR (23, 22))
3555 for (i
= 0; i
< (full
? 16 : 8); i
++)
3556 val
+= aarch64_get_vec_u8 (cpu
, vm
, i
);
3557 aarch64_set_vec_u64 (cpu
, rd
, 0, val
);
3564 for (i
= 0; i
< (full
? 8 : 4); i
++)
3565 val
+= aarch64_get_vec_u16 (cpu
, vm
, i
);
3566 aarch64_set_vec_u64 (cpu
, rd
, 0, val
);
3575 for (i
= 0; i
< 4; i
++)
3576 val
+= aarch64_get_vec_u32 (cpu
, vm
, i
);
3577 aarch64_set_vec_u64 (cpu
, rd
, 0, val
);
3587 do_vec_ins_2 (sim_cpu
*cpu
)
3589 /* instr[31,21] = 01001110000
3590 instr[20,18] = size & element selector
3592 instr[13] = direction: to vec(0), from vec (1)
3598 unsigned vm
= INSTR (9, 5);
3599 unsigned vd
= INSTR (4, 0);
3601 NYI_assert (31, 21, 0x270);
3602 NYI_assert (17, 14, 0);
3603 NYI_assert (12, 10, 7);
3605 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3606 if (INSTR (13, 13) == 1)
3608 if (INSTR (18, 18) == 1)
3611 elem
= INSTR (20, 19);
3612 aarch64_set_reg_u64 (cpu
, vd
, NO_SP
,
3613 aarch64_get_vec_u32 (cpu
, vm
, elem
));
3618 if (INSTR (19, 19) != 1)
3621 elem
= INSTR (20, 20);
3622 aarch64_set_reg_u64 (cpu
, vd
, NO_SP
,
3623 aarch64_get_vec_u64 (cpu
, vm
, elem
));
3628 if (INSTR (18, 18) == 1)
3631 elem
= INSTR (20, 19);
3632 aarch64_set_vec_u32 (cpu
, vd
, elem
,
3633 aarch64_get_reg_u32 (cpu
, vm
, NO_SP
));
3638 if (INSTR (19, 19) != 1)
3641 elem
= INSTR (20, 20);
3642 aarch64_set_vec_u64 (cpu
, vd
, elem
,
3643 aarch64_get_reg_u64 (cpu
, vm
, NO_SP
));
3648 #define DO_VEC_WIDENING_MUL(N, DST_TYPE, READ_TYPE, WRITE_TYPE) \
3651 DST_TYPE a[N], b[N]; \
3653 for (i = 0; i < (N); i++) \
3655 a[i] = aarch64_get_vec_##READ_TYPE (cpu, vn, i + bias); \
3656 b[i] = aarch64_get_vec_##READ_TYPE (cpu, vm, i + bias); \
3658 for (i = 0; i < (N); i++) \
3659 aarch64_set_vec_##WRITE_TYPE (cpu, vd, i, a[i] * b[i]); \
3664 do_vec_mull (sim_cpu
*cpu
)
3667 instr[30] = lower(0)/upper(1) selector
3668 instr[29] = signed(0)/unsigned(1)
3669 instr[28,24] = 0 1110
3670 instr[23,22] = size: 8-bit (00), 16-bit (01), 32-bit (10)
3673 instr[15,10] = 11 0000
3677 int unsign
= INSTR (29, 29);
3678 int bias
= INSTR (30, 30);
3679 unsigned vm
= INSTR (20, 16);
3680 unsigned vn
= INSTR ( 9, 5);
3681 unsigned vd
= INSTR ( 4, 0);
3684 NYI_assert (28, 24, 0x0E);
3685 NYI_assert (15, 10, 0x30);
3687 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3688 /* NB: Read source values before writing results, in case
3689 the source and destination vectors are the same. */
3690 switch (INSTR (23, 22))
3696 DO_VEC_WIDENING_MUL (8, uint16_t, u8
, u16
);
3698 DO_VEC_WIDENING_MUL (8, int16_t, s8
, s16
);
3705 DO_VEC_WIDENING_MUL (4, uint32_t, u16
, u32
);
3707 DO_VEC_WIDENING_MUL (4, int32_t, s16
, s32
);
3714 DO_VEC_WIDENING_MUL (2, uint64_t, u32
, u64
);
3716 DO_VEC_WIDENING_MUL (2, int64_t, s32
, s64
);
3725 do_vec_fadd (sim_cpu
*cpu
)
3728 instr[30] = half(0)/full(1)
3729 instr[29,24] = 001110
3730 instr[23] = FADD(0)/FSUB(1)
3731 instr[22] = float (0)/double(1)
3734 instr[15,10] = 110101
3738 unsigned vm
= INSTR (20, 16);
3739 unsigned vn
= INSTR (9, 5);
3740 unsigned vd
= INSTR (4, 0);
3742 int full
= INSTR (30, 30);
3744 NYI_assert (29, 24, 0x0E);
3745 NYI_assert (21, 21, 1);
3746 NYI_assert (15, 10, 0x35);
3748 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3756 for (i
= 0; i
< 2; i
++)
3757 aarch64_set_vec_double (cpu
, vd
, i
,
3758 aarch64_get_vec_double (cpu
, vn
, i
)
3759 - aarch64_get_vec_double (cpu
, vm
, i
));
3763 for (i
= 0; i
< (full
? 4 : 2); i
++)
3764 aarch64_set_vec_float (cpu
, vd
, i
,
3765 aarch64_get_vec_float (cpu
, vn
, i
)
3766 - aarch64_get_vec_float (cpu
, vm
, i
));
3776 for (i
= 0; i
< 2; i
++)
3777 aarch64_set_vec_double (cpu
, vd
, i
,
3778 aarch64_get_vec_double (cpu
, vm
, i
)
3779 + aarch64_get_vec_double (cpu
, vn
, i
));
3783 for (i
= 0; i
< (full
? 4 : 2); i
++)
3784 aarch64_set_vec_float (cpu
, vd
, i
,
3785 aarch64_get_vec_float (cpu
, vm
, i
)
3786 + aarch64_get_vec_float (cpu
, vn
, i
));
3792 do_vec_add (sim_cpu
*cpu
)
3795 instr[30] = full/half selector
3796 instr[29,24] = 001110
3797 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3800 instr[15,10] = 100001
3804 unsigned vm
= INSTR (20, 16);
3805 unsigned vn
= INSTR (9, 5);
3806 unsigned vd
= INSTR (4, 0);
3808 int full
= INSTR (30, 30);
3810 NYI_assert (29, 24, 0x0E);
3811 NYI_assert (21, 21, 1);
3812 NYI_assert (15, 10, 0x21);
3814 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3815 switch (INSTR (23, 22))
3818 for (i
= 0; i
< (full
? 16 : 8); i
++)
3819 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vn
, i
)
3820 + aarch64_get_vec_u8 (cpu
, vm
, i
));
3824 for (i
= 0; i
< (full
? 8 : 4); i
++)
3825 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vn
, i
)
3826 + aarch64_get_vec_u16 (cpu
, vm
, i
));
3830 for (i
= 0; i
< (full
? 4 : 2); i
++)
3831 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vn
, i
)
3832 + aarch64_get_vec_u32 (cpu
, vm
, i
));
3838 aarch64_set_vec_u64 (cpu
, vd
, 0, aarch64_get_vec_u64 (cpu
, vn
, 0)
3839 + aarch64_get_vec_u64 (cpu
, vm
, 0));
3840 aarch64_set_vec_u64 (cpu
, vd
, 1,
3841 aarch64_get_vec_u64 (cpu
, vn
, 1)
3842 + aarch64_get_vec_u64 (cpu
, vm
, 1));
3848 do_vec_mul (sim_cpu
*cpu
)
3851 instr[30] = full/half selector
3852 instr[29,24] = 00 1110
3853 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3856 instr[15,10] = 10 0111
3860 unsigned vm
= INSTR (20, 16);
3861 unsigned vn
= INSTR (9, 5);
3862 unsigned vd
= INSTR (4, 0);
3864 int full
= INSTR (30, 30);
3867 NYI_assert (29, 24, 0x0E);
3868 NYI_assert (21, 21, 1);
3869 NYI_assert (15, 10, 0x27);
3871 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3872 switch (INSTR (23, 22))
3875 DO_VEC_WIDENING_MUL (full
? 16 : 8, uint8_t, u8
, u8
);
3879 DO_VEC_WIDENING_MUL (full
? 8 : 4, uint16_t, u16
, u16
);
3883 DO_VEC_WIDENING_MUL (full
? 4 : 2, uint32_t, u32
, u32
);
3892 do_vec_MLA (sim_cpu
*cpu
)
3895 instr[30] = full/half selector
3896 instr[29,24] = 00 1110
3897 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3900 instr[15,10] = 1001 01
3904 unsigned vm
= INSTR (20, 16);
3905 unsigned vn
= INSTR (9, 5);
3906 unsigned vd
= INSTR (4, 0);
3908 int full
= INSTR (30, 30);
3910 NYI_assert (29, 24, 0x0E);
3911 NYI_assert (21, 21, 1);
3912 NYI_assert (15, 10, 0x25);
3914 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3915 switch (INSTR (23, 22))
3918 for (i
= 0; i
< (full
? 16 : 8); i
++)
3919 aarch64_set_vec_u8 (cpu
, vd
, i
,
3920 aarch64_get_vec_u8 (cpu
, vd
, i
)
3921 + (aarch64_get_vec_u8 (cpu
, vn
, i
)
3922 * aarch64_get_vec_u8 (cpu
, vm
, i
)));
3926 for (i
= 0; i
< (full
? 8 : 4); i
++)
3927 aarch64_set_vec_u16 (cpu
, vd
, i
,
3928 aarch64_get_vec_u16 (cpu
, vd
, i
)
3929 + (aarch64_get_vec_u16 (cpu
, vn
, i
)
3930 * aarch64_get_vec_u16 (cpu
, vm
, i
)));
3934 for (i
= 0; i
< (full
? 4 : 2); i
++)
3935 aarch64_set_vec_u32 (cpu
, vd
, i
,
3936 aarch64_get_vec_u32 (cpu
, vd
, i
)
3937 + (aarch64_get_vec_u32 (cpu
, vn
, i
)
3938 * aarch64_get_vec_u32 (cpu
, vm
, i
)));
3947 fmaxnm (float a
, float b
)
3952 return a
> b
? a
: b
;
3955 else if (! isnan (b
))
3961 fminnm (float a
, float b
)
3966 return a
< b
? a
: b
;
3969 else if (! isnan (b
))
3975 dmaxnm (double a
, double b
)
3980 return a
> b
? a
: b
;
3983 else if (! isnan (b
))
3989 dminnm (double a
, double b
)
3994 return a
< b
? a
: b
;
3997 else if (! isnan (b
))
4003 do_vec_FminmaxNMP (sim_cpu
*cpu
)
4006 instr [30] = half (0)/full (1)
4007 instr [29,24] = 10 1110
4008 instr [23] = max(0)/min(1)
4009 instr [22] = float (0)/double (1)
4012 instr [15,10] = 1100 01
4014 instr [4.0] = Vd. */
4016 unsigned vm
= INSTR (20, 16);
4017 unsigned vn
= INSTR (9, 5);
4018 unsigned vd
= INSTR (4, 0);
4019 int full
= INSTR (30, 30);
4021 NYI_assert (29, 24, 0x2E);
4022 NYI_assert (21, 21, 1);
4023 NYI_assert (15, 10, 0x31);
4025 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4028 double (* fn
)(double, double) = INSTR (23, 23)
4033 aarch64_set_vec_double (cpu
, vd
, 0,
4034 fn (aarch64_get_vec_double (cpu
, vn
, 0),
4035 aarch64_get_vec_double (cpu
, vn
, 1)));
4036 aarch64_set_vec_double (cpu
, vd
, 0,
4037 fn (aarch64_get_vec_double (cpu
, vm
, 0),
4038 aarch64_get_vec_double (cpu
, vm
, 1)));
4042 float (* fn
)(float, float) = INSTR (23, 23)
4045 aarch64_set_vec_float (cpu
, vd
, 0,
4046 fn (aarch64_get_vec_float (cpu
, vn
, 0),
4047 aarch64_get_vec_float (cpu
, vn
, 1)));
4049 aarch64_set_vec_float (cpu
, vd
, 1,
4050 fn (aarch64_get_vec_float (cpu
, vn
, 2),
4051 aarch64_get_vec_float (cpu
, vn
, 3)));
4053 aarch64_set_vec_float (cpu
, vd
, (full
? 2 : 1),
4054 fn (aarch64_get_vec_float (cpu
, vm
, 0),
4055 aarch64_get_vec_float (cpu
, vm
, 1)));
4057 aarch64_set_vec_float (cpu
, vd
, 3,
4058 fn (aarch64_get_vec_float (cpu
, vm
, 2),
4059 aarch64_get_vec_float (cpu
, vm
, 3)));
4064 do_vec_AND (sim_cpu
*cpu
)
4067 instr[30] = half (0)/full (1)
4068 instr[29,21] = 001110001
4070 instr[15,10] = 000111
4074 unsigned vm
= INSTR (20, 16);
4075 unsigned vn
= INSTR (9, 5);
4076 unsigned vd
= INSTR (4, 0);
4078 int full
= INSTR (30, 30);
4080 NYI_assert (29, 21, 0x071);
4081 NYI_assert (15, 10, 0x07);
4083 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4084 for (i
= 0; i
< (full
? 4 : 2); i
++)
4085 aarch64_set_vec_u32 (cpu
, vd
, i
,
4086 aarch64_get_vec_u32 (cpu
, vn
, i
)
4087 & aarch64_get_vec_u32 (cpu
, vm
, i
));
4091 do_vec_BSL (sim_cpu
*cpu
)
4094 instr[30] = half (0)/full (1)
4095 instr[29,21] = 101110011
4097 instr[15,10] = 000111
4101 unsigned vm
= INSTR (20, 16);
4102 unsigned vn
= INSTR (9, 5);
4103 unsigned vd
= INSTR (4, 0);
4105 int full
= INSTR (30, 30);
4107 NYI_assert (29, 21, 0x173);
4108 NYI_assert (15, 10, 0x07);
4110 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4111 for (i
= 0; i
< (full
? 16 : 8); i
++)
4112 aarch64_set_vec_u8 (cpu
, vd
, i
,
4113 ( aarch64_get_vec_u8 (cpu
, vd
, i
)
4114 & aarch64_get_vec_u8 (cpu
, vn
, i
))
4115 | ((~ aarch64_get_vec_u8 (cpu
, vd
, i
))
4116 & aarch64_get_vec_u8 (cpu
, vm
, i
)));
4120 do_vec_EOR (sim_cpu
*cpu
)
4123 instr[30] = half (0)/full (1)
4124 instr[29,21] = 10 1110 001
4126 instr[15,10] = 000111
4130 unsigned vm
= INSTR (20, 16);
4131 unsigned vn
= INSTR (9, 5);
4132 unsigned vd
= INSTR (4, 0);
4134 int full
= INSTR (30, 30);
4136 NYI_assert (29, 21, 0x171);
4137 NYI_assert (15, 10, 0x07);
4139 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4140 for (i
= 0; i
< (full
? 4 : 2); i
++)
4141 aarch64_set_vec_u32 (cpu
, vd
, i
,
4142 aarch64_get_vec_u32 (cpu
, vn
, i
)
4143 ^ aarch64_get_vec_u32 (cpu
, vm
, i
));
4147 do_vec_bit (sim_cpu
*cpu
)
4150 instr[30] = half (0)/full (1)
4151 instr[29,23] = 10 1110 1
4152 instr[22] = BIT (0) / BIF (1)
4155 instr[15,10] = 0001 11
4159 unsigned vm
= INSTR (20, 16);
4160 unsigned vn
= INSTR (9, 5);
4161 unsigned vd
= INSTR (4, 0);
4162 unsigned full
= INSTR (30, 30);
4163 unsigned test_false
= INSTR (22, 22);
4166 NYI_assert (29, 23, 0x5D);
4167 NYI_assert (21, 21, 1);
4168 NYI_assert (15, 10, 0x07);
4170 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4171 for (i
= 0; i
< (full
? 4 : 2); i
++)
4173 uint32_t vd_val
= aarch64_get_vec_u32 (cpu
, vd
, i
);
4174 uint32_t vn_val
= aarch64_get_vec_u32 (cpu
, vn
, i
);
4175 uint32_t vm_val
= aarch64_get_vec_u32 (cpu
, vm
, i
);
4177 aarch64_set_vec_u32 (cpu
, vd
, i
,
4178 (vd_val
& vm_val
) | (vn_val
& ~vm_val
));
4180 aarch64_set_vec_u32 (cpu
, vd
, i
,
4181 (vd_val
& ~vm_val
) | (vn_val
& vm_val
));
4186 do_vec_ORN (sim_cpu
*cpu
)
4189 instr[30] = half (0)/full (1)
4190 instr[29,21] = 00 1110 111
4192 instr[15,10] = 00 0111
4196 unsigned vm
= INSTR (20, 16);
4197 unsigned vn
= INSTR (9, 5);
4198 unsigned vd
= INSTR (4, 0);
4200 int full
= INSTR (30, 30);
4202 NYI_assert (29, 21, 0x077);
4203 NYI_assert (15, 10, 0x07);
4205 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4206 for (i
= 0; i
< (full
? 16 : 8); i
++)
4207 aarch64_set_vec_u8 (cpu
, vd
, i
,
4208 aarch64_get_vec_u8 (cpu
, vn
, i
)
4209 | ~ aarch64_get_vec_u8 (cpu
, vm
, i
));
4213 do_vec_ORR (sim_cpu
*cpu
)
4216 instr[30] = half (0)/full (1)
4217 instr[29,21] = 00 1110 101
4219 instr[15,10] = 0001 11
4223 unsigned vm
= INSTR (20, 16);
4224 unsigned vn
= INSTR (9, 5);
4225 unsigned vd
= INSTR (4, 0);
4227 int full
= INSTR (30, 30);
4229 NYI_assert (29, 21, 0x075);
4230 NYI_assert (15, 10, 0x07);
4232 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4233 for (i
= 0; i
< (full
? 16 : 8); i
++)
4234 aarch64_set_vec_u8 (cpu
, vd
, i
,
4235 aarch64_get_vec_u8 (cpu
, vn
, i
)
4236 | aarch64_get_vec_u8 (cpu
, vm
, i
));
4240 do_vec_BIC (sim_cpu
*cpu
)
4243 instr[30] = half (0)/full (1)
4244 instr[29,21] = 00 1110 011
4246 instr[15,10] = 00 0111
4250 unsigned vm
= INSTR (20, 16);
4251 unsigned vn
= INSTR (9, 5);
4252 unsigned vd
= INSTR (4, 0);
4254 int full
= INSTR (30, 30);
4256 NYI_assert (29, 21, 0x073);
4257 NYI_assert (15, 10, 0x07);
4259 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4260 for (i
= 0; i
< (full
? 16 : 8); i
++)
4261 aarch64_set_vec_u8 (cpu
, vd
, i
,
4262 aarch64_get_vec_u8 (cpu
, vn
, i
)
4263 & ~ aarch64_get_vec_u8 (cpu
, vm
, i
));
4267 do_vec_XTN (sim_cpu
*cpu
)
4270 instr[30] = first part (0)/ second part (1)
4271 instr[29,24] = 00 1110
4272 instr[23,22] = size: byte(00), half(01), word (10)
4273 instr[21,10] = 1000 0100 1010
4277 unsigned vs
= INSTR (9, 5);
4278 unsigned vd
= INSTR (4, 0);
4279 unsigned bias
= INSTR (30, 30);
4282 NYI_assert (29, 24, 0x0E);
4283 NYI_assert (21, 10, 0x84A);
4285 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4286 switch (INSTR (23, 22))
4289 for (i
= 0; i
< 8; i
++)
4290 aarch64_set_vec_u8 (cpu
, vd
, i
+ (bias
* 8),
4291 aarch64_get_vec_u16 (cpu
, vs
, i
));
4295 for (i
= 0; i
< 4; i
++)
4296 aarch64_set_vec_u16 (cpu
, vd
, i
+ (bias
* 4),
4297 aarch64_get_vec_u32 (cpu
, vs
, i
));
4301 for (i
= 0; i
< 2; i
++)
4302 aarch64_set_vec_u32 (cpu
, vd
, i
+ (bias
* 2),
4303 aarch64_get_vec_u64 (cpu
, vs
, i
));
4308 /* Return the number of bits set in the input value. */
4309 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
4310 # define popcount __builtin_popcount
4313 popcount (unsigned char x
)
4315 static const unsigned char popcnt
[16] =
4323 /* Only counts the low 8 bits of the input as that is all we need. */
4324 return popcnt
[x
% 16] + popcnt
[x
/ 16];
4329 do_vec_CNT (sim_cpu
*cpu
)
4332 instr[30] = half (0)/ full (1)
4333 instr[29,24] = 00 1110
4334 instr[23,22] = size: byte(00)
4335 instr[21,10] = 1000 0001 0110
4339 unsigned vs
= INSTR (9, 5);
4340 unsigned vd
= INSTR (4, 0);
4341 int full
= INSTR (30, 30);
4342 int size
= INSTR (23, 22);
4345 NYI_assert (29, 24, 0x0E);
4346 NYI_assert (21, 10, 0x816);
4351 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4353 for (i
= 0; i
< (full
? 16 : 8); i
++)
4354 aarch64_set_vec_u8 (cpu
, vd
, i
,
4355 popcount (aarch64_get_vec_u8 (cpu
, vs
, i
)));
4359 do_vec_maxv (sim_cpu
*cpu
)
4362 instr[30] = half(0)/full(1)
4363 instr[29] = signed (0)/unsigned(1)
4364 instr[28,24] = 0 1110
4365 instr[23,22] = size: byte(00), half(01), word (10)
4367 instr[20,17] = 1 000
4368 instr[16] = max(0)/min(1)
4369 instr[15,10] = 1010 10
4370 instr[9,5] = V source
4371 instr[4.0] = R dest. */
4373 unsigned vs
= INSTR (9, 5);
4374 unsigned rd
= INSTR (4, 0);
4375 unsigned full
= INSTR (30, 30);
4378 NYI_assert (28, 24, 0x0E);
4379 NYI_assert (21, 21, 1);
4380 NYI_assert (20, 17, 8);
4381 NYI_assert (15, 10, 0x2A);
4383 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4384 switch ((INSTR (29, 29) << 1) | INSTR (16, 16))
4386 case 0: /* SMAXV. */
4389 switch (INSTR (23, 22))
4392 smax
= aarch64_get_vec_s8 (cpu
, vs
, 0);
4393 for (i
= 1; i
< (full
? 16 : 8); i
++)
4394 smax
= max (smax
, aarch64_get_vec_s8 (cpu
, vs
, i
));
4397 smax
= aarch64_get_vec_s16 (cpu
, vs
, 0);
4398 for (i
= 1; i
< (full
? 8 : 4); i
++)
4399 smax
= max (smax
, aarch64_get_vec_s16 (cpu
, vs
, i
));
4402 smax
= aarch64_get_vec_s32 (cpu
, vs
, 0);
4403 for (i
= 1; i
< (full
? 4 : 2); i
++)
4404 smax
= max (smax
, aarch64_get_vec_s32 (cpu
, vs
, i
));
4409 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, smax
);
4413 case 1: /* SMINV. */
4416 switch (INSTR (23, 22))
4419 smin
= aarch64_get_vec_s8 (cpu
, vs
, 0);
4420 for (i
= 1; i
< (full
? 16 : 8); i
++)
4421 smin
= min (smin
, aarch64_get_vec_s8 (cpu
, vs
, i
));
4424 smin
= aarch64_get_vec_s16 (cpu
, vs
, 0);
4425 for (i
= 1; i
< (full
? 8 : 4); i
++)
4426 smin
= min (smin
, aarch64_get_vec_s16 (cpu
, vs
, i
));
4429 smin
= aarch64_get_vec_s32 (cpu
, vs
, 0);
4430 for (i
= 1; i
< (full
? 4 : 2); i
++)
4431 smin
= min (smin
, aarch64_get_vec_s32 (cpu
, vs
, i
));
4437 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, smin
);
4441 case 2: /* UMAXV. */
4444 switch (INSTR (23, 22))
4447 umax
= aarch64_get_vec_u8 (cpu
, vs
, 0);
4448 for (i
= 1; i
< (full
? 16 : 8); i
++)
4449 umax
= max (umax
, aarch64_get_vec_u8 (cpu
, vs
, i
));
4452 umax
= aarch64_get_vec_u16 (cpu
, vs
, 0);
4453 for (i
= 1; i
< (full
? 8 : 4); i
++)
4454 umax
= max (umax
, aarch64_get_vec_u16 (cpu
, vs
, i
));
4457 umax
= aarch64_get_vec_u32 (cpu
, vs
, 0);
4458 for (i
= 1; i
< (full
? 4 : 2); i
++)
4459 umax
= max (umax
, aarch64_get_vec_u32 (cpu
, vs
, i
));
4465 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, umax
);
4469 case 3: /* UMINV. */
4472 switch (INSTR (23, 22))
4475 umin
= aarch64_get_vec_u8 (cpu
, vs
, 0);
4476 for (i
= 1; i
< (full
? 16 : 8); i
++)
4477 umin
= min (umin
, aarch64_get_vec_u8 (cpu
, vs
, i
));
4480 umin
= aarch64_get_vec_u16 (cpu
, vs
, 0);
4481 for (i
= 1; i
< (full
? 8 : 4); i
++)
4482 umin
= min (umin
, aarch64_get_vec_u16 (cpu
, vs
, i
));
4485 umin
= aarch64_get_vec_u32 (cpu
, vs
, 0);
4486 for (i
= 1; i
< (full
? 4 : 2); i
++)
4487 umin
= min (umin
, aarch64_get_vec_u32 (cpu
, vs
, i
));
4493 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, umin
);
4500 do_vec_fminmaxV (sim_cpu
*cpu
)
4502 /* instr[31,24] = 0110 1110
4503 instr[23] = max(0)/min(1)
4504 instr[22,14] = 011 0000 11
4505 instr[13,12] = nm(00)/normal(11)
4507 instr[9,5] = V source
4508 instr[4.0] = R dest. */
4510 unsigned vs
= INSTR (9, 5);
4511 unsigned rd
= INSTR (4, 0);
4513 float res
= aarch64_get_vec_float (cpu
, vs
, 0);
4515 NYI_assert (31, 24, 0x6E);
4516 NYI_assert (22, 14, 0x0C3);
4517 NYI_assert (11, 10, 2);
4519 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4522 switch (INSTR (13, 12))
4524 case 0: /* FMNINNMV. */
4525 for (i
= 1; i
< 4; i
++)
4526 res
= fminnm (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4529 case 3: /* FMINV. */
4530 for (i
= 1; i
< 4; i
++)
4531 res
= min (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4540 switch (INSTR (13, 12))
4542 case 0: /* FMNAXNMV. */
4543 for (i
= 1; i
< 4; i
++)
4544 res
= fmaxnm (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4547 case 3: /* FMAXV. */
4548 for (i
= 1; i
< 4; i
++)
4549 res
= max (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4557 aarch64_set_FP_float (cpu
, rd
, res
);
4561 do_vec_Fminmax (sim_cpu
*cpu
)
4564 instr[30] = half(0)/full(1)
4565 instr[29,24] = 00 1110
4566 instr[23] = max(0)/min(1)
4567 instr[22] = float(0)/double(1)
4571 instr[13,12] = nm(00)/normal(11)
4576 unsigned vm
= INSTR (20, 16);
4577 unsigned vn
= INSTR (9, 5);
4578 unsigned vd
= INSTR (4, 0);
4579 unsigned full
= INSTR (30, 30);
4580 unsigned min
= INSTR (23, 23);
4583 NYI_assert (29, 24, 0x0E);
4584 NYI_assert (21, 21, 1);
4585 NYI_assert (15, 14, 3);
4586 NYI_assert (11, 10, 1);
4588 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4591 double (* func
)(double, double);
4596 if (INSTR (13, 12) == 0)
4597 func
= min
? dminnm
: dmaxnm
;
4598 else if (INSTR (13, 12) == 3)
4599 func
= min
? fmin
: fmax
;
4603 for (i
= 0; i
< 2; i
++)
4604 aarch64_set_vec_double (cpu
, vd
, i
,
4605 func (aarch64_get_vec_double (cpu
, vn
, i
),
4606 aarch64_get_vec_double (cpu
, vm
, i
)));
4610 float (* func
)(float, float);
4612 if (INSTR (13, 12) == 0)
4613 func
= min
? fminnm
: fmaxnm
;
4614 else if (INSTR (13, 12) == 3)
4615 func
= min
? fminf
: fmaxf
;
4619 for (i
= 0; i
< (full
? 4 : 2); i
++)
4620 aarch64_set_vec_float (cpu
, vd
, i
,
4621 func (aarch64_get_vec_float (cpu
, vn
, i
),
4622 aarch64_get_vec_float (cpu
, vm
, i
)));
4627 do_vec_SCVTF (sim_cpu
*cpu
)
4631 instr[29,23] = 00 1110 0
4632 instr[22] = float(0)/double(1)
4633 instr[21,10] = 10 0001 1101 10
4637 unsigned vn
= INSTR (9, 5);
4638 unsigned vd
= INSTR (4, 0);
4639 unsigned full
= INSTR (30, 30);
4640 unsigned size
= INSTR (22, 22);
4643 NYI_assert (29, 23, 0x1C);
4644 NYI_assert (21, 10, 0x876);
4646 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4652 for (i
= 0; i
< 2; i
++)
4654 double val
= (double) aarch64_get_vec_u64 (cpu
, vn
, i
);
4655 aarch64_set_vec_double (cpu
, vd
, i
, val
);
4660 for (i
= 0; i
< (full
? 4 : 2); i
++)
4662 float val
= (float) aarch64_get_vec_u32 (cpu
, vn
, i
);
4663 aarch64_set_vec_float (cpu
, vd
, i
, val
);
4668 #define VEC_CMP(SOURCE, CMP) \
4674 for (i = 0; i < (full ? 16 : 8); i++) \
4675 aarch64_set_vec_u8 (cpu, vd, i, \
4676 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4678 aarch64_get_vec_##SOURCE##8 (cpu, vm, i) \
4682 for (i = 0; i < (full ? 8 : 4); i++) \
4683 aarch64_set_vec_u16 (cpu, vd, i, \
4684 aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4686 aarch64_get_vec_##SOURCE##16 (cpu, vm, i) \
4690 for (i = 0; i < (full ? 4 : 2); i++) \
4691 aarch64_set_vec_u32 (cpu, vd, i, \
4692 aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4694 aarch64_get_vec_##SOURCE##32 (cpu, vm, i) \
4700 for (i = 0; i < 2; i++) \
4701 aarch64_set_vec_u64 (cpu, vd, i, \
4702 aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4704 aarch64_get_vec_##SOURCE##64 (cpu, vm, i) \
4711 #define VEC_CMP0(SOURCE, CMP) \
4717 for (i = 0; i < (full ? 16 : 8); i++) \
4718 aarch64_set_vec_u8 (cpu, vd, i, \
4719 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4723 for (i = 0; i < (full ? 8 : 4); i++) \
4724 aarch64_set_vec_u16 (cpu, vd, i, \
4725 aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4729 for (i = 0; i < (full ? 4 : 2); i++) \
4730 aarch64_set_vec_u32 (cpu, vd, i, \
4731 aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4737 for (i = 0; i < 2; i++) \
4738 aarch64_set_vec_u64 (cpu, vd, i, \
4739 aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4740 CMP 0 ? -1ULL : 0); \
4746 #define VEC_FCMP0(CMP) \
4751 if (INSTR (22, 22)) \
4755 for (i = 0; i < 2; i++) \
4756 aarch64_set_vec_u64 (cpu, vd, i, \
4757 aarch64_get_vec_double (cpu, vn, i) \
4758 CMP 0.0 ? -1 : 0); \
4762 for (i = 0; i < (full ? 4 : 2); i++) \
4763 aarch64_set_vec_u32 (cpu, vd, i, \
4764 aarch64_get_vec_float (cpu, vn, i) \
4765 CMP 0.0 ? -1 : 0); \
4771 #define VEC_FCMP(CMP) \
4774 if (INSTR (22, 22)) \
4778 for (i = 0; i < 2; i++) \
4779 aarch64_set_vec_u64 (cpu, vd, i, \
4780 aarch64_get_vec_double (cpu, vn, i) \
4782 aarch64_get_vec_double (cpu, vm, i) \
4787 for (i = 0; i < (full ? 4 : 2); i++) \
4788 aarch64_set_vec_u32 (cpu, vd, i, \
4789 aarch64_get_vec_float (cpu, vn, i) \
4791 aarch64_get_vec_float (cpu, vm, i) \
4799 do_vec_compare (sim_cpu
*cpu
)
4802 instr[30] = half(0)/full(1)
4803 instr[29] = part-of-comparison-type
4804 instr[28,24] = 0 1110
4805 instr[23,22] = size of integer compares: byte(00), half(01), word (10), long (11)
4806 type of float compares: single (-0) / double (-1)
4808 instr[20,16] = Vm or 00000 (compare vs 0)
4809 instr[15,10] = part-of-comparison-type
4813 int full
= INSTR (30, 30);
4814 int size
= INSTR (23, 22);
4815 unsigned vm
= INSTR (20, 16);
4816 unsigned vn
= INSTR (9, 5);
4817 unsigned vd
= INSTR (4, 0);
4820 NYI_assert (28, 24, 0x0E);
4821 NYI_assert (21, 21, 1);
4823 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4826 || ((INSTR (11, 11) == 0
4827 && INSTR (10, 10) == 0)))
4829 /* A compare vs 0. */
4832 if (INSTR (15, 10) == 0x2A)
4834 else if (INSTR (15, 10) == 0x32
4835 || INSTR (15, 10) == 0x3E)
4836 do_vec_fminmaxV (cpu
);
4837 else if (INSTR (29, 23) == 0x1C
4838 && INSTR (21, 10) == 0x876)
4848 /* A floating point compare. */
4849 unsigned decode
= (INSTR (29, 29) << 5) | (INSTR (23, 23) << 4)
4852 NYI_assert (15, 15, 1);
4856 case /* 0b010010: GT#0 */ 0x12: VEC_FCMP0 (>);
4857 case /* 0b110010: GE#0 */ 0x32: VEC_FCMP0 (>=);
4858 case /* 0b010110: EQ#0 */ 0x16: VEC_FCMP0 (==);
4859 case /* 0b110110: LE#0 */ 0x36: VEC_FCMP0 (<=);
4860 case /* 0b011010: LT#0 */ 0x1A: VEC_FCMP0 (<);
4861 case /* 0b111001: GT */ 0x39: VEC_FCMP (>);
4862 case /* 0b101001: GE */ 0x29: VEC_FCMP (>=);
4863 case /* 0b001001: EQ */ 0x09: VEC_FCMP (==);
4871 unsigned decode
= (INSTR (29, 29) << 6) | INSTR (15, 10);
4875 case 0x0D: /* 0001101 GT */ VEC_CMP (s
, > );
4876 case 0x0F: /* 0001111 GE */ VEC_CMP (s
, >= );
4877 case 0x22: /* 0100010 GT #0 */ VEC_CMP0 (s
, > );
4878 case 0x23: /* 0100011 TST */ VEC_CMP (u
, & );
4879 case 0x26: /* 0100110 EQ #0 */ VEC_CMP0 (s
, == );
4880 case 0x2A: /* 0101010 LT #0 */ VEC_CMP0 (s
, < );
4881 case 0x4D: /* 1001101 HI */ VEC_CMP (u
, > );
4882 case 0x4F: /* 1001111 HS */ VEC_CMP (u
, >= );
4883 case 0x62: /* 1100010 GE #0 */ VEC_CMP0 (s
, >= );
4884 case 0x63: /* 1100011 EQ */ VEC_CMP (u
, == );
4885 case 0x66: /* 1100110 LE #0 */ VEC_CMP0 (s
, <= );
4895 do_vec_SSHL (sim_cpu
*cpu
)
4898 instr[30] = first part (0)/ second part (1)
4899 instr[29,24] = 00 1110
4900 instr[23,22] = size: byte(00), half(01), word (10), long (11)
4903 instr[15,10] = 0100 01
4907 unsigned full
= INSTR (30, 30);
4908 unsigned vm
= INSTR (20, 16);
4909 unsigned vn
= INSTR (9, 5);
4910 unsigned vd
= INSTR (4, 0);
4914 NYI_assert (29, 24, 0x0E);
4915 NYI_assert (21, 21, 1);
4916 NYI_assert (15, 10, 0x11);
4918 /* FIXME: What is a signed shift left in this context ?. */
4920 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4921 switch (INSTR (23, 22))
4924 for (i
= 0; i
< (full
? 16 : 8); i
++)
4926 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
);
4928 aarch64_set_vec_s8 (cpu
, vd
, i
, aarch64_get_vec_s8 (cpu
, vn
, i
)
4931 aarch64_set_vec_s8 (cpu
, vd
, i
, aarch64_get_vec_s8 (cpu
, vn
, i
)
4937 for (i
= 0; i
< (full
? 8 : 4); i
++)
4939 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 2);
4941 aarch64_set_vec_s16 (cpu
, vd
, i
, aarch64_get_vec_s16 (cpu
, vn
, i
)
4944 aarch64_set_vec_s16 (cpu
, vd
, i
, aarch64_get_vec_s16 (cpu
, vn
, i
)
4950 for (i
= 0; i
< (full
? 4 : 2); i
++)
4952 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 4);
4954 aarch64_set_vec_s32 (cpu
, vd
, i
, aarch64_get_vec_s32 (cpu
, vn
, i
)
4957 aarch64_set_vec_s32 (cpu
, vd
, i
, aarch64_get_vec_s32 (cpu
, vn
, i
)
4965 for (i
= 0; i
< 2; i
++)
4967 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 8);
4969 aarch64_set_vec_s64 (cpu
, vd
, i
, aarch64_get_vec_s64 (cpu
, vn
, i
)
4972 aarch64_set_vec_s64 (cpu
, vd
, i
, aarch64_get_vec_s64 (cpu
, vn
, i
)
4980 do_vec_USHL (sim_cpu
*cpu
)
4983 instr[30] = first part (0)/ second part (1)
4984 instr[29,24] = 10 1110
4985 instr[23,22] = size: byte(00), half(01), word (10), long (11)
4988 instr[15,10] = 0100 01
4992 unsigned full
= INSTR (30, 30);
4993 unsigned vm
= INSTR (20, 16);
4994 unsigned vn
= INSTR (9, 5);
4995 unsigned vd
= INSTR (4, 0);
4999 NYI_assert (29, 24, 0x2E);
5000 NYI_assert (15, 10, 0x11);
5002 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5003 switch (INSTR (23, 22))
5006 for (i
= 0; i
< (full
? 16 : 8); i
++)
5008 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
);
5010 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vn
, i
)
5013 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vn
, i
)
5019 for (i
= 0; i
< (full
? 8 : 4); i
++)
5021 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 2);
5023 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vn
, i
)
5026 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vn
, i
)
5032 for (i
= 0; i
< (full
? 4 : 2); i
++)
5034 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 4);
5036 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vn
, i
)
5039 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vn
, i
)
5047 for (i
= 0; i
< 2; i
++)
5049 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 8);
5051 aarch64_set_vec_u64 (cpu
, vd
, i
, aarch64_get_vec_u64 (cpu
, vn
, i
)
5054 aarch64_set_vec_u64 (cpu
, vd
, i
, aarch64_get_vec_u64 (cpu
, vn
, i
)
5062 do_vec_FMLA (sim_cpu
*cpu
)
5065 instr[30] = full/half selector
5066 instr[29,23] = 0011100
5067 instr[22] = size: 0=>float, 1=>double
5070 instr[15,10] = 1100 11
5074 unsigned vm
= INSTR (20, 16);
5075 unsigned vn
= INSTR (9, 5);
5076 unsigned vd
= INSTR (4, 0);
5078 int full
= INSTR (30, 30);
5080 NYI_assert (29, 23, 0x1C);
5081 NYI_assert (21, 21, 1);
5082 NYI_assert (15, 10, 0x33);
5084 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5089 for (i
= 0; i
< 2; i
++)
5090 aarch64_set_vec_double (cpu
, vd
, i
,
5091 aarch64_get_vec_double (cpu
, vn
, i
) *
5092 aarch64_get_vec_double (cpu
, vm
, i
) +
5093 aarch64_get_vec_double (cpu
, vd
, i
));
5097 for (i
= 0; i
< (full
? 4 : 2); i
++)
5098 aarch64_set_vec_float (cpu
, vd
, i
,
5099 aarch64_get_vec_float (cpu
, vn
, i
) *
5100 aarch64_get_vec_float (cpu
, vm
, i
) +
5101 aarch64_get_vec_float (cpu
, vd
, i
));
5106 do_vec_max (sim_cpu
*cpu
)
5109 instr[30] = full/half selector
5110 instr[29] = SMAX (0) / UMAX (1)
5111 instr[28,24] = 0 1110
5112 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
5115 instr[15,10] = 0110 01
5119 unsigned vm
= INSTR (20, 16);
5120 unsigned vn
= INSTR (9, 5);
5121 unsigned vd
= INSTR (4, 0);
5123 int full
= INSTR (30, 30);
5125 NYI_assert (28, 24, 0x0E);
5126 NYI_assert (21, 21, 1);
5127 NYI_assert (15, 10, 0x19);
5129 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5132 switch (INSTR (23, 22))
5135 for (i
= 0; i
< (full
? 16 : 8); i
++)
5136 aarch64_set_vec_u8 (cpu
, vd
, i
,
5137 aarch64_get_vec_u8 (cpu
, vn
, i
)
5138 > aarch64_get_vec_u8 (cpu
, vm
, i
)
5139 ? aarch64_get_vec_u8 (cpu
, vn
, i
)
5140 : aarch64_get_vec_u8 (cpu
, vm
, i
));
5144 for (i
= 0; i
< (full
? 8 : 4); i
++)
5145 aarch64_set_vec_u16 (cpu
, vd
, i
,
5146 aarch64_get_vec_u16 (cpu
, vn
, i
)
5147 > aarch64_get_vec_u16 (cpu
, vm
, i
)
5148 ? aarch64_get_vec_u16 (cpu
, vn
, i
)
5149 : aarch64_get_vec_u16 (cpu
, vm
, i
));
5153 for (i
= 0; i
< (full
? 4 : 2); i
++)
5154 aarch64_set_vec_u32 (cpu
, vd
, i
,
5155 aarch64_get_vec_u32 (cpu
, vn
, i
)
5156 > aarch64_get_vec_u32 (cpu
, vm
, i
)
5157 ? aarch64_get_vec_u32 (cpu
, vn
, i
)
5158 : aarch64_get_vec_u32 (cpu
, vm
, i
));
5167 switch (INSTR (23, 22))
5170 for (i
= 0; i
< (full
? 16 : 8); i
++)
5171 aarch64_set_vec_s8 (cpu
, vd
, i
,
5172 aarch64_get_vec_s8 (cpu
, vn
, i
)
5173 > aarch64_get_vec_s8 (cpu
, vm
, i
)
5174 ? aarch64_get_vec_s8 (cpu
, vn
, i
)
5175 : aarch64_get_vec_s8 (cpu
, vm
, i
));
5179 for (i
= 0; i
< (full
? 8 : 4); i
++)
5180 aarch64_set_vec_s16 (cpu
, vd
, i
,
5181 aarch64_get_vec_s16 (cpu
, vn
, i
)
5182 > aarch64_get_vec_s16 (cpu
, vm
, i
)
5183 ? aarch64_get_vec_s16 (cpu
, vn
, i
)
5184 : aarch64_get_vec_s16 (cpu
, vm
, i
));
5188 for (i
= 0; i
< (full
? 4 : 2); i
++)
5189 aarch64_set_vec_s32 (cpu
, vd
, i
,
5190 aarch64_get_vec_s32 (cpu
, vn
, i
)
5191 > aarch64_get_vec_s32 (cpu
, vm
, i
)
5192 ? aarch64_get_vec_s32 (cpu
, vn
, i
)
5193 : aarch64_get_vec_s32 (cpu
, vm
, i
));
5203 do_vec_min (sim_cpu
*cpu
)
5206 instr[30] = full/half selector
5207 instr[29] = SMIN (0) / UMIN (1)
5208 instr[28,24] = 0 1110
5209 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
5212 instr[15,10] = 0110 11
5216 unsigned vm
= INSTR (20, 16);
5217 unsigned vn
= INSTR (9, 5);
5218 unsigned vd
= INSTR (4, 0);
5220 int full
= INSTR (30, 30);
5222 NYI_assert (28, 24, 0x0E);
5223 NYI_assert (21, 21, 1);
5224 NYI_assert (15, 10, 0x1B);
5226 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5229 switch (INSTR (23, 22))
5232 for (i
= 0; i
< (full
? 16 : 8); i
++)
5233 aarch64_set_vec_u8 (cpu
, vd
, i
,
5234 aarch64_get_vec_u8 (cpu
, vn
, i
)
5235 < aarch64_get_vec_u8 (cpu
, vm
, i
)
5236 ? aarch64_get_vec_u8 (cpu
, vn
, i
)
5237 : aarch64_get_vec_u8 (cpu
, vm
, i
));
5241 for (i
= 0; i
< (full
? 8 : 4); i
++)
5242 aarch64_set_vec_u16 (cpu
, vd
, i
,
5243 aarch64_get_vec_u16 (cpu
, vn
, i
)
5244 < aarch64_get_vec_u16 (cpu
, vm
, i
)
5245 ? aarch64_get_vec_u16 (cpu
, vn
, i
)
5246 : aarch64_get_vec_u16 (cpu
, vm
, i
));
5250 for (i
= 0; i
< (full
? 4 : 2); i
++)
5251 aarch64_set_vec_u32 (cpu
, vd
, i
,
5252 aarch64_get_vec_u32 (cpu
, vn
, i
)
5253 < aarch64_get_vec_u32 (cpu
, vm
, i
)
5254 ? aarch64_get_vec_u32 (cpu
, vn
, i
)
5255 : aarch64_get_vec_u32 (cpu
, vm
, i
));
5264 switch (INSTR (23, 22))
5267 for (i
= 0; i
< (full
? 16 : 8); i
++)
5268 aarch64_set_vec_s8 (cpu
, vd
, i
,
5269 aarch64_get_vec_s8 (cpu
, vn
, i
)
5270 < aarch64_get_vec_s8 (cpu
, vm
, i
)
5271 ? aarch64_get_vec_s8 (cpu
, vn
, i
)
5272 : aarch64_get_vec_s8 (cpu
, vm
, i
));
5276 for (i
= 0; i
< (full
? 8 : 4); i
++)
5277 aarch64_set_vec_s16 (cpu
, vd
, i
,
5278 aarch64_get_vec_s16 (cpu
, vn
, i
)
5279 < aarch64_get_vec_s16 (cpu
, vm
, i
)
5280 ? aarch64_get_vec_s16 (cpu
, vn
, i
)
5281 : aarch64_get_vec_s16 (cpu
, vm
, i
));
5285 for (i
= 0; i
< (full
? 4 : 2); i
++)
5286 aarch64_set_vec_s32 (cpu
, vd
, i
,
5287 aarch64_get_vec_s32 (cpu
, vn
, i
)
5288 < aarch64_get_vec_s32 (cpu
, vm
, i
)
5289 ? aarch64_get_vec_s32 (cpu
, vn
, i
)
5290 : aarch64_get_vec_s32 (cpu
, vm
, i
));
5300 do_vec_sub_long (sim_cpu
*cpu
)
5303 instr[30] = lower (0) / upper (1)
5304 instr[29] = signed (0) / unsigned (1)
5305 instr[28,24] = 0 1110
5306 instr[23,22] = size: bytes (00), half (01), word (10)
5309 instr[15,10] = 0010 00
5311 instr[4,0] = V dest. */
5313 unsigned size
= INSTR (23, 22);
5314 unsigned vm
= INSTR (20, 16);
5315 unsigned vn
= INSTR (9, 5);
5316 unsigned vd
= INSTR (4, 0);
5320 NYI_assert (28, 24, 0x0E);
5321 NYI_assert (21, 21, 1);
5322 NYI_assert (15, 10, 0x08);
5327 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5328 switch (INSTR (30, 29))
5330 case 2: /* SSUBL2. */
5332 case 0: /* SSUBL. */
5337 for (i
= 0; i
< 8; i
++)
5338 aarch64_set_vec_s16 (cpu
, vd
, i
,
5339 aarch64_get_vec_s8 (cpu
, vn
, i
+ bias
)
5340 - aarch64_get_vec_s8 (cpu
, vm
, i
+ bias
));
5345 for (i
= 0; i
< 4; i
++)
5346 aarch64_set_vec_s32 (cpu
, vd
, i
,
5347 aarch64_get_vec_s16 (cpu
, vn
, i
+ bias
)
5348 - aarch64_get_vec_s16 (cpu
, vm
, i
+ bias
));
5352 for (i
= 0; i
< 2; i
++)
5353 aarch64_set_vec_s64 (cpu
, vd
, i
,
5354 aarch64_get_vec_s32 (cpu
, vn
, i
+ bias
)
5355 - aarch64_get_vec_s32 (cpu
, vm
, i
+ bias
));
5363 case 3: /* USUBL2. */
5365 case 1: /* USUBL. */
5370 for (i
= 0; i
< 8; i
++)
5371 aarch64_set_vec_u16 (cpu
, vd
, i
,
5372 aarch64_get_vec_u8 (cpu
, vn
, i
+ bias
)
5373 - aarch64_get_vec_u8 (cpu
, vm
, i
+ bias
));
5378 for (i
= 0; i
< 4; i
++)
5379 aarch64_set_vec_u32 (cpu
, vd
, i
,
5380 aarch64_get_vec_u16 (cpu
, vn
, i
+ bias
)
5381 - aarch64_get_vec_u16 (cpu
, vm
, i
+ bias
));
5385 for (i
= 0; i
< 2; i
++)
5386 aarch64_set_vec_u64 (cpu
, vd
, i
,
5387 aarch64_get_vec_u32 (cpu
, vn
, i
+ bias
)
5388 - aarch64_get_vec_u32 (cpu
, vm
, i
+ bias
));
5399 do_vec_ADDP (sim_cpu
*cpu
)
5402 instr[30] = half(0)/full(1)
5403 instr[29,24] = 00 1110
5404 instr[23,22] = size: bytes (00), half (01), word (10), long (11)
5407 instr[15,10] = 1011 11
5409 instr[4,0] = V dest. */
5413 unsigned full
= INSTR (30, 30);
5414 unsigned size
= INSTR (23, 22);
5415 unsigned vm
= INSTR (20, 16);
5416 unsigned vn
= INSTR (9, 5);
5417 unsigned vd
= INSTR (4, 0);
5420 NYI_assert (29, 24, 0x0E);
5421 NYI_assert (21, 21, 1);
5422 NYI_assert (15, 10, 0x2F);
5424 /* Make copies of the source registers in case vd == vn/vm. */
5425 copy_vn
= cpu
->fr
[vn
];
5426 copy_vm
= cpu
->fr
[vm
];
5428 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5432 range
= full
? 8 : 4;
5433 for (i
= 0; i
< range
; i
++)
5435 aarch64_set_vec_u8 (cpu
, vd
, i
,
5436 copy_vn
.b
[i
* 2] + copy_vn
.b
[i
* 2 + 1]);
5437 aarch64_set_vec_u8 (cpu
, vd
, i
+ range
,
5438 copy_vm
.b
[i
* 2] + copy_vm
.b
[i
* 2 + 1]);
5443 range
= full
? 4 : 2;
5444 for (i
= 0; i
< range
; i
++)
5446 aarch64_set_vec_u16 (cpu
, vd
, i
,
5447 copy_vn
.h
[i
* 2] + copy_vn
.h
[i
* 2 + 1]);
5448 aarch64_set_vec_u16 (cpu
, vd
, i
+ range
,
5449 copy_vm
.h
[i
* 2] + copy_vm
.h
[i
* 2 + 1]);
5454 range
= full
? 2 : 1;
5455 for (i
= 0; i
< range
; i
++)
5457 aarch64_set_vec_u32 (cpu
, vd
, i
,
5458 copy_vn
.w
[i
* 2] + copy_vn
.w
[i
* 2 + 1]);
5459 aarch64_set_vec_u32 (cpu
, vd
, i
+ range
,
5460 copy_vm
.w
[i
* 2] + copy_vm
.w
[i
* 2 + 1]);
5467 aarch64_set_vec_u64 (cpu
, vd
, 0, copy_vn
.v
[0] + copy_vn
.v
[1]);
5468 aarch64_set_vec_u64 (cpu
, vd
, 1, copy_vm
.v
[0] + copy_vm
.v
[1]);
5473 /* Float point vector convert to longer (precision). */
5475 do_vec_FCVTL (sim_cpu
*cpu
)
5478 instr[30] = half (0) / all (1)
5479 instr[29,23] = 00 1110 0
5480 instr[22] = single (0) / double (1)
5481 instr[21,10] = 10 0001 0111 10
5485 unsigned rn
= INSTR (9, 5);
5486 unsigned rd
= INSTR (4, 0);
5487 unsigned full
= INSTR (30, 30);
5490 NYI_assert (31, 31, 0);
5491 NYI_assert (29, 23, 0x1C);
5492 NYI_assert (21, 10, 0x85E);
5494 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5497 for (i
= 0; i
< 2; i
++)
5498 aarch64_set_vec_double (cpu
, rd
, i
,
5499 aarch64_get_vec_float (cpu
, rn
, i
+ 2*full
));
5506 /* TODO: Implement missing half-float support. */
5507 for (i
= 0; i
< 4; i
++)
5508 aarch64_set_vec_float (cpu
, rd
, i
,
5509 aarch64_get_vec_halffloat (cpu
, rn
, i
+ 4*full
));
5515 do_vec_FABS (sim_cpu
*cpu
)
5518 instr[30] = half(0)/full(1)
5519 instr[29,23] = 00 1110 1
5520 instr[22] = float(0)/double(1)
5521 instr[21,16] = 10 0000
5522 instr[15,10] = 1111 10
5526 unsigned vn
= INSTR (9, 5);
5527 unsigned vd
= INSTR (4, 0);
5528 unsigned full
= INSTR (30, 30);
5531 NYI_assert (29, 23, 0x1D);
5532 NYI_assert (21, 10, 0x83E);
5534 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5540 for (i
= 0; i
< 2; i
++)
5541 aarch64_set_vec_double (cpu
, vd
, i
,
5542 fabs (aarch64_get_vec_double (cpu
, vn
, i
)));
5546 for (i
= 0; i
< (full
? 4 : 2); i
++)
5547 aarch64_set_vec_float (cpu
, vd
, i
,
5548 fabsf (aarch64_get_vec_float (cpu
, vn
, i
)));
5553 do_vec_FCVTZS (sim_cpu
*cpu
)
5556 instr[30] = half (0) / all (1)
5557 instr[29,23] = 00 1110 1
5558 instr[22] = single (0) / double (1)
5559 instr[21,10] = 10 0001 1011 10
5563 unsigned rn
= INSTR (9, 5);
5564 unsigned rd
= INSTR (4, 0);
5565 unsigned full
= INSTR (30, 30);
5568 NYI_assert (31, 31, 0);
5569 NYI_assert (29, 23, 0x1D);
5570 NYI_assert (21, 10, 0x86E);
5572 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5578 for (i
= 0; i
< 2; i
++)
5579 aarch64_set_vec_s64 (cpu
, rd
, i
,
5580 (int64_t) aarch64_get_vec_double (cpu
, rn
, i
));
5583 for (i
= 0; i
< (full
? 4 : 2); i
++)
5584 aarch64_set_vec_s32 (cpu
, rd
, i
,
5585 (int32_t) aarch64_get_vec_float (cpu
, rn
, i
));
5589 do_vec_REV64 (sim_cpu
*cpu
)
5592 instr[30] = full/half
5593 instr[29,24] = 00 1110
5595 instr[21,10] = 10 0000 0000 10
5599 unsigned rn
= INSTR (9, 5);
5600 unsigned rd
= INSTR (4, 0);
5601 unsigned size
= INSTR (23, 22);
5602 unsigned full
= INSTR (30, 30);
5606 NYI_assert (29, 24, 0x0E);
5607 NYI_assert (21, 10, 0x802);
5609 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5613 for (i
= 0; i
< (full
? 16 : 8); i
++)
5614 val
.b
[i
^ 0x7] = aarch64_get_vec_u8 (cpu
, rn
, i
);
5618 for (i
= 0; i
< (full
? 8 : 4); i
++)
5619 val
.h
[i
^ 0x3] = aarch64_get_vec_u16 (cpu
, rn
, i
);
5623 for (i
= 0; i
< (full
? 4 : 2); i
++)
5624 val
.w
[i
^ 0x1] = aarch64_get_vec_u32 (cpu
, rn
, i
);
5631 aarch64_set_vec_u64 (cpu
, rd
, 0, val
.v
[0]);
5633 aarch64_set_vec_u64 (cpu
, rd
, 1, val
.v
[1]);
5637 do_vec_REV16 (sim_cpu
*cpu
)
5640 instr[30] = full/half
5641 instr[29,24] = 00 1110
5643 instr[21,10] = 10 0000 0001 10
5647 unsigned rn
= INSTR (9, 5);
5648 unsigned rd
= INSTR (4, 0);
5649 unsigned size
= INSTR (23, 22);
5650 unsigned full
= INSTR (30, 30);
5654 NYI_assert (29, 24, 0x0E);
5655 NYI_assert (21, 10, 0x806);
5657 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5661 for (i
= 0; i
< (full
? 16 : 8); i
++)
5662 val
.b
[i
^ 0x1] = aarch64_get_vec_u8 (cpu
, rn
, i
);
5669 aarch64_set_vec_u64 (cpu
, rd
, 0, val
.v
[0]);
5671 aarch64_set_vec_u64 (cpu
, rd
, 1, val
.v
[1]);
5675 do_vec_op1 (sim_cpu
*cpu
)
5678 instr[30] = half/full
5679 instr[29,24] = 00 1110
5682 instr[15,10] = sub-opcode
5685 NYI_assert (29, 24, 0x0E);
5687 if (INSTR (21, 21) == 0)
5689 if (INSTR (23, 22) == 0)
5691 if (INSTR (30, 30) == 1
5692 && INSTR (17, 14) == 0
5693 && INSTR (12, 10) == 7)
5694 return do_vec_ins_2 (cpu
);
5696 switch (INSTR (15, 10))
5698 case 0x01: do_vec_DUP_vector_into_vector (cpu
); return;
5699 case 0x03: do_vec_DUP_scalar_into_vector (cpu
); return;
5700 case 0x07: do_vec_INS (cpu
); return;
5701 case 0x0B: do_vec_SMOV_into_scalar (cpu
); return;
5702 case 0x0F: do_vec_UMOV_into_scalar (cpu
); return;
5708 do_vec_TBL (cpu
); return;
5712 do_vec_UZP (cpu
); return;
5714 case 0x0A: do_vec_TRN (cpu
); return;
5718 do_vec_ZIP (cpu
); return;
5725 switch (INSTR (13, 10))
5727 case 0x6: do_vec_UZP (cpu
); return;
5728 case 0xE: do_vec_ZIP (cpu
); return;
5729 case 0xA: do_vec_TRN (cpu
); return;
5734 switch (INSTR (15, 10))
5736 case 0x02: do_vec_REV64 (cpu
); return;
5737 case 0x06: do_vec_REV16 (cpu
); return;
5740 switch (INSTR (23, 21))
5742 case 1: do_vec_AND (cpu
); return;
5743 case 3: do_vec_BIC (cpu
); return;
5744 case 5: do_vec_ORR (cpu
); return;
5745 case 7: do_vec_ORN (cpu
); return;
5749 case 0x08: do_vec_sub_long (cpu
); return;
5750 case 0x0a: do_vec_XTN (cpu
); return;
5751 case 0x11: do_vec_SSHL (cpu
); return;
5752 case 0x16: do_vec_CNT (cpu
); return;
5753 case 0x19: do_vec_max (cpu
); return;
5754 case 0x1B: do_vec_min (cpu
); return;
5755 case 0x21: do_vec_add (cpu
); return;
5756 case 0x25: do_vec_MLA (cpu
); return;
5757 case 0x27: do_vec_mul (cpu
); return;
5758 case 0x2F: do_vec_ADDP (cpu
); return;
5759 case 0x30: do_vec_mull (cpu
); return;
5760 case 0x33: do_vec_FMLA (cpu
); return;
5761 case 0x35: do_vec_fadd (cpu
); return;
5764 switch (INSTR (20, 16))
5766 case 0x01: do_vec_FCVTL (cpu
); return;
5771 switch (INSTR (20, 16))
5773 case 0x00: do_vec_ABS (cpu
); return;
5774 case 0x01: do_vec_FCVTZS (cpu
); return;
5775 case 0x11: do_vec_ADDV (cpu
); return;
5781 do_vec_Fminmax (cpu
); return;
5793 do_vec_compare (cpu
); return;
5796 do_vec_FABS (cpu
); return;
5804 do_vec_xtl (sim_cpu
*cpu
)
5807 instr[30,29] = SXTL (00), UXTL (01), SXTL2 (10), UXTL2 (11)
5808 instr[28,22] = 0 1111 00
5809 instr[21,16] = size & shift (USHLL, SSHLL, USHLL2, SSHLL2)
5810 instr[15,10] = 1010 01
5811 instr[9,5] = V source
5812 instr[4,0] = V dest. */
5814 unsigned vs
= INSTR (9, 5);
5815 unsigned vd
= INSTR (4, 0);
5816 unsigned i
, shift
, bias
= 0;
5818 NYI_assert (28, 22, 0x3C);
5819 NYI_assert (15, 10, 0x29);
5821 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5822 switch (INSTR (30, 29))
5824 case 2: /* SXTL2, SSHLL2. */
5826 case 0: /* SXTL, SSHLL. */
5831 shift
= INSTR (20, 16);
5832 /* Get the source values before setting the destination values
5833 in case the source and destination are the same. */
5834 val1
= aarch64_get_vec_s32 (cpu
, vs
, bias
) << shift
;
5835 val2
= aarch64_get_vec_s32 (cpu
, vs
, bias
+ 1) << shift
;
5836 aarch64_set_vec_s64 (cpu
, vd
, 0, val1
);
5837 aarch64_set_vec_s64 (cpu
, vd
, 1, val2
);
5839 else if (INSTR (20, 20))
5842 int32_t v1
,v2
,v3
,v4
;
5844 shift
= INSTR (19, 16);
5846 for (i
= 0; i
< 4; i
++)
5847 v
[i
] = aarch64_get_vec_s16 (cpu
, vs
, bias
+ i
) << shift
;
5848 for (i
= 0; i
< 4; i
++)
5849 aarch64_set_vec_s32 (cpu
, vd
, i
, v
[i
]);
5854 NYI_assert (19, 19, 1);
5856 shift
= INSTR (18, 16);
5858 for (i
= 0; i
< 8; i
++)
5859 v
[i
] = aarch64_get_vec_s8 (cpu
, vs
, i
+ bias
) << shift
;
5860 for (i
= 0; i
< 8; i
++)
5861 aarch64_set_vec_s16 (cpu
, vd
, i
, v
[i
]);
5865 case 3: /* UXTL2, USHLL2. */
5867 case 1: /* UXTL, USHLL. */
5871 shift
= INSTR (20, 16);
5872 v1
= aarch64_get_vec_u32 (cpu
, vs
, bias
) << shift
;
5873 v2
= aarch64_get_vec_u32 (cpu
, vs
, bias
+ 1) << shift
;
5874 aarch64_set_vec_u64 (cpu
, vd
, 0, v1
);
5875 aarch64_set_vec_u64 (cpu
, vd
, 1, v2
);
5877 else if (INSTR (20, 20))
5880 shift
= INSTR (19, 16);
5882 for (i
= 0; i
< 4; i
++)
5883 v
[i
] = aarch64_get_vec_u16 (cpu
, vs
, i
+ bias
) << shift
;
5884 for (i
= 0; i
< 4; i
++)
5885 aarch64_set_vec_u32 (cpu
, vd
, i
, v
[i
]);
5890 NYI_assert (19, 19, 1);
5892 shift
= INSTR (18, 16);
5894 for (i
= 0; i
< 8; i
++)
5895 v
[i
] = aarch64_get_vec_u8 (cpu
, vs
, i
+ bias
) << shift
;
5896 for (i
= 0; i
< 8; i
++)
5897 aarch64_set_vec_u16 (cpu
, vd
, i
, v
[i
]);
5904 do_vec_SHL (sim_cpu
*cpu
)
5907 instr [30] = half(0)/full(1)
5908 instr [29,23] = 001 1110
5909 instr [22,16] = size and shift amount
5910 instr [15,10] = 01 0101
5912 instr [4, 0] = Vd. */
5915 int full
= INSTR (30, 30);
5916 unsigned vs
= INSTR (9, 5);
5917 unsigned vd
= INSTR (4, 0);
5920 NYI_assert (29, 23, 0x1E);
5921 NYI_assert (15, 10, 0x15);
5923 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5926 shift
= INSTR (21, 16);
5931 for (i
= 0; i
< 2; i
++)
5933 uint64_t val
= aarch64_get_vec_u64 (cpu
, vs
, i
);
5934 aarch64_set_vec_u64 (cpu
, vd
, i
, val
<< shift
);
5942 shift
= INSTR (20, 16);
5944 for (i
= 0; i
< (full
? 4 : 2); i
++)
5946 uint32_t val
= aarch64_get_vec_u32 (cpu
, vs
, i
);
5947 aarch64_set_vec_u32 (cpu
, vd
, i
, val
<< shift
);
5955 shift
= INSTR (19, 16);
5957 for (i
= 0; i
< (full
? 8 : 4); i
++)
5959 uint16_t val
= aarch64_get_vec_u16 (cpu
, vs
, i
);
5960 aarch64_set_vec_u16 (cpu
, vd
, i
, val
<< shift
);
5966 if (INSTR (19, 19) == 0)
5969 shift
= INSTR (18, 16);
5971 for (i
= 0; i
< (full
? 16 : 8); i
++)
5973 uint8_t val
= aarch64_get_vec_u8 (cpu
, vs
, i
);
5974 aarch64_set_vec_u8 (cpu
, vd
, i
, val
<< shift
);
5979 do_vec_SSHR_USHR (sim_cpu
*cpu
)
5982 instr [30] = half(0)/full(1)
5983 instr [29] = signed(0)/unsigned(1)
5984 instr [28,23] = 0 1111 0
5985 instr [22,16] = size and shift amount
5986 instr [15,10] = 0000 01
5988 instr [4, 0] = Vd. */
5990 int full
= INSTR (30, 30);
5991 int sign
= ! INSTR (29, 29);
5992 unsigned shift
= INSTR (22, 16);
5993 unsigned vs
= INSTR (9, 5);
5994 unsigned vd
= INSTR (4, 0);
5997 NYI_assert (28, 23, 0x1E);
5998 NYI_assert (15, 10, 0x01);
6000 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6003 shift
= 128 - shift
;
6009 for (i
= 0; i
< 2; i
++)
6011 int64_t val
= aarch64_get_vec_s64 (cpu
, vs
, i
);
6012 aarch64_set_vec_s64 (cpu
, vd
, i
, val
>> shift
);
6015 for (i
= 0; i
< 2; i
++)
6017 uint64_t val
= aarch64_get_vec_u64 (cpu
, vs
, i
);
6018 aarch64_set_vec_u64 (cpu
, vd
, i
, val
>> shift
);
6029 for (i
= 0; i
< (full
? 4 : 2); i
++)
6031 int32_t val
= aarch64_get_vec_s32 (cpu
, vs
, i
);
6032 aarch64_set_vec_s32 (cpu
, vd
, i
, val
>> shift
);
6035 for (i
= 0; i
< (full
? 4 : 2); i
++)
6037 uint32_t val
= aarch64_get_vec_u32 (cpu
, vs
, i
);
6038 aarch64_set_vec_u32 (cpu
, vd
, i
, val
>> shift
);
6049 for (i
= 0; i
< (full
? 8 : 4); i
++)
6051 int16_t val
= aarch64_get_vec_s16 (cpu
, vs
, i
);
6052 aarch64_set_vec_s16 (cpu
, vd
, i
, val
>> shift
);
6055 for (i
= 0; i
< (full
? 8 : 4); i
++)
6057 uint16_t val
= aarch64_get_vec_u16 (cpu
, vs
, i
);
6058 aarch64_set_vec_u16 (cpu
, vd
, i
, val
>> shift
);
6064 if (INSTR (19, 19) == 0)
6070 for (i
= 0; i
< (full
? 16 : 8); i
++)
6072 int8_t val
= aarch64_get_vec_s8 (cpu
, vs
, i
);
6073 aarch64_set_vec_s8 (cpu
, vd
, i
, val
>> shift
);
6076 for (i
= 0; i
< (full
? 16 : 8); i
++)
6078 uint8_t val
= aarch64_get_vec_u8 (cpu
, vs
, i
);
6079 aarch64_set_vec_u8 (cpu
, vd
, i
, val
>> shift
);
6084 do_vec_MUL_by_element (sim_cpu
*cpu
)
6087 instr[30] = half/full
6088 instr[29,24] = 00 1111
6099 unsigned full
= INSTR (30, 30);
6100 unsigned L
= INSTR (21, 21);
6101 unsigned H
= INSTR (11, 11);
6102 unsigned vn
= INSTR (9, 5);
6103 unsigned vd
= INSTR (4, 0);
6104 unsigned size
= INSTR (23, 22);
6109 NYI_assert (29, 24, 0x0F);
6110 NYI_assert (15, 12, 0x8);
6111 NYI_assert (10, 10, 0);
6113 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6118 /* 16 bit products. */
6123 index
= (H
<< 2) | (L
<< 1) | INSTR (20, 20);
6124 vm
= INSTR (19, 16);
6125 element2
= aarch64_get_vec_u16 (cpu
, vm
, index
);
6127 for (e
= 0; e
< (full
? 8 : 4); e
++)
6129 element1
= aarch64_get_vec_u16 (cpu
, vn
, e
);
6130 product
= element1
* element2
;
6131 aarch64_set_vec_u16 (cpu
, vd
, e
, product
);
6138 /* 32 bit products. */
6143 index
= (H
<< 1) | L
;
6144 vm
= INSTR (20, 16);
6145 element2
= aarch64_get_vec_u32 (cpu
, vm
, index
);
6147 for (e
= 0; e
< (full
? 4 : 2); e
++)
6149 element1
= aarch64_get_vec_u32 (cpu
, vn
, e
);
6150 product
= element1
* element2
;
6151 aarch64_set_vec_u32 (cpu
, vd
, e
, product
);
6162 do_FMLA_by_element (sim_cpu
*cpu
)
6165 instr[30] = half/full
6166 instr[29,23] = 00 1111 1
6176 unsigned full
= INSTR (30, 30);
6177 unsigned size
= INSTR (22, 22);
6178 unsigned L
= INSTR (21, 21);
6179 unsigned vm
= INSTR (20, 16);
6180 unsigned H
= INSTR (11, 11);
6181 unsigned vn
= INSTR (9, 5);
6182 unsigned vd
= INSTR (4, 0);
6185 NYI_assert (29, 23, 0x1F);
6186 NYI_assert (15, 12, 0x1);
6187 NYI_assert (10, 10, 0);
6189 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6192 double element1
, element2
;
6197 element2
= aarch64_get_vec_double (cpu
, vm
, H
);
6199 for (e
= 0; e
< 2; e
++)
6201 element1
= aarch64_get_vec_double (cpu
, vn
, e
);
6202 element1
*= element2
;
6203 element1
+= aarch64_get_vec_double (cpu
, vd
, e
);
6204 aarch64_set_vec_double (cpu
, vd
, e
, element1
);
6210 float element2
= aarch64_get_vec_float (cpu
, vm
, (H
<< 1) | L
);
6212 for (e
= 0; e
< (full
? 4 : 2); e
++)
6214 element1
= aarch64_get_vec_float (cpu
, vn
, e
);
6215 element1
*= element2
;
6216 element1
+= aarch64_get_vec_float (cpu
, vd
, e
);
6217 aarch64_set_vec_float (cpu
, vd
, e
, element1
);
6223 do_vec_op2 (sim_cpu
*cpu
)
6226 instr[30] = half/full
6227 instr[29,24] = 00 1111
6229 instr[22,16] = element size & index
6230 instr[15,10] = sub-opcode
6234 NYI_assert (29, 24, 0x0F);
6236 if (INSTR (23, 23) != 0)
6238 switch (INSTR (15, 10))
6242 do_FMLA_by_element (cpu
);
6247 do_vec_MUL_by_element (cpu
);
6256 switch (INSTR (15, 10))
6258 case 0x01: do_vec_SSHR_USHR (cpu
); return;
6259 case 0x15: do_vec_SHL (cpu
); return;
6261 case 0x22: do_vec_MUL_by_element (cpu
); return;
6262 case 0x29: do_vec_xtl (cpu
); return;
6269 do_vec_neg (sim_cpu
*cpu
)
6272 instr[30] = full(1)/half(0)
6273 instr[29,24] = 10 1110
6274 instr[23,22] = size: byte(00), half (01), word (10), long (11)
6275 instr[21,10] = 1000 0010 1110
6279 int full
= INSTR (30, 30);
6280 unsigned vs
= INSTR (9, 5);
6281 unsigned vd
= INSTR (4, 0);
6284 NYI_assert (29, 24, 0x2E);
6285 NYI_assert (21, 10, 0x82E);
6287 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6288 switch (INSTR (23, 22))
6291 for (i
= 0; i
< (full
? 16 : 8); i
++)
6292 aarch64_set_vec_s8 (cpu
, vd
, i
, - aarch64_get_vec_s8 (cpu
, vs
, i
));
6296 for (i
= 0; i
< (full
? 8 : 4); i
++)
6297 aarch64_set_vec_s16 (cpu
, vd
, i
, - aarch64_get_vec_s16 (cpu
, vs
, i
));
6301 for (i
= 0; i
< (full
? 4 : 2); i
++)
6302 aarch64_set_vec_s32 (cpu
, vd
, i
, - aarch64_get_vec_s32 (cpu
, vs
, i
));
6308 for (i
= 0; i
< 2; i
++)
6309 aarch64_set_vec_s64 (cpu
, vd
, i
, - aarch64_get_vec_s64 (cpu
, vs
, i
));
6315 do_vec_sqrt (sim_cpu
*cpu
)
6318 instr[30] = full(1)/half(0)
6319 instr[29,23] = 101 1101
6320 instr[22] = single(0)/double(1)
6321 instr[21,10] = 1000 0111 1110
6325 int full
= INSTR (30, 30);
6326 unsigned vs
= INSTR (9, 5);
6327 unsigned vd
= INSTR (4, 0);
6330 NYI_assert (29, 23, 0x5B);
6331 NYI_assert (21, 10, 0x87E);
6333 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6334 if (INSTR (22, 22) == 0)
6335 for (i
= 0; i
< (full
? 4 : 2); i
++)
6336 aarch64_set_vec_float (cpu
, vd
, i
,
6337 sqrtf (aarch64_get_vec_float (cpu
, vs
, i
)));
6339 for (i
= 0; i
< 2; i
++)
6340 aarch64_set_vec_double (cpu
, vd
, i
,
6341 sqrt (aarch64_get_vec_double (cpu
, vs
, i
)));
6345 do_vec_mls_indexed (sim_cpu
*cpu
)
6348 instr[30] = half(0)/full(1)
6349 instr[29,24] = 10 1111
6350 instr[23,22] = 16-bit(01)/32-bit(10)
6351 instr[21,20+11] = index (if 16-bit)
6352 instr[21+11] = index (if 32-bit)
6355 instr[11] = part of index
6360 int full
= INSTR (30, 30);
6361 unsigned vs
= INSTR (9, 5);
6362 unsigned vd
= INSTR (4, 0);
6363 unsigned vm
= INSTR (20, 16);
6366 NYI_assert (15, 12, 4);
6367 NYI_assert (10, 10, 0);
6369 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6370 switch (INSTR (23, 22))
6380 elem
= (INSTR (21, 20) << 1) | INSTR (11, 11);
6381 val
= aarch64_get_vec_u16 (cpu
, vm
, elem
);
6383 for (i
= 0; i
< (full
? 8 : 4); i
++)
6384 aarch64_set_vec_u32 (cpu
, vd
, i
,
6385 aarch64_get_vec_u32 (cpu
, vd
, i
) -
6386 (aarch64_get_vec_u32 (cpu
, vs
, i
) * val
));
6392 unsigned elem
= (INSTR (21, 21) << 1) | INSTR (11, 11);
6393 uint64_t val
= aarch64_get_vec_u32 (cpu
, vm
, elem
);
6395 for (i
= 0; i
< (full
? 4 : 2); i
++)
6396 aarch64_set_vec_u64 (cpu
, vd
, i
,
6397 aarch64_get_vec_u64 (cpu
, vd
, i
) -
6398 (aarch64_get_vec_u64 (cpu
, vs
, i
) * val
));
6410 do_vec_SUB (sim_cpu
*cpu
)
6413 instr [30] = half(0)/full(1)
6414 instr [29,24] = 10 1110
6415 instr [23,22] = size: byte(00, half(01), word (10), long (11)
6418 instr [15,10] = 10 0001
6420 instr [4, 0] = Vd. */
6422 unsigned full
= INSTR (30, 30);
6423 unsigned vm
= INSTR (20, 16);
6424 unsigned vn
= INSTR (9, 5);
6425 unsigned vd
= INSTR (4, 0);
6428 NYI_assert (29, 24, 0x2E);
6429 NYI_assert (21, 21, 1);
6430 NYI_assert (15, 10, 0x21);
6432 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6433 switch (INSTR (23, 22))
6436 for (i
= 0; i
< (full
? 16 : 8); i
++)
6437 aarch64_set_vec_s8 (cpu
, vd
, i
,
6438 aarch64_get_vec_s8 (cpu
, vn
, i
)
6439 - aarch64_get_vec_s8 (cpu
, vm
, i
));
6443 for (i
= 0; i
< (full
? 8 : 4); i
++)
6444 aarch64_set_vec_s16 (cpu
, vd
, i
,
6445 aarch64_get_vec_s16 (cpu
, vn
, i
)
6446 - aarch64_get_vec_s16 (cpu
, vm
, i
));
6450 for (i
= 0; i
< (full
? 4 : 2); i
++)
6451 aarch64_set_vec_s32 (cpu
, vd
, i
,
6452 aarch64_get_vec_s32 (cpu
, vn
, i
)
6453 - aarch64_get_vec_s32 (cpu
, vm
, i
));
6460 for (i
= 0; i
< 2; i
++)
6461 aarch64_set_vec_s64 (cpu
, vd
, i
,
6462 aarch64_get_vec_s64 (cpu
, vn
, i
)
6463 - aarch64_get_vec_s64 (cpu
, vm
, i
));
6469 do_vec_MLS (sim_cpu
*cpu
)
6472 instr [30] = half(0)/full(1)
6473 instr [29,24] = 10 1110
6474 instr [23,22] = size: byte(00, half(01), word (10)
6477 instr [15,10] = 10 0101
6479 instr [4, 0] = Vd. */
6481 unsigned full
= INSTR (30, 30);
6482 unsigned vm
= INSTR (20, 16);
6483 unsigned vn
= INSTR (9, 5);
6484 unsigned vd
= INSTR (4, 0);
6487 NYI_assert (29, 24, 0x2E);
6488 NYI_assert (21, 21, 1);
6489 NYI_assert (15, 10, 0x25);
6491 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6492 switch (INSTR (23, 22))
6495 for (i
= 0; i
< (full
? 16 : 8); i
++)
6496 aarch64_set_vec_u8 (cpu
, vd
, i
,
6497 aarch64_get_vec_u8 (cpu
, vd
, i
)
6498 - (aarch64_get_vec_u8 (cpu
, vn
, i
)
6499 * aarch64_get_vec_u8 (cpu
, vm
, i
)));
6503 for (i
= 0; i
< (full
? 8 : 4); i
++)
6504 aarch64_set_vec_u16 (cpu
, vd
, i
,
6505 aarch64_get_vec_u16 (cpu
, vd
, i
)
6506 - (aarch64_get_vec_u16 (cpu
, vn
, i
)
6507 * aarch64_get_vec_u16 (cpu
, vm
, i
)));
6511 for (i
= 0; i
< (full
? 4 : 2); i
++)
6512 aarch64_set_vec_u32 (cpu
, vd
, i
,
6513 aarch64_get_vec_u32 (cpu
, vd
, i
)
6514 - (aarch64_get_vec_u32 (cpu
, vn
, i
)
6515 * aarch64_get_vec_u32 (cpu
, vm
, i
)));
6524 do_vec_FDIV (sim_cpu
*cpu
)
6527 instr [30] = half(0)/full(1)
6528 instr [29,23] = 10 1110 0
6529 instr [22] = float()/double(1)
6532 instr [15,10] = 1111 11
6534 instr [4, 0] = Vd. */
6536 unsigned full
= INSTR (30, 30);
6537 unsigned vm
= INSTR (20, 16);
6538 unsigned vn
= INSTR (9, 5);
6539 unsigned vd
= INSTR (4, 0);
6542 NYI_assert (29, 23, 0x5C);
6543 NYI_assert (21, 21, 1);
6544 NYI_assert (15, 10, 0x3F);
6546 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6552 for (i
= 0; i
< 2; i
++)
6553 aarch64_set_vec_double (cpu
, vd
, i
,
6554 aarch64_get_vec_double (cpu
, vn
, i
)
6555 / aarch64_get_vec_double (cpu
, vm
, i
));
6558 for (i
= 0; i
< (full
? 4 : 2); i
++)
6559 aarch64_set_vec_float (cpu
, vd
, i
,
6560 aarch64_get_vec_float (cpu
, vn
, i
)
6561 / aarch64_get_vec_float (cpu
, vm
, i
));
6565 do_vec_FMUL (sim_cpu
*cpu
)
6568 instr [30] = half(0)/full(1)
6569 instr [29,23] = 10 1110 0
6570 instr [22] = float(0)/double(1)
6573 instr [15,10] = 1101 11
6575 instr [4, 0] = Vd. */
6577 unsigned full
= INSTR (30, 30);
6578 unsigned vm
= INSTR (20, 16);
6579 unsigned vn
= INSTR (9, 5);
6580 unsigned vd
= INSTR (4, 0);
6583 NYI_assert (29, 23, 0x5C);
6584 NYI_assert (21, 21, 1);
6585 NYI_assert (15, 10, 0x37);
6587 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6593 for (i
= 0; i
< 2; i
++)
6594 aarch64_set_vec_double (cpu
, vd
, i
,
6595 aarch64_get_vec_double (cpu
, vn
, i
)
6596 * aarch64_get_vec_double (cpu
, vm
, i
));
6599 for (i
= 0; i
< (full
? 4 : 2); i
++)
6600 aarch64_set_vec_float (cpu
, vd
, i
,
6601 aarch64_get_vec_float (cpu
, vn
, i
)
6602 * aarch64_get_vec_float (cpu
, vm
, i
));
6606 do_vec_FADDP (sim_cpu
*cpu
)
6609 instr [30] = half(0)/full(1)
6610 instr [29,23] = 10 1110 0
6611 instr [22] = float(0)/double(1)
6614 instr [15,10] = 1101 01
6616 instr [4, 0] = Vd. */
6618 unsigned full
= INSTR (30, 30);
6619 unsigned vm
= INSTR (20, 16);
6620 unsigned vn
= INSTR (9, 5);
6621 unsigned vd
= INSTR (4, 0);
6623 NYI_assert (29, 23, 0x5C);
6624 NYI_assert (21, 21, 1);
6625 NYI_assert (15, 10, 0x35);
6627 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6630 /* Extract values before adding them incase vd == vn/vm. */
6631 double tmp1
= aarch64_get_vec_double (cpu
, vn
, 0);
6632 double tmp2
= aarch64_get_vec_double (cpu
, vn
, 1);
6633 double tmp3
= aarch64_get_vec_double (cpu
, vm
, 0);
6634 double tmp4
= aarch64_get_vec_double (cpu
, vm
, 1);
6639 aarch64_set_vec_double (cpu
, vd
, 0, tmp1
+ tmp2
);
6640 aarch64_set_vec_double (cpu
, vd
, 1, tmp3
+ tmp4
);
6644 /* Extract values before adding them incase vd == vn/vm. */
6645 float tmp1
= aarch64_get_vec_float (cpu
, vn
, 0);
6646 float tmp2
= aarch64_get_vec_float (cpu
, vn
, 1);
6647 float tmp5
= aarch64_get_vec_float (cpu
, vm
, 0);
6648 float tmp6
= aarch64_get_vec_float (cpu
, vm
, 1);
6652 float tmp3
= aarch64_get_vec_float (cpu
, vn
, 2);
6653 float tmp4
= aarch64_get_vec_float (cpu
, vn
, 3);
6654 float tmp7
= aarch64_get_vec_float (cpu
, vm
, 2);
6655 float tmp8
= aarch64_get_vec_float (cpu
, vm
, 3);
6657 aarch64_set_vec_float (cpu
, vd
, 0, tmp1
+ tmp2
);
6658 aarch64_set_vec_float (cpu
, vd
, 1, tmp3
+ tmp4
);
6659 aarch64_set_vec_float (cpu
, vd
, 2, tmp5
+ tmp6
);
6660 aarch64_set_vec_float (cpu
, vd
, 3, tmp7
+ tmp8
);
6664 aarch64_set_vec_float (cpu
, vd
, 0, tmp1
+ tmp2
);
6665 aarch64_set_vec_float (cpu
, vd
, 1, tmp5
+ tmp6
);
6671 do_vec_FSQRT (sim_cpu
*cpu
)
6674 instr[30] = half(0)/full(1)
6675 instr[29,23] = 10 1110 1
6676 instr[22] = single(0)/double(1)
6677 instr[21,10] = 10 0001 1111 10
6679 instr[4,0] = Vdest. */
6681 unsigned vn
= INSTR (9, 5);
6682 unsigned vd
= INSTR (4, 0);
6683 unsigned full
= INSTR (30, 30);
6686 NYI_assert (29, 23, 0x5D);
6687 NYI_assert (21, 10, 0x87E);
6689 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6695 for (i
= 0; i
< 2; i
++)
6696 aarch64_set_vec_double (cpu
, vd
, i
,
6697 sqrt (aarch64_get_vec_double (cpu
, vn
, i
)));
6701 for (i
= 0; i
< (full
? 4 : 2); i
++)
6702 aarch64_set_vec_float (cpu
, vd
, i
,
6703 sqrtf (aarch64_get_vec_float (cpu
, vn
, i
)));
6708 do_vec_FNEG (sim_cpu
*cpu
)
6711 instr[30] = half (0)/full (1)
6712 instr[29,23] = 10 1110 1
6713 instr[22] = single (0)/double (1)
6714 instr[21,10] = 10 0000 1111 10
6716 instr[4,0] = Vdest. */
6718 unsigned vn
= INSTR (9, 5);
6719 unsigned vd
= INSTR (4, 0);
6720 unsigned full
= INSTR (30, 30);
6723 NYI_assert (29, 23, 0x5D);
6724 NYI_assert (21, 10, 0x83E);
6726 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6732 for (i
= 0; i
< 2; i
++)
6733 aarch64_set_vec_double (cpu
, vd
, i
,
6734 - aarch64_get_vec_double (cpu
, vn
, i
));
6738 for (i
= 0; i
< (full
? 4 : 2); i
++)
6739 aarch64_set_vec_float (cpu
, vd
, i
,
6740 - aarch64_get_vec_float (cpu
, vn
, i
));
6745 do_vec_NOT (sim_cpu
*cpu
)
6748 instr[30] = half (0)/full (1)
6749 instr[29,10] = 10 1110 0010 0000 0101 10
6753 unsigned vn
= INSTR (9, 5);
6754 unsigned vd
= INSTR (4, 0);
6756 int full
= INSTR (30, 30);
6758 NYI_assert (29, 10, 0xB8816);
6760 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6761 for (i
= 0; i
< (full
? 16 : 8); i
++)
6762 aarch64_set_vec_u8 (cpu
, vd
, i
, ~ aarch64_get_vec_u8 (cpu
, vn
, i
));
6766 clz (uint64_t val
, unsigned size
)
6771 mask
<<= (size
- 1);
6786 do_vec_CLZ (sim_cpu
*cpu
)
6789 instr[30] = half (0)/full (1)
6790 instr[29,24] = 10 1110
6792 instr[21,10] = 10 0000 0100 10
6796 unsigned vn
= INSTR (9, 5);
6797 unsigned vd
= INSTR (4, 0);
6799 int full
= INSTR (30,30);
6801 NYI_assert (29, 24, 0x2E);
6802 NYI_assert (21, 10, 0x812);
6804 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6805 switch (INSTR (23, 22))
6808 for (i
= 0; i
< (full
? 16 : 8); i
++)
6809 aarch64_set_vec_u8 (cpu
, vd
, i
, clz (aarch64_get_vec_u8 (cpu
, vn
, i
), 8));
6812 for (i
= 0; i
< (full
? 8 : 4); i
++)
6813 aarch64_set_vec_u16 (cpu
, vd
, i
, clz (aarch64_get_vec_u16 (cpu
, vn
, i
), 16));
6816 for (i
= 0; i
< (full
? 4 : 2); i
++)
6817 aarch64_set_vec_u32 (cpu
, vd
, i
, clz (aarch64_get_vec_u32 (cpu
, vn
, i
), 32));
6822 aarch64_set_vec_u64 (cpu
, vd
, 0, clz (aarch64_get_vec_u64 (cpu
, vn
, 0), 64));
6823 aarch64_set_vec_u64 (cpu
, vd
, 1, clz (aarch64_get_vec_u64 (cpu
, vn
, 1), 64));
6829 do_vec_MOV_element (sim_cpu
*cpu
)
6831 /* instr[31,21] = 0110 1110 000
6832 instr[20,16] = size & dest index
6834 instr[14,11] = source index
6839 unsigned vs
= INSTR (9, 5);
6840 unsigned vd
= INSTR (4, 0);
6844 NYI_assert (31, 21, 0x370);
6845 NYI_assert (15, 15, 0);
6846 NYI_assert (10, 10, 1);
6848 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6852 src_index
= INSTR (14, 11);
6853 dst_index
= INSTR (20, 17);
6854 aarch64_set_vec_u8 (cpu
, vd
, dst_index
,
6855 aarch64_get_vec_u8 (cpu
, vs
, src_index
));
6857 else if (INSTR (17, 17))
6860 NYI_assert (11, 11, 0);
6861 src_index
= INSTR (14, 12);
6862 dst_index
= INSTR (20, 18);
6863 aarch64_set_vec_u16 (cpu
, vd
, dst_index
,
6864 aarch64_get_vec_u16 (cpu
, vs
, src_index
));
6866 else if (INSTR (18, 18))
6869 NYI_assert (12, 11, 0);
6870 src_index
= INSTR (14, 13);
6871 dst_index
= INSTR (20, 19);
6872 aarch64_set_vec_u32 (cpu
, vd
, dst_index
,
6873 aarch64_get_vec_u32 (cpu
, vs
, src_index
));
6877 NYI_assert (19, 19, 1);
6878 NYI_assert (13, 11, 0);
6879 src_index
= INSTR (14, 14);
6880 dst_index
= INSTR (20, 20);
6881 aarch64_set_vec_u64 (cpu
, vd
, dst_index
,
6882 aarch64_get_vec_u64 (cpu
, vs
, src_index
));
6887 do_vec_REV32 (sim_cpu
*cpu
)
6890 instr[30] = full/half
6891 instr[29,24] = 10 1110
6893 instr[21,10] = 10 0000 0000 10
6897 unsigned rn
= INSTR (9, 5);
6898 unsigned rd
= INSTR (4, 0);
6899 unsigned size
= INSTR (23, 22);
6900 unsigned full
= INSTR (30, 30);
6904 NYI_assert (29, 24, 0x2E);
6905 NYI_assert (21, 10, 0x802);
6907 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6911 for (i
= 0; i
< (full
? 16 : 8); i
++)
6912 val
.b
[i
^ 0x3] = aarch64_get_vec_u8 (cpu
, rn
, i
);
6916 for (i
= 0; i
< (full
? 8 : 4); i
++)
6917 val
.h
[i
^ 0x1] = aarch64_get_vec_u16 (cpu
, rn
, i
);
6924 aarch64_set_vec_u64 (cpu
, rd
, 0, val
.v
[0]);
6926 aarch64_set_vec_u64 (cpu
, rd
, 1, val
.v
[1]);
6930 do_vec_EXT (sim_cpu
*cpu
)
6933 instr[30] = full/half
6934 instr[29,21] = 10 1110 000
6937 instr[14,11] = source index
6942 unsigned vm
= INSTR (20, 16);
6943 unsigned vn
= INSTR (9, 5);
6944 unsigned vd
= INSTR (4, 0);
6945 unsigned src_index
= INSTR (14, 11);
6946 unsigned full
= INSTR (30, 30);
6951 NYI_assert (31, 21, 0x370);
6952 NYI_assert (15, 15, 0);
6953 NYI_assert (10, 10, 0);
6955 if (!full
&& (src_index
& 0x8))
6960 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6961 for (i
= src_index
; i
< (full
? 16 : 8); i
++)
6962 val
.b
[j
++] = aarch64_get_vec_u8 (cpu
, vn
, i
);
6963 for (i
= 0; i
< src_index
; i
++)
6964 val
.b
[j
++] = aarch64_get_vec_u8 (cpu
, vm
, i
);
6966 aarch64_set_vec_u64 (cpu
, vd
, 0, val
.v
[0]);
6968 aarch64_set_vec_u64 (cpu
, vd
, 1, val
.v
[1]);
6972 dexAdvSIMD0 (sim_cpu
*cpu
)
6974 /* instr [28,25] = 0 111. */
6975 if ( INSTR (15, 10) == 0x07
6979 if (INSTR (31, 21) == 0x075
6980 || INSTR (31, 21) == 0x275)
6982 do_vec_MOV_whole_vector (cpu
);
6987 if (INSTR (29, 19) == 0x1E0)
6989 do_vec_MOV_immediate (cpu
);
6993 if (INSTR (29, 19) == 0x5E0)
6999 if (INSTR (29, 19) == 0x1C0
7000 || INSTR (29, 19) == 0x1C1)
7002 if (INSTR (15, 10) == 0x03)
7004 do_vec_DUP_scalar_into_vector (cpu
);
7009 switch (INSTR (29, 24))
7011 case 0x0E: do_vec_op1 (cpu
); return;
7012 case 0x0F: do_vec_op2 (cpu
); return;
7015 if (INSTR (21, 21) == 1)
7017 switch (INSTR (15, 10))
7024 switch (INSTR (23, 22))
7026 case 0: do_vec_EOR (cpu
); return;
7027 case 1: do_vec_BSL (cpu
); return;
7029 case 3: do_vec_bit (cpu
); return;
7033 case 0x08: do_vec_sub_long (cpu
); return;
7034 case 0x11: do_vec_USHL (cpu
); return;
7035 case 0x12: do_vec_CLZ (cpu
); return;
7036 case 0x16: do_vec_NOT (cpu
); return;
7037 case 0x19: do_vec_max (cpu
); return;
7038 case 0x1B: do_vec_min (cpu
); return;
7039 case 0x21: do_vec_SUB (cpu
); return;
7040 case 0x25: do_vec_MLS (cpu
); return;
7041 case 0x31: do_vec_FminmaxNMP (cpu
); return;
7042 case 0x35: do_vec_FADDP (cpu
); return;
7043 case 0x37: do_vec_FMUL (cpu
); return;
7044 case 0x3F: do_vec_FDIV (cpu
); return;
7047 switch (INSTR (20, 16))
7049 case 0x00: do_vec_FNEG (cpu
); return;
7050 case 0x01: do_vec_FSQRT (cpu
); return;
7064 do_vec_compare (cpu
); return;
7071 if (INSTR (31, 21) == 0x370)
7074 do_vec_MOV_element (cpu
);
7080 switch (INSTR (21, 10))
7082 case 0x82E: do_vec_neg (cpu
); return;
7083 case 0x87E: do_vec_sqrt (cpu
); return;
7085 if (INSTR (15, 10) == 0x30)
7095 switch (INSTR (15, 10))
7097 case 0x01: do_vec_SSHR_USHR (cpu
); return;
7099 case 0x12: do_vec_mls_indexed (cpu
); return;
7100 case 0x29: do_vec_xtl (cpu
); return;
7114 /* Float multiply add. */
7116 fmadds (sim_cpu
*cpu
)
7118 unsigned sa
= INSTR (14, 10);
7119 unsigned sm
= INSTR (20, 16);
7120 unsigned sn
= INSTR ( 9, 5);
7121 unsigned sd
= INSTR ( 4, 0);
7123 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7124 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sa
)
7125 + aarch64_get_FP_float (cpu
, sn
)
7126 * aarch64_get_FP_float (cpu
, sm
));
7129 /* Double multiply add. */
7131 fmaddd (sim_cpu
*cpu
)
7133 unsigned sa
= INSTR (14, 10);
7134 unsigned sm
= INSTR (20, 16);
7135 unsigned sn
= INSTR ( 9, 5);
7136 unsigned sd
= INSTR ( 4, 0);
7138 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7139 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sa
)
7140 + aarch64_get_FP_double (cpu
, sn
)
7141 * aarch64_get_FP_double (cpu
, sm
));
7144 /* Float multiply subtract. */
7146 fmsubs (sim_cpu
*cpu
)
7148 unsigned sa
= INSTR (14, 10);
7149 unsigned sm
= INSTR (20, 16);
7150 unsigned sn
= INSTR ( 9, 5);
7151 unsigned sd
= INSTR ( 4, 0);
7153 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7154 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sa
)
7155 - aarch64_get_FP_float (cpu
, sn
)
7156 * aarch64_get_FP_float (cpu
, sm
));
7159 /* Double multiply subtract. */
7161 fmsubd (sim_cpu
*cpu
)
7163 unsigned sa
= INSTR (14, 10);
7164 unsigned sm
= INSTR (20, 16);
7165 unsigned sn
= INSTR ( 9, 5);
7166 unsigned sd
= INSTR ( 4, 0);
7168 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7169 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sa
)
7170 - aarch64_get_FP_double (cpu
, sn
)
7171 * aarch64_get_FP_double (cpu
, sm
));
7174 /* Float negative multiply add. */
7176 fnmadds (sim_cpu
*cpu
)
7178 unsigned sa
= INSTR (14, 10);
7179 unsigned sm
= INSTR (20, 16);
7180 unsigned sn
= INSTR ( 9, 5);
7181 unsigned sd
= INSTR ( 4, 0);
7183 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7184 aarch64_set_FP_float (cpu
, sd
, - aarch64_get_FP_float (cpu
, sa
)
7185 + (- aarch64_get_FP_float (cpu
, sn
))
7186 * aarch64_get_FP_float (cpu
, sm
));
7189 /* Double negative multiply add. */
7191 fnmaddd (sim_cpu
*cpu
)
7193 unsigned sa
= INSTR (14, 10);
7194 unsigned sm
= INSTR (20, 16);
7195 unsigned sn
= INSTR ( 9, 5);
7196 unsigned sd
= INSTR ( 4, 0);
7198 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7199 aarch64_set_FP_double (cpu
, sd
, - aarch64_get_FP_double (cpu
, sa
)
7200 + (- aarch64_get_FP_double (cpu
, sn
))
7201 * aarch64_get_FP_double (cpu
, sm
));
7204 /* Float negative multiply subtract. */
7206 fnmsubs (sim_cpu
*cpu
)
7208 unsigned sa
= INSTR (14, 10);
7209 unsigned sm
= INSTR (20, 16);
7210 unsigned sn
= INSTR ( 9, 5);
7211 unsigned sd
= INSTR ( 4, 0);
7213 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7214 aarch64_set_FP_float (cpu
, sd
, - aarch64_get_FP_float (cpu
, sa
)
7215 + aarch64_get_FP_float (cpu
, sn
)
7216 * aarch64_get_FP_float (cpu
, sm
));
7219 /* Double negative multiply subtract. */
7221 fnmsubd (sim_cpu
*cpu
)
7223 unsigned sa
= INSTR (14, 10);
7224 unsigned sm
= INSTR (20, 16);
7225 unsigned sn
= INSTR ( 9, 5);
7226 unsigned sd
= INSTR ( 4, 0);
7228 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7229 aarch64_set_FP_double (cpu
, sd
, - aarch64_get_FP_double (cpu
, sa
)
7230 + aarch64_get_FP_double (cpu
, sn
)
7231 * aarch64_get_FP_double (cpu
, sm
));
7235 dexSimpleFPDataProc3Source (sim_cpu
*cpu
)
7237 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
7239 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
7242 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
7243 instr[21] ==> o1 : 0 ==> unnegated, 1 ==> negated
7244 instr[15] ==> o2 : 0 ==> ADD, 1 ==> SUB */
7246 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
7247 /* dispatch on combined type:o1:o2. */
7248 uint32_t dispatch
= (INSTR (23, 21) << 1) | INSTR (15, 15);
7255 case 0: fmadds (cpu
); return;
7256 case 1: fmsubs (cpu
); return;
7257 case 2: fnmadds (cpu
); return;
7258 case 3: fnmsubs (cpu
); return;
7259 case 4: fmaddd (cpu
); return;
7260 case 5: fmsubd (cpu
); return;
7261 case 6: fnmaddd (cpu
); return;
7262 case 7: fnmsubd (cpu
); return;
7264 /* type > 1 is currently unallocated. */
7270 dexSimpleFPFixedConvert (sim_cpu
*cpu
)
7276 dexSimpleFPCondCompare (sim_cpu
*cpu
)
7278 /* instr [31,23] = 0001 1110 0
7282 instr [15,12] = condition
7286 instr [3,0] = nzcv */
7288 unsigned rm
= INSTR (20, 16);
7289 unsigned rn
= INSTR (9, 5);
7291 NYI_assert (31, 23, 0x3C);
7292 NYI_assert (11, 10, 0x1);
7293 NYI_assert (4, 4, 0);
7295 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7296 if (! testConditionCode (cpu
, INSTR (15, 12)))
7298 aarch64_set_CPSR (cpu
, INSTR (3, 0));
7304 /* Double precision. */
7305 double val1
= aarch64_get_vec_double (cpu
, rn
, 0);
7306 double val2
= aarch64_get_vec_double (cpu
, rm
, 0);
7308 /* FIXME: Check for NaNs. */
7310 aarch64_set_CPSR (cpu
, (Z
| C
));
7311 else if (val1
< val2
)
7312 aarch64_set_CPSR (cpu
, N
);
7313 else /* val1 > val2 */
7314 aarch64_set_CPSR (cpu
, C
);
7318 /* Single precision. */
7319 float val1
= aarch64_get_vec_float (cpu
, rn
, 0);
7320 float val2
= aarch64_get_vec_float (cpu
, rm
, 0);
7322 /* FIXME: Check for NaNs. */
7324 aarch64_set_CPSR (cpu
, (Z
| C
));
7325 else if (val1
< val2
)
7326 aarch64_set_CPSR (cpu
, N
);
7327 else /* val1 > val2 */
7328 aarch64_set_CPSR (cpu
, C
);
7336 fadds (sim_cpu
*cpu
)
7338 unsigned sm
= INSTR (20, 16);
7339 unsigned sn
= INSTR ( 9, 5);
7340 unsigned sd
= INSTR ( 4, 0);
7342 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7343 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
7344 + aarch64_get_FP_float (cpu
, sm
));
7349 faddd (sim_cpu
*cpu
)
7351 unsigned sm
= INSTR (20, 16);
7352 unsigned sn
= INSTR ( 9, 5);
7353 unsigned sd
= INSTR ( 4, 0);
7355 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7356 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
7357 + aarch64_get_FP_double (cpu
, sm
));
7362 fdivs (sim_cpu
*cpu
)
7364 unsigned sm
= INSTR (20, 16);
7365 unsigned sn
= INSTR ( 9, 5);
7366 unsigned sd
= INSTR ( 4, 0);
7368 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7369 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
7370 / aarch64_get_FP_float (cpu
, sm
));
7373 /* Double divide. */
7375 fdivd (sim_cpu
*cpu
)
7377 unsigned sm
= INSTR (20, 16);
7378 unsigned sn
= INSTR ( 9, 5);
7379 unsigned sd
= INSTR ( 4, 0);
7381 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7382 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
7383 / aarch64_get_FP_double (cpu
, sm
));
7386 /* Float multiply. */
7388 fmuls (sim_cpu
*cpu
)
7390 unsigned sm
= INSTR (20, 16);
7391 unsigned sn
= INSTR ( 9, 5);
7392 unsigned sd
= INSTR ( 4, 0);
7394 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7395 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
7396 * aarch64_get_FP_float (cpu
, sm
));
7399 /* Double multiply. */
7401 fmuld (sim_cpu
*cpu
)
7403 unsigned sm
= INSTR (20, 16);
7404 unsigned sn
= INSTR ( 9, 5);
7405 unsigned sd
= INSTR ( 4, 0);
7407 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7408 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
7409 * aarch64_get_FP_double (cpu
, sm
));
7412 /* Float negate and multiply. */
7414 fnmuls (sim_cpu
*cpu
)
7416 unsigned sm
= INSTR (20, 16);
7417 unsigned sn
= INSTR ( 9, 5);
7418 unsigned sd
= INSTR ( 4, 0);
7420 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7421 aarch64_set_FP_float (cpu
, sd
, - (aarch64_get_FP_float (cpu
, sn
)
7422 * aarch64_get_FP_float (cpu
, sm
)));
7425 /* Double negate and multiply. */
7427 fnmuld (sim_cpu
*cpu
)
7429 unsigned sm
= INSTR (20, 16);
7430 unsigned sn
= INSTR ( 9, 5);
7431 unsigned sd
= INSTR ( 4, 0);
7433 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7434 aarch64_set_FP_double (cpu
, sd
, - (aarch64_get_FP_double (cpu
, sn
)
7435 * aarch64_get_FP_double (cpu
, sm
)));
7438 /* Float subtract. */
7440 fsubs (sim_cpu
*cpu
)
7442 unsigned sm
= INSTR (20, 16);
7443 unsigned sn
= INSTR ( 9, 5);
7444 unsigned sd
= INSTR ( 4, 0);
7446 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7447 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
7448 - aarch64_get_FP_float (cpu
, sm
));
7451 /* Double subtract. */
7453 fsubd (sim_cpu
*cpu
)
7455 unsigned sm
= INSTR (20, 16);
7456 unsigned sn
= INSTR ( 9, 5);
7457 unsigned sd
= INSTR ( 4, 0);
7459 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7460 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
7461 - aarch64_get_FP_double (cpu
, sm
));
7465 do_FMINNM (sim_cpu
*cpu
)
7467 /* instr[31,23] = 0 0011 1100
7468 instr[22] = float(0)/double(1)
7471 instr[15,10] = 01 1110
7475 unsigned sm
= INSTR (20, 16);
7476 unsigned sn
= INSTR ( 9, 5);
7477 unsigned sd
= INSTR ( 4, 0);
7479 NYI_assert (31, 23, 0x03C);
7480 NYI_assert (15, 10, 0x1E);
7482 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7484 aarch64_set_FP_double (cpu
, sd
,
7485 dminnm (aarch64_get_FP_double (cpu
, sn
),
7486 aarch64_get_FP_double (cpu
, sm
)));
7488 aarch64_set_FP_float (cpu
, sd
,
7489 fminnm (aarch64_get_FP_float (cpu
, sn
),
7490 aarch64_get_FP_float (cpu
, sm
)));
7494 do_FMAXNM (sim_cpu
*cpu
)
7496 /* instr[31,23] = 0 0011 1100
7497 instr[22] = float(0)/double(1)
7500 instr[15,10] = 01 1010
7504 unsigned sm
= INSTR (20, 16);
7505 unsigned sn
= INSTR ( 9, 5);
7506 unsigned sd
= INSTR ( 4, 0);
7508 NYI_assert (31, 23, 0x03C);
7509 NYI_assert (15, 10, 0x1A);
7511 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7513 aarch64_set_FP_double (cpu
, sd
,
7514 dmaxnm (aarch64_get_FP_double (cpu
, sn
),
7515 aarch64_get_FP_double (cpu
, sm
)));
7517 aarch64_set_FP_float (cpu
, sd
,
7518 fmaxnm (aarch64_get_FP_float (cpu
, sn
),
7519 aarch64_get_FP_float (cpu
, sm
)));
7523 dexSimpleFPDataProc2Source (sim_cpu
*cpu
)
7525 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
7527 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
7530 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
7533 instr[15,12] ==> opcode : 0000 ==> FMUL, 0001 ==> FDIV
7534 0010 ==> FADD, 0011 ==> FSUB,
7535 0100 ==> FMAX, 0101 ==> FMIN
7536 0110 ==> FMAXNM, 0111 ==> FMINNM
7537 1000 ==> FNMUL, ow ==> UNALLOC
7542 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
7543 uint32_t type
= INSTR (23, 22);
7544 /* Dispatch on opcode. */
7545 uint32_t dispatch
= INSTR (15, 12);
7556 case 0: fmuld (cpu
); return;
7557 case 1: fdivd (cpu
); return;
7558 case 2: faddd (cpu
); return;
7559 case 3: fsubd (cpu
); return;
7560 case 6: do_FMAXNM (cpu
); return;
7561 case 7: do_FMINNM (cpu
); return;
7562 case 8: fnmuld (cpu
); return;
7564 /* Have not yet implemented fmax and fmin. */
7572 else /* type == 0 => floats. */
7575 case 0: fmuls (cpu
); return;
7576 case 1: fdivs (cpu
); return;
7577 case 2: fadds (cpu
); return;
7578 case 3: fsubs (cpu
); return;
7579 case 6: do_FMAXNM (cpu
); return;
7580 case 7: do_FMINNM (cpu
); return;
7581 case 8: fnmuls (cpu
); return;
7593 dexSimpleFPCondSelect (sim_cpu
*cpu
)
7596 instr[31,23] = 0 0011 1100
7597 instr[22] = 0=>single 1=>double
7604 unsigned sm
= INSTR (20, 16);
7605 unsigned sn
= INSTR ( 9, 5);
7606 unsigned sd
= INSTR ( 4, 0);
7607 uint32_t set
= testConditionCode (cpu
, INSTR (15, 12));
7609 NYI_assert (31, 23, 0x03C);
7610 NYI_assert (11, 10, 0x3);
7612 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7614 aarch64_set_FP_double (cpu
, sd
, (set
? aarch64_get_FP_double (cpu
, sn
)
7615 : aarch64_get_FP_double (cpu
, sm
)));
7617 aarch64_set_FP_float (cpu
, sd
, (set
? aarch64_get_FP_float (cpu
, sn
)
7618 : aarch64_get_FP_float (cpu
, sm
)));
7621 /* Store 32 bit unscaled signed 9 bit. */
7623 fsturs (sim_cpu
*cpu
, int32_t offset
)
7625 unsigned int rn
= INSTR (9, 5);
7626 unsigned int st
= INSTR (4, 0);
7628 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7629 aarch64_set_mem_u32 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, 1) + offset
,
7630 aarch64_get_vec_u32 (cpu
, st
, 0));
7633 /* Store 64 bit unscaled signed 9 bit. */
7635 fsturd (sim_cpu
*cpu
, int32_t offset
)
7637 unsigned int rn
= INSTR (9, 5);
7638 unsigned int st
= INSTR (4, 0);
7640 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7641 aarch64_set_mem_u64 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, 1) + offset
,
7642 aarch64_get_vec_u64 (cpu
, st
, 0));
7645 /* Store 128 bit unscaled signed 9 bit. */
7647 fsturq (sim_cpu
*cpu
, int32_t offset
)
7649 unsigned int rn
= INSTR (9, 5);
7650 unsigned int st
= INSTR (4, 0);
7653 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7654 aarch64_get_FP_long_double (cpu
, st
, & a
);
7655 aarch64_set_mem_long_double (cpu
,
7656 aarch64_get_reg_u64 (cpu
, rn
, 1)
7660 /* TODO FP move register. */
7662 /* 32 bit fp to fp move register. */
7664 ffmovs (sim_cpu
*cpu
)
7666 unsigned int rn
= INSTR (9, 5);
7667 unsigned int st
= INSTR (4, 0);
7669 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7670 aarch64_set_FP_float (cpu
, st
, aarch64_get_FP_float (cpu
, rn
));
7673 /* 64 bit fp to fp move register. */
7675 ffmovd (sim_cpu
*cpu
)
7677 unsigned int rn
= INSTR (9, 5);
7678 unsigned int st
= INSTR (4, 0);
7680 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7681 aarch64_set_FP_double (cpu
, st
, aarch64_get_FP_double (cpu
, rn
));
7684 /* 32 bit GReg to Vec move register. */
7686 fgmovs (sim_cpu
*cpu
)
7688 unsigned int rn
= INSTR (9, 5);
7689 unsigned int st
= INSTR (4, 0);
7691 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7692 aarch64_set_vec_u32 (cpu
, st
, 0, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
));
7695 /* 64 bit g to fp move register. */
7697 fgmovd (sim_cpu
*cpu
)
7699 unsigned int rn
= INSTR (9, 5);
7700 unsigned int st
= INSTR (4, 0);
7702 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7703 aarch64_set_vec_u64 (cpu
, st
, 0, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
7706 /* 32 bit fp to g move register. */
7708 gfmovs (sim_cpu
*cpu
)
7710 unsigned int rn
= INSTR (9, 5);
7711 unsigned int st
= INSTR (4, 0);
7713 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7714 aarch64_set_reg_u64 (cpu
, st
, NO_SP
, aarch64_get_vec_u32 (cpu
, rn
, 0));
7717 /* 64 bit fp to g move register. */
7719 gfmovd (sim_cpu
*cpu
)
7721 unsigned int rn
= INSTR (9, 5);
7722 unsigned int st
= INSTR (4, 0);
7724 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7725 aarch64_set_reg_u64 (cpu
, st
, NO_SP
, aarch64_get_vec_u64 (cpu
, rn
, 0));
7728 /* FP move immediate
7730 These install an immediate 8 bit value in the target register
7731 where the 8 bits comprise 1 sign bit, 4 bits of fraction and a 3
7735 fmovs (sim_cpu
*cpu
)
7737 unsigned int sd
= INSTR (4, 0);
7738 uint32_t imm
= INSTR (20, 13);
7739 float f
= fp_immediate_for_encoding_32 (imm
);
7741 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7742 aarch64_set_FP_float (cpu
, sd
, f
);
7746 fmovd (sim_cpu
*cpu
)
7748 unsigned int sd
= INSTR (4, 0);
7749 uint32_t imm
= INSTR (20, 13);
7750 double d
= fp_immediate_for_encoding_64 (imm
);
7752 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7753 aarch64_set_FP_double (cpu
, sd
, d
);
7757 dexSimpleFPImmediate (sim_cpu
*cpu
)
7759 /* instr[31,23] == 00111100
7760 instr[22] == type : single(0)/double(1)
7762 instr[20,13] == imm8
7764 instr[9,5] == imm5 : 00000 ==> PK, ow ==> UNALLOC
7766 uint32_t imm5
= INSTR (9, 5);
7768 NYI_assert (31, 23, 0x3C);
7779 /* TODO specific decode and execute for group Load Store. */
7781 /* TODO FP load/store single register (unscaled offset). */
7783 /* TODO load 8 bit unscaled signed 9 bit. */
7784 /* TODO load 16 bit unscaled signed 9 bit. */
7786 /* Load 32 bit unscaled signed 9 bit. */
7788 fldurs (sim_cpu
*cpu
, int32_t offset
)
7790 unsigned int rn
= INSTR (9, 5);
7791 unsigned int st
= INSTR (4, 0);
7793 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7794 aarch64_set_vec_u32 (cpu
, st
, 0, aarch64_get_mem_u32
7795 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
));
7798 /* Load 64 bit unscaled signed 9 bit. */
7800 fldurd (sim_cpu
*cpu
, int32_t offset
)
7802 unsigned int rn
= INSTR (9, 5);
7803 unsigned int st
= INSTR (4, 0);
7805 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7806 aarch64_set_vec_u64 (cpu
, st
, 0, aarch64_get_mem_u64
7807 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
));
7810 /* Load 128 bit unscaled signed 9 bit. */
7812 fldurq (sim_cpu
*cpu
, int32_t offset
)
7814 unsigned int rn
= INSTR (9, 5);
7815 unsigned int st
= INSTR (4, 0);
7817 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
;
7819 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7820 aarch64_get_mem_long_double (cpu
, addr
, & a
);
7821 aarch64_set_FP_long_double (cpu
, st
, a
);
7824 /* TODO store 8 bit unscaled signed 9 bit. */
7825 /* TODO store 16 bit unscaled signed 9 bit. */
7830 /* Float absolute value. */
7832 fabss (sim_cpu
*cpu
)
7834 unsigned sn
= INSTR (9, 5);
7835 unsigned sd
= INSTR (4, 0);
7836 float value
= aarch64_get_FP_float (cpu
, sn
);
7838 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7839 aarch64_set_FP_float (cpu
, sd
, fabsf (value
));
7842 /* Double absolute value. */
7844 fabcpu (sim_cpu
*cpu
)
7846 unsigned sn
= INSTR (9, 5);
7847 unsigned sd
= INSTR (4, 0);
7848 double value
= aarch64_get_FP_double (cpu
, sn
);
7850 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7851 aarch64_set_FP_double (cpu
, sd
, fabs (value
));
7854 /* Float negative value. */
7856 fnegs (sim_cpu
*cpu
)
7858 unsigned sn
= INSTR (9, 5);
7859 unsigned sd
= INSTR (4, 0);
7861 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7862 aarch64_set_FP_float (cpu
, sd
, - aarch64_get_FP_float (cpu
, sn
));
7865 /* Double negative value. */
7867 fnegd (sim_cpu
*cpu
)
7869 unsigned sn
= INSTR (9, 5);
7870 unsigned sd
= INSTR (4, 0);
7872 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7873 aarch64_set_FP_double (cpu
, sd
, - aarch64_get_FP_double (cpu
, sn
));
7876 /* Float square root. */
7878 fsqrts (sim_cpu
*cpu
)
7880 unsigned sn
= INSTR (9, 5);
7881 unsigned sd
= INSTR (4, 0);
7883 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7884 aarch64_set_FP_float (cpu
, sd
, sqrtf (aarch64_get_FP_float (cpu
, sn
)));
7887 /* Double square root. */
7889 fsqrtd (sim_cpu
*cpu
)
7891 unsigned sn
= INSTR (9, 5);
7892 unsigned sd
= INSTR (4, 0);
7894 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7895 aarch64_set_FP_double (cpu
, sd
,
7896 sqrt (aarch64_get_FP_double (cpu
, sn
)));
7899 /* Convert double to float. */
7901 fcvtds (sim_cpu
*cpu
)
7903 unsigned sn
= INSTR (9, 5);
7904 unsigned sd
= INSTR (4, 0);
7906 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7907 aarch64_set_FP_float (cpu
, sd
, (float) aarch64_get_FP_double (cpu
, sn
));
7910 /* Convert float to double. */
7912 fcvtcpu (sim_cpu
*cpu
)
7914 unsigned sn
= INSTR (9, 5);
7915 unsigned sd
= INSTR (4, 0);
7917 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7918 aarch64_set_FP_double (cpu
, sd
, (double) aarch64_get_FP_float (cpu
, sn
));
7922 do_FRINT (sim_cpu
*cpu
)
7924 /* instr[31,23] = 0001 1110 0
7925 instr[22] = single(0)/double(1)
7927 instr[17,15] = rounding mode
7928 instr[14,10] = 10000
7930 instr[4,0] = dest */
7933 unsigned rs
= INSTR (9, 5);
7934 unsigned rd
= INSTR (4, 0);
7935 unsigned int rmode
= INSTR (17, 15);
7937 NYI_assert (31, 23, 0x03C);
7938 NYI_assert (21, 18, 0x9);
7939 NYI_assert (14, 10, 0x10);
7941 if (rmode
== 6 || rmode
== 7)
7942 /* FIXME: Add support for rmode == 6 exactness check. */
7943 rmode
= uimm (aarch64_get_FPSR (cpu
), 23, 22);
7945 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7948 double val
= aarch64_get_FP_double (cpu
, rs
);
7952 case 0: /* mode N: nearest or even. */
7954 double rval
= round (val
);
7956 if (val
- rval
== 0.5)
7958 if (((rval
/ 2.0) * 2.0) != rval
)
7962 aarch64_set_FP_double (cpu
, rd
, round (val
));
7966 case 1: /* mode P: towards +inf. */
7968 aarch64_set_FP_double (cpu
, rd
, trunc (val
));
7970 aarch64_set_FP_double (cpu
, rd
, round (val
));
7973 case 2: /* mode M: towards -inf. */
7975 aarch64_set_FP_double (cpu
, rd
, round (val
));
7977 aarch64_set_FP_double (cpu
, rd
, trunc (val
));
7980 case 3: /* mode Z: towards 0. */
7981 aarch64_set_FP_double (cpu
, rd
, trunc (val
));
7984 case 4: /* mode A: away from 0. */
7985 aarch64_set_FP_double (cpu
, rd
, round (val
));
7988 case 6: /* mode X: use FPCR with exactness check. */
7989 case 7: /* mode I: use FPCR mode. */
7997 val
= aarch64_get_FP_float (cpu
, rs
);
8001 case 0: /* mode N: nearest or even. */
8003 float rval
= roundf (val
);
8005 if (val
- rval
== 0.5)
8007 if (((rval
/ 2.0) * 2.0) != rval
)
8011 aarch64_set_FP_float (cpu
, rd
, rval
);
8015 case 1: /* mode P: towards +inf. */
8017 aarch64_set_FP_float (cpu
, rd
, truncf (val
));
8019 aarch64_set_FP_float (cpu
, rd
, roundf (val
));
8022 case 2: /* mode M: towards -inf. */
8024 aarch64_set_FP_float (cpu
, rd
, truncf (val
));
8026 aarch64_set_FP_float (cpu
, rd
, roundf (val
));
8029 case 3: /* mode Z: towards 0. */
8030 aarch64_set_FP_float (cpu
, rd
, truncf (val
));
8033 case 4: /* mode A: away from 0. */
8034 aarch64_set_FP_float (cpu
, rd
, roundf (val
));
8037 case 6: /* mode X: use FPCR with exactness check. */
8038 case 7: /* mode I: use FPCR mode. */
8046 /* Convert half to float. */
8048 do_FCVT_half_to_single (sim_cpu
*cpu
)
8050 unsigned rn
= INSTR (9, 5);
8051 unsigned rd
= INSTR (4, 0);
8053 NYI_assert (31, 10, 0x7B890);
8055 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8056 aarch64_set_FP_float (cpu
, rd
, (float) aarch64_get_FP_half (cpu
, rn
));
8059 /* Convert half to double. */
8061 do_FCVT_half_to_double (sim_cpu
*cpu
)
8063 unsigned rn
= INSTR (9, 5);
8064 unsigned rd
= INSTR (4, 0);
8066 NYI_assert (31, 10, 0x7B8B0);
8068 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8069 aarch64_set_FP_double (cpu
, rd
, (double) aarch64_get_FP_half (cpu
, rn
));
8073 do_FCVT_single_to_half (sim_cpu
*cpu
)
8075 unsigned rn
= INSTR (9, 5);
8076 unsigned rd
= INSTR (4, 0);
8078 NYI_assert (31, 10, 0x788F0);
8080 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8081 aarch64_set_FP_half (cpu
, rd
, aarch64_get_FP_float (cpu
, rn
));
8084 /* Convert double to half. */
8086 do_FCVT_double_to_half (sim_cpu
*cpu
)
8088 unsigned rn
= INSTR (9, 5);
8089 unsigned rd
= INSTR (4, 0);
8091 NYI_assert (31, 10, 0x798F0);
8093 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8094 aarch64_set_FP_half (cpu
, rd
, (float) aarch64_get_FP_double (cpu
, rn
));
8098 dexSimpleFPDataProc1Source (sim_cpu
*cpu
)
8100 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
8102 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
8105 instr[23,22] ==> type : 00 ==> source is single,
8106 01 ==> source is double
8108 11 ==> UNALLOC or source is half
8110 instr[20,15] ==> opcode : with type 00 or 01
8111 000000 ==> FMOV, 000001 ==> FABS,
8112 000010 ==> FNEG, 000011 ==> FSQRT,
8113 000100 ==> UNALLOC, 000101 ==> FCVT,(to single/double)
8114 000110 ==> UNALLOC, 000111 ==> FCVT (to half)
8115 001000 ==> FRINTN, 001001 ==> FRINTP,
8116 001010 ==> FRINTM, 001011 ==> FRINTZ,
8117 001100 ==> FRINTA, 001101 ==> UNALLOC
8118 001110 ==> FRINTX, 001111 ==> FRINTI
8120 000100 ==> FCVT (half-to-single)
8121 000101 ==> FCVT (half-to-double)
8122 instr[14,10] = 10000. */
8124 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
8125 uint32_t type
= INSTR (23, 22);
8126 uint32_t opcode
= INSTR (20, 15);
8134 do_FCVT_half_to_single (cpu
);
8135 else if (opcode
== 5)
8136 do_FCVT_half_to_double (cpu
);
8188 case 8: /* FRINTN etc. */
8200 do_FCVT_double_to_half (cpu
);
8202 do_FCVT_single_to_half (cpu
);
8213 /* 32 bit signed int to float. */
8215 scvtf32 (sim_cpu
*cpu
)
8217 unsigned rn
= INSTR (9, 5);
8218 unsigned sd
= INSTR (4, 0);
8220 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8221 aarch64_set_FP_float
8222 (cpu
, sd
, (float) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
));
8225 /* signed int to float. */
8227 scvtf (sim_cpu
*cpu
)
8229 unsigned rn
= INSTR (9, 5);
8230 unsigned sd
= INSTR (4, 0);
8232 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8233 aarch64_set_FP_float
8234 (cpu
, sd
, (float) aarch64_get_reg_s64 (cpu
, rn
, NO_SP
));
8237 /* 32 bit signed int to double. */
8239 scvtd32 (sim_cpu
*cpu
)
8241 unsigned rn
= INSTR (9, 5);
8242 unsigned sd
= INSTR (4, 0);
8244 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8245 aarch64_set_FP_double
8246 (cpu
, sd
, (double) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
));
8249 /* signed int to double. */
8251 scvtd (sim_cpu
*cpu
)
8253 unsigned rn
= INSTR (9, 5);
8254 unsigned sd
= INSTR (4, 0);
8256 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8257 aarch64_set_FP_double
8258 (cpu
, sd
, (double) aarch64_get_reg_s64 (cpu
, rn
, NO_SP
));
8261 static const float FLOAT_INT_MAX
= (float) INT_MAX
;
8262 static const float FLOAT_INT_MIN
= (float) INT_MIN
;
8263 static const double DOUBLE_INT_MAX
= (double) INT_MAX
;
8264 static const double DOUBLE_INT_MIN
= (double) INT_MIN
;
8265 static const float FLOAT_LONG_MAX
= (float) LONG_MAX
;
8266 static const float FLOAT_LONG_MIN
= (float) LONG_MIN
;
8267 static const double DOUBLE_LONG_MAX
= (double) LONG_MAX
;
8268 static const double DOUBLE_LONG_MIN
= (double) LONG_MIN
;
8272 static const float FLOAT_UINT_MAX
= (float) UINT_MAX
;
8273 static const float FLOAT_UINT_MIN
= (float) UINT_MIN
;
8274 static const double DOUBLE_UINT_MAX
= (double) UINT_MAX
;
8275 static const double DOUBLE_UINT_MIN
= (double) UINT_MIN
;
8276 static const float FLOAT_ULONG_MAX
= (float) ULONG_MAX
;
8277 static const float FLOAT_ULONG_MIN
= (float) ULONG_MIN
;
8278 static const double DOUBLE_ULONG_MAX
= (double) ULONG_MAX
;
8279 static const double DOUBLE_ULONG_MIN
= (double) ULONG_MIN
;
8281 /* Check for FP exception conditions:
8284 Out of Range raises IO and IX and saturates value
8285 Denormal raises ID and IX and sets to zero. */
8286 #define RAISE_EXCEPTIONS(F, VALUE, FTYPE, ITYPE) \
8289 switch (fpclassify (F)) \
8293 aarch64_set_FPSR (cpu, IO); \
8295 VALUE = ITYPE##_MAX; \
8297 VALUE = ITYPE##_MIN; \
8301 if (F >= FTYPE##_##ITYPE##_MAX) \
8303 aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX); \
8304 VALUE = ITYPE##_MAX; \
8306 else if (F <= FTYPE##_##ITYPE##_MIN) \
8308 aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX); \
8309 VALUE = ITYPE##_MIN; \
8313 case FP_SUBNORMAL: \
8314 aarch64_set_FPSR_bits (cpu, IO | IX | ID, IX | ID); \
8326 /* 32 bit convert float to signed int truncate towards zero. */
8328 fcvtszs32 (sim_cpu
*cpu
)
8330 unsigned sn
= INSTR (9, 5);
8331 unsigned rd
= INSTR (4, 0);
8332 /* TODO : check that this rounds toward zero. */
8333 float f
= aarch64_get_FP_float (cpu
, sn
);
8334 int32_t value
= (int32_t) f
;
8336 RAISE_EXCEPTIONS (f
, value
, FLOAT
, INT
);
8338 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8339 /* Avoid sign extension to 64 bit. */
8340 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) value
);
8343 /* 64 bit convert float to signed int truncate towards zero. */
8345 fcvtszs (sim_cpu
*cpu
)
8347 unsigned sn
= INSTR (9, 5);
8348 unsigned rd
= INSTR (4, 0);
8349 float f
= aarch64_get_FP_float (cpu
, sn
);
8350 int64_t value
= (int64_t) f
;
8352 RAISE_EXCEPTIONS (f
, value
, FLOAT
, LONG
);
8354 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8355 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, value
);
8358 /* 32 bit convert double to signed int truncate towards zero. */
8360 fcvtszd32 (sim_cpu
*cpu
)
8362 unsigned sn
= INSTR (9, 5);
8363 unsigned rd
= INSTR (4, 0);
8364 /* TODO : check that this rounds toward zero. */
8365 double d
= aarch64_get_FP_double (cpu
, sn
);
8366 int32_t value
= (int32_t) d
;
8368 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, INT
);
8370 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8371 /* Avoid sign extension to 64 bit. */
8372 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) value
);
8375 /* 64 bit convert double to signed int truncate towards zero. */
8377 fcvtszd (sim_cpu
*cpu
)
8379 unsigned sn
= INSTR (9, 5);
8380 unsigned rd
= INSTR (4, 0);
8381 /* TODO : check that this rounds toward zero. */
8382 double d
= aarch64_get_FP_double (cpu
, sn
);
8385 value
= (int64_t) d
;
8387 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, LONG
);
8389 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8390 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, value
);
8394 do_fcvtzu (sim_cpu
*cpu
)
8396 /* instr[31] = size: 32-bit (0), 64-bit (1)
8397 instr[30,23] = 00111100
8398 instr[22] = type: single (0)/ double (1)
8399 instr[21] = enable (0)/disable(1) precision
8400 instr[20,16] = 11001
8401 instr[15,10] = precision
8405 unsigned rs
= INSTR (9, 5);
8406 unsigned rd
= INSTR (4, 0);
8408 NYI_assert (30, 23, 0x3C);
8409 NYI_assert (20, 16, 0x19);
8411 if (INSTR (21, 21) != 1)
8412 /* Convert to fixed point. */
8415 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8418 /* Convert to unsigned 64-bit integer. */
8421 double d
= aarch64_get_FP_double (cpu
, rs
);
8422 uint64_t value
= (uint64_t) d
;
8424 /* Do not raise an exception if we have reached ULONG_MAX. */
8425 if (value
!= (1ULL << 63))
8426 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, ULONG
);
8428 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
8432 float f
= aarch64_get_FP_float (cpu
, rs
);
8433 uint64_t value
= (uint64_t) f
;
8435 /* Do not raise an exception if we have reached ULONG_MAX. */
8436 if (value
!= (1ULL << 63))
8437 RAISE_EXCEPTIONS (f
, value
, FLOAT
, ULONG
);
8439 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
8446 /* Convert to unsigned 32-bit integer. */
8449 double d
= aarch64_get_FP_double (cpu
, rs
);
8451 value
= (uint32_t) d
;
8452 /* Do not raise an exception if we have reached UINT_MAX. */
8453 if (value
!= (1UL << 31))
8454 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, UINT
);
8458 float f
= aarch64_get_FP_float (cpu
, rs
);
8460 value
= (uint32_t) f
;
8461 /* Do not raise an exception if we have reached UINT_MAX. */
8462 if (value
!= (1UL << 31))
8463 RAISE_EXCEPTIONS (f
, value
, FLOAT
, UINT
);
8466 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
8471 do_UCVTF (sim_cpu
*cpu
)
8473 /* instr[31] = size: 32-bit (0), 64-bit (1)
8474 instr[30,23] = 001 1110 0
8475 instr[22] = type: single (0)/ double (1)
8476 instr[21] = enable (0)/disable(1) precision
8477 instr[20,16] = 0 0011
8478 instr[15,10] = precision
8482 unsigned rs
= INSTR (9, 5);
8483 unsigned rd
= INSTR (4, 0);
8485 NYI_assert (30, 23, 0x3C);
8486 NYI_assert (20, 16, 0x03);
8488 if (INSTR (21, 21) != 1)
8491 /* FIXME: Add exception raising. */
8492 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8495 uint64_t value
= aarch64_get_reg_u64 (cpu
, rs
, NO_SP
);
8498 aarch64_set_FP_double (cpu
, rd
, (double) value
);
8500 aarch64_set_FP_float (cpu
, rd
, (float) value
);
8504 uint32_t value
= aarch64_get_reg_u32 (cpu
, rs
, NO_SP
);
8507 aarch64_set_FP_double (cpu
, rd
, (double) value
);
8509 aarch64_set_FP_float (cpu
, rd
, (float) value
);
8514 float_vector_move (sim_cpu
*cpu
)
8516 /* instr[31,17] == 100 1111 0101 0111
8517 instr[16] ==> direction 0=> to GR, 1=> from GR
8519 instr[9,5] ==> source
8520 instr[4,0] ==> dest. */
8522 unsigned rn
= INSTR (9, 5);
8523 unsigned rd
= INSTR (4, 0);
8525 NYI_assert (31, 17, 0x4F57);
8527 if (INSTR (15, 10) != 0)
8530 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8532 aarch64_set_vec_u64 (cpu
, rd
, 1, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
8534 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, aarch64_get_vec_u64 (cpu
, rn
, 1));
8538 dexSimpleFPIntegerConvert (sim_cpu
*cpu
)
8540 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
8542 instr[29] = S : 0 ==> OK, 1 ==> UNALLOC
8545 instr[23,22] = type : 00 ==> single, 01 ==> double, 1x ==> UNALLOC
8547 instr[20,19] = rmode
8548 instr[18,16] = opcode
8549 instr[15,10] = 10 0000 */
8551 uint32_t rmode_opcode
;
8557 if (INSTR (31, 17) == 0x4F57)
8559 float_vector_move (cpu
);
8563 size
= INSTR (31, 31);
8568 type
= INSTR (23, 22);
8572 rmode_opcode
= INSTR (20, 16);
8573 size_type
= (size
<< 1) | type
; /* 0==32f, 1==32d, 2==64f, 3==64d. */
8575 switch (rmode_opcode
)
8577 case 2: /* SCVTF. */
8580 case 0: scvtf32 (cpu
); return;
8581 case 1: scvtd32 (cpu
); return;
8582 case 2: scvtf (cpu
); return;
8583 case 3: scvtd (cpu
); return;
8586 case 6: /* FMOV GR, Vec. */
8589 case 0: gfmovs (cpu
); return;
8590 case 3: gfmovd (cpu
); return;
8591 default: HALT_UNALLOC
;
8594 case 7: /* FMOV vec, GR. */
8597 case 0: fgmovs (cpu
); return;
8598 case 3: fgmovd (cpu
); return;
8599 default: HALT_UNALLOC
;
8602 case 24: /* FCVTZS. */
8605 case 0: fcvtszs32 (cpu
); return;
8606 case 1: fcvtszd32 (cpu
); return;
8607 case 2: fcvtszs (cpu
); return;
8608 case 3: fcvtszd (cpu
); return;
8611 case 25: do_fcvtzu (cpu
); return;
8612 case 3: do_UCVTF (cpu
); return;
8614 case 0: /* FCVTNS. */
8615 case 1: /* FCVTNU. */
8616 case 4: /* FCVTAS. */
8617 case 5: /* FCVTAU. */
8618 case 8: /* FCVPTS. */
8619 case 9: /* FCVTPU. */
8620 case 16: /* FCVTMS. */
8621 case 17: /* FCVTMU. */
8628 set_flags_for_float_compare (sim_cpu
*cpu
, float fvalue1
, float fvalue2
)
8632 /* FIXME: Add exception raising. */
8633 if (isnan (fvalue1
) || isnan (fvalue2
))
8635 else if (isinf (fvalue1
) && isinf (fvalue2
))
8637 /* Subtracting two infinities may give a NaN. We only need to compare
8638 the signs, which we can get from isinf. */
8639 int result
= isinf (fvalue1
) - isinf (fvalue2
);
8643 else if (result
< 0)
8645 else /* (result > 0). */
8650 float result
= fvalue1
- fvalue2
;
8654 else if (result
< 0)
8656 else /* (result > 0). */
8660 aarch64_set_CPSR (cpu
, flags
);
8664 fcmps (sim_cpu
*cpu
)
8666 unsigned sm
= INSTR (20, 16);
8667 unsigned sn
= INSTR ( 9, 5);
8669 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8670 float fvalue2
= aarch64_get_FP_float (cpu
, sm
);
8672 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8673 set_flags_for_float_compare (cpu
, fvalue1
, fvalue2
);
8676 /* Float compare to zero -- Invalid Operation exception
8677 only on signaling NaNs. */
8679 fcmpzs (sim_cpu
*cpu
)
8681 unsigned sn
= INSTR ( 9, 5);
8682 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8684 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8685 set_flags_for_float_compare (cpu
, fvalue1
, 0.0f
);
8688 /* Float compare -- Invalid Operation exception on all NaNs. */
8690 fcmpes (sim_cpu
*cpu
)
8692 unsigned sm
= INSTR (20, 16);
8693 unsigned sn
= INSTR ( 9, 5);
8695 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8696 float fvalue2
= aarch64_get_FP_float (cpu
, sm
);
8698 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8699 set_flags_for_float_compare (cpu
, fvalue1
, fvalue2
);
8702 /* Float compare to zero -- Invalid Operation exception on all NaNs. */
8704 fcmpzes (sim_cpu
*cpu
)
8706 unsigned sn
= INSTR ( 9, 5);
8707 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8709 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8710 set_flags_for_float_compare (cpu
, fvalue1
, 0.0f
);
8714 set_flags_for_double_compare (sim_cpu
*cpu
, double dval1
, double dval2
)
8718 /* FIXME: Add exception raising. */
8719 if (isnan (dval1
) || isnan (dval2
))
8721 else if (isinf (dval1
) && isinf (dval2
))
8723 /* Subtracting two infinities may give a NaN. We only need to compare
8724 the signs, which we can get from isinf. */
8725 int result
= isinf (dval1
) - isinf (dval2
);
8729 else if (result
< 0)
8731 else /* (result > 0). */
8736 double result
= dval1
- dval2
;
8740 else if (result
< 0)
8742 else /* (result > 0). */
8746 aarch64_set_CPSR (cpu
, flags
);
8749 /* Double compare -- Invalid Operation exception only on signaling NaNs. */
8751 fcmpd (sim_cpu
*cpu
)
8753 unsigned sm
= INSTR (20, 16);
8754 unsigned sn
= INSTR ( 9, 5);
8756 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8757 double dvalue2
= aarch64_get_FP_double (cpu
, sm
);
8759 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8760 set_flags_for_double_compare (cpu
, dvalue1
, dvalue2
);
8763 /* Double compare to zero -- Invalid Operation exception
8764 only on signaling NaNs. */
8766 fcmpzd (sim_cpu
*cpu
)
8768 unsigned sn
= INSTR ( 9, 5);
8769 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8771 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8772 set_flags_for_double_compare (cpu
, dvalue1
, 0.0);
8775 /* Double compare -- Invalid Operation exception on all NaNs. */
8777 fcmped (sim_cpu
*cpu
)
8779 unsigned sm
= INSTR (20, 16);
8780 unsigned sn
= INSTR ( 9, 5);
8782 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8783 double dvalue2
= aarch64_get_FP_double (cpu
, sm
);
8785 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8786 set_flags_for_double_compare (cpu
, dvalue1
, dvalue2
);
8789 /* Double compare to zero -- Invalid Operation exception on all NaNs. */
8791 fcmpzed (sim_cpu
*cpu
)
8793 unsigned sn
= INSTR ( 9, 5);
8794 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8796 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8797 set_flags_for_double_compare (cpu
, dvalue1
, 0.0);
8801 dexSimpleFPCompare (sim_cpu
*cpu
)
8803 /* assert instr[28,25] == 1111
8804 instr[30:24:21:13,10] = 0011000
8805 instr[31] = M : 0 ==> OK, 1 ==> UNALLOC
8806 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
8807 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
8808 instr[15,14] ==> op : 00 ==> OK, ow ==> UNALLOC
8809 instr[4,0] ==> opcode2 : 00000 ==> FCMP, 10000 ==> FCMPE,
8810 01000 ==> FCMPZ, 11000 ==> FCMPEZ,
8813 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
8814 uint32_t type
= INSTR (23, 22);
8815 uint32_t op
= INSTR (15, 14);
8816 uint32_t op2_2_0
= INSTR (2, 0);
8830 /* dispatch on type and top 2 bits of opcode. */
8831 dispatch
= (type
<< 2) | INSTR (4, 3);
8835 case 0: fcmps (cpu
); return;
8836 case 1: fcmpzs (cpu
); return;
8837 case 2: fcmpes (cpu
); return;
8838 case 3: fcmpzes (cpu
); return;
8839 case 4: fcmpd (cpu
); return;
8840 case 5: fcmpzd (cpu
); return;
8841 case 6: fcmped (cpu
); return;
8842 case 7: fcmpzed (cpu
); return;
8847 do_scalar_FADDP (sim_cpu
*cpu
)
8849 /* instr [31,23] = 0111 1110 0
8850 instr [22] = single(0)/double(1)
8851 instr [21,10] = 11 0000 1101 10
8853 instr [4,0] = Fd. */
8855 unsigned Fn
= INSTR (9, 5);
8856 unsigned Fd
= INSTR (4, 0);
8858 NYI_assert (31, 23, 0x0FC);
8859 NYI_assert (21, 10, 0xC36);
8861 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8864 double val1
= aarch64_get_vec_double (cpu
, Fn
, 0);
8865 double val2
= aarch64_get_vec_double (cpu
, Fn
, 1);
8867 aarch64_set_FP_double (cpu
, Fd
, val1
+ val2
);
8871 float val1
= aarch64_get_vec_float (cpu
, Fn
, 0);
8872 float val2
= aarch64_get_vec_float (cpu
, Fn
, 1);
8874 aarch64_set_FP_float (cpu
, Fd
, val1
+ val2
);
8878 /* Floating point absolute difference. */
8881 do_scalar_FABD (sim_cpu
*cpu
)
8883 /* instr [31,23] = 0111 1110 1
8884 instr [22] = float(0)/double(1)
8887 instr [15,10] = 1101 01
8889 instr [4, 0] = Rd. */
8891 unsigned rm
= INSTR (20, 16);
8892 unsigned rn
= INSTR (9, 5);
8893 unsigned rd
= INSTR (4, 0);
8895 NYI_assert (31, 23, 0x0FD);
8896 NYI_assert (21, 21, 1);
8897 NYI_assert (15, 10, 0x35);
8899 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8901 aarch64_set_FP_double (cpu
, rd
,
8902 fabs (aarch64_get_FP_double (cpu
, rn
)
8903 - aarch64_get_FP_double (cpu
, rm
)));
8905 aarch64_set_FP_float (cpu
, rd
,
8906 fabsf (aarch64_get_FP_float (cpu
, rn
)
8907 - aarch64_get_FP_float (cpu
, rm
)));
8911 do_scalar_CMGT (sim_cpu
*cpu
)
8913 /* instr [31,21] = 0101 1110 111
8915 instr [15,10] = 00 1101
8917 instr [4, 0] = Rd. */
8919 unsigned rm
= INSTR (20, 16);
8920 unsigned rn
= INSTR (9, 5);
8921 unsigned rd
= INSTR (4, 0);
8923 NYI_assert (31, 21, 0x2F7);
8924 NYI_assert (15, 10, 0x0D);
8926 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8927 aarch64_set_vec_u64 (cpu
, rd
, 0,
8928 aarch64_get_vec_u64 (cpu
, rn
, 0) >
8929 aarch64_get_vec_u64 (cpu
, rm
, 0) ? -1L : 0L);
8933 do_scalar_USHR (sim_cpu
*cpu
)
8935 /* instr [31,23] = 0111 1111 0
8936 instr [22,16] = shift amount
8937 instr [15,10] = 0000 01
8939 instr [4, 0] = Rd. */
8941 unsigned amount
= 128 - INSTR (22, 16);
8942 unsigned rn
= INSTR (9, 5);
8943 unsigned rd
= INSTR (4, 0);
8945 NYI_assert (31, 23, 0x0FE);
8946 NYI_assert (15, 10, 0x01);
8948 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8949 aarch64_set_vec_u64 (cpu
, rd
, 0,
8950 aarch64_get_vec_u64 (cpu
, rn
, 0) >> amount
);
8954 do_scalar_SSHL (sim_cpu
*cpu
)
8956 /* instr [31,21] = 0101 1110 111
8958 instr [15,10] = 0100 01
8960 instr [4, 0] = Rd. */
8962 unsigned rm
= INSTR (20, 16);
8963 unsigned rn
= INSTR (9, 5);
8964 unsigned rd
= INSTR (4, 0);
8965 signed int shift
= aarch64_get_vec_s8 (cpu
, rm
, 0);
8967 NYI_assert (31, 21, 0x2F7);
8968 NYI_assert (15, 10, 0x11);
8970 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8972 aarch64_set_vec_s64 (cpu
, rd
, 0,
8973 aarch64_get_vec_s64 (cpu
, rn
, 0) << shift
);
8975 aarch64_set_vec_s64 (cpu
, rd
, 0,
8976 aarch64_get_vec_s64 (cpu
, rn
, 0) >> - shift
);
8979 /* Floating point scalar compare greater than or equal to 0. */
8981 do_scalar_FCMGE_zero (sim_cpu
*cpu
)
8983 /* instr [31,23] = 0111 1110 1
8984 instr [22,22] = size
8985 instr [21,16] = 1000 00
8986 instr [15,10] = 1100 10
8988 instr [4, 0] = Rd. */
8990 unsigned size
= INSTR (22, 22);
8991 unsigned rn
= INSTR (9, 5);
8992 unsigned rd
= INSTR (4, 0);
8994 NYI_assert (31, 23, 0x0FD);
8995 NYI_assert (21, 16, 0x20);
8996 NYI_assert (15, 10, 0x32);
8998 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9000 aarch64_set_vec_u64 (cpu
, rd
, 0,
9001 aarch64_get_vec_double (cpu
, rn
, 0) >= 0.0 ? -1 : 0);
9003 aarch64_set_vec_u32 (cpu
, rd
, 0,
9004 aarch64_get_vec_float (cpu
, rn
, 0) >= 0.0 ? -1 : 0);
9007 /* Floating point scalar compare less than or equal to 0. */
9009 do_scalar_FCMLE_zero (sim_cpu
*cpu
)
9011 /* instr [31,23] = 0111 1110 1
9012 instr [22,22] = size
9013 instr [21,16] = 1000 00
9014 instr [15,10] = 1101 10
9016 instr [4, 0] = Rd. */
9018 unsigned size
= INSTR (22, 22);
9019 unsigned rn
= INSTR (9, 5);
9020 unsigned rd
= INSTR (4, 0);
9022 NYI_assert (31, 23, 0x0FD);
9023 NYI_assert (21, 16, 0x20);
9024 NYI_assert (15, 10, 0x36);
9026 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9028 aarch64_set_vec_u64 (cpu
, rd
, 0,
9029 aarch64_get_vec_double (cpu
, rn
, 0) <= 0.0 ? -1 : 0);
9031 aarch64_set_vec_u32 (cpu
, rd
, 0,
9032 aarch64_get_vec_float (cpu
, rn
, 0) <= 0.0 ? -1 : 0);
9035 /* Floating point scalar compare greater than 0. */
9037 do_scalar_FCMGT_zero (sim_cpu
*cpu
)
9039 /* instr [31,23] = 0101 1110 1
9040 instr [22,22] = size
9041 instr [21,16] = 1000 00
9042 instr [15,10] = 1100 10
9044 instr [4, 0] = Rd. */
9046 unsigned size
= INSTR (22, 22);
9047 unsigned rn
= INSTR (9, 5);
9048 unsigned rd
= INSTR (4, 0);
9050 NYI_assert (31, 23, 0x0BD);
9051 NYI_assert (21, 16, 0x20);
9052 NYI_assert (15, 10, 0x32);
9054 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9056 aarch64_set_vec_u64 (cpu
, rd
, 0,
9057 aarch64_get_vec_double (cpu
, rn
, 0) > 0.0 ? -1 : 0);
9059 aarch64_set_vec_u32 (cpu
, rd
, 0,
9060 aarch64_get_vec_float (cpu
, rn
, 0) > 0.0 ? -1 : 0);
9063 /* Floating point scalar compare equal to 0. */
9065 do_scalar_FCMEQ_zero (sim_cpu
*cpu
)
9067 /* instr [31,23] = 0101 1110 1
9068 instr [22,22] = size
9069 instr [21,16] = 1000 00
9070 instr [15,10] = 1101 10
9072 instr [4, 0] = Rd. */
9074 unsigned size
= INSTR (22, 22);
9075 unsigned rn
= INSTR (9, 5);
9076 unsigned rd
= INSTR (4, 0);
9078 NYI_assert (31, 23, 0x0BD);
9079 NYI_assert (21, 16, 0x20);
9080 NYI_assert (15, 10, 0x36);
9082 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9084 aarch64_set_vec_u64 (cpu
, rd
, 0,
9085 aarch64_get_vec_double (cpu
, rn
, 0) == 0.0 ? -1 : 0);
9087 aarch64_set_vec_u32 (cpu
, rd
, 0,
9088 aarch64_get_vec_float (cpu
, rn
, 0) == 0.0 ? -1 : 0);
9091 /* Floating point scalar compare less than 0. */
9093 do_scalar_FCMLT_zero (sim_cpu
*cpu
)
9095 /* instr [31,23] = 0101 1110 1
9096 instr [22,22] = size
9097 instr [21,16] = 1000 00
9098 instr [15,10] = 1110 10
9100 instr [4, 0] = Rd. */
9102 unsigned size
= INSTR (22, 22);
9103 unsigned rn
= INSTR (9, 5);
9104 unsigned rd
= INSTR (4, 0);
9106 NYI_assert (31, 23, 0x0BD);
9107 NYI_assert (21, 16, 0x20);
9108 NYI_assert (15, 10, 0x3A);
9110 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9112 aarch64_set_vec_u64 (cpu
, rd
, 0,
9113 aarch64_get_vec_double (cpu
, rn
, 0) < 0.0 ? -1 : 0);
9115 aarch64_set_vec_u32 (cpu
, rd
, 0,
9116 aarch64_get_vec_float (cpu
, rn
, 0) < 0.0 ? -1 : 0);
9120 do_scalar_shift (sim_cpu
*cpu
)
9122 /* instr [31,23] = 0101 1111 0
9123 instr [22,16] = shift amount
9124 instr [15,10] = 0101 01 [SHL]
9125 instr [15,10] = 0000 01 [SSHR]
9127 instr [4, 0] = Rd. */
9129 unsigned rn
= INSTR (9, 5);
9130 unsigned rd
= INSTR (4, 0);
9133 NYI_assert (31, 23, 0x0BE);
9135 if (INSTR (22, 22) == 0)
9138 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9139 switch (INSTR (15, 10))
9141 case 0x01: /* SSHR */
9142 amount
= 128 - INSTR (22, 16);
9143 aarch64_set_vec_s64 (cpu
, rd
, 0,
9144 aarch64_get_vec_s64 (cpu
, rn
, 0) >> amount
);
9146 case 0x15: /* SHL */
9147 amount
= INSTR (22, 16) - 64;
9148 aarch64_set_vec_u64 (cpu
, rd
, 0,
9149 aarch64_get_vec_u64 (cpu
, rn
, 0) << amount
);
9156 /* FCMEQ FCMGT FCMGE. */
9158 do_scalar_FCM (sim_cpu
*cpu
)
9160 /* instr [31,30] = 01
9162 instr [28,24] = 1 1110
9167 instr [15,12] = 1110
9171 instr [4, 0] = Rd. */
9173 unsigned rm
= INSTR (20, 16);
9174 unsigned rn
= INSTR (9, 5);
9175 unsigned rd
= INSTR (4, 0);
9176 unsigned EUac
= (INSTR (23, 23) << 2) | (INSTR (29, 29) << 1) | INSTR (11, 11);
9181 NYI_assert (31, 30, 1);
9182 NYI_assert (28, 24, 0x1E);
9183 NYI_assert (21, 21, 1);
9184 NYI_assert (15, 12, 0xE);
9185 NYI_assert (10, 10, 1);
9187 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9190 double val1
= aarch64_get_FP_double (cpu
, rn
);
9191 double val2
= aarch64_get_FP_double (cpu
, rm
);
9196 result
= val1
== val2
;
9204 result
= val1
>= val2
;
9212 result
= val1
> val2
;
9219 aarch64_set_vec_u32 (cpu
, rd
, 0, result
? -1 : 0);
9223 val1
= aarch64_get_FP_float (cpu
, rn
);
9224 val2
= aarch64_get_FP_float (cpu
, rm
);
9229 result
= val1
== val2
;
9233 val1
= fabsf (val1
);
9234 val2
= fabsf (val2
);
9237 result
= val1
>= val2
;
9241 val1
= fabsf (val1
);
9242 val2
= fabsf (val2
);
9245 result
= val1
> val2
;
9252 aarch64_set_vec_u32 (cpu
, rd
, 0, result
? -1 : 0);
9255 /* An alias of DUP. */
9257 do_scalar_MOV (sim_cpu
*cpu
)
9259 /* instr [31,21] = 0101 1110 000
9260 instr [20,16] = imm5
9261 instr [15,10] = 0000 01
9263 instr [4, 0] = Rd. */
9265 unsigned rn
= INSTR (9, 5);
9266 unsigned rd
= INSTR (4, 0);
9269 NYI_assert (31, 21, 0x2F0);
9270 NYI_assert (15, 10, 0x01);
9272 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9276 index
= INSTR (20, 17);
9278 (cpu
, rd
, 0, aarch64_get_vec_u8 (cpu
, rn
, index
));
9280 else if (INSTR (17, 17))
9283 index
= INSTR (20, 18);
9285 (cpu
, rd
, 0, aarch64_get_vec_u16 (cpu
, rn
, index
));
9287 else if (INSTR (18, 18))
9290 index
= INSTR (20, 19);
9292 (cpu
, rd
, 0, aarch64_get_vec_u32 (cpu
, rn
, index
));
9294 else if (INSTR (19, 19))
9297 index
= INSTR (20, 20);
9299 (cpu
, rd
, 0, aarch64_get_vec_u64 (cpu
, rn
, index
));
9306 do_scalar_NEG (sim_cpu
*cpu
)
9308 /* instr [31,10] = 0111 1110 1110 0000 1011 10
9310 instr [4, 0] = Rd. */
9312 unsigned rn
= INSTR (9, 5);
9313 unsigned rd
= INSTR (4, 0);
9315 NYI_assert (31, 10, 0x1FB82E);
9317 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9318 aarch64_set_vec_u64 (cpu
, rd
, 0, - aarch64_get_vec_u64 (cpu
, rn
, 0));
9322 do_scalar_USHL (sim_cpu
*cpu
)
9324 /* instr [31,21] = 0111 1110 111
9326 instr [15,10] = 0100 01
9328 instr [4, 0] = Rd. */
9330 unsigned rm
= INSTR (20, 16);
9331 unsigned rn
= INSTR (9, 5);
9332 unsigned rd
= INSTR (4, 0);
9333 signed int shift
= aarch64_get_vec_s8 (cpu
, rm
, 0);
9335 NYI_assert (31, 21, 0x3F7);
9336 NYI_assert (15, 10, 0x11);
9338 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9340 aarch64_set_vec_u64 (cpu
, rd
, 0, aarch64_get_vec_u64 (cpu
, rn
, 0) << shift
);
9342 aarch64_set_vec_u64 (cpu
, rd
, 0, aarch64_get_vec_u64 (cpu
, rn
, 0) >> - shift
);
9346 do_double_add (sim_cpu
*cpu
)
9348 /* instr [31,21] = 0101 1110 111
9350 instr [15,10] = 1000 01
9352 instr [4,0] = Fd. */
9359 NYI_assert (31, 21, 0x2F7);
9360 NYI_assert (15, 10, 0x21);
9364 Fn
= INSTR (20, 16);
9366 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9367 val1
= aarch64_get_FP_double (cpu
, Fm
);
9368 val2
= aarch64_get_FP_double (cpu
, Fn
);
9370 aarch64_set_FP_double (cpu
, Fd
, val1
+ val2
);
9374 do_scalar_UCVTF (sim_cpu
*cpu
)
9376 /* instr [31,23] = 0111 1110 0
9377 instr [22] = single(0)/double(1)
9378 instr [21,10] = 10 0001 1101 10
9380 instr [4,0] = rd. */
9382 unsigned rn
= INSTR (9, 5);
9383 unsigned rd
= INSTR (4, 0);
9385 NYI_assert (31, 23, 0x0FC);
9386 NYI_assert (21, 10, 0x876);
9388 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9391 uint64_t val
= aarch64_get_vec_u64 (cpu
, rn
, 0);
9393 aarch64_set_vec_double (cpu
, rd
, 0, (double) val
);
9397 uint32_t val
= aarch64_get_vec_u32 (cpu
, rn
, 0);
9399 aarch64_set_vec_float (cpu
, rd
, 0, (float) val
);
9404 do_scalar_vec (sim_cpu
*cpu
)
9406 /* instr [30] = 1. */
9407 /* instr [28,25] = 1111. */
9408 switch (INSTR (31, 23))
9411 switch (INSTR (15, 10))
9413 case 0x01: do_scalar_MOV (cpu
); return;
9414 case 0x39: do_scalar_FCM (cpu
); return;
9415 case 0x3B: do_scalar_FCM (cpu
); return;
9419 case 0xBE: do_scalar_shift (cpu
); return;
9422 switch (INSTR (15, 10))
9425 switch (INSTR (21, 16))
9427 case 0x30: do_scalar_FADDP (cpu
); return;
9428 case 0x21: do_scalar_UCVTF (cpu
); return;
9431 case 0x39: do_scalar_FCM (cpu
); return;
9432 case 0x3B: do_scalar_FCM (cpu
); return;
9437 switch (INSTR (15, 10))
9439 case 0x0D: do_scalar_CMGT (cpu
); return;
9440 case 0x11: do_scalar_USHL (cpu
); return;
9441 case 0x2E: do_scalar_NEG (cpu
); return;
9442 case 0x32: do_scalar_FCMGE_zero (cpu
); return;
9443 case 0x35: do_scalar_FABD (cpu
); return;
9444 case 0x36: do_scalar_FCMLE_zero (cpu
); return;
9445 case 0x39: do_scalar_FCM (cpu
); return;
9446 case 0x3B: do_scalar_FCM (cpu
); return;
9451 case 0xFE: do_scalar_USHR (cpu
); return;
9454 switch (INSTR (15, 10))
9456 case 0x21: do_double_add (cpu
); return;
9457 case 0x11: do_scalar_SSHL (cpu
); return;
9458 case 0x32: do_scalar_FCMGT_zero (cpu
); return;
9459 case 0x36: do_scalar_FCMEQ_zero (cpu
); return;
9460 case 0x3A: do_scalar_FCMLT_zero (cpu
); return;
9471 dexAdvSIMD1 (sim_cpu
*cpu
)
9473 /* instr [28,25] = 1 111. */
9475 /* We are currently only interested in the basic
9476 scalar fp routines which all have bit 30 = 0. */
9478 do_scalar_vec (cpu
);
9480 /* instr[24] is set for FP data processing 3-source and clear for
9481 all other basic scalar fp instruction groups. */
9482 else if (INSTR (24, 24))
9483 dexSimpleFPDataProc3Source (cpu
);
9485 /* instr[21] is clear for floating <-> fixed conversions and set for
9486 all other basic scalar fp instruction groups. */
9487 else if (!INSTR (21, 21))
9488 dexSimpleFPFixedConvert (cpu
);
9490 /* instr[11,10] : 01 ==> cond compare, 10 ==> Data Proc 2 Source
9491 11 ==> cond select, 00 ==> other. */
9493 switch (INSTR (11, 10))
9495 case 1: dexSimpleFPCondCompare (cpu
); return;
9496 case 2: dexSimpleFPDataProc2Source (cpu
); return;
9497 case 3: dexSimpleFPCondSelect (cpu
); return;
9500 /* Now an ordered cascade of tests.
9501 FP immediate has instr [12] == 1.
9502 FP compare has instr [13] == 1.
9503 FP Data Proc 1 Source has instr [14] == 1.
9504 FP floating <--> integer conversions has instr [15] == 0. */
9506 dexSimpleFPImmediate (cpu
);
9508 else if (INSTR (13, 13))
9509 dexSimpleFPCompare (cpu
);
9511 else if (INSTR (14, 14))
9512 dexSimpleFPDataProc1Source (cpu
);
9514 else if (!INSTR (15, 15))
9515 dexSimpleFPIntegerConvert (cpu
);
9518 /* If we get here then instr[15] == 1 which means UNALLOC. */
9523 /* PC relative addressing. */
9526 pcadr (sim_cpu
*cpu
)
9528 /* instr[31] = op : 0 ==> ADR, 1 ==> ADRP
9529 instr[30,29] = immlo
9530 instr[23,5] = immhi. */
9532 unsigned rd
= INSTR (4, 0);
9533 uint32_t isPage
= INSTR (31, 31);
9534 union { int64_t u64
; uint64_t s64
; } imm
;
9537 imm
.s64
= simm64 (aarch64_get_instr (cpu
), 23, 5);
9539 offset
= (offset
<< 2) | INSTR (30, 29);
9541 address
= aarch64_get_PC (cpu
);
9549 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9550 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, address
+ offset
);
9553 /* Specific decode and execute for group Data Processing Immediate. */
9556 dexPCRelAddressing (sim_cpu
*cpu
)
9558 /* assert instr[28,24] = 10000. */
9562 /* Immediate logical.
9563 The bimm32/64 argument is constructed by replicating a 2, 4, 8,
9564 16, 32 or 64 bit sequence pulled out at decode and possibly
9567 N.B. the output register (dest) can normally be Xn or SP
9568 the exception occurs for flag setting instructions which may
9569 only use Xn for the output (dest). The input register can
9572 /* 32 bit and immediate. */
9574 and32 (sim_cpu
*cpu
, uint32_t bimm
)
9576 unsigned rn
= INSTR (9, 5);
9577 unsigned rd
= INSTR (4, 0);
9579 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9580 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9581 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
) & bimm
);
9584 /* 64 bit and immediate. */
9586 and64 (sim_cpu
*cpu
, uint64_t bimm
)
9588 unsigned rn
= INSTR (9, 5);
9589 unsigned rd
= INSTR (4, 0);
9591 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9592 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9593 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) & bimm
);
9596 /* 32 bit and immediate set flags. */
9598 ands32 (sim_cpu
*cpu
, uint32_t bimm
)
9600 unsigned rn
= INSTR (9, 5);
9601 unsigned rd
= INSTR (4, 0);
9603 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9604 uint32_t value2
= bimm
;
9606 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9607 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9608 set_flags_for_binop32 (cpu
, value1
& value2
);
9611 /* 64 bit and immediate set flags. */
9613 ands64 (sim_cpu
*cpu
, uint64_t bimm
)
9615 unsigned rn
= INSTR (9, 5);
9616 unsigned rd
= INSTR (4, 0);
9618 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9619 uint64_t value2
= bimm
;
9621 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9622 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9623 set_flags_for_binop64 (cpu
, value1
& value2
);
9626 /* 32 bit exclusive or immediate. */
9628 eor32 (sim_cpu
*cpu
, uint32_t bimm
)
9630 unsigned rn
= INSTR (9, 5);
9631 unsigned rd
= INSTR (4, 0);
9633 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9634 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9635 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
) ^ bimm
);
9638 /* 64 bit exclusive or immediate. */
9640 eor64 (sim_cpu
*cpu
, uint64_t bimm
)
9642 unsigned rn
= INSTR (9, 5);
9643 unsigned rd
= INSTR (4, 0);
9645 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9646 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9647 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) ^ bimm
);
9650 /* 32 bit or immediate. */
9652 orr32 (sim_cpu
*cpu
, uint32_t bimm
)
9654 unsigned rn
= INSTR (9, 5);
9655 unsigned rd
= INSTR (4, 0);
9657 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9658 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9659 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
) | bimm
);
9662 /* 64 bit or immediate. */
9664 orr64 (sim_cpu
*cpu
, uint64_t bimm
)
9666 unsigned rn
= INSTR (9, 5);
9667 unsigned rd
= INSTR (4, 0);
9669 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9670 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9671 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) | bimm
);
9674 /* Logical shifted register.
9675 These allow an optional LSL, ASR, LSR or ROR to the second source
9676 register with a count up to the register bit count.
9677 N.B register args may not be SP. */
9679 /* 32 bit AND shifted register. */
9681 and32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9683 unsigned rm
= INSTR (20, 16);
9684 unsigned rn
= INSTR (9, 5);
9685 unsigned rd
= INSTR (4, 0);
9687 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9689 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9690 & shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9693 /* 64 bit AND shifted register. */
9695 and64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9697 unsigned rm
= INSTR (20, 16);
9698 unsigned rn
= INSTR (9, 5);
9699 unsigned rd
= INSTR (4, 0);
9701 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9703 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9704 & shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9707 /* 32 bit AND shifted register setting flags. */
9709 ands32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9711 unsigned rm
= INSTR (20, 16);
9712 unsigned rn
= INSTR (9, 5);
9713 unsigned rd
= INSTR (4, 0);
9715 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9716 uint32_t value2
= shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
9719 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9720 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9721 set_flags_for_binop32 (cpu
, value1
& value2
);
9724 /* 64 bit AND shifted register setting flags. */
9726 ands64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9728 unsigned rm
= INSTR (20, 16);
9729 unsigned rn
= INSTR (9, 5);
9730 unsigned rd
= INSTR (4, 0);
9732 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9733 uint64_t value2
= shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
9736 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9737 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9738 set_flags_for_binop64 (cpu
, value1
& value2
);
9741 /* 32 bit BIC shifted register. */
9743 bic32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9745 unsigned rm
= INSTR (20, 16);
9746 unsigned rn
= INSTR (9, 5);
9747 unsigned rd
= INSTR (4, 0);
9749 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9751 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9752 & ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9755 /* 64 bit BIC shifted register. */
9757 bic64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9759 unsigned rm
= INSTR (20, 16);
9760 unsigned rn
= INSTR (9, 5);
9761 unsigned rd
= INSTR (4, 0);
9763 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9765 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9766 & ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9769 /* 32 bit BIC shifted register setting flags. */
9771 bics32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9773 unsigned rm
= INSTR (20, 16);
9774 unsigned rn
= INSTR (9, 5);
9775 unsigned rd
= INSTR (4, 0);
9777 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9778 uint32_t value2
= ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
9781 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9782 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9783 set_flags_for_binop32 (cpu
, value1
& value2
);
9786 /* 64 bit BIC shifted register setting flags. */
9788 bics64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9790 unsigned rm
= INSTR (20, 16);
9791 unsigned rn
= INSTR (9, 5);
9792 unsigned rd
= INSTR (4, 0);
9794 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9795 uint64_t value2
= ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
9798 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9799 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9800 set_flags_for_binop64 (cpu
, value1
& value2
);
9803 /* 32 bit EON shifted register. */
9805 eon32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9807 unsigned rm
= INSTR (20, 16);
9808 unsigned rn
= INSTR (9, 5);
9809 unsigned rd
= INSTR (4, 0);
9811 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9813 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9814 ^ ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9817 /* 64 bit EON shifted register. */
9819 eon64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9821 unsigned rm
= INSTR (20, 16);
9822 unsigned rn
= INSTR (9, 5);
9823 unsigned rd
= INSTR (4, 0);
9825 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9827 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9828 ^ ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9831 /* 32 bit EOR shifted register. */
9833 eor32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9835 unsigned rm
= INSTR (20, 16);
9836 unsigned rn
= INSTR (9, 5);
9837 unsigned rd
= INSTR (4, 0);
9839 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9841 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9842 ^ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9845 /* 64 bit EOR shifted register. */
9847 eor64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9849 unsigned rm
= INSTR (20, 16);
9850 unsigned rn
= INSTR (9, 5);
9851 unsigned rd
= INSTR (4, 0);
9853 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9855 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9856 ^ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9859 /* 32 bit ORR shifted register. */
9861 orr32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9863 unsigned rm
= INSTR (20, 16);
9864 unsigned rn
= INSTR (9, 5);
9865 unsigned rd
= INSTR (4, 0);
9867 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9869 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9870 | shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9873 /* 64 bit ORR shifted register. */
9875 orr64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9877 unsigned rm
= INSTR (20, 16);
9878 unsigned rn
= INSTR (9, 5);
9879 unsigned rd
= INSTR (4, 0);
9881 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9883 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9884 | shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9887 /* 32 bit ORN shifted register. */
9889 orn32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9891 unsigned rm
= INSTR (20, 16);
9892 unsigned rn
= INSTR (9, 5);
9893 unsigned rd
= INSTR (4, 0);
9895 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9897 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9898 | ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9901 /* 64 bit ORN shifted register. */
9903 orn64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9905 unsigned rm
= INSTR (20, 16);
9906 unsigned rn
= INSTR (9, 5);
9907 unsigned rd
= INSTR (4, 0);
9909 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9911 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9912 | ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9916 dexLogicalImmediate (sim_cpu
*cpu
)
9918 /* assert instr[28,23] = 1001000
9919 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9920 instr[30,29] = op : 0 ==> AND, 1 ==> ORR, 2 ==> EOR, 3 ==> ANDS
9921 instr[22] = N : used to construct immediate mask
9927 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
9928 uint32_t size
= INSTR (31, 31);
9929 uint32_t N
= INSTR (22, 22);
9930 /* uint32_t immr = INSTR (21, 16);. */
9931 /* uint32_t imms = INSTR (15, 10);. */
9932 uint32_t index
= INSTR (22, 10);
9933 uint64_t bimm64
= LITable
[index
];
9934 uint32_t dispatch
= INSTR (30, 29);
9944 uint32_t bimm
= (uint32_t) bimm64
;
9948 case 0: and32 (cpu
, bimm
); return;
9949 case 1: orr32 (cpu
, bimm
); return;
9950 case 2: eor32 (cpu
, bimm
); return;
9951 case 3: ands32 (cpu
, bimm
); return;
9958 case 0: and64 (cpu
, bimm64
); return;
9959 case 1: orr64 (cpu
, bimm64
); return;
9960 case 2: eor64 (cpu
, bimm64
); return;
9961 case 3: ands64 (cpu
, bimm64
); return;
9968 The uimm argument is a 16 bit value to be inserted into the
9969 target register the pos argument locates the 16 bit word in the
9970 dest register i.e. it is in {0, 1} for 32 bit and {0, 1, 2,
9972 N.B register arg may not be SP so it should be.
9973 accessed using the setGZRegisterXXX accessors. */
9975 /* 32 bit move 16 bit immediate zero remaining shorts. */
9977 movz32 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9979 unsigned rd
= INSTR (4, 0);
9981 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9982 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val
<< (pos
* 16));
9985 /* 64 bit move 16 bit immediate zero remaining shorts. */
9987 movz64 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9989 unsigned rd
= INSTR (4, 0);
9991 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9992 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, ((uint64_t) val
) << (pos
* 16));
9995 /* 32 bit move 16 bit immediate negated. */
9997 movn32 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9999 unsigned rd
= INSTR (4, 0);
10001 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10002 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, ((val
<< (pos
* 16)) ^ 0xffffffffU
));
10005 /* 64 bit move 16 bit immediate negated. */
10007 movn64 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
10009 unsigned rd
= INSTR (4, 0);
10011 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10012 aarch64_set_reg_u64
10013 (cpu
, rd
, NO_SP
, ((((uint64_t) val
) << (pos
* 16))
10014 ^ 0xffffffffffffffffULL
));
10017 /* 32 bit move 16 bit immediate keep remaining shorts. */
10019 movk32 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
10021 unsigned rd
= INSTR (4, 0);
10022 uint32_t current
= aarch64_get_reg_u32 (cpu
, rd
, NO_SP
);
10023 uint32_t value
= val
<< (pos
* 16);
10024 uint32_t mask
= ~(0xffffU
<< (pos
* 16));
10026 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10027 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (value
| (current
& mask
)));
10030 /* 64 bit move 16 it immediate keep remaining shorts. */
10032 movk64 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
10034 unsigned rd
= INSTR (4, 0);
10035 uint64_t current
= aarch64_get_reg_u64 (cpu
, rd
, NO_SP
);
10036 uint64_t value
= (uint64_t) val
<< (pos
* 16);
10037 uint64_t mask
= ~(0xffffULL
<< (pos
* 16));
10039 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10040 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (value
| (current
& mask
)));
10044 dexMoveWideImmediate (sim_cpu
*cpu
)
10046 /* assert instr[28:23] = 100101
10047 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
10048 instr[30,29] = op : 0 ==> MOVN, 1 ==> UNALLOC, 2 ==> MOVZ, 3 ==> MOVK
10049 instr[22,21] = shift : 00 == LSL#0, 01 = LSL#16, 10 = LSL#32, 11 = LSL#48
10050 instr[20,5] = uimm16
10053 /* N.B. the (multiple of 16) shift is applied by the called routine,
10054 we just pass the multiplier. */
10057 uint32_t size
= INSTR (31, 31);
10058 uint32_t op
= INSTR (30, 29);
10059 uint32_t shift
= INSTR (22, 21);
10061 /* 32 bit can only shift 0 or 1 lot of 16.
10062 anything else is an unallocated instruction. */
10063 if (size
== 0 && (shift
> 1))
10069 imm
= INSTR (20, 5);
10074 movn32 (cpu
, imm
, shift
);
10076 movz32 (cpu
, imm
, shift
);
10078 movk32 (cpu
, imm
, shift
);
10083 movn64 (cpu
, imm
, shift
);
10085 movz64 (cpu
, imm
, shift
);
10087 movk64 (cpu
, imm
, shift
);
10091 /* Bitfield operations.
10092 These take a pair of bit positions r and s which are in {0..31}
10093 or {0..63} depending on the instruction word size.
10094 N.B register args may not be SP. */
10096 /* OK, we start with ubfm which just needs to pick
10097 some bits out of source zero the rest and write
10098 the result to dest. Just need two logical shifts. */
10100 /* 32 bit bitfield move, left and right of affected zeroed
10101 if r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
10103 ubfm32 (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
10106 unsigned rn
= INSTR (9, 5);
10107 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
10109 /* Pick either s+1-r or s+1 consecutive bits out of the original word. */
10112 /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
10113 We want only bits s:xxx:r at the bottom of the word
10114 so we LSL bit s up to bit 31 i.e. by 31 - s
10115 and then we LSR to bring bit 31 down to bit s - r
10116 i.e. by 31 + r - s. */
10118 value
>>= 31 + r
- s
;
10122 /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0
10123 We want only bits s:xxx:0 starting at it 31-(r-1)
10124 so we LSL bit s up to bit 31 i.e. by 31 - s
10125 and then we LSL to bring bit 31 down to 31-(r-1)+s
10126 i.e. by r - (s + 1). */
10128 value
>>= r
- (s
+ 1);
10131 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10133 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
10136 /* 64 bit bitfield move, left and right of affected zeroed
10137 if r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
10139 ubfm (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
10142 unsigned rn
= INSTR (9, 5);
10143 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
10147 /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
10148 We want only bits s:xxx:r at the bottom of the word.
10149 So we LSL bit s up to bit 63 i.e. by 63 - s
10150 and then we LSR to bring bit 63 down to bit s - r
10151 i.e. by 63 + r - s. */
10153 value
>>= 63 + r
- s
;
10157 /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0.
10158 We want only bits s:xxx:0 starting at it 63-(r-1).
10159 So we LSL bit s up to bit 63 i.e. by 63 - s
10160 and then we LSL to bring bit 63 down to 63-(r-1)+s
10161 i.e. by r - (s + 1). */
10163 value
>>= r
- (s
+ 1);
10166 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10168 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
10171 /* The signed versions need to insert sign bits
10172 on the left of the inserted bit field. so we do
10173 much the same as the unsigned version except we
10174 use an arithmetic shift right -- this just means
10175 we need to operate on signed values. */
10177 /* 32 bit bitfield move, left of affected sign-extended, right zeroed. */
10178 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
10180 sbfm32 (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
10183 unsigned rn
= INSTR (9, 5);
10184 /* as per ubfm32 but use an ASR instead of an LSR. */
10185 int32_t value
= aarch64_get_reg_s32 (cpu
, rn
, NO_SP
);
10190 value
>>= 31 + r
- s
;
10195 value
>>= r
- (s
+ 1);
10198 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10200 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) value
);
10203 /* 64 bit bitfield move, left of affected sign-extended, right zeroed. */
10204 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
10206 sbfm (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
10209 unsigned rn
= INSTR (9, 5);
10210 /* acpu per ubfm but use an ASR instead of an LSR. */
10211 int64_t value
= aarch64_get_reg_s64 (cpu
, rn
, NO_SP
);
10216 value
>>= 63 + r
- s
;
10221 value
>>= r
- (s
+ 1);
10224 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10226 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, value
);
10229 /* Finally, these versions leave non-affected bits
10230 as is. so we need to generate the bits as per
10231 ubfm and also generate a mask to pick the
10232 bits from the original and computed values. */
10234 /* 32 bit bitfield move, non-affected bits left as is.
10235 If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
10237 bfm32 (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
10239 unsigned rn
= INSTR (9, 5);
10240 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
10241 uint32_t mask
= -1;
10245 /* Pick either s+1-r or s+1 consecutive bits out of the original word. */
10248 /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
10249 We want only bits s:xxx:r at the bottom of the word
10250 so we LSL bit s up to bit 31 i.e. by 31 - s
10251 and then we LSR to bring bit 31 down to bit s - r
10252 i.e. by 31 + r - s. */
10254 value
>>= 31 + r
- s
;
10255 /* the mask must include the same bits. */
10257 mask
>>= 31 + r
- s
;
10261 /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0.
10262 We want only bits s:xxx:0 starting at it 31-(r-1)
10263 so we LSL bit s up to bit 31 i.e. by 31 - s
10264 and then we LSL to bring bit 31 down to 31-(r-1)+s
10265 i.e. by r - (s + 1). */
10267 value
>>= r
- (s
+ 1);
10268 /* The mask must include the same bits. */
10270 mask
>>= r
- (s
+ 1);
10274 value2
= aarch64_get_reg_u32 (cpu
, rd
, NO_SP
);
10279 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10280 aarch64_set_reg_u64
10281 (cpu
, rd
, NO_SP
, (aarch64_get_reg_u32 (cpu
, rd
, NO_SP
) & ~mask
) | value
);
10284 /* 64 bit bitfield move, non-affected bits left as is.
10285 If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
10287 bfm (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
10290 unsigned rn
= INSTR (9, 5);
10291 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
10292 uint64_t mask
= 0xffffffffffffffffULL
;
10296 /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
10297 We want only bits s:xxx:r at the bottom of the word
10298 so we LSL bit s up to bit 63 i.e. by 63 - s
10299 and then we LSR to bring bit 63 down to bit s - r
10300 i.e. by 63 + r - s. */
10302 value
>>= 63 + r
- s
;
10303 /* The mask must include the same bits. */
10305 mask
>>= 63 + r
- s
;
10309 /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0
10310 We want only bits s:xxx:0 starting at it 63-(r-1)
10311 so we LSL bit s up to bit 63 i.e. by 63 - s
10312 and then we LSL to bring bit 63 down to 63-(r-1)+s
10313 i.e. by r - (s + 1). */
10315 value
>>= r
- (s
+ 1);
10316 /* The mask must include the same bits. */
10318 mask
>>= r
- (s
+ 1);
10321 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10323 aarch64_set_reg_u64
10324 (cpu
, rd
, NO_SP
, (aarch64_get_reg_u64 (cpu
, rd
, NO_SP
) & ~mask
) | value
);
10328 dexBitfieldImmediate (sim_cpu
*cpu
)
10330 /* assert instr[28:23] = 100110
10331 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
10332 instr[30,29] = op : 0 ==> SBFM, 1 ==> BFM, 2 ==> UBFM, 3 ==> UNALLOC
10333 instr[22] = N : must be 0 for 32 bit, 1 for 64 bit ow UNALLOC
10334 instr[21,16] = immr : 0xxxxx for 32 bit, xxxxxx for 64 bit
10335 instr[15,10] = imms : 0xxxxx for 32 bit, xxxxxx for 64 bit
10339 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
10342 uint32_t size
= INSTR (31, 31);
10343 uint32_t N
= INSTR (22, 22);
10344 /* 32 bit operations must have immr[5] = 0 and imms[5] = 0. */
10345 /* or else we have an UNALLOC. */
10346 uint32_t immr
= INSTR (21, 16);
10351 if (!size
&& uimm (immr
, 5, 5))
10354 imms
= INSTR (15, 10);
10355 if (!size
&& uimm (imms
, 5, 5))
10358 /* Switch on combined size and op. */
10359 dispatch
= INSTR (31, 29);
10362 case 0: sbfm32 (cpu
, immr
, imms
); return;
10363 case 1: bfm32 (cpu
, immr
, imms
); return;
10364 case 2: ubfm32 (cpu
, immr
, imms
); return;
10365 case 4: sbfm (cpu
, immr
, imms
); return;
10366 case 5: bfm (cpu
, immr
, imms
); return;
10367 case 6: ubfm (cpu
, immr
, imms
); return;
10368 default: HALT_UNALLOC
;
10373 do_EXTR_32 (sim_cpu
*cpu
)
10375 /* instr[31:21] = 00010011100
10377 instr[15,10] = imms : 0xxxxx for 32 bit
10380 unsigned rm
= INSTR (20, 16);
10381 unsigned imms
= INSTR (15, 10) & 31;
10382 unsigned rn
= INSTR ( 9, 5);
10383 unsigned rd
= INSTR ( 4, 0);
10387 val1
= aarch64_get_reg_u32 (cpu
, rm
, NO_SP
);
10389 val2
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
10390 val2
<<= (32 - imms
);
10392 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10393 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val1
| val2
);
10397 do_EXTR_64 (sim_cpu
*cpu
)
10399 /* instr[31:21] = 10010011100
10401 instr[15,10] = imms
10404 unsigned rm
= INSTR (20, 16);
10405 unsigned imms
= INSTR (15, 10) & 63;
10406 unsigned rn
= INSTR ( 9, 5);
10407 unsigned rd
= INSTR ( 4, 0);
10410 val
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
10412 val
|= (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) << (64 - imms
));
10414 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val
);
10418 dexExtractImmediate (sim_cpu
*cpu
)
10420 /* assert instr[28:23] = 100111
10421 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
10422 instr[30,29] = op21 : 0 ==> EXTR, 1,2,3 ==> UNALLOC
10423 instr[22] = N : must be 0 for 32 bit, 1 for 64 bit or UNALLOC
10424 instr[21] = op0 : must be 0 or UNALLOC
10426 instr[15,10] = imms : 0xxxxx for 32 bit, xxxxxx for 64 bit
10430 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
10431 /* 64 bit operations must have N = 1 or else we have an UNALLOC. */
10433 uint32_t size
= INSTR (31, 31);
10434 uint32_t N
= INSTR (22, 22);
10435 /* 32 bit operations must have imms[5] = 0
10436 or else we have an UNALLOC. */
10437 uint32_t imms
= INSTR (15, 10);
10442 if (!size
&& uimm (imms
, 5, 5))
10445 /* Switch on combined size and op. */
10446 dispatch
= INSTR (31, 29);
10451 else if (dispatch
== 4)
10454 else if (dispatch
== 1)
10461 dexDPImm (sim_cpu
*cpu
)
10463 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
10464 assert group == GROUP_DPIMM_1000 || grpoup == GROUP_DPIMM_1001
10465 bits [25,23] of a DPImm are the secondary dispatch vector. */
10466 uint32_t group2
= dispatchDPImm (aarch64_get_instr (cpu
));
10470 case DPIMM_PCADR_000
:
10471 case DPIMM_PCADR_001
:
10472 dexPCRelAddressing (cpu
);
10475 case DPIMM_ADDSUB_010
:
10476 case DPIMM_ADDSUB_011
:
10477 dexAddSubtractImmediate (cpu
);
10480 case DPIMM_LOG_100
:
10481 dexLogicalImmediate (cpu
);
10484 case DPIMM_MOV_101
:
10485 dexMoveWideImmediate (cpu
);
10488 case DPIMM_BITF_110
:
10489 dexBitfieldImmediate (cpu
);
10492 case DPIMM_EXTR_111
:
10493 dexExtractImmediate (cpu
);
10497 /* Should never reach here. */
10503 dexLoadUnscaledImmediate (sim_cpu
*cpu
)
10505 /* instr[29,24] == 111_00
10508 instr[31,30] = size
10511 instr[20,12] = simm9
10512 instr[9,5] = rn may be SP. */
10513 /* unsigned rt = INSTR (4, 0); */
10514 uint32_t V
= INSTR (26, 26);
10515 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
10516 int32_t imm
= simm32 (aarch64_get_instr (cpu
), 20, 12);
10520 /* GReg operations. */
10523 case 0: sturb (cpu
, imm
); return;
10524 case 1: ldurb32 (cpu
, imm
); return;
10525 case 2: ldursb64 (cpu
, imm
); return;
10526 case 3: ldursb32 (cpu
, imm
); return;
10527 case 4: sturh (cpu
, imm
); return;
10528 case 5: ldurh32 (cpu
, imm
); return;
10529 case 6: ldursh64 (cpu
, imm
); return;
10530 case 7: ldursh32 (cpu
, imm
); return;
10531 case 8: stur32 (cpu
, imm
); return;
10532 case 9: ldur32 (cpu
, imm
); return;
10533 case 10: ldursw (cpu
, imm
); return;
10534 case 12: stur64 (cpu
, imm
); return;
10535 case 13: ldur64 (cpu
, imm
); return;
10548 /* FReg operations. */
10551 case 2: fsturq (cpu
, imm
); return;
10552 case 3: fldurq (cpu
, imm
); return;
10553 case 8: fsturs (cpu
, imm
); return;
10554 case 9: fldurs (cpu
, imm
); return;
10555 case 12: fsturd (cpu
, imm
); return;
10556 case 13: fldurd (cpu
, imm
); return;
10558 case 0: /* STUR 8 bit FP. */
10559 case 1: /* LDUR 8 bit FP. */
10560 case 4: /* STUR 16 bit FP. */
10561 case 5: /* LDUR 8 bit FP. */
10575 /* N.B. A preliminary note regarding all the ldrs<x>32
10578 The signed value loaded by these instructions is cast to unsigned
10579 before being assigned to aarch64_get_reg_u64 (cpu, N) i.e. to the
10580 64 bit element of the GReg union. this performs a 32 bit sign extension
10581 (as required) but avoids 64 bit sign extension, thus ensuring that the
10582 top half of the register word is zero. this is what the spec demands
10583 when a 32 bit load occurs. */
10585 /* 32 bit load sign-extended byte scaled unsigned 12 bit. */
10587 ldrsb32_abs (sim_cpu
*cpu
, uint32_t offset
)
10589 unsigned int rn
= INSTR (9, 5);
10590 unsigned int rt
= INSTR (4, 0);
10592 /* The target register may not be SP but the source may be
10593 there is no scaling required for a byte load. */
10594 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
;
10595 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
10596 (int64_t) aarch64_get_mem_s8 (cpu
, address
));
10599 /* 32 bit load sign-extended byte scaled or unscaled zero-
10600 or sign-extended 32-bit register offset. */
10602 ldrsb32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10604 unsigned int rm
= INSTR (20, 16);
10605 unsigned int rn
= INSTR (9, 5);
10606 unsigned int rt
= INSTR (4, 0);
10608 /* rn may reference SP, rm and rt must reference ZR. */
10610 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10611 int64_t displacement
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10614 /* There is no scaling required for a byte load. */
10615 aarch64_set_reg_u64
10616 (cpu
, rt
, NO_SP
, (int64_t) aarch64_get_mem_s8 (cpu
, address
10620 /* 32 bit load sign-extended byte unscaled signed 9 bit with
10621 pre- or post-writeback. */
10623 ldrsb32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10626 unsigned int rn
= INSTR (9, 5);
10627 unsigned int rt
= INSTR (4, 0);
10629 if (rn
== rt
&& wb
!= NoWriteBack
)
10632 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10637 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
10638 (int64_t) aarch64_get_mem_s8 (cpu
, address
));
10643 if (wb
!= NoWriteBack
)
10644 aarch64_set_reg_u64 (cpu
, rn
, NO_SP
, address
);
10647 /* 8 bit store scaled. */
10649 fstrb_abs (sim_cpu
*cpu
, uint32_t offset
)
10651 unsigned st
= INSTR (4, 0);
10652 unsigned rn
= INSTR (9, 5);
10654 aarch64_set_mem_u8 (cpu
,
10655 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
10656 aarch64_get_vec_u8 (cpu
, st
, 0));
10659 /* 8 bit store scaled or unscaled zero- or
10660 sign-extended 8-bit register offset. */
10662 fstrb_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10664 unsigned rm
= INSTR (20, 16);
10665 unsigned rn
= INSTR (9, 5);
10666 unsigned st
= INSTR (4, 0);
10668 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10669 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10671 uint64_t displacement
= scaling
== Scaled
? extended
: 0;
10674 (cpu
, address
+ displacement
, aarch64_get_vec_u8 (cpu
, st
, 0));
10677 /* 16 bit store scaled. */
10679 fstrh_abs (sim_cpu
*cpu
, uint32_t offset
)
10681 unsigned st
= INSTR (4, 0);
10682 unsigned rn
= INSTR (9, 5);
10684 aarch64_set_mem_u16
10686 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 16),
10687 aarch64_get_vec_u16 (cpu
, st
, 0));
10690 /* 16 bit store scaled or unscaled zero-
10691 or sign-extended 16-bit register offset. */
10693 fstrh_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10695 unsigned rm
= INSTR (20, 16);
10696 unsigned rn
= INSTR (9, 5);
10697 unsigned st
= INSTR (4, 0);
10699 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10700 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10702 uint64_t displacement
= OPT_SCALE (extended
, 16, scaling
);
10704 aarch64_set_mem_u16
10705 (cpu
, address
+ displacement
, aarch64_get_vec_u16 (cpu
, st
, 0));
10708 /* 32 bit store scaled unsigned 12 bit. */
10710 fstrs_abs (sim_cpu
*cpu
, uint32_t offset
)
10712 unsigned st
= INSTR (4, 0);
10713 unsigned rn
= INSTR (9, 5);
10715 aarch64_set_mem_u32
10717 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 32),
10718 aarch64_get_vec_u32 (cpu
, st
, 0));
10721 /* 32 bit store unscaled signed 9 bit with pre- or post-writeback. */
10723 fstrs_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10725 unsigned rn
= INSTR (9, 5);
10726 unsigned st
= INSTR (4, 0);
10728 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10733 aarch64_set_mem_u32 (cpu
, address
, aarch64_get_vec_u32 (cpu
, st
, 0));
10738 if (wb
!= NoWriteBack
)
10739 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
10742 /* 32 bit store scaled or unscaled zero-
10743 or sign-extended 32-bit register offset. */
10745 fstrs_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10747 unsigned rm
= INSTR (20, 16);
10748 unsigned rn
= INSTR (9, 5);
10749 unsigned st
= INSTR (4, 0);
10751 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10752 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10754 uint64_t displacement
= OPT_SCALE (extended
, 32, scaling
);
10756 aarch64_set_mem_u32
10757 (cpu
, address
+ displacement
, aarch64_get_vec_u32 (cpu
, st
, 0));
10760 /* 64 bit store scaled unsigned 12 bit. */
10762 fstrd_abs (sim_cpu
*cpu
, uint32_t offset
)
10764 unsigned st
= INSTR (4, 0);
10765 unsigned rn
= INSTR (9, 5);
10767 aarch64_set_mem_u64
10769 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 64),
10770 aarch64_get_vec_u64 (cpu
, st
, 0));
10773 /* 64 bit store unscaled signed 9 bit with pre- or post-writeback. */
10775 fstrd_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10777 unsigned rn
= INSTR (9, 5);
10778 unsigned st
= INSTR (4, 0);
10780 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10785 aarch64_set_mem_u64 (cpu
, address
, aarch64_get_vec_u64 (cpu
, st
, 0));
10790 if (wb
!= NoWriteBack
)
10791 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
10794 /* 64 bit store scaled or unscaled zero-
10795 or sign-extended 32-bit register offset. */
10797 fstrd_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10799 unsigned rm
= INSTR (20, 16);
10800 unsigned rn
= INSTR (9, 5);
10801 unsigned st
= INSTR (4, 0);
10803 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10804 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10806 uint64_t displacement
= OPT_SCALE (extended
, 64, scaling
);
10808 aarch64_set_mem_u64
10809 (cpu
, address
+ displacement
, aarch64_get_vec_u64 (cpu
, st
, 0));
10812 /* 128 bit store scaled unsigned 12 bit. */
10814 fstrq_abs (sim_cpu
*cpu
, uint32_t offset
)
10817 unsigned st
= INSTR (4, 0);
10818 unsigned rn
= INSTR (9, 5);
10821 aarch64_get_FP_long_double (cpu
, st
, & a
);
10823 addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 128);
10824 aarch64_set_mem_long_double (cpu
, addr
, a
);
10827 /* 128 bit store unscaled signed 9 bit with pre- or post-writeback. */
10829 fstrq_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10832 unsigned rn
= INSTR (9, 5);
10833 unsigned st
= INSTR (4, 0);
10834 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10839 aarch64_get_FP_long_double (cpu
, st
, & a
);
10840 aarch64_set_mem_long_double (cpu
, address
, a
);
10845 if (wb
!= NoWriteBack
)
10846 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
10849 /* 128 bit store scaled or unscaled zero-
10850 or sign-extended 32-bit register offset. */
10852 fstrq_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10854 unsigned rm
= INSTR (20, 16);
10855 unsigned rn
= INSTR (9, 5);
10856 unsigned st
= INSTR (4, 0);
10858 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10859 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10861 uint64_t displacement
= OPT_SCALE (extended
, 128, scaling
);
10865 aarch64_get_FP_long_double (cpu
, st
, & a
);
10866 aarch64_set_mem_long_double (cpu
, address
+ displacement
, a
);
10870 dexLoadImmediatePrePost (sim_cpu
*cpu
)
10872 /* instr[31,30] = size
10878 instr[20,12] = simm9
10879 instr[11] = wb : 0 ==> Post, 1 ==> Pre
10881 instr[9,5] = Rn may be SP.
10884 uint32_t V
= INSTR (26, 26);
10885 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
10886 int32_t imm
= simm32 (aarch64_get_instr (cpu
), 20, 12);
10887 WriteBack wb
= INSTR (11, 11);
10891 /* GReg operations. */
10894 case 0: strb_wb (cpu
, imm
, wb
); return;
10895 case 1: ldrb32_wb (cpu
, imm
, wb
); return;
10896 case 2: ldrsb_wb (cpu
, imm
, wb
); return;
10897 case 3: ldrsb32_wb (cpu
, imm
, wb
); return;
10898 case 4: strh_wb (cpu
, imm
, wb
); return;
10899 case 5: ldrh32_wb (cpu
, imm
, wb
); return;
10900 case 6: ldrsh64_wb (cpu
, imm
, wb
); return;
10901 case 7: ldrsh32_wb (cpu
, imm
, wb
); return;
10902 case 8: str32_wb (cpu
, imm
, wb
); return;
10903 case 9: ldr32_wb (cpu
, imm
, wb
); return;
10904 case 10: ldrsw_wb (cpu
, imm
, wb
); return;
10905 case 12: str_wb (cpu
, imm
, wb
); return;
10906 case 13: ldr_wb (cpu
, imm
, wb
); return;
10916 /* FReg operations. */
10919 case 2: fstrq_wb (cpu
, imm
, wb
); return;
10920 case 3: fldrq_wb (cpu
, imm
, wb
); return;
10921 case 8: fstrs_wb (cpu
, imm
, wb
); return;
10922 case 9: fldrs_wb (cpu
, imm
, wb
); return;
10923 case 12: fstrd_wb (cpu
, imm
, wb
); return;
10924 case 13: fldrd_wb (cpu
, imm
, wb
); return;
10926 case 0: /* STUR 8 bit FP. */
10927 case 1: /* LDUR 8 bit FP. */
10928 case 4: /* STUR 16 bit FP. */
10929 case 5: /* LDUR 8 bit FP. */
10944 dexLoadRegisterOffset (sim_cpu
*cpu
)
10946 /* instr[31,30] = size
10953 instr[15,13] = option : 010 ==> UXTW, 011 ==> UXTX/LSL,
10954 110 ==> SXTW, 111 ==> SXTX,
10959 instr[4,0] = rt. */
10961 uint32_t V
= INSTR (26, 26);
10962 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
10963 Scaling scale
= INSTR (12, 12);
10964 Extension extensionType
= INSTR (15, 13);
10966 /* Check for illegal extension types. */
10967 if (uimm (extensionType
, 1, 1) == 0)
10970 if (extensionType
== UXTX
|| extensionType
== SXTX
)
10971 extensionType
= NoExtension
;
10975 /* GReg operations. */
10978 case 0: strb_scale_ext (cpu
, scale
, extensionType
); return;
10979 case 1: ldrb32_scale_ext (cpu
, scale
, extensionType
); return;
10980 case 2: ldrsb_scale_ext (cpu
, scale
, extensionType
); return;
10981 case 3: ldrsb32_scale_ext (cpu
, scale
, extensionType
); return;
10982 case 4: strh_scale_ext (cpu
, scale
, extensionType
); return;
10983 case 5: ldrh32_scale_ext (cpu
, scale
, extensionType
); return;
10984 case 6: ldrsh_scale_ext (cpu
, scale
, extensionType
); return;
10985 case 7: ldrsh32_scale_ext (cpu
, scale
, extensionType
); return;
10986 case 8: str32_scale_ext (cpu
, scale
, extensionType
); return;
10987 case 9: ldr32_scale_ext (cpu
, scale
, extensionType
); return;
10988 case 10: ldrsw_scale_ext (cpu
, scale
, extensionType
); return;
10989 case 12: str_scale_ext (cpu
, scale
, extensionType
); return;
10990 case 13: ldr_scale_ext (cpu
, scale
, extensionType
); return;
10991 case 14: prfm_scale_ext (cpu
, scale
, extensionType
); return;
11000 /* FReg operations. */
11003 case 1: /* LDUR 8 bit FP. */
11005 case 3: fldrq_scale_ext (cpu
, scale
, extensionType
); return;
11006 case 5: /* LDUR 8 bit FP. */
11008 case 9: fldrs_scale_ext (cpu
, scale
, extensionType
); return;
11009 case 13: fldrd_scale_ext (cpu
, scale
, extensionType
); return;
11011 case 0: fstrb_scale_ext (cpu
, scale
, extensionType
); return;
11012 case 2: fstrq_scale_ext (cpu
, scale
, extensionType
); return;
11013 case 4: fstrh_scale_ext (cpu
, scale
, extensionType
); return;
11014 case 8: fstrs_scale_ext (cpu
, scale
, extensionType
); return;
11015 case 12: fstrd_scale_ext (cpu
, scale
, extensionType
); return;
11029 dexLoadUnsignedImmediate (sim_cpu
*cpu
)
11031 /* instr[29,24] == 111_01
11032 instr[31,30] = size
11035 instr[21,10] = uimm12 : unsigned immediate offset
11036 instr[9,5] = rn may be SP.
11037 instr[4,0] = rt. */
11039 uint32_t V
= INSTR (26,26);
11040 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
11041 uint32_t imm
= INSTR (21, 10);
11045 /* GReg operations. */
11048 case 0: strb_abs (cpu
, imm
); return;
11049 case 1: ldrb32_abs (cpu
, imm
); return;
11050 case 2: ldrsb_abs (cpu
, imm
); return;
11051 case 3: ldrsb32_abs (cpu
, imm
); return;
11052 case 4: strh_abs (cpu
, imm
); return;
11053 case 5: ldrh32_abs (cpu
, imm
); return;
11054 case 6: ldrsh_abs (cpu
, imm
); return;
11055 case 7: ldrsh32_abs (cpu
, imm
); return;
11056 case 8: str32_abs (cpu
, imm
); return;
11057 case 9: ldr32_abs (cpu
, imm
); return;
11058 case 10: ldrsw_abs (cpu
, imm
); return;
11059 case 12: str_abs (cpu
, imm
); return;
11060 case 13: ldr_abs (cpu
, imm
); return;
11061 case 14: prfm_abs (cpu
, imm
); return;
11070 /* FReg operations. */
11073 case 0: fstrb_abs (cpu
, imm
); return;
11074 case 4: fstrh_abs (cpu
, imm
); return;
11075 case 8: fstrs_abs (cpu
, imm
); return;
11076 case 12: fstrd_abs (cpu
, imm
); return;
11077 case 2: fstrq_abs (cpu
, imm
); return;
11079 case 1: fldrb_abs (cpu
, imm
); return;
11080 case 5: fldrh_abs (cpu
, imm
); return;
11081 case 9: fldrs_abs (cpu
, imm
); return;
11082 case 13: fldrd_abs (cpu
, imm
); return;
11083 case 3: fldrq_abs (cpu
, imm
); return;
11097 dexLoadExclusive (sim_cpu
*cpu
)
11099 /* assert instr[29:24] = 001000;
11100 instr[31,30] = size
11101 instr[23] = 0 if exclusive
11102 instr[22] = L : 1 if load, 0 if store
11103 instr[21] = 1 if pair
11105 instr[15] = o0 : 1 if ordered
11108 instr[4.0] = Rt. */
11110 switch (INSTR (22, 21))
11112 case 2: ldxr (cpu
); return;
11113 case 0: stxr (cpu
); return;
11119 dexLoadOther (sim_cpu
*cpu
)
11123 /* instr[29,25] = 111_0
11124 instr[24] == 0 ==> dispatch, 1 ==> ldst reg unsigned immediate
11125 instr[21:11,10] is the secondary dispatch. */
11126 if (INSTR (24, 24))
11128 dexLoadUnsignedImmediate (cpu
);
11132 dispatch
= ((INSTR (21, 21) << 2) | INSTR (11, 10));
11135 case 0: dexLoadUnscaledImmediate (cpu
); return;
11136 case 1: dexLoadImmediatePrePost (cpu
); return;
11137 case 3: dexLoadImmediatePrePost (cpu
); return;
11138 case 6: dexLoadRegisterOffset (cpu
); return;
11150 store_pair_u32 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11152 unsigned rn
= INSTR (14, 10);
11153 unsigned rd
= INSTR (9, 5);
11154 unsigned rm
= INSTR (4, 0);
11155 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11157 if ((rn
== rd
|| rm
== rd
) && wb
!= NoWriteBack
)
11158 HALT_UNALLOC
; /* ??? */
11165 aarch64_set_mem_u32 (cpu
, address
,
11166 aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
11167 aarch64_set_mem_u32 (cpu
, address
+ 4,
11168 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
));
11173 if (wb
!= NoWriteBack
)
11174 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11178 store_pair_u64 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11180 unsigned rn
= INSTR (14, 10);
11181 unsigned rd
= INSTR (9, 5);
11182 unsigned rm
= INSTR (4, 0);
11183 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11185 if ((rn
== rd
|| rm
== rd
) && wb
!= NoWriteBack
)
11186 HALT_UNALLOC
; /* ??? */
11193 aarch64_set_mem_u64 (cpu
, address
,
11194 aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
11195 aarch64_set_mem_u64 (cpu
, address
+ 8,
11196 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
11201 if (wb
!= NoWriteBack
)
11202 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11206 load_pair_u32 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11208 unsigned rn
= INSTR (14, 10);
11209 unsigned rd
= INSTR (9, 5);
11210 unsigned rm
= INSTR (4, 0);
11211 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11213 /* Treat this as unalloc to make sure we don't do it. */
11222 aarch64_set_reg_u64 (cpu
, rm
, SP_OK
, aarch64_get_mem_u32 (cpu
, address
));
11223 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, aarch64_get_mem_u32 (cpu
, address
+ 4));
11228 if (wb
!= NoWriteBack
)
11229 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11233 load_pair_s32 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11235 unsigned rn
= INSTR (14, 10);
11236 unsigned rd
= INSTR (9, 5);
11237 unsigned rm
= INSTR (4, 0);
11238 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11240 /* Treat this as unalloc to make sure we don't do it. */
11249 aarch64_set_reg_s64 (cpu
, rm
, SP_OK
, aarch64_get_mem_s32 (cpu
, address
));
11250 aarch64_set_reg_s64 (cpu
, rn
, SP_OK
, aarch64_get_mem_s32 (cpu
, address
+ 4));
11255 if (wb
!= NoWriteBack
)
11256 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11260 load_pair_u64 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11262 unsigned rn
= INSTR (14, 10);
11263 unsigned rd
= INSTR (9, 5);
11264 unsigned rm
= INSTR (4, 0);
11265 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11267 /* Treat this as unalloc to make sure we don't do it. */
11276 aarch64_set_reg_u64 (cpu
, rm
, SP_OK
, aarch64_get_mem_u64 (cpu
, address
));
11277 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, aarch64_get_mem_u64 (cpu
, address
+ 8));
11282 if (wb
!= NoWriteBack
)
11283 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11287 dex_load_store_pair_gr (sim_cpu
*cpu
)
11289 /* instr[31,30] = size (10=> 64-bit, 01=> signed 32-bit, 00=> 32-bit)
11290 instr[29,25] = instruction encoding: 101_0
11291 instr[26] = V : 1 if fp 0 if gp
11292 instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
11293 instr[22] = load/store (1=> load)
11294 instr[21,15] = signed, scaled, offset
11297 instr[ 4, 0] = Rm. */
11299 uint32_t dispatch
= ((INSTR (31, 30) << 3) | INSTR (24, 22));
11300 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 21, 15);
11304 case 2: store_pair_u32 (cpu
, offset
, Post
); return;
11305 case 3: load_pair_u32 (cpu
, offset
, Post
); return;
11306 case 4: store_pair_u32 (cpu
, offset
, NoWriteBack
); return;
11307 case 5: load_pair_u32 (cpu
, offset
, NoWriteBack
); return;
11308 case 6: store_pair_u32 (cpu
, offset
, Pre
); return;
11309 case 7: load_pair_u32 (cpu
, offset
, Pre
); return;
11311 case 11: load_pair_s32 (cpu
, offset
, Post
); return;
11312 case 13: load_pair_s32 (cpu
, offset
, NoWriteBack
); return;
11313 case 15: load_pair_s32 (cpu
, offset
, Pre
); return;
11315 case 18: store_pair_u64 (cpu
, offset
, Post
); return;
11316 case 19: load_pair_u64 (cpu
, offset
, Post
); return;
11317 case 20: store_pair_u64 (cpu
, offset
, NoWriteBack
); return;
11318 case 21: load_pair_u64 (cpu
, offset
, NoWriteBack
); return;
11319 case 22: store_pair_u64 (cpu
, offset
, Pre
); return;
11320 case 23: load_pair_u64 (cpu
, offset
, Pre
); return;
11328 store_pair_float (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11330 unsigned rn
= INSTR (14, 10);
11331 unsigned rd
= INSTR (9, 5);
11332 unsigned rm
= INSTR (4, 0);
11333 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11340 aarch64_set_mem_u32 (cpu
, address
, aarch64_get_vec_u32 (cpu
, rm
, 0));
11341 aarch64_set_mem_u32 (cpu
, address
+ 4, aarch64_get_vec_u32 (cpu
, rn
, 0));
11346 if (wb
!= NoWriteBack
)
11347 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11351 store_pair_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11353 unsigned rn
= INSTR (14, 10);
11354 unsigned rd
= INSTR (9, 5);
11355 unsigned rm
= INSTR (4, 0);
11356 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11363 aarch64_set_mem_u64 (cpu
, address
, aarch64_get_vec_u64 (cpu
, rm
, 0));
11364 aarch64_set_mem_u64 (cpu
, address
+ 8, aarch64_get_vec_u64 (cpu
, rn
, 0));
11369 if (wb
!= NoWriteBack
)
11370 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11374 store_pair_long_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11377 unsigned rn
= INSTR (14, 10);
11378 unsigned rd
= INSTR (9, 5);
11379 unsigned rm
= INSTR (4, 0);
11380 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11387 aarch64_get_FP_long_double (cpu
, rm
, & a
);
11388 aarch64_set_mem_long_double (cpu
, address
, a
);
11389 aarch64_get_FP_long_double (cpu
, rn
, & a
);
11390 aarch64_set_mem_long_double (cpu
, address
+ 16, a
);
11395 if (wb
!= NoWriteBack
)
11396 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11400 load_pair_float (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11402 unsigned rn
= INSTR (14, 10);
11403 unsigned rd
= INSTR (9, 5);
11404 unsigned rm
= INSTR (4, 0);
11405 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11415 aarch64_set_vec_u32 (cpu
, rm
, 0, aarch64_get_mem_u32 (cpu
, address
));
11416 aarch64_set_vec_u32 (cpu
, rn
, 0, aarch64_get_mem_u32 (cpu
, address
+ 4));
11421 if (wb
!= NoWriteBack
)
11422 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11426 load_pair_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11428 unsigned rn
= INSTR (14, 10);
11429 unsigned rd
= INSTR (9, 5);
11430 unsigned rm
= INSTR (4, 0);
11431 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11441 aarch64_set_vec_u64 (cpu
, rm
, 0, aarch64_get_mem_u64 (cpu
, address
));
11442 aarch64_set_vec_u64 (cpu
, rn
, 0, aarch64_get_mem_u64 (cpu
, address
+ 8));
11447 if (wb
!= NoWriteBack
)
11448 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11452 load_pair_long_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11455 unsigned rn
= INSTR (14, 10);
11456 unsigned rd
= INSTR (9, 5);
11457 unsigned rm
= INSTR (4, 0);
11458 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11468 aarch64_get_mem_long_double (cpu
, address
, & a
);
11469 aarch64_set_FP_long_double (cpu
, rm
, a
);
11470 aarch64_get_mem_long_double (cpu
, address
+ 16, & a
);
11471 aarch64_set_FP_long_double (cpu
, rn
, a
);
11476 if (wb
!= NoWriteBack
)
11477 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11481 dex_load_store_pair_fp (sim_cpu
*cpu
)
11483 /* instr[31,30] = size (10=> 128-bit, 01=> 64-bit, 00=> 32-bit)
11484 instr[29,25] = instruction encoding
11485 instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
11486 instr[22] = load/store (1=> load)
11487 instr[21,15] = signed, scaled, offset
11490 instr[ 4, 0] = Rm */
11492 uint32_t dispatch
= ((INSTR (31, 30) << 3) | INSTR (24, 22));
11493 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 21, 15);
11497 case 2: store_pair_float (cpu
, offset
, Post
); return;
11498 case 3: load_pair_float (cpu
, offset
, Post
); return;
11499 case 4: store_pair_float (cpu
, offset
, NoWriteBack
); return;
11500 case 5: load_pair_float (cpu
, offset
, NoWriteBack
); return;
11501 case 6: store_pair_float (cpu
, offset
, Pre
); return;
11502 case 7: load_pair_float (cpu
, offset
, Pre
); return;
11504 case 10: store_pair_double (cpu
, offset
, Post
); return;
11505 case 11: load_pair_double (cpu
, offset
, Post
); return;
11506 case 12: store_pair_double (cpu
, offset
, NoWriteBack
); return;
11507 case 13: load_pair_double (cpu
, offset
, NoWriteBack
); return;
11508 case 14: store_pair_double (cpu
, offset
, Pre
); return;
11509 case 15: load_pair_double (cpu
, offset
, Pre
); return;
11511 case 18: store_pair_long_double (cpu
, offset
, Post
); return;
11512 case 19: load_pair_long_double (cpu
, offset
, Post
); return;
11513 case 20: store_pair_long_double (cpu
, offset
, NoWriteBack
); return;
11514 case 21: load_pair_long_double (cpu
, offset
, NoWriteBack
); return;
11515 case 22: store_pair_long_double (cpu
, offset
, Pre
); return;
11516 case 23: load_pair_long_double (cpu
, offset
, Pre
); return;
11523 static inline unsigned
11524 vec_reg (unsigned v
, unsigned o
)
11526 return (v
+ o
) & 0x3F;
11529 /* Load multiple N-element structures to M consecutive registers. */
11531 vec_load (sim_cpu
*cpu
, uint64_t address
, unsigned N
, unsigned M
)
11533 int all
= INSTR (30, 30);
11534 unsigned size
= INSTR (11, 10);
11535 unsigned vd
= INSTR (4, 0);
11536 unsigned rpt
= (N
== M
) ? 1 : M
;
11537 unsigned selem
= N
;
11542 case 0: /* 8-bit operations. */
11543 for (i
= 0; i
< rpt
; i
++)
11544 for (j
= 0; j
< (8 + (8 * all
)); j
++)
11545 for (k
= 0; k
< selem
; k
++)
11547 aarch64_set_vec_u8 (cpu
, vec_reg (vd
, i
+ k
), j
,
11548 aarch64_get_mem_u8 (cpu
, address
));
11553 case 1: /* 16-bit operations. */
11554 for (i
= 0; i
< rpt
; i
++)
11555 for (j
= 0; j
< (4 + (4 * all
)); j
++)
11556 for (k
= 0; k
< selem
; k
++)
11558 aarch64_set_vec_u16 (cpu
, vec_reg (vd
, i
+ k
), j
,
11559 aarch64_get_mem_u16 (cpu
, address
));
11564 case 2: /* 32-bit operations. */
11565 for (i
= 0; i
< rpt
; i
++)
11566 for (j
= 0; j
< (2 + (2 * all
)); j
++)
11567 for (k
= 0; k
< selem
; k
++)
11569 aarch64_set_vec_u32 (cpu
, vec_reg (vd
, i
+ k
), j
,
11570 aarch64_get_mem_u32 (cpu
, address
));
11575 case 3: /* 64-bit operations. */
11576 for (i
= 0; i
< rpt
; i
++)
11577 for (j
= 0; j
< (1 + all
); j
++)
11578 for (k
= 0; k
< selem
; k
++)
11580 aarch64_set_vec_u64 (cpu
, vec_reg (vd
, i
+ k
), j
,
11581 aarch64_get_mem_u64 (cpu
, address
));
11588 /* Load multiple 4-element structures into four consecutive registers. */
11590 LD4 (sim_cpu
*cpu
, uint64_t address
)
11592 vec_load (cpu
, address
, 4, 4);
11595 /* Load multiple 3-element structures into three consecutive registers. */
11597 LD3 (sim_cpu
*cpu
, uint64_t address
)
11599 vec_load (cpu
, address
, 3, 3);
11602 /* Load multiple 2-element structures into two consecutive registers. */
11604 LD2 (sim_cpu
*cpu
, uint64_t address
)
11606 vec_load (cpu
, address
, 2, 2);
11609 /* Load multiple 1-element structures into one register. */
11611 LD1_1 (sim_cpu
*cpu
, uint64_t address
)
11613 vec_load (cpu
, address
, 1, 1);
11616 /* Load multiple 1-element structures into two registers. */
11618 LD1_2 (sim_cpu
*cpu
, uint64_t address
)
11620 vec_load (cpu
, address
, 1, 2);
11623 /* Load multiple 1-element structures into three registers. */
11625 LD1_3 (sim_cpu
*cpu
, uint64_t address
)
11627 vec_load (cpu
, address
, 1, 3);
11630 /* Load multiple 1-element structures into four registers. */
11632 LD1_4 (sim_cpu
*cpu
, uint64_t address
)
11634 vec_load (cpu
, address
, 1, 4);
11637 /* Store multiple N-element structures from M consecutive registers. */
11639 vec_store (sim_cpu
*cpu
, uint64_t address
, unsigned N
, unsigned M
)
11641 int all
= INSTR (30, 30);
11642 unsigned size
= INSTR (11, 10);
11643 unsigned vd
= INSTR (4, 0);
11644 unsigned rpt
= (N
== M
) ? 1 : M
;
11645 unsigned selem
= N
;
11650 case 0: /* 8-bit operations. */
11651 for (i
= 0; i
< rpt
; i
++)
11652 for (j
= 0; j
< (8 + (8 * all
)); j
++)
11653 for (k
= 0; k
< selem
; k
++)
11657 aarch64_get_vec_u8 (cpu
, vec_reg (vd
, i
+ k
), j
));
11662 case 1: /* 16-bit operations. */
11663 for (i
= 0; i
< rpt
; i
++)
11664 for (j
= 0; j
< (4 + (4 * all
)); j
++)
11665 for (k
= 0; k
< selem
; k
++)
11667 aarch64_set_mem_u16
11669 aarch64_get_vec_u16 (cpu
, vec_reg (vd
, i
+ k
), j
));
11674 case 2: /* 32-bit operations. */
11675 for (i
= 0; i
< rpt
; i
++)
11676 for (j
= 0; j
< (2 + (2 * all
)); j
++)
11677 for (k
= 0; k
< selem
; k
++)
11679 aarch64_set_mem_u32
11681 aarch64_get_vec_u32 (cpu
, vec_reg (vd
, i
+ k
), j
));
11686 case 3: /* 64-bit operations. */
11687 for (i
= 0; i
< rpt
; i
++)
11688 for (j
= 0; j
< (1 + all
); j
++)
11689 for (k
= 0; k
< selem
; k
++)
11691 aarch64_set_mem_u64
11693 aarch64_get_vec_u64 (cpu
, vec_reg (vd
, i
+ k
), j
));
11700 /* Store multiple 4-element structure from four consecutive registers. */
11702 ST4 (sim_cpu
*cpu
, uint64_t address
)
11704 vec_store (cpu
, address
, 4, 4);
11707 /* Store multiple 3-element structures from three consecutive registers. */
11709 ST3 (sim_cpu
*cpu
, uint64_t address
)
11711 vec_store (cpu
, address
, 3, 3);
11714 /* Store multiple 2-element structures from two consecutive registers. */
11716 ST2 (sim_cpu
*cpu
, uint64_t address
)
11718 vec_store (cpu
, address
, 2, 2);
11721 /* Store multiple 1-element structures from one register. */
11723 ST1_1 (sim_cpu
*cpu
, uint64_t address
)
11725 vec_store (cpu
, address
, 1, 1);
11728 /* Store multiple 1-element structures from two registers. */
11730 ST1_2 (sim_cpu
*cpu
, uint64_t address
)
11732 vec_store (cpu
, address
, 1, 2);
11735 /* Store multiple 1-element structures from three registers. */
11737 ST1_3 (sim_cpu
*cpu
, uint64_t address
)
11739 vec_store (cpu
, address
, 1, 3);
11742 /* Store multiple 1-element structures from four registers. */
11744 ST1_4 (sim_cpu
*cpu
, uint64_t address
)
11746 vec_store (cpu
, address
, 1, 4);
11749 #define LDn_STn_SINGLE_LANE_AND_SIZE() \
11752 switch (INSTR (15, 14)) \
11755 lane = (full << 3) | (s << 2) | size; \
11760 if ((size & 1) == 1) \
11762 lane = (full << 2) | (s << 1) | (size >> 1); \
11767 if ((size & 2) == 2) \
11770 if ((size & 1) == 0) \
11772 lane = (full << 1) | s; \
11790 /* Load single structure into one lane of N registers. */
11792 do_vec_LDn_single (sim_cpu
*cpu
, uint64_t address
)
11795 instr[30] = element selector 0=>half, 1=>all elements
11796 instr[29,24] = 00 1101
11797 instr[23] = 0=>simple, 1=>post
11799 instr[21] = width: LD1-or-LD3 (0) / LD2-or-LD4 (1)
11800 instr[20,16] = 0 0000 (simple), Vinc (reg-post-inc, no SP),
11801 11111 (immediate post inc)
11802 instr[15,13] = opcode
11803 instr[12] = S, used for lane number
11804 instr[11,10] = size, also used for lane number
11805 instr[9,5] = address
11808 unsigned full
= INSTR (30, 30);
11809 unsigned vd
= INSTR (4, 0);
11810 unsigned size
= INSTR (11, 10);
11811 unsigned s
= INSTR (12, 12);
11812 int nregs
= ((INSTR (13, 13) << 1) | INSTR (21, 21)) + 1;
11816 NYI_assert (29, 24, 0x0D);
11817 NYI_assert (22, 22, 1);
11819 /* Compute the lane number first (using size), and then compute size. */
11820 LDn_STn_SINGLE_LANE_AND_SIZE ();
11822 for (i
= 0; i
< nregs
; i
++)
11827 uint8_t val
= aarch64_get_mem_u8 (cpu
, address
+ i
);
11828 aarch64_set_vec_u8 (cpu
, vd
+ i
, lane
, val
);
11834 uint16_t val
= aarch64_get_mem_u16 (cpu
, address
+ (i
* 2));
11835 aarch64_set_vec_u16 (cpu
, vd
+ i
, lane
, val
);
11841 uint32_t val
= aarch64_get_mem_u32 (cpu
, address
+ (i
* 4));
11842 aarch64_set_vec_u32 (cpu
, vd
+ i
, lane
, val
);
11848 uint64_t val
= aarch64_get_mem_u64 (cpu
, address
+ (i
* 8));
11849 aarch64_set_vec_u64 (cpu
, vd
+ i
, lane
, val
);
11855 /* Store single structure from one lane from N registers. */
11857 do_vec_STn_single (sim_cpu
*cpu
, uint64_t address
)
11860 instr[30] = element selector 0=>half, 1=>all elements
11861 instr[29,24] = 00 1101
11862 instr[23] = 0=>simple, 1=>post
11864 instr[21] = width: LD1-or-LD3 (0) / LD2-or-LD4 (1)
11865 instr[20,16] = 0 0000 (simple), Vinc (reg-post-inc, no SP),
11866 11111 (immediate post inc)
11867 instr[15,13] = opcode
11868 instr[12] = S, used for lane number
11869 instr[11,10] = size, also used for lane number
11870 instr[9,5] = address
11873 unsigned full
= INSTR (30, 30);
11874 unsigned vd
= INSTR (4, 0);
11875 unsigned size
= INSTR (11, 10);
11876 unsigned s
= INSTR (12, 12);
11877 int nregs
= ((INSTR (13, 13) << 1) | INSTR (21, 21)) + 1;
11881 NYI_assert (29, 24, 0x0D);
11882 NYI_assert (22, 22, 0);
11884 /* Compute the lane number first (using size), and then compute size. */
11885 LDn_STn_SINGLE_LANE_AND_SIZE ();
11887 for (i
= 0; i
< nregs
; i
++)
11892 uint8_t val
= aarch64_get_vec_u8 (cpu
, vd
+ i
, lane
);
11893 aarch64_set_mem_u8 (cpu
, address
+ i
, val
);
11899 uint16_t val
= aarch64_get_vec_u16 (cpu
, vd
+ i
, lane
);
11900 aarch64_set_mem_u16 (cpu
, address
+ (i
* 2), val
);
11906 uint32_t val
= aarch64_get_vec_u32 (cpu
, vd
+ i
, lane
);
11907 aarch64_set_mem_u32 (cpu
, address
+ (i
* 4), val
);
11913 uint64_t val
= aarch64_get_vec_u64 (cpu
, vd
+ i
, lane
);
11914 aarch64_set_mem_u64 (cpu
, address
+ (i
* 8), val
);
11920 /* Load single structure into all lanes of N registers. */
11922 do_vec_LDnR (sim_cpu
*cpu
, uint64_t address
)
11925 instr[30] = element selector 0=>half, 1=>all elements
11926 instr[29,24] = 00 1101
11927 instr[23] = 0=>simple, 1=>post
11929 instr[21] = width: LD1R-or-LD3R (0) / LD2R-or-LD4R (1)
11930 instr[20,16] = 0 0000 (simple), Vinc (reg-post-inc, no SP),
11931 11111 (immediate post inc)
11933 instr[13] = width: LD1R-or-LD2R (0) / LD3R-or-LD4R (1)
11935 instr[11,10] = element size 00=> byte(b), 01=> half(h),
11936 10=> word(s), 11=> double(d)
11937 instr[9,5] = address
11940 unsigned full
= INSTR (30, 30);
11941 unsigned vd
= INSTR (4, 0);
11942 unsigned size
= INSTR (11, 10);
11943 int nregs
= ((INSTR (13, 13) << 1) | INSTR (21, 21)) + 1;
11946 NYI_assert (29, 24, 0x0D);
11947 NYI_assert (22, 22, 1);
11948 NYI_assert (15, 14, 3);
11949 NYI_assert (12, 12, 0);
11951 for (n
= 0; n
< nregs
; n
++)
11956 uint8_t val
= aarch64_get_mem_u8 (cpu
, address
+ n
);
11957 for (i
= 0; i
< (full
? 16 : 8); i
++)
11958 aarch64_set_vec_u8 (cpu
, vd
+ n
, i
, val
);
11964 uint16_t val
= aarch64_get_mem_u16 (cpu
, address
+ (n
* 2));
11965 for (i
= 0; i
< (full
? 8 : 4); i
++)
11966 aarch64_set_vec_u16 (cpu
, vd
+ n
, i
, val
);
11972 uint32_t val
= aarch64_get_mem_u32 (cpu
, address
+ (n
* 4));
11973 for (i
= 0; i
< (full
? 4 : 2); i
++)
11974 aarch64_set_vec_u32 (cpu
, vd
+ n
, i
, val
);
11980 uint64_t val
= aarch64_get_mem_u64 (cpu
, address
+ (n
* 8));
11981 for (i
= 0; i
< (full
? 2 : 1); i
++)
11982 aarch64_set_vec_u64 (cpu
, vd
+ n
, i
, val
);
11992 do_vec_load_store (sim_cpu
*cpu
)
11994 /* {LD|ST}<N> {Vd..Vd+N}, vaddr
11997 instr[30] = element selector 0=>half, 1=>all elements
11998 instr[29,25] = 00110
11999 instr[24] = 0=>multiple struct, 1=>single struct
12000 instr[23] = 0=>simple, 1=>post
12001 instr[22] = 0=>store, 1=>load
12002 instr[21] = 0 (LDn) / small(0)-large(1) selector (LDnR)
12003 instr[20,16] = 00000 (simple), Vinc (reg-post-inc, no SP),
12004 11111 (immediate post inc)
12005 instr[15,12] = elements and destinations. eg for load:
12006 0000=>LD4 => load multiple 4-element to
12007 four consecutive registers
12008 0100=>LD3 => load multiple 3-element to
12009 three consecutive registers
12010 1000=>LD2 => load multiple 2-element to
12011 two consecutive registers
12012 0010=>LD1 => load multiple 1-element to
12013 four consecutive registers
12014 0110=>LD1 => load multiple 1-element to
12015 three consecutive registers
12016 1010=>LD1 => load multiple 1-element to
12017 two consecutive registers
12018 0111=>LD1 => load multiple 1-element to
12022 instr[11,10] = element size 00=> byte(b), 01=> half(h),
12023 10=> word(s), 11=> double(d)
12024 instr[9,5] = Vn, can be SP
12034 if (INSTR (31, 31) != 0 || INSTR (29, 25) != 0x06)
12037 single
= INSTR (24, 24);
12038 post
= INSTR (23, 23);
12039 load
= INSTR (22, 22);
12040 type
= INSTR (15, 12);
12042 address
= aarch64_get_reg_u64 (cpu
, vn
, SP_OK
);
12044 if (! single
&& INSTR (21, 21) != 0)
12049 unsigned vm
= INSTR (20, 16);
12053 unsigned sizeof_operation
;
12057 if ((type
>= 0) && (type
<= 11))
12059 int nregs
= ((INSTR (13, 13) << 1) | INSTR (21, 21)) + 1;
12060 switch (INSTR (15, 14))
12063 sizeof_operation
= nregs
* 1;
12066 sizeof_operation
= nregs
* 2;
12069 if (INSTR (10, 10) == 0)
12070 sizeof_operation
= nregs
* 4;
12072 sizeof_operation
= nregs
* 8;
12078 else if (type
== 0xC)
12080 sizeof_operation
= INSTR (21, 21) ? 2 : 1;
12081 sizeof_operation
<<= INSTR (11, 10);
12083 else if (type
== 0xE)
12085 sizeof_operation
= INSTR (21, 21) ? 4 : 3;
12086 sizeof_operation
<<= INSTR (11, 10);
12095 case 0: sizeof_operation
= 32; break;
12096 case 4: sizeof_operation
= 24; break;
12097 case 8: sizeof_operation
= 16; break;
12100 /* One register, immediate offset variant. */
12101 sizeof_operation
= 8;
12105 /* Two registers, immediate offset variant. */
12106 sizeof_operation
= 16;
12110 /* Three registers, immediate offset variant. */
12111 sizeof_operation
= 24;
12115 /* Four registers, immediate offset variant. */
12116 sizeof_operation
= 32;
12123 if (INSTR (30, 30))
12124 sizeof_operation
*= 2;
12127 aarch64_set_reg_u64 (cpu
, vn
, SP_OK
, address
+ sizeof_operation
);
12130 aarch64_set_reg_u64 (cpu
, vn
, SP_OK
,
12131 address
+ aarch64_get_reg_u64 (cpu
, vm
, NO_SP
));
12135 NYI_assert (20, 16, 0);
12142 if ((type
>= 0) && (type
<= 11))
12143 do_vec_LDn_single (cpu
, address
);
12144 else if ((type
== 0xC) || (type
== 0xE))
12145 do_vec_LDnR (cpu
, address
);
12152 if ((type
>= 0) && (type
<= 11))
12154 do_vec_STn_single (cpu
, address
);
12165 case 0: LD4 (cpu
, address
); return;
12166 case 4: LD3 (cpu
, address
); return;
12167 case 8: LD2 (cpu
, address
); return;
12168 case 2: LD1_4 (cpu
, address
); return;
12169 case 6: LD1_3 (cpu
, address
); return;
12170 case 10: LD1_2 (cpu
, address
); return;
12171 case 7: LD1_1 (cpu
, address
); return;
12181 case 0: ST4 (cpu
, address
); return;
12182 case 4: ST3 (cpu
, address
); return;
12183 case 8: ST2 (cpu
, address
); return;
12184 case 2: ST1_4 (cpu
, address
); return;
12185 case 6: ST1_3 (cpu
, address
); return;
12186 case 10: ST1_2 (cpu
, address
); return;
12187 case 7: ST1_1 (cpu
, address
); return;
12194 dexLdSt (sim_cpu
*cpu
)
12196 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
12197 assert group == GROUP_LDST_0100 || group == GROUP_LDST_0110 ||
12198 group == GROUP_LDST_1100 || group == GROUP_LDST_1110
12199 bits [29,28:26] of a LS are the secondary dispatch vector. */
12200 uint32_t group2
= dispatchLS (aarch64_get_instr (cpu
));
12205 dexLoadExclusive (cpu
); return;
12209 dexLoadLiteral (cpu
); return;
12213 dexLoadOther (cpu
); return;
12215 case LS_ADVSIMD_001
:
12216 do_vec_load_store (cpu
); return;
12219 dex_load_store_pair_gr (cpu
); return;
12222 dex_load_store_pair_fp (cpu
); return;
12225 /* Should never reach here. */
12230 /* Specific decode and execute for group Data Processing Register. */
12233 dexLogicalShiftedRegister (sim_cpu
*cpu
)
12235 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12237 instr[28:24] = 01010
12238 instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> ROR
12241 instr[15,10] = count : must be 0xxxxx for 32 bit
12245 uint32_t size
= INSTR (31, 31);
12246 Shift shiftType
= INSTR (23, 22);
12247 uint32_t count
= INSTR (15, 10);
12249 /* 32 bit operations must have count[5] = 0.
12250 or else we have an UNALLOC. */
12251 if (size
== 0 && uimm (count
, 5, 5))
12254 /* Dispatch on size:op:N. */
12255 switch ((INSTR (31, 29) << 1) | INSTR (21, 21))
12257 case 0: and32_shift (cpu
, shiftType
, count
); return;
12258 case 1: bic32_shift (cpu
, shiftType
, count
); return;
12259 case 2: orr32_shift (cpu
, shiftType
, count
); return;
12260 case 3: orn32_shift (cpu
, shiftType
, count
); return;
12261 case 4: eor32_shift (cpu
, shiftType
, count
); return;
12262 case 5: eon32_shift (cpu
, shiftType
, count
); return;
12263 case 6: ands32_shift (cpu
, shiftType
, count
); return;
12264 case 7: bics32_shift (cpu
, shiftType
, count
); return;
12265 case 8: and64_shift (cpu
, shiftType
, count
); return;
12266 case 9: bic64_shift (cpu
, shiftType
, count
); return;
12267 case 10:orr64_shift (cpu
, shiftType
, count
); return;
12268 case 11:orn64_shift (cpu
, shiftType
, count
); return;
12269 case 12:eor64_shift (cpu
, shiftType
, count
); return;
12270 case 13:eon64_shift (cpu
, shiftType
, count
); return;
12271 case 14:ands64_shift (cpu
, shiftType
, count
); return;
12272 case 15:bics64_shift (cpu
, shiftType
, count
); return;
12276 /* 32 bit conditional select. */
12278 csel32 (sim_cpu
*cpu
, CondCode cc
)
12280 unsigned rm
= INSTR (20, 16);
12281 unsigned rn
= INSTR (9, 5);
12282 unsigned rd
= INSTR (4, 0);
12284 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12285 testConditionCode (cpu
, cc
)
12286 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12287 : aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12290 /* 64 bit conditional select. */
12292 csel64 (sim_cpu
*cpu
, CondCode cc
)
12294 unsigned rm
= INSTR (20, 16);
12295 unsigned rn
= INSTR (9, 5);
12296 unsigned rd
= INSTR (4, 0);
12298 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12299 testConditionCode (cpu
, cc
)
12300 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12301 : aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
12304 /* 32 bit conditional increment. */
12306 csinc32 (sim_cpu
*cpu
, CondCode cc
)
12308 unsigned rm
= INSTR (20, 16);
12309 unsigned rn
= INSTR (9, 5);
12310 unsigned rd
= INSTR (4, 0);
12312 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12313 testConditionCode (cpu
, cc
)
12314 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12315 : aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) + 1);
12318 /* 64 bit conditional increment. */
12320 csinc64 (sim_cpu
*cpu
, CondCode cc
)
12322 unsigned rm
= INSTR (20, 16);
12323 unsigned rn
= INSTR (9, 5);
12324 unsigned rd
= INSTR (4, 0);
12326 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12327 testConditionCode (cpu
, cc
)
12328 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12329 : aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) + 1);
12332 /* 32 bit conditional invert. */
12334 csinv32 (sim_cpu
*cpu
, CondCode cc
)
12336 unsigned rm
= INSTR (20, 16);
12337 unsigned rn
= INSTR (9, 5);
12338 unsigned rd
= INSTR (4, 0);
12340 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12341 testConditionCode (cpu
, cc
)
12342 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12343 : ~ aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12346 /* 64 bit conditional invert. */
12348 csinv64 (sim_cpu
*cpu
, CondCode cc
)
12350 unsigned rm
= INSTR (20, 16);
12351 unsigned rn
= INSTR (9, 5);
12352 unsigned rd
= INSTR (4, 0);
12354 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12355 testConditionCode (cpu
, cc
)
12356 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12357 : ~ aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
12360 /* 32 bit conditional negate. */
12362 csneg32 (sim_cpu
*cpu
, CondCode cc
)
12364 unsigned rm
= INSTR (20, 16);
12365 unsigned rn
= INSTR (9, 5);
12366 unsigned rd
= INSTR (4, 0);
12368 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12369 testConditionCode (cpu
, cc
)
12370 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12371 : - aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12374 /* 64 bit conditional negate. */
12376 csneg64 (sim_cpu
*cpu
, CondCode cc
)
12378 unsigned rm
= INSTR (20, 16);
12379 unsigned rn
= INSTR (9, 5);
12380 unsigned rd
= INSTR (4, 0);
12382 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12383 testConditionCode (cpu
, cc
)
12384 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12385 : - aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
12389 dexCondSelect (sim_cpu
*cpu
)
12391 /* instr[28,21] = 11011011
12392 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12393 instr[30:11,10] = op : 000 ==> CSEL, 001 ==> CSINC,
12394 100 ==> CSINV, 101 ==> CSNEG,
12396 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
12397 instr[15,12] = cond
12398 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC */
12400 CondCode cc
= INSTR (15, 12);
12401 uint32_t S
= INSTR (29, 29);
12402 uint32_t op2
= INSTR (11, 10);
12410 switch ((INSTR (31, 30) << 1) | op2
)
12412 case 0: csel32 (cpu
, cc
); return;
12413 case 1: csinc32 (cpu
, cc
); return;
12414 case 2: csinv32 (cpu
, cc
); return;
12415 case 3: csneg32 (cpu
, cc
); return;
12416 case 4: csel64 (cpu
, cc
); return;
12417 case 5: csinc64 (cpu
, cc
); return;
12418 case 6: csinv64 (cpu
, cc
); return;
12419 case 7: csneg64 (cpu
, cc
); return;
12423 /* Some helpers for counting leading 1 or 0 bits. */
12425 /* Counts the number of leading bits which are the same
12426 in a 32 bit value in the range 1 to 32. */
12428 leading32 (uint32_t value
)
12430 int32_t mask
= 0xffff0000;
12431 uint32_t count
= 16; /* Counts number of bits set in mask. */
12432 uint32_t lo
= 1; /* Lower bound for number of sign bits. */
12433 uint32_t hi
= 32; /* Upper bound for number of sign bits. */
12435 while (lo
+ 1 < hi
)
12437 int32_t test
= (value
& mask
);
12439 if (test
== 0 || test
== mask
)
12442 count
= (lo
+ hi
) / 2;
12443 mask
>>= (count
- lo
);
12448 count
= (lo
+ hi
) / 2;
12449 mask
<<= hi
- count
;
12458 test
= (value
& mask
);
12460 if (test
== 0 || test
== mask
)
12469 /* Counts the number of leading bits which are the same
12470 in a 64 bit value in the range 1 to 64. */
12472 leading64 (uint64_t value
)
12474 int64_t mask
= 0xffffffff00000000LL
;
12475 uint64_t count
= 32; /* Counts number of bits set in mask. */
12476 uint64_t lo
= 1; /* Lower bound for number of sign bits. */
12477 uint64_t hi
= 64; /* Upper bound for number of sign bits. */
12479 while (lo
+ 1 < hi
)
12481 int64_t test
= (value
& mask
);
12483 if (test
== 0 || test
== mask
)
12486 count
= (lo
+ hi
) / 2;
12487 mask
>>= (count
- lo
);
12492 count
= (lo
+ hi
) / 2;
12493 mask
<<= hi
- count
;
12502 test
= (value
& mask
);
12504 if (test
== 0 || test
== mask
)
12513 /* Bit operations. */
12514 /* N.B register args may not be SP. */
12516 /* 32 bit count leading sign bits. */
12518 cls32 (sim_cpu
*cpu
)
12520 unsigned rn
= INSTR (9, 5);
12521 unsigned rd
= INSTR (4, 0);
12523 /* N.B. the result needs to exclude the leading bit. */
12524 aarch64_set_reg_u64
12525 (cpu
, rd
, NO_SP
, leading32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)) - 1);
12528 /* 64 bit count leading sign bits. */
12530 cls64 (sim_cpu
*cpu
)
12532 unsigned rn
= INSTR (9, 5);
12533 unsigned rd
= INSTR (4, 0);
12535 /* N.B. the result needs to exclude the leading bit. */
12536 aarch64_set_reg_u64
12537 (cpu
, rd
, NO_SP
, leading64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)) - 1);
12540 /* 32 bit count leading zero bits. */
12542 clz32 (sim_cpu
*cpu
)
12544 unsigned rn
= INSTR (9, 5);
12545 unsigned rd
= INSTR (4, 0);
12546 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12548 /* if the sign (top) bit is set then the count is 0. */
12549 if (pick32 (value
, 31, 31))
12550 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, 0L);
12552 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, leading32 (value
));
12555 /* 64 bit count leading zero bits. */
12557 clz64 (sim_cpu
*cpu
)
12559 unsigned rn
= INSTR (9, 5);
12560 unsigned rd
= INSTR (4, 0);
12561 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12563 /* if the sign (top) bit is set then the count is 0. */
12564 if (pick64 (value
, 63, 63))
12565 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, 0L);
12567 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, leading64 (value
));
12570 /* 32 bit reverse bits. */
12572 rbit32 (sim_cpu
*cpu
)
12574 unsigned rn
= INSTR (9, 5);
12575 unsigned rd
= INSTR (4, 0);
12576 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12577 uint32_t result
= 0;
12580 for (i
= 0; i
< 32; i
++)
12583 result
|= (value
& 1);
12586 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12589 /* 64 bit reverse bits. */
12591 rbit64 (sim_cpu
*cpu
)
12593 unsigned rn
= INSTR (9, 5);
12594 unsigned rd
= INSTR (4, 0);
12595 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12596 uint64_t result
= 0;
12599 for (i
= 0; i
< 64; i
++)
12602 result
|= (value
& 1UL);
12605 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12608 /* 32 bit reverse bytes. */
12610 rev32 (sim_cpu
*cpu
)
12612 unsigned rn
= INSTR (9, 5);
12613 unsigned rd
= INSTR (4, 0);
12614 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12615 uint32_t result
= 0;
12618 for (i
= 0; i
< 4; i
++)
12621 result
|= (value
& 0xff);
12624 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12627 /* 64 bit reverse bytes. */
12629 rev64 (sim_cpu
*cpu
)
12631 unsigned rn
= INSTR (9, 5);
12632 unsigned rd
= INSTR (4, 0);
12633 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12634 uint64_t result
= 0;
12637 for (i
= 0; i
< 8; i
++)
12640 result
|= (value
& 0xffULL
);
12643 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12646 /* 32 bit reverse shorts. */
12647 /* N.B.this reverses the order of the bytes in each half word. */
12649 revh32 (sim_cpu
*cpu
)
12651 unsigned rn
= INSTR (9, 5);
12652 unsigned rd
= INSTR (4, 0);
12653 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12654 uint32_t result
= 0;
12657 for (i
= 0; i
< 2; i
++)
12660 result
|= (value
& 0x00ff00ff);
12663 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12666 /* 64 bit reverse shorts. */
12667 /* N.B.this reverses the order of the bytes in each half word. */
12669 revh64 (sim_cpu
*cpu
)
12671 unsigned rn
= INSTR (9, 5);
12672 unsigned rd
= INSTR (4, 0);
12673 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12674 uint64_t result
= 0;
12677 for (i
= 0; i
< 2; i
++)
12680 result
|= (value
& 0x00ff00ff00ff00ffULL
);
12683 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12687 dexDataProc1Source (sim_cpu
*cpu
)
12690 instr[28,21] = 111010110
12691 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12692 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
12693 instr[20,16] = opcode2 : 00000 ==> ok, ow ==> UNALLOC
12694 instr[15,10] = opcode : 000000 ==> RBIT, 000001 ==> REV16,
12695 000010 ==> REV, 000011 ==> UNALLOC
12696 000100 ==> CLZ, 000101 ==> CLS
12698 instr[9,5] = rn : may not be SP
12699 instr[4,0] = rd : may not be SP. */
12701 uint32_t S
= INSTR (29, 29);
12702 uint32_t opcode2
= INSTR (20, 16);
12703 uint32_t opcode
= INSTR (15, 10);
12704 uint32_t dispatch
= ((INSTR (31, 31) << 3) | opcode
);
12717 case 0: rbit32 (cpu
); return;
12718 case 1: revh32 (cpu
); return;
12719 case 2: rev32 (cpu
); return;
12720 case 4: clz32 (cpu
); return;
12721 case 5: cls32 (cpu
); return;
12722 case 8: rbit64 (cpu
); return;
12723 case 9: revh64 (cpu
); return;
12724 case 10:rev32 (cpu
); return;
12725 case 11:rev64 (cpu
); return;
12726 case 12:clz64 (cpu
); return;
12727 case 13:cls64 (cpu
); return;
12728 default: HALT_UNALLOC
;
12733 Shifts by count supplied in register.
12734 N.B register args may not be SP.
12735 These all use the shifted auxiliary function for
12736 simplicity and clarity. Writing the actual shift
12737 inline would avoid a branch and so be faster but
12738 would also necessitate getting signs right. */
12740 /* 32 bit arithmetic shift right. */
12742 asrv32 (sim_cpu
*cpu
)
12744 unsigned rm
= INSTR (20, 16);
12745 unsigned rn
= INSTR (9, 5);
12746 unsigned rd
= INSTR (4, 0);
12748 aarch64_set_reg_u64
12750 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), ASR
,
12751 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12754 /* 64 bit arithmetic shift right. */
12756 asrv64 (sim_cpu
*cpu
)
12758 unsigned rm
= INSTR (20, 16);
12759 unsigned rn
= INSTR (9, 5);
12760 unsigned rd
= INSTR (4, 0);
12762 aarch64_set_reg_u64
12764 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), ASR
,
12765 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12768 /* 32 bit logical shift left. */
12770 lslv32 (sim_cpu
*cpu
)
12772 unsigned rm
= INSTR (20, 16);
12773 unsigned rn
= INSTR (9, 5);
12774 unsigned rd
= INSTR (4, 0);
12776 aarch64_set_reg_u64
12778 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), LSL
,
12779 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12782 /* 64 bit arithmetic shift left. */
12784 lslv64 (sim_cpu
*cpu
)
12786 unsigned rm
= INSTR (20, 16);
12787 unsigned rn
= INSTR (9, 5);
12788 unsigned rd
= INSTR (4, 0);
12790 aarch64_set_reg_u64
12792 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), LSL
,
12793 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12796 /* 32 bit logical shift right. */
12798 lsrv32 (sim_cpu
*cpu
)
12800 unsigned rm
= INSTR (20, 16);
12801 unsigned rn
= INSTR (9, 5);
12802 unsigned rd
= INSTR (4, 0);
12804 aarch64_set_reg_u64
12806 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), LSR
,
12807 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12810 /* 64 bit logical shift right. */
12812 lsrv64 (sim_cpu
*cpu
)
12814 unsigned rm
= INSTR (20, 16);
12815 unsigned rn
= INSTR (9, 5);
12816 unsigned rd
= INSTR (4, 0);
12818 aarch64_set_reg_u64
12820 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), LSR
,
12821 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12824 /* 32 bit rotate right. */
12826 rorv32 (sim_cpu
*cpu
)
12828 unsigned rm
= INSTR (20, 16);
12829 unsigned rn
= INSTR (9, 5);
12830 unsigned rd
= INSTR (4, 0);
12832 aarch64_set_reg_u64
12834 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), ROR
,
12835 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12838 /* 64 bit rotate right. */
12840 rorv64 (sim_cpu
*cpu
)
12842 unsigned rm
= INSTR (20, 16);
12843 unsigned rn
= INSTR (9, 5);
12844 unsigned rd
= INSTR (4, 0);
12846 aarch64_set_reg_u64
12848 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), ROR
,
12849 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12855 /* 32 bit signed divide. */
12857 cpuiv32 (sim_cpu
*cpu
)
12859 unsigned rm
= INSTR (20, 16);
12860 unsigned rn
= INSTR (9, 5);
12861 unsigned rd
= INSTR (4, 0);
12862 /* N.B. the pseudo-code does the divide using 64 bit data. */
12863 /* TODO : check that this rounds towards zero as required. */
12864 int64_t dividend
= aarch64_get_reg_s32 (cpu
, rn
, NO_SP
);
12865 int64_t divisor
= aarch64_get_reg_s32 (cpu
, rm
, NO_SP
);
12867 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
,
12868 divisor
? ((int32_t) (dividend
/ divisor
)) : 0);
12871 /* 64 bit signed divide. */
12873 cpuiv64 (sim_cpu
*cpu
)
12875 unsigned rm
= INSTR (20, 16);
12876 unsigned rn
= INSTR (9, 5);
12877 unsigned rd
= INSTR (4, 0);
12879 /* TODO : check that this rounds towards zero as required. */
12880 int64_t divisor
= aarch64_get_reg_s64 (cpu
, rm
, NO_SP
);
12882 aarch64_set_reg_s64
12884 divisor
? (aarch64_get_reg_s64 (cpu
, rn
, NO_SP
) / divisor
) : 0);
12887 /* 32 bit unsigned divide. */
12889 udiv32 (sim_cpu
*cpu
)
12891 unsigned rm
= INSTR (20, 16);
12892 unsigned rn
= INSTR (9, 5);
12893 unsigned rd
= INSTR (4, 0);
12895 /* N.B. the pseudo-code does the divide using 64 bit data. */
12896 uint64_t dividend
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12897 uint64_t divisor
= aarch64_get_reg_u32 (cpu
, rm
, NO_SP
);
12899 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12900 divisor
? (uint32_t) (dividend
/ divisor
) : 0);
12903 /* 64 bit unsigned divide. */
12905 udiv64 (sim_cpu
*cpu
)
12907 unsigned rm
= INSTR (20, 16);
12908 unsigned rn
= INSTR (9, 5);
12909 unsigned rd
= INSTR (4, 0);
12911 /* TODO : check that this rounds towards zero as required. */
12912 uint64_t divisor
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
12914 aarch64_set_reg_u64
12916 divisor
? (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) / divisor
) : 0);
12920 dexDataProc2Source (sim_cpu
*cpu
)
12922 /* assert instr[30] == 0
12923 instr[28,21] == 11010110
12924 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12925 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
12926 instr[15,10] = opcode : 000010 ==> UDIV, 000011 ==> CPUIV,
12927 001000 ==> LSLV, 001001 ==> LSRV
12928 001010 ==> ASRV, 001011 ==> RORV
12932 uint32_t S
= INSTR (29, 29);
12933 uint32_t opcode
= INSTR (15, 10);
12941 dispatch
= ( (INSTR (31, 31) << 3)
12942 | (uimm (opcode
, 3, 3) << 2)
12943 | uimm (opcode
, 1, 0));
12946 case 2: udiv32 (cpu
); return;
12947 case 3: cpuiv32 (cpu
); return;
12948 case 4: lslv32 (cpu
); return;
12949 case 5: lsrv32 (cpu
); return;
12950 case 6: asrv32 (cpu
); return;
12951 case 7: rorv32 (cpu
); return;
12952 case 10: udiv64 (cpu
); return;
12953 case 11: cpuiv64 (cpu
); return;
12954 case 12: lslv64 (cpu
); return;
12955 case 13: lsrv64 (cpu
); return;
12956 case 14: asrv64 (cpu
); return;
12957 case 15: rorv64 (cpu
); return;
12958 default: HALT_UNALLOC
;
12965 /* 32 bit multiply and add. */
12967 madd32 (sim_cpu
*cpu
)
12969 unsigned rm
= INSTR (20, 16);
12970 unsigned ra
= INSTR (14, 10);
12971 unsigned rn
= INSTR (9, 5);
12972 unsigned rd
= INSTR (4, 0);
12974 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12975 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12976 aarch64_get_reg_u32 (cpu
, ra
, NO_SP
)
12977 + aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12978 * aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12981 /* 64 bit multiply and add. */
12983 madd64 (sim_cpu
*cpu
)
12985 unsigned rm
= INSTR (20, 16);
12986 unsigned ra
= INSTR (14, 10);
12987 unsigned rn
= INSTR (9, 5);
12988 unsigned rd
= INSTR (4, 0);
12990 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12991 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12992 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
12993 + (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12994 * aarch64_get_reg_u64 (cpu
, rm
, NO_SP
)));
12997 /* 32 bit multiply and sub. */
12999 msub32 (sim_cpu
*cpu
)
13001 unsigned rm
= INSTR (20, 16);
13002 unsigned ra
= INSTR (14, 10);
13003 unsigned rn
= INSTR (9, 5);
13004 unsigned rd
= INSTR (4, 0);
13006 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13007 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
13008 aarch64_get_reg_u32 (cpu
, ra
, NO_SP
)
13009 - aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
13010 * aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
13013 /* 64 bit multiply and sub. */
13015 msub64 (sim_cpu
*cpu
)
13017 unsigned rm
= INSTR (20, 16);
13018 unsigned ra
= INSTR (14, 10);
13019 unsigned rn
= INSTR (9, 5);
13020 unsigned rd
= INSTR (4, 0);
13022 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13023 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
13024 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
13025 - aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
13026 * aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
13029 /* Signed multiply add long -- source, source2 : 32 bit, source3 : 64 bit. */
13031 smaddl (sim_cpu
*cpu
)
13033 unsigned rm
= INSTR (20, 16);
13034 unsigned ra
= INSTR (14, 10);
13035 unsigned rn
= INSTR (9, 5);
13036 unsigned rd
= INSTR (4, 0);
13038 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
13039 obtain a 64 bit product. */
13040 aarch64_set_reg_s64
13042 aarch64_get_reg_s64 (cpu
, ra
, NO_SP
)
13043 + ((int64_t) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
))
13044 * ((int64_t) aarch64_get_reg_s32 (cpu
, rm
, NO_SP
)));
13047 /* Signed multiply sub long -- source, source2 : 32 bit, source3 : 64 bit. */
13049 smsubl (sim_cpu
*cpu
)
13051 unsigned rm
= INSTR (20, 16);
13052 unsigned ra
= INSTR (14, 10);
13053 unsigned rn
= INSTR (9, 5);
13054 unsigned rd
= INSTR (4, 0);
13056 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
13057 obtain a 64 bit product. */
13058 aarch64_set_reg_s64
13060 aarch64_get_reg_s64 (cpu
, ra
, NO_SP
)
13061 - ((int64_t) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
))
13062 * ((int64_t) aarch64_get_reg_s32 (cpu
, rm
, NO_SP
)));
13065 /* Integer Multiply/Divide. */
13067 /* First some macros and a helper function. */
13068 /* Macros to test or access elements of 64 bit words. */
13070 /* Mask used to access lo 32 bits of 64 bit unsigned int. */
13071 #define LOW_WORD_MASK ((1ULL << 32) - 1)
13072 /* Return the lo 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int. */
13073 #define lowWordToU64(_value_u64) ((_value_u64) & LOW_WORD_MASK)
13074 /* Return the hi 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int. */
13075 #define highWordToU64(_value_u64) ((_value_u64) >> 32)
13077 /* Offset of sign bit in 64 bit signed integger. */
13078 #define SIGN_SHIFT_U64 63
13079 /* The sign bit itself -- also identifies the minimum negative int value. */
13080 #define SIGN_BIT_U64 (1UL << SIGN_SHIFT_U64)
13081 /* Return true if a 64 bit signed int presented as an unsigned int is the
13082 most negative value. */
13083 #define isMinimumU64(_value_u64) ((_value_u64) == SIGN_BIT_U64)
13084 /* Return true (non-zero) if a 64 bit signed int presented as an unsigned
13085 int has its sign bit set to false. */
13086 #define isSignSetU64(_value_u64) ((_value_u64) & SIGN_BIT_U64)
13087 /* Return 1L or -1L according to whether a 64 bit signed int presented as
13088 an unsigned int has its sign bit set or not. */
13089 #define signOfU64(_value_u64) (1L + (((value_u64) >> SIGN_SHIFT_U64) * -2L)
13090 /* Clear the sign bit of a 64 bit signed int presented as an unsigned int. */
13091 #define clearSignU64(_value_u64) ((_value_u64) &= ~SIGN_BIT_U64)
13093 /* Multiply two 64 bit ints and return.
13094 the hi 64 bits of the 128 bit product. */
13097 mul64hi (uint64_t value1
, uint64_t value2
)
13099 uint64_t resultmid1
;
13101 uint64_t value1_lo
= lowWordToU64 (value1
);
13102 uint64_t value1_hi
= highWordToU64 (value1
) ;
13103 uint64_t value2_lo
= lowWordToU64 (value2
);
13104 uint64_t value2_hi
= highWordToU64 (value2
);
13106 /* Cross-multiply and collect results. */
13107 uint64_t xproductlo
= value1_lo
* value2_lo
;
13108 uint64_t xproductmid1
= value1_lo
* value2_hi
;
13109 uint64_t xproductmid2
= value1_hi
* value2_lo
;
13110 uint64_t xproducthi
= value1_hi
* value2_hi
;
13111 uint64_t carry
= 0;
13112 /* Start accumulating 64 bit results. */
13113 /* Drop bottom half of lowest cross-product. */
13114 uint64_t resultmid
= xproductlo
>> 32;
13115 /* Add in middle products. */
13116 resultmid
= resultmid
+ xproductmid1
;
13118 /* Check for overflow. */
13119 if (resultmid
< xproductmid1
)
13120 /* Carry over 1 into top cross-product. */
13123 resultmid1
= resultmid
+ xproductmid2
;
13125 /* Check for overflow. */
13126 if (resultmid1
< xproductmid2
)
13127 /* Carry over 1 into top cross-product. */
13130 /* Drop lowest 32 bits of middle cross-product. */
13131 result
= resultmid1
>> 32;
13132 /* Move carry bit to just above middle cross-product highest bit. */
13133 carry
= carry
<< 32;
13135 /* Add top cross-product plus and any carry. */
13136 result
+= xproducthi
+ carry
;
13141 /* Signed multiply high, source, source2 :
13142 64 bit, dest <-- high 64-bit of result. */
13144 smulh (sim_cpu
*cpu
)
13148 unsigned rm
= INSTR (20, 16);
13149 unsigned rn
= INSTR (9, 5);
13150 unsigned rd
= INSTR (4, 0);
13151 GReg ra
= INSTR (14, 10);
13152 int64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
13153 int64_t value2
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
13161 /* Convert to unsigned and use the unsigned mul64hi routine
13162 the fix the sign up afterwards. */
13183 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13185 uresult
= mul64hi (uvalue1
, uvalue2
);
13190 /* Multiply 128-bit result by -1, which means highpart gets inverted,
13191 and has carry in added only if low part is 0. */
13193 if ((uvalue1
* uvalue2
) == 0)
13197 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, result
);
13200 /* Unsigned multiply add long -- source, source2 :
13201 32 bit, source3 : 64 bit. */
13203 umaddl (sim_cpu
*cpu
)
13205 unsigned rm
= INSTR (20, 16);
13206 unsigned ra
= INSTR (14, 10);
13207 unsigned rn
= INSTR (9, 5);
13208 unsigned rd
= INSTR (4, 0);
13210 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13211 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
13212 obtain a 64 bit product. */
13213 aarch64_set_reg_u64
13215 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
13216 + ((uint64_t) aarch64_get_reg_u32 (cpu
, rn
, NO_SP
))
13217 * ((uint64_t) aarch64_get_reg_u32 (cpu
, rm
, NO_SP
)));
13220 /* Unsigned multiply sub long -- source, source2 : 32 bit, source3 : 64 bit. */
13222 umsubl (sim_cpu
*cpu
)
13224 unsigned rm
= INSTR (20, 16);
13225 unsigned ra
= INSTR (14, 10);
13226 unsigned rn
= INSTR (9, 5);
13227 unsigned rd
= INSTR (4, 0);
13229 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13230 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
13231 obtain a 64 bit product. */
13232 aarch64_set_reg_u64
13234 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
13235 - ((uint64_t) aarch64_get_reg_u32 (cpu
, rn
, NO_SP
))
13236 * ((uint64_t) aarch64_get_reg_u32 (cpu
, rm
, NO_SP
)));
13239 /* Unsigned multiply high, source, source2 :
13240 64 bit, dest <-- high 64-bit of result. */
13242 umulh (sim_cpu
*cpu
)
13244 unsigned rm
= INSTR (20, 16);
13245 unsigned rn
= INSTR (9, 5);
13246 unsigned rd
= INSTR (4, 0);
13247 GReg ra
= INSTR (14, 10);
13252 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13253 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
13254 mul64hi (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
),
13255 aarch64_get_reg_u64 (cpu
, rm
, NO_SP
)));
13259 dexDataProc3Source (sim_cpu
*cpu
)
13261 /* assert instr[28,24] == 11011. */
13262 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit (for rd at least)
13263 instr[30,29] = op54 : 00 ==> ok, ow ==> UNALLOC
13264 instr[23,21] = op31 : 111 ==> UNALLOC, o2 ==> ok
13265 instr[15] = o0 : 0/1 ==> ok
13266 instr[23,21:15] ==> op : 0000 ==> MADD, 0001 ==> MSUB, (32/64 bit)
13267 0010 ==> SMADDL, 0011 ==> SMSUBL, (64 bit only)
13268 0100 ==> SMULH, (64 bit only)
13269 1010 ==> UMADDL, 1011 ==> UNSUBL, (64 bit only)
13270 1100 ==> UMULH (64 bit only)
13274 uint32_t size
= INSTR (31, 31);
13275 uint32_t op54
= INSTR (30, 29);
13276 uint32_t op31
= INSTR (23, 21);
13277 uint32_t o0
= INSTR (15, 15);
13294 dispatch
= (op31
<< 1) | o0
;
13298 case 0: madd64 (cpu
); return;
13299 case 1: msub64 (cpu
); return;
13300 case 2: smaddl (cpu
); return;
13301 case 3: smsubl (cpu
); return;
13302 case 4: smulh (cpu
); return;
13303 case 10: umaddl (cpu
); return;
13304 case 11: umsubl (cpu
); return;
13305 case 12: umulh (cpu
); return;
13306 default: HALT_UNALLOC
;
13311 dexDPReg (sim_cpu
*cpu
)
13313 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
13314 assert group == GROUP_DPREG_0101 || group == GROUP_DPREG_1101
13315 bits [28:24:21] of a DPReg are the secondary dispatch vector. */
13316 uint32_t group2
= dispatchDPReg (aarch64_get_instr (cpu
));
13320 case DPREG_LOG_000
:
13321 case DPREG_LOG_001
:
13322 dexLogicalShiftedRegister (cpu
); return;
13324 case DPREG_ADDSHF_010
:
13325 dexAddSubtractShiftedRegister (cpu
); return;
13327 case DPREG_ADDEXT_011
:
13328 dexAddSubtractExtendedRegister (cpu
); return;
13330 case DPREG_ADDCOND_100
:
13332 /* This set bundles a variety of different operations. */
13334 /* 1) add/sub w carry. */
13335 uint32_t mask1
= 0x1FE00000U
;
13336 uint32_t val1
= 0x1A000000U
;
13337 /* 2) cond compare register/immediate. */
13338 uint32_t mask2
= 0x1FE00000U
;
13339 uint32_t val2
= 0x1A400000U
;
13340 /* 3) cond select. */
13341 uint32_t mask3
= 0x1FE00000U
;
13342 uint32_t val3
= 0x1A800000U
;
13343 /* 4) data proc 1/2 source. */
13344 uint32_t mask4
= 0x1FE00000U
;
13345 uint32_t val4
= 0x1AC00000U
;
13347 if ((aarch64_get_instr (cpu
) & mask1
) == val1
)
13348 dexAddSubtractWithCarry (cpu
);
13350 else if ((aarch64_get_instr (cpu
) & mask2
) == val2
)
13353 else if ((aarch64_get_instr (cpu
) & mask3
) == val3
)
13354 dexCondSelect (cpu
);
13356 else if ((aarch64_get_instr (cpu
) & mask4
) == val4
)
13358 /* Bit 30 is clear for data proc 2 source
13359 and set for data proc 1 source. */
13360 if (aarch64_get_instr (cpu
) & (1U << 30))
13361 dexDataProc1Source (cpu
);
13363 dexDataProc2Source (cpu
);
13367 /* Should not reach here. */
13373 case DPREG_3SRC_110
:
13374 dexDataProc3Source (cpu
); return;
13376 case DPREG_UNALLOC_101
:
13379 case DPREG_3SRC_111
:
13380 dexDataProc3Source (cpu
); return;
13383 /* Should never reach here. */
13388 /* Unconditional Branch immediate.
13389 Offset is a PC-relative byte offset in the range +/- 128MiB.
13390 The offset is assumed to be raw from the decode i.e. the
13391 simulator is expected to scale them from word offsets to byte. */
13393 /* Unconditional branch. */
13395 buc (sim_cpu
*cpu
, int32_t offset
)
13397 aarch64_set_next_PC_by_offset (cpu
, offset
);
13400 static unsigned stack_depth
= 0;
13402 /* Unconditional branch and link -- writes return PC to LR. */
13404 bl (sim_cpu
*cpu
, int32_t offset
)
13406 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13407 aarch64_save_LR (cpu
);
13408 aarch64_set_next_PC_by_offset (cpu
, offset
);
13410 if (TRACE_BRANCH_P (cpu
))
13414 " %*scall %" PRIx64
" [%s]"
13415 " [args: %" PRIx64
" %" PRIx64
" %" PRIx64
"]",
13416 stack_depth
, " ", aarch64_get_next_PC (cpu
),
13417 aarch64_get_func (CPU_STATE (cpu
),
13418 aarch64_get_next_PC (cpu
)),
13419 aarch64_get_reg_u64 (cpu
, 0, NO_SP
),
13420 aarch64_get_reg_u64 (cpu
, 1, NO_SP
),
13421 aarch64_get_reg_u64 (cpu
, 2, NO_SP
)
13426 /* Unconditional Branch register.
13427 Branch/return address is in source register. */
13429 /* Unconditional branch. */
13433 unsigned rn
= INSTR (9, 5);
13434 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13435 aarch64_set_next_PC (cpu
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
13438 /* Unconditional branch and link -- writes return PC to LR. */
13442 /* Ensure we read the destination before we write LR. */
13443 uint64_t target
= aarch64_get_reg_u64 (cpu
, INSTR (9, 5), NO_SP
);
13445 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13446 aarch64_save_LR (cpu
);
13447 aarch64_set_next_PC (cpu
, target
);
13449 if (TRACE_BRANCH_P (cpu
))
13453 " %*scall %" PRIx64
" [%s]"
13454 " [args: %" PRIx64
" %" PRIx64
" %" PRIx64
"]",
13455 stack_depth
, " ", aarch64_get_next_PC (cpu
),
13456 aarch64_get_func (CPU_STATE (cpu
),
13457 aarch64_get_next_PC (cpu
)),
13458 aarch64_get_reg_u64 (cpu
, 0, NO_SP
),
13459 aarch64_get_reg_u64 (cpu
, 1, NO_SP
),
13460 aarch64_get_reg_u64 (cpu
, 2, NO_SP
)
13465 /* Return -- assembler will default source to LR this is functionally
13466 equivalent to br but, presumably, unlike br it side effects the
13467 branch predictor. */
13471 unsigned rn
= INSTR (9, 5);
13472 aarch64_set_next_PC (cpu
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
13474 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13475 if (TRACE_BRANCH_P (cpu
))
13478 " %*sreturn [result: %" PRIx64
"]",
13479 stack_depth
, " ", aarch64_get_reg_u64 (cpu
, 0, NO_SP
));
13484 /* NOP -- we implement this and call it from the decode in case we
13485 want to intercept it later. */
13490 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13493 /* Data synchronization barrier. */
13498 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13501 /* Data memory barrier. */
13506 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13509 /* Instruction synchronization barrier. */
13514 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13518 dexBranchImmediate (sim_cpu
*cpu
)
13520 /* assert instr[30,26] == 00101
13521 instr[31] ==> 0 == B, 1 == BL
13522 instr[25,0] == imm26 branch offset counted in words. */
13524 uint32_t top
= INSTR (31, 31);
13525 /* We have a 26 byte signed word offset which we need to pass to the
13526 execute routine as a signed byte offset. */
13527 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 25, 0) << 2;
13535 /* Control Flow. */
13537 /* Conditional branch
13539 Offset is a PC-relative byte offset in the range +/- 1MiB pos is
13540 a bit position in the range 0 .. 63
13542 cc is a CondCode enum value as pulled out of the decode
13544 N.B. any offset register (source) can only be Xn or Wn. */
13547 bcc (sim_cpu
*cpu
, int32_t offset
, CondCode cc
)
13549 /* The test returns TRUE if CC is met. */
13550 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13551 if (testConditionCode (cpu
, cc
))
13552 aarch64_set_next_PC_by_offset (cpu
, offset
);
13555 /* 32 bit branch on register non-zero. */
13557 cbnz32 (sim_cpu
*cpu
, int32_t offset
)
13559 unsigned rt
= INSTR (4, 0);
13561 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13562 if (aarch64_get_reg_u32 (cpu
, rt
, NO_SP
) != 0)
13563 aarch64_set_next_PC_by_offset (cpu
, offset
);
13566 /* 64 bit branch on register zero. */
13568 cbnz (sim_cpu
*cpu
, int32_t offset
)
13570 unsigned rt
= INSTR (4, 0);
13572 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13573 if (aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) != 0)
13574 aarch64_set_next_PC_by_offset (cpu
, offset
);
13577 /* 32 bit branch on register non-zero. */
13579 cbz32 (sim_cpu
*cpu
, int32_t offset
)
13581 unsigned rt
= INSTR (4, 0);
13583 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13584 if (aarch64_get_reg_u32 (cpu
, rt
, NO_SP
) == 0)
13585 aarch64_set_next_PC_by_offset (cpu
, offset
);
13588 /* 64 bit branch on register zero. */
13590 cbz (sim_cpu
*cpu
, int32_t offset
)
13592 unsigned rt
= INSTR (4, 0);
13594 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13595 if (aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) == 0)
13596 aarch64_set_next_PC_by_offset (cpu
, offset
);
13599 /* Branch on register bit test non-zero -- one size fits all. */
13601 tbnz (sim_cpu
*cpu
, uint32_t pos
, int32_t offset
)
13603 unsigned rt
= INSTR (4, 0);
13605 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13606 if (aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) & (((uint64_t) 1) << pos
))
13607 aarch64_set_next_PC_by_offset (cpu
, offset
);
13610 /* Branch on register bit test zero -- one size fits all. */
13612 tbz (sim_cpu
*cpu
, uint32_t pos
, int32_t offset
)
13614 unsigned rt
= INSTR (4, 0);
13616 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13617 if (!(aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) & (((uint64_t) 1) << pos
)))
13618 aarch64_set_next_PC_by_offset (cpu
, offset
);
13622 dexCompareBranchImmediate (sim_cpu
*cpu
)
13624 /* instr[30,25] = 01 1010
13625 instr[31] = size : 0 ==> 32, 1 ==> 64
13626 instr[24] = op : 0 ==> CBZ, 1 ==> CBNZ
13627 instr[23,5] = simm19 branch offset counted in words
13630 uint32_t size
= INSTR (31, 31);
13631 uint32_t op
= INSTR (24, 24);
13632 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 23, 5) << 2;
13637 cbz32 (cpu
, offset
);
13639 cbnz32 (cpu
, offset
);
13646 cbnz (cpu
, offset
);
13651 dexTestBranchImmediate (sim_cpu
*cpu
)
13653 /* instr[31] = b5 : bit 5 of test bit idx
13654 instr[30,25] = 01 1011
13655 instr[24] = op : 0 ==> TBZ, 1 == TBNZ
13656 instr[23,19] = b40 : bits 4 to 0 of test bit idx
13657 instr[18,5] = simm14 : signed offset counted in words
13658 instr[4,0] = uimm5 */
13660 uint32_t pos
= ((INSTR (31, 31) << 5) | INSTR (23, 19));
13661 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 18, 5) << 2;
13663 NYI_assert (30, 25, 0x1b);
13665 if (INSTR (24, 24) == 0)
13666 tbz (cpu
, pos
, offset
);
13668 tbnz (cpu
, pos
, offset
);
13672 dexCondBranchImmediate (sim_cpu
*cpu
)
13674 /* instr[31,25] = 010 1010
13675 instr[24] = op1; op => 00 ==> B.cond
13676 instr[23,5] = simm19 : signed offset counted in words
13678 instr[3,0] = cond */
13681 uint32_t op
= ((INSTR (24, 24) << 1) | INSTR (4, 4));
13683 NYI_assert (31, 25, 0x2a);
13688 offset
= simm32 (aarch64_get_instr (cpu
), 23, 5) << 2;
13690 bcc (cpu
, offset
, INSTR (3, 0));
13694 dexBranchRegister (sim_cpu
*cpu
)
13696 /* instr[31,25] = 110 1011
13697 instr[24,21] = op : 0 ==> BR, 1 => BLR, 2 => RET, 3 => ERET, 4 => DRPS
13698 instr[20,16] = op2 : must be 11111
13699 instr[15,10] = op3 : must be 000000
13700 instr[4,0] = op2 : must be 11111. */
13702 uint32_t op
= INSTR (24, 21);
13703 uint32_t op2
= INSTR (20, 16);
13704 uint32_t op3
= INSTR (15, 10);
13705 uint32_t op4
= INSTR (4, 0);
13707 NYI_assert (31, 25, 0x6b);
13709 if (op2
!= 0x1F || op3
!= 0 || op4
!= 0)
13723 /* ERET and DRPS accept 0b11111 for rn = instr [4,0]. */
13724 /* anything else is unallocated. */
13725 uint32_t rn
= INSTR (4, 0);
13730 if (op
== 4 || op
== 5)
13737 /* FIXME: We should get the Angel SWI values from ../../libgloss/aarch64/svc.h
13738 but this may not be available. So instead we define the values we need
13740 #define AngelSVC_Reason_Open 0x01
13741 #define AngelSVC_Reason_Close 0x02
13742 #define AngelSVC_Reason_Write 0x05
13743 #define AngelSVC_Reason_Read 0x06
13744 #define AngelSVC_Reason_IsTTY 0x09
13745 #define AngelSVC_Reason_Seek 0x0A
13746 #define AngelSVC_Reason_FLen 0x0C
13747 #define AngelSVC_Reason_Remove 0x0E
13748 #define AngelSVC_Reason_Rename 0x0F
13749 #define AngelSVC_Reason_Clock 0x10
13750 #define AngelSVC_Reason_Time 0x11
13751 #define AngelSVC_Reason_System 0x12
13752 #define AngelSVC_Reason_Errno 0x13
13753 #define AngelSVC_Reason_GetCmdLine 0x15
13754 #define AngelSVC_Reason_HeapInfo 0x16
13755 #define AngelSVC_Reason_ReportException 0x18
13756 #define AngelSVC_Reason_Elapsed 0x30
13760 handle_halt (sim_cpu
*cpu
, uint32_t val
)
13762 uint64_t result
= 0;
13764 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13767 TRACE_SYSCALL (cpu
, " HLT [0x%x]", val
);
13768 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13769 sim_stopped
, SIM_SIGTRAP
);
13772 /* We have encountered an Angel SVC call. See if we can process it. */
13773 switch (aarch64_get_reg_u32 (cpu
, 0, NO_SP
))
13775 case AngelSVC_Reason_HeapInfo
:
13777 /* Get the values. */
13778 uint64_t stack_top
= aarch64_get_stack_start (cpu
);
13779 uint64_t heap_base
= aarch64_get_heap_start (cpu
);
13781 /* Get the pointer */
13782 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13783 ptr
= aarch64_get_mem_u64 (cpu
, ptr
);
13785 /* Fill in the memory block. */
13786 /* Start addr of heap. */
13787 aarch64_set_mem_u64 (cpu
, ptr
+ 0, heap_base
);
13788 /* End addr of heap. */
13789 aarch64_set_mem_u64 (cpu
, ptr
+ 8, stack_top
);
13790 /* Lowest stack addr. */
13791 aarch64_set_mem_u64 (cpu
, ptr
+ 16, heap_base
);
13792 /* Initial stack addr. */
13793 aarch64_set_mem_u64 (cpu
, ptr
+ 24, stack_top
);
13795 TRACE_SYSCALL (cpu
, " AngelSVC: Get Heap Info");
13799 case AngelSVC_Reason_Open
:
13801 /* Get the pointer */
13802 /* uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);. */
13803 /* FIXME: For now we just assume that we will only be asked
13804 to open the standard file descriptors. */
13808 TRACE_SYSCALL (cpu
, " AngelSVC: Open file %d", fd
- 1);
13812 case AngelSVC_Reason_Close
:
13814 uint64_t fh
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13815 TRACE_SYSCALL (cpu
, " AngelSVC: Close file %d", (int) fh
);
13820 case AngelSVC_Reason_Errno
:
13822 TRACE_SYSCALL (cpu
, " AngelSVC: Get Errno");
13825 case AngelSVC_Reason_Clock
:
13827 #ifdef CLOCKS_PER_SEC
13828 (CLOCKS_PER_SEC
>= 100)
13829 ? (clock () / (CLOCKS_PER_SEC
/ 100))
13830 : ((clock () * 100) / CLOCKS_PER_SEC
)
13832 /* Presume unix... clock() returns microseconds. */
13836 TRACE_SYSCALL (cpu
, " AngelSVC: Get Clock");
13839 case AngelSVC_Reason_GetCmdLine
:
13841 /* Get the pointer */
13842 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13843 ptr
= aarch64_get_mem_u64 (cpu
, ptr
);
13845 /* FIXME: No command line for now. */
13846 aarch64_set_mem_u64 (cpu
, ptr
, 0);
13847 TRACE_SYSCALL (cpu
, " AngelSVC: Get Command Line");
13851 case AngelSVC_Reason_IsTTY
:
13853 TRACE_SYSCALL (cpu
, " AngelSVC: IsTTY ?");
13856 case AngelSVC_Reason_Write
:
13858 /* Get the pointer */
13859 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13860 /* Get the write control block. */
13861 uint64_t fd
= aarch64_get_mem_u64 (cpu
, ptr
);
13862 uint64_t buf
= aarch64_get_mem_u64 (cpu
, ptr
+ 8);
13863 uint64_t len
= aarch64_get_mem_u64 (cpu
, ptr
+ 16);
13865 TRACE_SYSCALL (cpu
, "write of %" PRIx64
" bytes from %"
13866 PRIx64
" on descriptor %" PRIx64
,
13871 TRACE_SYSCALL (cpu
,
13872 " AngelSVC: Write: Suspiciously long write: %ld",
13874 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13875 sim_stopped
, SIM_SIGBUS
);
13879 printf ("%.*s", (int) len
, aarch64_get_mem_ptr (cpu
, buf
));
13883 TRACE (cpu
, 0, "\n");
13884 sim_io_eprintf (CPU_STATE (cpu
), "%.*s",
13885 (int) len
, aarch64_get_mem_ptr (cpu
, buf
));
13886 TRACE (cpu
, 0, "\n");
13890 TRACE_SYSCALL (cpu
,
13891 " AngelSVC: Write: Unexpected file handle: %d",
13893 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13894 sim_stopped
, SIM_SIGABRT
);
13899 case AngelSVC_Reason_ReportException
:
13901 /* Get the pointer */
13902 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13903 /*ptr = aarch64_get_mem_u64 (cpu, ptr);. */
13904 uint64_t type
= aarch64_get_mem_u64 (cpu
, ptr
);
13905 uint64_t state
= aarch64_get_mem_u64 (cpu
, ptr
+ 8);
13907 TRACE_SYSCALL (cpu
,
13908 "Angel Exception: type 0x%" PRIx64
" state %" PRIx64
,
13911 if (type
== 0x20026)
13912 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13913 sim_exited
, state
);
13915 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13916 sim_stopped
, SIM_SIGINT
);
13920 case AngelSVC_Reason_Read
:
13921 case AngelSVC_Reason_FLen
:
13922 case AngelSVC_Reason_Seek
:
13923 case AngelSVC_Reason_Remove
:
13924 case AngelSVC_Reason_Time
:
13925 case AngelSVC_Reason_System
:
13926 case AngelSVC_Reason_Rename
:
13927 case AngelSVC_Reason_Elapsed
:
13929 TRACE_SYSCALL (cpu
, " HLT [Unknown angel %x]",
13930 aarch64_get_reg_u32 (cpu
, 0, NO_SP
));
13931 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13932 sim_stopped
, SIM_SIGTRAP
);
13935 aarch64_set_reg_u64 (cpu
, 0, NO_SP
, result
);
13939 dexExcpnGen (sim_cpu
*cpu
)
13941 /* instr[31:24] = 11010100
13942 instr[23,21] = opc : 000 ==> GEN EXCPN, 001 ==> BRK
13943 010 ==> HLT, 101 ==> DBG GEN EXCPN
13944 instr[20,5] = imm16
13945 instr[4,2] = opc2 000 ==> OK, ow ==> UNALLOC
13946 instr[1,0] = LL : discriminates opc */
13948 uint32_t opc
= INSTR (23, 21);
13949 uint32_t imm16
= INSTR (20, 5);
13950 uint32_t opc2
= INSTR (4, 2);
13953 NYI_assert (31, 24, 0xd4);
13960 /* We only implement HLT and BRK for now. */
13961 if (opc
== 1 && LL
== 0)
13963 TRACE_EVENTS (cpu
, " BRK [0x%x]", imm16
);
13964 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13965 sim_exited
, aarch64_get_reg_s32 (cpu
, R0
, SP_OK
));
13968 if (opc
== 2 && LL
== 0)
13969 handle_halt (cpu
, imm16
);
13971 else if (opc
== 0 || opc
== 5)
13978 /* Stub for accessing system registers. */
13981 system_get (sim_cpu
*cpu
, unsigned op0
, unsigned op1
, unsigned crn
,
13982 unsigned crm
, unsigned op2
)
13984 if (crn
== 0 && op1
== 3 && crm
== 0 && op2
== 7)
13985 /* DCZID_EL0 - the Data Cache Zero ID register.
13986 We do not support DC ZVA at the moment, so
13987 we return a value with the disable bit set.
13988 We implement support for the DCZID register since
13989 it is used by the C library's memset function. */
13990 return ((uint64_t) 1) << 4;
13992 if (crn
== 0 && op1
== 3 && crm
== 0 && op2
== 1)
13993 /* Cache Type Register. */
13994 return 0x80008000UL
;
13996 if (crn
== 13 && op1
== 3 && crm
== 0 && op2
== 2)
13997 /* TPIDR_EL0 - thread pointer id. */
13998 return aarch64_get_thread_id (cpu
);
14000 if (op1
== 3 && crm
== 4 && op2
== 0)
14001 return aarch64_get_FPCR (cpu
);
14003 if (op1
== 3 && crm
== 4 && op2
== 1)
14004 return aarch64_get_FPSR (cpu
);
14006 else if (op1
== 3 && crm
== 2 && op2
== 0)
14007 return aarch64_get_CPSR (cpu
);
14013 system_set (sim_cpu
*cpu
, unsigned op0
, unsigned op1
, unsigned crn
,
14014 unsigned crm
, unsigned op2
, uint64_t val
)
14016 if (op1
== 3 && crm
== 4 && op2
== 0)
14017 aarch64_set_FPCR (cpu
, val
);
14019 else if (op1
== 3 && crm
== 4 && op2
== 1)
14020 aarch64_set_FPSR (cpu
, val
);
14022 else if (op1
== 3 && crm
== 2 && op2
== 0)
14023 aarch64_set_CPSR (cpu
, val
);
14030 do_mrs (sim_cpu
*cpu
)
14032 /* instr[31:20] = 1101 0101 0001 1
14039 unsigned sys_op0
= INSTR (19, 19) + 2;
14040 unsigned sys_op1
= INSTR (18, 16);
14041 unsigned sys_crn
= INSTR (15, 12);
14042 unsigned sys_crm
= INSTR (11, 8);
14043 unsigned sys_op2
= INSTR (7, 5);
14044 unsigned rt
= INSTR (4, 0);
14046 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
14047 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
14048 system_get (cpu
, sys_op0
, sys_op1
, sys_crn
, sys_crm
, sys_op2
));
14052 do_MSR_immediate (sim_cpu
*cpu
)
14054 /* instr[31:19] = 1101 0101 0000 0
14056 instr[15,12] = 0100
14059 instr[4,0] = 1 1111 */
14061 unsigned op1
= INSTR (18, 16);
14062 /*unsigned crm = INSTR (11, 8);*/
14063 unsigned op2
= INSTR (7, 5);
14065 NYI_assert (31, 19, 0x1AA0);
14066 NYI_assert (15, 12, 0x4);
14067 NYI_assert (4, 0, 0x1F);
14072 HALT_NYI
; /* set SPSel. */
14079 HALT_NYI
; /* set DAIFset. */
14081 HALT_NYI
; /* set DAIFclr. */
14090 do_MSR_reg (sim_cpu
*cpu
)
14092 /* instr[31:20] = 1101 0101 0001
14100 unsigned sys_op0
= INSTR (19, 19) + 2;
14101 unsigned sys_op1
= INSTR (18, 16);
14102 unsigned sys_crn
= INSTR (15, 12);
14103 unsigned sys_crm
= INSTR (11, 8);
14104 unsigned sys_op2
= INSTR (7, 5);
14105 unsigned rt
= INSTR (4, 0);
14107 NYI_assert (31, 20, 0xD51);
14109 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
14110 system_set (cpu
, sys_op0
, sys_op1
, sys_crn
, sys_crm
, sys_op2
,
14111 aarch64_get_reg_u64 (cpu
, rt
, NO_SP
));
14115 do_SYS (sim_cpu
*cpu
)
14117 /* instr[31,19] = 1101 0101 0000 1
14123 NYI_assert (31, 19, 0x1AA1);
14125 /* FIXME: For now we just silently accept system ops. */
14129 dexSystem (sim_cpu
*cpu
)
14131 /* instr[31:22] = 1101 01010 0
14138 instr[4,0] = uimm5 */
14140 /* We are interested in HINT, DSB, DMB and ISB
14142 Hint #0 encodes NOOP (this is the only hint we care about)
14143 L == 0, op0 == 0, op1 = 011, CRn = 0010, Rt = 11111,
14144 CRm op2 != 0000 000 OR CRm op2 == 0000 000 || CRm op > 0000 101
14146 DSB, DMB, ISB are data store barrier, data memory barrier and
14147 instruction store barrier, respectively, where
14149 L == 0, op0 == 0, op1 = 011, CRn = 0011, Rt = 11111,
14150 op2 : DSB ==> 100, DMB ==> 101, ISB ==> 110
14151 CRm<3:2> ==> domain, CRm<1:0> ==> types,
14152 domain : 00 ==> OuterShareable, 01 ==> Nonshareable,
14153 10 ==> InerShareable, 11 ==> FullSystem
14154 types : 01 ==> Reads, 10 ==> Writes,
14155 11 ==> All, 00 ==> All (domain == FullSystem). */
14157 unsigned rt
= INSTR (4, 0);
14159 NYI_assert (31, 22, 0x354);
14161 switch (INSTR (21, 12))
14166 /* NOP has CRm != 0000 OR. */
14167 /* (CRm == 0000 AND (op2 == 000 OR op2 > 101)). */
14168 uint32_t crm
= INSTR (11, 8);
14169 uint32_t op2
= INSTR (7, 5);
14171 if (crm
!= 0 || (op2
== 0 || op2
> 5))
14173 /* Actually call nop method so we can reimplement it later. */
14182 uint32_t op2
= INSTR (7, 5);
14187 case 4: dsb (cpu
); return;
14188 case 5: dmb (cpu
); return;
14189 case 6: isb (cpu
); return;
14190 default: HALT_UNALLOC
;
14201 do_SYS (cpu
); /* DC is an alias of SYS. */
14205 if (INSTR (21, 20) == 0x1)
14207 else if (INSTR (21, 19) == 0 && INSTR (15, 12) == 0x4)
14208 do_MSR_immediate (cpu
);
14216 dexBr (sim_cpu
*cpu
)
14218 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
14219 assert group == GROUP_BREXSYS_1010 || group == GROUP_BREXSYS_1011
14220 bits [31,29] of a BrExSys are the secondary dispatch vector. */
14221 uint32_t group2
= dispatchBrExSys (aarch64_get_instr (cpu
));
14226 return dexBranchImmediate (cpu
);
14228 case BR_IMMCMP_001
:
14229 /* Compare has bit 25 clear while test has it set. */
14230 if (!INSTR (25, 25))
14231 dexCompareBranchImmediate (cpu
);
14233 dexTestBranchImmediate (cpu
);
14236 case BR_IMMCOND_010
:
14237 /* This is a conditional branch if bit 25 is clear otherwise
14239 if (!INSTR (25, 25))
14240 dexCondBranchImmediate (cpu
);
14245 case BR_UNALLOC_011
:
14249 dexBranchImmediate (cpu
);
14252 case BR_IMMCMP_101
:
14253 /* Compare has bit 25 clear while test has it set. */
14254 if (!INSTR (25, 25))
14255 dexCompareBranchImmediate (cpu
);
14257 dexTestBranchImmediate (cpu
);
14261 /* Unconditional branch reg has bit 25 set. */
14262 if (INSTR (25, 25))
14263 dexBranchRegister (cpu
);
14265 /* This includes both Excpn Gen, System and unalloc operations.
14266 We need to decode the Excpn Gen operation BRK so we can plant
14267 debugger entry points.
14268 Excpn Gen operations have instr [24] = 0.
14269 we need to decode at least one of the System operations NOP
14270 which is an alias for HINT #0.
14271 System operations have instr [24,22] = 100. */
14272 else if (INSTR (24, 24) == 0)
14275 else if (INSTR (24, 22) == 4)
14283 case BR_UNALLOC_111
:
14287 /* Should never reach here. */
14293 aarch64_decode_and_execute (sim_cpu
*cpu
, uint64_t pc
)
14295 /* We need to check if gdb wants an in here. */
14296 /* checkBreak (cpu);. */
14298 uint64_t group
= dispatchGroup (aarch64_get_instr (cpu
));
14302 case GROUP_PSEUDO_0000
: dexPseudo (cpu
); break;
14303 case GROUP_LDST_0100
: dexLdSt (cpu
); break;
14304 case GROUP_DPREG_0101
: dexDPReg (cpu
); break;
14305 case GROUP_LDST_0110
: dexLdSt (cpu
); break;
14306 case GROUP_ADVSIMD_0111
: dexAdvSIMD0 (cpu
); break;
14307 case GROUP_DPIMM_1000
: dexDPImm (cpu
); break;
14308 case GROUP_DPIMM_1001
: dexDPImm (cpu
); break;
14309 case GROUP_BREXSYS_1010
: dexBr (cpu
); break;
14310 case GROUP_BREXSYS_1011
: dexBr (cpu
); break;
14311 case GROUP_LDST_1100
: dexLdSt (cpu
); break;
14312 case GROUP_DPREG_1101
: dexDPReg (cpu
); break;
14313 case GROUP_LDST_1110
: dexLdSt (cpu
); break;
14314 case GROUP_ADVSIMD_1111
: dexAdvSIMD1 (cpu
); break;
14316 case GROUP_UNALLOC_0001
:
14317 case GROUP_UNALLOC_0010
:
14318 case GROUP_UNALLOC_0011
:
14322 /* Should never reach here. */
14328 aarch64_step (sim_cpu
*cpu
)
14330 uint64_t pc
= aarch64_get_PC (cpu
);
14332 if (pc
== TOP_LEVEL_RETURN_PC
)
14335 aarch64_set_next_PC (cpu
, pc
+ 4);
14337 /* Code is always little-endian. */
14338 sim_core_read_buffer (CPU_STATE (cpu
), cpu
, read_map
,
14339 & aarch64_get_instr (cpu
), pc
, 4);
14340 aarch64_get_instr (cpu
) = endian_le2h_4 (aarch64_get_instr (cpu
));
14342 TRACE_INSN (cpu
, " pc = %" PRIx64
" instr = %08x", pc
,
14343 aarch64_get_instr (cpu
));
14344 TRACE_DISASM (cpu
, pc
);
14346 aarch64_decode_and_execute (cpu
, pc
);
14352 aarch64_run (SIM_DESC sd
)
14354 sim_cpu
*cpu
= STATE_CPU (sd
, 0);
14356 while (aarch64_step (cpu
))
14358 aarch64_update_PC (cpu
);
14360 if (sim_events_tick (sd
))
14361 sim_events_process (sd
);
14364 sim_engine_halt (sd
, cpu
, NULL
, aarch64_get_PC (cpu
),
14365 sim_exited
, aarch64_get_reg_s32 (cpu
, R0
, NO_SP
));
14369 aarch64_init (sim_cpu
*cpu
, uint64_t pc
)
14371 uint64_t sp
= aarch64_get_stack_start (cpu
);
14373 /* Install SP, FP and PC and set LR to -20
14374 so we can detect a top-level return. */
14375 aarch64_set_reg_u64 (cpu
, SP
, SP_OK
, sp
);
14376 aarch64_set_reg_u64 (cpu
, FP
, SP_OK
, sp
);
14377 aarch64_set_reg_u64 (cpu
, LR
, SP_OK
, TOP_LEVEL_RETURN_PC
);
14378 aarch64_set_next_PC (cpu
, pc
);
14379 aarch64_update_PC (cpu
);
14380 aarch64_init_LIT_table ();