1 /* simulator.c -- Interface for the AArch64 simulator.
3 Copyright (C) 2015-2023 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 "aarch64-sim.h"
34 #include "simulator.h"
38 #include "sim-signal.h"
43 #define TST(_flag) (aarch64_test_CPSR_bit (cpu, _flag))
44 #define IS_SET(_X) (TST (( _X )) ? 1 : 0)
45 #define IS_CLEAR(_X) (TST (( _X )) ? 0 : 1)
47 /* Space saver macro. */
48 #define INSTR(HIGH, LOW) uimm (aarch64_get_instr (cpu), (HIGH), (LOW))
50 #define HALT_UNALLOC \
53 TRACE_DISASM (cpu, aarch64_get_PC (cpu)); \
55 "Unallocated instruction detected at sim line %d," \
56 " exe addr %" PRIx64, \
57 __LINE__, aarch64_get_PC (cpu)); \
58 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),\
59 sim_stopped, SIM_SIGILL); \
66 TRACE_DISASM (cpu, aarch64_get_PC (cpu)); \
68 "Unimplemented instruction detected at sim line %d," \
69 " exe addr %" PRIx64, \
70 __LINE__, aarch64_get_PC (cpu)); \
71 if (! TRACE_ANY_P (cpu)) \
72 sim_io_eprintf (CPU_STATE (cpu), "SIM Error: Unimplemented instruction: %#08x\n", \
73 aarch64_get_instr (cpu)); \
74 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),\
75 sim_stopped, SIM_SIGABRT); \
79 #define NYI_assert(HI, LO, EXPECTED) \
82 if (INSTR ((HI), (LO)) != (EXPECTED)) \
88 expand_logical_immediate (uint32_t S
, uint32_t R
, uint32_t N
)
94 /* The immediate value is S+1 bits to 1, left rotated by SIMDsize - R
95 (in other words, right rotated by R), then replicated. */
99 mask
= 0xffffffffffffffffull
;
105 case 0x00 ... 0x1f: /* 0xxxxx */ simd_size
= 32; break;
106 case 0x20 ... 0x2f: /* 10xxxx */ simd_size
= 16; S
&= 0xf; break;
107 case 0x30 ... 0x37: /* 110xxx */ simd_size
= 8; S
&= 0x7; break;
108 case 0x38 ... 0x3b: /* 1110xx */ simd_size
= 4; S
&= 0x3; break;
109 case 0x3c ... 0x3d: /* 11110x */ simd_size
= 2; S
&= 0x1; break;
112 mask
= (1ull << simd_size
) - 1;
113 /* Top bits are IGNORED. */
117 /* NOTE: if S = simd_size - 1 we get 0xf..f which is rejected. */
118 if (S
== simd_size
- 1)
121 /* S+1 consecutive bits to 1. */
122 /* NOTE: S can't be 63 due to detection above. */
123 imm
= (1ull << (S
+ 1)) - 1;
125 /* Rotate to the left by simd_size - R. */
127 imm
= ((imm
<< (simd_size
- R
)) & mask
) | (imm
>> R
);
129 /* Replicate the value according to SIMD size. */
132 case 2: imm
= (imm
<< 2) | imm
;
133 case 4: imm
= (imm
<< 4) | imm
;
134 case 8: imm
= (imm
<< 8) | imm
;
135 case 16: imm
= (imm
<< 16) | imm
;
136 case 32: imm
= (imm
<< 32) | imm
;
144 /* Instr[22,10] encodes N immr and imms. we want a lookup table
145 for each possible combination i.e. 13 bits worth of int entries. */
146 #define LI_TABLE_SIZE (1 << 13)
147 static uint64_t LITable
[LI_TABLE_SIZE
];
150 aarch64_init_LIT_table (void)
154 for (index
= 0; index
< LI_TABLE_SIZE
; index
++)
156 uint32_t N
= uimm (index
, 12, 12);
157 uint32_t immr
= uimm (index
, 11, 6);
158 uint32_t imms
= uimm (index
, 5, 0);
160 LITable
[index
] = expand_logical_immediate (imms
, immr
, N
);
165 dexNotify (sim_cpu
*cpu
)
167 /* instr[14,0] == type : 0 ==> method entry, 1 ==> method reentry
168 2 ==> exit Java, 3 ==> start next bytecode. */
169 uint32_t type
= INSTR (14, 0);
171 TRACE_EVENTS (cpu
, "Notify Insn encountered, type = 0x%x", type
);
176 /* aarch64_notifyMethodEntry (aarch64_get_reg_u64 (cpu, R23, 0),
177 aarch64_get_reg_u64 (cpu, R22, 0)); */
180 /* aarch64_notifyMethodReentry (aarch64_get_reg_u64 (cpu, R23, 0),
181 aarch64_get_reg_u64 (cpu, R22, 0)); */
184 /* aarch64_notifyMethodExit (); */
187 /* aarch64_notifyBCStart (aarch64_get_reg_u64 (cpu, R23, 0),
188 aarch64_get_reg_u64 (cpu, R22, 0)); */
193 /* secondary decode within top level groups */
196 dexPseudo (sim_cpu
*cpu
)
198 /* assert instr[28,27] = 00
200 We provide 2 pseudo instructions:
202 HALT stops execution of the simulator causing an immediate
203 return to the x86 code which entered it.
205 CALLOUT initiates recursive entry into x86 code. A register
206 argument holds the address of the x86 routine. Immediate
207 values in the instruction identify the number of general
208 purpose and floating point register arguments to be passed
209 and the type of any value to be returned. */
211 uint32_t PSEUDO_HALT
= 0xE0000000U
;
212 uint32_t PSEUDO_CALLOUT
= 0x00018000U
;
213 uint32_t PSEUDO_CALLOUTR
= 0x00018001U
;
214 uint32_t PSEUDO_NOTIFY
= 0x00014000U
;
217 if (aarch64_get_instr (cpu
) == PSEUDO_HALT
)
219 TRACE_EVENTS (cpu
, " Pseudo Halt Instruction");
220 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
221 sim_stopped
, SIM_SIGTRAP
);
224 dispatch
= INSTR (31, 15);
226 /* We do not handle callouts at the moment. */
227 if (dispatch
== PSEUDO_CALLOUT
|| dispatch
== PSEUDO_CALLOUTR
)
229 TRACE_EVENTS (cpu
, " Callout");
230 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
231 sim_stopped
, SIM_SIGABRT
);
234 else if (dispatch
== PSEUDO_NOTIFY
)
241 /* Load-store single register (unscaled offset)
242 These instructions employ a base register plus an unscaled signed
245 N.B. the base register (source) can be Xn or SP. all other
246 registers may not be SP. */
248 /* 32 bit load 32 bit unscaled signed 9 bit. */
250 ldur32 (sim_cpu
*cpu
, int32_t offset
)
252 unsigned rn
= INSTR (9, 5);
253 unsigned rt
= INSTR (4, 0);
255 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
256 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u32
257 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
261 /* 64 bit load 64 bit unscaled signed 9 bit. */
263 ldur64 (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_u64
270 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
274 /* 32 bit load zero-extended byte unscaled signed 9 bit. */
276 ldurb32 (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_u8
283 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
287 /* 32 bit load sign-extended byte unscaled signed 9 bit. */
289 ldursb32 (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
, (uint32_t) aarch64_get_mem_s8
296 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
300 /* 64 bit load sign-extended byte unscaled signed 9 bit. */
302 ldursb64 (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_s64 (cpu
, rt
, NO_SP
, aarch64_get_mem_s8
309 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
313 /* 32 bit load zero-extended short unscaled signed 9 bit */
315 ldurh32 (sim_cpu
*cpu
, int32_t offset
)
317 unsigned rn
= INSTR (9, 5);
318 unsigned rd
= INSTR (4, 0);
320 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
321 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, aarch64_get_mem_u16
322 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
326 /* 32 bit load sign-extended short unscaled signed 9 bit */
328 ldursh32 (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
, (uint32_t) aarch64_get_mem_s16
335 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
339 /* 64 bit load sign-extended short unscaled signed 9 bit */
341 ldursh64 (sim_cpu
*cpu
, int32_t offset
)
343 unsigned rn
= INSTR (9, 5);
344 unsigned rt
= INSTR (4, 0);
346 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
347 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, aarch64_get_mem_s16
348 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
352 /* 64 bit load sign-extended word unscaled signed 9 bit */
354 ldursw (sim_cpu
*cpu
, int32_t offset
)
356 unsigned rn
= INSTR (9, 5);
357 unsigned rd
= INSTR (4, 0);
359 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
360 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) aarch64_get_mem_s32
361 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
365 /* N.B. with stores the value in source is written to the address
366 identified by source2 modified by offset. */
368 /* 32 bit store 32 bit unscaled signed 9 bit. */
370 stur32 (sim_cpu
*cpu
, int32_t offset
)
372 unsigned rn
= INSTR (9, 5);
373 unsigned rd
= INSTR (4, 0);
375 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
376 aarch64_set_mem_u32 (cpu
,
377 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
378 aarch64_get_reg_u32 (cpu
, rd
, NO_SP
));
381 /* 64 bit store 64 bit unscaled signed 9 bit */
383 stur64 (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_u64 (cpu
,
390 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
391 aarch64_get_reg_u64 (cpu
, rd
, NO_SP
));
394 /* 32 bit store byte unscaled signed 9 bit */
396 sturb (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_u8 (cpu
,
403 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
404 aarch64_get_reg_u8 (cpu
, rd
, NO_SP
));
407 /* 32 bit store short unscaled signed 9 bit */
409 sturh (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_u16 (cpu
,
416 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
417 aarch64_get_reg_u16 (cpu
, rd
, NO_SP
));
420 /* Load single register pc-relative label
421 Offset is a signed 19 bit immediate count in words
424 /* 32 bit pc-relative load */
426 ldr32_pcrel (sim_cpu
*cpu
, int32_t offset
)
428 unsigned rd
= INSTR (4, 0);
430 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
431 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
433 (cpu
, aarch64_get_PC (cpu
) + offset
* 4));
436 /* 64 bit pc-relative load */
438 ldr_pcrel (sim_cpu
*cpu
, int32_t offset
)
440 unsigned rd
= INSTR (4, 0);
442 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
443 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
445 (cpu
, aarch64_get_PC (cpu
) + offset
* 4));
448 /* sign extended 32 bit pc-relative load */
450 ldrsw_pcrel (sim_cpu
*cpu
, int32_t offset
)
452 unsigned rd
= INSTR (4, 0);
454 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
455 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
457 (cpu
, aarch64_get_PC (cpu
) + offset
* 4));
460 /* float pc-relative load */
462 fldrs_pcrel (sim_cpu
*cpu
, int32_t offset
)
464 unsigned int rd
= INSTR (4, 0);
466 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
467 aarch64_set_vec_u32 (cpu
, rd
, 0,
469 (cpu
, aarch64_get_PC (cpu
) + offset
* 4));
472 /* double pc-relative load */
474 fldrd_pcrel (sim_cpu
*cpu
, int32_t offset
)
476 unsigned int st
= INSTR (4, 0);
478 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
479 aarch64_set_vec_u64 (cpu
, st
, 0,
481 (cpu
, aarch64_get_PC (cpu
) + offset
* 4));
484 /* long double pc-relative load. */
486 fldrq_pcrel (sim_cpu
*cpu
, int32_t offset
)
488 unsigned int st
= INSTR (4, 0);
489 uint64_t addr
= aarch64_get_PC (cpu
) + offset
* 4;
492 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
493 aarch64_get_mem_long_double (cpu
, addr
, & a
);
494 aarch64_set_FP_long_double (cpu
, st
, a
);
497 /* This can be used to scale an offset by applying
498 the requisite shift. the second argument is either
501 #define SCALE(_offset, _elementSize) \
502 ((_offset) << ScaleShift ## _elementSize)
504 /* This can be used to optionally scale a register derived offset
505 by applying the requisite shift as indicated by the Scaling
506 argument. The second argument is either Byte, Short, Word
507 or Long. The third argument is either Scaled or Unscaled.
508 N.B. when _Scaling is Scaled the shift gets ANDed with
509 all 1s while when it is Unscaled it gets ANDed with 0. */
511 #define OPT_SCALE(_offset, _elementType, _Scaling) \
512 ((_offset) << (_Scaling ? ScaleShift ## _elementType : 0))
514 /* This can be used to zero or sign extend a 32 bit register derived
515 value to a 64 bit value. the first argument must be the value as
516 a uint32_t and the second must be either UXTW or SXTW. The result
517 is returned as an int64_t. */
519 static inline int64_t
520 extend (uint32_t value
, Extension extension
)
528 /* A branchless variant of this ought to be possible. */
529 if (extension
== UXTW
|| extension
== NoExtension
)
536 /* Scalar Floating Point
538 FP load/store single register (4 addressing modes)
540 N.B. the base register (source) can be the stack pointer.
541 The secondary source register (source2) can only be an Xn register. */
543 /* Load 32 bit unscaled signed 9 bit with pre- or post-writeback. */
545 fldrs_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
547 unsigned rn
= INSTR (9, 5);
548 unsigned st
= INSTR (4, 0);
549 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
554 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
555 aarch64_set_vec_u32 (cpu
, st
, 0, aarch64_get_mem_u32 (cpu
, address
));
559 if (wb
!= NoWriteBack
)
560 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
563 /* Load 8 bit with unsigned 12 bit offset. */
565 fldrb_abs (sim_cpu
*cpu
, uint32_t offset
)
567 unsigned rd
= INSTR (4, 0);
568 unsigned rn
= INSTR (9, 5);
569 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
;
571 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
572 aarch64_set_vec_u8 (cpu
, rd
, 0, aarch64_get_mem_u32 (cpu
, addr
));
575 /* Load 16 bit scaled unsigned 12 bit. */
577 fldrh_abs (sim_cpu
*cpu
, uint32_t offset
)
579 unsigned rd
= INSTR (4, 0);
580 unsigned rn
= INSTR (9, 5);
581 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 16);
583 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
584 aarch64_set_vec_u16 (cpu
, rd
, 0, aarch64_get_mem_u16 (cpu
, addr
));
587 /* Load 32 bit scaled unsigned 12 bit. */
589 fldrs_abs (sim_cpu
*cpu
, uint32_t offset
)
591 unsigned rd
= INSTR (4, 0);
592 unsigned rn
= INSTR (9, 5);
593 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 32);
595 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
596 aarch64_set_vec_u32 (cpu
, rd
, 0, aarch64_get_mem_u32 (cpu
, addr
));
599 /* Load 64 bit scaled unsigned 12 bit. */
601 fldrd_abs (sim_cpu
*cpu
, uint32_t offset
)
603 unsigned rd
= INSTR (4, 0);
604 unsigned rn
= INSTR (9, 5);
605 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 64);
607 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
608 aarch64_set_vec_u64 (cpu
, rd
, 0, aarch64_get_mem_u64 (cpu
, addr
));
611 /* Load 128 bit scaled unsigned 12 bit. */
613 fldrq_abs (sim_cpu
*cpu
, uint32_t offset
)
615 unsigned rd
= INSTR (4, 0);
616 unsigned rn
= INSTR (9, 5);
617 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 128);
619 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
620 aarch64_set_vec_u64 (cpu
, rd
, 0, aarch64_get_mem_u64 (cpu
, addr
));
621 aarch64_set_vec_u64 (cpu
, rd
, 1, aarch64_get_mem_u64 (cpu
, addr
+ 8));
624 /* Load 32 bit scaled or unscaled zero- or sign-extended
625 32-bit register offset. */
627 fldrs_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
629 unsigned rm
= INSTR (20, 16);
630 unsigned rn
= INSTR (9, 5);
631 unsigned st
= INSTR (4, 0);
632 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
633 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
634 uint64_t displacement
= OPT_SCALE (extended
, 32, scaling
);
636 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
637 aarch64_set_vec_u32 (cpu
, st
, 0, aarch64_get_mem_u32
638 (cpu
, address
+ displacement
));
641 /* Load 64 bit unscaled signed 9 bit with pre- or post-writeback. */
643 fldrd_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
645 unsigned rn
= INSTR (9, 5);
646 unsigned st
= INSTR (4, 0);
647 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
652 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
653 aarch64_set_vec_u64 (cpu
, st
, 0, aarch64_get_mem_u64 (cpu
, address
));
658 if (wb
!= NoWriteBack
)
659 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
662 /* Load 64 bit scaled or unscaled zero- or sign-extended 32-bit register offset. */
664 fldrd_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
666 unsigned rm
= INSTR (20, 16);
667 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
668 uint64_t displacement
= OPT_SCALE (extended
, 64, scaling
);
670 fldrd_wb (cpu
, displacement
, NoWriteBack
);
673 /* Load 128 bit unscaled signed 9 bit with pre- or post-writeback. */
675 fldrq_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
678 unsigned rn
= INSTR (9, 5);
679 unsigned st
= INSTR (4, 0);
680 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
685 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
686 aarch64_get_mem_long_double (cpu
, address
, & a
);
687 aarch64_set_FP_long_double (cpu
, st
, a
);
692 if (wb
!= NoWriteBack
)
693 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
696 /* Load 128 bit scaled or unscaled zero- or sign-extended 32-bit register offset */
698 fldrq_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
700 unsigned rm
= INSTR (20, 16);
701 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
702 uint64_t displacement
= OPT_SCALE (extended
, 128, scaling
);
704 fldrq_wb (cpu
, displacement
, NoWriteBack
);
709 load-store single register
710 There are four addressing modes available here which all employ a
711 64 bit source (base) register.
713 N.B. the base register (source) can be the stack pointer.
714 The secondary source register (source2)can only be an Xn register.
716 Scaled, 12-bit, unsigned immediate offset, without pre- and
718 Unscaled, 9-bit, signed immediate offset with pre- or post-index
720 scaled or unscaled 64-bit register offset.
721 scaled or unscaled 32-bit extended register offset.
723 All offsets are assumed to be raw from the decode i.e. the
724 simulator is expected to adjust scaled offsets based on the
725 accessed data size with register or extended register offset
726 versions the same applies except that in the latter case the
727 operation may also require a sign extend.
729 A separate method is provided for each possible addressing mode. */
731 /* 32 bit load 32 bit scaled unsigned 12 bit */
733 ldr32_abs (sim_cpu
*cpu
, uint32_t offset
)
735 unsigned rn
= INSTR (9, 5);
736 unsigned rt
= INSTR (4, 0);
738 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
739 /* The target register may not be SP but the source may be. */
740 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u32
741 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
742 + SCALE (offset
, 32)));
745 /* 32 bit load 32 bit unscaled signed 9 bit with pre- or post-writeback. */
747 ldr32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
749 unsigned rn
= INSTR (9, 5);
750 unsigned rt
= INSTR (4, 0);
753 if (rn
== rt
&& wb
!= NoWriteBack
)
756 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
761 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
762 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u32 (cpu
, address
));
767 if (wb
!= NoWriteBack
)
768 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
771 /* 32 bit load 32 bit scaled or unscaled
772 zero- or sign-extended 32-bit register offset */
774 ldr32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
776 unsigned rm
= INSTR (20, 16);
777 unsigned rn
= INSTR (9, 5);
778 unsigned rt
= INSTR (4, 0);
779 /* rn may reference SP, rm and rt must reference ZR */
781 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
782 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
783 uint64_t displacement
= OPT_SCALE (extended
, 32, scaling
);
785 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
786 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
787 aarch64_get_mem_u32 (cpu
, address
+ displacement
));
790 /* 64 bit load 64 bit scaled unsigned 12 bit */
792 ldr_abs (sim_cpu
*cpu
, uint32_t offset
)
794 unsigned rn
= INSTR (9, 5);
795 unsigned rt
= INSTR (4, 0);
797 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
798 /* The target register may not be SP but the source may be. */
799 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u64
800 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
801 + SCALE (offset
, 64)));
804 /* 64 bit load 64 bit unscaled signed 9 bit with pre- or post-writeback. */
806 ldr_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
808 unsigned rn
= INSTR (9, 5);
809 unsigned rt
= INSTR (4, 0);
812 if (rn
== rt
&& wb
!= NoWriteBack
)
815 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
820 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
821 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u64 (cpu
, address
));
826 if (wb
!= NoWriteBack
)
827 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
830 /* 64 bit load 64 bit scaled or unscaled zero-
831 or sign-extended 32-bit register offset. */
833 ldr_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
835 unsigned rm
= INSTR (20, 16);
836 unsigned rn
= INSTR (9, 5);
837 unsigned rt
= INSTR (4, 0);
838 /* rn may reference SP, rm and rt must reference ZR */
840 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
841 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
842 uint64_t displacement
= OPT_SCALE (extended
, 64, scaling
);
844 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
845 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
846 aarch64_get_mem_u64 (cpu
, address
+ displacement
));
849 /* 32 bit load zero-extended byte scaled unsigned 12 bit. */
851 ldrb32_abs (sim_cpu
*cpu
, uint32_t offset
)
853 unsigned rn
= INSTR (9, 5);
854 unsigned rt
= INSTR (4, 0);
856 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
857 /* The target register may not be SP but the source may be
858 there is no scaling required for a byte load. */
859 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
861 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
));
864 /* 32 bit load zero-extended byte unscaled signed 9 bit with pre- or post-writeback. */
866 ldrb32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
868 unsigned rn
= INSTR (9, 5);
869 unsigned rt
= INSTR (4, 0);
872 if (rn
== rt
&& wb
!= NoWriteBack
)
875 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
880 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
881 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u8 (cpu
, address
));
886 if (wb
!= NoWriteBack
)
887 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
890 /* 32 bit load zero-extended byte scaled or unscaled zero-
891 or sign-extended 32-bit register offset. */
893 ldrb32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
895 unsigned rm
= INSTR (20, 16);
896 unsigned rn
= INSTR (9, 5);
897 unsigned rt
= INSTR (4, 0);
898 /* rn may reference SP, rm and rt must reference ZR */
900 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
901 int64_t displacement
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
904 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
905 /* There is no scaling required for a byte load. */
906 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
907 aarch64_get_mem_u8 (cpu
, address
+ displacement
));
910 /* 64 bit load sign-extended byte unscaled signed 9 bit
911 with pre- or post-writeback. */
913 ldrsb_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
915 unsigned rn
= INSTR (9, 5);
916 unsigned rt
= INSTR (4, 0);
920 if (rn
== rt
&& wb
!= NoWriteBack
)
923 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
928 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
929 val
= aarch64_get_mem_s8 (cpu
, address
);
930 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, val
);
935 if (wb
!= NoWriteBack
)
936 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
939 /* 64 bit load sign-extended byte scaled unsigned 12 bit. */
941 ldrsb_abs (sim_cpu
*cpu
, uint32_t offset
)
943 ldrsb_wb (cpu
, offset
, NoWriteBack
);
946 /* 64 bit load sign-extended byte scaled or unscaled zero-
947 or sign-extended 32-bit register offset. */
949 ldrsb_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
951 unsigned rm
= INSTR (20, 16);
952 unsigned rn
= INSTR (9, 5);
953 unsigned rt
= INSTR (4, 0);
954 /* rn may reference SP, rm and rt must reference ZR */
956 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
957 int64_t displacement
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
959 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
960 /* There is no scaling required for a byte load. */
961 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
,
962 aarch64_get_mem_s8 (cpu
, address
+ displacement
));
965 /* 32 bit load zero-extended short scaled unsigned 12 bit. */
967 ldrh32_abs (sim_cpu
*cpu
, uint32_t offset
)
969 unsigned rn
= INSTR (9, 5);
970 unsigned rt
= INSTR (4, 0);
973 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
974 /* The target register may not be SP but the source may be. */
975 val
= aarch64_get_mem_u16 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
976 + SCALE (offset
, 16));
977 aarch64_set_reg_u32 (cpu
, rt
, NO_SP
, val
);
980 /* 32 bit load zero-extended short unscaled signed 9 bit
981 with pre- or post-writeback. */
983 ldrh32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
985 unsigned rn
= INSTR (9, 5);
986 unsigned rt
= INSTR (4, 0);
989 if (rn
== rt
&& wb
!= NoWriteBack
)
992 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
997 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
998 aarch64_set_reg_u32 (cpu
, rt
, NO_SP
, aarch64_get_mem_u16 (cpu
, address
));
1003 if (wb
!= NoWriteBack
)
1004 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1007 /* 32 bit load zero-extended short scaled or unscaled zero-
1008 or sign-extended 32-bit register offset. */
1010 ldrh32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1012 unsigned rm
= INSTR (20, 16);
1013 unsigned rn
= INSTR (9, 5);
1014 unsigned rt
= INSTR (4, 0);
1015 /* rn may reference SP, rm and rt must reference ZR */
1017 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1018 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
1019 uint64_t displacement
= OPT_SCALE (extended
, 16, scaling
);
1021 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1022 aarch64_set_reg_u32 (cpu
, rt
, NO_SP
,
1023 aarch64_get_mem_u16 (cpu
, address
+ displacement
));
1026 /* 32 bit load sign-extended short scaled unsigned 12 bit. */
1028 ldrsh32_abs (sim_cpu
*cpu
, uint32_t offset
)
1030 unsigned rn
= INSTR (9, 5);
1031 unsigned rt
= INSTR (4, 0);
1034 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1035 /* The target register may not be SP but the source may be. */
1036 val
= aarch64_get_mem_s16 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
1037 + SCALE (offset
, 16));
1038 aarch64_set_reg_s32 (cpu
, rt
, NO_SP
, val
);
1041 /* 32 bit load sign-extended short unscaled signed 9 bit
1042 with pre- or post-writeback. */
1044 ldrsh32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1046 unsigned rn
= INSTR (9, 5);
1047 unsigned rt
= INSTR (4, 0);
1050 if (rn
== rt
&& wb
!= NoWriteBack
)
1053 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1058 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1059 aarch64_set_reg_s32 (cpu
, rt
, NO_SP
,
1060 (int32_t) aarch64_get_mem_s16 (cpu
, address
));
1065 if (wb
!= NoWriteBack
)
1066 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1069 /* 32 bit load sign-extended short scaled or unscaled zero-
1070 or sign-extended 32-bit register offset. */
1072 ldrsh32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1074 unsigned rm
= INSTR (20, 16);
1075 unsigned rn
= INSTR (9, 5);
1076 unsigned rt
= INSTR (4, 0);
1077 /* rn may reference SP, rm and rt must reference ZR */
1079 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1080 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
1081 uint64_t displacement
= OPT_SCALE (extended
, 16, scaling
);
1083 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1084 aarch64_set_reg_s32 (cpu
, rt
, NO_SP
,
1085 (int32_t) aarch64_get_mem_s16
1086 (cpu
, address
+ displacement
));
1089 /* 64 bit load sign-extended short scaled unsigned 12 bit. */
1091 ldrsh_abs (sim_cpu
*cpu
, uint32_t offset
)
1093 unsigned rn
= INSTR (9, 5);
1094 unsigned rt
= INSTR (4, 0);
1097 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1098 /* The target register may not be SP but the source may be. */
1099 val
= aarch64_get_mem_s16 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
1100 + SCALE (offset
, 16));
1101 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, val
);
1104 /* 64 bit load sign-extended short unscaled signed 9 bit
1105 with pre- or post-writeback. */
1107 ldrsh64_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1109 unsigned rn
= INSTR (9, 5);
1110 unsigned rt
= INSTR (4, 0);
1114 if (rn
== rt
&& wb
!= NoWriteBack
)
1117 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1118 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1123 val
= aarch64_get_mem_s16 (cpu
, address
);
1124 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, val
);
1129 if (wb
!= NoWriteBack
)
1130 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1133 /* 64 bit load sign-extended short scaled or unscaled zero-
1134 or sign-extended 32-bit register offset. */
1136 ldrsh_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1138 unsigned rm
= INSTR (20, 16);
1139 unsigned rn
= INSTR (9, 5);
1140 unsigned rt
= INSTR (4, 0);
1142 /* rn may reference SP, rm and rt must reference ZR */
1144 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1145 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
1146 uint64_t displacement
= OPT_SCALE (extended
, 16, scaling
);
1149 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1150 val
= aarch64_get_mem_s16 (cpu
, address
+ displacement
);
1151 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, val
);
1154 /* 64 bit load sign-extended 32 bit scaled unsigned 12 bit. */
1156 ldrsw_abs (sim_cpu
*cpu
, uint32_t offset
)
1158 unsigned rn
= INSTR (9, 5);
1159 unsigned rt
= INSTR (4, 0);
1162 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1163 val
= aarch64_get_mem_s32 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
1164 + SCALE (offset
, 32));
1165 /* The target register may not be SP but the source may be. */
1166 return aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, val
);
1169 /* 64 bit load sign-extended 32 bit unscaled signed 9 bit
1170 with pre- or post-writeback. */
1172 ldrsw_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1174 unsigned rn
= INSTR (9, 5);
1175 unsigned rt
= INSTR (4, 0);
1178 if (rn
== rt
&& wb
!= NoWriteBack
)
1181 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1186 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1187 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
, aarch64_get_mem_s32 (cpu
, address
));
1192 if (wb
!= NoWriteBack
)
1193 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1196 /* 64 bit load sign-extended 32 bit scaled or unscaled zero-
1197 or sign-extended 32-bit register offset. */
1199 ldrsw_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1201 unsigned rm
= INSTR (20, 16);
1202 unsigned rn
= INSTR (9, 5);
1203 unsigned rt
= INSTR (4, 0);
1204 /* rn may reference SP, rm and rt must reference ZR */
1206 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1207 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
1208 uint64_t displacement
= OPT_SCALE (extended
, 32, scaling
);
1210 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1211 aarch64_set_reg_s64 (cpu
, rt
, NO_SP
,
1212 aarch64_get_mem_s32 (cpu
, address
+ displacement
));
1215 /* N.B. with stores the value in source is written to the
1216 address identified by source2 modified by source3/offset. */
1218 /* 32 bit store scaled unsigned 12 bit. */
1220 str32_abs (sim_cpu
*cpu
, uint32_t offset
)
1222 unsigned rn
= INSTR (9, 5);
1223 unsigned rt
= INSTR (4, 0);
1225 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1226 /* The target register may not be SP but the source may be. */
1227 aarch64_set_mem_u32 (cpu
, (aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
1228 + SCALE (offset
, 32)),
1229 aarch64_get_reg_u32 (cpu
, rt
, NO_SP
));
1232 /* 32 bit store unscaled signed 9 bit with pre- or post-writeback. */
1234 str32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1236 unsigned rn
= INSTR (9, 5);
1237 unsigned rt
= INSTR (4, 0);
1240 if (rn
== rt
&& wb
!= NoWriteBack
)
1243 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1247 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1248 aarch64_set_mem_u32 (cpu
, address
, aarch64_get_reg_u32 (cpu
, rt
, NO_SP
));
1253 if (wb
!= NoWriteBack
)
1254 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1257 /* 32 bit store scaled or unscaled zero- or
1258 sign-extended 32-bit register offset. */
1260 str32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1262 unsigned rm
= INSTR (20, 16);
1263 unsigned rn
= INSTR (9, 5);
1264 unsigned rt
= INSTR (4, 0);
1266 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1267 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
1268 uint64_t displacement
= OPT_SCALE (extended
, 32, scaling
);
1270 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1271 aarch64_set_mem_u32 (cpu
, address
+ displacement
,
1272 aarch64_get_reg_u64 (cpu
, rt
, NO_SP
));
1275 /* 64 bit store scaled unsigned 12 bit. */
1277 str_abs (sim_cpu
*cpu
, uint32_t offset
)
1279 unsigned rn
= INSTR (9, 5);
1280 unsigned rt
= INSTR (4, 0);
1282 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1283 aarch64_set_mem_u64 (cpu
,
1284 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
1285 + SCALE (offset
, 64),
1286 aarch64_get_reg_u64 (cpu
, rt
, NO_SP
));
1289 /* 64 bit store unscaled signed 9 bit with pre- or post-writeback. */
1291 str_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1293 unsigned rn
= INSTR (9, 5);
1294 unsigned rt
= INSTR (4, 0);
1297 if (rn
== rt
&& wb
!= NoWriteBack
)
1300 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1305 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1306 aarch64_set_mem_u64 (cpu
, address
, aarch64_get_reg_u64 (cpu
, rt
, NO_SP
));
1311 if (wb
!= NoWriteBack
)
1312 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1315 /* 64 bit store scaled or unscaled zero-
1316 or sign-extended 32-bit register offset. */
1318 str_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1320 unsigned rm
= INSTR (20, 16);
1321 unsigned rn
= INSTR (9, 5);
1322 unsigned rt
= INSTR (4, 0);
1323 /* rn may reference SP, rm and rt must reference ZR */
1325 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1326 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
1328 uint64_t displacement
= OPT_SCALE (extended
, 64, scaling
);
1330 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1331 aarch64_set_mem_u64 (cpu
, address
+ displacement
,
1332 aarch64_get_reg_u64 (cpu
, rt
, NO_SP
));
1335 /* 32 bit store byte scaled unsigned 12 bit. */
1337 strb_abs (sim_cpu
*cpu
, uint32_t offset
)
1339 unsigned rn
= INSTR (9, 5);
1340 unsigned rt
= INSTR (4, 0);
1342 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1343 /* The target register may not be SP but the source may be.
1344 There is no scaling required for a byte load. */
1345 aarch64_set_mem_u8 (cpu
,
1346 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
1347 aarch64_get_reg_u8 (cpu
, rt
, NO_SP
));
1350 /* 32 bit store byte unscaled signed 9 bit with pre- or post-writeback. */
1352 strb_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1354 unsigned rn
= INSTR (9, 5);
1355 unsigned rt
= INSTR (4, 0);
1358 if (rn
== rt
&& wb
!= NoWriteBack
)
1361 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1366 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1367 aarch64_set_mem_u8 (cpu
, address
, aarch64_get_reg_u8 (cpu
, rt
, NO_SP
));
1372 if (wb
!= NoWriteBack
)
1373 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1376 /* 32 bit store byte scaled or unscaled zero-
1377 or sign-extended 32-bit register offset. */
1379 strb_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1381 unsigned rm
= INSTR (20, 16);
1382 unsigned rn
= INSTR (9, 5);
1383 unsigned rt
= INSTR (4, 0);
1384 /* rn may reference SP, rm and rt must reference ZR */
1386 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1387 int64_t displacement
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
1390 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1391 /* There is no scaling required for a byte load. */
1392 aarch64_set_mem_u8 (cpu
, address
+ displacement
,
1393 aarch64_get_reg_u8 (cpu
, rt
, NO_SP
));
1396 /* 32 bit store short scaled unsigned 12 bit. */
1398 strh_abs (sim_cpu
*cpu
, uint32_t offset
)
1400 unsigned rn
= INSTR (9, 5);
1401 unsigned rt
= INSTR (4, 0);
1403 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1404 /* The target register may not be SP but the source may be. */
1405 aarch64_set_mem_u16 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
1406 + SCALE (offset
, 16),
1407 aarch64_get_reg_u16 (cpu
, rt
, NO_SP
));
1410 /* 32 bit store short unscaled signed 9 bit with pre- or post-writeback. */
1412 strh_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
1414 unsigned rn
= INSTR (9, 5);
1415 unsigned rt
= INSTR (4, 0);
1418 if (rn
== rt
&& wb
!= NoWriteBack
)
1421 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1426 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1427 aarch64_set_mem_u16 (cpu
, address
, aarch64_get_reg_u16 (cpu
, rt
, NO_SP
));
1432 if (wb
!= NoWriteBack
)
1433 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
1436 /* 32 bit store short scaled or unscaled zero-
1437 or sign-extended 32-bit register offset. */
1439 strh_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1441 unsigned rm
= INSTR (20, 16);
1442 unsigned rn
= INSTR (9, 5);
1443 unsigned rt
= INSTR (4, 0);
1444 /* rn may reference SP, rm and rt must reference ZR */
1446 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1447 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), extension
);
1448 uint64_t displacement
= OPT_SCALE (extended
, 16, scaling
);
1450 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1451 aarch64_set_mem_u16 (cpu
, address
+ displacement
,
1452 aarch64_get_reg_u16 (cpu
, rt
, NO_SP
));
1455 /* Prefetch unsigned 12 bit. */
1457 prfm_abs (sim_cpu
*cpu
, uint32_t offset
)
1459 /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1460 00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1461 00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1462 10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1463 10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1464 10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1466 PrfOp prfop = prfop (instr, 4, 0);
1467 uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK)
1468 + SCALE (offset, 64). */
1470 /* TODO : implement prefetch of address. */
1473 /* Prefetch scaled or unscaled zero- or sign-extended 32-bit register offset. */
1475 prfm_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
1477 /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1478 00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1479 00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1480 10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1481 10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1482 10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1484 rn may reference SP, rm may only reference ZR
1485 PrfOp prfop = prfop (instr, 4, 0);
1486 uint64_t base = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1487 int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1489 uint64_t displacement = OPT_SCALE (extended, 64, scaling);
1490 uint64_t address = base + displacement. */
1492 /* TODO : implement prefetch of address */
1495 /* 64 bit pc-relative prefetch. */
1497 prfm_pcrel (sim_cpu
*cpu
, int32_t offset
)
1499 /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1500 00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1501 00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1502 10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1503 10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1504 10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1506 PrfOp prfop = prfop (instr, 4, 0);
1507 uint64_t address = aarch64_get_PC (cpu) + offset. */
1509 /* TODO : implement this */
1512 /* Load-store exclusive. */
1517 unsigned rn
= INSTR (9, 5);
1518 unsigned rt
= INSTR (4, 0);
1519 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1520 int size
= INSTR (31, 30);
1521 /* int ordered = INSTR (15, 15); */
1522 /* int exclusive = ! INSTR (23, 23); */
1524 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1528 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u8 (cpu
, address
));
1531 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u16 (cpu
, address
));
1534 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u32 (cpu
, address
));
1537 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
, aarch64_get_mem_u64 (cpu
, address
));
1545 unsigned rn
= INSTR (9, 5);
1546 unsigned rt
= INSTR (4, 0);
1547 unsigned rs
= INSTR (20, 16);
1548 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1549 int size
= INSTR (31, 30);
1550 uint64_t data
= aarch64_get_reg_u64 (cpu
, rt
, NO_SP
);
1554 case 0: aarch64_set_mem_u8 (cpu
, address
, data
); break;
1555 case 1: aarch64_set_mem_u16 (cpu
, address
, data
); break;
1556 case 2: aarch64_set_mem_u32 (cpu
, address
, data
); break;
1557 case 3: aarch64_set_mem_u64 (cpu
, address
, data
); break;
1560 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1561 aarch64_set_reg_u64 (cpu
, rs
, NO_SP
, 0); /* Always exclusive... */
1565 dexLoadLiteral (sim_cpu
*cpu
)
1567 /* instr[29,27] == 011
1569 instr[31,30:26] = opc: 000 ==> LDRW, 001 ==> FLDRS
1570 010 ==> LDRX, 011 ==> FLDRD
1571 100 ==> LDRSW, 101 ==> FLDRQ
1572 110 ==> PRFM, 111 ==> UNALLOC
1573 instr[26] ==> V : 0 ==> GReg, 1 ==> FReg
1574 instr[23, 5] == simm19 */
1576 /* unsigned rt = INSTR (4, 0); */
1577 uint32_t dispatch
= (INSTR (31, 30) << 1) | INSTR (26, 26);
1578 int32_t imm
= simm32 (aarch64_get_instr (cpu
), 23, 5);
1582 case 0: ldr32_pcrel (cpu
, imm
); break;
1583 case 1: fldrs_pcrel (cpu
, imm
); break;
1584 case 2: ldr_pcrel (cpu
, imm
); break;
1585 case 3: fldrd_pcrel (cpu
, imm
); break;
1586 case 4: ldrsw_pcrel (cpu
, imm
); break;
1587 case 5: fldrq_pcrel (cpu
, imm
); break;
1588 case 6: prfm_pcrel (cpu
, imm
); break;
1595 /* Immediate arithmetic
1596 The aimm argument is a 12 bit unsigned value or a 12 bit unsigned
1597 value left shifted by 12 bits (done at decode).
1599 N.B. the register args (dest, source) can normally be Xn or SP.
1600 the exception occurs for flag setting instructions which may
1601 only use Xn for the output (dest). */
1603 /* 32 bit add immediate. */
1605 add32 (sim_cpu
*cpu
, uint32_t aimm
)
1607 unsigned rn
= INSTR (9, 5);
1608 unsigned rd
= INSTR (4, 0);
1610 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1611 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
1612 aarch64_get_reg_u32 (cpu
, rn
, SP_OK
) + aimm
);
1615 /* 64 bit add immediate. */
1617 add64 (sim_cpu
*cpu
, uint32_t aimm
)
1619 unsigned rn
= INSTR (9, 5);
1620 unsigned rd
= INSTR (4, 0);
1622 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1623 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
1624 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + aimm
);
1628 set_flags_for_add32 (sim_cpu
*cpu
, int32_t value1
, int32_t value2
)
1630 int32_t result
= value1
+ value2
;
1631 int64_t sresult
= (int64_t) value1
+ (int64_t) value2
;
1632 uint64_t uresult
= (uint64_t)(uint32_t) value1
1633 + (uint64_t)(uint32_t) value2
;
1639 if (result
& (1 << 31))
1642 if (uresult
!= (uint32_t)uresult
)
1645 if (sresult
!= (int32_t)sresult
)
1648 aarch64_set_CPSR (cpu
, flags
);
1651 #define NEG(a) (((a) & signbit) == signbit)
1652 #define POS(a) (((a) & signbit) == 0)
1655 set_flags_for_add64 (sim_cpu
*cpu
, uint64_t value1
, uint64_t value2
)
1657 uint64_t result
= value1
+ value2
;
1659 uint64_t signbit
= 1ULL << 63;
1667 if ( (NEG (value1
) && NEG (value2
))
1668 || (NEG (value1
) && POS (result
))
1669 || (NEG (value2
) && POS (result
)))
1672 if ( (NEG (value1
) && NEG (value2
) && POS (result
))
1673 || (POS (value1
) && POS (value2
) && NEG (result
)))
1676 aarch64_set_CPSR (cpu
, flags
);
1680 set_flags_for_sub32 (sim_cpu
*cpu
, uint32_t value1
, uint32_t value2
)
1682 uint32_t result
= value1
- value2
;
1684 uint32_t signbit
= 1U << 31;
1692 if ( (NEG (value1
) && POS (value2
))
1693 || (NEG (value1
) && POS (result
))
1694 || (POS (value2
) && POS (result
)))
1697 if ( (NEG (value1
) && POS (value2
) && POS (result
))
1698 || (POS (value1
) && NEG (value2
) && NEG (result
)))
1701 aarch64_set_CPSR (cpu
, flags
);
1705 set_flags_for_sub64 (sim_cpu
*cpu
, uint64_t value1
, uint64_t value2
)
1707 uint64_t result
= value1
- value2
;
1709 uint64_t signbit
= 1ULL << 63;
1717 if ( (NEG (value1
) && POS (value2
))
1718 || (NEG (value1
) && POS (result
))
1719 || (POS (value2
) && POS (result
)))
1722 if ( (NEG (value1
) && POS (value2
) && POS (result
))
1723 || (POS (value1
) && NEG (value2
) && NEG (result
)))
1726 aarch64_set_CPSR (cpu
, flags
);
1730 set_flags_for_binop32 (sim_cpu
*cpu
, uint32_t result
)
1739 if (result
& (1 << 31))
1744 aarch64_set_CPSR (cpu
, flags
);
1748 set_flags_for_binop64 (sim_cpu
*cpu
, uint64_t result
)
1757 if (result
& (1ULL << 63))
1762 aarch64_set_CPSR (cpu
, flags
);
1765 /* 32 bit add immediate set flags. */
1767 adds32 (sim_cpu
*cpu
, uint32_t aimm
)
1769 unsigned rn
= INSTR (9, 5);
1770 unsigned rd
= INSTR (4, 0);
1771 /* TODO : do we need to worry about signs here? */
1772 int32_t value1
= aarch64_get_reg_s32 (cpu
, rn
, SP_OK
);
1774 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1775 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ aimm
);
1776 set_flags_for_add32 (cpu
, value1
, aimm
);
1779 /* 64 bit add immediate set flags. */
1781 adds64 (sim_cpu
*cpu
, uint32_t aimm
)
1783 unsigned rn
= INSTR (9, 5);
1784 unsigned rd
= INSTR (4, 0);
1785 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1786 uint64_t value2
= aimm
;
1788 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1789 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
);
1790 set_flags_for_add64 (cpu
, value1
, value2
);
1793 /* 32 bit sub immediate. */
1795 sub32 (sim_cpu
*cpu
, uint32_t aimm
)
1797 unsigned rn
= INSTR (9, 5);
1798 unsigned rd
= INSTR (4, 0);
1800 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1801 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
1802 aarch64_get_reg_u32 (cpu
, rn
, SP_OK
) - aimm
);
1805 /* 64 bit sub immediate. */
1807 sub64 (sim_cpu
*cpu
, uint32_t aimm
)
1809 unsigned rn
= INSTR (9, 5);
1810 unsigned rd
= INSTR (4, 0);
1812 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1813 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
1814 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) - aimm
);
1817 /* 32 bit sub immediate set flags. */
1819 subs32 (sim_cpu
*cpu
, uint32_t aimm
)
1821 unsigned rn
= INSTR (9, 5);
1822 unsigned rd
= INSTR (4, 0);
1823 uint32_t value1
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1824 uint32_t value2
= aimm
;
1826 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1827 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
1828 set_flags_for_sub32 (cpu
, value1
, value2
);
1831 /* 64 bit sub immediate set flags. */
1833 subs64 (sim_cpu
*cpu
, uint32_t aimm
)
1835 unsigned rn
= INSTR (9, 5);
1836 unsigned rd
= INSTR (4, 0);
1837 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
1838 uint32_t value2
= aimm
;
1840 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1841 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
1842 set_flags_for_sub64 (cpu
, value1
, value2
);
1845 /* Data Processing Register. */
1847 /* First two helpers to perform the shift operations. */
1849 static inline uint32_t
1850 shifted32 (uint32_t value
, Shift shift
, uint32_t count
)
1856 return (value
<< count
);
1858 return (value
>> count
);
1861 int32_t svalue
= value
;
1862 return (svalue
>> count
);
1866 uint32_t top
= value
>> count
;
1867 uint32_t bottom
= value
<< (32 - count
);
1868 return (bottom
| top
);
1873 static inline uint64_t
1874 shifted64 (uint64_t value
, Shift shift
, uint32_t count
)
1880 return (value
<< count
);
1882 return (value
>> count
);
1885 int64_t svalue
= value
;
1886 return (svalue
>> count
);
1890 uint64_t top
= value
>> count
;
1891 uint64_t bottom
= value
<< (64 - count
);
1892 return (bottom
| top
);
1897 /* Arithmetic shifted register.
1898 These allow an optional LSL, ASR or LSR to the second source
1899 register with a count up to the register bit count.
1901 N.B register args may not be SP. */
1903 /* 32 bit ADD shifted register. */
1905 add32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1907 unsigned rm
= INSTR (20, 16);
1908 unsigned rn
= INSTR (9, 5);
1909 unsigned rd
= INSTR (4, 0);
1911 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1912 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
1913 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
1914 + shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
1918 /* 64 bit ADD shifted register. */
1920 add64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1922 unsigned rm
= INSTR (20, 16);
1923 unsigned rn
= INSTR (9, 5);
1924 unsigned rd
= INSTR (4, 0);
1926 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1927 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
1928 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
1929 + shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
1933 /* 32 bit ADD shifted register setting flags. */
1935 adds32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1937 unsigned rm
= INSTR (20, 16);
1938 unsigned rn
= INSTR (9, 5);
1939 unsigned rd
= INSTR (4, 0);
1941 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
1942 uint32_t value2
= shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
1945 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1946 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
);
1947 set_flags_for_add32 (cpu
, value1
, value2
);
1950 /* 64 bit ADD shifted register setting flags. */
1952 adds64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1954 unsigned rm
= INSTR (20, 16);
1955 unsigned rn
= INSTR (9, 5);
1956 unsigned rd
= INSTR (4, 0);
1958 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
1959 uint64_t value2
= shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
1962 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1963 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
);
1964 set_flags_for_add64 (cpu
, value1
, value2
);
1967 /* 32 bit SUB shifted register. */
1969 sub32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1971 unsigned rm
= INSTR (20, 16);
1972 unsigned rn
= INSTR (9, 5);
1973 unsigned rd
= INSTR (4, 0);
1975 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1976 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
1977 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
1978 - shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
1982 /* 64 bit SUB shifted register. */
1984 sub64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
1986 unsigned rm
= INSTR (20, 16);
1987 unsigned rn
= INSTR (9, 5);
1988 unsigned rd
= INSTR (4, 0);
1990 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
1991 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
1992 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
1993 - shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
1997 /* 32 bit SUB shifted register setting flags. */
1999 subs32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
2001 unsigned rm
= INSTR (20, 16);
2002 unsigned rn
= INSTR (9, 5);
2003 unsigned rd
= INSTR (4, 0);
2005 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
2006 uint32_t value2
= shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
2009 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2010 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
2011 set_flags_for_sub32 (cpu
, value1
, value2
);
2014 /* 64 bit SUB shifted register setting flags. */
2016 subs64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
2018 unsigned rm
= INSTR (20, 16);
2019 unsigned rn
= INSTR (9, 5);
2020 unsigned rd
= INSTR (4, 0);
2022 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
2023 uint64_t value2
= shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
2026 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2027 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
2028 set_flags_for_sub64 (cpu
, value1
, value2
);
2031 /* First a couple more helpers to fetch the
2032 relevant source register element either
2033 sign or zero extended as required by the
2037 extreg32 (sim_cpu
*cpu
, unsigned int lo
, Extension extension
)
2041 case UXTB
: return aarch64_get_reg_u8 (cpu
, lo
, NO_SP
);
2042 case UXTH
: return aarch64_get_reg_u16 (cpu
, lo
, NO_SP
);
2043 case UXTW
: /* Fall through. */
2044 case UXTX
: return aarch64_get_reg_u32 (cpu
, lo
, NO_SP
);
2045 case SXTB
: return aarch64_get_reg_s8 (cpu
, lo
, NO_SP
);
2046 case SXTH
: return aarch64_get_reg_s16 (cpu
, lo
, NO_SP
);
2047 case SXTW
: /* Fall through. */
2048 case SXTX
: /* Fall through. */
2049 default: return aarch64_get_reg_s32 (cpu
, lo
, NO_SP
);
2054 extreg64 (sim_cpu
*cpu
, unsigned int lo
, Extension extension
)
2058 case UXTB
: return aarch64_get_reg_u8 (cpu
, lo
, NO_SP
);
2059 case UXTH
: return aarch64_get_reg_u16 (cpu
, lo
, NO_SP
);
2060 case UXTW
: return aarch64_get_reg_u32 (cpu
, lo
, NO_SP
);
2061 case UXTX
: return aarch64_get_reg_u64 (cpu
, lo
, NO_SP
);
2062 case SXTB
: return aarch64_get_reg_s8 (cpu
, lo
, NO_SP
);
2063 case SXTH
: return aarch64_get_reg_s16 (cpu
, lo
, NO_SP
);
2064 case SXTW
: return aarch64_get_reg_s32 (cpu
, lo
, NO_SP
);
2066 default: return aarch64_get_reg_s64 (cpu
, lo
, NO_SP
);
2070 /* Arithmetic extending register
2071 These allow an optional sign extension of some portion of the
2072 second source register followed by an optional left shift of
2073 between 1 and 4 bits (i.e. a shift of 0-4 bits???)
2075 N.B output (dest) and first input arg (source) may normally be Xn
2076 or SP. However, for flag setting operations dest can only be
2077 Xn. Second input registers are always Xn. */
2079 /* 32 bit ADD extending register. */
2081 add32_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2083 unsigned rm
= INSTR (20, 16);
2084 unsigned rn
= INSTR (9, 5);
2085 unsigned rd
= INSTR (4, 0);
2087 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2088 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
2089 aarch64_get_reg_u32 (cpu
, rn
, SP_OK
)
2090 + (extreg32 (cpu
, rm
, extension
) << shift
));
2093 /* 64 bit ADD extending register.
2094 N.B. This subsumes the case with 64 bit source2 and UXTX #n or LSL #0. */
2096 add64_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2098 unsigned rm
= INSTR (20, 16);
2099 unsigned rn
= INSTR (9, 5);
2100 unsigned rd
= INSTR (4, 0);
2102 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2103 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
2104 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
2105 + (extreg64 (cpu
, rm
, extension
) << shift
));
2108 /* 32 bit ADD extending register setting flags. */
2110 adds32_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2112 unsigned rm
= INSTR (20, 16);
2113 unsigned rn
= INSTR (9, 5);
2114 unsigned rd
= INSTR (4, 0);
2116 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, SP_OK
);
2117 uint32_t value2
= extreg32 (cpu
, rm
, extension
) << shift
;
2119 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2120 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
);
2121 set_flags_for_add32 (cpu
, value1
, value2
);
2124 /* 64 bit ADD extending register setting flags */
2125 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0 */
2127 adds64_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2129 unsigned rm
= INSTR (20, 16);
2130 unsigned rn
= INSTR (9, 5);
2131 unsigned rd
= INSTR (4, 0);
2133 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
2134 uint64_t value2
= extreg64 (cpu
, rm
, extension
) << shift
;
2136 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2137 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
);
2138 set_flags_for_add64 (cpu
, value1
, value2
);
2141 /* 32 bit SUB extending register. */
2143 sub32_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2145 unsigned rm
= INSTR (20, 16);
2146 unsigned rn
= INSTR (9, 5);
2147 unsigned rd
= INSTR (4, 0);
2149 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2150 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
2151 aarch64_get_reg_u32 (cpu
, rn
, SP_OK
)
2152 - (extreg32 (cpu
, rm
, extension
) << shift
));
2155 /* 64 bit SUB extending register. */
2156 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0. */
2158 sub64_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2160 unsigned rm
= INSTR (20, 16);
2161 unsigned rn
= INSTR (9, 5);
2162 unsigned rd
= INSTR (4, 0);
2164 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2165 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
2166 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
)
2167 - (extreg64 (cpu
, rm
, extension
) << shift
));
2170 /* 32 bit SUB extending register setting flags. */
2172 subs32_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2174 unsigned rm
= INSTR (20, 16);
2175 unsigned rn
= INSTR (9, 5);
2176 unsigned rd
= INSTR (4, 0);
2178 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, SP_OK
);
2179 uint32_t value2
= extreg32 (cpu
, rm
, extension
) << shift
;
2181 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2182 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
2183 set_flags_for_sub32 (cpu
, value1
, value2
);
2186 /* 64 bit SUB extending register setting flags */
2187 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0 */
2189 subs64_ext (sim_cpu
*cpu
, Extension extension
, uint32_t shift
)
2191 unsigned rm
= INSTR (20, 16);
2192 unsigned rn
= INSTR (9, 5);
2193 unsigned rd
= INSTR (4, 0);
2195 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
2196 uint64_t value2
= extreg64 (cpu
, rm
, extension
) << shift
;
2198 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2199 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
- value2
);
2200 set_flags_for_sub64 (cpu
, value1
, value2
);
2204 dexAddSubtractImmediate (sim_cpu
*cpu
)
2206 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2207 instr[30] = op : 0 ==> ADD, 1 ==> SUB
2208 instr[29] = set : 0 ==> no flags, 1 ==> set flags
2209 instr[28,24] = 10001
2210 instr[23,22] = shift : 00 == LSL#0, 01 = LSL#12 1x = UNALLOC
2211 instr[21,10] = uimm12
2215 /* N.B. the shift is applied at decode before calling the add/sub routine. */
2216 uint32_t shift
= INSTR (23, 22);
2217 uint32_t imm
= INSTR (21, 10);
2218 uint32_t dispatch
= INSTR (31, 29);
2220 NYI_assert (28, 24, 0x11);
2230 case 0: add32 (cpu
, imm
); break;
2231 case 1: adds32 (cpu
, imm
); break;
2232 case 2: sub32 (cpu
, imm
); break;
2233 case 3: subs32 (cpu
, imm
); break;
2234 case 4: add64 (cpu
, imm
); break;
2235 case 5: adds64 (cpu
, imm
); break;
2236 case 6: sub64 (cpu
, imm
); break;
2237 case 7: subs64 (cpu
, imm
); break;
2242 dexAddSubtractShiftedRegister (sim_cpu
*cpu
)
2244 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2245 instr[30,29] = op : 00 ==> ADD, 01 ==> ADDS, 10 ==> SUB, 11 ==> SUBS
2246 instr[28,24] = 01011
2247 instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> UNALLOC
2250 instr[15,10] = count : must be 0xxxxx for 32 bit
2254 uint32_t size
= INSTR (31, 31);
2255 uint32_t count
= INSTR (15, 10);
2256 Shift shiftType
= INSTR (23, 22);
2258 NYI_assert (28, 24, 0x0B);
2259 NYI_assert (21, 21, 0);
2261 /* Shift encoded as ROR is unallocated. */
2262 if (shiftType
== ROR
)
2265 /* 32 bit operations must have count[5] = 0
2266 or else we have an UNALLOC. */
2267 if (size
== 0 && uimm (count
, 5, 5))
2270 /* Dispatch on size:op i.e instr [31,29]. */
2271 switch (INSTR (31, 29))
2273 case 0: add32_shift (cpu
, shiftType
, count
); break;
2274 case 1: adds32_shift (cpu
, shiftType
, count
); break;
2275 case 2: sub32_shift (cpu
, shiftType
, count
); break;
2276 case 3: subs32_shift (cpu
, shiftType
, count
); break;
2277 case 4: add64_shift (cpu
, shiftType
, count
); break;
2278 case 5: adds64_shift (cpu
, shiftType
, count
); break;
2279 case 6: sub64_shift (cpu
, shiftType
, count
); break;
2280 case 7: subs64_shift (cpu
, shiftType
, count
); break;
2285 dexAddSubtractExtendedRegister (sim_cpu
*cpu
)
2287 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2288 instr[30] = op : 0 ==> ADD, 1 ==> SUB
2289 instr[29] = set? : 0 ==> no flags, 1 ==> set flags
2290 instr[28,24] = 01011
2291 instr[23,22] = opt : 0 ==> ok, 1,2,3 ==> UNALLOC
2294 instr[15,13] = option : 000 ==> UXTB, 001 ==> UXTH,
2295 000 ==> LSL|UXTW, 001 ==> UXTZ,
2296 000 ==> SXTB, 001 ==> SXTH,
2297 000 ==> SXTW, 001 ==> SXTX,
2298 instr[12,10] = shift : 0,1,2,3,4 ==> ok, 5,6,7 ==> UNALLOC
2302 Extension extensionType
= INSTR (15, 13);
2303 uint32_t shift
= INSTR (12, 10);
2305 NYI_assert (28, 24, 0x0B);
2306 NYI_assert (21, 21, 1);
2308 /* Shift may not exceed 4. */
2312 /* Dispatch on size:op:set?. */
2313 switch (INSTR (31, 29))
2315 case 0: add32_ext (cpu
, extensionType
, shift
); break;
2316 case 1: adds32_ext (cpu
, extensionType
, shift
); break;
2317 case 2: sub32_ext (cpu
, extensionType
, shift
); break;
2318 case 3: subs32_ext (cpu
, extensionType
, shift
); break;
2319 case 4: add64_ext (cpu
, extensionType
, shift
); break;
2320 case 5: adds64_ext (cpu
, extensionType
, shift
); break;
2321 case 6: sub64_ext (cpu
, extensionType
, shift
); break;
2322 case 7: subs64_ext (cpu
, extensionType
, shift
); break;
2326 /* Conditional data processing
2327 Condition register is implicit 3rd source. */
2329 /* 32 bit add with carry. */
2330 /* N.B register args may not be SP. */
2333 adc32 (sim_cpu
*cpu
)
2335 unsigned rm
= INSTR (20, 16);
2336 unsigned rn
= INSTR (9, 5);
2337 unsigned rd
= INSTR (4, 0);
2339 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2340 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
2341 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
2342 + aarch64_get_reg_u32 (cpu
, rm
, NO_SP
)
2346 /* 64 bit add with carry */
2348 adc64 (sim_cpu
*cpu
)
2350 unsigned rm
= INSTR (20, 16);
2351 unsigned rn
= INSTR (9, 5);
2352 unsigned rd
= INSTR (4, 0);
2354 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2355 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
2356 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
2357 + aarch64_get_reg_u64 (cpu
, rm
, NO_SP
)
2361 /* 32 bit add with carry setting flags. */
2363 adcs32 (sim_cpu
*cpu
)
2365 unsigned rm
= INSTR (20, 16);
2366 unsigned rn
= INSTR (9, 5);
2367 unsigned rd
= INSTR (4, 0);
2369 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
2370 uint32_t value2
= aarch64_get_reg_u32 (cpu
, rm
, NO_SP
);
2371 uint32_t carry
= IS_SET (C
);
2373 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2374 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
+ carry
);
2375 set_flags_for_add32 (cpu
, value1
, value2
+ carry
);
2378 /* 64 bit add with carry setting flags. */
2380 adcs64 (sim_cpu
*cpu
)
2382 unsigned rm
= INSTR (20, 16);
2383 unsigned rn
= INSTR (9, 5);
2384 unsigned rd
= INSTR (4, 0);
2386 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
2387 uint64_t value2
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
2388 uint64_t carry
= IS_SET (C
);
2390 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2391 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
+ value2
+ carry
);
2392 set_flags_for_add64 (cpu
, value1
, value2
+ carry
);
2395 /* 32 bit sub with carry. */
2397 sbc32 (sim_cpu
*cpu
)
2399 unsigned rm
= INSTR (20, 16);
2400 unsigned rn
= INSTR (9, 5); /* ngc iff rn == 31. */
2401 unsigned rd
= INSTR (4, 0);
2403 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2404 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
2405 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
2406 - aarch64_get_reg_u32 (cpu
, rm
, NO_SP
)
2410 /* 64 bit sub with carry */
2412 sbc64 (sim_cpu
*cpu
)
2414 unsigned rm
= INSTR (20, 16);
2415 unsigned rn
= INSTR (9, 5);
2416 unsigned rd
= INSTR (4, 0);
2418 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2419 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
2420 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
2421 - aarch64_get_reg_u64 (cpu
, rm
, NO_SP
)
2425 /* 32 bit sub with carry setting flags */
2427 sbcs32 (sim_cpu
*cpu
)
2429 unsigned rm
= INSTR (20, 16);
2430 unsigned rn
= INSTR (9, 5);
2431 unsigned rd
= INSTR (4, 0);
2433 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
2434 uint32_t value2
= aarch64_get_reg_u32 (cpu
, rm
, NO_SP
);
2435 uint32_t carry
= IS_SET (C
);
2436 uint32_t result
= value1
- value2
+ 1 - carry
;
2438 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2439 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
2440 set_flags_for_sub32 (cpu
, value1
, value2
+ 1 - carry
);
2443 /* 64 bit sub with carry setting flags */
2445 sbcs64 (sim_cpu
*cpu
)
2447 unsigned rm
= INSTR (20, 16);
2448 unsigned rn
= INSTR (9, 5);
2449 unsigned rd
= INSTR (4, 0);
2451 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
2452 uint64_t value2
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
2453 uint64_t carry
= IS_SET (C
);
2454 uint64_t result
= value1
- value2
+ 1 - carry
;
2456 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2457 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
2458 set_flags_for_sub64 (cpu
, value1
, value2
+ 1 - carry
);
2462 dexAddSubtractWithCarry (sim_cpu
*cpu
)
2464 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2465 instr[30] = op : 0 ==> ADC, 1 ==> SBC
2466 instr[29] = set? : 0 ==> no flags, 1 ==> set flags
2467 instr[28,21] = 1 1010 000
2469 instr[15,10] = op2 : 00000 ==> ok, ow ==> UNALLOC
2473 uint32_t op2
= INSTR (15, 10);
2475 NYI_assert (28, 21, 0xD0);
2480 /* Dispatch on size:op:set?. */
2481 switch (INSTR (31, 29))
2483 case 0: adc32 (cpu
); break;
2484 case 1: adcs32 (cpu
); break;
2485 case 2: sbc32 (cpu
); break;
2486 case 3: sbcs32 (cpu
); break;
2487 case 4: adc64 (cpu
); break;
2488 case 5: adcs64 (cpu
); break;
2489 case 6: sbc64 (cpu
); break;
2490 case 7: sbcs64 (cpu
); break;
2495 testConditionCode (sim_cpu
*cpu
, CondCode cc
)
2497 /* This should be reduceable to branchless logic
2498 by some careful testing of bits in CC followed
2499 by the requisite masking and combining of bits
2500 from the flag register.
2502 For now we do it with a switch. */
2507 case EQ
: res
= IS_SET (Z
); break;
2508 case NE
: res
= IS_CLEAR (Z
); break;
2509 case CS
: res
= IS_SET (C
); break;
2510 case CC
: res
= IS_CLEAR (C
); break;
2511 case MI
: res
= IS_SET (N
); break;
2512 case PL
: res
= IS_CLEAR (N
); break;
2513 case VS
: res
= IS_SET (V
); break;
2514 case VC
: res
= IS_CLEAR (V
); break;
2515 case HI
: res
= IS_SET (C
) && IS_CLEAR (Z
); break;
2516 case LS
: res
= IS_CLEAR (C
) || IS_SET (Z
); break;
2517 case GE
: res
= IS_SET (N
) == IS_SET (V
); break;
2518 case LT
: res
= IS_SET (N
) != IS_SET (V
); break;
2519 case GT
: res
= IS_CLEAR (Z
) && (IS_SET (N
) == IS_SET (V
)); break;
2520 case LE
: res
= IS_SET (Z
) || (IS_SET (N
) != IS_SET (V
)); break;
2531 CondCompare (sim_cpu
*cpu
) /* aka: ccmp and ccmn */
2533 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
2534 instr[30] = compare with positive (1) or negative value (0)
2535 instr[29,21] = 1 1101 0010
2536 instr[20,16] = Rm or const
2538 instr[11] = compare reg (0) or const (1)
2542 instr[3,0] = value for CPSR bits if the comparison does not take place. */
2547 NYI_assert (29, 21, 0x1d2);
2548 NYI_assert (10, 10, 0);
2549 NYI_assert (4, 4, 0);
2551 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2552 if (! testConditionCode (cpu
, INSTR (15, 12)))
2554 aarch64_set_CPSR (cpu
, INSTR (3, 0));
2558 negate
= INSTR (30, 30) ? 1 : -1;
2559 rm
= INSTR (20, 16);
2565 set_flags_for_sub64 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
),
2566 negate
* (uint64_t) rm
);
2568 set_flags_for_sub64 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
),
2569 negate
* aarch64_get_reg_u64 (cpu
, rm
, SP_OK
));
2574 set_flags_for_sub32 (cpu
, aarch64_get_reg_u32 (cpu
, rn
, SP_OK
),
2577 set_flags_for_sub32 (cpu
, aarch64_get_reg_u32 (cpu
, rn
, SP_OK
),
2578 negate
* aarch64_get_reg_u32 (cpu
, rm
, SP_OK
));
2583 do_vec_MOV_whole_vector (sim_cpu
*cpu
)
2585 /* MOV Vd.T, Vs.T (alias for ORR Vd.T, Vn.T, Vm.T where Vn == Vm)
2588 instr[30] = half(0)/full(1)
2589 instr[29,21] = 001110101
2591 instr[15,10] = 000111
2595 unsigned vs
= INSTR (9, 5);
2596 unsigned vd
= INSTR (4, 0);
2598 NYI_assert (29, 21, 0x075);
2599 NYI_assert (15, 10, 0x07);
2601 if (INSTR (20, 16) != vs
)
2604 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2606 aarch64_set_vec_u64 (cpu
, vd
, 1, aarch64_get_vec_u64 (cpu
, vs
, 1));
2608 aarch64_set_vec_u64 (cpu
, vd
, 0, aarch64_get_vec_u64 (cpu
, vs
, 0));
2612 do_vec_SMOV_into_scalar (sim_cpu
*cpu
)
2615 instr[30] = word(0)/long(1)
2616 instr[29,21] = 00 1110 000
2617 instr[20,16] = element size and index
2618 instr[15,10] = 00 0010 11
2619 instr[9,5] = V source
2620 instr[4,0] = R dest */
2622 unsigned vs
= INSTR (9, 5);
2623 unsigned rd
= INSTR (4, 0);
2624 unsigned imm5
= INSTR (20, 16);
2625 unsigned full
= INSTR (30, 30);
2628 NYI_assert (29, 21, 0x070);
2629 NYI_assert (15, 10, 0x0B);
2631 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2636 index
= (imm5
>> 1) & 0xF;
2638 else if (imm5
& 0x2)
2641 index
= (imm5
>> 2) & 0x7;
2643 else if (full
&& (imm5
& 0x4))
2646 index
= (imm5
>> 3) & 0x3;
2655 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
,
2656 aarch64_get_vec_s8 (cpu
, vs
, index
));
2658 aarch64_set_reg_s32 (cpu
, rd
, NO_SP
,
2659 aarch64_get_vec_s8 (cpu
, vs
, index
));
2664 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
,
2665 aarch64_get_vec_s16 (cpu
, vs
, index
));
2667 aarch64_set_reg_s32 (cpu
, rd
, NO_SP
,
2668 aarch64_get_vec_s16 (cpu
, vs
, index
));
2672 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
,
2673 aarch64_get_vec_s32 (cpu
, vs
, index
));
2682 do_vec_UMOV_into_scalar (sim_cpu
*cpu
)
2685 instr[30] = word(0)/long(1)
2686 instr[29,21] = 00 1110 000
2687 instr[20,16] = element size and index
2688 instr[15,10] = 00 0011 11
2689 instr[9,5] = V source
2690 instr[4,0] = R dest */
2692 unsigned vs
= INSTR (9, 5);
2693 unsigned rd
= INSTR (4, 0);
2694 unsigned imm5
= INSTR (20, 16);
2695 unsigned full
= INSTR (30, 30);
2698 NYI_assert (29, 21, 0x070);
2699 NYI_assert (15, 10, 0x0F);
2701 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2708 index
= (imm5
>> 1) & 0xF;
2710 else if (imm5
& 0x2)
2713 index
= (imm5
>> 2) & 0x7;
2715 else if (imm5
& 0x4)
2718 index
= (imm5
>> 3) & 0x3;
2723 else if (imm5
& 0x8)
2726 index
= (imm5
>> 4) & 0x1;
2734 aarch64_set_reg_u32 (cpu
, rd
, NO_SP
,
2735 aarch64_get_vec_u8 (cpu
, vs
, index
));
2739 aarch64_set_reg_u32 (cpu
, rd
, NO_SP
,
2740 aarch64_get_vec_u16 (cpu
, vs
, index
));
2744 aarch64_set_reg_u32 (cpu
, rd
, NO_SP
,
2745 aarch64_get_vec_u32 (cpu
, vs
, index
));
2749 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
2750 aarch64_get_vec_u64 (cpu
, vs
, index
));
2759 do_vec_INS (sim_cpu
*cpu
)
2761 /* instr[31,21] = 01001110000
2762 instr[20,16] = element size and index
2763 instr[15,10] = 000111
2764 instr[9,5] = W source
2765 instr[4,0] = V dest */
2768 unsigned rs
= INSTR (9, 5);
2769 unsigned vd
= INSTR (4, 0);
2771 NYI_assert (31, 21, 0x270);
2772 NYI_assert (15, 10, 0x07);
2774 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2777 index
= INSTR (20, 17);
2778 aarch64_set_vec_u8 (cpu
, vd
, index
,
2779 aarch64_get_reg_u8 (cpu
, rs
, NO_SP
));
2781 else if (INSTR (17, 17))
2783 index
= INSTR (20, 18);
2784 aarch64_set_vec_u16 (cpu
, vd
, index
,
2785 aarch64_get_reg_u16 (cpu
, rs
, NO_SP
));
2787 else if (INSTR (18, 18))
2789 index
= INSTR (20, 19);
2790 aarch64_set_vec_u32 (cpu
, vd
, index
,
2791 aarch64_get_reg_u32 (cpu
, rs
, NO_SP
));
2793 else if (INSTR (19, 19))
2795 index
= INSTR (20, 20);
2796 aarch64_set_vec_u64 (cpu
, vd
, index
,
2797 aarch64_get_reg_u64 (cpu
, rs
, NO_SP
));
2804 do_vec_DUP_vector_into_vector (sim_cpu
*cpu
)
2807 instr[30] = half(0)/full(1)
2808 instr[29,21] = 00 1110 000
2809 instr[20,16] = element size and index
2810 instr[15,10] = 0000 01
2811 instr[9,5] = V source
2812 instr[4,0] = V dest. */
2814 unsigned full
= INSTR (30, 30);
2815 unsigned vs
= INSTR (9, 5);
2816 unsigned vd
= INSTR (4, 0);
2819 NYI_assert (29, 21, 0x070);
2820 NYI_assert (15, 10, 0x01);
2822 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2825 index
= INSTR (20, 17);
2827 for (i
= 0; i
< (full
? 16 : 8); i
++)
2828 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vs
, index
));
2830 else if (INSTR (17, 17))
2832 index
= INSTR (20, 18);
2834 for (i
= 0; i
< (full
? 8 : 4); i
++)
2835 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vs
, index
));
2837 else if (INSTR (18, 18))
2839 index
= INSTR (20, 19);
2841 for (i
= 0; i
< (full
? 4 : 2); i
++)
2842 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vs
, index
));
2846 if (INSTR (19, 19) == 0)
2852 index
= INSTR (20, 20);
2854 for (i
= 0; i
< 2; i
++)
2855 aarch64_set_vec_u64 (cpu
, vd
, i
, aarch64_get_vec_u64 (cpu
, vs
, index
));
2860 do_vec_TBL (sim_cpu
*cpu
)
2863 instr[30] = half(0)/full(1)
2864 instr[29,21] = 00 1110 000
2867 instr[14,13] = vec length
2869 instr[9,5] = V start
2870 instr[4,0] = V dest */
2872 int full
= INSTR (30, 30);
2873 int len
= INSTR (14, 13) + 1;
2874 unsigned vm
= INSTR (20, 16);
2875 unsigned vn
= INSTR (9, 5);
2876 unsigned vd
= INSTR (4, 0);
2879 NYI_assert (29, 21, 0x070);
2880 NYI_assert (12, 10, 0);
2882 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2883 for (i
= 0; i
< (full
? 16 : 8); i
++)
2885 unsigned int selector
= aarch64_get_vec_u8 (cpu
, vm
, i
);
2889 val
= aarch64_get_vec_u8 (cpu
, vn
, selector
);
2890 else if (selector
< 32)
2891 val
= len
< 2 ? 0 : aarch64_get_vec_u8 (cpu
, vn
+ 1, selector
- 16);
2892 else if (selector
< 48)
2893 val
= len
< 3 ? 0 : aarch64_get_vec_u8 (cpu
, vn
+ 2, selector
- 32);
2894 else if (selector
< 64)
2895 val
= len
< 4 ? 0 : aarch64_get_vec_u8 (cpu
, vn
+ 3, selector
- 48);
2899 aarch64_set_vec_u8 (cpu
, vd
, i
, val
);
2904 do_vec_TRN (sim_cpu
*cpu
)
2907 instr[30] = half(0)/full(1)
2908 instr[29,24] = 00 1110
2913 instr[14] = TRN1 (0) / TRN2 (1)
2915 instr[9,5] = V source
2916 instr[4,0] = V dest. */
2918 int full
= INSTR (30, 30);
2919 int second
= INSTR (14, 14);
2920 unsigned vm
= INSTR (20, 16);
2921 unsigned vn
= INSTR (9, 5);
2922 unsigned vd
= INSTR (4, 0);
2925 NYI_assert (29, 24, 0x0E);
2926 NYI_assert (13, 10, 0xA);
2928 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
2929 switch (INSTR (23, 22))
2932 for (i
= 0; i
< (full
? 8 : 4); i
++)
2936 aarch64_get_vec_u8 (cpu
, second
? vm
: vn
, i
* 2));
2938 (cpu
, vd
, 1 * 2 + 1,
2939 aarch64_get_vec_u8 (cpu
, second
? vn
: vm
, i
* 2 + 1));
2944 for (i
= 0; i
< (full
? 4 : 2); i
++)
2948 aarch64_get_vec_u16 (cpu
, second
? vm
: vn
, i
* 2));
2950 (cpu
, vd
, 1 * 2 + 1,
2951 aarch64_get_vec_u16 (cpu
, second
? vn
: vm
, i
* 2 + 1));
2957 (cpu
, vd
, 0, aarch64_get_vec_u32 (cpu
, second
? vm
: vn
, 0));
2959 (cpu
, vd
, 1, aarch64_get_vec_u32 (cpu
, second
? vn
: vm
, 1));
2961 (cpu
, vd
, 2, aarch64_get_vec_u32 (cpu
, second
? vm
: vn
, 2));
2963 (cpu
, vd
, 3, aarch64_get_vec_u32 (cpu
, second
? vn
: vm
, 3));
2970 aarch64_set_vec_u64 (cpu
, vd
, 0,
2971 aarch64_get_vec_u64 (cpu
, second
? vm
: vn
, 0));
2972 aarch64_set_vec_u64 (cpu
, vd
, 1,
2973 aarch64_get_vec_u64 (cpu
, second
? vn
: vm
, 1));
2979 do_vec_DUP_scalar_into_vector (sim_cpu
*cpu
)
2982 instr[30] = 0=> zero top 64-bits, 1=> duplicate into top 64-bits
2983 [must be 1 for 64-bit xfer]
2984 instr[29,20] = 00 1110 0000
2985 instr[19,16] = element size: 0001=> 8-bits, 0010=> 16-bits,
2986 0100=> 32-bits. 1000=>64-bits
2987 instr[15,10] = 0000 11
2988 instr[9,5] = W source
2989 instr[4,0] = V dest. */
2992 unsigned Vd
= INSTR (4, 0);
2993 unsigned Rs
= INSTR (9, 5);
2994 int both
= INSTR (30, 30);
2996 NYI_assert (29, 20, 0x0E0);
2997 NYI_assert (15, 10, 0x03);
2999 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3000 switch (INSTR (19, 16))
3003 for (i
= 0; i
< (both
? 16 : 8); i
++)
3004 aarch64_set_vec_u8 (cpu
, Vd
, i
, aarch64_get_reg_u8 (cpu
, Rs
, NO_SP
));
3008 for (i
= 0; i
< (both
? 8 : 4); i
++)
3009 aarch64_set_vec_u16 (cpu
, Vd
, i
, aarch64_get_reg_u16 (cpu
, Rs
, NO_SP
));
3013 for (i
= 0; i
< (both
? 4 : 2); i
++)
3014 aarch64_set_vec_u32 (cpu
, Vd
, i
, aarch64_get_reg_u32 (cpu
, Rs
, NO_SP
));
3020 aarch64_set_vec_u64 (cpu
, Vd
, 0, aarch64_get_reg_u64 (cpu
, Rs
, NO_SP
));
3021 aarch64_set_vec_u64 (cpu
, Vd
, 1, aarch64_get_reg_u64 (cpu
, Rs
, NO_SP
));
3030 do_vec_UZP (sim_cpu
*cpu
)
3033 instr[30] = half(0)/full(1)
3034 instr[29,24] = 00 1110
3035 instr[23,22] = size: byte(00), half(01), word (10), long (11)
3039 instr[14] = lower (0) / upper (1)
3044 int full
= INSTR (30, 30);
3045 int upper
= INSTR (14, 14);
3047 unsigned vm
= INSTR (20, 16);
3048 unsigned vn
= INSTR (9, 5);
3049 unsigned vd
= INSTR (4, 0);
3051 uint64_t val_m1
= aarch64_get_vec_u64 (cpu
, vm
, 0);
3052 uint64_t val_m2
= aarch64_get_vec_u64 (cpu
, vm
, 1);
3053 uint64_t val_n1
= aarch64_get_vec_u64 (cpu
, vn
, 0);
3054 uint64_t val_n2
= aarch64_get_vec_u64 (cpu
, vn
, 1);
3059 uint64_t input2
= full
? val_n2
: val_m1
;
3061 NYI_assert (29, 24, 0x0E);
3062 NYI_assert (21, 21, 0);
3063 NYI_assert (15, 15, 0);
3064 NYI_assert (13, 10, 6);
3066 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3067 switch (INSTR (23, 22))
3070 val1
= (val_n1
>> (upper
* 8)) & 0xFFULL
;
3071 val1
|= (val_n1
>> ((upper
* 8) + 8)) & 0xFF00ULL
;
3072 val1
|= (val_n1
>> ((upper
* 8) + 16)) & 0xFF0000ULL
;
3073 val1
|= (val_n1
>> ((upper
* 8) + 24)) & 0xFF000000ULL
;
3075 val1
|= (input2
<< (32 - (upper
* 8))) & 0xFF00000000ULL
;
3076 val1
|= (input2
<< (24 - (upper
* 8))) & 0xFF0000000000ULL
;
3077 val1
|= (input2
<< (16 - (upper
* 8))) & 0xFF000000000000ULL
;
3078 val1
|= (input2
<< (8 - (upper
* 8))) & 0xFF00000000000000ULL
;
3082 val2
= (val_m1
>> (upper
* 8)) & 0xFFULL
;
3083 val2
|= (val_m1
>> ((upper
* 8) + 8)) & 0xFF00ULL
;
3084 val2
|= (val_m1
>> ((upper
* 8) + 16)) & 0xFF0000ULL
;
3085 val2
|= (val_m1
>> ((upper
* 8) + 24)) & 0xFF000000ULL
;
3087 val2
|= (val_m2
<< (32 - (upper
* 8))) & 0xFF00000000ULL
;
3088 val2
|= (val_m2
<< (24 - (upper
* 8))) & 0xFF0000000000ULL
;
3089 val2
|= (val_m2
<< (16 - (upper
* 8))) & 0xFF000000000000ULL
;
3090 val2
|= (val_m2
<< (8 - (upper
* 8))) & 0xFF00000000000000ULL
;
3095 val1
= (val_n1
>> (upper
* 16)) & 0xFFFFULL
;
3096 val1
|= (val_n1
>> ((upper
* 16) + 16)) & 0xFFFF0000ULL
;
3098 val1
|= (input2
<< (32 - (upper
* 16))) & 0xFFFF00000000ULL
;;
3099 val1
|= (input2
<< (16 - (upper
* 16))) & 0xFFFF000000000000ULL
;
3103 val2
= (val_m1
>> (upper
* 16)) & 0xFFFFULL
;
3104 val2
|= (val_m1
>> ((upper
* 16) + 16)) & 0xFFFF0000ULL
;
3106 val2
|= (val_m2
<< (32 - (upper
* 16))) & 0xFFFF00000000ULL
;
3107 val2
|= (val_m2
<< (16 - (upper
* 16))) & 0xFFFF000000000000ULL
;
3112 val1
= (val_n1
>> (upper
* 32)) & 0xFFFFFFFF;
3113 val1
|= (input2
<< (32 - (upper
* 32))) & 0xFFFFFFFF00000000ULL
;
3117 val2
= (val_m1
>> (upper
* 32)) & 0xFFFFFFFF;
3118 val2
|= (val_m2
<< (32 - (upper
* 32))) & 0xFFFFFFFF00000000ULL
;
3126 val1
= upper
? val_n2
: val_n1
;
3127 val2
= upper
? val_m2
: val_m1
;
3131 aarch64_set_vec_u64 (cpu
, vd
, 0, val1
);
3133 aarch64_set_vec_u64 (cpu
, vd
, 1, val2
);
3137 do_vec_ZIP (sim_cpu
*cpu
)
3140 instr[30] = half(0)/full(1)
3141 instr[29,24] = 00 1110
3142 instr[23,22] = size: byte(00), hald(01), word (10), long (11)
3146 instr[14] = lower (0) / upper (1)
3151 int full
= INSTR (30, 30);
3152 int upper
= INSTR (14, 14);
3154 unsigned vm
= INSTR (20, 16);
3155 unsigned vn
= INSTR (9, 5);
3156 unsigned vd
= INSTR (4, 0);
3158 uint64_t val_m1
= aarch64_get_vec_u64 (cpu
, vm
, 0);
3159 uint64_t val_m2
= aarch64_get_vec_u64 (cpu
, vm
, 1);
3160 uint64_t val_n1
= aarch64_get_vec_u64 (cpu
, vn
, 0);
3161 uint64_t val_n2
= aarch64_get_vec_u64 (cpu
, vn
, 1);
3166 uint64_t input1
= upper
? val_n1
: val_m1
;
3167 uint64_t input2
= upper
? val_n2
: val_m2
;
3169 NYI_assert (29, 24, 0x0E);
3170 NYI_assert (21, 21, 0);
3171 NYI_assert (15, 15, 0);
3172 NYI_assert (13, 10, 0xE);
3174 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3175 switch (INSTR (23, 23))
3179 ((input1
<< 0) & (0xFF << 0))
3180 | ((input2
<< 8) & (0xFF << 8))
3181 | ((input1
<< 8) & (0xFF << 16))
3182 | ((input2
<< 16) & (0xFF << 24))
3183 | ((input1
<< 16) & (0xFFULL
<< 32))
3184 | ((input2
<< 24) & (0xFFULL
<< 40))
3185 | ((input1
<< 24) & (0xFFULL
<< 48))
3186 | ((input2
<< 32) & (0xFFULL
<< 56));
3189 ((input1
>> 32) & (0xFF << 0))
3190 | ((input2
>> 24) & (0xFF << 8))
3191 | ((input1
>> 24) & (0xFF << 16))
3192 | ((input2
>> 16) & (0xFF << 24))
3193 | ((input1
>> 16) & (0xFFULL
<< 32))
3194 | ((input2
>> 8) & (0xFFULL
<< 40))
3195 | ((input1
>> 8) & (0xFFULL
<< 48))
3196 | ((input2
>> 0) & (0xFFULL
<< 56));
3201 ((input1
<< 0) & (0xFFFF << 0))
3202 | ((input2
<< 16) & (0xFFFF << 16))
3203 | ((input1
<< 16) & (0xFFFFULL
<< 32))
3204 | ((input2
<< 32) & (0xFFFFULL
<< 48));
3207 ((input1
>> 32) & (0xFFFF << 0))
3208 | ((input2
>> 16) & (0xFFFF << 16))
3209 | ((input1
>> 16) & (0xFFFFULL
<< 32))
3210 | ((input2
>> 0) & (0xFFFFULL
<< 48));
3214 val1
= (input1
& 0xFFFFFFFFULL
) | (input2
<< 32);
3215 val2
= (input2
& 0xFFFFFFFFULL
) | (input1
<< 32);
3224 aarch64_set_vec_u64 (cpu
, vd
, 0, val1
);
3226 aarch64_set_vec_u64 (cpu
, vd
, 1, val2
);
3229 /* Floating point immediates are encoded in 8 bits.
3230 fpimm[7] = sign bit.
3231 fpimm[6:4] = signed exponent.
3232 fpimm[3:0] = fraction (assuming leading 1).
3233 i.e. F = s * 1.f * 2^(e - b). */
3236 fp_immediate_for_encoding_32 (uint32_t imm8
)
3239 uint32_t s
, e
, f
, i
;
3241 s
= (imm8
>> 7) & 0x1;
3242 e
= (imm8
>> 4) & 0x7;
3245 /* The fp value is s * n/16 * 2r where n is 16+e. */
3246 u
= (16.0 + f
) / 16.0;
3248 /* N.B. exponent is signed. */
3253 for (i
= 0; i
<= epos
; i
++)
3260 for (i
= 0; i
< eneg
; i
++)
3271 fp_immediate_for_encoding_64 (uint32_t imm8
)
3274 uint32_t s
, e
, f
, i
;
3276 s
= (imm8
>> 7) & 0x1;
3277 e
= (imm8
>> 4) & 0x7;
3280 /* The fp value is s * n/16 * 2r where n is 16+e. */
3281 u
= (16.0 + f
) / 16.0;
3283 /* N.B. exponent is signed. */
3288 for (i
= 0; i
<= epos
; i
++)
3295 for (i
= 0; i
< eneg
; i
++)
3306 do_vec_MOV_immediate (sim_cpu
*cpu
)
3309 instr[30] = full/half selector
3310 instr[29,19] = 00111100000
3311 instr[18,16] = high 3 bits of uimm8
3312 instr[15,12] = size & shift:
3314 0010 => 32-bit + LSL#8
3315 0100 => 32-bit + LSL#16
3316 0110 => 32-bit + LSL#24
3317 1010 => 16-bit + LSL#8
3319 1101 => 32-bit + MSL#16
3320 1100 => 32-bit + MSL#8
3324 instr[9,5] = low 5-bits of uimm8
3327 int full
= INSTR (30, 30);
3328 unsigned vd
= INSTR (4, 0);
3329 unsigned val
= (INSTR (18, 16) << 5) | INSTR (9, 5);
3332 NYI_assert (29, 19, 0x1E0);
3333 NYI_assert (11, 10, 1);
3335 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3336 switch (INSTR (15, 12))
3338 case 0x0: /* 32-bit, no shift. */
3339 case 0x2: /* 32-bit, shift by 8. */
3340 case 0x4: /* 32-bit, shift by 16. */
3341 case 0x6: /* 32-bit, shift by 24. */
3342 val
<<= (8 * INSTR (14, 13));
3343 for (i
= 0; i
< (full
? 4 : 2); i
++)
3344 aarch64_set_vec_u32 (cpu
, vd
, i
, val
);
3347 case 0xa: /* 16-bit, shift by 8. */
3350 case 0x8: /* 16-bit, no shift. */
3351 for (i
= 0; i
< (full
? 8 : 4); i
++)
3352 aarch64_set_vec_u16 (cpu
, vd
, i
, val
);
3355 case 0xd: /* 32-bit, mask shift by 16. */
3359 case 0xc: /* 32-bit, mask shift by 8. */
3362 for (i
= 0; i
< (full
? 4 : 2); i
++)
3363 aarch64_set_vec_u32 (cpu
, vd
, i
, val
);
3366 case 0xe: /* 8-bit, no shift. */
3367 for (i
= 0; i
< (full
? 16 : 8); i
++)
3368 aarch64_set_vec_u8 (cpu
, vd
, i
, val
);
3371 case 0xf: /* FMOV Vs.{2|4}S, #fpimm. */
3373 float u
= fp_immediate_for_encoding_32 (val
);
3374 for (i
= 0; i
< (full
? 4 : 2); i
++)
3375 aarch64_set_vec_float (cpu
, vd
, i
, u
);
3385 do_vec_MVNI (sim_cpu
*cpu
)
3388 instr[30] = full/half selector
3389 instr[29,19] = 10111100000
3390 instr[18,16] = high 3 bits of uimm8
3391 instr[15,12] = selector
3393 instr[9,5] = low 5-bits of uimm8
3396 int full
= INSTR (30, 30);
3397 unsigned vd
= INSTR (4, 0);
3398 unsigned val
= (INSTR (18, 16) << 5) | INSTR (9, 5);
3401 NYI_assert (29, 19, 0x5E0);
3402 NYI_assert (11, 10, 1);
3404 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3405 switch (INSTR (15, 12))
3407 case 0x0: /* 32-bit, no shift. */
3408 case 0x2: /* 32-bit, shift by 8. */
3409 case 0x4: /* 32-bit, shift by 16. */
3410 case 0x6: /* 32-bit, shift by 24. */
3411 val
<<= (8 * INSTR (14, 13));
3413 for (i
= 0; i
< (full
? 4 : 2); i
++)
3414 aarch64_set_vec_u32 (cpu
, vd
, i
, val
);
3417 case 0xa: /* 16-bit, 8 bit shift. */
3419 case 0x8: /* 16-bit, no shift. */
3421 for (i
= 0; i
< (full
? 8 : 4); i
++)
3422 aarch64_set_vec_u16 (cpu
, vd
, i
, val
);
3425 case 0xd: /* 32-bit, mask shift by 16. */
3428 case 0xc: /* 32-bit, mask shift by 8. */
3432 for (i
= 0; i
< (full
? 4 : 2); i
++)
3433 aarch64_set_vec_u32 (cpu
, vd
, i
, val
);
3436 case 0xE: /* MOVI Dn, #mask64 */
3440 for (i
= 0; i
< 8; i
++)
3442 mask
|= (0xFFUL
<< (i
* 8));
3443 aarch64_set_vec_u64 (cpu
, vd
, 0, mask
);
3444 aarch64_set_vec_u64 (cpu
, vd
, 1, mask
);
3448 case 0xf: /* FMOV Vd.2D, #fpimm. */
3450 double u
= fp_immediate_for_encoding_64 (val
);
3455 aarch64_set_vec_double (cpu
, vd
, 0, u
);
3456 aarch64_set_vec_double (cpu
, vd
, 1, u
);
3465 #define ABS(A) ((A) < 0 ? - (A) : (A))
3468 do_vec_ABS (sim_cpu
*cpu
)
3471 instr[30] = half(0)/full(1)
3472 instr[29,24] = 00 1110
3473 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3474 instr[21,10] = 10 0000 1011 10
3478 unsigned vn
= INSTR (9, 5);
3479 unsigned vd
= INSTR (4, 0);
3480 unsigned full
= INSTR (30, 30);
3483 NYI_assert (29, 24, 0x0E);
3484 NYI_assert (21, 10, 0x82E);
3486 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3487 switch (INSTR (23, 22))
3490 for (i
= 0; i
< (full
? 16 : 8); i
++)
3491 aarch64_set_vec_s8 (cpu
, vd
, i
,
3492 ABS (aarch64_get_vec_s8 (cpu
, vn
, i
)));
3496 for (i
= 0; i
< (full
? 8 : 4); i
++)
3497 aarch64_set_vec_s16 (cpu
, vd
, i
,
3498 ABS (aarch64_get_vec_s16 (cpu
, vn
, i
)));
3502 for (i
= 0; i
< (full
? 4 : 2); i
++)
3503 aarch64_set_vec_s32 (cpu
, vd
, i
,
3504 ABS (aarch64_get_vec_s32 (cpu
, vn
, i
)));
3510 for (i
= 0; i
< 2; i
++)
3511 aarch64_set_vec_s64 (cpu
, vd
, i
,
3512 ABS (aarch64_get_vec_s64 (cpu
, vn
, i
)));
3518 do_vec_ADDV (sim_cpu
*cpu
)
3521 instr[30] = full/half selector
3522 instr[29,24] = 00 1110
3523 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3524 instr[21,10] = 11 0001 1011 10
3528 unsigned vm
= INSTR (9, 5);
3529 unsigned rd
= INSTR (4, 0);
3531 int full
= INSTR (30, 30);
3533 NYI_assert (29, 24, 0x0E);
3534 NYI_assert (21, 10, 0xC6E);
3536 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3537 switch (INSTR (23, 22))
3542 for (i
= 0; i
< (full
? 16 : 8); i
++)
3543 val
+= aarch64_get_vec_u8 (cpu
, vm
, i
);
3544 aarch64_set_vec_u64 (cpu
, rd
, 0, val
);
3551 for (i
= 0; i
< (full
? 8 : 4); i
++)
3552 val
+= aarch64_get_vec_u16 (cpu
, vm
, i
);
3553 aarch64_set_vec_u64 (cpu
, rd
, 0, val
);
3562 for (i
= 0; i
< 4; i
++)
3563 val
+= aarch64_get_vec_u32 (cpu
, vm
, i
);
3564 aarch64_set_vec_u64 (cpu
, rd
, 0, val
);
3574 do_vec_ins_2 (sim_cpu
*cpu
)
3576 /* instr[31,21] = 01001110000
3577 instr[20,18] = size & element selector
3579 instr[13] = direction: to vec(0), from vec (1)
3585 unsigned vm
= INSTR (9, 5);
3586 unsigned vd
= INSTR (4, 0);
3588 NYI_assert (31, 21, 0x270);
3589 NYI_assert (17, 14, 0);
3590 NYI_assert (12, 10, 7);
3592 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3593 if (INSTR (13, 13) == 1)
3595 if (INSTR (18, 18) == 1)
3598 elem
= INSTR (20, 19);
3599 aarch64_set_reg_u64 (cpu
, vd
, NO_SP
,
3600 aarch64_get_vec_u32 (cpu
, vm
, elem
));
3605 if (INSTR (19, 19) != 1)
3608 elem
= INSTR (20, 20);
3609 aarch64_set_reg_u64 (cpu
, vd
, NO_SP
,
3610 aarch64_get_vec_u64 (cpu
, vm
, elem
));
3615 if (INSTR (18, 18) == 1)
3618 elem
= INSTR (20, 19);
3619 aarch64_set_vec_u32 (cpu
, vd
, elem
,
3620 aarch64_get_reg_u32 (cpu
, vm
, NO_SP
));
3625 if (INSTR (19, 19) != 1)
3628 elem
= INSTR (20, 20);
3629 aarch64_set_vec_u64 (cpu
, vd
, elem
,
3630 aarch64_get_reg_u64 (cpu
, vm
, NO_SP
));
3635 #define DO_VEC_WIDENING_MUL(N, DST_TYPE, READ_TYPE, WRITE_TYPE) \
3638 DST_TYPE a[N], b[N]; \
3640 for (i = 0; i < (N); i++) \
3642 a[i] = aarch64_get_vec_##READ_TYPE (cpu, vn, i + bias); \
3643 b[i] = aarch64_get_vec_##READ_TYPE (cpu, vm, i + bias); \
3645 for (i = 0; i < (N); i++) \
3646 aarch64_set_vec_##WRITE_TYPE (cpu, vd, i, a[i] * b[i]); \
3651 do_vec_mull (sim_cpu
*cpu
)
3654 instr[30] = lower(0)/upper(1) selector
3655 instr[29] = signed(0)/unsigned(1)
3656 instr[28,24] = 0 1110
3657 instr[23,22] = size: 8-bit (00), 16-bit (01), 32-bit (10)
3660 instr[15,10] = 11 0000
3664 int unsign
= INSTR (29, 29);
3665 int bias
= INSTR (30, 30);
3666 unsigned vm
= INSTR (20, 16);
3667 unsigned vn
= INSTR ( 9, 5);
3668 unsigned vd
= INSTR ( 4, 0);
3671 NYI_assert (28, 24, 0x0E);
3672 NYI_assert (15, 10, 0x30);
3674 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3675 /* NB: Read source values before writing results, in case
3676 the source and destination vectors are the same. */
3677 switch (INSTR (23, 22))
3683 DO_VEC_WIDENING_MUL (8, uint16_t, u8
, u16
);
3685 DO_VEC_WIDENING_MUL (8, int16_t, s8
, s16
);
3692 DO_VEC_WIDENING_MUL (4, uint32_t, u16
, u32
);
3694 DO_VEC_WIDENING_MUL (4, int32_t, s16
, s32
);
3701 DO_VEC_WIDENING_MUL (2, uint64_t, u32
, u64
);
3703 DO_VEC_WIDENING_MUL (2, int64_t, s32
, s64
);
3712 do_vec_fadd (sim_cpu
*cpu
)
3715 instr[30] = half(0)/full(1)
3716 instr[29,24] = 001110
3717 instr[23] = FADD(0)/FSUB(1)
3718 instr[22] = float (0)/double(1)
3721 instr[15,10] = 110101
3725 unsigned vm
= INSTR (20, 16);
3726 unsigned vn
= INSTR (9, 5);
3727 unsigned vd
= INSTR (4, 0);
3729 int full
= INSTR (30, 30);
3731 NYI_assert (29, 24, 0x0E);
3732 NYI_assert (21, 21, 1);
3733 NYI_assert (15, 10, 0x35);
3735 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3743 for (i
= 0; i
< 2; i
++)
3744 aarch64_set_vec_double (cpu
, vd
, i
,
3745 aarch64_get_vec_double (cpu
, vn
, i
)
3746 - aarch64_get_vec_double (cpu
, vm
, i
));
3750 for (i
= 0; i
< (full
? 4 : 2); i
++)
3751 aarch64_set_vec_float (cpu
, vd
, i
,
3752 aarch64_get_vec_float (cpu
, vn
, i
)
3753 - aarch64_get_vec_float (cpu
, vm
, i
));
3763 for (i
= 0; i
< 2; i
++)
3764 aarch64_set_vec_double (cpu
, vd
, i
,
3765 aarch64_get_vec_double (cpu
, vm
, i
)
3766 + aarch64_get_vec_double (cpu
, vn
, i
));
3770 for (i
= 0; i
< (full
? 4 : 2); i
++)
3771 aarch64_set_vec_float (cpu
, vd
, i
,
3772 aarch64_get_vec_float (cpu
, vm
, i
)
3773 + aarch64_get_vec_float (cpu
, vn
, i
));
3779 do_vec_add (sim_cpu
*cpu
)
3782 instr[30] = full/half selector
3783 instr[29,24] = 001110
3784 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3787 instr[15,10] = 100001
3791 unsigned vm
= INSTR (20, 16);
3792 unsigned vn
= INSTR (9, 5);
3793 unsigned vd
= INSTR (4, 0);
3795 int full
= INSTR (30, 30);
3797 NYI_assert (29, 24, 0x0E);
3798 NYI_assert (21, 21, 1);
3799 NYI_assert (15, 10, 0x21);
3801 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3802 switch (INSTR (23, 22))
3805 for (i
= 0; i
< (full
? 16 : 8); i
++)
3806 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vn
, i
)
3807 + aarch64_get_vec_u8 (cpu
, vm
, i
));
3811 for (i
= 0; i
< (full
? 8 : 4); i
++)
3812 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vn
, i
)
3813 + aarch64_get_vec_u16 (cpu
, vm
, i
));
3817 for (i
= 0; i
< (full
? 4 : 2); i
++)
3818 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vn
, i
)
3819 + aarch64_get_vec_u32 (cpu
, vm
, i
));
3825 aarch64_set_vec_u64 (cpu
, vd
, 0, aarch64_get_vec_u64 (cpu
, vn
, 0)
3826 + aarch64_get_vec_u64 (cpu
, vm
, 0));
3827 aarch64_set_vec_u64 (cpu
, vd
, 1,
3828 aarch64_get_vec_u64 (cpu
, vn
, 1)
3829 + aarch64_get_vec_u64 (cpu
, vm
, 1));
3835 do_vec_mul (sim_cpu
*cpu
)
3838 instr[30] = full/half selector
3839 instr[29,24] = 00 1110
3840 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3843 instr[15,10] = 10 0111
3847 unsigned vm
= INSTR (20, 16);
3848 unsigned vn
= INSTR (9, 5);
3849 unsigned vd
= INSTR (4, 0);
3851 int full
= INSTR (30, 30);
3854 NYI_assert (29, 24, 0x0E);
3855 NYI_assert (21, 21, 1);
3856 NYI_assert (15, 10, 0x27);
3858 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3859 switch (INSTR (23, 22))
3862 DO_VEC_WIDENING_MUL (full
? 16 : 8, uint8_t, u8
, u8
);
3866 DO_VEC_WIDENING_MUL (full
? 8 : 4, uint16_t, u16
, u16
);
3870 DO_VEC_WIDENING_MUL (full
? 4 : 2, uint32_t, u32
, u32
);
3879 do_vec_MLA (sim_cpu
*cpu
)
3882 instr[30] = full/half selector
3883 instr[29,24] = 00 1110
3884 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3887 instr[15,10] = 1001 01
3891 unsigned vm
= INSTR (20, 16);
3892 unsigned vn
= INSTR (9, 5);
3893 unsigned vd
= INSTR (4, 0);
3895 int full
= INSTR (30, 30);
3897 NYI_assert (29, 24, 0x0E);
3898 NYI_assert (21, 21, 1);
3899 NYI_assert (15, 10, 0x25);
3901 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
3902 switch (INSTR (23, 22))
3905 for (i
= 0; i
< (full
? 16 : 8); i
++)
3906 aarch64_set_vec_u8 (cpu
, vd
, i
,
3907 aarch64_get_vec_u8 (cpu
, vd
, i
)
3908 + (aarch64_get_vec_u8 (cpu
, vn
, i
)
3909 * aarch64_get_vec_u8 (cpu
, vm
, i
)));
3913 for (i
= 0; i
< (full
? 8 : 4); i
++)
3914 aarch64_set_vec_u16 (cpu
, vd
, i
,
3915 aarch64_get_vec_u16 (cpu
, vd
, i
)
3916 + (aarch64_get_vec_u16 (cpu
, vn
, i
)
3917 * aarch64_get_vec_u16 (cpu
, vm
, i
)));
3921 for (i
= 0; i
< (full
? 4 : 2); i
++)
3922 aarch64_set_vec_u32 (cpu
, vd
, i
,
3923 aarch64_get_vec_u32 (cpu
, vd
, i
)
3924 + (aarch64_get_vec_u32 (cpu
, vn
, i
)
3925 * aarch64_get_vec_u32 (cpu
, vm
, i
)));
3934 fmaxnm (float a
, float b
)
3939 return a
> b
? a
: b
;
3942 else if (! isnan (b
))
3948 fminnm (float a
, float b
)
3953 return a
< b
? a
: b
;
3956 else if (! isnan (b
))
3962 dmaxnm (double a
, double b
)
3967 return a
> b
? a
: b
;
3970 else if (! isnan (b
))
3976 dminnm (double a
, double b
)
3981 return a
< b
? a
: b
;
3984 else if (! isnan (b
))
3990 do_vec_FminmaxNMP (sim_cpu
*cpu
)
3993 instr [30] = half (0)/full (1)
3994 instr [29,24] = 10 1110
3995 instr [23] = max(0)/min(1)
3996 instr [22] = float (0)/double (1)
3999 instr [15,10] = 1100 01
4001 instr [4.0] = Vd. */
4003 unsigned vm
= INSTR (20, 16);
4004 unsigned vn
= INSTR (9, 5);
4005 unsigned vd
= INSTR (4, 0);
4006 int full
= INSTR (30, 30);
4008 NYI_assert (29, 24, 0x2E);
4009 NYI_assert (21, 21, 1);
4010 NYI_assert (15, 10, 0x31);
4012 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4015 double (* fn
)(double, double) = INSTR (23, 23)
4020 aarch64_set_vec_double (cpu
, vd
, 0,
4021 fn (aarch64_get_vec_double (cpu
, vn
, 0),
4022 aarch64_get_vec_double (cpu
, vn
, 1)));
4023 aarch64_set_vec_double (cpu
, vd
, 0,
4024 fn (aarch64_get_vec_double (cpu
, vm
, 0),
4025 aarch64_get_vec_double (cpu
, vm
, 1)));
4029 float (* fn
)(float, float) = INSTR (23, 23)
4032 aarch64_set_vec_float (cpu
, vd
, 0,
4033 fn (aarch64_get_vec_float (cpu
, vn
, 0),
4034 aarch64_get_vec_float (cpu
, vn
, 1)));
4036 aarch64_set_vec_float (cpu
, vd
, 1,
4037 fn (aarch64_get_vec_float (cpu
, vn
, 2),
4038 aarch64_get_vec_float (cpu
, vn
, 3)));
4040 aarch64_set_vec_float (cpu
, vd
, (full
? 2 : 1),
4041 fn (aarch64_get_vec_float (cpu
, vm
, 0),
4042 aarch64_get_vec_float (cpu
, vm
, 1)));
4044 aarch64_set_vec_float (cpu
, vd
, 3,
4045 fn (aarch64_get_vec_float (cpu
, vm
, 2),
4046 aarch64_get_vec_float (cpu
, vm
, 3)));
4051 do_vec_AND (sim_cpu
*cpu
)
4054 instr[30] = half (0)/full (1)
4055 instr[29,21] = 001110001
4057 instr[15,10] = 000111
4061 unsigned vm
= INSTR (20, 16);
4062 unsigned vn
= INSTR (9, 5);
4063 unsigned vd
= INSTR (4, 0);
4065 int full
= INSTR (30, 30);
4067 NYI_assert (29, 21, 0x071);
4068 NYI_assert (15, 10, 0x07);
4070 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4071 for (i
= 0; i
< (full
? 4 : 2); i
++)
4072 aarch64_set_vec_u32 (cpu
, vd
, i
,
4073 aarch64_get_vec_u32 (cpu
, vn
, i
)
4074 & aarch64_get_vec_u32 (cpu
, vm
, i
));
4078 do_vec_BSL (sim_cpu
*cpu
)
4081 instr[30] = half (0)/full (1)
4082 instr[29,21] = 101110011
4084 instr[15,10] = 000111
4088 unsigned vm
= INSTR (20, 16);
4089 unsigned vn
= INSTR (9, 5);
4090 unsigned vd
= INSTR (4, 0);
4092 int full
= INSTR (30, 30);
4094 NYI_assert (29, 21, 0x173);
4095 NYI_assert (15, 10, 0x07);
4097 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4098 for (i
= 0; i
< (full
? 16 : 8); i
++)
4099 aarch64_set_vec_u8 (cpu
, vd
, i
,
4100 ( aarch64_get_vec_u8 (cpu
, vd
, i
)
4101 & aarch64_get_vec_u8 (cpu
, vn
, i
))
4102 | ((~ aarch64_get_vec_u8 (cpu
, vd
, i
))
4103 & aarch64_get_vec_u8 (cpu
, vm
, i
)));
4107 do_vec_EOR (sim_cpu
*cpu
)
4110 instr[30] = half (0)/full (1)
4111 instr[29,21] = 10 1110 001
4113 instr[15,10] = 000111
4117 unsigned vm
= INSTR (20, 16);
4118 unsigned vn
= INSTR (9, 5);
4119 unsigned vd
= INSTR (4, 0);
4121 int full
= INSTR (30, 30);
4123 NYI_assert (29, 21, 0x171);
4124 NYI_assert (15, 10, 0x07);
4126 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4127 for (i
= 0; i
< (full
? 4 : 2); i
++)
4128 aarch64_set_vec_u32 (cpu
, vd
, i
,
4129 aarch64_get_vec_u32 (cpu
, vn
, i
)
4130 ^ aarch64_get_vec_u32 (cpu
, vm
, i
));
4134 do_vec_bit (sim_cpu
*cpu
)
4137 instr[30] = half (0)/full (1)
4138 instr[29,23] = 10 1110 1
4139 instr[22] = BIT (0) / BIF (1)
4142 instr[15,10] = 0001 11
4146 unsigned vm
= INSTR (20, 16);
4147 unsigned vn
= INSTR (9, 5);
4148 unsigned vd
= INSTR (4, 0);
4149 unsigned full
= INSTR (30, 30);
4150 unsigned test_false
= INSTR (22, 22);
4153 NYI_assert (29, 23, 0x5D);
4154 NYI_assert (21, 21, 1);
4155 NYI_assert (15, 10, 0x07);
4157 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4158 for (i
= 0; i
< (full
? 4 : 2); i
++)
4160 uint32_t vd_val
= aarch64_get_vec_u32 (cpu
, vd
, i
);
4161 uint32_t vn_val
= aarch64_get_vec_u32 (cpu
, vn
, i
);
4162 uint32_t vm_val
= aarch64_get_vec_u32 (cpu
, vm
, i
);
4164 aarch64_set_vec_u32 (cpu
, vd
, i
,
4165 (vd_val
& vm_val
) | (vn_val
& ~vm_val
));
4167 aarch64_set_vec_u32 (cpu
, vd
, i
,
4168 (vd_val
& ~vm_val
) | (vn_val
& vm_val
));
4173 do_vec_ORN (sim_cpu
*cpu
)
4176 instr[30] = half (0)/full (1)
4177 instr[29,21] = 00 1110 111
4179 instr[15,10] = 00 0111
4183 unsigned vm
= INSTR (20, 16);
4184 unsigned vn
= INSTR (9, 5);
4185 unsigned vd
= INSTR (4, 0);
4187 int full
= INSTR (30, 30);
4189 NYI_assert (29, 21, 0x077);
4190 NYI_assert (15, 10, 0x07);
4192 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4193 for (i
= 0; i
< (full
? 16 : 8); i
++)
4194 aarch64_set_vec_u8 (cpu
, vd
, i
,
4195 aarch64_get_vec_u8 (cpu
, vn
, i
)
4196 | ~ aarch64_get_vec_u8 (cpu
, vm
, i
));
4200 do_vec_ORR (sim_cpu
*cpu
)
4203 instr[30] = half (0)/full (1)
4204 instr[29,21] = 00 1110 101
4206 instr[15,10] = 0001 11
4210 unsigned vm
= INSTR (20, 16);
4211 unsigned vn
= INSTR (9, 5);
4212 unsigned vd
= INSTR (4, 0);
4214 int full
= INSTR (30, 30);
4216 NYI_assert (29, 21, 0x075);
4217 NYI_assert (15, 10, 0x07);
4219 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4220 for (i
= 0; i
< (full
? 16 : 8); i
++)
4221 aarch64_set_vec_u8 (cpu
, vd
, i
,
4222 aarch64_get_vec_u8 (cpu
, vn
, i
)
4223 | aarch64_get_vec_u8 (cpu
, vm
, i
));
4227 do_vec_BIC (sim_cpu
*cpu
)
4230 instr[30] = half (0)/full (1)
4231 instr[29,21] = 00 1110 011
4233 instr[15,10] = 00 0111
4237 unsigned vm
= INSTR (20, 16);
4238 unsigned vn
= INSTR (9, 5);
4239 unsigned vd
= INSTR (4, 0);
4241 int full
= INSTR (30, 30);
4243 NYI_assert (29, 21, 0x073);
4244 NYI_assert (15, 10, 0x07);
4246 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4247 for (i
= 0; i
< (full
? 16 : 8); i
++)
4248 aarch64_set_vec_u8 (cpu
, vd
, i
,
4249 aarch64_get_vec_u8 (cpu
, vn
, i
)
4250 & ~ aarch64_get_vec_u8 (cpu
, vm
, i
));
4254 do_vec_XTN (sim_cpu
*cpu
)
4257 instr[30] = first part (0)/ second part (1)
4258 instr[29,24] = 00 1110
4259 instr[23,22] = size: byte(00), half(01), word (10)
4260 instr[21,10] = 1000 0100 1010
4264 unsigned vs
= INSTR (9, 5);
4265 unsigned vd
= INSTR (4, 0);
4266 unsigned bias
= INSTR (30, 30);
4269 NYI_assert (29, 24, 0x0E);
4270 NYI_assert (21, 10, 0x84A);
4272 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4273 switch (INSTR (23, 22))
4276 for (i
= 0; i
< 8; i
++)
4277 aarch64_set_vec_u8 (cpu
, vd
, i
+ (bias
* 8),
4278 aarch64_get_vec_u16 (cpu
, vs
, i
));
4282 for (i
= 0; i
< 4; i
++)
4283 aarch64_set_vec_u16 (cpu
, vd
, i
+ (bias
* 4),
4284 aarch64_get_vec_u32 (cpu
, vs
, i
));
4288 for (i
= 0; i
< 2; i
++)
4289 aarch64_set_vec_u32 (cpu
, vd
, i
+ (bias
* 2),
4290 aarch64_get_vec_u64 (cpu
, vs
, i
));
4295 /* Return the number of bits set in the input value. */
4296 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
4297 # define popcount __builtin_popcount
4300 popcount (unsigned char x
)
4302 static const unsigned char popcnt
[16] =
4310 /* Only counts the low 8 bits of the input as that is all we need. */
4311 return popcnt
[x
% 16] + popcnt
[x
/ 16];
4316 do_vec_CNT (sim_cpu
*cpu
)
4319 instr[30] = half (0)/ full (1)
4320 instr[29,24] = 00 1110
4321 instr[23,22] = size: byte(00)
4322 instr[21,10] = 1000 0001 0110
4326 unsigned vs
= INSTR (9, 5);
4327 unsigned vd
= INSTR (4, 0);
4328 int full
= INSTR (30, 30);
4329 int size
= INSTR (23, 22);
4332 NYI_assert (29, 24, 0x0E);
4333 NYI_assert (21, 10, 0x816);
4338 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4340 for (i
= 0; i
< (full
? 16 : 8); i
++)
4341 aarch64_set_vec_u8 (cpu
, vd
, i
,
4342 popcount (aarch64_get_vec_u8 (cpu
, vs
, i
)));
4346 do_vec_maxv (sim_cpu
*cpu
)
4349 instr[30] = half(0)/full(1)
4350 instr[29] = signed (0)/unsigned(1)
4351 instr[28,24] = 0 1110
4352 instr[23,22] = size: byte(00), half(01), word (10)
4354 instr[20,17] = 1 000
4355 instr[16] = max(0)/min(1)
4356 instr[15,10] = 1010 10
4357 instr[9,5] = V source
4358 instr[4.0] = R dest. */
4360 unsigned vs
= INSTR (9, 5);
4361 unsigned rd
= INSTR (4, 0);
4362 unsigned full
= INSTR (30, 30);
4365 NYI_assert (28, 24, 0x0E);
4366 NYI_assert (21, 21, 1);
4367 NYI_assert (20, 17, 8);
4368 NYI_assert (15, 10, 0x2A);
4370 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4371 switch ((INSTR (29, 29) << 1) | INSTR (16, 16))
4373 case 0: /* SMAXV. */
4376 switch (INSTR (23, 22))
4379 smax
= aarch64_get_vec_s8 (cpu
, vs
, 0);
4380 for (i
= 1; i
< (full
? 16 : 8); i
++)
4381 smax
= max (smax
, aarch64_get_vec_s8 (cpu
, vs
, i
));
4384 smax
= aarch64_get_vec_s16 (cpu
, vs
, 0);
4385 for (i
= 1; i
< (full
? 8 : 4); i
++)
4386 smax
= max (smax
, aarch64_get_vec_s16 (cpu
, vs
, i
));
4389 smax
= aarch64_get_vec_s32 (cpu
, vs
, 0);
4390 for (i
= 1; i
< (full
? 4 : 2); i
++)
4391 smax
= max (smax
, aarch64_get_vec_s32 (cpu
, vs
, i
));
4396 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, smax
);
4400 case 1: /* SMINV. */
4403 switch (INSTR (23, 22))
4406 smin
= aarch64_get_vec_s8 (cpu
, vs
, 0);
4407 for (i
= 1; i
< (full
? 16 : 8); i
++)
4408 smin
= min (smin
, aarch64_get_vec_s8 (cpu
, vs
, i
));
4411 smin
= aarch64_get_vec_s16 (cpu
, vs
, 0);
4412 for (i
= 1; i
< (full
? 8 : 4); i
++)
4413 smin
= min (smin
, aarch64_get_vec_s16 (cpu
, vs
, i
));
4416 smin
= aarch64_get_vec_s32 (cpu
, vs
, 0);
4417 for (i
= 1; i
< (full
? 4 : 2); i
++)
4418 smin
= min (smin
, aarch64_get_vec_s32 (cpu
, vs
, i
));
4424 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, smin
);
4428 case 2: /* UMAXV. */
4431 switch (INSTR (23, 22))
4434 umax
= aarch64_get_vec_u8 (cpu
, vs
, 0);
4435 for (i
= 1; i
< (full
? 16 : 8); i
++)
4436 umax
= max (umax
, aarch64_get_vec_u8 (cpu
, vs
, i
));
4439 umax
= aarch64_get_vec_u16 (cpu
, vs
, 0);
4440 for (i
= 1; i
< (full
? 8 : 4); i
++)
4441 umax
= max (umax
, aarch64_get_vec_u16 (cpu
, vs
, i
));
4444 umax
= aarch64_get_vec_u32 (cpu
, vs
, 0);
4445 for (i
= 1; i
< (full
? 4 : 2); i
++)
4446 umax
= max (umax
, aarch64_get_vec_u32 (cpu
, vs
, i
));
4452 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, umax
);
4456 case 3: /* UMINV. */
4459 switch (INSTR (23, 22))
4462 umin
= aarch64_get_vec_u8 (cpu
, vs
, 0);
4463 for (i
= 1; i
< (full
? 16 : 8); i
++)
4464 umin
= min (umin
, aarch64_get_vec_u8 (cpu
, vs
, i
));
4467 umin
= aarch64_get_vec_u16 (cpu
, vs
, 0);
4468 for (i
= 1; i
< (full
? 8 : 4); i
++)
4469 umin
= min (umin
, aarch64_get_vec_u16 (cpu
, vs
, i
));
4472 umin
= aarch64_get_vec_u32 (cpu
, vs
, 0);
4473 for (i
= 1; i
< (full
? 4 : 2); i
++)
4474 umin
= min (umin
, aarch64_get_vec_u32 (cpu
, vs
, i
));
4480 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, umin
);
4487 do_vec_fminmaxV (sim_cpu
*cpu
)
4489 /* instr[31,24] = 0110 1110
4490 instr[23] = max(0)/min(1)
4491 instr[22,14] = 011 0000 11
4492 instr[13,12] = nm(00)/normal(11)
4494 instr[9,5] = V source
4495 instr[4.0] = R dest. */
4497 unsigned vs
= INSTR (9, 5);
4498 unsigned rd
= INSTR (4, 0);
4500 float res
= aarch64_get_vec_float (cpu
, vs
, 0);
4502 NYI_assert (31, 24, 0x6E);
4503 NYI_assert (22, 14, 0x0C3);
4504 NYI_assert (11, 10, 2);
4506 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4509 switch (INSTR (13, 12))
4511 case 0: /* FMNINNMV. */
4512 for (i
= 1; i
< 4; i
++)
4513 res
= fminnm (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4516 case 3: /* FMINV. */
4517 for (i
= 1; i
< 4; i
++)
4518 res
= min (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4527 switch (INSTR (13, 12))
4529 case 0: /* FMNAXNMV. */
4530 for (i
= 1; i
< 4; i
++)
4531 res
= fmaxnm (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4534 case 3: /* FMAXV. */
4535 for (i
= 1; i
< 4; i
++)
4536 res
= max (res
, aarch64_get_vec_float (cpu
, vs
, i
));
4544 aarch64_set_FP_float (cpu
, rd
, res
);
4548 do_vec_Fminmax (sim_cpu
*cpu
)
4551 instr[30] = half(0)/full(1)
4552 instr[29,24] = 00 1110
4553 instr[23] = max(0)/min(1)
4554 instr[22] = float(0)/double(1)
4558 instr[13,12] = nm(00)/normal(11)
4563 unsigned vm
= INSTR (20, 16);
4564 unsigned vn
= INSTR (9, 5);
4565 unsigned vd
= INSTR (4, 0);
4566 unsigned full
= INSTR (30, 30);
4567 unsigned min
= INSTR (23, 23);
4570 NYI_assert (29, 24, 0x0E);
4571 NYI_assert (21, 21, 1);
4572 NYI_assert (15, 14, 3);
4573 NYI_assert (11, 10, 1);
4575 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4578 double (* func
)(double, double);
4583 if (INSTR (13, 12) == 0)
4584 func
= min
? dminnm
: dmaxnm
;
4585 else if (INSTR (13, 12) == 3)
4586 func
= min
? fmin
: fmax
;
4590 for (i
= 0; i
< 2; i
++)
4591 aarch64_set_vec_double (cpu
, vd
, i
,
4592 func (aarch64_get_vec_double (cpu
, vn
, i
),
4593 aarch64_get_vec_double (cpu
, vm
, i
)));
4597 float (* func
)(float, float);
4599 if (INSTR (13, 12) == 0)
4600 func
= min
? fminnm
: fmaxnm
;
4601 else if (INSTR (13, 12) == 3)
4602 func
= min
? fminf
: fmaxf
;
4606 for (i
= 0; i
< (full
? 4 : 2); i
++)
4607 aarch64_set_vec_float (cpu
, vd
, i
,
4608 func (aarch64_get_vec_float (cpu
, vn
, i
),
4609 aarch64_get_vec_float (cpu
, vm
, i
)));
4614 do_vec_SCVTF (sim_cpu
*cpu
)
4618 instr[29,23] = 00 1110 0
4619 instr[22] = float(0)/double(1)
4620 instr[21,10] = 10 0001 1101 10
4624 unsigned vn
= INSTR (9, 5);
4625 unsigned vd
= INSTR (4, 0);
4626 unsigned full
= INSTR (30, 30);
4627 unsigned size
= INSTR (22, 22);
4630 NYI_assert (29, 23, 0x1C);
4631 NYI_assert (21, 10, 0x876);
4633 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4639 for (i
= 0; i
< 2; i
++)
4641 double val
= (double) aarch64_get_vec_u64 (cpu
, vn
, i
);
4642 aarch64_set_vec_double (cpu
, vd
, i
, val
);
4647 for (i
= 0; i
< (full
? 4 : 2); i
++)
4649 float val
= (float) aarch64_get_vec_u32 (cpu
, vn
, i
);
4650 aarch64_set_vec_float (cpu
, vd
, i
, val
);
4655 #define VEC_CMP(SOURCE, CMP) \
4661 for (i = 0; i < (full ? 16 : 8); i++) \
4662 aarch64_set_vec_u8 (cpu, vd, i, \
4663 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4665 aarch64_get_vec_##SOURCE##8 (cpu, vm, i) \
4669 for (i = 0; i < (full ? 8 : 4); i++) \
4670 aarch64_set_vec_u16 (cpu, vd, i, \
4671 aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4673 aarch64_get_vec_##SOURCE##16 (cpu, vm, i) \
4677 for (i = 0; i < (full ? 4 : 2); i++) \
4678 aarch64_set_vec_u32 (cpu, vd, i, \
4679 aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4681 aarch64_get_vec_##SOURCE##32 (cpu, vm, i) \
4687 for (i = 0; i < 2; i++) \
4688 aarch64_set_vec_u64 (cpu, vd, i, \
4689 aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4691 aarch64_get_vec_##SOURCE##64 (cpu, vm, i) \
4698 #define VEC_CMP0(SOURCE, CMP) \
4704 for (i = 0; i < (full ? 16 : 8); i++) \
4705 aarch64_set_vec_u8 (cpu, vd, i, \
4706 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4710 for (i = 0; i < (full ? 8 : 4); i++) \
4711 aarch64_set_vec_u16 (cpu, vd, i, \
4712 aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4716 for (i = 0; i < (full ? 4 : 2); i++) \
4717 aarch64_set_vec_u32 (cpu, vd, i, \
4718 aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4724 for (i = 0; i < 2; i++) \
4725 aarch64_set_vec_u64 (cpu, vd, i, \
4726 aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4727 CMP 0 ? -1ULL : 0); \
4733 #define VEC_FCMP0(CMP) \
4738 if (INSTR (22, 22)) \
4742 for (i = 0; i < 2; i++) \
4743 aarch64_set_vec_u64 (cpu, vd, i, \
4744 aarch64_get_vec_double (cpu, vn, i) \
4745 CMP 0.0 ? -1 : 0); \
4749 for (i = 0; i < (full ? 4 : 2); i++) \
4750 aarch64_set_vec_u32 (cpu, vd, i, \
4751 aarch64_get_vec_float (cpu, vn, i) \
4752 CMP 0.0 ? -1 : 0); \
4758 #define VEC_FCMP(CMP) \
4761 if (INSTR (22, 22)) \
4765 for (i = 0; i < 2; i++) \
4766 aarch64_set_vec_u64 (cpu, vd, i, \
4767 aarch64_get_vec_double (cpu, vn, i) \
4769 aarch64_get_vec_double (cpu, vm, i) \
4774 for (i = 0; i < (full ? 4 : 2); i++) \
4775 aarch64_set_vec_u32 (cpu, vd, i, \
4776 aarch64_get_vec_float (cpu, vn, i) \
4778 aarch64_get_vec_float (cpu, vm, i) \
4786 do_vec_compare (sim_cpu
*cpu
)
4789 instr[30] = half(0)/full(1)
4790 instr[29] = part-of-comparison-type
4791 instr[28,24] = 0 1110
4792 instr[23,22] = size of integer compares: byte(00), half(01), word (10), long (11)
4793 type of float compares: single (-0) / double (-1)
4795 instr[20,16] = Vm or 00000 (compare vs 0)
4796 instr[15,10] = part-of-comparison-type
4800 int full
= INSTR (30, 30);
4801 int size
= INSTR (23, 22);
4802 unsigned vm
= INSTR (20, 16);
4803 unsigned vn
= INSTR (9, 5);
4804 unsigned vd
= INSTR (4, 0);
4807 NYI_assert (28, 24, 0x0E);
4808 NYI_assert (21, 21, 1);
4810 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4813 || ((INSTR (11, 11) == 0
4814 && INSTR (10, 10) == 0)))
4816 /* A compare vs 0. */
4819 if (INSTR (15, 10) == 0x2A)
4821 else if (INSTR (15, 10) == 0x32
4822 || INSTR (15, 10) == 0x3E)
4823 do_vec_fminmaxV (cpu
);
4824 else if (INSTR (29, 23) == 0x1C
4825 && INSTR (21, 10) == 0x876)
4835 /* A floating point compare. */
4836 unsigned decode
= (INSTR (29, 29) << 5) | (INSTR (23, 23) << 4)
4839 NYI_assert (15, 15, 1);
4843 case /* 0b010010: GT#0 */ 0x12: VEC_FCMP0 (>);
4844 case /* 0b110010: GE#0 */ 0x32: VEC_FCMP0 (>=);
4845 case /* 0b010110: EQ#0 */ 0x16: VEC_FCMP0 (==);
4846 case /* 0b110110: LE#0 */ 0x36: VEC_FCMP0 (<=);
4847 case /* 0b011010: LT#0 */ 0x1A: VEC_FCMP0 (<);
4848 case /* 0b111001: GT */ 0x39: VEC_FCMP (>);
4849 case /* 0b101001: GE */ 0x29: VEC_FCMP (>=);
4850 case /* 0b001001: EQ */ 0x09: VEC_FCMP (==);
4858 unsigned decode
= (INSTR (29, 29) << 6) | INSTR (15, 10);
4862 case 0x0D: /* 0001101 GT */ VEC_CMP (s
, > );
4863 case 0x0F: /* 0001111 GE */ VEC_CMP (s
, >= );
4864 case 0x22: /* 0100010 GT #0 */ VEC_CMP0 (s
, > );
4865 case 0x23: /* 0100011 TST */ VEC_CMP (u
, & );
4866 case 0x26: /* 0100110 EQ #0 */ VEC_CMP0 (s
, == );
4867 case 0x2A: /* 0101010 LT #0 */ VEC_CMP0 (s
, < );
4868 case 0x4D: /* 1001101 HI */ VEC_CMP (u
, > );
4869 case 0x4F: /* 1001111 HS */ VEC_CMP (u
, >= );
4870 case 0x62: /* 1100010 GE #0 */ VEC_CMP0 (s
, >= );
4871 case 0x63: /* 1100011 EQ */ VEC_CMP (u
, == );
4872 case 0x66: /* 1100110 LE #0 */ VEC_CMP0 (s
, <= );
4882 do_vec_SSHL (sim_cpu
*cpu
)
4885 instr[30] = first part (0)/ second part (1)
4886 instr[29,24] = 00 1110
4887 instr[23,22] = size: byte(00), half(01), word (10), long (11)
4890 instr[15,10] = 0100 01
4894 unsigned full
= INSTR (30, 30);
4895 unsigned vm
= INSTR (20, 16);
4896 unsigned vn
= INSTR (9, 5);
4897 unsigned vd
= INSTR (4, 0);
4901 NYI_assert (29, 24, 0x0E);
4902 NYI_assert (21, 21, 1);
4903 NYI_assert (15, 10, 0x11);
4905 /* FIXME: What is a signed shift left in this context ?. */
4907 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4908 switch (INSTR (23, 22))
4911 for (i
= 0; i
< (full
? 16 : 8); i
++)
4913 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
);
4915 aarch64_set_vec_s8 (cpu
, vd
, i
, aarch64_get_vec_s8 (cpu
, vn
, i
)
4918 aarch64_set_vec_s8 (cpu
, vd
, i
, aarch64_get_vec_s8 (cpu
, vn
, i
)
4924 for (i
= 0; i
< (full
? 8 : 4); i
++)
4926 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 2);
4928 aarch64_set_vec_s16 (cpu
, vd
, i
, aarch64_get_vec_s16 (cpu
, vn
, i
)
4931 aarch64_set_vec_s16 (cpu
, vd
, i
, aarch64_get_vec_s16 (cpu
, vn
, i
)
4937 for (i
= 0; i
< (full
? 4 : 2); i
++)
4939 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 4);
4941 aarch64_set_vec_s32 (cpu
, vd
, i
, aarch64_get_vec_s32 (cpu
, vn
, i
)
4944 aarch64_set_vec_s32 (cpu
, vd
, i
, aarch64_get_vec_s32 (cpu
, vn
, i
)
4952 for (i
= 0; i
< 2; i
++)
4954 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 8);
4956 aarch64_set_vec_s64 (cpu
, vd
, i
, aarch64_get_vec_s64 (cpu
, vn
, i
)
4959 aarch64_set_vec_s64 (cpu
, vd
, i
, aarch64_get_vec_s64 (cpu
, vn
, i
)
4967 do_vec_USHL (sim_cpu
*cpu
)
4970 instr[30] = first part (0)/ second part (1)
4971 instr[29,24] = 10 1110
4972 instr[23,22] = size: byte(00), half(01), word (10), long (11)
4975 instr[15,10] = 0100 01
4979 unsigned full
= INSTR (30, 30);
4980 unsigned vm
= INSTR (20, 16);
4981 unsigned vn
= INSTR (9, 5);
4982 unsigned vd
= INSTR (4, 0);
4986 NYI_assert (29, 24, 0x2E);
4987 NYI_assert (15, 10, 0x11);
4989 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
4990 switch (INSTR (23, 22))
4993 for (i
= 0; i
< (full
? 16 : 8); i
++)
4995 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
);
4997 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vn
, i
)
5000 aarch64_set_vec_u8 (cpu
, vd
, i
, aarch64_get_vec_u8 (cpu
, vn
, i
)
5006 for (i
= 0; i
< (full
? 8 : 4); i
++)
5008 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 2);
5010 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vn
, i
)
5013 aarch64_set_vec_u16 (cpu
, vd
, i
, aarch64_get_vec_u16 (cpu
, vn
, i
)
5019 for (i
= 0; i
< (full
? 4 : 2); i
++)
5021 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 4);
5023 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vn
, i
)
5026 aarch64_set_vec_u32 (cpu
, vd
, i
, aarch64_get_vec_u32 (cpu
, vn
, i
)
5034 for (i
= 0; i
< 2; i
++)
5036 shift
= aarch64_get_vec_s8 (cpu
, vm
, i
* 8);
5038 aarch64_set_vec_u64 (cpu
, vd
, i
, aarch64_get_vec_u64 (cpu
, vn
, i
)
5041 aarch64_set_vec_u64 (cpu
, vd
, i
, aarch64_get_vec_u64 (cpu
, vn
, i
)
5049 do_vec_FMLA (sim_cpu
*cpu
)
5052 instr[30] = full/half selector
5053 instr[29,23] = 0011100
5054 instr[22] = size: 0=>float, 1=>double
5057 instr[15,10] = 1100 11
5061 unsigned vm
= INSTR (20, 16);
5062 unsigned vn
= INSTR (9, 5);
5063 unsigned vd
= INSTR (4, 0);
5065 int full
= INSTR (30, 30);
5067 NYI_assert (29, 23, 0x1C);
5068 NYI_assert (21, 21, 1);
5069 NYI_assert (15, 10, 0x33);
5071 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5076 for (i
= 0; i
< 2; i
++)
5077 aarch64_set_vec_double (cpu
, vd
, i
,
5078 aarch64_get_vec_double (cpu
, vn
, i
) *
5079 aarch64_get_vec_double (cpu
, vm
, i
) +
5080 aarch64_get_vec_double (cpu
, vd
, i
));
5084 for (i
= 0; i
< (full
? 4 : 2); i
++)
5085 aarch64_set_vec_float (cpu
, vd
, i
,
5086 aarch64_get_vec_float (cpu
, vn
, i
) *
5087 aarch64_get_vec_float (cpu
, vm
, i
) +
5088 aarch64_get_vec_float (cpu
, vd
, i
));
5093 do_vec_max (sim_cpu
*cpu
)
5096 instr[30] = full/half selector
5097 instr[29] = SMAX (0) / UMAX (1)
5098 instr[28,24] = 0 1110
5099 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
5102 instr[15,10] = 0110 01
5106 unsigned vm
= INSTR (20, 16);
5107 unsigned vn
= INSTR (9, 5);
5108 unsigned vd
= INSTR (4, 0);
5110 int full
= INSTR (30, 30);
5112 NYI_assert (28, 24, 0x0E);
5113 NYI_assert (21, 21, 1);
5114 NYI_assert (15, 10, 0x19);
5116 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5119 switch (INSTR (23, 22))
5122 for (i
= 0; i
< (full
? 16 : 8); i
++)
5123 aarch64_set_vec_u8 (cpu
, vd
, i
,
5124 aarch64_get_vec_u8 (cpu
, vn
, i
)
5125 > aarch64_get_vec_u8 (cpu
, vm
, i
)
5126 ? aarch64_get_vec_u8 (cpu
, vn
, i
)
5127 : aarch64_get_vec_u8 (cpu
, vm
, i
));
5131 for (i
= 0; i
< (full
? 8 : 4); i
++)
5132 aarch64_set_vec_u16 (cpu
, vd
, i
,
5133 aarch64_get_vec_u16 (cpu
, vn
, i
)
5134 > aarch64_get_vec_u16 (cpu
, vm
, i
)
5135 ? aarch64_get_vec_u16 (cpu
, vn
, i
)
5136 : aarch64_get_vec_u16 (cpu
, vm
, i
));
5140 for (i
= 0; i
< (full
? 4 : 2); i
++)
5141 aarch64_set_vec_u32 (cpu
, vd
, i
,
5142 aarch64_get_vec_u32 (cpu
, vn
, i
)
5143 > aarch64_get_vec_u32 (cpu
, vm
, i
)
5144 ? aarch64_get_vec_u32 (cpu
, vn
, i
)
5145 : aarch64_get_vec_u32 (cpu
, vm
, i
));
5154 switch (INSTR (23, 22))
5157 for (i
= 0; i
< (full
? 16 : 8); i
++)
5158 aarch64_set_vec_s8 (cpu
, vd
, i
,
5159 aarch64_get_vec_s8 (cpu
, vn
, i
)
5160 > aarch64_get_vec_s8 (cpu
, vm
, i
)
5161 ? aarch64_get_vec_s8 (cpu
, vn
, i
)
5162 : aarch64_get_vec_s8 (cpu
, vm
, i
));
5166 for (i
= 0; i
< (full
? 8 : 4); i
++)
5167 aarch64_set_vec_s16 (cpu
, vd
, i
,
5168 aarch64_get_vec_s16 (cpu
, vn
, i
)
5169 > aarch64_get_vec_s16 (cpu
, vm
, i
)
5170 ? aarch64_get_vec_s16 (cpu
, vn
, i
)
5171 : aarch64_get_vec_s16 (cpu
, vm
, i
));
5175 for (i
= 0; i
< (full
? 4 : 2); i
++)
5176 aarch64_set_vec_s32 (cpu
, vd
, i
,
5177 aarch64_get_vec_s32 (cpu
, vn
, i
)
5178 > aarch64_get_vec_s32 (cpu
, vm
, i
)
5179 ? aarch64_get_vec_s32 (cpu
, vn
, i
)
5180 : aarch64_get_vec_s32 (cpu
, vm
, i
));
5190 do_vec_min (sim_cpu
*cpu
)
5193 instr[30] = full/half selector
5194 instr[29] = SMIN (0) / UMIN (1)
5195 instr[28,24] = 0 1110
5196 instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
5199 instr[15,10] = 0110 11
5203 unsigned vm
= INSTR (20, 16);
5204 unsigned vn
= INSTR (9, 5);
5205 unsigned vd
= INSTR (4, 0);
5207 int full
= INSTR (30, 30);
5209 NYI_assert (28, 24, 0x0E);
5210 NYI_assert (21, 21, 1);
5211 NYI_assert (15, 10, 0x1B);
5213 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5216 switch (INSTR (23, 22))
5219 for (i
= 0; i
< (full
? 16 : 8); i
++)
5220 aarch64_set_vec_u8 (cpu
, vd
, i
,
5221 aarch64_get_vec_u8 (cpu
, vn
, i
)
5222 < aarch64_get_vec_u8 (cpu
, vm
, i
)
5223 ? aarch64_get_vec_u8 (cpu
, vn
, i
)
5224 : aarch64_get_vec_u8 (cpu
, vm
, i
));
5228 for (i
= 0; i
< (full
? 8 : 4); i
++)
5229 aarch64_set_vec_u16 (cpu
, vd
, i
,
5230 aarch64_get_vec_u16 (cpu
, vn
, i
)
5231 < aarch64_get_vec_u16 (cpu
, vm
, i
)
5232 ? aarch64_get_vec_u16 (cpu
, vn
, i
)
5233 : aarch64_get_vec_u16 (cpu
, vm
, i
));
5237 for (i
= 0; i
< (full
? 4 : 2); i
++)
5238 aarch64_set_vec_u32 (cpu
, vd
, i
,
5239 aarch64_get_vec_u32 (cpu
, vn
, i
)
5240 < aarch64_get_vec_u32 (cpu
, vm
, i
)
5241 ? aarch64_get_vec_u32 (cpu
, vn
, i
)
5242 : aarch64_get_vec_u32 (cpu
, vm
, i
));
5251 switch (INSTR (23, 22))
5254 for (i
= 0; i
< (full
? 16 : 8); i
++)
5255 aarch64_set_vec_s8 (cpu
, vd
, i
,
5256 aarch64_get_vec_s8 (cpu
, vn
, i
)
5257 < aarch64_get_vec_s8 (cpu
, vm
, i
)
5258 ? aarch64_get_vec_s8 (cpu
, vn
, i
)
5259 : aarch64_get_vec_s8 (cpu
, vm
, i
));
5263 for (i
= 0; i
< (full
? 8 : 4); i
++)
5264 aarch64_set_vec_s16 (cpu
, vd
, i
,
5265 aarch64_get_vec_s16 (cpu
, vn
, i
)
5266 < aarch64_get_vec_s16 (cpu
, vm
, i
)
5267 ? aarch64_get_vec_s16 (cpu
, vn
, i
)
5268 : aarch64_get_vec_s16 (cpu
, vm
, i
));
5272 for (i
= 0; i
< (full
? 4 : 2); i
++)
5273 aarch64_set_vec_s32 (cpu
, vd
, i
,
5274 aarch64_get_vec_s32 (cpu
, vn
, i
)
5275 < aarch64_get_vec_s32 (cpu
, vm
, i
)
5276 ? aarch64_get_vec_s32 (cpu
, vn
, i
)
5277 : aarch64_get_vec_s32 (cpu
, vm
, i
));
5287 do_vec_sub_long (sim_cpu
*cpu
)
5290 instr[30] = lower (0) / upper (1)
5291 instr[29] = signed (0) / unsigned (1)
5292 instr[28,24] = 0 1110
5293 instr[23,22] = size: bytes (00), half (01), word (10)
5296 instr[15,10] = 0010 00
5298 instr[4,0] = V dest. */
5300 unsigned size
= INSTR (23, 22);
5301 unsigned vm
= INSTR (20, 16);
5302 unsigned vn
= INSTR (9, 5);
5303 unsigned vd
= INSTR (4, 0);
5307 NYI_assert (28, 24, 0x0E);
5308 NYI_assert (21, 21, 1);
5309 NYI_assert (15, 10, 0x08);
5314 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5315 switch (INSTR (30, 29))
5317 case 2: /* SSUBL2. */
5319 case 0: /* SSUBL. */
5324 for (i
= 0; i
< 8; i
++)
5325 aarch64_set_vec_s16 (cpu
, vd
, i
,
5326 aarch64_get_vec_s8 (cpu
, vn
, i
+ bias
)
5327 - aarch64_get_vec_s8 (cpu
, vm
, i
+ bias
));
5332 for (i
= 0; i
< 4; i
++)
5333 aarch64_set_vec_s32 (cpu
, vd
, i
,
5334 aarch64_get_vec_s16 (cpu
, vn
, i
+ bias
)
5335 - aarch64_get_vec_s16 (cpu
, vm
, i
+ bias
));
5339 for (i
= 0; i
< 2; i
++)
5340 aarch64_set_vec_s64 (cpu
, vd
, i
,
5341 aarch64_get_vec_s32 (cpu
, vn
, i
+ bias
)
5342 - aarch64_get_vec_s32 (cpu
, vm
, i
+ bias
));
5350 case 3: /* USUBL2. */
5352 case 1: /* USUBL. */
5357 for (i
= 0; i
< 8; i
++)
5358 aarch64_set_vec_u16 (cpu
, vd
, i
,
5359 aarch64_get_vec_u8 (cpu
, vn
, i
+ bias
)
5360 - aarch64_get_vec_u8 (cpu
, vm
, i
+ bias
));
5365 for (i
= 0; i
< 4; i
++)
5366 aarch64_set_vec_u32 (cpu
, vd
, i
,
5367 aarch64_get_vec_u16 (cpu
, vn
, i
+ bias
)
5368 - aarch64_get_vec_u16 (cpu
, vm
, i
+ bias
));
5372 for (i
= 0; i
< 2; i
++)
5373 aarch64_set_vec_u64 (cpu
, vd
, i
,
5374 aarch64_get_vec_u32 (cpu
, vn
, i
+ bias
)
5375 - aarch64_get_vec_u32 (cpu
, vm
, i
+ bias
));
5386 do_vec_ADDP (sim_cpu
*cpu
)
5389 instr[30] = half(0)/full(1)
5390 instr[29,24] = 00 1110
5391 instr[23,22] = size: bytes (00), half (01), word (10), long (11)
5394 instr[15,10] = 1011 11
5396 instr[4,0] = V dest. */
5398 struct aarch64_sim_cpu
*aarch64_cpu
= AARCH64_SIM_CPU (cpu
);
5401 unsigned full
= INSTR (30, 30);
5402 unsigned size
= INSTR (23, 22);
5403 unsigned vm
= INSTR (20, 16);
5404 unsigned vn
= INSTR (9, 5);
5405 unsigned vd
= INSTR (4, 0);
5408 NYI_assert (29, 24, 0x0E);
5409 NYI_assert (21, 21, 1);
5410 NYI_assert (15, 10, 0x2F);
5412 /* Make copies of the source registers in case vd == vn/vm. */
5413 copy_vn
= aarch64_cpu
->fr
[vn
];
5414 copy_vm
= aarch64_cpu
->fr
[vm
];
5416 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5420 range
= full
? 8 : 4;
5421 for (i
= 0; i
< range
; i
++)
5423 aarch64_set_vec_u8 (cpu
, vd
, i
,
5424 copy_vn
.b
[i
* 2] + copy_vn
.b
[i
* 2 + 1]);
5425 aarch64_set_vec_u8 (cpu
, vd
, i
+ range
,
5426 copy_vm
.b
[i
* 2] + copy_vm
.b
[i
* 2 + 1]);
5431 range
= full
? 4 : 2;
5432 for (i
= 0; i
< range
; i
++)
5434 aarch64_set_vec_u16 (cpu
, vd
, i
,
5435 copy_vn
.h
[i
* 2] + copy_vn
.h
[i
* 2 + 1]);
5436 aarch64_set_vec_u16 (cpu
, vd
, i
+ range
,
5437 copy_vm
.h
[i
* 2] + copy_vm
.h
[i
* 2 + 1]);
5442 range
= full
? 2 : 1;
5443 for (i
= 0; i
< range
; i
++)
5445 aarch64_set_vec_u32 (cpu
, vd
, i
,
5446 copy_vn
.w
[i
* 2] + copy_vn
.w
[i
* 2 + 1]);
5447 aarch64_set_vec_u32 (cpu
, vd
, i
+ range
,
5448 copy_vm
.w
[i
* 2] + copy_vm
.w
[i
* 2 + 1]);
5455 aarch64_set_vec_u64 (cpu
, vd
, 0, copy_vn
.v
[0] + copy_vn
.v
[1]);
5456 aarch64_set_vec_u64 (cpu
, vd
, 1, copy_vm
.v
[0] + copy_vm
.v
[1]);
5461 /* Float point vector convert to longer (precision). */
5463 do_vec_FCVTL (sim_cpu
*cpu
)
5466 instr[30] = half (0) / all (1)
5467 instr[29,23] = 00 1110 0
5468 instr[22] = single (0) / double (1)
5469 instr[21,10] = 10 0001 0111 10
5473 unsigned rn
= INSTR (9, 5);
5474 unsigned rd
= INSTR (4, 0);
5475 unsigned full
= INSTR (30, 30);
5478 NYI_assert (31, 31, 0);
5479 NYI_assert (29, 23, 0x1C);
5480 NYI_assert (21, 10, 0x85E);
5482 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5485 for (i
= 0; i
< 2; i
++)
5486 aarch64_set_vec_double (cpu
, rd
, i
,
5487 aarch64_get_vec_float (cpu
, rn
, i
+ 2*full
));
5494 /* TODO: Implement missing half-float support. */
5495 for (i
= 0; i
< 4; i
++)
5496 aarch64_set_vec_float (cpu
, rd
, i
,
5497 aarch64_get_vec_halffloat (cpu
, rn
, i
+ 4*full
));
5503 do_vec_FABS (sim_cpu
*cpu
)
5506 instr[30] = half(0)/full(1)
5507 instr[29,23] = 00 1110 1
5508 instr[22] = float(0)/double(1)
5509 instr[21,16] = 10 0000
5510 instr[15,10] = 1111 10
5514 unsigned vn
= INSTR (9, 5);
5515 unsigned vd
= INSTR (4, 0);
5516 unsigned full
= INSTR (30, 30);
5519 NYI_assert (29, 23, 0x1D);
5520 NYI_assert (21, 10, 0x83E);
5522 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5528 for (i
= 0; i
< 2; i
++)
5529 aarch64_set_vec_double (cpu
, vd
, i
,
5530 fabs (aarch64_get_vec_double (cpu
, vn
, i
)));
5534 for (i
= 0; i
< (full
? 4 : 2); i
++)
5535 aarch64_set_vec_float (cpu
, vd
, i
,
5536 fabsf (aarch64_get_vec_float (cpu
, vn
, i
)));
5541 do_vec_FCVTZS (sim_cpu
*cpu
)
5544 instr[30] = half (0) / all (1)
5545 instr[29,23] = 00 1110 1
5546 instr[22] = single (0) / double (1)
5547 instr[21,10] = 10 0001 1011 10
5551 unsigned rn
= INSTR (9, 5);
5552 unsigned rd
= INSTR (4, 0);
5553 unsigned full
= INSTR (30, 30);
5556 NYI_assert (31, 31, 0);
5557 NYI_assert (29, 23, 0x1D);
5558 NYI_assert (21, 10, 0x86E);
5560 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5566 for (i
= 0; i
< 2; i
++)
5567 aarch64_set_vec_s64 (cpu
, rd
, i
,
5568 (int64_t) aarch64_get_vec_double (cpu
, rn
, i
));
5571 for (i
= 0; i
< (full
? 4 : 2); i
++)
5572 aarch64_set_vec_s32 (cpu
, rd
, i
,
5573 (int32_t) aarch64_get_vec_float (cpu
, rn
, i
));
5577 do_vec_REV64 (sim_cpu
*cpu
)
5580 instr[30] = full/half
5581 instr[29,24] = 00 1110
5583 instr[21,10] = 10 0000 0000 10
5587 unsigned rn
= INSTR (9, 5);
5588 unsigned rd
= INSTR (4, 0);
5589 unsigned size
= INSTR (23, 22);
5590 unsigned full
= INSTR (30, 30);
5594 NYI_assert (29, 24, 0x0E);
5595 NYI_assert (21, 10, 0x802);
5597 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5601 for (i
= 0; i
< (full
? 16 : 8); i
++)
5602 val
.b
[i
^ 0x7] = aarch64_get_vec_u8 (cpu
, rn
, i
);
5606 for (i
= 0; i
< (full
? 8 : 4); i
++)
5607 val
.h
[i
^ 0x3] = aarch64_get_vec_u16 (cpu
, rn
, i
);
5611 for (i
= 0; i
< (full
? 4 : 2); i
++)
5612 val
.w
[i
^ 0x1] = aarch64_get_vec_u32 (cpu
, rn
, i
);
5619 aarch64_set_vec_u64 (cpu
, rd
, 0, val
.v
[0]);
5621 aarch64_set_vec_u64 (cpu
, rd
, 1, val
.v
[1]);
5625 do_vec_REV16 (sim_cpu
*cpu
)
5628 instr[30] = full/half
5629 instr[29,24] = 00 1110
5631 instr[21,10] = 10 0000 0001 10
5635 unsigned rn
= INSTR (9, 5);
5636 unsigned rd
= INSTR (4, 0);
5637 unsigned size
= INSTR (23, 22);
5638 unsigned full
= INSTR (30, 30);
5642 NYI_assert (29, 24, 0x0E);
5643 NYI_assert (21, 10, 0x806);
5645 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5649 for (i
= 0; i
< (full
? 16 : 8); i
++)
5650 val
.b
[i
^ 0x1] = aarch64_get_vec_u8 (cpu
, rn
, i
);
5657 aarch64_set_vec_u64 (cpu
, rd
, 0, val
.v
[0]);
5659 aarch64_set_vec_u64 (cpu
, rd
, 1, val
.v
[1]);
5663 do_vec_op1 (sim_cpu
*cpu
)
5666 instr[30] = half/full
5667 instr[29,24] = 00 1110
5670 instr[15,10] = sub-opcode
5673 NYI_assert (29, 24, 0x0E);
5675 if (INSTR (21, 21) == 0)
5677 if (INSTR (23, 22) == 0)
5679 if (INSTR (30, 30) == 1
5680 && INSTR (17, 14) == 0
5681 && INSTR (12, 10) == 7)
5682 return do_vec_ins_2 (cpu
);
5684 switch (INSTR (15, 10))
5686 case 0x01: do_vec_DUP_vector_into_vector (cpu
); return;
5687 case 0x03: do_vec_DUP_scalar_into_vector (cpu
); return;
5688 case 0x07: do_vec_INS (cpu
); return;
5689 case 0x0B: do_vec_SMOV_into_scalar (cpu
); return;
5690 case 0x0F: do_vec_UMOV_into_scalar (cpu
); return;
5696 do_vec_TBL (cpu
); return;
5700 do_vec_UZP (cpu
); return;
5702 case 0x0A: do_vec_TRN (cpu
); return;
5706 do_vec_ZIP (cpu
); return;
5713 switch (INSTR (13, 10))
5715 case 0x6: do_vec_UZP (cpu
); return;
5716 case 0xE: do_vec_ZIP (cpu
); return;
5717 case 0xA: do_vec_TRN (cpu
); return;
5722 switch (INSTR (15, 10))
5724 case 0x02: do_vec_REV64 (cpu
); return;
5725 case 0x06: do_vec_REV16 (cpu
); return;
5728 switch (INSTR (23, 21))
5730 case 1: do_vec_AND (cpu
); return;
5731 case 3: do_vec_BIC (cpu
); return;
5732 case 5: do_vec_ORR (cpu
); return;
5733 case 7: do_vec_ORN (cpu
); return;
5737 case 0x08: do_vec_sub_long (cpu
); return;
5738 case 0x0a: do_vec_XTN (cpu
); return;
5739 case 0x11: do_vec_SSHL (cpu
); return;
5740 case 0x16: do_vec_CNT (cpu
); return;
5741 case 0x19: do_vec_max (cpu
); return;
5742 case 0x1B: do_vec_min (cpu
); return;
5743 case 0x21: do_vec_add (cpu
); return;
5744 case 0x25: do_vec_MLA (cpu
); return;
5745 case 0x27: do_vec_mul (cpu
); return;
5746 case 0x2F: do_vec_ADDP (cpu
); return;
5747 case 0x30: do_vec_mull (cpu
); return;
5748 case 0x33: do_vec_FMLA (cpu
); return;
5749 case 0x35: do_vec_fadd (cpu
); return;
5752 switch (INSTR (20, 16))
5754 case 0x01: do_vec_FCVTL (cpu
); return;
5759 switch (INSTR (20, 16))
5761 case 0x00: do_vec_ABS (cpu
); return;
5762 case 0x01: do_vec_FCVTZS (cpu
); return;
5763 case 0x11: do_vec_ADDV (cpu
); return;
5769 do_vec_Fminmax (cpu
); return;
5781 do_vec_compare (cpu
); return;
5784 do_vec_FABS (cpu
); return;
5792 do_vec_xtl (sim_cpu
*cpu
)
5795 instr[30,29] = SXTL (00), UXTL (01), SXTL2 (10), UXTL2 (11)
5796 instr[28,22] = 0 1111 00
5797 instr[21,16] = size & shift (USHLL, SSHLL, USHLL2, SSHLL2)
5798 instr[15,10] = 1010 01
5799 instr[9,5] = V source
5800 instr[4,0] = V dest. */
5802 unsigned vs
= INSTR (9, 5);
5803 unsigned vd
= INSTR (4, 0);
5804 unsigned i
, shift
, bias
= 0;
5806 NYI_assert (28, 22, 0x3C);
5807 NYI_assert (15, 10, 0x29);
5809 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5810 switch (INSTR (30, 29))
5812 case 2: /* SXTL2, SSHLL2. */
5814 case 0: /* SXTL, SSHLL. */
5819 shift
= INSTR (20, 16);
5820 /* Get the source values before setting the destination values
5821 in case the source and destination are the same. */
5822 val1
= aarch64_get_vec_s32 (cpu
, vs
, bias
) << shift
;
5823 val2
= aarch64_get_vec_s32 (cpu
, vs
, bias
+ 1) << shift
;
5824 aarch64_set_vec_s64 (cpu
, vd
, 0, val1
);
5825 aarch64_set_vec_s64 (cpu
, vd
, 1, val2
);
5827 else if (INSTR (20, 20))
5830 int32_t v1
,v2
,v3
,v4
;
5832 shift
= INSTR (19, 16);
5834 for (i
= 0; i
< 4; i
++)
5835 v
[i
] = aarch64_get_vec_s16 (cpu
, vs
, bias
+ i
) << shift
;
5836 for (i
= 0; i
< 4; i
++)
5837 aarch64_set_vec_s32 (cpu
, vd
, i
, v
[i
]);
5842 NYI_assert (19, 19, 1);
5844 shift
= INSTR (18, 16);
5846 for (i
= 0; i
< 8; i
++)
5847 v
[i
] = aarch64_get_vec_s8 (cpu
, vs
, i
+ bias
) << shift
;
5848 for (i
= 0; i
< 8; i
++)
5849 aarch64_set_vec_s16 (cpu
, vd
, i
, v
[i
]);
5853 case 3: /* UXTL2, USHLL2. */
5855 case 1: /* UXTL, USHLL. */
5859 shift
= INSTR (20, 16);
5860 v1
= aarch64_get_vec_u32 (cpu
, vs
, bias
) << shift
;
5861 v2
= aarch64_get_vec_u32 (cpu
, vs
, bias
+ 1) << shift
;
5862 aarch64_set_vec_u64 (cpu
, vd
, 0, v1
);
5863 aarch64_set_vec_u64 (cpu
, vd
, 1, v2
);
5865 else if (INSTR (20, 20))
5868 shift
= INSTR (19, 16);
5870 for (i
= 0; i
< 4; i
++)
5871 v
[i
] = aarch64_get_vec_u16 (cpu
, vs
, i
+ bias
) << shift
;
5872 for (i
= 0; i
< 4; i
++)
5873 aarch64_set_vec_u32 (cpu
, vd
, i
, v
[i
]);
5878 NYI_assert (19, 19, 1);
5880 shift
= INSTR (18, 16);
5882 for (i
= 0; i
< 8; i
++)
5883 v
[i
] = aarch64_get_vec_u8 (cpu
, vs
, i
+ bias
) << shift
;
5884 for (i
= 0; i
< 8; i
++)
5885 aarch64_set_vec_u16 (cpu
, vd
, i
, v
[i
]);
5892 do_vec_SHL (sim_cpu
*cpu
)
5895 instr [30] = half(0)/full(1)
5896 instr [29,23] = 001 1110
5897 instr [22,16] = size and shift amount
5898 instr [15,10] = 01 0101
5900 instr [4, 0] = Vd. */
5903 int full
= INSTR (30, 30);
5904 unsigned vs
= INSTR (9, 5);
5905 unsigned vd
= INSTR (4, 0);
5908 NYI_assert (29, 23, 0x1E);
5909 NYI_assert (15, 10, 0x15);
5911 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5914 shift
= INSTR (21, 16);
5919 for (i
= 0; i
< 2; i
++)
5921 uint64_t val
= aarch64_get_vec_u64 (cpu
, vs
, i
);
5922 aarch64_set_vec_u64 (cpu
, vd
, i
, val
<< shift
);
5930 shift
= INSTR (20, 16);
5932 for (i
= 0; i
< (full
? 4 : 2); i
++)
5934 uint32_t val
= aarch64_get_vec_u32 (cpu
, vs
, i
);
5935 aarch64_set_vec_u32 (cpu
, vd
, i
, val
<< shift
);
5943 shift
= INSTR (19, 16);
5945 for (i
= 0; i
< (full
? 8 : 4); i
++)
5947 uint16_t val
= aarch64_get_vec_u16 (cpu
, vs
, i
);
5948 aarch64_set_vec_u16 (cpu
, vd
, i
, val
<< shift
);
5954 if (INSTR (19, 19) == 0)
5957 shift
= INSTR (18, 16);
5959 for (i
= 0; i
< (full
? 16 : 8); i
++)
5961 uint8_t val
= aarch64_get_vec_u8 (cpu
, vs
, i
);
5962 aarch64_set_vec_u8 (cpu
, vd
, i
, val
<< shift
);
5967 do_vec_SSHR_USHR (sim_cpu
*cpu
)
5970 instr [30] = half(0)/full(1)
5971 instr [29] = signed(0)/unsigned(1)
5972 instr [28,23] = 0 1111 0
5973 instr [22,16] = size and shift amount
5974 instr [15,10] = 0000 01
5976 instr [4, 0] = Vd. */
5978 int full
= INSTR (30, 30);
5979 int sign
= ! INSTR (29, 29);
5980 unsigned shift
= INSTR (22, 16);
5981 unsigned vs
= INSTR (9, 5);
5982 unsigned vd
= INSTR (4, 0);
5985 NYI_assert (28, 23, 0x1E);
5986 NYI_assert (15, 10, 0x01);
5988 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
5991 shift
= 128 - shift
;
5997 for (i
= 0; i
< 2; i
++)
5999 int64_t val
= aarch64_get_vec_s64 (cpu
, vs
, i
);
6000 aarch64_set_vec_s64 (cpu
, vd
, i
, val
>> shift
);
6003 for (i
= 0; i
< 2; i
++)
6005 uint64_t val
= aarch64_get_vec_u64 (cpu
, vs
, i
);
6006 aarch64_set_vec_u64 (cpu
, vd
, i
, val
>> shift
);
6017 for (i
= 0; i
< (full
? 4 : 2); i
++)
6019 int32_t val
= aarch64_get_vec_s32 (cpu
, vs
, i
);
6020 aarch64_set_vec_s32 (cpu
, vd
, i
, val
>> shift
);
6023 for (i
= 0; i
< (full
? 4 : 2); i
++)
6025 uint32_t val
= aarch64_get_vec_u32 (cpu
, vs
, i
);
6026 aarch64_set_vec_u32 (cpu
, vd
, i
, val
>> shift
);
6037 for (i
= 0; i
< (full
? 8 : 4); i
++)
6039 int16_t val
= aarch64_get_vec_s16 (cpu
, vs
, i
);
6040 aarch64_set_vec_s16 (cpu
, vd
, i
, val
>> shift
);
6043 for (i
= 0; i
< (full
? 8 : 4); i
++)
6045 uint16_t val
= aarch64_get_vec_u16 (cpu
, vs
, i
);
6046 aarch64_set_vec_u16 (cpu
, vd
, i
, val
>> shift
);
6052 if (INSTR (19, 19) == 0)
6058 for (i
= 0; i
< (full
? 16 : 8); i
++)
6060 int8_t val
= aarch64_get_vec_s8 (cpu
, vs
, i
);
6061 aarch64_set_vec_s8 (cpu
, vd
, i
, val
>> shift
);
6064 for (i
= 0; i
< (full
? 16 : 8); i
++)
6066 uint8_t val
= aarch64_get_vec_u8 (cpu
, vs
, i
);
6067 aarch64_set_vec_u8 (cpu
, vd
, i
, val
>> shift
);
6072 do_vec_MUL_by_element (sim_cpu
*cpu
)
6075 instr[30] = half/full
6076 instr[29,24] = 00 1111
6087 unsigned full
= INSTR (30, 30);
6088 unsigned L
= INSTR (21, 21);
6089 unsigned H
= INSTR (11, 11);
6090 unsigned vn
= INSTR (9, 5);
6091 unsigned vd
= INSTR (4, 0);
6092 unsigned size
= INSTR (23, 22);
6097 NYI_assert (29, 24, 0x0F);
6098 NYI_assert (15, 12, 0x8);
6099 NYI_assert (10, 10, 0);
6101 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6106 /* 16 bit products. */
6111 index
= (H
<< 2) | (L
<< 1) | INSTR (20, 20);
6112 vm
= INSTR (19, 16);
6113 element2
= aarch64_get_vec_u16 (cpu
, vm
, index
);
6115 for (e
= 0; e
< (full
? 8 : 4); e
++)
6117 element1
= aarch64_get_vec_u16 (cpu
, vn
, e
);
6118 product
= element1
* element2
;
6119 aarch64_set_vec_u16 (cpu
, vd
, e
, product
);
6126 /* 32 bit products. */
6131 index
= (H
<< 1) | L
;
6132 vm
= INSTR (20, 16);
6133 element2
= aarch64_get_vec_u32 (cpu
, vm
, index
);
6135 for (e
= 0; e
< (full
? 4 : 2); e
++)
6137 element1
= aarch64_get_vec_u32 (cpu
, vn
, e
);
6138 product
= element1
* element2
;
6139 aarch64_set_vec_u32 (cpu
, vd
, e
, product
);
6150 do_FMLA_by_element (sim_cpu
*cpu
)
6153 instr[30] = half/full
6154 instr[29,23] = 00 1111 1
6164 unsigned full
= INSTR (30, 30);
6165 unsigned size
= INSTR (22, 22);
6166 unsigned L
= INSTR (21, 21);
6167 unsigned vm
= INSTR (20, 16);
6168 unsigned H
= INSTR (11, 11);
6169 unsigned vn
= INSTR (9, 5);
6170 unsigned vd
= INSTR (4, 0);
6173 NYI_assert (29, 23, 0x1F);
6174 NYI_assert (15, 12, 0x1);
6175 NYI_assert (10, 10, 0);
6177 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6180 double element1
, element2
;
6185 element2
= aarch64_get_vec_double (cpu
, vm
, H
);
6187 for (e
= 0; e
< 2; e
++)
6189 element1
= aarch64_get_vec_double (cpu
, vn
, e
);
6190 element1
*= element2
;
6191 element1
+= aarch64_get_vec_double (cpu
, vd
, e
);
6192 aarch64_set_vec_double (cpu
, vd
, e
, element1
);
6198 float element2
= aarch64_get_vec_float (cpu
, vm
, (H
<< 1) | L
);
6200 for (e
= 0; e
< (full
? 4 : 2); e
++)
6202 element1
= aarch64_get_vec_float (cpu
, vn
, e
);
6203 element1
*= element2
;
6204 element1
+= aarch64_get_vec_float (cpu
, vd
, e
);
6205 aarch64_set_vec_float (cpu
, vd
, e
, element1
);
6211 do_vec_op2 (sim_cpu
*cpu
)
6214 instr[30] = half/full
6215 instr[29,24] = 00 1111
6217 instr[22,16] = element size & index
6218 instr[15,10] = sub-opcode
6222 NYI_assert (29, 24, 0x0F);
6224 if (INSTR (23, 23) != 0)
6226 switch (INSTR (15, 10))
6230 do_FMLA_by_element (cpu
);
6235 do_vec_MUL_by_element (cpu
);
6244 switch (INSTR (15, 10))
6246 case 0x01: do_vec_SSHR_USHR (cpu
); return;
6247 case 0x15: do_vec_SHL (cpu
); return;
6249 case 0x22: do_vec_MUL_by_element (cpu
); return;
6250 case 0x29: do_vec_xtl (cpu
); return;
6257 do_vec_neg (sim_cpu
*cpu
)
6260 instr[30] = full(1)/half(0)
6261 instr[29,24] = 10 1110
6262 instr[23,22] = size: byte(00), half (01), word (10), long (11)
6263 instr[21,10] = 1000 0010 1110
6267 int full
= INSTR (30, 30);
6268 unsigned vs
= INSTR (9, 5);
6269 unsigned vd
= INSTR (4, 0);
6272 NYI_assert (29, 24, 0x2E);
6273 NYI_assert (21, 10, 0x82E);
6275 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6276 switch (INSTR (23, 22))
6279 for (i
= 0; i
< (full
? 16 : 8); i
++)
6280 aarch64_set_vec_s8 (cpu
, vd
, i
, - aarch64_get_vec_s8 (cpu
, vs
, i
));
6284 for (i
= 0; i
< (full
? 8 : 4); i
++)
6285 aarch64_set_vec_s16 (cpu
, vd
, i
, - aarch64_get_vec_s16 (cpu
, vs
, i
));
6289 for (i
= 0; i
< (full
? 4 : 2); i
++)
6290 aarch64_set_vec_s32 (cpu
, vd
, i
, - aarch64_get_vec_s32 (cpu
, vs
, i
));
6296 for (i
= 0; i
< 2; i
++)
6297 aarch64_set_vec_s64 (cpu
, vd
, i
, - aarch64_get_vec_s64 (cpu
, vs
, i
));
6303 do_vec_sqrt (sim_cpu
*cpu
)
6306 instr[30] = full(1)/half(0)
6307 instr[29,23] = 101 1101
6308 instr[22] = single(0)/double(1)
6309 instr[21,10] = 1000 0111 1110
6313 int full
= INSTR (30, 30);
6314 unsigned vs
= INSTR (9, 5);
6315 unsigned vd
= INSTR (4, 0);
6318 NYI_assert (29, 23, 0x5B);
6319 NYI_assert (21, 10, 0x87E);
6321 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6322 if (INSTR (22, 22) == 0)
6323 for (i
= 0; i
< (full
? 4 : 2); i
++)
6324 aarch64_set_vec_float (cpu
, vd
, i
,
6325 sqrtf (aarch64_get_vec_float (cpu
, vs
, i
)));
6327 for (i
= 0; i
< 2; i
++)
6328 aarch64_set_vec_double (cpu
, vd
, i
,
6329 sqrt (aarch64_get_vec_double (cpu
, vs
, i
)));
6333 do_vec_mls_indexed (sim_cpu
*cpu
)
6336 instr[30] = half(0)/full(1)
6337 instr[29,24] = 10 1111
6338 instr[23,22] = 16-bit(01)/32-bit(10)
6339 instr[21,20+11] = index (if 16-bit)
6340 instr[21+11] = index (if 32-bit)
6343 instr[11] = part of index
6348 int full
= INSTR (30, 30);
6349 unsigned vs
= INSTR (9, 5);
6350 unsigned vd
= INSTR (4, 0);
6351 unsigned vm
= INSTR (20, 16);
6354 NYI_assert (15, 12, 4);
6355 NYI_assert (10, 10, 0);
6357 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6358 switch (INSTR (23, 22))
6368 elem
= (INSTR (21, 20) << 1) | INSTR (11, 11);
6369 val
= aarch64_get_vec_u16 (cpu
, vm
, elem
);
6371 for (i
= 0; i
< (full
? 8 : 4); i
++)
6372 aarch64_set_vec_u32 (cpu
, vd
, i
,
6373 aarch64_get_vec_u32 (cpu
, vd
, i
) -
6374 (aarch64_get_vec_u32 (cpu
, vs
, i
) * val
));
6380 unsigned elem
= (INSTR (21, 21) << 1) | INSTR (11, 11);
6381 uint64_t val
= aarch64_get_vec_u32 (cpu
, vm
, elem
);
6383 for (i
= 0; i
< (full
? 4 : 2); i
++)
6384 aarch64_set_vec_u64 (cpu
, vd
, i
,
6385 aarch64_get_vec_u64 (cpu
, vd
, i
) -
6386 (aarch64_get_vec_u64 (cpu
, vs
, i
) * val
));
6398 do_vec_SUB (sim_cpu
*cpu
)
6401 instr [30] = half(0)/full(1)
6402 instr [29,24] = 10 1110
6403 instr [23,22] = size: byte(00, half(01), word (10), long (11)
6406 instr [15,10] = 10 0001
6408 instr [4, 0] = Vd. */
6410 unsigned full
= INSTR (30, 30);
6411 unsigned vm
= INSTR (20, 16);
6412 unsigned vn
= INSTR (9, 5);
6413 unsigned vd
= INSTR (4, 0);
6416 NYI_assert (29, 24, 0x2E);
6417 NYI_assert (21, 21, 1);
6418 NYI_assert (15, 10, 0x21);
6420 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6421 switch (INSTR (23, 22))
6424 for (i
= 0; i
< (full
? 16 : 8); i
++)
6425 aarch64_set_vec_s8 (cpu
, vd
, i
,
6426 aarch64_get_vec_s8 (cpu
, vn
, i
)
6427 - aarch64_get_vec_s8 (cpu
, vm
, i
));
6431 for (i
= 0; i
< (full
? 8 : 4); i
++)
6432 aarch64_set_vec_s16 (cpu
, vd
, i
,
6433 aarch64_get_vec_s16 (cpu
, vn
, i
)
6434 - aarch64_get_vec_s16 (cpu
, vm
, i
));
6438 for (i
= 0; i
< (full
? 4 : 2); i
++)
6439 aarch64_set_vec_s32 (cpu
, vd
, i
,
6440 aarch64_get_vec_s32 (cpu
, vn
, i
)
6441 - aarch64_get_vec_s32 (cpu
, vm
, i
));
6448 for (i
= 0; i
< 2; i
++)
6449 aarch64_set_vec_s64 (cpu
, vd
, i
,
6450 aarch64_get_vec_s64 (cpu
, vn
, i
)
6451 - aarch64_get_vec_s64 (cpu
, vm
, i
));
6457 do_vec_MLS (sim_cpu
*cpu
)
6460 instr [30] = half(0)/full(1)
6461 instr [29,24] = 10 1110
6462 instr [23,22] = size: byte(00, half(01), word (10)
6465 instr [15,10] = 10 0101
6467 instr [4, 0] = Vd. */
6469 unsigned full
= INSTR (30, 30);
6470 unsigned vm
= INSTR (20, 16);
6471 unsigned vn
= INSTR (9, 5);
6472 unsigned vd
= INSTR (4, 0);
6475 NYI_assert (29, 24, 0x2E);
6476 NYI_assert (21, 21, 1);
6477 NYI_assert (15, 10, 0x25);
6479 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6480 switch (INSTR (23, 22))
6483 for (i
= 0; i
< (full
? 16 : 8); i
++)
6484 aarch64_set_vec_u8 (cpu
, vd
, i
,
6485 aarch64_get_vec_u8 (cpu
, vd
, i
)
6486 - (aarch64_get_vec_u8 (cpu
, vn
, i
)
6487 * aarch64_get_vec_u8 (cpu
, vm
, i
)));
6491 for (i
= 0; i
< (full
? 8 : 4); i
++)
6492 aarch64_set_vec_u16 (cpu
, vd
, i
,
6493 aarch64_get_vec_u16 (cpu
, vd
, i
)
6494 - (aarch64_get_vec_u16 (cpu
, vn
, i
)
6495 * aarch64_get_vec_u16 (cpu
, vm
, i
)));
6499 for (i
= 0; i
< (full
? 4 : 2); i
++)
6500 aarch64_set_vec_u32 (cpu
, vd
, i
,
6501 aarch64_get_vec_u32 (cpu
, vd
, i
)
6502 - (aarch64_get_vec_u32 (cpu
, vn
, i
)
6503 * aarch64_get_vec_u32 (cpu
, vm
, i
)));
6512 do_vec_FDIV (sim_cpu
*cpu
)
6515 instr [30] = half(0)/full(1)
6516 instr [29,23] = 10 1110 0
6517 instr [22] = float()/double(1)
6520 instr [15,10] = 1111 11
6522 instr [4, 0] = Vd. */
6524 unsigned full
= INSTR (30, 30);
6525 unsigned vm
= INSTR (20, 16);
6526 unsigned vn
= INSTR (9, 5);
6527 unsigned vd
= INSTR (4, 0);
6530 NYI_assert (29, 23, 0x5C);
6531 NYI_assert (21, 21, 1);
6532 NYI_assert (15, 10, 0x3F);
6534 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6540 for (i
= 0; i
< 2; i
++)
6541 aarch64_set_vec_double (cpu
, vd
, i
,
6542 aarch64_get_vec_double (cpu
, vn
, i
)
6543 / aarch64_get_vec_double (cpu
, vm
, i
));
6546 for (i
= 0; i
< (full
? 4 : 2); i
++)
6547 aarch64_set_vec_float (cpu
, vd
, i
,
6548 aarch64_get_vec_float (cpu
, vn
, i
)
6549 / aarch64_get_vec_float (cpu
, vm
, i
));
6553 do_vec_FMUL (sim_cpu
*cpu
)
6556 instr [30] = half(0)/full(1)
6557 instr [29,23] = 10 1110 0
6558 instr [22] = float(0)/double(1)
6561 instr [15,10] = 1101 11
6563 instr [4, 0] = Vd. */
6565 unsigned full
= INSTR (30, 30);
6566 unsigned vm
= INSTR (20, 16);
6567 unsigned vn
= INSTR (9, 5);
6568 unsigned vd
= INSTR (4, 0);
6571 NYI_assert (29, 23, 0x5C);
6572 NYI_assert (21, 21, 1);
6573 NYI_assert (15, 10, 0x37);
6575 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6581 for (i
= 0; i
< 2; i
++)
6582 aarch64_set_vec_double (cpu
, vd
, i
,
6583 aarch64_get_vec_double (cpu
, vn
, i
)
6584 * aarch64_get_vec_double (cpu
, vm
, i
));
6587 for (i
= 0; i
< (full
? 4 : 2); i
++)
6588 aarch64_set_vec_float (cpu
, vd
, i
,
6589 aarch64_get_vec_float (cpu
, vn
, i
)
6590 * aarch64_get_vec_float (cpu
, vm
, i
));
6594 do_vec_FADDP (sim_cpu
*cpu
)
6597 instr [30] = half(0)/full(1)
6598 instr [29,23] = 10 1110 0
6599 instr [22] = float(0)/double(1)
6602 instr [15,10] = 1101 01
6604 instr [4, 0] = Vd. */
6606 unsigned full
= INSTR (30, 30);
6607 unsigned vm
= INSTR (20, 16);
6608 unsigned vn
= INSTR (9, 5);
6609 unsigned vd
= INSTR (4, 0);
6611 NYI_assert (29, 23, 0x5C);
6612 NYI_assert (21, 21, 1);
6613 NYI_assert (15, 10, 0x35);
6615 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6618 /* Extract values before adding them incase vd == vn/vm. */
6619 double tmp1
= aarch64_get_vec_double (cpu
, vn
, 0);
6620 double tmp2
= aarch64_get_vec_double (cpu
, vn
, 1);
6621 double tmp3
= aarch64_get_vec_double (cpu
, vm
, 0);
6622 double tmp4
= aarch64_get_vec_double (cpu
, vm
, 1);
6627 aarch64_set_vec_double (cpu
, vd
, 0, tmp1
+ tmp2
);
6628 aarch64_set_vec_double (cpu
, vd
, 1, tmp3
+ tmp4
);
6632 /* Extract values before adding them incase vd == vn/vm. */
6633 float tmp1
= aarch64_get_vec_float (cpu
, vn
, 0);
6634 float tmp2
= aarch64_get_vec_float (cpu
, vn
, 1);
6635 float tmp5
= aarch64_get_vec_float (cpu
, vm
, 0);
6636 float tmp6
= aarch64_get_vec_float (cpu
, vm
, 1);
6640 float tmp3
= aarch64_get_vec_float (cpu
, vn
, 2);
6641 float tmp4
= aarch64_get_vec_float (cpu
, vn
, 3);
6642 float tmp7
= aarch64_get_vec_float (cpu
, vm
, 2);
6643 float tmp8
= aarch64_get_vec_float (cpu
, vm
, 3);
6645 aarch64_set_vec_float (cpu
, vd
, 0, tmp1
+ tmp2
);
6646 aarch64_set_vec_float (cpu
, vd
, 1, tmp3
+ tmp4
);
6647 aarch64_set_vec_float (cpu
, vd
, 2, tmp5
+ tmp6
);
6648 aarch64_set_vec_float (cpu
, vd
, 3, tmp7
+ tmp8
);
6652 aarch64_set_vec_float (cpu
, vd
, 0, tmp1
+ tmp2
);
6653 aarch64_set_vec_float (cpu
, vd
, 1, tmp5
+ tmp6
);
6659 do_vec_FSQRT (sim_cpu
*cpu
)
6662 instr[30] = half(0)/full(1)
6663 instr[29,23] = 10 1110 1
6664 instr[22] = single(0)/double(1)
6665 instr[21,10] = 10 0001 1111 10
6667 instr[4,0] = Vdest. */
6669 unsigned vn
= INSTR (9, 5);
6670 unsigned vd
= INSTR (4, 0);
6671 unsigned full
= INSTR (30, 30);
6674 NYI_assert (29, 23, 0x5D);
6675 NYI_assert (21, 10, 0x87E);
6677 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6683 for (i
= 0; i
< 2; i
++)
6684 aarch64_set_vec_double (cpu
, vd
, i
,
6685 sqrt (aarch64_get_vec_double (cpu
, vn
, i
)));
6689 for (i
= 0; i
< (full
? 4 : 2); i
++)
6690 aarch64_set_vec_float (cpu
, vd
, i
,
6691 sqrtf (aarch64_get_vec_float (cpu
, vn
, i
)));
6696 do_vec_FNEG (sim_cpu
*cpu
)
6699 instr[30] = half (0)/full (1)
6700 instr[29,23] = 10 1110 1
6701 instr[22] = single (0)/double (1)
6702 instr[21,10] = 10 0000 1111 10
6704 instr[4,0] = Vdest. */
6706 unsigned vn
= INSTR (9, 5);
6707 unsigned vd
= INSTR (4, 0);
6708 unsigned full
= INSTR (30, 30);
6711 NYI_assert (29, 23, 0x5D);
6712 NYI_assert (21, 10, 0x83E);
6714 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6720 for (i
= 0; i
< 2; i
++)
6721 aarch64_set_vec_double (cpu
, vd
, i
,
6722 - aarch64_get_vec_double (cpu
, vn
, i
));
6726 for (i
= 0; i
< (full
? 4 : 2); i
++)
6727 aarch64_set_vec_float (cpu
, vd
, i
,
6728 - aarch64_get_vec_float (cpu
, vn
, i
));
6733 do_vec_NOT (sim_cpu
*cpu
)
6736 instr[30] = half (0)/full (1)
6737 instr[29,10] = 10 1110 0010 0000 0101 10
6741 unsigned vn
= INSTR (9, 5);
6742 unsigned vd
= INSTR (4, 0);
6744 int full
= INSTR (30, 30);
6746 NYI_assert (29, 10, 0xB8816);
6748 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6749 for (i
= 0; i
< (full
? 16 : 8); i
++)
6750 aarch64_set_vec_u8 (cpu
, vd
, i
, ~ aarch64_get_vec_u8 (cpu
, vn
, i
));
6754 clz (uint64_t val
, unsigned size
)
6759 mask
<<= (size
- 1);
6774 do_vec_CLZ (sim_cpu
*cpu
)
6777 instr[30] = half (0)/full (1)
6778 instr[29,24] = 10 1110
6780 instr[21,10] = 10 0000 0100 10
6784 unsigned vn
= INSTR (9, 5);
6785 unsigned vd
= INSTR (4, 0);
6787 int full
= INSTR (30,30);
6789 NYI_assert (29, 24, 0x2E);
6790 NYI_assert (21, 10, 0x812);
6792 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6793 switch (INSTR (23, 22))
6796 for (i
= 0; i
< (full
? 16 : 8); i
++)
6797 aarch64_set_vec_u8 (cpu
, vd
, i
, clz (aarch64_get_vec_u8 (cpu
, vn
, i
), 8));
6800 for (i
= 0; i
< (full
? 8 : 4); i
++)
6801 aarch64_set_vec_u16 (cpu
, vd
, i
, clz (aarch64_get_vec_u16 (cpu
, vn
, i
), 16));
6804 for (i
= 0; i
< (full
? 4 : 2); i
++)
6805 aarch64_set_vec_u32 (cpu
, vd
, i
, clz (aarch64_get_vec_u32 (cpu
, vn
, i
), 32));
6810 aarch64_set_vec_u64 (cpu
, vd
, 0, clz (aarch64_get_vec_u64 (cpu
, vn
, 0), 64));
6811 aarch64_set_vec_u64 (cpu
, vd
, 1, clz (aarch64_get_vec_u64 (cpu
, vn
, 1), 64));
6817 do_vec_MOV_element (sim_cpu
*cpu
)
6819 /* instr[31,21] = 0110 1110 000
6820 instr[20,16] = size & dest index
6822 instr[14,11] = source index
6827 unsigned vs
= INSTR (9, 5);
6828 unsigned vd
= INSTR (4, 0);
6832 NYI_assert (31, 21, 0x370);
6833 NYI_assert (15, 15, 0);
6834 NYI_assert (10, 10, 1);
6836 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6840 src_index
= INSTR (14, 11);
6841 dst_index
= INSTR (20, 17);
6842 aarch64_set_vec_u8 (cpu
, vd
, dst_index
,
6843 aarch64_get_vec_u8 (cpu
, vs
, src_index
));
6845 else if (INSTR (17, 17))
6848 NYI_assert (11, 11, 0);
6849 src_index
= INSTR (14, 12);
6850 dst_index
= INSTR (20, 18);
6851 aarch64_set_vec_u16 (cpu
, vd
, dst_index
,
6852 aarch64_get_vec_u16 (cpu
, vs
, src_index
));
6854 else if (INSTR (18, 18))
6857 NYI_assert (12, 11, 0);
6858 src_index
= INSTR (14, 13);
6859 dst_index
= INSTR (20, 19);
6860 aarch64_set_vec_u32 (cpu
, vd
, dst_index
,
6861 aarch64_get_vec_u32 (cpu
, vs
, src_index
));
6865 NYI_assert (19, 19, 1);
6866 NYI_assert (13, 11, 0);
6867 src_index
= INSTR (14, 14);
6868 dst_index
= INSTR (20, 20);
6869 aarch64_set_vec_u64 (cpu
, vd
, dst_index
,
6870 aarch64_get_vec_u64 (cpu
, vs
, src_index
));
6875 do_vec_REV32 (sim_cpu
*cpu
)
6878 instr[30] = full/half
6879 instr[29,24] = 10 1110
6881 instr[21,10] = 10 0000 0000 10
6885 unsigned rn
= INSTR (9, 5);
6886 unsigned rd
= INSTR (4, 0);
6887 unsigned size
= INSTR (23, 22);
6888 unsigned full
= INSTR (30, 30);
6892 NYI_assert (29, 24, 0x2E);
6893 NYI_assert (21, 10, 0x802);
6895 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6899 for (i
= 0; i
< (full
? 16 : 8); i
++)
6900 val
.b
[i
^ 0x3] = aarch64_get_vec_u8 (cpu
, rn
, i
);
6904 for (i
= 0; i
< (full
? 8 : 4); i
++)
6905 val
.h
[i
^ 0x1] = aarch64_get_vec_u16 (cpu
, rn
, i
);
6912 aarch64_set_vec_u64 (cpu
, rd
, 0, val
.v
[0]);
6914 aarch64_set_vec_u64 (cpu
, rd
, 1, val
.v
[1]);
6918 do_vec_EXT (sim_cpu
*cpu
)
6921 instr[30] = full/half
6922 instr[29,21] = 10 1110 000
6925 instr[14,11] = source index
6930 unsigned vm
= INSTR (20, 16);
6931 unsigned vn
= INSTR (9, 5);
6932 unsigned vd
= INSTR (4, 0);
6933 unsigned src_index
= INSTR (14, 11);
6934 unsigned full
= INSTR (30, 30);
6939 NYI_assert (31, 21, 0x370);
6940 NYI_assert (15, 15, 0);
6941 NYI_assert (10, 10, 0);
6943 if (!full
&& (src_index
& 0x8))
6948 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
6949 for (i
= src_index
; i
< (full
? 16 : 8); i
++)
6950 val
.b
[j
++] = aarch64_get_vec_u8 (cpu
, vn
, i
);
6951 for (i
= 0; i
< src_index
; i
++)
6952 val
.b
[j
++] = aarch64_get_vec_u8 (cpu
, vm
, i
);
6954 aarch64_set_vec_u64 (cpu
, vd
, 0, val
.v
[0]);
6956 aarch64_set_vec_u64 (cpu
, vd
, 1, val
.v
[1]);
6960 dexAdvSIMD0 (sim_cpu
*cpu
)
6962 /* instr [28,25] = 0 111. */
6963 if ( INSTR (15, 10) == 0x07
6967 if (INSTR (31, 21) == 0x075
6968 || INSTR (31, 21) == 0x275)
6970 do_vec_MOV_whole_vector (cpu
);
6975 if (INSTR (29, 19) == 0x1E0)
6977 do_vec_MOV_immediate (cpu
);
6981 if (INSTR (29, 19) == 0x5E0)
6987 if (INSTR (29, 19) == 0x1C0
6988 || INSTR (29, 19) == 0x1C1)
6990 if (INSTR (15, 10) == 0x03)
6992 do_vec_DUP_scalar_into_vector (cpu
);
6997 switch (INSTR (29, 24))
6999 case 0x0E: do_vec_op1 (cpu
); return;
7000 case 0x0F: do_vec_op2 (cpu
); return;
7003 if (INSTR (21, 21) == 1)
7005 switch (INSTR (15, 10))
7012 switch (INSTR (23, 22))
7014 case 0: do_vec_EOR (cpu
); return;
7015 case 1: do_vec_BSL (cpu
); return;
7017 case 3: do_vec_bit (cpu
); return;
7021 case 0x08: do_vec_sub_long (cpu
); return;
7022 case 0x11: do_vec_USHL (cpu
); return;
7023 case 0x12: do_vec_CLZ (cpu
); return;
7024 case 0x16: do_vec_NOT (cpu
); return;
7025 case 0x19: do_vec_max (cpu
); return;
7026 case 0x1B: do_vec_min (cpu
); return;
7027 case 0x21: do_vec_SUB (cpu
); return;
7028 case 0x25: do_vec_MLS (cpu
); return;
7029 case 0x31: do_vec_FminmaxNMP (cpu
); return;
7030 case 0x35: do_vec_FADDP (cpu
); return;
7031 case 0x37: do_vec_FMUL (cpu
); return;
7032 case 0x3F: do_vec_FDIV (cpu
); return;
7035 switch (INSTR (20, 16))
7037 case 0x00: do_vec_FNEG (cpu
); return;
7038 case 0x01: do_vec_FSQRT (cpu
); return;
7052 do_vec_compare (cpu
); return;
7059 if (INSTR (31, 21) == 0x370)
7062 do_vec_MOV_element (cpu
);
7068 switch (INSTR (21, 10))
7070 case 0x82E: do_vec_neg (cpu
); return;
7071 case 0x87E: do_vec_sqrt (cpu
); return;
7073 if (INSTR (15, 10) == 0x30)
7083 switch (INSTR (15, 10))
7085 case 0x01: do_vec_SSHR_USHR (cpu
); return;
7087 case 0x12: do_vec_mls_indexed (cpu
); return;
7088 case 0x29: do_vec_xtl (cpu
); return;
7102 /* Float multiply add. */
7104 fmadds (sim_cpu
*cpu
)
7106 unsigned sa
= INSTR (14, 10);
7107 unsigned sm
= INSTR (20, 16);
7108 unsigned sn
= INSTR ( 9, 5);
7109 unsigned sd
= INSTR ( 4, 0);
7111 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7112 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sa
)
7113 + aarch64_get_FP_float (cpu
, sn
)
7114 * aarch64_get_FP_float (cpu
, sm
));
7117 /* Double multiply add. */
7119 fmaddd (sim_cpu
*cpu
)
7121 unsigned sa
= INSTR (14, 10);
7122 unsigned sm
= INSTR (20, 16);
7123 unsigned sn
= INSTR ( 9, 5);
7124 unsigned sd
= INSTR ( 4, 0);
7126 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7127 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sa
)
7128 + aarch64_get_FP_double (cpu
, sn
)
7129 * aarch64_get_FP_double (cpu
, sm
));
7132 /* Float multiply subtract. */
7134 fmsubs (sim_cpu
*cpu
)
7136 unsigned sa
= INSTR (14, 10);
7137 unsigned sm
= INSTR (20, 16);
7138 unsigned sn
= INSTR ( 9, 5);
7139 unsigned sd
= INSTR ( 4, 0);
7141 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7142 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sa
)
7143 - aarch64_get_FP_float (cpu
, sn
)
7144 * aarch64_get_FP_float (cpu
, sm
));
7147 /* Double multiply subtract. */
7149 fmsubd (sim_cpu
*cpu
)
7151 unsigned sa
= INSTR (14, 10);
7152 unsigned sm
= INSTR (20, 16);
7153 unsigned sn
= INSTR ( 9, 5);
7154 unsigned sd
= INSTR ( 4, 0);
7156 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7157 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sa
)
7158 - aarch64_get_FP_double (cpu
, sn
)
7159 * aarch64_get_FP_double (cpu
, sm
));
7162 /* Float negative multiply add. */
7164 fnmadds (sim_cpu
*cpu
)
7166 unsigned sa
= INSTR (14, 10);
7167 unsigned sm
= INSTR (20, 16);
7168 unsigned sn
= INSTR ( 9, 5);
7169 unsigned sd
= INSTR ( 4, 0);
7171 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7172 aarch64_set_FP_float (cpu
, sd
, - aarch64_get_FP_float (cpu
, sa
)
7173 + (- aarch64_get_FP_float (cpu
, sn
))
7174 * aarch64_get_FP_float (cpu
, sm
));
7177 /* Double negative multiply add. */
7179 fnmaddd (sim_cpu
*cpu
)
7181 unsigned sa
= INSTR (14, 10);
7182 unsigned sm
= INSTR (20, 16);
7183 unsigned sn
= INSTR ( 9, 5);
7184 unsigned sd
= INSTR ( 4, 0);
7186 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7187 aarch64_set_FP_double (cpu
, sd
, - aarch64_get_FP_double (cpu
, sa
)
7188 + (- aarch64_get_FP_double (cpu
, sn
))
7189 * aarch64_get_FP_double (cpu
, sm
));
7192 /* Float negative multiply subtract. */
7194 fnmsubs (sim_cpu
*cpu
)
7196 unsigned sa
= INSTR (14, 10);
7197 unsigned sm
= INSTR (20, 16);
7198 unsigned sn
= INSTR ( 9, 5);
7199 unsigned sd
= INSTR ( 4, 0);
7201 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7202 aarch64_set_FP_float (cpu
, sd
, - aarch64_get_FP_float (cpu
, sa
)
7203 + aarch64_get_FP_float (cpu
, sn
)
7204 * aarch64_get_FP_float (cpu
, sm
));
7207 /* Double negative multiply subtract. */
7209 fnmsubd (sim_cpu
*cpu
)
7211 unsigned sa
= INSTR (14, 10);
7212 unsigned sm
= INSTR (20, 16);
7213 unsigned sn
= INSTR ( 9, 5);
7214 unsigned sd
= INSTR ( 4, 0);
7216 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7217 aarch64_set_FP_double (cpu
, sd
, - aarch64_get_FP_double (cpu
, sa
)
7218 + aarch64_get_FP_double (cpu
, sn
)
7219 * aarch64_get_FP_double (cpu
, sm
));
7223 dexSimpleFPDataProc3Source (sim_cpu
*cpu
)
7225 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
7227 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
7230 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
7231 instr[21] ==> o1 : 0 ==> unnegated, 1 ==> negated
7232 instr[15] ==> o2 : 0 ==> ADD, 1 ==> SUB */
7234 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
7235 /* dispatch on combined type:o1:o2. */
7236 uint32_t dispatch
= (INSTR (23, 21) << 1) | INSTR (15, 15);
7243 case 0: fmadds (cpu
); return;
7244 case 1: fmsubs (cpu
); return;
7245 case 2: fnmadds (cpu
); return;
7246 case 3: fnmsubs (cpu
); return;
7247 case 4: fmaddd (cpu
); return;
7248 case 5: fmsubd (cpu
); return;
7249 case 6: fnmaddd (cpu
); return;
7250 case 7: fnmsubd (cpu
); return;
7252 /* type > 1 is currently unallocated. */
7258 dexSimpleFPFixedConvert (sim_cpu
*cpu
)
7264 dexSimpleFPCondCompare (sim_cpu
*cpu
)
7266 /* instr [31,23] = 0001 1110 0
7270 instr [15,12] = condition
7274 instr [3,0] = nzcv */
7276 unsigned rm
= INSTR (20, 16);
7277 unsigned rn
= INSTR (9, 5);
7279 NYI_assert (31, 23, 0x3C);
7280 NYI_assert (11, 10, 0x1);
7281 NYI_assert (4, 4, 0);
7283 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7284 if (! testConditionCode (cpu
, INSTR (15, 12)))
7286 aarch64_set_CPSR (cpu
, INSTR (3, 0));
7292 /* Double precision. */
7293 double val1
= aarch64_get_vec_double (cpu
, rn
, 0);
7294 double val2
= aarch64_get_vec_double (cpu
, rm
, 0);
7296 /* FIXME: Check for NaNs. */
7298 aarch64_set_CPSR (cpu
, (Z
| C
));
7299 else if (val1
< val2
)
7300 aarch64_set_CPSR (cpu
, N
);
7301 else /* val1 > val2 */
7302 aarch64_set_CPSR (cpu
, C
);
7306 /* Single precision. */
7307 float val1
= aarch64_get_vec_float (cpu
, rn
, 0);
7308 float val2
= aarch64_get_vec_float (cpu
, rm
, 0);
7310 /* FIXME: Check for NaNs. */
7312 aarch64_set_CPSR (cpu
, (Z
| C
));
7313 else if (val1
< val2
)
7314 aarch64_set_CPSR (cpu
, N
);
7315 else /* val1 > val2 */
7316 aarch64_set_CPSR (cpu
, C
);
7324 fadds (sim_cpu
*cpu
)
7326 unsigned sm
= INSTR (20, 16);
7327 unsigned sn
= INSTR ( 9, 5);
7328 unsigned sd
= INSTR ( 4, 0);
7330 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7331 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
7332 + aarch64_get_FP_float (cpu
, sm
));
7337 faddd (sim_cpu
*cpu
)
7339 unsigned sm
= INSTR (20, 16);
7340 unsigned sn
= INSTR ( 9, 5);
7341 unsigned sd
= INSTR ( 4, 0);
7343 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7344 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
7345 + aarch64_get_FP_double (cpu
, sm
));
7350 fdivs (sim_cpu
*cpu
)
7352 unsigned sm
= INSTR (20, 16);
7353 unsigned sn
= INSTR ( 9, 5);
7354 unsigned sd
= INSTR ( 4, 0);
7356 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7357 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
7358 / aarch64_get_FP_float (cpu
, sm
));
7361 /* Double divide. */
7363 fdivd (sim_cpu
*cpu
)
7365 unsigned sm
= INSTR (20, 16);
7366 unsigned sn
= INSTR ( 9, 5);
7367 unsigned sd
= INSTR ( 4, 0);
7369 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7370 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
7371 / aarch64_get_FP_double (cpu
, sm
));
7374 /* Float multiply. */
7376 fmuls (sim_cpu
*cpu
)
7378 unsigned sm
= INSTR (20, 16);
7379 unsigned sn
= INSTR ( 9, 5);
7380 unsigned sd
= INSTR ( 4, 0);
7382 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7383 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
7384 * aarch64_get_FP_float (cpu
, sm
));
7387 /* Double multiply. */
7389 fmuld (sim_cpu
*cpu
)
7391 unsigned sm
= INSTR (20, 16);
7392 unsigned sn
= INSTR ( 9, 5);
7393 unsigned sd
= INSTR ( 4, 0);
7395 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7396 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
7397 * aarch64_get_FP_double (cpu
, sm
));
7400 /* Float negate and multiply. */
7402 fnmuls (sim_cpu
*cpu
)
7404 unsigned sm
= INSTR (20, 16);
7405 unsigned sn
= INSTR ( 9, 5);
7406 unsigned sd
= INSTR ( 4, 0);
7408 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7409 aarch64_set_FP_float (cpu
, sd
, - (aarch64_get_FP_float (cpu
, sn
)
7410 * aarch64_get_FP_float (cpu
, sm
)));
7413 /* Double negate and multiply. */
7415 fnmuld (sim_cpu
*cpu
)
7417 unsigned sm
= INSTR (20, 16);
7418 unsigned sn
= INSTR ( 9, 5);
7419 unsigned sd
= INSTR ( 4, 0);
7421 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7422 aarch64_set_FP_double (cpu
, sd
, - (aarch64_get_FP_double (cpu
, sn
)
7423 * aarch64_get_FP_double (cpu
, sm
)));
7426 /* Float subtract. */
7428 fsubs (sim_cpu
*cpu
)
7430 unsigned sm
= INSTR (20, 16);
7431 unsigned sn
= INSTR ( 9, 5);
7432 unsigned sd
= INSTR ( 4, 0);
7434 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7435 aarch64_set_FP_float (cpu
, sd
, aarch64_get_FP_float (cpu
, sn
)
7436 - aarch64_get_FP_float (cpu
, sm
));
7439 /* Double subtract. */
7441 fsubd (sim_cpu
*cpu
)
7443 unsigned sm
= INSTR (20, 16);
7444 unsigned sn
= INSTR ( 9, 5);
7445 unsigned sd
= INSTR ( 4, 0);
7447 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7448 aarch64_set_FP_double (cpu
, sd
, aarch64_get_FP_double (cpu
, sn
)
7449 - aarch64_get_FP_double (cpu
, sm
));
7453 do_FMINNM (sim_cpu
*cpu
)
7455 /* instr[31,23] = 0 0011 1100
7456 instr[22] = float(0)/double(1)
7459 instr[15,10] = 01 1110
7463 unsigned sm
= INSTR (20, 16);
7464 unsigned sn
= INSTR ( 9, 5);
7465 unsigned sd
= INSTR ( 4, 0);
7467 NYI_assert (31, 23, 0x03C);
7468 NYI_assert (15, 10, 0x1E);
7470 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7472 aarch64_set_FP_double (cpu
, sd
,
7473 dminnm (aarch64_get_FP_double (cpu
, sn
),
7474 aarch64_get_FP_double (cpu
, sm
)));
7476 aarch64_set_FP_float (cpu
, sd
,
7477 fminnm (aarch64_get_FP_float (cpu
, sn
),
7478 aarch64_get_FP_float (cpu
, sm
)));
7482 do_FMAXNM (sim_cpu
*cpu
)
7484 /* instr[31,23] = 0 0011 1100
7485 instr[22] = float(0)/double(1)
7488 instr[15,10] = 01 1010
7492 unsigned sm
= INSTR (20, 16);
7493 unsigned sn
= INSTR ( 9, 5);
7494 unsigned sd
= INSTR ( 4, 0);
7496 NYI_assert (31, 23, 0x03C);
7497 NYI_assert (15, 10, 0x1A);
7499 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7501 aarch64_set_FP_double (cpu
, sd
,
7502 dmaxnm (aarch64_get_FP_double (cpu
, sn
),
7503 aarch64_get_FP_double (cpu
, sm
)));
7505 aarch64_set_FP_float (cpu
, sd
,
7506 fmaxnm (aarch64_get_FP_float (cpu
, sn
),
7507 aarch64_get_FP_float (cpu
, sm
)));
7511 dexSimpleFPDataProc2Source (sim_cpu
*cpu
)
7513 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
7515 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
7518 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
7521 instr[15,12] ==> opcode : 0000 ==> FMUL, 0001 ==> FDIV
7522 0010 ==> FADD, 0011 ==> FSUB,
7523 0100 ==> FMAX, 0101 ==> FMIN
7524 0110 ==> FMAXNM, 0111 ==> FMINNM
7525 1000 ==> FNMUL, ow ==> UNALLOC
7530 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
7531 uint32_t type
= INSTR (23, 22);
7532 /* Dispatch on opcode. */
7533 uint32_t dispatch
= INSTR (15, 12);
7544 case 0: fmuld (cpu
); return;
7545 case 1: fdivd (cpu
); return;
7546 case 2: faddd (cpu
); return;
7547 case 3: fsubd (cpu
); return;
7548 case 6: do_FMAXNM (cpu
); return;
7549 case 7: do_FMINNM (cpu
); return;
7550 case 8: fnmuld (cpu
); return;
7552 /* Have not yet implemented fmax and fmin. */
7560 else /* type == 0 => floats. */
7563 case 0: fmuls (cpu
); return;
7564 case 1: fdivs (cpu
); return;
7565 case 2: fadds (cpu
); return;
7566 case 3: fsubs (cpu
); return;
7567 case 6: do_FMAXNM (cpu
); return;
7568 case 7: do_FMINNM (cpu
); return;
7569 case 8: fnmuls (cpu
); return;
7581 dexSimpleFPCondSelect (sim_cpu
*cpu
)
7584 instr[31,23] = 0 0011 1100
7585 instr[22] = 0=>single 1=>double
7592 unsigned sm
= INSTR (20, 16);
7593 unsigned sn
= INSTR ( 9, 5);
7594 unsigned sd
= INSTR ( 4, 0);
7595 uint32_t set
= testConditionCode (cpu
, INSTR (15, 12));
7597 NYI_assert (31, 23, 0x03C);
7598 NYI_assert (11, 10, 0x3);
7600 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7602 aarch64_set_FP_double (cpu
, sd
, (set
? aarch64_get_FP_double (cpu
, sn
)
7603 : aarch64_get_FP_double (cpu
, sm
)));
7605 aarch64_set_FP_float (cpu
, sd
, (set
? aarch64_get_FP_float (cpu
, sn
)
7606 : aarch64_get_FP_float (cpu
, sm
)));
7609 /* Store 32 bit unscaled signed 9 bit. */
7611 fsturs (sim_cpu
*cpu
, int32_t offset
)
7613 unsigned int rn
= INSTR (9, 5);
7614 unsigned int st
= INSTR (4, 0);
7616 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7617 aarch64_set_mem_u32 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, 1) + offset
,
7618 aarch64_get_vec_u32 (cpu
, st
, 0));
7621 /* Store 64 bit unscaled signed 9 bit. */
7623 fsturd (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_u64 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, 1) + offset
,
7630 aarch64_get_vec_u64 (cpu
, st
, 0));
7633 /* Store 128 bit unscaled signed 9 bit. */
7635 fsturq (sim_cpu
*cpu
, int32_t offset
)
7637 unsigned int rn
= INSTR (9, 5);
7638 unsigned int st
= INSTR (4, 0);
7641 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7642 aarch64_get_FP_long_double (cpu
, st
, & a
);
7643 aarch64_set_mem_long_double (cpu
,
7644 aarch64_get_reg_u64 (cpu
, rn
, 1)
7648 /* TODO FP move register. */
7650 /* 32 bit fp to fp move register. */
7652 ffmovs (sim_cpu
*cpu
)
7654 unsigned int rn
= INSTR (9, 5);
7655 unsigned int st
= INSTR (4, 0);
7657 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7658 aarch64_set_FP_float (cpu
, st
, aarch64_get_FP_float (cpu
, rn
));
7661 /* 64 bit fp to fp move register. */
7663 ffmovd (sim_cpu
*cpu
)
7665 unsigned int rn
= INSTR (9, 5);
7666 unsigned int st
= INSTR (4, 0);
7668 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7669 aarch64_set_FP_double (cpu
, st
, aarch64_get_FP_double (cpu
, rn
));
7672 /* 32 bit GReg to Vec move register. */
7674 fgmovs (sim_cpu
*cpu
)
7676 unsigned int rn
= INSTR (9, 5);
7677 unsigned int st
= INSTR (4, 0);
7679 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7680 aarch64_set_vec_u32 (cpu
, st
, 0, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
));
7683 /* 64 bit g to fp move register. */
7685 fgmovd (sim_cpu
*cpu
)
7687 unsigned int rn
= INSTR (9, 5);
7688 unsigned int st
= INSTR (4, 0);
7690 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7691 aarch64_set_vec_u64 (cpu
, st
, 0, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
7694 /* 32 bit fp to g move register. */
7696 gfmovs (sim_cpu
*cpu
)
7698 unsigned int rn
= INSTR (9, 5);
7699 unsigned int st
= INSTR (4, 0);
7701 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7702 aarch64_set_reg_u64 (cpu
, st
, NO_SP
, aarch64_get_vec_u32 (cpu
, rn
, 0));
7705 /* 64 bit fp to g move register. */
7707 gfmovd (sim_cpu
*cpu
)
7709 unsigned int rn
= INSTR (9, 5);
7710 unsigned int st
= INSTR (4, 0);
7712 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7713 aarch64_set_reg_u64 (cpu
, st
, NO_SP
, aarch64_get_vec_u64 (cpu
, rn
, 0));
7716 /* FP move immediate
7718 These install an immediate 8 bit value in the target register
7719 where the 8 bits comprise 1 sign bit, 4 bits of fraction and a 3
7723 fmovs (sim_cpu
*cpu
)
7725 unsigned int sd
= INSTR (4, 0);
7726 uint32_t imm
= INSTR (20, 13);
7727 float f
= fp_immediate_for_encoding_32 (imm
);
7729 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7730 aarch64_set_FP_float (cpu
, sd
, f
);
7734 fmovd (sim_cpu
*cpu
)
7736 unsigned int sd
= INSTR (4, 0);
7737 uint32_t imm
= INSTR (20, 13);
7738 double d
= fp_immediate_for_encoding_64 (imm
);
7740 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7741 aarch64_set_FP_double (cpu
, sd
, d
);
7745 dexSimpleFPImmediate (sim_cpu
*cpu
)
7747 /* instr[31,23] == 00111100
7748 instr[22] == type : single(0)/double(1)
7750 instr[20,13] == imm8
7752 instr[9,5] == imm5 : 00000 ==> PK, ow ==> UNALLOC
7754 uint32_t imm5
= INSTR (9, 5);
7756 NYI_assert (31, 23, 0x3C);
7767 /* TODO specific decode and execute for group Load Store. */
7769 /* TODO FP load/store single register (unscaled offset). */
7771 /* TODO load 8 bit unscaled signed 9 bit. */
7772 /* TODO load 16 bit unscaled signed 9 bit. */
7774 /* Load 32 bit unscaled signed 9 bit. */
7776 fldurs (sim_cpu
*cpu
, int32_t offset
)
7778 unsigned int rn
= INSTR (9, 5);
7779 unsigned int st
= INSTR (4, 0);
7781 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7782 aarch64_set_vec_u32 (cpu
, st
, 0, aarch64_get_mem_u32
7783 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
));
7786 /* Load 64 bit unscaled signed 9 bit. */
7788 fldurd (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_u64 (cpu
, st
, 0, aarch64_get_mem_u64
7795 (cpu
, aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
));
7798 /* Load 128 bit unscaled signed 9 bit. */
7800 fldurq (sim_cpu
*cpu
, int32_t offset
)
7802 unsigned int rn
= INSTR (9, 5);
7803 unsigned int st
= INSTR (4, 0);
7805 uint64_t addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
;
7807 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7808 aarch64_get_mem_long_double (cpu
, addr
, & a
);
7809 aarch64_set_FP_long_double (cpu
, st
, a
);
7812 /* TODO store 8 bit unscaled signed 9 bit. */
7813 /* TODO store 16 bit unscaled signed 9 bit. */
7818 /* Float absolute value. */
7820 fabss (sim_cpu
*cpu
)
7822 unsigned sn
= INSTR (9, 5);
7823 unsigned sd
= INSTR (4, 0);
7824 float value
= aarch64_get_FP_float (cpu
, sn
);
7826 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7827 aarch64_set_FP_float (cpu
, sd
, fabsf (value
));
7830 /* Double absolute value. */
7832 fabcpu (sim_cpu
*cpu
)
7834 unsigned sn
= INSTR (9, 5);
7835 unsigned sd
= INSTR (4, 0);
7836 double value
= aarch64_get_FP_double (cpu
, sn
);
7838 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7839 aarch64_set_FP_double (cpu
, sd
, fabs (value
));
7842 /* Float negative value. */
7844 fnegs (sim_cpu
*cpu
)
7846 unsigned sn
= INSTR (9, 5);
7847 unsigned sd
= INSTR (4, 0);
7849 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7850 aarch64_set_FP_float (cpu
, sd
, - aarch64_get_FP_float (cpu
, sn
));
7853 /* Double negative value. */
7855 fnegd (sim_cpu
*cpu
)
7857 unsigned sn
= INSTR (9, 5);
7858 unsigned sd
= INSTR (4, 0);
7860 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7861 aarch64_set_FP_double (cpu
, sd
, - aarch64_get_FP_double (cpu
, sn
));
7864 /* Float square root. */
7866 fsqrts (sim_cpu
*cpu
)
7868 unsigned sn
= INSTR (9, 5);
7869 unsigned sd
= INSTR (4, 0);
7871 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7872 aarch64_set_FP_float (cpu
, sd
, sqrtf (aarch64_get_FP_float (cpu
, sn
)));
7875 /* Double square root. */
7877 fsqrtd (sim_cpu
*cpu
)
7879 unsigned sn
= INSTR (9, 5);
7880 unsigned sd
= INSTR (4, 0);
7882 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7883 aarch64_set_FP_double (cpu
, sd
,
7884 sqrt (aarch64_get_FP_double (cpu
, sn
)));
7887 /* Convert double to float. */
7889 fcvtds (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_float (cpu
, sd
, (float) aarch64_get_FP_double (cpu
, sn
));
7898 /* Convert float to double. */
7900 fcvtcpu (sim_cpu
*cpu
)
7902 unsigned sn
= INSTR (9, 5);
7903 unsigned sd
= INSTR (4, 0);
7905 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7906 aarch64_set_FP_double (cpu
, sd
, (double) aarch64_get_FP_float (cpu
, sn
));
7910 do_FRINT (sim_cpu
*cpu
)
7912 /* instr[31,23] = 0001 1110 0
7913 instr[22] = single(0)/double(1)
7915 instr[17,15] = rounding mode
7916 instr[14,10] = 10000
7918 instr[4,0] = dest */
7921 unsigned rs
= INSTR (9, 5);
7922 unsigned rd
= INSTR (4, 0);
7923 unsigned int rmode
= INSTR (17, 15);
7925 NYI_assert (31, 23, 0x03C);
7926 NYI_assert (21, 18, 0x9);
7927 NYI_assert (14, 10, 0x10);
7929 if (rmode
== 6 || rmode
== 7)
7930 /* FIXME: Add support for rmode == 6 exactness check. */
7931 rmode
= uimm (aarch64_get_FPSR (cpu
), 23, 22);
7933 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
7936 double val
= aarch64_get_FP_double (cpu
, rs
);
7940 case 0: /* mode N: nearest or even. */
7942 double rval
= round (val
);
7944 if (val
- rval
== 0.5)
7946 if (((rval
/ 2.0) * 2.0) != rval
)
7950 aarch64_set_FP_double (cpu
, rd
, round (val
));
7954 case 1: /* mode P: towards +inf. */
7956 aarch64_set_FP_double (cpu
, rd
, trunc (val
));
7958 aarch64_set_FP_double (cpu
, rd
, round (val
));
7961 case 2: /* mode M: towards -inf. */
7963 aarch64_set_FP_double (cpu
, rd
, round (val
));
7965 aarch64_set_FP_double (cpu
, rd
, trunc (val
));
7968 case 3: /* mode Z: towards 0. */
7969 aarch64_set_FP_double (cpu
, rd
, trunc (val
));
7972 case 4: /* mode A: away from 0. */
7973 aarch64_set_FP_double (cpu
, rd
, round (val
));
7976 case 6: /* mode X: use FPCR with exactness check. */
7977 case 7: /* mode I: use FPCR mode. */
7985 val
= aarch64_get_FP_float (cpu
, rs
);
7989 case 0: /* mode N: nearest or even. */
7991 float rval
= roundf (val
);
7993 if (val
- rval
== 0.5)
7995 if (((rval
/ 2.0) * 2.0) != rval
)
7999 aarch64_set_FP_float (cpu
, rd
, rval
);
8003 case 1: /* mode P: towards +inf. */
8005 aarch64_set_FP_float (cpu
, rd
, truncf (val
));
8007 aarch64_set_FP_float (cpu
, rd
, roundf (val
));
8010 case 2: /* mode M: towards -inf. */
8012 aarch64_set_FP_float (cpu
, rd
, truncf (val
));
8014 aarch64_set_FP_float (cpu
, rd
, roundf (val
));
8017 case 3: /* mode Z: towards 0. */
8018 aarch64_set_FP_float (cpu
, rd
, truncf (val
));
8021 case 4: /* mode A: away from 0. */
8022 aarch64_set_FP_float (cpu
, rd
, roundf (val
));
8025 case 6: /* mode X: use FPCR with exactness check. */
8026 case 7: /* mode I: use FPCR mode. */
8034 /* Convert half to float. */
8036 do_FCVT_half_to_single (sim_cpu
*cpu
)
8038 unsigned rn
= INSTR (9, 5);
8039 unsigned rd
= INSTR (4, 0);
8041 NYI_assert (31, 10, 0x7B890);
8043 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8044 aarch64_set_FP_float (cpu
, rd
, (float) aarch64_get_FP_half (cpu
, rn
));
8047 /* Convert half to double. */
8049 do_FCVT_half_to_double (sim_cpu
*cpu
)
8051 unsigned rn
= INSTR (9, 5);
8052 unsigned rd
= INSTR (4, 0);
8054 NYI_assert (31, 10, 0x7B8B0);
8056 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8057 aarch64_set_FP_double (cpu
, rd
, (double) aarch64_get_FP_half (cpu
, rn
));
8061 do_FCVT_single_to_half (sim_cpu
*cpu
)
8063 unsigned rn
= INSTR (9, 5);
8064 unsigned rd
= INSTR (4, 0);
8066 NYI_assert (31, 10, 0x788F0);
8068 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8069 aarch64_set_FP_half (cpu
, rd
, aarch64_get_FP_float (cpu
, rn
));
8072 /* Convert double to half. */
8074 do_FCVT_double_to_half (sim_cpu
*cpu
)
8076 unsigned rn
= INSTR (9, 5);
8077 unsigned rd
= INSTR (4, 0);
8079 NYI_assert (31, 10, 0x798F0);
8081 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8082 aarch64_set_FP_half (cpu
, rd
, (float) aarch64_get_FP_double (cpu
, rn
));
8086 dexSimpleFPDataProc1Source (sim_cpu
*cpu
)
8088 /* instr[31] ==> M : 0 ==> OK, 1 ==> UNALLOC
8090 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
8093 instr[23,22] ==> type : 00 ==> source is single,
8094 01 ==> source is double
8096 11 ==> UNALLOC or source is half
8098 instr[20,15] ==> opcode : with type 00 or 01
8099 000000 ==> FMOV, 000001 ==> FABS,
8100 000010 ==> FNEG, 000011 ==> FSQRT,
8101 000100 ==> UNALLOC, 000101 ==> FCVT,(to single/double)
8102 000110 ==> UNALLOC, 000111 ==> FCVT (to half)
8103 001000 ==> FRINTN, 001001 ==> FRINTP,
8104 001010 ==> FRINTM, 001011 ==> FRINTZ,
8105 001100 ==> FRINTA, 001101 ==> UNALLOC
8106 001110 ==> FRINTX, 001111 ==> FRINTI
8108 000100 ==> FCVT (half-to-single)
8109 000101 ==> FCVT (half-to-double)
8110 instr[14,10] = 10000. */
8112 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
8113 uint32_t type
= INSTR (23, 22);
8114 uint32_t opcode
= INSTR (20, 15);
8122 do_FCVT_half_to_single (cpu
);
8123 else if (opcode
== 5)
8124 do_FCVT_half_to_double (cpu
);
8176 case 8: /* FRINTN etc. */
8188 do_FCVT_double_to_half (cpu
);
8190 do_FCVT_single_to_half (cpu
);
8201 /* 32 bit signed int to float. */
8203 scvtf32 (sim_cpu
*cpu
)
8205 unsigned rn
= INSTR (9, 5);
8206 unsigned sd
= INSTR (4, 0);
8208 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8209 aarch64_set_FP_float
8210 (cpu
, sd
, (float) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
));
8213 /* signed int to float. */
8215 scvtf (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_s64 (cpu
, rn
, NO_SP
));
8225 /* 32 bit signed int to double. */
8227 scvtd32 (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_double
8234 (cpu
, sd
, (double) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
));
8237 /* signed int to double. */
8239 scvtd (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_s64 (cpu
, rn
, NO_SP
));
8249 static const float FLOAT_INT_MAX
= (float) INT_MAX
;
8250 static const float FLOAT_INT_MIN
= (float) INT_MIN
;
8251 static const double DOUBLE_INT_MAX
= (double) INT_MAX
;
8252 static const double DOUBLE_INT_MIN
= (double) INT_MIN
;
8253 static const float FLOAT_LONG_MAX
= (float) LONG_MAX
;
8254 static const float FLOAT_LONG_MIN
= (float) LONG_MIN
;
8255 static const double DOUBLE_LONG_MAX
= (double) LONG_MAX
;
8256 static const double DOUBLE_LONG_MIN
= (double) LONG_MIN
;
8260 static const float FLOAT_UINT_MAX
= (float) UINT_MAX
;
8261 static const float FLOAT_UINT_MIN
= (float) UINT_MIN
;
8262 static const double DOUBLE_UINT_MAX
= (double) UINT_MAX
;
8263 static const double DOUBLE_UINT_MIN
= (double) UINT_MIN
;
8264 static const float FLOAT_ULONG_MAX
= (float) ULONG_MAX
;
8265 static const float FLOAT_ULONG_MIN
= (float) ULONG_MIN
;
8266 static const double DOUBLE_ULONG_MAX
= (double) ULONG_MAX
;
8267 static const double DOUBLE_ULONG_MIN
= (double) ULONG_MIN
;
8269 /* Check for FP exception conditions:
8272 Out of Range raises IO and IX and saturates value
8273 Denormal raises ID and IX and sets to zero. */
8274 #define RAISE_EXCEPTIONS(F, VALUE, FTYPE, ITYPE) \
8277 switch (fpclassify (F)) \
8281 aarch64_set_FPSR (cpu, IO); \
8283 VALUE = ITYPE##_MAX; \
8285 VALUE = ITYPE##_MIN; \
8289 if (F >= FTYPE##_##ITYPE##_MAX) \
8291 aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX); \
8292 VALUE = ITYPE##_MAX; \
8294 else if (F <= FTYPE##_##ITYPE##_MIN) \
8296 aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX); \
8297 VALUE = ITYPE##_MIN; \
8301 case FP_SUBNORMAL: \
8302 aarch64_set_FPSR_bits (cpu, IO | IX | ID, IX | ID); \
8314 /* 32 bit convert float to signed int truncate towards zero. */
8316 fcvtszs32 (sim_cpu
*cpu
)
8318 unsigned sn
= INSTR (9, 5);
8319 unsigned rd
= INSTR (4, 0);
8320 /* TODO : check that this rounds toward zero. */
8321 float f
= aarch64_get_FP_float (cpu
, sn
);
8322 int32_t value
= (int32_t) f
;
8324 RAISE_EXCEPTIONS (f
, value
, FLOAT
, INT
);
8326 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8327 /* Avoid sign extension to 64 bit. */
8328 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) value
);
8331 /* 64 bit convert float to signed int truncate towards zero. */
8333 fcvtszs (sim_cpu
*cpu
)
8335 unsigned sn
= INSTR (9, 5);
8336 unsigned rd
= INSTR (4, 0);
8337 float f
= aarch64_get_FP_float (cpu
, sn
);
8338 int64_t value
= (int64_t) f
;
8340 RAISE_EXCEPTIONS (f
, value
, FLOAT
, LONG
);
8342 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8343 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, value
);
8346 /* 32 bit convert double to signed int truncate towards zero. */
8348 fcvtszd32 (sim_cpu
*cpu
)
8350 unsigned sn
= INSTR (9, 5);
8351 unsigned rd
= INSTR (4, 0);
8352 /* TODO : check that this rounds toward zero. */
8353 double d
= aarch64_get_FP_double (cpu
, sn
);
8354 int32_t value
= (int32_t) d
;
8356 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, INT
);
8358 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8359 /* Avoid sign extension to 64 bit. */
8360 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) value
);
8363 /* 64 bit convert double to signed int truncate towards zero. */
8365 fcvtszd (sim_cpu
*cpu
)
8367 unsigned sn
= INSTR (9, 5);
8368 unsigned rd
= INSTR (4, 0);
8369 /* TODO : check that this rounds toward zero. */
8370 double d
= aarch64_get_FP_double (cpu
, sn
);
8373 value
= (int64_t) d
;
8375 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, LONG
);
8377 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8378 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, value
);
8382 do_fcvtzu (sim_cpu
*cpu
)
8384 /* instr[31] = size: 32-bit (0), 64-bit (1)
8385 instr[30,23] = 00111100
8386 instr[22] = type: single (0)/ double (1)
8387 instr[21] = enable (0)/disable(1) precision
8388 instr[20,16] = 11001
8389 instr[15,10] = precision
8393 unsigned rs
= INSTR (9, 5);
8394 unsigned rd
= INSTR (4, 0);
8396 NYI_assert (30, 23, 0x3C);
8397 NYI_assert (20, 16, 0x19);
8399 if (INSTR (21, 21) != 1)
8400 /* Convert to fixed point. */
8403 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8406 /* Convert to unsigned 64-bit integer. */
8409 double d
= aarch64_get_FP_double (cpu
, rs
);
8410 uint64_t value
= (uint64_t) d
;
8412 /* Do not raise an exception if we have reached ULONG_MAX. */
8413 if (value
!= (1ULL << 63))
8414 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, ULONG
);
8416 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
8420 float f
= aarch64_get_FP_float (cpu
, rs
);
8421 uint64_t value
= (uint64_t) f
;
8423 /* Do not raise an exception if we have reached ULONG_MAX. */
8424 if (value
!= (1ULL << 63))
8425 RAISE_EXCEPTIONS (f
, value
, FLOAT
, ULONG
);
8427 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
8434 /* Convert to unsigned 32-bit integer. */
8437 double d
= aarch64_get_FP_double (cpu
, rs
);
8439 value
= (uint32_t) d
;
8440 /* Do not raise an exception if we have reached UINT_MAX. */
8441 if (value
!= (1UL << 31))
8442 RAISE_EXCEPTIONS (d
, value
, DOUBLE
, UINT
);
8446 float f
= aarch64_get_FP_float (cpu
, rs
);
8448 value
= (uint32_t) f
;
8449 /* Do not raise an exception if we have reached UINT_MAX. */
8450 if (value
!= (1UL << 31))
8451 RAISE_EXCEPTIONS (f
, value
, FLOAT
, UINT
);
8454 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
8459 do_UCVTF (sim_cpu
*cpu
)
8461 /* instr[31] = size: 32-bit (0), 64-bit (1)
8462 instr[30,23] = 001 1110 0
8463 instr[22] = type: single (0)/ double (1)
8464 instr[21] = enable (0)/disable(1) precision
8465 instr[20,16] = 0 0011
8466 instr[15,10] = precision
8470 unsigned rs
= INSTR (9, 5);
8471 unsigned rd
= INSTR (4, 0);
8473 NYI_assert (30, 23, 0x3C);
8474 NYI_assert (20, 16, 0x03);
8476 if (INSTR (21, 21) != 1)
8479 /* FIXME: Add exception raising. */
8480 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8483 uint64_t value
= aarch64_get_reg_u64 (cpu
, rs
, NO_SP
);
8486 aarch64_set_FP_double (cpu
, rd
, (double) value
);
8488 aarch64_set_FP_float (cpu
, rd
, (float) value
);
8492 uint32_t value
= aarch64_get_reg_u32 (cpu
, rs
, NO_SP
);
8495 aarch64_set_FP_double (cpu
, rd
, (double) value
);
8497 aarch64_set_FP_float (cpu
, rd
, (float) value
);
8502 float_vector_move (sim_cpu
*cpu
)
8504 /* instr[31,17] == 100 1111 0101 0111
8505 instr[16] ==> direction 0=> to GR, 1=> from GR
8507 instr[9,5] ==> source
8508 instr[4,0] ==> dest. */
8510 unsigned rn
= INSTR (9, 5);
8511 unsigned rd
= INSTR (4, 0);
8513 NYI_assert (31, 17, 0x4F57);
8515 if (INSTR (15, 10) != 0)
8518 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8520 aarch64_set_vec_u64 (cpu
, rd
, 1, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
8522 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, aarch64_get_vec_u64 (cpu
, rn
, 1));
8526 dexSimpleFPIntegerConvert (sim_cpu
*cpu
)
8528 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
8530 instr[29] = S : 0 ==> OK, 1 ==> UNALLOC
8533 instr[23,22] = type : 00 ==> single, 01 ==> double, 1x ==> UNALLOC
8535 instr[20,19] = rmode
8536 instr[18,16] = opcode
8537 instr[15,10] = 10 0000 */
8539 uint32_t rmode_opcode
;
8545 if (INSTR (31, 17) == 0x4F57)
8547 float_vector_move (cpu
);
8551 size
= INSTR (31, 31);
8556 type
= INSTR (23, 22);
8560 rmode_opcode
= INSTR (20, 16);
8561 size_type
= (size
<< 1) | type
; /* 0==32f, 1==32d, 2==64f, 3==64d. */
8563 switch (rmode_opcode
)
8565 case 2: /* SCVTF. */
8568 case 0: scvtf32 (cpu
); return;
8569 case 1: scvtd32 (cpu
); return;
8570 case 2: scvtf (cpu
); return;
8571 case 3: scvtd (cpu
); return;
8574 case 6: /* FMOV GR, Vec. */
8577 case 0: gfmovs (cpu
); return;
8578 case 3: gfmovd (cpu
); return;
8579 default: HALT_UNALLOC
;
8582 case 7: /* FMOV vec, GR. */
8585 case 0: fgmovs (cpu
); return;
8586 case 3: fgmovd (cpu
); return;
8587 default: HALT_UNALLOC
;
8590 case 24: /* FCVTZS. */
8593 case 0: fcvtszs32 (cpu
); return;
8594 case 1: fcvtszd32 (cpu
); return;
8595 case 2: fcvtszs (cpu
); return;
8596 case 3: fcvtszd (cpu
); return;
8599 case 25: do_fcvtzu (cpu
); return;
8600 case 3: do_UCVTF (cpu
); return;
8602 case 0: /* FCVTNS. */
8603 case 1: /* FCVTNU. */
8604 case 4: /* FCVTAS. */
8605 case 5: /* FCVTAU. */
8606 case 8: /* FCVPTS. */
8607 case 9: /* FCVTPU. */
8608 case 16: /* FCVTMS. */
8609 case 17: /* FCVTMU. */
8616 set_flags_for_float_compare (sim_cpu
*cpu
, float fvalue1
, float fvalue2
)
8620 /* FIXME: Add exception raising. */
8621 if (isnan (fvalue1
) || isnan (fvalue2
))
8623 else if (isinf (fvalue1
) && isinf (fvalue2
))
8625 /* Subtracting two infinities may give a NaN. We only need to compare
8626 the signs, which we can get from isinf. */
8627 int result
= isinf (fvalue1
) - isinf (fvalue2
);
8631 else if (result
< 0)
8633 else /* (result > 0). */
8638 float result
= fvalue1
- fvalue2
;
8642 else if (result
< 0)
8644 else /* (result > 0). */
8648 aarch64_set_CPSR (cpu
, flags
);
8652 fcmps (sim_cpu
*cpu
)
8654 unsigned sm
= INSTR (20, 16);
8655 unsigned sn
= INSTR ( 9, 5);
8657 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8658 float fvalue2
= aarch64_get_FP_float (cpu
, sm
);
8660 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8661 set_flags_for_float_compare (cpu
, fvalue1
, fvalue2
);
8664 /* Float compare to zero -- Invalid Operation exception
8665 only on signaling NaNs. */
8667 fcmpzs (sim_cpu
*cpu
)
8669 unsigned sn
= INSTR ( 9, 5);
8670 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8672 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8673 set_flags_for_float_compare (cpu
, fvalue1
, 0.0f
);
8676 /* Float compare -- Invalid Operation exception on all NaNs. */
8678 fcmpes (sim_cpu
*cpu
)
8680 unsigned sm
= INSTR (20, 16);
8681 unsigned sn
= INSTR ( 9, 5);
8683 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8684 float fvalue2
= aarch64_get_FP_float (cpu
, sm
);
8686 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8687 set_flags_for_float_compare (cpu
, fvalue1
, fvalue2
);
8690 /* Float compare to zero -- Invalid Operation exception on all NaNs. */
8692 fcmpzes (sim_cpu
*cpu
)
8694 unsigned sn
= INSTR ( 9, 5);
8695 float fvalue1
= aarch64_get_FP_float (cpu
, sn
);
8697 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8698 set_flags_for_float_compare (cpu
, fvalue1
, 0.0f
);
8702 set_flags_for_double_compare (sim_cpu
*cpu
, double dval1
, double dval2
)
8706 /* FIXME: Add exception raising. */
8707 if (isnan (dval1
) || isnan (dval2
))
8709 else if (isinf (dval1
) && isinf (dval2
))
8711 /* Subtracting two infinities may give a NaN. We only need to compare
8712 the signs, which we can get from isinf. */
8713 int result
= isinf (dval1
) - isinf (dval2
);
8717 else if (result
< 0)
8719 else /* (result > 0). */
8724 double result
= dval1
- dval2
;
8728 else if (result
< 0)
8730 else /* (result > 0). */
8734 aarch64_set_CPSR (cpu
, flags
);
8737 /* Double compare -- Invalid Operation exception only on signaling NaNs. */
8739 fcmpd (sim_cpu
*cpu
)
8741 unsigned sm
= INSTR (20, 16);
8742 unsigned sn
= INSTR ( 9, 5);
8744 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8745 double dvalue2
= aarch64_get_FP_double (cpu
, sm
);
8747 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8748 set_flags_for_double_compare (cpu
, dvalue1
, dvalue2
);
8751 /* Double compare to zero -- Invalid Operation exception
8752 only on signaling NaNs. */
8754 fcmpzd (sim_cpu
*cpu
)
8756 unsigned sn
= INSTR ( 9, 5);
8757 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8759 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8760 set_flags_for_double_compare (cpu
, dvalue1
, 0.0);
8763 /* Double compare -- Invalid Operation exception on all NaNs. */
8765 fcmped (sim_cpu
*cpu
)
8767 unsigned sm
= INSTR (20, 16);
8768 unsigned sn
= INSTR ( 9, 5);
8770 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8771 double dvalue2
= aarch64_get_FP_double (cpu
, sm
);
8773 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8774 set_flags_for_double_compare (cpu
, dvalue1
, dvalue2
);
8777 /* Double compare to zero -- Invalid Operation exception on all NaNs. */
8779 fcmpzed (sim_cpu
*cpu
)
8781 unsigned sn
= INSTR ( 9, 5);
8782 double dvalue1
= aarch64_get_FP_double (cpu
, sn
);
8784 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8785 set_flags_for_double_compare (cpu
, dvalue1
, 0.0);
8789 dexSimpleFPCompare (sim_cpu
*cpu
)
8791 /* assert instr[28,25] == 1111
8792 instr[30:24:21:13,10] = 0011000
8793 instr[31] = M : 0 ==> OK, 1 ==> UNALLOC
8794 instr[29] ==> S : 0 ==> OK, 1 ==> UNALLOC
8795 instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
8796 instr[15,14] ==> op : 00 ==> OK, ow ==> UNALLOC
8797 instr[4,0] ==> opcode2 : 00000 ==> FCMP, 10000 ==> FCMPE,
8798 01000 ==> FCMPZ, 11000 ==> FCMPEZ,
8801 uint32_t M_S
= (INSTR (31, 31) << 1) | INSTR (29, 29);
8802 uint32_t type
= INSTR (23, 22);
8803 uint32_t op
= INSTR (15, 14);
8804 uint32_t op2_2_0
= INSTR (2, 0);
8818 /* dispatch on type and top 2 bits of opcode. */
8819 dispatch
= (type
<< 2) | INSTR (4, 3);
8823 case 0: fcmps (cpu
); return;
8824 case 1: fcmpzs (cpu
); return;
8825 case 2: fcmpes (cpu
); return;
8826 case 3: fcmpzes (cpu
); return;
8827 case 4: fcmpd (cpu
); return;
8828 case 5: fcmpzd (cpu
); return;
8829 case 6: fcmped (cpu
); return;
8830 case 7: fcmpzed (cpu
); return;
8835 do_scalar_FADDP (sim_cpu
*cpu
)
8837 /* instr [31,23] = 0111 1110 0
8838 instr [22] = single(0)/double(1)
8839 instr [21,10] = 11 0000 1101 10
8841 instr [4,0] = Fd. */
8843 unsigned Fn
= INSTR (9, 5);
8844 unsigned Fd
= INSTR (4, 0);
8846 NYI_assert (31, 23, 0x0FC);
8847 NYI_assert (21, 10, 0xC36);
8849 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8852 double val1
= aarch64_get_vec_double (cpu
, Fn
, 0);
8853 double val2
= aarch64_get_vec_double (cpu
, Fn
, 1);
8855 aarch64_set_FP_double (cpu
, Fd
, val1
+ val2
);
8859 float val1
= aarch64_get_vec_float (cpu
, Fn
, 0);
8860 float val2
= aarch64_get_vec_float (cpu
, Fn
, 1);
8862 aarch64_set_FP_float (cpu
, Fd
, val1
+ val2
);
8866 /* Floating point absolute difference. */
8869 do_scalar_FABD (sim_cpu
*cpu
)
8871 /* instr [31,23] = 0111 1110 1
8872 instr [22] = float(0)/double(1)
8875 instr [15,10] = 1101 01
8877 instr [4, 0] = Rd. */
8879 unsigned rm
= INSTR (20, 16);
8880 unsigned rn
= INSTR (9, 5);
8881 unsigned rd
= INSTR (4, 0);
8883 NYI_assert (31, 23, 0x0FD);
8884 NYI_assert (21, 21, 1);
8885 NYI_assert (15, 10, 0x35);
8887 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8889 aarch64_set_FP_double (cpu
, rd
,
8890 fabs (aarch64_get_FP_double (cpu
, rn
)
8891 - aarch64_get_FP_double (cpu
, rm
)));
8893 aarch64_set_FP_float (cpu
, rd
,
8894 fabsf (aarch64_get_FP_float (cpu
, rn
)
8895 - aarch64_get_FP_float (cpu
, rm
)));
8899 do_scalar_CMGT (sim_cpu
*cpu
)
8901 /* instr [31,21] = 0101 1110 111
8903 instr [15,10] = 00 1101
8905 instr [4, 0] = Rd. */
8907 unsigned rm
= INSTR (20, 16);
8908 unsigned rn
= INSTR (9, 5);
8909 unsigned rd
= INSTR (4, 0);
8911 NYI_assert (31, 21, 0x2F7);
8912 NYI_assert (15, 10, 0x0D);
8914 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8915 aarch64_set_vec_u64 (cpu
, rd
, 0,
8916 aarch64_get_vec_u64 (cpu
, rn
, 0) >
8917 aarch64_get_vec_u64 (cpu
, rm
, 0) ? -1L : 0L);
8921 do_scalar_USHR (sim_cpu
*cpu
)
8923 /* instr [31,23] = 0111 1111 0
8924 instr [22,16] = shift amount
8925 instr [15,10] = 0000 01
8927 instr [4, 0] = Rd. */
8929 unsigned amount
= 128 - INSTR (22, 16);
8930 unsigned rn
= INSTR (9, 5);
8931 unsigned rd
= INSTR (4, 0);
8933 NYI_assert (31, 23, 0x0FE);
8934 NYI_assert (15, 10, 0x01);
8936 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8937 aarch64_set_vec_u64 (cpu
, rd
, 0,
8938 aarch64_get_vec_u64 (cpu
, rn
, 0) >> amount
);
8942 do_scalar_SSHL (sim_cpu
*cpu
)
8944 /* instr [31,21] = 0101 1110 111
8946 instr [15,10] = 0100 01
8948 instr [4, 0] = Rd. */
8950 unsigned rm
= INSTR (20, 16);
8951 unsigned rn
= INSTR (9, 5);
8952 unsigned rd
= INSTR (4, 0);
8953 signed int shift
= aarch64_get_vec_s8 (cpu
, rm
, 0);
8955 NYI_assert (31, 21, 0x2F7);
8956 NYI_assert (15, 10, 0x11);
8958 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8960 aarch64_set_vec_s64 (cpu
, rd
, 0,
8961 aarch64_get_vec_s64 (cpu
, rn
, 0) << shift
);
8963 aarch64_set_vec_s64 (cpu
, rd
, 0,
8964 aarch64_get_vec_s64 (cpu
, rn
, 0) >> - shift
);
8967 /* Floating point scalar compare greater than or equal to 0. */
8969 do_scalar_FCMGE_zero (sim_cpu
*cpu
)
8971 /* instr [31,23] = 0111 1110 1
8972 instr [22,22] = size
8973 instr [21,16] = 1000 00
8974 instr [15,10] = 1100 10
8976 instr [4, 0] = Rd. */
8978 unsigned size
= INSTR (22, 22);
8979 unsigned rn
= INSTR (9, 5);
8980 unsigned rd
= INSTR (4, 0);
8982 NYI_assert (31, 23, 0x0FD);
8983 NYI_assert (21, 16, 0x20);
8984 NYI_assert (15, 10, 0x32);
8986 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
8988 aarch64_set_vec_u64 (cpu
, rd
, 0,
8989 aarch64_get_vec_double (cpu
, rn
, 0) >= 0.0 ? -1 : 0);
8991 aarch64_set_vec_u32 (cpu
, rd
, 0,
8992 aarch64_get_vec_float (cpu
, rn
, 0) >= 0.0 ? -1 : 0);
8995 /* Floating point scalar compare less than or equal to 0. */
8997 do_scalar_FCMLE_zero (sim_cpu
*cpu
)
8999 /* instr [31,23] = 0111 1110 1
9000 instr [22,22] = size
9001 instr [21,16] = 1000 00
9002 instr [15,10] = 1101 10
9004 instr [4, 0] = Rd. */
9006 unsigned size
= INSTR (22, 22);
9007 unsigned rn
= INSTR (9, 5);
9008 unsigned rd
= INSTR (4, 0);
9010 NYI_assert (31, 23, 0x0FD);
9011 NYI_assert (21, 16, 0x20);
9012 NYI_assert (15, 10, 0x36);
9014 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9016 aarch64_set_vec_u64 (cpu
, rd
, 0,
9017 aarch64_get_vec_double (cpu
, rn
, 0) <= 0.0 ? -1 : 0);
9019 aarch64_set_vec_u32 (cpu
, rd
, 0,
9020 aarch64_get_vec_float (cpu
, rn
, 0) <= 0.0 ? -1 : 0);
9023 /* Floating point scalar compare greater than 0. */
9025 do_scalar_FCMGT_zero (sim_cpu
*cpu
)
9027 /* instr [31,23] = 0101 1110 1
9028 instr [22,22] = size
9029 instr [21,16] = 1000 00
9030 instr [15,10] = 1100 10
9032 instr [4, 0] = Rd. */
9034 unsigned size
= INSTR (22, 22);
9035 unsigned rn
= INSTR (9, 5);
9036 unsigned rd
= INSTR (4, 0);
9038 NYI_assert (31, 23, 0x0BD);
9039 NYI_assert (21, 16, 0x20);
9040 NYI_assert (15, 10, 0x32);
9042 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9044 aarch64_set_vec_u64 (cpu
, rd
, 0,
9045 aarch64_get_vec_double (cpu
, rn
, 0) > 0.0 ? -1 : 0);
9047 aarch64_set_vec_u32 (cpu
, rd
, 0,
9048 aarch64_get_vec_float (cpu
, rn
, 0) > 0.0 ? -1 : 0);
9051 /* Floating point scalar compare equal to 0. */
9053 do_scalar_FCMEQ_zero (sim_cpu
*cpu
)
9055 /* instr [31,23] = 0101 1110 1
9056 instr [22,22] = size
9057 instr [21,16] = 1000 00
9058 instr [15,10] = 1101 10
9060 instr [4, 0] = Rd. */
9062 unsigned size
= INSTR (22, 22);
9063 unsigned rn
= INSTR (9, 5);
9064 unsigned rd
= INSTR (4, 0);
9066 NYI_assert (31, 23, 0x0BD);
9067 NYI_assert (21, 16, 0x20);
9068 NYI_assert (15, 10, 0x36);
9070 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9072 aarch64_set_vec_u64 (cpu
, rd
, 0,
9073 aarch64_get_vec_double (cpu
, rn
, 0) == 0.0 ? -1 : 0);
9075 aarch64_set_vec_u32 (cpu
, rd
, 0,
9076 aarch64_get_vec_float (cpu
, rn
, 0) == 0.0 ? -1 : 0);
9079 /* Floating point scalar compare less than 0. */
9081 do_scalar_FCMLT_zero (sim_cpu
*cpu
)
9083 /* instr [31,23] = 0101 1110 1
9084 instr [22,22] = size
9085 instr [21,16] = 1000 00
9086 instr [15,10] = 1110 10
9088 instr [4, 0] = Rd. */
9090 unsigned size
= INSTR (22, 22);
9091 unsigned rn
= INSTR (9, 5);
9092 unsigned rd
= INSTR (4, 0);
9094 NYI_assert (31, 23, 0x0BD);
9095 NYI_assert (21, 16, 0x20);
9096 NYI_assert (15, 10, 0x3A);
9098 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9100 aarch64_set_vec_u64 (cpu
, rd
, 0,
9101 aarch64_get_vec_double (cpu
, rn
, 0) < 0.0 ? -1 : 0);
9103 aarch64_set_vec_u32 (cpu
, rd
, 0,
9104 aarch64_get_vec_float (cpu
, rn
, 0) < 0.0 ? -1 : 0);
9108 do_scalar_shift (sim_cpu
*cpu
)
9110 /* instr [31,23] = 0101 1111 0
9111 instr [22,16] = shift amount
9112 instr [15,10] = 0101 01 [SHL]
9113 instr [15,10] = 0000 01 [SSHR]
9115 instr [4, 0] = Rd. */
9117 unsigned rn
= INSTR (9, 5);
9118 unsigned rd
= INSTR (4, 0);
9121 NYI_assert (31, 23, 0x0BE);
9123 if (INSTR (22, 22) == 0)
9126 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9127 switch (INSTR (15, 10))
9129 case 0x01: /* SSHR */
9130 amount
= 128 - INSTR (22, 16);
9131 aarch64_set_vec_s64 (cpu
, rd
, 0,
9132 aarch64_get_vec_s64 (cpu
, rn
, 0) >> amount
);
9134 case 0x15: /* SHL */
9135 amount
= INSTR (22, 16) - 64;
9136 aarch64_set_vec_u64 (cpu
, rd
, 0,
9137 aarch64_get_vec_u64 (cpu
, rn
, 0) << amount
);
9144 /* FCMEQ FCMGT FCMGE. */
9146 do_scalar_FCM (sim_cpu
*cpu
)
9148 /* instr [31,30] = 01
9150 instr [28,24] = 1 1110
9155 instr [15,12] = 1110
9159 instr [4, 0] = Rd. */
9161 unsigned rm
= INSTR (20, 16);
9162 unsigned rn
= INSTR (9, 5);
9163 unsigned rd
= INSTR (4, 0);
9164 unsigned EUac
= (INSTR (23, 23) << 2) | (INSTR (29, 29) << 1) | INSTR (11, 11);
9169 NYI_assert (31, 30, 1);
9170 NYI_assert (28, 24, 0x1E);
9171 NYI_assert (21, 21, 1);
9172 NYI_assert (15, 12, 0xE);
9173 NYI_assert (10, 10, 1);
9175 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9178 double val1
= aarch64_get_FP_double (cpu
, rn
);
9179 double val2
= aarch64_get_FP_double (cpu
, rm
);
9184 result
= val1
== val2
;
9192 result
= val1
>= val2
;
9200 result
= val1
> val2
;
9207 aarch64_set_vec_u32 (cpu
, rd
, 0, result
? -1 : 0);
9211 val1
= aarch64_get_FP_float (cpu
, rn
);
9212 val2
= aarch64_get_FP_float (cpu
, rm
);
9217 result
= val1
== val2
;
9221 val1
= fabsf (val1
);
9222 val2
= fabsf (val2
);
9225 result
= val1
>= val2
;
9229 val1
= fabsf (val1
);
9230 val2
= fabsf (val2
);
9233 result
= val1
> val2
;
9240 aarch64_set_vec_u32 (cpu
, rd
, 0, result
? -1 : 0);
9243 /* An alias of DUP. */
9245 do_scalar_MOV (sim_cpu
*cpu
)
9247 /* instr [31,21] = 0101 1110 000
9248 instr [20,16] = imm5
9249 instr [15,10] = 0000 01
9251 instr [4, 0] = Rd. */
9253 unsigned rn
= INSTR (9, 5);
9254 unsigned rd
= INSTR (4, 0);
9257 NYI_assert (31, 21, 0x2F0);
9258 NYI_assert (15, 10, 0x01);
9260 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9264 index
= INSTR (20, 17);
9266 (cpu
, rd
, 0, aarch64_get_vec_u8 (cpu
, rn
, index
));
9268 else if (INSTR (17, 17))
9271 index
= INSTR (20, 18);
9273 (cpu
, rd
, 0, aarch64_get_vec_u16 (cpu
, rn
, index
));
9275 else if (INSTR (18, 18))
9278 index
= INSTR (20, 19);
9280 (cpu
, rd
, 0, aarch64_get_vec_u32 (cpu
, rn
, index
));
9282 else if (INSTR (19, 19))
9285 index
= INSTR (20, 20);
9287 (cpu
, rd
, 0, aarch64_get_vec_u64 (cpu
, rn
, index
));
9294 do_scalar_NEG (sim_cpu
*cpu
)
9296 /* instr [31,10] = 0111 1110 1110 0000 1011 10
9298 instr [4, 0] = Rd. */
9300 unsigned rn
= INSTR (9, 5);
9301 unsigned rd
= INSTR (4, 0);
9303 NYI_assert (31, 10, 0x1FB82E);
9305 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9306 aarch64_set_vec_u64 (cpu
, rd
, 0, - aarch64_get_vec_u64 (cpu
, rn
, 0));
9310 do_scalar_USHL (sim_cpu
*cpu
)
9312 /* instr [31,21] = 0111 1110 111
9314 instr [15,10] = 0100 01
9316 instr [4, 0] = Rd. */
9318 unsigned rm
= INSTR (20, 16);
9319 unsigned rn
= INSTR (9, 5);
9320 unsigned rd
= INSTR (4, 0);
9321 signed int shift
= aarch64_get_vec_s8 (cpu
, rm
, 0);
9323 NYI_assert (31, 21, 0x3F7);
9324 NYI_assert (15, 10, 0x11);
9326 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9328 aarch64_set_vec_u64 (cpu
, rd
, 0, aarch64_get_vec_u64 (cpu
, rn
, 0) << shift
);
9330 aarch64_set_vec_u64 (cpu
, rd
, 0, aarch64_get_vec_u64 (cpu
, rn
, 0) >> - shift
);
9334 do_double_add (sim_cpu
*cpu
)
9336 /* instr [31,21] = 0101 1110 111
9338 instr [15,10] = 1000 01
9340 instr [4,0] = Fd. */
9347 NYI_assert (31, 21, 0x2F7);
9348 NYI_assert (15, 10, 0x21);
9352 Fn
= INSTR (20, 16);
9354 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9355 val1
= aarch64_get_FP_double (cpu
, Fm
);
9356 val2
= aarch64_get_FP_double (cpu
, Fn
);
9358 aarch64_set_FP_double (cpu
, Fd
, val1
+ val2
);
9362 do_scalar_UCVTF (sim_cpu
*cpu
)
9364 /* instr [31,23] = 0111 1110 0
9365 instr [22] = single(0)/double(1)
9366 instr [21,10] = 10 0001 1101 10
9368 instr [4,0] = rd. */
9370 unsigned rn
= INSTR (9, 5);
9371 unsigned rd
= INSTR (4, 0);
9373 NYI_assert (31, 23, 0x0FC);
9374 NYI_assert (21, 10, 0x876);
9376 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9379 uint64_t val
= aarch64_get_vec_u64 (cpu
, rn
, 0);
9381 aarch64_set_vec_double (cpu
, rd
, 0, (double) val
);
9385 uint32_t val
= aarch64_get_vec_u32 (cpu
, rn
, 0);
9387 aarch64_set_vec_float (cpu
, rd
, 0, (float) val
);
9392 do_scalar_vec (sim_cpu
*cpu
)
9394 /* instr [30] = 1. */
9395 /* instr [28,25] = 1111. */
9396 switch (INSTR (31, 23))
9399 switch (INSTR (15, 10))
9401 case 0x01: do_scalar_MOV (cpu
); return;
9402 case 0x39: do_scalar_FCM (cpu
); return;
9403 case 0x3B: do_scalar_FCM (cpu
); return;
9407 case 0xBE: do_scalar_shift (cpu
); return;
9410 switch (INSTR (15, 10))
9413 switch (INSTR (21, 16))
9415 case 0x30: do_scalar_FADDP (cpu
); return;
9416 case 0x21: do_scalar_UCVTF (cpu
); return;
9419 case 0x39: do_scalar_FCM (cpu
); return;
9420 case 0x3B: do_scalar_FCM (cpu
); return;
9425 switch (INSTR (15, 10))
9427 case 0x0D: do_scalar_CMGT (cpu
); return;
9428 case 0x11: do_scalar_USHL (cpu
); return;
9429 case 0x2E: do_scalar_NEG (cpu
); return;
9430 case 0x32: do_scalar_FCMGE_zero (cpu
); return;
9431 case 0x35: do_scalar_FABD (cpu
); return;
9432 case 0x36: do_scalar_FCMLE_zero (cpu
); return;
9433 case 0x39: do_scalar_FCM (cpu
); return;
9434 case 0x3B: do_scalar_FCM (cpu
); return;
9439 case 0xFE: do_scalar_USHR (cpu
); return;
9442 switch (INSTR (15, 10))
9444 case 0x21: do_double_add (cpu
); return;
9445 case 0x11: do_scalar_SSHL (cpu
); return;
9446 case 0x32: do_scalar_FCMGT_zero (cpu
); return;
9447 case 0x36: do_scalar_FCMEQ_zero (cpu
); return;
9448 case 0x3A: do_scalar_FCMLT_zero (cpu
); return;
9459 dexAdvSIMD1 (sim_cpu
*cpu
)
9461 /* instr [28,25] = 1 111. */
9463 /* We are currently only interested in the basic
9464 scalar fp routines which all have bit 30 = 0. */
9466 do_scalar_vec (cpu
);
9468 /* instr[24] is set for FP data processing 3-source and clear for
9469 all other basic scalar fp instruction groups. */
9470 else if (INSTR (24, 24))
9471 dexSimpleFPDataProc3Source (cpu
);
9473 /* instr[21] is clear for floating <-> fixed conversions and set for
9474 all other basic scalar fp instruction groups. */
9475 else if (!INSTR (21, 21))
9476 dexSimpleFPFixedConvert (cpu
);
9478 /* instr[11,10] : 01 ==> cond compare, 10 ==> Data Proc 2 Source
9479 11 ==> cond select, 00 ==> other. */
9481 switch (INSTR (11, 10))
9483 case 1: dexSimpleFPCondCompare (cpu
); return;
9484 case 2: dexSimpleFPDataProc2Source (cpu
); return;
9485 case 3: dexSimpleFPCondSelect (cpu
); return;
9488 /* Now an ordered cascade of tests.
9489 FP immediate has instr [12] == 1.
9490 FP compare has instr [13] == 1.
9491 FP Data Proc 1 Source has instr [14] == 1.
9492 FP floating <--> integer conversions has instr [15] == 0. */
9494 dexSimpleFPImmediate (cpu
);
9496 else if (INSTR (13, 13))
9497 dexSimpleFPCompare (cpu
);
9499 else if (INSTR (14, 14))
9500 dexSimpleFPDataProc1Source (cpu
);
9502 else if (!INSTR (15, 15))
9503 dexSimpleFPIntegerConvert (cpu
);
9506 /* If we get here then instr[15] == 1 which means UNALLOC. */
9511 /* PC relative addressing. */
9514 pcadr (sim_cpu
*cpu
)
9516 /* instr[31] = op : 0 ==> ADR, 1 ==> ADRP
9517 instr[30,29] = immlo
9518 instr[23,5] = immhi. */
9520 unsigned rd
= INSTR (4, 0);
9521 uint32_t isPage
= INSTR (31, 31);
9522 union { int64_t u64
; uint64_t s64
; } imm
;
9525 imm
.s64
= simm64 (aarch64_get_instr (cpu
), 23, 5);
9527 offset
= (offset
<< 2) | INSTR (30, 29);
9529 address
= aarch64_get_PC (cpu
);
9537 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9538 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, address
+ offset
);
9541 /* Specific decode and execute for group Data Processing Immediate. */
9544 dexPCRelAddressing (sim_cpu
*cpu
)
9546 /* assert instr[28,24] = 10000. */
9550 /* Immediate logical.
9551 The bimm32/64 argument is constructed by replicating a 2, 4, 8,
9552 16, 32 or 64 bit sequence pulled out at decode and possibly
9555 N.B. the output register (dest) can normally be Xn or SP
9556 the exception occurs for flag setting instructions which may
9557 only use Xn for the output (dest). The input register can
9560 /* 32 bit and immediate. */
9562 and32 (sim_cpu
*cpu
, uint32_t bimm
)
9564 unsigned rn
= INSTR (9, 5);
9565 unsigned rd
= INSTR (4, 0);
9567 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9568 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9569 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
) & bimm
);
9572 /* 64 bit and immediate. */
9574 and64 (sim_cpu
*cpu
, uint64_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_u64 (cpu
, rn
, NO_SP
) & bimm
);
9584 /* 32 bit and immediate set flags. */
9586 ands32 (sim_cpu
*cpu
, uint32_t bimm
)
9588 unsigned rn
= INSTR (9, 5);
9589 unsigned rd
= INSTR (4, 0);
9591 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9592 uint32_t value2
= bimm
;
9594 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9595 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9596 set_flags_for_binop32 (cpu
, value1
& value2
);
9599 /* 64 bit and immediate set flags. */
9601 ands64 (sim_cpu
*cpu
, uint64_t bimm
)
9603 unsigned rn
= INSTR (9, 5);
9604 unsigned rd
= INSTR (4, 0);
9606 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9607 uint64_t value2
= bimm
;
9609 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9610 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9611 set_flags_for_binop64 (cpu
, value1
& value2
);
9614 /* 32 bit exclusive or immediate. */
9616 eor32 (sim_cpu
*cpu
, uint32_t bimm
)
9618 unsigned rn
= INSTR (9, 5);
9619 unsigned rd
= INSTR (4, 0);
9621 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9622 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
,
9623 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
) ^ bimm
);
9626 /* 64 bit exclusive or immediate. */
9628 eor64 (sim_cpu
*cpu
, uint64_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_u64 (cpu
, rn
, NO_SP
) ^ bimm
);
9638 /* 32 bit or immediate. */
9640 orr32 (sim_cpu
*cpu
, uint32_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_u32 (cpu
, rn
, NO_SP
) | bimm
);
9650 /* 64 bit or immediate. */
9652 orr64 (sim_cpu
*cpu
, uint64_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_u64 (cpu
, rn
, NO_SP
) | bimm
);
9662 /* Logical shifted register.
9663 These allow an optional LSL, ASR, LSR or ROR to the second source
9664 register with a count up to the register bit count.
9665 N.B register args may not be SP. */
9667 /* 32 bit AND shifted register. */
9669 and32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9671 unsigned rm
= INSTR (20, 16);
9672 unsigned rn
= INSTR (9, 5);
9673 unsigned rd
= INSTR (4, 0);
9675 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9677 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9678 & shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9681 /* 64 bit AND shifted register. */
9683 and64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9685 unsigned rm
= INSTR (20, 16);
9686 unsigned rn
= INSTR (9, 5);
9687 unsigned rd
= INSTR (4, 0);
9689 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9691 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9692 & shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9695 /* 32 bit AND shifted register setting flags. */
9697 ands32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9699 unsigned rm
= INSTR (20, 16);
9700 unsigned rn
= INSTR (9, 5);
9701 unsigned rd
= INSTR (4, 0);
9703 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9704 uint32_t value2
= shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
9707 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9708 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9709 set_flags_for_binop32 (cpu
, value1
& value2
);
9712 /* 64 bit AND shifted register setting flags. */
9714 ands64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9716 unsigned rm
= INSTR (20, 16);
9717 unsigned rn
= INSTR (9, 5);
9718 unsigned rd
= INSTR (4, 0);
9720 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9721 uint64_t value2
= shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
9724 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9725 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9726 set_flags_for_binop64 (cpu
, value1
& value2
);
9729 /* 32 bit BIC shifted register. */
9731 bic32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9733 unsigned rm
= INSTR (20, 16);
9734 unsigned rn
= INSTR (9, 5);
9735 unsigned rd
= INSTR (4, 0);
9737 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9739 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9740 & ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9743 /* 64 bit BIC shifted register. */
9745 bic64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9747 unsigned rm
= INSTR (20, 16);
9748 unsigned rn
= INSTR (9, 5);
9749 unsigned rd
= INSTR (4, 0);
9751 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9753 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9754 & ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9757 /* 32 bit BIC shifted register setting flags. */
9759 bics32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9761 unsigned rm
= INSTR (20, 16);
9762 unsigned rn
= INSTR (9, 5);
9763 unsigned rd
= INSTR (4, 0);
9765 uint32_t value1
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
9766 uint32_t value2
= ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
9769 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9770 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9771 set_flags_for_binop32 (cpu
, value1
& value2
);
9774 /* 64 bit BIC shifted register setting flags. */
9776 bics64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9778 unsigned rm
= INSTR (20, 16);
9779 unsigned rn
= INSTR (9, 5);
9780 unsigned rd
= INSTR (4, 0);
9782 uint64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
9783 uint64_t value2
= ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
),
9786 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9787 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value1
& value2
);
9788 set_flags_for_binop64 (cpu
, value1
& value2
);
9791 /* 32 bit EON shifted register. */
9793 eon32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9795 unsigned rm
= INSTR (20, 16);
9796 unsigned rn
= INSTR (9, 5);
9797 unsigned rd
= INSTR (4, 0);
9799 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9801 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9802 ^ ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9805 /* 64 bit EON shifted register. */
9807 eon64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9809 unsigned rm
= INSTR (20, 16);
9810 unsigned rn
= INSTR (9, 5);
9811 unsigned rd
= INSTR (4, 0);
9813 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9815 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9816 ^ ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9819 /* 32 bit EOR shifted register. */
9821 eor32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9823 unsigned rm
= INSTR (20, 16);
9824 unsigned rn
= INSTR (9, 5);
9825 unsigned rd
= INSTR (4, 0);
9827 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9829 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9830 ^ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9833 /* 64 bit EOR shifted register. */
9835 eor64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9837 unsigned rm
= INSTR (20, 16);
9838 unsigned rn
= INSTR (9, 5);
9839 unsigned rd
= INSTR (4, 0);
9841 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9843 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9844 ^ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9847 /* 32 bit ORR shifted register. */
9849 orr32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9851 unsigned rm
= INSTR (20, 16);
9852 unsigned rn
= INSTR (9, 5);
9853 unsigned rd
= INSTR (4, 0);
9855 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9857 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9858 | shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9861 /* 64 bit ORR shifted register. */
9863 orr64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9865 unsigned rm
= INSTR (20, 16);
9866 unsigned rn
= INSTR (9, 5);
9867 unsigned rd
= INSTR (4, 0);
9869 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9871 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9872 | shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9875 /* 32 bit ORN shifted register. */
9877 orn32_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9879 unsigned rm
= INSTR (20, 16);
9880 unsigned rn
= INSTR (9, 5);
9881 unsigned rd
= INSTR (4, 0);
9883 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9885 (cpu
, rd
, NO_SP
, aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
9886 | ~ shifted32 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
), shift
, count
));
9889 /* 64 bit ORN shifted register. */
9891 orn64_shift (sim_cpu
*cpu
, Shift shift
, uint32_t count
)
9893 unsigned rm
= INSTR (20, 16);
9894 unsigned rn
= INSTR (9, 5);
9895 unsigned rd
= INSTR (4, 0);
9897 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9899 (cpu
, rd
, NO_SP
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
9900 | ~ shifted64 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
), shift
, count
));
9904 dexLogicalImmediate (sim_cpu
*cpu
)
9906 /* assert instr[28,23] = 1001000
9907 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9908 instr[30,29] = op : 0 ==> AND, 1 ==> ORR, 2 ==> EOR, 3 ==> ANDS
9909 instr[22] = N : used to construct immediate mask
9915 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
9916 uint32_t size
= INSTR (31, 31);
9917 uint32_t N
= INSTR (22, 22);
9918 /* uint32_t immr = INSTR (21, 16);. */
9919 /* uint32_t imms = INSTR (15, 10);. */
9920 uint32_t index
= INSTR (22, 10);
9921 uint64_t bimm64
= LITable
[index
];
9922 uint32_t dispatch
= INSTR (30, 29);
9932 uint32_t bimm
= (uint32_t) bimm64
;
9936 case 0: and32 (cpu
, bimm
); return;
9937 case 1: orr32 (cpu
, bimm
); return;
9938 case 2: eor32 (cpu
, bimm
); return;
9939 case 3: ands32 (cpu
, bimm
); return;
9946 case 0: and64 (cpu
, bimm64
); return;
9947 case 1: orr64 (cpu
, bimm64
); return;
9948 case 2: eor64 (cpu
, bimm64
); return;
9949 case 3: ands64 (cpu
, bimm64
); return;
9956 The uimm argument is a 16 bit value to be inserted into the
9957 target register the pos argument locates the 16 bit word in the
9958 dest register i.e. it is in {0, 1} for 32 bit and {0, 1, 2,
9960 N.B register arg may not be SP so it should be.
9961 accessed using the setGZRegisterXXX accessors. */
9963 /* 32 bit move 16 bit immediate zero remaining shorts. */
9965 movz32 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9967 unsigned rd
= INSTR (4, 0);
9969 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9970 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val
<< (pos
* 16));
9973 /* 64 bit move 16 bit immediate zero remaining shorts. */
9975 movz64 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9977 unsigned rd
= INSTR (4, 0);
9979 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9980 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, ((uint64_t) val
) << (pos
* 16));
9983 /* 32 bit move 16 bit immediate negated. */
9985 movn32 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9987 unsigned rd
= INSTR (4, 0);
9989 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
9990 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, ((val
<< (pos
* 16)) ^ 0xffffffffU
));
9993 /* 64 bit move 16 bit immediate negated. */
9995 movn64 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
9997 unsigned rd
= INSTR (4, 0);
9999 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10000 aarch64_set_reg_u64
10001 (cpu
, rd
, NO_SP
, ((((uint64_t) val
) << (pos
* 16))
10002 ^ 0xffffffffffffffffULL
));
10005 /* 32 bit move 16 bit immediate keep remaining shorts. */
10007 movk32 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
10009 unsigned rd
= INSTR (4, 0);
10010 uint32_t current
= aarch64_get_reg_u32 (cpu
, rd
, NO_SP
);
10011 uint32_t value
= val
<< (pos
* 16);
10012 uint32_t mask
= ~(0xffffU
<< (pos
* 16));
10014 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10015 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (value
| (current
& mask
)));
10018 /* 64 bit move 16 it immediate keep remaining shorts. */
10020 movk64 (sim_cpu
*cpu
, uint32_t val
, uint32_t pos
)
10022 unsigned rd
= INSTR (4, 0);
10023 uint64_t current
= aarch64_get_reg_u64 (cpu
, rd
, NO_SP
);
10024 uint64_t value
= (uint64_t) val
<< (pos
* 16);
10025 uint64_t mask
= ~(0xffffULL
<< (pos
* 16));
10027 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10028 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (value
| (current
& mask
)));
10032 dexMoveWideImmediate (sim_cpu
*cpu
)
10034 /* assert instr[28:23] = 100101
10035 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
10036 instr[30,29] = op : 0 ==> MOVN, 1 ==> UNALLOC, 2 ==> MOVZ, 3 ==> MOVK
10037 instr[22,21] = shift : 00 == LSL#0, 01 = LSL#16, 10 = LSL#32, 11 = LSL#48
10038 instr[20,5] = uimm16
10041 /* N.B. the (multiple of 16) shift is applied by the called routine,
10042 we just pass the multiplier. */
10045 uint32_t size
= INSTR (31, 31);
10046 uint32_t op
= INSTR (30, 29);
10047 uint32_t shift
= INSTR (22, 21);
10049 /* 32 bit can only shift 0 or 1 lot of 16.
10050 anything else is an unallocated instruction. */
10051 if (size
== 0 && (shift
> 1))
10057 imm
= INSTR (20, 5);
10062 movn32 (cpu
, imm
, shift
);
10064 movz32 (cpu
, imm
, shift
);
10066 movk32 (cpu
, imm
, shift
);
10071 movn64 (cpu
, imm
, shift
);
10073 movz64 (cpu
, imm
, shift
);
10075 movk64 (cpu
, imm
, shift
);
10079 /* Bitfield operations.
10080 These take a pair of bit positions r and s which are in {0..31}
10081 or {0..63} depending on the instruction word size.
10082 N.B register args may not be SP. */
10084 /* OK, we start with ubfm which just needs to pick
10085 some bits out of source zero the rest and write
10086 the result to dest. Just need two logical shifts. */
10088 /* 32 bit bitfield move, left and right of affected zeroed
10089 if r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
10091 ubfm32 (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
10094 unsigned rn
= INSTR (9, 5);
10095 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
10097 /* Pick either s+1-r or s+1 consecutive bits out of the original word. */
10100 /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
10101 We want only bits s:xxx:r at the bottom of the word
10102 so we LSL bit s up to bit 31 i.e. by 31 - s
10103 and then we LSR to bring bit 31 down to bit s - r
10104 i.e. by 31 + r - s. */
10106 value
>>= 31 + r
- s
;
10110 /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0
10111 We want only bits s:xxx:0 starting at it 31-(r-1)
10112 so we LSL bit s up to bit 31 i.e. by 31 - s
10113 and then we LSL to bring bit 31 down to 31-(r-1)+s
10114 i.e. by r - (s + 1). */
10116 value
>>= r
- (s
+ 1);
10119 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10121 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
10124 /* 64 bit bitfield move, left and right of affected zeroed
10125 if r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
10127 ubfm (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
10130 unsigned rn
= INSTR (9, 5);
10131 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
10135 /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
10136 We want only bits s:xxx:r at the bottom of the word.
10137 So we LSL bit s up to bit 63 i.e. by 63 - s
10138 and then we LSR to bring bit 63 down to bit s - r
10139 i.e. by 63 + r - s. */
10141 value
>>= 63 + r
- s
;
10145 /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0.
10146 We want only bits s:xxx:0 starting at it 63-(r-1).
10147 So we LSL bit s up to bit 63 i.e. by 63 - s
10148 and then we LSL to bring bit 63 down to 63-(r-1)+s
10149 i.e. by r - (s + 1). */
10151 value
>>= r
- (s
+ 1);
10154 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10156 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, value
);
10159 /* The signed versions need to insert sign bits
10160 on the left of the inserted bit field. so we do
10161 much the same as the unsigned version except we
10162 use an arithmetic shift right -- this just means
10163 we need to operate on signed values. */
10165 /* 32 bit bitfield move, left of affected sign-extended, right zeroed. */
10166 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
10168 sbfm32 (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
10171 unsigned rn
= INSTR (9, 5);
10172 /* as per ubfm32 but use an ASR instead of an LSR. */
10173 int32_t value
= aarch64_get_reg_s32 (cpu
, rn
, NO_SP
);
10178 value
>>= 31 + r
- s
;
10183 value
>>= r
- (s
+ 1);
10186 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10188 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, (uint32_t) value
);
10191 /* 64 bit bitfield move, left of affected sign-extended, right zeroed. */
10192 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
10194 sbfm (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
10197 unsigned rn
= INSTR (9, 5);
10198 /* acpu per ubfm but use an ASR instead of an LSR. */
10199 int64_t value
= aarch64_get_reg_s64 (cpu
, rn
, NO_SP
);
10204 value
>>= 63 + r
- s
;
10209 value
>>= r
- (s
+ 1);
10212 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10214 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, value
);
10217 /* Finally, these versions leave non-affected bits
10218 as is. so we need to generate the bits as per
10219 ubfm and also generate a mask to pick the
10220 bits from the original and computed values. */
10222 /* 32 bit bitfield move, non-affected bits left as is.
10223 If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>. */
10225 bfm32 (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
10227 unsigned rn
= INSTR (9, 5);
10228 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
10229 uint32_t mask
= -1;
10233 /* Pick either s+1-r or s+1 consecutive bits out of the original word. */
10236 /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
10237 We want only bits s:xxx:r at the bottom of the word
10238 so we LSL bit s up to bit 31 i.e. by 31 - s
10239 and then we LSR to bring bit 31 down to bit s - r
10240 i.e. by 31 + r - s. */
10242 value
>>= 31 + r
- s
;
10243 /* the mask must include the same bits. */
10245 mask
>>= 31 + r
- s
;
10249 /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0.
10250 We want only bits s:xxx:0 starting at it 31-(r-1)
10251 so we LSL bit s up to bit 31 i.e. by 31 - s
10252 and then we LSL to bring bit 31 down to 31-(r-1)+s
10253 i.e. by r - (s + 1). */
10255 value
>>= r
- (s
+ 1);
10256 /* The mask must include the same bits. */
10258 mask
>>= r
- (s
+ 1);
10262 value2
= aarch64_get_reg_u32 (cpu
, rd
, NO_SP
);
10267 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10268 aarch64_set_reg_u64
10269 (cpu
, rd
, NO_SP
, (aarch64_get_reg_u32 (cpu
, rd
, NO_SP
) & ~mask
) | value
);
10272 /* 64 bit bitfield move, non-affected bits left as is.
10273 If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>. */
10275 bfm (sim_cpu
*cpu
, uint32_t r
, uint32_t s
)
10278 unsigned rn
= INSTR (9, 5);
10279 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
10280 uint64_t mask
= 0xffffffffffffffffULL
;
10284 /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
10285 We want only bits s:xxx:r at the bottom of the word
10286 so we LSL bit s up to bit 63 i.e. by 63 - s
10287 and then we LSR to bring bit 63 down to bit s - r
10288 i.e. by 63 + r - s. */
10290 value
>>= 63 + r
- s
;
10291 /* The mask must include the same bits. */
10293 mask
>>= 63 + r
- s
;
10297 /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0
10298 We want only bits s:xxx:0 starting at it 63-(r-1)
10299 so we LSL bit s up to bit 63 i.e. by 63 - s
10300 and then we LSL to bring bit 63 down to 63-(r-1)+s
10301 i.e. by r - (s + 1). */
10303 value
>>= r
- (s
+ 1);
10304 /* The mask must include the same bits. */
10306 mask
>>= r
- (s
+ 1);
10309 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10311 aarch64_set_reg_u64
10312 (cpu
, rd
, NO_SP
, (aarch64_get_reg_u64 (cpu
, rd
, NO_SP
) & ~mask
) | value
);
10316 dexBitfieldImmediate (sim_cpu
*cpu
)
10318 /* assert instr[28:23] = 100110
10319 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
10320 instr[30,29] = op : 0 ==> SBFM, 1 ==> BFM, 2 ==> UBFM, 3 ==> UNALLOC
10321 instr[22] = N : must be 0 for 32 bit, 1 for 64 bit ow UNALLOC
10322 instr[21,16] = immr : 0xxxxx for 32 bit, xxxxxx for 64 bit
10323 instr[15,10] = imms : 0xxxxx for 32 bit, xxxxxx for 64 bit
10327 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
10330 uint32_t size
= INSTR (31, 31);
10331 uint32_t N
= INSTR (22, 22);
10332 /* 32 bit operations must have immr[5] = 0 and imms[5] = 0. */
10333 /* or else we have an UNALLOC. */
10334 uint32_t immr
= INSTR (21, 16);
10339 if (!size
&& uimm (immr
, 5, 5))
10342 imms
= INSTR (15, 10);
10343 if (!size
&& uimm (imms
, 5, 5))
10346 /* Switch on combined size and op. */
10347 dispatch
= INSTR (31, 29);
10350 case 0: sbfm32 (cpu
, immr
, imms
); return;
10351 case 1: bfm32 (cpu
, immr
, imms
); return;
10352 case 2: ubfm32 (cpu
, immr
, imms
); return;
10353 case 4: sbfm (cpu
, immr
, imms
); return;
10354 case 5: bfm (cpu
, immr
, imms
); return;
10355 case 6: ubfm (cpu
, immr
, imms
); return;
10356 default: HALT_UNALLOC
;
10361 do_EXTR_32 (sim_cpu
*cpu
)
10363 /* instr[31:21] = 00010011100
10365 instr[15,10] = imms : 0xxxxx for 32 bit
10368 unsigned rm
= INSTR (20, 16);
10369 unsigned imms
= INSTR (15, 10) & 31;
10370 unsigned rn
= INSTR ( 9, 5);
10371 unsigned rd
= INSTR ( 4, 0);
10375 val1
= aarch64_get_reg_u32 (cpu
, rm
, NO_SP
);
10377 val2
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
10378 val2
<<= (32 - imms
);
10380 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
10381 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val1
| val2
);
10385 do_EXTR_64 (sim_cpu
*cpu
)
10387 /* instr[31:21] = 10010011100
10389 instr[15,10] = imms
10392 unsigned rm
= INSTR (20, 16);
10393 unsigned imms
= INSTR (15, 10) & 63;
10394 unsigned rn
= INSTR ( 9, 5);
10395 unsigned rd
= INSTR ( 4, 0);
10398 val
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
10400 val
|= (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) << (64 - imms
));
10402 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, val
);
10406 dexExtractImmediate (sim_cpu
*cpu
)
10408 /* assert instr[28:23] = 100111
10409 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
10410 instr[30,29] = op21 : 0 ==> EXTR, 1,2,3 ==> UNALLOC
10411 instr[22] = N : must be 0 for 32 bit, 1 for 64 bit or UNALLOC
10412 instr[21] = op0 : must be 0 or UNALLOC
10414 instr[15,10] = imms : 0xxxxx for 32 bit, xxxxxx for 64 bit
10418 /* 32 bit operations must have N = 0 or else we have an UNALLOC. */
10419 /* 64 bit operations must have N = 1 or else we have an UNALLOC. */
10421 uint32_t size
= INSTR (31, 31);
10422 uint32_t N
= INSTR (22, 22);
10423 /* 32 bit operations must have imms[5] = 0
10424 or else we have an UNALLOC. */
10425 uint32_t imms
= INSTR (15, 10);
10430 if (!size
&& uimm (imms
, 5, 5))
10433 /* Switch on combined size and op. */
10434 dispatch
= INSTR (31, 29);
10439 else if (dispatch
== 4)
10442 else if (dispatch
== 1)
10449 dexDPImm (sim_cpu
*cpu
)
10451 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
10452 assert group == GROUP_DPIMM_1000 || grpoup == GROUP_DPIMM_1001
10453 bits [25,23] of a DPImm are the secondary dispatch vector. */
10454 uint32_t group2
= dispatchDPImm (aarch64_get_instr (cpu
));
10458 case DPIMM_PCADR_000
:
10459 case DPIMM_PCADR_001
:
10460 dexPCRelAddressing (cpu
);
10463 case DPIMM_ADDSUB_010
:
10464 case DPIMM_ADDSUB_011
:
10465 dexAddSubtractImmediate (cpu
);
10468 case DPIMM_LOG_100
:
10469 dexLogicalImmediate (cpu
);
10472 case DPIMM_MOV_101
:
10473 dexMoveWideImmediate (cpu
);
10476 case DPIMM_BITF_110
:
10477 dexBitfieldImmediate (cpu
);
10480 case DPIMM_EXTR_111
:
10481 dexExtractImmediate (cpu
);
10485 /* Should never reach here. */
10491 dexLoadUnscaledImmediate (sim_cpu
*cpu
)
10493 /* instr[29,24] == 111_00
10496 instr[31,30] = size
10499 instr[20,12] = simm9
10500 instr[9,5] = rn may be SP. */
10501 /* unsigned rt = INSTR (4, 0); */
10502 uint32_t V
= INSTR (26, 26);
10503 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
10504 int32_t imm
= simm32 (aarch64_get_instr (cpu
), 20, 12);
10508 /* GReg operations. */
10511 case 0: sturb (cpu
, imm
); return;
10512 case 1: ldurb32 (cpu
, imm
); return;
10513 case 2: ldursb64 (cpu
, imm
); return;
10514 case 3: ldursb32 (cpu
, imm
); return;
10515 case 4: sturh (cpu
, imm
); return;
10516 case 5: ldurh32 (cpu
, imm
); return;
10517 case 6: ldursh64 (cpu
, imm
); return;
10518 case 7: ldursh32 (cpu
, imm
); return;
10519 case 8: stur32 (cpu
, imm
); return;
10520 case 9: ldur32 (cpu
, imm
); return;
10521 case 10: ldursw (cpu
, imm
); return;
10522 case 12: stur64 (cpu
, imm
); return;
10523 case 13: ldur64 (cpu
, imm
); return;
10536 /* FReg operations. */
10539 case 2: fsturq (cpu
, imm
); return;
10540 case 3: fldurq (cpu
, imm
); return;
10541 case 8: fsturs (cpu
, imm
); return;
10542 case 9: fldurs (cpu
, imm
); return;
10543 case 12: fsturd (cpu
, imm
); return;
10544 case 13: fldurd (cpu
, imm
); return;
10546 case 0: /* STUR 8 bit FP. */
10547 case 1: /* LDUR 8 bit FP. */
10548 case 4: /* STUR 16 bit FP. */
10549 case 5: /* LDUR 8 bit FP. */
10563 /* N.B. A preliminary note regarding all the ldrs<x>32
10566 The signed value loaded by these instructions is cast to unsigned
10567 before being assigned to aarch64_get_reg_u64 (cpu, N) i.e. to the
10568 64 bit element of the GReg union. this performs a 32 bit sign extension
10569 (as required) but avoids 64 bit sign extension, thus ensuring that the
10570 top half of the register word is zero. this is what the spec demands
10571 when a 32 bit load occurs. */
10573 /* 32 bit load sign-extended byte scaled unsigned 12 bit. */
10575 ldrsb32_abs (sim_cpu
*cpu
, uint32_t offset
)
10577 unsigned int rn
= INSTR (9, 5);
10578 unsigned int rt
= INSTR (4, 0);
10580 /* The target register may not be SP but the source may be
10581 there is no scaling required for a byte load. */
10582 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
;
10583 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
10584 (int64_t) aarch64_get_mem_s8 (cpu
, address
));
10587 /* 32 bit load sign-extended byte scaled or unscaled zero-
10588 or sign-extended 32-bit register offset. */
10590 ldrsb32_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10592 unsigned int rm
= INSTR (20, 16);
10593 unsigned int rn
= INSTR (9, 5);
10594 unsigned int rt
= INSTR (4, 0);
10596 /* rn may reference SP, rm and rt must reference ZR. */
10598 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10599 int64_t displacement
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10602 /* There is no scaling required for a byte load. */
10603 aarch64_set_reg_u64
10604 (cpu
, rt
, NO_SP
, (int64_t) aarch64_get_mem_s8 (cpu
, address
10608 /* 32 bit load sign-extended byte unscaled signed 9 bit with
10609 pre- or post-writeback. */
10611 ldrsb32_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10614 unsigned int rn
= INSTR (9, 5);
10615 unsigned int rt
= INSTR (4, 0);
10617 if (rn
== rt
&& wb
!= NoWriteBack
)
10620 address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10625 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
10626 (int64_t) aarch64_get_mem_s8 (cpu
, address
));
10631 if (wb
!= NoWriteBack
)
10632 aarch64_set_reg_u64 (cpu
, rn
, NO_SP
, address
);
10635 /* 8 bit store scaled. */
10637 fstrb_abs (sim_cpu
*cpu
, uint32_t offset
)
10639 unsigned st
= INSTR (4, 0);
10640 unsigned rn
= INSTR (9, 5);
10642 aarch64_set_mem_u8 (cpu
,
10643 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + offset
,
10644 aarch64_get_vec_u8 (cpu
, st
, 0));
10647 /* 8 bit store scaled or unscaled zero- or
10648 sign-extended 8-bit register offset. */
10650 fstrb_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10652 unsigned rm
= INSTR (20, 16);
10653 unsigned rn
= INSTR (9, 5);
10654 unsigned st
= INSTR (4, 0);
10656 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10657 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10659 uint64_t displacement
= scaling
== Scaled
? extended
: 0;
10662 (cpu
, address
+ displacement
, aarch64_get_vec_u8 (cpu
, st
, 0));
10665 /* 16 bit store scaled. */
10667 fstrh_abs (sim_cpu
*cpu
, uint32_t offset
)
10669 unsigned st
= INSTR (4, 0);
10670 unsigned rn
= INSTR (9, 5);
10672 aarch64_set_mem_u16
10674 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 16),
10675 aarch64_get_vec_u16 (cpu
, st
, 0));
10678 /* 16 bit store scaled or unscaled zero-
10679 or sign-extended 16-bit register offset. */
10681 fstrh_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10683 unsigned rm
= INSTR (20, 16);
10684 unsigned rn
= INSTR (9, 5);
10685 unsigned st
= INSTR (4, 0);
10687 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10688 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10690 uint64_t displacement
= OPT_SCALE (extended
, 16, scaling
);
10692 aarch64_set_mem_u16
10693 (cpu
, address
+ displacement
, aarch64_get_vec_u16 (cpu
, st
, 0));
10696 /* 32 bit store scaled unsigned 12 bit. */
10698 fstrs_abs (sim_cpu
*cpu
, uint32_t offset
)
10700 unsigned st
= INSTR (4, 0);
10701 unsigned rn
= INSTR (9, 5);
10703 aarch64_set_mem_u32
10705 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 32),
10706 aarch64_get_vec_u32 (cpu
, st
, 0));
10709 /* 32 bit store unscaled signed 9 bit with pre- or post-writeback. */
10711 fstrs_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10713 unsigned rn
= INSTR (9, 5);
10714 unsigned st
= INSTR (4, 0);
10716 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10721 aarch64_set_mem_u32 (cpu
, address
, aarch64_get_vec_u32 (cpu
, st
, 0));
10726 if (wb
!= NoWriteBack
)
10727 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
10730 /* 32 bit store scaled or unscaled zero-
10731 or sign-extended 32-bit register offset. */
10733 fstrs_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10735 unsigned rm
= INSTR (20, 16);
10736 unsigned rn
= INSTR (9, 5);
10737 unsigned st
= INSTR (4, 0);
10739 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10740 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10742 uint64_t displacement
= OPT_SCALE (extended
, 32, scaling
);
10744 aarch64_set_mem_u32
10745 (cpu
, address
+ displacement
, aarch64_get_vec_u32 (cpu
, st
, 0));
10748 /* 64 bit store scaled unsigned 12 bit. */
10750 fstrd_abs (sim_cpu
*cpu
, uint32_t offset
)
10752 unsigned st
= INSTR (4, 0);
10753 unsigned rn
= INSTR (9, 5);
10755 aarch64_set_mem_u64
10757 aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 64),
10758 aarch64_get_vec_u64 (cpu
, st
, 0));
10761 /* 64 bit store unscaled signed 9 bit with pre- or post-writeback. */
10763 fstrd_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10765 unsigned rn
= INSTR (9, 5);
10766 unsigned st
= INSTR (4, 0);
10768 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10773 aarch64_set_mem_u64 (cpu
, address
, aarch64_get_vec_u64 (cpu
, st
, 0));
10778 if (wb
!= NoWriteBack
)
10779 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
10782 /* 64 bit store scaled or unscaled zero-
10783 or sign-extended 32-bit register offset. */
10785 fstrd_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10787 unsigned rm
= INSTR (20, 16);
10788 unsigned rn
= INSTR (9, 5);
10789 unsigned st
= INSTR (4, 0);
10791 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10792 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10794 uint64_t displacement
= OPT_SCALE (extended
, 64, scaling
);
10796 aarch64_set_mem_u64
10797 (cpu
, address
+ displacement
, aarch64_get_vec_u64 (cpu
, st
, 0));
10800 /* 128 bit store scaled unsigned 12 bit. */
10802 fstrq_abs (sim_cpu
*cpu
, uint32_t offset
)
10805 unsigned st
= INSTR (4, 0);
10806 unsigned rn
= INSTR (9, 5);
10809 aarch64_get_FP_long_double (cpu
, st
, & a
);
10811 addr
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
) + SCALE (offset
, 128);
10812 aarch64_set_mem_long_double (cpu
, addr
, a
);
10815 /* 128 bit store unscaled signed 9 bit with pre- or post-writeback. */
10817 fstrq_wb (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
10820 unsigned rn
= INSTR (9, 5);
10821 unsigned st
= INSTR (4, 0);
10822 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10827 aarch64_get_FP_long_double (cpu
, st
, & a
);
10828 aarch64_set_mem_long_double (cpu
, address
, a
);
10833 if (wb
!= NoWriteBack
)
10834 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, address
);
10837 /* 128 bit store scaled or unscaled zero-
10838 or sign-extended 32-bit register offset. */
10840 fstrq_scale_ext (sim_cpu
*cpu
, Scaling scaling
, Extension extension
)
10842 unsigned rm
= INSTR (20, 16);
10843 unsigned rn
= INSTR (9, 5);
10844 unsigned st
= INSTR (4, 0);
10846 uint64_t address
= aarch64_get_reg_u64 (cpu
, rn
, SP_OK
);
10847 int64_t extended
= extend (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
),
10849 uint64_t displacement
= OPT_SCALE (extended
, 128, scaling
);
10853 aarch64_get_FP_long_double (cpu
, st
, & a
);
10854 aarch64_set_mem_long_double (cpu
, address
+ displacement
, a
);
10858 dexLoadImmediatePrePost (sim_cpu
*cpu
)
10860 /* instr[31,30] = size
10866 instr[20,12] = simm9
10867 instr[11] = wb : 0 ==> Post, 1 ==> Pre
10869 instr[9,5] = Rn may be SP.
10872 uint32_t V
= INSTR (26, 26);
10873 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
10874 int32_t imm
= simm32 (aarch64_get_instr (cpu
), 20, 12);
10875 WriteBack wb
= INSTR (11, 11);
10879 /* GReg operations. */
10882 case 0: strb_wb (cpu
, imm
, wb
); return;
10883 case 1: ldrb32_wb (cpu
, imm
, wb
); return;
10884 case 2: ldrsb_wb (cpu
, imm
, wb
); return;
10885 case 3: ldrsb32_wb (cpu
, imm
, wb
); return;
10886 case 4: strh_wb (cpu
, imm
, wb
); return;
10887 case 5: ldrh32_wb (cpu
, imm
, wb
); return;
10888 case 6: ldrsh64_wb (cpu
, imm
, wb
); return;
10889 case 7: ldrsh32_wb (cpu
, imm
, wb
); return;
10890 case 8: str32_wb (cpu
, imm
, wb
); return;
10891 case 9: ldr32_wb (cpu
, imm
, wb
); return;
10892 case 10: ldrsw_wb (cpu
, imm
, wb
); return;
10893 case 12: str_wb (cpu
, imm
, wb
); return;
10894 case 13: ldr_wb (cpu
, imm
, wb
); return;
10904 /* FReg operations. */
10907 case 2: fstrq_wb (cpu
, imm
, wb
); return;
10908 case 3: fldrq_wb (cpu
, imm
, wb
); return;
10909 case 8: fstrs_wb (cpu
, imm
, wb
); return;
10910 case 9: fldrs_wb (cpu
, imm
, wb
); return;
10911 case 12: fstrd_wb (cpu
, imm
, wb
); return;
10912 case 13: fldrd_wb (cpu
, imm
, wb
); return;
10914 case 0: /* STUR 8 bit FP. */
10915 case 1: /* LDUR 8 bit FP. */
10916 case 4: /* STUR 16 bit FP. */
10917 case 5: /* LDUR 8 bit FP. */
10932 dexLoadRegisterOffset (sim_cpu
*cpu
)
10934 /* instr[31,30] = size
10941 instr[15,13] = option : 010 ==> UXTW, 011 ==> UXTX/LSL,
10942 110 ==> SXTW, 111 ==> SXTX,
10947 instr[4,0] = rt. */
10949 uint32_t V
= INSTR (26, 26);
10950 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
10951 Scaling scale
= INSTR (12, 12);
10952 Extension extensionType
= INSTR (15, 13);
10954 /* Check for illegal extension types. */
10955 if (uimm (extensionType
, 1, 1) == 0)
10958 if (extensionType
== UXTX
|| extensionType
== SXTX
)
10959 extensionType
= NoExtension
;
10963 /* GReg operations. */
10966 case 0: strb_scale_ext (cpu
, scale
, extensionType
); return;
10967 case 1: ldrb32_scale_ext (cpu
, scale
, extensionType
); return;
10968 case 2: ldrsb_scale_ext (cpu
, scale
, extensionType
); return;
10969 case 3: ldrsb32_scale_ext (cpu
, scale
, extensionType
); return;
10970 case 4: strh_scale_ext (cpu
, scale
, extensionType
); return;
10971 case 5: ldrh32_scale_ext (cpu
, scale
, extensionType
); return;
10972 case 6: ldrsh_scale_ext (cpu
, scale
, extensionType
); return;
10973 case 7: ldrsh32_scale_ext (cpu
, scale
, extensionType
); return;
10974 case 8: str32_scale_ext (cpu
, scale
, extensionType
); return;
10975 case 9: ldr32_scale_ext (cpu
, scale
, extensionType
); return;
10976 case 10: ldrsw_scale_ext (cpu
, scale
, extensionType
); return;
10977 case 12: str_scale_ext (cpu
, scale
, extensionType
); return;
10978 case 13: ldr_scale_ext (cpu
, scale
, extensionType
); return;
10979 case 14: prfm_scale_ext (cpu
, scale
, extensionType
); return;
10988 /* FReg operations. */
10991 case 1: /* LDUR 8 bit FP. */
10993 case 3: fldrq_scale_ext (cpu
, scale
, extensionType
); return;
10994 case 5: /* LDUR 8 bit FP. */
10996 case 9: fldrs_scale_ext (cpu
, scale
, extensionType
); return;
10997 case 13: fldrd_scale_ext (cpu
, scale
, extensionType
); return;
10999 case 0: fstrb_scale_ext (cpu
, scale
, extensionType
); return;
11000 case 2: fstrq_scale_ext (cpu
, scale
, extensionType
); return;
11001 case 4: fstrh_scale_ext (cpu
, scale
, extensionType
); return;
11002 case 8: fstrs_scale_ext (cpu
, scale
, extensionType
); return;
11003 case 12: fstrd_scale_ext (cpu
, scale
, extensionType
); return;
11017 dexLoadUnsignedImmediate (sim_cpu
*cpu
)
11019 /* instr[29,24] == 111_01
11020 instr[31,30] = size
11023 instr[21,10] = uimm12 : unsigned immediate offset
11024 instr[9,5] = rn may be SP.
11025 instr[4,0] = rt. */
11027 uint32_t V
= INSTR (26,26);
11028 uint32_t dispatch
= ((INSTR (31, 30) << 2) | INSTR (23, 22));
11029 uint32_t imm
= INSTR (21, 10);
11033 /* GReg operations. */
11036 case 0: strb_abs (cpu
, imm
); return;
11037 case 1: ldrb32_abs (cpu
, imm
); return;
11038 case 2: ldrsb_abs (cpu
, imm
); return;
11039 case 3: ldrsb32_abs (cpu
, imm
); return;
11040 case 4: strh_abs (cpu
, imm
); return;
11041 case 5: ldrh32_abs (cpu
, imm
); return;
11042 case 6: ldrsh_abs (cpu
, imm
); return;
11043 case 7: ldrsh32_abs (cpu
, imm
); return;
11044 case 8: str32_abs (cpu
, imm
); return;
11045 case 9: ldr32_abs (cpu
, imm
); return;
11046 case 10: ldrsw_abs (cpu
, imm
); return;
11047 case 12: str_abs (cpu
, imm
); return;
11048 case 13: ldr_abs (cpu
, imm
); return;
11049 case 14: prfm_abs (cpu
, imm
); return;
11058 /* FReg operations. */
11061 case 0: fstrb_abs (cpu
, imm
); return;
11062 case 4: fstrh_abs (cpu
, imm
); return;
11063 case 8: fstrs_abs (cpu
, imm
); return;
11064 case 12: fstrd_abs (cpu
, imm
); return;
11065 case 2: fstrq_abs (cpu
, imm
); return;
11067 case 1: fldrb_abs (cpu
, imm
); return;
11068 case 5: fldrh_abs (cpu
, imm
); return;
11069 case 9: fldrs_abs (cpu
, imm
); return;
11070 case 13: fldrd_abs (cpu
, imm
); return;
11071 case 3: fldrq_abs (cpu
, imm
); return;
11085 dexLoadExclusive (sim_cpu
*cpu
)
11087 /* assert instr[29:24] = 001000;
11088 instr[31,30] = size
11089 instr[23] = 0 if exclusive
11090 instr[22] = L : 1 if load, 0 if store
11091 instr[21] = 1 if pair
11093 instr[15] = o0 : 1 if ordered
11096 instr[4.0] = Rt. */
11098 switch (INSTR (22, 21))
11100 case 2: ldxr (cpu
); return;
11101 case 0: stxr (cpu
); return;
11107 dexLoadOther (sim_cpu
*cpu
)
11111 /* instr[29,25] = 111_0
11112 instr[24] == 0 ==> dispatch, 1 ==> ldst reg unsigned immediate
11113 instr[21:11,10] is the secondary dispatch. */
11114 if (INSTR (24, 24))
11116 dexLoadUnsignedImmediate (cpu
);
11120 dispatch
= ((INSTR (21, 21) << 2) | INSTR (11, 10));
11123 case 0: dexLoadUnscaledImmediate (cpu
); return;
11124 case 1: dexLoadImmediatePrePost (cpu
); return;
11125 case 3: dexLoadImmediatePrePost (cpu
); return;
11126 case 6: dexLoadRegisterOffset (cpu
); return;
11138 store_pair_u32 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11140 unsigned rn
= INSTR (14, 10);
11141 unsigned rd
= INSTR (9, 5);
11142 unsigned rm
= INSTR (4, 0);
11143 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11145 if ((rn
== rd
|| rm
== rd
) && wb
!= NoWriteBack
)
11146 HALT_UNALLOC
; /* ??? */
11153 aarch64_set_mem_u32 (cpu
, address
,
11154 aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
11155 aarch64_set_mem_u32 (cpu
, address
+ 4,
11156 aarch64_get_reg_u32 (cpu
, rn
, NO_SP
));
11161 if (wb
!= NoWriteBack
)
11162 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11166 store_pair_u64 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11168 unsigned rn
= INSTR (14, 10);
11169 unsigned rd
= INSTR (9, 5);
11170 unsigned rm
= INSTR (4, 0);
11171 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11173 if ((rn
== rd
|| rm
== rd
) && wb
!= NoWriteBack
)
11174 HALT_UNALLOC
; /* ??? */
11181 aarch64_set_mem_u64 (cpu
, address
,
11182 aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
11183 aarch64_set_mem_u64 (cpu
, address
+ 8,
11184 aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
11189 if (wb
!= NoWriteBack
)
11190 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11194 load_pair_u32 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11196 unsigned rn
= INSTR (14, 10);
11197 unsigned rd
= INSTR (9, 5);
11198 unsigned rm
= INSTR (4, 0);
11199 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11201 /* Treat this as unalloc to make sure we don't do it. */
11210 aarch64_set_reg_u64 (cpu
, rm
, SP_OK
, aarch64_get_mem_u32 (cpu
, address
));
11211 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, aarch64_get_mem_u32 (cpu
, address
+ 4));
11216 if (wb
!= NoWriteBack
)
11217 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11221 load_pair_s32 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11223 unsigned rn
= INSTR (14, 10);
11224 unsigned rd
= INSTR (9, 5);
11225 unsigned rm
= INSTR (4, 0);
11226 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11228 /* Treat this as unalloc to make sure we don't do it. */
11237 aarch64_set_reg_s64 (cpu
, rm
, SP_OK
, aarch64_get_mem_s32 (cpu
, address
));
11238 aarch64_set_reg_s64 (cpu
, rn
, SP_OK
, aarch64_get_mem_s32 (cpu
, address
+ 4));
11243 if (wb
!= NoWriteBack
)
11244 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11248 load_pair_u64 (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11250 unsigned rn
= INSTR (14, 10);
11251 unsigned rd
= INSTR (9, 5);
11252 unsigned rm
= INSTR (4, 0);
11253 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11255 /* Treat this as unalloc to make sure we don't do it. */
11264 aarch64_set_reg_u64 (cpu
, rm
, SP_OK
, aarch64_get_mem_u64 (cpu
, address
));
11265 aarch64_set_reg_u64 (cpu
, rn
, SP_OK
, aarch64_get_mem_u64 (cpu
, address
+ 8));
11270 if (wb
!= NoWriteBack
)
11271 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11275 dex_load_store_pair_gr (sim_cpu
*cpu
)
11277 /* instr[31,30] = size (10=> 64-bit, 01=> signed 32-bit, 00=> 32-bit)
11278 instr[29,25] = instruction encoding: 101_0
11279 instr[26] = V : 1 if fp 0 if gp
11280 instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
11281 instr[22] = load/store (1=> load)
11282 instr[21,15] = signed, scaled, offset
11285 instr[ 4, 0] = Rm. */
11287 uint32_t dispatch
= ((INSTR (31, 30) << 3) | INSTR (24, 22));
11288 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 21, 15);
11292 case 2: store_pair_u32 (cpu
, offset
, Post
); return;
11293 case 3: load_pair_u32 (cpu
, offset
, Post
); return;
11294 case 4: store_pair_u32 (cpu
, offset
, NoWriteBack
); return;
11295 case 5: load_pair_u32 (cpu
, offset
, NoWriteBack
); return;
11296 case 6: store_pair_u32 (cpu
, offset
, Pre
); return;
11297 case 7: load_pair_u32 (cpu
, offset
, Pre
); return;
11299 case 11: load_pair_s32 (cpu
, offset
, Post
); return;
11300 case 13: load_pair_s32 (cpu
, offset
, NoWriteBack
); return;
11301 case 15: load_pair_s32 (cpu
, offset
, Pre
); return;
11303 case 18: store_pair_u64 (cpu
, offset
, Post
); return;
11304 case 19: load_pair_u64 (cpu
, offset
, Post
); return;
11305 case 20: store_pair_u64 (cpu
, offset
, NoWriteBack
); return;
11306 case 21: load_pair_u64 (cpu
, offset
, NoWriteBack
); return;
11307 case 22: store_pair_u64 (cpu
, offset
, Pre
); return;
11308 case 23: load_pair_u64 (cpu
, offset
, Pre
); return;
11316 store_pair_float (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11318 unsigned rn
= INSTR (14, 10);
11319 unsigned rd
= INSTR (9, 5);
11320 unsigned rm
= INSTR (4, 0);
11321 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11328 aarch64_set_mem_u32 (cpu
, address
, aarch64_get_vec_u32 (cpu
, rm
, 0));
11329 aarch64_set_mem_u32 (cpu
, address
+ 4, aarch64_get_vec_u32 (cpu
, rn
, 0));
11334 if (wb
!= NoWriteBack
)
11335 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11339 store_pair_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11341 unsigned rn
= INSTR (14, 10);
11342 unsigned rd
= INSTR (9, 5);
11343 unsigned rm
= INSTR (4, 0);
11344 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11351 aarch64_set_mem_u64 (cpu
, address
, aarch64_get_vec_u64 (cpu
, rm
, 0));
11352 aarch64_set_mem_u64 (cpu
, address
+ 8, aarch64_get_vec_u64 (cpu
, rn
, 0));
11357 if (wb
!= NoWriteBack
)
11358 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11362 store_pair_long_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11365 unsigned rn
= INSTR (14, 10);
11366 unsigned rd
= INSTR (9, 5);
11367 unsigned rm
= INSTR (4, 0);
11368 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11375 aarch64_get_FP_long_double (cpu
, rm
, & a
);
11376 aarch64_set_mem_long_double (cpu
, address
, a
);
11377 aarch64_get_FP_long_double (cpu
, rn
, & a
);
11378 aarch64_set_mem_long_double (cpu
, address
+ 16, a
);
11383 if (wb
!= NoWriteBack
)
11384 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11388 load_pair_float (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11390 unsigned rn
= INSTR (14, 10);
11391 unsigned rd
= INSTR (9, 5);
11392 unsigned rm
= INSTR (4, 0);
11393 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11403 aarch64_set_vec_u32 (cpu
, rm
, 0, aarch64_get_mem_u32 (cpu
, address
));
11404 aarch64_set_vec_u32 (cpu
, rn
, 0, aarch64_get_mem_u32 (cpu
, address
+ 4));
11409 if (wb
!= NoWriteBack
)
11410 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11414 load_pair_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11416 unsigned rn
= INSTR (14, 10);
11417 unsigned rd
= INSTR (9, 5);
11418 unsigned rm
= INSTR (4, 0);
11419 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11429 aarch64_set_vec_u64 (cpu
, rm
, 0, aarch64_get_mem_u64 (cpu
, address
));
11430 aarch64_set_vec_u64 (cpu
, rn
, 0, aarch64_get_mem_u64 (cpu
, address
+ 8));
11435 if (wb
!= NoWriteBack
)
11436 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11440 load_pair_long_double (sim_cpu
*cpu
, int32_t offset
, WriteBack wb
)
11443 unsigned rn
= INSTR (14, 10);
11444 unsigned rd
= INSTR (9, 5);
11445 unsigned rm
= INSTR (4, 0);
11446 uint64_t address
= aarch64_get_reg_u64 (cpu
, rd
, SP_OK
);
11456 aarch64_get_mem_long_double (cpu
, address
, & a
);
11457 aarch64_set_FP_long_double (cpu
, rm
, a
);
11458 aarch64_get_mem_long_double (cpu
, address
+ 16, & a
);
11459 aarch64_set_FP_long_double (cpu
, rn
, a
);
11464 if (wb
!= NoWriteBack
)
11465 aarch64_set_reg_u64 (cpu
, rd
, SP_OK
, address
);
11469 dex_load_store_pair_fp (sim_cpu
*cpu
)
11471 /* instr[31,30] = size (10=> 128-bit, 01=> 64-bit, 00=> 32-bit)
11472 instr[29,25] = instruction encoding
11473 instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
11474 instr[22] = load/store (1=> load)
11475 instr[21,15] = signed, scaled, offset
11478 instr[ 4, 0] = Rm */
11480 uint32_t dispatch
= ((INSTR (31, 30) << 3) | INSTR (24, 22));
11481 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 21, 15);
11485 case 2: store_pair_float (cpu
, offset
, Post
); return;
11486 case 3: load_pair_float (cpu
, offset
, Post
); return;
11487 case 4: store_pair_float (cpu
, offset
, NoWriteBack
); return;
11488 case 5: load_pair_float (cpu
, offset
, NoWriteBack
); return;
11489 case 6: store_pair_float (cpu
, offset
, Pre
); return;
11490 case 7: load_pair_float (cpu
, offset
, Pre
); return;
11492 case 10: store_pair_double (cpu
, offset
, Post
); return;
11493 case 11: load_pair_double (cpu
, offset
, Post
); return;
11494 case 12: store_pair_double (cpu
, offset
, NoWriteBack
); return;
11495 case 13: load_pair_double (cpu
, offset
, NoWriteBack
); return;
11496 case 14: store_pair_double (cpu
, offset
, Pre
); return;
11497 case 15: load_pair_double (cpu
, offset
, Pre
); return;
11499 case 18: store_pair_long_double (cpu
, offset
, Post
); return;
11500 case 19: load_pair_long_double (cpu
, offset
, Post
); return;
11501 case 20: store_pair_long_double (cpu
, offset
, NoWriteBack
); return;
11502 case 21: load_pair_long_double (cpu
, offset
, NoWriteBack
); return;
11503 case 22: store_pair_long_double (cpu
, offset
, Pre
); return;
11504 case 23: load_pair_long_double (cpu
, offset
, Pre
); return;
11511 static inline unsigned
11512 vec_reg (unsigned v
, unsigned o
)
11514 return (v
+ o
) & 0x3F;
11517 /* Load multiple N-element structures to M consecutive registers. */
11519 vec_load (sim_cpu
*cpu
, uint64_t address
, unsigned N
, unsigned M
)
11521 int all
= INSTR (30, 30);
11522 unsigned size
= INSTR (11, 10);
11523 unsigned vd
= INSTR (4, 0);
11524 unsigned rpt
= (N
== M
) ? 1 : M
;
11525 unsigned selem
= N
;
11530 case 0: /* 8-bit operations. */
11531 for (i
= 0; i
< rpt
; i
++)
11532 for (j
= 0; j
< (8 + (8 * all
)); j
++)
11533 for (k
= 0; k
< selem
; k
++)
11535 aarch64_set_vec_u8 (cpu
, vec_reg (vd
, i
+ k
), j
,
11536 aarch64_get_mem_u8 (cpu
, address
));
11541 case 1: /* 16-bit operations. */
11542 for (i
= 0; i
< rpt
; i
++)
11543 for (j
= 0; j
< (4 + (4 * all
)); j
++)
11544 for (k
= 0; k
< selem
; k
++)
11546 aarch64_set_vec_u16 (cpu
, vec_reg (vd
, i
+ k
), j
,
11547 aarch64_get_mem_u16 (cpu
, address
));
11552 case 2: /* 32-bit operations. */
11553 for (i
= 0; i
< rpt
; i
++)
11554 for (j
= 0; j
< (2 + (2 * all
)); j
++)
11555 for (k
= 0; k
< selem
; k
++)
11557 aarch64_set_vec_u32 (cpu
, vec_reg (vd
, i
+ k
), j
,
11558 aarch64_get_mem_u32 (cpu
, address
));
11563 case 3: /* 64-bit operations. */
11564 for (i
= 0; i
< rpt
; i
++)
11565 for (j
= 0; j
< (1 + all
); j
++)
11566 for (k
= 0; k
< selem
; k
++)
11568 aarch64_set_vec_u64 (cpu
, vec_reg (vd
, i
+ k
), j
,
11569 aarch64_get_mem_u64 (cpu
, address
));
11576 /* Load multiple 4-element structures into four consecutive registers. */
11578 LD4 (sim_cpu
*cpu
, uint64_t address
)
11580 vec_load (cpu
, address
, 4, 4);
11583 /* Load multiple 3-element structures into three consecutive registers. */
11585 LD3 (sim_cpu
*cpu
, uint64_t address
)
11587 vec_load (cpu
, address
, 3, 3);
11590 /* Load multiple 2-element structures into two consecutive registers. */
11592 LD2 (sim_cpu
*cpu
, uint64_t address
)
11594 vec_load (cpu
, address
, 2, 2);
11597 /* Load multiple 1-element structures into one register. */
11599 LD1_1 (sim_cpu
*cpu
, uint64_t address
)
11601 vec_load (cpu
, address
, 1, 1);
11604 /* Load multiple 1-element structures into two registers. */
11606 LD1_2 (sim_cpu
*cpu
, uint64_t address
)
11608 vec_load (cpu
, address
, 1, 2);
11611 /* Load multiple 1-element structures into three registers. */
11613 LD1_3 (sim_cpu
*cpu
, uint64_t address
)
11615 vec_load (cpu
, address
, 1, 3);
11618 /* Load multiple 1-element structures into four registers. */
11620 LD1_4 (sim_cpu
*cpu
, uint64_t address
)
11622 vec_load (cpu
, address
, 1, 4);
11625 /* Store multiple N-element structures from M consecutive registers. */
11627 vec_store (sim_cpu
*cpu
, uint64_t address
, unsigned N
, unsigned M
)
11629 int all
= INSTR (30, 30);
11630 unsigned size
= INSTR (11, 10);
11631 unsigned vd
= INSTR (4, 0);
11632 unsigned rpt
= (N
== M
) ? 1 : M
;
11633 unsigned selem
= N
;
11638 case 0: /* 8-bit operations. */
11639 for (i
= 0; i
< rpt
; i
++)
11640 for (j
= 0; j
< (8 + (8 * all
)); j
++)
11641 for (k
= 0; k
< selem
; k
++)
11645 aarch64_get_vec_u8 (cpu
, vec_reg (vd
, i
+ k
), j
));
11650 case 1: /* 16-bit operations. */
11651 for (i
= 0; i
< rpt
; i
++)
11652 for (j
= 0; j
< (4 + (4 * all
)); j
++)
11653 for (k
= 0; k
< selem
; k
++)
11655 aarch64_set_mem_u16
11657 aarch64_get_vec_u16 (cpu
, vec_reg (vd
, i
+ k
), j
));
11662 case 2: /* 32-bit operations. */
11663 for (i
= 0; i
< rpt
; i
++)
11664 for (j
= 0; j
< (2 + (2 * all
)); j
++)
11665 for (k
= 0; k
< selem
; k
++)
11667 aarch64_set_mem_u32
11669 aarch64_get_vec_u32 (cpu
, vec_reg (vd
, i
+ k
), j
));
11674 case 3: /* 64-bit operations. */
11675 for (i
= 0; i
< rpt
; i
++)
11676 for (j
= 0; j
< (1 + all
); j
++)
11677 for (k
= 0; k
< selem
; k
++)
11679 aarch64_set_mem_u64
11681 aarch64_get_vec_u64 (cpu
, vec_reg (vd
, i
+ k
), j
));
11688 /* Store multiple 4-element structure from four consecutive registers. */
11690 ST4 (sim_cpu
*cpu
, uint64_t address
)
11692 vec_store (cpu
, address
, 4, 4);
11695 /* Store multiple 3-element structures from three consecutive registers. */
11697 ST3 (sim_cpu
*cpu
, uint64_t address
)
11699 vec_store (cpu
, address
, 3, 3);
11702 /* Store multiple 2-element structures from two consecutive registers. */
11704 ST2 (sim_cpu
*cpu
, uint64_t address
)
11706 vec_store (cpu
, address
, 2, 2);
11709 /* Store multiple 1-element structures from one register. */
11711 ST1_1 (sim_cpu
*cpu
, uint64_t address
)
11713 vec_store (cpu
, address
, 1, 1);
11716 /* Store multiple 1-element structures from two registers. */
11718 ST1_2 (sim_cpu
*cpu
, uint64_t address
)
11720 vec_store (cpu
, address
, 1, 2);
11723 /* Store multiple 1-element structures from three registers. */
11725 ST1_3 (sim_cpu
*cpu
, uint64_t address
)
11727 vec_store (cpu
, address
, 1, 3);
11730 /* Store multiple 1-element structures from four registers. */
11732 ST1_4 (sim_cpu
*cpu
, uint64_t address
)
11734 vec_store (cpu
, address
, 1, 4);
11737 #define LDn_STn_SINGLE_LANE_AND_SIZE() \
11740 switch (INSTR (15, 14)) \
11743 lane = (full << 3) | (s << 2) | size; \
11748 if ((size & 1) == 1) \
11750 lane = (full << 2) | (s << 1) | (size >> 1); \
11755 if ((size & 2) == 2) \
11758 if ((size & 1) == 0) \
11760 lane = (full << 1) | s; \
11778 /* Load single structure into one lane of N registers. */
11780 do_vec_LDn_single (sim_cpu
*cpu
, uint64_t address
)
11783 instr[30] = element selector 0=>half, 1=>all elements
11784 instr[29,24] = 00 1101
11785 instr[23] = 0=>simple, 1=>post
11787 instr[21] = width: LD1-or-LD3 (0) / LD2-or-LD4 (1)
11788 instr[20,16] = 0 0000 (simple), Vinc (reg-post-inc, no SP),
11789 11111 (immediate post inc)
11790 instr[15,13] = opcode
11791 instr[12] = S, used for lane number
11792 instr[11,10] = size, also used for lane number
11793 instr[9,5] = address
11796 unsigned full
= INSTR (30, 30);
11797 unsigned vd
= INSTR (4, 0);
11798 unsigned size
= INSTR (11, 10);
11799 unsigned s
= INSTR (12, 12);
11800 int nregs
= ((INSTR (13, 13) << 1) | INSTR (21, 21)) + 1;
11804 NYI_assert (29, 24, 0x0D);
11805 NYI_assert (22, 22, 1);
11807 /* Compute the lane number first (using size), and then compute size. */
11808 LDn_STn_SINGLE_LANE_AND_SIZE ();
11810 for (i
= 0; i
< nregs
; i
++)
11815 uint8_t val
= aarch64_get_mem_u8 (cpu
, address
+ i
);
11816 aarch64_set_vec_u8 (cpu
, vd
+ i
, lane
, val
);
11822 uint16_t val
= aarch64_get_mem_u16 (cpu
, address
+ (i
* 2));
11823 aarch64_set_vec_u16 (cpu
, vd
+ i
, lane
, val
);
11829 uint32_t val
= aarch64_get_mem_u32 (cpu
, address
+ (i
* 4));
11830 aarch64_set_vec_u32 (cpu
, vd
+ i
, lane
, val
);
11836 uint64_t val
= aarch64_get_mem_u64 (cpu
, address
+ (i
* 8));
11837 aarch64_set_vec_u64 (cpu
, vd
+ i
, lane
, val
);
11843 /* Store single structure from one lane from N registers. */
11845 do_vec_STn_single (sim_cpu
*cpu
, uint64_t address
)
11848 instr[30] = element selector 0=>half, 1=>all elements
11849 instr[29,24] = 00 1101
11850 instr[23] = 0=>simple, 1=>post
11852 instr[21] = width: LD1-or-LD3 (0) / LD2-or-LD4 (1)
11853 instr[20,16] = 0 0000 (simple), Vinc (reg-post-inc, no SP),
11854 11111 (immediate post inc)
11855 instr[15,13] = opcode
11856 instr[12] = S, used for lane number
11857 instr[11,10] = size, also used for lane number
11858 instr[9,5] = address
11861 unsigned full
= INSTR (30, 30);
11862 unsigned vd
= INSTR (4, 0);
11863 unsigned size
= INSTR (11, 10);
11864 unsigned s
= INSTR (12, 12);
11865 int nregs
= ((INSTR (13, 13) << 1) | INSTR (21, 21)) + 1;
11869 NYI_assert (29, 24, 0x0D);
11870 NYI_assert (22, 22, 0);
11872 /* Compute the lane number first (using size), and then compute size. */
11873 LDn_STn_SINGLE_LANE_AND_SIZE ();
11875 for (i
= 0; i
< nregs
; i
++)
11880 uint8_t val
= aarch64_get_vec_u8 (cpu
, vd
+ i
, lane
);
11881 aarch64_set_mem_u8 (cpu
, address
+ i
, val
);
11887 uint16_t val
= aarch64_get_vec_u16 (cpu
, vd
+ i
, lane
);
11888 aarch64_set_mem_u16 (cpu
, address
+ (i
* 2), val
);
11894 uint32_t val
= aarch64_get_vec_u32 (cpu
, vd
+ i
, lane
);
11895 aarch64_set_mem_u32 (cpu
, address
+ (i
* 4), val
);
11901 uint64_t val
= aarch64_get_vec_u64 (cpu
, vd
+ i
, lane
);
11902 aarch64_set_mem_u64 (cpu
, address
+ (i
* 8), val
);
11908 /* Load single structure into all lanes of N registers. */
11910 do_vec_LDnR (sim_cpu
*cpu
, uint64_t address
)
11913 instr[30] = element selector 0=>half, 1=>all elements
11914 instr[29,24] = 00 1101
11915 instr[23] = 0=>simple, 1=>post
11917 instr[21] = width: LD1R-or-LD3R (0) / LD2R-or-LD4R (1)
11918 instr[20,16] = 0 0000 (simple), Vinc (reg-post-inc, no SP),
11919 11111 (immediate post inc)
11921 instr[13] = width: LD1R-or-LD2R (0) / LD3R-or-LD4R (1)
11923 instr[11,10] = element size 00=> byte(b), 01=> half(h),
11924 10=> word(s), 11=> double(d)
11925 instr[9,5] = address
11928 unsigned full
= INSTR (30, 30);
11929 unsigned vd
= INSTR (4, 0);
11930 unsigned size
= INSTR (11, 10);
11931 int nregs
= ((INSTR (13, 13) << 1) | INSTR (21, 21)) + 1;
11934 NYI_assert (29, 24, 0x0D);
11935 NYI_assert (22, 22, 1);
11936 NYI_assert (15, 14, 3);
11937 NYI_assert (12, 12, 0);
11939 for (n
= 0; n
< nregs
; n
++)
11944 uint8_t val
= aarch64_get_mem_u8 (cpu
, address
+ n
);
11945 for (i
= 0; i
< (full
? 16 : 8); i
++)
11946 aarch64_set_vec_u8 (cpu
, vd
+ n
, i
, val
);
11952 uint16_t val
= aarch64_get_mem_u16 (cpu
, address
+ (n
* 2));
11953 for (i
= 0; i
< (full
? 8 : 4); i
++)
11954 aarch64_set_vec_u16 (cpu
, vd
+ n
, i
, val
);
11960 uint32_t val
= aarch64_get_mem_u32 (cpu
, address
+ (n
* 4));
11961 for (i
= 0; i
< (full
? 4 : 2); i
++)
11962 aarch64_set_vec_u32 (cpu
, vd
+ n
, i
, val
);
11968 uint64_t val
= aarch64_get_mem_u64 (cpu
, address
+ (n
* 8));
11969 for (i
= 0; i
< (full
? 2 : 1); i
++)
11970 aarch64_set_vec_u64 (cpu
, vd
+ n
, i
, val
);
11980 do_vec_load_store (sim_cpu
*cpu
)
11982 /* {LD|ST}<N> {Vd..Vd+N}, vaddr
11985 instr[30] = element selector 0=>half, 1=>all elements
11986 instr[29,25] = 00110
11987 instr[24] = 0=>multiple struct, 1=>single struct
11988 instr[23] = 0=>simple, 1=>post
11989 instr[22] = 0=>store, 1=>load
11990 instr[21] = 0 (LDn) / small(0)-large(1) selector (LDnR)
11991 instr[20,16] = 00000 (simple), Vinc (reg-post-inc, no SP),
11992 11111 (immediate post inc)
11993 instr[15,12] = elements and destinations. eg for load:
11994 0000=>LD4 => load multiple 4-element to
11995 four consecutive registers
11996 0100=>LD3 => load multiple 3-element to
11997 three consecutive registers
11998 1000=>LD2 => load multiple 2-element to
11999 two consecutive registers
12000 0010=>LD1 => load multiple 1-element to
12001 four consecutive registers
12002 0110=>LD1 => load multiple 1-element to
12003 three consecutive registers
12004 1010=>LD1 => load multiple 1-element to
12005 two consecutive registers
12006 0111=>LD1 => load multiple 1-element to
12010 instr[11,10] = element size 00=> byte(b), 01=> half(h),
12011 10=> word(s), 11=> double(d)
12012 instr[9,5] = Vn, can be SP
12022 if (INSTR (31, 31) != 0 || INSTR (29, 25) != 0x06)
12025 single
= INSTR (24, 24);
12026 post
= INSTR (23, 23);
12027 load
= INSTR (22, 22);
12028 type
= INSTR (15, 12);
12030 address
= aarch64_get_reg_u64 (cpu
, vn
, SP_OK
);
12032 if (! single
&& INSTR (21, 21) != 0)
12037 unsigned vm
= INSTR (20, 16);
12041 unsigned sizeof_operation
;
12045 if ((type
>= 0) && (type
<= 11))
12047 int nregs
= ((INSTR (13, 13) << 1) | INSTR (21, 21)) + 1;
12048 switch (INSTR (15, 14))
12051 sizeof_operation
= nregs
* 1;
12054 sizeof_operation
= nregs
* 2;
12057 if (INSTR (10, 10) == 0)
12058 sizeof_operation
= nregs
* 4;
12060 sizeof_operation
= nregs
* 8;
12066 else if (type
== 0xC)
12068 sizeof_operation
= INSTR (21, 21) ? 2 : 1;
12069 sizeof_operation
<<= INSTR (11, 10);
12071 else if (type
== 0xE)
12073 sizeof_operation
= INSTR (21, 21) ? 4 : 3;
12074 sizeof_operation
<<= INSTR (11, 10);
12083 case 0: sizeof_operation
= 32; break;
12084 case 4: sizeof_operation
= 24; break;
12085 case 8: sizeof_operation
= 16; break;
12088 /* One register, immediate offset variant. */
12089 sizeof_operation
= 8;
12093 /* Two registers, immediate offset variant. */
12094 sizeof_operation
= 16;
12098 /* Three registers, immediate offset variant. */
12099 sizeof_operation
= 24;
12103 /* Four registers, immediate offset variant. */
12104 sizeof_operation
= 32;
12111 if (INSTR (30, 30))
12112 sizeof_operation
*= 2;
12115 aarch64_set_reg_u64 (cpu
, vn
, SP_OK
, address
+ sizeof_operation
);
12118 aarch64_set_reg_u64 (cpu
, vn
, SP_OK
,
12119 address
+ aarch64_get_reg_u64 (cpu
, vm
, NO_SP
));
12123 NYI_assert (20, 16, 0);
12130 if ((type
>= 0) && (type
<= 11))
12131 do_vec_LDn_single (cpu
, address
);
12132 else if ((type
== 0xC) || (type
== 0xE))
12133 do_vec_LDnR (cpu
, address
);
12140 if ((type
>= 0) && (type
<= 11))
12142 do_vec_STn_single (cpu
, address
);
12153 case 0: LD4 (cpu
, address
); return;
12154 case 4: LD3 (cpu
, address
); return;
12155 case 8: LD2 (cpu
, address
); return;
12156 case 2: LD1_4 (cpu
, address
); return;
12157 case 6: LD1_3 (cpu
, address
); return;
12158 case 10: LD1_2 (cpu
, address
); return;
12159 case 7: LD1_1 (cpu
, address
); return;
12169 case 0: ST4 (cpu
, address
); return;
12170 case 4: ST3 (cpu
, address
); return;
12171 case 8: ST2 (cpu
, address
); return;
12172 case 2: ST1_4 (cpu
, address
); return;
12173 case 6: ST1_3 (cpu
, address
); return;
12174 case 10: ST1_2 (cpu
, address
); return;
12175 case 7: ST1_1 (cpu
, address
); return;
12182 dexLdSt (sim_cpu
*cpu
)
12184 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
12185 assert group == GROUP_LDST_0100 || group == GROUP_LDST_0110 ||
12186 group == GROUP_LDST_1100 || group == GROUP_LDST_1110
12187 bits [29,28:26] of a LS are the secondary dispatch vector. */
12188 uint32_t group2
= dispatchLS (aarch64_get_instr (cpu
));
12193 dexLoadExclusive (cpu
); return;
12197 dexLoadLiteral (cpu
); return;
12201 dexLoadOther (cpu
); return;
12203 case LS_ADVSIMD_001
:
12204 do_vec_load_store (cpu
); return;
12207 dex_load_store_pair_gr (cpu
); return;
12210 dex_load_store_pair_fp (cpu
); return;
12213 /* Should never reach here. */
12218 /* Specific decode and execute for group Data Processing Register. */
12221 dexLogicalShiftedRegister (sim_cpu
*cpu
)
12223 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12225 instr[28:24] = 01010
12226 instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> ROR
12229 instr[15,10] = count : must be 0xxxxx for 32 bit
12233 uint32_t size
= INSTR (31, 31);
12234 Shift shiftType
= INSTR (23, 22);
12235 uint32_t count
= INSTR (15, 10);
12237 /* 32 bit operations must have count[5] = 0.
12238 or else we have an UNALLOC. */
12239 if (size
== 0 && uimm (count
, 5, 5))
12242 /* Dispatch on size:op:N. */
12243 switch ((INSTR (31, 29) << 1) | INSTR (21, 21))
12245 case 0: and32_shift (cpu
, shiftType
, count
); return;
12246 case 1: bic32_shift (cpu
, shiftType
, count
); return;
12247 case 2: orr32_shift (cpu
, shiftType
, count
); return;
12248 case 3: orn32_shift (cpu
, shiftType
, count
); return;
12249 case 4: eor32_shift (cpu
, shiftType
, count
); return;
12250 case 5: eon32_shift (cpu
, shiftType
, count
); return;
12251 case 6: ands32_shift (cpu
, shiftType
, count
); return;
12252 case 7: bics32_shift (cpu
, shiftType
, count
); return;
12253 case 8: and64_shift (cpu
, shiftType
, count
); return;
12254 case 9: bic64_shift (cpu
, shiftType
, count
); return;
12255 case 10:orr64_shift (cpu
, shiftType
, count
); return;
12256 case 11:orn64_shift (cpu
, shiftType
, count
); return;
12257 case 12:eor64_shift (cpu
, shiftType
, count
); return;
12258 case 13:eon64_shift (cpu
, shiftType
, count
); return;
12259 case 14:ands64_shift (cpu
, shiftType
, count
); return;
12260 case 15:bics64_shift (cpu
, shiftType
, count
); return;
12264 /* 32 bit conditional select. */
12266 csel32 (sim_cpu
*cpu
, CondCode cc
)
12268 unsigned rm
= INSTR (20, 16);
12269 unsigned rn
= INSTR (9, 5);
12270 unsigned rd
= INSTR (4, 0);
12272 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12273 testConditionCode (cpu
, cc
)
12274 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12275 : aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12278 /* 64 bit conditional select. */
12280 csel64 (sim_cpu
*cpu
, CondCode cc
)
12282 unsigned rm
= INSTR (20, 16);
12283 unsigned rn
= INSTR (9, 5);
12284 unsigned rd
= INSTR (4, 0);
12286 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12287 testConditionCode (cpu
, cc
)
12288 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12289 : aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
12292 /* 32 bit conditional increment. */
12294 csinc32 (sim_cpu
*cpu
, CondCode cc
)
12296 unsigned rm
= INSTR (20, 16);
12297 unsigned rn
= INSTR (9, 5);
12298 unsigned rd
= INSTR (4, 0);
12300 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12301 testConditionCode (cpu
, cc
)
12302 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12303 : aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) + 1);
12306 /* 64 bit conditional increment. */
12308 csinc64 (sim_cpu
*cpu
, CondCode cc
)
12310 unsigned rm
= INSTR (20, 16);
12311 unsigned rn
= INSTR (9, 5);
12312 unsigned rd
= INSTR (4, 0);
12314 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12315 testConditionCode (cpu
, cc
)
12316 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12317 : aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) + 1);
12320 /* 32 bit conditional invert. */
12322 csinv32 (sim_cpu
*cpu
, CondCode cc
)
12324 unsigned rm
= INSTR (20, 16);
12325 unsigned rn
= INSTR (9, 5);
12326 unsigned rd
= INSTR (4, 0);
12328 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12329 testConditionCode (cpu
, cc
)
12330 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12331 : ~ aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12334 /* 64 bit conditional invert. */
12336 csinv64 (sim_cpu
*cpu
, CondCode cc
)
12338 unsigned rm
= INSTR (20, 16);
12339 unsigned rn
= INSTR (9, 5);
12340 unsigned rd
= INSTR (4, 0);
12342 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12343 testConditionCode (cpu
, cc
)
12344 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12345 : ~ aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
12348 /* 32 bit conditional negate. */
12350 csneg32 (sim_cpu
*cpu
, CondCode cc
)
12352 unsigned rm
= INSTR (20, 16);
12353 unsigned rn
= INSTR (9, 5);
12354 unsigned rd
= INSTR (4, 0);
12356 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12357 testConditionCode (cpu
, cc
)
12358 ? aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12359 : - aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12362 /* 64 bit conditional negate. */
12364 csneg64 (sim_cpu
*cpu
, CondCode cc
)
12366 unsigned rm
= INSTR (20, 16);
12367 unsigned rn
= INSTR (9, 5);
12368 unsigned rd
= INSTR (4, 0);
12370 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12371 testConditionCode (cpu
, cc
)
12372 ? aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12373 : - aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
12377 dexCondSelect (sim_cpu
*cpu
)
12379 /* instr[28,21] = 11011011
12380 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12381 instr[30:11,10] = op : 000 ==> CSEL, 001 ==> CSINC,
12382 100 ==> CSINV, 101 ==> CSNEG,
12384 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
12385 instr[15,12] = cond
12386 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC */
12388 CondCode cc
= INSTR (15, 12);
12389 uint32_t S
= INSTR (29, 29);
12390 uint32_t op2
= INSTR (11, 10);
12398 switch ((INSTR (31, 30) << 1) | op2
)
12400 case 0: csel32 (cpu
, cc
); return;
12401 case 1: csinc32 (cpu
, cc
); return;
12402 case 2: csinv32 (cpu
, cc
); return;
12403 case 3: csneg32 (cpu
, cc
); return;
12404 case 4: csel64 (cpu
, cc
); return;
12405 case 5: csinc64 (cpu
, cc
); return;
12406 case 6: csinv64 (cpu
, cc
); return;
12407 case 7: csneg64 (cpu
, cc
); return;
12411 /* Some helpers for counting leading 1 or 0 bits. */
12413 /* Counts the number of leading bits which are the same
12414 in a 32 bit value in the range 1 to 32. */
12416 leading32 (uint32_t value
)
12418 int32_t mask
= 0xffff0000;
12419 uint32_t count
= 16; /* Counts number of bits set in mask. */
12420 uint32_t lo
= 1; /* Lower bound for number of sign bits. */
12421 uint32_t hi
= 32; /* Upper bound for number of sign bits. */
12423 while (lo
+ 1 < hi
)
12425 int32_t test
= (value
& mask
);
12427 if (test
== 0 || test
== mask
)
12430 count
= (lo
+ hi
) / 2;
12431 mask
>>= (count
- lo
);
12436 count
= (lo
+ hi
) / 2;
12437 mask
<<= hi
- count
;
12446 test
= (value
& mask
);
12448 if (test
== 0 || test
== mask
)
12457 /* Counts the number of leading bits which are the same
12458 in a 64 bit value in the range 1 to 64. */
12460 leading64 (uint64_t value
)
12462 int64_t mask
= 0xffffffff00000000LL
;
12463 uint64_t count
= 32; /* Counts number of bits set in mask. */
12464 uint64_t lo
= 1; /* Lower bound for number of sign bits. */
12465 uint64_t hi
= 64; /* Upper bound for number of sign bits. */
12467 while (lo
+ 1 < hi
)
12469 int64_t test
= (value
& mask
);
12471 if (test
== 0 || test
== mask
)
12474 count
= (lo
+ hi
) / 2;
12475 mask
>>= (count
- lo
);
12480 count
= (lo
+ hi
) / 2;
12481 mask
<<= hi
- count
;
12490 test
= (value
& mask
);
12492 if (test
== 0 || test
== mask
)
12501 /* Bit operations. */
12502 /* N.B register args may not be SP. */
12504 /* 32 bit count leading sign bits. */
12506 cls32 (sim_cpu
*cpu
)
12508 unsigned rn
= INSTR (9, 5);
12509 unsigned rd
= INSTR (4, 0);
12511 /* N.B. the result needs to exclude the leading bit. */
12512 aarch64_set_reg_u64
12513 (cpu
, rd
, NO_SP
, leading32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)) - 1);
12516 /* 64 bit count leading sign bits. */
12518 cls64 (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
, leading64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)) - 1);
12528 /* 32 bit count leading zero bits. */
12530 clz32 (sim_cpu
*cpu
)
12532 unsigned rn
= INSTR (9, 5);
12533 unsigned rd
= INSTR (4, 0);
12534 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12536 /* if the sign (top) bit is set then the count is 0. */
12537 if (pick32 (value
, 31, 31))
12538 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, 0L);
12540 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, leading32 (value
));
12543 /* 64 bit count leading zero bits. */
12545 clz64 (sim_cpu
*cpu
)
12547 unsigned rn
= INSTR (9, 5);
12548 unsigned rd
= INSTR (4, 0);
12549 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12551 /* if the sign (top) bit is set then the count is 0. */
12552 if (pick64 (value
, 63, 63))
12553 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, 0L);
12555 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, leading64 (value
));
12558 /* 32 bit reverse bits. */
12560 rbit32 (sim_cpu
*cpu
)
12562 unsigned rn
= INSTR (9, 5);
12563 unsigned rd
= INSTR (4, 0);
12564 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12565 uint32_t result
= 0;
12568 for (i
= 0; i
< 32; i
++)
12571 result
|= (value
& 1);
12574 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12577 /* 64 bit reverse bits. */
12579 rbit64 (sim_cpu
*cpu
)
12581 unsigned rn
= INSTR (9, 5);
12582 unsigned rd
= INSTR (4, 0);
12583 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12584 uint64_t result
= 0;
12587 for (i
= 0; i
< 64; i
++)
12590 result
|= (value
& 1UL);
12593 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12596 /* 32 bit reverse bytes. */
12598 rev32 (sim_cpu
*cpu
)
12600 unsigned rn
= INSTR (9, 5);
12601 unsigned rd
= INSTR (4, 0);
12602 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12603 uint32_t result
= 0;
12606 for (i
= 0; i
< 4; i
++)
12609 result
|= (value
& 0xff);
12612 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12615 /* 64 bit reverse bytes. */
12617 rev64 (sim_cpu
*cpu
)
12619 unsigned rn
= INSTR (9, 5);
12620 unsigned rd
= INSTR (4, 0);
12621 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12622 uint64_t result
= 0;
12625 for (i
= 0; i
< 8; i
++)
12628 result
|= (value
& 0xffULL
);
12631 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12634 /* 32 bit reverse shorts. */
12635 /* N.B.this reverses the order of the bytes in each half word. */
12637 revh32 (sim_cpu
*cpu
)
12639 unsigned rn
= INSTR (9, 5);
12640 unsigned rd
= INSTR (4, 0);
12641 uint32_t value
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12642 uint32_t result
= 0;
12645 for (i
= 0; i
< 2; i
++)
12648 result
|= (value
& 0x00ff00ff);
12651 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12654 /* 64 bit reverse shorts. */
12655 /* N.B.this reverses the order of the bytes in each half word. */
12657 revh64 (sim_cpu
*cpu
)
12659 unsigned rn
= INSTR (9, 5);
12660 unsigned rd
= INSTR (4, 0);
12661 uint64_t value
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
12662 uint64_t result
= 0;
12665 for (i
= 0; i
< 2; i
++)
12668 result
|= (value
& 0x00ff00ff00ff00ffULL
);
12671 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
, result
);
12675 dexDataProc1Source (sim_cpu
*cpu
)
12678 instr[28,21] = 111010110
12679 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12680 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
12681 instr[20,16] = opcode2 : 00000 ==> ok, ow ==> UNALLOC
12682 instr[15,10] = opcode : 000000 ==> RBIT, 000001 ==> REV16,
12683 000010 ==> REV, 000011 ==> UNALLOC
12684 000100 ==> CLZ, 000101 ==> CLS
12686 instr[9,5] = rn : may not be SP
12687 instr[4,0] = rd : may not be SP. */
12689 uint32_t S
= INSTR (29, 29);
12690 uint32_t opcode2
= INSTR (20, 16);
12691 uint32_t opcode
= INSTR (15, 10);
12692 uint32_t dispatch
= ((INSTR (31, 31) << 3) | opcode
);
12705 case 0: rbit32 (cpu
); return;
12706 case 1: revh32 (cpu
); return;
12707 case 2: rev32 (cpu
); return;
12708 case 4: clz32 (cpu
); return;
12709 case 5: cls32 (cpu
); return;
12710 case 8: rbit64 (cpu
); return;
12711 case 9: revh64 (cpu
); return;
12712 case 10:rev32 (cpu
); return;
12713 case 11:rev64 (cpu
); return;
12714 case 12:clz64 (cpu
); return;
12715 case 13:cls64 (cpu
); return;
12716 default: HALT_UNALLOC
;
12721 Shifts by count supplied in register.
12722 N.B register args may not be SP.
12723 These all use the shifted auxiliary function for
12724 simplicity and clarity. Writing the actual shift
12725 inline would avoid a branch and so be faster but
12726 would also necessitate getting signs right. */
12728 /* 32 bit arithmetic shift right. */
12730 asrv32 (sim_cpu
*cpu
)
12732 unsigned rm
= INSTR (20, 16);
12733 unsigned rn
= INSTR (9, 5);
12734 unsigned rd
= INSTR (4, 0);
12736 aarch64_set_reg_u64
12738 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), ASR
,
12739 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12742 /* 64 bit arithmetic shift right. */
12744 asrv64 (sim_cpu
*cpu
)
12746 unsigned rm
= INSTR (20, 16);
12747 unsigned rn
= INSTR (9, 5);
12748 unsigned rd
= INSTR (4, 0);
12750 aarch64_set_reg_u64
12752 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), ASR
,
12753 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12756 /* 32 bit logical shift left. */
12758 lslv32 (sim_cpu
*cpu
)
12760 unsigned rm
= INSTR (20, 16);
12761 unsigned rn
= INSTR (9, 5);
12762 unsigned rd
= INSTR (4, 0);
12764 aarch64_set_reg_u64
12766 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), LSL
,
12767 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12770 /* 64 bit arithmetic shift left. */
12772 lslv64 (sim_cpu
*cpu
)
12774 unsigned rm
= INSTR (20, 16);
12775 unsigned rn
= INSTR (9, 5);
12776 unsigned rd
= INSTR (4, 0);
12778 aarch64_set_reg_u64
12780 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), LSL
,
12781 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12784 /* 32 bit logical shift right. */
12786 lsrv32 (sim_cpu
*cpu
)
12788 unsigned rm
= INSTR (20, 16);
12789 unsigned rn
= INSTR (9, 5);
12790 unsigned rd
= INSTR (4, 0);
12792 aarch64_set_reg_u64
12794 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), LSR
,
12795 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12798 /* 64 bit logical shift right. */
12800 lsrv64 (sim_cpu
*cpu
)
12802 unsigned rm
= INSTR (20, 16);
12803 unsigned rn
= INSTR (9, 5);
12804 unsigned rd
= INSTR (4, 0);
12806 aarch64_set_reg_u64
12808 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), LSR
,
12809 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12812 /* 32 bit rotate right. */
12814 rorv32 (sim_cpu
*cpu
)
12816 unsigned rm
= INSTR (20, 16);
12817 unsigned rn
= INSTR (9, 5);
12818 unsigned rd
= INSTR (4, 0);
12820 aarch64_set_reg_u64
12822 shifted32 (aarch64_get_reg_u32 (cpu
, rn
, NO_SP
), ROR
,
12823 (aarch64_get_reg_u32 (cpu
, rm
, NO_SP
) & 0x1f)));
12826 /* 64 bit rotate right. */
12828 rorv64 (sim_cpu
*cpu
)
12830 unsigned rm
= INSTR (20, 16);
12831 unsigned rn
= INSTR (9, 5);
12832 unsigned rd
= INSTR (4, 0);
12834 aarch64_set_reg_u64
12836 shifted64 (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
), ROR
,
12837 (aarch64_get_reg_u64 (cpu
, rm
, NO_SP
) & 0x3f)));
12843 /* 32 bit signed divide. */
12845 cpuiv32 (sim_cpu
*cpu
)
12847 unsigned rm
= INSTR (20, 16);
12848 unsigned rn
= INSTR (9, 5);
12849 unsigned rd
= INSTR (4, 0);
12850 /* N.B. the pseudo-code does the divide using 64 bit data. */
12851 /* TODO : check that this rounds towards zero as required. */
12852 int64_t dividend
= aarch64_get_reg_s32 (cpu
, rn
, NO_SP
);
12853 int64_t divisor
= aarch64_get_reg_s32 (cpu
, rm
, NO_SP
);
12855 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
,
12856 divisor
? ((int32_t) (dividend
/ divisor
)) : 0);
12859 /* 64 bit signed divide. */
12861 cpuiv64 (sim_cpu
*cpu
)
12863 unsigned rm
= INSTR (20, 16);
12864 unsigned rn
= INSTR (9, 5);
12865 unsigned rd
= INSTR (4, 0);
12867 /* TODO : check that this rounds towards zero as required. */
12868 int64_t divisor
= aarch64_get_reg_s64 (cpu
, rm
, NO_SP
);
12870 aarch64_set_reg_s64
12872 divisor
? (aarch64_get_reg_s64 (cpu
, rn
, NO_SP
) / divisor
) : 0);
12875 /* 32 bit unsigned divide. */
12877 udiv32 (sim_cpu
*cpu
)
12879 unsigned rm
= INSTR (20, 16);
12880 unsigned rn
= INSTR (9, 5);
12881 unsigned rd
= INSTR (4, 0);
12883 /* N.B. the pseudo-code does the divide using 64 bit data. */
12884 uint64_t dividend
= aarch64_get_reg_u32 (cpu
, rn
, NO_SP
);
12885 uint64_t divisor
= aarch64_get_reg_u32 (cpu
, rm
, NO_SP
);
12887 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12888 divisor
? (uint32_t) (dividend
/ divisor
) : 0);
12891 /* 64 bit unsigned divide. */
12893 udiv64 (sim_cpu
*cpu
)
12895 unsigned rm
= INSTR (20, 16);
12896 unsigned rn
= INSTR (9, 5);
12897 unsigned rd
= INSTR (4, 0);
12899 /* TODO : check that this rounds towards zero as required. */
12900 uint64_t divisor
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
12902 aarch64_set_reg_u64
12904 divisor
? (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
) / divisor
) : 0);
12908 dexDataProc2Source (sim_cpu
*cpu
)
12910 /* assert instr[30] == 0
12911 instr[28,21] == 11010110
12912 instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12913 instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
12914 instr[15,10] = opcode : 000010 ==> UDIV, 000011 ==> CPUIV,
12915 001000 ==> LSLV, 001001 ==> LSRV
12916 001010 ==> ASRV, 001011 ==> RORV
12920 uint32_t S
= INSTR (29, 29);
12921 uint32_t opcode
= INSTR (15, 10);
12929 dispatch
= ( (INSTR (31, 31) << 3)
12930 | (uimm (opcode
, 3, 3) << 2)
12931 | uimm (opcode
, 1, 0));
12934 case 2: udiv32 (cpu
); return;
12935 case 3: cpuiv32 (cpu
); return;
12936 case 4: lslv32 (cpu
); return;
12937 case 5: lsrv32 (cpu
); return;
12938 case 6: asrv32 (cpu
); return;
12939 case 7: rorv32 (cpu
); return;
12940 case 10: udiv64 (cpu
); return;
12941 case 11: cpuiv64 (cpu
); return;
12942 case 12: lslv64 (cpu
); return;
12943 case 13: lsrv64 (cpu
); return;
12944 case 14: asrv64 (cpu
); return;
12945 case 15: rorv64 (cpu
); return;
12946 default: HALT_UNALLOC
;
12953 /* 32 bit multiply and add. */
12955 madd32 (sim_cpu
*cpu
)
12957 unsigned rm
= INSTR (20, 16);
12958 unsigned ra
= INSTR (14, 10);
12959 unsigned rn
= INSTR (9, 5);
12960 unsigned rd
= INSTR (4, 0);
12962 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12963 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12964 aarch64_get_reg_u32 (cpu
, ra
, NO_SP
)
12965 + aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12966 * aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
12969 /* 64 bit multiply and add. */
12971 madd64 (sim_cpu
*cpu
)
12973 unsigned rm
= INSTR (20, 16);
12974 unsigned ra
= INSTR (14, 10);
12975 unsigned rn
= INSTR (9, 5);
12976 unsigned rd
= INSTR (4, 0);
12978 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12979 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12980 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
12981 + (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
12982 * aarch64_get_reg_u64 (cpu
, rm
, NO_SP
)));
12985 /* 32 bit multiply and sub. */
12987 msub32 (sim_cpu
*cpu
)
12989 unsigned rm
= INSTR (20, 16);
12990 unsigned ra
= INSTR (14, 10);
12991 unsigned rn
= INSTR (9, 5);
12992 unsigned rd
= INSTR (4, 0);
12994 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
12995 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
12996 aarch64_get_reg_u32 (cpu
, ra
, NO_SP
)
12997 - aarch64_get_reg_u32 (cpu
, rn
, NO_SP
)
12998 * aarch64_get_reg_u32 (cpu
, rm
, NO_SP
));
13001 /* 64 bit multiply and sub. */
13003 msub64 (sim_cpu
*cpu
)
13005 unsigned rm
= INSTR (20, 16);
13006 unsigned ra
= INSTR (14, 10);
13007 unsigned rn
= INSTR (9, 5);
13008 unsigned rd
= INSTR (4, 0);
13010 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13011 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
13012 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
13013 - aarch64_get_reg_u64 (cpu
, rn
, NO_SP
)
13014 * aarch64_get_reg_u64 (cpu
, rm
, NO_SP
));
13017 /* Signed multiply add long -- source, source2 : 32 bit, source3 : 64 bit. */
13019 smaddl (sim_cpu
*cpu
)
13021 unsigned rm
= INSTR (20, 16);
13022 unsigned ra
= INSTR (14, 10);
13023 unsigned rn
= INSTR (9, 5);
13024 unsigned rd
= INSTR (4, 0);
13026 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
13027 obtain a 64 bit product. */
13028 aarch64_set_reg_s64
13030 aarch64_get_reg_s64 (cpu
, ra
, NO_SP
)
13031 + ((int64_t) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
))
13032 * ((int64_t) aarch64_get_reg_s32 (cpu
, rm
, NO_SP
)));
13035 /* Signed multiply sub long -- source, source2 : 32 bit, source3 : 64 bit. */
13037 smsubl (sim_cpu
*cpu
)
13039 unsigned rm
= INSTR (20, 16);
13040 unsigned ra
= INSTR (14, 10);
13041 unsigned rn
= INSTR (9, 5);
13042 unsigned rd
= INSTR (4, 0);
13044 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
13045 obtain a 64 bit product. */
13046 aarch64_set_reg_s64
13048 aarch64_get_reg_s64 (cpu
, ra
, NO_SP
)
13049 - ((int64_t) aarch64_get_reg_s32 (cpu
, rn
, NO_SP
))
13050 * ((int64_t) aarch64_get_reg_s32 (cpu
, rm
, NO_SP
)));
13053 /* Integer Multiply/Divide. */
13055 /* First some macros and a helper function. */
13056 /* Macros to test or access elements of 64 bit words. */
13058 /* Mask used to access lo 32 bits of 64 bit unsigned int. */
13059 #define LOW_WORD_MASK ((1ULL << 32) - 1)
13060 /* Return the lo 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int. */
13061 #define lowWordToU64(_value_u64) ((_value_u64) & LOW_WORD_MASK)
13062 /* Return the hi 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int. */
13063 #define highWordToU64(_value_u64) ((_value_u64) >> 32)
13065 /* Offset of sign bit in 64 bit signed integger. */
13066 #define SIGN_SHIFT_U64 63
13067 /* The sign bit itself -- also identifies the minimum negative int value. */
13068 #define SIGN_BIT_U64 (1UL << SIGN_SHIFT_U64)
13069 /* Return true if a 64 bit signed int presented as an unsigned int is the
13070 most negative value. */
13071 #define isMinimumU64(_value_u64) ((_value_u64) == SIGN_BIT_U64)
13072 /* Return true (non-zero) if a 64 bit signed int presented as an unsigned
13073 int has its sign bit set to false. */
13074 #define isSignSetU64(_value_u64) ((_value_u64) & SIGN_BIT_U64)
13075 /* Return 1L or -1L according to whether a 64 bit signed int presented as
13076 an unsigned int has its sign bit set or not. */
13077 #define signOfU64(_value_u64) (1L + (((value_u64) >> SIGN_SHIFT_U64) * -2L)
13078 /* Clear the sign bit of a 64 bit signed int presented as an unsigned int. */
13079 #define clearSignU64(_value_u64) ((_value_u64) &= ~SIGN_BIT_U64)
13081 /* Multiply two 64 bit ints and return.
13082 the hi 64 bits of the 128 bit product. */
13085 mul64hi (uint64_t value1
, uint64_t value2
)
13087 uint64_t resultmid1
;
13089 uint64_t value1_lo
= lowWordToU64 (value1
);
13090 uint64_t value1_hi
= highWordToU64 (value1
) ;
13091 uint64_t value2_lo
= lowWordToU64 (value2
);
13092 uint64_t value2_hi
= highWordToU64 (value2
);
13094 /* Cross-multiply and collect results. */
13095 uint64_t xproductlo
= value1_lo
* value2_lo
;
13096 uint64_t xproductmid1
= value1_lo
* value2_hi
;
13097 uint64_t xproductmid2
= value1_hi
* value2_lo
;
13098 uint64_t xproducthi
= value1_hi
* value2_hi
;
13099 uint64_t carry
= 0;
13100 /* Start accumulating 64 bit results. */
13101 /* Drop bottom half of lowest cross-product. */
13102 uint64_t resultmid
= xproductlo
>> 32;
13103 /* Add in middle products. */
13104 resultmid
= resultmid
+ xproductmid1
;
13106 /* Check for overflow. */
13107 if (resultmid
< xproductmid1
)
13108 /* Carry over 1 into top cross-product. */
13111 resultmid1
= resultmid
+ xproductmid2
;
13113 /* Check for overflow. */
13114 if (resultmid1
< xproductmid2
)
13115 /* Carry over 1 into top cross-product. */
13118 /* Drop lowest 32 bits of middle cross-product. */
13119 result
= resultmid1
>> 32;
13120 /* Move carry bit to just above middle cross-product highest bit. */
13121 carry
= carry
<< 32;
13123 /* Add top cross-product plus and any carry. */
13124 result
+= xproducthi
+ carry
;
13129 /* Signed multiply high, source, source2 :
13130 64 bit, dest <-- high 64-bit of result. */
13132 smulh (sim_cpu
*cpu
)
13136 unsigned rm
= INSTR (20, 16);
13137 unsigned rn
= INSTR (9, 5);
13138 unsigned rd
= INSTR (4, 0);
13139 GReg ra
= INSTR (14, 10);
13140 int64_t value1
= aarch64_get_reg_u64 (cpu
, rn
, NO_SP
);
13141 int64_t value2
= aarch64_get_reg_u64 (cpu
, rm
, NO_SP
);
13149 /* Convert to unsigned and use the unsigned mul64hi routine
13150 the fix the sign up afterwards. */
13171 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13173 uresult
= mul64hi (uvalue1
, uvalue2
);
13178 /* Multiply 128-bit result by -1, which means highpart gets inverted,
13179 and has carry in added only if low part is 0. */
13181 if ((uvalue1
* uvalue2
) == 0)
13185 aarch64_set_reg_s64 (cpu
, rd
, NO_SP
, result
);
13188 /* Unsigned multiply add long -- source, source2 :
13189 32 bit, source3 : 64 bit. */
13191 umaddl (sim_cpu
*cpu
)
13193 unsigned rm
= INSTR (20, 16);
13194 unsigned ra
= INSTR (14, 10);
13195 unsigned rn
= INSTR (9, 5);
13196 unsigned rd
= INSTR (4, 0);
13198 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13199 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
13200 obtain a 64 bit product. */
13201 aarch64_set_reg_u64
13203 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
13204 + ((uint64_t) aarch64_get_reg_u32 (cpu
, rn
, NO_SP
))
13205 * ((uint64_t) aarch64_get_reg_u32 (cpu
, rm
, NO_SP
)));
13208 /* Unsigned multiply sub long -- source, source2 : 32 bit, source3 : 64 bit. */
13210 umsubl (sim_cpu
*cpu
)
13212 unsigned rm
= INSTR (20, 16);
13213 unsigned ra
= INSTR (14, 10);
13214 unsigned rn
= INSTR (9, 5);
13215 unsigned rd
= INSTR (4, 0);
13217 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13218 /* N.B. we need to multiply the signed 32 bit values in rn, rm to
13219 obtain a 64 bit product. */
13220 aarch64_set_reg_u64
13222 aarch64_get_reg_u64 (cpu
, ra
, NO_SP
)
13223 - ((uint64_t) aarch64_get_reg_u32 (cpu
, rn
, NO_SP
))
13224 * ((uint64_t) aarch64_get_reg_u32 (cpu
, rm
, NO_SP
)));
13227 /* Unsigned multiply high, source, source2 :
13228 64 bit, dest <-- high 64-bit of result. */
13230 umulh (sim_cpu
*cpu
)
13232 unsigned rm
= INSTR (20, 16);
13233 unsigned rn
= INSTR (9, 5);
13234 unsigned rd
= INSTR (4, 0);
13235 GReg ra
= INSTR (14, 10);
13240 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13241 aarch64_set_reg_u64 (cpu
, rd
, NO_SP
,
13242 mul64hi (aarch64_get_reg_u64 (cpu
, rn
, NO_SP
),
13243 aarch64_get_reg_u64 (cpu
, rm
, NO_SP
)));
13247 dexDataProc3Source (sim_cpu
*cpu
)
13249 /* assert instr[28,24] == 11011. */
13250 /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit (for rd at least)
13251 instr[30,29] = op54 : 00 ==> ok, ow ==> UNALLOC
13252 instr[23,21] = op31 : 111 ==> UNALLOC, o2 ==> ok
13253 instr[15] = o0 : 0/1 ==> ok
13254 instr[23,21:15] ==> op : 0000 ==> MADD, 0001 ==> MSUB, (32/64 bit)
13255 0010 ==> SMADDL, 0011 ==> SMSUBL, (64 bit only)
13256 0100 ==> SMULH, (64 bit only)
13257 1010 ==> UMADDL, 1011 ==> UNSUBL, (64 bit only)
13258 1100 ==> UMULH (64 bit only)
13262 uint32_t size
= INSTR (31, 31);
13263 uint32_t op54
= INSTR (30, 29);
13264 uint32_t op31
= INSTR (23, 21);
13265 uint32_t o0
= INSTR (15, 15);
13282 dispatch
= (op31
<< 1) | o0
;
13286 case 0: madd64 (cpu
); return;
13287 case 1: msub64 (cpu
); return;
13288 case 2: smaddl (cpu
); return;
13289 case 3: smsubl (cpu
); return;
13290 case 4: smulh (cpu
); return;
13291 case 10: umaddl (cpu
); return;
13292 case 11: umsubl (cpu
); return;
13293 case 12: umulh (cpu
); return;
13294 default: HALT_UNALLOC
;
13299 dexDPReg (sim_cpu
*cpu
)
13301 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
13302 assert group == GROUP_DPREG_0101 || group == GROUP_DPREG_1101
13303 bits [28:24:21] of a DPReg are the secondary dispatch vector. */
13304 uint32_t group2
= dispatchDPReg (aarch64_get_instr (cpu
));
13308 case DPREG_LOG_000
:
13309 case DPREG_LOG_001
:
13310 dexLogicalShiftedRegister (cpu
); return;
13312 case DPREG_ADDSHF_010
:
13313 dexAddSubtractShiftedRegister (cpu
); return;
13315 case DPREG_ADDEXT_011
:
13316 dexAddSubtractExtendedRegister (cpu
); return;
13318 case DPREG_ADDCOND_100
:
13320 /* This set bundles a variety of different operations. */
13322 /* 1) add/sub w carry. */
13323 uint32_t mask1
= 0x1FE00000U
;
13324 uint32_t val1
= 0x1A000000U
;
13325 /* 2) cond compare register/immediate. */
13326 uint32_t mask2
= 0x1FE00000U
;
13327 uint32_t val2
= 0x1A400000U
;
13328 /* 3) cond select. */
13329 uint32_t mask3
= 0x1FE00000U
;
13330 uint32_t val3
= 0x1A800000U
;
13331 /* 4) data proc 1/2 source. */
13332 uint32_t mask4
= 0x1FE00000U
;
13333 uint32_t val4
= 0x1AC00000U
;
13335 if ((aarch64_get_instr (cpu
) & mask1
) == val1
)
13336 dexAddSubtractWithCarry (cpu
);
13338 else if ((aarch64_get_instr (cpu
) & mask2
) == val2
)
13341 else if ((aarch64_get_instr (cpu
) & mask3
) == val3
)
13342 dexCondSelect (cpu
);
13344 else if ((aarch64_get_instr (cpu
) & mask4
) == val4
)
13346 /* Bit 30 is clear for data proc 2 source
13347 and set for data proc 1 source. */
13348 if (aarch64_get_instr (cpu
) & (1U << 30))
13349 dexDataProc1Source (cpu
);
13351 dexDataProc2Source (cpu
);
13355 /* Should not reach here. */
13361 case DPREG_3SRC_110
:
13362 dexDataProc3Source (cpu
); return;
13364 case DPREG_UNALLOC_101
:
13367 case DPREG_3SRC_111
:
13368 dexDataProc3Source (cpu
); return;
13371 /* Should never reach here. */
13376 /* Unconditional Branch immediate.
13377 Offset is a PC-relative byte offset in the range +/- 128MiB.
13378 The offset is assumed to be raw from the decode i.e. the
13379 simulator is expected to scale them from word offsets to byte. */
13381 /* Unconditional branch. */
13383 buc (sim_cpu
*cpu
, int32_t offset
)
13385 aarch64_set_next_PC_by_offset (cpu
, offset
);
13388 static unsigned stack_depth
= 0;
13390 /* Unconditional branch and link -- writes return PC to LR. */
13392 bl (sim_cpu
*cpu
, int32_t offset
)
13394 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13395 aarch64_save_LR (cpu
);
13396 aarch64_set_next_PC_by_offset (cpu
, offset
);
13398 if (TRACE_BRANCH_P (cpu
))
13402 " %*scall %" PRIx64
" [%s]"
13403 " [args: %" PRIx64
" %" PRIx64
" %" PRIx64
"]",
13404 stack_depth
, " ", aarch64_get_next_PC (cpu
),
13405 aarch64_get_func (CPU_STATE (cpu
),
13406 aarch64_get_next_PC (cpu
)),
13407 aarch64_get_reg_u64 (cpu
, 0, NO_SP
),
13408 aarch64_get_reg_u64 (cpu
, 1, NO_SP
),
13409 aarch64_get_reg_u64 (cpu
, 2, NO_SP
)
13414 /* Unconditional Branch register.
13415 Branch/return address is in source register. */
13417 /* Unconditional branch. */
13421 unsigned rn
= INSTR (9, 5);
13422 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13423 aarch64_set_next_PC (cpu
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
13426 /* Unconditional branch and link -- writes return PC to LR. */
13430 /* Ensure we read the destination before we write LR. */
13431 uint64_t target
= aarch64_get_reg_u64 (cpu
, INSTR (9, 5), NO_SP
);
13433 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13434 aarch64_save_LR (cpu
);
13435 aarch64_set_next_PC (cpu
, target
);
13437 if (TRACE_BRANCH_P (cpu
))
13441 " %*scall %" PRIx64
" [%s]"
13442 " [args: %" PRIx64
" %" PRIx64
" %" PRIx64
"]",
13443 stack_depth
, " ", aarch64_get_next_PC (cpu
),
13444 aarch64_get_func (CPU_STATE (cpu
),
13445 aarch64_get_next_PC (cpu
)),
13446 aarch64_get_reg_u64 (cpu
, 0, NO_SP
),
13447 aarch64_get_reg_u64 (cpu
, 1, NO_SP
),
13448 aarch64_get_reg_u64 (cpu
, 2, NO_SP
)
13453 /* Return -- assembler will default source to LR this is functionally
13454 equivalent to br but, presumably, unlike br it side effects the
13455 branch predictor. */
13459 unsigned rn
= INSTR (9, 5);
13460 aarch64_set_next_PC (cpu
, aarch64_get_reg_u64 (cpu
, rn
, NO_SP
));
13462 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13463 if (TRACE_BRANCH_P (cpu
))
13466 " %*sreturn [result: %" PRIx64
"]",
13467 stack_depth
, " ", aarch64_get_reg_u64 (cpu
, 0, NO_SP
));
13472 /* NOP -- we implement this and call it from the decode in case we
13473 want to intercept it later. */
13478 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13481 /* Data synchronization barrier. */
13486 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13489 /* Data memory barrier. */
13494 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13497 /* Instruction synchronization barrier. */
13502 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13506 dexBranchImmediate (sim_cpu
*cpu
)
13508 /* assert instr[30,26] == 00101
13509 instr[31] ==> 0 == B, 1 == BL
13510 instr[25,0] == imm26 branch offset counted in words. */
13512 uint32_t top
= INSTR (31, 31);
13513 /* We have a 26 byte signed word offset which we need to pass to the
13514 execute routine as a signed byte offset. */
13515 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 25, 0) << 2;
13523 /* Control Flow. */
13525 /* Conditional branch
13527 Offset is a PC-relative byte offset in the range +/- 1MiB pos is
13528 a bit position in the range 0 .. 63
13530 cc is a CondCode enum value as pulled out of the decode
13532 N.B. any offset register (source) can only be Xn or Wn. */
13535 bcc (sim_cpu
*cpu
, int32_t offset
, CondCode cc
)
13537 /* The test returns TRUE if CC is met. */
13538 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13539 if (testConditionCode (cpu
, cc
))
13540 aarch64_set_next_PC_by_offset (cpu
, offset
);
13543 /* 32 bit branch on register non-zero. */
13545 cbnz32 (sim_cpu
*cpu
, int32_t offset
)
13547 unsigned rt
= INSTR (4, 0);
13549 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13550 if (aarch64_get_reg_u32 (cpu
, rt
, NO_SP
) != 0)
13551 aarch64_set_next_PC_by_offset (cpu
, offset
);
13554 /* 64 bit branch on register zero. */
13556 cbnz (sim_cpu
*cpu
, int32_t offset
)
13558 unsigned rt
= INSTR (4, 0);
13560 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13561 if (aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) != 0)
13562 aarch64_set_next_PC_by_offset (cpu
, offset
);
13565 /* 32 bit branch on register non-zero. */
13567 cbz32 (sim_cpu
*cpu
, int32_t offset
)
13569 unsigned rt
= INSTR (4, 0);
13571 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13572 if (aarch64_get_reg_u32 (cpu
, rt
, NO_SP
) == 0)
13573 aarch64_set_next_PC_by_offset (cpu
, offset
);
13576 /* 64 bit branch on register zero. */
13578 cbz (sim_cpu
*cpu
, int32_t offset
)
13580 unsigned rt
= INSTR (4, 0);
13582 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13583 if (aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) == 0)
13584 aarch64_set_next_PC_by_offset (cpu
, offset
);
13587 /* Branch on register bit test non-zero -- one size fits all. */
13589 tbnz (sim_cpu
*cpu
, uint32_t pos
, int32_t offset
)
13591 unsigned rt
= INSTR (4, 0);
13593 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13594 if (aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) & (((uint64_t) 1) << pos
))
13595 aarch64_set_next_PC_by_offset (cpu
, offset
);
13598 /* Branch on register bit test zero -- one size fits all. */
13600 tbz (sim_cpu
*cpu
, uint32_t pos
, int32_t offset
)
13602 unsigned rt
= INSTR (4, 0);
13604 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13605 if (!(aarch64_get_reg_u64 (cpu
, rt
, NO_SP
) & (((uint64_t) 1) << pos
)))
13606 aarch64_set_next_PC_by_offset (cpu
, offset
);
13610 dexCompareBranchImmediate (sim_cpu
*cpu
)
13612 /* instr[30,25] = 01 1010
13613 instr[31] = size : 0 ==> 32, 1 ==> 64
13614 instr[24] = op : 0 ==> CBZ, 1 ==> CBNZ
13615 instr[23,5] = simm19 branch offset counted in words
13618 uint32_t size
= INSTR (31, 31);
13619 uint32_t op
= INSTR (24, 24);
13620 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 23, 5) << 2;
13625 cbz32 (cpu
, offset
);
13627 cbnz32 (cpu
, offset
);
13634 cbnz (cpu
, offset
);
13639 dexTestBranchImmediate (sim_cpu
*cpu
)
13641 /* instr[31] = b5 : bit 5 of test bit idx
13642 instr[30,25] = 01 1011
13643 instr[24] = op : 0 ==> TBZ, 1 == TBNZ
13644 instr[23,19] = b40 : bits 4 to 0 of test bit idx
13645 instr[18,5] = simm14 : signed offset counted in words
13646 instr[4,0] = uimm5 */
13648 uint32_t pos
= ((INSTR (31, 31) << 5) | INSTR (23, 19));
13649 int32_t offset
= simm32 (aarch64_get_instr (cpu
), 18, 5) << 2;
13651 NYI_assert (30, 25, 0x1b);
13653 if (INSTR (24, 24) == 0)
13654 tbz (cpu
, pos
, offset
);
13656 tbnz (cpu
, pos
, offset
);
13660 dexCondBranchImmediate (sim_cpu
*cpu
)
13662 /* instr[31,25] = 010 1010
13663 instr[24] = op1; op => 00 ==> B.cond
13664 instr[23,5] = simm19 : signed offset counted in words
13666 instr[3,0] = cond */
13669 uint32_t op
= ((INSTR (24, 24) << 1) | INSTR (4, 4));
13671 NYI_assert (31, 25, 0x2a);
13676 offset
= simm32 (aarch64_get_instr (cpu
), 23, 5) << 2;
13678 bcc (cpu
, offset
, INSTR (3, 0));
13682 dexBranchRegister (sim_cpu
*cpu
)
13684 /* instr[31,25] = 110 1011
13685 instr[24,21] = op : 0 ==> BR, 1 => BLR, 2 => RET, 3 => ERET, 4 => DRPS
13686 instr[20,16] = op2 : must be 11111
13687 instr[15,10] = op3 : must be 000000
13688 instr[4,0] = op2 : must be 11111. */
13690 uint32_t op
= INSTR (24, 21);
13691 uint32_t op2
= INSTR (20, 16);
13692 uint32_t op3
= INSTR (15, 10);
13693 uint32_t op4
= INSTR (4, 0);
13695 NYI_assert (31, 25, 0x6b);
13697 if (op2
!= 0x1F || op3
!= 0 || op4
!= 0)
13711 /* ERET and DRPS accept 0b11111 for rn = instr [4,0]. */
13712 /* anything else is unallocated. */
13713 uint32_t rn
= INSTR (4, 0);
13718 if (op
== 4 || op
== 5)
13725 /* FIXME: We should get the Angel SWI values from ../../libgloss/aarch64/svc.h
13726 but this may not be available. So instead we define the values we need
13728 #define AngelSVC_Reason_Open 0x01
13729 #define AngelSVC_Reason_Close 0x02
13730 #define AngelSVC_Reason_Write 0x05
13731 #define AngelSVC_Reason_Read 0x06
13732 #define AngelSVC_Reason_IsTTY 0x09
13733 #define AngelSVC_Reason_Seek 0x0A
13734 #define AngelSVC_Reason_FLen 0x0C
13735 #define AngelSVC_Reason_Remove 0x0E
13736 #define AngelSVC_Reason_Rename 0x0F
13737 #define AngelSVC_Reason_Clock 0x10
13738 #define AngelSVC_Reason_Time 0x11
13739 #define AngelSVC_Reason_System 0x12
13740 #define AngelSVC_Reason_Errno 0x13
13741 #define AngelSVC_Reason_GetCmdLine 0x15
13742 #define AngelSVC_Reason_HeapInfo 0x16
13743 #define AngelSVC_Reason_ReportException 0x18
13744 #define AngelSVC_Reason_Elapsed 0x30
13748 handle_halt (sim_cpu
*cpu
, uint32_t val
)
13750 uint64_t result
= 0;
13752 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
13755 TRACE_SYSCALL (cpu
, " HLT [0x%x]", val
);
13756 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13757 sim_stopped
, SIM_SIGTRAP
);
13760 /* We have encountered an Angel SVC call. See if we can process it. */
13761 switch (aarch64_get_reg_u32 (cpu
, 0, NO_SP
))
13763 case AngelSVC_Reason_HeapInfo
:
13765 /* Get the values. */
13766 uint64_t stack_top
= aarch64_get_stack_start (cpu
);
13767 uint64_t heap_base
= aarch64_get_heap_start (cpu
);
13769 /* Get the pointer */
13770 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13771 ptr
= aarch64_get_mem_u64 (cpu
, ptr
);
13773 /* Fill in the memory block. */
13774 /* Start addr of heap. */
13775 aarch64_set_mem_u64 (cpu
, ptr
+ 0, heap_base
);
13776 /* End addr of heap. */
13777 aarch64_set_mem_u64 (cpu
, ptr
+ 8, stack_top
);
13778 /* Lowest stack addr. */
13779 aarch64_set_mem_u64 (cpu
, ptr
+ 16, heap_base
);
13780 /* Initial stack addr. */
13781 aarch64_set_mem_u64 (cpu
, ptr
+ 24, stack_top
);
13783 TRACE_SYSCALL (cpu
, " AngelSVC: Get Heap Info");
13787 case AngelSVC_Reason_Open
:
13789 /* Get the pointer */
13790 /* uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);. */
13791 /* FIXME: For now we just assume that we will only be asked
13792 to open the standard file descriptors. */
13796 TRACE_SYSCALL (cpu
, " AngelSVC: Open file %d", fd
- 1);
13800 case AngelSVC_Reason_Close
:
13802 uint64_t fh
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13803 TRACE_SYSCALL (cpu
, " AngelSVC: Close file %d", (int) fh
);
13808 case AngelSVC_Reason_Errno
:
13810 TRACE_SYSCALL (cpu
, " AngelSVC: Get Errno");
13813 case AngelSVC_Reason_Clock
:
13815 #ifdef CLOCKS_PER_SEC
13816 (CLOCKS_PER_SEC
>= 100)
13817 ? (clock () / (CLOCKS_PER_SEC
/ 100))
13818 : ((clock () * 100) / CLOCKS_PER_SEC
)
13820 /* Presume unix... clock() returns microseconds. */
13824 TRACE_SYSCALL (cpu
, " AngelSVC: Get Clock");
13827 case AngelSVC_Reason_GetCmdLine
:
13829 /* Get the pointer */
13830 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13831 ptr
= aarch64_get_mem_u64 (cpu
, ptr
);
13833 /* FIXME: No command line for now. */
13834 aarch64_set_mem_u64 (cpu
, ptr
, 0);
13835 TRACE_SYSCALL (cpu
, " AngelSVC: Get Command Line");
13839 case AngelSVC_Reason_IsTTY
:
13841 TRACE_SYSCALL (cpu
, " AngelSVC: IsTTY ?");
13844 case AngelSVC_Reason_Write
:
13846 /* Get the pointer */
13847 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13848 /* Get the write control block. */
13849 uint64_t fd
= aarch64_get_mem_u64 (cpu
, ptr
);
13850 uint64_t buf
= aarch64_get_mem_u64 (cpu
, ptr
+ 8);
13851 uint64_t len
= aarch64_get_mem_u64 (cpu
, ptr
+ 16);
13853 TRACE_SYSCALL (cpu
, "write of %" PRIx64
" bytes from %"
13854 PRIx64
" on descriptor %" PRIx64
,
13859 TRACE_SYSCALL (cpu
,
13860 " AngelSVC: Write: Suspiciously long write: %ld",
13862 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13863 sim_stopped
, SIM_SIGBUS
);
13867 printf ("%.*s", (int) len
, aarch64_get_mem_ptr (cpu
, buf
));
13871 TRACE (cpu
, 0, "\n");
13872 sim_io_eprintf (CPU_STATE (cpu
), "%.*s",
13873 (int) len
, aarch64_get_mem_ptr (cpu
, buf
));
13874 TRACE (cpu
, 0, "\n");
13878 TRACE_SYSCALL (cpu
,
13879 " AngelSVC: Write: Unexpected file handle: %d",
13881 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13882 sim_stopped
, SIM_SIGABRT
);
13887 case AngelSVC_Reason_ReportException
:
13889 /* Get the pointer */
13890 uint64_t ptr
= aarch64_get_reg_u64 (cpu
, 1, SP_OK
);
13891 /*ptr = aarch64_get_mem_u64 (cpu, ptr);. */
13892 uint64_t type
= aarch64_get_mem_u64 (cpu
, ptr
);
13893 uint64_t state
= aarch64_get_mem_u64 (cpu
, ptr
+ 8);
13895 TRACE_SYSCALL (cpu
,
13896 "Angel Exception: type 0x%" PRIx64
" state %" PRIx64
,
13899 if (type
== 0x20026)
13900 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13901 sim_exited
, state
);
13903 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13904 sim_stopped
, SIM_SIGINT
);
13908 case AngelSVC_Reason_Read
:
13909 case AngelSVC_Reason_FLen
:
13910 case AngelSVC_Reason_Seek
:
13911 case AngelSVC_Reason_Remove
:
13912 case AngelSVC_Reason_Time
:
13913 case AngelSVC_Reason_System
:
13914 case AngelSVC_Reason_Rename
:
13915 case AngelSVC_Reason_Elapsed
:
13917 TRACE_SYSCALL (cpu
, " HLT [Unknown angel %x]",
13918 aarch64_get_reg_u32 (cpu
, 0, NO_SP
));
13919 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13920 sim_stopped
, SIM_SIGTRAP
);
13923 aarch64_set_reg_u64 (cpu
, 0, NO_SP
, result
);
13927 dexExcpnGen (sim_cpu
*cpu
)
13929 /* instr[31:24] = 11010100
13930 instr[23,21] = opc : 000 ==> GEN EXCPN, 001 ==> BRK
13931 010 ==> HLT, 101 ==> DBG GEN EXCPN
13932 instr[20,5] = imm16
13933 instr[4,2] = opc2 000 ==> OK, ow ==> UNALLOC
13934 instr[1,0] = LL : discriminates opc */
13936 uint32_t opc
= INSTR (23, 21);
13937 uint32_t imm16
= INSTR (20, 5);
13938 uint32_t opc2
= INSTR (4, 2);
13941 NYI_assert (31, 24, 0xd4);
13948 /* We only implement HLT and BRK for now. */
13949 if (opc
== 1 && LL
== 0)
13951 TRACE_EVENTS (cpu
, " BRK [0x%x]", imm16
);
13952 sim_engine_halt (CPU_STATE (cpu
), cpu
, NULL
, aarch64_get_PC (cpu
),
13953 sim_exited
, aarch64_get_reg_s32 (cpu
, R0
, SP_OK
));
13956 if (opc
== 2 && LL
== 0)
13957 handle_halt (cpu
, imm16
);
13959 else if (opc
== 0 || opc
== 5)
13966 /* Stub for accessing system registers. */
13969 system_get (sim_cpu
*cpu
, unsigned op0
, unsigned op1
, unsigned crn
,
13970 unsigned crm
, unsigned op2
)
13972 if (crn
== 0 && op1
== 3 && crm
== 0 && op2
== 7)
13973 /* DCZID_EL0 - the Data Cache Zero ID register.
13974 We do not support DC ZVA at the moment, so
13975 we return a value with the disable bit set.
13976 We implement support for the DCZID register since
13977 it is used by the C library's memset function. */
13978 return ((uint64_t) 1) << 4;
13980 if (crn
== 0 && op1
== 3 && crm
== 0 && op2
== 1)
13981 /* Cache Type Register. */
13982 return 0x80008000UL
;
13984 if (crn
== 13 && op1
== 3 && crm
== 0 && op2
== 2)
13985 /* TPIDR_EL0 - thread pointer id. */
13986 return aarch64_get_thread_id (cpu
);
13988 if (op1
== 3 && crm
== 4 && op2
== 0)
13989 return aarch64_get_FPCR (cpu
);
13991 if (op1
== 3 && crm
== 4 && op2
== 1)
13992 return aarch64_get_FPSR (cpu
);
13994 else if (op1
== 3 && crm
== 2 && op2
== 0)
13995 return aarch64_get_CPSR (cpu
);
14001 system_set (sim_cpu
*cpu
, unsigned op0
, unsigned op1
, unsigned crn
,
14002 unsigned crm
, unsigned op2
, uint64_t val
)
14004 if (op1
== 3 && crm
== 4 && op2
== 0)
14005 aarch64_set_FPCR (cpu
, val
);
14007 else if (op1
== 3 && crm
== 4 && op2
== 1)
14008 aarch64_set_FPSR (cpu
, val
);
14010 else if (op1
== 3 && crm
== 2 && op2
== 0)
14011 aarch64_set_CPSR (cpu
, val
);
14018 do_mrs (sim_cpu
*cpu
)
14020 /* instr[31:20] = 1101 0101 0001 1
14027 unsigned sys_op0
= INSTR (19, 19) + 2;
14028 unsigned sys_op1
= INSTR (18, 16);
14029 unsigned sys_crn
= INSTR (15, 12);
14030 unsigned sys_crm
= INSTR (11, 8);
14031 unsigned sys_op2
= INSTR (7, 5);
14032 unsigned rt
= INSTR (4, 0);
14034 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
14035 aarch64_set_reg_u64 (cpu
, rt
, NO_SP
,
14036 system_get (cpu
, sys_op0
, sys_op1
, sys_crn
, sys_crm
, sys_op2
));
14040 do_MSR_immediate (sim_cpu
*cpu
)
14042 /* instr[31:19] = 1101 0101 0000 0
14044 instr[15,12] = 0100
14047 instr[4,0] = 1 1111 */
14049 unsigned op1
= INSTR (18, 16);
14050 /*unsigned crm = INSTR (11, 8);*/
14051 unsigned op2
= INSTR (7, 5);
14053 NYI_assert (31, 19, 0x1AA0);
14054 NYI_assert (15, 12, 0x4);
14055 NYI_assert (4, 0, 0x1F);
14060 HALT_NYI
; /* set SPSel. */
14067 HALT_NYI
; /* set DAIFset. */
14069 HALT_NYI
; /* set DAIFclr. */
14078 do_MSR_reg (sim_cpu
*cpu
)
14080 /* instr[31:20] = 1101 0101 0001
14088 unsigned sys_op0
= INSTR (19, 19) + 2;
14089 unsigned sys_op1
= INSTR (18, 16);
14090 unsigned sys_crn
= INSTR (15, 12);
14091 unsigned sys_crm
= INSTR (11, 8);
14092 unsigned sys_op2
= INSTR (7, 5);
14093 unsigned rt
= INSTR (4, 0);
14095 NYI_assert (31, 20, 0xD51);
14097 TRACE_DECODE (cpu
, "emulated at line %d", __LINE__
);
14098 system_set (cpu
, sys_op0
, sys_op1
, sys_crn
, sys_crm
, sys_op2
,
14099 aarch64_get_reg_u64 (cpu
, rt
, NO_SP
));
14103 do_SYS (sim_cpu
*cpu
)
14105 /* instr[31,19] = 1101 0101 0000 1
14111 NYI_assert (31, 19, 0x1AA1);
14113 /* FIXME: For now we just silently accept system ops. */
14117 dexSystem (sim_cpu
*cpu
)
14119 /* instr[31:22] = 1101 01010 0
14126 instr[4,0] = uimm5 */
14128 /* We are interested in HINT, DSB, DMB and ISB
14130 Hint #0 encodes NOOP (this is the only hint we care about)
14131 L == 0, op0 == 0, op1 = 011, CRn = 0010, Rt = 11111,
14132 CRm op2 != 0000 000 OR CRm op2 == 0000 000 || CRm op > 0000 101
14134 DSB, DMB, ISB are data store barrier, data memory barrier and
14135 instruction store barrier, respectively, where
14137 L == 0, op0 == 0, op1 = 011, CRn = 0011, Rt = 11111,
14138 op2 : DSB ==> 100, DMB ==> 101, ISB ==> 110
14139 CRm<3:2> ==> domain, CRm<1:0> ==> types,
14140 domain : 00 ==> OuterShareable, 01 ==> Nonshareable,
14141 10 ==> InerShareable, 11 ==> FullSystem
14142 types : 01 ==> Reads, 10 ==> Writes,
14143 11 ==> All, 00 ==> All (domain == FullSystem). */
14145 unsigned rt
= INSTR (4, 0);
14147 NYI_assert (31, 22, 0x354);
14149 switch (INSTR (21, 12))
14154 /* NOP has CRm != 0000 OR. */
14155 /* (CRm == 0000 AND (op2 == 000 OR op2 > 101)). */
14156 uint32_t crm
= INSTR (11, 8);
14157 uint32_t op2
= INSTR (7, 5);
14159 if (crm
!= 0 || (op2
== 0 || op2
> 5))
14161 /* Actually call nop method so we can reimplement it later. */
14170 uint32_t op2
= INSTR (7, 5);
14175 case 4: dsb (cpu
); return;
14176 case 5: dmb (cpu
); return;
14177 case 6: isb (cpu
); return;
14178 default: HALT_UNALLOC
;
14189 do_SYS (cpu
); /* DC is an alias of SYS. */
14193 if (INSTR (21, 20) == 0x1)
14195 else if (INSTR (21, 19) == 0 && INSTR (15, 12) == 0x4)
14196 do_MSR_immediate (cpu
);
14204 dexBr (sim_cpu
*cpu
)
14206 /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
14207 assert group == GROUP_BREXSYS_1010 || group == GROUP_BREXSYS_1011
14208 bits [31,29] of a BrExSys are the secondary dispatch vector. */
14209 uint32_t group2
= dispatchBrExSys (aarch64_get_instr (cpu
));
14214 return dexBranchImmediate (cpu
);
14216 case BR_IMMCMP_001
:
14217 /* Compare has bit 25 clear while test has it set. */
14218 if (!INSTR (25, 25))
14219 dexCompareBranchImmediate (cpu
);
14221 dexTestBranchImmediate (cpu
);
14224 case BR_IMMCOND_010
:
14225 /* This is a conditional branch if bit 25 is clear otherwise
14227 if (!INSTR (25, 25))
14228 dexCondBranchImmediate (cpu
);
14233 case BR_UNALLOC_011
:
14237 dexBranchImmediate (cpu
);
14240 case BR_IMMCMP_101
:
14241 /* Compare has bit 25 clear while test has it set. */
14242 if (!INSTR (25, 25))
14243 dexCompareBranchImmediate (cpu
);
14245 dexTestBranchImmediate (cpu
);
14249 /* Unconditional branch reg has bit 25 set. */
14250 if (INSTR (25, 25))
14251 dexBranchRegister (cpu
);
14253 /* This includes both Excpn Gen, System and unalloc operations.
14254 We need to decode the Excpn Gen operation BRK so we can plant
14255 debugger entry points.
14256 Excpn Gen operations have instr [24] = 0.
14257 we need to decode at least one of the System operations NOP
14258 which is an alias for HINT #0.
14259 System operations have instr [24,22] = 100. */
14260 else if (INSTR (24, 24) == 0)
14263 else if (INSTR (24, 22) == 4)
14271 case BR_UNALLOC_111
:
14275 /* Should never reach here. */
14281 aarch64_decode_and_execute (sim_cpu
*cpu
, uint64_t pc
)
14283 /* We need to check if gdb wants an in here. */
14284 /* checkBreak (cpu);. */
14286 uint64_t group
= dispatchGroup (aarch64_get_instr (cpu
));
14290 case GROUP_PSEUDO_0000
: dexPseudo (cpu
); break;
14291 case GROUP_LDST_0100
: dexLdSt (cpu
); break;
14292 case GROUP_DPREG_0101
: dexDPReg (cpu
); break;
14293 case GROUP_LDST_0110
: dexLdSt (cpu
); break;
14294 case GROUP_ADVSIMD_0111
: dexAdvSIMD0 (cpu
); break;
14295 case GROUP_DPIMM_1000
: dexDPImm (cpu
); break;
14296 case GROUP_DPIMM_1001
: dexDPImm (cpu
); break;
14297 case GROUP_BREXSYS_1010
: dexBr (cpu
); break;
14298 case GROUP_BREXSYS_1011
: dexBr (cpu
); break;
14299 case GROUP_LDST_1100
: dexLdSt (cpu
); break;
14300 case GROUP_DPREG_1101
: dexDPReg (cpu
); break;
14301 case GROUP_LDST_1110
: dexLdSt (cpu
); break;
14302 case GROUP_ADVSIMD_1111
: dexAdvSIMD1 (cpu
); break;
14304 case GROUP_UNALLOC_0001
:
14305 case GROUP_UNALLOC_0010
:
14306 case GROUP_UNALLOC_0011
:
14310 /* Should never reach here. */
14316 aarch64_step (sim_cpu
*cpu
)
14318 uint64_t pc
= aarch64_get_PC (cpu
);
14320 if (pc
== TOP_LEVEL_RETURN_PC
)
14323 aarch64_set_next_PC (cpu
, pc
+ 4);
14325 /* Code is always little-endian. */
14326 sim_core_read_buffer (CPU_STATE (cpu
), cpu
, read_map
,
14327 & aarch64_get_instr (cpu
), pc
, 4);
14328 aarch64_get_instr (cpu
) = endian_le2h_4 (aarch64_get_instr (cpu
));
14330 TRACE_INSN (cpu
, " pc = %" PRIx64
" instr = %08x", pc
,
14331 aarch64_get_instr (cpu
));
14332 TRACE_DISASM (cpu
, pc
);
14334 aarch64_decode_and_execute (cpu
, pc
);
14340 aarch64_run (SIM_DESC sd
)
14342 sim_cpu
*cpu
= STATE_CPU (sd
, 0);
14344 while (aarch64_step (cpu
))
14346 aarch64_update_PC (cpu
);
14348 if (sim_events_tick (sd
))
14349 sim_events_process (sd
);
14352 sim_engine_halt (sd
, cpu
, NULL
, aarch64_get_PC (cpu
),
14353 sim_exited
, aarch64_get_reg_s32 (cpu
, R0
, NO_SP
));
14357 aarch64_init (sim_cpu
*cpu
, uint64_t pc
)
14359 uint64_t sp
= aarch64_get_stack_start (cpu
);
14361 /* Install SP, FP and PC and set LR to -20
14362 so we can detect a top-level return. */
14363 aarch64_set_reg_u64 (cpu
, SP
, SP_OK
, sp
);
14364 aarch64_set_reg_u64 (cpu
, FP
, SP_OK
, sp
);
14365 aarch64_set_reg_u64 (cpu
, LR
, SP_OK
, TOP_LEVEL_RETURN_PC
);
14366 aarch64_set_next_PC (cpu
, pc
);
14367 aarch64_update_PC (cpu
);
14368 aarch64_init_LIT_table ();