sim: unify min/max macros
[external/binutils.git] / sim / aarch64 / simulator.c
1 /* simulator.c -- Interface for the AArch64 simulator.
2
3    Copyright (C) 2015-2016 Free Software Foundation, Inc.
4
5    Contributed by Red Hat.
6
7    This file is part of GDB.
8
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.
13
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.
18
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/>.  */
21
22 #include "config.h"
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <sys/types.h>
27 #include <math.h>
28 #include <time.h>
29 #include <limits.h>
30
31 #include "dis-asm.h"
32
33 #include "simulator.h"
34 #include "cpustate.h"
35 #include "memory.h"
36
37 #define NO_SP 0
38 #define SP_OK 1
39
40 bfd_boolean disas = FALSE;
41
42 #define TST(_flag)   (aarch64_test_CPSR_bit (cpu, _flag))
43 #define IS_SET(_X)   ( TST (( _X )))
44 #define IS_CLEAR(_X) (!TST (( _X )))
45
46 #define HALT_UNALLOC                                                    \
47   do                                                                    \
48     {                                                                   \
49       if (TRACE_INSN_P (cpu))                                           \
50         {                                                               \
51           aarch64_print_insn (CPU_STATE (cpu), aarch64_get_PC (cpu));   \
52           TRACE_INSN (cpu,                                              \
53                       "Unallocated instruction detected at sim line %d,"\
54                       " exe addr %" PRIx64,                             \
55                       __LINE__, aarch64_get_PC (cpu));                  \
56         }                                                               \
57       sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),\
58                        sim_stopped, SIM_SIGILL);                        \
59     }                                                                   \
60   while (0)
61
62 #define HALT_NYI                                                        \
63   do                                                                    \
64     {                                                                   \
65       if (TRACE_INSN_P (cpu))                                           \
66         {                                                               \
67           aarch64_print_insn (CPU_STATE (cpu), aarch64_get_PC (cpu));   \
68           TRACE_INSN (cpu,                                              \
69                       "Unimplemented instruction detected at sim line %d,"\
70                       " exe addr %" PRIx64,                             \
71                       __LINE__, aarch64_get_PC (cpu));                  \
72         }                                                               \
73       sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),\
74                        sim_stopped, SIM_SIGABRT);                       \
75     }                                                                   \
76   while (0)
77
78 #define NYI_assert(HI, LO, EXPECTED)                                    \
79   do                                                                    \
80     {                                                                   \
81       if (uimm (aarch64_get_instr (cpu), (HI), (LO)) != (EXPECTED))     \
82         HALT_NYI;                                                       \
83     }                                                                   \
84   while (0)
85
86 #define HALT_UNREACHABLE                                                \
87   do                                                                    \
88     {                                                                   \
89       TRACE_EVENTS (cpu, "ISE: unreachable code point");                \
90       sim_engine_abort (NULL, cpu, aarch64_get_PC (cpu), "Internal Error"); \
91     }                                                                   \
92   while (0)
93
94 /* Helper functions used by expandLogicalImmediate.  */
95
96 /* for i = 1, ... N result<i-1> = 1 other bits are zero  */
97 static inline uint64_t
98 ones (int N)
99 {
100   return (N == 64 ? (uint64_t)-1UL : ((1UL << N) - 1));
101 }
102
103 /* result<0> to val<N>  */
104 static inline uint64_t
105 pickbit (uint64_t val, int N)
106 {
107   return pickbits64 (val, N, N);
108 }
109
110 static uint64_t
111 expand_logical_immediate (uint32_t S, uint32_t R, uint32_t N)
112 {
113   uint64_t mask;
114   uint64_t imm;
115   unsigned simd_size;
116
117   /* The immediate value is S+1 bits to 1, left rotated by SIMDsize - R
118      (in other words, right rotated by R), then replicated. */
119   if (N != 0)
120     {
121       simd_size = 64;
122       mask = 0xffffffffffffffffull;
123     }
124   else
125     {
126       switch (S)
127         {
128         case 0x00 ... 0x1f: /* 0xxxxx */ simd_size = 32;           break;
129         case 0x20 ... 0x2f: /* 10xxxx */ simd_size = 16; S &= 0xf; break;
130         case 0x30 ... 0x37: /* 110xxx */ simd_size =  8; S &= 0x7; break;
131         case 0x38 ... 0x3b: /* 1110xx */ simd_size =  4; S &= 0x3; break;
132         case 0x3c ... 0x3d: /* 11110x */ simd_size =  2; S &= 0x1; break;
133         default: return 0;
134         }
135       mask = (1ull << simd_size) - 1;
136       /* Top bits are IGNORED.  */
137       R &= simd_size - 1;
138     }
139
140   /* NOTE: if S = simd_size - 1 we get 0xf..f which is rejected.  */
141   if (S == simd_size - 1)
142     return 0;
143
144   /* S+1 consecutive bits to 1.  */
145   /* NOTE: S can't be 63 due to detection above.  */
146   imm = (1ull << (S + 1)) - 1;
147
148   /* Rotate to the left by simd_size - R.  */
149   if (R != 0)
150     imm = ((imm << (simd_size - R)) & mask) | (imm >> R);
151
152   /* Replicate the value according to SIMD size.  */
153   switch (simd_size)
154     {
155     case  2: imm = (imm <<  2) | imm;
156     case  4: imm = (imm <<  4) | imm;
157     case  8: imm = (imm <<  8) | imm;
158     case 16: imm = (imm << 16) | imm;
159     case 32: imm = (imm << 32) | imm;
160     case 64: break;
161     default: return 0;
162     }
163
164   return imm;
165 }
166
167 /* Instr[22,10] encodes N immr and imms. we want a lookup table
168    for each possible combination i.e. 13 bits worth of int entries.  */
169 #define  LI_TABLE_SIZE  (1 << 13)
170 static uint64_t LITable[LI_TABLE_SIZE];
171
172 void
173 aarch64_init_LIT_table (void)
174 {
175   unsigned index;
176
177   for (index = 0; index < LI_TABLE_SIZE; index++)
178     {
179       uint32_t N    = uimm (index, 12, 12);
180       uint32_t immr = uimm (index, 11, 6);
181       uint32_t imms = uimm (index, 5, 0);
182
183       LITable [index] = expand_logical_immediate (imms, immr, N);
184     }
185 }
186
187 static void
188 dexNotify (sim_cpu *cpu)
189 {
190   /* instr[14,0] == type : 0 ==> method entry, 1 ==> method reentry
191                            2 ==> exit Java, 3 ==> start next bytecode.  */
192   uint32_t type = uimm (aarch64_get_instr (cpu), 14, 0);
193
194   TRACE_EVENTS (cpu, "Notify Insn encountered, type = 0x%x", type);
195
196   switch (type)
197     {
198     case 0:
199       /* aarch64_notifyMethodEntry (aarch64_get_reg_u64 (cpu, R23, 0),
200          aarch64_get_reg_u64 (cpu, R22, 0));  */
201       break;
202     case 1:
203       /* aarch64_notifyMethodReentry (aarch64_get_reg_u64 (cpu, R23, 0),
204          aarch64_get_reg_u64 (cpu, R22, 0));  */
205       break;
206     case 2:
207       /* aarch64_notifyMethodExit ();  */
208       break;
209     case 3:
210       /* aarch64_notifyBCStart (aarch64_get_reg_u64 (cpu, R23, 0),
211          aarch64_get_reg_u64 (cpu, R22, 0));  */
212       break;
213     }
214 }
215
216 /* secondary decode within top level groups  */
217
218 static void
219 dexPseudo (sim_cpu *cpu)
220 {
221   /* assert instr[28,27] = 00
222
223      We provide 2 pseudo instructions:
224
225      HALT stops execution of the simulator causing an immediate
226      return to the x86 code which entered it.
227
228      CALLOUT initiates recursive entry into x86 code.  A register
229      argument holds the address of the x86 routine.  Immediate
230      values in the instruction identify the number of general
231      purpose and floating point register arguments to be passed
232      and the type of any value to be returned.  */
233
234   uint32_t PSEUDO_HALT      =  0xE0000000U;
235   uint32_t PSEUDO_CALLOUT   =  0x00018000U;
236   uint32_t PSEUDO_CALLOUTR  =  0x00018001U;
237   uint32_t PSEUDO_NOTIFY    =  0x00014000U;
238   uint32_t dispatch;
239
240   if (aarch64_get_instr (cpu) == PSEUDO_HALT)
241     {
242       TRACE_EVENTS (cpu, " Pseudo Halt Instruction");
243       sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
244                        sim_stopped, SIM_SIGTRAP);
245     }
246
247   dispatch = uimm (aarch64_get_instr (cpu), 31, 15);
248
249   /* We do not handle callouts at the moment.  */
250   if (dispatch == PSEUDO_CALLOUT || dispatch == PSEUDO_CALLOUTR)
251     {
252       TRACE_EVENTS (cpu, " Callout");
253       sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
254                        sim_stopped, SIM_SIGABRT);
255     }
256
257   else if (dispatch == PSEUDO_NOTIFY)
258     dexNotify (cpu);
259
260   else
261     HALT_UNALLOC;
262 }
263
264 /* Load-store single register (unscaled offset)
265    These instructions employ a base register plus an unscaled signed
266    9 bit offset.
267
268    N.B. the base register (source) can be Xn or SP. all other
269    registers may not be SP.  */
270
271 /* 32 bit load 32 bit unscaled signed 9 bit.  */
272 static void
273 ldur32 (sim_cpu *cpu, int32_t offset)
274 {
275   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
276   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
277
278   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32
279                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
280                         + offset));
281 }
282
283 /* 64 bit load 64 bit unscaled signed 9 bit.  */
284 static void
285 ldur64 (sim_cpu *cpu, int32_t offset)
286 {
287   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
288   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
289
290   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64
291                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
292                         + offset));
293 }
294
295 /* 32 bit load zero-extended byte unscaled signed 9 bit.  */
296 static void
297 ldurb32 (sim_cpu *cpu, int32_t offset)
298 {
299   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
300   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
301
302   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u8
303                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
304                         + offset));
305 }
306
307 /* 32 bit load sign-extended byte unscaled signed 9 bit.  */
308 static void
309 ldursb32 (sim_cpu *cpu, int32_t offset)
310 {
311   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
312   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
313
314   aarch64_set_reg_u64 (cpu, rt, NO_SP, (uint32_t) aarch64_get_mem_s8
315                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
316                         + offset));
317 }
318
319 /* 64 bit load sign-extended byte unscaled signed 9 bit.  */
320 static void
321 ldursb64 (sim_cpu *cpu, int32_t offset)
322 {
323   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
324   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
325
326   aarch64_set_reg_s64 (cpu, rt, NO_SP, aarch64_get_mem_s8
327                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
328                         + offset));
329 }
330
331 /* 32 bit load zero-extended short unscaled signed 9 bit  */
332 static void
333 ldurh32 (sim_cpu *cpu, int32_t offset)
334 {
335   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
336   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
337
338   aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_mem_u16
339                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
340                         + offset));
341 }
342
343 /* 32 bit load sign-extended short unscaled signed 9 bit  */
344 static void
345 ldursh32 (sim_cpu *cpu, int32_t offset)
346 {
347   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
348   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
349
350   aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) aarch64_get_mem_s16
351                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
352                         + offset));
353 }
354
355 /* 64 bit load sign-extended short unscaled signed 9 bit  */
356 static void
357 ldursh64 (sim_cpu *cpu, int32_t offset)
358 {
359   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
360   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
361
362   aarch64_set_reg_s64 (cpu, rt, NO_SP, aarch64_get_mem_s16
363                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
364                         + offset));
365 }
366
367 /* 64 bit load sign-extended word unscaled signed 9 bit  */
368 static void
369 ldursw (sim_cpu *cpu, int32_t offset)
370 {
371   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
372   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
373
374   aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) aarch64_get_mem_s32
375                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
376                         + offset));
377 }
378
379 /* N.B. with stores the value in source is written to the address
380    identified by source2 modified by offset.  */
381
382 /* 32 bit store 32 bit unscaled signed 9 bit.  */
383 static void
384 stur32 (sim_cpu *cpu, int32_t offset)
385 {
386   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
387   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
388
389   aarch64_set_mem_u32 (cpu,
390                        aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
391                        aarch64_get_reg_u32 (cpu, rd, NO_SP));
392 }
393
394 /* 64 bit store 64 bit unscaled signed 9 bit  */
395 static void
396 stur64 (sim_cpu *cpu, int32_t offset)
397 {
398   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
399   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
400
401   aarch64_set_mem_u64 (cpu,
402                        aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
403                        aarch64_get_reg_u64 (cpu, rd, NO_SP));
404 }
405
406 /* 32 bit store byte unscaled signed 9 bit  */
407 static void
408 sturb (sim_cpu *cpu, int32_t offset)
409 {
410   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
411   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
412
413   aarch64_set_mem_u8 (cpu,
414                       aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
415                       aarch64_get_reg_u8 (cpu, rd, NO_SP));
416 }
417
418 /* 32 bit store short unscaled signed 9 bit  */
419 static void
420 sturh (sim_cpu *cpu, int32_t offset)
421 {
422   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
423   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
424
425   aarch64_set_mem_u16 (cpu,
426                        aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
427                        aarch64_get_reg_u16 (cpu, rd, NO_SP));
428 }
429
430 /* Load single register pc-relative label
431    Offset is a signed 19 bit immediate count in words
432    rt may not be SP.  */
433
434 /* 32 bit pc-relative load  */
435 static void
436 ldr32_pcrel (sim_cpu *cpu, int32_t offset)
437 {
438   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
439
440   aarch64_set_reg_u64 (cpu, rd, NO_SP,
441                        aarch64_get_mem_u32
442                        (cpu, aarch64_get_PC (cpu) + offset * 4));
443 }
444
445 /* 64 bit pc-relative load  */
446 static void
447 ldr_pcrel (sim_cpu *cpu, int32_t offset)
448 {
449   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
450
451   aarch64_set_reg_u64 (cpu, rd, NO_SP,
452                        aarch64_get_mem_u64
453                        (cpu, aarch64_get_PC (cpu) + offset * 4));
454 }
455
456 /* sign extended 32 bit pc-relative load  */
457 static void
458 ldrsw_pcrel (sim_cpu *cpu, int32_t offset)
459 {
460   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
461
462   aarch64_set_reg_u64 (cpu, rd, NO_SP,
463                        aarch64_get_mem_s32
464                        (cpu, aarch64_get_PC (cpu) + offset * 4));
465 }
466
467 /* float pc-relative load  */
468 static void
469 fldrs_pcrel (sim_cpu *cpu, int32_t offset)
470 {
471   unsigned int rd = uimm (aarch64_get_instr (cpu), 4, 0);
472
473   aarch64_set_FP_float (cpu, rd,
474                         aarch64_get_mem_float
475                         (cpu, aarch64_get_PC (cpu) + offset * 4));
476 }
477
478 /* double pc-relative load  */
479 static void
480 fldrd_pcrel (sim_cpu *cpu, int32_t offset)
481 {
482   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
483
484   aarch64_set_FP_double (cpu, st,
485                          aarch64_get_mem_double
486                          (cpu, aarch64_get_PC (cpu) + offset * 4));
487 }
488
489 /* long double pc-relative load.  */
490 static void
491 fldrq_pcrel (sim_cpu *cpu, int32_t offset)
492 {
493   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
494   uint64_t addr = aarch64_get_PC (cpu) + offset * 4;
495   FRegister a;
496
497   aarch64_get_mem_long_double (cpu, addr, & a);
498   aarch64_set_FP_long_double (cpu, st, a);
499 }
500
501 /* This can be used to scale an offset by applying
502    the requisite shift. the second argument is either
503    16, 32 or 64.  */
504
505 #define SCALE(_offset, _elementSize) \
506     ((_offset) << ScaleShift ## _elementSize)
507
508 /* This can be used to optionally scale a register derived offset
509    by applying the requisite shift as indicated by the Scaling
510    argument. the second argument is either Byte, Short, Word
511    or Long. The third argument is either Scaled or Unscaled.
512    N.B. when _Scaling is Scaled the shift gets ANDed with
513    all 1s while when it is Unscaled it gets ANDed with 0.  */
514
515 #define OPT_SCALE(_offset, _elementType, _Scaling) \
516   ((_offset) << (_Scaling ? ScaleShift ## _elementType : 0))
517
518 /* This can be used to zero or sign extend a 32 bit register derived
519    value to a 64 bit value.  the first argument must be the value as
520    a uint32_t and the second must be either UXTW or SXTW. The result
521    is returned as an int64_t.  */
522
523 static inline int64_t
524 extend (uint32_t value, Extension extension)
525 {
526   union
527   {
528     uint32_t u;
529     int32_t   n;
530   } x;
531
532   /* A branchless variant of this ought to be possible.  */
533   if (extension == UXTW || extension == NoExtension)
534     return value;
535
536   x.u = value;
537   return x.n;
538 }
539
540 /* Scalar Floating Point
541
542    FP load/store single register (4 addressing modes)
543
544    N.B. the base register (source) can be the stack pointer.
545    The secondary source register (source2) can only be an Xn register.  */
546
547 /* Load 32 bit unscaled signed 9 bit with pre- or post-writeback.  */
548 static void
549 fldrs_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
550 {
551   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
552   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
553   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
554
555   if (wb != Post)
556     address += offset;
557
558   aarch64_set_FP_float (cpu, st, aarch64_get_mem_float (cpu, address));
559   if (wb == Post)
560     address += offset;
561
562   if (wb != NoWriteBack)
563     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
564 }
565
566 /* Load 32 bit scaled unsigned 12 bit.  */
567 static void
568 fldrs_abs (sim_cpu *cpu, uint32_t offset)
569 {
570   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
571   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
572
573   aarch64_set_FP_float (cpu, st,
574                         aarch64_get_mem_float
575                         (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
576                          + SCALE (offset, 32)));
577 }
578
579 /* Load 32 bit scaled or unscaled zero- or sign-extended
580    32-bit register offset.  */
581 static void
582 fldrs_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
583 {
584   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
585   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
586   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
587   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
588   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
589   uint64_t displacement = OPT_SCALE (extended, 32, scaling);
590
591   aarch64_set_FP_float (cpu, st,
592                         aarch64_get_mem_float
593                         (cpu, address + displacement));
594 }
595
596 /* Load 64 bit unscaled signed 9 bit with pre- or post-writeback.  */
597 static void
598 fldrd_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
599 {
600   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
601   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
602   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
603
604   if (wb != Post)
605     address += offset;
606
607   aarch64_set_FP_double (cpu, st, aarch64_get_mem_double (cpu, address));
608
609   if (wb == Post)
610     address += offset;
611
612   if (wb != NoWriteBack)
613     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
614 }
615
616 /* Load 64 bit scaled unsigned 12 bit.  */
617 static void
618 fldrd_abs (sim_cpu *cpu, uint32_t offset)
619 {
620   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
621   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
622   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 64);
623
624   aarch64_set_FP_double (cpu, st, aarch64_get_mem_double (cpu, address));
625 }
626
627 /* Load 64 bit scaled or unscaled zero- or sign-extended 32-bit register offset.  */
628 static void
629 fldrd_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
630 {
631   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
632   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
633   uint64_t displacement = OPT_SCALE (extended, 64, scaling);
634
635   fldrd_wb (cpu, displacement, NoWriteBack);
636 }
637
638 /* Load 128 bit unscaled signed 9 bit with pre- or post-writeback.  */
639 static void
640 fldrq_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
641 {
642   FRegister a;
643   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
644   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
645   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
646
647   if (wb != Post)
648     address += offset;
649
650   aarch64_get_mem_long_double (cpu, address, & a);
651   aarch64_set_FP_long_double (cpu, st, a);
652
653   if (wb == Post)
654     address += offset;
655
656   if (wb != NoWriteBack)
657     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
658 }
659
660 /* Load 128 bit scaled unsigned 12 bit.  */
661 static void
662 fldrq_abs (sim_cpu *cpu, uint32_t offset)
663 {
664   FRegister a;
665   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
666   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
667   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 128);
668
669   aarch64_get_mem_long_double (cpu, address, & a);
670   aarch64_set_FP_long_double (cpu, st, a);
671 }
672
673 /* Load 128 bit scaled or unscaled zero- or sign-extended 32-bit register offset  */
674 static void
675 fldrq_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
676 {
677   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
678   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
679   uint64_t displacement = OPT_SCALE (extended, 128, scaling);
680
681   fldrq_wb (cpu, displacement, NoWriteBack);
682 }
683
684 /* Memory Access
685
686    load-store single register
687    There are four addressing modes available here which all employ a
688    64 bit source (base) register.
689
690    N.B. the base register (source) can be the stack pointer.
691    The secondary source register (source2)can only be an Xn register.
692
693    Scaled, 12-bit, unsigned immediate offset, without pre- and
694    post-index options.
695    Unscaled, 9-bit, signed immediate offset with pre- or post-index
696    writeback.
697    scaled or unscaled 64-bit register offset.
698    scaled or unscaled 32-bit extended register offset.
699
700    All offsets are assumed to be raw from the decode i.e. the
701    simulator is expected to adjust scaled offsets based on the
702    accessed data size with register or extended register offset
703    versions the same applies except that in the latter case the
704    operation may also require a sign extend.
705
706    A separate method is provided for each possible addressing mode.  */
707
708 /* 32 bit load 32 bit scaled unsigned 12 bit  */
709 static void
710 ldr32_abs (sim_cpu *cpu, uint32_t offset)
711 {
712   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
713   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
714
715   /* The target register may not be SP but the source may be.  */
716   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32
717                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
718                         + SCALE (offset, 32)));
719 }
720
721 /* 32 bit load 32 bit unscaled signed 9 bit with pre- or post-writeback.  */
722 static void
723 ldr32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
724 {
725   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
726   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
727   uint64_t address;
728
729   if (rn == rt && wb != NoWriteBack)
730     HALT_UNALLOC;
731
732   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
733
734   if (wb != Post)
735     address += offset;
736
737   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32 (cpu, address));
738
739   if (wb == Post)
740     address += offset;
741
742   if (wb != NoWriteBack)
743     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
744 }
745
746 /* 32 bit load 32 bit scaled or unscaled
747    zero- or sign-extended 32-bit register offset  */
748 static void
749 ldr32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
750 {
751   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
752   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
753   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
754   /* rn may reference SP, rm and rt must reference ZR  */
755
756   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
757   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
758   uint64_t displacement =  OPT_SCALE (extended, 32, scaling);
759
760   aarch64_set_reg_u64 (cpu, rt, NO_SP,
761                        aarch64_get_mem_u32 (cpu, address + displacement));
762 }
763
764 /* 64 bit load 64 bit scaled unsigned 12 bit  */
765 static void
766 ldr_abs (sim_cpu *cpu, uint32_t offset)
767 {
768   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
769   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
770
771   /* The target register may not be SP but the source may be.  */
772   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64
773                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
774                         + SCALE (offset, 64)));
775 }
776
777 /* 64 bit load 64 bit unscaled signed 9 bit with pre- or post-writeback.  */
778 static void
779 ldr_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
780 {
781   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
782   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
783   uint64_t address;
784
785   if (rn == rt && wb != NoWriteBack)
786     HALT_UNALLOC;
787
788   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
789
790   if (wb != Post)
791     address += offset;
792
793   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64 (cpu, address));
794
795   if (wb == Post)
796     address += offset;
797
798   if (wb != NoWriteBack)
799     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
800 }
801
802 /* 64 bit load 64 bit scaled or unscaled zero-
803    or sign-extended 32-bit register offset.  */
804 static void
805 ldr_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
806 {
807   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
808   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
809   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
810   /* rn may reference SP, rm and rt must reference ZR  */
811
812   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
813   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
814   uint64_t displacement =  OPT_SCALE (extended, 64, scaling);
815
816   aarch64_set_reg_u64 (cpu, rt, NO_SP,
817                        aarch64_get_mem_u64 (cpu, address + displacement));
818 }
819
820 /* 32 bit load zero-extended byte scaled unsigned 12 bit.  */
821 static void
822 ldrb32_abs (sim_cpu *cpu, uint32_t offset)
823 {
824   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
825   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
826
827   /* The target register may not be SP but the source may be
828      there is no scaling required for a byte load.  */
829   aarch64_set_reg_u64 (cpu, rt, NO_SP,
830                        aarch64_get_mem_u8
831                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset));
832 }
833
834 /* 32 bit load zero-extended byte unscaled signed 9 bit with pre- or post-writeback.  */
835 static void
836 ldrb32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
837 {
838   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
839   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
840   uint64_t address;
841
842   if (rn == rt && wb != NoWriteBack)
843     HALT_UNALLOC;
844
845   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
846
847   if (wb != Post)
848     address += offset;
849
850   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u8 (cpu, address));
851
852   if (wb == Post)
853     address += offset;
854
855   if (wb != NoWriteBack)
856     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
857 }
858
859 /* 32 bit load zero-extended byte scaled or unscaled zero-
860    or sign-extended 32-bit register offset.  */
861 static void
862 ldrb32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
863 {
864   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
865   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
866   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
867   /* rn may reference SP, rm and rt must reference ZR  */
868
869   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
870   int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
871                                  extension);
872
873   /* There is no scaling required for a byte load.  */
874   aarch64_set_reg_u64 (cpu, rt, NO_SP,
875                        aarch64_get_mem_u8 (cpu, address + displacement));
876 }
877
878 /* 64 bit load sign-extended byte unscaled signed 9 bit
879    with pre- or post-writeback.  */
880 static void
881 ldrsb_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
882 {
883   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
884   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
885   uint64_t address;
886
887   if (rn == rt && wb != NoWriteBack)
888     HALT_UNALLOC;
889
890   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
891
892   if (wb != Post)
893     address += offset;
894
895   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_s8 (cpu, address));
896
897   if (wb == Post)
898     address += offset;
899
900   if (wb != NoWriteBack)
901     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
902 }
903
904 /* 64 bit load sign-extended byte scaled unsigned 12 bit.  */
905 static void
906 ldrsb_abs (sim_cpu *cpu, uint32_t offset)
907 {
908   ldrsb_wb (cpu, offset, NoWriteBack);
909 }
910
911 /* 64 bit load sign-extended byte scaled or unscaled zero-
912    or sign-extended 32-bit register offset.  */
913 static void
914 ldrsb_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
915 {
916   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
917   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
918   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
919   /* rn may reference SP, rm and rt must reference ZR  */
920
921   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
922   int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
923                                  extension);
924   /* There is no scaling required for a byte load.  */
925   aarch64_set_reg_u64 (cpu, rt, NO_SP,
926                        aarch64_get_mem_s8 (cpu, address + displacement));
927 }
928
929 /* 32 bit load zero-extended short scaled unsigned 12 bit.  */
930 static void
931 ldrh32_abs (sim_cpu *cpu, uint32_t offset)
932 {
933   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
934   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
935
936   /* The target register may not be SP but the source may be.  */
937   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u16
938                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
939                         + SCALE (offset, 16)));
940 }
941
942 /* 32 bit load zero-extended short unscaled signed 9 bit
943    with pre- or post-writeback.  */
944 static void
945 ldrh32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
946 {
947   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
948   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
949   uint64_t address;
950
951   if (rn == rt && wb != NoWriteBack)
952     HALT_UNALLOC;
953
954   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
955
956   if (wb != Post)
957     address += offset;
958
959   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u16 (cpu, address));
960
961   if (wb == Post)
962     address += offset;
963
964   if (wb != NoWriteBack)
965     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
966 }
967
968 /* 32 bit load zero-extended short scaled or unscaled zero-
969    or sign-extended 32-bit register offset.  */
970 static void
971 ldrh32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
972 {
973   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
974   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
975   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
976   /* rn may reference SP, rm and rt must reference ZR  */
977
978   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
979   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
980   uint64_t displacement =  OPT_SCALE (extended, 16, scaling);
981
982   aarch64_set_reg_u64 (cpu, rt, NO_SP,
983                        aarch64_get_mem_u16 (cpu, address + displacement));
984 }
985
986 /* 32 bit load sign-extended short scaled unsigned 12 bit.  */
987 static void
988 ldrsh32_abs (sim_cpu *cpu, uint32_t offset)
989 {
990   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
991   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
992
993   /* The target register may not be SP but the source may be.  */
994   aarch64_set_reg_u64 (cpu, rt, NO_SP, (uint32_t) aarch64_get_mem_s16
995                        (cpu,
996                         aarch64_get_reg_u64 (cpu, rn, SP_OK)
997                         + SCALE (offset, 16)));
998 }
999
1000 /* 32 bit load sign-extended short unscaled signed 9 bit
1001    with pre- or post-writeback.  */
1002 static void
1003 ldrsh32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1004 {
1005   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1006   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1007   uint64_t address;
1008
1009   if (rn == rt && wb != NoWriteBack)
1010     HALT_UNALLOC;
1011
1012   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1013
1014   if (wb != Post)
1015     address += offset;
1016
1017   aarch64_set_reg_u64 (cpu, rt, NO_SP,
1018                        (uint32_t) aarch64_get_mem_s16 (cpu, address));
1019
1020   if (wb == Post)
1021     address += offset;
1022
1023   if (wb != NoWriteBack)
1024     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1025 }
1026
1027 /* 32 bit load sign-extended short scaled or unscaled zero-
1028    or sign-extended 32-bit register offset.  */
1029 static void
1030 ldrsh32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1031 {
1032   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1033   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1034   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1035   /* rn may reference SP, rm and rt must reference ZR  */
1036
1037   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1038   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1039   uint64_t displacement =  OPT_SCALE (extended, 16, scaling);
1040
1041   aarch64_set_reg_u64 (cpu, rt, NO_SP,
1042                        (uint32_t) aarch64_get_mem_s16
1043                        (cpu, address + displacement));
1044 }
1045
1046 /* 64 bit load sign-extended short scaled unsigned 12 bit.  */
1047 static void
1048 ldrsh_abs (sim_cpu *cpu, uint32_t offset)
1049 {
1050   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1051   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1052
1053   /* The target register may not be SP but the source may be.  */
1054   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_s16
1055                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
1056                         + SCALE (offset, 16)));
1057 }
1058
1059 /* 64 bit load sign-extended short unscaled signed 9 bit
1060    with pre- or post-writeback.  */
1061 static void
1062 ldrsh64_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1063 {
1064   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1065   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1066   uint64_t address;
1067
1068   if (rn == rt && wb != NoWriteBack)
1069     HALT_UNALLOC;
1070
1071   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1072
1073   if (wb != Post)
1074     address += offset;
1075
1076   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_s16 (cpu, address));
1077
1078   if (wb == Post)
1079     address += offset;
1080
1081   if (wb != NoWriteBack)
1082     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1083 }
1084
1085 /* 64 bit load sign-extended short scaled or unscaled zero-
1086    or sign-extended 32-bit register offset.  */
1087 static void
1088 ldrsh_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1089 {
1090   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1091   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1092   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1093   /* rn may reference SP, rm and rt must reference ZR  */
1094
1095   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1096   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1097   uint64_t displacement = OPT_SCALE (extended, 16, scaling);
1098
1099   aarch64_set_reg_u64 (cpu, rt, NO_SP,
1100                        aarch64_get_mem_s16 (cpu, address + displacement));
1101 }
1102
1103 /* 64 bit load sign-extended 32 bit scaled unsigned 12 bit.  */
1104 static void
1105 ldrsw_abs (sim_cpu *cpu, uint32_t offset)
1106 {
1107   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1108   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1109
1110   /* The target register may not be SP but the source may be.  */
1111   return aarch64_set_reg_s64 (cpu, rt, NO_SP, aarch64_get_mem_s32
1112                               (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
1113                                + SCALE (offset, 32)));
1114 }
1115
1116 /* 64 bit load sign-extended 32 bit unscaled signed 9 bit
1117    with pre- or post-writeback.  */
1118 static void
1119 ldrsw_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1120 {
1121   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1122   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1123   uint64_t address;
1124
1125   if (rn == rt && wb != NoWriteBack)
1126     HALT_UNALLOC;
1127
1128   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1129
1130   if (wb != Post)
1131     address += offset;
1132
1133   aarch64_set_reg_s64 (cpu, rt, NO_SP, aarch64_get_mem_s32 (cpu, address));
1134
1135   if (wb == Post)
1136     address += offset;
1137
1138   if (wb != NoWriteBack)
1139     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1140 }
1141
1142 /* 64 bit load sign-extended 32 bit scaled or unscaled zero-
1143    or sign-extended 32-bit register offset.  */
1144 static void
1145 ldrsw_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1146 {
1147   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1148   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1149   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1150   /* rn may reference SP, rm and rt must reference ZR  */
1151
1152   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1153   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1154   uint64_t displacement =  OPT_SCALE (extended, 32, scaling);
1155
1156   aarch64_set_reg_s64 (cpu, rt, NO_SP,
1157                        aarch64_get_mem_s32 (cpu, address + displacement));
1158 }
1159
1160 /* N.B. with stores the value in source is written to the
1161    address identified by source2 modified by source3/offset.  */
1162
1163 /* 32 bit store scaled unsigned 12 bit.  */
1164 static void
1165 str32_abs (sim_cpu *cpu, uint32_t offset)
1166 {
1167   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1168   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1169
1170   /* The target register may not be SP but the source may be.  */
1171   aarch64_set_mem_u32 (cpu, (aarch64_get_reg_u64 (cpu, rn, SP_OK)
1172                              + SCALE (offset, 32)),
1173                        aarch64_get_reg_u32 (cpu, rt, NO_SP));
1174 }
1175
1176 /* 32 bit store unscaled signed 9 bit with pre- or post-writeback.  */
1177 static void
1178 str32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1179 {
1180   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1181   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1182   uint64_t address;
1183
1184   if (rn == rt && wb != NoWriteBack)
1185     HALT_UNALLOC;
1186
1187   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1188   if (wb != Post)
1189     address += offset;
1190
1191   aarch64_set_mem_u32 (cpu, address, aarch64_get_reg_u32 (cpu, rt, NO_SP));
1192
1193   if (wb == Post)
1194     address += offset;
1195
1196   if (wb != NoWriteBack)
1197     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1198 }
1199
1200 /* 32 bit store scaled or unscaled zero- or
1201    sign-extended 32-bit register offset.  */
1202 static void
1203 str32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1204 {
1205   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1206   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1207   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1208
1209   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1210   int64_t  extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1211   uint64_t displacement = OPT_SCALE (extended, 32, scaling);
1212
1213   aarch64_set_mem_u32 (cpu, address + displacement,
1214                        aarch64_get_reg_u64 (cpu, rt, NO_SP));
1215 }
1216
1217 /* 64 bit store scaled unsigned 12 bit.  */
1218 static void
1219 str_abs (sim_cpu *cpu, uint32_t offset)
1220 {
1221   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1222   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1223
1224   aarch64_set_mem_u64 (cpu,
1225                        aarch64_get_reg_u64 (cpu, rn, SP_OK)
1226                        + SCALE (offset, 64),
1227                        aarch64_get_reg_u64 (cpu, rt, NO_SP));
1228 }
1229
1230 /* 64 bit store unscaled signed 9 bit with pre- or post-writeback.  */
1231 static void
1232 str_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1233 {
1234   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1235   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1236   uint64_t address;
1237
1238   if (rn == rt && wb != NoWriteBack)
1239     HALT_UNALLOC;
1240
1241   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1242
1243   if (wb != Post)
1244     address += offset;
1245
1246   aarch64_set_mem_u64 (cpu, address, aarch64_get_reg_u64 (cpu, rt, NO_SP));
1247
1248   if (wb == Post)
1249     address += offset;
1250
1251   if (wb != NoWriteBack)
1252     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1253 }
1254
1255 /* 64 bit store scaled or unscaled zero-
1256    or sign-extended 32-bit register offset.  */
1257 static void
1258 str_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1259 {
1260   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1261   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1262   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1263   /* rn may reference SP, rm and rt must reference ZR  */
1264
1265   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1266   int64_t   extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1267                                extension);
1268   uint64_t displacement = OPT_SCALE (extended, 64, scaling);
1269
1270   aarch64_set_mem_u64 (cpu, address + displacement,
1271                        aarch64_get_reg_u64 (cpu, rt, NO_SP));
1272 }
1273
1274 /* 32 bit store byte scaled unsigned 12 bit.  */
1275 static void
1276 strb_abs (sim_cpu *cpu, uint32_t offset)
1277 {
1278   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1279   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1280
1281   /* The target register may not be SP but the source may be.
1282      There is no scaling required for a byte load.  */
1283   aarch64_set_mem_u8 (cpu,
1284                       aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
1285                       aarch64_get_reg_u8 (cpu, rt, NO_SP));
1286 }
1287
1288 /* 32 bit store byte unscaled signed 9 bit with pre- or post-writeback.  */
1289 static void
1290 strb_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1291 {
1292   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1293   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1294   uint64_t address;
1295
1296   if (rn == rt && wb != NoWriteBack)
1297     HALT_UNALLOC;
1298
1299   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1300
1301   if (wb != Post)
1302     address += offset;
1303
1304   aarch64_set_mem_u8 (cpu, address, aarch64_get_reg_u8 (cpu, rt, NO_SP));
1305
1306   if (wb == Post)
1307     address += offset;
1308
1309   if (wb != NoWriteBack)
1310     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1311 }
1312
1313 /* 32 bit store byte scaled or unscaled zero-
1314    or sign-extended 32-bit register offset.  */
1315 static void
1316 strb_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1317 {
1318   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1319   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1320   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1321   /* rn may reference SP, rm and rt must reference ZR  */
1322
1323   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1324   int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1325                                  extension);
1326
1327   /* There is no scaling required for a byte load.  */
1328   aarch64_set_mem_u8 (cpu, address + displacement,
1329                       aarch64_get_reg_u8 (cpu, rt, NO_SP));
1330 }
1331
1332 /* 32 bit store short scaled unsigned 12 bit.  */
1333 static void
1334 strh_abs (sim_cpu *cpu, uint32_t offset)
1335 {
1336   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1337   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1338
1339   /* The target register may not be SP but the source may be.  */
1340   aarch64_set_mem_u16 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
1341                        + SCALE (offset, 16),
1342                        aarch64_get_reg_u16 (cpu, rt, NO_SP));
1343 }
1344
1345 /* 32 bit store short unscaled signed 9 bit with pre- or post-writeback.  */
1346 static void
1347 strh_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1348 {
1349   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1350   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1351   uint64_t address;
1352
1353   if (rn == rt && wb != NoWriteBack)
1354     HALT_UNALLOC;
1355
1356   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1357
1358   if (wb != Post)
1359     address += offset;
1360
1361   aarch64_set_mem_u16 (cpu, address, aarch64_get_reg_u16 (cpu, rt, NO_SP));
1362
1363   if (wb == Post)
1364     address += offset;
1365
1366   if (wb != NoWriteBack)
1367     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1368 }
1369
1370 /* 32 bit store short scaled or unscaled zero-
1371    or sign-extended 32-bit register offset.  */
1372 static void
1373 strh_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1374 {
1375   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1376   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1377   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1378   /* rn may reference SP, rm and rt must reference ZR  */
1379
1380   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1381   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1382   uint64_t displacement =  OPT_SCALE (extended, 16, scaling);
1383
1384   aarch64_set_mem_u16 (cpu, address + displacement,
1385                        aarch64_get_reg_u16 (cpu, rt, NO_SP));
1386 }
1387
1388 /* Prefetch unsigned 12 bit.  */
1389 static void
1390 prfm_abs (sim_cpu *cpu, uint32_t offset)
1391 {
1392   /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1393                           00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1394                           00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1395                           10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1396                           10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1397                           10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1398                           ow ==> UNALLOC
1399      PrfOp prfop = prfop (aarch64_get_instr (cpu), 4, 0);
1400      uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK)
1401      + SCALE (offset, 64).  */
1402
1403   /* TODO : implement prefetch of address.  */
1404 }
1405
1406 /* Prefetch scaled or unscaled zero- or sign-extended 32-bit register offset.  */
1407 static void
1408 prfm_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1409 {
1410   /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1411                           00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1412                           00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1413                           10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1414                           10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1415                           10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1416                           ow ==> UNALLOC
1417      rn may reference SP, rm may only reference ZR
1418      PrfOp prfop = prfop (aarch64_get_instr (cpu), 4, 0);
1419      uint64_t base = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1420      int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1421                                 extension);
1422      uint64_t displacement =  OPT_SCALE (extended, 64, scaling);
1423      uint64_t address = base + displacement.  */
1424
1425   /* TODO : implement prefetch of address  */
1426 }
1427
1428 /* 64 bit pc-relative prefetch.  */
1429 static void
1430 prfm_pcrel (sim_cpu *cpu, int32_t offset)
1431 {
1432   /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1433                           00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1434                           00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1435                           10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1436                           10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1437                           10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1438                           ow ==> UNALLOC
1439      PrfOp prfop = prfop (aarch64_get_instr (cpu), 4, 0);
1440      uint64_t address = aarch64_get_PC (cpu) + offset.  */
1441
1442   /* TODO : implement this  */
1443 }
1444
1445 /* Load-store exclusive.  */
1446
1447 static void
1448 ldxr (sim_cpu *cpu)
1449 {
1450   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1451   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1452   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1453   int size = uimm (aarch64_get_instr (cpu), 31, 30);
1454   /* int ordered = uimm (aarch64_get_instr (cpu), 15, 15);  */
1455   /* int exclusive = ! uimm (aarch64_get_instr (cpu), 23, 23);  */
1456
1457   switch (size)
1458     {
1459     case 0:
1460       aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u8 (cpu, address));
1461       break;
1462     case 1:
1463       aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u16 (cpu, address));
1464       break;
1465     case 2:
1466       aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32 (cpu, address));
1467       break;
1468     case 3:
1469       aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64 (cpu, address));
1470       break;
1471     default:
1472       HALT_UNALLOC;
1473     }
1474 }
1475
1476 static void
1477 stxr (sim_cpu *cpu)
1478 {
1479   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1480   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1481   unsigned rs = uimm (aarch64_get_instr (cpu), 20, 16);
1482   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1483   int      size = uimm (aarch64_get_instr (cpu), 31, 30);
1484   uint64_t data = aarch64_get_reg_u64 (cpu, rt, NO_SP);
1485
1486   switch (size)
1487     {
1488     case 0: aarch64_set_mem_u8 (cpu, address, data); break;
1489     case 1: aarch64_set_mem_u16 (cpu, address, data); break;
1490     case 2: aarch64_set_mem_u32 (cpu, address, data); break;
1491     case 3: aarch64_set_mem_u64 (cpu, address, data); break;
1492     default: HALT_UNALLOC;
1493     }
1494
1495   aarch64_set_reg_u64 (cpu, rs, NO_SP, 0); /* Always exclusive...  */
1496 }
1497
1498 static void
1499 dexLoadLiteral (sim_cpu *cpu)
1500 {
1501   /* instr[29,27] == 011
1502      instr[25,24] == 00
1503      instr[31,30:26] = opc: 000 ==> LDRW,  001 ==> FLDRS
1504                             010 ==> LDRX,  011 ==> FLDRD
1505                             100 ==> LDRSW, 101 ==> FLDRQ
1506                             110 ==> PRFM, 111 ==> UNALLOC
1507      instr[26] ==> V : 0 ==> GReg, 1 ==> FReg
1508      instr[23, 5] == simm19  */
1509
1510   /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);  */
1511   uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 1)
1512                         | uimm (aarch64_get_instr (cpu), 26, 26));
1513   int32_t imm = simm32 (aarch64_get_instr (cpu), 23, 5);
1514
1515   switch (dispatch)
1516     {
1517     case 0: ldr32_pcrel (cpu, imm); break;
1518     case 1: fldrs_pcrel (cpu, imm); break;
1519     case 2: ldr_pcrel   (cpu, imm); break;
1520     case 3: fldrd_pcrel (cpu, imm); break;
1521     case 4: ldrsw_pcrel (cpu, imm); break;
1522     case 5: fldrq_pcrel (cpu, imm); break;
1523     case 6: prfm_pcrel  (cpu, imm); break;
1524     case 7:
1525     default:
1526       HALT_UNALLOC;
1527     }
1528 }
1529
1530 /* Immediate arithmetic
1531    The aimm argument is a 12 bit unsigned value or a 12 bit unsigned
1532    value left shifted by 12 bits (done at decode).
1533
1534    N.B. the register args (dest, source) can normally be Xn or SP.
1535    the exception occurs for flag setting instructions which may
1536    only use Xn for the output (dest).  */
1537
1538 /* 32 bit add immediate.  */
1539 static void
1540 add32 (sim_cpu *cpu, uint32_t aimm)
1541 {
1542   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1543   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1544
1545   aarch64_set_reg_u64 (cpu, rd, SP_OK,
1546                        aarch64_get_reg_u32 (cpu, rn, SP_OK) + aimm);
1547 }
1548
1549 /* 64 bit add immediate.  */
1550 static void
1551 add64 (sim_cpu *cpu, uint32_t aimm)
1552 {
1553   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1554   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1555
1556   aarch64_set_reg_u64 (cpu, rd, SP_OK,
1557                        aarch64_get_reg_u64 (cpu, rn, SP_OK) + aimm);
1558 }
1559
1560 static void
1561 set_flags_for_add32 (sim_cpu *cpu, int32_t value1, int32_t value2)
1562 {
1563   int32_t   result = value1 + value2;
1564   int64_t   sresult = (int64_t) value1 + (int64_t) value2;
1565   uint64_t  uresult = (uint64_t)(uint32_t) value1
1566     + (uint64_t)(uint32_t) value2;
1567   uint32_t  flags = 0;
1568
1569   if (result == 0)
1570     flags |= Z;
1571
1572   if (result & (1 << 31))
1573     flags |= N;
1574
1575   if (uresult != result)
1576     flags |= C;
1577
1578   if (sresult != result)
1579     flags |= V;
1580
1581   aarch64_set_CPSR (cpu, flags);
1582 }
1583
1584 static void
1585 set_flags_for_add64 (sim_cpu *cpu, uint64_t value1, uint64_t value2)
1586 {
1587   int64_t   sval1 = value1;
1588   int64_t   sval2 = value2;
1589   uint64_t  result = value1 + value2;
1590   int64_t   sresult = sval1 + sval2;
1591   uint32_t  flags = 0;
1592
1593   if (result == 0)
1594     flags |= Z;
1595
1596   if (result & (1ULL << 63))
1597     flags |= N;
1598
1599   if (sval1 < 0)
1600     {
1601       if (sval2 < 0)
1602         {
1603           /* Negative plus a negative.  Overflow happens if
1604              the result is greater than either of the operands.  */
1605           if (sresult > sval1 || sresult > sval2)
1606             flags |= V;
1607         }
1608       /* else Negative plus a positive.  Overflow cannot happen.  */
1609     }
1610   else /* value1 is +ve.  */
1611     {
1612       if (sval2 < 0)
1613         {
1614           /* Overflow can only occur if we computed "0 - MININT".  */
1615           if (sval1 == 0 && sval2 == (1LL << 63))
1616             flags |= V;
1617         }
1618       else
1619         {
1620           /* Postive plus positive - overflow has happened if the
1621              result is smaller than either of the operands.  */
1622           if (result < value1 || result < value2)
1623             flags |= V | C;
1624         }
1625     }
1626
1627   aarch64_set_CPSR (cpu, flags);
1628 }
1629
1630 #define NEG(a) (((a) & signbit) == signbit)
1631 #define POS(a) (((a) & signbit) == 0)
1632
1633 static void
1634 set_flags_for_sub32 (sim_cpu *cpu, uint32_t value1, uint32_t value2)
1635 {
1636   uint32_t result = value1 - value2;
1637   uint32_t flags = 0;
1638   uint32_t signbit = 1ULL << 31;
1639
1640   if (result == 0)
1641     flags |= Z;
1642
1643   if (NEG (result))
1644     flags |= N;
1645
1646   if (   (NEG (value1) && POS (value2))
1647       || (NEG (value1) && POS (result))
1648       || (POS (value2) && POS (result)))
1649     flags |= C;
1650
1651   if (   (NEG (value1) && POS (value2) && POS (result))
1652       || (POS (value1) && NEG (value2) && NEG (result)))
1653     flags |= V;
1654
1655   aarch64_set_CPSR (cpu, flags);
1656 }
1657
1658 static void
1659 set_flags_for_sub64 (sim_cpu *cpu, uint64_t value1, uint64_t value2)
1660 {
1661   uint64_t result = value1 - value2;
1662   uint32_t flags = 0;
1663   uint64_t signbit = 1ULL << 63;
1664
1665   if (result == 0)
1666     flags |= Z;
1667
1668   if (NEG (result))
1669     flags |= N;
1670
1671   if (   (NEG (value1) && POS (value2))
1672       || (NEG (value1) && POS (result))
1673       || (POS (value2) && POS (result)))
1674     flags |= C;
1675
1676   if (   (NEG (value1) && POS (value2) && POS (result))
1677       || (POS (value1) && NEG (value2) && NEG (result)))
1678     flags |= V;
1679
1680   aarch64_set_CPSR (cpu, flags);
1681 }
1682
1683 static void
1684 set_flags_for_binop32 (sim_cpu *cpu, uint32_t result)
1685 {
1686   uint32_t flags = 0;
1687
1688   if (result == 0)
1689     flags |= Z;
1690   else
1691     flags &= ~ Z;
1692
1693   if (result & (1 << 31))
1694     flags |= N;
1695   else
1696     flags &= ~ N;
1697
1698   aarch64_set_CPSR (cpu, flags);
1699 }
1700
1701 static void
1702 set_flags_for_binop64 (sim_cpu *cpu, uint64_t result)
1703 {
1704   uint32_t flags = 0;
1705
1706   if (result == 0)
1707     flags |= Z;
1708   else
1709     flags &= ~ Z;
1710
1711   if (result & (1ULL << 63))
1712     flags |= N;
1713   else
1714     flags &= ~ N;
1715
1716   aarch64_set_CPSR (cpu, flags);
1717 }
1718
1719 /* 32 bit add immediate set flags.  */
1720 static void
1721 adds32 (sim_cpu *cpu, uint32_t aimm)
1722 {
1723   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1724   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1725   /* TODO : do we need to worry about signs here?  */
1726   int32_t value1 = aarch64_get_reg_s32 (cpu, rn, SP_OK);
1727
1728   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + aimm);
1729   set_flags_for_add32 (cpu, value1, aimm);
1730 }
1731
1732 /* 64 bit add immediate set flags.  */
1733 static void
1734 adds64 (sim_cpu *cpu, uint32_t aimm)
1735 {
1736   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1737   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1738   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1739   uint64_t value2 = aimm;
1740
1741   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
1742   set_flags_for_add64 (cpu, value1, value2);
1743 }
1744
1745 /* 32 bit sub immediate.  */
1746 static void
1747 sub32 (sim_cpu *cpu, uint32_t aimm)
1748 {
1749   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1750   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1751
1752   aarch64_set_reg_u64 (cpu, rd, SP_OK,
1753                        aarch64_get_reg_u32 (cpu, rn, SP_OK) - aimm);
1754 }
1755
1756 /* 64 bit sub immediate.  */
1757 static void
1758 sub64 (sim_cpu *cpu, uint32_t aimm)
1759 {
1760   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1761   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1762
1763   aarch64_set_reg_u64 (cpu, rd, SP_OK,
1764                        aarch64_get_reg_u64 (cpu, rn, SP_OK) - aimm);
1765 }
1766
1767 /* 32 bit sub immediate set flags.  */
1768 static void
1769 subs32 (sim_cpu *cpu, uint32_t aimm)
1770 {
1771   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1772   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1773   uint32_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1774   uint32_t value2 = aimm;
1775
1776   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1777   set_flags_for_sub32 (cpu, value1, value2);
1778 }
1779
1780 /* 64 bit sub immediate set flags.  */
1781 static void
1782 subs64 (sim_cpu *cpu, uint32_t aimm)
1783 {
1784   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1785   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1786   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1787   uint32_t value2 = aimm;
1788
1789   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1790   set_flags_for_sub64 (cpu, value1, value2);
1791 }
1792
1793 /* Data Processing Register.  */
1794
1795 /* First two helpers to perform the shift operations.  */
1796
1797 static inline uint32_t
1798 shifted32 (uint32_t value, Shift shift, uint32_t count)
1799 {
1800   switch (shift)
1801     {
1802     default:
1803     case LSL:
1804       return (value << count);
1805     case LSR:
1806       return (value >> count);
1807     case ASR:
1808       {
1809         int32_t svalue = value;
1810         return (svalue >> count);
1811       }
1812     case ROR:
1813       {
1814         uint32_t top = value >> count;
1815         uint32_t bottom = value << (32 - count);
1816         return (bottom | top);
1817       }
1818     }
1819 }
1820
1821 static inline uint64_t
1822 shifted64 (uint64_t value, Shift shift, uint32_t count)
1823 {
1824   switch (shift)
1825     {
1826     default:
1827     case LSL:
1828       return (value << count);
1829     case LSR:
1830       return (value >> count);
1831     case ASR:
1832       {
1833         int64_t svalue = value;
1834         return (svalue >> count);
1835       }
1836     case ROR:
1837       {
1838         uint64_t top = value >> count;
1839         uint64_t bottom = value << (64 - count);
1840         return (bottom | top);
1841       }
1842     }
1843 }
1844
1845 /* Arithmetic shifted register.
1846    These allow an optional LSL, ASR or LSR to the second source
1847    register with a count up to the register bit count.
1848
1849    N.B register args may not be SP.  */
1850
1851 /* 32 bit ADD shifted register.  */
1852 static void
1853 add32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1854 {
1855   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1856   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1857   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1858
1859   aarch64_set_reg_u64 (cpu, rd, NO_SP,
1860                        aarch64_get_reg_u32 (cpu, rn, NO_SP)
1861                        + shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1862                                     shift, count));
1863 }
1864
1865 /* 64 bit ADD shifted register.  */
1866 static void
1867 add64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1868 {
1869   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1870   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1871   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1872
1873   aarch64_set_reg_u64 (cpu, rd, NO_SP,
1874                        aarch64_get_reg_u64 (cpu, rn, NO_SP)
1875                        + shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1876                                     shift, count));
1877 }
1878
1879 /* 32 bit ADD shifted register setting flags.  */
1880 static void
1881 adds32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1882 {
1883   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1884   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1885   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1886
1887   uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
1888   uint32_t value2 = shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1889                                shift, count);
1890
1891   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
1892   set_flags_for_add32 (cpu, value1, value2);
1893 }
1894
1895 /* 64 bit ADD shifted register setting flags.  */
1896 static void
1897 adds64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1898 {
1899   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1900   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1901   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1902
1903   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
1904   uint64_t value2 = shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1905                                shift, count);
1906
1907   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
1908   set_flags_for_add64 (cpu, value1, value2);
1909 }
1910
1911 /* 32 bit SUB shifted register.  */
1912 static void
1913 sub32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1914 {
1915   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1916   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1917   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1918
1919   aarch64_set_reg_u64 (cpu, rd, NO_SP,
1920                        aarch64_get_reg_u32 (cpu, rn, NO_SP)
1921                        - shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1922                                     shift, count));
1923 }
1924
1925 /* 64 bit SUB shifted register.  */
1926 static void
1927 sub64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1928 {
1929   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1930   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1931   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1932
1933   aarch64_set_reg_u64 (cpu, rd, NO_SP,
1934                        aarch64_get_reg_u64 (cpu, rn, NO_SP)
1935                        - shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1936                                     shift, count));
1937 }
1938
1939 /* 32 bit SUB shifted register setting flags.  */
1940 static void
1941 subs32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1942 {
1943   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1944   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1945   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1946
1947   uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
1948   uint32_t value2 = shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1949                               shift, count);
1950
1951   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1952   set_flags_for_sub32 (cpu, value1, value2);
1953 }
1954
1955 /* 64 bit SUB shifted register setting flags.  */
1956 static void
1957 subs64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1958 {
1959   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1960   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1961   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1962
1963   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
1964   uint64_t value2 = shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1965                                shift, count);
1966
1967   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1968   set_flags_for_sub64 (cpu, value1, value2);
1969 }
1970
1971 /* First a couple more helpers to fetch the
1972    relevant source register element either
1973    sign or zero extended as required by the
1974    extension value.  */
1975
1976 static uint32_t
1977 extreg32 (sim_cpu *cpu, unsigned int lo, Extension extension)
1978 {
1979   switch (extension)
1980     {
1981     case UXTB: return aarch64_get_reg_u8  (cpu, lo, NO_SP);
1982     case UXTH: return aarch64_get_reg_u16 (cpu, lo, NO_SP);
1983     case UXTW: /* Fall through.  */
1984     case UXTX: return aarch64_get_reg_u32 (cpu, lo, NO_SP);
1985     case SXTB: return aarch64_get_reg_s8  (cpu, lo, NO_SP);
1986     case SXTH: return aarch64_get_reg_s16 (cpu, lo, NO_SP);
1987     case SXTW: /* Fall through.  */
1988     case SXTX: /* Fall through.  */
1989     default:   return aarch64_get_reg_s32 (cpu, lo, NO_SP);
1990   }
1991 }
1992
1993 static uint64_t
1994 extreg64 (sim_cpu *cpu, unsigned int lo, Extension extension)
1995 {
1996   switch (extension)
1997     {
1998     case UXTB: return aarch64_get_reg_u8  (cpu, lo, NO_SP);
1999     case UXTH: return aarch64_get_reg_u16 (cpu, lo, NO_SP);
2000     case UXTW: return aarch64_get_reg_u32 (cpu, lo, NO_SP);
2001     case UXTX: return aarch64_get_reg_u64 (cpu, lo, NO_SP);
2002     case SXTB: return aarch64_get_reg_s8  (cpu, lo, NO_SP);
2003     case SXTH: return aarch64_get_reg_s16 (cpu, lo, NO_SP);
2004     case SXTW: return aarch64_get_reg_s32 (cpu, lo, NO_SP);
2005     case SXTX:
2006     default:   return aarch64_get_reg_s64 (cpu, lo, NO_SP);
2007     }
2008 }
2009
2010 /* Arithmetic extending register
2011    These allow an optional sign extension of some portion of the
2012    second source register followed by an optional left shift of
2013    between 1 and 4 bits (i.e. a shift of 0-4 bits???)
2014
2015    N.B output (dest) and first input arg (source) may normally be Xn
2016    or SP. However, for flag setting operations dest can only be
2017    Xn. Second input registers are always Xn.  */
2018
2019 /* 32 bit ADD extending register.  */
2020 static void
2021 add32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2022 {
2023   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2024   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2025   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2026
2027   aarch64_set_reg_u64 (cpu, rd, SP_OK,
2028                        aarch64_get_reg_u32 (cpu, rn, SP_OK)
2029                        + (extreg32 (cpu, rm, extension) << shift));
2030 }
2031
2032 /* 64 bit ADD extending register.
2033    N.B. This subsumes the case with 64 bit source2 and UXTX #n or LSL #0.  */
2034 static void
2035 add64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2036 {
2037   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2038   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2039   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2040
2041   aarch64_set_reg_u64 (cpu, rd, SP_OK,
2042                        aarch64_get_reg_u64 (cpu, rn, SP_OK)
2043                        + (extreg64 (cpu, rm, extension) << shift));
2044 }
2045
2046 /* 32 bit ADD extending register setting flags.  */
2047 static void
2048 adds32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2049 {
2050   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2051   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2052   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2053
2054   uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, SP_OK);
2055   uint32_t value2 = extreg32 (cpu, rm, extension) << shift;
2056
2057   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
2058   set_flags_for_add32 (cpu, value1, value2);
2059 }
2060
2061 /* 64 bit ADD extending register setting flags  */
2062 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0  */
2063 static void
2064 adds64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2065 {
2066   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2067   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2068   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2069
2070   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
2071   uint64_t value2 = extreg64 (cpu, rm, extension) << shift;
2072
2073   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
2074   set_flags_for_add64 (cpu, value1, value2);
2075 }
2076
2077 /* 32 bit SUB extending register.  */
2078 static void
2079 sub32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2080 {
2081   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2082   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2083   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2084
2085   aarch64_set_reg_u64 (cpu, rd, SP_OK,
2086                        aarch64_get_reg_u32 (cpu, rn, SP_OK)
2087                        - (extreg32 (cpu, rm, extension) << shift));
2088 }
2089
2090 /* 64 bit SUB extending register.  */
2091 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0.  */
2092 static void
2093 sub64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2094 {
2095   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2096   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2097   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2098
2099   aarch64_set_reg_u64 (cpu, rd, SP_OK,
2100                        aarch64_get_reg_u64 (cpu, rn, SP_OK)
2101                        - (extreg64 (cpu, rm, extension) << shift));
2102 }
2103
2104 /* 32 bit SUB extending register setting flags.  */
2105 static void
2106 subs32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2107 {
2108   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2109   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2110   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2111
2112   uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, SP_OK);
2113   uint32_t value2 = extreg32 (cpu, rm, extension) << shift;
2114
2115   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
2116   set_flags_for_sub32 (cpu, value1, value2);
2117 }
2118
2119 /* 64 bit SUB extending register setting flags  */
2120 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0  */
2121 static void
2122 subs64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2123 {
2124   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2125   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2126   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2127
2128   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
2129   uint64_t value2 = extreg64 (cpu, rm, extension) << shift;
2130
2131   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
2132   set_flags_for_sub64 (cpu, value1, value2);
2133 }
2134
2135 static void
2136 dexAddSubtractImmediate (sim_cpu *cpu)
2137 {
2138   /* instr[31]    = size : 0 ==> 32 bit, 1 ==> 64 bit
2139      instr[30]    = op : 0 ==> ADD, 1 ==> SUB
2140      instr[29]    = set : 0 ==> no flags, 1 ==> set flags
2141      instr[28,24] = 10001
2142      instr[23,22] = shift : 00 == LSL#0, 01 = LSL#12 1x = UNALLOC
2143      instr[21,10] = uimm12
2144      instr[9,5]   = Rn
2145      instr[4,0]   = Rd  */
2146
2147   /* N.B. the shift is applied at decode before calling the add/sub routine.  */
2148   uint32_t shift = uimm (aarch64_get_instr (cpu), 23, 22);
2149   uint32_t imm = uimm (aarch64_get_instr (cpu), 21, 10);
2150   uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2151
2152   NYI_assert (28, 24, 0x11);
2153
2154   if (shift > 1)
2155     HALT_UNALLOC;
2156
2157   if (shift)
2158     imm <<= 12;
2159
2160   switch (dispatch)
2161     {
2162     case 0: add32 (cpu, imm); break;
2163     case 1: adds32 (cpu, imm); break;
2164     case 2: sub32 (cpu, imm); break;
2165     case 3: subs32 (cpu, imm); break;
2166     case 4: add64 (cpu, imm); break;
2167     case 5: adds64 (cpu, imm); break;
2168     case 6: sub64 (cpu, imm); break;
2169     case 7: subs64 (cpu, imm); break;
2170     default:
2171       HALT_UNALLOC;
2172     }
2173 }
2174
2175 static void
2176 dexAddSubtractShiftedRegister (sim_cpu *cpu)
2177 {
2178   /* instr[31]    = size : 0 ==> 32 bit, 1 ==> 64 bit
2179      instr[30,29] = op : 00 ==> ADD, 01 ==> ADDS, 10 ==> SUB, 11 ==> SUBS
2180      instr[28,24] = 01011
2181      instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> UNALLOC
2182      instr[21]    = 0
2183      instr[20,16] = Rm
2184      instr[15,10] = count : must be 0xxxxx for 32 bit
2185      instr[9,5]   = Rn
2186      instr[4,0]   = Rd  */
2187
2188   uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
2189   /* 32 bit operations must have count[5] = 0
2190      or else we have an UNALLOC.  */
2191   uint32_t count = uimm (aarch64_get_instr (cpu), 15, 10);
2192   /* Shift encoded as ROR is unallocated.  */
2193   Shift shiftType = shift (aarch64_get_instr (cpu), 22);
2194   /* Dispatch on size:op i.e aarch64_get_instr (cpu)[31,29].  */
2195   uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2196
2197   NYI_assert (28, 24, 0x0B);
2198   NYI_assert (21, 21, 0);
2199
2200   if (shiftType == ROR)
2201     HALT_UNALLOC;
2202
2203   if (!size && uimm (count, 5, 5))
2204     HALT_UNALLOC;
2205
2206   switch (dispatch)
2207     {
2208     case 0: add32_shift  (cpu, shiftType, count); break;
2209     case 1: adds32_shift (cpu, shiftType, count); break;
2210     case 2: sub32_shift  (cpu, shiftType, count); break;
2211     case 3: subs32_shift (cpu, shiftType, count); break;
2212     case 4: add64_shift  (cpu, shiftType, count); break;
2213     case 5: adds64_shift (cpu, shiftType, count); break;
2214     case 6: sub64_shift  (cpu, shiftType, count); break;
2215     case 7: subs64_shift (cpu, shiftType, count); break;
2216     default:
2217       HALT_UNALLOC;
2218     }
2219 }
2220
2221 static void
2222 dexAddSubtractExtendedRegister (sim_cpu *cpu)
2223 {
2224   /* instr[31]    = size : 0 ==> 32 bit, 1 ==> 64 bit
2225      instr[30]    = op : 0 ==> ADD, 1 ==> SUB
2226      instr[29]    = set? : 0 ==> no flags, 1 ==> set flags
2227      instr[28,24] = 01011
2228      instr[23,22] = opt : 0 ==> ok, 1,2,3 ==> UNALLOC
2229      instr[21]    = 1
2230      instr[20,16] = Rm
2231      instr[15,13] = option : 000 ==> UXTB, 001 ==> UXTH,
2232                              000 ==> LSL|UXTW, 001 ==> UXTZ,
2233                              000 ==> SXTB, 001 ==> SXTH,
2234                              000 ==> SXTW, 001 ==> SXTX,
2235      instr[12,10] = shift : 0,1,2,3,4 ==> ok, 5,6,7 ==> UNALLOC
2236      instr[9,5]   = Rn
2237      instr[4,0]   = Rd  */
2238
2239   Extension extensionType = extension (aarch64_get_instr (cpu), 13);
2240   uint32_t shift = uimm (aarch64_get_instr (cpu), 12, 10);
2241   /* dispatch on size:op:set? i.e aarch64_get_instr (cpu)[31,29]  */
2242   uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2243
2244   NYI_assert (28, 24, 0x0B);
2245   NYI_assert (21, 21, 1);
2246
2247   /* Shift may not exceed 4.  */
2248   if (shift > 4)
2249     HALT_UNALLOC;
2250
2251   switch (dispatch)
2252     {
2253     case 0: add32_ext  (cpu, extensionType, shift); break;
2254     case 1: adds32_ext (cpu, extensionType, shift); break;
2255     case 2: sub32_ext  (cpu, extensionType, shift); break;
2256     case 3: subs32_ext (cpu, extensionType, shift); break;
2257     case 4: add64_ext  (cpu, extensionType, shift); break;
2258     case 5: adds64_ext (cpu, extensionType, shift); break;
2259     case 6: sub64_ext  (cpu, extensionType, shift); break;
2260     case 7: subs64_ext (cpu, extensionType, shift); break;
2261     default: HALT_UNALLOC;
2262     }
2263 }
2264
2265 /* Conditional data processing
2266    Condition register is implicit 3rd source.  */
2267
2268 /* 32 bit add with carry.  */
2269 /* N.B register args may not be SP.  */
2270
2271 static void
2272 adc32 (sim_cpu *cpu)
2273 {
2274   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2275   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2276   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2277
2278   aarch64_set_reg_u64 (cpu, rd, NO_SP,
2279                        aarch64_get_reg_u32 (cpu, rn, NO_SP)
2280                        + aarch64_get_reg_u32 (cpu, rm, NO_SP)
2281                        + IS_SET (C));
2282 }
2283
2284 /* 64 bit add with carry  */
2285 static void
2286 adc64 (sim_cpu *cpu)
2287 {
2288   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2289   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2290   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2291
2292   aarch64_set_reg_u64 (cpu, rd, NO_SP,
2293                        aarch64_get_reg_u64 (cpu, rn, NO_SP)
2294                        + aarch64_get_reg_u64 (cpu, rm, NO_SP)
2295                        + IS_SET (C));
2296 }
2297
2298 /* 32 bit add with carry setting flags.  */
2299 static void
2300 adcs32 (sim_cpu *cpu)
2301 {
2302   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2303   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2304   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2305
2306   uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
2307   uint32_t value2 = aarch64_get_reg_u32 (cpu, rm, NO_SP);
2308   uint32_t carry = IS_SET (C);
2309
2310   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2 + carry);
2311   set_flags_for_add32 (cpu, value1, value2 + carry);
2312 }
2313
2314 /* 64 bit add with carry setting flags.  */
2315 static void
2316 adcs64 (sim_cpu *cpu)
2317 {
2318   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2319   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2320   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2321
2322   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
2323   uint64_t value2 = aarch64_get_reg_u64 (cpu, rm, NO_SP);
2324   uint64_t carry = IS_SET (C);
2325
2326   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2 + carry);
2327   set_flags_for_add64 (cpu, value1, value2 + carry);
2328 }
2329
2330 /* 32 bit sub with carry.  */
2331 static void
2332 sbc32 (sim_cpu *cpu)
2333 {
2334   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2335   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2336   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2337
2338   aarch64_set_reg_u64 (cpu, rd, NO_SP,
2339                        aarch64_get_reg_u32 (cpu, rn, NO_SP)
2340                        - aarch64_get_reg_u32 (cpu, rm, NO_SP)
2341                        - 1 + IS_SET (C));
2342 }
2343
2344 /* 64 bit sub with carry  */
2345 static void
2346 sbc64 (sim_cpu *cpu)
2347 {
2348   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2349   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2350   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2351
2352   aarch64_set_reg_u64 (cpu, rd, NO_SP,
2353                        aarch64_get_reg_u64 (cpu, rn, NO_SP)
2354                        - aarch64_get_reg_u64 (cpu, rm, NO_SP)
2355                        - 1 + IS_SET (C));
2356 }
2357
2358 /* 32 bit sub with carry setting flags  */
2359 static void
2360 sbcs32 (sim_cpu *cpu)
2361 {
2362   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2363   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2364   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2365
2366   uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
2367   uint32_t value2 = aarch64_get_reg_u32 (cpu, rm, NO_SP);
2368   uint32_t carry  = IS_SET (C);
2369   uint32_t result = value1 - value2 + 1 - carry;
2370
2371   aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
2372   set_flags_for_sub32 (cpu, value1, value2 + 1 - carry);
2373 }
2374
2375 /* 64 bit sub with carry setting flags  */
2376 static void
2377 sbcs64 (sim_cpu *cpu)
2378 {
2379   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2380   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2381   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2382
2383   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
2384   uint64_t value2 = aarch64_get_reg_u64 (cpu, rm, NO_SP);
2385   uint64_t carry  = IS_SET (C);
2386   uint64_t result = value1 - value2 + 1 - carry;
2387
2388   aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
2389   set_flags_for_sub64 (cpu, value1, value2 + 1 - carry);
2390 }
2391
2392 static void
2393 dexAddSubtractWithCarry (sim_cpu *cpu)
2394 {
2395   /* instr[31]    = size : 0 ==> 32 bit, 1 ==> 64 bit
2396      instr[30]    = op : 0 ==> ADC, 1 ==> SBC
2397      instr[29]    = set? : 0 ==> no flags, 1 ==> set flags
2398      instr[28,21] = 1 1010 000
2399      instr[20,16] = Rm
2400      instr[15,10] = op2 : 00000 ==> ok, ow ==> UNALLOC
2401      instr[9,5]   = Rn
2402      instr[4,0]   = Rd  */
2403
2404   uint32_t op2 = uimm (aarch64_get_instr (cpu), 15, 10);
2405   /* Dispatch on size:op:set? i.e aarch64_get_instr (cpu)[31,29]  */
2406   uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2407
2408   NYI_assert (28, 21, 0xD0);
2409
2410   if (op2 != 0)
2411     HALT_UNALLOC;
2412
2413   switch (dispatch)
2414     {
2415     case 0: adc32 (cpu); break;
2416     case 1: adcs32 (cpu); break;
2417     case 2: sbc32 (cpu); break;
2418     case 3: sbcs32 (cpu); break;
2419     case 4: adc64 (cpu); break;
2420     case 5: adcs64 (cpu); break;
2421     case 6: sbc64 (cpu); break;
2422     case 7: sbcs64 (cpu); break;
2423     default: HALT_UNALLOC;
2424     }
2425 }
2426
2427 static uint32_t
2428 testConditionCode (sim_cpu *cpu, CondCode cc)
2429 {
2430   /* This should be reduceable to branchless logic
2431      by some careful testing of bits in CC followed
2432      by the requisite masking and combining of bits
2433      from the flag register.
2434
2435      For now we do it with a switch.  */
2436   int res;
2437
2438   switch (cc)
2439     {
2440     case EQ:  res = IS_SET (Z);    break;
2441     case NE:  res = IS_CLEAR (Z);  break;
2442     case CS:  res = IS_SET (C);    break;
2443     case CC:  res = IS_CLEAR (C);  break;
2444     case MI:  res = IS_SET (N);    break;
2445     case PL:  res = IS_CLEAR (N);  break;
2446     case VS:  res = IS_SET (V);    break;
2447     case VC:  res = IS_CLEAR (V);  break;
2448     case HI:  res = IS_SET (C) && IS_CLEAR (Z);  break;
2449     case LS:  res = IS_CLEAR (C) || IS_SET (Z);  break;
2450     case GE:  res = IS_SET (N) == IS_SET (V);    break;
2451     case LT:  res = IS_SET (N) != IS_SET (V);    break;
2452     case GT:  res = IS_CLEAR (Z) && (IS_SET (N) == IS_SET (V));  break;
2453     case LE:  res = IS_SET (Z) || (IS_SET (N) != IS_SET (V));    break;
2454     case AL:
2455     case NV:
2456     default:
2457       res = 1;
2458       break;
2459     }
2460   return res;
2461 }
2462
2463 static void
2464 CondCompare (sim_cpu *cpu) /* aka: ccmp and ccmn  */
2465 {
2466   /* instr[31]    = size : 0 ==> 32 bit, 1 ==> 64 bit
2467      instr[30]    = compare with positive (0) or negative value (1)
2468      instr[29,21] = 1 1101 0010
2469      instr[20,16] = Rm or const
2470      instr[15,12] = cond
2471      instr[11]    = compare reg (0) or const (1)
2472      instr[10]    = 0
2473      instr[9,5]   = Rn
2474      instr[4]     = 0
2475      instr[3,0]   = value for CPSR bits if the comparison does not take place.  */
2476   signed int negate;
2477   unsigned rm;
2478   unsigned rn;
2479
2480   NYI_assert (29, 21, 0x1d2);
2481   NYI_assert (10, 10, 0);
2482   NYI_assert (4, 4, 0);
2483
2484   if (! testConditionCode (cpu, uimm (aarch64_get_instr (cpu), 15, 12)))
2485     {
2486       aarch64_set_CPSR (cpu, uimm (aarch64_get_instr (cpu), 3, 0));
2487       return;
2488     }
2489
2490   negate = uimm (aarch64_get_instr (cpu), 30, 30) ? -1 : 1;
2491   rm = uimm (aarch64_get_instr (cpu), 20, 16);
2492   rn = uimm (aarch64_get_instr (cpu),  9,  5);
2493
2494   if (uimm (aarch64_get_instr (cpu), 31, 31))
2495     {
2496       if (uimm (aarch64_get_instr (cpu), 11, 11))
2497         set_flags_for_sub64 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK),
2498                              negate * (uint64_t) rm);
2499       else
2500         set_flags_for_sub64 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK),
2501                              negate * aarch64_get_reg_u64 (cpu, rm, SP_OK));
2502     }
2503   else
2504     {
2505       if (uimm (aarch64_get_instr (cpu), 11, 11))
2506         set_flags_for_sub32 (cpu, aarch64_get_reg_u32 (cpu, rn, SP_OK),
2507                              negate * rm);
2508       else
2509         set_flags_for_sub32 (cpu, aarch64_get_reg_u32 (cpu, rn, SP_OK),
2510                              negate * aarch64_get_reg_u32 (cpu, rm, SP_OK));
2511     }
2512 }
2513
2514 static void
2515 do_vec_MOV_whole_vector (sim_cpu *cpu)
2516 {
2517   /* MOV Vd.T, Vs.T  (alias for ORR Vd.T, Vn.T, Vm.T where Vn == Vm)
2518
2519      instr[31]    = 0
2520      instr[30]    = half(0)/full(1)
2521      instr[29,21] = 001110101
2522      instr[20,16] = Vs
2523      instr[15,10] = 000111
2524      instr[9,5]   = Vs
2525      instr[4,0]   = Vd  */
2526
2527   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
2528   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2529
2530   NYI_assert (29, 21, 0x075);
2531   NYI_assert (15, 10, 0x07);
2532
2533   if (uimm (aarch64_get_instr (cpu), 20, 16) != vs)
2534     HALT_NYI;
2535
2536   if (uimm (aarch64_get_instr (cpu), 30, 30))
2537     aarch64_set_vec_u64 (cpu, vd, 1, aarch64_get_vec_u64 (cpu, vs, 1));
2538
2539   aarch64_set_vec_u64 (cpu, vd, 0, aarch64_get_vec_u64 (cpu, vs, 0));
2540 }
2541
2542 static void
2543 do_vec_MOV_into_scalar (sim_cpu *cpu)
2544 {
2545   /* instr[31]    = 0
2546      instr[30]    = word(0)/long(1)
2547      instr[29,21] = 00 1110 000
2548      instr[20,18] = element size and index
2549      instr[17,10] = 00 0011 11
2550      instr[9,5]   = V source
2551      instr[4,0]   = R dest  */
2552
2553   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
2554   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2555
2556   NYI_assert (29, 21, 0x070);
2557   NYI_assert (17, 10, 0x0F);
2558
2559   switch (uimm (aarch64_get_instr (cpu), 20, 18))
2560     {
2561     case 0x2:
2562       aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u64 (cpu, vs, 0));
2563       break;
2564
2565     case 0x6:
2566       aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u64 (cpu, vs, 1));
2567       break;
2568
2569     case 0x1:
2570     case 0x3:
2571     case 0x5:
2572     case 0x7:
2573       aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u32
2574                            (cpu, vs, uimm (aarch64_get_instr (cpu), 20, 19)));
2575       break;
2576
2577     default:
2578       HALT_NYI;
2579     }
2580 }
2581
2582 static void
2583 do_vec_INS (sim_cpu *cpu)
2584 {
2585   /* instr[31,21] = 01001110000
2586      instr[20,16] = element size and index
2587      instr[15,10] = 000111
2588      instr[9,5]   = W source
2589      instr[4,0]   = V dest  */
2590
2591   int index;
2592   unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
2593   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2594
2595   NYI_assert (31, 21, 0x270);
2596   NYI_assert (15, 10, 0x07);
2597
2598   if (uimm (aarch64_get_instr (cpu), 16, 16))
2599     {
2600       index = uimm (aarch64_get_instr (cpu), 20, 17);
2601       aarch64_set_vec_u8 (cpu, vd, index,
2602                           aarch64_get_reg_u8 (cpu, rs, NO_SP));
2603     }
2604   else if (uimm (aarch64_get_instr (cpu), 17, 17))
2605     {
2606       index = uimm (aarch64_get_instr (cpu), 20, 18);
2607       aarch64_set_vec_u16 (cpu, vd, index,
2608                            aarch64_get_reg_u16 (cpu, rs, NO_SP));
2609     }
2610   else if (uimm (aarch64_get_instr (cpu), 18, 18))
2611     {
2612       index = uimm (aarch64_get_instr (cpu), 20, 19);
2613       aarch64_set_vec_u32 (cpu, vd, index,
2614                            aarch64_get_reg_u32 (cpu, rs, NO_SP));
2615     }
2616   else if (uimm (aarch64_get_instr (cpu), 19, 19))
2617     {
2618       index = uimm (aarch64_get_instr (cpu), 20, 20);
2619       aarch64_set_vec_u64 (cpu, vd, index,
2620                            aarch64_get_reg_u64 (cpu, rs, NO_SP));
2621     }
2622   else
2623     HALT_NYI;
2624 }
2625
2626 static void
2627 do_vec_DUP_vector_into_vector (sim_cpu *cpu)
2628 {
2629   /* instr[31]    = 0
2630      instr[30]    = half(0)/full(1)
2631      instr[29,21] = 00 1110 000
2632      instr[20,16] = element size and index
2633      instr[15,10] = 0000 01
2634      instr[9,5]   = V source
2635      instr[4,0]   = V dest.  */
2636
2637   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
2638   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
2639   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2640   int i, index;
2641
2642   NYI_assert (29, 21, 0x070);
2643   NYI_assert (15, 10, 0x01);
2644
2645   if (uimm (aarch64_get_instr (cpu), 16, 16))
2646     {
2647       index = uimm (aarch64_get_instr (cpu), 20, 17);
2648
2649       for (i = 0; i < (full ? 16 : 8); i++)
2650         aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vs, index));
2651     }
2652   else if (uimm (aarch64_get_instr (cpu), 17, 17))
2653     {
2654       index = uimm (aarch64_get_instr (cpu), 20, 18);
2655
2656       for (i = 0; i < (full ? 8 : 4); i++)
2657         aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vs, index));
2658     }
2659   else if (uimm (aarch64_get_instr (cpu), 18, 18))
2660     {
2661       index = uimm (aarch64_get_instr (cpu), 20, 19);
2662
2663       for (i = 0; i < (full ? 4 : 2); i++)
2664         aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vs, index));
2665     }
2666   else
2667     {
2668       if (uimm (aarch64_get_instr (cpu), 19, 19) == 0)
2669         HALT_UNALLOC;
2670
2671       if (! full)
2672         HALT_UNALLOC;
2673
2674       index = uimm (aarch64_get_instr (cpu), 20, 20);
2675
2676       for (i = 0; i < 2; i++)
2677         aarch64_set_vec_u64 (cpu, vd, i, aarch64_get_vec_u64 (cpu, vs, index));
2678     }
2679 }
2680
2681 static void
2682 do_vec_TBL (sim_cpu *cpu)
2683 {
2684   /* instr[31]    = 0
2685      instr[30]    = half(0)/full(1)
2686      instr[29,21] = 00 1110 000
2687      instr[20,16] = Vm
2688      instr[15]    = 0
2689      instr[14,13] = vec length
2690      instr[12,10] = 000
2691      instr[9,5]   = V start
2692      instr[4,0]   = V dest  */
2693
2694   int full    = uimm (aarch64_get_instr (cpu), 30, 30);
2695   int len     = uimm (aarch64_get_instr (cpu), 14, 13) + 1;
2696   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2697   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2698   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2699   unsigned i;
2700
2701   NYI_assert (29, 21, 0x070);
2702   NYI_assert (12, 10, 0);
2703
2704   for (i = 0; i < (full ? 16 : 8); i++)
2705     {
2706       unsigned int selector = aarch64_get_vec_u8 (cpu, vm, i);
2707       uint8_t val;
2708
2709       if (selector < 16)
2710         val = aarch64_get_vec_u8 (cpu, vn, selector);
2711       else if (selector < 32)
2712         val = len < 2 ? 0 : aarch64_get_vec_u8 (cpu, vn + 1, selector - 16);
2713       else if (selector < 48)
2714         val = len < 3 ? 0 : aarch64_get_vec_u8 (cpu, vn + 2, selector - 32);
2715       else if (selector < 64)
2716         val = len < 4 ? 0 : aarch64_get_vec_u8 (cpu, vn + 3, selector - 48);
2717       else
2718         val = 0;
2719
2720       aarch64_set_vec_u8 (cpu, vd, i, val);
2721     }
2722 }
2723
2724 static void
2725 do_vec_TRN (sim_cpu *cpu)
2726 {
2727   /* instr[31]    = 0
2728      instr[30]    = half(0)/full(1)
2729      instr[29,24] = 00 1110
2730      instr[23,22] = size
2731      instr[21]    = 0
2732      instr[20,16] = Vm
2733      instr[15]    = 0
2734      instr[14]    = TRN1 (0) / TRN2 (1)
2735      instr[13,10] = 1010
2736      instr[9,5]   = V source
2737      instr[4,0]   = V dest.  */
2738
2739   int full    = uimm (aarch64_get_instr (cpu), 30, 30);
2740   int second  = uimm (aarch64_get_instr (cpu), 14, 14);
2741   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2742   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2743   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2744   unsigned i;
2745
2746   NYI_assert (29, 24, 0x0E);
2747   NYI_assert (13, 10, 0xA);
2748
2749   switch (uimm (aarch64_get_instr (cpu), 23, 22))
2750     {
2751     case 0:
2752       for (i = 0; i < (full ? 8 : 4); i++)
2753         {
2754           aarch64_set_vec_u8
2755             (cpu, vd, i * 2,
2756              aarch64_get_vec_u8 (cpu, second ? vm : vn, i * 2));
2757           aarch64_set_vec_u8
2758             (cpu, vd, 1 * 2 + 1,
2759              aarch64_get_vec_u8 (cpu, second ? vn : vm, i * 2 + 1));
2760         }
2761       break;
2762
2763     case 1:
2764       for (i = 0; i < (full ? 4 : 2); i++)
2765         {
2766           aarch64_set_vec_u16
2767             (cpu, vd, i * 2,
2768              aarch64_get_vec_u16 (cpu, second ? vm : vn, i * 2));
2769           aarch64_set_vec_u16
2770             (cpu, vd, 1 * 2 + 1,
2771              aarch64_get_vec_u16 (cpu, second ? vn : vm, i * 2 + 1));
2772         }
2773       break;
2774
2775     case 2:
2776       aarch64_set_vec_u32
2777         (cpu, vd, 0, aarch64_get_vec_u32 (cpu, second ? vm : vn, 0));
2778       aarch64_set_vec_u32
2779         (cpu, vd, 1, aarch64_get_vec_u32 (cpu, second ? vn : vm, 1));
2780       aarch64_set_vec_u32
2781         (cpu, vd, 2, aarch64_get_vec_u32 (cpu, second ? vm : vn, 2));
2782       aarch64_set_vec_u32
2783         (cpu, vd, 3, aarch64_get_vec_u32 (cpu, second ? vn : vm, 3));
2784       break;
2785
2786     case 3:
2787       if (! full)
2788         HALT_UNALLOC;
2789
2790       aarch64_set_vec_u64 (cpu, vd, 0,
2791                            aarch64_get_vec_u64 (cpu, second ? vm : vn, 0));
2792       aarch64_set_vec_u64 (cpu, vd, 1,
2793                            aarch64_get_vec_u64 (cpu, second ? vn : vm, 1));
2794       break;
2795
2796     default:
2797       HALT_UNALLOC;
2798     }
2799 }
2800
2801 static void
2802 do_vec_DUP_scalar_into_vector (sim_cpu *cpu)
2803 {
2804   /* instr[31]    = 0
2805      instr[30]    = 0=> zero top 64-bits, 1=> duplicate into top 64-bits
2806                     [must be 1 for 64-bit xfer]
2807      instr[29,20] = 00 1110 0000
2808      instr[19,16] = element size: 0001=> 8-bits, 0010=> 16-bits,
2809                                   0100=> 32-bits. 1000=>64-bits
2810      instr[15,10] = 0000 11
2811      instr[9,5]   = W source
2812      instr[4,0]   = V dest.  */
2813
2814   unsigned i;
2815   unsigned Vd = uimm (aarch64_get_instr (cpu), 4, 0);
2816   unsigned Rs = uimm (aarch64_get_instr (cpu), 9, 5);
2817   int both    = uimm (aarch64_get_instr (cpu), 30, 30);
2818
2819   NYI_assert (29, 20, 0x0E0);
2820   NYI_assert (15, 10, 0x03);
2821
2822   switch (uimm (aarch64_get_instr (cpu), 19, 16))
2823     {
2824     case 1:
2825       for (i = 0; i < (both ? 16 : 8); i++)
2826         aarch64_set_vec_u8 (cpu, Vd, i, aarch64_get_reg_u8 (cpu, Rs, NO_SP));
2827       break;
2828
2829     case 2:
2830       for (i = 0; i < (both ? 8 : 4); i++)
2831         aarch64_set_vec_u16 (cpu, Vd, i, aarch64_get_reg_u16 (cpu, Rs, NO_SP));
2832       break;
2833
2834     case 4:
2835       for (i = 0; i < (both ? 4 : 2); i++)
2836         aarch64_set_vec_u32 (cpu, Vd, i, aarch64_get_reg_u32 (cpu, Rs, NO_SP));
2837       break;
2838
2839     case 8:
2840       if (!both)
2841         HALT_NYI;
2842       aarch64_set_vec_u64 (cpu, Vd, 0, aarch64_get_reg_u64 (cpu, Rs, NO_SP));
2843       aarch64_set_vec_u64 (cpu, Vd, 1, aarch64_get_reg_u64 (cpu, Rs, NO_SP));
2844       break;
2845
2846     default:
2847       HALT_NYI;
2848     }
2849 }
2850
2851 static void
2852 do_vec_UZP (sim_cpu *cpu)
2853 {
2854   /* instr[31]    = 0
2855      instr[30]    = half(0)/full(1)
2856      instr[29,24] = 00 1110
2857      instr[23,22] = size: byte(00), half(01), word (10), long (11)
2858      instr[21]    = 0
2859      instr[20,16] = Vm
2860      instr[15]    = 0
2861      instr[14]    = lower (0) / upper (1)
2862      instr[13,10] = 0110
2863      instr[9,5]   = Vn
2864      instr[4,0]   = Vd.  */
2865
2866   int full = uimm (aarch64_get_instr (cpu), 30, 30);
2867   int upper = uimm (aarch64_get_instr (cpu), 14, 14);
2868
2869   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2870   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2871   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2872
2873   uint64_t val_m1 = aarch64_get_vec_u64 (cpu, vm, 0);
2874   uint64_t val_m2 = aarch64_get_vec_u64 (cpu, vm, 1);
2875   uint64_t val_n1 = aarch64_get_vec_u64 (cpu, vn, 0);
2876   uint64_t val_n2 = aarch64_get_vec_u64 (cpu, vn, 1);
2877
2878   uint64_t val1 = 0;
2879   uint64_t val2 = 0;
2880
2881   uint64_t input1 = upper ? val_n1 : val_m1;
2882   uint64_t input2 = upper ? val_n2 : val_m2;
2883   unsigned i;
2884
2885   NYI_assert (29, 24, 0x0E);
2886   NYI_assert (21, 21, 0);
2887   NYI_assert (15, 15, 0);
2888   NYI_assert (13, 10, 6);
2889
2890   switch (uimm (aarch64_get_instr (cpu), 23, 23))
2891     {
2892     case 0:
2893       for (i = 0; i < 8; i++)
2894         {
2895           val1 |= (input1 >> (i * 8)) & (0xFFULL << (i * 8));
2896           val2 |= (input2 >> (i * 8)) & (0xFFULL << (i * 8));
2897         }
2898       break;
2899
2900     case 1:
2901       for (i = 0; i < 4; i++)
2902         {
2903           val1 |= (input1 >> (i * 16)) & (0xFFFFULL << (i * 16));
2904           val2 |= (input2 >> (i * 16)) & (0xFFFFULL << (i * 16));
2905         }
2906       break;
2907
2908     case 2:
2909       val1 = ((input1 & 0xFFFFFFFF) | ((input1 >> 32) & 0xFFFFFFFF00000000ULL));
2910       val2 = ((input2 & 0xFFFFFFFF) | ((input2 >> 32) & 0xFFFFFFFF00000000ULL));
2911
2912     case 3:
2913       val1 = input1;
2914       val2 = input2;
2915            break;
2916     }
2917
2918   aarch64_set_vec_u64 (cpu, vd, 0, val1);
2919   if (full)
2920     aarch64_set_vec_u64 (cpu, vd, 1, val2);
2921 }
2922
2923 static void
2924 do_vec_ZIP (sim_cpu *cpu)
2925 {
2926   /* instr[31]    = 0
2927      instr[30]    = half(0)/full(1)
2928      instr[29,24] = 00 1110
2929      instr[23,22] = size: byte(00), hald(01), word (10), long (11)
2930      instr[21]    = 0
2931      instr[20,16] = Vm
2932      instr[15]    = 0
2933      instr[14]    = lower (0) / upper (1)
2934      instr[13,10] = 1110
2935      instr[9,5]   = Vn
2936      instr[4,0]   = Vd.  */
2937
2938   int full = uimm (aarch64_get_instr (cpu), 30, 30);
2939   int upper = uimm (aarch64_get_instr (cpu), 14, 14);
2940
2941   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2942   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2943   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2944
2945   uint64_t val_m1 = aarch64_get_vec_u64 (cpu, vm, 0);
2946   uint64_t val_m2 = aarch64_get_vec_u64 (cpu, vm, 1);
2947   uint64_t val_n1 = aarch64_get_vec_u64 (cpu, vn, 0);
2948   uint64_t val_n2 = aarch64_get_vec_u64 (cpu, vn, 1);
2949
2950   uint64_t val1 = 0;
2951   uint64_t val2 = 0;
2952
2953   uint64_t input1 = upper ? val_n1 : val_m1;
2954   uint64_t input2 = upper ? val_n2 : val_m2;
2955
2956   NYI_assert (29, 24, 0x0E);
2957   NYI_assert (21, 21, 0);
2958   NYI_assert (15, 15, 0);
2959   NYI_assert (13, 10, 0xE);
2960
2961   switch (uimm (aarch64_get_instr (cpu), 23, 23))
2962     {
2963     case 0:
2964       val1 =
2965           ((input1 <<  0) & (0xFF    <<  0))
2966         | ((input2 <<  8) & (0xFF    <<  8))
2967         | ((input1 <<  8) & (0xFF    << 16))
2968         | ((input2 << 16) & (0xFF    << 24))
2969         | ((input1 << 16) & (0xFFULL << 32))
2970         | ((input2 << 24) & (0xFFULL << 40))
2971         | ((input1 << 24) & (0xFFULL << 48))
2972         | ((input2 << 32) & (0xFFULL << 56));
2973
2974       val2 =
2975           ((input1 >> 32) & (0xFF    <<  0))
2976         | ((input2 >> 24) & (0xFF    <<  8))
2977         | ((input1 >> 24) & (0xFF    << 16))
2978         | ((input2 >> 16) & (0xFF    << 24))
2979         | ((input1 >> 16) & (0xFFULL << 32))
2980         | ((input2 >>  8) & (0xFFULL << 40))
2981         | ((input1 >>  8) & (0xFFULL << 48))
2982         | ((input2 >>  0) & (0xFFULL << 56));
2983       break;
2984
2985     case 1:
2986       val1 =
2987           ((input1 <<  0) & (0xFFFF    <<  0))
2988         | ((input2 << 16) & (0xFFFF    << 16))
2989         | ((input1 << 16) & (0xFFFFULL << 32))
2990         | ((input2 << 32) & (0xFFFFULL << 48));
2991
2992       val2 =
2993           ((input1 >> 32) & (0xFFFF    <<  0))
2994         | ((input2 >> 16) & (0xFFFF    << 16))
2995         | ((input1 >> 16) & (0xFFFFULL << 32))
2996         | ((input2 >>  0) & (0xFFFFULL << 48));
2997       break;
2998
2999     case 2:
3000       val1 = (input1 & 0xFFFFFFFFULL) | (input2 << 32);
3001       val2 = (input2 & 0xFFFFFFFFULL) | (input1 << 32);
3002       break;
3003
3004     case 3:
3005       val1 = input1;
3006       val2 = input2;
3007       break;
3008     }
3009
3010   aarch64_set_vec_u64 (cpu, vd, 0, val1);
3011   if (full)
3012     aarch64_set_vec_u64 (cpu, vd, 1, val2);
3013 }
3014
3015 /* Floating point immediates are encoded in 8 bits.
3016    fpimm[7] = sign bit.
3017    fpimm[6:4] = signed exponent.
3018    fpimm[3:0] = fraction (assuming leading 1).
3019    i.e. F = s * 1.f * 2^(e - b).  */
3020
3021 static float
3022 fp_immediate_for_encoding_32 (uint32_t imm8)
3023 {
3024   float u;
3025   uint32_t s, e, f, i;
3026
3027   s = (imm8 >> 7) & 0x1;
3028   e = (imm8 >> 4) & 0x7;
3029   f = imm8 & 0xf;
3030
3031   /* The fp value is s * n/16 * 2r where n is 16+e.  */
3032   u = (16.0 + f) / 16.0;
3033
3034   /* N.B. exponent is signed.  */
3035   if (e < 4)
3036     {
3037       int epos = e;
3038
3039       for (i = 0; i <= epos; i++)
3040         u *= 2.0;
3041     }
3042   else
3043     {
3044       int eneg = 7 - e;
3045
3046       for (i = 0; i < eneg; i++)
3047         u /= 2.0;
3048     }
3049
3050   if (s)
3051     u = - u;
3052
3053   return u;
3054 }
3055
3056 static double
3057 fp_immediate_for_encoding_64 (uint32_t imm8)
3058 {
3059   double u;
3060   uint32_t s, e, f, i;
3061
3062   s = (imm8 >> 7) & 0x1;
3063   e = (imm8 >> 4) & 0x7;
3064   f = imm8 & 0xf;
3065
3066   /* The fp value is s * n/16 * 2r where n is 16+e.  */
3067   u = (16.0 + f) / 16.0;
3068
3069   /* N.B. exponent is signed.  */
3070   if (e < 4)
3071     {
3072       int epos = e;
3073
3074       for (i = 0; i <= epos; i++)
3075         u *= 2.0;
3076     }
3077   else
3078     {
3079       int eneg = 7 - e;
3080
3081       for (i = 0; i < eneg; i++)
3082         u /= 2.0;
3083     }
3084
3085   if (s)
3086     u = - u;
3087
3088   return u;
3089 }
3090
3091 static void
3092 do_vec_MOV_immediate (sim_cpu *cpu)
3093 {
3094   /* instr[31]    = 0
3095      instr[30]    = full/half selector
3096      instr[29,19] = 00111100000
3097      instr[18,16] = high 3 bits of uimm8
3098      instr[15,12] = size & shift:
3099                                   0000 => 32-bit
3100                                   0010 => 32-bit + LSL#8
3101                                   0100 => 32-bit + LSL#16
3102                                   0110 => 32-bit + LSL#24
3103                                   1010 => 16-bit + LSL#8
3104                                   1000 => 16-bit
3105                                   1101 => 32-bit + MSL#16
3106                                   1100 => 32-bit + MSL#8
3107                                   1110 => 8-bit
3108                                   1111 => double
3109      instr[11,10] = 01
3110      instr[9,5]   = low 5-bits of uimm8
3111      instr[4,0]   = Vd.  */
3112
3113   int full     = uimm (aarch64_get_instr (cpu), 30, 30);
3114   unsigned vd  = uimm (aarch64_get_instr (cpu), 4, 0);
3115   unsigned val = uimm (aarch64_get_instr (cpu), 18, 16) << 5
3116     | uimm (aarch64_get_instr (cpu), 9, 5);
3117   unsigned i;
3118
3119   NYI_assert (29, 19, 0x1E0);
3120   NYI_assert (11, 10, 1);
3121
3122   switch (uimm (aarch64_get_instr (cpu), 15, 12))
3123     {
3124     case 0x0: /* 32-bit, no shift.  */
3125     case 0x2: /* 32-bit, shift by 8.  */
3126     case 0x4: /* 32-bit, shift by 16.  */
3127     case 0x6: /* 32-bit, shift by 24.  */
3128       val <<= (8 * uimm (aarch64_get_instr (cpu), 14, 13));
3129       for (i = 0; i < (full ? 4 : 2); i++)
3130         aarch64_set_vec_u32 (cpu, vd, i, val);
3131       break;
3132
3133     case 0xa: /* 16-bit, shift by 8.  */
3134       val <<= 8;
3135       /* Fall through.  */
3136     case 0x8: /* 16-bit, no shift.  */
3137       for (i = 0; i < (full ? 8 : 4); i++)
3138         aarch64_set_vec_u16 (cpu, vd, i, val);
3139       /* Fall through.  */
3140     case 0xd: /* 32-bit, mask shift by 16.  */
3141       val <<= 8;
3142       val |= 0xFF;
3143       /* Fall through.  */
3144     case 0xc: /* 32-bit, mask shift by 8. */
3145       val <<= 8;
3146       val |= 0xFF;
3147       for (i = 0; i < (full ? 4 : 2); i++)
3148         aarch64_set_vec_u32 (cpu, vd, i, val);
3149       break;
3150
3151     case 0xe: /* 8-bit, no shift.  */
3152       for (i = 0; i < (full ? 16 : 8); i++)
3153         aarch64_set_vec_u8 (cpu, vd, i, val);
3154       break;
3155
3156     case 0xf: /* FMOV Vs.{2|4}S, #fpimm.  */
3157       {
3158         float u = fp_immediate_for_encoding_32 (val);
3159         for (i = 0; i < (full ? 4 : 2); i++)
3160           aarch64_set_vec_float (cpu, vd, i, u);
3161         break;
3162       }
3163
3164     default:
3165       HALT_NYI;
3166     }
3167 }
3168
3169 static void
3170 do_vec_MVNI (sim_cpu *cpu)
3171 {
3172   /* instr[31]    = 0
3173      instr[30]    = full/half selector
3174      instr[29,19] = 10111100000
3175      instr[18,16] = high 3 bits of uimm8
3176      instr[15,12] = selector
3177      instr[11,10] = 01
3178      instr[9,5]   = low 5-bits of uimm8
3179      instr[4,0]   = Vd.  */
3180
3181   int full     = uimm (aarch64_get_instr (cpu), 30, 30);
3182   unsigned vd  = uimm (aarch64_get_instr (cpu), 4, 0);
3183   unsigned val = uimm (aarch64_get_instr (cpu), 18, 16) << 5
3184     | uimm (aarch64_get_instr (cpu), 9, 5);
3185   unsigned i;
3186
3187   NYI_assert (29, 19, 0x5E0);
3188   NYI_assert (11, 10, 1);
3189
3190   switch (uimm (aarch64_get_instr (cpu), 15, 12))
3191     {
3192     case 0x0: /* 32-bit, no shift.  */
3193     case 0x2: /* 32-bit, shift by 8.  */
3194     case 0x4: /* 32-bit, shift by 16.  */
3195     case 0x6: /* 32-bit, shift by 24.  */
3196       val <<= (8 * uimm (aarch64_get_instr (cpu), 14, 13));
3197       val = ~ val;
3198       for (i = 0; i < (full ? 4 : 2); i++)
3199         aarch64_set_vec_u32 (cpu, vd, i, val);
3200       return;
3201
3202     case 0xa: /* 16-bit, 8 bit shift. */
3203       val <<= 8;
3204     case 0x8: /* 16-bit, no shift. */
3205       val = ~ val;
3206       for (i = 0; i < (full ? 8 : 4); i++)
3207         aarch64_set_vec_u16 (cpu, vd, i, val);
3208       return;
3209
3210     case 0xd: /* 32-bit, mask shift by 16.  */
3211       val <<= 8;
3212       val |= 0xFF;
3213     case 0xc: /* 32-bit, mask shift by 8. */
3214       val <<= 8;
3215       val |= 0xFF;
3216       val = ~ val;
3217       for (i = 0; i < (full ? 4 : 2); i++)
3218         aarch64_set_vec_u32 (cpu, vd, i, val);
3219       return;
3220
3221     case 0xE: /* MOVI Dn, #mask64 */
3222       {
3223         uint64_t mask = 0;
3224
3225         for (i = 0; i < 8; i++)
3226           if (val & (1 << i))
3227             mask |= (0xF << (i * 4));
3228         aarch64_set_vec_u64 (cpu, vd, 0, mask);
3229         aarch64_set_vec_u64 (cpu, vd, 1, 0);
3230         return;
3231       }
3232
3233     case 0xf: /* FMOV Vd.2D, #fpimm.  */
3234       {
3235         double u = fp_immediate_for_encoding_64 (val);
3236
3237         if (! full)
3238           HALT_UNALLOC;
3239
3240         aarch64_set_vec_double (cpu, vd, 0, u);
3241         aarch64_set_vec_double (cpu, vd, 1, u);
3242         return;
3243       }
3244
3245     default:
3246       HALT_NYI;
3247     }
3248 }
3249
3250 #define ABS(A) ((A) < 0 ? - (A) : (A))
3251
3252 static void
3253 do_vec_ABS (sim_cpu *cpu)
3254 {
3255   /* instr[31]    = 0
3256      instr[30]    = half(0)/full(1)
3257      instr[29,24] = 00 1110
3258      instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3259      instr[21,10] = 10 0000 1011 10
3260      instr[9,5]   = Vn
3261      instr[4.0]   = Vd.  */
3262
3263   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3264   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3265   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
3266   unsigned i;
3267
3268   NYI_assert (29, 24, 0x0E);
3269   NYI_assert (21, 10, 0x82E);
3270
3271   switch (uimm (aarch64_get_instr (cpu), 23, 22))
3272     {
3273     case 0:
3274       for (i = 0; i < (full ? 16 : 8); i++)
3275         aarch64_set_vec_s8 (cpu, vd, i,
3276                             ABS (aarch64_get_vec_s8 (cpu, vn, i)));
3277       break;
3278
3279     case 1:
3280       for (i = 0; i < (full ? 8 : 4); i++)
3281         aarch64_set_vec_s16 (cpu, vd, i,
3282                              ABS (aarch64_get_vec_s16 (cpu, vn, i)));
3283       break;
3284
3285     case 2:
3286       for (i = 0; i < (full ? 4 : 2); i++)
3287         aarch64_set_vec_s32 (cpu, vd, i,
3288                              ABS (aarch64_get_vec_s32 (cpu, vn, i)));
3289       break;
3290
3291     case 3:
3292       if (! full)
3293         HALT_NYI;
3294       for (i = 0; i < 2; i++)
3295         aarch64_set_vec_s64 (cpu, vd, i,
3296                              ABS (aarch64_get_vec_s64 (cpu, vn, i)));
3297       break;
3298     }
3299 }
3300
3301 static void
3302 do_vec_ADDV (sim_cpu *cpu)
3303 {
3304   /* instr[31]    = 0
3305      instr[30]    = full/half selector
3306      instr[29,24] = 00 1110
3307      instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3308      instr[21,10] = 11 0001 1011 10
3309      instr[9,5]   = Vm
3310      instr[4.0]   = Rd.  */
3311
3312   unsigned vm = uimm (aarch64_get_instr (cpu), 9, 5);
3313   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
3314   unsigned i;
3315   uint64_t val = 0;
3316   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3317
3318   NYI_assert (29, 24, 0x0E);
3319   NYI_assert (21, 10, 0xC6E);
3320
3321   switch (uimm (aarch64_get_instr (cpu), 23, 22))
3322     {
3323     case 0:
3324       for (i = 0; i < (full ? 16 : 8); i++)
3325         val += aarch64_get_vec_u8 (cpu, vm, i);
3326       aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3327       return;
3328
3329     case 1:
3330       for (i = 0; i < (full ? 8 : 4); i++)
3331         val += aarch64_get_vec_u16 (cpu, vm, i);
3332       aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3333       return;
3334
3335     case 2:
3336       for (i = 0; i < (full ? 4 : 2); i++)
3337         val += aarch64_get_vec_u32 (cpu, vm, i);
3338       aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3339       return;
3340
3341     case 3:
3342       if (! full)
3343         HALT_UNALLOC;
3344       val = aarch64_get_vec_u64 (cpu, vm, 0);
3345       val += aarch64_get_vec_u64 (cpu, vm, 1);
3346       aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3347       return;
3348
3349     default:
3350       HALT_UNREACHABLE;
3351     }
3352 }
3353
3354 static void
3355 do_vec_ins_2 (sim_cpu *cpu)
3356 {
3357   /* instr[31,21] = 01001110000
3358      instr[20,18] = size & element selector
3359      instr[17,14] = 0000
3360      instr[13]    = direction: to vec(0), from vec (1)
3361      instr[12,10] = 111
3362      instr[9,5]   = Vm
3363      instr[4,0]   = Vd.  */
3364
3365   unsigned elem;
3366   unsigned vm = uimm (aarch64_get_instr (cpu), 9, 5);
3367   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3368
3369   NYI_assert (31, 21, 0x270);
3370   NYI_assert (17, 14, 0);
3371   NYI_assert (12, 10, 7);
3372
3373   if (uimm (aarch64_get_instr (cpu), 13, 13) == 1)
3374     {
3375       if (uimm (aarch64_get_instr (cpu), 18, 18) == 1)
3376         {
3377           /* 32-bit moves.  */
3378           elem = uimm (aarch64_get_instr (cpu), 20, 19);
3379           aarch64_set_reg_u64 (cpu, vd, NO_SP,
3380                                aarch64_get_vec_u32 (cpu, vm, elem));
3381         }
3382       else
3383         {
3384           /* 64-bit moves.  */
3385           if (uimm (aarch64_get_instr (cpu), 19, 19) != 1)
3386             HALT_NYI;
3387
3388           elem = uimm (aarch64_get_instr (cpu), 20, 20);
3389           aarch64_set_reg_u64 (cpu, vd, NO_SP,
3390                                aarch64_get_vec_u64 (cpu, vm, elem));
3391         }
3392     }
3393   else
3394     {
3395       if (uimm (aarch64_get_instr (cpu), 18, 18) == 1)
3396         {
3397           /* 32-bit moves.  */
3398           elem = uimm (aarch64_get_instr (cpu), 20, 19);
3399           aarch64_set_vec_u32 (cpu, vd, elem,
3400                                aarch64_get_reg_u32 (cpu, vm, NO_SP));
3401         }
3402       else
3403         {
3404           /* 64-bit moves.  */
3405           if (uimm (aarch64_get_instr (cpu), 19, 19) != 1)
3406             HALT_NYI;
3407
3408           elem = uimm (aarch64_get_instr (cpu), 20, 20);
3409           aarch64_set_vec_u64 (cpu, vd, elem,
3410                                aarch64_get_reg_u64 (cpu, vm, NO_SP));
3411         }
3412     }
3413 }
3414
3415 static void
3416 do_vec_mull (sim_cpu *cpu)
3417 {
3418   /* instr[31]    = 0
3419      instr[30]    = lower(0)/upper(1) selector
3420      instr[29]    = signed(0)/unsigned(1)
3421      instr[28,24] = 0 1110
3422      instr[23,22] = size: 8-bit (00), 16-bit (01), 32-bit (10)
3423      instr[21]    = 1
3424      instr[20,16] = Vm
3425      instr[15,10] = 11 0000
3426      instr[9,5]   = Vn
3427      instr[4.0]   = Vd.  */
3428
3429   int    unsign = uimm (aarch64_get_instr (cpu), 29, 29);
3430   int    bias = uimm (aarch64_get_instr (cpu), 30, 30);
3431   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3432   unsigned vn = uimm (aarch64_get_instr (cpu),  9,  5);
3433   unsigned vd = uimm (aarch64_get_instr (cpu),  4,  0);
3434   unsigned i;
3435
3436   NYI_assert (28, 24, 0x0E);
3437   NYI_assert (15, 10, 0x30);
3438
3439   switch (uimm (aarch64_get_instr (cpu), 23, 22))
3440     {
3441     case 0:
3442       if (bias)
3443         bias = 8;
3444       if (unsign)
3445         for (i = 0; i < 8; i++)
3446           aarch64_set_vec_u16 (cpu, vd, i,
3447                                aarch64_get_vec_u8 (cpu, vn, i + bias)
3448                                * aarch64_get_vec_u8 (cpu, vm, i + bias));
3449       else
3450         for (i = 0; i < 8; i++)
3451           aarch64_set_vec_s16 (cpu, vd, i,
3452                                aarch64_get_vec_s8 (cpu, vn, i + bias)
3453                                * aarch64_get_vec_s8 (cpu, vm, i + bias));
3454       return;
3455
3456     case 1:
3457       if (bias)
3458         bias = 4;
3459       if (unsign)
3460         for (i = 0; i < 4; i++)
3461           aarch64_set_vec_u32 (cpu, vd, i,
3462                                aarch64_get_vec_u16 (cpu, vn, i + bias)
3463                                * aarch64_get_vec_u16 (cpu, vm, i + bias));
3464       else
3465         for (i = 0; i < 4; i++)
3466           aarch64_set_vec_s32 (cpu, vd, i,
3467                                aarch64_get_vec_s16 (cpu, vn, i + bias)
3468                                * aarch64_get_vec_s16 (cpu, vm, i + bias));
3469       return;
3470
3471     case 2:
3472       if (bias)
3473         bias = 2;
3474       if (unsign)
3475         for (i = 0; i < 2; i++)
3476           aarch64_set_vec_u64 (cpu, vd, i,
3477                                (uint64_t) aarch64_get_vec_u32 (cpu, vn,
3478                                                                i + bias)
3479                                * (uint64_t) aarch64_get_vec_u32 (cpu, vm,
3480                                                                  i + bias));
3481       else
3482         for (i = 0; i < 2; i++)
3483           aarch64_set_vec_s64 (cpu, vd, i,
3484                                aarch64_get_vec_s32 (cpu, vn, i + bias)
3485                                * aarch64_get_vec_s32 (cpu, vm, i + bias));
3486       return;
3487
3488     case 3:
3489     default:
3490       HALT_NYI;
3491     }
3492 }
3493
3494 static void
3495 do_vec_fadd (sim_cpu *cpu)
3496 {
3497   /* instr[31]    = 0
3498      instr[30]    = half(0)/full(1)
3499      instr[29,24] = 001110
3500      instr[23]    = FADD(0)/FSUB(1)
3501      instr[22]    = float (0)/double(1)
3502      instr[21]    = 1
3503      instr[20,16] = Vm
3504      instr[15,10] = 110101
3505      instr[9,5]   = Vn
3506      instr[4.0]   = Vd.  */
3507
3508   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3509   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3510   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3511   unsigned i;
3512   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3513
3514   NYI_assert (29, 24, 0x0E);
3515   NYI_assert (21, 21, 1);
3516   NYI_assert (15, 10, 0x35);
3517
3518   if (uimm (aarch64_get_instr (cpu), 23, 23))
3519     {
3520       if (uimm (aarch64_get_instr (cpu), 22, 22))
3521         {
3522           if (! full)
3523             HALT_NYI;
3524
3525           for (i = 0; i < 2; i++)
3526             aarch64_set_vec_double (cpu, vd, i,
3527                                     aarch64_get_vec_double (cpu, vn, i)
3528                                     - aarch64_get_vec_double (cpu, vm, i));
3529         }
3530       else
3531         {
3532           for (i = 0; i < (full ? 4 : 2); i++)
3533             aarch64_set_vec_float (cpu, vd, i,
3534                                    aarch64_get_vec_float (cpu, vn, i)
3535                                    - aarch64_get_vec_float (cpu, vm, i));
3536         }
3537     }
3538   else
3539     {
3540       if (uimm (aarch64_get_instr (cpu), 22, 22))
3541         {
3542           if (! full)
3543             HALT_NYI;
3544
3545           for (i = 0; i < 2; i++)
3546             aarch64_set_vec_double (cpu, vd, i,
3547                                     aarch64_get_vec_double (cpu, vm, i)
3548                                     + aarch64_get_vec_double (cpu, vn, i));
3549         }
3550       else
3551         {
3552           for (i = 0; i < (full ? 4 : 2); i++)
3553             aarch64_set_vec_float (cpu, vd, i,
3554                                    aarch64_get_vec_float (cpu, vm, i)
3555                                    + aarch64_get_vec_float (cpu, vn, i));
3556         }
3557     }
3558 }
3559
3560 static void
3561 do_vec_add (sim_cpu *cpu)
3562 {
3563   /* instr[31]    = 0
3564      instr[30]    = full/half selector
3565      instr[29,24] = 001110
3566      instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3567      instr[21]    = 1
3568      instr[20,16] = Vn
3569      instr[15,10] = 100001
3570      instr[9,5]   = Vm
3571      instr[4.0]   = Vd.  */
3572
3573   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3574   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3575   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3576   unsigned i;
3577   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3578
3579   NYI_assert (29, 24, 0x0E);
3580   NYI_assert (21, 21, 1);
3581   NYI_assert (15, 10, 0x21);
3582
3583   switch (uimm (aarch64_get_instr (cpu), 23, 22))
3584     {
3585     case 0:
3586       for (i = 0; i < (full ? 16 : 8); i++)
3587         aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vn, i)
3588                             + aarch64_get_vec_u8 (cpu, vm, i));
3589       return;
3590
3591     case 1:
3592       for (i = 0; i < (full ? 8 : 4); i++)
3593         aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vn, i)
3594                              + aarch64_get_vec_u16 (cpu, vm, i));
3595       return;
3596
3597     case 2:
3598       for (i = 0; i < (full ? 4 : 2); i++)
3599         aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vn, i)
3600                              + aarch64_get_vec_u32 (cpu, vm, i));
3601       return;
3602
3603     case 3:
3604       if (! full)
3605         HALT_UNALLOC;
3606       aarch64_set_vec_u64 (cpu, vd, 0, aarch64_get_vec_u64 (cpu, vn, 0)
3607                            + aarch64_get_vec_u64 (cpu, vm, 0));
3608       aarch64_set_vec_u64 (cpu, vd, 1,
3609                            aarch64_get_vec_u64 (cpu, vn, 1)
3610                            + aarch64_get_vec_u64 (cpu, vm, 1));
3611       return;
3612
3613     default:
3614       HALT_UNREACHABLE;
3615     }
3616 }
3617
3618 static void
3619 do_vec_mul (sim_cpu *cpu)
3620 {
3621   /* instr[31]    = 0
3622      instr[30]    = full/half selector
3623      instr[29,24] = 00 1110
3624      instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3625      instr[21]    = 1
3626      instr[20,16] = Vn
3627      instr[15,10] = 10 0111
3628      instr[9,5]   = Vm
3629      instr[4.0]   = Vd.  */
3630
3631   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3632   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3633   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3634   unsigned i;
3635   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3636
3637   NYI_assert (29, 24, 0x0E);
3638   NYI_assert (21, 21, 1);
3639   NYI_assert (15, 10, 0x27);
3640
3641   switch (uimm (aarch64_get_instr (cpu), 23, 22))
3642     {
3643     case 0:
3644       for (i = 0; i < (full ? 16 : 8); i++)
3645         {
3646           uint16_t val = aarch64_get_vec_u8 (cpu, vn, i);
3647           val *= aarch64_get_vec_u8 (cpu, vm, i);
3648
3649           aarch64_set_vec_u16 (cpu, vd, i, val);
3650         }
3651       return;
3652
3653     case 1:
3654       for (i = 0; i < (full ? 8 : 4); i++)
3655         {
3656           uint32_t val = aarch64_get_vec_u16 (cpu, vn, i);
3657           val *= aarch64_get_vec_u16 (cpu, vm, i);
3658
3659           aarch64_set_vec_u32 (cpu, vd, i, val);
3660         }
3661       return;
3662
3663     case 2:
3664       for (i = 0; i < (full ? 4 : 2); i++)
3665         {
3666           uint64_t val = aarch64_get_vec_u32 (cpu, vn, i);
3667           val *= aarch64_get_vec_u32 (cpu, vm, i);
3668
3669           aarch64_set_vec_u64 (cpu, vd, i, val);
3670         }
3671       return;
3672
3673     default:
3674     case 3:
3675       HALT_UNALLOC;
3676     }
3677 }
3678
3679 static void
3680 do_vec_MLA (sim_cpu *cpu)
3681 {
3682   /* instr[31]    = 0
3683      instr[30]    = full/half selector
3684      instr[29,24] = 00 1110
3685      instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3686      instr[21]    = 1
3687      instr[20,16] = Vn
3688      instr[15,10] = 1001 01
3689      instr[9,5]   = Vm
3690      instr[4.0]   = Vd.  */
3691
3692   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3693   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3694   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3695   unsigned i;
3696   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3697
3698   NYI_assert (29, 24, 0x0E);
3699   NYI_assert (21, 21, 1);
3700   NYI_assert (15, 10, 0x25);
3701
3702   switch (uimm (aarch64_get_instr (cpu), 23, 22))
3703     {
3704     case 0:
3705       for (i = 0; i < (full ? 16 : 8); i++)
3706         {
3707           uint16_t val = aarch64_get_vec_u8 (cpu, vn, i);
3708           val *= aarch64_get_vec_u8 (cpu, vm, i);
3709           val += aarch64_get_vec_u8 (cpu, vd, i);
3710
3711           aarch64_set_vec_u16 (cpu, vd, i, val);
3712         }
3713       return;
3714
3715     case 1:
3716       for (i = 0; i < (full ? 8 : 4); i++)
3717         {
3718           uint32_t val = aarch64_get_vec_u16 (cpu, vn, i);
3719           val *= aarch64_get_vec_u16 (cpu, vm, i);
3720           val += aarch64_get_vec_u16 (cpu, vd, i);
3721
3722           aarch64_set_vec_u32 (cpu, vd, i, val);
3723         }
3724       return;
3725
3726     case 2:
3727       for (i = 0; i < (full ? 4 : 2); i++)
3728         {
3729           uint64_t val = aarch64_get_vec_u32 (cpu, vn, i);
3730           val *= aarch64_get_vec_u32 (cpu, vm, i);
3731           val += aarch64_get_vec_u32 (cpu, vd, i);
3732
3733           aarch64_set_vec_u64 (cpu, vd, i, val);
3734         }
3735       return;
3736
3737     default:
3738     case 3:
3739       HALT_UNALLOC;
3740     }
3741 }
3742
3743 static float
3744 fmaxnm (float a, float b)
3745 {
3746   if (fpclassify (a) == FP_NORMAL)
3747     {
3748       if (fpclassify (b) == FP_NORMAL)
3749         return a > b ? a : b;
3750       return a;
3751     }
3752   else if (fpclassify (b) == FP_NORMAL)
3753     return b;
3754   return a;
3755 }
3756
3757 static float
3758 fminnm (float a, float b)
3759 {
3760   if (fpclassify (a) == FP_NORMAL)
3761     {
3762       if (fpclassify (b) == FP_NORMAL)
3763         return a < b ? a : b;
3764       return a;
3765     }
3766   else if (fpclassify (b) == FP_NORMAL)
3767     return b;
3768   return a;
3769 }
3770
3771 static double
3772 dmaxnm (double a, double b)
3773 {
3774   if (fpclassify (a) == FP_NORMAL)
3775     {
3776       if (fpclassify (b) == FP_NORMAL)
3777         return a > b ? a : b;
3778       return a;
3779     }
3780   else if (fpclassify (b) == FP_NORMAL)
3781     return b;
3782   return a;
3783 }
3784
3785 static double
3786 dminnm (double a, double b)
3787 {
3788   if (fpclassify (a) == FP_NORMAL)
3789     {
3790       if (fpclassify (b) == FP_NORMAL)
3791         return a < b ? a : b;
3792       return a;
3793     }
3794   else if (fpclassify (b) == FP_NORMAL)
3795     return b;
3796   return a;
3797 }
3798
3799 static void
3800 do_vec_FminmaxNMP (sim_cpu *cpu)
3801 {
3802   /* aarch64_get_instr (cpu)[31]    = 0
3803      aarch64_get_instr (cpu)[30]    = half (0)/full (1)
3804      aarch64_get_instr (cpu)[29,24] = 10 1110
3805      aarch64_get_instr (cpu)[23]    = max(0)/min(1)
3806      aarch64_get_instr (cpu)[22]    = float (0)/double (1)
3807      aarch64_get_instr (cpu)[21]    = 1
3808      aarch64_get_instr (cpu)[20,16] = Vn
3809      aarch64_get_instr (cpu)[15,10] = 1100 01
3810      aarch64_get_instr (cpu)[9,5]   = Vm
3811      aarch64_get_instr (cpu)[4.0]   = Vd.  */
3812
3813   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3814   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3815   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3816   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3817
3818   NYI_assert (29, 24, 0x2E);
3819   NYI_assert (21, 21, 1);
3820   NYI_assert (15, 10, 0x31);
3821
3822   if (uimm (aarch64_get_instr (cpu), 22, 22))
3823     {
3824       double (* fn)(double, double) = uimm (aarch64_get_instr (cpu), 23, 23)
3825         ? dminnm : dmaxnm;
3826
3827       if (! full)
3828         HALT_NYI;
3829       aarch64_set_vec_double (cpu, vd, 0,
3830                               fn (aarch64_get_vec_double (cpu, vn, 0),
3831                                   aarch64_get_vec_double (cpu, vn, 1)));
3832       aarch64_set_vec_double (cpu, vd, 0,
3833                               fn (aarch64_get_vec_double (cpu, vm, 0),
3834                                   aarch64_get_vec_double (cpu, vm, 1)));
3835     }
3836   else
3837     {
3838       float (* fn)(float, float) = uimm (aarch64_get_instr (cpu), 23, 23)
3839         ? fminnm : fmaxnm;
3840
3841       aarch64_set_vec_float (cpu, vd, 0,
3842                              fn (aarch64_get_vec_float (cpu, vn, 0),
3843                                  aarch64_get_vec_float (cpu, vn, 1)));
3844       if (full)
3845         aarch64_set_vec_float (cpu, vd, 1,
3846                                fn (aarch64_get_vec_float (cpu, vn, 2),
3847                                    aarch64_get_vec_float (cpu, vn, 3)));
3848
3849       aarch64_set_vec_float (cpu, vd, (full ? 2 : 1),
3850                              fn (aarch64_get_vec_float (cpu, vm, 0),
3851                                  aarch64_get_vec_float (cpu, vm, 1)));
3852       if (full)
3853         aarch64_set_vec_float (cpu, vd, 3,
3854                                fn (aarch64_get_vec_float (cpu, vm, 2),
3855                                    aarch64_get_vec_float (cpu, vm, 3)));
3856     }
3857 }
3858
3859 static void
3860 do_vec_AND (sim_cpu *cpu)
3861 {
3862   /* instr[31]    = 0
3863      instr[30]    = half (0)/full (1)
3864      instr[29,21] = 001110001
3865      instr[20,16] = Vm
3866      instr[15,10] = 000111
3867      instr[9,5]   = Vn
3868      instr[4.0]   = Vd.  */
3869
3870   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3871   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3872   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3873   unsigned i;
3874   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3875
3876   NYI_assert (29, 21, 0x071);
3877   NYI_assert (15, 10, 0x07);
3878
3879   for (i = 0; i < (full ? 4 : 2); i++)
3880     aarch64_set_vec_u32 (cpu, vd, i,
3881                          aarch64_get_vec_u32 (cpu, vn, i)
3882                          & aarch64_get_vec_u32 (cpu, vm, i));
3883 }
3884
3885 static void
3886 do_vec_BSL (sim_cpu *cpu)
3887 {
3888   /* instr[31]    = 0
3889      instr[30]    = half (0)/full (1)
3890      instr[29,21] = 101110011
3891      instr[20,16] = Vm
3892      instr[15,10] = 000111
3893      instr[9,5]   = Vn
3894      instr[4.0]   = Vd.  */
3895
3896   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3897   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3898   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3899   unsigned i;
3900   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3901
3902   NYI_assert (29, 21, 0x173);
3903   NYI_assert (15, 10, 0x07);
3904
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, vd, i))
3910                            & aarch64_get_vec_u8 (cpu, vm, i)));
3911 }
3912
3913 static void
3914 do_vec_EOR (sim_cpu *cpu)
3915 {
3916   /* instr[31]    = 0
3917      instr[30]    = half (0)/full (1)
3918      instr[29,21] = 10 1110 001
3919      instr[20,16] = Vm
3920      instr[15,10] = 000111
3921      instr[9,5]   = Vn
3922      instr[4.0]   = Vd.  */
3923
3924   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3925   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3926   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3927   unsigned i;
3928   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3929
3930   NYI_assert (29, 21, 0x171);
3931   NYI_assert (15, 10, 0x07);
3932
3933   for (i = 0; i < (full ? 4 : 2); i++)
3934     aarch64_set_vec_u32 (cpu, vd, i,
3935                          aarch64_get_vec_u32 (cpu, vn, i)
3936                          ^ aarch64_get_vec_u32 (cpu, vm, i));
3937 }
3938
3939 static void
3940 do_vec_bit (sim_cpu *cpu)
3941 {
3942   /* instr[31]    = 0
3943      instr[30]    = half (0)/full (1)
3944      instr[29,23] = 10 1110 1
3945      instr[22]    = BIT (0) / BIF (1)
3946      instr[21]    = 1
3947      instr[20,16] = Vm
3948      instr[15,10] = 0001 11
3949      instr[9,5]   = Vn
3950      instr[4.0]   = Vd.  */
3951
3952   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3953   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3954   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3955   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
3956   unsigned test_false = uimm (aarch64_get_instr (cpu), 22, 22);
3957   unsigned i;
3958
3959   NYI_assert (29, 23, 0x5D);
3960   NYI_assert (21, 21, 1);
3961   NYI_assert (15, 10, 0x07);
3962
3963   if (test_false)
3964     {
3965       for (i = 0; i < (full ? 16 : 8); i++)
3966         if (aarch64_get_vec_u32 (cpu, vn, i) == 0)
3967           aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vm, i));
3968     }
3969   else
3970     {
3971       for (i = 0; i < (full ? 16 : 8); i++)
3972         if (aarch64_get_vec_u32 (cpu, vn, i) != 0)
3973           aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vm, i));
3974     }
3975 }
3976
3977 static void
3978 do_vec_ORN (sim_cpu *cpu)
3979 {
3980   /* instr[31]    = 0
3981      instr[30]    = half (0)/full (1)
3982      instr[29,21] = 00 1110 111
3983      instr[20,16] = Vm
3984      instr[15,10] = 00 0111
3985      instr[9,5]   = Vn
3986      instr[4.0]   = Vd.  */
3987
3988   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3989   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3990   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3991   unsigned i;
3992   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3993
3994   NYI_assert (29, 21, 0x077);
3995   NYI_assert (15, 10, 0x07);
3996
3997   for (i = 0; i < (full ? 16 : 8); i++)
3998     aarch64_set_vec_u8 (cpu, vd, i,
3999                         aarch64_get_vec_u8 (cpu, vn, i)
4000                         | ~ aarch64_get_vec_u8 (cpu, vm, i));
4001 }
4002
4003 static void
4004 do_vec_ORR (sim_cpu *cpu)
4005 {
4006   /* instr[31]    = 0
4007      instr[30]    = half (0)/full (1)
4008      instr[29,21] = 00 1110 101
4009      instr[20,16] = Vm
4010      instr[15,10] = 0001 11
4011      instr[9,5]   = Vn
4012      instr[4.0]   = Vd.  */
4013
4014   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4015   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4016   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4017   unsigned i;
4018   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
4019
4020   NYI_assert (29, 21, 0x075);
4021   NYI_assert (15, 10, 0x07);
4022
4023   for (i = 0; i < (full ? 16 : 8); i++)
4024     aarch64_set_vec_u8 (cpu, vd, i,
4025                         aarch64_get_vec_u8 (cpu, vn, i)
4026                         | aarch64_get_vec_u8 (cpu, vm, i));
4027 }
4028
4029 static void
4030 do_vec_BIC (sim_cpu *cpu)
4031 {
4032   /* instr[31]    = 0
4033      instr[30]    = half (0)/full (1)
4034      instr[29,21] = 00 1110 011
4035      instr[20,16] = Vm
4036      instr[15,10] = 00 0111
4037      instr[9,5]   = Vn
4038      instr[4.0]   = Vd.  */
4039
4040   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4041   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4042   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4043   unsigned i;
4044   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
4045
4046   NYI_assert (29, 21, 0x073);
4047   NYI_assert (15, 10, 0x07);
4048
4049   for (i = 0; i < (full ? 16 : 8); i++)
4050     aarch64_set_vec_u8 (cpu, vd, i,
4051                         aarch64_get_vec_u8 (cpu, vn, i)
4052                         & ~ aarch64_get_vec_u8 (cpu, vm, i));
4053 }
4054
4055 static void
4056 do_vec_XTN (sim_cpu *cpu)
4057 {
4058   /* instr[31]    = 0
4059      instr[30]    = first part (0)/ second part (1)
4060      instr[29,24] = 00 1110
4061      instr[23,22] = size: byte(00), half(01), word (10)
4062      instr[21,10] = 1000 0100 1010
4063      instr[9,5]   = Vs
4064      instr[4,0]   = Vd.  */
4065
4066   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
4067   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4068   unsigned bias = uimm (aarch64_get_instr (cpu), 30, 30);
4069   unsigned i;
4070
4071   NYI_assert (29, 24, 0x0E);
4072   NYI_assert (21, 10, 0x84A);
4073
4074   switch (uimm (aarch64_get_instr (cpu), 23, 22))
4075     {
4076     case 0:
4077       if (bias)
4078         for (i = 0; i < 8; i++)
4079           aarch64_set_vec_u8 (cpu, vd, i + 8,
4080                               aarch64_get_vec_u16 (cpu, vs, i) >> 8);
4081       else
4082         for (i = 0; i < 8; i++)
4083           aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vs, i));
4084       return;
4085
4086     case 1:
4087       if (bias)
4088         for (i = 0; i < 4; i++)
4089           aarch64_set_vec_u16 (cpu, vd, i + 4,
4090                                aarch64_get_vec_u32 (cpu, vs, i) >> 16);
4091       else
4092         for (i = 0; i < 4; i++)
4093           aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vs, i));
4094       return;
4095
4096     case 2:
4097       if (bias)
4098         for (i = 0; i < 2; i++)
4099           aarch64_set_vec_u32 (cpu, vd, i + 4,
4100                                aarch64_get_vec_u64 (cpu, vs, i) >> 32);
4101       else
4102         for (i = 0; i < 2; i++)
4103           aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u64 (cpu, vs, i));
4104       return;
4105
4106     default:
4107       HALT_UNALLOC;
4108     }
4109 }
4110
4111 static void
4112 do_vec_maxv (sim_cpu *cpu)
4113 {
4114   /* instr[31]    = 0
4115      instr[30]    = half(0)/full(1)
4116      instr[29]    = signed (0)/unsigned(1)
4117      instr[28,24] = 0 1110
4118      instr[23,22] = size: byte(00), half(01), word (10)
4119      instr[21]    = 1
4120      instr[20,17] = 1 000
4121      instr[16]    = max(0)/min(1)
4122      instr[15,10] = 1010 10
4123      instr[9,5]   = V source
4124      instr[4.0]   = R dest.  */
4125
4126   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
4127   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
4128   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4129   unsigned i;
4130
4131   NYI_assert (28, 24, 0x0E);
4132   NYI_assert (21, 21, 1);
4133   NYI_assert (20, 17, 8);
4134   NYI_assert (15, 10, 0x2A);
4135
4136   switch ((uimm (aarch64_get_instr (cpu), 29, 29) << 1)
4137           | uimm (aarch64_get_instr (cpu), 16, 16))
4138     {
4139     case 0: /* SMAXV.  */
4140        {
4141         int64_t smax;
4142         switch (uimm (aarch64_get_instr (cpu), 23, 22))
4143           {
4144           case 0:
4145             smax = aarch64_get_vec_s8 (cpu, vs, 0);
4146             for (i = 1; i < (full ? 16 : 8); i++)
4147               smax = max (smax, aarch64_get_vec_s8 (cpu, vs, i));
4148             break;
4149           case 1:
4150             smax = aarch64_get_vec_s16 (cpu, vs, 0);
4151             for (i = 1; i < (full ? 8 : 4); i++)
4152               smax = max (smax, aarch64_get_vec_s16 (cpu, vs, i));
4153             break;
4154           case 2:
4155             smax = aarch64_get_vec_s32 (cpu, vs, 0);
4156             for (i = 1; i < (full ? 4 : 2); i++)
4157               smax = max (smax, aarch64_get_vec_s32 (cpu, vs, i));
4158             break;
4159           default:
4160           case 3:
4161             HALT_UNALLOC;
4162           }
4163         aarch64_set_reg_s64 (cpu, rd, NO_SP, smax);
4164         return;
4165       }
4166
4167     case 1: /* SMINV.  */
4168       {
4169         int64_t smin;
4170         switch (uimm (aarch64_get_instr (cpu), 23, 22))
4171           {
4172           case 0:
4173             smin = aarch64_get_vec_s8 (cpu, vs, 0);
4174             for (i = 1; i < (full ? 16 : 8); i++)
4175               smin = min (smin, aarch64_get_vec_s8 (cpu, vs, i));
4176             break;
4177           case 1:
4178             smin = aarch64_get_vec_s16 (cpu, vs, 0);
4179             for (i = 1; i < (full ? 8 : 4); i++)
4180               smin = min (smin, aarch64_get_vec_s16 (cpu, vs, i));
4181             break;
4182           case 2:
4183             smin = aarch64_get_vec_s32 (cpu, vs, 0);
4184             for (i = 1; i < (full ? 4 : 2); i++)
4185               smin = min (smin, aarch64_get_vec_s32 (cpu, vs, i));
4186             break;
4187           default:
4188           case 3:
4189             HALT_UNALLOC;
4190           }
4191         aarch64_set_reg_s64 (cpu, rd, NO_SP, smin);
4192         return;
4193       }
4194
4195     case 2: /* UMAXV.  */
4196       {
4197         uint64_t umax;
4198         switch (uimm (aarch64_get_instr (cpu), 23, 22))
4199           {
4200           case 0:
4201             umax = aarch64_get_vec_u8 (cpu, vs, 0);
4202             for (i = 1; i < (full ? 16 : 8); i++)
4203               umax = max (umax, aarch64_get_vec_u8 (cpu, vs, i));
4204             break;
4205           case 1:
4206             umax = aarch64_get_vec_u16 (cpu, vs, 0);
4207             for (i = 1; i < (full ? 8 : 4); i++)
4208               umax = max (umax, aarch64_get_vec_u16 (cpu, vs, i));
4209             break;
4210           case 2:
4211             umax = aarch64_get_vec_u32 (cpu, vs, 0);
4212             for (i = 1; i < (full ? 4 : 2); i++)
4213               umax = max (umax, aarch64_get_vec_u32 (cpu, vs, i));
4214             break;
4215           default:
4216           case 3:
4217             HALT_UNALLOC;
4218           }
4219         aarch64_set_reg_u64 (cpu, rd, NO_SP, umax);
4220         return;
4221       }
4222
4223     case 3: /* UMINV.  */
4224       {
4225         uint64_t umin;
4226         switch (uimm (aarch64_get_instr (cpu), 23, 22))
4227           {
4228           case 0:
4229             umin = aarch64_get_vec_u8 (cpu, vs, 0);
4230             for (i = 1; i < (full ? 16 : 8); i++)
4231               umin = min (umin, aarch64_get_vec_u8 (cpu, vs, i));
4232             break;
4233           case 1:
4234             umin = aarch64_get_vec_u16 (cpu, vs, 0);
4235             for (i = 1; i < (full ? 8 : 4); i++)
4236               umin = min (umin, aarch64_get_vec_u16 (cpu, vs, i));
4237             break;
4238           case 2:
4239             umin = aarch64_get_vec_u32 (cpu, vs, 0);
4240             for (i = 1; i < (full ? 4 : 2); i++)
4241               umin = min (umin, aarch64_get_vec_u32 (cpu, vs, i));
4242             break;
4243           default:
4244           case 3:
4245             HALT_UNALLOC;
4246           }
4247         aarch64_set_reg_u64 (cpu, rd, NO_SP, umin);
4248         return;
4249       }
4250
4251     default:
4252       HALT_UNALLOC;
4253     }
4254 }
4255
4256 static void
4257 do_vec_fminmaxV (sim_cpu *cpu)
4258 {
4259   /* instr[31,24] = 0110 1110
4260      instr[23]    = max(0)/min(1)
4261      instr[22,14] = 011 0000 11
4262      instr[13,12] = nm(00)/normal(11)
4263      instr[11,10] = 10
4264      instr[9,5]   = V source
4265      instr[4.0]   = R dest.  */
4266
4267   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
4268   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
4269   unsigned i;
4270   float res   = aarch64_get_vec_float (cpu, vs, 0);
4271
4272   NYI_assert (31, 24, 0x6E);
4273   NYI_assert (22, 14, 0x0C3);
4274   NYI_assert (11, 10, 2);
4275
4276   if (uimm (aarch64_get_instr (cpu), 23, 23))
4277     {
4278       switch (uimm (aarch64_get_instr (cpu), 13, 12))
4279         {
4280         case 0: /* FMNINNMV.  */
4281           for (i = 1; i < 4; i++)
4282             res = fminnm (res, aarch64_get_vec_float (cpu, vs, i));
4283           break;
4284
4285         case 3: /* FMINV.  */
4286           for (i = 1; i < 4; i++)
4287             res = min (res, aarch64_get_vec_float (cpu, vs, i));
4288           break;
4289
4290         default:
4291           HALT_NYI;
4292         }
4293     }
4294   else
4295     {
4296       switch (uimm (aarch64_get_instr (cpu), 13, 12))
4297         {
4298         case 0: /* FMNAXNMV.  */
4299           for (i = 1; i < 4; i++)
4300             res = fmaxnm (res, aarch64_get_vec_float (cpu, vs, i));
4301           break;
4302
4303         case 3: /* FMAXV.  */
4304           for (i = 1; i < 4; i++)
4305             res = max (res, aarch64_get_vec_float (cpu, vs, i));
4306           break;
4307
4308         default:
4309           HALT_NYI;
4310         }
4311     }
4312
4313   aarch64_set_FP_float (cpu, rd, res);
4314 }
4315
4316 static void
4317 do_vec_Fminmax (sim_cpu *cpu)
4318 {
4319   /* instr[31]    = 0
4320      instr[30]    = half(0)/full(1)
4321      instr[29,24] = 00 1110
4322      instr[23]    = max(0)/min(1)
4323      instr[22]    = float(0)/double(1)
4324      instr[21]    = 1
4325      instr[20,16] = Vm
4326      instr[15,14] = 11
4327      instr[13,12] = nm(00)/normal(11)
4328      instr[11,10] = 01
4329      instr[9,5]   = Vn
4330      instr[4,0]   = Vd.  */
4331
4332   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4333   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4334   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4335   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4336   unsigned min = uimm (aarch64_get_instr (cpu), 23, 23);
4337   unsigned i;
4338
4339   NYI_assert (29, 24, 0x0E);
4340   NYI_assert (21, 21, 1);
4341   NYI_assert (15, 14, 3);
4342   NYI_assert (11, 10, 1);
4343
4344   if (uimm (aarch64_get_instr (cpu), 22, 22))
4345     {
4346       double (* func)(double, double);
4347
4348       if (! full)
4349         HALT_NYI;
4350
4351       if (uimm (aarch64_get_instr (cpu), 13, 12) == 0)
4352         func = min ? dminnm : dmaxnm;
4353       else if (uimm (aarch64_get_instr (cpu), 13, 12) == 3)
4354         func = min ? fmin : fmax;
4355       else
4356         HALT_NYI;
4357
4358       for (i = 0; i < 2; i++)
4359         aarch64_set_vec_double (cpu, vd, i,
4360                                 func (aarch64_get_vec_double (cpu, vn, i),
4361                                       aarch64_get_vec_double (cpu, vm, i)));
4362     }
4363   else
4364     {
4365       float (* func)(float, float);
4366
4367       if (uimm (aarch64_get_instr (cpu), 13, 12) == 0)
4368         func = min ? fminnm : fmaxnm;
4369       else if (uimm (aarch64_get_instr (cpu), 13, 12) == 3)
4370         func = min ? fminf : fmaxf;
4371       else
4372         HALT_NYI;
4373
4374       for (i = 0; i < (full ? 4 : 2); i++)
4375         aarch64_set_vec_float (cpu, vd, i,
4376                                func (aarch64_get_vec_float (cpu, vn, i),
4377                                      aarch64_get_vec_float (cpu, vm, i)));
4378     }
4379 }
4380
4381 static void
4382 do_vec_SCVTF (sim_cpu *cpu)
4383 {
4384   /* instr[31]    = 0
4385      instr[30]    = Q
4386      instr[29,23] = 00 1110 0
4387      instr[22]    = float(0)/double(1)
4388      instr[21,10] = 10 0001 1101 10
4389      instr[9,5]   = Vn
4390      instr[4,0]   = Vd.  */
4391
4392   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4393   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4394   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4395   unsigned size = uimm (aarch64_get_instr (cpu), 22, 22);
4396   unsigned i;
4397
4398   NYI_assert (29, 23, 0x1C);
4399   NYI_assert (21, 10, 0x876);
4400
4401   if (size)
4402     {
4403       if (! full)
4404         HALT_UNALLOC;
4405
4406       for (i = 0; i < 2; i++)
4407         {
4408           double val = (double) aarch64_get_vec_u64 (cpu, vn, i);
4409           aarch64_set_vec_double (cpu, vd, i, val);
4410         }
4411     }
4412   else
4413     {
4414       for (i = 0; i < (full ? 4 : 2); i++)
4415         {
4416           float val = (float) aarch64_get_vec_u32 (cpu, vn, i);
4417           aarch64_set_vec_float (cpu, vd, i, val);
4418         }
4419     }
4420 }
4421
4422 #define VEC_CMP(SOURCE, CMP)                                            \
4423   do                                                                    \
4424     {                                                                   \
4425       switch (size)                                                     \
4426         {                                                               \
4427         case 0:                                                         \
4428           for (i = 0; i < (full ? 16 : 8); i++)                         \
4429             aarch64_set_vec_u8 (cpu, vd, i,                             \
4430                                 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4431                                 CMP                                     \
4432                                 aarch64_get_vec_##SOURCE##8 (cpu, vm, i) \
4433                                 ? -1 : 0);                              \
4434           return;                                                       \
4435         case 1:                                                         \
4436           for (i = 0; i < (full ? 8 : 4); i++)                          \
4437             aarch64_set_vec_u16 (cpu, vd, i,                            \
4438                                  aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4439                                  CMP                                    \
4440                                  aarch64_get_vec_##SOURCE##16 (cpu, vm, i) \
4441                                  ? -1 : 0);                             \
4442           return;                                                       \
4443         case 2:                                                         \
4444           for (i = 0; i < (full ? 4 : 2); i++)                          \
4445             aarch64_set_vec_u32 (cpu, vd, i, \
4446                                  aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4447                                  CMP                                    \
4448                                  aarch64_get_vec_##SOURCE##32 (cpu, vm, i) \
4449                                  ? -1 : 0);                             \
4450           return;                                                       \
4451         case 3:                                                         \
4452           if (! full)                                                   \
4453             HALT_UNALLOC;                                               \
4454           for (i = 0; i < 2; i++)                                       \
4455             aarch64_set_vec_u64 (cpu, vd, i, \
4456                                  aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4457                                  CMP                                    \
4458                                  aarch64_get_vec_##SOURCE##64 (cpu, vm, i) \
4459                                  ? -1ULL : 0);                          \
4460           return;                                                       \
4461         default:                                                        \
4462         HALT_UNALLOC;                                                   \
4463         }                                                               \
4464     }                                                                   \
4465   while (0)
4466
4467 #define VEC_CMP0(SOURCE, CMP)                                           \
4468   do                                                                    \
4469     {                                                                   \
4470       switch (size)                                                     \
4471         {                                                               \
4472         case 0:                                                         \
4473           for (i = 0; i < (full ? 16 : 8); i++)                         \
4474             aarch64_set_vec_u8 (cpu, vd, i,                             \
4475                                 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4476                                 CMP 0 ? -1 : 0);                        \
4477           return;                                                       \
4478         case 1:                                                         \
4479           for (i = 0; i < (full ? 8 : 4); i++)                          \
4480             aarch64_set_vec_u16 (cpu, vd, i,                            \
4481                                  aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4482                                  CMP 0 ? -1 : 0);                       \
4483           return;                                                       \
4484         case 2:                                                         \
4485           for (i = 0; i < (full ? 4 : 2); i++)                          \
4486             aarch64_set_vec_u32 (cpu, vd, i,                            \
4487                                  aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4488                                  CMP 0 ? -1 : 0);                       \
4489           return;                                                       \
4490         case 3:                                                         \
4491           if (! full)                                                   \
4492             HALT_UNALLOC;                                               \
4493           for (i = 0; i < 2; i++)                                       \
4494             aarch64_set_vec_u64 (cpu, vd, i,                            \
4495                                  aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4496                                  CMP 0 ? -1ULL : 0);                    \
4497           return;                                                       \
4498         default:                                                        \
4499           HALT_UNALLOC;                                                 \
4500         }                                                               \
4501     }                                                                   \
4502   while (0)
4503
4504 #define VEC_FCMP0(CMP)                                                  \
4505   do                                                                    \
4506     {                                                                   \
4507       if (vm != 0)                                                      \
4508         HALT_NYI;                                                       \
4509       if (uimm (aarch64_get_instr (cpu), 22, 22))                       \
4510         {                                                               \
4511           if (! full)                                                   \
4512             HALT_NYI;                                                   \
4513           for (i = 0; i < 2; i++)                                       \
4514             aarch64_set_vec_u64 (cpu, vd, i,                            \
4515                                  aarch64_get_vec_double (cpu, vn, i)    \
4516                                  CMP 0.0 ? -1 : 0);                     \
4517         }                                                               \
4518       else                                                              \
4519         {                                                               \
4520           for (i = 0; i < (full ? 4 : 2); i++)                          \
4521             aarch64_set_vec_u32 (cpu, vd, i,                            \
4522                                  aarch64_get_vec_float (cpu, vn, i)     \
4523                                  CMP 0.0 ? -1 : 0);                     \
4524         }                                                               \
4525       return;                                                           \
4526     }                                                                   \
4527   while (0)
4528
4529 #define VEC_FCMP(CMP)                                                   \
4530   do                                                                    \
4531     {                                                                   \
4532       if (uimm (aarch64_get_instr (cpu), 22, 22))                       \
4533         {                                                               \
4534           if (! full)                                                   \
4535             HALT_NYI;                                                   \
4536           for (i = 0; i < 2; i++)                                       \
4537             aarch64_set_vec_u64 (cpu, vd, i,                            \
4538                                  aarch64_get_vec_double (cpu, vn, i)    \
4539                                  CMP                                    \
4540                                  aarch64_get_vec_double (cpu, vm, i)    \
4541                                  ? -1 : 0);                             \
4542         }                                                               \
4543       else                                                              \
4544         {                                                               \
4545           for (i = 0; i < (full ? 4 : 2); i++)                          \
4546             aarch64_set_vec_u32 (cpu, vd, i,                            \
4547                                  aarch64_get_vec_float (cpu, vn, i)     \
4548                                  CMP                                    \
4549                                  aarch64_get_vec_float (cpu, vm, i)     \
4550                                  ? -1 : 0);                             \
4551         }                                                               \
4552       return;                                                           \
4553     }                                                                   \
4554   while (0)
4555
4556 static void
4557 do_vec_compare (sim_cpu *cpu)
4558 {
4559   /* instr[31]    = 0
4560      instr[30]    = half(0)/full(1)
4561      instr[29]    = part-of-comparison-type
4562      instr[28,24] = 0 1110
4563      instr[23,22] = size of integer compares: byte(00), half(01), word (10), long (11)
4564                     type of float compares: single (-0) / double (-1)
4565      instr[21]    = 1
4566      instr[20,16] = Vm or 00000 (compare vs 0)
4567      instr[15,10] = part-of-comparison-type
4568      instr[9,5]   = Vn
4569      instr[4.0]   = Vd.  */
4570
4571   int full = uimm (aarch64_get_instr (cpu), 30, 30);
4572   int size = uimm (aarch64_get_instr (cpu), 23, 22);
4573   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4574   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4575   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4576   unsigned i;
4577
4578   NYI_assert (28, 24, 0x0E);
4579   NYI_assert (21, 21, 1);
4580
4581   if ((uimm (aarch64_get_instr (cpu), 11, 11)
4582        && uimm (aarch64_get_instr (cpu), 14, 14))
4583       || ((uimm (aarch64_get_instr (cpu), 11, 11) == 0
4584            && uimm (aarch64_get_instr (cpu), 10, 10) == 0)))
4585     {
4586       /* A compare vs 0.  */
4587       if (vm != 0)
4588         {
4589           if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x2A)
4590             do_vec_maxv (cpu);
4591           else if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x32
4592                    || uimm (aarch64_get_instr (cpu), 15, 10) == 0x3E)
4593             do_vec_fminmaxV (cpu);
4594           else if (uimm (aarch64_get_instr (cpu), 29, 23) == 0x1C
4595                    && uimm (aarch64_get_instr (cpu), 21, 10) == 0x876)
4596             do_vec_SCVTF (cpu);
4597           else
4598             HALT_NYI;
4599           return;
4600         }
4601     }
4602
4603   if (uimm (aarch64_get_instr (cpu), 14, 14))
4604     {
4605       /* A floating point compare.  */
4606       unsigned decode = (uimm (aarch64_get_instr (cpu), 29, 29) << 5)
4607         | (uimm (aarch64_get_instr (cpu), 23, 23) << 4)
4608         | uimm (aarch64_get_instr (cpu), 13, 10);
4609
4610       NYI_assert (15, 15, 1);
4611
4612       switch (decode)
4613         {
4614         case /* 0b010010: GT#0 */ 0x12: VEC_FCMP0 (>);
4615         case /* 0b110010: GE#0 */ 0x32: VEC_FCMP0 (>=);
4616         case /* 0b010110: EQ#0 */ 0x16: VEC_FCMP0 (==);
4617         case /* 0b110110: LE#0 */ 0x36: VEC_FCMP0 (<=);
4618         case /* 0b011010: LT#0 */ 0x1A: VEC_FCMP0 (<);
4619         case /* 0b111001: GT */   0x39: VEC_FCMP  (>);
4620         case /* 0b101001: GE */   0x29: VEC_FCMP  (>=);
4621         case /* 0b001001: EQ */   0x09: VEC_FCMP  (==);
4622
4623         default:
4624           HALT_NYI;
4625         }
4626     }
4627   else
4628     {
4629       unsigned decode = (uimm (aarch64_get_instr (cpu), 29, 29) << 6)
4630         | uimm (aarch64_get_instr (cpu), 15, 10);
4631
4632       switch (decode)
4633         {
4634         case 0x0D: /* 0001101 GT */     VEC_CMP  (s, > );
4635         case 0x0F: /* 0001111 GE */     VEC_CMP  (s, >= );
4636         case 0x22: /* 0100010 GT #0 */  VEC_CMP0 (s, > );
4637         case 0x26: /* 0100110 EQ #0 */  VEC_CMP0 (s, == );
4638         case 0x2A: /* 0101010 LT #0 */  VEC_CMP0 (s, < );
4639         case 0x4D: /* 1001101 HI */     VEC_CMP  (u, > );
4640         case 0x4F: /* 1001111 HS */     VEC_CMP  (u, >= );
4641         case 0x62: /* 1100010 GE #0 */  VEC_CMP0 (s, >= );
4642         case 0x63: /* 1100011 EQ */     VEC_CMP  (u, == );
4643         case 0x66: /* 1100110 LE #0 */  VEC_CMP0 (s, <= );
4644         default:
4645           if (vm == 0)
4646             HALT_NYI;
4647           do_vec_maxv (cpu);
4648         }
4649     }
4650 }
4651
4652 static void
4653 do_vec_SSHL (sim_cpu *cpu)
4654 {
4655   /* instr[31]    = 0
4656      instr[30]    = first part (0)/ second part (1)
4657      instr[29,24] = 00 1110
4658      instr[23,22] = size: byte(00), half(01), word (10), long (11)
4659      instr[21]    = 1
4660      instr[20,16] = Vm
4661      instr[15,10] = 0100 01
4662      instr[9,5]   = Vn
4663      instr[4,0]   = Vd.  */
4664
4665   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4666   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4667   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4668   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4669   unsigned i;
4670
4671   NYI_assert (29, 24, 0x0E);
4672   NYI_assert (21, 21, 1);
4673   NYI_assert (15, 10, 0x11);
4674
4675   /* FIXME: What is a signed shift left in this context ?.  */
4676
4677   switch (uimm (aarch64_get_instr (cpu), 23, 22))
4678     {
4679     case 0:
4680       for (i = 0; i < (full ? 16 : 8); i++)
4681         aarch64_set_vec_s8 (cpu, vd, i, aarch64_get_vec_s8 (cpu, vn, i)
4682                             << aarch64_get_vec_s8 (cpu, vm, i));
4683       return;
4684
4685     case 1:
4686       for (i = 0; i < (full ? 8 : 4); i++)
4687         aarch64_set_vec_s16 (cpu, vd, i, aarch64_get_vec_s16 (cpu, vn, i)
4688                              << aarch64_get_vec_s16 (cpu, vm, i));
4689       return;
4690
4691     case 2:
4692       for (i = 0; i < (full ? 4 : 2); i++)
4693         aarch64_set_vec_s32 (cpu, vd, i, aarch64_get_vec_s32 (cpu, vn, i)
4694                              << aarch64_get_vec_s32 (cpu, vm, i));
4695       return;
4696
4697     case 3:
4698       if (! full)
4699         HALT_UNALLOC;
4700       for (i = 0; i < 2; i++)
4701         aarch64_set_vec_s64 (cpu, vd, i, aarch64_get_vec_s64 (cpu, vn, i)
4702                              << aarch64_get_vec_s64 (cpu, vm, i));
4703       return;
4704
4705     default:
4706       HALT_NYI;
4707     }
4708 }
4709
4710 static void
4711 do_vec_USHL (sim_cpu *cpu)
4712 {
4713   /* instr[31]    = 0
4714      instr[30]    = first part (0)/ second part (1)
4715      instr[29,24] = 10 1110
4716      instr[23,22] = size: byte(00), half(01), word (10), long (11)
4717      instr[21]    = 1
4718      instr[20,16] = Vm
4719      instr[15,10] = 0100 01
4720      instr[9,5]   = Vn
4721      instr[4,0]   = Vd  */
4722
4723   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4724   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4725   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4726   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4727   unsigned i;
4728
4729   NYI_assert (29, 24, 0x2E);
4730   NYI_assert (15, 10, 0x11);
4731
4732   switch (uimm (aarch64_get_instr (cpu), 23, 22))
4733     {
4734     case 0:
4735       for (i = 0; i < (full ? 16 : 8); i++)
4736         aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vn, i)
4737                             << aarch64_get_vec_u8 (cpu, vm, i));
4738       return;
4739
4740     case 1:
4741       for (i = 0; i < (full ? 8 : 4); i++)
4742         aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vn, i)
4743                              << aarch64_get_vec_u16 (cpu, vm, i));
4744       return;
4745
4746     case 2:
4747       for (i = 0; i < (full ? 4 : 2); i++)
4748         aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vn, i)
4749                              << aarch64_get_vec_u32 (cpu, vm, i));
4750       return;
4751
4752     case 3:
4753       if (! full)
4754         HALT_UNALLOC;
4755       for (i = 0; i < 2; i++)
4756         aarch64_set_vec_u64 (cpu, vd, i, aarch64_get_vec_u64 (cpu, vn, i)
4757                              << aarch64_get_vec_u64 (cpu, vm, i));
4758       return;
4759
4760     default:
4761       HALT_NYI;
4762     }
4763 }
4764
4765 static void
4766 do_vec_FMLA (sim_cpu *cpu)
4767 {
4768   /* instr[31]    = 0
4769      instr[30]    = full/half selector
4770      instr[29,23] = 0011100
4771      instr[22]    = size: 0=>float, 1=>double
4772      instr[21]    = 1
4773      instr[20,16] = Vn
4774      instr[15,10] = 1100 11
4775      instr[9,5]   = Vm
4776      instr[4.0]   = Vd.  */
4777
4778   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4779   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4780   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4781   unsigned i;
4782   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
4783
4784   NYI_assert (29, 23, 0x1C);
4785   NYI_assert (21, 21, 1);
4786   NYI_assert (15, 10, 0x33);
4787
4788   if (uimm (aarch64_get_instr (cpu), 22, 22))
4789     {
4790       if (! full)
4791         HALT_UNALLOC;
4792       for (i = 0; i < 2; i++)
4793         aarch64_set_vec_double (cpu, vd, i,
4794                                 aarch64_get_vec_double (cpu, vn, i) *
4795                                 aarch64_get_vec_double (cpu, vm, i) +
4796                                 aarch64_get_vec_double (cpu, vd, i));
4797     }
4798   else
4799     {
4800       for (i = 0; i < (full ? 4 : 2); i++)
4801         aarch64_set_vec_float (cpu, vd, i,
4802                                aarch64_get_vec_float (cpu, vn, i) *
4803                                aarch64_get_vec_float (cpu, vm, i) +
4804                                aarch64_get_vec_float (cpu, vd, i));
4805     }
4806 }
4807
4808 static void
4809 do_vec_max (sim_cpu *cpu)
4810 {
4811   /* instr[31]    = 0
4812      instr[30]    = full/half selector
4813      instr[29]    = SMAX (0) / UMAX (1)
4814      instr[28,24] = 0 1110
4815      instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
4816      instr[21]    = 1
4817      instr[20,16] = Vn
4818      instr[15,10] = 0110 01
4819      instr[9,5]   = Vm
4820      instr[4.0]   = Vd.  */
4821
4822   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4823   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4824   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4825   unsigned i;
4826   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
4827
4828   NYI_assert (28, 24, 0x0E);
4829   NYI_assert (21, 21, 1);
4830   NYI_assert (15, 10, 0x19);
4831
4832   if (uimm (aarch64_get_instr (cpu), 29, 29))
4833     {
4834       switch (uimm (aarch64_get_instr (cpu), 23, 22))
4835         {
4836         case 0:
4837           for (i = 0; i < (full ? 16 : 8); i++)
4838             aarch64_set_vec_u8 (cpu, vd, i,
4839                                 aarch64_get_vec_u8 (cpu, vn, i)
4840                                 > aarch64_get_vec_u8 (cpu, vm, i)
4841                                 ? aarch64_get_vec_u8 (cpu, vn, i)
4842                                 : aarch64_get_vec_u8 (cpu, vm, i));
4843           return;
4844
4845         case 1:
4846           for (i = 0; i < (full ? 8 : 4); i++)
4847             aarch64_set_vec_u16 (cpu, vd, i,
4848                                  aarch64_get_vec_u16 (cpu, vn, i)
4849                                  > aarch64_get_vec_u16 (cpu, vm, i)
4850                                  ? aarch64_get_vec_u16 (cpu, vn, i)
4851                                  : aarch64_get_vec_u16 (cpu, vm, i));
4852           return;
4853
4854         case 2:
4855           for (i = 0; i < (full ? 4 : 2); i++)
4856             aarch64_set_vec_u32 (cpu, vd, i,
4857                                  aarch64_get_vec_u32 (cpu, vn, i)
4858                                  > aarch64_get_vec_u32 (cpu, vm, i)
4859                                  ? aarch64_get_vec_u32 (cpu, vn, i)
4860                                  : aarch64_get_vec_u32 (cpu, vm, i));
4861           return;
4862
4863         default:
4864         case 3:
4865           HALT_UNALLOC;
4866         }
4867     }
4868   else
4869     {
4870       switch (uimm (aarch64_get_instr (cpu), 23, 22))
4871         {
4872         case 0:
4873           for (i = 0; i < (full ? 16 : 8); i++)
4874             aarch64_set_vec_s8 (cpu, vd, i,
4875                                 aarch64_get_vec_s8 (cpu, vn, i)
4876                                 > aarch64_get_vec_s8 (cpu, vm, i)
4877                                 ? aarch64_get_vec_s8 (cpu, vn, i)
4878                                 : aarch64_get_vec_s8 (cpu, vm, i));
4879           return;
4880
4881         case 1:
4882           for (i = 0; i < (full ? 8 : 4); i++)
4883             aarch64_set_vec_s16 (cpu, vd, i,
4884                                  aarch64_get_vec_s16 (cpu, vn, i)
4885                                  > aarch64_get_vec_s16 (cpu, vm, i)
4886                                  ? aarch64_get_vec_s16 (cpu, vn, i)
4887                                  : aarch64_get_vec_s16 (cpu, vm, i));
4888           return;
4889
4890         case 2:
4891           for (i = 0; i < (full ? 4 : 2); i++)
4892             aarch64_set_vec_s32 (cpu, vd, i,
4893                                  aarch64_get_vec_s32 (cpu, vn, i)
4894                                  > aarch64_get_vec_s32 (cpu, vm, i)
4895                                  ? aarch64_get_vec_s32 (cpu, vn, i)
4896                                  : aarch64_get_vec_s32 (cpu, vm, i));
4897           return;
4898
4899         default:
4900         case 3:
4901           HALT_UNALLOC;
4902         }
4903     }
4904 }
4905
4906 static void
4907 do_vec_min (sim_cpu *cpu)
4908 {
4909   /* instr[31]    = 0
4910      instr[30]    = full/half selector
4911      instr[29]    = SMIN (0) / UMIN (1)
4912      instr[28,24] = 0 1110
4913      instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
4914      instr[21]    = 1
4915      instr[20,16] = Vn
4916      instr[15,10] = 0110 11
4917      instr[9,5]   = Vm
4918      instr[4.0]   = Vd.  */
4919
4920   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4921   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4922   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4923   unsigned i;
4924   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
4925
4926   NYI_assert (28, 24, 0x0E);
4927   NYI_assert (21, 21, 1);
4928   NYI_assert (15, 10, 0x1B);
4929
4930   if (uimm (aarch64_get_instr (cpu), 29, 29))
4931     {
4932       switch (uimm (aarch64_get_instr (cpu), 23, 22))
4933         {
4934         case 0:
4935           for (i = 0; i < (full ? 16 : 8); i++)
4936             aarch64_set_vec_u8 (cpu, vd, i,
4937                                 aarch64_get_vec_u8 (cpu, vn, i)
4938                                 < aarch64_get_vec_u8 (cpu, vm, i)
4939                                 ? aarch64_get_vec_u8 (cpu, vn, i)
4940                                 : aarch64_get_vec_u8 (cpu, vm, i));
4941           return;
4942
4943         case 1:
4944           for (i = 0; i < (full ? 8 : 4); i++)
4945             aarch64_set_vec_u16 (cpu, vd, i,
4946                                  aarch64_get_vec_u16 (cpu, vn, i)
4947                                  < aarch64_get_vec_u16 (cpu, vm, i)
4948                                  ? aarch64_get_vec_u16 (cpu, vn, i)
4949                                  : aarch64_get_vec_u16 (cpu, vm, i));
4950           return;
4951
4952         case 2:
4953           for (i = 0; i < (full ? 4 : 2); i++)
4954             aarch64_set_vec_u32 (cpu, vd, i,
4955                                  aarch64_get_vec_u32 (cpu, vn, i)
4956                                  < aarch64_get_vec_u32 (cpu, vm, i)
4957                                  ? aarch64_get_vec_u32 (cpu, vn, i)
4958                                  : aarch64_get_vec_u32 (cpu, vm, i));
4959           return;
4960
4961         default:
4962         case 3:
4963           HALT_UNALLOC;
4964         }
4965     }
4966   else
4967     {
4968       switch (uimm (aarch64_get_instr (cpu), 23, 22))
4969         {
4970         case 0:
4971           for (i = 0; i < (full ? 16 : 8); i++)
4972             aarch64_set_vec_s8 (cpu, vd, i,
4973                                 aarch64_get_vec_s8 (cpu, vn, i)
4974                                 < aarch64_get_vec_s8 (cpu, vm, i)
4975                                 ? aarch64_get_vec_s8 (cpu, vn, i)
4976                                 : aarch64_get_vec_s8 (cpu, vm, i));
4977           return;
4978
4979         case 1:
4980           for (i = 0; i < (full ? 8 : 4); i++)
4981             aarch64_set_vec_s16 (cpu, vd, i,
4982                                  aarch64_get_vec_s16 (cpu, vn, i)
4983                                  < aarch64_get_vec_s16 (cpu, vm, i)
4984                                  ? aarch64_get_vec_s16 (cpu, vn, i)
4985                                  : aarch64_get_vec_s16 (cpu, vm, i));
4986           return;
4987
4988         case 2:
4989           for (i = 0; i < (full ? 4 : 2); i++)
4990             aarch64_set_vec_s32 (cpu, vd, i,
4991                                  aarch64_get_vec_s32 (cpu, vn, i)
4992                                  < aarch64_get_vec_s32 (cpu, vm, i)
4993                                  ? aarch64_get_vec_s32 (cpu, vn, i)
4994                                  : aarch64_get_vec_s32 (cpu, vm, i));
4995           return;
4996
4997         default:
4998         case 3:
4999           HALT_UNALLOC;
5000         }
5001     }
5002 }
5003
5004 static void
5005 do_vec_sub_long (sim_cpu *cpu)
5006 {
5007   /* instr[31]    = 0
5008      instr[30]    = lower (0) / upper (1)
5009      instr[29]    = signed (0) / unsigned (1)
5010      instr[28,24] = 0 1110
5011      instr[23,22] = size: bytes (00), half (01), word (10)
5012      instr[21]    = 1
5013      insrt[20,16] = Vm
5014      instr[15,10] = 0010 00
5015      instr[9,5]   = Vn
5016      instr[4,0]   = V dest.  */
5017
5018   unsigned size = uimm (aarch64_get_instr (cpu), 23, 22);
5019   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5020   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5021   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5022   unsigned bias = 0;
5023   unsigned i;
5024
5025   NYI_assert (28, 24, 0x0E);
5026   NYI_assert (21, 21, 1);
5027   NYI_assert (15, 10, 0x08);
5028
5029   if (size == 3)
5030     HALT_UNALLOC;
5031
5032   switch (uimm (aarch64_get_instr (cpu), 30, 29))
5033     {
5034     case 2: /* SSUBL2.  */
5035       bias = 2;
5036     case 0: /* SSUBL.  */
5037       switch (size)
5038         {
5039         case 0:
5040           bias *= 3;
5041           for (i = 0; i < 8; i++)
5042             aarch64_set_vec_s16 (cpu, vd, i,
5043                                  aarch64_get_vec_s8 (cpu, vn, i + bias)
5044                                  - aarch64_get_vec_s8 (cpu, vm, i + bias));
5045           break;
5046
5047         case 1:
5048           bias *= 2;
5049           for (i = 0; i < 4; i++)
5050             aarch64_set_vec_s32 (cpu, vd, i,
5051                                  aarch64_get_vec_s16 (cpu, vn, i + bias)
5052                                  - aarch64_get_vec_s16 (cpu, vm, i + bias));
5053           break;
5054
5055         case 2:
5056           for (i = 0; i < 2; i++)
5057             aarch64_set_vec_s64 (cpu, vd, i,
5058                                  aarch64_get_vec_s32 (cpu, vn, i + bias)
5059                                  - aarch64_get_vec_s32 (cpu, vm, i + bias));
5060           break;
5061
5062         default:
5063           HALT_UNALLOC;
5064         }
5065       break;
5066
5067     case 3: /* USUBL2.  */
5068       bias = 2;
5069     case 1: /* USUBL.  */
5070       switch (size)
5071         {
5072         case 0:
5073           bias *= 3;
5074           for (i = 0; i < 8; i++)
5075             aarch64_set_vec_u16 (cpu, vd, i,
5076                                  aarch64_get_vec_u8 (cpu, vn, i + bias)
5077                                  - aarch64_get_vec_u8 (cpu, vm, i + bias));
5078           break;
5079
5080         case 1:
5081           bias *= 2;
5082           for (i = 0; i < 4; i++)
5083             aarch64_set_vec_u32 (cpu, vd, i,
5084                                  aarch64_get_vec_u16 (cpu, vn, i + bias)
5085                                  - aarch64_get_vec_u16 (cpu, vm, i + bias));
5086           break;
5087
5088         case 2:
5089           for (i = 0; i < 2; i++)
5090             aarch64_set_vec_u64 (cpu, vd, i,
5091                                  aarch64_get_vec_u32 (cpu, vn, i + bias)
5092                                  - aarch64_get_vec_u32 (cpu, vm, i + bias));
5093           break;
5094
5095         default:
5096           HALT_UNALLOC;
5097         }
5098       break;
5099     }
5100 }
5101
5102 #define DO_ADDP(FN)                                                     \
5103   do                                                                    \
5104     {                                                                   \
5105       for (i = 0; i < range; i++)                                       \
5106         {                                                               \
5107           aarch64_set_vec_##FN (cpu, vd, i,                             \
5108                                 aarch64_get_vec_##FN (cpu, vn, i * 2)   \
5109                                 + aarch64_get_vec_##FN (cpu, vn, i * 2 + 1)); \
5110           aarch64_set_vec_##FN (cpu, vd, i + range,                     \
5111                                 aarch64_get_vec_##FN (cpu, vm, i * 2)   \
5112                                 + aarch64_get_vec_##FN (cpu, vm, i * 2 + 1)); \
5113         }                                                               \
5114       }                                                                 \
5115     while (0)
5116
5117 static void
5118 do_vec_ADDP (sim_cpu *cpu)
5119 {
5120   /* instr[31]    = 0
5121      instr[30]    = half(0)/full(1)
5122      instr[29,24] = 00 1110
5123      instr[23,22] = size: bytes (00), half (01), word (10), long (11)
5124      instr[21]    = 1
5125      insrt[20,16] = Vm
5126      instr[15,10] = 1011 11
5127      instr[9,5]   = Vn
5128      instr[4,0]   = V dest.  */
5129
5130   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5131   unsigned size = uimm (aarch64_get_instr (cpu), 23, 22);
5132   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5133   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5134   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5135   unsigned i, range;
5136
5137   NYI_assert (29, 24, 0x0E);
5138   NYI_assert (21, 21, 1);
5139   NYI_assert (15, 10, 0x2F);
5140
5141   switch (size)
5142     {
5143     case 0:
5144       range = full ? 8 : 4;
5145       DO_ADDP (u8);
5146       return;
5147
5148     case 1:
5149       range = full ? 4 : 2;
5150       DO_ADDP (u16);
5151       return;
5152
5153     case 2:
5154       range = full ? 2 : 1;
5155       DO_ADDP (u32);
5156       return;
5157
5158     case 3:
5159       if (! full)
5160         HALT_UNALLOC;
5161       range = 1;
5162       DO_ADDP (u64);
5163       return;
5164
5165     default:
5166       HALT_NYI;
5167     }
5168 }
5169
5170 static void
5171 do_vec_UMOV (sim_cpu *cpu)
5172 {
5173   /* instr[31]    = 0
5174      instr[30]    = 32-bit(0)/64-bit(1)
5175      instr[29,21] = 00 1110 000
5176      insrt[20,16] = size & index
5177      instr[15,10] = 0011 11
5178      instr[9,5]   = V source
5179      instr[4,0]   = R dest.  */
5180
5181   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5182   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
5183   unsigned index;
5184
5185   NYI_assert (29, 21, 0x070);
5186   NYI_assert (15, 10, 0x0F);
5187
5188   if (uimm (aarch64_get_instr (cpu), 16, 16))
5189     {
5190       /* Byte transfer.  */
5191       index = uimm (aarch64_get_instr (cpu), 20, 17);
5192       aarch64_set_reg_u64 (cpu, rd, NO_SP,
5193                            aarch64_get_vec_u8 (cpu, vs, index));
5194     }
5195   else if (uimm (aarch64_get_instr (cpu), 17, 17))
5196     {
5197       index = uimm (aarch64_get_instr (cpu), 20, 18);
5198       aarch64_set_reg_u64 (cpu, rd, NO_SP,
5199                            aarch64_get_vec_u16 (cpu, vs, index));
5200     }
5201   else if (uimm (aarch64_get_instr (cpu), 18, 18))
5202     {
5203       index = uimm (aarch64_get_instr (cpu), 20, 19);
5204       aarch64_set_reg_u64 (cpu, rd, NO_SP,
5205                            aarch64_get_vec_u32 (cpu, vs, index));
5206     }
5207   else
5208     {
5209       if (uimm (aarch64_get_instr (cpu), 30, 30) != 1)
5210         HALT_UNALLOC;
5211
5212       index = uimm (aarch64_get_instr (cpu), 20, 20);
5213       aarch64_set_reg_u64 (cpu, rd, NO_SP,
5214                            aarch64_get_vec_u64 (cpu, vs, index));
5215     }
5216 }
5217
5218 static void
5219 do_vec_FABS (sim_cpu *cpu)
5220 {
5221   /* instr[31]    = 0
5222      instr[30]    = half(0)/full(1)
5223      instr[29,23] = 00 1110 1
5224      instr[22]    = float(0)/double(1)
5225      instr[21,16] = 10 0000
5226      instr[15,10] = 1111 10
5227      instr[9,5]   = Vn
5228      instr[4,0]   = Vd.  */
5229
5230   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5231   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5232   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5233   unsigned i;
5234
5235   NYI_assert (29, 23, 0x1D);
5236   NYI_assert (21, 10, 0x83E);
5237
5238   if (uimm (aarch64_get_instr (cpu), 22, 22))
5239     {
5240       if (! full)
5241         HALT_NYI;
5242
5243       for (i = 0; i < 2; i++)
5244         aarch64_set_vec_double (cpu, vd, i,
5245                                 fabs (aarch64_get_vec_double (cpu, vn, i)));
5246     }
5247   else
5248     {
5249       for (i = 0; i < (full ? 4 : 2); i++)
5250         aarch64_set_vec_float (cpu, vd, i,
5251                                fabsf (aarch64_get_vec_float (cpu, vn, i)));
5252     }
5253 }
5254
5255 static void
5256 do_vec_FCVTZS (sim_cpu *cpu)
5257 {
5258   /* instr[31]    = 0
5259      instr[30]    = half (0) / all (1)
5260      instr[29,23] = 00 1110 1
5261      instr[22]    = single (0) / double (1)
5262      instr[21,10] = 10 0001 1011 10
5263      instr[9,5]   = Rn
5264      instr[4,0]   = Rd.  */
5265
5266   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
5267   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
5268   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5269   unsigned i;
5270
5271   NYI_assert (31, 31, 0);
5272   NYI_assert (29, 23, 0x1D);
5273   NYI_assert (21, 10, 0x86E);
5274
5275   if (uimm (aarch64_get_instr (cpu), 22, 22))
5276     {
5277       if (! full)
5278         HALT_UNALLOC;
5279
5280       for (i = 0; i < 2; i++)
5281         aarch64_set_vec_s64 (cpu, rd, i,
5282                              (int64_t) aarch64_get_vec_double (cpu, rn, i));
5283     }
5284   else
5285     for (i = 0; i < (full ? 4 : 2); i++)
5286       aarch64_set_vec_s32 (cpu, rd, i,
5287                            (int32_t) aarch64_get_vec_float (cpu, rn, i));
5288 }
5289
5290 static void
5291 do_vec_op1 (sim_cpu *cpu)
5292 {
5293   /* instr[31]    = 0
5294      instr[30]    = half/full
5295      instr[29,24] = 00 1110
5296      instr[23,21] = ???
5297      instr[20,16] = Vm
5298      instr[15,10] = sub-opcode
5299      instr[9,5]   = Vn
5300      instr[4,0]   = Vd  */
5301   NYI_assert (29, 24, 0x0E);
5302
5303   if (uimm (aarch64_get_instr (cpu), 21, 21) == 0)
5304     {
5305       if (uimm (aarch64_get_instr (cpu), 23, 22) == 0)
5306         {
5307           if (uimm (aarch64_get_instr (cpu), 30, 30) == 1
5308               && uimm (aarch64_get_instr (cpu), 17, 14) == 0
5309               && uimm (aarch64_get_instr (cpu), 12, 10) == 7)
5310             return do_vec_ins_2 (cpu);
5311
5312           switch (uimm (aarch64_get_instr (cpu), 15, 10))
5313             {
5314             case 0x01: do_vec_DUP_vector_into_vector (cpu); return;
5315             case 0x03: do_vec_DUP_scalar_into_vector (cpu); return;
5316             case 0x07: do_vec_INS (cpu); return;
5317             case 0x0A: do_vec_TRN (cpu); return;
5318
5319             case 0x0F:
5320               if (uimm (aarch64_get_instr (cpu), 17, 16) == 0)
5321                 {
5322                   do_vec_MOV_into_scalar (cpu);
5323                   return;
5324                 }
5325               break;
5326
5327             case 0x00:
5328             case 0x08:
5329             case 0x10:
5330             case 0x18:
5331               do_vec_TBL (cpu); return;
5332
5333             case 0x06:
5334             case 0x16:
5335               do_vec_UZP (cpu); return;
5336
5337             case 0x0E:
5338             case 0x1E:
5339               do_vec_ZIP (cpu); return;
5340
5341             default:
5342               HALT_NYI;
5343             }
5344         }
5345
5346       switch (uimm (aarch64_get_instr (cpu), 13, 10))
5347         {
5348         case 0x6: do_vec_UZP (cpu); return;
5349         case 0xE: do_vec_ZIP (cpu); return;
5350         case 0xA: do_vec_TRN (cpu); return;
5351         case 0xF: do_vec_UMOV (cpu); return;
5352         default:  HALT_NYI;
5353         }
5354     }
5355
5356   switch (uimm (aarch64_get_instr (cpu), 15, 10))
5357     {
5358     case 0x07:
5359       switch (uimm (aarch64_get_instr (cpu), 23, 21))
5360         {
5361         case 1: do_vec_AND (cpu); return;
5362         case 3: do_vec_BIC (cpu); return;
5363         case 5: do_vec_ORR (cpu); return;
5364         case 7: do_vec_ORN (cpu); return;
5365         default: HALT_NYI;
5366         }
5367
5368     case 0x08: do_vec_sub_long (cpu); return;
5369     case 0x0a: do_vec_XTN (cpu); return;
5370     case 0x11: do_vec_SSHL (cpu); return;
5371     case 0x19: do_vec_max (cpu); return;
5372     case 0x1B: do_vec_min (cpu); return;
5373     case 0x21: do_vec_add (cpu); return;
5374     case 0x25: do_vec_MLA (cpu); return;
5375     case 0x27: do_vec_mul (cpu); return;
5376     case 0x2F: do_vec_ADDP (cpu); return;
5377     case 0x30: do_vec_mull (cpu); return;
5378     case 0x33: do_vec_FMLA (cpu); return;
5379     case 0x35: do_vec_fadd (cpu); return;
5380
5381     case 0x2E:
5382       switch (uimm (aarch64_get_instr (cpu), 20, 16))
5383         {
5384         case 0x00: do_vec_ABS (cpu); return;
5385         case 0x01: do_vec_FCVTZS (cpu); return;
5386         case 0x11: do_vec_ADDV (cpu); return;
5387         default: HALT_NYI;
5388         }
5389
5390     case 0x31:
5391     case 0x3B:
5392       do_vec_Fminmax (cpu); return;
5393
5394     case 0x0D:
5395     case 0x0F:
5396     case 0x22:
5397     case 0x23:
5398     case 0x26:
5399     case 0x2A:
5400     case 0x32:
5401     case 0x36:
5402     case 0x39:
5403     case 0x3A:
5404       do_vec_compare (cpu); return;
5405
5406     case 0x3E:
5407       do_vec_FABS (cpu); return;
5408
5409     default:
5410       HALT_NYI;
5411     }
5412 }
5413
5414 static void
5415 do_vec_xtl (sim_cpu *cpu)
5416 {
5417   /* instr[31]    = 0
5418      instr[30,29] = SXTL (00), UXTL (01), SXTL2 (10), UXTL2 (11)
5419      instr[28,22] = 0 1111 00
5420      instr[21,16] = size & shift (USHLL, SSHLL, USHLL2, SSHLL2)
5421      instr[15,10] = 1010 01
5422      instr[9,5]   = V source
5423      instr[4,0]   = V dest.  */
5424
5425   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5426   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5427   unsigned i, shift, bias = 0;
5428
5429   NYI_assert (28, 22, 0x3C);
5430   NYI_assert (15, 10, 0x29);
5431
5432   switch (uimm (aarch64_get_instr (cpu), 30, 29))
5433     {
5434     case 2: /* SXTL2, SSHLL2.  */
5435       bias = 2;
5436     case 0: /* SXTL, SSHLL.  */
5437       if (uimm (aarch64_get_instr (cpu), 21, 21))
5438         {
5439           shift = uimm (aarch64_get_instr (cpu), 20, 16);
5440           aarch64_set_vec_s64
5441             (cpu, vd, 0, aarch64_get_vec_s32 (cpu, vs, bias) << shift);
5442           aarch64_set_vec_s64
5443             (cpu, vd, 1, aarch64_get_vec_s32 (cpu, vs, bias + 1) << shift);
5444         }
5445       else if (uimm (aarch64_get_instr (cpu), 20, 20))
5446         {
5447           shift = uimm (aarch64_get_instr (cpu), 19, 16);
5448           bias *= 2;
5449           for (i = 0; i < 4; i++)
5450             aarch64_set_vec_s32
5451               (cpu, vd, i, aarch64_get_vec_s16 (cpu, vs, i + bias) << shift);
5452         }
5453       else
5454         {
5455           NYI_assert (19, 19, 1);
5456
5457           shift = uimm (aarch64_get_instr (cpu), 18, 16);
5458           bias *= 3;
5459           for (i = 0; i < 8; i++)
5460             aarch64_set_vec_s16
5461               (cpu, vd, i, aarch64_get_vec_s8 (cpu, vs, i + bias) << shift);
5462         }
5463       return;
5464
5465     case 3: /* UXTL2, USHLL2.  */
5466       bias = 2;
5467     case 1: /* UXTL, USHLL.  */
5468       if (uimm (aarch64_get_instr (cpu), 21, 21))
5469         {
5470           shift = uimm (aarch64_get_instr (cpu), 20, 16);
5471           aarch64_set_vec_u64
5472             (cpu, vd, 0, aarch64_get_vec_u32 (cpu, vs, bias) << shift);
5473           aarch64_set_vec_u64
5474             (cpu, vd, 1, aarch64_get_vec_u32 (cpu, vs, bias + 1) << shift);
5475         }
5476       else if (uimm (aarch64_get_instr (cpu), 20, 20))
5477         {
5478           shift = uimm (aarch64_get_instr (cpu), 19, 16);
5479           bias *= 2;
5480           for (i = 0; i < 4; i++)
5481             aarch64_set_vec_u32
5482               (cpu, vd, i, aarch64_get_vec_u16 (cpu, vs, i + bias) << shift);
5483         }
5484       else
5485         {
5486           NYI_assert (19, 19, 1);
5487
5488           shift = uimm (aarch64_get_instr (cpu), 18, 16);
5489           bias *= 3;
5490           for (i = 0; i < 8; i++)
5491             aarch64_set_vec_u16
5492               (cpu, vd, i, aarch64_get_vec_u8 (cpu, vs, i + bias) << shift);
5493         }
5494       return;
5495
5496     default:
5497       HALT_NYI;
5498     }
5499 }
5500
5501 static void
5502 do_vec_SHL (sim_cpu *cpu)
5503 {
5504   /* instr [31]    = 0
5505      instr [30]    = half(0)/full(1)
5506      instr [29,23] = 001 1110
5507      instr [22,16] = size and shift amount
5508      instr [15,10] = 01 0101
5509      instr [9, 5]  = Vs
5510      instr [4, 0]  = Vd.  */
5511
5512   int shift;
5513   int full = uimm (aarch64_get_instr (cpu), 30, 30);
5514   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5515   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5516   unsigned i;
5517
5518   NYI_assert (29, 23, 0x1E);
5519   NYI_assert (15, 10, 0x15);
5520
5521   if (uimm (aarch64_get_instr (cpu), 22, 22))
5522     {
5523       shift = uimm (aarch64_get_instr (cpu), 21, 16) - 1;
5524
5525       if (full == 0)
5526         HALT_UNALLOC;
5527
5528       for (i = 0; i < 2; i++)
5529         {
5530           uint64_t val = aarch64_get_vec_u64 (cpu, vs, i);
5531           aarch64_set_vec_u64 (cpu, vd, i, val << shift);
5532         }
5533
5534       return;
5535     }
5536
5537   if (uimm (aarch64_get_instr (cpu), 21, 21))
5538     {
5539       shift = uimm (aarch64_get_instr (cpu), 20, 16) - 1;
5540
5541       for (i = 0; i < (full ? 4 : 2); i++)
5542         {
5543           uint32_t val = aarch64_get_vec_u32 (cpu, vs, i);
5544           aarch64_set_vec_u32 (cpu, vd, i, val << shift);
5545         }
5546
5547       return;
5548     }
5549
5550   if (uimm (aarch64_get_instr (cpu), 20, 20))
5551     {
5552       shift = uimm (aarch64_get_instr (cpu), 19, 16) - 1;
5553
5554       for (i = 0; i < (full ? 8 : 4); i++)
5555         {
5556           uint16_t val = aarch64_get_vec_u16 (cpu, vs, i);
5557           aarch64_set_vec_u16 (cpu, vd, i, val << shift);
5558         }
5559
5560       return;
5561     }
5562
5563   if (uimm (aarch64_get_instr (cpu), 19, 19) == 0)
5564     HALT_UNALLOC;
5565
5566   shift = uimm (aarch64_get_instr (cpu), 18, 16) - 1;
5567
5568   for (i = 0; i < (full ? 16 : 8); i++)
5569     {
5570       uint8_t val = aarch64_get_vec_u8 (cpu, vs, i);
5571       aarch64_set_vec_u8 (cpu, vd, i, val << shift);
5572     }
5573 }
5574
5575 static void
5576 do_vec_SSHR_USHR (sim_cpu *cpu)
5577 {
5578   /* instr [31]    = 0
5579      instr [30]    = half(0)/full(1)
5580      instr [29]    = signed(0)/unsigned(1)
5581      instr [28,23] = 01 1110
5582      instr [22,16] = size and shift amount
5583      instr [15,10] = 0000 01
5584      instr [9, 5]  = Vs
5585      instr [4, 0]  = Vd.  */
5586
5587   int shift;
5588   int full = uimm (aarch64_get_instr (cpu), 30, 30);
5589   int sign = uimm (aarch64_get_instr (cpu), 29, 29);
5590   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5591   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5592   unsigned i;
5593
5594   NYI_assert (28, 23, 0x1E);
5595   NYI_assert (15, 10, 0x01);
5596
5597   if (uimm (aarch64_get_instr (cpu), 22, 22))
5598     {
5599       shift = uimm (aarch64_get_instr (cpu), 21, 16);
5600
5601       if (full == 0)
5602         HALT_UNALLOC;
5603
5604       if (sign)
5605         for (i = 0; i < 2; i++)
5606           {
5607             int64_t val = aarch64_get_vec_s64 (cpu, vs, i);
5608             aarch64_set_vec_s64 (cpu, vd, i, val >> shift);
5609           }
5610       else
5611         for (i = 0; i < 2; i++)
5612           {
5613             uint64_t val = aarch64_get_vec_u64 (cpu, vs, i);
5614             aarch64_set_vec_u64 (cpu, vd, i, val >> shift);
5615           }
5616
5617       return;
5618     }
5619
5620   if (uimm (aarch64_get_instr (cpu), 21, 21))
5621     {
5622       shift = uimm (aarch64_get_instr (cpu), 20, 16);
5623
5624       if (sign)
5625         for (i = 0; i < (full ? 4 : 2); i++)
5626           {
5627             int32_t val = aarch64_get_vec_s32 (cpu, vs, i);
5628             aarch64_set_vec_s32 (cpu, vd, i, val >> shift);
5629           }
5630       else
5631         for (i = 0; i < (full ? 4 : 2); i++)
5632           {
5633             uint32_t val = aarch64_get_vec_u32 (cpu, vs, i);
5634             aarch64_set_vec_u32 (cpu, vd, i, val >> shift);
5635           }
5636
5637       return;
5638     }
5639
5640   if (uimm (aarch64_get_instr (cpu), 20, 20))
5641     {
5642       shift = uimm (aarch64_get_instr (cpu), 19, 16);
5643
5644       if (sign)
5645         for (i = 0; i < (full ? 8 : 4); i++)
5646           {
5647             int16_t val = aarch64_get_vec_s16 (cpu, vs, i);
5648             aarch64_set_vec_s16 (cpu, vd, i, val >> shift);
5649           }
5650       else
5651         for (i = 0; i < (full ? 8 : 4); i++)
5652           {
5653             uint16_t val = aarch64_get_vec_u16 (cpu, vs, i);
5654             aarch64_set_vec_u16 (cpu, vd, i, val >> shift);
5655           }
5656
5657       return;
5658     }
5659
5660   if (uimm (aarch64_get_instr (cpu), 19, 19) == 0)
5661     HALT_UNALLOC;
5662
5663   shift = uimm (aarch64_get_instr (cpu), 18, 16);
5664
5665   if (sign)
5666     for (i = 0; i < (full ? 16 : 8); i++)
5667       {
5668         int8_t val = aarch64_get_vec_s8 (cpu, vs, i);
5669         aarch64_set_vec_s8 (cpu, vd, i, val >> shift);
5670       }
5671   else
5672     for (i = 0; i < (full ? 16 : 8); i++)
5673       {
5674         uint8_t val = aarch64_get_vec_u8 (cpu, vs, i);
5675         aarch64_set_vec_u8 (cpu, vd, i, val >> shift);
5676       }
5677 }
5678
5679 static void
5680 do_vec_op2 (sim_cpu *cpu)
5681 {
5682   /* instr[31]    = 0
5683      instr[30]    = half/full
5684      instr[29,24] = 00 1111
5685      instr[23]    = ?
5686      instr[22,16] = element size & index
5687      instr[15,10] = sub-opcode
5688      instr[9,5]   = Vm
5689      instr[4.0]   = Vd  */
5690
5691   NYI_assert (29, 24, 0x0F);
5692
5693   if (uimm (aarch64_get_instr (cpu), 23, 23) != 0)
5694     HALT_NYI;
5695
5696   switch (uimm (aarch64_get_instr (cpu), 15, 10))
5697     {
5698     case 0x01: do_vec_SSHR_USHR (cpu); return;
5699     case 0x15: do_vec_SHL (cpu); return;
5700     case 0x29: do_vec_xtl (cpu); return;
5701     default:   HALT_NYI;
5702     }
5703 }
5704
5705 static void
5706 do_vec_neg (sim_cpu *cpu)
5707 {
5708   /* instr[31]    = 0
5709      instr[30]    = full(1)/half(0)
5710      instr[29,24] = 10 1110
5711      instr[23,22] = size: byte(00), half (01), word (10), long (11)
5712      instr[21,10] = 1000 0010 1110
5713      instr[9,5]   = Vs
5714      instr[4,0]   = Vd  */
5715
5716   int    full = uimm (aarch64_get_instr (cpu), 30, 30);
5717   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5718   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5719   unsigned i;
5720
5721   NYI_assert (29, 24, 0x2E);
5722   NYI_assert (21, 10, 0x82E);
5723
5724   switch (uimm (aarch64_get_instr (cpu), 23, 22))
5725     {
5726     case 0:
5727       for (i = 0; i < (full ? 16 : 8); i++)
5728         aarch64_set_vec_s8 (cpu, vd, i, - aarch64_get_vec_s8 (cpu, vs, i));
5729       return;
5730
5731     case 1:
5732       for (i = 0; i < (full ? 8 : 4); i++)
5733         aarch64_set_vec_s16 (cpu, vd, i, - aarch64_get_vec_s16 (cpu, vs, i));
5734       return;
5735
5736     case 2:
5737       for (i = 0; i < (full ? 4 : 2); i++)
5738         aarch64_set_vec_s32 (cpu, vd, i, - aarch64_get_vec_s32 (cpu, vs, i));
5739       return;
5740
5741     case 3:
5742       if (! full)
5743         HALT_NYI;
5744       for (i = 0; i < 2; i++)
5745         aarch64_set_vec_s64 (cpu, vd, i, - aarch64_get_vec_s64 (cpu, vs, i));
5746       return;
5747
5748     default:
5749       HALT_UNREACHABLE;
5750     }
5751 }
5752
5753 static void
5754 do_vec_sqrt (sim_cpu *cpu)
5755 {
5756   /* instr[31]    = 0
5757      instr[30]    = full(1)/half(0)
5758      instr[29,23] = 101 1101
5759      instr[22]    = single(0)/double(1)
5760      instr[21,10] = 1000 0111 1110
5761      instr[9,5]   = Vs
5762      instr[4,0]   = Vd.  */
5763
5764   int    full = uimm (aarch64_get_instr (cpu), 30, 30);
5765   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5766   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5767   unsigned i;
5768
5769   NYI_assert (29, 23, 0x5B);
5770   NYI_assert (21, 10, 0x87E);
5771
5772   if (uimm (aarch64_get_instr (cpu), 22, 22) == 0)
5773     for (i = 0; i < (full ? 4 : 2); i++)
5774       aarch64_set_vec_float (cpu, vd, i,
5775                              sqrtf (aarch64_get_vec_float (cpu, vs, i)));
5776   else
5777     for (i = 0; i < 2; i++)
5778       aarch64_set_vec_double (cpu, vd, i,
5779                               sqrt (aarch64_get_vec_double (cpu, vs, i)));
5780 }
5781
5782 static void
5783 do_vec_mls_indexed (sim_cpu *cpu)
5784 {
5785   /* instr[31]       = 0
5786      instr[30]       = half(0)/full(1)
5787      instr[29,24]    = 10 1111
5788      instr[23,22]    = 16-bit(01)/32-bit(10)
5789      instr[21,20+11] = index (if 16-bit)
5790      instr[21+11]    = index (if 32-bit)
5791      instr[20,16]    = Vm
5792      instr[15,12]    = 0100
5793      instr[11]       = part of index
5794      instr[10]       = 0
5795      instr[9,5]      = Vs
5796      instr[4,0]      = Vd.  */
5797
5798   int    full = uimm (aarch64_get_instr (cpu), 30, 30);
5799   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5800   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5801   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5802   unsigned i;
5803
5804   NYI_assert (15, 12, 4);
5805   NYI_assert (10, 10, 0);
5806
5807   switch (uimm (aarch64_get_instr (cpu), 23, 22))
5808     {
5809     case 1:
5810       {
5811         unsigned elem;
5812         uint32_t val;
5813
5814         if (vm > 15)
5815           HALT_NYI;
5816
5817         elem = (uimm (aarch64_get_instr (cpu), 21, 20) << 1)
5818           | uimm (aarch64_get_instr (cpu), 11, 11);
5819         val = aarch64_get_vec_u16 (cpu, vm, elem);
5820
5821         for (i = 0; i < (full ? 8 : 4); i++)
5822           aarch64_set_vec_u32 (cpu, vd, i,
5823                                aarch64_get_vec_u32 (cpu, vd, i) -
5824                                (aarch64_get_vec_u32 (cpu, vs, i) * val));
5825         return;
5826       }
5827
5828     case 2:
5829       {
5830         unsigned elem = (uimm (aarch64_get_instr (cpu), 21, 21) << 1)
5831           | uimm (aarch64_get_instr (cpu), 11, 11);
5832         uint64_t val = aarch64_get_vec_u32 (cpu, vm, elem);
5833
5834         for (i = 0; i < (full ? 4 : 2); i++)
5835           aarch64_set_vec_u64 (cpu, vd, i,
5836                                aarch64_get_vec_u64 (cpu, vd, i) -
5837                                (aarch64_get_vec_u64 (cpu, vs, i) * val));
5838         return;
5839       }
5840
5841     case 0:
5842     case 3:
5843     default:
5844       HALT_NYI;
5845     }
5846 }
5847
5848 static void
5849 do_vec_SUB (sim_cpu *cpu)
5850 {
5851   /* instr [31]    = 0
5852      instr [30]    = half(0)/full(1)
5853      instr [29,24] = 10 1110
5854      instr [23,22] = size: byte(00, half(01), word (10), long (11)
5855      instr [21]    = 1
5856      instr [20,16] = Vm
5857      instr [15,10] = 10 0001
5858      instr [9, 5]  = Vn
5859      instr [4, 0]  = Vd.  */
5860
5861   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5862   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5863   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5864   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5865   unsigned i;
5866
5867   NYI_assert (29, 24, 0x2E);
5868   NYI_assert (21, 21, 1);
5869   NYI_assert (15, 10, 0x21);
5870
5871   switch (uimm (aarch64_get_instr (cpu), 23, 22))
5872     {
5873     case 0:
5874       for (i = 0; i < (full ? 16 : 8); i++)
5875         aarch64_set_vec_s8 (cpu, vd, i,
5876                             aarch64_get_vec_s8 (cpu, vn, i)
5877                             - aarch64_get_vec_s8 (cpu, vm, i));
5878       return;
5879
5880     case 1:
5881       for (i = 0; i < (full ? 8 : 4); i++)
5882         aarch64_set_vec_s16 (cpu, vd, i,
5883                              aarch64_get_vec_s16 (cpu, vn, i)
5884                              - aarch64_get_vec_s16 (cpu, vm, i));
5885       return;
5886
5887     case 2:
5888       for (i = 0; i < (full ? 4 : 2); i++)
5889         aarch64_set_vec_s32 (cpu, vd, i,
5890                              aarch64_get_vec_s32 (cpu, vn, i)
5891                              - aarch64_get_vec_s32 (cpu, vm, i));
5892       return;
5893
5894     case 3:
5895       if (full == 0)
5896         HALT_UNALLOC;
5897
5898       for (i = 0; i < 2; i++)
5899         aarch64_set_vec_s64 (cpu, vd, i,
5900                              aarch64_get_vec_s64 (cpu, vn, i)
5901                              - aarch64_get_vec_s64 (cpu, vm, i));
5902       return;
5903
5904     default:
5905       HALT_UNREACHABLE;
5906     }
5907 }
5908
5909 static void
5910 do_vec_MLS (sim_cpu *cpu)
5911 {
5912   /* instr [31]    = 0
5913      instr [30]    = half(0)/full(1)
5914      instr [29,24] = 10 1110
5915      instr [23,22] = size: byte(00, half(01), word (10)
5916      instr [21]    = 1
5917      instr [20,16] = Vm
5918      instr [15,10] = 10 0101
5919      instr [9, 5]  = Vn
5920      instr [4, 0]  = Vd.  */
5921
5922   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5923   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5924   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5925   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5926   unsigned i;
5927
5928   NYI_assert (29, 24, 0x2E);
5929   NYI_assert (21, 21, 1);
5930   NYI_assert (15, 10, 0x25);
5931
5932   switch (uimm (aarch64_get_instr (cpu), 23, 22))
5933     {
5934     case 0:
5935       for (i = 0; i < (full ? 16 : 8); i++)
5936         aarch64_set_vec_u8 (cpu, vd, i,
5937                             (aarch64_get_vec_u8 (cpu, vn, i)
5938                              * aarch64_get_vec_u8 (cpu, vm, i))
5939                             - aarch64_get_vec_u8 (cpu, vd, i));
5940       return;
5941
5942     case 1:
5943       for (i = 0; i < (full ? 8 : 4); i++)
5944         aarch64_set_vec_u16 (cpu, vd, i,
5945                              (aarch64_get_vec_u16 (cpu, vn, i)
5946                               * aarch64_get_vec_u16 (cpu, vm, i))
5947                              - aarch64_get_vec_u16 (cpu, vd, i));
5948       return;
5949
5950     case 2:
5951       for (i = 0; i < (full ? 4 : 2); i++)
5952         aarch64_set_vec_u32 (cpu, vd, i,
5953                              (aarch64_get_vec_u32 (cpu, vn, i)
5954                               * aarch64_get_vec_u32 (cpu, vm, i))
5955                              - aarch64_get_vec_u32 (cpu, vd, i));
5956       return;
5957
5958     default:
5959       HALT_UNALLOC;
5960     }
5961 }
5962
5963 static void
5964 do_vec_FDIV (sim_cpu *cpu)
5965 {
5966   /* instr [31]    = 0
5967      instr [30]    = half(0)/full(1)
5968      instr [29,23] = 10 1110 0
5969      instr [22]    = float()/double(1)
5970      instr [21]    = 1
5971      instr [20,16] = Vm
5972      instr [15,10] = 1111 11
5973      instr [9, 5]  = Vn
5974      instr [4, 0]  = Vd.  */
5975
5976   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5977   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5978   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5979   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5980   unsigned i;
5981
5982   NYI_assert (29, 23, 0x5C);
5983   NYI_assert (21, 21, 1);
5984   NYI_assert (15, 10, 0x3F);
5985
5986   if (uimm (aarch64_get_instr (cpu), 22, 22))
5987     {
5988       if (! full)
5989         HALT_UNALLOC;
5990
5991       for (i = 0; i < 2; i++)
5992         aarch64_set_vec_double (cpu, vd, i,
5993                                 aarch64_get_vec_double (cpu, vn, i)
5994                                 / aarch64_get_vec_double (cpu, vm, i));
5995     }
5996   else
5997     for (i = 0; i < (full ? 4 : 2); i++)
5998       aarch64_set_vec_float (cpu, vd, i,
5999                              aarch64_get_vec_float (cpu, vn, i)
6000                              / aarch64_get_vec_float (cpu, vm, i));
6001 }
6002
6003 static void
6004 do_vec_FMUL (sim_cpu *cpu)
6005 {
6006   /* instr [31]    = 0
6007      instr [30]    = half(0)/full(1)
6008      instr [29,23] = 10 1110 0
6009      instr [22]    = float(0)/double(1)
6010      instr [21]    = 1
6011      instr [20,16] = Vm
6012      instr [15,10] = 1101 11
6013      instr [9, 5]  = Vn
6014      instr [4, 0]  = Vd.  */
6015
6016   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6017   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
6018   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6019   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6020   unsigned i;
6021
6022   NYI_assert (29, 23, 0x5C);
6023   NYI_assert (21, 21, 1);
6024   NYI_assert (15, 10, 0x37);
6025
6026   if (uimm (aarch64_get_instr (cpu), 22, 22))
6027     {
6028       if (! full)
6029         HALT_UNALLOC;
6030
6031       for (i = 0; i < 2; i++)
6032         aarch64_set_vec_double (cpu, vd, i,
6033                                 aarch64_get_vec_double (cpu, vn, i)
6034                                 * aarch64_get_vec_double (cpu, vm, i));
6035     }
6036   else
6037     for (i = 0; i < (full ? 4 : 2); i++)
6038       aarch64_set_vec_float (cpu, vd, i,
6039                              aarch64_get_vec_float (cpu, vn, i)
6040                              * aarch64_get_vec_float (cpu, vm, i));
6041 }
6042
6043 static void
6044 do_vec_FADDP (sim_cpu *cpu)
6045 {
6046   /* instr [31]    = 0
6047      instr [30]    = half(0)/full(1)
6048      instr [29,23] = 10 1110 0
6049      instr [22]    = float(0)/double(1)
6050      instr [21]    = 1
6051      instr [20,16] = Vm
6052      instr [15,10] = 1101 01
6053      instr [9, 5]  = Vn
6054      instr [4, 0]  = Vd.  */
6055
6056   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6057   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
6058   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6059   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6060
6061   NYI_assert (29, 23, 0x5C);
6062   NYI_assert (21, 21, 1);
6063   NYI_assert (15, 10, 0x35);
6064
6065   if (uimm (aarch64_get_instr (cpu), 22, 22))
6066     {
6067       if (! full)
6068         HALT_UNALLOC;
6069
6070       aarch64_set_vec_double (cpu, vd, 0, aarch64_get_vec_double (cpu, vn, 0)
6071                               + aarch64_get_vec_double (cpu, vn, 1));
6072       aarch64_set_vec_double (cpu, vd, 1, aarch64_get_vec_double (cpu, vm, 0)
6073                               + aarch64_get_vec_double (cpu, vm, 1));
6074     }
6075   else
6076     {
6077       aarch64_set_vec_float (cpu, vd, 0, aarch64_get_vec_float (cpu, vn, 0)
6078                              + aarch64_get_vec_float (cpu, vn, 1));
6079       if (full)
6080         aarch64_set_vec_float (cpu, vd, 1, aarch64_get_vec_float (cpu, vn, 2)
6081                                + aarch64_get_vec_float (cpu, vn, 3));
6082       aarch64_set_vec_float (cpu, vd, full ? 2 : 1,
6083                              aarch64_get_vec_float (cpu, vm, 0)
6084                              + aarch64_get_vec_float (cpu, vm, 1));
6085       if (full)
6086         aarch64_set_vec_float (cpu, vd, 3,
6087                                aarch64_get_vec_float (cpu, vm, 2)
6088                                + aarch64_get_vec_float (cpu, vm, 3));
6089     }
6090 }
6091
6092 static void
6093 do_vec_FSQRT (sim_cpu *cpu)
6094 {
6095   /* instr[31]    = 0
6096      instr[30]    = half(0)/full(1)
6097      instr[29,23] = 10 1110 1
6098      instr[22]    = single(0)/double(1)
6099      instr[21,10] = 10 0001 1111 10
6100      instr[9,5]   = Vsrc
6101      instr[4,0]   = Vdest.  */
6102
6103   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6104   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6105   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6106   int i;
6107
6108   NYI_assert (29, 23, 0x5D);
6109   NYI_assert (21, 10, 0x87E);
6110
6111   if (uimm (aarch64_get_instr (cpu), 22, 22))
6112     {
6113       if (! full)
6114         HALT_UNALLOC;
6115
6116       for (i = 0; i < 2; i++)
6117         aarch64_set_vec_double (cpu, vd, i,
6118                                 sqrt (aarch64_get_vec_double (cpu, vn, i)));
6119     }
6120   else
6121     {
6122       for (i = 0; i < (full ? 4 : 2); i++)
6123         aarch64_set_vec_float (cpu, vd, i,
6124                                sqrtf (aarch64_get_vec_float (cpu, vn, i)));
6125     }
6126 }
6127
6128 static void
6129 do_vec_FNEG (sim_cpu *cpu)
6130 {
6131   /* instr[31]    = 0
6132      instr[30]    = half (0)/full (1)
6133      instr[29,23] = 10 1110 1
6134      instr[22]    = single (0)/double (1)
6135      instr[21,10] = 10 0000 1111 10
6136      instr[9,5]   = Vsrc
6137      instr[4,0]   = Vdest.  */
6138
6139   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6140   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6141   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6142   int i;
6143
6144   NYI_assert (29, 23, 0x5D);
6145   NYI_assert (21, 10, 0x83E);
6146
6147   if (uimm (aarch64_get_instr (cpu), 22, 22))
6148     {
6149       if (! full)
6150         HALT_UNALLOC;
6151
6152       for (i = 0; i < 2; i++)
6153         aarch64_set_vec_double (cpu, vd, i,
6154                                 - aarch64_get_vec_double (cpu, vn, i));
6155     }
6156   else
6157     {
6158       for (i = 0; i < (full ? 4 : 2); i++)
6159         aarch64_set_vec_float (cpu, vd, i,
6160                                - aarch64_get_vec_float (cpu, vn, i));
6161     }
6162 }
6163
6164 static void
6165 do_vec_NOT (sim_cpu *cpu)
6166 {
6167   /* instr[31]    = 0
6168      instr[30]    = half (0)/full (1)
6169      instr[29,21] = 10 1110 001
6170      instr[20,16] = 0 0000
6171      instr[15,10] = 0101 10
6172      instr[9,5]   = Vn
6173      instr[4.0]   = Vd.  */
6174
6175   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6176   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6177   unsigned i;
6178   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
6179
6180   NYI_assert (29, 10, 0xB8816);
6181
6182   for (i = 0; i < (full ? 16 : 8); i++)
6183     aarch64_set_vec_u8 (cpu, vd, i, ~ aarch64_get_vec_u8 (cpu, vn, i));
6184 }
6185
6186 static void
6187 do_vec_MOV_element (sim_cpu *cpu)
6188 {
6189   /* instr[31,21] = 0110 1110 000
6190      instr[20,16] = size & dest index
6191      instr[15]    = 0
6192      instr[14,11] = source index
6193      instr[10]    = 1
6194      instr[9,5]   = Vs
6195      instr[4.0]   = Vd.  */
6196
6197   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
6198   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6199   unsigned src_index;
6200   unsigned dst_index;
6201
6202   NYI_assert (31, 21, 0x370);
6203   NYI_assert (15, 15, 0);
6204   NYI_assert (10, 10, 1);
6205
6206   if (uimm (aarch64_get_instr (cpu), 16, 16))
6207     {
6208       /* Move a byte.  */
6209       src_index = uimm (aarch64_get_instr (cpu), 14, 11);
6210       dst_index = uimm (aarch64_get_instr (cpu), 20, 17);
6211       aarch64_set_vec_u8 (cpu, vd, dst_index,
6212                           aarch64_get_vec_u8 (cpu, vs, src_index));
6213     }
6214   else if (uimm (aarch64_get_instr (cpu), 17, 17))
6215     {
6216       /* Move 16-bits.  */
6217       NYI_assert (11, 11, 0);
6218       src_index = uimm (aarch64_get_instr (cpu), 14, 12);
6219       dst_index = uimm (aarch64_get_instr (cpu), 20, 18);
6220       aarch64_set_vec_u16 (cpu, vd, dst_index,
6221                            aarch64_get_vec_u16 (cpu, vs, src_index));
6222     }
6223   else if (uimm (aarch64_get_instr (cpu), 18, 18))
6224     {
6225       /* Move 32-bits.  */
6226       NYI_assert (12, 11, 0);
6227       src_index = uimm (aarch64_get_instr (cpu), 14, 13);
6228       dst_index = uimm (aarch64_get_instr (cpu), 20, 19);
6229       aarch64_set_vec_u32 (cpu, vd, dst_index,
6230                            aarch64_get_vec_u32 (cpu, vs, src_index));
6231     }
6232   else
6233     {
6234       NYI_assert (19, 19, 1);
6235       NYI_assert (13, 11, 0);
6236       src_index = uimm (aarch64_get_instr (cpu), 14, 14);
6237       dst_index = uimm (aarch64_get_instr (cpu), 20, 20);
6238       aarch64_set_vec_u64 (cpu, vd, dst_index,
6239                            aarch64_get_vec_u64 (cpu, vs, src_index));
6240     }
6241 }
6242
6243 static void
6244 dexAdvSIMD0 (sim_cpu *cpu)
6245 {
6246   /* instr [28,25] = 0 111.  */
6247   if (    uimm (aarch64_get_instr (cpu), 15, 10) == 0x07
6248       && (uimm (aarch64_get_instr (cpu), 9, 5) ==
6249           uimm (aarch64_get_instr (cpu), 20, 16)))
6250     {
6251       if (uimm (aarch64_get_instr (cpu), 31, 21) == 0x075
6252           || uimm (aarch64_get_instr (cpu), 31, 21) == 0x275)
6253         {
6254           do_vec_MOV_whole_vector (cpu);
6255           return;
6256         }
6257     }
6258
6259   if (uimm (aarch64_get_instr (cpu), 29, 19) == 0x1E0)
6260     {
6261       do_vec_MOV_immediate (cpu);
6262       return;
6263     }
6264
6265   if (uimm (aarch64_get_instr (cpu), 29, 19) == 0x5E0)
6266     {
6267       do_vec_MVNI (cpu);
6268       return;
6269     }
6270
6271   if (uimm (aarch64_get_instr (cpu), 29, 19) == 0x1C0
6272       || uimm (aarch64_get_instr (cpu), 29, 19) == 0x1C1)
6273     {
6274       if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x03)
6275         {
6276           do_vec_DUP_scalar_into_vector (cpu);
6277           return;
6278         }
6279     }
6280
6281   switch (uimm (aarch64_get_instr (cpu), 29, 24))
6282     {
6283     case 0x0E: do_vec_op1 (cpu); return;
6284     case 0x0F: do_vec_op2 (cpu); return;
6285
6286     case 0x2f:
6287       switch (uimm (aarch64_get_instr (cpu), 15, 10))
6288         {
6289         case 0x01: do_vec_SSHR_USHR (cpu); return;
6290         case 0x10:
6291         case 0x12: do_vec_mls_indexed (cpu); return;
6292         case 0x29: do_vec_xtl (cpu); return;
6293         default:
6294           HALT_NYI;
6295         }
6296
6297     case 0x2E:
6298       if (uimm (aarch64_get_instr (cpu), 21, 21) == 1)
6299         {
6300           switch (uimm (aarch64_get_instr (cpu), 15, 10))
6301             {
6302             case 0x07:
6303               switch (uimm (aarch64_get_instr (cpu), 23, 22))
6304                 {
6305                 case 0: do_vec_EOR (cpu); return;
6306                 case 1: do_vec_BSL (cpu); return;
6307                 case 2:
6308                 case 3: do_vec_bit (cpu); return;
6309                 }
6310               break;
6311
6312             case 0x08: do_vec_sub_long (cpu); return;
6313             case 0x11: do_vec_USHL (cpu); return;
6314             case 0x16: do_vec_NOT (cpu); return;
6315             case 0x19: do_vec_max (cpu); return;
6316             case 0x1B: do_vec_min (cpu); return;
6317             case 0x21: do_vec_SUB (cpu); return;
6318             case 0x25: do_vec_MLS (cpu); return;
6319             case 0x31: do_vec_FminmaxNMP (cpu); return;
6320             case 0x35: do_vec_FADDP (cpu); return;
6321             case 0x37: do_vec_FMUL (cpu); return;
6322             case 0x3F: do_vec_FDIV (cpu); return;
6323
6324             case 0x3E:
6325               switch (uimm (aarch64_get_instr (cpu), 20, 16))
6326                 {
6327                 case 0x00: do_vec_FNEG (cpu); return;
6328                 case 0x01: do_vec_FSQRT (cpu); return;
6329                 default:   HALT_NYI;
6330                 }
6331
6332             case 0x0D:
6333             case 0x0F:
6334             case 0x22:
6335             case 0x23:
6336             case 0x26:
6337             case 0x2A:
6338             case 0x32:
6339             case 0x36:
6340             case 0x39:
6341             case 0x3A:
6342               do_vec_compare (cpu); return;
6343
6344             default: break;
6345             }
6346         }
6347
6348       if (uimm (aarch64_get_instr (cpu), 31, 21) == 0x370)
6349         {
6350           do_vec_MOV_element (cpu);
6351           return;
6352         }
6353
6354       switch (uimm (aarch64_get_instr (cpu), 21, 10))
6355         {
6356         case 0x82E: do_vec_neg (cpu); return;
6357         case 0x87E: do_vec_sqrt (cpu); return;
6358         default:
6359           if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x30)
6360             {
6361               do_vec_mull (cpu);
6362               return;
6363             }
6364           break;
6365         }
6366       break;
6367
6368     default:
6369       break;
6370     }
6371
6372   HALT_NYI;
6373 }
6374
6375 /* 3 sources.  */
6376
6377 /* Float multiply add.  */
6378 static void
6379 fmadds (sim_cpu *cpu)
6380 {
6381   unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6382   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6383   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6384   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6385
6386   aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sa)
6387                         + aarch64_get_FP_float (cpu, sn)
6388                         * aarch64_get_FP_float (cpu, sm));
6389 }
6390
6391 /* Double multiply add.  */
6392 static void
6393 fmaddd (sim_cpu *cpu)
6394 {
6395   unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6396   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6397   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6398   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6399
6400   aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sa)
6401                          + aarch64_get_FP_double (cpu, sn)
6402                          * aarch64_get_FP_double (cpu, sm));
6403 }
6404
6405 /* Float multiply subtract.  */
6406 static void
6407 fmsubs (sim_cpu *cpu)
6408 {
6409   unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6410   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6411   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6412   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6413
6414   aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sa)
6415                         - aarch64_get_FP_float (cpu, sn)
6416                         * aarch64_get_FP_float (cpu, sm));
6417 }
6418
6419 /* Double multiply subtract.  */
6420 static void
6421 fmsubd (sim_cpu *cpu)
6422 {
6423   unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6424   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6425   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6426   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6427
6428   aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sa)
6429                          - aarch64_get_FP_double (cpu, sn)
6430                          * aarch64_get_FP_double (cpu, sm));
6431 }
6432
6433 /* Float negative multiply add.  */
6434 static void
6435 fnmadds (sim_cpu *cpu)
6436 {
6437   unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6438   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6439   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6440   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6441
6442   aarch64_set_FP_float (cpu, sd, - aarch64_get_FP_float (cpu, sa)
6443                         + (- aarch64_get_FP_float (cpu, sn))
6444                         * aarch64_get_FP_float (cpu, sm));
6445 }
6446
6447 /* Double negative multiply add.  */
6448 static void
6449 fnmaddd (sim_cpu *cpu)
6450 {
6451   unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6452   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6453   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6454   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6455
6456   aarch64_set_FP_double (cpu, sd, - aarch64_get_FP_double (cpu, sa)
6457                          + (- aarch64_get_FP_double (cpu, sn))
6458                          * aarch64_get_FP_double (cpu, sm));
6459 }
6460
6461 /* Float negative multiply subtract.  */
6462 static void
6463 fnmsubs (sim_cpu *cpu)
6464 {
6465   unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6466   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6467   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6468   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6469
6470   aarch64_set_FP_float (cpu, sd, - aarch64_get_FP_float (cpu, sa)
6471                         + aarch64_get_FP_float (cpu, sn)
6472                         * aarch64_get_FP_float (cpu, sm));
6473 }
6474
6475 /* Double negative multiply subtract.  */
6476 static void
6477 fnmsubd (sim_cpu *cpu)
6478 {
6479   unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6480   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6481   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6482   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6483
6484   aarch64_set_FP_double (cpu, sd, - aarch64_get_FP_double (cpu, sa)
6485                          + aarch64_get_FP_double (cpu, sn)
6486                          * aarch64_get_FP_double (cpu, sm));
6487 }
6488
6489 static void
6490 dexSimpleFPDataProc3Source (sim_cpu *cpu)
6491 {
6492   /* instr[31]    ==> M : 0 ==> OK, 1 ==> UNALLOC
6493      instr[30]    = 0
6494      instr[29]    ==> S :  0 ==> OK, 1 ==> UNALLOC
6495      instr[28,25] = 1111
6496      instr[24]    = 1
6497      instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
6498      instr[21]    ==> o1 : 0 ==> unnegated, 1 ==> negated
6499      instr[15]    ==> o2 : 0 ==> ADD, 1 ==> SUB  */
6500
6501   uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
6502     | uimm (aarch64_get_instr (cpu), 29, 29);
6503   /* dispatch on combined type:o1:o2.  */
6504   uint32_t dispatch = (uimm (aarch64_get_instr (cpu), 23, 21) << 1)
6505     | uimm (aarch64_get_instr (cpu), 15, 15);
6506
6507   if (M_S != 0)
6508     HALT_UNALLOC;
6509
6510   switch (dispatch)
6511     {
6512     case 0: fmadds (cpu); return;
6513     case 1: fmsubs (cpu); return;
6514     case 2: fnmadds (cpu); return;
6515     case 3: fnmsubs (cpu); return;
6516     case 4: fmaddd (cpu); return;
6517     case 5: fmsubd (cpu); return;
6518     case 6: fnmaddd (cpu); return;
6519     case 7: fnmsubd (cpu); return;
6520     default:
6521       /* type > 1 is currently unallocated.  */
6522       HALT_UNALLOC;
6523     }
6524 }
6525
6526 static void
6527 dexSimpleFPFixedConvert (sim_cpu *cpu)
6528 {
6529   HALT_NYI;
6530 }
6531
6532 static void
6533 dexSimpleFPCondCompare (sim_cpu *cpu)
6534 {
6535   HALT_NYI;
6536 }
6537
6538 /* 2 sources.  */
6539
6540 /* Float add.  */
6541 static void
6542 fadds (sim_cpu *cpu)
6543 {
6544   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6545   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6546   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6547
6548   aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6549                         + aarch64_get_FP_float (cpu, sm));
6550 }
6551
6552 /* Double add.  */
6553 static void
6554 faddd (sim_cpu *cpu)
6555 {
6556   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6557   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6558   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6559
6560   aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6561                          + aarch64_get_FP_double (cpu, sm));
6562 }
6563
6564 /* Float divide.  */
6565 static void
6566 fdivs (sim_cpu *cpu)
6567 {
6568   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6569   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6570   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6571
6572   aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6573                         / aarch64_get_FP_float (cpu, sm));
6574 }
6575
6576 /* Double divide.  */
6577 static void
6578 fdivd (sim_cpu *cpu)
6579 {
6580   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6581   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6582   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6583
6584   aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6585                          / aarch64_get_FP_double (cpu, sm));
6586 }
6587
6588 /* Float multiply.  */
6589 static void
6590 fmuls (sim_cpu *cpu)
6591 {
6592   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6593   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6594   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6595
6596   aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6597                         * aarch64_get_FP_float (cpu, sm));
6598 }
6599
6600 /* Double multiply.  */
6601 static void
6602 fmuld (sim_cpu *cpu)
6603 {
6604   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6605   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6606   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6607
6608   aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6609                          * aarch64_get_FP_double (cpu, sm));
6610 }
6611
6612 /* Float negate and multiply.  */
6613 static void
6614 fnmuls (sim_cpu *cpu)
6615 {
6616   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6617   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6618   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6619
6620   aarch64_set_FP_float (cpu, sd, - (aarch64_get_FP_float (cpu, sn)
6621                                     * aarch64_get_FP_float (cpu, sm)));
6622 }
6623
6624 /* Double negate and multiply.  */
6625 static void
6626 fnmuld (sim_cpu *cpu)
6627 {
6628   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6629   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6630   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6631
6632   aarch64_set_FP_double (cpu, sd, - (aarch64_get_FP_double (cpu, sn)
6633                                      * aarch64_get_FP_double (cpu, sm)));
6634 }
6635
6636 /* Float subtract.  */
6637 static void
6638 fsubs (sim_cpu *cpu)
6639 {
6640   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6641   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6642   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6643
6644   aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6645                         - aarch64_get_FP_float (cpu, sm));
6646 }
6647
6648 /* Double subtract.  */
6649 static void
6650 fsubd (sim_cpu *cpu)
6651 {
6652   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6653   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6654   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6655
6656   aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6657                          - aarch64_get_FP_double (cpu, sm));
6658 }
6659
6660 static void
6661 do_FMINNM (sim_cpu *cpu)
6662 {
6663   /* instr[31,23] = 0 0011 1100
6664      instr[22]    = float(0)/double(1)
6665      instr[21]    = 1
6666      instr[20,16] = Sm
6667      instr[15,10] = 01 1110
6668      instr[9,5]   = Sn
6669      instr[4,0]   = Cpu  */
6670
6671   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6672   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6673   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6674
6675   NYI_assert (31, 23, 0x03C);
6676   NYI_assert (15, 10, 0x1E);
6677
6678   if (uimm (aarch64_get_instr (cpu), 22, 22))
6679     aarch64_set_FP_double (cpu, sd,
6680                            dminnm (aarch64_get_FP_double (cpu, sn),
6681                                    aarch64_get_FP_double (cpu, sm)));
6682   else
6683     aarch64_set_FP_float (cpu, sd,
6684                           fminnm (aarch64_get_FP_float (cpu, sn),
6685                                   aarch64_get_FP_float (cpu, sm)));
6686 }
6687
6688 static void
6689 do_FMAXNM (sim_cpu *cpu)
6690 {
6691   /* instr[31,23] = 0 0011 1100
6692      instr[22]    = float(0)/double(1)
6693      instr[21]    = 1
6694      instr[20,16] = Sm
6695      instr[15,10] = 01 1010
6696      instr[9,5]   = Sn
6697      instr[4,0]   = Cpu  */
6698
6699   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6700   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6701   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6702
6703   NYI_assert (31, 23, 0x03C);
6704   NYI_assert (15, 10, 0x1A);
6705
6706   if (uimm (aarch64_get_instr (cpu), 22, 22))
6707     aarch64_set_FP_double (cpu, sd,
6708                            dmaxnm (aarch64_get_FP_double (cpu, sn),
6709                                    aarch64_get_FP_double (cpu, sm)));
6710   else
6711     aarch64_set_FP_float (cpu, sd,
6712                           fmaxnm (aarch64_get_FP_float (cpu, sn),
6713                                   aarch64_get_FP_float (cpu, sm)));
6714 }
6715
6716 static void
6717 dexSimpleFPDataProc2Source (sim_cpu *cpu)
6718 {
6719   /* instr[31]    ==> M : 0 ==> OK, 1 ==> UNALLOC
6720      instr[30]    = 0
6721      instr[29]    ==> S :  0 ==> OK, 1 ==> UNALLOC
6722      instr[28,25] = 1111
6723      instr[24]    = 0
6724      instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
6725      instr[21]    = 1
6726      instr[20,16] = Vm
6727      instr[15,12] ==> opcode : 0000 ==> FMUL, 0001 ==> FDIV
6728                                0010 ==> FADD, 0011 ==> FSUB,
6729                                0100 ==> FMAX, 0101 ==> FMIN
6730                                0110 ==> FMAXNM, 0111 ==> FMINNM
6731                                1000 ==> FNMUL, ow ==> UNALLOC
6732      instr[11,10] = 10
6733      instr[9,5]   = Vn
6734      instr[4,0]   = Vd  */
6735
6736   uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
6737     | uimm (aarch64_get_instr (cpu), 29, 29);
6738   uint32_t type = uimm (aarch64_get_instr (cpu), 23, 22);
6739   /* Dispatch on opcode.  */
6740   uint32_t dispatch = uimm (aarch64_get_instr (cpu), 15, 12);
6741
6742   if (type > 1)
6743     HALT_UNALLOC;
6744
6745   if (M_S != 0)
6746     HALT_UNALLOC;
6747
6748   if (type)
6749     switch (dispatch)
6750       {
6751       case 0: fmuld (cpu); return;
6752       case 1: fdivd (cpu); return;
6753       case 2: faddd (cpu); return;
6754       case 3: fsubd (cpu); return;
6755       case 6: do_FMAXNM (cpu); return;
6756       case 7: do_FMINNM (cpu); return;
6757       case 8: fnmuld (cpu); return;
6758
6759         /* Have not yet implemented fmax and fmin.  */
6760       case 4:
6761       case 5:
6762         HALT_NYI;
6763
6764       default:
6765         HALT_UNALLOC;
6766       }
6767   else /* type == 0 => floats.  */
6768     switch (dispatch)
6769       {
6770       case 0: fmuls (cpu); return;
6771       case 1: fdivs (cpu); return;
6772       case 2: fadds (cpu); return;
6773       case 3: fsubs (cpu); return;
6774       case 6: do_FMAXNM (cpu); return;
6775       case 7: do_FMINNM (cpu); return;
6776       case 8: fnmuls (cpu); return;
6777
6778       case 4:
6779       case 5:
6780         HALT_NYI;
6781
6782       default:
6783         HALT_UNALLOC;
6784       }
6785 }
6786
6787 static void
6788 dexSimpleFPCondSelect (sim_cpu *cpu)
6789 {
6790   /* FCSEL
6791      instr[31,23] = 0 0011 1100
6792      instr[22]    = 0=>single 1=>double
6793      instr[21]    = 1
6794      instr[20,16] = Sm
6795      instr[15,12] = cond
6796      instr[11,10] = 11
6797      instr[9,5]   = Sn
6798      instr[4,0]   = Cpu  */
6799   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6800   unsigned sn = uimm (aarch64_get_instr (cpu),  9, 5);
6801   unsigned sd = uimm (aarch64_get_instr (cpu),  4, 0);
6802   uint32_t set = testConditionCode (cpu, uimm (aarch64_get_instr (cpu), 15, 12));
6803
6804   NYI_assert (31, 23, 0x03C);
6805   NYI_assert (11, 10, 0x3);
6806
6807   if (uimm (aarch64_get_instr (cpu), 22, 22))
6808     aarch64_set_FP_double (cpu, sd, set ? sn : sm);
6809   else
6810     aarch64_set_FP_float (cpu, sd, set ? sn : sm);
6811 }
6812
6813 /* Store 32 bit unscaled signed 9 bit.  */
6814 static void
6815 fsturs (sim_cpu *cpu, int32_t offset)
6816 {
6817   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6818   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6819
6820   aarch64_set_mem_float (cpu, aarch64_get_reg_u64 (cpu, st, 1) + offset,
6821                          aarch64_get_FP_float (cpu, rn));
6822 }
6823
6824 /* Store 64 bit unscaled signed 9 bit.  */
6825 static void
6826 fsturd (sim_cpu *cpu, int32_t offset)
6827 {
6828   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6829   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6830
6831   aarch64_set_mem_double (cpu, aarch64_get_reg_u64 (cpu, st, 1) + offset,
6832                           aarch64_get_FP_double (cpu, rn));
6833 }
6834
6835 /* Store 128 bit unscaled signed 9 bit.  */
6836 static void
6837 fsturq (sim_cpu *cpu, int32_t offset)
6838 {
6839   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6840   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6841   FRegister a;
6842
6843   aarch64_get_FP_long_double (cpu, rn, & a);
6844   aarch64_set_mem_long_double (cpu,
6845                                aarch64_get_reg_u64 (cpu, st, 1)
6846                                + offset, a);
6847 }
6848
6849 /* TODO FP move register.  */
6850
6851 /* 32 bit fp to fp move register.  */
6852 static void
6853 ffmovs (sim_cpu *cpu)
6854 {
6855   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6856   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6857
6858   aarch64_set_FP_float (cpu, st, aarch64_get_FP_float (cpu, rn));
6859 }
6860
6861 /* 64 bit fp to fp move register.  */
6862 static void
6863 ffmovd (sim_cpu *cpu)
6864 {
6865   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6866   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6867
6868   aarch64_set_FP_double (cpu, st, aarch64_get_FP_double (cpu, rn));
6869 }
6870
6871 /* 32 bit GReg to Vec move register.  */
6872 static void
6873 fgmovs (sim_cpu *cpu)
6874 {
6875   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6876   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6877
6878   aarch64_set_vec_u32 (cpu, st, 0, aarch64_get_reg_u32 (cpu, rn, NO_SP));
6879 }
6880
6881 /* 64 bit g to fp move register.  */
6882 static void
6883 fgmovd (sim_cpu *cpu)
6884 {
6885   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6886   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6887
6888   aarch64_set_vec_u64 (cpu, st, 0, aarch64_get_reg_u64 (cpu, rn, NO_SP));
6889 }
6890
6891 /* 32 bit fp to g move register.  */
6892 static void
6893 gfmovs (sim_cpu *cpu)
6894 {
6895   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6896   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6897
6898   aarch64_set_reg_u64 (cpu, st, NO_SP, aarch64_get_vec_u32 (cpu, rn, 0));
6899 }
6900
6901 /* 64 bit fp to g move register.  */
6902 static void
6903 gfmovd (sim_cpu *cpu)
6904 {
6905   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6906   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6907
6908   aarch64_set_reg_u64 (cpu, st, NO_SP, aarch64_get_vec_u64 (cpu, rn, 0));
6909 }
6910
6911 /* FP move immediate
6912
6913    These install an immediate 8 bit value in the target register
6914    where the 8 bits comprise 1 sign bit, 4 bits of fraction and a 3
6915    bit exponent.  */
6916
6917 static void
6918 fmovs (sim_cpu *cpu)
6919 {
6920   unsigned int sd = uimm (aarch64_get_instr (cpu), 4, 0);
6921   uint32_t imm = uimm (aarch64_get_instr (cpu), 20, 13);
6922   float f = fp_immediate_for_encoding_32 (imm);
6923
6924   aarch64_set_FP_float (cpu, sd, f);
6925 }
6926
6927 static void
6928 fmovd (sim_cpu *cpu)
6929 {
6930   unsigned int sd = uimm (aarch64_get_instr (cpu), 4, 0);
6931   uint32_t imm = uimm (aarch64_get_instr (cpu), 20, 13);
6932   double d = fp_immediate_for_encoding_64 (imm);
6933
6934   aarch64_set_FP_double (cpu, sd, d);
6935 }
6936
6937 static void
6938 dexSimpleFPImmediate (sim_cpu *cpu)
6939 {
6940   /* instr[31,23] == 00111100
6941      instr[22]    == type : single(0)/double(1)
6942      instr[21]    == 1
6943      instr[20,13] == imm8
6944      instr[12,10] == 100
6945      instr[9,5]   == imm5 : 00000 ==> PK, ow ==> UNALLOC
6946      instr[4,0]   == Rd  */
6947   uint32_t imm5 = uimm (aarch64_get_instr (cpu), 9, 5);
6948
6949   NYI_assert (31, 23, 0x3C);
6950
6951   if (imm5 != 0)
6952     HALT_UNALLOC;
6953
6954   if (uimm (aarch64_get_instr (cpu), 22, 22))
6955     fmovd (cpu);
6956   else
6957     fmovs (cpu);
6958 }
6959
6960 /* TODO specific decode and execute for group Load Store.  */
6961
6962 /* TODO FP load/store single register (unscaled offset).  */
6963
6964 /* TODO load 8 bit unscaled signed 9 bit.  */
6965 /* TODO load 16 bit unscaled signed 9 bit.  */
6966
6967 /* Load 32 bit unscaled signed 9 bit.  */
6968 static void
6969 fldurs (sim_cpu *cpu, int32_t offset)
6970 {
6971   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6972   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6973
6974   aarch64_set_FP_float (cpu, st, aarch64_get_mem_float
6975                         (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset));
6976 }
6977
6978 /* Load 64 bit unscaled signed 9 bit.  */
6979 static void
6980 fldurd (sim_cpu *cpu, int32_t offset)
6981 {
6982   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6983   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6984
6985   aarch64_set_FP_double (cpu, st, aarch64_get_mem_double
6986                          (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset));
6987 }
6988
6989 /* Load 128 bit unscaled signed 9 bit.  */
6990 static void
6991 fldurq (sim_cpu *cpu, int32_t offset)
6992 {
6993   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6994   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6995   FRegister a;
6996   uint64_t addr = aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset;
6997
6998   aarch64_get_mem_long_double (cpu, addr, & a);
6999   aarch64_set_FP_long_double (cpu, st, a);
7000 }
7001
7002 /* TODO store 8 bit unscaled signed 9 bit.  */
7003 /* TODO store 16 bit unscaled signed 9 bit.  */
7004
7005
7006 /* 1 source.  */
7007
7008 /* Float absolute value.  */
7009 static void
7010 fabss (sim_cpu *cpu)
7011 {
7012   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7013   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7014   float value = aarch64_get_FP_float (cpu, sn);
7015
7016   aarch64_set_FP_float (cpu, sd, fabsf (value));
7017 }
7018
7019 /* Double absolute value.  */
7020 static void
7021 fabcpu (sim_cpu *cpu)
7022 {
7023   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7024   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7025   double value = aarch64_get_FP_double (cpu, sn);
7026
7027   aarch64_set_FP_double (cpu, sd, fabs (value));
7028 }
7029
7030 /* Float negative value.  */
7031 static void
7032 fnegs (sim_cpu *cpu)
7033 {
7034   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7035   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7036
7037   aarch64_set_FP_float (cpu, sd, - aarch64_get_FP_float (cpu, sn));
7038 }
7039
7040 /* Double negative value.  */
7041 static void
7042 fnegd (sim_cpu *cpu)
7043 {
7044   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7045   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7046
7047   aarch64_set_FP_double (cpu, sd, - aarch64_get_FP_double (cpu, sn));
7048 }
7049
7050 /* Float square root.  */
7051 static void
7052 fsqrts (sim_cpu *cpu)
7053 {
7054   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7055   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7056
7057   aarch64_set_FP_float (cpu, sd, sqrt (aarch64_get_FP_float (cpu, sn)));
7058 }
7059
7060 /* Double square root.  */
7061 static void
7062 fsqrtd (sim_cpu *cpu)
7063 {
7064   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7065   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7066
7067   aarch64_set_FP_double (cpu, sd,
7068                          sqrt (aarch64_get_FP_double (cpu, sn)));
7069 }
7070
7071 /* Convert double to float.  */
7072 static void
7073 fcvtds (sim_cpu *cpu)
7074 {
7075   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7076   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7077
7078   aarch64_set_FP_float (cpu, sd, (float) aarch64_get_FP_double (cpu, sn));
7079 }
7080
7081 /* Convert float to double.  */
7082 static void
7083 fcvtcpu (sim_cpu *cpu)
7084 {
7085   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7086   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7087
7088   aarch64_set_FP_double (cpu, sd, (double) aarch64_get_FP_float (cpu, sn));
7089 }
7090
7091 static void
7092 do_FRINT (sim_cpu *cpu)
7093 {
7094   /* instr[31,23] = 0001 1110 0
7095      instr[22]    = single(0)/double(1)
7096      instr[21,18] = 1001
7097      instr[17,15] = rounding mode
7098      instr[14,10] = 10000
7099      instr[9,5]   = source
7100      instr[4,0]   = dest  */
7101
7102   float val;
7103   unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
7104   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7105   unsigned int rmode = uimm (aarch64_get_instr (cpu), 17, 15);
7106
7107   NYI_assert (31, 23, 0x03C);
7108   NYI_assert (21, 18, 0x9);
7109   NYI_assert (14, 10, 0x10);
7110
7111   if (rmode == 6 || rmode == 7)
7112     /* FIXME: Add support for rmode == 6 exactness check.  */
7113     rmode = uimm (aarch64_get_FPSR (cpu), 23, 22);
7114
7115   if (uimm (aarch64_get_instr (cpu), 22, 22))
7116     {
7117       double val = aarch64_get_FP_double (cpu, rs);
7118
7119       switch (rmode)
7120         {
7121         case 0: /* mode N: nearest or even.  */
7122           {
7123             double rval = round (val);
7124
7125             if (val - rval == 0.5)
7126               {
7127                 if (((rval / 2.0) * 2.0) != rval)
7128                   rval += 1.0;
7129               }
7130
7131             aarch64_set_FP_double (cpu, rd, round (val));
7132             return;
7133           }
7134
7135         case 1: /* mode P: towards +inf.  */
7136           if (val < 0.0)
7137             aarch64_set_FP_double (cpu, rd, trunc (val));
7138           else
7139             aarch64_set_FP_double (cpu, rd, round (val));
7140           return;
7141
7142         case 2: /* mode M: towards -inf.  */
7143           if (val < 0.0)
7144             aarch64_set_FP_double (cpu, rd, round (val));
7145           else
7146             aarch64_set_FP_double (cpu, rd, trunc (val));
7147           return;
7148
7149         case 3: /* mode Z: towards 0.  */
7150           aarch64_set_FP_double (cpu, rd, trunc (val));
7151           return;
7152
7153         case 4: /* mode A: away from 0.  */
7154           aarch64_set_FP_double (cpu, rd, round (val));
7155           return;
7156
7157         case 6: /* mode X: use FPCR with exactness check.  */
7158         case 7: /* mode I: use FPCR mode.  */
7159           HALT_NYI;
7160
7161         default:
7162           HALT_UNALLOC;
7163         }
7164     }
7165
7166   val = aarch64_get_FP_float (cpu, rs);
7167
7168   switch (rmode)
7169     {
7170     case 0: /* mode N: nearest or even.  */
7171       {
7172         float rval = roundf (val);
7173
7174         if (val - rval == 0.5)
7175           {
7176             if (((rval / 2.0) * 2.0) != rval)
7177               rval += 1.0;
7178           }
7179
7180         aarch64_set_FP_float (cpu, rd, rval);
7181         return;
7182       }
7183
7184     case 1: /* mode P: towards +inf.  */
7185       if (val < 0.0)
7186         aarch64_set_FP_float (cpu, rd, truncf (val));
7187       else
7188         aarch64_set_FP_float (cpu, rd, roundf (val));
7189       return;
7190
7191     case 2: /* mode M: towards -inf.  */
7192       if (val < 0.0)
7193         aarch64_set_FP_float (cpu, rd, truncf (val));
7194       else
7195         aarch64_set_FP_float (cpu, rd, roundf (val));
7196       return;
7197
7198     case 3: /* mode Z: towards 0.  */
7199       aarch64_set_FP_float (cpu, rd, truncf (val));
7200       return;
7201
7202     case 4: /* mode A: away from 0.  */
7203       aarch64_set_FP_float (cpu, rd, roundf (val));
7204       return;
7205
7206     case 6: /* mode X: use FPCR with exactness check.  */
7207     case 7: /* mode I: use FPCR mode.  */
7208       HALT_NYI;
7209
7210     default:
7211       HALT_UNALLOC;
7212     }
7213 }
7214
7215 static void
7216 dexSimpleFPDataProc1Source (sim_cpu *cpu)
7217 {
7218   /* instr[31]    ==> M : 0 ==> OK, 1 ==> UNALLOC
7219      instr[30]    = 0
7220      instr[29]    ==> S :  0 ==> OK, 1 ==> UNALLOC
7221      instr[28,25] = 1111
7222      instr[24]    = 0
7223      instr[23,22] ==> type : 00 ==> source is single,
7224                              01 ==> source is double
7225                              10 ==> UNALLOC
7226                              11 ==> UNALLOC or source is half
7227      instr[21]    = 1
7228      instr[20,15] ==> opcode : with type 00 or 01
7229                                000000 ==> FMOV, 000001 ==> FABS,
7230                                000010 ==> FNEG, 000011 ==> FSQRT,
7231                                000100 ==> UNALLOC, 000101 ==> FCVT,(to single/double)
7232                                000110 ==> UNALLOC, 000111 ==> FCVT (to half)
7233                                001000 ==> FRINTN, 001001 ==> FRINTP,
7234                                001010 ==> FRINTM, 001011 ==> FRINTZ,
7235                                001100 ==> FRINTA, 001101 ==> UNALLOC
7236                                001110 ==> FRINTX, 001111 ==> FRINTI
7237                                with type 11
7238                                000100 ==> FCVT (half-to-single)
7239                                000101 ==> FCVT (half-to-double)
7240                                instr[14,10] = 10000.  */
7241
7242   uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
7243     | uimm (aarch64_get_instr (cpu), 29, 29);
7244   uint32_t type   = uimm (aarch64_get_instr (cpu), 23, 22);
7245   uint32_t opcode = uimm (aarch64_get_instr (cpu), 20, 15);
7246
7247   if (M_S != 0)
7248     HALT_UNALLOC;
7249
7250   if (type == 3)
7251     {
7252       if (opcode == 4 || opcode == 5)
7253         HALT_NYI;
7254       else
7255         HALT_UNALLOC;
7256     }
7257
7258   if (type == 2)
7259     HALT_UNALLOC;
7260
7261   switch (opcode)
7262     {
7263     case 0:
7264       if (type)
7265         ffmovd (cpu);
7266       else
7267         ffmovs (cpu);
7268       return;
7269
7270     case 1:
7271       if (type)
7272         fabcpu (cpu);
7273       else
7274         fabss (cpu);
7275       return;
7276
7277     case 2:
7278       if (type)
7279         fnegd (cpu);
7280       else
7281         fnegs (cpu);
7282       return;
7283
7284     case 3:
7285       if (type)
7286         fsqrtd (cpu);
7287       else
7288         fsqrts (cpu);
7289       return;
7290
7291     case 4:
7292       if (type)
7293         fcvtds (cpu);
7294       else
7295         HALT_UNALLOC;
7296       return;
7297
7298     case 5:
7299       if (type)
7300         HALT_UNALLOC;
7301       fcvtcpu (cpu);
7302       return;
7303
7304     case 8:             /* FRINTN etc.  */
7305     case 9:
7306     case 10:
7307     case 11:
7308     case 12:
7309     case 14:
7310     case 15:
7311        do_FRINT (cpu);
7312        return;
7313
7314     case 7:             /* FCVT double/single to half precision.  */
7315     case 13:
7316       HALT_NYI;
7317
7318     default:
7319       HALT_UNALLOC;
7320     }
7321 }
7322
7323 /* 32 bit signed int to float.  */
7324 static void
7325 scvtf32 (sim_cpu *cpu)
7326 {
7327   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7328   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7329
7330   aarch64_set_FP_float
7331     (cpu, sd, (float) aarch64_get_reg_s32 (cpu, rn, NO_SP));
7332 }
7333
7334 /* signed int to float.  */
7335 static void
7336 scvtf (sim_cpu *cpu)
7337 {
7338   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7339   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7340
7341   aarch64_set_FP_float
7342     (cpu, sd, (float) aarch64_get_reg_s64 (cpu, rn, NO_SP));
7343 }
7344
7345 /* 32 bit signed int to double.  */
7346 static void
7347 scvtd32 (sim_cpu *cpu)
7348 {
7349   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7350   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7351
7352   aarch64_set_FP_double
7353     (cpu, sd, (double) aarch64_get_reg_s32 (cpu, rn, NO_SP));
7354 }
7355
7356 /* signed int to double.  */
7357 static void
7358 scvtd (sim_cpu *cpu)
7359 {
7360   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7361   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7362
7363   aarch64_set_FP_double
7364     (cpu, sd, (double) aarch64_get_reg_s64 (cpu, rn, NO_SP));
7365 }
7366
7367 static const float  FLOAT_INT_MAX   = (float)  INT_MAX;
7368 static const float  FLOAT_INT_MIN   = (float)  INT_MIN;
7369 static const double DOUBLE_INT_MAX  = (double) INT_MAX;
7370 static const double DOUBLE_INT_MIN  = (double) INT_MIN;
7371 static const float  FLOAT_LONG_MAX  = (float)  LONG_MAX;
7372 static const float  FLOAT_LONG_MIN  = (float)  LONG_MIN;
7373 static const double DOUBLE_LONG_MAX = (double) LONG_MAX;
7374 static const double DOUBLE_LONG_MIN = (double) LONG_MIN;
7375
7376 /* Check for FP exception conditions:
7377      NaN raises IO
7378      Infinity raises IO
7379      Out of Range raises IO and IX and saturates value
7380      Denormal raises ID and IX and sets to zero.  */
7381 #define RAISE_EXCEPTIONS(F, VALUE, FTYPE, ITYPE)        \
7382   do                                                    \
7383     {                                                   \
7384       switch (fpclassify (F))                           \
7385         {                                               \
7386         case FP_INFINITE:                               \
7387         case FP_NAN:                                    \
7388           aarch64_set_FPSR (cpu, IO);                   \
7389           if (signbit (F))                              \
7390             VALUE = ITYPE##_MAX;                        \
7391           else                                          \
7392             VALUE = ITYPE##_MIN;                        \
7393           break;                                        \
7394                                                         \
7395         case FP_NORMAL:                                 \
7396           if (F >= FTYPE##_##ITYPE##_MAX)               \
7397             {                                           \
7398               aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX);    \
7399               VALUE = ITYPE##_MAX;                      \
7400             }                                           \
7401           else if (F <= FTYPE##_##ITYPE##_MIN)          \
7402             {                                           \
7403               aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX);    \
7404               VALUE = ITYPE##_MIN;                      \
7405             }                                           \
7406           break;                                        \
7407                                                         \
7408         case FP_SUBNORMAL:                              \
7409           aarch64_set_FPSR_bits (cpu, IO | IX | ID, IX | ID);   \
7410           VALUE = 0;                                    \
7411           break;                                        \
7412                                                         \
7413         default:                                        \
7414         case FP_ZERO:                                   \
7415           VALUE = 0;                                    \
7416           break;                                        \
7417         }                                               \
7418     }                                                   \
7419   while (0)
7420
7421 /* 32 bit convert float to signed int truncate towards zero.  */
7422 static void
7423 fcvtszs32 (sim_cpu *cpu)
7424 {
7425   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7426   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7427   /* TODO : check that this rounds toward zero.  */
7428   float   f = aarch64_get_FP_float (cpu, sn);
7429   int32_t value = (int32_t) f;
7430
7431   RAISE_EXCEPTIONS (f, value, FLOAT, INT);
7432
7433   /* Avoid sign extension to 64 bit.  */
7434   aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) value);
7435 }
7436
7437 /* 64 bit convert float to signed int truncate towards zero.  */
7438 static void
7439 fcvtszs (sim_cpu *cpu)
7440 {
7441   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7442   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7443   float f = aarch64_get_FP_float (cpu, sn);
7444   int64_t value = (int64_t) f;
7445
7446   RAISE_EXCEPTIONS (f, value, FLOAT, LONG);
7447
7448   aarch64_set_reg_s64 (cpu, rd, NO_SP, value);
7449 }
7450
7451 /* 32 bit convert double to signed int truncate towards zero.  */
7452 static void
7453 fcvtszd32 (sim_cpu *cpu)
7454 {
7455   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7456   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7457   /* TODO : check that this rounds toward zero.  */
7458   double   d = aarch64_get_FP_double (cpu, sn);
7459   int32_t  value = (int32_t) d;
7460
7461   RAISE_EXCEPTIONS (d, value, DOUBLE, INT);
7462
7463   /* Avoid sign extension to 64 bit.  */
7464   aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) value);
7465 }
7466
7467 /* 64 bit convert double to signed int truncate towards zero.  */
7468 static void
7469 fcvtszd (sim_cpu *cpu)
7470 {
7471   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7472   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7473   /* TODO : check that this rounds toward zero.  */
7474   double  d = aarch64_get_FP_double (cpu, sn);
7475   int64_t value;
7476
7477   value = (int64_t) d;
7478
7479   RAISE_EXCEPTIONS (d, value, DOUBLE, LONG);
7480
7481   aarch64_set_reg_s64 (cpu, rd, NO_SP, value);
7482 }
7483
7484 static void
7485 do_fcvtzu (sim_cpu *cpu)
7486 {
7487   /* instr[31]    = size: 32-bit (0), 64-bit (1)
7488      instr[30,23] = 00111100
7489      instr[22]    = type: single (0)/ double (1)
7490      instr[21]    = enable (0)/disable(1) precision
7491      instr[20,16] = 11001
7492      instr[15,10] = precision
7493      instr[9,5]   = Rs
7494      instr[4,0]   = Rd.  */
7495
7496   unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
7497   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7498
7499   NYI_assert (30, 23, 0x3C);
7500   NYI_assert (20, 16, 0x19);
7501
7502   if (uimm (aarch64_get_instr (cpu), 21, 21) != 1)
7503     /* Convert to fixed point.  */
7504     HALT_NYI;
7505
7506   if (uimm (aarch64_get_instr (cpu), 31, 31))
7507     {
7508       /* Convert to unsigned 64-bit integer.  */
7509       if (uimm (aarch64_get_instr (cpu), 22, 22))
7510         {
7511           double  d = aarch64_get_FP_double (cpu, rs);
7512           uint64_t value = (uint64_t) d;
7513
7514           /* Do not raise an exception if we have reached ULONG_MAX.  */
7515           if (value != (1UL << 63))
7516             RAISE_EXCEPTIONS (d, value, DOUBLE, LONG);
7517
7518           aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
7519         }
7520       else
7521         {
7522           float  f = aarch64_get_FP_float (cpu, rs);
7523           uint64_t value = (uint64_t) f;
7524
7525           /* Do not raise an exception if we have reached ULONG_MAX.  */
7526           if (value != (1UL << 63))
7527             RAISE_EXCEPTIONS (f, value, FLOAT, LONG);
7528
7529           aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
7530         }
7531     }
7532   else
7533     {
7534       uint32_t value;
7535
7536       /* Convert to unsigned 32-bit integer.  */
7537       if (uimm (aarch64_get_instr (cpu), 22, 22))
7538         {
7539           double  d = aarch64_get_FP_double (cpu, rs);
7540
7541           value = (uint32_t) d;
7542           /* Do not raise an exception if we have reached UINT_MAX.  */
7543           if (value != (1UL << 31))
7544             RAISE_EXCEPTIONS (d, value, DOUBLE, INT);
7545         }
7546       else
7547         {
7548           float  f = aarch64_get_FP_float (cpu, rs);
7549
7550           value = (uint32_t) f;
7551           /* Do not raise an exception if we have reached UINT_MAX.  */
7552           if (value != (1UL << 31))
7553             RAISE_EXCEPTIONS (f, value, FLOAT, INT);
7554         }
7555
7556       aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
7557     }
7558 }
7559
7560 static void
7561 do_UCVTF (sim_cpu *cpu)
7562 {
7563   /* instr[31]    = size: 32-bit (0), 64-bit (1)
7564      instr[30,23] = 001 1110 0
7565      instr[22]    = type: single (0)/ double (1)
7566      instr[21]    = enable (0)/disable(1) precision
7567      instr[20,16] = 0 0011
7568      instr[15,10] = precision
7569      instr[9,5]   = Rs
7570      instr[4,0]   = Rd.  */
7571
7572   unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
7573   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7574
7575   NYI_assert (30, 23, 0x3C);
7576   NYI_assert (20, 16, 0x03);
7577
7578   if (uimm (aarch64_get_instr (cpu), 21, 21) != 1)
7579     HALT_NYI;
7580
7581   /* FIXME: Add exception raising.  */
7582   if (uimm (aarch64_get_instr (cpu), 31, 31))
7583     {
7584       uint64_t value = aarch64_get_reg_u64 (cpu, rs, NO_SP);
7585
7586       if (uimm (aarch64_get_instr (cpu), 22, 22))
7587         aarch64_set_FP_double (cpu, rd, (double) value);
7588       else
7589         aarch64_set_FP_float (cpu, rd, (float) value);
7590     }
7591   else
7592     {
7593       uint32_t value =  aarch64_get_reg_u32 (cpu, rs, NO_SP);
7594
7595       if (uimm (aarch64_get_instr (cpu), 22, 22))
7596         aarch64_set_FP_double (cpu, rd, (double) value);
7597       else
7598         aarch64_set_FP_float (cpu, rd, (float) value);
7599     }
7600 }
7601
7602 static void
7603 float_vector_move (sim_cpu *cpu)
7604 {
7605   /* instr[31,17] == 100 1111 0101 0111
7606      instr[16]    ==> direction 0=> to GR, 1=> from GR
7607      instr[15,10] => ???
7608      instr[9,5]   ==> source
7609      instr[4,0]   ==> dest.  */
7610
7611   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7612   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7613
7614   NYI_assert (31, 17, 0x4F57);
7615
7616   if (uimm (aarch64_get_instr (cpu), 15, 10) != 0)
7617     HALT_UNALLOC;
7618
7619   if (uimm (aarch64_get_instr (cpu), 16, 16))
7620     aarch64_set_vec_u64 (cpu, rd, 1, aarch64_get_reg_u64 (cpu, rn, NO_SP));
7621   else
7622     aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u64 (cpu, rn, 1));
7623 }
7624
7625 static void
7626 dexSimpleFPIntegerConvert (sim_cpu *cpu)
7627 {
7628   /* instr[31]    = size : 0 ==> 32 bit, 1 ==> 64 bit
7629      instr[30     = 0
7630      instr[29]    = S :  0 ==> OK, 1 ==> UNALLOC
7631      instr[28,25] = 1111
7632      instr[24]    = 0
7633      instr[23,22] = type : 00 ==> single, 01 ==> double, 1x ==> UNALLOC
7634      instr[21]    = 1
7635      instr[20,19] = rmode
7636      instr[18,16] = opcode
7637      instr[15,10] = 10 0000  */
7638
7639   uint32_t rmode_opcode;
7640   uint32_t size_type;
7641   uint32_t type;
7642   uint32_t size;
7643   uint32_t S;
7644
7645   if (uimm (aarch64_get_instr (cpu), 31, 17) == 0x4F57)
7646     {
7647       float_vector_move (cpu);
7648       return;
7649     }
7650
7651   size = uimm (aarch64_get_instr (cpu), 31, 31);
7652   S = uimm (aarch64_get_instr (cpu), 29, 29);
7653   if (S != 0)
7654     HALT_UNALLOC;
7655
7656   type = uimm (aarch64_get_instr (cpu), 23, 22);
7657   if (type > 1)
7658     HALT_UNALLOC;
7659
7660   rmode_opcode = uimm (aarch64_get_instr (cpu), 20, 16);
7661   size_type = (size << 1) | type; /* 0==32f, 1==32d, 2==64f, 3==64d.  */
7662
7663   switch (rmode_opcode)
7664     {
7665     case 2:                     /* SCVTF.  */
7666       switch (size_type)
7667         {
7668         case 0: scvtf32 (cpu); return;
7669         case 1: scvtd32 (cpu); return;
7670         case 2: scvtf (cpu); return;
7671         case 3: scvtd (cpu); return;
7672         default:
7673           HALT_UNREACHABLE;
7674         }
7675
7676     case 6:                     /* FMOV GR, Vec.  */
7677       switch (size_type)
7678         {
7679         case 0:  gfmovs (cpu); return;
7680         case 3:  gfmovd (cpu); return;
7681         default: HALT_UNALLOC;
7682         }
7683
7684     case 7:                     /* FMOV vec, GR.  */
7685       switch (size_type)
7686         {
7687         case 0:  fgmovs (cpu); return;
7688         case 3:  fgmovd (cpu); return;
7689         default: HALT_UNALLOC;
7690         }
7691
7692     case 24:                    /* FCVTZS.  */
7693       switch (size_type)
7694         {
7695         case 0: fcvtszs32 (cpu); return;
7696         case 1: fcvtszd32 (cpu); return;
7697         case 2: fcvtszs (cpu); return;
7698         case 3: fcvtszd (cpu); return;
7699         default: HALT_UNREACHABLE;
7700         }
7701
7702     case 25: do_fcvtzu (cpu); return;
7703     case 3:  do_UCVTF (cpu); return;
7704
7705     case 0:     /* FCVTNS.  */
7706     case 1:     /* FCVTNU.  */
7707     case 4:     /* FCVTAS.  */
7708     case 5:     /* FCVTAU.  */
7709     case 8:     /* FCVPTS.  */
7710     case 9:     /* FCVTPU.  */
7711     case 16:    /* FCVTMS.  */
7712     case 17:    /* FCVTMU.  */
7713     default:
7714       HALT_NYI;
7715     }
7716 }
7717
7718 static void
7719 set_flags_for_float_compare (sim_cpu *cpu, float fvalue1, float fvalue2)
7720 {
7721   uint32_t flags;
7722
7723   if (isnan (fvalue1) || isnan (fvalue2))
7724     flags = C|V;
7725   else
7726     {
7727       float result = fvalue1 - fvalue2;
7728
7729       if (result == 0.0)
7730         flags = Z|C;
7731       else if (result < 0)
7732         flags = N;
7733       else /* (result > 0).  */
7734         flags = C;
7735     }
7736
7737   aarch64_set_CPSR (cpu, flags);
7738 }
7739
7740 static void
7741 fcmps (sim_cpu *cpu)
7742 {
7743   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
7744   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
7745
7746   float fvalue1 = aarch64_get_FP_float (cpu, sn);
7747   float fvalue2 = aarch64_get_FP_float (cpu, sm);
7748
7749   set_flags_for_float_compare (cpu, fvalue1, fvalue2);
7750 }
7751
7752 /* Float compare to zero -- Invalid Operation exception
7753    only on signaling NaNs.  */
7754 static void
7755 fcmpzs (sim_cpu *cpu)
7756 {
7757   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
7758   float fvalue1 = aarch64_get_FP_float (cpu, sn);
7759
7760   set_flags_for_float_compare (cpu, fvalue1, 0.0f);
7761 }
7762
7763 /* Float compare -- Invalid Operation exception on all NaNs.  */
7764 static void
7765 fcmpes (sim_cpu *cpu)
7766 {
7767   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
7768   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
7769
7770   float fvalue1 = aarch64_get_FP_float (cpu, sn);
7771   float fvalue2 = aarch64_get_FP_float (cpu, sm);
7772
7773   set_flags_for_float_compare (cpu, fvalue1, fvalue2);
7774 }
7775
7776 /* Float compare to zero -- Invalid Operation exception on all NaNs.  */
7777 static void
7778 fcmpzes (sim_cpu *cpu)
7779 {
7780   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
7781   float fvalue1 = aarch64_get_FP_float (cpu, sn);
7782
7783   set_flags_for_float_compare (cpu, fvalue1, 0.0f);
7784 }
7785
7786 static void
7787 set_flags_for_double_compare (sim_cpu *cpu, double dval1, double dval2)
7788 {
7789   uint32_t flags;
7790
7791   if (isnan (dval1) || isnan (dval2))
7792     flags = C|V;
7793   else
7794     {
7795       double result = dval1 - dval2;
7796
7797       if (result == 0.0)
7798         flags = Z|C;
7799       else if (result < 0)
7800         flags = N;
7801       else /* (result > 0).  */
7802         flags = C;
7803     }
7804
7805   aarch64_set_CPSR (cpu, flags);
7806 }
7807
7808 /* Double compare -- Invalid Operation exception only on signaling NaNs.  */
7809 static void
7810 fcmpd (sim_cpu *cpu)
7811 {
7812   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
7813   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
7814
7815   double dvalue1 = aarch64_get_FP_double (cpu, sn);
7816   double dvalue2 = aarch64_get_FP_double (cpu, sm);
7817
7818   set_flags_for_double_compare (cpu, dvalue1, dvalue2);
7819 }
7820
7821 /* Double compare to zero -- Invalid Operation exception
7822    only on signaling NaNs.  */
7823 static void
7824 fcmpzd (sim_cpu *cpu)
7825 {
7826   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
7827   double dvalue1 = aarch64_get_FP_double (cpu, sn);
7828
7829   set_flags_for_double_compare (cpu, dvalue1, 0.0);
7830 }
7831
7832 /* Double compare -- Invalid Operation exception on all NaNs.  */
7833 static void
7834 fcmped (sim_cpu *cpu)
7835 {
7836   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
7837   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
7838
7839   double dvalue1 = aarch64_get_FP_double (cpu, sn);
7840   double dvalue2 = aarch64_get_FP_double (cpu, sm);
7841
7842   set_flags_for_double_compare (cpu, dvalue1, dvalue2);
7843 }
7844
7845 /* Double compare to zero -- Invalid Operation exception on all NaNs.  */
7846 static void
7847 fcmpzed (sim_cpu *cpu)
7848 {
7849   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
7850   double dvalue1 = aarch64_get_FP_double (cpu, sn);
7851
7852   set_flags_for_double_compare (cpu, dvalue1, 0.0);
7853 }
7854
7855 static void
7856 dexSimpleFPCompare (sim_cpu *cpu)
7857 {
7858   /* assert instr[28,25] == 1111
7859      instr[30:24:21:13,10] = 0011000
7860      instr[31] = M : 0 ==> OK, 1 ==> UNALLOC
7861      instr[29] ==> S :  0 ==> OK, 1 ==> UNALLOC
7862      instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
7863      instr[15,14] ==> op : 00 ==> OK, ow ==> UNALLOC
7864      instr[4,0] ==> opcode2 : 00000 ==> FCMP, 10000 ==> FCMPE,
7865                               01000 ==> FCMPZ, 11000 ==> FCMPEZ,
7866                               ow ==> UNALLOC  */
7867   uint32_t dispatch;
7868   uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
7869     | uimm (aarch64_get_instr (cpu), 29, 29);
7870   uint32_t type = uimm (aarch64_get_instr (cpu), 23, 22);
7871   uint32_t op = uimm (aarch64_get_instr (cpu), 15, 14);
7872   uint32_t op2_2_0 = uimm (aarch64_get_instr (cpu), 2, 0);
7873
7874   if (op2_2_0 != 0)
7875     HALT_UNALLOC;
7876
7877   if (M_S != 0)
7878     HALT_UNALLOC;
7879
7880   if (type > 1)
7881     HALT_UNALLOC;
7882
7883   if (op != 0)
7884     HALT_UNALLOC;
7885
7886   /* dispatch on type and top 2 bits of opcode.  */
7887   dispatch = (type << 2) | uimm (aarch64_get_instr (cpu), 4, 3);
7888
7889   switch (dispatch)
7890     {
7891     case 0: fcmps (cpu); return;
7892     case 1: fcmpzs (cpu); return;
7893     case 2: fcmpes (cpu); return;
7894     case 3: fcmpzes (cpu); return;
7895     case 4: fcmpd (cpu); return;
7896     case 5: fcmpzd (cpu); return;
7897     case 6: fcmped (cpu); return;
7898     case 7: fcmpzed (cpu); return;
7899     default: HALT_UNREACHABLE;
7900     }
7901 }
7902
7903 static void
7904 do_scalar_FADDP (sim_cpu *cpu)
7905 {
7906   /* instr [31,23] = 011111100
7907      instr [22]    = single(0)/double(1)
7908      instr [21,10] = 1100 0011 0110
7909      instr [9,5]   = Fn
7910      instr [4,0]   = Fd.  */
7911
7912   unsigned Fn = uimm (aarch64_get_instr (cpu), 9, 5);
7913   unsigned Fd = uimm (aarch64_get_instr (cpu), 4, 0);
7914
7915   NYI_assert (31, 23, 0x0FC);
7916   NYI_assert (21, 10, 0xC36);
7917
7918   if (uimm (aarch64_get_instr (cpu), 22, 22))
7919     {
7920       double val1 = aarch64_get_vec_double (cpu, Fn, 0);
7921       double val2 = aarch64_get_vec_double (cpu, Fn, 1);
7922
7923       aarch64_set_FP_double (cpu, Fd, val1 + val2);
7924     }
7925   else
7926     {
7927       float val1 = aarch64_get_vec_float (cpu, Fn, 0);
7928       float val2 = aarch64_get_vec_float (cpu, Fn, 1);
7929
7930       aarch64_set_FP_float (cpu, Fd, val1 + val2);
7931     }
7932 }
7933
7934 /* Floating point absolute difference.  */
7935
7936 static void
7937 do_scalar_FABD (sim_cpu *cpu)
7938 {
7939   /* instr [31,23] = 0111 1110 1
7940      instr [22]    = float(0)/double(1)
7941      instr [21]    = 1
7942      instr [20,16] = Rm
7943      instr [15,10] = 1101 01
7944      instr [9, 5]  = Rn
7945      instr [4, 0]  = Rd.  */
7946
7947   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
7948   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7949   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7950
7951   NYI_assert (31, 23, 0x0FD);
7952   NYI_assert (21, 21, 1);
7953   NYI_assert (15, 10, 0x35);
7954
7955   if (uimm (aarch64_get_instr (cpu), 22, 22))
7956     aarch64_set_FP_double (cpu, rd,
7957                            fabs (aarch64_get_FP_double (cpu, rn)
7958                                  - aarch64_get_FP_double (cpu, rm)));
7959   else
7960     aarch64_set_FP_float (cpu, rd,
7961                           fabsf (aarch64_get_FP_float (cpu, rn)
7962                                  - aarch64_get_FP_float (cpu, rm)));
7963 }
7964
7965 static void
7966 do_scalar_CMGT (sim_cpu *cpu)
7967 {
7968   /* instr [31,21] = 0101 1110 111
7969      instr [20,16] = Rm
7970      instr [15,10] = 00 1101
7971      instr [9, 5]  = Rn
7972      instr [4, 0]  = Rd.  */
7973
7974   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
7975   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7976   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7977
7978   NYI_assert (31, 21, 0x2F7);
7979   NYI_assert (15, 10, 0x0D);
7980
7981   aarch64_set_vec_u64 (cpu, rd, 0,
7982                        aarch64_get_vec_u64 (cpu, rn, 0) >
7983                        aarch64_get_vec_u64 (cpu, rm, 0) ? -1L : 0L);
7984 }
7985
7986 static void
7987 do_scalar_USHR (sim_cpu *cpu)
7988 {
7989   /* instr [31,23] = 0111 1111 0
7990      instr [22,16] = shift amount
7991      instr [15,10] = 0000 01
7992      instr [9, 5]  = Rn
7993      instr [4, 0]  = Rd.  */
7994
7995   unsigned amount = 128 - uimm (aarch64_get_instr (cpu), 22, 16);
7996   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7997   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7998
7999   NYI_assert (31, 23, 0x0FE);
8000   NYI_assert (15, 10, 0x01);
8001
8002   aarch64_set_vec_u64 (cpu, rd, 0,
8003                        aarch64_get_vec_u64 (cpu, rn, 0) >> amount);
8004 }
8005
8006 static void
8007 do_scalar_SHL (sim_cpu *cpu)
8008 {
8009   /* instr [31,23] = 0111 1101 0
8010      instr [22,16] = shift amount
8011      instr [15,10] = 0101 01
8012      instr [9, 5]  = Rn
8013      instr [4, 0]  = Rd.  */
8014
8015   unsigned amount = uimm (aarch64_get_instr (cpu), 22, 16) - 64;
8016   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8017   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8018
8019   NYI_assert (31, 23, 0x0BE);
8020   NYI_assert (15, 10, 0x15);
8021
8022   if (uimm (aarch64_get_instr (cpu), 22, 22) == 0)
8023     HALT_UNALLOC;
8024
8025   aarch64_set_vec_u64 (cpu, rd, 0,
8026                        aarch64_get_vec_u64 (cpu, rn, 0) << amount);
8027 }
8028
8029 /* FCMEQ FCMGT FCMGE.  */
8030 static void
8031 do_scalar_FCM (sim_cpu *cpu)
8032 {
8033   /* instr [31,30] = 01
8034      instr [29]    = U
8035      instr [28,24] = 1 1110
8036      instr [23]    = E
8037      instr [22]    = size
8038      instr [21]    = 1
8039      instr [20,16] = Rm
8040      instr [15,12] = 1110
8041      instr [11]    = AC
8042      instr [10]    = 1
8043      instr [9, 5]  = Rn
8044      instr [4, 0]  = Rd.  */
8045
8046   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8047   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8048   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8049   unsigned EUac = (uimm (aarch64_get_instr (cpu), 23, 23) << 2)
8050     | (uimm (aarch64_get_instr (cpu), 29, 29) << 1)
8051     | uimm (aarch64_get_instr (cpu), 11, 11);
8052   unsigned result;
8053   float val1;
8054   float val2;
8055
8056   NYI_assert (31, 30, 1);
8057   NYI_assert (28, 24, 0x1E);
8058   NYI_assert (21, 21, 1);
8059   NYI_assert (15, 12, 0xE);
8060   NYI_assert (10, 10, 1);
8061
8062   if (uimm (aarch64_get_instr (cpu), 22, 22))
8063     {
8064       double val1 = aarch64_get_FP_double (cpu, rn);
8065       double val2 = aarch64_get_FP_double (cpu, rm);
8066
8067       switch (EUac)
8068         {
8069         case 0: /* 000 */
8070           result = val1 == val2;
8071           break;
8072
8073         case 3: /* 011 */
8074           val1 = fabs (val1);
8075           val2 = fabs (val2);
8076           /* Fall through. */
8077         case 2: /* 010 */
8078           result = val1 >= val2;
8079           break;
8080
8081         case 7: /* 111 */
8082           val1 = fabs (val1);
8083           val2 = fabs (val2);
8084           /* Fall through. */
8085         case 6: /* 110 */
8086           result = val1 > val2;
8087           break;
8088
8089         default:
8090           HALT_UNALLOC;
8091         }
8092
8093       aarch64_set_vec_u32 (cpu, rd, 0, result ? -1 : 0);
8094       return;
8095     }
8096
8097   val1 = aarch64_get_FP_float (cpu, rn);
8098   val2 = aarch64_get_FP_float (cpu, rm);
8099
8100   switch (EUac)
8101     {
8102     case 0: /* 000 */
8103       result = val1 == val2;
8104       break;
8105
8106     case 3: /* 011 */
8107       val1 = fabsf (val1);
8108       val2 = fabsf (val2);
8109       /* Fall through. */
8110     case 2: /* 010 */
8111       result = val1 >= val2;
8112       break;
8113
8114     case 7: /* 111 */
8115       val1 = fabsf (val1);
8116       val2 = fabsf (val2);
8117       /* Fall through. */
8118     case 6: /* 110 */
8119       result = val1 > val2;
8120       break;
8121
8122     default:
8123       HALT_UNALLOC;
8124     }
8125
8126   aarch64_set_vec_u32 (cpu, rd, 0, result ? -1 : 0);
8127 }
8128
8129 /* An alias of DUP.  */
8130 static void
8131 do_scalar_MOV (sim_cpu *cpu)
8132 {
8133   /* instr [31,21] = 0101 1110 000
8134      instr [20,16] = imm5
8135      instr [15,10] = 0000 01
8136      instr [9, 5]  = Rn
8137      instr [4, 0]  = Rd.  */
8138
8139   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8140   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8141   unsigned index;
8142
8143   NYI_assert (31, 21, 0x2F0);
8144   NYI_assert (15, 10, 0x01);
8145
8146   if (uimm (aarch64_get_instr (cpu), 16, 16))
8147     {
8148       /* 8-bit.  */
8149       index = uimm (aarch64_get_instr (cpu), 20, 17);
8150       aarch64_set_vec_u8
8151         (cpu, rd, 0, aarch64_get_vec_u8 (cpu, rn, index));
8152     }
8153   else if (uimm (aarch64_get_instr (cpu), 17, 17))
8154     {
8155       /* 16-bit.  */
8156       index = uimm (aarch64_get_instr (cpu), 20, 18);
8157       aarch64_set_vec_u16
8158         (cpu, rd, 0, aarch64_get_vec_u16 (cpu, rn, index));
8159     }
8160   else if (uimm (aarch64_get_instr (cpu), 18, 18))
8161     {
8162       /* 32-bit.  */
8163       index = uimm (aarch64_get_instr (cpu), 20, 19);
8164       aarch64_set_vec_u32
8165         (cpu, rd, 0, aarch64_get_vec_u32 (cpu, rn, index));
8166     }
8167   else if (uimm (aarch64_get_instr (cpu), 19, 19))
8168     {
8169       /* 64-bit.  */
8170       index = uimm (aarch64_get_instr (cpu), 20, 20);
8171       aarch64_set_vec_u64
8172         (cpu, rd, 0, aarch64_get_vec_u64 (cpu, rn, index));
8173     }
8174   else
8175     HALT_UNALLOC;
8176 }
8177
8178 static void
8179 do_double_add (sim_cpu *cpu)
8180 {
8181   /* instr [28,25] = 1111.  */
8182   unsigned Fd;
8183   unsigned Fm;
8184   unsigned Fn;
8185   double val1;
8186   double val2;
8187
8188   switch (uimm (aarch64_get_instr (cpu), 31, 23))
8189     {
8190     case 0xBC:
8191       switch (uimm (aarch64_get_instr (cpu), 15, 10))
8192         {
8193         case 0x01: do_scalar_MOV (cpu); return;
8194         case 0x39: do_scalar_FCM (cpu); return;
8195         case 0x3B: do_scalar_FCM (cpu); return;
8196         }
8197       break;
8198
8199     case 0xBE: do_scalar_SHL (cpu); return;
8200
8201     case 0xFC:
8202       switch (uimm (aarch64_get_instr (cpu), 15, 10))
8203         {
8204         case 0x36: do_scalar_FADDP (cpu); return;
8205         case 0x39: do_scalar_FCM (cpu); return;
8206         case 0x3B: do_scalar_FCM (cpu); return;
8207         }
8208       break;
8209
8210     case 0xFD:
8211       switch (uimm (aarch64_get_instr (cpu), 15, 10))
8212         {
8213         case 0x0D: do_scalar_CMGT (cpu); return;
8214         case 0x35: do_scalar_FABD (cpu); return;
8215         case 0x39: do_scalar_FCM (cpu); return;
8216         case 0x3B: do_scalar_FCM (cpu); return;
8217         default:
8218           HALT_NYI;
8219         }
8220
8221     case 0xFE: do_scalar_USHR (cpu); return;
8222     default:
8223       break;
8224     }
8225
8226   /* instr [31,21] = 0101 1110 111
8227      instr [20,16] = Fn
8228      instr [15,10] = 1000 01
8229      instr [9,5]   = Fm
8230      instr [4,0]   = Fd.  */
8231   if (uimm (aarch64_get_instr (cpu), 31, 21) != 0x2F7
8232       || uimm (aarch64_get_instr (cpu), 15, 10) != 0x21)
8233     HALT_NYI;
8234
8235   Fd = uimm (aarch64_get_instr (cpu), 4, 0);
8236   Fm = uimm (aarch64_get_instr (cpu), 9, 5);
8237   Fn = uimm (aarch64_get_instr (cpu), 20, 16);
8238
8239   val1 = aarch64_get_FP_double (cpu, Fm);
8240   val2 = aarch64_get_FP_double (cpu, Fn);
8241
8242   aarch64_set_FP_double (cpu, Fd, val1 + val2);
8243 }
8244
8245 static void
8246 dexAdvSIMD1 (sim_cpu *cpu)
8247 {
8248   /* instr [28,25] = 1 111.  */
8249
8250   /* we are currently only interested in the basic
8251      scalar fp routines which all have bit 30 = 0.  */
8252   if (uimm (aarch64_get_instr (cpu), 30, 30))
8253     do_double_add (cpu);
8254
8255   /* instr[24] is set for FP data processing 3-source and clear for
8256      all other basic scalar fp instruction groups.  */
8257   else if (uimm (aarch64_get_instr (cpu), 24, 24))
8258     dexSimpleFPDataProc3Source (cpu);
8259
8260   /* instr[21] is clear for floating <-> fixed conversions and set for
8261      all other basic scalar fp instruction groups.  */
8262   else if (!uimm (aarch64_get_instr (cpu), 21, 21))
8263     dexSimpleFPFixedConvert (cpu);
8264
8265   /* instr[11,10] : 01 ==> cond compare, 10 ==> Data Proc 2 Source
8266      11 ==> cond select,  00 ==> other.  */
8267   else
8268     switch (uimm (aarch64_get_instr (cpu), 11, 10))
8269       {
8270       case 1: dexSimpleFPCondCompare (cpu); return;
8271       case 2: dexSimpleFPDataProc2Source (cpu); return;
8272       case 3: dexSimpleFPCondSelect (cpu); return;
8273
8274       default:
8275         /* Now an ordered cascade of tests.
8276            FP immediate has aarch64_get_instr (cpu)[12] == 1.
8277            FP compare has aarch64_get_instr (cpu)[13] == 1.
8278            FP Data Proc 1 Source has aarch64_get_instr (cpu)[14] == 1.
8279            FP floating <--> integer conversions has aarch64_get_instr (cpu)[15] == 0.  */
8280         if (uimm (aarch64_get_instr (cpu), 12, 12))
8281           dexSimpleFPImmediate (cpu);
8282
8283         else if (uimm (aarch64_get_instr (cpu), 13, 13))
8284           dexSimpleFPCompare (cpu);
8285
8286         else if (uimm (aarch64_get_instr (cpu), 14, 14))
8287           dexSimpleFPDataProc1Source (cpu);
8288
8289         else if (!uimm (aarch64_get_instr (cpu), 15, 15))
8290           dexSimpleFPIntegerConvert (cpu);
8291
8292         else
8293           /* If we get here then instr[15] == 1 which means UNALLOC.  */
8294           HALT_UNALLOC;
8295       }
8296 }
8297
8298 /* PC relative addressing.  */
8299
8300 static void
8301 pcadr (sim_cpu *cpu)
8302 {
8303   /* instr[31] = op : 0 ==> ADR, 1 ==> ADRP
8304      instr[30,29] = immlo
8305      instr[23,5] = immhi.  */
8306   uint64_t address;
8307   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8308   uint32_t isPage = uimm (aarch64_get_instr (cpu), 31, 31);
8309   union { int64_t u64; uint64_t s64; } imm;
8310   uint64_t offset;
8311
8312   imm.s64 = simm64 (aarch64_get_instr (cpu), 23, 5);
8313   offset = imm.u64;
8314   offset = (offset << 2) | uimm (aarch64_get_instr (cpu), 30, 29);
8315
8316   address = aarch64_get_PC (cpu);
8317
8318   if (isPage)
8319     {
8320       offset <<= 12;
8321       address &= ~0xfff;
8322     }
8323
8324   aarch64_set_reg_u64 (cpu, rd, NO_SP, address + offset);
8325 }
8326
8327 /* Specific decode and execute for group Data Processing Immediate.  */
8328
8329 static void
8330 dexPCRelAddressing (sim_cpu *cpu)
8331 {
8332   /* assert instr[28,24] = 10000.  */
8333   pcadr (cpu);
8334 }
8335
8336 /* Immediate logical.
8337    The bimm32/64 argument is constructed by replicating a 2, 4, 8,
8338    16, 32 or 64 bit sequence pulled out at decode and possibly
8339    inverting it..
8340
8341    N.B. the output register (dest) can normally be Xn or SP
8342    the exception occurs for flag setting instructions which may
8343    only use Xn for the output (dest).  The input register can
8344    never be SP.  */
8345
8346 /* 32 bit and immediate.  */
8347 static void
8348 and32 (sim_cpu *cpu, uint32_t bimm)
8349 {
8350   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8351   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8352
8353   aarch64_set_reg_u64 (cpu, rd, SP_OK,
8354                        aarch64_get_reg_u32 (cpu, rn, NO_SP) & bimm);
8355 }
8356
8357 /* 64 bit and immediate.  */
8358 static void
8359 and64 (sim_cpu *cpu, uint64_t bimm)
8360 {
8361   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8362   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8363
8364   aarch64_set_reg_u64 (cpu, rd, SP_OK,
8365                        aarch64_get_reg_u64 (cpu, rn, NO_SP) & bimm);
8366 }
8367
8368 /* 32 bit and immediate set flags.  */
8369 static void
8370 ands32 (sim_cpu *cpu, uint32_t bimm)
8371 {
8372   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8373   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8374
8375   uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8376   uint32_t value2 = bimm;
8377
8378   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8379   set_flags_for_binop32 (cpu, value1 & value2);
8380 }
8381
8382 /* 64 bit and immediate set flags.  */
8383 static void
8384 ands64 (sim_cpu *cpu, uint64_t bimm)
8385 {
8386   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8387   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8388
8389   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
8390   uint64_t value2 = bimm;
8391
8392   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8393   set_flags_for_binop64 (cpu, value1 & value2);
8394 }
8395
8396 /* 32 bit exclusive or immediate.  */
8397 static void
8398 eor32 (sim_cpu *cpu, uint32_t bimm)
8399 {
8400   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8401   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8402
8403   aarch64_set_reg_u64 (cpu, rd, SP_OK,
8404                        aarch64_get_reg_u32 (cpu, rn, NO_SP) ^ bimm);
8405 }
8406
8407 /* 64 bit exclusive or immediate.  */
8408 static void
8409 eor64 (sim_cpu *cpu, uint64_t bimm)
8410 {
8411   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8412   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8413
8414   aarch64_set_reg_u64 (cpu, rd, SP_OK,
8415                        aarch64_get_reg_u64 (cpu, rn, NO_SP) ^ bimm);
8416 }
8417
8418 /* 32 bit or immediate.  */
8419 static void
8420 orr32 (sim_cpu *cpu, uint32_t bimm)
8421 {
8422   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8423   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8424
8425   aarch64_set_reg_u64 (cpu, rd, SP_OK,
8426                        aarch64_get_reg_u32 (cpu, rn, NO_SP) | bimm);
8427 }
8428
8429 /* 64 bit or immediate.  */
8430 static void
8431 orr64 (sim_cpu *cpu, uint64_t bimm)
8432 {
8433   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8434   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8435
8436   aarch64_set_reg_u64 (cpu, rd, SP_OK,
8437                        aarch64_get_reg_u64 (cpu, rn, NO_SP) | bimm);
8438 }
8439
8440 /* Logical shifted register.
8441    These allow an optional LSL, ASR, LSR or ROR to the second source
8442    register with a count up to the register bit count.
8443    N.B register args may not be SP.  */
8444
8445 /* 32 bit AND shifted register.  */
8446 static void
8447 and32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8448 {
8449   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8450   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8451   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8452
8453   aarch64_set_reg_u64
8454     (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8455      & shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8456 }
8457
8458 /* 64 bit AND shifted register.  */
8459 static void
8460 and64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8461 {
8462   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8463   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8464   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8465
8466   aarch64_set_reg_u64
8467     (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8468      & shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8469 }
8470
8471 /* 32 bit AND shifted register setting flags.  */
8472 static void
8473 ands32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8474 {
8475   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8476   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8477   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8478
8479   uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8480   uint32_t value2 = shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
8481                                shift, count);
8482
8483   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8484   set_flags_for_binop32 (cpu, value1 & value2);
8485 }
8486
8487 /* 64 bit AND shifted register setting flags.  */
8488 static void
8489 ands64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8490 {
8491   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8492   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8493   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8494
8495   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
8496   uint64_t value2 = shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
8497                                shift, count);
8498
8499   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8500   set_flags_for_binop64 (cpu, value1 & value2);
8501 }
8502
8503 /* 32 bit BIC shifted register.  */
8504 static void
8505 bic32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8506 {
8507   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8508   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8509   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8510
8511   aarch64_set_reg_u64
8512     (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8513      & ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8514 }
8515
8516 /* 64 bit BIC shifted register.  */
8517 static void
8518 bic64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8519 {
8520   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8521   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8522   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8523
8524   aarch64_set_reg_u64
8525     (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8526      & ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8527 }
8528
8529 /* 32 bit BIC shifted register setting flags.  */
8530 static void
8531 bics32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8532 {
8533   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8534   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8535   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8536
8537   uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8538   uint32_t value2 = ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
8539                                  shift, count);
8540
8541   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8542   set_flags_for_binop32 (cpu, value1 & value2);
8543 }
8544
8545 /* 64 bit BIC shifted register setting flags.  */
8546 static void
8547 bics64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8548 {
8549   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8550   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8551   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8552
8553   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
8554   uint64_t value2 = ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
8555                                  shift, count);
8556
8557   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8558   set_flags_for_binop64 (cpu, value1 & value2);
8559 }
8560
8561 /* 32 bit EON shifted register.  */
8562 static void
8563 eon32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8564 {
8565   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8566   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8567   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8568
8569   aarch64_set_reg_u64
8570     (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8571      ^ ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8572 }
8573
8574 /* 64 bit EON shifted register.  */
8575 static void
8576 eon64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8577 {
8578   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8579   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8580   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8581
8582   aarch64_set_reg_u64
8583     (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8584      ^ ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8585 }
8586
8587 /* 32 bit EOR shifted register.  */
8588 static void
8589 eor32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8590 {
8591   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8592   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8593   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8594
8595   aarch64_set_reg_u64
8596     (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8597      ^ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8598 }
8599
8600 /* 64 bit EOR shifted register.  */
8601 static void
8602 eor64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8603 {
8604   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8605   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8606   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8607
8608   aarch64_set_reg_u64
8609     (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8610      ^ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8611 }
8612
8613 /* 32 bit ORR shifted register.  */
8614 static void
8615 orr32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8616 {
8617   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8618   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8619   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8620
8621   aarch64_set_reg_u64
8622     (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8623      | shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8624 }
8625
8626 /* 64 bit ORR shifted register.  */
8627 static void
8628 orr64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8629 {
8630   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8631   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8632   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8633
8634   aarch64_set_reg_u64
8635     (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8636      | shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8637 }
8638
8639 /* 32 bit ORN shifted register.  */
8640 static void
8641 orn32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8642 {
8643   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8644   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8645   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8646
8647   aarch64_set_reg_u64
8648     (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8649      | ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8650 }
8651
8652 /* 64 bit ORN shifted register.  */
8653 static void
8654 orn64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8655 {
8656   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8657   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8658   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8659
8660   aarch64_set_reg_u64
8661     (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8662      | ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8663 }
8664
8665 static void
8666 dexLogicalImmediate (sim_cpu *cpu)
8667 {
8668   /* assert instr[28,23] = 1001000
8669      instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
8670      instr[30,29] = op : 0 ==> AND, 1 ==> ORR, 2 ==> EOR, 3 ==> ANDS
8671      instr[22] = N : used to construct immediate mask
8672      instr[21,16] = immr
8673      instr[15,10] = imms
8674      instr[9,5] = Rn
8675      instr[4,0] = Rd  */
8676
8677   /* 32 bit operations must have N = 0 or else we have an UNALLOC.  */
8678   uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
8679   uint32_t N = uimm (aarch64_get_instr (cpu), 22, 22);
8680   /* uint32_t immr = uimm (aarch64_get_instr (cpu), 21, 16);.  */
8681   /* uint32_t imms = uimm (aarch64_get_instr (cpu), 15, 10);.  */
8682   uint32_t index = uimm (aarch64_get_instr (cpu), 22, 10);
8683   uint64_t bimm64 = LITable [index];
8684   uint32_t dispatch = uimm (aarch64_get_instr (cpu), 30, 29);
8685
8686   if (~size & N)
8687     HALT_UNALLOC;
8688
8689   if (!bimm64)
8690     HALT_UNALLOC;
8691
8692   if (size == 0)
8693     {
8694       uint32_t bimm = (uint32_t) bimm64;
8695
8696       switch (dispatch)
8697         {
8698         case 0: and32 (cpu, bimm); return;
8699         case 1: orr32 (cpu, bimm); return;
8700         case 2: eor32 (cpu, bimm); return;
8701         case 3: ands32 (cpu, bimm); return;
8702         }
8703     }
8704   else
8705     {
8706       switch (dispatch)
8707         {
8708         case 0: and64 (cpu, bimm64); return;
8709         case 1: orr64 (cpu, bimm64); return;
8710         case 2: eor64 (cpu, bimm64); return;
8711         case 3: ands64 (cpu, bimm64); return;
8712         }
8713     }
8714   HALT_UNALLOC;
8715 }
8716
8717 /* Immediate move.
8718    The uimm argument is a 16 bit value to be inserted into the
8719    target register the pos argument locates the 16 bit word in the
8720    dest register i.e. it is in {0, 1} for 32 bit and {0, 1, 2,
8721    3} for 64 bit.
8722    N.B register arg may not be SP so it should be.
8723    accessed using the setGZRegisterXXX accessors.  */
8724
8725 /* 32 bit move 16 bit immediate zero remaining shorts.  */
8726 static void
8727 movz32 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8728 {
8729   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8730
8731   aarch64_set_reg_u64 (cpu, rd, NO_SP, val << (pos * 16));
8732 }
8733
8734 /* 64 bit move 16 bit immediate zero remaining shorts.  */
8735 static void
8736 movz64 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8737 {
8738   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8739
8740   aarch64_set_reg_u64 (cpu, rd, NO_SP, ((uint64_t) val) << (pos * 16));
8741 }
8742
8743 /* 32 bit move 16 bit immediate negated.  */
8744 static void
8745 movn32 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8746 {
8747   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8748
8749   aarch64_set_reg_u64 (cpu, rd, NO_SP, ((val << (pos * 16)) ^ 0xffffffffU));
8750 }
8751
8752 /* 64 bit move 16 bit immediate negated.  */
8753 static void
8754 movn64 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8755 {
8756   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8757
8758   aarch64_set_reg_u64
8759     (cpu, rd, NO_SP, ((((uint64_t) val) << (pos * 16))
8760                       ^ 0xffffffffffffffffULL));
8761 }
8762
8763 /* 32 bit move 16 bit immediate keep remaining shorts.  */
8764 static void
8765 movk32 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8766 {
8767   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8768   uint32_t current = aarch64_get_reg_u32 (cpu, rd, NO_SP);
8769   uint32_t value = val << (pos * 16);
8770   uint32_t mask = ~(0xffffU << (pos * 16));
8771
8772   aarch64_set_reg_u64 (cpu, rd, NO_SP, (value | (current & mask)));
8773 }
8774
8775 /* 64 bit move 16 it immediate keep remaining shorts.  */
8776 static void
8777 movk64 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8778 {
8779   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8780   uint64_t current = aarch64_get_reg_u64 (cpu, rd, NO_SP);
8781   uint64_t value = (uint64_t) val << (pos * 16);
8782   uint64_t mask = ~(0xffffULL << (pos * 16));
8783
8784   aarch64_set_reg_u64 (cpu, rd, NO_SP, (value | (current & mask)));
8785 }
8786
8787 static void
8788 dexMoveWideImmediate (sim_cpu *cpu)
8789 {
8790   /* assert instr[28:23] = 100101
8791      instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
8792      instr[30,29] = op : 0 ==> MOVN, 1 ==> UNALLOC, 2 ==> MOVZ, 3 ==> MOVK
8793      instr[22,21] = shift : 00 == LSL#0, 01 = LSL#16, 10 = LSL#32, 11 = LSL#48
8794      instr[20,5] = uimm16
8795      instr[4,0] = Rd  */
8796
8797   /* N.B. the (multiple of 16) shift is applied by the called routine,
8798      we just pass the multiplier.  */
8799
8800   uint32_t imm;
8801   uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
8802   uint32_t op = uimm (aarch64_get_instr (cpu), 30, 29);
8803   uint32_t shift = uimm (aarch64_get_instr (cpu), 22, 21);
8804
8805   /* 32 bit can only shift 0 or 1 lot of 16.
8806      anything else is an unallocated instruction.  */
8807   if (size == 0 && (shift > 1))
8808     HALT_UNALLOC;
8809
8810   if (op == 1)
8811     HALT_UNALLOC;
8812
8813   imm = uimm (aarch64_get_instr (cpu), 20, 5);
8814
8815   if (size == 0)
8816     {
8817       if (op == 0)
8818         movn32 (cpu, imm, shift);
8819       else if (op == 2)
8820         movz32 (cpu, imm, shift);
8821       else
8822         movk32 (cpu, imm, shift);
8823     }
8824   else
8825     {
8826       if (op == 0)
8827         movn64 (cpu, imm, shift);
8828       else if (op == 2)
8829         movz64 (cpu, imm, shift);
8830       else
8831         movk64 (cpu, imm, shift);
8832     }
8833 }
8834
8835 /* Bitfield operations.
8836    These take a pair of bit positions r and s which are in {0..31}
8837    or {0..63} depending on the instruction word size.
8838    N.B register args may not be SP.  */
8839
8840 /* OK, we start with ubfm which just needs to pick
8841    some bits out of source zero the rest and write
8842    the result to dest.  Just need two logical shifts.  */
8843
8844 /* 32 bit bitfield move, left and right of affected zeroed
8845    if r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>.  */
8846 static void
8847 ubfm32 (sim_cpu *cpu, uint32_t r, uint32_t s)
8848 {
8849   unsigned rd;
8850   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8851   uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8852
8853   /* Pick either s+1-r or s+1 consecutive bits out of the original word.  */
8854   if (r <= s)
8855     {
8856       /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
8857          We want only bits s:xxx:r at the bottom of the word
8858          so we LSL bit s up to bit 31 i.e. by 31 - s
8859          and then we LSR to bring bit 31 down to bit s - r
8860          i.e. by 31 + r - s.  */
8861       value <<= 31 - s;
8862       value >>= 31 + r - s;
8863     }
8864   else
8865     {
8866       /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0
8867          We want only bits s:xxx:0 starting at it 31-(r-1)
8868          so we LSL bit s up to bit 31 i.e. by 31 - s
8869          and then we LSL to bring bit 31 down to 31-(r-1)+s
8870          i.e. by r - (s + 1).  */
8871       value <<= 31 - s;
8872       value >>= r - (s + 1);
8873     }
8874
8875   rd = uimm (aarch64_get_instr (cpu), 4, 0);
8876   aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
8877 }
8878
8879 /* 64 bit bitfield move, left and right of affected zeroed
8880    if r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>.  */
8881 static void
8882 ubfm (sim_cpu *cpu, uint32_t r, uint32_t s)
8883 {
8884   unsigned rd;
8885   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8886   uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
8887
8888   if (r <= s)
8889     {
8890       /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
8891          We want only bits s:xxx:r at the bottom of the word.
8892          So we LSL bit s up to bit 63 i.e. by 63 - s
8893          and then we LSR to bring bit 63 down to bit s - r
8894          i.e. by 63 + r - s.  */
8895       value <<= 63 - s;
8896       value >>= 63 + r - s;
8897     }
8898   else
8899     {
8900       /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0.
8901          We want only bits s:xxx:0 starting at it 63-(r-1).
8902          So we LSL bit s up to bit 63 i.e. by 63 - s
8903          and then we LSL to bring bit 63 down to 63-(r-1)+s
8904          i.e. by r - (s + 1).  */
8905       value <<= 63 - s;
8906       value >>= r - (s + 1);
8907     }
8908
8909   rd = uimm (aarch64_get_instr (cpu), 4, 0);
8910   aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
8911 }
8912
8913 /* The signed versions need to insert sign bits
8914    on the left of the inserted bit field. so we do
8915    much the same as the unsigned version except we
8916    use an arithmetic shift right -- this just means
8917    we need to operate on signed values.  */
8918
8919 /* 32 bit bitfield move, left of affected sign-extended, right zeroed.  */
8920 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>.  */
8921 static void
8922 sbfm32 (sim_cpu *cpu, uint32_t r, uint32_t s)
8923 {
8924   unsigned rd;
8925   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8926   /* as per ubfm32 but use an ASR instead of an LSR.  */
8927   int32_t value = aarch64_get_reg_s32 (cpu, rn, NO_SP);
8928
8929   if (r <= s)
8930     {
8931       value <<= 31 - s;
8932       value >>= 31 + r - s;
8933     }
8934   else
8935     {
8936       value <<= 31 - s;
8937       value >>= r - (s + 1);
8938     }
8939
8940   rd = uimm (aarch64_get_instr (cpu), 4, 0);
8941   aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) value);
8942 }
8943
8944 /* 64 bit bitfield move, left of affected sign-extended, right zeroed.  */
8945 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>.  */
8946 static void
8947 sbfm (sim_cpu *cpu, uint32_t r, uint32_t s)
8948 {
8949   unsigned rd;
8950   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8951   /* acpu per ubfm but use an ASR instead of an LSR.  */
8952   int64_t value = aarch64_get_reg_s64 (cpu, rn, NO_SP);
8953
8954   if (r <= s)
8955     {
8956       value <<= 63 - s;
8957       value >>= 63 + r - s;
8958     }
8959   else
8960     {
8961       value <<= 63 - s;
8962       value >>= r - (s + 1);
8963     }
8964
8965   rd = uimm (aarch64_get_instr (cpu), 4, 0);
8966   aarch64_set_reg_s64 (cpu, rd, NO_SP, value);
8967 }
8968
8969 /* Finally, these versions leave non-affected bits
8970    as is. so we need to generate the bits as per
8971    ubfm and also generate a mask to pick the
8972    bits from the original and computed values.  */
8973
8974 /* 32 bit bitfield move, non-affected bits left as is.
8975    If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>.  */
8976 static void
8977 bfm32 (sim_cpu *cpu, uint32_t r, uint32_t s)
8978 {
8979   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8980   uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8981   uint32_t mask = -1;
8982   unsigned rd;
8983   uint32_t value2;
8984
8985   /* Pick either s+1-r or s+1 consecutive bits out of the original word.  */
8986   if (r <= s)
8987     {
8988       /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
8989          We want only bits s:xxx:r at the bottom of the word
8990          so we LSL bit s up to bit 31 i.e. by 31 - s
8991          and then we LSR to bring bit 31 down to bit s - r
8992          i.e. by 31 + r - s.  */
8993       value <<= 31 - s;
8994       value >>= 31 + r - s;
8995       /* the mask must include the same bits.  */
8996       mask <<= 31 - s;
8997       mask >>= 31 + r - s;
8998     }
8999   else
9000     {
9001       /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0.
9002          We want only bits s:xxx:0 starting at it 31-(r-1)
9003          so we LSL bit s up to bit 31 i.e. by 31 - s
9004          and then we LSL to bring bit 31 down to 31-(r-1)+s
9005          i.e. by r - (s + 1).  */
9006       value <<= 31 - s;
9007       value >>= r - (s + 1);
9008       /* The mask must include the same bits.  */
9009       mask <<= 31 - s;
9010       mask >>= r - (s + 1);
9011     }
9012
9013   rd = uimm (aarch64_get_instr (cpu), 4, 0);
9014   value2 = aarch64_get_reg_u32 (cpu, rd, NO_SP);
9015
9016   value2 &= ~mask;
9017   value2 |= value;
9018
9019   aarch64_set_reg_u64
9020     (cpu, rd, NO_SP, (aarch64_get_reg_u32 (cpu, rd, NO_SP) & ~mask) | value);
9021 }
9022
9023 /* 64 bit bitfield move, non-affected bits left as is.
9024    If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>.  */
9025 static void
9026 bfm (sim_cpu *cpu, uint32_t r, uint32_t s)
9027 {
9028   unsigned rd;
9029   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9030   uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
9031   uint64_t mask = 0xffffffffffffffffULL;
9032
9033   if (r <= s)
9034     {
9035       /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
9036          We want only bits s:xxx:r at the bottom of the word
9037          so we LSL bit s up to bit 63 i.e. by 63 - s
9038          and then we LSR to bring bit 63 down to bit s - r
9039          i.e. by 63 + r - s.  */
9040       value <<= 63 - s;
9041       value >>= 63 + r - s;
9042       /* The mask must include the same bits.  */
9043       mask <<= 63 - s;
9044       mask >>= 63 + r - s;
9045     }
9046   else
9047     {
9048       /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0
9049          We want only bits s:xxx:0 starting at it 63-(r-1)
9050          so we LSL bit s up to bit 63 i.e. by 63 - s
9051          and then we LSL to bring bit 63 down to 63-(r-1)+s
9052          i.e. by r - (s + 1).  */
9053       value <<= 63 - s;
9054       value >>= r - (s + 1);
9055       /* The mask must include the same bits.  */
9056       mask <<= 63 - s;
9057       mask >>= r - (s + 1);
9058     }
9059
9060   rd = uimm (aarch64_get_instr (cpu), 4, 0);
9061   aarch64_set_reg_u64
9062     (cpu, rd, NO_SP, (aarch64_get_reg_u64 (cpu, rd, NO_SP) & ~mask) | value);
9063 }
9064
9065 static void
9066 dexBitfieldImmediate (sim_cpu *cpu)
9067 {
9068   /* assert instr[28:23] = 100110
9069      instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9070      instr[30,29] = op : 0 ==> SBFM, 1 ==> BFM, 2 ==> UBFM, 3 ==> UNALLOC
9071      instr[22] = N : must be 0 for 32 bit, 1 for 64 bit ow UNALLOC
9072      instr[21,16] = immr : 0xxxxx for 32 bit, xxxxxx for 64 bit
9073      instr[15,10] = imms :  0xxxxx for 32 bit, xxxxxx for 64 bit
9074      instr[9,5] = Rn
9075      instr[4,0] = Rd  */
9076
9077   /* 32 bit operations must have N = 0 or else we have an UNALLOC.  */
9078   uint32_t dispatch;
9079   uint32_t imms;
9080   uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
9081   uint32_t N = uimm (aarch64_get_instr (cpu), 22, 22);
9082   /* 32 bit operations must have immr[5] = 0 and imms[5] = 0.  */
9083   /* or else we have an UNALLOC.  */
9084   uint32_t immr = uimm (aarch64_get_instr (cpu), 21, 16);
9085
9086   if (~size & N)
9087     HALT_UNALLOC;
9088
9089   if (!size && uimm (immr, 5, 5))
9090     HALT_UNALLOC;
9091
9092   imms = uimm (aarch64_get_instr (cpu), 15, 10);
9093   if (!size && uimm (imms, 5, 5))
9094     HALT_UNALLOC;
9095
9096   /* Switch on combined size and op.  */
9097   dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
9098   switch (dispatch)
9099     {
9100     case 0: sbfm32 (cpu, immr, imms); return;
9101     case 1: bfm32 (cpu, immr, imms); return;
9102     case 2: ubfm32 (cpu, immr, imms); return;
9103     case 4: sbfm (cpu, immr, imms); return;
9104     case 5: bfm (cpu, immr, imms); return;
9105     case 6: ubfm (cpu, immr, imms); return;
9106     default: HALT_UNALLOC;
9107     }
9108 }
9109
9110 static void
9111 do_EXTR_32 (sim_cpu *cpu)
9112 {
9113   /* instr[31:21] = 00010011100
9114      instr[20,16] = Rm
9115      instr[15,10] = imms :  0xxxxx for 32 bit
9116      instr[9,5]   = Rn
9117      instr[4,0]   = Rd  */
9118   unsigned rm   = uimm (aarch64_get_instr (cpu), 20, 16);
9119   unsigned imms = uimm (aarch64_get_instr (cpu), 15, 10) & 31;
9120   unsigned rn   = uimm (aarch64_get_instr (cpu),  9,  5);
9121   unsigned rd   = uimm (aarch64_get_instr (cpu),  4,  0);
9122   uint64_t val1;
9123   uint64_t val2;
9124
9125   val1 = aarch64_get_reg_u32 (cpu, rm, NO_SP);
9126   val1 >>= imms;
9127   val2 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
9128   val2 <<= (32 - imms);
9129
9130   aarch64_set_reg_u64 (cpu, rd, NO_SP, val1 | val2);
9131 }
9132
9133 static void
9134 do_EXTR_64 (sim_cpu *cpu)
9135 {
9136   /* instr[31:21] = 10010011100
9137      instr[20,16] = Rm
9138      instr[15,10] = imms
9139      instr[9,5]   = Rn
9140      instr[4,0]   = Rd  */
9141   unsigned rm   = uimm (aarch64_get_instr (cpu), 20, 16);
9142   unsigned imms = uimm (aarch64_get_instr (cpu), 15, 10) & 63;
9143   unsigned rn   = uimm (aarch64_get_instr (cpu),  9,  5);
9144   unsigned rd   = uimm (aarch64_get_instr (cpu),  4,  0);
9145   uint64_t val;
9146
9147   val = aarch64_get_reg_u64 (cpu, rm, NO_SP);
9148   val >>= imms;
9149   val |= (aarch64_get_reg_u64 (cpu, rn, NO_SP) << (64 - imms));
9150
9151   aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
9152 }
9153
9154 static void
9155 dexExtractImmediate (sim_cpu *cpu)
9156 {
9157   /* assert instr[28:23] = 100111
9158      instr[31]    = size : 0 ==> 32 bit, 1 ==> 64 bit
9159      instr[30,29] = op21 : 0 ==> EXTR, 1,2,3 ==> UNALLOC
9160      instr[22]    = N : must be 0 for 32 bit, 1 for 64 bit or UNALLOC
9161      instr[21]    = op0 : must be 0 or UNALLOC
9162      instr[20,16] = Rm
9163      instr[15,10] = imms :  0xxxxx for 32 bit, xxxxxx for 64 bit
9164      instr[9,5]   = Rn
9165      instr[4,0]   = Rd  */
9166
9167   /* 32 bit operations must have N = 0 or else we have an UNALLOC.  */
9168   /* 64 bit operations must have N = 1 or else we have an UNALLOC.  */
9169   uint32_t dispatch;
9170   uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
9171   uint32_t N = uimm (aarch64_get_instr (cpu), 22, 22);
9172   /* 32 bit operations must have imms[5] = 0
9173      or else we have an UNALLOC.  */
9174   uint32_t imms = uimm (aarch64_get_instr (cpu), 15, 10);
9175
9176   if (size ^ N)
9177     HALT_UNALLOC;
9178
9179   if (!size && uimm (imms, 5, 5))
9180     HALT_UNALLOC;
9181
9182   /* Switch on combined size and op.  */
9183   dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
9184
9185   if (dispatch == 0)
9186     do_EXTR_32 (cpu);
9187
9188   else if (dispatch == 4)
9189     do_EXTR_64 (cpu);
9190
9191   else if (dispatch == 1)
9192     HALT_NYI;
9193   else
9194     HALT_UNALLOC;
9195 }
9196
9197 static void
9198 dexDPImm (sim_cpu *cpu)
9199 {
9200   /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
9201      assert  group == GROUP_DPIMM_1000 || grpoup == GROUP_DPIMM_1001
9202      bits [25,23] of a DPImm are the secondary dispatch vector.  */
9203   uint32_t group2 = dispatchDPImm (aarch64_get_instr (cpu));
9204
9205   switch (group2)
9206     {
9207     case DPIMM_PCADR_000:
9208     case DPIMM_PCADR_001:
9209       dexPCRelAddressing (cpu);
9210       return;
9211
9212     case DPIMM_ADDSUB_010:
9213     case DPIMM_ADDSUB_011:
9214       dexAddSubtractImmediate (cpu);
9215       return;
9216
9217     case DPIMM_LOG_100:
9218       dexLogicalImmediate (cpu);
9219       return;
9220
9221     case DPIMM_MOV_101:
9222       dexMoveWideImmediate (cpu);
9223       return;
9224
9225     case DPIMM_BITF_110:
9226       dexBitfieldImmediate (cpu);
9227       return;
9228
9229     case DPIMM_EXTR_111:
9230       dexExtractImmediate (cpu);
9231       return;
9232
9233     default:
9234       /* Should never reach here.  */
9235       HALT_NYI;
9236     }
9237 }
9238
9239 static void
9240 dexLoadUnscaledImmediate (sim_cpu *cpu)
9241 {
9242   /* instr[29,24] == 111_00
9243      instr[21] == 0
9244      instr[11,10] == 00
9245      instr[31,30] = size
9246      instr[26] = V
9247      instr[23,22] = opc
9248      instr[20,12] = simm9
9249      instr[9,5] = rn may be SP.  */
9250   /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);  */
9251   uint32_t V = uimm (aarch64_get_instr (cpu), 26, 26);
9252   uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
9253                         | uimm (aarch64_get_instr (cpu), 23, 22));
9254   int32_t imm = simm32 (aarch64_get_instr (cpu), 20, 12);
9255
9256   if (!V)
9257     {
9258       /* GReg operations.  */
9259       switch (dispatch)
9260         {
9261         case 0:  sturb (cpu, imm); return;
9262         case 1:  ldurb32 (cpu, imm); return;
9263         case 2:  ldursb64 (cpu, imm); return;
9264         case 3:  ldursb32 (cpu, imm); return;
9265         case 4:  sturh (cpu, imm); return;
9266         case 5:  ldurh32 (cpu, imm); return;
9267         case 6:  ldursh64 (cpu, imm); return;
9268         case 7:  ldursh32 (cpu, imm); return;
9269         case 8:  stur32 (cpu, imm); return;
9270         case 9:  ldur32 (cpu, imm); return;
9271         case 10: ldursw (cpu, imm); return;
9272         case 12: stur64 (cpu, imm); return;
9273         case 13: ldur64 (cpu, imm); return;
9274
9275         case 14:
9276           /* PRFUM NYI.  */
9277           HALT_NYI;
9278
9279         default:
9280         case 11:
9281         case 15:
9282           HALT_UNALLOC;
9283         }
9284     }
9285
9286   /* FReg operations.  */
9287   switch (dispatch)
9288     {
9289     case 2:  fsturq (cpu, imm); return;
9290     case 3:  fldurq (cpu, imm); return;
9291     case 8:  fsturs (cpu, imm); return;
9292     case 9:  fldurs (cpu, imm); return;
9293     case 12: fsturd (cpu, imm); return;
9294     case 13: fldurd (cpu, imm); return;
9295
9296     case 0: /* STUR 8 bit FP.  */
9297     case 1: /* LDUR 8 bit FP.  */
9298     case 4: /* STUR 16 bit FP.  */
9299     case 5: /* LDUR 8 bit FP.  */
9300       HALT_NYI;
9301
9302     default:
9303     case 6:
9304     case 7:
9305     case 10:
9306     case 11:
9307     case 14:
9308     case 15:
9309       HALT_UNALLOC;
9310     }
9311 }
9312
9313 /*  N.B. A preliminary note regarding all the ldrs<x>32
9314     instructions
9315
9316    The signed value loaded by these instructions is cast to unsigned
9317    before being assigned to aarch64_get_reg_u64 (cpu, N) i.e. to the
9318    64 bit element of the GReg union. this performs a 32 bit sign extension
9319    (as required) but avoids 64 bit sign extension, thus ensuring that the
9320    top half of the register word is zero. this is what the spec demands
9321    when a 32 bit load occurs.  */
9322
9323 /* 32 bit load sign-extended byte scaled unsigned 12 bit.  */
9324 static void
9325 ldrsb32_abs (sim_cpu *cpu, uint32_t offset)
9326 {
9327   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
9328   unsigned int rt = uimm (aarch64_get_instr (cpu), 4, 0);
9329
9330   /* The target register may not be SP but the source may be
9331      there is no scaling required for a byte load.  */
9332   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset;
9333   aarch64_set_reg_u64 (cpu, rt, NO_SP,
9334                        (int64_t) aarch64_get_mem_s8 (cpu, address));
9335 }
9336
9337 /* 32 bit load sign-extended byte scaled or unscaled zero-
9338    or sign-extended 32-bit register offset.  */
9339 static void
9340 ldrsb32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9341 {
9342   unsigned int rm = uimm (aarch64_get_instr (cpu), 20, 16);
9343   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
9344   unsigned int rt = uimm (aarch64_get_instr (cpu), 4, 0);
9345
9346   /* rn may reference SP, rm and rt must reference ZR.  */
9347
9348   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9349   int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9350                                  extension);
9351
9352   /* There is no scaling required for a byte load.  */
9353   aarch64_set_reg_u64
9354     (cpu, rt, NO_SP, (int64_t) aarch64_get_mem_s8 (cpu, address
9355                                                    + displacement));
9356 }
9357
9358 /* 32 bit load sign-extended byte unscaled signed 9 bit with
9359    pre- or post-writeback.  */
9360 static void
9361 ldrsb32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9362 {
9363   uint64_t address;
9364   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
9365   unsigned int rt = uimm (aarch64_get_instr (cpu), 4, 0);
9366
9367   if (rn == rt && wb != NoWriteBack)
9368     HALT_UNALLOC;
9369
9370   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9371
9372   if (wb == Pre)
9373       address += offset;
9374
9375   aarch64_set_reg_u64 (cpu, rt, NO_SP,
9376                        (int64_t) aarch64_get_mem_s8 (cpu, address));
9377
9378   if (wb == Post)
9379     address += offset;
9380
9381   if (wb != NoWriteBack)
9382     aarch64_set_reg_u64 (cpu, rn, NO_SP, address);
9383 }
9384
9385 /* 8 bit store scaled.  */
9386 static void
9387 fstrb_abs (sim_cpu *cpu, uint32_t offset)
9388 {
9389   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9390   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9391
9392   aarch64_set_mem_u8 (cpu,
9393                       aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
9394                       aarch64_get_vec_u8 (cpu, st, 0));
9395 }
9396
9397 /* 8 bit store scaled or unscaled zero- or
9398    sign-extended 8-bit register offset.  */
9399 static void
9400 fstrb_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9401 {
9402   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9403   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9404   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9405
9406   uint64_t  address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9407   int64_t   extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9408                                extension);
9409   uint64_t  displacement = OPT_SCALE (extended, 32, scaling);
9410
9411   aarch64_set_mem_u8
9412     (cpu, address + displacement, aarch64_get_vec_u8 (cpu, st, 0));
9413 }
9414
9415 /* 16 bit store scaled.  */
9416 static void
9417 fstrh_abs (sim_cpu *cpu, uint32_t offset)
9418 {
9419   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9420   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9421
9422   aarch64_set_mem_u16
9423     (cpu,
9424      aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 16),
9425      aarch64_get_vec_u16 (cpu, st, 0));
9426 }
9427
9428 /* 16 bit store scaled or unscaled zero-
9429    or sign-extended 16-bit register offset.  */
9430 static void
9431 fstrh_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9432 {
9433   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9434   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9435   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9436
9437   uint64_t  address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9438   int64_t   extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9439                                extension);
9440   uint64_t  displacement = OPT_SCALE (extended, 32, scaling);
9441
9442   aarch64_set_mem_u16
9443     (cpu, address + displacement, aarch64_get_vec_u16 (cpu, st, 0));
9444 }
9445
9446 /* 32 bit store scaled unsigned 12 bit.  */
9447 static void
9448 fstrs_abs (sim_cpu *cpu, uint32_t offset)
9449 {
9450   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9451   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9452
9453   aarch64_set_mem_float
9454     (cpu,
9455      aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 32),
9456      aarch64_get_FP_float (cpu, st));
9457 }
9458
9459 /* 32 bit store unscaled signed 9 bit with pre- or post-writeback.  */
9460 static void
9461 fstrs_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9462 {
9463   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9464   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9465
9466   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9467
9468   if (wb != Post)
9469     address += offset;
9470
9471   aarch64_set_mem_float (cpu, address, aarch64_get_FP_float (cpu, st));
9472
9473   if (wb == Post)
9474     address += offset;
9475
9476   if (wb != NoWriteBack)
9477     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
9478 }
9479
9480 /* 32 bit store scaled or unscaled zero-
9481    or sign-extended 32-bit register offset.  */
9482 static void
9483 fstrs_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9484 {
9485   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9486   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9487   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9488
9489   uint64_t  address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9490   int64_t   extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9491                                extension);
9492   uint64_t  displacement = OPT_SCALE (extended, 32, scaling);
9493
9494   aarch64_set_mem_float
9495     (cpu, address + displacement, aarch64_get_FP_float (cpu, st));
9496 }
9497
9498 /* 64 bit store scaled unsigned 12 bit.  */
9499 static void
9500 fstrd_abs (sim_cpu *cpu, uint32_t offset)
9501 {
9502   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9503   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9504
9505   aarch64_set_mem_double
9506     (cpu,
9507      aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 64),
9508      aarch64_get_FP_double (cpu, st));
9509 }
9510
9511 /* 64 bit store unscaled signed 9 bit with pre- or post-writeback.  */
9512 static void
9513 fstrd_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9514 {
9515   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9516   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9517
9518   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9519
9520   if (wb != Post)
9521     address += offset;
9522
9523   aarch64_set_mem_double (cpu, address, aarch64_get_FP_double (cpu, st));
9524
9525   if (wb == Post)
9526     address += offset;
9527
9528   if (wb != NoWriteBack)
9529     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
9530 }
9531
9532 /* 64 bit store scaled or unscaled zero-
9533    or sign-extended 32-bit register offset.  */
9534 static void
9535 fstrd_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9536 {
9537   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9538   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9539   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9540
9541   uint64_t  address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9542   int64_t   extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9543                                extension);
9544   uint64_t  displacement = OPT_SCALE (extended, 64, scaling);
9545
9546   aarch64_set_mem_double
9547     (cpu, address + displacement, aarch64_get_FP_double (cpu, st));
9548 }
9549
9550 /* 128 bit store scaled unsigned 12 bit.  */
9551 static void
9552 fstrq_abs (sim_cpu *cpu, uint32_t offset)
9553 {
9554   FRegister a;
9555   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9556   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9557   uint64_t addr;
9558
9559   aarch64_get_FP_long_double (cpu, st, & a);
9560
9561   addr = aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 128);
9562   aarch64_set_mem_long_double (cpu, addr, a);
9563 }
9564
9565 /* 128 bit store unscaled signed 9 bit with pre- or post-writeback.  */
9566 static void
9567 fstrq_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9568 {
9569   FRegister a;
9570   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9571   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9572   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9573
9574   if (wb != Post)
9575     address += offset;
9576
9577   aarch64_get_FP_long_double (cpu, st, & a);
9578   aarch64_set_mem_long_double (cpu, address, a);
9579
9580   if (wb == Post)
9581     address += offset;
9582
9583   if (wb != NoWriteBack)
9584     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
9585 }
9586
9587 /* 128 bit store scaled or unscaled zero-
9588    or sign-extended 32-bit register offset.  */
9589 static void
9590 fstrq_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9591 {
9592   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9593   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9594   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9595
9596   uint64_t  address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9597   int64_t   extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9598                                extension);
9599   uint64_t  displacement = OPT_SCALE (extended, 128, scaling);
9600
9601   FRegister a;
9602
9603   aarch64_get_FP_long_double (cpu, st, & a);
9604   aarch64_set_mem_long_double (cpu, address + displacement, a);
9605 }
9606
9607 static void
9608 dexLoadImmediatePrePost (sim_cpu *cpu)
9609 {
9610   /* instr[29,24] == 111_00
9611      instr[21] == 0
9612      instr[11,10] == 00
9613      instr[31,30] = size
9614      instr[26] = V
9615      instr[23,22] = opc
9616      instr[20,12] = simm9
9617      instr[11] = wb : 0 ==> Post, 1 ==> Pre
9618      instr[9,5] = rn may be SP.  */
9619   /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0); */
9620   uint32_t V = uimm (aarch64_get_instr (cpu), 26, 26);
9621   uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
9622                        | uimm (aarch64_get_instr (cpu), 23, 22));
9623   int32_t imm = simm32 (aarch64_get_instr (cpu), 20, 12);
9624   WriteBack wb = writeback (aarch64_get_instr (cpu), 11);
9625
9626   if (!V)
9627     {
9628       /* GReg operations.  */
9629       switch (dispatch)
9630         {
9631         case 0:  strb_wb (cpu, imm, wb); return;
9632         case 1:  ldrb32_wb (cpu, imm, wb); return;
9633         case 2:  ldrsb_wb (cpu, imm, wb); return;
9634         case 3:  ldrsb32_wb (cpu, imm, wb); return;
9635         case 4:  strh_wb (cpu, imm, wb); return;
9636         case 5:  ldrh32_wb (cpu, imm, wb); return;
9637         case 6:  ldrsh64_wb (cpu, imm, wb); return;
9638         case 7:  ldrsh32_wb (cpu, imm, wb); return;
9639         case 8:  str32_wb (cpu, imm, wb); return;
9640         case 9:  ldr32_wb (cpu, imm, wb); return;
9641         case 10: ldrsw_wb (cpu, imm, wb); return;
9642         case 12: str_wb (cpu, imm, wb); return;
9643         case 13: ldr_wb (cpu, imm, wb); return;
9644
9645         default:
9646         case 11:
9647         case 14:
9648         case 15:
9649           HALT_UNALLOC;
9650         }
9651     }
9652
9653   /* FReg operations.  */
9654   switch (dispatch)
9655     {
9656     case 2:  fstrq_wb (cpu, imm, wb); return;
9657     case 3:  fldrq_wb (cpu, imm, wb); return;
9658     case 8:  fstrs_wb (cpu, imm, wb); return;
9659     case 9:  fldrs_wb (cpu, imm, wb); return;
9660     case 12: fstrd_wb (cpu, imm, wb); return;
9661     case 13: fldrd_wb (cpu, imm, wb); return;
9662
9663     case 0:       /* STUR 8 bit FP.  */
9664     case 1:       /* LDUR 8 bit FP.  */
9665     case 4:       /* STUR 16 bit FP.  */
9666     case 5:       /* LDUR 8 bit FP.  */
9667       HALT_NYI;
9668
9669     default:
9670     case 6:
9671     case 7:
9672     case 10:
9673     case 11:
9674     case 14:
9675     case 15:
9676       HALT_UNALLOC;
9677     }
9678 }
9679
9680 static void
9681 dexLoadRegisterOffset (sim_cpu *cpu)
9682 {
9683   /* instr[31,30] = size
9684      instr[29,27] = 111
9685      instr[26]    = V
9686      instr[25,24] = 00
9687      instr[23,22] = opc
9688      instr[21]    = 1
9689      instr[20,16] = rm
9690      instr[15,13] = option : 010 ==> UXTW, 011 ==> UXTX/LSL,
9691                              110 ==> SXTW, 111 ==> SXTX,
9692                              ow ==> RESERVED
9693      instr[12]    = scaled
9694      instr[11,10] = 10
9695      instr[9,5]   = rn
9696      instr[4,0]   = rt.  */
9697
9698   uint32_t V = uimm (aarch64_get_instr (cpu), 26,26);
9699   uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
9700                        | uimm (aarch64_get_instr (cpu), 23, 22));
9701   Scaling scale = scaling (aarch64_get_instr (cpu), 12);
9702   Extension extensionType = extension (aarch64_get_instr (cpu), 13);
9703
9704   /* Check for illegal extension types.  */
9705   if (uimm (extensionType, 1, 1) == 0)
9706     HALT_UNALLOC;
9707
9708   if (extensionType == UXTX || extensionType == SXTX)
9709     extensionType = NoExtension;
9710
9711   if (!V)
9712     {
9713       /* GReg operations.  */
9714       switch (dispatch)
9715         {
9716         case 0:  strb_scale_ext (cpu, scale, extensionType); return;
9717         case 1:  ldrb32_scale_ext (cpu, scale, extensionType); return;
9718         case 2:  ldrsb_scale_ext (cpu, scale, extensionType); return;
9719         case 3:  ldrsb32_scale_ext (cpu, scale, extensionType); return;
9720         case 4:  strh_scale_ext (cpu, scale, extensionType); return;
9721         case 5:  ldrh32_scale_ext (cpu, scale, extensionType); return;
9722         case 6:  ldrsh_scale_ext (cpu, scale, extensionType); return;
9723         case 7:  ldrsh32_scale_ext (cpu, scale, extensionType); return;
9724         case 8:  str32_scale_ext (cpu, scale, extensionType); return;
9725         case 9:  ldr32_scale_ext (cpu, scale, extensionType); return;
9726         case 10: ldrsw_scale_ext (cpu, scale, extensionType); return;
9727         case 12: str_scale_ext (cpu, scale, extensionType); return;
9728         case 13: ldr_scale_ext (cpu, scale, extensionType); return;
9729         case 14: prfm_scale_ext (cpu, scale, extensionType); return;
9730
9731         default:
9732         case 11:
9733         case 15:
9734           HALT_UNALLOC;
9735         }
9736     }
9737
9738   /* FReg operations.  */
9739   switch (dispatch)
9740     {
9741     case 1: /* LDUR 8 bit FP.  */
9742       HALT_NYI;
9743     case 3:  fldrq_scale_ext (cpu, scale, extensionType); return;
9744     case 5: /* LDUR 8 bit FP.  */
9745       HALT_NYI;
9746     case 9:  fldrs_scale_ext (cpu, scale, extensionType); return;
9747     case 13: fldrd_scale_ext (cpu, scale, extensionType); return;
9748
9749     case 0:  fstrb_scale_ext (cpu, scale, extensionType); return;
9750     case 2:  fstrq_scale_ext (cpu, scale, extensionType); return;
9751     case 4:  fstrh_scale_ext (cpu, scale, extensionType); return;
9752     case 8:  fstrs_scale_ext (cpu, scale, extensionType); return;
9753     case 12: fstrd_scale_ext (cpu, scale, extensionType); return;
9754
9755     default:
9756     case 6:
9757     case 7:
9758     case 10:
9759     case 11:
9760     case 14:
9761     case 15:
9762       HALT_UNALLOC;
9763     }
9764 }
9765
9766 static void
9767 dexLoadUnsignedImmediate (sim_cpu *cpu)
9768 {
9769   /* assert instr[29,24] == 111_01
9770      instr[31,30] = size
9771      instr[26] = V
9772      instr[23,22] = opc
9773      instr[21,10] = uimm12 : unsigned immediate offset
9774      instr[9,5] = rn may be SP.  */
9775   /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0); */
9776   uint32_t V = uimm (aarch64_get_instr (cpu), 26,26);
9777   uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
9778                        | uimm (aarch64_get_instr (cpu), 23, 22));
9779   uint32_t imm = uimm (aarch64_get_instr (cpu), 21, 10);
9780
9781   if (!V)
9782     {
9783       /* GReg operations.  */
9784       switch (dispatch)
9785         {
9786         case 0:  strb_abs (cpu, imm); return;
9787         case 1:  ldrb32_abs (cpu, imm); return;
9788         case 2:  ldrsb_abs (cpu, imm); return;
9789         case 3:  ldrsb32_abs (cpu, imm); return;
9790         case 4:  strh_abs (cpu, imm); return;
9791         case 5:  ldrh32_abs (cpu, imm); return;
9792         case 6:  ldrsh_abs (cpu, imm); return;
9793         case 7:  ldrsh32_abs (cpu, imm); return;
9794         case 8:  str32_abs (cpu, imm); return;
9795         case 9:  ldr32_abs (cpu, imm); return;
9796         case 10: ldrsw_abs (cpu, imm); return;
9797         case 12: str_abs (cpu, imm); return;
9798         case 13: ldr_abs (cpu, imm); return;
9799         case 14: prfm_abs (cpu, imm); return;
9800
9801         default:
9802         case 11:
9803         case 15:
9804           HALT_UNALLOC;
9805         }
9806     }
9807
9808   /* FReg operations.  */
9809   switch (dispatch)
9810     {
9811     case 3:  fldrq_abs (cpu, imm); return;
9812     case 9:  fldrs_abs (cpu, imm); return;
9813     case 13: fldrd_abs (cpu, imm); return;
9814
9815     case 0:  fstrb_abs (cpu, imm); return;
9816     case 2:  fstrq_abs (cpu, imm); return;
9817     case 4:  fstrh_abs (cpu, imm); return;
9818     case 8:  fstrs_abs (cpu, imm); return;
9819     case 12: fstrd_abs (cpu, imm); return;
9820
9821     case 1: /* LDR 8 bit FP.  */
9822     case 5: /* LDR 8 bit FP.  */
9823       HALT_NYI;
9824
9825     default:
9826     case 6:
9827     case 7:
9828     case 10:
9829     case 11:
9830     case 14:
9831     case 15:
9832       HALT_UNALLOC;
9833     }
9834 }
9835
9836 static void
9837 dexLoadExclusive (sim_cpu *cpu)
9838 {
9839   /* assert instr[29:24] = 001000;
9840      instr[31,30] = size
9841      instr[23] = 0 if exclusive
9842      instr[22] = L : 1 if load, 0 if store
9843      instr[21] = 1 if pair
9844      instr[20,16] = Rs
9845      instr[15] = o0 : 1 if ordered
9846      instr[14,10] = Rt2
9847      instr[9,5] = Rn
9848      instr[4.0] = Rt.  */
9849
9850   switch (uimm (aarch64_get_instr (cpu), 22, 21))
9851     {
9852     case 2:   ldxr (cpu); return;
9853     case 0:   stxr (cpu); return;
9854     default:  HALT_NYI;
9855     }
9856 }
9857
9858 static void
9859 dexLoadOther (sim_cpu *cpu)
9860 {
9861   uint32_t dispatch;
9862
9863   /* instr[29,25] = 111_0
9864      instr[24] == 0 ==> dispatch, 1 ==> ldst reg unsigned immediate
9865      instr[21:11,10] is the secondary dispatch.  */
9866   if (uimm (aarch64_get_instr (cpu), 24, 24))
9867     {
9868       dexLoadUnsignedImmediate (cpu);
9869       return;
9870     }
9871
9872   dispatch = ( (uimm (aarch64_get_instr (cpu), 21, 21) << 2)
9873               | uimm (aarch64_get_instr (cpu), 11, 10));
9874   switch (dispatch)
9875     {
9876     case 0: dexLoadUnscaledImmediate (cpu); return;
9877     case 1: dexLoadImmediatePrePost (cpu); return;
9878     case 3: dexLoadImmediatePrePost (cpu); return;
9879     case 6: dexLoadRegisterOffset (cpu); return;
9880
9881     default:
9882     case 2:
9883     case 4:
9884     case 5:
9885     case 7:
9886       HALT_NYI;
9887     }
9888 }
9889
9890 static void
9891 store_pair_u32 (sim_cpu *cpu, int32_t offset, WriteBack wb)
9892 {
9893   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
9894   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
9895   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
9896   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
9897
9898   if ((rn == rd || rm == rd) && wb != NoWriteBack)
9899     HALT_UNALLOC; /* ??? */
9900
9901   offset <<= 2;
9902
9903   if (wb != Post)
9904     address += offset;
9905
9906   aarch64_set_mem_u32 (cpu, address,
9907                        aarch64_get_reg_u32 (cpu, rm, NO_SP));
9908   aarch64_set_mem_u32 (cpu, address + 4,
9909                        aarch64_get_reg_u32 (cpu, rn, NO_SP));
9910
9911   if (wb == Post)
9912     address += offset;
9913
9914   if (wb != NoWriteBack)
9915     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
9916 }
9917
9918 static void
9919 store_pair_u64 (sim_cpu *cpu, int32_t offset, WriteBack wb)
9920 {
9921   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
9922   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
9923   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
9924   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
9925
9926   if ((rn == rd || rm == rd) && wb != NoWriteBack)
9927     HALT_UNALLOC; /* ??? */
9928
9929   offset <<= 3;
9930
9931   if (wb != Post)
9932     address += offset;
9933
9934   aarch64_set_mem_u64 (cpu, address,
9935                        aarch64_get_reg_u64 (cpu, rm, SP_OK));
9936   aarch64_set_mem_u64 (cpu, address + 8,
9937                        aarch64_get_reg_u64 (cpu, rn, SP_OK));
9938
9939   if (wb == Post)
9940     address += offset;
9941
9942   if (wb != NoWriteBack)
9943     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
9944 }
9945
9946 static void
9947 load_pair_u32 (sim_cpu *cpu, int32_t offset, WriteBack wb)
9948 {
9949   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
9950   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
9951   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
9952   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
9953
9954   /* treat this as unalloc to make sure we don't do it.  */
9955   if (rn == rm)
9956     HALT_UNALLOC;
9957
9958   offset <<= 2;
9959
9960   if (wb != Post)
9961     address += offset;
9962
9963   aarch64_set_reg_u64 (cpu, rm, SP_OK, aarch64_get_mem_u32 (cpu, address));
9964   aarch64_set_reg_u64 (cpu, rn, SP_OK, aarch64_get_mem_u32 (cpu, address + 4));
9965
9966   if (wb == Post)
9967     address += offset;
9968
9969   if (wb != NoWriteBack)
9970     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
9971 }
9972
9973 static void
9974 load_pair_s32 (sim_cpu *cpu, int32_t offset, WriteBack wb)
9975 {
9976   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
9977   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
9978   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
9979   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
9980
9981   /* Treat this as unalloc to make sure we don't do it.  */
9982   if (rn == rm)
9983     HALT_UNALLOC;
9984
9985   offset <<= 2;
9986
9987   if (wb != Post)
9988     address += offset;
9989
9990   aarch64_set_reg_s64 (cpu, rm, SP_OK, aarch64_get_mem_s32 (cpu, address));
9991   aarch64_set_reg_s64 (cpu, rn, SP_OK, aarch64_get_mem_s32 (cpu, address + 4));
9992
9993   if (wb == Post)
9994     address += offset;
9995
9996   if (wb != NoWriteBack)
9997     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
9998 }
9999
10000 static void
10001 load_pair_u64 (sim_cpu *cpu, int32_t offset, WriteBack wb)
10002 {
10003   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10004   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10005   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10006   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10007
10008   /* Treat this as unalloc to make sure we don't do it.  */
10009   if (rn == rm)
10010     HALT_UNALLOC;
10011
10012   offset <<= 3;
10013
10014   if (wb != Post)
10015     address += offset;
10016
10017   aarch64_set_reg_u64 (cpu, rm, SP_OK, aarch64_get_mem_u64 (cpu, address));
10018   aarch64_set_reg_u64 (cpu, rn, SP_OK, aarch64_get_mem_u64 (cpu, address + 8));
10019
10020   if (wb == Post)
10021     address += offset;
10022
10023   if (wb != NoWriteBack)
10024     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10025 }
10026
10027 static void
10028 dex_load_store_pair_gr (sim_cpu *cpu)
10029 {
10030   /* instr[31,30] = size (10=> 64-bit, 01=> signed 32-bit, 00=> 32-bit)
10031      instr[29,25] = instruction encoding: 101_0
10032      instr[26]    = V : 1 if fp 0 if gp
10033      instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
10034      instr[22]    = load/store (1=> load)
10035      instr[21,15] = signed, scaled, offset
10036      instr[14,10] = Rn
10037      instr[ 9, 5] = Rd
10038      instr[ 4, 0] = Rm.  */
10039
10040   uint32_t dispatch = ((uimm (aarch64_get_instr (cpu), 31, 30) << 3)
10041                         | uimm (aarch64_get_instr (cpu), 24, 22));
10042   int32_t offset = simm32 (aarch64_get_instr (cpu), 21, 15);
10043
10044   switch (dispatch)
10045     {
10046     case 2: store_pair_u32 (cpu, offset, Post); return;
10047     case 3: load_pair_u32  (cpu, offset, Post); return;
10048     case 4: store_pair_u32 (cpu, offset, NoWriteBack); return;
10049     case 5: load_pair_u32  (cpu, offset, NoWriteBack); return;
10050     case 6: store_pair_u32 (cpu, offset, Pre); return;
10051     case 7: load_pair_u32  (cpu, offset, Pre); return;
10052
10053     case 11: load_pair_s32  (cpu, offset, Post); return;
10054     case 13: load_pair_s32  (cpu, offset, NoWriteBack); return;
10055     case 15: load_pair_s32  (cpu, offset, Pre); return;
10056
10057     case 18: store_pair_u64 (cpu, offset, Post); return;
10058     case 19: load_pair_u64  (cpu, offset, Post); return;
10059     case 20: store_pair_u64 (cpu, offset, NoWriteBack); return;
10060     case 21: load_pair_u64  (cpu, offset, NoWriteBack); return;
10061     case 22: store_pair_u64 (cpu, offset, Pre); return;
10062     case 23: load_pair_u64  (cpu, offset, Pre); return;
10063
10064     default:
10065       HALT_UNALLOC;
10066     }
10067 }
10068
10069 static void
10070 store_pair_float (sim_cpu *cpu, int32_t offset, WriteBack wb)
10071 {
10072   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10073   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10074   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10075   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10076
10077   offset <<= 2;
10078
10079   if (wb != Post)
10080     address += offset;
10081
10082   aarch64_set_mem_float (cpu, address,     aarch64_get_FP_float (cpu, rm));
10083   aarch64_set_mem_float (cpu, address + 4, aarch64_get_FP_float (cpu, rn));
10084
10085   if (wb == Post)
10086     address += offset;
10087
10088   if (wb != NoWriteBack)
10089     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10090 }
10091
10092 static void
10093 store_pair_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10094 {
10095   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10096   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10097   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10098   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10099
10100   offset <<= 3;
10101
10102   if (wb != Post)
10103     address += offset;
10104
10105   aarch64_set_mem_double (cpu, address,     aarch64_get_FP_double (cpu, rm));
10106   aarch64_set_mem_double (cpu, address + 8, aarch64_get_FP_double (cpu, rn));
10107
10108   if (wb == Post)
10109     address += offset;
10110
10111   if (wb != NoWriteBack)
10112     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10113 }
10114
10115 static void
10116 store_pair_long_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10117 {
10118   FRegister a;
10119   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10120   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10121   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10122   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10123
10124   offset <<= 4;
10125
10126   if (wb != Post)
10127     address += offset;
10128
10129   aarch64_get_FP_long_double (cpu, rm, & a);
10130   aarch64_set_mem_long_double (cpu, address, a);
10131   aarch64_get_FP_long_double (cpu, rn, & a);
10132   aarch64_set_mem_long_double (cpu, address + 16, a);
10133
10134   if (wb == Post)
10135     address += offset;
10136
10137   if (wb != NoWriteBack)
10138     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10139 }
10140
10141 static void
10142 load_pair_float (sim_cpu *cpu, int32_t offset, WriteBack wb)
10143 {
10144   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10145   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10146   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10147   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10148
10149   if (rm == rn)
10150     HALT_UNALLOC;
10151
10152   offset <<= 2;
10153
10154   if (wb != Post)
10155     address += offset;
10156
10157   aarch64_set_FP_float (cpu, rm, aarch64_get_mem_float (cpu, address));
10158   aarch64_set_FP_float (cpu, rn, aarch64_get_mem_float (cpu, address + 4));
10159
10160   if (wb == Post)
10161     address += offset;
10162
10163   if (wb != NoWriteBack)
10164     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10165 }
10166
10167 static void
10168 load_pair_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10169 {
10170   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10171   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10172   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10173   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10174
10175   if (rm == rn)
10176     HALT_UNALLOC;
10177
10178   offset <<= 3;
10179
10180   if (wb != Post)
10181     address += offset;
10182
10183   aarch64_set_FP_double (cpu, rm, aarch64_get_mem_double (cpu, address));
10184   aarch64_set_FP_double (cpu, rn, aarch64_get_mem_double (cpu, address + 8));
10185
10186   if (wb == Post)
10187     address += offset;
10188
10189   if (wb != NoWriteBack)
10190     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10191 }
10192
10193 static void
10194 load_pair_long_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10195 {
10196   FRegister a;
10197   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10198   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10199   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10200   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10201
10202   if (rm == rn)
10203     HALT_UNALLOC;
10204
10205   offset <<= 4;
10206
10207   if (wb != Post)
10208     address += offset;
10209
10210   aarch64_get_mem_long_double (cpu, address, & a);
10211   aarch64_set_FP_long_double (cpu, rm, a);
10212   aarch64_get_mem_long_double (cpu, address + 16, & a);
10213   aarch64_set_FP_long_double (cpu, rn, a);
10214
10215   if (wb == Post)
10216     address += offset;
10217
10218   if (wb != NoWriteBack)
10219     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10220 }
10221
10222 static void
10223 dex_load_store_pair_fp (sim_cpu *cpu)
10224 {
10225   /* instr[31,30] = size (10=> 128-bit, 01=> 64-bit, 00=> 32-bit)
10226      instr[29,25] = instruction encoding
10227      instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
10228      instr[22]    = load/store (1=> load)
10229      instr[21,15] = signed, scaled, offset
10230      instr[14,10] = Rn
10231      instr[ 9, 5] = Rd
10232      instr[ 4, 0] = Rm  */
10233
10234   uint32_t dispatch = ((uimm (aarch64_get_instr (cpu), 31, 30) << 3)
10235                         | uimm (aarch64_get_instr (cpu), 24, 22));
10236   int32_t offset = simm32 (aarch64_get_instr (cpu), 21, 15);
10237
10238   switch (dispatch)
10239     {
10240     case 2: store_pair_float (cpu, offset, Post); return;
10241     case 3: load_pair_float  (cpu, offset, Post); return;
10242     case 4: store_pair_float (cpu, offset, NoWriteBack); return;
10243     case 5: load_pair_float  (cpu, offset, NoWriteBack); return;
10244     case 6: store_pair_float (cpu, offset, Pre); return;
10245     case 7: load_pair_float  (cpu, offset, Pre); return;
10246
10247     case 10: store_pair_double (cpu, offset, Post); return;
10248     case 11: load_pair_double  (cpu, offset, Post); return;
10249     case 12: store_pair_double (cpu, offset, NoWriteBack); return;
10250     case 13: load_pair_double  (cpu, offset, NoWriteBack); return;
10251     case 14: store_pair_double (cpu, offset, Pre); return;
10252     case 15: load_pair_double  (cpu, offset, Pre); return;
10253
10254     case 18: store_pair_long_double (cpu, offset, Post); return;
10255     case 19: load_pair_long_double  (cpu, offset, Post); return;
10256     case 20: store_pair_long_double (cpu, offset, NoWriteBack); return;
10257     case 21: load_pair_long_double  (cpu, offset, NoWriteBack); return;
10258     case 22: store_pair_long_double (cpu, offset, Pre); return;
10259     case 23: load_pair_long_double  (cpu, offset, Pre); return;
10260
10261     default:
10262       HALT_UNALLOC;
10263     }
10264 }
10265
10266 static inline unsigned
10267 vec_reg (unsigned v, unsigned o)
10268 {
10269   return (v + o) & 0x3F;
10270 }
10271
10272 /* Load multiple N-element structures to N consecutive registers.  */
10273 static void
10274 vec_load (sim_cpu *cpu, uint64_t address, unsigned N)
10275 {
10276   int      all  = uimm (aarch64_get_instr (cpu), 30, 30);
10277   unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10278   unsigned vd   = uimm (aarch64_get_instr (cpu), 4, 0);
10279   unsigned i;
10280
10281   switch (size)
10282     {
10283     case 0: /* 8-bit operations.  */
10284       if (all)
10285         for (i = 0; i < (16 * N); i++)
10286           aarch64_set_vec_u8 (cpu, vec_reg (vd, i >> 4), i & 15,
10287                               aarch64_get_mem_u8 (cpu, address + i));
10288       else
10289         for (i = 0; i < (8 * N); i++)
10290           aarch64_set_vec_u8 (cpu, vec_reg (vd, i >> 3), i & 7,
10291                               aarch64_get_mem_u8 (cpu, address + i));
10292       return;
10293
10294     case 1: /* 16-bit operations.  */
10295       if (all)
10296         for (i = 0; i < (8 * N); i++)
10297           aarch64_set_vec_u16 (cpu, vec_reg (vd, i >> 3), i & 7,
10298                                aarch64_get_mem_u16 (cpu, address + i * 2));
10299       else
10300         for (i = 0; i < (4 * N); i++)
10301           aarch64_set_vec_u16 (cpu, vec_reg (vd, i >> 2), i & 3,
10302                                aarch64_get_mem_u16 (cpu, address + i * 2));
10303       return;
10304
10305     case 2: /* 32-bit operations.  */
10306       if (all)
10307         for (i = 0; i < (4 * N); i++)
10308           aarch64_set_vec_u32 (cpu, vec_reg (vd, i >> 2), i & 3,
10309                                aarch64_get_mem_u32 (cpu, address + i * 4));
10310       else
10311         for (i = 0; i < (2 * N); i++)
10312           aarch64_set_vec_u32 (cpu, vec_reg (vd, i >> 1), i & 1,
10313                                aarch64_get_mem_u32 (cpu, address + i * 4));
10314       return;
10315
10316     case 3: /* 64-bit operations.  */
10317       if (all)
10318         for (i = 0; i < (2 * N); i++)
10319           aarch64_set_vec_u64 (cpu, vec_reg (vd, i >> 1), i & 1,
10320                                aarch64_get_mem_u64 (cpu, address + i * 8));
10321       else
10322         for (i = 0; i < N; i++)
10323           aarch64_set_vec_u64 (cpu, vec_reg (vd, i), 0,
10324                                aarch64_get_mem_u64 (cpu, address + i * 8));
10325       return;
10326
10327     default:
10328       HALT_UNREACHABLE;
10329     }
10330 }
10331
10332 /* LD4: load multiple 4-element to four consecutive registers.  */
10333 static void
10334 LD4 (sim_cpu *cpu, uint64_t address)
10335 {
10336   vec_load (cpu, address, 4);
10337 }
10338
10339 /* LD3: load multiple 3-element structures to three consecutive registers.  */
10340 static void
10341 LD3 (sim_cpu *cpu, uint64_t address)
10342 {
10343   vec_load (cpu, address, 3);
10344 }
10345
10346 /* LD2: load multiple 2-element structures to two consecutive registers.  */
10347 static void
10348 LD2 (sim_cpu *cpu, uint64_t address)
10349 {
10350   vec_load (cpu, address, 2);
10351 }
10352
10353 /* Load multiple 1-element structures into one register.  */
10354 static void
10355 LD1_1 (sim_cpu *cpu, uint64_t address)
10356 {
10357   int      all  = uimm (aarch64_get_instr (cpu), 30, 30);
10358   unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10359   unsigned vd   = uimm (aarch64_get_instr (cpu), 4, 0);
10360   unsigned i;
10361
10362   switch (size)
10363     {
10364     case 0:
10365       /* LD1 {Vd.16b}, addr, #16 */
10366       /* LD1 {Vd.8b}, addr, #8 */
10367       for (i = 0; i < (all ? 16 : 8); i++)
10368         aarch64_set_vec_u8 (cpu, vd, i,
10369                             aarch64_get_mem_u8 (cpu, address + i));
10370       return;
10371
10372     case 1:
10373       /* LD1 {Vd.8h}, addr, #16 */
10374       /* LD1 {Vd.4h}, addr, #8 */
10375       for (i = 0; i < (all ? 8 : 4); i++)
10376         aarch64_set_vec_u16 (cpu, vd, i,
10377                              aarch64_get_mem_u16 (cpu, address + i * 2));
10378       return;
10379
10380     case 2:
10381       /* LD1 {Vd.4s}, addr, #16 */
10382       /* LD1 {Vd.2s}, addr, #8 */
10383       for (i = 0; i < (all ? 4 : 2); i++)
10384         aarch64_set_vec_u32 (cpu, vd, i,
10385                              aarch64_get_mem_u32 (cpu, address + i * 4));
10386       return;
10387
10388     case 3:
10389       /* LD1 {Vd.2d}, addr, #16 */
10390       /* LD1 {Vd.1d}, addr, #8 */
10391       for (i = 0; i < (all ? 2 : 1); i++)
10392         aarch64_set_vec_u64 (cpu, vd, i,
10393                              aarch64_get_mem_u64 (cpu, address + i * 8));
10394       return;
10395
10396     default:
10397       HALT_UNREACHABLE;
10398     }
10399 }
10400
10401 /* Load multiple 1-element structures into two registers.  */
10402 static void
10403 LD1_2 (sim_cpu *cpu, uint64_t address)
10404 {
10405   /* FIXME: This algorithm is *exactly* the same as the LD2 version.
10406      So why have two different instructions ?  There must be something
10407      wrong somewhere.  */
10408   vec_load (cpu, address, 2);
10409 }
10410
10411 /* Load multiple 1-element structures into three registers.  */
10412 static void
10413 LD1_3 (sim_cpu *cpu, uint64_t address)
10414 {
10415   /* FIXME: This algorithm is *exactly* the same as the LD3 version.
10416      So why have two different instructions ?  There must be something
10417      wrong somewhere.  */
10418   vec_load (cpu, address, 3);
10419 }
10420
10421 /* Load multiple 1-element structures into four registers.  */
10422 static void
10423 LD1_4 (sim_cpu *cpu, uint64_t address)
10424 {
10425   /* FIXME: This algorithm is *exactly* the same as the LD4 version.
10426      So why have two different instructions ?  There must be something
10427      wrong somewhere.  */
10428   vec_load (cpu, address, 4);
10429 }
10430
10431 /* Store multiple N-element structures to N consecutive registers.  */
10432 static void
10433 vec_store (sim_cpu *cpu, uint64_t address, unsigned N)
10434 {
10435   int      all  = uimm (aarch64_get_instr (cpu), 30, 30);
10436   unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10437   unsigned vd   = uimm (aarch64_get_instr (cpu), 4, 0);
10438   unsigned i;
10439
10440   switch (size)
10441     {
10442     case 0: /* 8-bit operations.  */
10443       if (all)
10444         for (i = 0; i < (16 * N); i++)
10445           aarch64_set_mem_u8
10446             (cpu, address + i,
10447              aarch64_get_vec_u8 (cpu, vec_reg (vd, i >> 4), i & 15));
10448       else
10449         for (i = 0; i < (8 * N); i++)
10450           aarch64_set_mem_u8
10451             (cpu, address + i,
10452              aarch64_get_vec_u8 (cpu, vec_reg (vd, i >> 3), i & 7));
10453       return;
10454
10455     case 1: /* 16-bit operations.  */
10456       if (all)
10457         for (i = 0; i < (8 * N); i++)
10458           aarch64_set_mem_u16
10459             (cpu, address + i * 2,
10460              aarch64_get_vec_u16 (cpu, vec_reg (vd, i >> 3), i & 7));
10461       else
10462         for (i = 0; i < (4 * N); i++)
10463           aarch64_set_mem_u16
10464             (cpu, address + i * 2,
10465              aarch64_get_vec_u16 (cpu, vec_reg (vd, i >> 2), i & 3));
10466       return;
10467
10468     case 2: /* 32-bit operations.  */
10469       if (all)
10470         for (i = 0; i < (4 * N); i++)
10471           aarch64_set_mem_u32
10472             (cpu, address + i * 4,
10473              aarch64_get_vec_u32 (cpu, vec_reg (vd, i >> 2), i & 3));
10474       else
10475         for (i = 0; i < (2 * N); i++)
10476           aarch64_set_mem_u32
10477             (cpu, address + i * 4,
10478              aarch64_get_vec_u32 (cpu, vec_reg (vd, i >> 1), i & 1));
10479       return;
10480
10481     case 3: /* 64-bit operations.  */
10482       if (all)
10483         for (i = 0; i < (2 * N); i++)
10484           aarch64_set_mem_u64
10485             (cpu, address + i * 8,
10486              aarch64_get_vec_u64 (cpu, vec_reg (vd, i >> 1), i & 1));
10487       else
10488         for (i = 0; i < N; i++)
10489           aarch64_set_mem_u64
10490             (cpu, address + i * 8,
10491              aarch64_get_vec_u64 (cpu, vec_reg (vd, i), 0));
10492       return;
10493
10494     default:
10495       HALT_UNREACHABLE;
10496     }
10497 }
10498
10499 /* Store multiple 4-element structure to four consecutive registers.  */
10500 static void
10501 ST4 (sim_cpu *cpu, uint64_t address)
10502 {
10503   vec_store (cpu, address, 4);
10504 }
10505
10506 /* Store multiple 3-element structures to three consecutive registers.  */
10507 static void
10508 ST3 (sim_cpu *cpu, uint64_t address)
10509 {
10510   vec_store (cpu, address, 3);
10511 }
10512
10513 /* Store multiple 2-element structures to two consecutive registers.  */
10514 static void
10515 ST2 (sim_cpu *cpu, uint64_t address)
10516 {
10517   vec_store (cpu, address, 2);
10518 }
10519
10520 /* Store multiple 1-element structures into one register.  */
10521 static void
10522 ST1_1 (sim_cpu *cpu, uint64_t address)
10523 {
10524   int      all  = uimm (aarch64_get_instr (cpu), 30, 30);
10525   unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10526   unsigned vd   = uimm (aarch64_get_instr (cpu), 4, 0);
10527   unsigned i;
10528
10529   switch (size)
10530     {
10531     case 0:
10532       for (i = 0; i < (all ? 16 : 8); i++)
10533         aarch64_set_mem_u8 (cpu, address + i,
10534                             aarch64_get_vec_u8 (cpu, vd, i));
10535       return;
10536
10537     case 1:
10538       for (i = 0; i < (all ? 8 : 4); i++)
10539         aarch64_set_mem_u16 (cpu, address + i * 2,
10540                              aarch64_get_vec_u16 (cpu, vd, i));
10541       return;
10542
10543     case 2:
10544       for (i = 0; i < (all ? 4 : 2); i++)
10545         aarch64_set_mem_u32 (cpu, address + i * 4,
10546                              aarch64_get_vec_u32 (cpu, vd, i));
10547       return;
10548
10549     case 3:
10550       for (i = 0; i < (all ? 2 : 1); i++)
10551         aarch64_set_mem_u64 (cpu, address + i * 8,
10552                              aarch64_get_vec_u64 (cpu, vd, i));
10553       return;
10554
10555     default:
10556       HALT_UNREACHABLE;
10557     }
10558 }
10559
10560 /* Store multiple 1-element structures into two registers.  */
10561 static void
10562 ST1_2 (sim_cpu *cpu, uint64_t address)
10563 {
10564   /* FIXME: This algorithm is *exactly* the same as the ST2 version.
10565      So why have two different instructions ?  There must be
10566      something wrong somewhere.  */
10567   vec_store (cpu, address, 2);
10568 }
10569
10570 /* Store multiple 1-element structures into three registers.  */
10571 static void
10572 ST1_3 (sim_cpu *cpu, uint64_t address)
10573 {
10574   /* FIXME: This algorithm is *exactly* the same as the ST3 version.
10575      So why have two different instructions ?  There must be
10576      something wrong somewhere.  */
10577   vec_store (cpu, address, 3);
10578 }
10579
10580 /* Store multiple 1-element structures into four registers.  */
10581 static void
10582 ST1_4 (sim_cpu *cpu, uint64_t address)
10583 {
10584   /* FIXME: This algorithm is *exactly* the same as the ST4 version.
10585      So why have two different instructions ?  There must be
10586      something wrong somewhere.  */
10587   vec_store (cpu, address, 4);
10588 }
10589
10590 static void
10591 do_vec_LDnR (sim_cpu *cpu, uint64_t address)
10592 {
10593   /* instr[31]    = 0
10594      instr[30]    = element selector 0=>half, 1=>all elements
10595      instr[29,24] = 00 1101
10596      instr[23]    = 0=>simple, 1=>post
10597      instr[22]    = 1
10598      instr[21]    = width: LD1R-or-LD3R (0) / LD2R-or-LD4R (1)
10599      instr[20,16] = 0 0000 (simple), Vinc (reg-post-inc, no SP),
10600                       11111 (immediate post inc)
10601      instr[15,14] = 11
10602      instr[13]    = width: LD1R-or-LD2R (0) / LD3R-or-LD4R (1)
10603      instr[12]    = 0
10604      instr[11,10] = element size 00=> byte(b), 01=> half(h),
10605                                  10=> word(s), 11=> double(d)
10606      instr[9,5]   = address
10607      instr[4,0]   = Vd  */
10608
10609   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
10610   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
10611   unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10612   int i;
10613
10614   NYI_assert (29, 24, 0x0D);
10615   NYI_assert (22, 22, 1);
10616   NYI_assert (15, 14, 3);
10617   NYI_assert (12, 12, 0);
10618
10619   switch ((uimm (aarch64_get_instr (cpu), 13, 13) << 1)
10620           | uimm (aarch64_get_instr (cpu), 21, 21))
10621     {
10622     case 0: /* LD1R.  */
10623       switch (size)
10624         {
10625         case 0:
10626           {
10627             uint8_t val = aarch64_get_mem_u8 (cpu, address);
10628             for (i = 0; i < (full ? 16 : 8); i++)
10629               aarch64_set_vec_u8 (cpu, vd, i, val);
10630             break;
10631           }
10632
10633         case 1:
10634           {
10635             uint16_t val = aarch64_get_mem_u16 (cpu, address);
10636             for (i = 0; i < (full ? 8 : 4); i++)
10637               aarch64_set_vec_u16 (cpu, vd, i, val);
10638             break;
10639           }
10640
10641         case 2:
10642           {
10643             uint32_t val = aarch64_get_mem_u32 (cpu, address);
10644             for (i = 0; i < (full ? 4 : 2); i++)
10645               aarch64_set_vec_u32 (cpu, vd, i, val);
10646             break;
10647           }
10648
10649         case 3:
10650           {
10651             uint64_t val = aarch64_get_mem_u64 (cpu, address);
10652             for (i = 0; i < (full ? 2 : 1); i++)
10653               aarch64_set_vec_u64 (cpu, vd, i, val);
10654             break;
10655           }
10656
10657         default:
10658           HALT_UNALLOC;
10659         }
10660       break;
10661
10662     case 1: /* LD2R.  */
10663       switch (size)
10664         {
10665         case 0:
10666           {
10667             uint8_t val1 = aarch64_get_mem_u8 (cpu, address);
10668             uint8_t val2 = aarch64_get_mem_u8 (cpu, address + 1);
10669
10670             for (i = 0; i < (full ? 16 : 8); i++)
10671               {
10672                 aarch64_set_vec_u8 (cpu, vd, 0, val1);
10673                 aarch64_set_vec_u8 (cpu, vd + 1, 0, val2);
10674               }
10675             break;
10676           }
10677
10678         case 1:
10679           {
10680             uint16_t val1 = aarch64_get_mem_u16 (cpu, address);
10681             uint16_t val2 = aarch64_get_mem_u16 (cpu, address + 2);
10682
10683             for (i = 0; i < (full ? 8 : 4); i++)
10684               {
10685                 aarch64_set_vec_u16 (cpu, vd, 0, val1);
10686                 aarch64_set_vec_u16 (cpu, vd + 1, 0, val2);
10687               }
10688             break;
10689           }
10690
10691         case 2:
10692           {
10693             uint32_t val1 = aarch64_get_mem_u32 (cpu, address);
10694             uint32_t val2 = aarch64_get_mem_u32 (cpu, address + 4);
10695
10696             for (i = 0; i < (full ? 4 : 2); i++)
10697               {
10698                 aarch64_set_vec_u32 (cpu, vd, 0, val1);
10699                 aarch64_set_vec_u32 (cpu, vd + 1, 0, val2);
10700               }
10701             break;
10702           }
10703
10704         case 3:
10705           {
10706             uint64_t val1 = aarch64_get_mem_u64 (cpu, address);
10707             uint64_t val2 = aarch64_get_mem_u64 (cpu, address + 8);
10708
10709             for (i = 0; i < (full ? 2 : 1); i++)
10710               {
10711                 aarch64_set_vec_u64 (cpu, vd, 0, val1);
10712                 aarch64_set_vec_u64 (cpu, vd + 1, 0, val2);
10713               }
10714             break;
10715           }
10716
10717         default:
10718           HALT_UNALLOC;
10719         }
10720       break;
10721
10722     case 2: /* LD3R.  */
10723       switch (size)
10724         {
10725         case 0:
10726           {
10727             uint8_t val1 = aarch64_get_mem_u8 (cpu, address);
10728             uint8_t val2 = aarch64_get_mem_u8 (cpu, address + 1);
10729             uint8_t val3 = aarch64_get_mem_u8 (cpu, address + 2);
10730
10731             for (i = 0; i < (full ? 16 : 8); i++)
10732               {
10733                 aarch64_set_vec_u8 (cpu, vd, 0, val1);
10734                 aarch64_set_vec_u8 (cpu, vd + 1, 0, val2);
10735                 aarch64_set_vec_u8 (cpu, vd + 2, 0, val3);
10736               }
10737           }
10738           break;
10739
10740         case 1:
10741           {
10742             uint32_t val1 = aarch64_get_mem_u16 (cpu, address);
10743             uint32_t val2 = aarch64_get_mem_u16 (cpu, address + 2);
10744             uint32_t val3 = aarch64_get_mem_u16 (cpu, address + 4);
10745
10746             for (i = 0; i < (full ? 8 : 4); i++)
10747               {
10748                 aarch64_set_vec_u16 (cpu, vd, 0, val1);
10749                 aarch64_set_vec_u16 (cpu, vd + 1, 0, val2);
10750                 aarch64_set_vec_u16 (cpu, vd + 2, 0, val3);
10751               }
10752           }
10753           break;
10754
10755         case 2:
10756           {
10757             uint32_t val1 = aarch64_get_mem_u32 (cpu, address);
10758             uint32_t val2 = aarch64_get_mem_u32 (cpu, address + 4);
10759             uint32_t val3 = aarch64_get_mem_u32 (cpu, address + 8);
10760
10761             for (i = 0; i < (full ? 4 : 2); i++)
10762               {
10763                 aarch64_set_vec_u32 (cpu, vd, 0, val1);
10764                 aarch64_set_vec_u32 (cpu, vd + 1, 0, val2);
10765                 aarch64_set_vec_u32 (cpu, vd + 2, 0, val3);
10766               }
10767           }
10768           break;
10769
10770         case 3:
10771           {
10772             uint64_t val1 = aarch64_get_mem_u64 (cpu, address);
10773             uint64_t val2 = aarch64_get_mem_u64 (cpu, address + 8);
10774             uint64_t val3 = aarch64_get_mem_u64 (cpu, address + 16);
10775
10776             for (i = 0; i < (full ? 2 : 1); i++)
10777               {
10778                 aarch64_set_vec_u64 (cpu, vd, 0, val1);
10779                 aarch64_set_vec_u64 (cpu, vd + 1, 0, val2);
10780                 aarch64_set_vec_u64 (cpu, vd + 2, 0, val3);
10781               }
10782           }
10783           break;
10784
10785         default:
10786           HALT_UNALLOC;
10787         }
10788       break;
10789
10790     case 3: /* LD4R.  */
10791       switch (size)
10792         {
10793         case 0:
10794           {
10795             uint8_t val1 = aarch64_get_mem_u8 (cpu, address);
10796             uint8_t val2 = aarch64_get_mem_u8 (cpu, address + 1);
10797             uint8_t val3 = aarch64_get_mem_u8 (cpu, address + 2);
10798             uint8_t val4 = aarch64_get_mem_u8 (cpu, address + 3);
10799
10800             for (i = 0; i < (full ? 16 : 8); i++)
10801               {
10802                 aarch64_set_vec_u8 (cpu, vd, 0, val1);
10803                 aarch64_set_vec_u8 (cpu, vd + 1, 0, val2);
10804                 aarch64_set_vec_u8 (cpu, vd + 2, 0, val3);
10805                 aarch64_set_vec_u8 (cpu, vd + 3, 0, val4);
10806               }
10807           }
10808           break;
10809
10810         case 1:
10811           {
10812             uint32_t val1 = aarch64_get_mem_u16 (cpu, address);
10813             uint32_t val2 = aarch64_get_mem_u16 (cpu, address + 2);
10814             uint32_t val3 = aarch64_get_mem_u16 (cpu, address + 4);
10815             uint32_t val4 = aarch64_get_mem_u16 (cpu, address + 6);
10816
10817             for (i = 0; i < (full ? 8 : 4); i++)
10818               {
10819                 aarch64_set_vec_u16 (cpu, vd, 0, val1);
10820                 aarch64_set_vec_u16 (cpu, vd + 1, 0, val2);
10821                 aarch64_set_vec_u16 (cpu, vd + 2, 0, val3);
10822                 aarch64_set_vec_u16 (cpu, vd + 3, 0, val4);
10823               }
10824           }
10825           break;
10826
10827         case 2:
10828           {
10829             uint32_t val1 = aarch64_get_mem_u32 (cpu, address);
10830             uint32_t val2 = aarch64_get_mem_u32 (cpu, address + 4);
10831             uint32_t val3 = aarch64_get_mem_u32 (cpu, address + 8);
10832             uint32_t val4 = aarch64_get_mem_u32 (cpu, address + 12);
10833
10834             for (i = 0; i < (full ? 4 : 2); i++)
10835               {
10836                 aarch64_set_vec_u32 (cpu, vd, 0, val1);
10837                 aarch64_set_vec_u32 (cpu, vd + 1, 0, val2);
10838                 aarch64_set_vec_u32 (cpu, vd + 2, 0, val3);
10839                 aarch64_set_vec_u32 (cpu, vd + 3, 0, val4);
10840               }
10841           }
10842           break;
10843
10844         case 3:
10845           {
10846             uint64_t val1 = aarch64_get_mem_u64 (cpu, address);
10847             uint64_t val2 = aarch64_get_mem_u64 (cpu, address + 8);
10848             uint64_t val3 = aarch64_get_mem_u64 (cpu, address + 16);
10849             uint64_t val4 = aarch64_get_mem_u64 (cpu, address + 24);
10850
10851             for (i = 0; i < (full ? 2 : 1); i++)
10852               {
10853                 aarch64_set_vec_u64 (cpu, vd, 0, val1);
10854                 aarch64_set_vec_u64 (cpu, vd + 1, 0, val2);
10855                 aarch64_set_vec_u64 (cpu, vd + 2, 0, val3);
10856                 aarch64_set_vec_u64 (cpu, vd + 3, 0, val4);
10857               }
10858           }
10859           break;
10860
10861         default:
10862           HALT_UNALLOC;
10863         }
10864       break;
10865
10866     default:
10867       HALT_UNALLOC;
10868     }
10869 }
10870
10871 static void
10872 do_vec_load_store (sim_cpu *cpu)
10873 {
10874   /* {LD|ST}<N>   {Vd..Vd+N}, vaddr
10875
10876      instr[31]    = 0
10877      instr[30]    = element selector 0=>half, 1=>all elements
10878      instr[29,25] = 00110
10879      instr[24]    = ?
10880      instr[23]    = 0=>simple, 1=>post
10881      instr[22]    = 0=>store, 1=>load
10882      instr[21]    = 0 (LDn) / small(0)-large(1) selector (LDnR)
10883      instr[20,16] = 00000 (simple), Vinc (reg-post-inc, no SP),
10884                     11111 (immediate post inc)
10885      instr[15,12] = elements and destinations.  eg for load:
10886                      0000=>LD4 => load multiple 4-element to
10887                      four consecutive registers
10888                      0100=>LD3 => load multiple 3-element to
10889                      three consecutive registers
10890                      1000=>LD2 => load multiple 2-element to
10891                      two consecutive registers
10892                      0010=>LD1 => load multiple 1-element to
10893                      four consecutive registers
10894                      0110=>LD1 => load multiple 1-element to
10895                      three consecutive registers
10896                      1010=>LD1 => load multiple 1-element to
10897                      two consecutive registers
10898                      0111=>LD1 => load multiple 1-element to
10899                      one register
10900                      1100=>LDR1,LDR2
10901                      1110=>LDR3,LDR4
10902      instr[11,10] = element size 00=> byte(b), 01=> half(h),
10903                                  10=> word(s), 11=> double(d)
10904      instr[9,5]   = Vn, can be SP
10905      instr[4,0]   = Vd  */
10906
10907   int post;
10908   int load;
10909   unsigned vn;
10910   uint64_t address;
10911   int type;
10912
10913   if (uimm (aarch64_get_instr (cpu), 31, 31) != 0
10914       || uimm (aarch64_get_instr (cpu), 29, 25) != 0x06)
10915     HALT_NYI;
10916
10917   type = uimm (aarch64_get_instr (cpu), 15, 12);
10918   if (type != 0xE && type != 0xE && uimm (aarch64_get_instr (cpu), 21, 21) != 0)
10919     HALT_NYI;
10920
10921   post = uimm (aarch64_get_instr (cpu), 23, 23);
10922   load = uimm (aarch64_get_instr (cpu), 22, 22);
10923   vn = uimm (aarch64_get_instr (cpu), 9, 5);
10924   address = aarch64_get_reg_u64 (cpu, vn, SP_OK);
10925
10926   if (post)
10927     {
10928       unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
10929
10930       if (vm == R31)
10931         {
10932           unsigned sizeof_operation;
10933
10934           switch (type)
10935             {
10936             case 0: sizeof_operation = 32; break;
10937             case 4: sizeof_operation = 24; break;
10938             case 8: sizeof_operation = 16; break;
10939
10940             case 0xC:
10941               sizeof_operation = uimm (aarch64_get_instr (cpu), 21, 21) ? 2 : 1;
10942               sizeof_operation <<= uimm (aarch64_get_instr (cpu), 11, 10);
10943               break;
10944
10945             case 0xE:
10946               sizeof_operation = uimm (aarch64_get_instr (cpu), 21, 21) ? 8 : 4;
10947               sizeof_operation <<= uimm (aarch64_get_instr (cpu), 11, 10);
10948               break;
10949
10950             case 2:
10951             case 6:
10952             case 10:
10953             case 7:
10954               sizeof_operation = 2 << uimm (aarch64_get_instr (cpu), 11, 10);
10955               break;
10956
10957             default:
10958               HALT_UNALLOC;
10959             }
10960
10961           if (uimm (aarch64_get_instr (cpu), 30, 30))
10962             sizeof_operation *= 2;
10963
10964           aarch64_set_reg_u64 (cpu, vn, SP_OK, address + sizeof_operation);
10965         }
10966       else
10967         aarch64_set_reg_u64 (cpu, vn, SP_OK,
10968                              address + aarch64_get_reg_u64 (cpu, vm, NO_SP));
10969     }
10970   else
10971     {
10972       NYI_assert (20, 16, 0);
10973     }
10974
10975   if (load)
10976     {
10977       switch (type)
10978         {
10979         case 0:  LD4 (cpu, address); return;
10980         case 4:  LD3 (cpu, address); return;
10981         case 8:  LD2 (cpu, address); return;
10982         case 2:  LD1_4 (cpu, address); return;
10983         case 6:  LD1_3 (cpu, address); return;
10984         case 10: LD1_2 (cpu, address); return;
10985         case 7:  LD1_1 (cpu, address); return;
10986
10987         case 0xE:
10988         case 0xC: do_vec_LDnR (cpu, address); return;
10989
10990         default:
10991           HALT_NYI;
10992         }
10993     }
10994
10995   /* Stores.  */
10996   switch (type)
10997     {
10998     case 0:  ST4 (cpu, address); return;
10999     case 4:  ST3 (cpu, address); return;
11000     case 8:  ST2 (cpu, address); return;
11001     case 2:  ST1_4 (cpu, address); return;
11002     case 6:  ST1_3 (cpu, address); return;
11003     case 10: ST1_2 (cpu, address); return;
11004     case 7:  ST1_1 (cpu, address); return;
11005     default:
11006       HALT_NYI;
11007     }
11008 }
11009
11010 static void
11011 dexLdSt (sim_cpu *cpu)
11012 {
11013   /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
11014      assert  group == GROUP_LDST_0100 || group == GROUP_LDST_0110 ||
11015              group == GROUP_LDST_1100 || group == GROUP_LDST_1110
11016      bits [29,28:26] of a LS are the secondary dispatch vector.  */
11017   uint32_t group2 = dispatchLS (aarch64_get_instr (cpu));
11018
11019   switch (group2)
11020     {
11021     case LS_EXCL_000:
11022       dexLoadExclusive (cpu); return;
11023
11024     case LS_LIT_010:
11025     case LS_LIT_011:
11026       dexLoadLiteral (cpu); return;
11027
11028     case LS_OTHER_110:
11029     case LS_OTHER_111:
11030       dexLoadOther (cpu); return;
11031
11032     case LS_ADVSIMD_001:
11033       do_vec_load_store (cpu); return;
11034
11035     case LS_PAIR_100:
11036       dex_load_store_pair_gr (cpu); return;
11037
11038     case LS_PAIR_101:
11039       dex_load_store_pair_fp (cpu); return;
11040
11041     default:
11042       /* Should never reach here.  */
11043       HALT_NYI;
11044     }
11045 }
11046
11047 /* Specific decode and execute for group Data Processing Register.  */
11048
11049 static void
11050 dexLogicalShiftedRegister (sim_cpu *cpu)
11051 {
11052   /* assert instr[28:24] = 01010
11053      instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11054      instr[30,29:21] = op,N : 000 ==> AND, 001 ==> BIC,
11055                                010 ==> ORR, 011 ==> ORN
11056                                100 ==> EOR, 101 ==> EON,
11057                                110 ==> ANDS, 111 ==> BICS
11058      instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> ROR
11059      instr[15,10] = count : must be 0xxxxx for 32 bit
11060      instr[9,5] = Rn
11061      instr[4,0] = Rd  */
11062
11063   /* unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16); */
11064   uint32_t dispatch;
11065   Shift shiftType;
11066   uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
11067
11068   /* 32 bit operations must have count[5] = 0.  */
11069   /* or else we have an UNALLOC.  */
11070   uint32_t count = uimm (aarch64_get_instr (cpu), 15, 10);
11071
11072   if (!size && uimm (count, 5, 5))
11073     HALT_UNALLOC;
11074
11075   shiftType = shift (aarch64_get_instr (cpu), 22);
11076
11077   /* dispatch on size:op:N i.e aarch64_get_instr (cpu)[31,29:21].  */
11078   dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 29) << 1)
11079               | uimm (aarch64_get_instr (cpu), 21, 21));
11080
11081   switch (dispatch)
11082     {
11083     case 0: and32_shift  (cpu, shiftType, count); return;
11084     case 1: bic32_shift  (cpu, shiftType, count); return;
11085     case 2: orr32_shift  (cpu, shiftType, count); return;
11086     case 3: orn32_shift  (cpu, shiftType, count); return;
11087     case 4: eor32_shift  (cpu, shiftType, count); return;
11088     case 5: eon32_shift  (cpu, shiftType, count); return;
11089     case 6: ands32_shift (cpu, shiftType, count); return;
11090     case 7: bics32_shift (cpu, shiftType, count); return;
11091     case 8: and64_shift  (cpu, shiftType, count); return;
11092     case 9: bic64_shift  (cpu, shiftType, count); return;
11093     case 10:orr64_shift  (cpu, shiftType, count); return;
11094     case 11:orn64_shift  (cpu, shiftType, count); return;
11095     case 12:eor64_shift  (cpu, shiftType, count); return;
11096     case 13:eon64_shift  (cpu, shiftType, count); return;
11097     case 14:ands64_shift (cpu, shiftType, count); return;
11098     case 15:bics64_shift (cpu, shiftType, count); return;
11099     default: HALT_UNALLOC;
11100     }
11101 }
11102
11103 /* 32 bit conditional select.  */
11104 static void
11105 csel32 (sim_cpu *cpu, CondCode cc)
11106 {
11107   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11108   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11109   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11110
11111   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11112                        testConditionCode (cpu, cc)
11113                        ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11114                        : aarch64_get_reg_u32 (cpu, rm, NO_SP));
11115 }
11116
11117 /* 64 bit conditional select.  */
11118 static void
11119 csel64 (sim_cpu *cpu, CondCode cc)
11120 {
11121   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11122   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11123   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11124
11125   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11126                        testConditionCode (cpu, cc)
11127                        ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11128                        : aarch64_get_reg_u64 (cpu, rm, NO_SP));
11129 }
11130
11131 /* 32 bit conditional increment.  */
11132 static void
11133 csinc32 (sim_cpu *cpu, CondCode cc)
11134 {
11135   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11136   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11137   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11138
11139   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11140                        testConditionCode (cpu, cc)
11141                        ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11142                        : aarch64_get_reg_u32 (cpu, rm, NO_SP) + 1);
11143 }
11144
11145 /* 64 bit conditional increment.  */
11146 static void
11147 csinc64 (sim_cpu *cpu, CondCode cc)
11148 {
11149   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11150   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11151   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11152
11153   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11154                        testConditionCode (cpu, cc)
11155                        ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11156                        : aarch64_get_reg_u64 (cpu, rm, NO_SP) + 1);
11157 }
11158
11159 /* 32 bit conditional invert.  */
11160 static void
11161 csinv32 (sim_cpu *cpu, CondCode cc)
11162 {
11163   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11164   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11165   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11166
11167   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11168                        testConditionCode (cpu, cc)
11169                        ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11170                        : ~ aarch64_get_reg_u32 (cpu, rm, NO_SP));
11171 }
11172
11173 /* 64 bit conditional invert.  */
11174 static void
11175 csinv64 (sim_cpu *cpu, CondCode cc)
11176 {
11177   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11178   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11179   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11180
11181   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11182                        testConditionCode (cpu, cc)
11183                        ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11184                        : ~ aarch64_get_reg_u64 (cpu, rm, NO_SP));
11185 }
11186
11187 /* 32 bit conditional negate.  */
11188 static void
11189 csneg32 (sim_cpu *cpu, CondCode cc)
11190 {
11191   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11192   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11193   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11194
11195   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11196                        testConditionCode (cpu, cc)
11197                        ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11198                        : - aarch64_get_reg_u32 (cpu, rm, NO_SP));
11199 }
11200
11201 /* 64 bit conditional negate.  */
11202 static void
11203 csneg64 (sim_cpu *cpu, CondCode cc)
11204 {
11205   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11206   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11207   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11208
11209   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11210                        testConditionCode (cpu, cc)
11211                        ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11212                        : - aarch64_get_reg_u64 (cpu, rm, NO_SP));
11213 }
11214
11215 static void
11216 dexCondSelect (sim_cpu *cpu)
11217 {
11218   /* assert instr[28,21] = 11011011
11219      instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11220      instr[30:11,10] = op : 000 ==> CSEL, 001 ==> CSINC,
11221                             100 ==> CSINV, 101 ==> CSNEG,
11222                             _1_ ==> UNALLOC
11223      instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
11224      instr[15,12] = cond
11225      instr[29] = S : 0 ==> ok, 1 ==> UNALLOC  */
11226
11227   CondCode cc;
11228   uint32_t dispatch;
11229   uint32_t S = uimm (aarch64_get_instr (cpu), 29, 29);
11230   uint32_t op2 = uimm (aarch64_get_instr (cpu), 11, 10);
11231
11232   if (S == 1)
11233     HALT_UNALLOC;
11234
11235   if (op2 & 0x2)
11236     HALT_UNALLOC;
11237
11238   cc = condcode (aarch64_get_instr (cpu), 12);
11239   dispatch = ((uimm (aarch64_get_instr (cpu), 31, 30) << 1) | op2);
11240
11241   switch (dispatch)
11242     {
11243     case 0: csel32  (cpu, cc); return;
11244     case 1: csinc32 (cpu, cc); return;
11245     case 2: csinv32 (cpu, cc); return;
11246     case 3: csneg32 (cpu, cc); return;
11247     case 4: csel64  (cpu, cc); return;
11248     case 5: csinc64 (cpu, cc); return;
11249     case 6: csinv64 (cpu, cc); return;
11250     case 7: csneg64 (cpu, cc); return;
11251     default: HALT_UNALLOC;
11252     }
11253 }
11254
11255 /* Some helpers for counting leading 1 or 0 bits.  */
11256
11257 /* Counts the number of leading bits which are the same
11258    in a 32 bit value in the range 1 to 32.  */
11259 static uint32_t
11260 leading32 (uint32_t value)
11261 {
11262   int32_t mask= 0xffff0000;
11263   uint32_t count= 16; /* Counts number of bits set in mask.  */
11264   uint32_t lo = 1;    /* Lower bound for number of sign bits.  */
11265   uint32_t hi = 32;   /* Upper bound for number of sign bits.  */
11266
11267   while (lo + 1 < hi)
11268     {
11269       int32_t test = (value & mask);
11270
11271       if (test == 0 || test == mask)
11272         {
11273           lo = count;
11274           count = (lo + hi) / 2;
11275           mask >>= (count - lo);
11276         }
11277       else
11278         {
11279           hi = count;
11280           count = (lo + hi) / 2;
11281           mask <<= hi - count;
11282         }
11283     }
11284
11285   if (lo != hi)
11286     {
11287       int32_t test;
11288
11289       mask >>= 1;
11290       test = (value & mask);
11291
11292       if (test == 0 || test == mask)
11293         count = hi;
11294       else
11295         count = lo;
11296     }
11297
11298   return count;
11299 }
11300
11301 /* Counts the number of leading bits which are the same
11302    in a 64 bit value in the range 1 to 64.  */
11303 static uint64_t
11304 leading64 (uint64_t value)
11305 {
11306   int64_t mask= 0xffffffff00000000LL;
11307   uint64_t count = 32; /* Counts number of bits set in mask.  */
11308   uint64_t lo = 1;     /* Lower bound for number of sign bits.  */
11309   uint64_t hi = 64;    /* Upper bound for number of sign bits.  */
11310
11311   while (lo + 1 < hi)
11312     {
11313       int64_t test = (value & mask);
11314
11315       if (test == 0 || test == mask)
11316         {
11317           lo = count;
11318           count = (lo + hi) / 2;
11319           mask >>= (count - lo);
11320         }
11321       else
11322         {
11323           hi = count;
11324           count = (lo + hi) / 2;
11325           mask <<= hi - count;
11326         }
11327     }
11328
11329   if (lo != hi)
11330     {
11331       int64_t test;
11332
11333       mask >>= 1;
11334       test = (value & mask);
11335
11336       if (test == 0 || test == mask)
11337         count = hi;
11338       else
11339         count = lo;
11340     }
11341
11342   return count;
11343 }
11344
11345 /* Bit operations.  */
11346 /* N.B register args may not be SP.  */
11347
11348 /* 32 bit count leading sign bits.  */
11349 static void
11350 cls32 (sim_cpu *cpu)
11351 {
11352   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11353   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11354
11355   /* N.B. the result needs to exclude the leading bit.  */
11356   aarch64_set_reg_u64
11357     (cpu, rd, NO_SP, leading32 (aarch64_get_reg_u32 (cpu, rn, NO_SP)) - 1);
11358 }
11359
11360 /* 64 bit count leading sign bits.  */
11361 static void
11362 cls64 (sim_cpu *cpu)
11363 {
11364   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11365   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11366
11367   /* N.B. the result needs to exclude the leading bit.  */
11368   aarch64_set_reg_u64
11369     (cpu, rd, NO_SP, leading64 (aarch64_get_reg_u64 (cpu, rn, NO_SP)) - 1);
11370 }
11371
11372 /* 32 bit count leading zero bits.  */
11373 static void
11374 clz32 (sim_cpu *cpu)
11375 {
11376   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11377   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11378   uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11379
11380   /* if the sign (top) bit is set then the count is 0.  */
11381   if (pick32 (value, 31, 31))
11382     aarch64_set_reg_u64 (cpu, rd, NO_SP, 0L);
11383   else
11384     aarch64_set_reg_u64 (cpu, rd, NO_SP, leading32 (value));
11385 }
11386
11387 /* 64 bit count leading zero bits.  */
11388 static void
11389 clz64 (sim_cpu *cpu)
11390 {
11391   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11392   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11393   uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11394
11395   /* if the sign (top) bit is set then the count is 0.  */
11396   if (pick64 (value, 63, 63))
11397     aarch64_set_reg_u64 (cpu, rd, NO_SP, 0L);
11398   else
11399     aarch64_set_reg_u64 (cpu, rd, NO_SP, leading64 (value));
11400 }
11401
11402 /* 32 bit reverse bits.  */
11403 static void
11404 rbit32 (sim_cpu *cpu)
11405 {
11406   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11407   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11408   uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11409   uint32_t result = 0;
11410   int i;
11411
11412   for (i = 0; i < 32; i++)
11413     {
11414       result <<= 1;
11415       result |= (value & 1);
11416       value >>= 1;
11417     }
11418   aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11419 }
11420
11421 /* 64 bit reverse bits.  */
11422 static void
11423 rbit64 (sim_cpu *cpu)
11424 {
11425   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11426   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11427   uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11428   uint64_t result = 0;
11429   int i;
11430
11431   for (i = 0; i < 64; i++)
11432     {
11433       result <<= 1;
11434       result |= (value & 1L);
11435       value >>= 1;
11436     }
11437   aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11438 }
11439
11440 /* 32 bit reverse bytes.  */
11441 static void
11442 rev32 (sim_cpu *cpu)
11443 {
11444   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11445   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11446   uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11447   uint32_t result = 0;
11448   int i;
11449
11450   for (i = 0; i < 4; i++)
11451     {
11452       result <<= 8;
11453       result |= (value & 0xff);
11454       value >>= 8;
11455     }
11456   aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11457 }
11458
11459 /* 64 bit reverse bytes.  */
11460 static void
11461 rev64 (sim_cpu *cpu)
11462 {
11463   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11464   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11465   uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11466   uint64_t result = 0;
11467   int i;
11468
11469   for (i = 0; i < 8; i++)
11470     {
11471       result <<= 8;
11472       result |= (value & 0xffULL);
11473       value >>= 8;
11474     }
11475   aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11476 }
11477
11478 /* 32 bit reverse shorts.  */
11479 /* N.B.this reverses the order of the bytes in each half word.  */
11480 static void
11481 revh32 (sim_cpu *cpu)
11482 {
11483   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11484   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11485   uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11486   uint32_t result = 0;
11487   int i;
11488
11489   for (i = 0; i < 2; i++)
11490     {
11491       result <<= 8;
11492       result |= (value & 0x00ff00ff);
11493       value >>= 8;
11494     }
11495   aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11496 }
11497
11498 /* 64 bit reverse shorts.  */
11499 /* N.B.this reverses the order of the bytes in each half word.  */
11500 static void
11501 revh64 (sim_cpu *cpu)
11502 {
11503   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11504   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11505   uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11506   uint64_t result = 0;
11507   int i;
11508
11509   for (i = 0; i < 2; i++)
11510     {
11511       result <<= 8;
11512       result |= (value & 0x00ff00ff00ff00ffULL);
11513       value >>= 8;
11514     }
11515   aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11516 }
11517
11518 static void
11519 dexDataProc1Source (sim_cpu *cpu)
11520 {
11521   /* assert instr[30] == 1
11522      aarch64_get_instr (cpu)[28,21] == 111010110
11523      instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11524      instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
11525      instr[20,16] = opcode2 : 00000 ==> ok, ow ==> UNALLOC
11526      instr[15,10] = opcode : 000000 ==> RBIT, 000001 ==> REV16,
11527                              000010 ==> REV, 000011 ==> UNALLOC
11528                              000100 ==> CLZ, 000101 ==> CLS
11529                              ow ==> UNALLOC
11530      instr[9,5] = rn : may not be SP
11531      instr[4,0] = rd : may not be SP.  */
11532
11533   uint32_t S = uimm (aarch64_get_instr (cpu), 29, 29);
11534   uint32_t opcode2 = uimm (aarch64_get_instr (cpu), 20, 16);
11535   uint32_t opcode = uimm (aarch64_get_instr (cpu), 15, 10);
11536   uint32_t dispatch = ((uimm (aarch64_get_instr (cpu), 31, 31) << 3) | opcode);
11537
11538   if (S == 1)
11539     HALT_UNALLOC;
11540
11541   if (opcode2 != 0)
11542     HALT_UNALLOC;
11543
11544   if (opcode & 0x38)
11545     HALT_UNALLOC;
11546
11547   switch (dispatch)
11548     {
11549     case 0: rbit32 (cpu); return;
11550     case 1: revh32 (cpu); return;
11551     case 2: rev32 (cpu); return;
11552     case 4: clz32 (cpu); return;
11553     case 5: cls32 (cpu); return;
11554     case 8: rbit64 (cpu); return;
11555     case 9: revh64 (cpu); return;
11556     case 10:rev32 (cpu); return;
11557     case 11:rev64 (cpu); return;
11558     case 12:clz64 (cpu); return;
11559     case 13:cls64 (cpu); return;
11560     default: HALT_UNALLOC;
11561     }
11562 }
11563
11564 /* Variable shift.
11565    Shifts by count supplied in register.
11566    N.B register args may not be SP.
11567    These all use the shifted auxiliary function for
11568    simplicity and clarity.  Writing the actual shift
11569    inline would avoid a branch and so be faster but
11570    would also necessitate getting signs right.  */
11571
11572 /* 32 bit arithmetic shift right.  */
11573 static void
11574 asrv32 (sim_cpu *cpu)
11575 {
11576   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11577   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11578   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11579
11580   aarch64_set_reg_u64
11581     (cpu, rd, NO_SP,
11582      shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), ASR,
11583                 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
11584 }
11585
11586 /* 64 bit arithmetic shift right.  */
11587 static void
11588 asrv64 (sim_cpu *cpu)
11589 {
11590   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11591   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11592   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11593
11594   aarch64_set_reg_u64
11595     (cpu, rd, NO_SP,
11596      shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), ASR,
11597                 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
11598 }
11599
11600 /* 32 bit logical shift left.  */
11601 static void
11602 lslv32 (sim_cpu *cpu)
11603 {
11604   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11605   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11606   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11607
11608   aarch64_set_reg_u64
11609     (cpu, rd, NO_SP,
11610      shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), LSL,
11611                 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
11612 }
11613
11614 /* 64 bit arithmetic shift left.  */
11615 static void
11616 lslv64 (sim_cpu *cpu)
11617 {
11618   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11619   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11620   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11621
11622   aarch64_set_reg_u64
11623     (cpu, rd, NO_SP,
11624      shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), LSL,
11625                 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
11626 }
11627
11628 /* 32 bit logical shift right.  */
11629 static void
11630 lsrv32 (sim_cpu *cpu)
11631 {
11632   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11633   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11634   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11635
11636   aarch64_set_reg_u64
11637     (cpu, rd, NO_SP,
11638      shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), LSR,
11639                 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
11640 }
11641
11642 /* 64 bit logical shift right.  */
11643 static void
11644 lsrv64 (sim_cpu *cpu)
11645 {
11646   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11647   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11648   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11649
11650   aarch64_set_reg_u64
11651     (cpu, rd, NO_SP,
11652      shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), LSR,
11653                 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
11654 }
11655
11656 /* 32 bit rotate right.  */
11657 static void
11658 rorv32 (sim_cpu *cpu)
11659 {
11660   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11661   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11662   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11663
11664   aarch64_set_reg_u64
11665     (cpu, rd, NO_SP,
11666      shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), ROR,
11667                 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
11668 }
11669
11670 /* 64 bit rotate right.  */
11671 static void
11672 rorv64 (sim_cpu *cpu)
11673 {
11674   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11675   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11676   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11677
11678   aarch64_set_reg_u64
11679     (cpu, rd, NO_SP,
11680      shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), ROR,
11681                 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
11682 }
11683
11684
11685 /* divide.  */
11686
11687 /* 32 bit signed divide.  */
11688 static void
11689 cpuiv32 (sim_cpu *cpu)
11690 {
11691   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11692   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11693   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11694   /* N.B. the pseudo-code does the divide using 64 bit data.  */
11695   /* TODO : check that this rounds towards zero as required.  */
11696   int64_t dividend = aarch64_get_reg_s32 (cpu, rn, NO_SP);
11697   int64_t divisor = aarch64_get_reg_s32 (cpu, rm, NO_SP);
11698
11699   aarch64_set_reg_s64 (cpu, rd, NO_SP,
11700                        divisor ? ((int32_t) (dividend / divisor)) : 0);
11701 }
11702
11703 /* 64 bit signed divide.  */
11704 static void
11705 cpuiv64 (sim_cpu *cpu)
11706 {
11707   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11708   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11709   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11710
11711   /* TODO : check that this rounds towards zero as required.  */
11712   int64_t divisor = aarch64_get_reg_s64 (cpu, rm, NO_SP);
11713
11714   aarch64_set_reg_s64
11715     (cpu, rd, NO_SP,
11716      divisor ? (aarch64_get_reg_s64 (cpu, rn, NO_SP) / divisor) : 0);
11717 }
11718
11719 /* 32 bit unsigned divide.  */
11720 static void
11721 udiv32 (sim_cpu *cpu)
11722 {
11723   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11724   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11725   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11726
11727   /* N.B. the pseudo-code does the divide using 64 bit data.  */
11728   uint64_t dividend = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11729   uint64_t divisor  = aarch64_get_reg_u32 (cpu, rm, NO_SP);
11730
11731   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11732                        divisor ? (uint32_t) (dividend / divisor) : 0);
11733 }
11734
11735 /* 64 bit unsigned divide.  */
11736 static void
11737 udiv64 (sim_cpu *cpu)
11738 {
11739   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11740   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11741   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11742
11743   /* TODO : check that this rounds towards zero as required.  */
11744   uint64_t divisor = aarch64_get_reg_u64 (cpu, rm, NO_SP);
11745
11746   aarch64_set_reg_u64
11747     (cpu, rd, NO_SP,
11748      divisor ? (aarch64_get_reg_u64 (cpu, rn, NO_SP) / divisor) : 0);
11749 }
11750
11751 static void
11752 dexDataProc2Source (sim_cpu *cpu)
11753 {
11754   /* assert instr[30] == 0
11755      instr[28,21] == 11010110
11756      instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11757      instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
11758      instr[15,10] = opcode : 000010 ==> UDIV, 000011 ==> CPUIV,
11759                              001000 ==> LSLV, 001001 ==> LSRV
11760                              001010 ==> ASRV, 001011 ==> RORV
11761                              ow ==> UNALLOC.  */
11762
11763   uint32_t dispatch;
11764   uint32_t S = uimm (aarch64_get_instr (cpu), 29, 29);
11765   uint32_t opcode = uimm (aarch64_get_instr (cpu), 15, 10);
11766
11767   if (S == 1)
11768     HALT_UNALLOC;
11769
11770   if (opcode & 0x34)
11771     HALT_UNALLOC;
11772
11773   dispatch = (  (uimm (aarch64_get_instr (cpu), 31, 31) << 3)
11774               | (uimm (opcode, 3, 3) << 2)
11775               |  uimm (opcode, 1, 0));
11776   switch (dispatch)
11777     {
11778     case 2:  udiv32 (cpu); return;
11779     case 3:  cpuiv32 (cpu); return;
11780     case 4:  lslv32 (cpu); return;
11781     case 5:  lsrv32 (cpu); return;
11782     case 6:  asrv32 (cpu); return;
11783     case 7:  rorv32 (cpu); return;
11784     case 10: udiv64 (cpu); return;
11785     case 11: cpuiv64 (cpu); return;
11786     case 12: lslv64 (cpu); return;
11787     case 13: lsrv64 (cpu); return;
11788     case 14: asrv64 (cpu); return;
11789     case 15: rorv64 (cpu); return;
11790     default: HALT_UNALLOC;
11791     }
11792 }
11793
11794
11795 /* Multiply.  */
11796
11797 /* 32 bit multiply and add.  */
11798 static void
11799 madd32 (sim_cpu *cpu)
11800 {
11801   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11802   unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11803   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11804   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11805
11806   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11807                        aarch64_get_reg_u32 (cpu, ra, NO_SP)
11808                        + aarch64_get_reg_u32 (cpu, rn, NO_SP)
11809                        * aarch64_get_reg_u32 (cpu, rm, NO_SP));
11810 }
11811
11812 /* 64 bit multiply and add.  */
11813 static void
11814 madd64 (sim_cpu *cpu)
11815 {
11816   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11817   unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11818   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11819   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11820
11821   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11822                        aarch64_get_reg_u64 (cpu, ra, NO_SP)
11823                        + aarch64_get_reg_u64 (cpu, rn, NO_SP)
11824                        * aarch64_get_reg_u64 (cpu, rm, NO_SP));
11825 }
11826
11827 /* 32 bit multiply and sub.  */
11828 static void
11829 msub32 (sim_cpu *cpu)
11830 {
11831   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11832   unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11833   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11834   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11835
11836   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11837                        aarch64_get_reg_u32 (cpu, ra, NO_SP)
11838                        - aarch64_get_reg_u32 (cpu, rn, NO_SP)
11839                        * aarch64_get_reg_u32 (cpu, rm, NO_SP));
11840 }
11841
11842 /* 64 bit multiply and sub.  */
11843 static void
11844 msub64 (sim_cpu *cpu)
11845 {
11846   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11847   unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11848   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11849   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11850
11851   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11852                        aarch64_get_reg_u64 (cpu, ra, NO_SP)
11853                        - aarch64_get_reg_u64 (cpu, rn, NO_SP)
11854                        * aarch64_get_reg_u64 (cpu, rm, NO_SP));
11855 }
11856
11857 /* Signed multiply add long -- source, source2 : 32 bit, source3 : 64 bit.  */
11858 static void
11859 smaddl (sim_cpu *cpu)
11860 {
11861   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11862   unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11863   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11864   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11865
11866   /* N.B. we need to multiply the signed 32 bit values in rn, rm to
11867      obtain a 64 bit product.  */
11868   aarch64_set_reg_s64
11869     (cpu, rd, NO_SP,
11870      aarch64_get_reg_s64 (cpu, ra, NO_SP)
11871      + ((int64_t) aarch64_get_reg_s32 (cpu, rn, NO_SP))
11872      * ((int64_t) aarch64_get_reg_s32 (cpu, rm, NO_SP)));
11873 }
11874
11875 /* Signed multiply sub long -- source, source2 : 32 bit, source3 : 64 bit.  */
11876 static void
11877 smsubl (sim_cpu *cpu)
11878 {
11879   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11880   unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11881   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11882   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11883
11884   /* N.B. we need to multiply the signed 32 bit values in rn, rm to
11885      obtain a 64 bit product.  */
11886   aarch64_set_reg_s64
11887     (cpu, rd, NO_SP,
11888      aarch64_get_reg_s64 (cpu, ra, NO_SP)
11889      - ((int64_t) aarch64_get_reg_s32 (cpu, rn, NO_SP))
11890      * ((int64_t) aarch64_get_reg_s32 (cpu, rm, NO_SP)));
11891 }
11892
11893 /* Integer Multiply/Divide.  */
11894
11895 /* First some macros and a helper function.  */
11896 /* Macros to test or access elements of 64 bit words.  */
11897
11898 /* Mask used to access lo 32 bits of 64 bit unsigned int.  */
11899 #define LOW_WORD_MASK ((1ULL << 32) - 1)
11900 /* Return the lo 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int.  */
11901 #define lowWordToU64(_value_u64) ((_value_u64) & LOW_WORD_MASK)
11902 /* Return the hi 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int.  */
11903 #define highWordToU64(_value_u64) ((_value_u64) >> 32)
11904
11905 /* Offset of sign bit in 64 bit signed integger.  */
11906 #define SIGN_SHIFT_U64 63
11907 /* The sign bit itself -- also identifies the minimum negative int value.  */
11908 #define SIGN_BIT_U64 (1UL << SIGN_SHIFT_U64)
11909 /* Return true if a 64 bit signed int presented as an unsigned int is the
11910    most negative value.  */
11911 #define isMinimumU64(_value_u64) ((_value_u64) == SIGN_BIT_U64)
11912 /* Return true (non-zero) if a 64 bit signed int presented as an unsigned
11913    int has its sign bit set to false.  */
11914 #define isSignSetU64(_value_u64) ((_value_u64) & SIGN_BIT_U64)
11915 /* Return 1L or -1L according to whether a 64 bit signed int presented as
11916    an unsigned int has its sign bit set or not.  */
11917 #define signOfU64(_value_u64) (1L + (((value_u64) >> SIGN_SHIFT_U64) * -2L)
11918 /* Clear the sign bit of a 64 bit signed int presented as an unsigned int.  */
11919 #define clearSignU64(_value_u64) ((_value_u64) &= ~SIGN_BIT_U64)
11920
11921 /* Multiply two 64 bit ints and return.
11922    the hi 64 bits of the 128 bit product.  */
11923
11924 static uint64_t
11925 mul64hi (uint64_t value1, uint64_t value2)
11926 {
11927   uint64_t resultmid1;
11928   uint64_t result;
11929   uint64_t value1_lo = lowWordToU64 (value1);
11930   uint64_t value1_hi = highWordToU64 (value1) ;
11931   uint64_t value2_lo = lowWordToU64 (value2);
11932   uint64_t value2_hi = highWordToU64 (value2);
11933
11934   /* Cross-multiply and collect results.  */
11935
11936   uint64_t xproductlo = value1_lo * value2_lo;
11937   uint64_t xproductmid1 = value1_lo * value2_hi;
11938   uint64_t xproductmid2 = value1_hi * value2_lo;
11939   uint64_t xproducthi = value1_hi * value2_hi;
11940   uint64_t carry = 0;
11941   /* Start accumulating 64 bit results.  */
11942   /* Drop bottom half of lowest cross-product.  */
11943   uint64_t resultmid = xproductlo >> 32;
11944   /* Add in middle products.  */
11945   resultmid = resultmid + xproductmid1;
11946
11947   /* Check for overflow.  */
11948   if (resultmid < xproductmid1)
11949     /* Carry over 1 into top cross-product.  */
11950     carry++;
11951
11952   resultmid1  = resultmid + xproductmid2;
11953
11954   /* Check for overflow.  */
11955   if (resultmid1 < xproductmid2)
11956     /* Carry over 1 into top cross-product.  */
11957     carry++;
11958
11959   /* Drop lowest 32 bits of middle cross-product.  */
11960   result = resultmid1 >> 32;
11961
11962   /* Add top cross-product plus and any carry.  */
11963   result += xproducthi + carry;
11964
11965   return result;
11966 }
11967
11968 /* Signed multiply high, source, source2 :
11969    64 bit, dest <-- high 64-bit of result.  */
11970 static void
11971 smulh (sim_cpu *cpu)
11972 {
11973   uint64_t uresult;
11974   int64_t result;
11975   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11976   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11977   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11978   GReg ra = greg (aarch64_get_instr (cpu), 10);
11979   int64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11980   int64_t value2 = aarch64_get_reg_u64 (cpu, rm, NO_SP);
11981   uint64_t uvalue1;
11982   uint64_t uvalue2;
11983   int64_t signum = 1;
11984
11985   if (ra != R31)
11986     HALT_UNALLOC;
11987
11988   /* Convert to unsigned and use the unsigned mul64hi routine
11989      the fix the sign up afterwards.  */
11990   if (value1 < 0)
11991     {
11992       signum *= -1L;
11993       uvalue1 = -value1;
11994     }
11995   else
11996     {
11997       uvalue1 = value1;
11998     }
11999
12000   if (value2 < 0)
12001     {
12002       signum *= -1L;
12003       uvalue2 = -value2;
12004     }
12005   else
12006     {
12007       uvalue2 = value2;
12008     }
12009
12010   uresult = mul64hi (uvalue1, uvalue2);
12011   result = uresult;
12012   result *= signum;
12013
12014   aarch64_set_reg_s64 (cpu, rd, NO_SP, result);
12015 }
12016
12017 /* Unsigned multiply add long -- source, source2 :
12018    32 bit, source3 : 64 bit.  */
12019 static void
12020 umaddl (sim_cpu *cpu)
12021 {
12022   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12023   unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
12024   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12025   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12026
12027   /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12028      obtain a 64 bit product.  */
12029   aarch64_set_reg_u64
12030     (cpu, rd, NO_SP,
12031      aarch64_get_reg_u64 (cpu, ra, NO_SP)
12032      + ((uint64_t) aarch64_get_reg_u32 (cpu, rn, NO_SP))
12033      * ((uint64_t) aarch64_get_reg_u32 (cpu, rm, NO_SP)));
12034 }
12035
12036 /* Unsigned multiply sub long -- source, source2 : 32 bit, source3 : 64 bit.  */
12037 static void
12038 umsubl (sim_cpu *cpu)
12039 {
12040   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12041   unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
12042   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12043   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12044
12045   /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12046      obtain a 64 bit product.  */
12047   aarch64_set_reg_u64
12048     (cpu, rd, NO_SP,
12049      aarch64_get_reg_u64 (cpu, ra, NO_SP)
12050      - ((uint64_t) aarch64_get_reg_u32 (cpu, rn, NO_SP))
12051      * ((uint64_t) aarch64_get_reg_u32 (cpu, rm, NO_SP)));
12052 }
12053
12054 /* Unsigned multiply high, source, source2 :
12055    64 bit, dest <-- high 64-bit of result.  */
12056 static void
12057 umulh (sim_cpu *cpu)
12058 {
12059   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12060   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12061   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12062   GReg ra = greg (aarch64_get_instr (cpu), 10);
12063
12064   if (ra != R31)
12065     HALT_UNALLOC;
12066
12067   aarch64_set_reg_u64 (cpu, rd, NO_SP,
12068                        mul64hi (aarch64_get_reg_u64 (cpu, rn, NO_SP),
12069                                 aarch64_get_reg_u64 (cpu, rm, NO_SP)));
12070 }
12071
12072 static void
12073 dexDataProc3Source (sim_cpu *cpu)
12074 {
12075   /* assert instr[28,24] == 11011.  */
12076   /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit (for rd at least)
12077      instr[30,29] = op54 : 00 ==> ok, ow ==> UNALLOC
12078      instr[23,21] = op31 : 111 ==> UNALLOC, o2 ==> ok
12079      instr[15] = o0 : 0/1 ==> ok
12080      instr[23,21:15] ==> op : 0000 ==> MADD, 0001 ==> MSUB,     (32/64 bit)
12081                               0010 ==> SMADDL, 0011 ==> SMSUBL, (64 bit only)
12082                               0100 ==> SMULH,                   (64 bit only)
12083                               1010 ==> UMADDL, 1011 ==> UNSUBL, (64 bit only)
12084                               1100 ==> UMULH                    (64 bit only)
12085                               ow ==> UNALLOC.  */
12086
12087   uint32_t dispatch;
12088   uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
12089   uint32_t op54 = uimm (aarch64_get_instr (cpu), 30, 29);
12090   uint32_t op31 = uimm (aarch64_get_instr (cpu), 23, 21);
12091   uint32_t o0 = uimm (aarch64_get_instr (cpu), 15, 15);
12092
12093   if (op54 != 0)
12094     HALT_UNALLOC;
12095
12096   if (size == 0)
12097     {
12098       if (op31 != 0)
12099         HALT_UNALLOC;
12100
12101       if (o0 == 0)
12102         madd32 (cpu);
12103       else
12104         msub32 (cpu);
12105       return;
12106     }
12107
12108   dispatch = (op31 << 1) | o0;
12109
12110   switch (dispatch)
12111     {
12112     case 0:  madd64 (cpu); return;
12113     case 1:  msub64 (cpu); return;
12114     case 2:  smaddl (cpu); return;
12115     case 3:  smsubl (cpu); return;
12116     case 4:  smulh (cpu); return;
12117     case 10: umaddl (cpu); return;
12118     case 11: umsubl (cpu); return;
12119     case 12: umulh (cpu); return;
12120     default: HALT_UNALLOC;
12121     }
12122 }
12123
12124 static void
12125 dexDPReg (sim_cpu *cpu)
12126 {
12127   /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
12128      assert  group == GROUP_DPREG_0101 || group == GROUP_DPREG_1101
12129      bits [28:24:21] of a DPReg are the secondary dispatch vector.  */
12130   uint32_t group2 = dispatchDPReg (aarch64_get_instr (cpu));
12131
12132   switch (group2)
12133     {
12134     case DPREG_LOG_000:
12135     case DPREG_LOG_001:
12136       dexLogicalShiftedRegister (cpu); return;
12137
12138     case DPREG_ADDSHF_010:
12139       dexAddSubtractShiftedRegister (cpu); return;
12140
12141     case DPREG_ADDEXT_011:
12142       dexAddSubtractExtendedRegister (cpu); return;
12143
12144     case DPREG_ADDCOND_100:
12145       {
12146         /* This set bundles a variety of different operations.  */
12147         /* Check for.  */
12148         /* 1) add/sub w carry.  */
12149         uint32_t mask1 = 0x1FE00000U;
12150         uint32_t val1  = 0x1A000000U;
12151         /* 2) cond compare register/immediate.  */
12152         uint32_t mask2 = 0x1FE00000U;
12153         uint32_t val2  = 0x1A400000U;
12154         /* 3) cond select.  */
12155         uint32_t mask3 = 0x1FE00000U;
12156         uint32_t val3  = 0x1A800000U;
12157         /* 4) data proc 1/2 source.  */
12158         uint32_t mask4 = 0x1FE00000U;
12159         uint32_t val4  = 0x1AC00000U;
12160
12161         if ((aarch64_get_instr (cpu) & mask1) == val1)
12162           dexAddSubtractWithCarry (cpu);
12163
12164         else if ((aarch64_get_instr (cpu) & mask2) == val2)
12165           CondCompare (cpu);
12166
12167         else if ((aarch64_get_instr (cpu) & mask3) == val3)
12168           dexCondSelect (cpu);
12169
12170         else if ((aarch64_get_instr (cpu) & mask4) == val4)
12171           {
12172             /* Bit 30 is clear for data proc 2 source
12173                and set for data proc 1 source.  */
12174             if (aarch64_get_instr (cpu)  & (1U << 30))
12175               dexDataProc1Source (cpu);
12176             else
12177               dexDataProc2Source (cpu);
12178           }
12179
12180         else
12181           /* Should not reach here.  */
12182           HALT_NYI;
12183
12184         return;
12185       }
12186
12187     case DPREG_3SRC_110:
12188       dexDataProc3Source (cpu); return;
12189
12190     case DPREG_UNALLOC_101:
12191       HALT_UNALLOC;
12192
12193     case DPREG_3SRC_111:
12194       dexDataProc3Source (cpu); return;
12195
12196     default:
12197       /* Should never reach here.  */
12198       HALT_NYI;
12199     }
12200 }
12201
12202 /* Unconditional Branch immediate.
12203    Offset is a PC-relative byte offset in the range +/- 128MiB.
12204    The offset is assumed to be raw from the decode i.e. the
12205    simulator is expected to scale them from word offsets to byte.  */
12206
12207 /* Unconditional branch.  */
12208 static void
12209 buc (sim_cpu *cpu, int32_t offset)
12210 {
12211   aarch64_set_next_PC_by_offset (cpu, offset);
12212 }
12213
12214 static unsigned stack_depth = 0;
12215
12216 /* Unconditional branch and link -- writes return PC to LR.  */
12217 static void
12218 bl (sim_cpu *cpu, int32_t offset)
12219 {
12220   aarch64_save_LR (cpu);
12221   aarch64_set_next_PC_by_offset (cpu, offset);
12222
12223   if (TRACE_BRANCH_P (cpu))
12224     {
12225       ++ stack_depth;
12226       TRACE_BRANCH (cpu,
12227                     " %*scall %" PRIx64 " [%s]"
12228                     " [args: %" PRIx64 " %" PRIx64 " %" PRIx64 "]",
12229                     stack_depth, " ", aarch64_get_next_PC (cpu),
12230                     aarch64_get_func (aarch64_get_next_PC (cpu)),
12231                     aarch64_get_reg_u64 (cpu, 0, NO_SP),
12232                     aarch64_get_reg_u64 (cpu, 1, NO_SP),
12233                     aarch64_get_reg_u64 (cpu, 2, NO_SP)
12234                     );
12235     }
12236 }
12237
12238 /* Unconditional Branch register.
12239    Branch/return address is in source register.  */
12240
12241 /* Unconditional branch.  */
12242 static void
12243 br (sim_cpu *cpu)
12244 {
12245   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12246   aarch64_set_next_PC (cpu, aarch64_get_reg_u64 (cpu, rn, NO_SP));
12247 }
12248
12249 /* Unconditional branch and link -- writes return PC to LR.  */
12250 static void
12251 blr (sim_cpu *cpu)
12252 {
12253   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12254
12255   /* The pseudo code in the spec says we update LR before fetching.
12256      the value from the rn.  */
12257   aarch64_save_LR (cpu);
12258   aarch64_set_next_PC (cpu, aarch64_get_reg_u64 (cpu, rn, NO_SP));
12259
12260   if (TRACE_BRANCH_P (cpu))
12261     {
12262       ++ stack_depth;
12263       TRACE_BRANCH (cpu,
12264                     " %*scall %" PRIx64 " [%s]"
12265                     " [args: %" PRIx64 " %" PRIx64 " %" PRIx64 "]",
12266                     stack_depth, " ", aarch64_get_next_PC (cpu),
12267                     aarch64_get_func (aarch64_get_next_PC (cpu)),
12268                     aarch64_get_reg_u64 (cpu, 0, NO_SP),
12269                     aarch64_get_reg_u64 (cpu, 1, NO_SP),
12270                     aarch64_get_reg_u64 (cpu, 2, NO_SP)
12271                     );
12272     }
12273 }
12274
12275 /* Return -- assembler will default source to LR this is functionally
12276    equivalent to br but, presumably, unlike br it side effects the
12277    branch predictor.  */
12278 static void
12279 ret (sim_cpu *cpu)
12280 {
12281   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12282   aarch64_set_next_PC (cpu, aarch64_get_reg_u64 (cpu, rn, NO_SP));
12283
12284   if (TRACE_BRANCH_P (cpu))
12285     {
12286       TRACE_BRANCH (cpu,
12287                     " %*sreturn [result: %" PRIx64 "]",
12288                     stack_depth, " ", aarch64_get_reg_u64 (cpu, 0, NO_SP));
12289       -- stack_depth;
12290     }
12291 }
12292
12293 /* NOP -- we implement this and call it from the decode in case we
12294    want to intercept it later.  */
12295
12296 static void
12297 nop (sim_cpu *cpu)
12298 {
12299 }
12300
12301 /* Data synchronization barrier.  */
12302
12303 static void
12304 dsb (sim_cpu *cpu)
12305 {
12306 }
12307
12308 /* Data memory barrier.  */
12309
12310 static void
12311 dmb (sim_cpu *cpu)
12312 {
12313 }
12314
12315 /* Instruction synchronization barrier.  */
12316
12317 static void
12318 isb (sim_cpu *cpu)
12319 {
12320 }
12321
12322 static void
12323 dexBranchImmediate (sim_cpu *cpu)
12324 {
12325   /* assert instr[30,26] == 00101
12326      instr[31] ==> 0 == B, 1 == BL
12327      instr[25,0] == imm26 branch offset counted in words.  */
12328
12329   uint32_t top = uimm (aarch64_get_instr (cpu), 31, 31);
12330   /* We have a 26 byte signed word offset which we need to pass to the
12331      execute routine as a signed byte offset.  */
12332   int32_t offset = simm32 (aarch64_get_instr (cpu), 25, 0) << 2;
12333
12334   if (top)
12335     bl (cpu, offset);
12336   else
12337     buc (cpu, offset);
12338 }
12339
12340 /* Control Flow.  */
12341
12342 /* Conditional branch
12343
12344    Offset is a PC-relative byte offset in the range +/- 1MiB pos is
12345    a bit position in the range 0 .. 63
12346
12347    cc is a CondCode enum value as pulled out of the decode
12348
12349    N.B. any offset register (source) can only be Xn or Wn.  */
12350
12351 static void
12352 bcc (sim_cpu *cpu, int32_t offset, CondCode cc)
12353 {
12354   /* the test returns TRUE if CC is met.  */
12355   if (testConditionCode (cpu, cc))
12356     aarch64_set_next_PC_by_offset (cpu, offset);
12357 }
12358
12359 /* 32 bit branch on register non-zero.  */
12360 static void
12361 cbnz32 (sim_cpu *cpu, int32_t offset)
12362 {
12363   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12364
12365   if (aarch64_get_reg_u32 (cpu, rt, NO_SP) != 0)
12366     aarch64_set_next_PC_by_offset (cpu, offset);
12367 }
12368
12369 /* 64 bit branch on register zero.  */
12370 static void
12371 cbnz (sim_cpu *cpu, int32_t offset)
12372 {
12373   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12374
12375   if (aarch64_get_reg_u64 (cpu, rt, NO_SP) != 0)
12376     aarch64_set_next_PC_by_offset (cpu, offset);
12377 }
12378
12379 /* 32 bit branch on register non-zero.  */
12380 static void
12381 cbz32 (sim_cpu *cpu, int32_t offset)
12382 {
12383   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12384
12385   if (aarch64_get_reg_u32 (cpu, rt, NO_SP) == 0)
12386     aarch64_set_next_PC_by_offset (cpu, offset);
12387 }
12388
12389 /* 64 bit branch on register zero.  */
12390 static void
12391 cbz (sim_cpu *cpu, int32_t offset)
12392 {
12393   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12394
12395   if (aarch64_get_reg_u64 (cpu, rt, NO_SP) == 0)
12396     aarch64_set_next_PC_by_offset (cpu, offset);
12397 }
12398
12399 /* Branch on register bit test non-zero -- one size fits all.  */
12400 static void
12401 tbnz (sim_cpu *cpu, uint32_t  pos, int32_t offset)
12402 {
12403   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12404
12405   if (aarch64_get_reg_u64 (cpu, rt, NO_SP) & (1 << pos))
12406     aarch64_set_next_PC_by_offset (cpu, offset);
12407 }
12408
12409 /* branch on register bit test zero -- one size fits all.  */
12410 static void
12411 tbz (sim_cpu *cpu, uint32_t  pos, int32_t offset)
12412 {
12413   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12414
12415   if (!(aarch64_get_reg_u64 (cpu, rt, NO_SP) & (1 << pos)))
12416     aarch64_set_next_PC_by_offset (cpu, offset);
12417 }
12418
12419 static void
12420 dexCompareBranchImmediate (sim_cpu *cpu)
12421 {
12422   /* instr[30,25] = 01 1010
12423      instr[31]    = size : 0 ==> 32, 1 ==> 64
12424      instr[24]    = op : 0 ==> CBZ, 1 ==> CBNZ
12425      instr[23,5]  = simm19 branch offset counted in words
12426      instr[4,0]   = rt  */
12427
12428   uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
12429   uint32_t op   = uimm (aarch64_get_instr (cpu), 24, 24);
12430   int32_t offset = simm32 (aarch64_get_instr (cpu), 23, 5) << 2;
12431
12432   if (size == 0)
12433     {
12434       if (op == 0)
12435         cbz32 (cpu, offset);
12436       else
12437         cbnz32 (cpu, offset);
12438     }
12439   else
12440     {
12441       if (op == 0)
12442         cbz (cpu, offset);
12443       else
12444         cbnz (cpu, offset);
12445     }
12446 }
12447
12448 static void
12449 dexTestBranchImmediate (sim_cpu *cpu)
12450 {
12451   /* instr[31]    = b5 : bit 5 of test bit idx
12452      instr[30,25] = 01 1011
12453      instr[24]    = op : 0 ==> TBZ, 1 == TBNZ
12454      instr[23,19] = b40 : bits 4 to 0 of test bit idx
12455      instr[18,5]  = simm14 : signed offset counted in words
12456      instr[4,0]   = uimm5  */
12457
12458   uint32_t pos = ((uimm (aarch64_get_instr (cpu), 31, 31) << 4)
12459                   | uimm (aarch64_get_instr (cpu), 23,19));
12460   int32_t offset = simm32 (aarch64_get_instr (cpu), 18, 5) << 2;
12461
12462   NYI_assert (30, 25, 0x1b);
12463
12464   if (uimm (aarch64_get_instr (cpu), 24, 24) == 0)
12465     tbz (cpu, pos, offset);
12466   else
12467     tbnz (cpu, pos, offset);
12468 }
12469
12470 static void
12471 dexCondBranchImmediate (sim_cpu *cpu)
12472 {
12473   /* instr[31,25] = 010 1010
12474      instr[24]    = op1; op => 00 ==> B.cond
12475      instr[23,5]  = simm19 : signed offset counted in words
12476      instr[4]     = op0
12477      instr[3,0]   = cond  */
12478
12479   int32_t offset;
12480   CondCode cc;
12481   uint32_t op = ((uimm (aarch64_get_instr (cpu), 24, 24) << 1)
12482                  | uimm (aarch64_get_instr (cpu), 4, 4));
12483
12484   NYI_assert (31, 25, 0x2a);
12485
12486   if (op != 0)
12487     HALT_UNALLOC;
12488
12489   offset = simm32 (aarch64_get_instr (cpu), 23, 5) << 2;
12490   cc = condcode (aarch64_get_instr (cpu), 0);
12491
12492   bcc (cpu, offset, cc);
12493 }
12494
12495 static void
12496 dexBranchRegister (sim_cpu *cpu)
12497 {
12498   /* instr[31,25] = 110 1011
12499      instr[24,21] = op : 0 ==> BR, 1 => BLR, 2 => RET, 3 => ERET, 4 => DRPS
12500      instr[20,16] = op2 : must be 11111
12501      instr[15,10] = op3 : must be 000000
12502      instr[4,0]   = op2 : must be 11111.  */
12503
12504   uint32_t op = uimm (aarch64_get_instr (cpu), 24, 21);
12505   uint32_t op2 = uimm (aarch64_get_instr (cpu), 20, 16);
12506   uint32_t op3 = uimm (aarch64_get_instr (cpu), 15, 10);
12507   uint32_t op4 = uimm (aarch64_get_instr (cpu), 4, 0);
12508
12509   NYI_assert (31, 25, 0x6b);
12510
12511   if (op2 != 0x1F || op3 != 0 || op4 != 0)
12512     HALT_UNALLOC;
12513
12514   if (op == 0)
12515     br (cpu);
12516
12517   else if (op == 1)
12518     blr (cpu);
12519
12520   else if (op == 2)
12521     ret (cpu);
12522
12523   else
12524     {
12525       /* ERET and DRPS accept 0b11111 for rn = aarch64_get_instr (cpu)[4,0].  */
12526       /* anything else is unallocated.  */
12527       uint32_t rn = greg (aarch64_get_instr (cpu), 0);
12528
12529       if (rn != 0x1f)
12530         HALT_UNALLOC;
12531
12532       if (op == 4 || op == 5)
12533         HALT_NYI;
12534
12535       HALT_UNALLOC;
12536     }
12537 }
12538
12539 /* FIXME: We should get the Angel SWI values from ../../libgloss/aarch64/svc.h
12540    but this may not be available.  So instead we define the values we need
12541    here.  */
12542 #define AngelSVC_Reason_Open            0x01
12543 #define AngelSVC_Reason_Close           0x02
12544 #define AngelSVC_Reason_Write           0x05
12545 #define AngelSVC_Reason_Read            0x06
12546 #define AngelSVC_Reason_IsTTY           0x09
12547 #define AngelSVC_Reason_Seek            0x0A
12548 #define AngelSVC_Reason_FLen            0x0C
12549 #define AngelSVC_Reason_Remove          0x0E
12550 #define AngelSVC_Reason_Rename          0x0F
12551 #define AngelSVC_Reason_Clock           0x10
12552 #define AngelSVC_Reason_Time            0x11
12553 #define AngelSVC_Reason_System          0x12
12554 #define AngelSVC_Reason_Errno           0x13
12555 #define AngelSVC_Reason_GetCmdLine      0x15
12556 #define AngelSVC_Reason_HeapInfo        0x16
12557 #define AngelSVC_Reason_ReportException 0x18
12558 #define AngelSVC_Reason_Elapsed         0x30
12559
12560
12561 static void
12562 handle_halt (sim_cpu *cpu, uint32_t val)
12563 {
12564   uint64_t result = 0;
12565
12566   if (val != 0xf000)
12567     {
12568       TRACE_SYSCALL (cpu, " HLT [0x%x]", val);
12569       sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12570                        sim_stopped, SIM_SIGTRAP);
12571     }
12572
12573   /* We have encountered an Angel SVC call.  See if we can process it.  */
12574   switch (aarch64_get_reg_u32 (cpu, 0, NO_SP))
12575     {
12576     case AngelSVC_Reason_HeapInfo:
12577       {
12578         /* Get the values.  */
12579         uint64_t stack_top = aarch64_get_stack_start (cpu);
12580         uint64_t heap_base = aarch64_get_heap_start (cpu);
12581
12582         /* Get the pointer  */
12583         uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12584         ptr = aarch64_get_mem_u64 (cpu, ptr);
12585
12586         /* Fill in the memory block.  */
12587         /* Start addr of heap.  */
12588         aarch64_set_mem_u64 (cpu, ptr +  0, heap_base);
12589         /* End addr of heap.  */
12590         aarch64_set_mem_u64 (cpu, ptr +  8, stack_top);
12591         /* Lowest stack addr.  */
12592         aarch64_set_mem_u64 (cpu, ptr + 16, heap_base);
12593         /* Initial stack addr.  */
12594         aarch64_set_mem_u64 (cpu, ptr + 24, stack_top);
12595
12596         TRACE_SYSCALL (cpu, " AngelSVC: Get Heap Info");
12597       }
12598       break;
12599
12600     case AngelSVC_Reason_Open:
12601       {
12602         /* Get the pointer  */
12603         /* uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);.  */
12604         /* FIXME: For now we just assume that we will only be asked
12605            to open the standard file descriptors.  */
12606         static int fd = 0;
12607         result = fd ++;
12608
12609         TRACE_SYSCALL (cpu, " AngelSVC: Open file %d", fd - 1);
12610       }
12611       break;
12612
12613     case AngelSVC_Reason_Close:
12614       {
12615         uint64_t fh = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12616         TRACE_SYSCALL (cpu, " AngelSVC: Close file %d", (int) fh);
12617         result = 0;
12618       }
12619       break;
12620
12621     case AngelSVC_Reason_Errno:
12622       result = 0;
12623       TRACE_SYSCALL (cpu, " AngelSVC: Get Errno");
12624       break;
12625
12626     case AngelSVC_Reason_Clock:
12627       result =
12628 #ifdef CLOCKS_PER_SEC
12629         (CLOCKS_PER_SEC >= 100)
12630         ? (clock () / (CLOCKS_PER_SEC / 100))
12631         : ((clock () * 100) / CLOCKS_PER_SEC)
12632 #else
12633         /* Presume unix... clock() returns microseconds.  */
12634         (clock () / 10000)
12635 #endif
12636         ;
12637         TRACE_SYSCALL (cpu, " AngelSVC: Get Clock");
12638       break;
12639
12640     case AngelSVC_Reason_GetCmdLine:
12641       {
12642         /* Get the pointer  */
12643         uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12644         ptr = aarch64_get_mem_u64 (cpu, ptr);
12645
12646         /* FIXME: No command line for now.  */
12647         aarch64_set_mem_u64 (cpu, ptr, 0);
12648         TRACE_SYSCALL (cpu, " AngelSVC: Get Command Line");
12649       }
12650       break;
12651
12652     case AngelSVC_Reason_IsTTY:
12653       result = 1;
12654         TRACE_SYSCALL (cpu, " AngelSVC: IsTTY ?");
12655       break;
12656
12657     case AngelSVC_Reason_Write:
12658       {
12659         /* Get the pointer  */
12660         uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12661         /* Get the write control block.  */
12662         uint64_t fd  = aarch64_get_mem_u64 (cpu, ptr);
12663         uint64_t buf = aarch64_get_mem_u64 (cpu, ptr + 8);
12664         uint64_t len = aarch64_get_mem_u64 (cpu, ptr + 16);
12665
12666         TRACE_SYSCALL (cpu, "write of %" PRIx64 " bytes from %"
12667                        PRIx64 " on descriptor %" PRIx64,
12668                        len, buf, fd);
12669
12670         if (len > 1280)
12671           {
12672             TRACE_SYSCALL (cpu,
12673                            " AngelSVC: Write: Suspiciously long write: %ld",
12674                            (long) len);
12675             sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12676                              sim_stopped, SIM_SIGBUS);
12677           }
12678         else if (fd == 1)
12679           {
12680             printf ("%.*s", (int) len, aarch64_get_mem_ptr (cpu, buf));
12681             if (disas)
12682               /* So that the output stays in sync with trace output.  */
12683               fflush (stdout);
12684           }
12685         else if (fd == 2)
12686           {
12687             TRACE (cpu, 0, "\n");
12688             sim_io_eprintf (CPU_STATE (cpu), "%.*s",
12689                             (int) len, aarch64_get_mem_ptr (cpu, buf));
12690             TRACE (cpu, 0, "\n");
12691           }
12692         else
12693           {
12694             TRACE_SYSCALL (cpu,
12695                            " AngelSVC: Write: Unexpected file handle: %d",
12696                            (int) fd);
12697             sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12698                              sim_stopped, SIM_SIGABRT);
12699           }
12700       }
12701       break;
12702
12703     case AngelSVC_Reason_ReportException:
12704       {
12705         /* Get the pointer  */
12706         uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12707         /*ptr = aarch64_get_mem_u64 (cpu, ptr);.  */
12708         uint64_t type = aarch64_get_mem_u64 (cpu, ptr);
12709         uint64_t state = aarch64_get_mem_u64 (cpu, ptr + 8);
12710
12711         TRACE_SYSCALL (cpu,
12712                        "Angel Exception: type 0x%" PRIx64 " state %" PRIx64,
12713                        type, state);
12714
12715         if (type == 0x20026)
12716           sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12717                            sim_exited, state);
12718         else
12719           sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12720                            sim_stopped, SIM_SIGINT);
12721       }
12722       break;
12723
12724     case AngelSVC_Reason_Read:
12725     case AngelSVC_Reason_FLen:
12726     case AngelSVC_Reason_Seek:
12727     case AngelSVC_Reason_Remove:
12728     case AngelSVC_Reason_Time:
12729     case AngelSVC_Reason_System:
12730     case AngelSVC_Reason_Rename:
12731     case AngelSVC_Reason_Elapsed:
12732     default:
12733       TRACE_SYSCALL (cpu, " HLT [Unknown angel %x]",
12734                      aarch64_get_reg_u32 (cpu, 0, NO_SP));
12735       sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12736                        sim_stopped, SIM_SIGTRAP);
12737     }
12738
12739   aarch64_set_reg_u64 (cpu, 0, NO_SP, result);
12740 }
12741
12742 static void
12743 dexExcpnGen (sim_cpu *cpu)
12744 {
12745   /* instr[31:24] = 11010100
12746      instr[23,21] = opc : 000 ==> GEN EXCPN, 001 ==> BRK
12747                           010 ==> HLT,       101 ==> DBG GEN EXCPN
12748      instr[20,5]  = imm16
12749      instr[4,2]   = opc2 000 ==> OK, ow ==> UNALLOC
12750      instr[1,0]   = LL : discriminates opc  */
12751
12752   uint32_t opc = uimm (aarch64_get_instr (cpu), 23, 21);
12753   uint32_t imm16 = uimm (aarch64_get_instr (cpu), 20, 5);
12754   uint32_t opc2 = uimm (aarch64_get_instr (cpu), 4, 2);
12755   uint32_t LL;
12756
12757   NYI_assert (31, 24, 0xd4);
12758
12759   if (opc2 != 0)
12760     HALT_UNALLOC;
12761
12762   LL = uimm (aarch64_get_instr (cpu), 1, 0);
12763
12764   /* We only implement HLT and BRK for now.  */
12765   if (opc == 1 && LL == 0)
12766     {
12767       TRACE_EVENTS (cpu, " BRK [0x%x]", imm16);
12768       sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12769                        sim_exited, aarch64_get_reg_s32 (cpu, R0, SP_OK));
12770     }
12771
12772   if (opc == 2 && LL == 0)
12773     handle_halt (cpu, imm16);
12774
12775   else if (opc == 0 || opc == 5)
12776     HALT_NYI;
12777
12778   else
12779     HALT_UNALLOC;
12780 }
12781
12782 /* Stub for accessing system registers.
12783    We implement support for the DCZID register since this is used
12784    by the C library's memset function.  */
12785
12786 static uint64_t
12787 system_get (sim_cpu *cpu, unsigned op0, unsigned op1, unsigned crn,
12788             unsigned crm, unsigned op2)
12789 {
12790   if (crn == 0 && op1 == 3 && crm == 0 && op2 == 7)
12791     /* DCZID_EL0 - the Data Cache Zero ID register.
12792        We do not support DC ZVA at the moment, so
12793        we return a value with the disable bit set.  */
12794     return ((uint64_t) 1) << 4;
12795
12796   HALT_NYI;
12797 }
12798
12799 static void
12800 do_mrs (sim_cpu *cpu)
12801 {
12802   /* instr[31:20] = 1101 01010 0011
12803      instr[19]    = op0
12804      instr[18,16] = op1
12805      instr[15,12] = CRn
12806      instr[11,8]  = CRm
12807      instr[7,5]   = op2
12808      instr[4,0]   = Rt  */
12809   unsigned sys_op0 = uimm (aarch64_get_instr (cpu), 19, 19) + 2;
12810   unsigned sys_op1 = uimm (aarch64_get_instr (cpu), 18, 16);
12811   unsigned sys_crn = uimm (aarch64_get_instr (cpu), 15, 12);
12812   unsigned sys_crm = uimm (aarch64_get_instr (cpu), 11, 8);
12813   unsigned sys_op2 = uimm (aarch64_get_instr (cpu), 7, 5);
12814   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12815
12816   aarch64_set_reg_u64 (cpu, rt, NO_SP,
12817                        system_get (cpu, sys_op0, sys_op1, sys_crn, sys_crm, sys_op2));
12818 }
12819
12820 static void
12821 dexSystem (sim_cpu *cpu)
12822 {
12823   /* instr[31:22] = 1101 01010 0
12824      instr[21]    = L
12825      instr[20,19] = op0
12826      instr[18,16] = op1
12827      instr[15,12] = CRn
12828      instr[11,8]  = CRm
12829      instr[7,5]   = op2
12830      instr[4,0]   = uimm5  */
12831
12832   /* We are interested in HINT, DSB, DMB and ISB
12833
12834      Hint #0 encodes NOOP (this is the only hint we care about)
12835      L == 0, op0 == 0, op1 = 011, CRn = 0010, Rt = 11111,
12836      CRm op2  != 0000 000 OR CRm op2 == 0000 000 || CRm op > 0000 101
12837
12838      DSB, DMB, ISB are data store barrier, data memory barrier and
12839      instruction store barrier, respectively, where
12840
12841      L == 0, op0 == 0, op1 = 011, CRn = 0011, Rt = 11111,
12842      op2 : DSB ==> 100, DMB ==> 101, ISB ==> 110
12843      CRm<3:2> ==> domain, CRm<1:0> ==> types,
12844      domain : 00 ==> OuterShareable, 01 ==> Nonshareable,
12845               10 ==> InerShareable, 11 ==> FullSystem
12846      types :  01 ==> Reads, 10 ==> Writes,
12847               11 ==> All, 00 ==> All (domain == FullSystem).  */
12848
12849   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12850   uint32_t l_op0_op1_crn = uimm (aarch64_get_instr (cpu), 21, 12);
12851
12852   NYI_assert (31, 22, 0x354);
12853
12854   switch (l_op0_op1_crn)
12855     {
12856     case 0x032:
12857       if (rt == 0x1F)
12858         {
12859           /* NOP has CRm != 0000 OR.  */
12860           /*         (CRm == 0000 AND (op2 == 000 OR op2 > 101)).  */
12861           uint32_t crm = uimm (aarch64_get_instr (cpu), 11, 8);
12862           uint32_t op2 = uimm (aarch64_get_instr (cpu), 7, 5);
12863
12864           if (crm != 0 || (op2 == 0 || op2 > 5))
12865             {
12866               /* Actually call nop method so we can reimplement it later.  */
12867               nop (cpu);
12868               return;
12869             }
12870         }
12871       HALT_NYI;
12872
12873     case 0x033:
12874       {
12875         uint32_t op2 =  uimm (aarch64_get_instr (cpu), 7, 5);
12876
12877         switch (op2)
12878           {
12879           case 2: HALT_NYI;
12880           case 4: dsb (cpu); return;
12881           case 5: dmb (cpu); return;
12882           case 6: isb (cpu); return;
12883           case 7:
12884           default: HALT_UNALLOC;
12885         }
12886       }
12887
12888     case 0x3B0:
12889       /* MRS Wt, sys-reg.  */
12890       do_mrs (cpu);
12891       return;
12892
12893     case 0x3B4:
12894     case 0x3BD:
12895       /* MRS Xt, sys-reg.  */
12896       do_mrs (cpu);
12897       return;
12898
12899     case 0x0B7:
12900       /* DC <type>, x<n>.  */
12901       HALT_NYI;
12902       return;
12903
12904     default:
12905       /* if (uimm (aarch64_get_instr (cpu), 21, 20) == 0x1)
12906          MRS Xt, sys-reg.  */
12907       HALT_NYI;
12908       return;
12909     }
12910 }
12911
12912 static void
12913 dexBr (sim_cpu *cpu)
12914 {
12915   /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
12916      assert  group == GROUP_BREXSYS_1010 || group == GROUP_BREXSYS_1011
12917      bits [31,29] of a BrExSys are the secondary dispatch vector.  */
12918   uint32_t group2 = dispatchBrExSys (aarch64_get_instr (cpu));
12919
12920   switch (group2)
12921     {
12922     case BR_IMM_000:
12923       return dexBranchImmediate (cpu);
12924
12925     case BR_IMMCMP_001:
12926       /* Compare has bit 25 clear while test has it set.  */
12927       if (!uimm (aarch64_get_instr (cpu), 25, 25))
12928         dexCompareBranchImmediate (cpu);
12929       else
12930         dexTestBranchImmediate (cpu);
12931       return;
12932
12933     case BR_IMMCOND_010:
12934       /* This is a conditional branch if bit 25 is clear otherwise
12935          unallocated.  */
12936       if (!uimm (aarch64_get_instr (cpu), 25, 25))
12937         dexCondBranchImmediate (cpu);
12938       else
12939         HALT_UNALLOC;
12940       return;
12941
12942     case BR_UNALLOC_011:
12943       HALT_UNALLOC;
12944
12945     case BR_IMM_100:
12946       dexBranchImmediate (cpu);
12947       return;
12948
12949     case BR_IMMCMP_101:
12950       /* Compare has bit 25 clear while test has it set.  */
12951       if (!uimm (aarch64_get_instr (cpu), 25, 25))
12952         dexCompareBranchImmediate (cpu);
12953       else
12954         dexTestBranchImmediate (cpu);
12955       return;
12956
12957     case BR_REG_110:
12958       /* Unconditional branch reg has bit 25 set.  */
12959       if (uimm (aarch64_get_instr (cpu), 25, 25))
12960         dexBranchRegister (cpu);
12961
12962       /* This includes both Excpn Gen, System and unalloc operations.
12963          We need to decode the Excpn Gen operation BRK so we can plant
12964          debugger entry points.
12965          Excpn Gen operations have aarch64_get_instr (cpu)[24] = 0.
12966          we need to decode at least one of the System operations NOP
12967          which is an alias for HINT #0.
12968          System operations have aarch64_get_instr (cpu)[24,22] = 100.  */
12969       else if (uimm (aarch64_get_instr (cpu), 24, 24) == 0)
12970         dexExcpnGen (cpu);
12971
12972       else if (uimm (aarch64_get_instr (cpu), 24, 22) == 4)
12973         dexSystem (cpu);
12974
12975       else
12976         HALT_UNALLOC;
12977
12978       return;
12979
12980     case BR_UNALLOC_111:
12981       HALT_UNALLOC;
12982
12983     default:
12984       /* Should never reach here.  */
12985       HALT_NYI;
12986     }
12987 }
12988
12989 static void
12990 aarch64_decode_and_execute (sim_cpu *cpu, uint64_t pc)
12991 {
12992   /* We need to check if gdb wants an in here.  */
12993   /* checkBreak (cpu);.  */
12994
12995   uint64_t group = dispatchGroup (aarch64_get_instr (cpu));
12996
12997   switch (group)
12998     {
12999     case GROUP_PSEUDO_0000:   dexPseudo (cpu); break;
13000     case GROUP_LDST_0100:     dexLdSt (cpu); break;
13001     case GROUP_DPREG_0101:    dexDPReg (cpu); break;
13002     case GROUP_LDST_0110:     dexLdSt (cpu); break;
13003     case GROUP_ADVSIMD_0111:  dexAdvSIMD0 (cpu); break;
13004     case GROUP_DPIMM_1000:    dexDPImm (cpu); break;
13005     case GROUP_DPIMM_1001:    dexDPImm (cpu); break;
13006     case GROUP_BREXSYS_1010:  dexBr (cpu); break;
13007     case GROUP_BREXSYS_1011:  dexBr (cpu); break;
13008     case GROUP_LDST_1100:     dexLdSt (cpu); break;
13009     case GROUP_DPREG_1101:    dexDPReg (cpu); break;
13010     case GROUP_LDST_1110:     dexLdSt (cpu); break;
13011     case GROUP_ADVSIMD_1111:  dexAdvSIMD1 (cpu); break;
13012
13013     case GROUP_UNALLOC_0001:
13014     case GROUP_UNALLOC_0010:
13015     case GROUP_UNALLOC_0011:
13016       HALT_UNALLOC;
13017
13018     default:
13019       /* Should never reach here.  */
13020       HALT_NYI;
13021     }
13022 }
13023
13024 static bfd_boolean
13025 aarch64_step (sim_cpu *cpu)
13026 {
13027   uint64_t pc = aarch64_get_PC (cpu);
13028
13029   if (pc == TOP_LEVEL_RETURN_PC)
13030     return FALSE;
13031
13032   aarch64_set_next_PC (cpu, pc + 4);
13033   aarch64_get_instr (cpu) = aarch64_get_mem_u32 (cpu, pc);
13034
13035   if (TRACE_INSN_P (cpu))
13036     {
13037       if (disas)
13038         TRACE_INSN (cpu, " pc = %" PRIx64 " ", pc);
13039       else
13040         TRACE_INSN (cpu, " pc = %" PRIx64 " instr = %x", pc,
13041                     aarch64_get_instr (cpu));
13042     }
13043   else if (disas)
13044     sim_io_eprintf (CPU_STATE (cpu), " %" PRIx64 " ", pc);
13045
13046   if (disas)
13047     aarch64_print_insn (CPU_STATE (cpu), pc);
13048
13049   aarch64_decode_and_execute (cpu, pc);
13050
13051   return TRUE;
13052 }
13053
13054 void
13055 aarch64_run (SIM_DESC sd)
13056 {
13057   sim_cpu *cpu = STATE_CPU (sd, 0);
13058
13059   while (aarch64_step (cpu))
13060     aarch64_update_PC (cpu);
13061
13062   sim_engine_halt (sd, NULL, NULL, aarch64_get_PC (cpu),
13063                    sim_exited, aarch64_get_reg_s32 (cpu, R0, SP_OK));
13064 }
13065
13066 void
13067 aarch64_init (sim_cpu *cpu, uint64_t pc)
13068 {
13069   uint64_t sp = aarch64_get_stack_start (cpu);
13070
13071   /* Install SP, FP and PC and set LR to -20
13072      so we can detect a top-level return.  */
13073   aarch64_set_reg_u64 (cpu, SP, SP_OK, sp);
13074   aarch64_set_reg_u64 (cpu, FP, SP_OK, sp);
13075   aarch64_set_reg_u64 (cpu, LR, SP_OK, TOP_LEVEL_RETURN_PC);
13076   aarch64_set_next_PC (cpu, pc);
13077   aarch64_update_PC (cpu);
13078   aarch64_init_LIT_table ();
13079 }