Add simulation of MUL and NEG instructions to AArch64 simulator.
[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 "simulator.h"
32 #include "cpustate.h"
33 #include "memory.h"
34
35 #define NO_SP 0
36 #define SP_OK 1
37
38 #define TST(_flag)   (aarch64_test_CPSR_bit (cpu, _flag))
39 #define IS_SET(_X)   (TST (( _X )) ? 1 : 0)
40 #define IS_CLEAR(_X) (TST (( _X )) ? 0 : 1)
41
42 #define HALT_UNALLOC                                                    \
43   do                                                                    \
44     {                                                                   \
45       TRACE_DISASM (cpu, aarch64_get_PC (cpu));                         \
46       TRACE_INSN (cpu,                                                  \
47                   "Unallocated instruction detected at sim line %d,"    \
48                   " exe addr %" PRIx64,                                 \
49                   __LINE__, aarch64_get_PC (cpu));                      \
50       sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),\
51                        sim_stopped, SIM_SIGILL);                        \
52     }                                                                   \
53   while (0)
54
55 #define HALT_NYI                                                        \
56   do                                                                    \
57     {                                                                   \
58       TRACE_DISASM (cpu, aarch64_get_PC (cpu));                         \
59       TRACE_INSN (cpu,                                                  \
60                   "Unimplemented instruction detected at sim line %d,"  \
61                   " exe addr %" PRIx64,                                 \
62                   __LINE__, aarch64_get_PC (cpu));                      \
63       sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),\
64                        sim_stopped, SIM_SIGABRT);                       \
65     }                                                                   \
66   while (0)
67
68 #define NYI_assert(HI, LO, EXPECTED)                                    \
69   do                                                                    \
70     {                                                                   \
71       if (uimm (aarch64_get_instr (cpu), (HI), (LO)) != (EXPECTED))     \
72         HALT_NYI;                                                       \
73     }                                                                   \
74   while (0)
75
76 #define HALT_UNREACHABLE                                                \
77   do                                                                    \
78     {                                                                   \
79       TRACE_EVENTS (cpu, "ISE: unreachable code point");                \
80       sim_engine_abort (NULL, cpu, aarch64_get_PC (cpu), "Internal Error"); \
81     }                                                                   \
82   while (0)
83
84 /* Helper functions used by expandLogicalImmediate.  */
85
86 /* for i = 1, ... N result<i-1> = 1 other bits are zero  */
87 static inline uint64_t
88 ones (int N)
89 {
90   return (N == 64 ? (uint64_t)-1UL : ((1UL << N) - 1));
91 }
92
93 /* result<0> to val<N>  */
94 static inline uint64_t
95 pickbit (uint64_t val, int N)
96 {
97   return pickbits64 (val, N, N);
98 }
99
100 static uint64_t
101 expand_logical_immediate (uint32_t S, uint32_t R, uint32_t N)
102 {
103   uint64_t mask;
104   uint64_t imm;
105   unsigned simd_size;
106
107   /* The immediate value is S+1 bits to 1, left rotated by SIMDsize - R
108      (in other words, right rotated by R), then replicated. */
109   if (N != 0)
110     {
111       simd_size = 64;
112       mask = 0xffffffffffffffffull;
113     }
114   else
115     {
116       switch (S)
117         {
118         case 0x00 ... 0x1f: /* 0xxxxx */ simd_size = 32;           break;
119         case 0x20 ... 0x2f: /* 10xxxx */ simd_size = 16; S &= 0xf; break;
120         case 0x30 ... 0x37: /* 110xxx */ simd_size =  8; S &= 0x7; break;
121         case 0x38 ... 0x3b: /* 1110xx */ simd_size =  4; S &= 0x3; break;
122         case 0x3c ... 0x3d: /* 11110x */ simd_size =  2; S &= 0x1; break;
123         default: return 0;
124         }
125       mask = (1ull << simd_size) - 1;
126       /* Top bits are IGNORED.  */
127       R &= simd_size - 1;
128     }
129
130   /* NOTE: if S = simd_size - 1 we get 0xf..f which is rejected.  */
131   if (S == simd_size - 1)
132     return 0;
133
134   /* S+1 consecutive bits to 1.  */
135   /* NOTE: S can't be 63 due to detection above.  */
136   imm = (1ull << (S + 1)) - 1;
137
138   /* Rotate to the left by simd_size - R.  */
139   if (R != 0)
140     imm = ((imm << (simd_size - R)) & mask) | (imm >> R);
141
142   /* Replicate the value according to SIMD size.  */
143   switch (simd_size)
144     {
145     case  2: imm = (imm <<  2) | imm;
146     case  4: imm = (imm <<  4) | imm;
147     case  8: imm = (imm <<  8) | imm;
148     case 16: imm = (imm << 16) | imm;
149     case 32: imm = (imm << 32) | imm;
150     case 64: break;
151     default: return 0;
152     }
153
154   return imm;
155 }
156
157 /* Instr[22,10] encodes N immr and imms. we want a lookup table
158    for each possible combination i.e. 13 bits worth of int entries.  */
159 #define  LI_TABLE_SIZE  (1 << 13)
160 static uint64_t LITable[LI_TABLE_SIZE];
161
162 void
163 aarch64_init_LIT_table (void)
164 {
165   unsigned index;
166
167   for (index = 0; index < LI_TABLE_SIZE; index++)
168     {
169       uint32_t N    = uimm (index, 12, 12);
170       uint32_t immr = uimm (index, 11, 6);
171       uint32_t imms = uimm (index, 5, 0);
172
173       LITable [index] = expand_logical_immediate (imms, immr, N);
174     }
175 }
176
177 static void
178 dexNotify (sim_cpu *cpu)
179 {
180   /* instr[14,0] == type : 0 ==> method entry, 1 ==> method reentry
181                            2 ==> exit Java, 3 ==> start next bytecode.  */
182   uint32_t type = uimm (aarch64_get_instr (cpu), 14, 0);
183
184   TRACE_EVENTS (cpu, "Notify Insn encountered, type = 0x%x", type);
185
186   switch (type)
187     {
188     case 0:
189       /* aarch64_notifyMethodEntry (aarch64_get_reg_u64 (cpu, R23, 0),
190          aarch64_get_reg_u64 (cpu, R22, 0));  */
191       break;
192     case 1:
193       /* aarch64_notifyMethodReentry (aarch64_get_reg_u64 (cpu, R23, 0),
194          aarch64_get_reg_u64 (cpu, R22, 0));  */
195       break;
196     case 2:
197       /* aarch64_notifyMethodExit ();  */
198       break;
199     case 3:
200       /* aarch64_notifyBCStart (aarch64_get_reg_u64 (cpu, R23, 0),
201          aarch64_get_reg_u64 (cpu, R22, 0));  */
202       break;
203     }
204 }
205
206 /* secondary decode within top level groups  */
207
208 static void
209 dexPseudo (sim_cpu *cpu)
210 {
211   /* assert instr[28,27] = 00
212
213      We provide 2 pseudo instructions:
214
215      HALT stops execution of the simulator causing an immediate
216      return to the x86 code which entered it.
217
218      CALLOUT initiates recursive entry into x86 code.  A register
219      argument holds the address of the x86 routine.  Immediate
220      values in the instruction identify the number of general
221      purpose and floating point register arguments to be passed
222      and the type of any value to be returned.  */
223
224   uint32_t PSEUDO_HALT      =  0xE0000000U;
225   uint32_t PSEUDO_CALLOUT   =  0x00018000U;
226   uint32_t PSEUDO_CALLOUTR  =  0x00018001U;
227   uint32_t PSEUDO_NOTIFY    =  0x00014000U;
228   uint32_t dispatch;
229
230   if (aarch64_get_instr (cpu) == PSEUDO_HALT)
231     {
232       TRACE_EVENTS (cpu, " Pseudo Halt Instruction");
233       sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
234                        sim_stopped, SIM_SIGTRAP);
235     }
236
237   dispatch = uimm (aarch64_get_instr (cpu), 31, 15);
238
239   /* We do not handle callouts at the moment.  */
240   if (dispatch == PSEUDO_CALLOUT || dispatch == PSEUDO_CALLOUTR)
241     {
242       TRACE_EVENTS (cpu, " Callout");
243       sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
244                        sim_stopped, SIM_SIGABRT);
245     }
246
247   else if (dispatch == PSEUDO_NOTIFY)
248     dexNotify (cpu);
249
250   else
251     HALT_UNALLOC;
252 }
253
254 /* Load-store single register (unscaled offset)
255    These instructions employ a base register plus an unscaled signed
256    9 bit offset.
257
258    N.B. the base register (source) can be Xn or SP. all other
259    registers may not be SP.  */
260
261 /* 32 bit load 32 bit unscaled signed 9 bit.  */
262 static void
263 ldur32 (sim_cpu *cpu, int32_t offset)
264 {
265   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
266   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
267
268   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32
269                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
270                         + offset));
271 }
272
273 /* 64 bit load 64 bit unscaled signed 9 bit.  */
274 static void
275 ldur64 (sim_cpu *cpu, int32_t offset)
276 {
277   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
278   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
279
280   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64
281                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
282                         + offset));
283 }
284
285 /* 32 bit load zero-extended byte unscaled signed 9 bit.  */
286 static void
287 ldurb32 (sim_cpu *cpu, int32_t offset)
288 {
289   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
290   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
291
292   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u8
293                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
294                         + offset));
295 }
296
297 /* 32 bit load sign-extended byte unscaled signed 9 bit.  */
298 static void
299 ldursb32 (sim_cpu *cpu, int32_t offset)
300 {
301   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
302   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
303
304   aarch64_set_reg_u64 (cpu, rt, NO_SP, (uint32_t) aarch64_get_mem_s8
305                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
306                         + offset));
307 }
308
309 /* 64 bit load sign-extended byte unscaled signed 9 bit.  */
310 static void
311 ldursb64 (sim_cpu *cpu, int32_t offset)
312 {
313   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
314   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
315
316   aarch64_set_reg_s64 (cpu, rt, NO_SP, aarch64_get_mem_s8
317                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
318                         + offset));
319 }
320
321 /* 32 bit load zero-extended short unscaled signed 9 bit  */
322 static void
323 ldurh32 (sim_cpu *cpu, int32_t offset)
324 {
325   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
326   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
327
328   aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_mem_u16
329                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
330                         + offset));
331 }
332
333 /* 32 bit load sign-extended short unscaled signed 9 bit  */
334 static void
335 ldursh32 (sim_cpu *cpu, int32_t offset)
336 {
337   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
338   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
339
340   aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) aarch64_get_mem_s16
341                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
342                         + offset));
343 }
344
345 /* 64 bit load sign-extended short unscaled signed 9 bit  */
346 static void
347 ldursh64 (sim_cpu *cpu, int32_t offset)
348 {
349   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
350   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
351
352   aarch64_set_reg_s64 (cpu, rt, NO_SP, aarch64_get_mem_s16
353                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
354                         + offset));
355 }
356
357 /* 64 bit load sign-extended word unscaled signed 9 bit  */
358 static void
359 ldursw (sim_cpu *cpu, int32_t offset)
360 {
361   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
362   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
363
364   aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) aarch64_get_mem_s32
365                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
366                         + offset));
367 }
368
369 /* N.B. with stores the value in source is written to the address
370    identified by source2 modified by offset.  */
371
372 /* 32 bit store 32 bit unscaled signed 9 bit.  */
373 static void
374 stur32 (sim_cpu *cpu, int32_t offset)
375 {
376   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
377   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
378
379   aarch64_set_mem_u32 (cpu,
380                        aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
381                        aarch64_get_reg_u32 (cpu, rd, NO_SP));
382 }
383
384 /* 64 bit store 64 bit unscaled signed 9 bit  */
385 static void
386 stur64 (sim_cpu *cpu, int32_t offset)
387 {
388   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
389   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
390
391   aarch64_set_mem_u64 (cpu,
392                        aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
393                        aarch64_get_reg_u64 (cpu, rd, NO_SP));
394 }
395
396 /* 32 bit store byte unscaled signed 9 bit  */
397 static void
398 sturb (sim_cpu *cpu, int32_t offset)
399 {
400   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
401   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
402
403   aarch64_set_mem_u8 (cpu,
404                       aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
405                       aarch64_get_reg_u8 (cpu, rd, NO_SP));
406 }
407
408 /* 32 bit store short unscaled signed 9 bit  */
409 static void
410 sturh (sim_cpu *cpu, int32_t offset)
411 {
412   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
413   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
414
415   aarch64_set_mem_u16 (cpu,
416                        aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
417                        aarch64_get_reg_u16 (cpu, rd, NO_SP));
418 }
419
420 /* Load single register pc-relative label
421    Offset is a signed 19 bit immediate count in words
422    rt may not be SP.  */
423
424 /* 32 bit pc-relative load  */
425 static void
426 ldr32_pcrel (sim_cpu *cpu, int32_t offset)
427 {
428   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
429
430   aarch64_set_reg_u64 (cpu, rd, NO_SP,
431                        aarch64_get_mem_u32
432                        (cpu, aarch64_get_PC (cpu) + offset * 4));
433 }
434
435 /* 64 bit pc-relative load  */
436 static void
437 ldr_pcrel (sim_cpu *cpu, int32_t offset)
438 {
439   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
440
441   aarch64_set_reg_u64 (cpu, rd, NO_SP,
442                        aarch64_get_mem_u64
443                        (cpu, aarch64_get_PC (cpu) + offset * 4));
444 }
445
446 /* sign extended 32 bit pc-relative load  */
447 static void
448 ldrsw_pcrel (sim_cpu *cpu, int32_t offset)
449 {
450   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
451
452   aarch64_set_reg_u64 (cpu, rd, NO_SP,
453                        aarch64_get_mem_s32
454                        (cpu, aarch64_get_PC (cpu) + offset * 4));
455 }
456
457 /* float pc-relative load  */
458 static void
459 fldrs_pcrel (sim_cpu *cpu, int32_t offset)
460 {
461   unsigned int rd = uimm (aarch64_get_instr (cpu), 4, 0);
462
463   aarch64_set_vec_u32 (cpu, rd, 0,
464                        aarch64_get_mem_u32
465                        (cpu, aarch64_get_PC (cpu) + offset * 4));
466 }
467
468 /* double pc-relative load  */
469 static void
470 fldrd_pcrel (sim_cpu *cpu, int32_t offset)
471 {
472   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
473
474   aarch64_set_vec_u64 (cpu, st, 0,
475                        aarch64_get_mem_u64
476                        (cpu, aarch64_get_PC (cpu) + offset * 4));
477 }
478
479 /* long double pc-relative load.  */
480 static void
481 fldrq_pcrel (sim_cpu *cpu, int32_t offset)
482 {
483   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
484   uint64_t addr = aarch64_get_PC (cpu) + offset * 4;
485   FRegister a;
486
487   aarch64_get_mem_long_double (cpu, addr, & a);
488   aarch64_set_FP_long_double (cpu, st, a);
489 }
490
491 /* This can be used to scale an offset by applying
492    the requisite shift. the second argument is either
493    16, 32 or 64.  */
494
495 #define SCALE(_offset, _elementSize) \
496     ((_offset) << ScaleShift ## _elementSize)
497
498 /* This can be used to optionally scale a register derived offset
499    by applying the requisite shift as indicated by the Scaling
500    argument. the second argument is either Byte, Short, Word
501    or Long. The third argument is either Scaled or Unscaled.
502    N.B. when _Scaling is Scaled the shift gets ANDed with
503    all 1s while when it is Unscaled it gets ANDed with 0.  */
504
505 #define OPT_SCALE(_offset, _elementType, _Scaling) \
506   ((_offset) << (_Scaling ? ScaleShift ## _elementType : 0))
507
508 /* This can be used to zero or sign extend a 32 bit register derived
509    value to a 64 bit value.  the first argument must be the value as
510    a uint32_t and the second must be either UXTW or SXTW. The result
511    is returned as an int64_t.  */
512
513 static inline int64_t
514 extend (uint32_t value, Extension extension)
515 {
516   union
517   {
518     uint32_t u;
519     int32_t   n;
520   } x;
521
522   /* A branchless variant of this ought to be possible.  */
523   if (extension == UXTW || extension == NoExtension)
524     return value;
525
526   x.u = value;
527   return x.n;
528 }
529
530 /* Scalar Floating Point
531
532    FP load/store single register (4 addressing modes)
533
534    N.B. the base register (source) can be the stack pointer.
535    The secondary source register (source2) can only be an Xn register.  */
536
537 /* Load 32 bit unscaled signed 9 bit with pre- or post-writeback.  */
538 static void
539 fldrs_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
540 {
541   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
542   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
543   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
544
545   if (wb != Post)
546     address += offset;
547
548   aarch64_set_vec_u32 (cpu, st, 0, aarch64_get_mem_u32 (cpu, address));
549   if (wb == Post)
550     address += offset;
551
552   if (wb != NoWriteBack)
553     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
554 }
555
556 /* Load 32 bit scaled unsigned 12 bit.  */
557 static void
558 fldrs_abs (sim_cpu *cpu, uint32_t offset)
559 {
560   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
561   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
562
563   aarch64_set_vec_u32 (cpu, st, 0, aarch64_get_mem_u32
564                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
565                         + SCALE (offset, 32)));
566 }
567
568 /* Load 32 bit scaled or unscaled zero- or sign-extended
569    32-bit register offset.  */
570 static void
571 fldrs_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
572 {
573   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
574   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
575   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
576   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
577   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
578   uint64_t displacement = OPT_SCALE (extended, 32, scaling);
579
580   aarch64_set_vec_u32 (cpu, st, 0, aarch64_get_mem_u32
581                        (cpu, address + displacement));
582 }
583
584 /* Load 64 bit unscaled signed 9 bit with pre- or post-writeback.  */
585 static void
586 fldrd_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
587 {
588   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
589   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
590   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
591
592   if (wb != Post)
593     address += offset;
594
595   aarch64_set_vec_u64 (cpu, st, 0, aarch64_get_mem_u64 (cpu, address));
596
597   if (wb == Post)
598     address += offset;
599
600   if (wb != NoWriteBack)
601     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
602 }
603
604 /* Load 64 bit scaled unsigned 12 bit.  */
605 static void
606 fldrd_abs (sim_cpu *cpu, uint32_t offset)
607 {
608   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
609   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
610   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 64);
611
612   aarch64_set_vec_u64 (cpu, st, 0, aarch64_get_mem_u64 (cpu, address));
613 }
614
615 /* Load 64 bit scaled or unscaled zero- or sign-extended 32-bit register offset.  */
616 static void
617 fldrd_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
618 {
619   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
620   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
621   uint64_t displacement = OPT_SCALE (extended, 64, scaling);
622
623   fldrd_wb (cpu, displacement, NoWriteBack);
624 }
625
626 /* Load 128 bit unscaled signed 9 bit with pre- or post-writeback.  */
627 static void
628 fldrq_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
629 {
630   FRegister a;
631   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
632   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
633   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
634
635   if (wb != Post)
636     address += offset;
637
638   aarch64_get_mem_long_double (cpu, address, & a);
639   aarch64_set_FP_long_double (cpu, st, a);
640
641   if (wb == Post)
642     address += offset;
643
644   if (wb != NoWriteBack)
645     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
646 }
647
648 /* Load 128 bit scaled unsigned 12 bit.  */
649 static void
650 fldrq_abs (sim_cpu *cpu, uint32_t offset)
651 {
652   FRegister a;
653   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
654   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
655   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 128);
656
657   aarch64_get_mem_long_double (cpu, address, & a);
658   aarch64_set_FP_long_double (cpu, st, a);
659 }
660
661 /* Load 128 bit scaled or unscaled zero- or sign-extended 32-bit register offset  */
662 static void
663 fldrq_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
664 {
665   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
666   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
667   uint64_t displacement = OPT_SCALE (extended, 128, scaling);
668
669   fldrq_wb (cpu, displacement, NoWriteBack);
670 }
671
672 /* Memory Access
673
674    load-store single register
675    There are four addressing modes available here which all employ a
676    64 bit source (base) register.
677
678    N.B. the base register (source) can be the stack pointer.
679    The secondary source register (source2)can only be an Xn register.
680
681    Scaled, 12-bit, unsigned immediate offset, without pre- and
682    post-index options.
683    Unscaled, 9-bit, signed immediate offset with pre- or post-index
684    writeback.
685    scaled or unscaled 64-bit register offset.
686    scaled or unscaled 32-bit extended register offset.
687
688    All offsets are assumed to be raw from the decode i.e. the
689    simulator is expected to adjust scaled offsets based on the
690    accessed data size with register or extended register offset
691    versions the same applies except that in the latter case the
692    operation may also require a sign extend.
693
694    A separate method is provided for each possible addressing mode.  */
695
696 /* 32 bit load 32 bit scaled unsigned 12 bit  */
697 static void
698 ldr32_abs (sim_cpu *cpu, uint32_t offset)
699 {
700   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
701   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
702
703   /* The target register may not be SP but the source may be.  */
704   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32
705                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
706                         + SCALE (offset, 32)));
707 }
708
709 /* 32 bit load 32 bit unscaled signed 9 bit with pre- or post-writeback.  */
710 static void
711 ldr32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
712 {
713   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
714   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
715   uint64_t address;
716
717   if (rn == rt && wb != NoWriteBack)
718     HALT_UNALLOC;
719
720   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
721
722   if (wb != Post)
723     address += offset;
724
725   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32 (cpu, address));
726
727   if (wb == Post)
728     address += offset;
729
730   if (wb != NoWriteBack)
731     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
732 }
733
734 /* 32 bit load 32 bit scaled or unscaled
735    zero- or sign-extended 32-bit register offset  */
736 static void
737 ldr32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
738 {
739   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
740   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
741   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
742   /* rn may reference SP, rm and rt must reference ZR  */
743
744   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
745   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
746   uint64_t displacement =  OPT_SCALE (extended, 32, scaling);
747
748   aarch64_set_reg_u64 (cpu, rt, NO_SP,
749                        aarch64_get_mem_u32 (cpu, address + displacement));
750 }
751
752 /* 64 bit load 64 bit scaled unsigned 12 bit  */
753 static void
754 ldr_abs (sim_cpu *cpu, uint32_t offset)
755 {
756   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
757   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
758
759   /* The target register may not be SP but the source may be.  */
760   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64
761                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
762                         + SCALE (offset, 64)));
763 }
764
765 /* 64 bit load 64 bit unscaled signed 9 bit with pre- or post-writeback.  */
766 static void
767 ldr_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
768 {
769   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
770   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
771   uint64_t address;
772
773   if (rn == rt && wb != NoWriteBack)
774     HALT_UNALLOC;
775
776   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
777
778   if (wb != Post)
779     address += offset;
780
781   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64 (cpu, address));
782
783   if (wb == Post)
784     address += offset;
785
786   if (wb != NoWriteBack)
787     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
788 }
789
790 /* 64 bit load 64 bit scaled or unscaled zero-
791    or sign-extended 32-bit register offset.  */
792 static void
793 ldr_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
794 {
795   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
796   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
797   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
798   /* rn may reference SP, rm and rt must reference ZR  */
799
800   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
801   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
802   uint64_t displacement =  OPT_SCALE (extended, 64, scaling);
803
804   aarch64_set_reg_u64 (cpu, rt, NO_SP,
805                        aarch64_get_mem_u64 (cpu, address + displacement));
806 }
807
808 /* 32 bit load zero-extended byte scaled unsigned 12 bit.  */
809 static void
810 ldrb32_abs (sim_cpu *cpu, uint32_t offset)
811 {
812   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
813   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
814
815   /* The target register may not be SP but the source may be
816      there is no scaling required for a byte load.  */
817   aarch64_set_reg_u64 (cpu, rt, NO_SP,
818                        aarch64_get_mem_u8
819                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset));
820 }
821
822 /* 32 bit load zero-extended byte unscaled signed 9 bit with pre- or post-writeback.  */
823 static void
824 ldrb32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
825 {
826   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
827   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
828   uint64_t address;
829
830   if (rn == rt && wb != NoWriteBack)
831     HALT_UNALLOC;
832
833   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
834
835   if (wb != Post)
836     address += offset;
837
838   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u8 (cpu, address));
839
840   if (wb == Post)
841     address += offset;
842
843   if (wb != NoWriteBack)
844     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
845 }
846
847 /* 32 bit load zero-extended byte scaled or unscaled zero-
848    or sign-extended 32-bit register offset.  */
849 static void
850 ldrb32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
851 {
852   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
853   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
854   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
855   /* rn may reference SP, rm and rt must reference ZR  */
856
857   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
858   int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
859                                  extension);
860
861   /* There is no scaling required for a byte load.  */
862   aarch64_set_reg_u64 (cpu, rt, NO_SP,
863                        aarch64_get_mem_u8 (cpu, address + displacement));
864 }
865
866 /* 64 bit load sign-extended byte unscaled signed 9 bit
867    with pre- or post-writeback.  */
868 static void
869 ldrsb_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
870 {
871   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
872   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
873   uint64_t address;
874
875   if (rn == rt && wb != NoWriteBack)
876     HALT_UNALLOC;
877
878   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
879
880   if (wb != Post)
881     address += offset;
882
883   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_s8 (cpu, address));
884
885   if (wb == Post)
886     address += offset;
887
888   if (wb != NoWriteBack)
889     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
890 }
891
892 /* 64 bit load sign-extended byte scaled unsigned 12 bit.  */
893 static void
894 ldrsb_abs (sim_cpu *cpu, uint32_t offset)
895 {
896   ldrsb_wb (cpu, offset, NoWriteBack);
897 }
898
899 /* 64 bit load sign-extended byte scaled or unscaled zero-
900    or sign-extended 32-bit register offset.  */
901 static void
902 ldrsb_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
903 {
904   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
905   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
906   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
907   /* rn may reference SP, rm and rt must reference ZR  */
908
909   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
910   int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
911                                  extension);
912   /* There is no scaling required for a byte load.  */
913   aarch64_set_reg_u64 (cpu, rt, NO_SP,
914                        aarch64_get_mem_s8 (cpu, address + displacement));
915 }
916
917 /* 32 bit load zero-extended short scaled unsigned 12 bit.  */
918 static void
919 ldrh32_abs (sim_cpu *cpu, uint32_t offset)
920 {
921   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
922   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
923
924   /* The target register may not be SP but the source may be.  */
925   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u16
926                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
927                         + SCALE (offset, 16)));
928 }
929
930 /* 32 bit load zero-extended short unscaled signed 9 bit
931    with pre- or post-writeback.  */
932 static void
933 ldrh32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
934 {
935   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
936   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
937   uint64_t address;
938
939   if (rn == rt && wb != NoWriteBack)
940     HALT_UNALLOC;
941
942   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
943
944   if (wb != Post)
945     address += offset;
946
947   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u16 (cpu, address));
948
949   if (wb == Post)
950     address += offset;
951
952   if (wb != NoWriteBack)
953     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
954 }
955
956 /* 32 bit load zero-extended short scaled or unscaled zero-
957    or sign-extended 32-bit register offset.  */
958 static void
959 ldrh32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
960 {
961   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
962   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
963   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
964   /* rn may reference SP, rm and rt must reference ZR  */
965
966   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
967   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
968   uint64_t displacement =  OPT_SCALE (extended, 16, scaling);
969
970   aarch64_set_reg_u64 (cpu, rt, NO_SP,
971                        aarch64_get_mem_u16 (cpu, address + displacement));
972 }
973
974 /* 32 bit load sign-extended short scaled unsigned 12 bit.  */
975 static void
976 ldrsh32_abs (sim_cpu *cpu, uint32_t offset)
977 {
978   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
979   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
980
981   /* The target register may not be SP but the source may be.  */
982   aarch64_set_reg_u64 (cpu, rt, NO_SP, (uint32_t) aarch64_get_mem_s16
983                        (cpu,
984                         aarch64_get_reg_u64 (cpu, rn, SP_OK)
985                         + SCALE (offset, 16)));
986 }
987
988 /* 32 bit load sign-extended short unscaled signed 9 bit
989    with pre- or post-writeback.  */
990 static void
991 ldrsh32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
992 {
993   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
994   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
995   uint64_t address;
996
997   if (rn == rt && wb != NoWriteBack)
998     HALT_UNALLOC;
999
1000   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1001
1002   if (wb != Post)
1003     address += offset;
1004
1005   aarch64_set_reg_u64 (cpu, rt, NO_SP,
1006                        (uint32_t) aarch64_get_mem_s16 (cpu, address));
1007
1008   if (wb == Post)
1009     address += offset;
1010
1011   if (wb != NoWriteBack)
1012     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1013 }
1014
1015 /* 32 bit load sign-extended short scaled or unscaled zero-
1016    or sign-extended 32-bit register offset.  */
1017 static void
1018 ldrsh32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1019 {
1020   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1021   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1022   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1023   /* rn may reference SP, rm and rt must reference ZR  */
1024
1025   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1026   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1027   uint64_t displacement =  OPT_SCALE (extended, 16, scaling);
1028
1029   aarch64_set_reg_u64 (cpu, rt, NO_SP,
1030                        (uint32_t) aarch64_get_mem_s16
1031                        (cpu, address + displacement));
1032 }
1033
1034 /* 64 bit load sign-extended short scaled unsigned 12 bit.  */
1035 static void
1036 ldrsh_abs (sim_cpu *cpu, uint32_t offset)
1037 {
1038   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1039   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1040
1041   /* The target register may not be SP but the source may be.  */
1042   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_s16
1043                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
1044                         + SCALE (offset, 16)));
1045 }
1046
1047 /* 64 bit load sign-extended short unscaled signed 9 bit
1048    with pre- or post-writeback.  */
1049 static void
1050 ldrsh64_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1051 {
1052   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1053   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1054   uint64_t address;
1055
1056   if (rn == rt && wb != NoWriteBack)
1057     HALT_UNALLOC;
1058
1059   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1060
1061   if (wb != Post)
1062     address += offset;
1063
1064   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_s16 (cpu, address));
1065
1066   if (wb == Post)
1067     address += offset;
1068
1069   if (wb != NoWriteBack)
1070     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1071 }
1072
1073 /* 64 bit load sign-extended short scaled or unscaled zero-
1074    or sign-extended 32-bit register offset.  */
1075 static void
1076 ldrsh_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1077 {
1078   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1079   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1080   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1081   /* rn may reference SP, rm and rt must reference ZR  */
1082
1083   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1084   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1085   uint64_t displacement = OPT_SCALE (extended, 16, scaling);
1086
1087   aarch64_set_reg_u64 (cpu, rt, NO_SP,
1088                        aarch64_get_mem_s16 (cpu, address + displacement));
1089 }
1090
1091 /* 64 bit load sign-extended 32 bit scaled unsigned 12 bit.  */
1092 static void
1093 ldrsw_abs (sim_cpu *cpu, uint32_t offset)
1094 {
1095   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1096   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1097
1098   /* The target register may not be SP but the source may be.  */
1099   return aarch64_set_reg_s64 (cpu, rt, NO_SP, aarch64_get_mem_s32
1100                               (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
1101                                + SCALE (offset, 32)));
1102 }
1103
1104 /* 64 bit load sign-extended 32 bit unscaled signed 9 bit
1105    with pre- or post-writeback.  */
1106 static void
1107 ldrsw_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1108 {
1109   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1110   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1111   uint64_t address;
1112
1113   if (rn == rt && wb != NoWriteBack)
1114     HALT_UNALLOC;
1115
1116   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1117
1118   if (wb != Post)
1119     address += offset;
1120
1121   aarch64_set_reg_s64 (cpu, rt, NO_SP, aarch64_get_mem_s32 (cpu, address));
1122
1123   if (wb == Post)
1124     address += offset;
1125
1126   if (wb != NoWriteBack)
1127     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1128 }
1129
1130 /* 64 bit load sign-extended 32 bit scaled or unscaled zero-
1131    or sign-extended 32-bit register offset.  */
1132 static void
1133 ldrsw_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1134 {
1135   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1136   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1137   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1138   /* rn may reference SP, rm and rt must reference ZR  */
1139
1140   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1141   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1142   uint64_t displacement =  OPT_SCALE (extended, 32, scaling);
1143
1144   aarch64_set_reg_s64 (cpu, rt, NO_SP,
1145                        aarch64_get_mem_s32 (cpu, address + displacement));
1146 }
1147
1148 /* N.B. with stores the value in source is written to the
1149    address identified by source2 modified by source3/offset.  */
1150
1151 /* 32 bit store scaled unsigned 12 bit.  */
1152 static void
1153 str32_abs (sim_cpu *cpu, uint32_t offset)
1154 {
1155   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1156   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1157
1158   /* The target register may not be SP but the source may be.  */
1159   aarch64_set_mem_u32 (cpu, (aarch64_get_reg_u64 (cpu, rn, SP_OK)
1160                              + SCALE (offset, 32)),
1161                        aarch64_get_reg_u32 (cpu, rt, NO_SP));
1162 }
1163
1164 /* 32 bit store unscaled signed 9 bit with pre- or post-writeback.  */
1165 static void
1166 str32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1167 {
1168   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1169   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1170   uint64_t address;
1171
1172   if (rn == rt && wb != NoWriteBack)
1173     HALT_UNALLOC;
1174
1175   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1176   if (wb != Post)
1177     address += offset;
1178
1179   aarch64_set_mem_u32 (cpu, address, aarch64_get_reg_u32 (cpu, rt, NO_SP));
1180
1181   if (wb == Post)
1182     address += offset;
1183
1184   if (wb != NoWriteBack)
1185     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1186 }
1187
1188 /* 32 bit store scaled or unscaled zero- or
1189    sign-extended 32-bit register offset.  */
1190 static void
1191 str32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1192 {
1193   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1194   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1195   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1196
1197   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1198   int64_t  extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1199   uint64_t displacement = OPT_SCALE (extended, 32, scaling);
1200
1201   aarch64_set_mem_u32 (cpu, address + displacement,
1202                        aarch64_get_reg_u64 (cpu, rt, NO_SP));
1203 }
1204
1205 /* 64 bit store scaled unsigned 12 bit.  */
1206 static void
1207 str_abs (sim_cpu *cpu, uint32_t offset)
1208 {
1209   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1210   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1211
1212   aarch64_set_mem_u64 (cpu,
1213                        aarch64_get_reg_u64 (cpu, rn, SP_OK)
1214                        + SCALE (offset, 64),
1215                        aarch64_get_reg_u64 (cpu, rt, NO_SP));
1216 }
1217
1218 /* 64 bit store unscaled signed 9 bit with pre- or post-writeback.  */
1219 static void
1220 str_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1221 {
1222   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1223   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1224   uint64_t address;
1225
1226   if (rn == rt && wb != NoWriteBack)
1227     HALT_UNALLOC;
1228
1229   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1230
1231   if (wb != Post)
1232     address += offset;
1233
1234   aarch64_set_mem_u64 (cpu, address, aarch64_get_reg_u64 (cpu, rt, NO_SP));
1235
1236   if (wb == Post)
1237     address += offset;
1238
1239   if (wb != NoWriteBack)
1240     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1241 }
1242
1243 /* 64 bit store scaled or unscaled zero-
1244    or sign-extended 32-bit register offset.  */
1245 static void
1246 str_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1247 {
1248   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1249   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1250   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1251   /* rn may reference SP, rm and rt must reference ZR  */
1252
1253   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1254   int64_t   extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1255                                extension);
1256   uint64_t displacement = OPT_SCALE (extended, 64, scaling);
1257
1258   aarch64_set_mem_u64 (cpu, address + displacement,
1259                        aarch64_get_reg_u64 (cpu, rt, NO_SP));
1260 }
1261
1262 /* 32 bit store byte scaled unsigned 12 bit.  */
1263 static void
1264 strb_abs (sim_cpu *cpu, uint32_t offset)
1265 {
1266   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1267   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1268
1269   /* The target register may not be SP but the source may be.
1270      There is no scaling required for a byte load.  */
1271   aarch64_set_mem_u8 (cpu,
1272                       aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
1273                       aarch64_get_reg_u8 (cpu, rt, NO_SP));
1274 }
1275
1276 /* 32 bit store byte unscaled signed 9 bit with pre- or post-writeback.  */
1277 static void
1278 strb_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1279 {
1280   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1281   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1282   uint64_t address;
1283
1284   if (rn == rt && wb != NoWriteBack)
1285     HALT_UNALLOC;
1286
1287   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1288
1289   if (wb != Post)
1290     address += offset;
1291
1292   aarch64_set_mem_u8 (cpu, address, aarch64_get_reg_u8 (cpu, rt, NO_SP));
1293
1294   if (wb == Post)
1295     address += offset;
1296
1297   if (wb != NoWriteBack)
1298     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1299 }
1300
1301 /* 32 bit store byte scaled or unscaled zero-
1302    or sign-extended 32-bit register offset.  */
1303 static void
1304 strb_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1305 {
1306   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1307   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1308   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1309   /* rn may reference SP, rm and rt must reference ZR  */
1310
1311   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1312   int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1313                                  extension);
1314
1315   /* There is no scaling required for a byte load.  */
1316   aarch64_set_mem_u8 (cpu, address + displacement,
1317                       aarch64_get_reg_u8 (cpu, rt, NO_SP));
1318 }
1319
1320 /* 32 bit store short scaled unsigned 12 bit.  */
1321 static void
1322 strh_abs (sim_cpu *cpu, uint32_t offset)
1323 {
1324   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1325   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1326
1327   /* The target register may not be SP but the source may be.  */
1328   aarch64_set_mem_u16 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
1329                        + SCALE (offset, 16),
1330                        aarch64_get_reg_u16 (cpu, rt, NO_SP));
1331 }
1332
1333 /* 32 bit store short unscaled signed 9 bit with pre- or post-writeback.  */
1334 static void
1335 strh_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1336 {
1337   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1338   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1339   uint64_t address;
1340
1341   if (rn == rt && wb != NoWriteBack)
1342     HALT_UNALLOC;
1343
1344   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1345
1346   if (wb != Post)
1347     address += offset;
1348
1349   aarch64_set_mem_u16 (cpu, address, aarch64_get_reg_u16 (cpu, rt, NO_SP));
1350
1351   if (wb == Post)
1352     address += offset;
1353
1354   if (wb != NoWriteBack)
1355     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1356 }
1357
1358 /* 32 bit store short scaled or unscaled zero-
1359    or sign-extended 32-bit register offset.  */
1360 static void
1361 strh_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1362 {
1363   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1364   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1365   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1366   /* rn may reference SP, rm and rt must reference ZR  */
1367
1368   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1369   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1370   uint64_t displacement =  OPT_SCALE (extended, 16, scaling);
1371
1372   aarch64_set_mem_u16 (cpu, address + displacement,
1373                        aarch64_get_reg_u16 (cpu, rt, NO_SP));
1374 }
1375
1376 /* Prefetch unsigned 12 bit.  */
1377 static void
1378 prfm_abs (sim_cpu *cpu, uint32_t offset)
1379 {
1380   /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1381                           00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1382                           00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1383                           10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1384                           10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1385                           10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1386                           ow ==> UNALLOC
1387      PrfOp prfop = prfop (aarch64_get_instr (cpu), 4, 0);
1388      uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK)
1389      + SCALE (offset, 64).  */
1390
1391   /* TODO : implement prefetch of address.  */
1392 }
1393
1394 /* Prefetch scaled or unscaled zero- or sign-extended 32-bit register offset.  */
1395 static void
1396 prfm_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1397 {
1398   /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1399                           00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1400                           00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1401                           10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1402                           10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1403                           10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1404                           ow ==> UNALLOC
1405      rn may reference SP, rm may only reference ZR
1406      PrfOp prfop = prfop (aarch64_get_instr (cpu), 4, 0);
1407      uint64_t base = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1408      int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1409                                 extension);
1410      uint64_t displacement =  OPT_SCALE (extended, 64, scaling);
1411      uint64_t address = base + displacement.  */
1412
1413   /* TODO : implement prefetch of address  */
1414 }
1415
1416 /* 64 bit pc-relative prefetch.  */
1417 static void
1418 prfm_pcrel (sim_cpu *cpu, int32_t offset)
1419 {
1420   /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1421                           00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1422                           00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1423                           10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1424                           10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1425                           10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1426                           ow ==> UNALLOC
1427      PrfOp prfop = prfop (aarch64_get_instr (cpu), 4, 0);
1428      uint64_t address = aarch64_get_PC (cpu) + offset.  */
1429
1430   /* TODO : implement this  */
1431 }
1432
1433 /* Load-store exclusive.  */
1434
1435 static void
1436 ldxr (sim_cpu *cpu)
1437 {
1438   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1439   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1440   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1441   int size = uimm (aarch64_get_instr (cpu), 31, 30);
1442   /* int ordered = uimm (aarch64_get_instr (cpu), 15, 15);  */
1443   /* int exclusive = ! uimm (aarch64_get_instr (cpu), 23, 23);  */
1444
1445   switch (size)
1446     {
1447     case 0:
1448       aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u8 (cpu, address));
1449       break;
1450     case 1:
1451       aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u16 (cpu, address));
1452       break;
1453     case 2:
1454       aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32 (cpu, address));
1455       break;
1456     case 3:
1457       aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64 (cpu, address));
1458       break;
1459     default:
1460       HALT_UNALLOC;
1461     }
1462 }
1463
1464 static void
1465 stxr (sim_cpu *cpu)
1466 {
1467   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1468   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1469   unsigned rs = uimm (aarch64_get_instr (cpu), 20, 16);
1470   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1471   int      size = uimm (aarch64_get_instr (cpu), 31, 30);
1472   uint64_t data = aarch64_get_reg_u64 (cpu, rt, NO_SP);
1473
1474   switch (size)
1475     {
1476     case 0: aarch64_set_mem_u8 (cpu, address, data); break;
1477     case 1: aarch64_set_mem_u16 (cpu, address, data); break;
1478     case 2: aarch64_set_mem_u32 (cpu, address, data); break;
1479     case 3: aarch64_set_mem_u64 (cpu, address, data); break;
1480     default: HALT_UNALLOC;
1481     }
1482
1483   aarch64_set_reg_u64 (cpu, rs, NO_SP, 0); /* Always exclusive...  */
1484 }
1485
1486 static void
1487 dexLoadLiteral (sim_cpu *cpu)
1488 {
1489   /* instr[29,27] == 011
1490      instr[25,24] == 00
1491      instr[31,30:26] = opc: 000 ==> LDRW,  001 ==> FLDRS
1492                             010 ==> LDRX,  011 ==> FLDRD
1493                             100 ==> LDRSW, 101 ==> FLDRQ
1494                             110 ==> PRFM, 111 ==> UNALLOC
1495      instr[26] ==> V : 0 ==> GReg, 1 ==> FReg
1496      instr[23, 5] == simm19  */
1497
1498   /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);  */
1499   uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 1)
1500                         | uimm (aarch64_get_instr (cpu), 26, 26));
1501   int32_t imm = simm32 (aarch64_get_instr (cpu), 23, 5);
1502
1503   switch (dispatch)
1504     {
1505     case 0: ldr32_pcrel (cpu, imm); break;
1506     case 1: fldrs_pcrel (cpu, imm); break;
1507     case 2: ldr_pcrel   (cpu, imm); break;
1508     case 3: fldrd_pcrel (cpu, imm); break;
1509     case 4: ldrsw_pcrel (cpu, imm); break;
1510     case 5: fldrq_pcrel (cpu, imm); break;
1511     case 6: prfm_pcrel  (cpu, imm); break;
1512     case 7:
1513     default:
1514       HALT_UNALLOC;
1515     }
1516 }
1517
1518 /* Immediate arithmetic
1519    The aimm argument is a 12 bit unsigned value or a 12 bit unsigned
1520    value left shifted by 12 bits (done at decode).
1521
1522    N.B. the register args (dest, source) can normally be Xn or SP.
1523    the exception occurs for flag setting instructions which may
1524    only use Xn for the output (dest).  */
1525
1526 /* 32 bit add immediate.  */
1527 static void
1528 add32 (sim_cpu *cpu, uint32_t aimm)
1529 {
1530   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1531   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1532
1533   aarch64_set_reg_u64 (cpu, rd, SP_OK,
1534                        aarch64_get_reg_u32 (cpu, rn, SP_OK) + aimm);
1535 }
1536
1537 /* 64 bit add immediate.  */
1538 static void
1539 add64 (sim_cpu *cpu, uint32_t aimm)
1540 {
1541   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1542   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1543
1544   aarch64_set_reg_u64 (cpu, rd, SP_OK,
1545                        aarch64_get_reg_u64 (cpu, rn, SP_OK) + aimm);
1546 }
1547
1548 static void
1549 set_flags_for_add32 (sim_cpu *cpu, int32_t value1, int32_t value2)
1550 {
1551   int32_t   result = value1 + value2;
1552   int64_t   sresult = (int64_t) value1 + (int64_t) value2;
1553   uint64_t  uresult = (uint64_t)(uint32_t) value1
1554     + (uint64_t)(uint32_t) value2;
1555   uint32_t  flags = 0;
1556
1557   if (result == 0)
1558     flags |= Z;
1559
1560   if (result & (1 << 31))
1561     flags |= N;
1562
1563   if (uresult != result)
1564     flags |= C;
1565
1566   if (sresult != result)
1567     flags |= V;
1568
1569   aarch64_set_CPSR (cpu, flags);
1570 }
1571
1572 static void
1573 set_flags_for_add64 (sim_cpu *cpu, uint64_t value1, uint64_t value2)
1574 {
1575   int64_t   sval1 = value1;
1576   int64_t   sval2 = value2;
1577   uint64_t  result = value1 + value2;
1578   int64_t   sresult = sval1 + sval2;
1579   uint32_t  flags = 0;
1580
1581   if (result == 0)
1582     flags |= Z;
1583
1584   if (result & (1ULL << 63))
1585     flags |= N;
1586
1587   if (sval1 < 0)
1588     {
1589       if (sval2 < 0)
1590         {
1591           /* Negative plus a negative.  Overflow happens if
1592              the result is greater than either of the operands.  */
1593           if (sresult > sval1 || sresult > sval2)
1594             flags |= V;
1595         }
1596       /* else Negative plus a positive.  Overflow cannot happen.  */
1597     }
1598   else /* value1 is +ve.  */
1599     {
1600       if (sval2 < 0)
1601         {
1602           /* Overflow can only occur if we computed "0 - MININT".  */
1603           if (sval1 == 0 && sval2 == (1LL << 63))
1604             flags |= V;
1605         }
1606       else
1607         {
1608           /* Postive plus positive - overflow has happened if the
1609              result is smaller than either of the operands.  */
1610           if (result < value1 || result < value2)
1611             flags |= V | C;
1612         }
1613     }
1614
1615   aarch64_set_CPSR (cpu, flags);
1616 }
1617
1618 #define NEG(a) (((a) & signbit) == signbit)
1619 #define POS(a) (((a) & signbit) == 0)
1620
1621 static void
1622 set_flags_for_sub32 (sim_cpu *cpu, uint32_t value1, uint32_t value2)
1623 {
1624   uint32_t result = value1 - value2;
1625   uint32_t flags = 0;
1626   uint32_t signbit = 1U << 31;
1627
1628   if (result == 0)
1629     flags |= Z;
1630
1631   if (NEG (result))
1632     flags |= N;
1633
1634   if (   (NEG (value1) && POS (value2))
1635       || (NEG (value1) && POS (result))
1636       || (POS (value2) && POS (result)))
1637     flags |= C;
1638
1639   if (   (NEG (value1) && POS (value2) && POS (result))
1640       || (POS (value1) && NEG (value2) && NEG (result)))
1641     flags |= V;
1642
1643   aarch64_set_CPSR (cpu, flags);
1644 }
1645
1646 static void
1647 set_flags_for_sub64 (sim_cpu *cpu, uint64_t value1, uint64_t value2)
1648 {
1649   uint64_t result = value1 - value2;
1650   uint32_t flags = 0;
1651   uint64_t signbit = 1ULL << 63;
1652
1653   if (result == 0)
1654     flags |= Z;
1655
1656   if (NEG (result))
1657     flags |= N;
1658
1659   if (   (NEG (value1) && POS (value2))
1660       || (NEG (value1) && POS (result))
1661       || (POS (value2) && POS (result)))
1662     flags |= C;
1663
1664   if (   (NEG (value1) && POS (value2) && POS (result))
1665       || (POS (value1) && NEG (value2) && NEG (result)))
1666     flags |= V;
1667
1668   aarch64_set_CPSR (cpu, flags);
1669 }
1670
1671 static void
1672 set_flags_for_binop32 (sim_cpu *cpu, uint32_t result)
1673 {
1674   uint32_t flags = 0;
1675
1676   if (result == 0)
1677     flags |= Z;
1678   else
1679     flags &= ~ Z;
1680
1681   if (result & (1 << 31))
1682     flags |= N;
1683   else
1684     flags &= ~ N;
1685
1686   aarch64_set_CPSR (cpu, flags);
1687 }
1688
1689 static void
1690 set_flags_for_binop64 (sim_cpu *cpu, uint64_t result)
1691 {
1692   uint32_t flags = 0;
1693
1694   if (result == 0)
1695     flags |= Z;
1696   else
1697     flags &= ~ Z;
1698
1699   if (result & (1ULL << 63))
1700     flags |= N;
1701   else
1702     flags &= ~ N;
1703
1704   aarch64_set_CPSR (cpu, flags);
1705 }
1706
1707 /* 32 bit add immediate set flags.  */
1708 static void
1709 adds32 (sim_cpu *cpu, uint32_t aimm)
1710 {
1711   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1712   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1713   /* TODO : do we need to worry about signs here?  */
1714   int32_t value1 = aarch64_get_reg_s32 (cpu, rn, SP_OK);
1715
1716   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + aimm);
1717   set_flags_for_add32 (cpu, value1, aimm);
1718 }
1719
1720 /* 64 bit add immediate set flags.  */
1721 static void
1722 adds64 (sim_cpu *cpu, uint32_t aimm)
1723 {
1724   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1725   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1726   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1727   uint64_t value2 = aimm;
1728
1729   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
1730   set_flags_for_add64 (cpu, value1, value2);
1731 }
1732
1733 /* 32 bit sub immediate.  */
1734 static void
1735 sub32 (sim_cpu *cpu, uint32_t aimm)
1736 {
1737   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1738   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1739
1740   aarch64_set_reg_u64 (cpu, rd, SP_OK,
1741                        aarch64_get_reg_u32 (cpu, rn, SP_OK) - aimm);
1742 }
1743
1744 /* 64 bit sub immediate.  */
1745 static void
1746 sub64 (sim_cpu *cpu, uint32_t aimm)
1747 {
1748   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1749   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1750
1751   aarch64_set_reg_u64 (cpu, rd, SP_OK,
1752                        aarch64_get_reg_u64 (cpu, rn, SP_OK) - aimm);
1753 }
1754
1755 /* 32 bit sub immediate set flags.  */
1756 static void
1757 subs32 (sim_cpu *cpu, uint32_t aimm)
1758 {
1759   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1760   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1761   uint32_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1762   uint32_t value2 = aimm;
1763
1764   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1765   set_flags_for_sub32 (cpu, value1, value2);
1766 }
1767
1768 /* 64 bit sub immediate set flags.  */
1769 static void
1770 subs64 (sim_cpu *cpu, uint32_t aimm)
1771 {
1772   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1773   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1774   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1775   uint32_t value2 = aimm;
1776
1777   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1778   set_flags_for_sub64 (cpu, value1, value2);
1779 }
1780
1781 /* Data Processing Register.  */
1782
1783 /* First two helpers to perform the shift operations.  */
1784
1785 static inline uint32_t
1786 shifted32 (uint32_t value, Shift shift, uint32_t count)
1787 {
1788   switch (shift)
1789     {
1790     default:
1791     case LSL:
1792       return (value << count);
1793     case LSR:
1794       return (value >> count);
1795     case ASR:
1796       {
1797         int32_t svalue = value;
1798         return (svalue >> count);
1799       }
1800     case ROR:
1801       {
1802         uint32_t top = value >> count;
1803         uint32_t bottom = value << (32 - count);
1804         return (bottom | top);
1805       }
1806     }
1807 }
1808
1809 static inline uint64_t
1810 shifted64 (uint64_t value, Shift shift, uint32_t count)
1811 {
1812   switch (shift)
1813     {
1814     default:
1815     case LSL:
1816       return (value << count);
1817     case LSR:
1818       return (value >> count);
1819     case ASR:
1820       {
1821         int64_t svalue = value;
1822         return (svalue >> count);
1823       }
1824     case ROR:
1825       {
1826         uint64_t top = value >> count;
1827         uint64_t bottom = value << (64 - count);
1828         return (bottom | top);
1829       }
1830     }
1831 }
1832
1833 /* Arithmetic shifted register.
1834    These allow an optional LSL, ASR or LSR to the second source
1835    register with a count up to the register bit count.
1836
1837    N.B register args may not be SP.  */
1838
1839 /* 32 bit ADD shifted register.  */
1840 static void
1841 add32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1842 {
1843   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1844   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1845   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1846
1847   aarch64_set_reg_u64 (cpu, rd, NO_SP,
1848                        aarch64_get_reg_u32 (cpu, rn, NO_SP)
1849                        + shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1850                                     shift, count));
1851 }
1852
1853 /* 64 bit ADD shifted register.  */
1854 static void
1855 add64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1856 {
1857   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1858   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1859   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1860
1861   aarch64_set_reg_u64 (cpu, rd, NO_SP,
1862                        aarch64_get_reg_u64 (cpu, rn, NO_SP)
1863                        + shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1864                                     shift, count));
1865 }
1866
1867 /* 32 bit ADD shifted register setting flags.  */
1868 static void
1869 adds32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1870 {
1871   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1872   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1873   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1874
1875   uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
1876   uint32_t value2 = shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1877                                shift, count);
1878
1879   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
1880   set_flags_for_add32 (cpu, value1, value2);
1881 }
1882
1883 /* 64 bit ADD shifted register setting flags.  */
1884 static void
1885 adds64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1886 {
1887   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1888   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1889   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1890
1891   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
1892   uint64_t value2 = shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1893                                shift, count);
1894
1895   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
1896   set_flags_for_add64 (cpu, value1, value2);
1897 }
1898
1899 /* 32 bit SUB shifted register.  */
1900 static void
1901 sub32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1902 {
1903   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1904   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1905   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1906
1907   aarch64_set_reg_u64 (cpu, rd, NO_SP,
1908                        aarch64_get_reg_u32 (cpu, rn, NO_SP)
1909                        - shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1910                                     shift, count));
1911 }
1912
1913 /* 64 bit SUB shifted register.  */
1914 static void
1915 sub64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1916 {
1917   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1918   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1919   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1920
1921   aarch64_set_reg_u64 (cpu, rd, NO_SP,
1922                        aarch64_get_reg_u64 (cpu, rn, NO_SP)
1923                        - shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1924                                     shift, count));
1925 }
1926
1927 /* 32 bit SUB shifted register setting flags.  */
1928 static void
1929 subs32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1930 {
1931   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1932   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1933   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1934
1935   uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
1936   uint32_t value2 = shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1937                               shift, count);
1938
1939   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1940   set_flags_for_sub32 (cpu, value1, value2);
1941 }
1942
1943 /* 64 bit SUB shifted register setting flags.  */
1944 static void
1945 subs64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1946 {
1947   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1948   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1949   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1950
1951   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
1952   uint64_t value2 = shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1953                                shift, count);
1954
1955   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1956   set_flags_for_sub64 (cpu, value1, value2);
1957 }
1958
1959 /* First a couple more helpers to fetch the
1960    relevant source register element either
1961    sign or zero extended as required by the
1962    extension value.  */
1963
1964 static uint32_t
1965 extreg32 (sim_cpu *cpu, unsigned int lo, Extension extension)
1966 {
1967   switch (extension)
1968     {
1969     case UXTB: return aarch64_get_reg_u8  (cpu, lo, NO_SP);
1970     case UXTH: return aarch64_get_reg_u16 (cpu, lo, NO_SP);
1971     case UXTW: /* Fall through.  */
1972     case UXTX: return aarch64_get_reg_u32 (cpu, lo, NO_SP);
1973     case SXTB: return aarch64_get_reg_s8  (cpu, lo, NO_SP);
1974     case SXTH: return aarch64_get_reg_s16 (cpu, lo, NO_SP);
1975     case SXTW: /* Fall through.  */
1976     case SXTX: /* Fall through.  */
1977     default:   return aarch64_get_reg_s32 (cpu, lo, NO_SP);
1978   }
1979 }
1980
1981 static uint64_t
1982 extreg64 (sim_cpu *cpu, unsigned int lo, Extension extension)
1983 {
1984   switch (extension)
1985     {
1986     case UXTB: return aarch64_get_reg_u8  (cpu, lo, NO_SP);
1987     case UXTH: return aarch64_get_reg_u16 (cpu, lo, NO_SP);
1988     case UXTW: return aarch64_get_reg_u32 (cpu, lo, NO_SP);
1989     case UXTX: return aarch64_get_reg_u64 (cpu, lo, NO_SP);
1990     case SXTB: return aarch64_get_reg_s8  (cpu, lo, NO_SP);
1991     case SXTH: return aarch64_get_reg_s16 (cpu, lo, NO_SP);
1992     case SXTW: return aarch64_get_reg_s32 (cpu, lo, NO_SP);
1993     case SXTX:
1994     default:   return aarch64_get_reg_s64 (cpu, lo, NO_SP);
1995     }
1996 }
1997
1998 /* Arithmetic extending register
1999    These allow an optional sign extension of some portion of the
2000    second source register followed by an optional left shift of
2001    between 1 and 4 bits (i.e. a shift of 0-4 bits???)
2002
2003    N.B output (dest) and first input arg (source) may normally be Xn
2004    or SP. However, for flag setting operations dest can only be
2005    Xn. Second input registers are always Xn.  */
2006
2007 /* 32 bit ADD extending register.  */
2008 static void
2009 add32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2010 {
2011   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2012   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2013   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2014
2015   aarch64_set_reg_u64 (cpu, rd, SP_OK,
2016                        aarch64_get_reg_u32 (cpu, rn, SP_OK)
2017                        + (extreg32 (cpu, rm, extension) << shift));
2018 }
2019
2020 /* 64 bit ADD extending register.
2021    N.B. This subsumes the case with 64 bit source2 and UXTX #n or LSL #0.  */
2022 static void
2023 add64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2024 {
2025   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2026   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2027   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2028
2029   aarch64_set_reg_u64 (cpu, rd, SP_OK,
2030                        aarch64_get_reg_u64 (cpu, rn, SP_OK)
2031                        + (extreg64 (cpu, rm, extension) << shift));
2032 }
2033
2034 /* 32 bit ADD extending register setting flags.  */
2035 static void
2036 adds32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2037 {
2038   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2039   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2040   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2041
2042   uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, SP_OK);
2043   uint32_t value2 = extreg32 (cpu, rm, extension) << shift;
2044
2045   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
2046   set_flags_for_add32 (cpu, value1, value2);
2047 }
2048
2049 /* 64 bit ADD extending register setting flags  */
2050 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0  */
2051 static void
2052 adds64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2053 {
2054   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2055   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2056   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2057
2058   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
2059   uint64_t value2 = extreg64 (cpu, rm, extension) << shift;
2060
2061   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
2062   set_flags_for_add64 (cpu, value1, value2);
2063 }
2064
2065 /* 32 bit SUB extending register.  */
2066 static void
2067 sub32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2068 {
2069   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2070   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2071   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2072
2073   aarch64_set_reg_u64 (cpu, rd, SP_OK,
2074                        aarch64_get_reg_u32 (cpu, rn, SP_OK)
2075                        - (extreg32 (cpu, rm, extension) << shift));
2076 }
2077
2078 /* 64 bit SUB extending register.  */
2079 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0.  */
2080 static void
2081 sub64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2082 {
2083   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2084   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2085   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2086
2087   aarch64_set_reg_u64 (cpu, rd, SP_OK,
2088                        aarch64_get_reg_u64 (cpu, rn, SP_OK)
2089                        - (extreg64 (cpu, rm, extension) << shift));
2090 }
2091
2092 /* 32 bit SUB extending register setting flags.  */
2093 static void
2094 subs32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2095 {
2096   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2097   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2098   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2099
2100   uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, SP_OK);
2101   uint32_t value2 = extreg32 (cpu, rm, extension) << shift;
2102
2103   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
2104   set_flags_for_sub32 (cpu, value1, value2);
2105 }
2106
2107 /* 64 bit SUB extending register setting flags  */
2108 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0  */
2109 static void
2110 subs64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2111 {
2112   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2113   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2114   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2115
2116   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
2117   uint64_t value2 = extreg64 (cpu, rm, extension) << shift;
2118
2119   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
2120   set_flags_for_sub64 (cpu, value1, value2);
2121 }
2122
2123 static void
2124 dexAddSubtractImmediate (sim_cpu *cpu)
2125 {
2126   /* instr[31]    = size : 0 ==> 32 bit, 1 ==> 64 bit
2127      instr[30]    = op : 0 ==> ADD, 1 ==> SUB
2128      instr[29]    = set : 0 ==> no flags, 1 ==> set flags
2129      instr[28,24] = 10001
2130      instr[23,22] = shift : 00 == LSL#0, 01 = LSL#12 1x = UNALLOC
2131      instr[21,10] = uimm12
2132      instr[9,5]   = Rn
2133      instr[4,0]   = Rd  */
2134
2135   /* N.B. the shift is applied at decode before calling the add/sub routine.  */
2136   uint32_t shift = uimm (aarch64_get_instr (cpu), 23, 22);
2137   uint32_t imm = uimm (aarch64_get_instr (cpu), 21, 10);
2138   uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2139
2140   NYI_assert (28, 24, 0x11);
2141
2142   if (shift > 1)
2143     HALT_UNALLOC;
2144
2145   if (shift)
2146     imm <<= 12;
2147
2148   switch (dispatch)
2149     {
2150     case 0: add32 (cpu, imm); break;
2151     case 1: adds32 (cpu, imm); break;
2152     case 2: sub32 (cpu, imm); break;
2153     case 3: subs32 (cpu, imm); break;
2154     case 4: add64 (cpu, imm); break;
2155     case 5: adds64 (cpu, imm); break;
2156     case 6: sub64 (cpu, imm); break;
2157     case 7: subs64 (cpu, imm); break;
2158     default:
2159       HALT_UNALLOC;
2160     }
2161 }
2162
2163 static void
2164 dexAddSubtractShiftedRegister (sim_cpu *cpu)
2165 {
2166   /* instr[31]    = size : 0 ==> 32 bit, 1 ==> 64 bit
2167      instr[30,29] = op : 00 ==> ADD, 01 ==> ADDS, 10 ==> SUB, 11 ==> SUBS
2168      instr[28,24] = 01011
2169      instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> UNALLOC
2170      instr[21]    = 0
2171      instr[20,16] = Rm
2172      instr[15,10] = count : must be 0xxxxx for 32 bit
2173      instr[9,5]   = Rn
2174      instr[4,0]   = Rd  */
2175
2176   uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
2177   /* 32 bit operations must have count[5] = 0
2178      or else we have an UNALLOC.  */
2179   uint32_t count = uimm (aarch64_get_instr (cpu), 15, 10);
2180   /* Shift encoded as ROR is unallocated.  */
2181   Shift shiftType = shift (aarch64_get_instr (cpu), 22);
2182   /* Dispatch on size:op i.e aarch64_get_instr (cpu)[31,29].  */
2183   uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2184
2185   NYI_assert (28, 24, 0x0B);
2186   NYI_assert (21, 21, 0);
2187
2188   if (shiftType == ROR)
2189     HALT_UNALLOC;
2190
2191   if (!size && uimm (count, 5, 5))
2192     HALT_UNALLOC;
2193
2194   switch (dispatch)
2195     {
2196     case 0: add32_shift  (cpu, shiftType, count); break;
2197     case 1: adds32_shift (cpu, shiftType, count); break;
2198     case 2: sub32_shift  (cpu, shiftType, count); break;
2199     case 3: subs32_shift (cpu, shiftType, count); break;
2200     case 4: add64_shift  (cpu, shiftType, count); break;
2201     case 5: adds64_shift (cpu, shiftType, count); break;
2202     case 6: sub64_shift  (cpu, shiftType, count); break;
2203     case 7: subs64_shift (cpu, shiftType, count); break;
2204     default:
2205       HALT_UNALLOC;
2206     }
2207 }
2208
2209 static void
2210 dexAddSubtractExtendedRegister (sim_cpu *cpu)
2211 {
2212   /* instr[31]    = size : 0 ==> 32 bit, 1 ==> 64 bit
2213      instr[30]    = op : 0 ==> ADD, 1 ==> SUB
2214      instr[29]    = set? : 0 ==> no flags, 1 ==> set flags
2215      instr[28,24] = 01011
2216      instr[23,22] = opt : 0 ==> ok, 1,2,3 ==> UNALLOC
2217      instr[21]    = 1
2218      instr[20,16] = Rm
2219      instr[15,13] = option : 000 ==> UXTB, 001 ==> UXTH,
2220                              000 ==> LSL|UXTW, 001 ==> UXTZ,
2221                              000 ==> SXTB, 001 ==> SXTH,
2222                              000 ==> SXTW, 001 ==> SXTX,
2223      instr[12,10] = shift : 0,1,2,3,4 ==> ok, 5,6,7 ==> UNALLOC
2224      instr[9,5]   = Rn
2225      instr[4,0]   = Rd  */
2226
2227   Extension extensionType = extension (aarch64_get_instr (cpu), 13);
2228   uint32_t shift = uimm (aarch64_get_instr (cpu), 12, 10);
2229   /* dispatch on size:op:set? i.e aarch64_get_instr (cpu)[31,29]  */
2230   uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2231
2232   NYI_assert (28, 24, 0x0B);
2233   NYI_assert (21, 21, 1);
2234
2235   /* Shift may not exceed 4.  */
2236   if (shift > 4)
2237     HALT_UNALLOC;
2238
2239   switch (dispatch)
2240     {
2241     case 0: add32_ext  (cpu, extensionType, shift); break;
2242     case 1: adds32_ext (cpu, extensionType, shift); break;
2243     case 2: sub32_ext  (cpu, extensionType, shift); break;
2244     case 3: subs32_ext (cpu, extensionType, shift); break;
2245     case 4: add64_ext  (cpu, extensionType, shift); break;
2246     case 5: adds64_ext (cpu, extensionType, shift); break;
2247     case 6: sub64_ext  (cpu, extensionType, shift); break;
2248     case 7: subs64_ext (cpu, extensionType, shift); break;
2249     default: HALT_UNALLOC;
2250     }
2251 }
2252
2253 /* Conditional data processing
2254    Condition register is implicit 3rd source.  */
2255
2256 /* 32 bit add with carry.  */
2257 /* N.B register args may not be SP.  */
2258
2259 static void
2260 adc32 (sim_cpu *cpu)
2261 {
2262   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2263   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2264   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2265
2266   aarch64_set_reg_u64 (cpu, rd, NO_SP,
2267                        aarch64_get_reg_u32 (cpu, rn, NO_SP)
2268                        + aarch64_get_reg_u32 (cpu, rm, NO_SP)
2269                        + IS_SET (C));
2270 }
2271
2272 /* 64 bit add with carry  */
2273 static void
2274 adc64 (sim_cpu *cpu)
2275 {
2276   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2277   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2278   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2279
2280   aarch64_set_reg_u64 (cpu, rd, NO_SP,
2281                        aarch64_get_reg_u64 (cpu, rn, NO_SP)
2282                        + aarch64_get_reg_u64 (cpu, rm, NO_SP)
2283                        + IS_SET (C));
2284 }
2285
2286 /* 32 bit add with carry setting flags.  */
2287 static void
2288 adcs32 (sim_cpu *cpu)
2289 {
2290   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2291   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2292   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2293
2294   uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
2295   uint32_t value2 = aarch64_get_reg_u32 (cpu, rm, NO_SP);
2296   uint32_t carry = IS_SET (C);
2297
2298   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2 + carry);
2299   set_flags_for_add32 (cpu, value1, value2 + carry);
2300 }
2301
2302 /* 64 bit add with carry setting flags.  */
2303 static void
2304 adcs64 (sim_cpu *cpu)
2305 {
2306   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2307   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2308   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2309
2310   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
2311   uint64_t value2 = aarch64_get_reg_u64 (cpu, rm, NO_SP);
2312   uint64_t carry = IS_SET (C);
2313
2314   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2 + carry);
2315   set_flags_for_add64 (cpu, value1, value2 + carry);
2316 }
2317
2318 /* 32 bit sub with carry.  */
2319 static void
2320 sbc32 (sim_cpu *cpu)
2321 {
2322   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2323   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5); /* ngc iff rn == 31.  */
2324   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2325
2326   aarch64_set_reg_u64 (cpu, rd, NO_SP,
2327                        aarch64_get_reg_u32 (cpu, rn, NO_SP)
2328                        - aarch64_get_reg_u32 (cpu, rm, NO_SP)
2329                        - 1 + IS_SET (C));
2330 }
2331
2332 /* 64 bit sub with carry  */
2333 static void
2334 sbc64 (sim_cpu *cpu)
2335 {
2336   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2337   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2338   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2339
2340   aarch64_set_reg_u64 (cpu, rd, NO_SP,
2341                        aarch64_get_reg_u64 (cpu, rn, NO_SP)
2342                        - aarch64_get_reg_u64 (cpu, rm, NO_SP)
2343                        - 1 + IS_SET (C));
2344 }
2345
2346 /* 32 bit sub with carry setting flags  */
2347 static void
2348 sbcs32 (sim_cpu *cpu)
2349 {
2350   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2351   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2352   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2353
2354   uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
2355   uint32_t value2 = aarch64_get_reg_u32 (cpu, rm, NO_SP);
2356   uint32_t carry  = IS_SET (C);
2357   uint32_t result = value1 - value2 + 1 - carry;
2358
2359   aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
2360   set_flags_for_sub32 (cpu, value1, value2 + 1 - carry);
2361 }
2362
2363 /* 64 bit sub with carry setting flags  */
2364 static void
2365 sbcs64 (sim_cpu *cpu)
2366 {
2367   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2368   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2369   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2370
2371   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
2372   uint64_t value2 = aarch64_get_reg_u64 (cpu, rm, NO_SP);
2373   uint64_t carry  = IS_SET (C);
2374   uint64_t result = value1 - value2 + 1 - carry;
2375
2376   aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
2377   set_flags_for_sub64 (cpu, value1, value2 + 1 - carry);
2378 }
2379
2380 static void
2381 dexAddSubtractWithCarry (sim_cpu *cpu)
2382 {
2383   /* instr[31]    = size : 0 ==> 32 bit, 1 ==> 64 bit
2384      instr[30]    = op : 0 ==> ADC, 1 ==> SBC
2385      instr[29]    = set? : 0 ==> no flags, 1 ==> set flags
2386      instr[28,21] = 1 1010 000
2387      instr[20,16] = Rm
2388      instr[15,10] = op2 : 00000 ==> ok, ow ==> UNALLOC
2389      instr[9,5]   = Rn
2390      instr[4,0]   = Rd  */
2391
2392   uint32_t op2 = uimm (aarch64_get_instr (cpu), 15, 10);
2393   /* Dispatch on size:op:set? i.e aarch64_get_instr (cpu)[31,29]  */
2394   uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2395
2396   NYI_assert (28, 21, 0xD0);
2397
2398   if (op2 != 0)
2399     HALT_UNALLOC;
2400
2401   switch (dispatch)
2402     {
2403     case 0: adc32 (cpu); break;
2404     case 1: adcs32 (cpu); break;
2405     case 2: sbc32 (cpu); break;
2406     case 3: sbcs32 (cpu); break;
2407     case 4: adc64 (cpu); break;
2408     case 5: adcs64 (cpu); break;
2409     case 6: sbc64 (cpu); break;
2410     case 7: sbcs64 (cpu); break;
2411     default: HALT_UNALLOC;
2412     }
2413 }
2414
2415 static uint32_t
2416 testConditionCode (sim_cpu *cpu, CondCode cc)
2417 {
2418   /* This should be reduceable to branchless logic
2419      by some careful testing of bits in CC followed
2420      by the requisite masking and combining of bits
2421      from the flag register.
2422
2423      For now we do it with a switch.  */
2424   int res;
2425
2426   switch (cc)
2427     {
2428     case EQ:  res = IS_SET (Z);    break;
2429     case NE:  res = IS_CLEAR (Z);  break;
2430     case CS:  res = IS_SET (C);    break;
2431     case CC:  res = IS_CLEAR (C);  break;
2432     case MI:  res = IS_SET (N);    break;
2433     case PL:  res = IS_CLEAR (N);  break;
2434     case VS:  res = IS_SET (V);    break;
2435     case VC:  res = IS_CLEAR (V);  break;
2436     case HI:  res = IS_SET (C) && IS_CLEAR (Z);  break;
2437     case LS:  res = IS_CLEAR (C) || IS_SET (Z);  break;
2438     case GE:  res = IS_SET (N) == IS_SET (V);    break;
2439     case LT:  res = IS_SET (N) != IS_SET (V);    break;
2440     case GT:  res = IS_CLEAR (Z) && (IS_SET (N) == IS_SET (V));  break;
2441     case LE:  res = IS_SET (Z) || (IS_SET (N) != IS_SET (V));    break;
2442     case AL:
2443     case NV:
2444     default:
2445       res = 1;
2446       break;
2447     }
2448   return res;
2449 }
2450
2451 static void
2452 CondCompare (sim_cpu *cpu) /* aka: ccmp and ccmn  */
2453 {
2454   /* instr[31]    = size : 0 ==> 32 bit, 1 ==> 64 bit
2455      instr[30]    = compare with positive (1) or negative value (0)
2456      instr[29,21] = 1 1101 0010
2457      instr[20,16] = Rm or const
2458      instr[15,12] = cond
2459      instr[11]    = compare reg (0) or const (1)
2460      instr[10]    = 0
2461      instr[9,5]   = Rn
2462      instr[4]     = 0
2463      instr[3,0]   = value for CPSR bits if the comparison does not take place.  */
2464   signed int negate;
2465   unsigned rm;
2466   unsigned rn;
2467
2468   NYI_assert (29, 21, 0x1d2);
2469   NYI_assert (10, 10, 0);
2470   NYI_assert (4, 4, 0);
2471
2472   if (! testConditionCode (cpu, uimm (aarch64_get_instr (cpu), 15, 12)))
2473     {
2474       aarch64_set_CPSR (cpu, uimm (aarch64_get_instr (cpu), 3, 0));
2475       return;
2476     }
2477
2478   negate = uimm (aarch64_get_instr (cpu), 30, 30) ? 1 : -1;
2479   rm = uimm (aarch64_get_instr (cpu), 20, 16);
2480   rn = uimm (aarch64_get_instr (cpu),  9,  5);
2481
2482   if (uimm (aarch64_get_instr (cpu), 31, 31))
2483     {
2484       if (uimm (aarch64_get_instr (cpu), 11, 11))
2485         set_flags_for_sub64 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK),
2486                              negate * (uint64_t) rm);
2487       else
2488         set_flags_for_sub64 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK),
2489                              negate * aarch64_get_reg_u64 (cpu, rm, SP_OK));
2490     }
2491   else
2492     {
2493       if (uimm (aarch64_get_instr (cpu), 11, 11))
2494         set_flags_for_sub32 (cpu, aarch64_get_reg_u32 (cpu, rn, SP_OK),
2495                              negate * rm);
2496       else
2497         set_flags_for_sub32 (cpu, aarch64_get_reg_u32 (cpu, rn, SP_OK),
2498                              negate * aarch64_get_reg_u32 (cpu, rm, SP_OK));
2499     }
2500 }
2501
2502 static void
2503 do_vec_MOV_whole_vector (sim_cpu *cpu)
2504 {
2505   /* MOV Vd.T, Vs.T  (alias for ORR Vd.T, Vn.T, Vm.T where Vn == Vm)
2506
2507      instr[31]    = 0
2508      instr[30]    = half(0)/full(1)
2509      instr[29,21] = 001110101
2510      instr[20,16] = Vs
2511      instr[15,10] = 000111
2512      instr[9,5]   = Vs
2513      instr[4,0]   = Vd  */
2514
2515   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
2516   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2517
2518   NYI_assert (29, 21, 0x075);
2519   NYI_assert (15, 10, 0x07);
2520
2521   if (uimm (aarch64_get_instr (cpu), 20, 16) != vs)
2522     HALT_NYI;
2523
2524   if (uimm (aarch64_get_instr (cpu), 30, 30))
2525     aarch64_set_vec_u64 (cpu, vd, 1, aarch64_get_vec_u64 (cpu, vs, 1));
2526
2527   aarch64_set_vec_u64 (cpu, vd, 0, aarch64_get_vec_u64 (cpu, vs, 0));
2528 }
2529
2530 static void
2531 do_vec_MOV_into_scalar (sim_cpu *cpu)
2532 {
2533   /* instr[31]    = 0
2534      instr[30]    = word(0)/long(1)
2535      instr[29,21] = 00 1110 000
2536      instr[20,18] = element size and index
2537      instr[17,10] = 00 0011 11
2538      instr[9,5]   = V source
2539      instr[4,0]   = R dest  */
2540
2541   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
2542   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2543
2544   NYI_assert (29, 21, 0x070);
2545   NYI_assert (17, 10, 0x0F);
2546
2547   switch (uimm (aarch64_get_instr (cpu), 20, 18))
2548     {
2549     case 0x2:
2550       aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u64 (cpu, vs, 0));
2551       break;
2552
2553     case 0x6:
2554       aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u64 (cpu, vs, 1));
2555       break;
2556
2557     case 0x1:
2558     case 0x3:
2559     case 0x5:
2560     case 0x7:
2561       aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u32
2562                            (cpu, vs, uimm (aarch64_get_instr (cpu), 20, 19)));
2563       break;
2564
2565     default:
2566       HALT_NYI;
2567     }
2568 }
2569
2570 static void
2571 do_vec_INS (sim_cpu *cpu)
2572 {
2573   /* instr[31,21] = 01001110000
2574      instr[20,16] = element size and index
2575      instr[15,10] = 000111
2576      instr[9,5]   = W source
2577      instr[4,0]   = V dest  */
2578
2579   int index;
2580   unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
2581   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2582
2583   NYI_assert (31, 21, 0x270);
2584   NYI_assert (15, 10, 0x07);
2585
2586   if (uimm (aarch64_get_instr (cpu), 16, 16))
2587     {
2588       index = uimm (aarch64_get_instr (cpu), 20, 17);
2589       aarch64_set_vec_u8 (cpu, vd, index,
2590                           aarch64_get_reg_u8 (cpu, rs, NO_SP));
2591     }
2592   else if (uimm (aarch64_get_instr (cpu), 17, 17))
2593     {
2594       index = uimm (aarch64_get_instr (cpu), 20, 18);
2595       aarch64_set_vec_u16 (cpu, vd, index,
2596                            aarch64_get_reg_u16 (cpu, rs, NO_SP));
2597     }
2598   else if (uimm (aarch64_get_instr (cpu), 18, 18))
2599     {
2600       index = uimm (aarch64_get_instr (cpu), 20, 19);
2601       aarch64_set_vec_u32 (cpu, vd, index,
2602                            aarch64_get_reg_u32 (cpu, rs, NO_SP));
2603     }
2604   else if (uimm (aarch64_get_instr (cpu), 19, 19))
2605     {
2606       index = uimm (aarch64_get_instr (cpu), 20, 20);
2607       aarch64_set_vec_u64 (cpu, vd, index,
2608                            aarch64_get_reg_u64 (cpu, rs, NO_SP));
2609     }
2610   else
2611     HALT_NYI;
2612 }
2613
2614 static void
2615 do_vec_DUP_vector_into_vector (sim_cpu *cpu)
2616 {
2617   /* instr[31]    = 0
2618      instr[30]    = half(0)/full(1)
2619      instr[29,21] = 00 1110 000
2620      instr[20,16] = element size and index
2621      instr[15,10] = 0000 01
2622      instr[9,5]   = V source
2623      instr[4,0]   = V dest.  */
2624
2625   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
2626   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
2627   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2628   int i, index;
2629
2630   NYI_assert (29, 21, 0x070);
2631   NYI_assert (15, 10, 0x01);
2632
2633   if (uimm (aarch64_get_instr (cpu), 16, 16))
2634     {
2635       index = uimm (aarch64_get_instr (cpu), 20, 17);
2636
2637       for (i = 0; i < (full ? 16 : 8); i++)
2638         aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vs, index));
2639     }
2640   else if (uimm (aarch64_get_instr (cpu), 17, 17))
2641     {
2642       index = uimm (aarch64_get_instr (cpu), 20, 18);
2643
2644       for (i = 0; i < (full ? 8 : 4); i++)
2645         aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vs, index));
2646     }
2647   else if (uimm (aarch64_get_instr (cpu), 18, 18))
2648     {
2649       index = uimm (aarch64_get_instr (cpu), 20, 19);
2650
2651       for (i = 0; i < (full ? 4 : 2); i++)
2652         aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vs, index));
2653     }
2654   else
2655     {
2656       if (uimm (aarch64_get_instr (cpu), 19, 19) == 0)
2657         HALT_UNALLOC;
2658
2659       if (! full)
2660         HALT_UNALLOC;
2661
2662       index = uimm (aarch64_get_instr (cpu), 20, 20);
2663
2664       for (i = 0; i < 2; i++)
2665         aarch64_set_vec_u64 (cpu, vd, i, aarch64_get_vec_u64 (cpu, vs, index));
2666     }
2667 }
2668
2669 static void
2670 do_vec_TBL (sim_cpu *cpu)
2671 {
2672   /* instr[31]    = 0
2673      instr[30]    = half(0)/full(1)
2674      instr[29,21] = 00 1110 000
2675      instr[20,16] = Vm
2676      instr[15]    = 0
2677      instr[14,13] = vec length
2678      instr[12,10] = 000
2679      instr[9,5]   = V start
2680      instr[4,0]   = V dest  */
2681
2682   int full    = uimm (aarch64_get_instr (cpu), 30, 30);
2683   int len     = uimm (aarch64_get_instr (cpu), 14, 13) + 1;
2684   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2685   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2686   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2687   unsigned i;
2688
2689   NYI_assert (29, 21, 0x070);
2690   NYI_assert (12, 10, 0);
2691
2692   for (i = 0; i < (full ? 16 : 8); i++)
2693     {
2694       unsigned int selector = aarch64_get_vec_u8 (cpu, vm, i);
2695       uint8_t val;
2696
2697       if (selector < 16)
2698         val = aarch64_get_vec_u8 (cpu, vn, selector);
2699       else if (selector < 32)
2700         val = len < 2 ? 0 : aarch64_get_vec_u8 (cpu, vn + 1, selector - 16);
2701       else if (selector < 48)
2702         val = len < 3 ? 0 : aarch64_get_vec_u8 (cpu, vn + 2, selector - 32);
2703       else if (selector < 64)
2704         val = len < 4 ? 0 : aarch64_get_vec_u8 (cpu, vn + 3, selector - 48);
2705       else
2706         val = 0;
2707
2708       aarch64_set_vec_u8 (cpu, vd, i, val);
2709     }
2710 }
2711
2712 static void
2713 do_vec_TRN (sim_cpu *cpu)
2714 {
2715   /* instr[31]    = 0
2716      instr[30]    = half(0)/full(1)
2717      instr[29,24] = 00 1110
2718      instr[23,22] = size
2719      instr[21]    = 0
2720      instr[20,16] = Vm
2721      instr[15]    = 0
2722      instr[14]    = TRN1 (0) / TRN2 (1)
2723      instr[13,10] = 1010
2724      instr[9,5]   = V source
2725      instr[4,0]   = V dest.  */
2726
2727   int full    = uimm (aarch64_get_instr (cpu), 30, 30);
2728   int second  = uimm (aarch64_get_instr (cpu), 14, 14);
2729   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2730   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2731   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2732   unsigned i;
2733
2734   NYI_assert (29, 24, 0x0E);
2735   NYI_assert (13, 10, 0xA);
2736
2737   switch (uimm (aarch64_get_instr (cpu), 23, 22))
2738     {
2739     case 0:
2740       for (i = 0; i < (full ? 8 : 4); i++)
2741         {
2742           aarch64_set_vec_u8
2743             (cpu, vd, i * 2,
2744              aarch64_get_vec_u8 (cpu, second ? vm : vn, i * 2));
2745           aarch64_set_vec_u8
2746             (cpu, vd, 1 * 2 + 1,
2747              aarch64_get_vec_u8 (cpu, second ? vn : vm, i * 2 + 1));
2748         }
2749       break;
2750
2751     case 1:
2752       for (i = 0; i < (full ? 4 : 2); i++)
2753         {
2754           aarch64_set_vec_u16
2755             (cpu, vd, i * 2,
2756              aarch64_get_vec_u16 (cpu, second ? vm : vn, i * 2));
2757           aarch64_set_vec_u16
2758             (cpu, vd, 1 * 2 + 1,
2759              aarch64_get_vec_u16 (cpu, second ? vn : vm, i * 2 + 1));
2760         }
2761       break;
2762
2763     case 2:
2764       aarch64_set_vec_u32
2765         (cpu, vd, 0, aarch64_get_vec_u32 (cpu, second ? vm : vn, 0));
2766       aarch64_set_vec_u32
2767         (cpu, vd, 1, aarch64_get_vec_u32 (cpu, second ? vn : vm, 1));
2768       aarch64_set_vec_u32
2769         (cpu, vd, 2, aarch64_get_vec_u32 (cpu, second ? vm : vn, 2));
2770       aarch64_set_vec_u32
2771         (cpu, vd, 3, aarch64_get_vec_u32 (cpu, second ? vn : vm, 3));
2772       break;
2773
2774     case 3:
2775       if (! full)
2776         HALT_UNALLOC;
2777
2778       aarch64_set_vec_u64 (cpu, vd, 0,
2779                            aarch64_get_vec_u64 (cpu, second ? vm : vn, 0));
2780       aarch64_set_vec_u64 (cpu, vd, 1,
2781                            aarch64_get_vec_u64 (cpu, second ? vn : vm, 1));
2782       break;
2783
2784     default:
2785       HALT_UNALLOC;
2786     }
2787 }
2788
2789 static void
2790 do_vec_DUP_scalar_into_vector (sim_cpu *cpu)
2791 {
2792   /* instr[31]    = 0
2793      instr[30]    = 0=> zero top 64-bits, 1=> duplicate into top 64-bits
2794                     [must be 1 for 64-bit xfer]
2795      instr[29,20] = 00 1110 0000
2796      instr[19,16] = element size: 0001=> 8-bits, 0010=> 16-bits,
2797                                   0100=> 32-bits. 1000=>64-bits
2798      instr[15,10] = 0000 11
2799      instr[9,5]   = W source
2800      instr[4,0]   = V dest.  */
2801
2802   unsigned i;
2803   unsigned Vd = uimm (aarch64_get_instr (cpu), 4, 0);
2804   unsigned Rs = uimm (aarch64_get_instr (cpu), 9, 5);
2805   int both    = uimm (aarch64_get_instr (cpu), 30, 30);
2806
2807   NYI_assert (29, 20, 0x0E0);
2808   NYI_assert (15, 10, 0x03);
2809
2810   switch (uimm (aarch64_get_instr (cpu), 19, 16))
2811     {
2812     case 1:
2813       for (i = 0; i < (both ? 16 : 8); i++)
2814         aarch64_set_vec_u8 (cpu, Vd, i, aarch64_get_reg_u8 (cpu, Rs, NO_SP));
2815       break;
2816
2817     case 2:
2818       for (i = 0; i < (both ? 8 : 4); i++)
2819         aarch64_set_vec_u16 (cpu, Vd, i, aarch64_get_reg_u16 (cpu, Rs, NO_SP));
2820       break;
2821
2822     case 4:
2823       for (i = 0; i < (both ? 4 : 2); i++)
2824         aarch64_set_vec_u32 (cpu, Vd, i, aarch64_get_reg_u32 (cpu, Rs, NO_SP));
2825       break;
2826
2827     case 8:
2828       if (!both)
2829         HALT_NYI;
2830       aarch64_set_vec_u64 (cpu, Vd, 0, aarch64_get_reg_u64 (cpu, Rs, NO_SP));
2831       aarch64_set_vec_u64 (cpu, Vd, 1, aarch64_get_reg_u64 (cpu, Rs, NO_SP));
2832       break;
2833
2834     default:
2835       HALT_NYI;
2836     }
2837 }
2838
2839 static void
2840 do_vec_UZP (sim_cpu *cpu)
2841 {
2842   /* instr[31]    = 0
2843      instr[30]    = half(0)/full(1)
2844      instr[29,24] = 00 1110
2845      instr[23,22] = size: byte(00), half(01), word (10), long (11)
2846      instr[21]    = 0
2847      instr[20,16] = Vm
2848      instr[15]    = 0
2849      instr[14]    = lower (0) / upper (1)
2850      instr[13,10] = 0110
2851      instr[9,5]   = Vn
2852      instr[4,0]   = Vd.  */
2853
2854   int full = uimm (aarch64_get_instr (cpu), 30, 30);
2855   int upper = uimm (aarch64_get_instr (cpu), 14, 14);
2856
2857   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2858   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2859   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2860
2861   uint64_t val_m1 = aarch64_get_vec_u64 (cpu, vm, 0);
2862   uint64_t val_m2 = aarch64_get_vec_u64 (cpu, vm, 1);
2863   uint64_t val_n1 = aarch64_get_vec_u64 (cpu, vn, 0);
2864   uint64_t val_n2 = aarch64_get_vec_u64 (cpu, vn, 1);
2865
2866   uint64_t val1 = 0;
2867   uint64_t val2 = 0;
2868
2869   uint64_t input1 = upper ? val_n1 : val_m1;
2870   uint64_t input2 = upper ? val_n2 : val_m2;
2871   unsigned i;
2872
2873   NYI_assert (29, 24, 0x0E);
2874   NYI_assert (21, 21, 0);
2875   NYI_assert (15, 15, 0);
2876   NYI_assert (13, 10, 6);
2877
2878   switch (uimm (aarch64_get_instr (cpu), 23, 23))
2879     {
2880     case 0:
2881       for (i = 0; i < 8; i++)
2882         {
2883           val1 |= (input1 >> (i * 8)) & (0xFFULL << (i * 8));
2884           val2 |= (input2 >> (i * 8)) & (0xFFULL << (i * 8));
2885         }
2886       break;
2887
2888     case 1:
2889       for (i = 0; i < 4; i++)
2890         {
2891           val1 |= (input1 >> (i * 16)) & (0xFFFFULL << (i * 16));
2892           val2 |= (input2 >> (i * 16)) & (0xFFFFULL << (i * 16));
2893         }
2894       break;
2895
2896     case 2:
2897       val1 = ((input1 & 0xFFFFFFFF) | ((input1 >> 32) & 0xFFFFFFFF00000000ULL));
2898       val2 = ((input2 & 0xFFFFFFFF) | ((input2 >> 32) & 0xFFFFFFFF00000000ULL));
2899
2900     case 3:
2901       val1 = input1;
2902       val2 = input2;
2903            break;
2904     }
2905
2906   aarch64_set_vec_u64 (cpu, vd, 0, val1);
2907   if (full)
2908     aarch64_set_vec_u64 (cpu, vd, 1, val2);
2909 }
2910
2911 static void
2912 do_vec_ZIP (sim_cpu *cpu)
2913 {
2914   /* instr[31]    = 0
2915      instr[30]    = half(0)/full(1)
2916      instr[29,24] = 00 1110
2917      instr[23,22] = size: byte(00), hald(01), word (10), long (11)
2918      instr[21]    = 0
2919      instr[20,16] = Vm
2920      instr[15]    = 0
2921      instr[14]    = lower (0) / upper (1)
2922      instr[13,10] = 1110
2923      instr[9,5]   = Vn
2924      instr[4,0]   = Vd.  */
2925
2926   int full = uimm (aarch64_get_instr (cpu), 30, 30);
2927   int upper = uimm (aarch64_get_instr (cpu), 14, 14);
2928
2929   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2930   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2931   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2932
2933   uint64_t val_m1 = aarch64_get_vec_u64 (cpu, vm, 0);
2934   uint64_t val_m2 = aarch64_get_vec_u64 (cpu, vm, 1);
2935   uint64_t val_n1 = aarch64_get_vec_u64 (cpu, vn, 0);
2936   uint64_t val_n2 = aarch64_get_vec_u64 (cpu, vn, 1);
2937
2938   uint64_t val1 = 0;
2939   uint64_t val2 = 0;
2940
2941   uint64_t input1 = upper ? val_n1 : val_m1;
2942   uint64_t input2 = upper ? val_n2 : val_m2;
2943
2944   NYI_assert (29, 24, 0x0E);
2945   NYI_assert (21, 21, 0);
2946   NYI_assert (15, 15, 0);
2947   NYI_assert (13, 10, 0xE);
2948
2949   switch (uimm (aarch64_get_instr (cpu), 23, 23))
2950     {
2951     case 0:
2952       val1 =
2953           ((input1 <<  0) & (0xFF    <<  0))
2954         | ((input2 <<  8) & (0xFF    <<  8))
2955         | ((input1 <<  8) & (0xFF    << 16))
2956         | ((input2 << 16) & (0xFF    << 24))
2957         | ((input1 << 16) & (0xFFULL << 32))
2958         | ((input2 << 24) & (0xFFULL << 40))
2959         | ((input1 << 24) & (0xFFULL << 48))
2960         | ((input2 << 32) & (0xFFULL << 56));
2961
2962       val2 =
2963           ((input1 >> 32) & (0xFF    <<  0))
2964         | ((input2 >> 24) & (0xFF    <<  8))
2965         | ((input1 >> 24) & (0xFF    << 16))
2966         | ((input2 >> 16) & (0xFF    << 24))
2967         | ((input1 >> 16) & (0xFFULL << 32))
2968         | ((input2 >>  8) & (0xFFULL << 40))
2969         | ((input1 >>  8) & (0xFFULL << 48))
2970         | ((input2 >>  0) & (0xFFULL << 56));
2971       break;
2972
2973     case 1:
2974       val1 =
2975           ((input1 <<  0) & (0xFFFF    <<  0))
2976         | ((input2 << 16) & (0xFFFF    << 16))
2977         | ((input1 << 16) & (0xFFFFULL << 32))
2978         | ((input2 << 32) & (0xFFFFULL << 48));
2979
2980       val2 =
2981           ((input1 >> 32) & (0xFFFF    <<  0))
2982         | ((input2 >> 16) & (0xFFFF    << 16))
2983         | ((input1 >> 16) & (0xFFFFULL << 32))
2984         | ((input2 >>  0) & (0xFFFFULL << 48));
2985       break;
2986
2987     case 2:
2988       val1 = (input1 & 0xFFFFFFFFULL) | (input2 << 32);
2989       val2 = (input2 & 0xFFFFFFFFULL) | (input1 << 32);
2990       break;
2991
2992     case 3:
2993       val1 = input1;
2994       val2 = input2;
2995       break;
2996     }
2997
2998   aarch64_set_vec_u64 (cpu, vd, 0, val1);
2999   if (full)
3000     aarch64_set_vec_u64 (cpu, vd, 1, val2);
3001 }
3002
3003 /* Floating point immediates are encoded in 8 bits.
3004    fpimm[7] = sign bit.
3005    fpimm[6:4] = signed exponent.
3006    fpimm[3:0] = fraction (assuming leading 1).
3007    i.e. F = s * 1.f * 2^(e - b).  */
3008
3009 static float
3010 fp_immediate_for_encoding_32 (uint32_t imm8)
3011 {
3012   float u;
3013   uint32_t s, e, f, i;
3014
3015   s = (imm8 >> 7) & 0x1;
3016   e = (imm8 >> 4) & 0x7;
3017   f = imm8 & 0xf;
3018
3019   /* The fp value is s * n/16 * 2r where n is 16+e.  */
3020   u = (16.0 + f) / 16.0;
3021
3022   /* N.B. exponent is signed.  */
3023   if (e < 4)
3024     {
3025       int epos = e;
3026
3027       for (i = 0; i <= epos; i++)
3028         u *= 2.0;
3029     }
3030   else
3031     {
3032       int eneg = 7 - e;
3033
3034       for (i = 0; i < eneg; i++)
3035         u /= 2.0;
3036     }
3037
3038   if (s)
3039     u = - u;
3040
3041   return u;
3042 }
3043
3044 static double
3045 fp_immediate_for_encoding_64 (uint32_t imm8)
3046 {
3047   double u;
3048   uint32_t s, e, f, i;
3049
3050   s = (imm8 >> 7) & 0x1;
3051   e = (imm8 >> 4) & 0x7;
3052   f = imm8 & 0xf;
3053
3054   /* The fp value is s * n/16 * 2r where n is 16+e.  */
3055   u = (16.0 + f) / 16.0;
3056
3057   /* N.B. exponent is signed.  */
3058   if (e < 4)
3059     {
3060       int epos = e;
3061
3062       for (i = 0; i <= epos; i++)
3063         u *= 2.0;
3064     }
3065   else
3066     {
3067       int eneg = 7 - e;
3068
3069       for (i = 0; i < eneg; i++)
3070         u /= 2.0;
3071     }
3072
3073   if (s)
3074     u = - u;
3075
3076   return u;
3077 }
3078
3079 static void
3080 do_vec_MOV_immediate (sim_cpu *cpu)
3081 {
3082   /* instr[31]    = 0
3083      instr[30]    = full/half selector
3084      instr[29,19] = 00111100000
3085      instr[18,16] = high 3 bits of uimm8
3086      instr[15,12] = size & shift:
3087                                   0000 => 32-bit
3088                                   0010 => 32-bit + LSL#8
3089                                   0100 => 32-bit + LSL#16
3090                                   0110 => 32-bit + LSL#24
3091                                   1010 => 16-bit + LSL#8
3092                                   1000 => 16-bit
3093                                   1101 => 32-bit + MSL#16
3094                                   1100 => 32-bit + MSL#8
3095                                   1110 => 8-bit
3096                                   1111 => double
3097      instr[11,10] = 01
3098      instr[9,5]   = low 5-bits of uimm8
3099      instr[4,0]   = Vd.  */
3100
3101   int full     = uimm (aarch64_get_instr (cpu), 30, 30);
3102   unsigned vd  = uimm (aarch64_get_instr (cpu), 4, 0);
3103   unsigned val = uimm (aarch64_get_instr (cpu), 18, 16) << 5
3104     | uimm (aarch64_get_instr (cpu), 9, 5);
3105   unsigned i;
3106
3107   NYI_assert (29, 19, 0x1E0);
3108   NYI_assert (11, 10, 1);
3109
3110   switch (uimm (aarch64_get_instr (cpu), 15, 12))
3111     {
3112     case 0x0: /* 32-bit, no shift.  */
3113     case 0x2: /* 32-bit, shift by 8.  */
3114     case 0x4: /* 32-bit, shift by 16.  */
3115     case 0x6: /* 32-bit, shift by 24.  */
3116       val <<= (8 * uimm (aarch64_get_instr (cpu), 14, 13));
3117       for (i = 0; i < (full ? 4 : 2); i++)
3118         aarch64_set_vec_u32 (cpu, vd, i, val);
3119       break;
3120
3121     case 0xa: /* 16-bit, shift by 8.  */
3122       val <<= 8;
3123       /* Fall through.  */
3124     case 0x8: /* 16-bit, no shift.  */
3125       for (i = 0; i < (full ? 8 : 4); i++)
3126         aarch64_set_vec_u16 (cpu, vd, i, val);
3127       /* Fall through.  */
3128     case 0xd: /* 32-bit, mask shift by 16.  */
3129       val <<= 8;
3130       val |= 0xFF;
3131       /* Fall through.  */
3132     case 0xc: /* 32-bit, mask shift by 8. */
3133       val <<= 8;
3134       val |= 0xFF;
3135       for (i = 0; i < (full ? 4 : 2); i++)
3136         aarch64_set_vec_u32 (cpu, vd, i, val);
3137       break;
3138
3139     case 0xe: /* 8-bit, no shift.  */
3140       for (i = 0; i < (full ? 16 : 8); i++)
3141         aarch64_set_vec_u8 (cpu, vd, i, val);
3142       break;
3143
3144     case 0xf: /* FMOV Vs.{2|4}S, #fpimm.  */
3145       {
3146         float u = fp_immediate_for_encoding_32 (val);
3147         for (i = 0; i < (full ? 4 : 2); i++)
3148           aarch64_set_vec_float (cpu, vd, i, u);
3149         break;
3150       }
3151
3152     default:
3153       HALT_NYI;
3154     }
3155 }
3156
3157 static void
3158 do_vec_MVNI (sim_cpu *cpu)
3159 {
3160   /* instr[31]    = 0
3161      instr[30]    = full/half selector
3162      instr[29,19] = 10111100000
3163      instr[18,16] = high 3 bits of uimm8
3164      instr[15,12] = selector
3165      instr[11,10] = 01
3166      instr[9,5]   = low 5-bits of uimm8
3167      instr[4,0]   = Vd.  */
3168
3169   int full     = uimm (aarch64_get_instr (cpu), 30, 30);
3170   unsigned vd  = uimm (aarch64_get_instr (cpu), 4, 0);
3171   unsigned val = uimm (aarch64_get_instr (cpu), 18, 16) << 5
3172     | uimm (aarch64_get_instr (cpu), 9, 5);
3173   unsigned i;
3174
3175   NYI_assert (29, 19, 0x5E0);
3176   NYI_assert (11, 10, 1);
3177
3178   switch (uimm (aarch64_get_instr (cpu), 15, 12))
3179     {
3180     case 0x0: /* 32-bit, no shift.  */
3181     case 0x2: /* 32-bit, shift by 8.  */
3182     case 0x4: /* 32-bit, shift by 16.  */
3183     case 0x6: /* 32-bit, shift by 24.  */
3184       val <<= (8 * uimm (aarch64_get_instr (cpu), 14, 13));
3185       val = ~ val;
3186       for (i = 0; i < (full ? 4 : 2); i++)
3187         aarch64_set_vec_u32 (cpu, vd, i, val);
3188       return;
3189
3190     case 0xa: /* 16-bit, 8 bit shift. */
3191       val <<= 8;
3192     case 0x8: /* 16-bit, no shift. */
3193       val = ~ val;
3194       for (i = 0; i < (full ? 8 : 4); i++)
3195         aarch64_set_vec_u16 (cpu, vd, i, val);
3196       return;
3197
3198     case 0xd: /* 32-bit, mask shift by 16.  */
3199       val <<= 8;
3200       val |= 0xFF;
3201     case 0xc: /* 32-bit, mask shift by 8. */
3202       val <<= 8;
3203       val |= 0xFF;
3204       val = ~ val;
3205       for (i = 0; i < (full ? 4 : 2); i++)
3206         aarch64_set_vec_u32 (cpu, vd, i, val);
3207       return;
3208
3209     case 0xE: /* MOVI Dn, #mask64 */
3210       {
3211         uint64_t mask = 0;
3212
3213         for (i = 0; i < 8; i++)
3214           if (val & (1 << i))
3215             mask |= (0xF << (i * 4));
3216         aarch64_set_vec_u64 (cpu, vd, 0, mask);
3217         aarch64_set_vec_u64 (cpu, vd, 1, 0);
3218         return;
3219       }
3220
3221     case 0xf: /* FMOV Vd.2D, #fpimm.  */
3222       {
3223         double u = fp_immediate_for_encoding_64 (val);
3224
3225         if (! full)
3226           HALT_UNALLOC;
3227
3228         aarch64_set_vec_double (cpu, vd, 0, u);
3229         aarch64_set_vec_double (cpu, vd, 1, u);
3230         return;
3231       }
3232
3233     default:
3234       HALT_NYI;
3235     }
3236 }
3237
3238 #define ABS(A) ((A) < 0 ? - (A) : (A))
3239
3240 static void
3241 do_vec_ABS (sim_cpu *cpu)
3242 {
3243   /* instr[31]    = 0
3244      instr[30]    = half(0)/full(1)
3245      instr[29,24] = 00 1110
3246      instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3247      instr[21,10] = 10 0000 1011 10
3248      instr[9,5]   = Vn
3249      instr[4.0]   = Vd.  */
3250
3251   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3252   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3253   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
3254   unsigned i;
3255
3256   NYI_assert (29, 24, 0x0E);
3257   NYI_assert (21, 10, 0x82E);
3258
3259   switch (uimm (aarch64_get_instr (cpu), 23, 22))
3260     {
3261     case 0:
3262       for (i = 0; i < (full ? 16 : 8); i++)
3263         aarch64_set_vec_s8 (cpu, vd, i,
3264                             ABS (aarch64_get_vec_s8 (cpu, vn, i)));
3265       break;
3266
3267     case 1:
3268       for (i = 0; i < (full ? 8 : 4); i++)
3269         aarch64_set_vec_s16 (cpu, vd, i,
3270                              ABS (aarch64_get_vec_s16 (cpu, vn, i)));
3271       break;
3272
3273     case 2:
3274       for (i = 0; i < (full ? 4 : 2); i++)
3275         aarch64_set_vec_s32 (cpu, vd, i,
3276                              ABS (aarch64_get_vec_s32 (cpu, vn, i)));
3277       break;
3278
3279     case 3:
3280       if (! full)
3281         HALT_NYI;
3282       for (i = 0; i < 2; i++)
3283         aarch64_set_vec_s64 (cpu, vd, i,
3284                              ABS (aarch64_get_vec_s64 (cpu, vn, i)));
3285       break;
3286     }
3287 }
3288
3289 static void
3290 do_vec_ADDV (sim_cpu *cpu)
3291 {
3292   /* instr[31]    = 0
3293      instr[30]    = full/half selector
3294      instr[29,24] = 00 1110
3295      instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3296      instr[21,10] = 11 0001 1011 10
3297      instr[9,5]   = Vm
3298      instr[4.0]   = Rd.  */
3299
3300   unsigned vm = uimm (aarch64_get_instr (cpu), 9, 5);
3301   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
3302   unsigned i;
3303   uint64_t val = 0;
3304   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3305
3306   NYI_assert (29, 24, 0x0E);
3307   NYI_assert (21, 10, 0xC6E);
3308
3309   switch (uimm (aarch64_get_instr (cpu), 23, 22))
3310     {
3311     case 0:
3312       for (i = 0; i < (full ? 16 : 8); i++)
3313         val += aarch64_get_vec_u8 (cpu, vm, i);
3314       aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3315       return;
3316
3317     case 1:
3318       for (i = 0; i < (full ? 8 : 4); i++)
3319         val += aarch64_get_vec_u16 (cpu, vm, i);
3320       aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3321       return;
3322
3323     case 2:
3324       for (i = 0; i < (full ? 4 : 2); i++)
3325         val += aarch64_get_vec_u32 (cpu, vm, i);
3326       aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3327       return;
3328
3329     case 3:
3330       if (! full)
3331         HALT_UNALLOC;
3332       val = aarch64_get_vec_u64 (cpu, vm, 0);
3333       val += aarch64_get_vec_u64 (cpu, vm, 1);
3334       aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3335       return;
3336
3337     default:
3338       HALT_UNREACHABLE;
3339     }
3340 }
3341
3342 static void
3343 do_vec_ins_2 (sim_cpu *cpu)
3344 {
3345   /* instr[31,21] = 01001110000
3346      instr[20,18] = size & element selector
3347      instr[17,14] = 0000
3348      instr[13]    = direction: to vec(0), from vec (1)
3349      instr[12,10] = 111
3350      instr[9,5]   = Vm
3351      instr[4,0]   = Vd.  */
3352
3353   unsigned elem;
3354   unsigned vm = uimm (aarch64_get_instr (cpu), 9, 5);
3355   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3356
3357   NYI_assert (31, 21, 0x270);
3358   NYI_assert (17, 14, 0);
3359   NYI_assert (12, 10, 7);
3360
3361   if (uimm (aarch64_get_instr (cpu), 13, 13) == 1)
3362     {
3363       if (uimm (aarch64_get_instr (cpu), 18, 18) == 1)
3364         {
3365           /* 32-bit moves.  */
3366           elem = uimm (aarch64_get_instr (cpu), 20, 19);
3367           aarch64_set_reg_u64 (cpu, vd, NO_SP,
3368                                aarch64_get_vec_u32 (cpu, vm, elem));
3369         }
3370       else
3371         {
3372           /* 64-bit moves.  */
3373           if (uimm (aarch64_get_instr (cpu), 19, 19) != 1)
3374             HALT_NYI;
3375
3376           elem = uimm (aarch64_get_instr (cpu), 20, 20);
3377           aarch64_set_reg_u64 (cpu, vd, NO_SP,
3378                                aarch64_get_vec_u64 (cpu, vm, elem));
3379         }
3380     }
3381   else
3382     {
3383       if (uimm (aarch64_get_instr (cpu), 18, 18) == 1)
3384         {
3385           /* 32-bit moves.  */
3386           elem = uimm (aarch64_get_instr (cpu), 20, 19);
3387           aarch64_set_vec_u32 (cpu, vd, elem,
3388                                aarch64_get_reg_u32 (cpu, vm, NO_SP));
3389         }
3390       else
3391         {
3392           /* 64-bit moves.  */
3393           if (uimm (aarch64_get_instr (cpu), 19, 19) != 1)
3394             HALT_NYI;
3395
3396           elem = uimm (aarch64_get_instr (cpu), 20, 20);
3397           aarch64_set_vec_u64 (cpu, vd, elem,
3398                                aarch64_get_reg_u64 (cpu, vm, NO_SP));
3399         }
3400     }
3401 }
3402
3403 static void
3404 do_vec_mull (sim_cpu *cpu)
3405 {
3406   /* instr[31]    = 0
3407      instr[30]    = lower(0)/upper(1) selector
3408      instr[29]    = signed(0)/unsigned(1)
3409      instr[28,24] = 0 1110
3410      instr[23,22] = size: 8-bit (00), 16-bit (01), 32-bit (10)
3411      instr[21]    = 1
3412      instr[20,16] = Vm
3413      instr[15,10] = 11 0000
3414      instr[9,5]   = Vn
3415      instr[4.0]   = Vd.  */
3416
3417   int    unsign = uimm (aarch64_get_instr (cpu), 29, 29);
3418   int    bias = uimm (aarch64_get_instr (cpu), 30, 30);
3419   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3420   unsigned vn = uimm (aarch64_get_instr (cpu),  9,  5);
3421   unsigned vd = uimm (aarch64_get_instr (cpu),  4,  0);
3422   unsigned i;
3423
3424   NYI_assert (28, 24, 0x0E);
3425   NYI_assert (15, 10, 0x30);
3426
3427   switch (uimm (aarch64_get_instr (cpu), 23, 22))
3428     {
3429     case 0:
3430       if (bias)
3431         bias = 8;
3432       if (unsign)
3433         for (i = 0; i < 8; i++)
3434           aarch64_set_vec_u16 (cpu, vd, i,
3435                                aarch64_get_vec_u8 (cpu, vn, i + bias)
3436                                * aarch64_get_vec_u8 (cpu, vm, i + bias));
3437       else
3438         for (i = 0; i < 8; i++)
3439           aarch64_set_vec_s16 (cpu, vd, i,
3440                                aarch64_get_vec_s8 (cpu, vn, i + bias)
3441                                * aarch64_get_vec_s8 (cpu, vm, i + bias));
3442       return;
3443
3444     case 1:
3445       if (bias)
3446         bias = 4;
3447       if (unsign)
3448         for (i = 0; i < 4; i++)
3449           aarch64_set_vec_u32 (cpu, vd, i,
3450                                aarch64_get_vec_u16 (cpu, vn, i + bias)
3451                                * aarch64_get_vec_u16 (cpu, vm, i + bias));
3452       else
3453         for (i = 0; i < 4; i++)
3454           aarch64_set_vec_s32 (cpu, vd, i,
3455                                aarch64_get_vec_s16 (cpu, vn, i + bias)
3456                                * aarch64_get_vec_s16 (cpu, vm, i + bias));
3457       return;
3458
3459     case 2:
3460       if (bias)
3461         bias = 2;
3462       if (unsign)
3463         for (i = 0; i < 2; i++)
3464           aarch64_set_vec_u64 (cpu, vd, i,
3465                                (uint64_t) aarch64_get_vec_u32 (cpu, vn,
3466                                                                i + bias)
3467                                * (uint64_t) aarch64_get_vec_u32 (cpu, vm,
3468                                                                  i + bias));
3469       else
3470         for (i = 0; i < 2; i++)
3471           aarch64_set_vec_s64 (cpu, vd, i,
3472                                aarch64_get_vec_s32 (cpu, vn, i + bias)
3473                                * aarch64_get_vec_s32 (cpu, vm, i + bias));
3474       return;
3475
3476     case 3:
3477     default:
3478       HALT_NYI;
3479     }
3480 }
3481
3482 static void
3483 do_vec_fadd (sim_cpu *cpu)
3484 {
3485   /* instr[31]    = 0
3486      instr[30]    = half(0)/full(1)
3487      instr[29,24] = 001110
3488      instr[23]    = FADD(0)/FSUB(1)
3489      instr[22]    = float (0)/double(1)
3490      instr[21]    = 1
3491      instr[20,16] = Vm
3492      instr[15,10] = 110101
3493      instr[9,5]   = Vn
3494      instr[4.0]   = Vd.  */
3495
3496   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3497   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3498   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3499   unsigned i;
3500   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3501
3502   NYI_assert (29, 24, 0x0E);
3503   NYI_assert (21, 21, 1);
3504   NYI_assert (15, 10, 0x35);
3505
3506   if (uimm (aarch64_get_instr (cpu), 23, 23))
3507     {
3508       if (uimm (aarch64_get_instr (cpu), 22, 22))
3509         {
3510           if (! full)
3511             HALT_NYI;
3512
3513           for (i = 0; i < 2; i++)
3514             aarch64_set_vec_double (cpu, vd, i,
3515                                     aarch64_get_vec_double (cpu, vn, i)
3516                                     - aarch64_get_vec_double (cpu, vm, i));
3517         }
3518       else
3519         {
3520           for (i = 0; i < (full ? 4 : 2); i++)
3521             aarch64_set_vec_float (cpu, vd, i,
3522                                    aarch64_get_vec_float (cpu, vn, i)
3523                                    - aarch64_get_vec_float (cpu, vm, i));
3524         }
3525     }
3526   else
3527     {
3528       if (uimm (aarch64_get_instr (cpu), 22, 22))
3529         {
3530           if (! full)
3531             HALT_NYI;
3532
3533           for (i = 0; i < 2; i++)
3534             aarch64_set_vec_double (cpu, vd, i,
3535                                     aarch64_get_vec_double (cpu, vm, i)
3536                                     + aarch64_get_vec_double (cpu, vn, i));
3537         }
3538       else
3539         {
3540           for (i = 0; i < (full ? 4 : 2); i++)
3541             aarch64_set_vec_float (cpu, vd, i,
3542                                    aarch64_get_vec_float (cpu, vm, i)
3543                                    + aarch64_get_vec_float (cpu, vn, i));
3544         }
3545     }
3546 }
3547
3548 static void
3549 do_vec_add (sim_cpu *cpu)
3550 {
3551   /* instr[31]    = 0
3552      instr[30]    = full/half selector
3553      instr[29,24] = 001110
3554      instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3555      instr[21]    = 1
3556      instr[20,16] = Vn
3557      instr[15,10] = 100001
3558      instr[9,5]   = Vm
3559      instr[4.0]   = Vd.  */
3560
3561   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3562   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3563   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3564   unsigned i;
3565   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3566
3567   NYI_assert (29, 24, 0x0E);
3568   NYI_assert (21, 21, 1);
3569   NYI_assert (15, 10, 0x21);
3570
3571   switch (uimm (aarch64_get_instr (cpu), 23, 22))
3572     {
3573     case 0:
3574       for (i = 0; i < (full ? 16 : 8); i++)
3575         aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vn, i)
3576                             + aarch64_get_vec_u8 (cpu, vm, i));
3577       return;
3578
3579     case 1:
3580       for (i = 0; i < (full ? 8 : 4); i++)
3581         aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vn, i)
3582                              + aarch64_get_vec_u16 (cpu, vm, i));
3583       return;
3584
3585     case 2:
3586       for (i = 0; i < (full ? 4 : 2); i++)
3587         aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vn, i)
3588                              + aarch64_get_vec_u32 (cpu, vm, i));
3589       return;
3590
3591     case 3:
3592       if (! full)
3593         HALT_UNALLOC;
3594       aarch64_set_vec_u64 (cpu, vd, 0, aarch64_get_vec_u64 (cpu, vn, 0)
3595                            + aarch64_get_vec_u64 (cpu, vm, 0));
3596       aarch64_set_vec_u64 (cpu, vd, 1,
3597                            aarch64_get_vec_u64 (cpu, vn, 1)
3598                            + aarch64_get_vec_u64 (cpu, vm, 1));
3599       return;
3600
3601     default:
3602       HALT_UNREACHABLE;
3603     }
3604 }
3605
3606 static void
3607 do_vec_mul (sim_cpu *cpu)
3608 {
3609   /* instr[31]    = 0
3610      instr[30]    = full/half selector
3611      instr[29,24] = 00 1110
3612      instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3613      instr[21]    = 1
3614      instr[20,16] = Vn
3615      instr[15,10] = 10 0111
3616      instr[9,5]   = Vm
3617      instr[4.0]   = Vd.  */
3618
3619   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3620   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3621   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3622   unsigned i;
3623   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3624
3625   NYI_assert (29, 24, 0x0E);
3626   NYI_assert (21, 21, 1);
3627   NYI_assert (15, 10, 0x27);
3628
3629   switch (uimm (aarch64_get_instr (cpu), 23, 22))
3630     {
3631     case 0:
3632       for (i = 0; i < (full ? 16 : 8); i++)
3633         {
3634           uint16_t val = aarch64_get_vec_u8 (cpu, vn, i);
3635           val *= aarch64_get_vec_u8 (cpu, vm, i);
3636
3637           aarch64_set_vec_u16 (cpu, vd, i, val);
3638         }
3639       return;
3640
3641     case 1:
3642       for (i = 0; i < (full ? 8 : 4); i++)
3643         {
3644           uint32_t val = aarch64_get_vec_u16 (cpu, vn, i);
3645           val *= aarch64_get_vec_u16 (cpu, vm, i);
3646
3647           aarch64_set_vec_u32 (cpu, vd, i, val);
3648         }
3649       return;
3650
3651     case 2:
3652       for (i = 0; i < (full ? 4 : 2); i++)
3653         {
3654           uint64_t val = aarch64_get_vec_u32 (cpu, vn, i);
3655           val *= aarch64_get_vec_u32 (cpu, vm, i);
3656
3657           aarch64_set_vec_u64 (cpu, vd, i, val);
3658         }
3659       return;
3660
3661     default:
3662     case 3:
3663       HALT_UNALLOC;
3664     }
3665 }
3666
3667 static void
3668 do_vec_MLA (sim_cpu *cpu)
3669 {
3670   /* instr[31]    = 0
3671      instr[30]    = full/half selector
3672      instr[29,24] = 00 1110
3673      instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3674      instr[21]    = 1
3675      instr[20,16] = Vn
3676      instr[15,10] = 1001 01
3677      instr[9,5]   = Vm
3678      instr[4.0]   = Vd.  */
3679
3680   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3681   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3682   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3683   unsigned i;
3684   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3685
3686   NYI_assert (29, 24, 0x0E);
3687   NYI_assert (21, 21, 1);
3688   NYI_assert (15, 10, 0x25);
3689
3690   switch (uimm (aarch64_get_instr (cpu), 23, 22))
3691     {
3692     case 0:
3693       for (i = 0; i < (full ? 16 : 8); i++)
3694         {
3695           uint16_t val = aarch64_get_vec_u8 (cpu, vn, i);
3696           val *= aarch64_get_vec_u8 (cpu, vm, i);
3697           val += aarch64_get_vec_u8 (cpu, vd, i);
3698
3699           aarch64_set_vec_u16 (cpu, vd, i, val);
3700         }
3701       return;
3702
3703     case 1:
3704       for (i = 0; i < (full ? 8 : 4); i++)
3705         {
3706           uint32_t val = aarch64_get_vec_u16 (cpu, vn, i);
3707           val *= aarch64_get_vec_u16 (cpu, vm, i);
3708           val += aarch64_get_vec_u16 (cpu, vd, i);
3709
3710           aarch64_set_vec_u32 (cpu, vd, i, val);
3711         }
3712       return;
3713
3714     case 2:
3715       for (i = 0; i < (full ? 4 : 2); i++)
3716         {
3717           uint64_t val = aarch64_get_vec_u32 (cpu, vn, i);
3718           val *= aarch64_get_vec_u32 (cpu, vm, i);
3719           val += aarch64_get_vec_u32 (cpu, vd, i);
3720
3721           aarch64_set_vec_u64 (cpu, vd, i, val);
3722         }
3723       return;
3724
3725     default:
3726     case 3:
3727       HALT_UNALLOC;
3728     }
3729 }
3730
3731 static float
3732 fmaxnm (float a, float b)
3733 {
3734   if (fpclassify (a) == FP_NORMAL)
3735     {
3736       if (fpclassify (b) == FP_NORMAL)
3737         return a > b ? a : b;
3738       return a;
3739     }
3740   else if (fpclassify (b) == FP_NORMAL)
3741     return b;
3742   return a;
3743 }
3744
3745 static float
3746 fminnm (float a, float b)
3747 {
3748   if (fpclassify (a) == FP_NORMAL)
3749     {
3750       if (fpclassify (b) == FP_NORMAL)
3751         return a < b ? a : b;
3752       return a;
3753     }
3754   else if (fpclassify (b) == FP_NORMAL)
3755     return b;
3756   return a;
3757 }
3758
3759 static double
3760 dmaxnm (double a, double b)
3761 {
3762   if (fpclassify (a) == FP_NORMAL)
3763     {
3764       if (fpclassify (b) == FP_NORMAL)
3765         return a > b ? a : b;
3766       return a;
3767     }
3768   else if (fpclassify (b) == FP_NORMAL)
3769     return b;
3770   return a;
3771 }
3772
3773 static double
3774 dminnm (double a, double b)
3775 {
3776   if (fpclassify (a) == FP_NORMAL)
3777     {
3778       if (fpclassify (b) == FP_NORMAL)
3779         return a < b ? a : b;
3780       return a;
3781     }
3782   else if (fpclassify (b) == FP_NORMAL)
3783     return b;
3784   return a;
3785 }
3786
3787 static void
3788 do_vec_FminmaxNMP (sim_cpu *cpu)
3789 {
3790   /* aarch64_get_instr (cpu)[31]    = 0
3791      aarch64_get_instr (cpu)[30]    = half (0)/full (1)
3792      aarch64_get_instr (cpu)[29,24] = 10 1110
3793      aarch64_get_instr (cpu)[23]    = max(0)/min(1)
3794      aarch64_get_instr (cpu)[22]    = float (0)/double (1)
3795      aarch64_get_instr (cpu)[21]    = 1
3796      aarch64_get_instr (cpu)[20,16] = Vn
3797      aarch64_get_instr (cpu)[15,10] = 1100 01
3798      aarch64_get_instr (cpu)[9,5]   = Vm
3799      aarch64_get_instr (cpu)[4.0]   = Vd.  */
3800
3801   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3802   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3803   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3804   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3805
3806   NYI_assert (29, 24, 0x2E);
3807   NYI_assert (21, 21, 1);
3808   NYI_assert (15, 10, 0x31);
3809
3810   if (uimm (aarch64_get_instr (cpu), 22, 22))
3811     {
3812       double (* fn)(double, double) = uimm (aarch64_get_instr (cpu), 23, 23)
3813         ? dminnm : dmaxnm;
3814
3815       if (! full)
3816         HALT_NYI;
3817       aarch64_set_vec_double (cpu, vd, 0,
3818                               fn (aarch64_get_vec_double (cpu, vn, 0),
3819                                   aarch64_get_vec_double (cpu, vn, 1)));
3820       aarch64_set_vec_double (cpu, vd, 0,
3821                               fn (aarch64_get_vec_double (cpu, vm, 0),
3822                                   aarch64_get_vec_double (cpu, vm, 1)));
3823     }
3824   else
3825     {
3826       float (* fn)(float, float) = uimm (aarch64_get_instr (cpu), 23, 23)
3827         ? fminnm : fmaxnm;
3828
3829       aarch64_set_vec_float (cpu, vd, 0,
3830                              fn (aarch64_get_vec_float (cpu, vn, 0),
3831                                  aarch64_get_vec_float (cpu, vn, 1)));
3832       if (full)
3833         aarch64_set_vec_float (cpu, vd, 1,
3834                                fn (aarch64_get_vec_float (cpu, vn, 2),
3835                                    aarch64_get_vec_float (cpu, vn, 3)));
3836
3837       aarch64_set_vec_float (cpu, vd, (full ? 2 : 1),
3838                              fn (aarch64_get_vec_float (cpu, vm, 0),
3839                                  aarch64_get_vec_float (cpu, vm, 1)));
3840       if (full)
3841         aarch64_set_vec_float (cpu, vd, 3,
3842                                fn (aarch64_get_vec_float (cpu, vm, 2),
3843                                    aarch64_get_vec_float (cpu, vm, 3)));
3844     }
3845 }
3846
3847 static void
3848 do_vec_AND (sim_cpu *cpu)
3849 {
3850   /* instr[31]    = 0
3851      instr[30]    = half (0)/full (1)
3852      instr[29,21] = 001110001
3853      instr[20,16] = Vm
3854      instr[15,10] = 000111
3855      instr[9,5]   = Vn
3856      instr[4.0]   = Vd.  */
3857
3858   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3859   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3860   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3861   unsigned i;
3862   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3863
3864   NYI_assert (29, 21, 0x071);
3865   NYI_assert (15, 10, 0x07);
3866
3867   for (i = 0; i < (full ? 4 : 2); i++)
3868     aarch64_set_vec_u32 (cpu, vd, i,
3869                          aarch64_get_vec_u32 (cpu, vn, i)
3870                          & aarch64_get_vec_u32 (cpu, vm, i));
3871 }
3872
3873 static void
3874 do_vec_BSL (sim_cpu *cpu)
3875 {
3876   /* instr[31]    = 0
3877      instr[30]    = half (0)/full (1)
3878      instr[29,21] = 101110011
3879      instr[20,16] = Vm
3880      instr[15,10] = 000111
3881      instr[9,5]   = Vn
3882      instr[4.0]   = Vd.  */
3883
3884   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3885   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3886   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3887   unsigned i;
3888   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3889
3890   NYI_assert (29, 21, 0x173);
3891   NYI_assert (15, 10, 0x07);
3892
3893   for (i = 0; i < (full ? 16 : 8); i++)
3894     aarch64_set_vec_u8 (cpu, vd, i,
3895                         (    aarch64_get_vec_u8 (cpu, vd, i)
3896                            & aarch64_get_vec_u8 (cpu, vn, i))
3897                         | ((~ aarch64_get_vec_u8 (cpu, vd, i))
3898                            & aarch64_get_vec_u8 (cpu, vm, i)));
3899 }
3900
3901 static void
3902 do_vec_EOR (sim_cpu *cpu)
3903 {
3904   /* instr[31]    = 0
3905      instr[30]    = half (0)/full (1)
3906      instr[29,21] = 10 1110 001
3907      instr[20,16] = Vm
3908      instr[15,10] = 000111
3909      instr[9,5]   = Vn
3910      instr[4.0]   = Vd.  */
3911
3912   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3913   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3914   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3915   unsigned i;
3916   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3917
3918   NYI_assert (29, 21, 0x171);
3919   NYI_assert (15, 10, 0x07);
3920
3921   for (i = 0; i < (full ? 4 : 2); i++)
3922     aarch64_set_vec_u32 (cpu, vd, i,
3923                          aarch64_get_vec_u32 (cpu, vn, i)
3924                          ^ aarch64_get_vec_u32 (cpu, vm, i));
3925 }
3926
3927 static void
3928 do_vec_bit (sim_cpu *cpu)
3929 {
3930   /* instr[31]    = 0
3931      instr[30]    = half (0)/full (1)
3932      instr[29,23] = 10 1110 1
3933      instr[22]    = BIT (0) / BIF (1)
3934      instr[21]    = 1
3935      instr[20,16] = Vm
3936      instr[15,10] = 0001 11
3937      instr[9,5]   = Vn
3938      instr[4.0]   = Vd.  */
3939
3940   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3941   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3942   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3943   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
3944   unsigned test_false = uimm (aarch64_get_instr (cpu), 22, 22);
3945   unsigned i;
3946
3947   NYI_assert (29, 23, 0x5D);
3948   NYI_assert (21, 21, 1);
3949   NYI_assert (15, 10, 0x07);
3950
3951   if (test_false)
3952     {
3953       for (i = 0; i < (full ? 16 : 8); i++)
3954         if (aarch64_get_vec_u32 (cpu, vn, i) == 0)
3955           aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vm, i));
3956     }
3957   else
3958     {
3959       for (i = 0; i < (full ? 16 : 8); i++)
3960         if (aarch64_get_vec_u32 (cpu, vn, i) != 0)
3961           aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vm, i));
3962     }
3963 }
3964
3965 static void
3966 do_vec_ORN (sim_cpu *cpu)
3967 {
3968   /* instr[31]    = 0
3969      instr[30]    = half (0)/full (1)
3970      instr[29,21] = 00 1110 111
3971      instr[20,16] = Vm
3972      instr[15,10] = 00 0111
3973      instr[9,5]   = Vn
3974      instr[4.0]   = Vd.  */
3975
3976   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3977   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3978   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3979   unsigned i;
3980   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3981
3982   NYI_assert (29, 21, 0x077);
3983   NYI_assert (15, 10, 0x07);
3984
3985   for (i = 0; i < (full ? 16 : 8); i++)
3986     aarch64_set_vec_u8 (cpu, vd, i,
3987                         aarch64_get_vec_u8 (cpu, vn, i)
3988                         | ~ aarch64_get_vec_u8 (cpu, vm, i));
3989 }
3990
3991 static void
3992 do_vec_ORR (sim_cpu *cpu)
3993 {
3994   /* instr[31]    = 0
3995      instr[30]    = half (0)/full (1)
3996      instr[29,21] = 00 1110 101
3997      instr[20,16] = Vm
3998      instr[15,10] = 0001 11
3999      instr[9,5]   = Vn
4000      instr[4.0]   = Vd.  */
4001
4002   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4003   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4004   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4005   unsigned i;
4006   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
4007
4008   NYI_assert (29, 21, 0x075);
4009   NYI_assert (15, 10, 0x07);
4010
4011   for (i = 0; i < (full ? 16 : 8); i++)
4012     aarch64_set_vec_u8 (cpu, vd, i,
4013                         aarch64_get_vec_u8 (cpu, vn, i)
4014                         | aarch64_get_vec_u8 (cpu, vm, i));
4015 }
4016
4017 static void
4018 do_vec_BIC (sim_cpu *cpu)
4019 {
4020   /* instr[31]    = 0
4021      instr[30]    = half (0)/full (1)
4022      instr[29,21] = 00 1110 011
4023      instr[20,16] = Vm
4024      instr[15,10] = 00 0111
4025      instr[9,5]   = Vn
4026      instr[4.0]   = Vd.  */
4027
4028   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4029   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4030   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4031   unsigned i;
4032   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
4033
4034   NYI_assert (29, 21, 0x073);
4035   NYI_assert (15, 10, 0x07);
4036
4037   for (i = 0; i < (full ? 16 : 8); i++)
4038     aarch64_set_vec_u8 (cpu, vd, i,
4039                         aarch64_get_vec_u8 (cpu, vn, i)
4040                         & ~ aarch64_get_vec_u8 (cpu, vm, i));
4041 }
4042
4043 static void
4044 do_vec_XTN (sim_cpu *cpu)
4045 {
4046   /* instr[31]    = 0
4047      instr[30]    = first part (0)/ second part (1)
4048      instr[29,24] = 00 1110
4049      instr[23,22] = size: byte(00), half(01), word (10)
4050      instr[21,10] = 1000 0100 1010
4051      instr[9,5]   = Vs
4052      instr[4,0]   = Vd.  */
4053
4054   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
4055   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4056   unsigned bias = uimm (aarch64_get_instr (cpu), 30, 30);
4057   unsigned i;
4058
4059   NYI_assert (29, 24, 0x0E);
4060   NYI_assert (21, 10, 0x84A);
4061
4062   switch (uimm (aarch64_get_instr (cpu), 23, 22))
4063     {
4064     case 0:
4065       if (bias)
4066         for (i = 0; i < 8; i++)
4067           aarch64_set_vec_u8 (cpu, vd, i + 8,
4068                               aarch64_get_vec_u16 (cpu, vs, i) >> 8);
4069       else
4070         for (i = 0; i < 8; i++)
4071           aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vs, i));
4072       return;
4073
4074     case 1:
4075       if (bias)
4076         for (i = 0; i < 4; i++)
4077           aarch64_set_vec_u16 (cpu, vd, i + 4,
4078                                aarch64_get_vec_u32 (cpu, vs, i) >> 16);
4079       else
4080         for (i = 0; i < 4; i++)
4081           aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vs, i));
4082       return;
4083
4084     case 2:
4085       if (bias)
4086         for (i = 0; i < 2; i++)
4087           aarch64_set_vec_u32 (cpu, vd, i + 4,
4088                                aarch64_get_vec_u64 (cpu, vs, i) >> 32);
4089       else
4090         for (i = 0; i < 2; i++)
4091           aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u64 (cpu, vs, i));
4092       return;
4093
4094     default:
4095       HALT_UNALLOC;
4096     }
4097 }
4098
4099 static void
4100 do_vec_maxv (sim_cpu *cpu)
4101 {
4102   /* instr[31]    = 0
4103      instr[30]    = half(0)/full(1)
4104      instr[29]    = signed (0)/unsigned(1)
4105      instr[28,24] = 0 1110
4106      instr[23,22] = size: byte(00), half(01), word (10)
4107      instr[21]    = 1
4108      instr[20,17] = 1 000
4109      instr[16]    = max(0)/min(1)
4110      instr[15,10] = 1010 10
4111      instr[9,5]   = V source
4112      instr[4.0]   = R dest.  */
4113
4114   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
4115   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
4116   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4117   unsigned i;
4118
4119   NYI_assert (28, 24, 0x0E);
4120   NYI_assert (21, 21, 1);
4121   NYI_assert (20, 17, 8);
4122   NYI_assert (15, 10, 0x2A);
4123
4124   switch ((uimm (aarch64_get_instr (cpu), 29, 29) << 1)
4125           | uimm (aarch64_get_instr (cpu), 16, 16))
4126     {
4127     case 0: /* SMAXV.  */
4128        {
4129         int64_t smax;
4130         switch (uimm (aarch64_get_instr (cpu), 23, 22))
4131           {
4132           case 0:
4133             smax = aarch64_get_vec_s8 (cpu, vs, 0);
4134             for (i = 1; i < (full ? 16 : 8); i++)
4135               smax = max (smax, aarch64_get_vec_s8 (cpu, vs, i));
4136             break;
4137           case 1:
4138             smax = aarch64_get_vec_s16 (cpu, vs, 0);
4139             for (i = 1; i < (full ? 8 : 4); i++)
4140               smax = max (smax, aarch64_get_vec_s16 (cpu, vs, i));
4141             break;
4142           case 2:
4143             smax = aarch64_get_vec_s32 (cpu, vs, 0);
4144             for (i = 1; i < (full ? 4 : 2); i++)
4145               smax = max (smax, aarch64_get_vec_s32 (cpu, vs, i));
4146             break;
4147           default:
4148           case 3:
4149             HALT_UNALLOC;
4150           }
4151         aarch64_set_reg_s64 (cpu, rd, NO_SP, smax);
4152         return;
4153       }
4154
4155     case 1: /* SMINV.  */
4156       {
4157         int64_t smin;
4158         switch (uimm (aarch64_get_instr (cpu), 23, 22))
4159           {
4160           case 0:
4161             smin = aarch64_get_vec_s8 (cpu, vs, 0);
4162             for (i = 1; i < (full ? 16 : 8); i++)
4163               smin = min (smin, aarch64_get_vec_s8 (cpu, vs, i));
4164             break;
4165           case 1:
4166             smin = aarch64_get_vec_s16 (cpu, vs, 0);
4167             for (i = 1; i < (full ? 8 : 4); i++)
4168               smin = min (smin, aarch64_get_vec_s16 (cpu, vs, i));
4169             break;
4170           case 2:
4171             smin = aarch64_get_vec_s32 (cpu, vs, 0);
4172             for (i = 1; i < (full ? 4 : 2); i++)
4173               smin = min (smin, aarch64_get_vec_s32 (cpu, vs, i));
4174             break;
4175           default:
4176           case 3:
4177             HALT_UNALLOC;
4178           }
4179         aarch64_set_reg_s64 (cpu, rd, NO_SP, smin);
4180         return;
4181       }
4182
4183     case 2: /* UMAXV.  */
4184       {
4185         uint64_t umax;
4186         switch (uimm (aarch64_get_instr (cpu), 23, 22))
4187           {
4188           case 0:
4189             umax = aarch64_get_vec_u8 (cpu, vs, 0);
4190             for (i = 1; i < (full ? 16 : 8); i++)
4191               umax = max (umax, aarch64_get_vec_u8 (cpu, vs, i));
4192             break;
4193           case 1:
4194             umax = aarch64_get_vec_u16 (cpu, vs, 0);
4195             for (i = 1; i < (full ? 8 : 4); i++)
4196               umax = max (umax, aarch64_get_vec_u16 (cpu, vs, i));
4197             break;
4198           case 2:
4199             umax = aarch64_get_vec_u32 (cpu, vs, 0);
4200             for (i = 1; i < (full ? 4 : 2); i++)
4201               umax = max (umax, aarch64_get_vec_u32 (cpu, vs, i));
4202             break;
4203           default:
4204           case 3:
4205             HALT_UNALLOC;
4206           }
4207         aarch64_set_reg_u64 (cpu, rd, NO_SP, umax);
4208         return;
4209       }
4210
4211     case 3: /* UMINV.  */
4212       {
4213         uint64_t umin;
4214         switch (uimm (aarch64_get_instr (cpu), 23, 22))
4215           {
4216           case 0:
4217             umin = aarch64_get_vec_u8 (cpu, vs, 0);
4218             for (i = 1; i < (full ? 16 : 8); i++)
4219               umin = min (umin, aarch64_get_vec_u8 (cpu, vs, i));
4220             break;
4221           case 1:
4222             umin = aarch64_get_vec_u16 (cpu, vs, 0);
4223             for (i = 1; i < (full ? 8 : 4); i++)
4224               umin = min (umin, aarch64_get_vec_u16 (cpu, vs, i));
4225             break;
4226           case 2:
4227             umin = aarch64_get_vec_u32 (cpu, vs, 0);
4228             for (i = 1; i < (full ? 4 : 2); i++)
4229               umin = min (umin, aarch64_get_vec_u32 (cpu, vs, i));
4230             break;
4231           default:
4232           case 3:
4233             HALT_UNALLOC;
4234           }
4235         aarch64_set_reg_u64 (cpu, rd, NO_SP, umin);
4236         return;
4237       }
4238
4239     default:
4240       HALT_UNALLOC;
4241     }
4242 }
4243
4244 static void
4245 do_vec_fminmaxV (sim_cpu *cpu)
4246 {
4247   /* instr[31,24] = 0110 1110
4248      instr[23]    = max(0)/min(1)
4249      instr[22,14] = 011 0000 11
4250      instr[13,12] = nm(00)/normal(11)
4251      instr[11,10] = 10
4252      instr[9,5]   = V source
4253      instr[4.0]   = R dest.  */
4254
4255   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
4256   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
4257   unsigned i;
4258   float res   = aarch64_get_vec_float (cpu, vs, 0);
4259
4260   NYI_assert (31, 24, 0x6E);
4261   NYI_assert (22, 14, 0x0C3);
4262   NYI_assert (11, 10, 2);
4263
4264   if (uimm (aarch64_get_instr (cpu), 23, 23))
4265     {
4266       switch (uimm (aarch64_get_instr (cpu), 13, 12))
4267         {
4268         case 0: /* FMNINNMV.  */
4269           for (i = 1; i < 4; i++)
4270             res = fminnm (res, aarch64_get_vec_float (cpu, vs, i));
4271           break;
4272
4273         case 3: /* FMINV.  */
4274           for (i = 1; i < 4; i++)
4275             res = min (res, aarch64_get_vec_float (cpu, vs, i));
4276           break;
4277
4278         default:
4279           HALT_NYI;
4280         }
4281     }
4282   else
4283     {
4284       switch (uimm (aarch64_get_instr (cpu), 13, 12))
4285         {
4286         case 0: /* FMNAXNMV.  */
4287           for (i = 1; i < 4; i++)
4288             res = fmaxnm (res, aarch64_get_vec_float (cpu, vs, i));
4289           break;
4290
4291         case 3: /* FMAXV.  */
4292           for (i = 1; i < 4; i++)
4293             res = max (res, aarch64_get_vec_float (cpu, vs, i));
4294           break;
4295
4296         default:
4297           HALT_NYI;
4298         }
4299     }
4300
4301   aarch64_set_FP_float (cpu, rd, res);
4302 }
4303
4304 static void
4305 do_vec_Fminmax (sim_cpu *cpu)
4306 {
4307   /* instr[31]    = 0
4308      instr[30]    = half(0)/full(1)
4309      instr[29,24] = 00 1110
4310      instr[23]    = max(0)/min(1)
4311      instr[22]    = float(0)/double(1)
4312      instr[21]    = 1
4313      instr[20,16] = Vm
4314      instr[15,14] = 11
4315      instr[13,12] = nm(00)/normal(11)
4316      instr[11,10] = 01
4317      instr[9,5]   = Vn
4318      instr[4,0]   = Vd.  */
4319
4320   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4321   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4322   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4323   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4324   unsigned min = uimm (aarch64_get_instr (cpu), 23, 23);
4325   unsigned i;
4326
4327   NYI_assert (29, 24, 0x0E);
4328   NYI_assert (21, 21, 1);
4329   NYI_assert (15, 14, 3);
4330   NYI_assert (11, 10, 1);
4331
4332   if (uimm (aarch64_get_instr (cpu), 22, 22))
4333     {
4334       double (* func)(double, double);
4335
4336       if (! full)
4337         HALT_NYI;
4338
4339       if (uimm (aarch64_get_instr (cpu), 13, 12) == 0)
4340         func = min ? dminnm : dmaxnm;
4341       else if (uimm (aarch64_get_instr (cpu), 13, 12) == 3)
4342         func = min ? fmin : fmax;
4343       else
4344         HALT_NYI;
4345
4346       for (i = 0; i < 2; i++)
4347         aarch64_set_vec_double (cpu, vd, i,
4348                                 func (aarch64_get_vec_double (cpu, vn, i),
4349                                       aarch64_get_vec_double (cpu, vm, i)));
4350     }
4351   else
4352     {
4353       float (* func)(float, float);
4354
4355       if (uimm (aarch64_get_instr (cpu), 13, 12) == 0)
4356         func = min ? fminnm : fmaxnm;
4357       else if (uimm (aarch64_get_instr (cpu), 13, 12) == 3)
4358         func = min ? fminf : fmaxf;
4359       else
4360         HALT_NYI;
4361
4362       for (i = 0; i < (full ? 4 : 2); i++)
4363         aarch64_set_vec_float (cpu, vd, i,
4364                                func (aarch64_get_vec_float (cpu, vn, i),
4365                                      aarch64_get_vec_float (cpu, vm, i)));
4366     }
4367 }
4368
4369 static void
4370 do_vec_SCVTF (sim_cpu *cpu)
4371 {
4372   /* instr[31]    = 0
4373      instr[30]    = Q
4374      instr[29,23] = 00 1110 0
4375      instr[22]    = float(0)/double(1)
4376      instr[21,10] = 10 0001 1101 10
4377      instr[9,5]   = Vn
4378      instr[4,0]   = Vd.  */
4379
4380   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4381   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4382   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4383   unsigned size = uimm (aarch64_get_instr (cpu), 22, 22);
4384   unsigned i;
4385
4386   NYI_assert (29, 23, 0x1C);
4387   NYI_assert (21, 10, 0x876);
4388
4389   if (size)
4390     {
4391       if (! full)
4392         HALT_UNALLOC;
4393
4394       for (i = 0; i < 2; i++)
4395         {
4396           double val = (double) aarch64_get_vec_u64 (cpu, vn, i);
4397           aarch64_set_vec_double (cpu, vd, i, val);
4398         }
4399     }
4400   else
4401     {
4402       for (i = 0; i < (full ? 4 : 2); i++)
4403         {
4404           float val = (float) aarch64_get_vec_u32 (cpu, vn, i);
4405           aarch64_set_vec_float (cpu, vd, i, val);
4406         }
4407     }
4408 }
4409
4410 #define VEC_CMP(SOURCE, CMP)                                            \
4411   do                                                                    \
4412     {                                                                   \
4413       switch (size)                                                     \
4414         {                                                               \
4415         case 0:                                                         \
4416           for (i = 0; i < (full ? 16 : 8); i++)                         \
4417             aarch64_set_vec_u8 (cpu, vd, i,                             \
4418                                 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4419                                 CMP                                     \
4420                                 aarch64_get_vec_##SOURCE##8 (cpu, vm, i) \
4421                                 ? -1 : 0);                              \
4422           return;                                                       \
4423         case 1:                                                         \
4424           for (i = 0; i < (full ? 8 : 4); i++)                          \
4425             aarch64_set_vec_u16 (cpu, vd, i,                            \
4426                                  aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4427                                  CMP                                    \
4428                                  aarch64_get_vec_##SOURCE##16 (cpu, vm, i) \
4429                                  ? -1 : 0);                             \
4430           return;                                                       \
4431         case 2:                                                         \
4432           for (i = 0; i < (full ? 4 : 2); i++)                          \
4433             aarch64_set_vec_u32 (cpu, vd, i, \
4434                                  aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4435                                  CMP                                    \
4436                                  aarch64_get_vec_##SOURCE##32 (cpu, vm, i) \
4437                                  ? -1 : 0);                             \
4438           return;                                                       \
4439         case 3:                                                         \
4440           if (! full)                                                   \
4441             HALT_UNALLOC;                                               \
4442           for (i = 0; i < 2; i++)                                       \
4443             aarch64_set_vec_u64 (cpu, vd, i, \
4444                                  aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4445                                  CMP                                    \
4446                                  aarch64_get_vec_##SOURCE##64 (cpu, vm, i) \
4447                                  ? -1ULL : 0);                          \
4448           return;                                                       \
4449         default:                                                        \
4450         HALT_UNALLOC;                                                   \
4451         }                                                               \
4452     }                                                                   \
4453   while (0)
4454
4455 #define VEC_CMP0(SOURCE, CMP)                                           \
4456   do                                                                    \
4457     {                                                                   \
4458       switch (size)                                                     \
4459         {                                                               \
4460         case 0:                                                         \
4461           for (i = 0; i < (full ? 16 : 8); i++)                         \
4462             aarch64_set_vec_u8 (cpu, vd, i,                             \
4463                                 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4464                                 CMP 0 ? -1 : 0);                        \
4465           return;                                                       \
4466         case 1:                                                         \
4467           for (i = 0; i < (full ? 8 : 4); i++)                          \
4468             aarch64_set_vec_u16 (cpu, vd, i,                            \
4469                                  aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4470                                  CMP 0 ? -1 : 0);                       \
4471           return;                                                       \
4472         case 2:                                                         \
4473           for (i = 0; i < (full ? 4 : 2); i++)                          \
4474             aarch64_set_vec_u32 (cpu, vd, i,                            \
4475                                  aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4476                                  CMP 0 ? -1 : 0);                       \
4477           return;                                                       \
4478         case 3:                                                         \
4479           if (! full)                                                   \
4480             HALT_UNALLOC;                                               \
4481           for (i = 0; i < 2; i++)                                       \
4482             aarch64_set_vec_u64 (cpu, vd, i,                            \
4483                                  aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4484                                  CMP 0 ? -1ULL : 0);                    \
4485           return;                                                       \
4486         default:                                                        \
4487           HALT_UNALLOC;                                                 \
4488         }                                                               \
4489     }                                                                   \
4490   while (0)
4491
4492 #define VEC_FCMP0(CMP)                                                  \
4493   do                                                                    \
4494     {                                                                   \
4495       if (vm != 0)                                                      \
4496         HALT_NYI;                                                       \
4497       if (uimm (aarch64_get_instr (cpu), 22, 22))                       \
4498         {                                                               \
4499           if (! full)                                                   \
4500             HALT_NYI;                                                   \
4501           for (i = 0; i < 2; i++)                                       \
4502             aarch64_set_vec_u64 (cpu, vd, i,                            \
4503                                  aarch64_get_vec_double (cpu, vn, i)    \
4504                                  CMP 0.0 ? -1 : 0);                     \
4505         }                                                               \
4506       else                                                              \
4507         {                                                               \
4508           for (i = 0; i < (full ? 4 : 2); i++)                          \
4509             aarch64_set_vec_u32 (cpu, vd, i,                            \
4510                                  aarch64_get_vec_float (cpu, vn, i)     \
4511                                  CMP 0.0 ? -1 : 0);                     \
4512         }                                                               \
4513       return;                                                           \
4514     }                                                                   \
4515   while (0)
4516
4517 #define VEC_FCMP(CMP)                                                   \
4518   do                                                                    \
4519     {                                                                   \
4520       if (uimm (aarch64_get_instr (cpu), 22, 22))                       \
4521         {                                                               \
4522           if (! full)                                                   \
4523             HALT_NYI;                                                   \
4524           for (i = 0; i < 2; i++)                                       \
4525             aarch64_set_vec_u64 (cpu, vd, i,                            \
4526                                  aarch64_get_vec_double (cpu, vn, i)    \
4527                                  CMP                                    \
4528                                  aarch64_get_vec_double (cpu, vm, i)    \
4529                                  ? -1 : 0);                             \
4530         }                                                               \
4531       else                                                              \
4532         {                                                               \
4533           for (i = 0; i < (full ? 4 : 2); i++)                          \
4534             aarch64_set_vec_u32 (cpu, vd, i,                            \
4535                                  aarch64_get_vec_float (cpu, vn, i)     \
4536                                  CMP                                    \
4537                                  aarch64_get_vec_float (cpu, vm, i)     \
4538                                  ? -1 : 0);                             \
4539         }                                                               \
4540       return;                                                           \
4541     }                                                                   \
4542   while (0)
4543
4544 static void
4545 do_vec_compare (sim_cpu *cpu)
4546 {
4547   /* instr[31]    = 0
4548      instr[30]    = half(0)/full(1)
4549      instr[29]    = part-of-comparison-type
4550      instr[28,24] = 0 1110
4551      instr[23,22] = size of integer compares: byte(00), half(01), word (10), long (11)
4552                     type of float compares: single (-0) / double (-1)
4553      instr[21]    = 1
4554      instr[20,16] = Vm or 00000 (compare vs 0)
4555      instr[15,10] = part-of-comparison-type
4556      instr[9,5]   = Vn
4557      instr[4.0]   = Vd.  */
4558
4559   int full = uimm (aarch64_get_instr (cpu), 30, 30);
4560   int size = uimm (aarch64_get_instr (cpu), 23, 22);
4561   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4562   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4563   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4564   unsigned i;
4565
4566   NYI_assert (28, 24, 0x0E);
4567   NYI_assert (21, 21, 1);
4568
4569   if ((uimm (aarch64_get_instr (cpu), 11, 11)
4570        && uimm (aarch64_get_instr (cpu), 14, 14))
4571       || ((uimm (aarch64_get_instr (cpu), 11, 11) == 0
4572            && uimm (aarch64_get_instr (cpu), 10, 10) == 0)))
4573     {
4574       /* A compare vs 0.  */
4575       if (vm != 0)
4576         {
4577           if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x2A)
4578             do_vec_maxv (cpu);
4579           else if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x32
4580                    || uimm (aarch64_get_instr (cpu), 15, 10) == 0x3E)
4581             do_vec_fminmaxV (cpu);
4582           else if (uimm (aarch64_get_instr (cpu), 29, 23) == 0x1C
4583                    && uimm (aarch64_get_instr (cpu), 21, 10) == 0x876)
4584             do_vec_SCVTF (cpu);
4585           else
4586             HALT_NYI;
4587           return;
4588         }
4589     }
4590
4591   if (uimm (aarch64_get_instr (cpu), 14, 14))
4592     {
4593       /* A floating point compare.  */
4594       unsigned decode = (uimm (aarch64_get_instr (cpu), 29, 29) << 5)
4595         | (uimm (aarch64_get_instr (cpu), 23, 23) << 4)
4596         | uimm (aarch64_get_instr (cpu), 13, 10);
4597
4598       NYI_assert (15, 15, 1);
4599
4600       switch (decode)
4601         {
4602         case /* 0b010010: GT#0 */ 0x12: VEC_FCMP0 (>);
4603         case /* 0b110010: GE#0 */ 0x32: VEC_FCMP0 (>=);
4604         case /* 0b010110: EQ#0 */ 0x16: VEC_FCMP0 (==);
4605         case /* 0b110110: LE#0 */ 0x36: VEC_FCMP0 (<=);
4606         case /* 0b011010: LT#0 */ 0x1A: VEC_FCMP0 (<);
4607         case /* 0b111001: GT */   0x39: VEC_FCMP  (>);
4608         case /* 0b101001: GE */   0x29: VEC_FCMP  (>=);
4609         case /* 0b001001: EQ */   0x09: VEC_FCMP  (==);
4610
4611         default:
4612           HALT_NYI;
4613         }
4614     }
4615   else
4616     {
4617       unsigned decode = (uimm (aarch64_get_instr (cpu), 29, 29) << 6)
4618         | uimm (aarch64_get_instr (cpu), 15, 10);
4619
4620       switch (decode)
4621         {
4622         case 0x0D: /* 0001101 GT */     VEC_CMP  (s, > );
4623         case 0x0F: /* 0001111 GE */     VEC_CMP  (s, >= );
4624         case 0x22: /* 0100010 GT #0 */  VEC_CMP0 (s, > );
4625         case 0x26: /* 0100110 EQ #0 */  VEC_CMP0 (s, == );
4626         case 0x2A: /* 0101010 LT #0 */  VEC_CMP0 (s, < );
4627         case 0x4D: /* 1001101 HI */     VEC_CMP  (u, > );
4628         case 0x4F: /* 1001111 HS */     VEC_CMP  (u, >= );
4629         case 0x62: /* 1100010 GE #0 */  VEC_CMP0 (s, >= );
4630         case 0x63: /* 1100011 EQ */     VEC_CMP  (u, == );
4631         case 0x66: /* 1100110 LE #0 */  VEC_CMP0 (s, <= );
4632         default:
4633           if (vm == 0)
4634             HALT_NYI;
4635           do_vec_maxv (cpu);
4636         }
4637     }
4638 }
4639
4640 static void
4641 do_vec_SSHL (sim_cpu *cpu)
4642 {
4643   /* instr[31]    = 0
4644      instr[30]    = first part (0)/ second part (1)
4645      instr[29,24] = 00 1110
4646      instr[23,22] = size: byte(00), half(01), word (10), long (11)
4647      instr[21]    = 1
4648      instr[20,16] = Vm
4649      instr[15,10] = 0100 01
4650      instr[9,5]   = Vn
4651      instr[4,0]   = Vd.  */
4652
4653   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4654   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4655   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4656   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4657   unsigned i;
4658
4659   NYI_assert (29, 24, 0x0E);
4660   NYI_assert (21, 21, 1);
4661   NYI_assert (15, 10, 0x11);
4662
4663   /* FIXME: What is a signed shift left in this context ?.  */
4664
4665   switch (uimm (aarch64_get_instr (cpu), 23, 22))
4666     {
4667     case 0:
4668       for (i = 0; i < (full ? 16 : 8); i++)
4669         aarch64_set_vec_s8 (cpu, vd, i, aarch64_get_vec_s8 (cpu, vn, i)
4670                             << aarch64_get_vec_s8 (cpu, vm, i));
4671       return;
4672
4673     case 1:
4674       for (i = 0; i < (full ? 8 : 4); i++)
4675         aarch64_set_vec_s16 (cpu, vd, i, aarch64_get_vec_s16 (cpu, vn, i)
4676                              << aarch64_get_vec_s16 (cpu, vm, i));
4677       return;
4678
4679     case 2:
4680       for (i = 0; i < (full ? 4 : 2); i++)
4681         aarch64_set_vec_s32 (cpu, vd, i, aarch64_get_vec_s32 (cpu, vn, i)
4682                              << aarch64_get_vec_s32 (cpu, vm, i));
4683       return;
4684
4685     case 3:
4686       if (! full)
4687         HALT_UNALLOC;
4688       for (i = 0; i < 2; i++)
4689         aarch64_set_vec_s64 (cpu, vd, i, aarch64_get_vec_s64 (cpu, vn, i)
4690                              << aarch64_get_vec_s64 (cpu, vm, i));
4691       return;
4692
4693     default:
4694       HALT_NYI;
4695     }
4696 }
4697
4698 static void
4699 do_vec_USHL (sim_cpu *cpu)
4700 {
4701   /* instr[31]    = 0
4702      instr[30]    = first part (0)/ second part (1)
4703      instr[29,24] = 10 1110
4704      instr[23,22] = size: byte(00), half(01), word (10), long (11)
4705      instr[21]    = 1
4706      instr[20,16] = Vm
4707      instr[15,10] = 0100 01
4708      instr[9,5]   = Vn
4709      instr[4,0]   = Vd  */
4710
4711   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4712   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4713   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4714   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4715   unsigned i;
4716
4717   NYI_assert (29, 24, 0x2E);
4718   NYI_assert (15, 10, 0x11);
4719
4720   switch (uimm (aarch64_get_instr (cpu), 23, 22))
4721     {
4722     case 0:
4723       for (i = 0; i < (full ? 16 : 8); i++)
4724         aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vn, i)
4725                             << aarch64_get_vec_u8 (cpu, vm, i));
4726       return;
4727
4728     case 1:
4729       for (i = 0; i < (full ? 8 : 4); i++)
4730         aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vn, i)
4731                              << aarch64_get_vec_u16 (cpu, vm, i));
4732       return;
4733
4734     case 2:
4735       for (i = 0; i < (full ? 4 : 2); i++)
4736         aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vn, i)
4737                              << aarch64_get_vec_u32 (cpu, vm, i));
4738       return;
4739
4740     case 3:
4741       if (! full)
4742         HALT_UNALLOC;
4743       for (i = 0; i < 2; i++)
4744         aarch64_set_vec_u64 (cpu, vd, i, aarch64_get_vec_u64 (cpu, vn, i)
4745                              << aarch64_get_vec_u64 (cpu, vm, i));
4746       return;
4747
4748     default:
4749       HALT_NYI;
4750     }
4751 }
4752
4753 static void
4754 do_vec_FMLA (sim_cpu *cpu)
4755 {
4756   /* instr[31]    = 0
4757      instr[30]    = full/half selector
4758      instr[29,23] = 0011100
4759      instr[22]    = size: 0=>float, 1=>double
4760      instr[21]    = 1
4761      instr[20,16] = Vn
4762      instr[15,10] = 1100 11
4763      instr[9,5]   = Vm
4764      instr[4.0]   = Vd.  */
4765
4766   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4767   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4768   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4769   unsigned i;
4770   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
4771
4772   NYI_assert (29, 23, 0x1C);
4773   NYI_assert (21, 21, 1);
4774   NYI_assert (15, 10, 0x33);
4775
4776   if (uimm (aarch64_get_instr (cpu), 22, 22))
4777     {
4778       if (! full)
4779         HALT_UNALLOC;
4780       for (i = 0; i < 2; i++)
4781         aarch64_set_vec_double (cpu, vd, i,
4782                                 aarch64_get_vec_double (cpu, vn, i) *
4783                                 aarch64_get_vec_double (cpu, vm, i) +
4784                                 aarch64_get_vec_double (cpu, vd, i));
4785     }
4786   else
4787     {
4788       for (i = 0; i < (full ? 4 : 2); i++)
4789         aarch64_set_vec_float (cpu, vd, i,
4790                                aarch64_get_vec_float (cpu, vn, i) *
4791                                aarch64_get_vec_float (cpu, vm, i) +
4792                                aarch64_get_vec_float (cpu, vd, i));
4793     }
4794 }
4795
4796 static void
4797 do_vec_max (sim_cpu *cpu)
4798 {
4799   /* instr[31]    = 0
4800      instr[30]    = full/half selector
4801      instr[29]    = SMAX (0) / UMAX (1)
4802      instr[28,24] = 0 1110
4803      instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
4804      instr[21]    = 1
4805      instr[20,16] = Vn
4806      instr[15,10] = 0110 01
4807      instr[9,5]   = Vm
4808      instr[4.0]   = Vd.  */
4809
4810   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4811   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4812   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4813   unsigned i;
4814   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
4815
4816   NYI_assert (28, 24, 0x0E);
4817   NYI_assert (21, 21, 1);
4818   NYI_assert (15, 10, 0x19);
4819
4820   if (uimm (aarch64_get_instr (cpu), 29, 29))
4821     {
4822       switch (uimm (aarch64_get_instr (cpu), 23, 22))
4823         {
4824         case 0:
4825           for (i = 0; i < (full ? 16 : 8); i++)
4826             aarch64_set_vec_u8 (cpu, vd, i,
4827                                 aarch64_get_vec_u8 (cpu, vn, i)
4828                                 > aarch64_get_vec_u8 (cpu, vm, i)
4829                                 ? aarch64_get_vec_u8 (cpu, vn, i)
4830                                 : aarch64_get_vec_u8 (cpu, vm, i));
4831           return;
4832
4833         case 1:
4834           for (i = 0; i < (full ? 8 : 4); i++)
4835             aarch64_set_vec_u16 (cpu, vd, i,
4836                                  aarch64_get_vec_u16 (cpu, vn, i)
4837                                  > aarch64_get_vec_u16 (cpu, vm, i)
4838                                  ? aarch64_get_vec_u16 (cpu, vn, i)
4839                                  : aarch64_get_vec_u16 (cpu, vm, i));
4840           return;
4841
4842         case 2:
4843           for (i = 0; i < (full ? 4 : 2); i++)
4844             aarch64_set_vec_u32 (cpu, vd, i,
4845                                  aarch64_get_vec_u32 (cpu, vn, i)
4846                                  > aarch64_get_vec_u32 (cpu, vm, i)
4847                                  ? aarch64_get_vec_u32 (cpu, vn, i)
4848                                  : aarch64_get_vec_u32 (cpu, vm, i));
4849           return;
4850
4851         default:
4852         case 3:
4853           HALT_UNALLOC;
4854         }
4855     }
4856   else
4857     {
4858       switch (uimm (aarch64_get_instr (cpu), 23, 22))
4859         {
4860         case 0:
4861           for (i = 0; i < (full ? 16 : 8); i++)
4862             aarch64_set_vec_s8 (cpu, vd, i,
4863                                 aarch64_get_vec_s8 (cpu, vn, i)
4864                                 > aarch64_get_vec_s8 (cpu, vm, i)
4865                                 ? aarch64_get_vec_s8 (cpu, vn, i)
4866                                 : aarch64_get_vec_s8 (cpu, vm, i));
4867           return;
4868
4869         case 1:
4870           for (i = 0; i < (full ? 8 : 4); i++)
4871             aarch64_set_vec_s16 (cpu, vd, i,
4872                                  aarch64_get_vec_s16 (cpu, vn, i)
4873                                  > aarch64_get_vec_s16 (cpu, vm, i)
4874                                  ? aarch64_get_vec_s16 (cpu, vn, i)
4875                                  : aarch64_get_vec_s16 (cpu, vm, i));
4876           return;
4877
4878         case 2:
4879           for (i = 0; i < (full ? 4 : 2); i++)
4880             aarch64_set_vec_s32 (cpu, vd, i,
4881                                  aarch64_get_vec_s32 (cpu, vn, i)
4882                                  > aarch64_get_vec_s32 (cpu, vm, i)
4883                                  ? aarch64_get_vec_s32 (cpu, vn, i)
4884                                  : aarch64_get_vec_s32 (cpu, vm, i));
4885           return;
4886
4887         default:
4888         case 3:
4889           HALT_UNALLOC;
4890         }
4891     }
4892 }
4893
4894 static void
4895 do_vec_min (sim_cpu *cpu)
4896 {
4897   /* instr[31]    = 0
4898      instr[30]    = full/half selector
4899      instr[29]    = SMIN (0) / UMIN (1)
4900      instr[28,24] = 0 1110
4901      instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
4902      instr[21]    = 1
4903      instr[20,16] = Vn
4904      instr[15,10] = 0110 11
4905      instr[9,5]   = Vm
4906      instr[4.0]   = Vd.  */
4907
4908   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4909   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4910   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4911   unsigned i;
4912   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
4913
4914   NYI_assert (28, 24, 0x0E);
4915   NYI_assert (21, 21, 1);
4916   NYI_assert (15, 10, 0x1B);
4917
4918   if (uimm (aarch64_get_instr (cpu), 29, 29))
4919     {
4920       switch (uimm (aarch64_get_instr (cpu), 23, 22))
4921         {
4922         case 0:
4923           for (i = 0; i < (full ? 16 : 8); i++)
4924             aarch64_set_vec_u8 (cpu, vd, i,
4925                                 aarch64_get_vec_u8 (cpu, vn, i)
4926                                 < aarch64_get_vec_u8 (cpu, vm, i)
4927                                 ? aarch64_get_vec_u8 (cpu, vn, i)
4928                                 : aarch64_get_vec_u8 (cpu, vm, i));
4929           return;
4930
4931         case 1:
4932           for (i = 0; i < (full ? 8 : 4); i++)
4933             aarch64_set_vec_u16 (cpu, vd, i,
4934                                  aarch64_get_vec_u16 (cpu, vn, i)
4935                                  < aarch64_get_vec_u16 (cpu, vm, i)
4936                                  ? aarch64_get_vec_u16 (cpu, vn, i)
4937                                  : aarch64_get_vec_u16 (cpu, vm, i));
4938           return;
4939
4940         case 2:
4941           for (i = 0; i < (full ? 4 : 2); i++)
4942             aarch64_set_vec_u32 (cpu, vd, i,
4943                                  aarch64_get_vec_u32 (cpu, vn, i)
4944                                  < aarch64_get_vec_u32 (cpu, vm, i)
4945                                  ? aarch64_get_vec_u32 (cpu, vn, i)
4946                                  : aarch64_get_vec_u32 (cpu, vm, i));
4947           return;
4948
4949         default:
4950         case 3:
4951           HALT_UNALLOC;
4952         }
4953     }
4954   else
4955     {
4956       switch (uimm (aarch64_get_instr (cpu), 23, 22))
4957         {
4958         case 0:
4959           for (i = 0; i < (full ? 16 : 8); i++)
4960             aarch64_set_vec_s8 (cpu, vd, i,
4961                                 aarch64_get_vec_s8 (cpu, vn, i)
4962                                 < aarch64_get_vec_s8 (cpu, vm, i)
4963                                 ? aarch64_get_vec_s8 (cpu, vn, i)
4964                                 : aarch64_get_vec_s8 (cpu, vm, i));
4965           return;
4966
4967         case 1:
4968           for (i = 0; i < (full ? 8 : 4); i++)
4969             aarch64_set_vec_s16 (cpu, vd, i,
4970                                  aarch64_get_vec_s16 (cpu, vn, i)
4971                                  < aarch64_get_vec_s16 (cpu, vm, i)
4972                                  ? aarch64_get_vec_s16 (cpu, vn, i)
4973                                  : aarch64_get_vec_s16 (cpu, vm, i));
4974           return;
4975
4976         case 2:
4977           for (i = 0; i < (full ? 4 : 2); i++)
4978             aarch64_set_vec_s32 (cpu, vd, i,
4979                                  aarch64_get_vec_s32 (cpu, vn, i)
4980                                  < aarch64_get_vec_s32 (cpu, vm, i)
4981                                  ? aarch64_get_vec_s32 (cpu, vn, i)
4982                                  : aarch64_get_vec_s32 (cpu, vm, i));
4983           return;
4984
4985         default:
4986         case 3:
4987           HALT_UNALLOC;
4988         }
4989     }
4990 }
4991
4992 static void
4993 do_vec_sub_long (sim_cpu *cpu)
4994 {
4995   /* instr[31]    = 0
4996      instr[30]    = lower (0) / upper (1)
4997      instr[29]    = signed (0) / unsigned (1)
4998      instr[28,24] = 0 1110
4999      instr[23,22] = size: bytes (00), half (01), word (10)
5000      instr[21]    = 1
5001      insrt[20,16] = Vm
5002      instr[15,10] = 0010 00
5003      instr[9,5]   = Vn
5004      instr[4,0]   = V dest.  */
5005
5006   unsigned size = uimm (aarch64_get_instr (cpu), 23, 22);
5007   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5008   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5009   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5010   unsigned bias = 0;
5011   unsigned i;
5012
5013   NYI_assert (28, 24, 0x0E);
5014   NYI_assert (21, 21, 1);
5015   NYI_assert (15, 10, 0x08);
5016
5017   if (size == 3)
5018     HALT_UNALLOC;
5019
5020   switch (uimm (aarch64_get_instr (cpu), 30, 29))
5021     {
5022     case 2: /* SSUBL2.  */
5023       bias = 2;
5024     case 0: /* SSUBL.  */
5025       switch (size)
5026         {
5027         case 0:
5028           bias *= 3;
5029           for (i = 0; i < 8; i++)
5030             aarch64_set_vec_s16 (cpu, vd, i,
5031                                  aarch64_get_vec_s8 (cpu, vn, i + bias)
5032                                  - aarch64_get_vec_s8 (cpu, vm, i + bias));
5033           break;
5034
5035         case 1:
5036           bias *= 2;
5037           for (i = 0; i < 4; i++)
5038             aarch64_set_vec_s32 (cpu, vd, i,
5039                                  aarch64_get_vec_s16 (cpu, vn, i + bias)
5040                                  - aarch64_get_vec_s16 (cpu, vm, i + bias));
5041           break;
5042
5043         case 2:
5044           for (i = 0; i < 2; i++)
5045             aarch64_set_vec_s64 (cpu, vd, i,
5046                                  aarch64_get_vec_s32 (cpu, vn, i + bias)
5047                                  - aarch64_get_vec_s32 (cpu, vm, i + bias));
5048           break;
5049
5050         default:
5051           HALT_UNALLOC;
5052         }
5053       break;
5054
5055     case 3: /* USUBL2.  */
5056       bias = 2;
5057     case 1: /* USUBL.  */
5058       switch (size)
5059         {
5060         case 0:
5061           bias *= 3;
5062           for (i = 0; i < 8; i++)
5063             aarch64_set_vec_u16 (cpu, vd, i,
5064                                  aarch64_get_vec_u8 (cpu, vn, i + bias)
5065                                  - aarch64_get_vec_u8 (cpu, vm, i + bias));
5066           break;
5067
5068         case 1:
5069           bias *= 2;
5070           for (i = 0; i < 4; i++)
5071             aarch64_set_vec_u32 (cpu, vd, i,
5072                                  aarch64_get_vec_u16 (cpu, vn, i + bias)
5073                                  - aarch64_get_vec_u16 (cpu, vm, i + bias));
5074           break;
5075
5076         case 2:
5077           for (i = 0; i < 2; i++)
5078             aarch64_set_vec_u64 (cpu, vd, i,
5079                                  aarch64_get_vec_u32 (cpu, vn, i + bias)
5080                                  - aarch64_get_vec_u32 (cpu, vm, i + bias));
5081           break;
5082
5083         default:
5084           HALT_UNALLOC;
5085         }
5086       break;
5087     }
5088 }
5089
5090 static void
5091 do_vec_ADDP (sim_cpu *cpu)
5092 {
5093   /* instr[31]    = 0
5094      instr[30]    = half(0)/full(1)
5095      instr[29,24] = 00 1110
5096      instr[23,22] = size: bytes (00), half (01), word (10), long (11)
5097      instr[21]    = 1
5098      insrt[20,16] = Vm
5099      instr[15,10] = 1011 11
5100      instr[9,5]   = Vn
5101      instr[4,0]   = V dest.  */
5102
5103   FRegister copy_vn;
5104   FRegister copy_vm;
5105   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5106   unsigned size = uimm (aarch64_get_instr (cpu), 23, 22);
5107   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5108   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5109   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5110   unsigned i, range;
5111
5112   NYI_assert (29, 24, 0x0E);
5113   NYI_assert (21, 21, 1);
5114   NYI_assert (15, 10, 0x2F);
5115
5116   /* Make copies of the source registers in case vd == vn/vm.  */
5117   copy_vn = cpu->fr[vn];
5118   copy_vm = cpu->fr[vm];
5119
5120   switch (size)
5121     {
5122     case 0:
5123       range = full ? 8 : 4;
5124       for (i = 0; i < range; i++)
5125         {
5126           aarch64_set_vec_u8 (cpu, vd, i,
5127                               copy_vn.b[i * 2] + copy_vn.b[i * 2 + 1]);
5128           aarch64_set_vec_u8 (cpu, vd, i + range,
5129                               copy_vm.b[i * 2] + copy_vm.b[i * 2 + 1]);
5130         }
5131       return;
5132
5133     case 1:
5134       range = full ? 4 : 2;
5135       for (i = 0; i < range; i++)
5136         {
5137           aarch64_set_vec_u16 (cpu, vd, i,
5138                                copy_vn.h[i * 2] + copy_vn.h[i * 2 + 1]);
5139           aarch64_set_vec_u16 (cpu, vd, i + range,
5140                                copy_vm.h[i * 2] + copy_vm.h[i * 2 + 1]);
5141         }
5142       return;
5143
5144     case 2:
5145       range = full ? 2 : 1;
5146       for (i = 0; i < range; i++)
5147         {
5148           aarch64_set_vec_u32 (cpu, vd, i,
5149                                copy_vn.w[i * 2] + copy_vn.w[i * 2 + 1]);
5150           aarch64_set_vec_u32 (cpu, vd, i + range,
5151                                copy_vm.w[i * 2] + copy_vm.w[i * 2 + 1]);
5152         }
5153       return;
5154
5155     case 3:
5156       if (! full)
5157         HALT_UNALLOC;
5158       aarch64_set_vec_u64 (cpu, vd, 0, copy_vn.v[0] + copy_vn.v[1]);
5159       aarch64_set_vec_u64 (cpu, vd, 1, copy_vm.v[0] + copy_vm.v[1]);
5160       return;
5161
5162     default:
5163       HALT_NYI;
5164     }
5165 }
5166
5167 static void
5168 do_vec_UMOV (sim_cpu *cpu)
5169 {
5170   /* instr[31]    = 0
5171      instr[30]    = 32-bit(0)/64-bit(1)
5172      instr[29,21] = 00 1110 000
5173      insrt[20,16] = size & index
5174      instr[15,10] = 0011 11
5175      instr[9,5]   = V source
5176      instr[4,0]   = R dest.  */
5177
5178   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5179   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
5180   unsigned index;
5181
5182   NYI_assert (29, 21, 0x070);
5183   NYI_assert (15, 10, 0x0F);
5184
5185   if (uimm (aarch64_get_instr (cpu), 16, 16))
5186     {
5187       /* Byte transfer.  */
5188       index = uimm (aarch64_get_instr (cpu), 20, 17);
5189       aarch64_set_reg_u64 (cpu, rd, NO_SP,
5190                            aarch64_get_vec_u8 (cpu, vs, index));
5191     }
5192   else if (uimm (aarch64_get_instr (cpu), 17, 17))
5193     {
5194       index = uimm (aarch64_get_instr (cpu), 20, 18);
5195       aarch64_set_reg_u64 (cpu, rd, NO_SP,
5196                            aarch64_get_vec_u16 (cpu, vs, index));
5197     }
5198   else if (uimm (aarch64_get_instr (cpu), 18, 18))
5199     {
5200       index = uimm (aarch64_get_instr (cpu), 20, 19);
5201       aarch64_set_reg_u64 (cpu, rd, NO_SP,
5202                            aarch64_get_vec_u32 (cpu, vs, index));
5203     }
5204   else
5205     {
5206       if (uimm (aarch64_get_instr (cpu), 30, 30) != 1)
5207         HALT_UNALLOC;
5208
5209       index = uimm (aarch64_get_instr (cpu), 20, 20);
5210       aarch64_set_reg_u64 (cpu, rd, NO_SP,
5211                            aarch64_get_vec_u64 (cpu, vs, index));
5212     }
5213 }
5214
5215 static void
5216 do_vec_FABS (sim_cpu *cpu)
5217 {
5218   /* instr[31]    = 0
5219      instr[30]    = half(0)/full(1)
5220      instr[29,23] = 00 1110 1
5221      instr[22]    = float(0)/double(1)
5222      instr[21,16] = 10 0000
5223      instr[15,10] = 1111 10
5224      instr[9,5]   = Vn
5225      instr[4,0]   = Vd.  */
5226
5227   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5228   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5229   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5230   unsigned i;
5231
5232   NYI_assert (29, 23, 0x1D);
5233   NYI_assert (21, 10, 0x83E);
5234
5235   if (uimm (aarch64_get_instr (cpu), 22, 22))
5236     {
5237       if (! full)
5238         HALT_NYI;
5239
5240       for (i = 0; i < 2; i++)
5241         aarch64_set_vec_double (cpu, vd, i,
5242                                 fabs (aarch64_get_vec_double (cpu, vn, i)));
5243     }
5244   else
5245     {
5246       for (i = 0; i < (full ? 4 : 2); i++)
5247         aarch64_set_vec_float (cpu, vd, i,
5248                                fabsf (aarch64_get_vec_float (cpu, vn, i)));
5249     }
5250 }
5251
5252 static void
5253 do_vec_FCVTZS (sim_cpu *cpu)
5254 {
5255   /* instr[31]    = 0
5256      instr[30]    = half (0) / all (1)
5257      instr[29,23] = 00 1110 1
5258      instr[22]    = single (0) / double (1)
5259      instr[21,10] = 10 0001 1011 10
5260      instr[9,5]   = Rn
5261      instr[4,0]   = Rd.  */
5262
5263   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
5264   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
5265   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5266   unsigned i;
5267
5268   NYI_assert (31, 31, 0);
5269   NYI_assert (29, 23, 0x1D);
5270   NYI_assert (21, 10, 0x86E);
5271
5272   if (uimm (aarch64_get_instr (cpu), 22, 22))
5273     {
5274       if (! full)
5275         HALT_UNALLOC;
5276
5277       for (i = 0; i < 2; i++)
5278         aarch64_set_vec_s64 (cpu, rd, i,
5279                              (int64_t) aarch64_get_vec_double (cpu, rn, i));
5280     }
5281   else
5282     for (i = 0; i < (full ? 4 : 2); i++)
5283       aarch64_set_vec_s32 (cpu, rd, i,
5284                            (int32_t) aarch64_get_vec_float (cpu, rn, i));
5285 }
5286
5287 static void
5288 do_vec_op1 (sim_cpu *cpu)
5289 {
5290   /* instr[31]    = 0
5291      instr[30]    = half/full
5292      instr[29,24] = 00 1110
5293      instr[23,21] = ???
5294      instr[20,16] = Vm
5295      instr[15,10] = sub-opcode
5296      instr[9,5]   = Vn
5297      instr[4,0]   = Vd  */
5298   NYI_assert (29, 24, 0x0E);
5299
5300   if (uimm (aarch64_get_instr (cpu), 21, 21) == 0)
5301     {
5302       if (uimm (aarch64_get_instr (cpu), 23, 22) == 0)
5303         {
5304           if (uimm (aarch64_get_instr (cpu), 30, 30) == 1
5305               && uimm (aarch64_get_instr (cpu), 17, 14) == 0
5306               && uimm (aarch64_get_instr (cpu), 12, 10) == 7)
5307             return do_vec_ins_2 (cpu);
5308
5309           switch (uimm (aarch64_get_instr (cpu), 15, 10))
5310             {
5311             case 0x01: do_vec_DUP_vector_into_vector (cpu); return;
5312             case 0x03: do_vec_DUP_scalar_into_vector (cpu); return;
5313             case 0x07: do_vec_INS (cpu); return;
5314             case 0x0A: do_vec_TRN (cpu); return;
5315
5316             case 0x0F:
5317               if (uimm (aarch64_get_instr (cpu), 17, 16) == 0)
5318                 {
5319                   do_vec_MOV_into_scalar (cpu);
5320                   return;
5321                 }
5322               break;
5323
5324             case 0x00:
5325             case 0x08:
5326             case 0x10:
5327             case 0x18:
5328               do_vec_TBL (cpu); return;
5329
5330             case 0x06:
5331             case 0x16:
5332               do_vec_UZP (cpu); return;
5333
5334             case 0x0E:
5335             case 0x1E:
5336               do_vec_ZIP (cpu); return;
5337
5338             default:
5339               HALT_NYI;
5340             }
5341         }
5342
5343       switch (uimm (aarch64_get_instr (cpu), 13, 10))
5344         {
5345         case 0x6: do_vec_UZP (cpu); return;
5346         case 0xE: do_vec_ZIP (cpu); return;
5347         case 0xA: do_vec_TRN (cpu); return;
5348         case 0xF: do_vec_UMOV (cpu); return;
5349         default:  HALT_NYI;
5350         }
5351     }
5352
5353   switch (uimm (aarch64_get_instr (cpu), 15, 10))
5354     {
5355     case 0x07:
5356       switch (uimm (aarch64_get_instr (cpu), 23, 21))
5357         {
5358         case 1: do_vec_AND (cpu); return;
5359         case 3: do_vec_BIC (cpu); return;
5360         case 5: do_vec_ORR (cpu); return;
5361         case 7: do_vec_ORN (cpu); return;
5362         default: HALT_NYI;
5363         }
5364
5365     case 0x08: do_vec_sub_long (cpu); return;
5366     case 0x0a: do_vec_XTN (cpu); return;
5367     case 0x11: do_vec_SSHL (cpu); return;
5368     case 0x19: do_vec_max (cpu); return;
5369     case 0x1B: do_vec_min (cpu); return;
5370     case 0x21: do_vec_add (cpu); return;
5371     case 0x25: do_vec_MLA (cpu); return;
5372     case 0x27: do_vec_mul (cpu); return;
5373     case 0x2F: do_vec_ADDP (cpu); return;
5374     case 0x30: do_vec_mull (cpu); return;
5375     case 0x33: do_vec_FMLA (cpu); return;
5376     case 0x35: do_vec_fadd (cpu); return;
5377
5378     case 0x2E:
5379       switch (uimm (aarch64_get_instr (cpu), 20, 16))
5380         {
5381         case 0x00: do_vec_ABS (cpu); return;
5382         case 0x01: do_vec_FCVTZS (cpu); return;
5383         case 0x11: do_vec_ADDV (cpu); return;
5384         default: HALT_NYI;
5385         }
5386
5387     case 0x31:
5388     case 0x3B:
5389       do_vec_Fminmax (cpu); return;
5390
5391     case 0x0D:
5392     case 0x0F:
5393     case 0x22:
5394     case 0x23:
5395     case 0x26:
5396     case 0x2A:
5397     case 0x32:
5398     case 0x36:
5399     case 0x39:
5400     case 0x3A:
5401       do_vec_compare (cpu); return;
5402
5403     case 0x3E:
5404       do_vec_FABS (cpu); return;
5405
5406     default:
5407       HALT_NYI;
5408     }
5409 }
5410
5411 static void
5412 do_vec_xtl (sim_cpu *cpu)
5413 {
5414   /* instr[31]    = 0
5415      instr[30,29] = SXTL (00), UXTL (01), SXTL2 (10), UXTL2 (11)
5416      instr[28,22] = 0 1111 00
5417      instr[21,16] = size & shift (USHLL, SSHLL, USHLL2, SSHLL2)
5418      instr[15,10] = 1010 01
5419      instr[9,5]   = V source
5420      instr[4,0]   = V dest.  */
5421
5422   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5423   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5424   unsigned i, shift, bias = 0;
5425
5426   NYI_assert (28, 22, 0x3C);
5427   NYI_assert (15, 10, 0x29);
5428
5429   switch (uimm (aarch64_get_instr (cpu), 30, 29))
5430     {
5431     case 2: /* SXTL2, SSHLL2.  */
5432       bias = 2;
5433     case 0: /* SXTL, SSHLL.  */
5434       if (uimm (aarch64_get_instr (cpu), 21, 21))
5435         {
5436           shift = uimm (aarch64_get_instr (cpu), 20, 16);
5437           aarch64_set_vec_s64
5438             (cpu, vd, 0, aarch64_get_vec_s32 (cpu, vs, bias) << shift);
5439           aarch64_set_vec_s64
5440             (cpu, vd, 1, aarch64_get_vec_s32 (cpu, vs, bias + 1) << shift);
5441         }
5442       else if (uimm (aarch64_get_instr (cpu), 20, 20))
5443         {
5444           shift = uimm (aarch64_get_instr (cpu), 19, 16);
5445           bias *= 2;
5446           for (i = 0; i < 4; i++)
5447             aarch64_set_vec_s32
5448               (cpu, vd, i, aarch64_get_vec_s16 (cpu, vs, i + bias) << shift);
5449         }
5450       else
5451         {
5452           NYI_assert (19, 19, 1);
5453
5454           shift = uimm (aarch64_get_instr (cpu), 18, 16);
5455           bias *= 3;
5456           for (i = 0; i < 8; i++)
5457             aarch64_set_vec_s16
5458               (cpu, vd, i, aarch64_get_vec_s8 (cpu, vs, i + bias) << shift);
5459         }
5460       return;
5461
5462     case 3: /* UXTL2, USHLL2.  */
5463       bias = 2;
5464     case 1: /* UXTL, USHLL.  */
5465       if (uimm (aarch64_get_instr (cpu), 21, 21))
5466         {
5467           shift = uimm (aarch64_get_instr (cpu), 20, 16);
5468           aarch64_set_vec_u64
5469             (cpu, vd, 0, aarch64_get_vec_u32 (cpu, vs, bias) << shift);
5470           aarch64_set_vec_u64
5471             (cpu, vd, 1, aarch64_get_vec_u32 (cpu, vs, bias + 1) << shift);
5472         }
5473       else if (uimm (aarch64_get_instr (cpu), 20, 20))
5474         {
5475           shift = uimm (aarch64_get_instr (cpu), 19, 16);
5476           bias *= 2;
5477           for (i = 0; i < 4; i++)
5478             aarch64_set_vec_u32
5479               (cpu, vd, i, aarch64_get_vec_u16 (cpu, vs, i + bias) << shift);
5480         }
5481       else
5482         {
5483           NYI_assert (19, 19, 1);
5484
5485           shift = uimm (aarch64_get_instr (cpu), 18, 16);
5486           bias *= 3;
5487           for (i = 0; i < 8; i++)
5488             aarch64_set_vec_u16
5489               (cpu, vd, i, aarch64_get_vec_u8 (cpu, vs, i + bias) << shift);
5490         }
5491       return;
5492
5493     default:
5494       HALT_NYI;
5495     }
5496 }
5497
5498 static void
5499 do_vec_SHL (sim_cpu *cpu)
5500 {
5501   /* instr [31]    = 0
5502      instr [30]    = half(0)/full(1)
5503      instr [29,23] = 001 1110
5504      instr [22,16] = size and shift amount
5505      instr [15,10] = 01 0101
5506      instr [9, 5]  = Vs
5507      instr [4, 0]  = Vd.  */
5508
5509   int shift;
5510   int full = uimm (aarch64_get_instr (cpu), 30, 30);
5511   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5512   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5513   unsigned i;
5514
5515   NYI_assert (29, 23, 0x1E);
5516   NYI_assert (15, 10, 0x15);
5517
5518   if (uimm (aarch64_get_instr (cpu), 22, 22))
5519     {
5520       shift = uimm (aarch64_get_instr (cpu), 21, 16) - 1;
5521
5522       if (full == 0)
5523         HALT_UNALLOC;
5524
5525       for (i = 0; i < 2; i++)
5526         {
5527           uint64_t val = aarch64_get_vec_u64 (cpu, vs, i);
5528           aarch64_set_vec_u64 (cpu, vd, i, val << shift);
5529         }
5530
5531       return;
5532     }
5533
5534   if (uimm (aarch64_get_instr (cpu), 21, 21))
5535     {
5536       shift = uimm (aarch64_get_instr (cpu), 20, 16) - 1;
5537
5538       for (i = 0; i < (full ? 4 : 2); i++)
5539         {
5540           uint32_t val = aarch64_get_vec_u32 (cpu, vs, i);
5541           aarch64_set_vec_u32 (cpu, vd, i, val << shift);
5542         }
5543
5544       return;
5545     }
5546
5547   if (uimm (aarch64_get_instr (cpu), 20, 20))
5548     {
5549       shift = uimm (aarch64_get_instr (cpu), 19, 16) - 1;
5550
5551       for (i = 0; i < (full ? 8 : 4); i++)
5552         {
5553           uint16_t val = aarch64_get_vec_u16 (cpu, vs, i);
5554           aarch64_set_vec_u16 (cpu, vd, i, val << shift);
5555         }
5556
5557       return;
5558     }
5559
5560   if (uimm (aarch64_get_instr (cpu), 19, 19) == 0)
5561     HALT_UNALLOC;
5562
5563   shift = uimm (aarch64_get_instr (cpu), 18, 16) - 1;
5564
5565   for (i = 0; i < (full ? 16 : 8); i++)
5566     {
5567       uint8_t val = aarch64_get_vec_u8 (cpu, vs, i);
5568       aarch64_set_vec_u8 (cpu, vd, i, val << shift);
5569     }
5570 }
5571
5572 static void
5573 do_vec_SSHR_USHR (sim_cpu *cpu)
5574 {
5575   /* instr [31]    = 0
5576      instr [30]    = half(0)/full(1)
5577      instr [29]    = signed(0)/unsigned(1)
5578      instr [28,23] = 01 1110
5579      instr [22,16] = size and shift amount
5580      instr [15,10] = 0000 01
5581      instr [9, 5]  = Vs
5582      instr [4, 0]  = Vd.  */
5583
5584   int shift;
5585   int full = uimm (aarch64_get_instr (cpu), 30, 30);
5586   int sign = uimm (aarch64_get_instr (cpu), 29, 29);
5587   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5588   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5589   unsigned i;
5590
5591   NYI_assert (28, 23, 0x1E);
5592   NYI_assert (15, 10, 0x01);
5593
5594   if (uimm (aarch64_get_instr (cpu), 22, 22))
5595     {
5596       shift = uimm (aarch64_get_instr (cpu), 21, 16);
5597
5598       if (full == 0)
5599         HALT_UNALLOC;
5600
5601       if (sign)
5602         for (i = 0; i < 2; i++)
5603           {
5604             int64_t val = aarch64_get_vec_s64 (cpu, vs, i);
5605             aarch64_set_vec_s64 (cpu, vd, i, val >> shift);
5606           }
5607       else
5608         for (i = 0; i < 2; i++)
5609           {
5610             uint64_t val = aarch64_get_vec_u64 (cpu, vs, i);
5611             aarch64_set_vec_u64 (cpu, vd, i, val >> shift);
5612           }
5613
5614       return;
5615     }
5616
5617   if (uimm (aarch64_get_instr (cpu), 21, 21))
5618     {
5619       shift = uimm (aarch64_get_instr (cpu), 20, 16);
5620
5621       if (sign)
5622         for (i = 0; i < (full ? 4 : 2); i++)
5623           {
5624             int32_t val = aarch64_get_vec_s32 (cpu, vs, i);
5625             aarch64_set_vec_s32 (cpu, vd, i, val >> shift);
5626           }
5627       else
5628         for (i = 0; i < (full ? 4 : 2); i++)
5629           {
5630             uint32_t val = aarch64_get_vec_u32 (cpu, vs, i);
5631             aarch64_set_vec_u32 (cpu, vd, i, val >> shift);
5632           }
5633
5634       return;
5635     }
5636
5637   if (uimm (aarch64_get_instr (cpu), 20, 20))
5638     {
5639       shift = uimm (aarch64_get_instr (cpu), 19, 16);
5640
5641       if (sign)
5642         for (i = 0; i < (full ? 8 : 4); i++)
5643           {
5644             int16_t val = aarch64_get_vec_s16 (cpu, vs, i);
5645             aarch64_set_vec_s16 (cpu, vd, i, val >> shift);
5646           }
5647       else
5648         for (i = 0; i < (full ? 8 : 4); i++)
5649           {
5650             uint16_t val = aarch64_get_vec_u16 (cpu, vs, i);
5651             aarch64_set_vec_u16 (cpu, vd, i, val >> shift);
5652           }
5653
5654       return;
5655     }
5656
5657   if (uimm (aarch64_get_instr (cpu), 19, 19) == 0)
5658     HALT_UNALLOC;
5659
5660   shift = uimm (aarch64_get_instr (cpu), 18, 16);
5661
5662   if (sign)
5663     for (i = 0; i < (full ? 16 : 8); i++)
5664       {
5665         int8_t val = aarch64_get_vec_s8 (cpu, vs, i);
5666         aarch64_set_vec_s8 (cpu, vd, i, val >> shift);
5667       }
5668   else
5669     for (i = 0; i < (full ? 16 : 8); i++)
5670       {
5671         uint8_t val = aarch64_get_vec_u8 (cpu, vs, i);
5672         aarch64_set_vec_u8 (cpu, vd, i, val >> shift);
5673       }
5674 }
5675
5676 static void
5677 do_vec_MUL_by_element (sim_cpu *cpu)
5678 {
5679   /* instr[31]    = 0
5680      instr[30]    = half/full
5681      instr[29,24] = 00 1111
5682      instr[23,22] = size
5683      instr[21]    = L
5684      instr[20]    = M
5685      instr[19,16] = m
5686      instr[15,12] = 1000
5687      instr[11]    = H
5688      instr[10]    = 0
5689      instr[9,5]   = Vn
5690      instr[4,0]   = Vd  */
5691
5692   unsigned full     = uimm (aarch64_get_instr (cpu), 30, 30);
5693   unsigned L        = uimm (aarch64_get_instr (cpu), 21, 21);
5694   unsigned H        = uimm (aarch64_get_instr (cpu), 11, 11);
5695   unsigned vn       = uimm (aarch64_get_instr (cpu), 9, 5);
5696   unsigned vd       = uimm (aarch64_get_instr (cpu), 4, 0);
5697   unsigned size     = uimm (aarch64_get_instr (cpu), 23, 22);
5698   unsigned index;
5699   unsigned vm;
5700   unsigned e;
5701
5702   NYI_assert (29, 24, 0x0F);
5703   NYI_assert (15, 12, 0x8);
5704   NYI_assert (10, 10, 0);
5705
5706   switch (size)
5707     {
5708     case 1:
5709       {
5710         /* 16 bit products.  */
5711         uint16_t product;
5712         uint16_t element1;
5713         uint16_t element2;
5714
5715         index = (H << 2) | (L << 1) | uimm (aarch64_get_instr (cpu), 20, 20);
5716         vm = uimm (aarch64_get_instr (cpu), 19, 16);
5717         element2 = aarch64_get_vec_u16 (cpu, vm, index);
5718
5719         for (e = 0; e < (full ? 8 : 4); e ++)
5720           {
5721             element1 = aarch64_get_vec_u16 (cpu, vn, e);
5722             product  = element1 * element2;
5723             aarch64_set_vec_u16 (cpu, vd, e, product);
5724           }
5725       }
5726       break;
5727
5728     case 2:
5729       {
5730         /* 32 bit products.  */
5731         uint32_t product;
5732         uint32_t element1;
5733         uint32_t element2;
5734
5735         index = (H << 1) | L;
5736         vm = uimm (aarch64_get_instr (cpu), 20, 16);
5737         element2 = aarch64_get_vec_u32 (cpu, vm, index);
5738
5739         for (e = 0; e < (full ? 4 : 2); e ++)
5740           {
5741             element1 = aarch64_get_vec_u32 (cpu, vn, e);
5742             product  = element1 * element2;
5743             aarch64_set_vec_u32 (cpu, vd, e, product);
5744           }
5745       }
5746       break;
5747
5748     default:
5749       HALT_UNALLOC;
5750     }
5751 }
5752
5753 static void
5754 do_vec_op2 (sim_cpu *cpu)
5755 {
5756   /* instr[31]    = 0
5757      instr[30]    = half/full
5758      instr[29,24] = 00 1111
5759      instr[23]    = ?
5760      instr[22,16] = element size & index
5761      instr[15,10] = sub-opcode
5762      instr[9,5]   = Vm
5763      instr[4,0]   = Vd  */
5764
5765   NYI_assert (29, 24, 0x0F);
5766
5767   if (uimm (aarch64_get_instr (cpu), 23, 23) != 0)
5768     {
5769       switch (uimm (aarch64_get_instr (cpu), 15, 10))
5770         {
5771         case 0x20:
5772         case 0x22: do_vec_MUL_by_element (cpu); return;
5773         default:   HALT_NYI;
5774         }
5775     }
5776   else
5777     {
5778       switch (uimm (aarch64_get_instr (cpu), 15, 10))
5779         {
5780         case 0x01: do_vec_SSHR_USHR (cpu); return;
5781         case 0x15: do_vec_SHL (cpu); return;
5782         case 0x20:
5783         case 0x22: do_vec_MUL_by_element (cpu); return;
5784         case 0x29: do_vec_xtl (cpu); return;
5785         default:   HALT_NYI;
5786         }
5787     }
5788 }
5789
5790 static void
5791 do_vec_neg (sim_cpu *cpu)
5792 {
5793   /* instr[31]    = 0
5794      instr[30]    = full(1)/half(0)
5795      instr[29,24] = 10 1110
5796      instr[23,22] = size: byte(00), half (01), word (10), long (11)
5797      instr[21,10] = 1000 0010 1110
5798      instr[9,5]   = Vs
5799      instr[4,0]   = Vd  */
5800
5801   int    full = uimm (aarch64_get_instr (cpu), 30, 30);
5802   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5803   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5804   unsigned i;
5805
5806   NYI_assert (29, 24, 0x2E);
5807   NYI_assert (21, 10, 0x82E);
5808
5809   switch (uimm (aarch64_get_instr (cpu), 23, 22))
5810     {
5811     case 0:
5812       for (i = 0; i < (full ? 16 : 8); i++)
5813         aarch64_set_vec_s8 (cpu, vd, i, - aarch64_get_vec_s8 (cpu, vs, i));
5814       return;
5815
5816     case 1:
5817       for (i = 0; i < (full ? 8 : 4); i++)
5818         aarch64_set_vec_s16 (cpu, vd, i, - aarch64_get_vec_s16 (cpu, vs, i));
5819       return;
5820
5821     case 2:
5822       for (i = 0; i < (full ? 4 : 2); i++)
5823         aarch64_set_vec_s32 (cpu, vd, i, - aarch64_get_vec_s32 (cpu, vs, i));
5824       return;
5825
5826     case 3:
5827       if (! full)
5828         HALT_NYI;
5829       for (i = 0; i < 2; i++)
5830         aarch64_set_vec_s64 (cpu, vd, i, - aarch64_get_vec_s64 (cpu, vs, i));
5831       return;
5832
5833     default:
5834       HALT_UNREACHABLE;
5835     }
5836 }
5837
5838 static void
5839 do_vec_sqrt (sim_cpu *cpu)
5840 {
5841   /* instr[31]    = 0
5842      instr[30]    = full(1)/half(0)
5843      instr[29,23] = 101 1101
5844      instr[22]    = single(0)/double(1)
5845      instr[21,10] = 1000 0111 1110
5846      instr[9,5]   = Vs
5847      instr[4,0]   = Vd.  */
5848
5849   int    full = uimm (aarch64_get_instr (cpu), 30, 30);
5850   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5851   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5852   unsigned i;
5853
5854   NYI_assert (29, 23, 0x5B);
5855   NYI_assert (21, 10, 0x87E);
5856
5857   if (uimm (aarch64_get_instr (cpu), 22, 22) == 0)
5858     for (i = 0; i < (full ? 4 : 2); i++)
5859       aarch64_set_vec_float (cpu, vd, i,
5860                              sqrtf (aarch64_get_vec_float (cpu, vs, i)));
5861   else
5862     for (i = 0; i < 2; i++)
5863       aarch64_set_vec_double (cpu, vd, i,
5864                               sqrt (aarch64_get_vec_double (cpu, vs, i)));
5865 }
5866
5867 static void
5868 do_vec_mls_indexed (sim_cpu *cpu)
5869 {
5870   /* instr[31]       = 0
5871      instr[30]       = half(0)/full(1)
5872      instr[29,24]    = 10 1111
5873      instr[23,22]    = 16-bit(01)/32-bit(10)
5874      instr[21,20+11] = index (if 16-bit)
5875      instr[21+11]    = index (if 32-bit)
5876      instr[20,16]    = Vm
5877      instr[15,12]    = 0100
5878      instr[11]       = part of index
5879      instr[10]       = 0
5880      instr[9,5]      = Vs
5881      instr[4,0]      = Vd.  */
5882
5883   int    full = uimm (aarch64_get_instr (cpu), 30, 30);
5884   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5885   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5886   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5887   unsigned i;
5888
5889   NYI_assert (15, 12, 4);
5890   NYI_assert (10, 10, 0);
5891
5892   switch (uimm (aarch64_get_instr (cpu), 23, 22))
5893     {
5894     case 1:
5895       {
5896         unsigned elem;
5897         uint32_t val;
5898
5899         if (vm > 15)
5900           HALT_NYI;
5901
5902         elem = (uimm (aarch64_get_instr (cpu), 21, 20) << 1)
5903           | uimm (aarch64_get_instr (cpu), 11, 11);
5904         val = aarch64_get_vec_u16 (cpu, vm, elem);
5905
5906         for (i = 0; i < (full ? 8 : 4); i++)
5907           aarch64_set_vec_u32 (cpu, vd, i,
5908                                aarch64_get_vec_u32 (cpu, vd, i) -
5909                                (aarch64_get_vec_u32 (cpu, vs, i) * val));
5910         return;
5911       }
5912
5913     case 2:
5914       {
5915         unsigned elem = (uimm (aarch64_get_instr (cpu), 21, 21) << 1)
5916           | uimm (aarch64_get_instr (cpu), 11, 11);
5917         uint64_t val = aarch64_get_vec_u32 (cpu, vm, elem);
5918
5919         for (i = 0; i < (full ? 4 : 2); i++)
5920           aarch64_set_vec_u64 (cpu, vd, i,
5921                                aarch64_get_vec_u64 (cpu, vd, i) -
5922                                (aarch64_get_vec_u64 (cpu, vs, i) * val));
5923         return;
5924       }
5925
5926     case 0:
5927     case 3:
5928     default:
5929       HALT_NYI;
5930     }
5931 }
5932
5933 static void
5934 do_vec_SUB (sim_cpu *cpu)
5935 {
5936   /* instr [31]    = 0
5937      instr [30]    = half(0)/full(1)
5938      instr [29,24] = 10 1110
5939      instr [23,22] = size: byte(00, half(01), word (10), long (11)
5940      instr [21]    = 1
5941      instr [20,16] = Vm
5942      instr [15,10] = 10 0001
5943      instr [9, 5]  = Vn
5944      instr [4, 0]  = Vd.  */
5945
5946   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5947   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5948   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5949   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5950   unsigned i;
5951
5952   NYI_assert (29, 24, 0x2E);
5953   NYI_assert (21, 21, 1);
5954   NYI_assert (15, 10, 0x21);
5955
5956   switch (uimm (aarch64_get_instr (cpu), 23, 22))
5957     {
5958     case 0:
5959       for (i = 0; i < (full ? 16 : 8); i++)
5960         aarch64_set_vec_s8 (cpu, vd, i,
5961                             aarch64_get_vec_s8 (cpu, vn, i)
5962                             - aarch64_get_vec_s8 (cpu, vm, i));
5963       return;
5964
5965     case 1:
5966       for (i = 0; i < (full ? 8 : 4); i++)
5967         aarch64_set_vec_s16 (cpu, vd, i,
5968                              aarch64_get_vec_s16 (cpu, vn, i)
5969                              - aarch64_get_vec_s16 (cpu, vm, i));
5970       return;
5971
5972     case 2:
5973       for (i = 0; i < (full ? 4 : 2); i++)
5974         aarch64_set_vec_s32 (cpu, vd, i,
5975                              aarch64_get_vec_s32 (cpu, vn, i)
5976                              - aarch64_get_vec_s32 (cpu, vm, i));
5977       return;
5978
5979     case 3:
5980       if (full == 0)
5981         HALT_UNALLOC;
5982
5983       for (i = 0; i < 2; i++)
5984         aarch64_set_vec_s64 (cpu, vd, i,
5985                              aarch64_get_vec_s64 (cpu, vn, i)
5986                              - aarch64_get_vec_s64 (cpu, vm, i));
5987       return;
5988
5989     default:
5990       HALT_UNREACHABLE;
5991     }
5992 }
5993
5994 static void
5995 do_vec_MLS (sim_cpu *cpu)
5996 {
5997   /* instr [31]    = 0
5998      instr [30]    = half(0)/full(1)
5999      instr [29,24] = 10 1110
6000      instr [23,22] = size: byte(00, half(01), word (10)
6001      instr [21]    = 1
6002      instr [20,16] = Vm
6003      instr [15,10] = 10 0101
6004      instr [9, 5]  = Vn
6005      instr [4, 0]  = Vd.  */
6006
6007   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6008   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
6009   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6010   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6011   unsigned i;
6012
6013   NYI_assert (29, 24, 0x2E);
6014   NYI_assert (21, 21, 1);
6015   NYI_assert (15, 10, 0x25);
6016
6017   switch (uimm (aarch64_get_instr (cpu), 23, 22))
6018     {
6019     case 0:
6020       for (i = 0; i < (full ? 16 : 8); i++)
6021         aarch64_set_vec_u8 (cpu, vd, i,
6022                             (aarch64_get_vec_u8 (cpu, vn, i)
6023                              * aarch64_get_vec_u8 (cpu, vm, i))
6024                             - aarch64_get_vec_u8 (cpu, vd, i));
6025       return;
6026
6027     case 1:
6028       for (i = 0; i < (full ? 8 : 4); i++)
6029         aarch64_set_vec_u16 (cpu, vd, i,
6030                              (aarch64_get_vec_u16 (cpu, vn, i)
6031                               * aarch64_get_vec_u16 (cpu, vm, i))
6032                              - aarch64_get_vec_u16 (cpu, vd, i));
6033       return;
6034
6035     case 2:
6036       for (i = 0; i < (full ? 4 : 2); i++)
6037         aarch64_set_vec_u32 (cpu, vd, i,
6038                              (aarch64_get_vec_u32 (cpu, vn, i)
6039                               * aarch64_get_vec_u32 (cpu, vm, i))
6040                              - aarch64_get_vec_u32 (cpu, vd, i));
6041       return;
6042
6043     default:
6044       HALT_UNALLOC;
6045     }
6046 }
6047
6048 static void
6049 do_vec_FDIV (sim_cpu *cpu)
6050 {
6051   /* instr [31]    = 0
6052      instr [30]    = half(0)/full(1)
6053      instr [29,23] = 10 1110 0
6054      instr [22]    = float()/double(1)
6055      instr [21]    = 1
6056      instr [20,16] = Vm
6057      instr [15,10] = 1111 11
6058      instr [9, 5]  = Vn
6059      instr [4, 0]  = Vd.  */
6060
6061   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6062   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
6063   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6064   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6065   unsigned i;
6066
6067   NYI_assert (29, 23, 0x5C);
6068   NYI_assert (21, 21, 1);
6069   NYI_assert (15, 10, 0x3F);
6070
6071   if (uimm (aarch64_get_instr (cpu), 22, 22))
6072     {
6073       if (! full)
6074         HALT_UNALLOC;
6075
6076       for (i = 0; i < 2; i++)
6077         aarch64_set_vec_double (cpu, vd, i,
6078                                 aarch64_get_vec_double (cpu, vn, i)
6079                                 / aarch64_get_vec_double (cpu, vm, i));
6080     }
6081   else
6082     for (i = 0; i < (full ? 4 : 2); i++)
6083       aarch64_set_vec_float (cpu, vd, i,
6084                              aarch64_get_vec_float (cpu, vn, i)
6085                              / aarch64_get_vec_float (cpu, vm, i));
6086 }
6087
6088 static void
6089 do_vec_FMUL (sim_cpu *cpu)
6090 {
6091   /* instr [31]    = 0
6092      instr [30]    = half(0)/full(1)
6093      instr [29,23] = 10 1110 0
6094      instr [22]    = float(0)/double(1)
6095      instr [21]    = 1
6096      instr [20,16] = Vm
6097      instr [15,10] = 1101 11
6098      instr [9, 5]  = Vn
6099      instr [4, 0]  = Vd.  */
6100
6101   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6102   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
6103   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6104   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6105   unsigned i;
6106
6107   NYI_assert (29, 23, 0x5C);
6108   NYI_assert (21, 21, 1);
6109   NYI_assert (15, 10, 0x37);
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                                 aarch64_get_vec_double (cpu, vn, i)
6119                                 * aarch64_get_vec_double (cpu, vm, i));
6120     }
6121   else
6122     for (i = 0; i < (full ? 4 : 2); i++)
6123       aarch64_set_vec_float (cpu, vd, i,
6124                              aarch64_get_vec_float (cpu, vn, i)
6125                              * aarch64_get_vec_float (cpu, vm, i));
6126 }
6127
6128 static void
6129 do_vec_FADDP (sim_cpu *cpu)
6130 {
6131   /* instr [31]    = 0
6132      instr [30]    = half(0)/full(1)
6133      instr [29,23] = 10 1110 0
6134      instr [22]    = float(0)/double(1)
6135      instr [21]    = 1
6136      instr [20,16] = Vm
6137      instr [15,10] = 1101 01
6138      instr [9, 5]  = Vn
6139      instr [4, 0]  = Vd.  */
6140
6141   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6142   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
6143   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6144   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6145
6146   NYI_assert (29, 23, 0x5C);
6147   NYI_assert (21, 21, 1);
6148   NYI_assert (15, 10, 0x35);
6149
6150   if (uimm (aarch64_get_instr (cpu), 22, 22))
6151     {
6152       /* Extract values before adding them incase vd == vn/vm.  */
6153       double tmp1 = aarch64_get_vec_double (cpu, vn, 0);
6154       double tmp2 = aarch64_get_vec_double (cpu, vn, 1);
6155       double tmp3 = aarch64_get_vec_double (cpu, vm, 0);
6156       double tmp4 = aarch64_get_vec_double (cpu, vm, 1);
6157
6158       if (! full)
6159         HALT_UNALLOC;
6160
6161       aarch64_set_vec_double (cpu, vd, 0, tmp1 + tmp2);
6162       aarch64_set_vec_double (cpu, vd, 1, tmp3 + tmp4);
6163     }
6164   else
6165     {
6166       /* Extract values before adding them incase vd == vn/vm.  */
6167       float tmp1 = aarch64_get_vec_float (cpu, vn, 0);
6168       float tmp2 = aarch64_get_vec_float (cpu, vn, 1);
6169       float tmp5 = aarch64_get_vec_float (cpu, vm, 0);
6170       float tmp6 = aarch64_get_vec_float (cpu, vm, 1);
6171
6172       if (full)
6173         {
6174           float tmp3 = aarch64_get_vec_float (cpu, vn, 2);
6175           float tmp4 = aarch64_get_vec_float (cpu, vn, 3);
6176           float tmp7 = aarch64_get_vec_float (cpu, vm, 2);
6177           float tmp8 = aarch64_get_vec_float (cpu, vm, 3);
6178
6179           aarch64_set_vec_float (cpu, vd, 0, tmp1 + tmp2);
6180           aarch64_set_vec_float (cpu, vd, 1, tmp3 + tmp4);
6181           aarch64_set_vec_float (cpu, vd, 2, tmp5 + tmp6);
6182           aarch64_set_vec_float (cpu, vd, 3, tmp7 + tmp8);
6183         }
6184       else
6185         {
6186           aarch64_set_vec_float (cpu, vd, 0, tmp1 + tmp2);
6187           aarch64_set_vec_float (cpu, vd, 1, tmp5 + tmp6);
6188         }
6189     }
6190 }
6191
6192 static void
6193 do_vec_FSQRT (sim_cpu *cpu)
6194 {
6195   /* instr[31]    = 0
6196      instr[30]    = half(0)/full(1)
6197      instr[29,23] = 10 1110 1
6198      instr[22]    = single(0)/double(1)
6199      instr[21,10] = 10 0001 1111 10
6200      instr[9,5]   = Vsrc
6201      instr[4,0]   = Vdest.  */
6202
6203   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6204   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6205   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6206   int i;
6207
6208   NYI_assert (29, 23, 0x5D);
6209   NYI_assert (21, 10, 0x87E);
6210
6211   if (uimm (aarch64_get_instr (cpu), 22, 22))
6212     {
6213       if (! full)
6214         HALT_UNALLOC;
6215
6216       for (i = 0; i < 2; i++)
6217         aarch64_set_vec_double (cpu, vd, i,
6218                                 sqrt (aarch64_get_vec_double (cpu, vn, i)));
6219     }
6220   else
6221     {
6222       for (i = 0; i < (full ? 4 : 2); i++)
6223         aarch64_set_vec_float (cpu, vd, i,
6224                                sqrtf (aarch64_get_vec_float (cpu, vn, i)));
6225     }
6226 }
6227
6228 static void
6229 do_vec_FNEG (sim_cpu *cpu)
6230 {
6231   /* instr[31]    = 0
6232      instr[30]    = half (0)/full (1)
6233      instr[29,23] = 10 1110 1
6234      instr[22]    = single (0)/double (1)
6235      instr[21,10] = 10 0000 1111 10
6236      instr[9,5]   = Vsrc
6237      instr[4,0]   = Vdest.  */
6238
6239   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6240   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6241   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6242   int i;
6243
6244   NYI_assert (29, 23, 0x5D);
6245   NYI_assert (21, 10, 0x83E);
6246
6247   if (uimm (aarch64_get_instr (cpu), 22, 22))
6248     {
6249       if (! full)
6250         HALT_UNALLOC;
6251
6252       for (i = 0; i < 2; i++)
6253         aarch64_set_vec_double (cpu, vd, i,
6254                                 - aarch64_get_vec_double (cpu, vn, i));
6255     }
6256   else
6257     {
6258       for (i = 0; i < (full ? 4 : 2); i++)
6259         aarch64_set_vec_float (cpu, vd, i,
6260                                - aarch64_get_vec_float (cpu, vn, i));
6261     }
6262 }
6263
6264 static void
6265 do_vec_NOT (sim_cpu *cpu)
6266 {
6267   /* instr[31]    = 0
6268      instr[30]    = half (0)/full (1)
6269      instr[29,21] = 10 1110 001
6270      instr[20,16] = 0 0000
6271      instr[15,10] = 0101 10
6272      instr[9,5]   = Vn
6273      instr[4.0]   = Vd.  */
6274
6275   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6276   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6277   unsigned i;
6278   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
6279
6280   NYI_assert (29, 10, 0xB8816);
6281
6282   for (i = 0; i < (full ? 16 : 8); i++)
6283     aarch64_set_vec_u8 (cpu, vd, i, ~ aarch64_get_vec_u8 (cpu, vn, i));
6284 }
6285
6286 static void
6287 do_vec_MOV_element (sim_cpu *cpu)
6288 {
6289   /* instr[31,21] = 0110 1110 000
6290      instr[20,16] = size & dest index
6291      instr[15]    = 0
6292      instr[14,11] = source index
6293      instr[10]    = 1
6294      instr[9,5]   = Vs
6295      instr[4.0]   = Vd.  */
6296
6297   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
6298   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6299   unsigned src_index;
6300   unsigned dst_index;
6301
6302   NYI_assert (31, 21, 0x370);
6303   NYI_assert (15, 15, 0);
6304   NYI_assert (10, 10, 1);
6305
6306   if (uimm (aarch64_get_instr (cpu), 16, 16))
6307     {
6308       /* Move a byte.  */
6309       src_index = uimm (aarch64_get_instr (cpu), 14, 11);
6310       dst_index = uimm (aarch64_get_instr (cpu), 20, 17);
6311       aarch64_set_vec_u8 (cpu, vd, dst_index,
6312                           aarch64_get_vec_u8 (cpu, vs, src_index));
6313     }
6314   else if (uimm (aarch64_get_instr (cpu), 17, 17))
6315     {
6316       /* Move 16-bits.  */
6317       NYI_assert (11, 11, 0);
6318       src_index = uimm (aarch64_get_instr (cpu), 14, 12);
6319       dst_index = uimm (aarch64_get_instr (cpu), 20, 18);
6320       aarch64_set_vec_u16 (cpu, vd, dst_index,
6321                            aarch64_get_vec_u16 (cpu, vs, src_index));
6322     }
6323   else if (uimm (aarch64_get_instr (cpu), 18, 18))
6324     {
6325       /* Move 32-bits.  */
6326       NYI_assert (12, 11, 0);
6327       src_index = uimm (aarch64_get_instr (cpu), 14, 13);
6328       dst_index = uimm (aarch64_get_instr (cpu), 20, 19);
6329       aarch64_set_vec_u32 (cpu, vd, dst_index,
6330                            aarch64_get_vec_u32 (cpu, vs, src_index));
6331     }
6332   else
6333     {
6334       NYI_assert (19, 19, 1);
6335       NYI_assert (13, 11, 0);
6336       src_index = uimm (aarch64_get_instr (cpu), 14, 14);
6337       dst_index = uimm (aarch64_get_instr (cpu), 20, 20);
6338       aarch64_set_vec_u64 (cpu, vd, dst_index,
6339                            aarch64_get_vec_u64 (cpu, vs, src_index));
6340     }
6341 }
6342
6343 static void
6344 dexAdvSIMD0 (sim_cpu *cpu)
6345 {
6346   /* instr [28,25] = 0 111.  */
6347   if (    uimm (aarch64_get_instr (cpu), 15, 10) == 0x07
6348       && (uimm (aarch64_get_instr (cpu), 9, 5) ==
6349           uimm (aarch64_get_instr (cpu), 20, 16)))
6350     {
6351       if (uimm (aarch64_get_instr (cpu), 31, 21) == 0x075
6352           || uimm (aarch64_get_instr (cpu), 31, 21) == 0x275)
6353         {
6354           do_vec_MOV_whole_vector (cpu);
6355           return;
6356         }
6357     }
6358
6359   if (uimm (aarch64_get_instr (cpu), 29, 19) == 0x1E0)
6360     {
6361       do_vec_MOV_immediate (cpu);
6362       return;
6363     }
6364
6365   if (uimm (aarch64_get_instr (cpu), 29, 19) == 0x5E0)
6366     {
6367       do_vec_MVNI (cpu);
6368       return;
6369     }
6370
6371   if (uimm (aarch64_get_instr (cpu), 29, 19) == 0x1C0
6372       || uimm (aarch64_get_instr (cpu), 29, 19) == 0x1C1)
6373     {
6374       if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x03)
6375         {
6376           do_vec_DUP_scalar_into_vector (cpu);
6377           return;
6378         }
6379     }
6380
6381   switch (uimm (aarch64_get_instr (cpu), 29, 24))
6382     {
6383     case 0x0E: do_vec_op1 (cpu); return;
6384     case 0x0F: do_vec_op2 (cpu); return;
6385
6386     case 0x2f:
6387       switch (uimm (aarch64_get_instr (cpu), 15, 10))
6388         {
6389         case 0x01: do_vec_SSHR_USHR (cpu); return;
6390         case 0x10:
6391         case 0x12: do_vec_mls_indexed (cpu); return;
6392         case 0x29: do_vec_xtl (cpu); return;
6393         default:
6394           HALT_NYI;
6395         }
6396
6397     case 0x2E:
6398       if (uimm (aarch64_get_instr (cpu), 21, 21) == 1)
6399         {
6400           switch (uimm (aarch64_get_instr (cpu), 15, 10))
6401             {
6402             case 0x07:
6403               switch (uimm (aarch64_get_instr (cpu), 23, 22))
6404                 {
6405                 case 0: do_vec_EOR (cpu); return;
6406                 case 1: do_vec_BSL (cpu); return;
6407                 case 2:
6408                 case 3: do_vec_bit (cpu); return;
6409                 }
6410               break;
6411
6412             case 0x08: do_vec_sub_long (cpu); return;
6413             case 0x11: do_vec_USHL (cpu); return;
6414             case 0x16: do_vec_NOT (cpu); return;
6415             case 0x19: do_vec_max (cpu); return;
6416             case 0x1B: do_vec_min (cpu); return;
6417             case 0x21: do_vec_SUB (cpu); return;
6418             case 0x25: do_vec_MLS (cpu); return;
6419             case 0x31: do_vec_FminmaxNMP (cpu); return;
6420             case 0x35: do_vec_FADDP (cpu); return;
6421             case 0x37: do_vec_FMUL (cpu); return;
6422             case 0x3F: do_vec_FDIV (cpu); return;
6423
6424             case 0x3E:
6425               switch (uimm (aarch64_get_instr (cpu), 20, 16))
6426                 {
6427                 case 0x00: do_vec_FNEG (cpu); return;
6428                 case 0x01: do_vec_FSQRT (cpu); return;
6429                 default:   HALT_NYI;
6430                 }
6431
6432             case 0x0D:
6433             case 0x0F:
6434             case 0x22:
6435             case 0x23:
6436             case 0x26:
6437             case 0x2A:
6438             case 0x32:
6439             case 0x36:
6440             case 0x39:
6441             case 0x3A:
6442               do_vec_compare (cpu); return;
6443
6444             default: break;
6445             }
6446         }
6447
6448       if (uimm (aarch64_get_instr (cpu), 31, 21) == 0x370)
6449         {
6450           do_vec_MOV_element (cpu);
6451           return;
6452         }
6453
6454       switch (uimm (aarch64_get_instr (cpu), 21, 10))
6455         {
6456         case 0x82E: do_vec_neg (cpu); return;
6457         case 0x87E: do_vec_sqrt (cpu); return;
6458         default:
6459           if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x30)
6460             {
6461               do_vec_mull (cpu);
6462               return;
6463             }
6464           break;
6465         }
6466       break;
6467
6468     default:
6469       break;
6470     }
6471
6472   HALT_NYI;
6473 }
6474
6475 /* 3 sources.  */
6476
6477 /* Float multiply add.  */
6478 static void
6479 fmadds (sim_cpu *cpu)
6480 {
6481   unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6482   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6483   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6484   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6485
6486   aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sa)
6487                         + aarch64_get_FP_float (cpu, sn)
6488                         * aarch64_get_FP_float (cpu, sm));
6489 }
6490
6491 /* Double multiply add.  */
6492 static void
6493 fmaddd (sim_cpu *cpu)
6494 {
6495   unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6496   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6497   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6498   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6499
6500   aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sa)
6501                          + aarch64_get_FP_double (cpu, sn)
6502                          * aarch64_get_FP_double (cpu, sm));
6503 }
6504
6505 /* Float multiply subtract.  */
6506 static void
6507 fmsubs (sim_cpu *cpu)
6508 {
6509   unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6510   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6511   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6512   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6513
6514   aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sa)
6515                         - aarch64_get_FP_float (cpu, sn)
6516                         * aarch64_get_FP_float (cpu, sm));
6517 }
6518
6519 /* Double multiply subtract.  */
6520 static void
6521 fmsubd (sim_cpu *cpu)
6522 {
6523   unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6524   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6525   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6526   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6527
6528   aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sa)
6529                          - aarch64_get_FP_double (cpu, sn)
6530                          * aarch64_get_FP_double (cpu, sm));
6531 }
6532
6533 /* Float negative multiply add.  */
6534 static void
6535 fnmadds (sim_cpu *cpu)
6536 {
6537   unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6538   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6539   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6540   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6541
6542   aarch64_set_FP_float (cpu, sd, - aarch64_get_FP_float (cpu, sa)
6543                         + (- aarch64_get_FP_float (cpu, sn))
6544                         * aarch64_get_FP_float (cpu, sm));
6545 }
6546
6547 /* Double negative multiply add.  */
6548 static void
6549 fnmaddd (sim_cpu *cpu)
6550 {
6551   unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6552   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6553   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6554   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6555
6556   aarch64_set_FP_double (cpu, sd, - aarch64_get_FP_double (cpu, sa)
6557                          + (- aarch64_get_FP_double (cpu, sn))
6558                          * aarch64_get_FP_double (cpu, sm));
6559 }
6560
6561 /* Float negative multiply subtract.  */
6562 static void
6563 fnmsubs (sim_cpu *cpu)
6564 {
6565   unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6566   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6567   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6568   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6569
6570   aarch64_set_FP_float (cpu, sd, - aarch64_get_FP_float (cpu, sa)
6571                         + aarch64_get_FP_float (cpu, sn)
6572                         * aarch64_get_FP_float (cpu, sm));
6573 }
6574
6575 /* Double negative multiply subtract.  */
6576 static void
6577 fnmsubd (sim_cpu *cpu)
6578 {
6579   unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
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, sa)
6585                          + aarch64_get_FP_double (cpu, sn)
6586                          * aarch64_get_FP_double (cpu, sm));
6587 }
6588
6589 static void
6590 dexSimpleFPDataProc3Source (sim_cpu *cpu)
6591 {
6592   /* instr[31]    ==> M : 0 ==> OK, 1 ==> UNALLOC
6593      instr[30]    = 0
6594      instr[29]    ==> S :  0 ==> OK, 1 ==> UNALLOC
6595      instr[28,25] = 1111
6596      instr[24]    = 1
6597      instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
6598      instr[21]    ==> o1 : 0 ==> unnegated, 1 ==> negated
6599      instr[15]    ==> o2 : 0 ==> ADD, 1 ==> SUB  */
6600
6601   uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
6602     | uimm (aarch64_get_instr (cpu), 29, 29);
6603   /* dispatch on combined type:o1:o2.  */
6604   uint32_t dispatch = (uimm (aarch64_get_instr (cpu), 23, 21) << 1)
6605     | uimm (aarch64_get_instr (cpu), 15, 15);
6606
6607   if (M_S != 0)
6608     HALT_UNALLOC;
6609
6610   switch (dispatch)
6611     {
6612     case 0: fmadds (cpu); return;
6613     case 1: fmsubs (cpu); return;
6614     case 2: fnmadds (cpu); return;
6615     case 3: fnmsubs (cpu); return;
6616     case 4: fmaddd (cpu); return;
6617     case 5: fmsubd (cpu); return;
6618     case 6: fnmaddd (cpu); return;
6619     case 7: fnmsubd (cpu); return;
6620     default:
6621       /* type > 1 is currently unallocated.  */
6622       HALT_UNALLOC;
6623     }
6624 }
6625
6626 static void
6627 dexSimpleFPFixedConvert (sim_cpu *cpu)
6628 {
6629   HALT_NYI;
6630 }
6631
6632 static void
6633 dexSimpleFPCondCompare (sim_cpu *cpu)
6634 {
6635   HALT_NYI;
6636 }
6637
6638 /* 2 sources.  */
6639
6640 /* Float add.  */
6641 static void
6642 fadds (sim_cpu *cpu)
6643 {
6644   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6645   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6646   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6647
6648   aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6649                         + aarch64_get_FP_float (cpu, sm));
6650 }
6651
6652 /* Double add.  */
6653 static void
6654 faddd (sim_cpu *cpu)
6655 {
6656   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6657   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6658   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6659
6660   aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6661                          + aarch64_get_FP_double (cpu, sm));
6662 }
6663
6664 /* Float divide.  */
6665 static void
6666 fdivs (sim_cpu *cpu)
6667 {
6668   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6669   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6670   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6671
6672   aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6673                         / aarch64_get_FP_float (cpu, sm));
6674 }
6675
6676 /* Double divide.  */
6677 static void
6678 fdivd (sim_cpu *cpu)
6679 {
6680   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6681   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6682   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6683
6684   aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6685                          / aarch64_get_FP_double (cpu, sm));
6686 }
6687
6688 /* Float multiply.  */
6689 static void
6690 fmuls (sim_cpu *cpu)
6691 {
6692   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6693   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6694   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6695
6696   aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6697                         * aarch64_get_FP_float (cpu, sm));
6698 }
6699
6700 /* Double multiply.  */
6701 static void
6702 fmuld (sim_cpu *cpu)
6703 {
6704   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6705   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6706   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6707
6708   aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6709                          * aarch64_get_FP_double (cpu, sm));
6710 }
6711
6712 /* Float negate and multiply.  */
6713 static void
6714 fnmuls (sim_cpu *cpu)
6715 {
6716   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6717   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6718   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6719
6720   aarch64_set_FP_float (cpu, sd, - (aarch64_get_FP_float (cpu, sn)
6721                                     * aarch64_get_FP_float (cpu, sm)));
6722 }
6723
6724 /* Double negate and multiply.  */
6725 static void
6726 fnmuld (sim_cpu *cpu)
6727 {
6728   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6729   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6730   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6731
6732   aarch64_set_FP_double (cpu, sd, - (aarch64_get_FP_double (cpu, sn)
6733                                      * aarch64_get_FP_double (cpu, sm)));
6734 }
6735
6736 /* Float subtract.  */
6737 static void
6738 fsubs (sim_cpu *cpu)
6739 {
6740   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6741   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6742   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6743
6744   aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6745                         - aarch64_get_FP_float (cpu, sm));
6746 }
6747
6748 /* Double subtract.  */
6749 static void
6750 fsubd (sim_cpu *cpu)
6751 {
6752   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6753   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6754   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6755
6756   aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6757                          - aarch64_get_FP_double (cpu, sm));
6758 }
6759
6760 static void
6761 do_FMINNM (sim_cpu *cpu)
6762 {
6763   /* instr[31,23] = 0 0011 1100
6764      instr[22]    = float(0)/double(1)
6765      instr[21]    = 1
6766      instr[20,16] = Sm
6767      instr[15,10] = 01 1110
6768      instr[9,5]   = Sn
6769      instr[4,0]   = Cpu  */
6770
6771   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6772   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6773   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6774
6775   NYI_assert (31, 23, 0x03C);
6776   NYI_assert (15, 10, 0x1E);
6777
6778   if (uimm (aarch64_get_instr (cpu), 22, 22))
6779     aarch64_set_FP_double (cpu, sd,
6780                            dminnm (aarch64_get_FP_double (cpu, sn),
6781                                    aarch64_get_FP_double (cpu, sm)));
6782   else
6783     aarch64_set_FP_float (cpu, sd,
6784                           fminnm (aarch64_get_FP_float (cpu, sn),
6785                                   aarch64_get_FP_float (cpu, sm)));
6786 }
6787
6788 static void
6789 do_FMAXNM (sim_cpu *cpu)
6790 {
6791   /* instr[31,23] = 0 0011 1100
6792      instr[22]    = float(0)/double(1)
6793      instr[21]    = 1
6794      instr[20,16] = Sm
6795      instr[15,10] = 01 1010
6796      instr[9,5]   = Sn
6797      instr[4,0]   = Cpu  */
6798
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
6803   NYI_assert (31, 23, 0x03C);
6804   NYI_assert (15, 10, 0x1A);
6805
6806   if (uimm (aarch64_get_instr (cpu), 22, 22))
6807     aarch64_set_FP_double (cpu, sd,
6808                            dmaxnm (aarch64_get_FP_double (cpu, sn),
6809                                    aarch64_get_FP_double (cpu, sm)));
6810   else
6811     aarch64_set_FP_float (cpu, sd,
6812                           fmaxnm (aarch64_get_FP_float (cpu, sn),
6813                                   aarch64_get_FP_float (cpu, sm)));
6814 }
6815
6816 static void
6817 dexSimpleFPDataProc2Source (sim_cpu *cpu)
6818 {
6819   /* instr[31]    ==> M : 0 ==> OK, 1 ==> UNALLOC
6820      instr[30]    = 0
6821      instr[29]    ==> S :  0 ==> OK, 1 ==> UNALLOC
6822      instr[28,25] = 1111
6823      instr[24]    = 0
6824      instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
6825      instr[21]    = 1
6826      instr[20,16] = Vm
6827      instr[15,12] ==> opcode : 0000 ==> FMUL, 0001 ==> FDIV
6828                                0010 ==> FADD, 0011 ==> FSUB,
6829                                0100 ==> FMAX, 0101 ==> FMIN
6830                                0110 ==> FMAXNM, 0111 ==> FMINNM
6831                                1000 ==> FNMUL, ow ==> UNALLOC
6832      instr[11,10] = 10
6833      instr[9,5]   = Vn
6834      instr[4,0]   = Vd  */
6835
6836   uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
6837     | uimm (aarch64_get_instr (cpu), 29, 29);
6838   uint32_t type = uimm (aarch64_get_instr (cpu), 23, 22);
6839   /* Dispatch on opcode.  */
6840   uint32_t dispatch = uimm (aarch64_get_instr (cpu), 15, 12);
6841
6842   if (type > 1)
6843     HALT_UNALLOC;
6844
6845   if (M_S != 0)
6846     HALT_UNALLOC;
6847
6848   if (type)
6849     switch (dispatch)
6850       {
6851       case 0: fmuld (cpu); return;
6852       case 1: fdivd (cpu); return;
6853       case 2: faddd (cpu); return;
6854       case 3: fsubd (cpu); return;
6855       case 6: do_FMAXNM (cpu); return;
6856       case 7: do_FMINNM (cpu); return;
6857       case 8: fnmuld (cpu); return;
6858
6859         /* Have not yet implemented fmax and fmin.  */
6860       case 4:
6861       case 5:
6862         HALT_NYI;
6863
6864       default:
6865         HALT_UNALLOC;
6866       }
6867   else /* type == 0 => floats.  */
6868     switch (dispatch)
6869       {
6870       case 0: fmuls (cpu); return;
6871       case 1: fdivs (cpu); return;
6872       case 2: fadds (cpu); return;
6873       case 3: fsubs (cpu); return;
6874       case 6: do_FMAXNM (cpu); return;
6875       case 7: do_FMINNM (cpu); return;
6876       case 8: fnmuls (cpu); return;
6877
6878       case 4:
6879       case 5:
6880         HALT_NYI;
6881
6882       default:
6883         HALT_UNALLOC;
6884       }
6885 }
6886
6887 static void
6888 dexSimpleFPCondSelect (sim_cpu *cpu)
6889 {
6890   /* FCSEL
6891      instr[31,23] = 0 0011 1100
6892      instr[22]    = 0=>single 1=>double
6893      instr[21]    = 1
6894      instr[20,16] = Sm
6895      instr[15,12] = cond
6896      instr[11,10] = 11
6897      instr[9,5]   = Sn
6898      instr[4,0]   = Cpu  */
6899   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6900   unsigned sn = uimm (aarch64_get_instr (cpu),  9, 5);
6901   unsigned sd = uimm (aarch64_get_instr (cpu),  4, 0);
6902   uint32_t set = testConditionCode (cpu, uimm (aarch64_get_instr (cpu), 15, 12));
6903
6904   NYI_assert (31, 23, 0x03C);
6905   NYI_assert (11, 10, 0x3);
6906
6907   if (uimm (aarch64_get_instr (cpu), 22, 22))
6908     aarch64_set_FP_double (cpu, sd, set ? sn : sm);
6909   else
6910     aarch64_set_FP_float (cpu, sd, set ? sn : sm);
6911 }
6912
6913 /* Store 32 bit unscaled signed 9 bit.  */
6914 static void
6915 fsturs (sim_cpu *cpu, int32_t offset)
6916 {
6917   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6918   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6919
6920   aarch64_set_mem_u32 (cpu, aarch64_get_reg_u64 (cpu, st, 1) + offset,
6921                        aarch64_get_vec_u32 (cpu, rn, 0));
6922 }
6923
6924 /* Store 64 bit unscaled signed 9 bit.  */
6925 static void
6926 fsturd (sim_cpu *cpu, int32_t offset)
6927 {
6928   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6929   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6930
6931   aarch64_set_mem_u64 (cpu, aarch64_get_reg_u64 (cpu, st, 1) + offset,
6932                        aarch64_get_vec_u64 (cpu, rn, 0));
6933 }
6934
6935 /* Store 128 bit unscaled signed 9 bit.  */
6936 static void
6937 fsturq (sim_cpu *cpu, int32_t offset)
6938 {
6939   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6940   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6941   FRegister a;
6942
6943   aarch64_get_FP_long_double (cpu, rn, & a);
6944   aarch64_set_mem_long_double (cpu,
6945                                aarch64_get_reg_u64 (cpu, st, 1)
6946                                + offset, a);
6947 }
6948
6949 /* TODO FP move register.  */
6950
6951 /* 32 bit fp to fp move register.  */
6952 static void
6953 ffmovs (sim_cpu *cpu)
6954 {
6955   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6956   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6957
6958   aarch64_set_FP_float (cpu, st, aarch64_get_FP_float (cpu, rn));
6959 }
6960
6961 /* 64 bit fp to fp move register.  */
6962 static void
6963 ffmovd (sim_cpu *cpu)
6964 {
6965   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6966   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6967
6968   aarch64_set_FP_double (cpu, st, aarch64_get_FP_double (cpu, rn));
6969 }
6970
6971 /* 32 bit GReg to Vec move register.  */
6972 static void
6973 fgmovs (sim_cpu *cpu)
6974 {
6975   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6976   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6977
6978   aarch64_set_vec_u32 (cpu, st, 0, aarch64_get_reg_u32 (cpu, rn, NO_SP));
6979 }
6980
6981 /* 64 bit g to fp move register.  */
6982 static void
6983 fgmovd (sim_cpu *cpu)
6984 {
6985   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6986   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6987
6988   aarch64_set_vec_u64 (cpu, st, 0, aarch64_get_reg_u64 (cpu, rn, NO_SP));
6989 }
6990
6991 /* 32 bit fp to g move register.  */
6992 static void
6993 gfmovs (sim_cpu *cpu)
6994 {
6995   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6996   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6997
6998   aarch64_set_reg_u64 (cpu, st, NO_SP, aarch64_get_vec_u32 (cpu, rn, 0));
6999 }
7000
7001 /* 64 bit fp to g move register.  */
7002 static void
7003 gfmovd (sim_cpu *cpu)
7004 {
7005   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
7006   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
7007
7008   aarch64_set_reg_u64 (cpu, st, NO_SP, aarch64_get_vec_u64 (cpu, rn, 0));
7009 }
7010
7011 /* FP move immediate
7012
7013    These install an immediate 8 bit value in the target register
7014    where the 8 bits comprise 1 sign bit, 4 bits of fraction and a 3
7015    bit exponent.  */
7016
7017 static void
7018 fmovs (sim_cpu *cpu)
7019 {
7020   unsigned int sd = uimm (aarch64_get_instr (cpu), 4, 0);
7021   uint32_t imm = uimm (aarch64_get_instr (cpu), 20, 13);
7022   float f = fp_immediate_for_encoding_32 (imm);
7023
7024   aarch64_set_FP_float (cpu, sd, f);
7025 }
7026
7027 static void
7028 fmovd (sim_cpu *cpu)
7029 {
7030   unsigned int sd = uimm (aarch64_get_instr (cpu), 4, 0);
7031   uint32_t imm = uimm (aarch64_get_instr (cpu), 20, 13);
7032   double d = fp_immediate_for_encoding_64 (imm);
7033
7034   aarch64_set_FP_double (cpu, sd, d);
7035 }
7036
7037 static void
7038 dexSimpleFPImmediate (sim_cpu *cpu)
7039 {
7040   /* instr[31,23] == 00111100
7041      instr[22]    == type : single(0)/double(1)
7042      instr[21]    == 1
7043      instr[20,13] == imm8
7044      instr[12,10] == 100
7045      instr[9,5]   == imm5 : 00000 ==> PK, ow ==> UNALLOC
7046      instr[4,0]   == Rd  */
7047   uint32_t imm5 = uimm (aarch64_get_instr (cpu), 9, 5);
7048
7049   NYI_assert (31, 23, 0x3C);
7050
7051   if (imm5 != 0)
7052     HALT_UNALLOC;
7053
7054   if (uimm (aarch64_get_instr (cpu), 22, 22))
7055     fmovd (cpu);
7056   else
7057     fmovs (cpu);
7058 }
7059
7060 /* TODO specific decode and execute for group Load Store.  */
7061
7062 /* TODO FP load/store single register (unscaled offset).  */
7063
7064 /* TODO load 8 bit unscaled signed 9 bit.  */
7065 /* TODO load 16 bit unscaled signed 9 bit.  */
7066
7067 /* Load 32 bit unscaled signed 9 bit.  */
7068 static void
7069 fldurs (sim_cpu *cpu, int32_t offset)
7070 {
7071   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
7072   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
7073
7074   aarch64_set_vec_u32 (cpu, st, 0, aarch64_get_mem_u32
7075                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset));
7076 }
7077
7078 /* Load 64 bit unscaled signed 9 bit.  */
7079 static void
7080 fldurd (sim_cpu *cpu, int32_t offset)
7081 {
7082   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
7083   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
7084
7085   aarch64_set_vec_u64 (cpu, st, 0, aarch64_get_mem_u64
7086                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset));
7087 }
7088
7089 /* Load 128 bit unscaled signed 9 bit.  */
7090 static void
7091 fldurq (sim_cpu *cpu, int32_t offset)
7092 {
7093   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
7094   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
7095   FRegister a;
7096   uint64_t addr = aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset;
7097
7098   aarch64_get_mem_long_double (cpu, addr, & a);
7099   aarch64_set_FP_long_double (cpu, st, a);
7100 }
7101
7102 /* TODO store 8 bit unscaled signed 9 bit.  */
7103 /* TODO store 16 bit unscaled signed 9 bit.  */
7104
7105
7106 /* 1 source.  */
7107
7108 /* Float absolute value.  */
7109 static void
7110 fabss (sim_cpu *cpu)
7111 {
7112   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7113   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7114   float value = aarch64_get_FP_float (cpu, sn);
7115
7116   aarch64_set_FP_float (cpu, sd, fabsf (value));
7117 }
7118
7119 /* Double absolute value.  */
7120 static void
7121 fabcpu (sim_cpu *cpu)
7122 {
7123   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7124   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7125   double value = aarch64_get_FP_double (cpu, sn);
7126
7127   aarch64_set_FP_double (cpu, sd, fabs (value));
7128 }
7129
7130 /* Float negative value.  */
7131 static void
7132 fnegs (sim_cpu *cpu)
7133 {
7134   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7135   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7136
7137   aarch64_set_FP_float (cpu, sd, - aarch64_get_FP_float (cpu, sn));
7138 }
7139
7140 /* Double negative value.  */
7141 static void
7142 fnegd (sim_cpu *cpu)
7143 {
7144   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7145   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7146
7147   aarch64_set_FP_double (cpu, sd, - aarch64_get_FP_double (cpu, sn));
7148 }
7149
7150 /* Float square root.  */
7151 static void
7152 fsqrts (sim_cpu *cpu)
7153 {
7154   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7155   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7156
7157   aarch64_set_FP_float (cpu, sd, sqrt (aarch64_get_FP_float (cpu, sn)));
7158 }
7159
7160 /* Double square root.  */
7161 static void
7162 fsqrtd (sim_cpu *cpu)
7163 {
7164   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7165   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7166
7167   aarch64_set_FP_double (cpu, sd,
7168                          sqrt (aarch64_get_FP_double (cpu, sn)));
7169 }
7170
7171 /* Convert double to float.  */
7172 static void
7173 fcvtds (sim_cpu *cpu)
7174 {
7175   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7176   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7177
7178   aarch64_set_FP_float (cpu, sd, (float) aarch64_get_FP_double (cpu, sn));
7179 }
7180
7181 /* Convert float to double.  */
7182 static void
7183 fcvtcpu (sim_cpu *cpu)
7184 {
7185   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7186   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7187
7188   aarch64_set_FP_double (cpu, sd, (double) aarch64_get_FP_float (cpu, sn));
7189 }
7190
7191 static void
7192 do_FRINT (sim_cpu *cpu)
7193 {
7194   /* instr[31,23] = 0001 1110 0
7195      instr[22]    = single(0)/double(1)
7196      instr[21,18] = 1001
7197      instr[17,15] = rounding mode
7198      instr[14,10] = 10000
7199      instr[9,5]   = source
7200      instr[4,0]   = dest  */
7201
7202   float val;
7203   unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
7204   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7205   unsigned int rmode = uimm (aarch64_get_instr (cpu), 17, 15);
7206
7207   NYI_assert (31, 23, 0x03C);
7208   NYI_assert (21, 18, 0x9);
7209   NYI_assert (14, 10, 0x10);
7210
7211   if (rmode == 6 || rmode == 7)
7212     /* FIXME: Add support for rmode == 6 exactness check.  */
7213     rmode = uimm (aarch64_get_FPSR (cpu), 23, 22);
7214
7215   if (uimm (aarch64_get_instr (cpu), 22, 22))
7216     {
7217       double val = aarch64_get_FP_double (cpu, rs);
7218
7219       switch (rmode)
7220         {
7221         case 0: /* mode N: nearest or even.  */
7222           {
7223             double rval = round (val);
7224
7225             if (val - rval == 0.5)
7226               {
7227                 if (((rval / 2.0) * 2.0) != rval)
7228                   rval += 1.0;
7229               }
7230
7231             aarch64_set_FP_double (cpu, rd, round (val));
7232             return;
7233           }
7234
7235         case 1: /* mode P: towards +inf.  */
7236           if (val < 0.0)
7237             aarch64_set_FP_double (cpu, rd, trunc (val));
7238           else
7239             aarch64_set_FP_double (cpu, rd, round (val));
7240           return;
7241
7242         case 2: /* mode M: towards -inf.  */
7243           if (val < 0.0)
7244             aarch64_set_FP_double (cpu, rd, round (val));
7245           else
7246             aarch64_set_FP_double (cpu, rd, trunc (val));
7247           return;
7248
7249         case 3: /* mode Z: towards 0.  */
7250           aarch64_set_FP_double (cpu, rd, trunc (val));
7251           return;
7252
7253         case 4: /* mode A: away from 0.  */
7254           aarch64_set_FP_double (cpu, rd, round (val));
7255           return;
7256
7257         case 6: /* mode X: use FPCR with exactness check.  */
7258         case 7: /* mode I: use FPCR mode.  */
7259           HALT_NYI;
7260
7261         default:
7262           HALT_UNALLOC;
7263         }
7264     }
7265
7266   val = aarch64_get_FP_float (cpu, rs);
7267
7268   switch (rmode)
7269     {
7270     case 0: /* mode N: nearest or even.  */
7271       {
7272         float rval = roundf (val);
7273
7274         if (val - rval == 0.5)
7275           {
7276             if (((rval / 2.0) * 2.0) != rval)
7277               rval += 1.0;
7278           }
7279
7280         aarch64_set_FP_float (cpu, rd, rval);
7281         return;
7282       }
7283
7284     case 1: /* mode P: towards +inf.  */
7285       if (val < 0.0)
7286         aarch64_set_FP_float (cpu, rd, truncf (val));
7287       else
7288         aarch64_set_FP_float (cpu, rd, roundf (val));
7289       return;
7290
7291     case 2: /* mode M: towards -inf.  */
7292       if (val < 0.0)
7293         aarch64_set_FP_float (cpu, rd, truncf (val));
7294       else
7295         aarch64_set_FP_float (cpu, rd, roundf (val));
7296       return;
7297
7298     case 3: /* mode Z: towards 0.  */
7299       aarch64_set_FP_float (cpu, rd, truncf (val));
7300       return;
7301
7302     case 4: /* mode A: away from 0.  */
7303       aarch64_set_FP_float (cpu, rd, roundf (val));
7304       return;
7305
7306     case 6: /* mode X: use FPCR with exactness check.  */
7307     case 7: /* mode I: use FPCR mode.  */
7308       HALT_NYI;
7309
7310     default:
7311       HALT_UNALLOC;
7312     }
7313 }
7314
7315 static void
7316 dexSimpleFPDataProc1Source (sim_cpu *cpu)
7317 {
7318   /* instr[31]    ==> M : 0 ==> OK, 1 ==> UNALLOC
7319      instr[30]    = 0
7320      instr[29]    ==> S :  0 ==> OK, 1 ==> UNALLOC
7321      instr[28,25] = 1111
7322      instr[24]    = 0
7323      instr[23,22] ==> type : 00 ==> source is single,
7324                              01 ==> source is double
7325                              10 ==> UNALLOC
7326                              11 ==> UNALLOC or source is half
7327      instr[21]    = 1
7328      instr[20,15] ==> opcode : with type 00 or 01
7329                                000000 ==> FMOV, 000001 ==> FABS,
7330                                000010 ==> FNEG, 000011 ==> FSQRT,
7331                                000100 ==> UNALLOC, 000101 ==> FCVT,(to single/double)
7332                                000110 ==> UNALLOC, 000111 ==> FCVT (to half)
7333                                001000 ==> FRINTN, 001001 ==> FRINTP,
7334                                001010 ==> FRINTM, 001011 ==> FRINTZ,
7335                                001100 ==> FRINTA, 001101 ==> UNALLOC
7336                                001110 ==> FRINTX, 001111 ==> FRINTI
7337                                with type 11
7338                                000100 ==> FCVT (half-to-single)
7339                                000101 ==> FCVT (half-to-double)
7340                                instr[14,10] = 10000.  */
7341
7342   uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
7343     | uimm (aarch64_get_instr (cpu), 29, 29);
7344   uint32_t type   = uimm (aarch64_get_instr (cpu), 23, 22);
7345   uint32_t opcode = uimm (aarch64_get_instr (cpu), 20, 15);
7346
7347   if (M_S != 0)
7348     HALT_UNALLOC;
7349
7350   if (type == 3)
7351     {
7352       if (opcode == 4 || opcode == 5)
7353         HALT_NYI;
7354       else
7355         HALT_UNALLOC;
7356     }
7357
7358   if (type == 2)
7359     HALT_UNALLOC;
7360
7361   switch (opcode)
7362     {
7363     case 0:
7364       if (type)
7365         ffmovd (cpu);
7366       else
7367         ffmovs (cpu);
7368       return;
7369
7370     case 1:
7371       if (type)
7372         fabcpu (cpu);
7373       else
7374         fabss (cpu);
7375       return;
7376
7377     case 2:
7378       if (type)
7379         fnegd (cpu);
7380       else
7381         fnegs (cpu);
7382       return;
7383
7384     case 3:
7385       if (type)
7386         fsqrtd (cpu);
7387       else
7388         fsqrts (cpu);
7389       return;
7390
7391     case 4:
7392       if (type)
7393         fcvtds (cpu);
7394       else
7395         HALT_UNALLOC;
7396       return;
7397
7398     case 5:
7399       if (type)
7400         HALT_UNALLOC;
7401       fcvtcpu (cpu);
7402       return;
7403
7404     case 8:             /* FRINTN etc.  */
7405     case 9:
7406     case 10:
7407     case 11:
7408     case 12:
7409     case 14:
7410     case 15:
7411        do_FRINT (cpu);
7412        return;
7413
7414     case 7:             /* FCVT double/single to half precision.  */
7415     case 13:
7416       HALT_NYI;
7417
7418     default:
7419       HALT_UNALLOC;
7420     }
7421 }
7422
7423 /* 32 bit signed int to float.  */
7424 static void
7425 scvtf32 (sim_cpu *cpu)
7426 {
7427   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7428   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7429
7430   aarch64_set_FP_float
7431     (cpu, sd, (float) aarch64_get_reg_s32 (cpu, rn, NO_SP));
7432 }
7433
7434 /* signed int to float.  */
7435 static void
7436 scvtf (sim_cpu *cpu)
7437 {
7438   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7439   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7440
7441   aarch64_set_FP_float
7442     (cpu, sd, (float) aarch64_get_reg_s64 (cpu, rn, NO_SP));
7443 }
7444
7445 /* 32 bit signed int to double.  */
7446 static void
7447 scvtd32 (sim_cpu *cpu)
7448 {
7449   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7450   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7451
7452   aarch64_set_FP_double
7453     (cpu, sd, (double) aarch64_get_reg_s32 (cpu, rn, NO_SP));
7454 }
7455
7456 /* signed int to double.  */
7457 static void
7458 scvtd (sim_cpu *cpu)
7459 {
7460   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7461   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7462
7463   aarch64_set_FP_double
7464     (cpu, sd, (double) aarch64_get_reg_s64 (cpu, rn, NO_SP));
7465 }
7466
7467 static const float  FLOAT_INT_MAX   = (float)  INT_MAX;
7468 static const float  FLOAT_INT_MIN   = (float)  INT_MIN;
7469 static const double DOUBLE_INT_MAX  = (double) INT_MAX;
7470 static const double DOUBLE_INT_MIN  = (double) INT_MIN;
7471 static const float  FLOAT_LONG_MAX  = (float)  LONG_MAX;
7472 static const float  FLOAT_LONG_MIN  = (float)  LONG_MIN;
7473 static const double DOUBLE_LONG_MAX = (double) LONG_MAX;
7474 static const double DOUBLE_LONG_MIN = (double) LONG_MIN;
7475
7476 /* Check for FP exception conditions:
7477      NaN raises IO
7478      Infinity raises IO
7479      Out of Range raises IO and IX and saturates value
7480      Denormal raises ID and IX and sets to zero.  */
7481 #define RAISE_EXCEPTIONS(F, VALUE, FTYPE, ITYPE)        \
7482   do                                                    \
7483     {                                                   \
7484       switch (fpclassify (F))                           \
7485         {                                               \
7486         case FP_INFINITE:                               \
7487         case FP_NAN:                                    \
7488           aarch64_set_FPSR (cpu, IO);                   \
7489           if (signbit (F))                              \
7490             VALUE = ITYPE##_MAX;                        \
7491           else                                          \
7492             VALUE = ITYPE##_MIN;                        \
7493           break;                                        \
7494                                                         \
7495         case FP_NORMAL:                                 \
7496           if (F >= FTYPE##_##ITYPE##_MAX)               \
7497             {                                           \
7498               aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX);    \
7499               VALUE = ITYPE##_MAX;                      \
7500             }                                           \
7501           else if (F <= FTYPE##_##ITYPE##_MIN)          \
7502             {                                           \
7503               aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX);    \
7504               VALUE = ITYPE##_MIN;                      \
7505             }                                           \
7506           break;                                        \
7507                                                         \
7508         case FP_SUBNORMAL:                              \
7509           aarch64_set_FPSR_bits (cpu, IO | IX | ID, IX | ID);   \
7510           VALUE = 0;                                    \
7511           break;                                        \
7512                                                         \
7513         default:                                        \
7514         case FP_ZERO:                                   \
7515           VALUE = 0;                                    \
7516           break;                                        \
7517         }                                               \
7518     }                                                   \
7519   while (0)
7520
7521 /* 32 bit convert float to signed int truncate towards zero.  */
7522 static void
7523 fcvtszs32 (sim_cpu *cpu)
7524 {
7525   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7526   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7527   /* TODO : check that this rounds toward zero.  */
7528   float   f = aarch64_get_FP_float (cpu, sn);
7529   int32_t value = (int32_t) f;
7530
7531   RAISE_EXCEPTIONS (f, value, FLOAT, INT);
7532
7533   /* Avoid sign extension to 64 bit.  */
7534   aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) value);
7535 }
7536
7537 /* 64 bit convert float to signed int truncate towards zero.  */
7538 static void
7539 fcvtszs (sim_cpu *cpu)
7540 {
7541   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7542   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7543   float f = aarch64_get_FP_float (cpu, sn);
7544   int64_t value = (int64_t) f;
7545
7546   RAISE_EXCEPTIONS (f, value, FLOAT, LONG);
7547
7548   aarch64_set_reg_s64 (cpu, rd, NO_SP, value);
7549 }
7550
7551 /* 32 bit convert double to signed int truncate towards zero.  */
7552 static void
7553 fcvtszd32 (sim_cpu *cpu)
7554 {
7555   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7556   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7557   /* TODO : check that this rounds toward zero.  */
7558   double   d = aarch64_get_FP_double (cpu, sn);
7559   int32_t  value = (int32_t) d;
7560
7561   RAISE_EXCEPTIONS (d, value, DOUBLE, INT);
7562
7563   /* Avoid sign extension to 64 bit.  */
7564   aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) value);
7565 }
7566
7567 /* 64 bit convert double to signed int truncate towards zero.  */
7568 static void
7569 fcvtszd (sim_cpu *cpu)
7570 {
7571   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7572   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7573   /* TODO : check that this rounds toward zero.  */
7574   double  d = aarch64_get_FP_double (cpu, sn);
7575   int64_t value;
7576
7577   value = (int64_t) d;
7578
7579   RAISE_EXCEPTIONS (d, value, DOUBLE, LONG);
7580
7581   aarch64_set_reg_s64 (cpu, rd, NO_SP, value);
7582 }
7583
7584 static void
7585 do_fcvtzu (sim_cpu *cpu)
7586 {
7587   /* instr[31]    = size: 32-bit (0), 64-bit (1)
7588      instr[30,23] = 00111100
7589      instr[22]    = type: single (0)/ double (1)
7590      instr[21]    = enable (0)/disable(1) precision
7591      instr[20,16] = 11001
7592      instr[15,10] = precision
7593      instr[9,5]   = Rs
7594      instr[4,0]   = Rd.  */
7595
7596   unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
7597   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7598
7599   NYI_assert (30, 23, 0x3C);
7600   NYI_assert (20, 16, 0x19);
7601
7602   if (uimm (aarch64_get_instr (cpu), 21, 21) != 1)
7603     /* Convert to fixed point.  */
7604     HALT_NYI;
7605
7606   if (uimm (aarch64_get_instr (cpu), 31, 31))
7607     {
7608       /* Convert to unsigned 64-bit integer.  */
7609       if (uimm (aarch64_get_instr (cpu), 22, 22))
7610         {
7611           double  d = aarch64_get_FP_double (cpu, rs);
7612           uint64_t value = (uint64_t) d;
7613
7614           /* Do not raise an exception if we have reached ULONG_MAX.  */
7615           if (value != (1UL << 63))
7616             RAISE_EXCEPTIONS (d, value, DOUBLE, LONG);
7617
7618           aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
7619         }
7620       else
7621         {
7622           float  f = aarch64_get_FP_float (cpu, rs);
7623           uint64_t value = (uint64_t) f;
7624
7625           /* Do not raise an exception if we have reached ULONG_MAX.  */
7626           if (value != (1UL << 63))
7627             RAISE_EXCEPTIONS (f, value, FLOAT, LONG);
7628
7629           aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
7630         }
7631     }
7632   else
7633     {
7634       uint32_t value;
7635
7636       /* Convert to unsigned 32-bit integer.  */
7637       if (uimm (aarch64_get_instr (cpu), 22, 22))
7638         {
7639           double  d = aarch64_get_FP_double (cpu, rs);
7640
7641           value = (uint32_t) d;
7642           /* Do not raise an exception if we have reached UINT_MAX.  */
7643           if (value != (1UL << 31))
7644             RAISE_EXCEPTIONS (d, value, DOUBLE, INT);
7645         }
7646       else
7647         {
7648           float  f = aarch64_get_FP_float (cpu, rs);
7649
7650           value = (uint32_t) f;
7651           /* Do not raise an exception if we have reached UINT_MAX.  */
7652           if (value != (1UL << 31))
7653             RAISE_EXCEPTIONS (f, value, FLOAT, INT);
7654         }
7655
7656       aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
7657     }
7658 }
7659
7660 static void
7661 do_UCVTF (sim_cpu *cpu)
7662 {
7663   /* instr[31]    = size: 32-bit (0), 64-bit (1)
7664      instr[30,23] = 001 1110 0
7665      instr[22]    = type: single (0)/ double (1)
7666      instr[21]    = enable (0)/disable(1) precision
7667      instr[20,16] = 0 0011
7668      instr[15,10] = precision
7669      instr[9,5]   = Rs
7670      instr[4,0]   = Rd.  */
7671
7672   unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
7673   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7674
7675   NYI_assert (30, 23, 0x3C);
7676   NYI_assert (20, 16, 0x03);
7677
7678   if (uimm (aarch64_get_instr (cpu), 21, 21) != 1)
7679     HALT_NYI;
7680
7681   /* FIXME: Add exception raising.  */
7682   if (uimm (aarch64_get_instr (cpu), 31, 31))
7683     {
7684       uint64_t value = aarch64_get_reg_u64 (cpu, rs, NO_SP);
7685
7686       if (uimm (aarch64_get_instr (cpu), 22, 22))
7687         aarch64_set_FP_double (cpu, rd, (double) value);
7688       else
7689         aarch64_set_FP_float (cpu, rd, (float) value);
7690     }
7691   else
7692     {
7693       uint32_t value =  aarch64_get_reg_u32 (cpu, rs, NO_SP);
7694
7695       if (uimm (aarch64_get_instr (cpu), 22, 22))
7696         aarch64_set_FP_double (cpu, rd, (double) value);
7697       else
7698         aarch64_set_FP_float (cpu, rd, (float) value);
7699     }
7700 }
7701
7702 static void
7703 float_vector_move (sim_cpu *cpu)
7704 {
7705   /* instr[31,17] == 100 1111 0101 0111
7706      instr[16]    ==> direction 0=> to GR, 1=> from GR
7707      instr[15,10] => ???
7708      instr[9,5]   ==> source
7709      instr[4,0]   ==> dest.  */
7710
7711   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7712   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7713
7714   NYI_assert (31, 17, 0x4F57);
7715
7716   if (uimm (aarch64_get_instr (cpu), 15, 10) != 0)
7717     HALT_UNALLOC;
7718
7719   if (uimm (aarch64_get_instr (cpu), 16, 16))
7720     aarch64_set_vec_u64 (cpu, rd, 1, aarch64_get_reg_u64 (cpu, rn, NO_SP));
7721   else
7722     aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u64 (cpu, rn, 1));
7723 }
7724
7725 static void
7726 dexSimpleFPIntegerConvert (sim_cpu *cpu)
7727 {
7728   /* instr[31]    = size : 0 ==> 32 bit, 1 ==> 64 bit
7729      instr[30     = 0
7730      instr[29]    = S :  0 ==> OK, 1 ==> UNALLOC
7731      instr[28,25] = 1111
7732      instr[24]    = 0
7733      instr[23,22] = type : 00 ==> single, 01 ==> double, 1x ==> UNALLOC
7734      instr[21]    = 1
7735      instr[20,19] = rmode
7736      instr[18,16] = opcode
7737      instr[15,10] = 10 0000  */
7738
7739   uint32_t rmode_opcode;
7740   uint32_t size_type;
7741   uint32_t type;
7742   uint32_t size;
7743   uint32_t S;
7744
7745   if (uimm (aarch64_get_instr (cpu), 31, 17) == 0x4F57)
7746     {
7747       float_vector_move (cpu);
7748       return;
7749     }
7750
7751   size = uimm (aarch64_get_instr (cpu), 31, 31);
7752   S = uimm (aarch64_get_instr (cpu), 29, 29);
7753   if (S != 0)
7754     HALT_UNALLOC;
7755
7756   type = uimm (aarch64_get_instr (cpu), 23, 22);
7757   if (type > 1)
7758     HALT_UNALLOC;
7759
7760   rmode_opcode = uimm (aarch64_get_instr (cpu), 20, 16);
7761   size_type = (size << 1) | type; /* 0==32f, 1==32d, 2==64f, 3==64d.  */
7762
7763   switch (rmode_opcode)
7764     {
7765     case 2:                     /* SCVTF.  */
7766       switch (size_type)
7767         {
7768         case 0: scvtf32 (cpu); return;
7769         case 1: scvtd32 (cpu); return;
7770         case 2: scvtf (cpu); return;
7771         case 3: scvtd (cpu); return;
7772         default:
7773           HALT_UNREACHABLE;
7774         }
7775
7776     case 6:                     /* FMOV GR, Vec.  */
7777       switch (size_type)
7778         {
7779         case 0:  gfmovs (cpu); return;
7780         case 3:  gfmovd (cpu); return;
7781         default: HALT_UNALLOC;
7782         }
7783
7784     case 7:                     /* FMOV vec, GR.  */
7785       switch (size_type)
7786         {
7787         case 0:  fgmovs (cpu); return;
7788         case 3:  fgmovd (cpu); return;
7789         default: HALT_UNALLOC;
7790         }
7791
7792     case 24:                    /* FCVTZS.  */
7793       switch (size_type)
7794         {
7795         case 0: fcvtszs32 (cpu); return;
7796         case 1: fcvtszd32 (cpu); return;
7797         case 2: fcvtszs (cpu); return;
7798         case 3: fcvtszd (cpu); return;
7799         default: HALT_UNREACHABLE;
7800         }
7801
7802     case 25: do_fcvtzu (cpu); return;
7803     case 3:  do_UCVTF (cpu); return;
7804
7805     case 0:     /* FCVTNS.  */
7806     case 1:     /* FCVTNU.  */
7807     case 4:     /* FCVTAS.  */
7808     case 5:     /* FCVTAU.  */
7809     case 8:     /* FCVPTS.  */
7810     case 9:     /* FCVTPU.  */
7811     case 16:    /* FCVTMS.  */
7812     case 17:    /* FCVTMU.  */
7813     default:
7814       HALT_NYI;
7815     }
7816 }
7817
7818 static void
7819 set_flags_for_float_compare (sim_cpu *cpu, float fvalue1, float fvalue2)
7820 {
7821   uint32_t flags;
7822
7823   if (isnan (fvalue1) || isnan (fvalue2))
7824     flags = C|V;
7825   else
7826     {
7827       float result = fvalue1 - fvalue2;
7828
7829       if (result == 0.0)
7830         flags = Z|C;
7831       else if (result < 0)
7832         flags = N;
7833       else /* (result > 0).  */
7834         flags = C;
7835     }
7836
7837   aarch64_set_CPSR (cpu, flags);
7838 }
7839
7840 static void
7841 fcmps (sim_cpu *cpu)
7842 {
7843   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
7844   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
7845
7846   float fvalue1 = aarch64_get_FP_float (cpu, sn);
7847   float fvalue2 = aarch64_get_FP_float (cpu, sm);
7848
7849   set_flags_for_float_compare (cpu, fvalue1, fvalue2);
7850 }
7851
7852 /* Float compare to zero -- Invalid Operation exception
7853    only on signaling NaNs.  */
7854 static void
7855 fcmpzs (sim_cpu *cpu)
7856 {
7857   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
7858   float fvalue1 = aarch64_get_FP_float (cpu, sn);
7859
7860   set_flags_for_float_compare (cpu, fvalue1, 0.0f);
7861 }
7862
7863 /* Float compare -- Invalid Operation exception on all NaNs.  */
7864 static void
7865 fcmpes (sim_cpu *cpu)
7866 {
7867   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
7868   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
7869
7870   float fvalue1 = aarch64_get_FP_float (cpu, sn);
7871   float fvalue2 = aarch64_get_FP_float (cpu, sm);
7872
7873   set_flags_for_float_compare (cpu, fvalue1, fvalue2);
7874 }
7875
7876 /* Float compare to zero -- Invalid Operation exception on all NaNs.  */
7877 static void
7878 fcmpzes (sim_cpu *cpu)
7879 {
7880   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
7881   float fvalue1 = aarch64_get_FP_float (cpu, sn);
7882
7883   set_flags_for_float_compare (cpu, fvalue1, 0.0f);
7884 }
7885
7886 static void
7887 set_flags_for_double_compare (sim_cpu *cpu, double dval1, double dval2)
7888 {
7889   uint32_t flags;
7890
7891   if (isnan (dval1) || isnan (dval2))
7892     flags = C|V;
7893   else
7894     {
7895       double result = dval1 - dval2;
7896
7897       if (result == 0.0)
7898         flags = Z|C;
7899       else if (result < 0)
7900         flags = N;
7901       else /* (result > 0).  */
7902         flags = C;
7903     }
7904
7905   aarch64_set_CPSR (cpu, flags);
7906 }
7907
7908 /* Double compare -- Invalid Operation exception only on signaling NaNs.  */
7909 static void
7910 fcmpd (sim_cpu *cpu)
7911 {
7912   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
7913   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
7914
7915   double dvalue1 = aarch64_get_FP_double (cpu, sn);
7916   double dvalue2 = aarch64_get_FP_double (cpu, sm);
7917
7918   set_flags_for_double_compare (cpu, dvalue1, dvalue2);
7919 }
7920
7921 /* Double compare to zero -- Invalid Operation exception
7922    only on signaling NaNs.  */
7923 static void
7924 fcmpzd (sim_cpu *cpu)
7925 {
7926   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
7927   double dvalue1 = aarch64_get_FP_double (cpu, sn);
7928
7929   set_flags_for_double_compare (cpu, dvalue1, 0.0);
7930 }
7931
7932 /* Double compare -- Invalid Operation exception on all NaNs.  */
7933 static void
7934 fcmped (sim_cpu *cpu)
7935 {
7936   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
7937   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
7938
7939   double dvalue1 = aarch64_get_FP_double (cpu, sn);
7940   double dvalue2 = aarch64_get_FP_double (cpu, sm);
7941
7942   set_flags_for_double_compare (cpu, dvalue1, dvalue2);
7943 }
7944
7945 /* Double compare to zero -- Invalid Operation exception on all NaNs.  */
7946 static void
7947 fcmpzed (sim_cpu *cpu)
7948 {
7949   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
7950   double dvalue1 = aarch64_get_FP_double (cpu, sn);
7951
7952   set_flags_for_double_compare (cpu, dvalue1, 0.0);
7953 }
7954
7955 static void
7956 dexSimpleFPCompare (sim_cpu *cpu)
7957 {
7958   /* assert instr[28,25] == 1111
7959      instr[30:24:21:13,10] = 0011000
7960      instr[31] = M : 0 ==> OK, 1 ==> UNALLOC
7961      instr[29] ==> S :  0 ==> OK, 1 ==> UNALLOC
7962      instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
7963      instr[15,14] ==> op : 00 ==> OK, ow ==> UNALLOC
7964      instr[4,0] ==> opcode2 : 00000 ==> FCMP, 10000 ==> FCMPE,
7965                               01000 ==> FCMPZ, 11000 ==> FCMPEZ,
7966                               ow ==> UNALLOC  */
7967   uint32_t dispatch;
7968   uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
7969     | uimm (aarch64_get_instr (cpu), 29, 29);
7970   uint32_t type = uimm (aarch64_get_instr (cpu), 23, 22);
7971   uint32_t op = uimm (aarch64_get_instr (cpu), 15, 14);
7972   uint32_t op2_2_0 = uimm (aarch64_get_instr (cpu), 2, 0);
7973
7974   if (op2_2_0 != 0)
7975     HALT_UNALLOC;
7976
7977   if (M_S != 0)
7978     HALT_UNALLOC;
7979
7980   if (type > 1)
7981     HALT_UNALLOC;
7982
7983   if (op != 0)
7984     HALT_UNALLOC;
7985
7986   /* dispatch on type and top 2 bits of opcode.  */
7987   dispatch = (type << 2) | uimm (aarch64_get_instr (cpu), 4, 3);
7988
7989   switch (dispatch)
7990     {
7991     case 0: fcmps (cpu); return;
7992     case 1: fcmpzs (cpu); return;
7993     case 2: fcmpes (cpu); return;
7994     case 3: fcmpzes (cpu); return;
7995     case 4: fcmpd (cpu); return;
7996     case 5: fcmpzd (cpu); return;
7997     case 6: fcmped (cpu); return;
7998     case 7: fcmpzed (cpu); return;
7999     default: HALT_UNREACHABLE;
8000     }
8001 }
8002
8003 static void
8004 do_scalar_FADDP (sim_cpu *cpu)
8005 {
8006   /* instr [31,23] = 011111100
8007      instr [22]    = single(0)/double(1)
8008      instr [21,10] = 1100 0011 0110
8009      instr [9,5]   = Fn
8010      instr [4,0]   = Fd.  */
8011
8012   unsigned Fn = uimm (aarch64_get_instr (cpu), 9, 5);
8013   unsigned Fd = uimm (aarch64_get_instr (cpu), 4, 0);
8014
8015   NYI_assert (31, 23, 0x0FC);
8016   NYI_assert (21, 10, 0xC36);
8017
8018   if (uimm (aarch64_get_instr (cpu), 22, 22))
8019     {
8020       double val1 = aarch64_get_vec_double (cpu, Fn, 0);
8021       double val2 = aarch64_get_vec_double (cpu, Fn, 1);
8022
8023       aarch64_set_FP_double (cpu, Fd, val1 + val2);
8024     }
8025   else
8026     {
8027       float val1 = aarch64_get_vec_float (cpu, Fn, 0);
8028       float val2 = aarch64_get_vec_float (cpu, Fn, 1);
8029
8030       aarch64_set_FP_float (cpu, Fd, val1 + val2);
8031     }
8032 }
8033
8034 /* Floating point absolute difference.  */
8035
8036 static void
8037 do_scalar_FABD (sim_cpu *cpu)
8038 {
8039   /* instr [31,23] = 0111 1110 1
8040      instr [22]    = float(0)/double(1)
8041      instr [21]    = 1
8042      instr [20,16] = Rm
8043      instr [15,10] = 1101 01
8044      instr [9, 5]  = Rn
8045      instr [4, 0]  = Rd.  */
8046
8047   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8048   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8049   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8050
8051   NYI_assert (31, 23, 0x0FD);
8052   NYI_assert (21, 21, 1);
8053   NYI_assert (15, 10, 0x35);
8054
8055   if (uimm (aarch64_get_instr (cpu), 22, 22))
8056     aarch64_set_FP_double (cpu, rd,
8057                            fabs (aarch64_get_FP_double (cpu, rn)
8058                                  - aarch64_get_FP_double (cpu, rm)));
8059   else
8060     aarch64_set_FP_float (cpu, rd,
8061                           fabsf (aarch64_get_FP_float (cpu, rn)
8062                                  - aarch64_get_FP_float (cpu, rm)));
8063 }
8064
8065 static void
8066 do_scalar_CMGT (sim_cpu *cpu)
8067 {
8068   /* instr [31,21] = 0101 1110 111
8069      instr [20,16] = Rm
8070      instr [15,10] = 00 1101
8071      instr [9, 5]  = Rn
8072      instr [4, 0]  = Rd.  */
8073
8074   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8075   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8076   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8077
8078   NYI_assert (31, 21, 0x2F7);
8079   NYI_assert (15, 10, 0x0D);
8080
8081   aarch64_set_vec_u64 (cpu, rd, 0,
8082                        aarch64_get_vec_u64 (cpu, rn, 0) >
8083                        aarch64_get_vec_u64 (cpu, rm, 0) ? -1L : 0L);
8084 }
8085
8086 static void
8087 do_scalar_USHR (sim_cpu *cpu)
8088 {
8089   /* instr [31,23] = 0111 1111 0
8090      instr [22,16] = shift amount
8091      instr [15,10] = 0000 01
8092      instr [9, 5]  = Rn
8093      instr [4, 0]  = Rd.  */
8094
8095   unsigned amount = 128 - uimm (aarch64_get_instr (cpu), 22, 16);
8096   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8097   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8098
8099   NYI_assert (31, 23, 0x0FE);
8100   NYI_assert (15, 10, 0x01);
8101
8102   aarch64_set_vec_u64 (cpu, rd, 0,
8103                        aarch64_get_vec_u64 (cpu, rn, 0) >> amount);
8104 }
8105
8106 static void
8107 do_scalar_SHL (sim_cpu *cpu)
8108 {
8109   /* instr [31,23] = 0111 1101 0
8110      instr [22,16] = shift amount
8111      instr [15,10] = 0101 01
8112      instr [9, 5]  = Rn
8113      instr [4, 0]  = Rd.  */
8114
8115   unsigned amount = uimm (aarch64_get_instr (cpu), 22, 16) - 64;
8116   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8117   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8118
8119   NYI_assert (31, 23, 0x0BE);
8120   NYI_assert (15, 10, 0x15);
8121
8122   if (uimm (aarch64_get_instr (cpu), 22, 22) == 0)
8123     HALT_UNALLOC;
8124
8125   aarch64_set_vec_u64 (cpu, rd, 0,
8126                        aarch64_get_vec_u64 (cpu, rn, 0) << amount);
8127 }
8128
8129 /* FCMEQ FCMGT FCMGE.  */
8130 static void
8131 do_scalar_FCM (sim_cpu *cpu)
8132 {
8133   /* instr [31,30] = 01
8134      instr [29]    = U
8135      instr [28,24] = 1 1110
8136      instr [23]    = E
8137      instr [22]    = size
8138      instr [21]    = 1
8139      instr [20,16] = Rm
8140      instr [15,12] = 1110
8141      instr [11]    = AC
8142      instr [10]    = 1
8143      instr [9, 5]  = Rn
8144      instr [4, 0]  = Rd.  */
8145
8146   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8147   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8148   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8149   unsigned EUac = (uimm (aarch64_get_instr (cpu), 23, 23) << 2)
8150     | (uimm (aarch64_get_instr (cpu), 29, 29) << 1)
8151     | uimm (aarch64_get_instr (cpu), 11, 11);
8152   unsigned result;
8153   float val1;
8154   float val2;
8155
8156   NYI_assert (31, 30, 1);
8157   NYI_assert (28, 24, 0x1E);
8158   NYI_assert (21, 21, 1);
8159   NYI_assert (15, 12, 0xE);
8160   NYI_assert (10, 10, 1);
8161
8162   if (uimm (aarch64_get_instr (cpu), 22, 22))
8163     {
8164       double val1 = aarch64_get_FP_double (cpu, rn);
8165       double val2 = aarch64_get_FP_double (cpu, rm);
8166
8167       switch (EUac)
8168         {
8169         case 0: /* 000 */
8170           result = val1 == val2;
8171           break;
8172
8173         case 3: /* 011 */
8174           val1 = fabs (val1);
8175           val2 = fabs (val2);
8176           /* Fall through. */
8177         case 2: /* 010 */
8178           result = val1 >= val2;
8179           break;
8180
8181         case 7: /* 111 */
8182           val1 = fabs (val1);
8183           val2 = fabs (val2);
8184           /* Fall through. */
8185         case 6: /* 110 */
8186           result = val1 > val2;
8187           break;
8188
8189         default:
8190           HALT_UNALLOC;
8191         }
8192
8193       aarch64_set_vec_u32 (cpu, rd, 0, result ? -1 : 0);
8194       return;
8195     }
8196
8197   val1 = aarch64_get_FP_float (cpu, rn);
8198   val2 = aarch64_get_FP_float (cpu, rm);
8199
8200   switch (EUac)
8201     {
8202     case 0: /* 000 */
8203       result = val1 == val2;
8204       break;
8205
8206     case 3: /* 011 */
8207       val1 = fabsf (val1);
8208       val2 = fabsf (val2);
8209       /* Fall through. */
8210     case 2: /* 010 */
8211       result = val1 >= val2;
8212       break;
8213
8214     case 7: /* 111 */
8215       val1 = fabsf (val1);
8216       val2 = fabsf (val2);
8217       /* Fall through. */
8218     case 6: /* 110 */
8219       result = val1 > val2;
8220       break;
8221
8222     default:
8223       HALT_UNALLOC;
8224     }
8225
8226   aarch64_set_vec_u32 (cpu, rd, 0, result ? -1 : 0);
8227 }
8228
8229 /* An alias of DUP.  */
8230 static void
8231 do_scalar_MOV (sim_cpu *cpu)
8232 {
8233   /* instr [31,21] = 0101 1110 000
8234      instr [20,16] = imm5
8235      instr [15,10] = 0000 01
8236      instr [9, 5]  = Rn
8237      instr [4, 0]  = Rd.  */
8238
8239   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8240   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8241   unsigned index;
8242
8243   NYI_assert (31, 21, 0x2F0);
8244   NYI_assert (15, 10, 0x01);
8245
8246   if (uimm (aarch64_get_instr (cpu), 16, 16))
8247     {
8248       /* 8-bit.  */
8249       index = uimm (aarch64_get_instr (cpu), 20, 17);
8250       aarch64_set_vec_u8
8251         (cpu, rd, 0, aarch64_get_vec_u8 (cpu, rn, index));
8252     }
8253   else if (uimm (aarch64_get_instr (cpu), 17, 17))
8254     {
8255       /* 16-bit.  */
8256       index = uimm (aarch64_get_instr (cpu), 20, 18);
8257       aarch64_set_vec_u16
8258         (cpu, rd, 0, aarch64_get_vec_u16 (cpu, rn, index));
8259     }
8260   else if (uimm (aarch64_get_instr (cpu), 18, 18))
8261     {
8262       /* 32-bit.  */
8263       index = uimm (aarch64_get_instr (cpu), 20, 19);
8264       aarch64_set_vec_u32
8265         (cpu, rd, 0, aarch64_get_vec_u32 (cpu, rn, index));
8266     }
8267   else if (uimm (aarch64_get_instr (cpu), 19, 19))
8268     {
8269       /* 64-bit.  */
8270       index = uimm (aarch64_get_instr (cpu), 20, 20);
8271       aarch64_set_vec_u64
8272         (cpu, rd, 0, aarch64_get_vec_u64 (cpu, rn, index));
8273     }
8274   else
8275     HALT_UNALLOC;
8276 }
8277
8278 static void
8279 do_scalar_NEG (sim_cpu *cpu)
8280 {
8281   /* instr [31,24] = 0111 1110
8282      instr [23,22] = 11
8283      instr [21,10] = 1000 0010 1110
8284      instr [9, 5]  = Rn
8285      instr [4, 0]  = Rd.  */
8286
8287   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8288   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8289
8290   NYI_assert (31, 24, 0x7E);
8291   NYI_assert (21, 10, 0x82E);
8292   NYI_assert (23, 22, 3);
8293
8294   aarch64_set_vec_u64 (cpu, rd, 0, - aarch64_get_vec_u64 (cpu, rn, 0));
8295 }
8296
8297 static void
8298 do_double_add (sim_cpu *cpu)
8299 {
8300   /* instr [28,25] = 1111.  */
8301   unsigned Fd;
8302   unsigned Fm;
8303   unsigned Fn;
8304   double val1;
8305   double val2;
8306
8307   switch (uimm (aarch64_get_instr (cpu), 31, 23))
8308     {
8309     case 0xBC:
8310       switch (uimm (aarch64_get_instr (cpu), 15, 10))
8311         {
8312         case 0x01: do_scalar_MOV (cpu); return;
8313         case 0x39: do_scalar_FCM (cpu); return;
8314         case 0x3B: do_scalar_FCM (cpu); return;
8315         }
8316       break;
8317
8318     case 0xBE: do_scalar_SHL (cpu); return;
8319
8320     case 0xFC:
8321       switch (uimm (aarch64_get_instr (cpu), 15, 10))
8322         {
8323         case 0x36: do_scalar_FADDP (cpu); return;
8324         case 0x39: do_scalar_FCM (cpu); return;
8325         case 0x3B: do_scalar_FCM (cpu); return;
8326         }
8327       break;
8328
8329     case 0xFD:
8330       switch (uimm (aarch64_get_instr (cpu), 15, 10))
8331         {
8332         case 0x0D: do_scalar_CMGT (cpu); return;
8333         case 0x35: do_scalar_FABD (cpu); return;
8334         case 0x39: do_scalar_FCM (cpu); return;
8335         case 0x3B: do_scalar_FCM (cpu); return;
8336         case 0x2E: do_scalar_NEG (cpu); return;
8337         default:
8338           HALT_NYI;
8339         }
8340
8341     case 0xFE: do_scalar_USHR (cpu); return;
8342     default:
8343       break;
8344     }
8345
8346   /* instr [31,21] = 0101 1110 111
8347      instr [20,16] = Fn
8348      instr [15,10] = 1000 01
8349      instr [9,5]   = Fm
8350      instr [4,0]   = Fd.  */
8351   if (uimm (aarch64_get_instr (cpu), 31, 21) != 0x2F7
8352       || uimm (aarch64_get_instr (cpu), 15, 10) != 0x21)
8353     HALT_NYI;
8354
8355   Fd = uimm (aarch64_get_instr (cpu), 4, 0);
8356   Fm = uimm (aarch64_get_instr (cpu), 9, 5);
8357   Fn = uimm (aarch64_get_instr (cpu), 20, 16);
8358
8359   val1 = aarch64_get_FP_double (cpu, Fm);
8360   val2 = aarch64_get_FP_double (cpu, Fn);
8361
8362   aarch64_set_FP_double (cpu, Fd, val1 + val2);
8363 }
8364
8365 static void
8366 dexAdvSIMD1 (sim_cpu *cpu)
8367 {
8368   /* instr [28,25] = 1 111.  */
8369
8370   /* we are currently only interested in the basic
8371      scalar fp routines which all have bit 30 = 0.  */
8372   if (uimm (aarch64_get_instr (cpu), 30, 30))
8373     do_double_add (cpu);
8374
8375   /* instr[24] is set for FP data processing 3-source and clear for
8376      all other basic scalar fp instruction groups.  */
8377   else if (uimm (aarch64_get_instr (cpu), 24, 24))
8378     dexSimpleFPDataProc3Source (cpu);
8379
8380   /* instr[21] is clear for floating <-> fixed conversions and set for
8381      all other basic scalar fp instruction groups.  */
8382   else if (!uimm (aarch64_get_instr (cpu), 21, 21))
8383     dexSimpleFPFixedConvert (cpu);
8384
8385   /* instr[11,10] : 01 ==> cond compare, 10 ==> Data Proc 2 Source
8386      11 ==> cond select,  00 ==> other.  */
8387   else
8388     switch (uimm (aarch64_get_instr (cpu), 11, 10))
8389       {
8390       case 1: dexSimpleFPCondCompare (cpu); return;
8391       case 2: dexSimpleFPDataProc2Source (cpu); return;
8392       case 3: dexSimpleFPCondSelect (cpu); return;
8393
8394       default:
8395         /* Now an ordered cascade of tests.
8396            FP immediate has aarch64_get_instr (cpu)[12] == 1.
8397            FP compare has aarch64_get_instr (cpu)[13] == 1.
8398            FP Data Proc 1 Source has aarch64_get_instr (cpu)[14] == 1.
8399            FP floating <--> integer conversions has aarch64_get_instr (cpu)[15] == 0.  */
8400         if (uimm (aarch64_get_instr (cpu), 12, 12))
8401           dexSimpleFPImmediate (cpu);
8402
8403         else if (uimm (aarch64_get_instr (cpu), 13, 13))
8404           dexSimpleFPCompare (cpu);
8405
8406         else if (uimm (aarch64_get_instr (cpu), 14, 14))
8407           dexSimpleFPDataProc1Source (cpu);
8408
8409         else if (!uimm (aarch64_get_instr (cpu), 15, 15))
8410           dexSimpleFPIntegerConvert (cpu);
8411
8412         else
8413           /* If we get here then instr[15] == 1 which means UNALLOC.  */
8414           HALT_UNALLOC;
8415       }
8416 }
8417
8418 /* PC relative addressing.  */
8419
8420 static void
8421 pcadr (sim_cpu *cpu)
8422 {
8423   /* instr[31] = op : 0 ==> ADR, 1 ==> ADRP
8424      instr[30,29] = immlo
8425      instr[23,5] = immhi.  */
8426   uint64_t address;
8427   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8428   uint32_t isPage = uimm (aarch64_get_instr (cpu), 31, 31);
8429   union { int64_t u64; uint64_t s64; } imm;
8430   uint64_t offset;
8431
8432   imm.s64 = simm64 (aarch64_get_instr (cpu), 23, 5);
8433   offset = imm.u64;
8434   offset = (offset << 2) | uimm (aarch64_get_instr (cpu), 30, 29);
8435
8436   address = aarch64_get_PC (cpu);
8437
8438   if (isPage)
8439     {
8440       offset <<= 12;
8441       address &= ~0xfff;
8442     }
8443
8444   aarch64_set_reg_u64 (cpu, rd, NO_SP, address + offset);
8445 }
8446
8447 /* Specific decode and execute for group Data Processing Immediate.  */
8448
8449 static void
8450 dexPCRelAddressing (sim_cpu *cpu)
8451 {
8452   /* assert instr[28,24] = 10000.  */
8453   pcadr (cpu);
8454 }
8455
8456 /* Immediate logical.
8457    The bimm32/64 argument is constructed by replicating a 2, 4, 8,
8458    16, 32 or 64 bit sequence pulled out at decode and possibly
8459    inverting it..
8460
8461    N.B. the output register (dest) can normally be Xn or SP
8462    the exception occurs for flag setting instructions which may
8463    only use Xn for the output (dest).  The input register can
8464    never be SP.  */
8465
8466 /* 32 bit and immediate.  */
8467 static void
8468 and32 (sim_cpu *cpu, uint32_t bimm)
8469 {
8470   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8471   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8472
8473   aarch64_set_reg_u64 (cpu, rd, SP_OK,
8474                        aarch64_get_reg_u32 (cpu, rn, NO_SP) & bimm);
8475 }
8476
8477 /* 64 bit and immediate.  */
8478 static void
8479 and64 (sim_cpu *cpu, uint64_t bimm)
8480 {
8481   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8482   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8483
8484   aarch64_set_reg_u64 (cpu, rd, SP_OK,
8485                        aarch64_get_reg_u64 (cpu, rn, NO_SP) & bimm);
8486 }
8487
8488 /* 32 bit and immediate set flags.  */
8489 static void
8490 ands32 (sim_cpu *cpu, uint32_t bimm)
8491 {
8492   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8493   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8494
8495   uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8496   uint32_t value2 = bimm;
8497
8498   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8499   set_flags_for_binop32 (cpu, value1 & value2);
8500 }
8501
8502 /* 64 bit and immediate set flags.  */
8503 static void
8504 ands64 (sim_cpu *cpu, uint64_t bimm)
8505 {
8506   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8507   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8508
8509   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
8510   uint64_t value2 = bimm;
8511
8512   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8513   set_flags_for_binop64 (cpu, value1 & value2);
8514 }
8515
8516 /* 32 bit exclusive or immediate.  */
8517 static void
8518 eor32 (sim_cpu *cpu, uint32_t bimm)
8519 {
8520   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8521   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8522
8523   aarch64_set_reg_u64 (cpu, rd, SP_OK,
8524                        aarch64_get_reg_u32 (cpu, rn, NO_SP) ^ bimm);
8525 }
8526
8527 /* 64 bit exclusive or immediate.  */
8528 static void
8529 eor64 (sim_cpu *cpu, uint64_t bimm)
8530 {
8531   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8532   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8533
8534   aarch64_set_reg_u64 (cpu, rd, SP_OK,
8535                        aarch64_get_reg_u64 (cpu, rn, NO_SP) ^ bimm);
8536 }
8537
8538 /* 32 bit or immediate.  */
8539 static void
8540 orr32 (sim_cpu *cpu, uint32_t bimm)
8541 {
8542   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8543   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8544
8545   aarch64_set_reg_u64 (cpu, rd, SP_OK,
8546                        aarch64_get_reg_u32 (cpu, rn, NO_SP) | bimm);
8547 }
8548
8549 /* 64 bit or immediate.  */
8550 static void
8551 orr64 (sim_cpu *cpu, uint64_t bimm)
8552 {
8553   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8554   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8555
8556   aarch64_set_reg_u64 (cpu, rd, SP_OK,
8557                        aarch64_get_reg_u64 (cpu, rn, NO_SP) | bimm);
8558 }
8559
8560 /* Logical shifted register.
8561    These allow an optional LSL, ASR, LSR or ROR to the second source
8562    register with a count up to the register bit count.
8563    N.B register args may not be SP.  */
8564
8565 /* 32 bit AND shifted register.  */
8566 static void
8567 and32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8568 {
8569   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8570   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8571   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8572
8573   aarch64_set_reg_u64
8574     (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8575      & shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8576 }
8577
8578 /* 64 bit AND shifted register.  */
8579 static void
8580 and64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8581 {
8582   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8583   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8584   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8585
8586   aarch64_set_reg_u64
8587     (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8588      & shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8589 }
8590
8591 /* 32 bit AND shifted register setting flags.  */
8592 static void
8593 ands32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8594 {
8595   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8596   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8597   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8598
8599   uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8600   uint32_t value2 = shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
8601                                shift, count);
8602
8603   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8604   set_flags_for_binop32 (cpu, value1 & value2);
8605 }
8606
8607 /* 64 bit AND shifted register setting flags.  */
8608 static void
8609 ands64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8610 {
8611   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8612   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8613   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8614
8615   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
8616   uint64_t value2 = shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
8617                                shift, count);
8618
8619   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8620   set_flags_for_binop64 (cpu, value1 & value2);
8621 }
8622
8623 /* 32 bit BIC shifted register.  */
8624 static void
8625 bic32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8626 {
8627   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8628   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8629   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8630
8631   aarch64_set_reg_u64
8632     (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8633      & ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8634 }
8635
8636 /* 64 bit BIC shifted register.  */
8637 static void
8638 bic64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8639 {
8640   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8641   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8642   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8643
8644   aarch64_set_reg_u64
8645     (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8646      & ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8647 }
8648
8649 /* 32 bit BIC shifted register setting flags.  */
8650 static void
8651 bics32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8652 {
8653   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8654   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8655   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8656
8657   uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8658   uint32_t value2 = ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
8659                                  shift, count);
8660
8661   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8662   set_flags_for_binop32 (cpu, value1 & value2);
8663 }
8664
8665 /* 64 bit BIC shifted register setting flags.  */
8666 static void
8667 bics64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8668 {
8669   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8670   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8671   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8672
8673   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
8674   uint64_t value2 = ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
8675                                  shift, count);
8676
8677   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8678   set_flags_for_binop64 (cpu, value1 & value2);
8679 }
8680
8681 /* 32 bit EON shifted register.  */
8682 static void
8683 eon32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8684 {
8685   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8686   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8687   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8688
8689   aarch64_set_reg_u64
8690     (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8691      ^ ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8692 }
8693
8694 /* 64 bit EON shifted register.  */
8695 static void
8696 eon64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8697 {
8698   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8699   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8700   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8701
8702   aarch64_set_reg_u64
8703     (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8704      ^ ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8705 }
8706
8707 /* 32 bit EOR shifted register.  */
8708 static void
8709 eor32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8710 {
8711   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8712   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8713   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8714
8715   aarch64_set_reg_u64
8716     (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8717      ^ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8718 }
8719
8720 /* 64 bit EOR shifted register.  */
8721 static void
8722 eor64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8723 {
8724   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8725   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8726   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8727
8728   aarch64_set_reg_u64
8729     (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8730      ^ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8731 }
8732
8733 /* 32 bit ORR shifted register.  */
8734 static void
8735 orr32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8736 {
8737   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8738   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8739   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8740
8741   aarch64_set_reg_u64
8742     (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8743      | shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8744 }
8745
8746 /* 64 bit ORR shifted register.  */
8747 static void
8748 orr64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8749 {
8750   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8751   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8752   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8753
8754   aarch64_set_reg_u64
8755     (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8756      | shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8757 }
8758
8759 /* 32 bit ORN shifted register.  */
8760 static void
8761 orn32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8762 {
8763   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8764   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8765   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8766
8767   aarch64_set_reg_u64
8768     (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8769      | ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8770 }
8771
8772 /* 64 bit ORN shifted register.  */
8773 static void
8774 orn64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8775 {
8776   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8777   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8778   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8779
8780   aarch64_set_reg_u64
8781     (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8782      | ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8783 }
8784
8785 static void
8786 dexLogicalImmediate (sim_cpu *cpu)
8787 {
8788   /* assert instr[28,23] = 1001000
8789      instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
8790      instr[30,29] = op : 0 ==> AND, 1 ==> ORR, 2 ==> EOR, 3 ==> ANDS
8791      instr[22] = N : used to construct immediate mask
8792      instr[21,16] = immr
8793      instr[15,10] = imms
8794      instr[9,5] = Rn
8795      instr[4,0] = Rd  */
8796
8797   /* 32 bit operations must have N = 0 or else we have an UNALLOC.  */
8798   uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
8799   uint32_t N = uimm (aarch64_get_instr (cpu), 22, 22);
8800   /* uint32_t immr = uimm (aarch64_get_instr (cpu), 21, 16);.  */
8801   /* uint32_t imms = uimm (aarch64_get_instr (cpu), 15, 10);.  */
8802   uint32_t index = uimm (aarch64_get_instr (cpu), 22, 10);
8803   uint64_t bimm64 = LITable [index];
8804   uint32_t dispatch = uimm (aarch64_get_instr (cpu), 30, 29);
8805
8806   if (~size & N)
8807     HALT_UNALLOC;
8808
8809   if (!bimm64)
8810     HALT_UNALLOC;
8811
8812   if (size == 0)
8813     {
8814       uint32_t bimm = (uint32_t) bimm64;
8815
8816       switch (dispatch)
8817         {
8818         case 0: and32 (cpu, bimm); return;
8819         case 1: orr32 (cpu, bimm); return;
8820         case 2: eor32 (cpu, bimm); return;
8821         case 3: ands32 (cpu, bimm); return;
8822         }
8823     }
8824   else
8825     {
8826       switch (dispatch)
8827         {
8828         case 0: and64 (cpu, bimm64); return;
8829         case 1: orr64 (cpu, bimm64); return;
8830         case 2: eor64 (cpu, bimm64); return;
8831         case 3: ands64 (cpu, bimm64); return;
8832         }
8833     }
8834   HALT_UNALLOC;
8835 }
8836
8837 /* Immediate move.
8838    The uimm argument is a 16 bit value to be inserted into the
8839    target register the pos argument locates the 16 bit word in the
8840    dest register i.e. it is in {0, 1} for 32 bit and {0, 1, 2,
8841    3} for 64 bit.
8842    N.B register arg may not be SP so it should be.
8843    accessed using the setGZRegisterXXX accessors.  */
8844
8845 /* 32 bit move 16 bit immediate zero remaining shorts.  */
8846 static void
8847 movz32 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8848 {
8849   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8850
8851   aarch64_set_reg_u64 (cpu, rd, NO_SP, val << (pos * 16));
8852 }
8853
8854 /* 64 bit move 16 bit immediate zero remaining shorts.  */
8855 static void
8856 movz64 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8857 {
8858   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8859
8860   aarch64_set_reg_u64 (cpu, rd, NO_SP, ((uint64_t) val) << (pos * 16));
8861 }
8862
8863 /* 32 bit move 16 bit immediate negated.  */
8864 static void
8865 movn32 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8866 {
8867   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8868
8869   aarch64_set_reg_u64 (cpu, rd, NO_SP, ((val << (pos * 16)) ^ 0xffffffffU));
8870 }
8871
8872 /* 64 bit move 16 bit immediate negated.  */
8873 static void
8874 movn64 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8875 {
8876   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8877
8878   aarch64_set_reg_u64
8879     (cpu, rd, NO_SP, ((((uint64_t) val) << (pos * 16))
8880                       ^ 0xffffffffffffffffULL));
8881 }
8882
8883 /* 32 bit move 16 bit immediate keep remaining shorts.  */
8884 static void
8885 movk32 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8886 {
8887   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8888   uint32_t current = aarch64_get_reg_u32 (cpu, rd, NO_SP);
8889   uint32_t value = val << (pos * 16);
8890   uint32_t mask = ~(0xffffU << (pos * 16));
8891
8892   aarch64_set_reg_u64 (cpu, rd, NO_SP, (value | (current & mask)));
8893 }
8894
8895 /* 64 bit move 16 it immediate keep remaining shorts.  */
8896 static void
8897 movk64 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8898 {
8899   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8900   uint64_t current = aarch64_get_reg_u64 (cpu, rd, NO_SP);
8901   uint64_t value = (uint64_t) val << (pos * 16);
8902   uint64_t mask = ~(0xffffULL << (pos * 16));
8903
8904   aarch64_set_reg_u64 (cpu, rd, NO_SP, (value | (current & mask)));
8905 }
8906
8907 static void
8908 dexMoveWideImmediate (sim_cpu *cpu)
8909 {
8910   /* assert instr[28:23] = 100101
8911      instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
8912      instr[30,29] = op : 0 ==> MOVN, 1 ==> UNALLOC, 2 ==> MOVZ, 3 ==> MOVK
8913      instr[22,21] = shift : 00 == LSL#0, 01 = LSL#16, 10 = LSL#32, 11 = LSL#48
8914      instr[20,5] = uimm16
8915      instr[4,0] = Rd  */
8916
8917   /* N.B. the (multiple of 16) shift is applied by the called routine,
8918      we just pass the multiplier.  */
8919
8920   uint32_t imm;
8921   uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
8922   uint32_t op = uimm (aarch64_get_instr (cpu), 30, 29);
8923   uint32_t shift = uimm (aarch64_get_instr (cpu), 22, 21);
8924
8925   /* 32 bit can only shift 0 or 1 lot of 16.
8926      anything else is an unallocated instruction.  */
8927   if (size == 0 && (shift > 1))
8928     HALT_UNALLOC;
8929
8930   if (op == 1)
8931     HALT_UNALLOC;
8932
8933   imm = uimm (aarch64_get_instr (cpu), 20, 5);
8934
8935   if (size == 0)
8936     {
8937       if (op == 0)
8938         movn32 (cpu, imm, shift);
8939       else if (op == 2)
8940         movz32 (cpu, imm, shift);
8941       else
8942         movk32 (cpu, imm, shift);
8943     }
8944   else
8945     {
8946       if (op == 0)
8947         movn64 (cpu, imm, shift);
8948       else if (op == 2)
8949         movz64 (cpu, imm, shift);
8950       else
8951         movk64 (cpu, imm, shift);
8952     }
8953 }
8954
8955 /* Bitfield operations.
8956    These take a pair of bit positions r and s which are in {0..31}
8957    or {0..63} depending on the instruction word size.
8958    N.B register args may not be SP.  */
8959
8960 /* OK, we start with ubfm which just needs to pick
8961    some bits out of source zero the rest and write
8962    the result to dest.  Just need two logical shifts.  */
8963
8964 /* 32 bit bitfield move, left and right of affected zeroed
8965    if r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>.  */
8966 static void
8967 ubfm32 (sim_cpu *cpu, uint32_t r, uint32_t s)
8968 {
8969   unsigned rd;
8970   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8971   uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8972
8973   /* Pick either s+1-r or s+1 consecutive bits out of the original word.  */
8974   if (r <= s)
8975     {
8976       /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
8977          We want only bits s:xxx:r at the bottom of the word
8978          so we LSL bit s up to bit 31 i.e. by 31 - s
8979          and then we LSR to bring bit 31 down to bit s - r
8980          i.e. by 31 + r - s.  */
8981       value <<= 31 - s;
8982       value >>= 31 + r - s;
8983     }
8984   else
8985     {
8986       /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0
8987          We want only bits s:xxx:0 starting at it 31-(r-1)
8988          so we LSL bit s up to bit 31 i.e. by 31 - s
8989          and then we LSL to bring bit 31 down to 31-(r-1)+s
8990          i.e. by r - (s + 1).  */
8991       value <<= 31 - s;
8992       value >>= r - (s + 1);
8993     }
8994
8995   rd = uimm (aarch64_get_instr (cpu), 4, 0);
8996   aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
8997 }
8998
8999 /* 64 bit bitfield move, left and right of affected zeroed
9000    if r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>.  */
9001 static void
9002 ubfm (sim_cpu *cpu, uint32_t r, uint32_t s)
9003 {
9004   unsigned rd;
9005   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9006   uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
9007
9008   if (r <= s)
9009     {
9010       /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
9011          We want only bits s:xxx:r at the bottom of the word.
9012          So we LSL bit s up to bit 63 i.e. by 63 - s
9013          and then we LSR to bring bit 63 down to bit s - r
9014          i.e. by 63 + r - s.  */
9015       value <<= 63 - s;
9016       value >>= 63 + r - s;
9017     }
9018   else
9019     {
9020       /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0.
9021          We want only bits s:xxx:0 starting at it 63-(r-1).
9022          So we LSL bit s up to bit 63 i.e. by 63 - s
9023          and then we LSL to bring bit 63 down to 63-(r-1)+s
9024          i.e. by r - (s + 1).  */
9025       value <<= 63 - s;
9026       value >>= r - (s + 1);
9027     }
9028
9029   rd = uimm (aarch64_get_instr (cpu), 4, 0);
9030   aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
9031 }
9032
9033 /* The signed versions need to insert sign bits
9034    on the left of the inserted bit field. so we do
9035    much the same as the unsigned version except we
9036    use an arithmetic shift right -- this just means
9037    we need to operate on signed values.  */
9038
9039 /* 32 bit bitfield move, left of affected sign-extended, right zeroed.  */
9040 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>.  */
9041 static void
9042 sbfm32 (sim_cpu *cpu, uint32_t r, uint32_t s)
9043 {
9044   unsigned rd;
9045   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9046   /* as per ubfm32 but use an ASR instead of an LSR.  */
9047   int32_t value = aarch64_get_reg_s32 (cpu, rn, NO_SP);
9048
9049   if (r <= s)
9050     {
9051       value <<= 31 - s;
9052       value >>= 31 + r - s;
9053     }
9054   else
9055     {
9056       value <<= 31 - s;
9057       value >>= r - (s + 1);
9058     }
9059
9060   rd = uimm (aarch64_get_instr (cpu), 4, 0);
9061   aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) value);
9062 }
9063
9064 /* 64 bit bitfield move, left of affected sign-extended, right zeroed.  */
9065 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>.  */
9066 static void
9067 sbfm (sim_cpu *cpu, uint32_t r, uint32_t s)
9068 {
9069   unsigned rd;
9070   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9071   /* acpu per ubfm but use an ASR instead of an LSR.  */
9072   int64_t value = aarch64_get_reg_s64 (cpu, rn, NO_SP);
9073
9074   if (r <= s)
9075     {
9076       value <<= 63 - s;
9077       value >>= 63 + r - s;
9078     }
9079   else
9080     {
9081       value <<= 63 - s;
9082       value >>= r - (s + 1);
9083     }
9084
9085   rd = uimm (aarch64_get_instr (cpu), 4, 0);
9086   aarch64_set_reg_s64 (cpu, rd, NO_SP, value);
9087 }
9088
9089 /* Finally, these versions leave non-affected bits
9090    as is. so we need to generate the bits as per
9091    ubfm and also generate a mask to pick the
9092    bits from the original and computed values.  */
9093
9094 /* 32 bit bitfield move, non-affected bits left as is.
9095    If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>.  */
9096 static void
9097 bfm32 (sim_cpu *cpu, uint32_t r, uint32_t s)
9098 {
9099   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9100   uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
9101   uint32_t mask = -1;
9102   unsigned rd;
9103   uint32_t value2;
9104
9105   /* Pick either s+1-r or s+1 consecutive bits out of the original word.  */
9106   if (r <= s)
9107     {
9108       /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
9109          We want only bits s:xxx:r at the bottom of the word
9110          so we LSL bit s up to bit 31 i.e. by 31 - s
9111          and then we LSR to bring bit 31 down to bit s - r
9112          i.e. by 31 + r - s.  */
9113       value <<= 31 - s;
9114       value >>= 31 + r - s;
9115       /* the mask must include the same bits.  */
9116       mask <<= 31 - s;
9117       mask >>= 31 + r - s;
9118     }
9119   else
9120     {
9121       /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0.
9122          We want only bits s:xxx:0 starting at it 31-(r-1)
9123          so we LSL bit s up to bit 31 i.e. by 31 - s
9124          and then we LSL to bring bit 31 down to 31-(r-1)+s
9125          i.e. by r - (s + 1).  */
9126       value <<= 31 - s;
9127       value >>= r - (s + 1);
9128       /* The mask must include the same bits.  */
9129       mask <<= 31 - s;
9130       mask >>= r - (s + 1);
9131     }
9132
9133   rd = uimm (aarch64_get_instr (cpu), 4, 0);
9134   value2 = aarch64_get_reg_u32 (cpu, rd, NO_SP);
9135
9136   value2 &= ~mask;
9137   value2 |= value;
9138
9139   aarch64_set_reg_u64
9140     (cpu, rd, NO_SP, (aarch64_get_reg_u32 (cpu, rd, NO_SP) & ~mask) | value);
9141 }
9142
9143 /* 64 bit bitfield move, non-affected bits left as is.
9144    If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>.  */
9145 static void
9146 bfm (sim_cpu *cpu, uint32_t r, uint32_t s)
9147 {
9148   unsigned rd;
9149   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9150   uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
9151   uint64_t mask = 0xffffffffffffffffULL;
9152
9153   if (r <= s)
9154     {
9155       /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
9156          We want only bits s:xxx:r at the bottom of the word
9157          so we LSL bit s up to bit 63 i.e. by 63 - s
9158          and then we LSR to bring bit 63 down to bit s - r
9159          i.e. by 63 + r - s.  */
9160       value <<= 63 - s;
9161       value >>= 63 + r - s;
9162       /* The mask must include the same bits.  */
9163       mask <<= 63 - s;
9164       mask >>= 63 + r - s;
9165     }
9166   else
9167     {
9168       /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0
9169          We want only bits s:xxx:0 starting at it 63-(r-1)
9170          so we LSL bit s up to bit 63 i.e. by 63 - s
9171          and then we LSL to bring bit 63 down to 63-(r-1)+s
9172          i.e. by r - (s + 1).  */
9173       value <<= 63 - s;
9174       value >>= r - (s + 1);
9175       /* The mask must include the same bits.  */
9176       mask <<= 63 - s;
9177       mask >>= r - (s + 1);
9178     }
9179
9180   rd = uimm (aarch64_get_instr (cpu), 4, 0);
9181   aarch64_set_reg_u64
9182     (cpu, rd, NO_SP, (aarch64_get_reg_u64 (cpu, rd, NO_SP) & ~mask) | value);
9183 }
9184
9185 static void
9186 dexBitfieldImmediate (sim_cpu *cpu)
9187 {
9188   /* assert instr[28:23] = 100110
9189      instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9190      instr[30,29] = op : 0 ==> SBFM, 1 ==> BFM, 2 ==> UBFM, 3 ==> UNALLOC
9191      instr[22] = N : must be 0 for 32 bit, 1 for 64 bit ow UNALLOC
9192      instr[21,16] = immr : 0xxxxx for 32 bit, xxxxxx for 64 bit
9193      instr[15,10] = imms :  0xxxxx for 32 bit, xxxxxx for 64 bit
9194      instr[9,5] = Rn
9195      instr[4,0] = Rd  */
9196
9197   /* 32 bit operations must have N = 0 or else we have an UNALLOC.  */
9198   uint32_t dispatch;
9199   uint32_t imms;
9200   uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
9201   uint32_t N = uimm (aarch64_get_instr (cpu), 22, 22);
9202   /* 32 bit operations must have immr[5] = 0 and imms[5] = 0.  */
9203   /* or else we have an UNALLOC.  */
9204   uint32_t immr = uimm (aarch64_get_instr (cpu), 21, 16);
9205
9206   if (~size & N)
9207     HALT_UNALLOC;
9208
9209   if (!size && uimm (immr, 5, 5))
9210     HALT_UNALLOC;
9211
9212   imms = uimm (aarch64_get_instr (cpu), 15, 10);
9213   if (!size && uimm (imms, 5, 5))
9214     HALT_UNALLOC;
9215
9216   /* Switch on combined size and op.  */
9217   dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
9218   switch (dispatch)
9219     {
9220     case 0: sbfm32 (cpu, immr, imms); return;
9221     case 1: bfm32 (cpu, immr, imms); return;
9222     case 2: ubfm32 (cpu, immr, imms); return;
9223     case 4: sbfm (cpu, immr, imms); return;
9224     case 5: bfm (cpu, immr, imms); return;
9225     case 6: ubfm (cpu, immr, imms); return;
9226     default: HALT_UNALLOC;
9227     }
9228 }
9229
9230 static void
9231 do_EXTR_32 (sim_cpu *cpu)
9232 {
9233   /* instr[31:21] = 00010011100
9234      instr[20,16] = Rm
9235      instr[15,10] = imms :  0xxxxx for 32 bit
9236      instr[9,5]   = Rn
9237      instr[4,0]   = Rd  */
9238   unsigned rm   = uimm (aarch64_get_instr (cpu), 20, 16);
9239   unsigned imms = uimm (aarch64_get_instr (cpu), 15, 10) & 31;
9240   unsigned rn   = uimm (aarch64_get_instr (cpu),  9,  5);
9241   unsigned rd   = uimm (aarch64_get_instr (cpu),  4,  0);
9242   uint64_t val1;
9243   uint64_t val2;
9244
9245   val1 = aarch64_get_reg_u32 (cpu, rm, NO_SP);
9246   val1 >>= imms;
9247   val2 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
9248   val2 <<= (32 - imms);
9249
9250   aarch64_set_reg_u64 (cpu, rd, NO_SP, val1 | val2);
9251 }
9252
9253 static void
9254 do_EXTR_64 (sim_cpu *cpu)
9255 {
9256   /* instr[31:21] = 10010011100
9257      instr[20,16] = Rm
9258      instr[15,10] = imms
9259      instr[9,5]   = Rn
9260      instr[4,0]   = Rd  */
9261   unsigned rm   = uimm (aarch64_get_instr (cpu), 20, 16);
9262   unsigned imms = uimm (aarch64_get_instr (cpu), 15, 10) & 63;
9263   unsigned rn   = uimm (aarch64_get_instr (cpu),  9,  5);
9264   unsigned rd   = uimm (aarch64_get_instr (cpu),  4,  0);
9265   uint64_t val;
9266
9267   val = aarch64_get_reg_u64 (cpu, rm, NO_SP);
9268   val >>= imms;
9269   val |= (aarch64_get_reg_u64 (cpu, rn, NO_SP) << (64 - imms));
9270
9271   aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
9272 }
9273
9274 static void
9275 dexExtractImmediate (sim_cpu *cpu)
9276 {
9277   /* assert instr[28:23] = 100111
9278      instr[31]    = size : 0 ==> 32 bit, 1 ==> 64 bit
9279      instr[30,29] = op21 : 0 ==> EXTR, 1,2,3 ==> UNALLOC
9280      instr[22]    = N : must be 0 for 32 bit, 1 for 64 bit or UNALLOC
9281      instr[21]    = op0 : must be 0 or UNALLOC
9282      instr[20,16] = Rm
9283      instr[15,10] = imms :  0xxxxx for 32 bit, xxxxxx for 64 bit
9284      instr[9,5]   = Rn
9285      instr[4,0]   = Rd  */
9286
9287   /* 32 bit operations must have N = 0 or else we have an UNALLOC.  */
9288   /* 64 bit operations must have N = 1 or else we have an UNALLOC.  */
9289   uint32_t dispatch;
9290   uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
9291   uint32_t N = uimm (aarch64_get_instr (cpu), 22, 22);
9292   /* 32 bit operations must have imms[5] = 0
9293      or else we have an UNALLOC.  */
9294   uint32_t imms = uimm (aarch64_get_instr (cpu), 15, 10);
9295
9296   if (size ^ N)
9297     HALT_UNALLOC;
9298
9299   if (!size && uimm (imms, 5, 5))
9300     HALT_UNALLOC;
9301
9302   /* Switch on combined size and op.  */
9303   dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
9304
9305   if (dispatch == 0)
9306     do_EXTR_32 (cpu);
9307
9308   else if (dispatch == 4)
9309     do_EXTR_64 (cpu);
9310
9311   else if (dispatch == 1)
9312     HALT_NYI;
9313   else
9314     HALT_UNALLOC;
9315 }
9316
9317 static void
9318 dexDPImm (sim_cpu *cpu)
9319 {
9320   /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
9321      assert  group == GROUP_DPIMM_1000 || grpoup == GROUP_DPIMM_1001
9322      bits [25,23] of a DPImm are the secondary dispatch vector.  */
9323   uint32_t group2 = dispatchDPImm (aarch64_get_instr (cpu));
9324
9325   switch (group2)
9326     {
9327     case DPIMM_PCADR_000:
9328     case DPIMM_PCADR_001:
9329       dexPCRelAddressing (cpu);
9330       return;
9331
9332     case DPIMM_ADDSUB_010:
9333     case DPIMM_ADDSUB_011:
9334       dexAddSubtractImmediate (cpu);
9335       return;
9336
9337     case DPIMM_LOG_100:
9338       dexLogicalImmediate (cpu);
9339       return;
9340
9341     case DPIMM_MOV_101:
9342       dexMoveWideImmediate (cpu);
9343       return;
9344
9345     case DPIMM_BITF_110:
9346       dexBitfieldImmediate (cpu);
9347       return;
9348
9349     case DPIMM_EXTR_111:
9350       dexExtractImmediate (cpu);
9351       return;
9352
9353     default:
9354       /* Should never reach here.  */
9355       HALT_NYI;
9356     }
9357 }
9358
9359 static void
9360 dexLoadUnscaledImmediate (sim_cpu *cpu)
9361 {
9362   /* instr[29,24] == 111_00
9363      instr[21] == 0
9364      instr[11,10] == 00
9365      instr[31,30] = size
9366      instr[26] = V
9367      instr[23,22] = opc
9368      instr[20,12] = simm9
9369      instr[9,5] = rn may be SP.  */
9370   /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);  */
9371   uint32_t V = uimm (aarch64_get_instr (cpu), 26, 26);
9372   uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
9373                         | uimm (aarch64_get_instr (cpu), 23, 22));
9374   int32_t imm = simm32 (aarch64_get_instr (cpu), 20, 12);
9375
9376   if (!V)
9377     {
9378       /* GReg operations.  */
9379       switch (dispatch)
9380         {
9381         case 0:  sturb (cpu, imm); return;
9382         case 1:  ldurb32 (cpu, imm); return;
9383         case 2:  ldursb64 (cpu, imm); return;
9384         case 3:  ldursb32 (cpu, imm); return;
9385         case 4:  sturh (cpu, imm); return;
9386         case 5:  ldurh32 (cpu, imm); return;
9387         case 6:  ldursh64 (cpu, imm); return;
9388         case 7:  ldursh32 (cpu, imm); return;
9389         case 8:  stur32 (cpu, imm); return;
9390         case 9:  ldur32 (cpu, imm); return;
9391         case 10: ldursw (cpu, imm); return;
9392         case 12: stur64 (cpu, imm); return;
9393         case 13: ldur64 (cpu, imm); return;
9394
9395         case 14:
9396           /* PRFUM NYI.  */
9397           HALT_NYI;
9398
9399         default:
9400         case 11:
9401         case 15:
9402           HALT_UNALLOC;
9403         }
9404     }
9405
9406   /* FReg operations.  */
9407   switch (dispatch)
9408     {
9409     case 2:  fsturq (cpu, imm); return;
9410     case 3:  fldurq (cpu, imm); return;
9411     case 8:  fsturs (cpu, imm); return;
9412     case 9:  fldurs (cpu, imm); return;
9413     case 12: fsturd (cpu, imm); return;
9414     case 13: fldurd (cpu, imm); return;
9415
9416     case 0: /* STUR 8 bit FP.  */
9417     case 1: /* LDUR 8 bit FP.  */
9418     case 4: /* STUR 16 bit FP.  */
9419     case 5: /* LDUR 8 bit FP.  */
9420       HALT_NYI;
9421
9422     default:
9423     case 6:
9424     case 7:
9425     case 10:
9426     case 11:
9427     case 14:
9428     case 15:
9429       HALT_UNALLOC;
9430     }
9431 }
9432
9433 /*  N.B. A preliminary note regarding all the ldrs<x>32
9434     instructions
9435
9436    The signed value loaded by these instructions is cast to unsigned
9437    before being assigned to aarch64_get_reg_u64 (cpu, N) i.e. to the
9438    64 bit element of the GReg union. this performs a 32 bit sign extension
9439    (as required) but avoids 64 bit sign extension, thus ensuring that the
9440    top half of the register word is zero. this is what the spec demands
9441    when a 32 bit load occurs.  */
9442
9443 /* 32 bit load sign-extended byte scaled unsigned 12 bit.  */
9444 static void
9445 ldrsb32_abs (sim_cpu *cpu, uint32_t offset)
9446 {
9447   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
9448   unsigned int rt = uimm (aarch64_get_instr (cpu), 4, 0);
9449
9450   /* The target register may not be SP but the source may be
9451      there is no scaling required for a byte load.  */
9452   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset;
9453   aarch64_set_reg_u64 (cpu, rt, NO_SP,
9454                        (int64_t) aarch64_get_mem_s8 (cpu, address));
9455 }
9456
9457 /* 32 bit load sign-extended byte scaled or unscaled zero-
9458    or sign-extended 32-bit register offset.  */
9459 static void
9460 ldrsb32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9461 {
9462   unsigned int rm = uimm (aarch64_get_instr (cpu), 20, 16);
9463   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
9464   unsigned int rt = uimm (aarch64_get_instr (cpu), 4, 0);
9465
9466   /* rn may reference SP, rm and rt must reference ZR.  */
9467
9468   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9469   int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9470                                  extension);
9471
9472   /* There is no scaling required for a byte load.  */
9473   aarch64_set_reg_u64
9474     (cpu, rt, NO_SP, (int64_t) aarch64_get_mem_s8 (cpu, address
9475                                                    + displacement));
9476 }
9477
9478 /* 32 bit load sign-extended byte unscaled signed 9 bit with
9479    pre- or post-writeback.  */
9480 static void
9481 ldrsb32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9482 {
9483   uint64_t address;
9484   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
9485   unsigned int rt = uimm (aarch64_get_instr (cpu), 4, 0);
9486
9487   if (rn == rt && wb != NoWriteBack)
9488     HALT_UNALLOC;
9489
9490   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9491
9492   if (wb == Pre)
9493       address += offset;
9494
9495   aarch64_set_reg_u64 (cpu, rt, NO_SP,
9496                        (int64_t) aarch64_get_mem_s8 (cpu, address));
9497
9498   if (wb == Post)
9499     address += offset;
9500
9501   if (wb != NoWriteBack)
9502     aarch64_set_reg_u64 (cpu, rn, NO_SP, address);
9503 }
9504
9505 /* 8 bit store scaled.  */
9506 static void
9507 fstrb_abs (sim_cpu *cpu, uint32_t offset)
9508 {
9509   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9510   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9511
9512   aarch64_set_mem_u8 (cpu,
9513                       aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
9514                       aarch64_get_vec_u8 (cpu, st, 0));
9515 }
9516
9517 /* 8 bit store scaled or unscaled zero- or
9518    sign-extended 8-bit register offset.  */
9519 static void
9520 fstrb_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9521 {
9522   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9523   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9524   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9525
9526   uint64_t  address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9527   int64_t   extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9528                                extension);
9529   uint64_t  displacement = OPT_SCALE (extended, 32, scaling);
9530
9531   aarch64_set_mem_u8
9532     (cpu, address + displacement, aarch64_get_vec_u8 (cpu, st, 0));
9533 }
9534
9535 /* 16 bit store scaled.  */
9536 static void
9537 fstrh_abs (sim_cpu *cpu, uint32_t offset)
9538 {
9539   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9540   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9541
9542   aarch64_set_mem_u16
9543     (cpu,
9544      aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 16),
9545      aarch64_get_vec_u16 (cpu, st, 0));
9546 }
9547
9548 /* 16 bit store scaled or unscaled zero-
9549    or sign-extended 16-bit register offset.  */
9550 static void
9551 fstrh_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9552 {
9553   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9554   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9555   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9556
9557   uint64_t  address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9558   int64_t   extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9559                                extension);
9560   uint64_t  displacement = OPT_SCALE (extended, 32, scaling);
9561
9562   aarch64_set_mem_u16
9563     (cpu, address + displacement, aarch64_get_vec_u16 (cpu, st, 0));
9564 }
9565
9566 /* 32 bit store scaled unsigned 12 bit.  */
9567 static void
9568 fstrs_abs (sim_cpu *cpu, uint32_t offset)
9569 {
9570   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9571   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9572
9573   aarch64_set_mem_u32
9574     (cpu,
9575      aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 32),
9576      aarch64_get_vec_u32 (cpu, st, 0));
9577 }
9578
9579 /* 32 bit store unscaled signed 9 bit with pre- or post-writeback.  */
9580 static void
9581 fstrs_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9582 {
9583   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9584   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9585
9586   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9587
9588   if (wb != Post)
9589     address += offset;
9590
9591   aarch64_set_mem_u32 (cpu, address, aarch64_get_vec_u32 (cpu, st, 0));
9592
9593   if (wb == Post)
9594     address += offset;
9595
9596   if (wb != NoWriteBack)
9597     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
9598 }
9599
9600 /* 32 bit store scaled or unscaled zero-
9601    or sign-extended 32-bit register offset.  */
9602 static void
9603 fstrs_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9604 {
9605   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9606   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9607   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9608
9609   uint64_t  address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9610   int64_t   extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9611                                extension);
9612   uint64_t  displacement = OPT_SCALE (extended, 32, scaling);
9613
9614   aarch64_set_mem_u32
9615     (cpu, address + displacement, aarch64_get_vec_u32 (cpu, st, 0));
9616 }
9617
9618 /* 64 bit store scaled unsigned 12 bit.  */
9619 static void
9620 fstrd_abs (sim_cpu *cpu, uint32_t offset)
9621 {
9622   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9623   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9624
9625   aarch64_set_mem_u64
9626     (cpu,
9627      aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 64),
9628      aarch64_get_vec_u64 (cpu, st, 0));
9629 }
9630
9631 /* 64 bit store unscaled signed 9 bit with pre- or post-writeback.  */
9632 static void
9633 fstrd_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9634 {
9635   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9636   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9637
9638   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9639
9640   if (wb != Post)
9641     address += offset;
9642
9643   aarch64_set_mem_u64 (cpu, address, aarch64_get_vec_u64 (cpu, st, 0));
9644
9645   if (wb == Post)
9646     address += offset;
9647
9648   if (wb != NoWriteBack)
9649     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
9650 }
9651
9652 /* 64 bit store scaled or unscaled zero-
9653    or sign-extended 32-bit register offset.  */
9654 static void
9655 fstrd_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9656 {
9657   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9658   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9659   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9660
9661   uint64_t  address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9662   int64_t   extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9663                                extension);
9664   uint64_t  displacement = OPT_SCALE (extended, 64, scaling);
9665
9666   aarch64_set_mem_u64
9667     (cpu, address + displacement, aarch64_get_vec_u64 (cpu, st, 0));
9668 }
9669
9670 /* 128 bit store scaled unsigned 12 bit.  */
9671 static void
9672 fstrq_abs (sim_cpu *cpu, uint32_t offset)
9673 {
9674   FRegister a;
9675   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9676   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9677   uint64_t addr;
9678
9679   aarch64_get_FP_long_double (cpu, st, & a);
9680
9681   addr = aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 128);
9682   aarch64_set_mem_long_double (cpu, addr, a);
9683 }
9684
9685 /* 128 bit store unscaled signed 9 bit with pre- or post-writeback.  */
9686 static void
9687 fstrq_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9688 {
9689   FRegister a;
9690   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9691   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9692   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9693
9694   if (wb != Post)
9695     address += offset;
9696
9697   aarch64_get_FP_long_double (cpu, st, & a);
9698   aarch64_set_mem_long_double (cpu, address, a);
9699
9700   if (wb == Post)
9701     address += offset;
9702
9703   if (wb != NoWriteBack)
9704     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
9705 }
9706
9707 /* 128 bit store scaled or unscaled zero-
9708    or sign-extended 32-bit register offset.  */
9709 static void
9710 fstrq_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9711 {
9712   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9713   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9714   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9715
9716   uint64_t  address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9717   int64_t   extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9718                                extension);
9719   uint64_t  displacement = OPT_SCALE (extended, 128, scaling);
9720
9721   FRegister a;
9722
9723   aarch64_get_FP_long_double (cpu, st, & a);
9724   aarch64_set_mem_long_double (cpu, address + displacement, a);
9725 }
9726
9727 static void
9728 dexLoadImmediatePrePost (sim_cpu *cpu)
9729 {
9730   /* instr[29,24] == 111_00
9731      instr[21] == 0
9732      instr[11,10] == 00
9733      instr[31,30] = size
9734      instr[26] = V
9735      instr[23,22] = opc
9736      instr[20,12] = simm9
9737      instr[11] = wb : 0 ==> Post, 1 ==> Pre
9738      instr[9,5] = rn may be SP.  */
9739   /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0); */
9740   uint32_t V = uimm (aarch64_get_instr (cpu), 26, 26);
9741   uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
9742                        | uimm (aarch64_get_instr (cpu), 23, 22));
9743   int32_t imm = simm32 (aarch64_get_instr (cpu), 20, 12);
9744   WriteBack wb = writeback (aarch64_get_instr (cpu), 11);
9745
9746   if (!V)
9747     {
9748       /* GReg operations.  */
9749       switch (dispatch)
9750         {
9751         case 0:  strb_wb (cpu, imm, wb); return;
9752         case 1:  ldrb32_wb (cpu, imm, wb); return;
9753         case 2:  ldrsb_wb (cpu, imm, wb); return;
9754         case 3:  ldrsb32_wb (cpu, imm, wb); return;
9755         case 4:  strh_wb (cpu, imm, wb); return;
9756         case 5:  ldrh32_wb (cpu, imm, wb); return;
9757         case 6:  ldrsh64_wb (cpu, imm, wb); return;
9758         case 7:  ldrsh32_wb (cpu, imm, wb); return;
9759         case 8:  str32_wb (cpu, imm, wb); return;
9760         case 9:  ldr32_wb (cpu, imm, wb); return;
9761         case 10: ldrsw_wb (cpu, imm, wb); return;
9762         case 12: str_wb (cpu, imm, wb); return;
9763         case 13: ldr_wb (cpu, imm, wb); return;
9764
9765         default:
9766         case 11:
9767         case 14:
9768         case 15:
9769           HALT_UNALLOC;
9770         }
9771     }
9772
9773   /* FReg operations.  */
9774   switch (dispatch)
9775     {
9776     case 2:  fstrq_wb (cpu, imm, wb); return;
9777     case 3:  fldrq_wb (cpu, imm, wb); return;
9778     case 8:  fstrs_wb (cpu, imm, wb); return;
9779     case 9:  fldrs_wb (cpu, imm, wb); return;
9780     case 12: fstrd_wb (cpu, imm, wb); return;
9781     case 13: fldrd_wb (cpu, imm, wb); return;
9782
9783     case 0:       /* STUR 8 bit FP.  */
9784     case 1:       /* LDUR 8 bit FP.  */
9785     case 4:       /* STUR 16 bit FP.  */
9786     case 5:       /* LDUR 8 bit FP.  */
9787       HALT_NYI;
9788
9789     default:
9790     case 6:
9791     case 7:
9792     case 10:
9793     case 11:
9794     case 14:
9795     case 15:
9796       HALT_UNALLOC;
9797     }
9798 }
9799
9800 static void
9801 dexLoadRegisterOffset (sim_cpu *cpu)
9802 {
9803   /* instr[31,30] = size
9804      instr[29,27] = 111
9805      instr[26]    = V
9806      instr[25,24] = 00
9807      instr[23,22] = opc
9808      instr[21]    = 1
9809      instr[20,16] = rm
9810      instr[15,13] = option : 010 ==> UXTW, 011 ==> UXTX/LSL,
9811                              110 ==> SXTW, 111 ==> SXTX,
9812                              ow ==> RESERVED
9813      instr[12]    = scaled
9814      instr[11,10] = 10
9815      instr[9,5]   = rn
9816      instr[4,0]   = rt.  */
9817
9818   uint32_t V = uimm (aarch64_get_instr (cpu), 26,26);
9819   uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
9820                        | uimm (aarch64_get_instr (cpu), 23, 22));
9821   Scaling scale = scaling (aarch64_get_instr (cpu), 12);
9822   Extension extensionType = extension (aarch64_get_instr (cpu), 13);
9823
9824   /* Check for illegal extension types.  */
9825   if (uimm (extensionType, 1, 1) == 0)
9826     HALT_UNALLOC;
9827
9828   if (extensionType == UXTX || extensionType == SXTX)
9829     extensionType = NoExtension;
9830
9831   if (!V)
9832     {
9833       /* GReg operations.  */
9834       switch (dispatch)
9835         {
9836         case 0:  strb_scale_ext (cpu, scale, extensionType); return;
9837         case 1:  ldrb32_scale_ext (cpu, scale, extensionType); return;
9838         case 2:  ldrsb_scale_ext (cpu, scale, extensionType); return;
9839         case 3:  ldrsb32_scale_ext (cpu, scale, extensionType); return;
9840         case 4:  strh_scale_ext (cpu, scale, extensionType); return;
9841         case 5:  ldrh32_scale_ext (cpu, scale, extensionType); return;
9842         case 6:  ldrsh_scale_ext (cpu, scale, extensionType); return;
9843         case 7:  ldrsh32_scale_ext (cpu, scale, extensionType); return;
9844         case 8:  str32_scale_ext (cpu, scale, extensionType); return;
9845         case 9:  ldr32_scale_ext (cpu, scale, extensionType); return;
9846         case 10: ldrsw_scale_ext (cpu, scale, extensionType); return;
9847         case 12: str_scale_ext (cpu, scale, extensionType); return;
9848         case 13: ldr_scale_ext (cpu, scale, extensionType); return;
9849         case 14: prfm_scale_ext (cpu, scale, extensionType); return;
9850
9851         default:
9852         case 11:
9853         case 15:
9854           HALT_UNALLOC;
9855         }
9856     }
9857
9858   /* FReg operations.  */
9859   switch (dispatch)
9860     {
9861     case 1: /* LDUR 8 bit FP.  */
9862       HALT_NYI;
9863     case 3:  fldrq_scale_ext (cpu, scale, extensionType); return;
9864     case 5: /* LDUR 8 bit FP.  */
9865       HALT_NYI;
9866     case 9:  fldrs_scale_ext (cpu, scale, extensionType); return;
9867     case 13: fldrd_scale_ext (cpu, scale, extensionType); return;
9868
9869     case 0:  fstrb_scale_ext (cpu, scale, extensionType); return;
9870     case 2:  fstrq_scale_ext (cpu, scale, extensionType); return;
9871     case 4:  fstrh_scale_ext (cpu, scale, extensionType); return;
9872     case 8:  fstrs_scale_ext (cpu, scale, extensionType); return;
9873     case 12: fstrd_scale_ext (cpu, scale, extensionType); return;
9874
9875     default:
9876     case 6:
9877     case 7:
9878     case 10:
9879     case 11:
9880     case 14:
9881     case 15:
9882       HALT_UNALLOC;
9883     }
9884 }
9885
9886 static void
9887 dexLoadUnsignedImmediate (sim_cpu *cpu)
9888 {
9889   /* assert instr[29,24] == 111_01
9890      instr[31,30] = size
9891      instr[26] = V
9892      instr[23,22] = opc
9893      instr[21,10] = uimm12 : unsigned immediate offset
9894      instr[9,5] = rn may be SP.  */
9895   /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0); */
9896   uint32_t V = uimm (aarch64_get_instr (cpu), 26,26);
9897   uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
9898                        | uimm (aarch64_get_instr (cpu), 23, 22));
9899   uint32_t imm = uimm (aarch64_get_instr (cpu), 21, 10);
9900
9901   if (!V)
9902     {
9903       /* GReg operations.  */
9904       switch (dispatch)
9905         {
9906         case 0:  strb_abs (cpu, imm); return;
9907         case 1:  ldrb32_abs (cpu, imm); return;
9908         case 2:  ldrsb_abs (cpu, imm); return;
9909         case 3:  ldrsb32_abs (cpu, imm); return;
9910         case 4:  strh_abs (cpu, imm); return;
9911         case 5:  ldrh32_abs (cpu, imm); return;
9912         case 6:  ldrsh_abs (cpu, imm); return;
9913         case 7:  ldrsh32_abs (cpu, imm); return;
9914         case 8:  str32_abs (cpu, imm); return;
9915         case 9:  ldr32_abs (cpu, imm); return;
9916         case 10: ldrsw_abs (cpu, imm); return;
9917         case 12: str_abs (cpu, imm); return;
9918         case 13: ldr_abs (cpu, imm); return;
9919         case 14: prfm_abs (cpu, imm); return;
9920
9921         default:
9922         case 11:
9923         case 15:
9924           HALT_UNALLOC;
9925         }
9926     }
9927
9928   /* FReg operations.  */
9929   switch (dispatch)
9930     {
9931     case 3:  fldrq_abs (cpu, imm); return;
9932     case 9:  fldrs_abs (cpu, imm); return;
9933     case 13: fldrd_abs (cpu, imm); return;
9934
9935     case 0:  fstrb_abs (cpu, imm); return;
9936     case 2:  fstrq_abs (cpu, imm); return;
9937     case 4:  fstrh_abs (cpu, imm); return;
9938     case 8:  fstrs_abs (cpu, imm); return;
9939     case 12: fstrd_abs (cpu, imm); return;
9940
9941     case 1: /* LDR 8 bit FP.  */
9942     case 5: /* LDR 8 bit FP.  */
9943       HALT_NYI;
9944
9945     default:
9946     case 6:
9947     case 7:
9948     case 10:
9949     case 11:
9950     case 14:
9951     case 15:
9952       HALT_UNALLOC;
9953     }
9954 }
9955
9956 static void
9957 dexLoadExclusive (sim_cpu *cpu)
9958 {
9959   /* assert instr[29:24] = 001000;
9960      instr[31,30] = size
9961      instr[23] = 0 if exclusive
9962      instr[22] = L : 1 if load, 0 if store
9963      instr[21] = 1 if pair
9964      instr[20,16] = Rs
9965      instr[15] = o0 : 1 if ordered
9966      instr[14,10] = Rt2
9967      instr[9,5] = Rn
9968      instr[4.0] = Rt.  */
9969
9970   switch (uimm (aarch64_get_instr (cpu), 22, 21))
9971     {
9972     case 2:   ldxr (cpu); return;
9973     case 0:   stxr (cpu); return;
9974     default:  HALT_NYI;
9975     }
9976 }
9977
9978 static void
9979 dexLoadOther (sim_cpu *cpu)
9980 {
9981   uint32_t dispatch;
9982
9983   /* instr[29,25] = 111_0
9984      instr[24] == 0 ==> dispatch, 1 ==> ldst reg unsigned immediate
9985      instr[21:11,10] is the secondary dispatch.  */
9986   if (uimm (aarch64_get_instr (cpu), 24, 24))
9987     {
9988       dexLoadUnsignedImmediate (cpu);
9989       return;
9990     }
9991
9992   dispatch = ( (uimm (aarch64_get_instr (cpu), 21, 21) << 2)
9993               | uimm (aarch64_get_instr (cpu), 11, 10));
9994   switch (dispatch)
9995     {
9996     case 0: dexLoadUnscaledImmediate (cpu); return;
9997     case 1: dexLoadImmediatePrePost (cpu); return;
9998     case 3: dexLoadImmediatePrePost (cpu); return;
9999     case 6: dexLoadRegisterOffset (cpu); return;
10000
10001     default:
10002     case 2:
10003     case 4:
10004     case 5:
10005     case 7:
10006       HALT_NYI;
10007     }
10008 }
10009
10010 static void
10011 store_pair_u32 (sim_cpu *cpu, int32_t offset, WriteBack wb)
10012 {
10013   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10014   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10015   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10016   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10017
10018   if ((rn == rd || rm == rd) && wb != NoWriteBack)
10019     HALT_UNALLOC; /* ??? */
10020
10021   offset <<= 2;
10022
10023   if (wb != Post)
10024     address += offset;
10025
10026   aarch64_set_mem_u32 (cpu, address,
10027                        aarch64_get_reg_u32 (cpu, rm, NO_SP));
10028   aarch64_set_mem_u32 (cpu, address + 4,
10029                        aarch64_get_reg_u32 (cpu, rn, NO_SP));
10030
10031   if (wb == Post)
10032     address += offset;
10033
10034   if (wb != NoWriteBack)
10035     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10036 }
10037
10038 static void
10039 store_pair_u64 (sim_cpu *cpu, int32_t offset, WriteBack wb)
10040 {
10041   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10042   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10043   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10044   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10045
10046   if ((rn == rd || rm == rd) && wb != NoWriteBack)
10047     HALT_UNALLOC; /* ??? */
10048
10049   offset <<= 3;
10050
10051   if (wb != Post)
10052     address += offset;
10053
10054   aarch64_set_mem_u64 (cpu, address,
10055                        aarch64_get_reg_u64 (cpu, rm, SP_OK));
10056   aarch64_set_mem_u64 (cpu, address + 8,
10057                        aarch64_get_reg_u64 (cpu, rn, SP_OK));
10058
10059   if (wb == Post)
10060     address += offset;
10061
10062   if (wb != NoWriteBack)
10063     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10064 }
10065
10066 static void
10067 load_pair_u32 (sim_cpu *cpu, int32_t offset, WriteBack wb)
10068 {
10069   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10070   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10071   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10072   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10073
10074   /* treat this as unalloc to make sure we don't do it.  */
10075   if (rn == rm)
10076     HALT_UNALLOC;
10077
10078   offset <<= 2;
10079
10080   if (wb != Post)
10081     address += offset;
10082
10083   aarch64_set_reg_u64 (cpu, rm, SP_OK, aarch64_get_mem_u32 (cpu, address));
10084   aarch64_set_reg_u64 (cpu, rn, SP_OK, aarch64_get_mem_u32 (cpu, address + 4));
10085
10086   if (wb == Post)
10087     address += offset;
10088
10089   if (wb != NoWriteBack)
10090     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10091 }
10092
10093 static void
10094 load_pair_s32 (sim_cpu *cpu, int32_t offset, WriteBack wb)
10095 {
10096   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10097   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10098   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10099   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10100
10101   /* Treat this as unalloc to make sure we don't do it.  */
10102   if (rn == rm)
10103     HALT_UNALLOC;
10104
10105   offset <<= 2;
10106
10107   if (wb != Post)
10108     address += offset;
10109
10110   aarch64_set_reg_s64 (cpu, rm, SP_OK, aarch64_get_mem_s32 (cpu, address));
10111   aarch64_set_reg_s64 (cpu, rn, SP_OK, aarch64_get_mem_s32 (cpu, address + 4));
10112
10113   if (wb == Post)
10114     address += offset;
10115
10116   if (wb != NoWriteBack)
10117     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10118 }
10119
10120 static void
10121 load_pair_u64 (sim_cpu *cpu, int32_t offset, WriteBack wb)
10122 {
10123   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10124   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10125   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10126   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10127
10128   /* Treat this as unalloc to make sure we don't do it.  */
10129   if (rn == rm)
10130     HALT_UNALLOC;
10131
10132   offset <<= 3;
10133
10134   if (wb != Post)
10135     address += offset;
10136
10137   aarch64_set_reg_u64 (cpu, rm, SP_OK, aarch64_get_mem_u64 (cpu, address));
10138   aarch64_set_reg_u64 (cpu, rn, SP_OK, aarch64_get_mem_u64 (cpu, address + 8));
10139
10140   if (wb == Post)
10141     address += offset;
10142
10143   if (wb != NoWriteBack)
10144     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10145 }
10146
10147 static void
10148 dex_load_store_pair_gr (sim_cpu *cpu)
10149 {
10150   /* instr[31,30] = size (10=> 64-bit, 01=> signed 32-bit, 00=> 32-bit)
10151      instr[29,25] = instruction encoding: 101_0
10152      instr[26]    = V : 1 if fp 0 if gp
10153      instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
10154      instr[22]    = load/store (1=> load)
10155      instr[21,15] = signed, scaled, offset
10156      instr[14,10] = Rn
10157      instr[ 9, 5] = Rd
10158      instr[ 4, 0] = Rm.  */
10159
10160   uint32_t dispatch = ((uimm (aarch64_get_instr (cpu), 31, 30) << 3)
10161                         | uimm (aarch64_get_instr (cpu), 24, 22));
10162   int32_t offset = simm32 (aarch64_get_instr (cpu), 21, 15);
10163
10164   switch (dispatch)
10165     {
10166     case 2: store_pair_u32 (cpu, offset, Post); return;
10167     case 3: load_pair_u32  (cpu, offset, Post); return;
10168     case 4: store_pair_u32 (cpu, offset, NoWriteBack); return;
10169     case 5: load_pair_u32  (cpu, offset, NoWriteBack); return;
10170     case 6: store_pair_u32 (cpu, offset, Pre); return;
10171     case 7: load_pair_u32  (cpu, offset, Pre); return;
10172
10173     case 11: load_pair_s32  (cpu, offset, Post); return;
10174     case 13: load_pair_s32  (cpu, offset, NoWriteBack); return;
10175     case 15: load_pair_s32  (cpu, offset, Pre); return;
10176
10177     case 18: store_pair_u64 (cpu, offset, Post); return;
10178     case 19: load_pair_u64  (cpu, offset, Post); return;
10179     case 20: store_pair_u64 (cpu, offset, NoWriteBack); return;
10180     case 21: load_pair_u64  (cpu, offset, NoWriteBack); return;
10181     case 22: store_pair_u64 (cpu, offset, Pre); return;
10182     case 23: load_pair_u64  (cpu, offset, Pre); return;
10183
10184     default:
10185       HALT_UNALLOC;
10186     }
10187 }
10188
10189 static void
10190 store_pair_float (sim_cpu *cpu, int32_t offset, WriteBack wb)
10191 {
10192   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10193   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10194   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10195   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10196
10197   offset <<= 2;
10198
10199   if (wb != Post)
10200     address += offset;
10201
10202   aarch64_set_mem_u32 (cpu, address,     aarch64_get_vec_u32 (cpu, rm, 0));
10203   aarch64_set_mem_u32 (cpu, address + 4, aarch64_get_vec_u32 (cpu, rn, 0));
10204
10205   if (wb == Post)
10206     address += offset;
10207
10208   if (wb != NoWriteBack)
10209     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10210 }
10211
10212 static void
10213 store_pair_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10214 {
10215   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10216   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10217   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10218   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10219
10220   offset <<= 3;
10221
10222   if (wb != Post)
10223     address += offset;
10224
10225   aarch64_set_mem_u64 (cpu, address,     aarch64_get_vec_u64 (cpu, rm, 0));
10226   aarch64_set_mem_u64 (cpu, address + 8, aarch64_get_vec_u64 (cpu, rn, 0));
10227
10228   if (wb == Post)
10229     address += offset;
10230
10231   if (wb != NoWriteBack)
10232     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10233 }
10234
10235 static void
10236 store_pair_long_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10237 {
10238   FRegister a;
10239   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10240   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10241   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10242   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10243
10244   offset <<= 4;
10245
10246   if (wb != Post)
10247     address += offset;
10248
10249   aarch64_get_FP_long_double (cpu, rm, & a);
10250   aarch64_set_mem_long_double (cpu, address, a);
10251   aarch64_get_FP_long_double (cpu, rn, & a);
10252   aarch64_set_mem_long_double (cpu, address + 16, a);
10253
10254   if (wb == Post)
10255     address += offset;
10256
10257   if (wb != NoWriteBack)
10258     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10259 }
10260
10261 static void
10262 load_pair_float (sim_cpu *cpu, int32_t offset, WriteBack wb)
10263 {
10264   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10265   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10266   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10267   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10268
10269   if (rm == rn)
10270     HALT_UNALLOC;
10271
10272   offset <<= 2;
10273
10274   if (wb != Post)
10275     address += offset;
10276
10277   aarch64_set_vec_u32 (cpu, rm, 0, aarch64_get_mem_u32 (cpu, address));
10278   aarch64_set_vec_u32 (cpu, rn, 0, aarch64_get_mem_u32 (cpu, address + 4));
10279
10280   if (wb == Post)
10281     address += offset;
10282
10283   if (wb != NoWriteBack)
10284     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10285 }
10286
10287 static void
10288 load_pair_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10289 {
10290   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10291   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10292   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10293   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10294
10295   if (rm == rn)
10296     HALT_UNALLOC;
10297
10298   offset <<= 3;
10299
10300   if (wb != Post)
10301     address += offset;
10302
10303   aarch64_set_vec_u64 (cpu, rm, 0, aarch64_get_mem_u64 (cpu, address));
10304   aarch64_set_vec_u64 (cpu, rn, 0, aarch64_get_mem_u64 (cpu, address + 8));
10305
10306   if (wb == Post)
10307     address += offset;
10308
10309   if (wb != NoWriteBack)
10310     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10311 }
10312
10313 static void
10314 load_pair_long_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10315 {
10316   FRegister a;
10317   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10318   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10319   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10320   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10321
10322   if (rm == rn)
10323     HALT_UNALLOC;
10324
10325   offset <<= 4;
10326
10327   if (wb != Post)
10328     address += offset;
10329
10330   aarch64_get_mem_long_double (cpu, address, & a);
10331   aarch64_set_FP_long_double (cpu, rm, a);
10332   aarch64_get_mem_long_double (cpu, address + 16, & a);
10333   aarch64_set_FP_long_double (cpu, rn, a);
10334
10335   if (wb == Post)
10336     address += offset;
10337
10338   if (wb != NoWriteBack)
10339     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10340 }
10341
10342 static void
10343 dex_load_store_pair_fp (sim_cpu *cpu)
10344 {
10345   /* instr[31,30] = size (10=> 128-bit, 01=> 64-bit, 00=> 32-bit)
10346      instr[29,25] = instruction encoding
10347      instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
10348      instr[22]    = load/store (1=> load)
10349      instr[21,15] = signed, scaled, offset
10350      instr[14,10] = Rn
10351      instr[ 9, 5] = Rd
10352      instr[ 4, 0] = Rm  */
10353
10354   uint32_t dispatch = ((uimm (aarch64_get_instr (cpu), 31, 30) << 3)
10355                         | uimm (aarch64_get_instr (cpu), 24, 22));
10356   int32_t offset = simm32 (aarch64_get_instr (cpu), 21, 15);
10357
10358   switch (dispatch)
10359     {
10360     case 2: store_pair_float (cpu, offset, Post); return;
10361     case 3: load_pair_float  (cpu, offset, Post); return;
10362     case 4: store_pair_float (cpu, offset, NoWriteBack); return;
10363     case 5: load_pair_float  (cpu, offset, NoWriteBack); return;
10364     case 6: store_pair_float (cpu, offset, Pre); return;
10365     case 7: load_pair_float  (cpu, offset, Pre); return;
10366
10367     case 10: store_pair_double (cpu, offset, Post); return;
10368     case 11: load_pair_double  (cpu, offset, Post); return;
10369     case 12: store_pair_double (cpu, offset, NoWriteBack); return;
10370     case 13: load_pair_double  (cpu, offset, NoWriteBack); return;
10371     case 14: store_pair_double (cpu, offset, Pre); return;
10372     case 15: load_pair_double  (cpu, offset, Pre); return;
10373
10374     case 18: store_pair_long_double (cpu, offset, Post); return;
10375     case 19: load_pair_long_double  (cpu, offset, Post); return;
10376     case 20: store_pair_long_double (cpu, offset, NoWriteBack); return;
10377     case 21: load_pair_long_double  (cpu, offset, NoWriteBack); return;
10378     case 22: store_pair_long_double (cpu, offset, Pre); return;
10379     case 23: load_pair_long_double  (cpu, offset, Pre); return;
10380
10381     default:
10382       HALT_UNALLOC;
10383     }
10384 }
10385
10386 static inline unsigned
10387 vec_reg (unsigned v, unsigned o)
10388 {
10389   return (v + o) & 0x3F;
10390 }
10391
10392 /* Load multiple N-element structures to N consecutive registers.  */
10393 static void
10394 vec_load (sim_cpu *cpu, uint64_t address, unsigned N)
10395 {
10396   int      all  = uimm (aarch64_get_instr (cpu), 30, 30);
10397   unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10398   unsigned vd   = uimm (aarch64_get_instr (cpu), 4, 0);
10399   unsigned i;
10400
10401   switch (size)
10402     {
10403     case 0: /* 8-bit operations.  */
10404       if (all)
10405         for (i = 0; i < (16 * N); i++)
10406           aarch64_set_vec_u8 (cpu, vec_reg (vd, i >> 4), i & 15,
10407                               aarch64_get_mem_u8 (cpu, address + i));
10408       else
10409         for (i = 0; i < (8 * N); i++)
10410           aarch64_set_vec_u8 (cpu, vec_reg (vd, i >> 3), i & 7,
10411                               aarch64_get_mem_u8 (cpu, address + i));
10412       return;
10413
10414     case 1: /* 16-bit operations.  */
10415       if (all)
10416         for (i = 0; i < (8 * N); i++)
10417           aarch64_set_vec_u16 (cpu, vec_reg (vd, i >> 3), i & 7,
10418                                aarch64_get_mem_u16 (cpu, address + i * 2));
10419       else
10420         for (i = 0; i < (4 * N); i++)
10421           aarch64_set_vec_u16 (cpu, vec_reg (vd, i >> 2), i & 3,
10422                                aarch64_get_mem_u16 (cpu, address + i * 2));
10423       return;
10424
10425     case 2: /* 32-bit operations.  */
10426       if (all)
10427         for (i = 0; i < (4 * N); i++)
10428           aarch64_set_vec_u32 (cpu, vec_reg (vd, i >> 2), i & 3,
10429                                aarch64_get_mem_u32 (cpu, address + i * 4));
10430       else
10431         for (i = 0; i < (2 * N); i++)
10432           aarch64_set_vec_u32 (cpu, vec_reg (vd, i >> 1), i & 1,
10433                                aarch64_get_mem_u32 (cpu, address + i * 4));
10434       return;
10435
10436     case 3: /* 64-bit operations.  */
10437       if (all)
10438         for (i = 0; i < (2 * N); i++)
10439           aarch64_set_vec_u64 (cpu, vec_reg (vd, i >> 1), i & 1,
10440                                aarch64_get_mem_u64 (cpu, address + i * 8));
10441       else
10442         for (i = 0; i < N; i++)
10443           aarch64_set_vec_u64 (cpu, vec_reg (vd, i), 0,
10444                                aarch64_get_mem_u64 (cpu, address + i * 8));
10445       return;
10446
10447     default:
10448       HALT_UNREACHABLE;
10449     }
10450 }
10451
10452 /* LD4: load multiple 4-element to four consecutive registers.  */
10453 static void
10454 LD4 (sim_cpu *cpu, uint64_t address)
10455 {
10456   vec_load (cpu, address, 4);
10457 }
10458
10459 /* LD3: load multiple 3-element structures to three consecutive registers.  */
10460 static void
10461 LD3 (sim_cpu *cpu, uint64_t address)
10462 {
10463   vec_load (cpu, address, 3);
10464 }
10465
10466 /* LD2: load multiple 2-element structures to two consecutive registers.  */
10467 static void
10468 LD2 (sim_cpu *cpu, uint64_t address)
10469 {
10470   vec_load (cpu, address, 2);
10471 }
10472
10473 /* Load multiple 1-element structures into one register.  */
10474 static void
10475 LD1_1 (sim_cpu *cpu, uint64_t address)
10476 {
10477   int      all  = uimm (aarch64_get_instr (cpu), 30, 30);
10478   unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10479   unsigned vd   = uimm (aarch64_get_instr (cpu), 4, 0);
10480   unsigned i;
10481
10482   switch (size)
10483     {
10484     case 0:
10485       /* LD1 {Vd.16b}, addr, #16 */
10486       /* LD1 {Vd.8b}, addr, #8 */
10487       for (i = 0; i < (all ? 16 : 8); i++)
10488         aarch64_set_vec_u8 (cpu, vd, i,
10489                             aarch64_get_mem_u8 (cpu, address + i));
10490       return;
10491
10492     case 1:
10493       /* LD1 {Vd.8h}, addr, #16 */
10494       /* LD1 {Vd.4h}, addr, #8 */
10495       for (i = 0; i < (all ? 8 : 4); i++)
10496         aarch64_set_vec_u16 (cpu, vd, i,
10497                              aarch64_get_mem_u16 (cpu, address + i * 2));
10498       return;
10499
10500     case 2:
10501       /* LD1 {Vd.4s}, addr, #16 */
10502       /* LD1 {Vd.2s}, addr, #8 */
10503       for (i = 0; i < (all ? 4 : 2); i++)
10504         aarch64_set_vec_u32 (cpu, vd, i,
10505                              aarch64_get_mem_u32 (cpu, address + i * 4));
10506       return;
10507
10508     case 3:
10509       /* LD1 {Vd.2d}, addr, #16 */
10510       /* LD1 {Vd.1d}, addr, #8 */
10511       for (i = 0; i < (all ? 2 : 1); i++)
10512         aarch64_set_vec_u64 (cpu, vd, i,
10513                              aarch64_get_mem_u64 (cpu, address + i * 8));
10514       return;
10515
10516     default:
10517       HALT_UNREACHABLE;
10518     }
10519 }
10520
10521 /* Load multiple 1-element structures into two registers.  */
10522 static void
10523 LD1_2 (sim_cpu *cpu, uint64_t address)
10524 {
10525   /* FIXME: This algorithm is *exactly* the same as the LD2 version.
10526      So why have two different instructions ?  There must be something
10527      wrong somewhere.  */
10528   vec_load (cpu, address, 2);
10529 }
10530
10531 /* Load multiple 1-element structures into three registers.  */
10532 static void
10533 LD1_3 (sim_cpu *cpu, uint64_t address)
10534 {
10535   /* FIXME: This algorithm is *exactly* the same as the LD3 version.
10536      So why have two different instructions ?  There must be something
10537      wrong somewhere.  */
10538   vec_load (cpu, address, 3);
10539 }
10540
10541 /* Load multiple 1-element structures into four registers.  */
10542 static void
10543 LD1_4 (sim_cpu *cpu, uint64_t address)
10544 {
10545   /* FIXME: This algorithm is *exactly* the same as the LD4 version.
10546      So why have two different instructions ?  There must be something
10547      wrong somewhere.  */
10548   vec_load (cpu, address, 4);
10549 }
10550
10551 /* Store multiple N-element structures to N consecutive registers.  */
10552 static void
10553 vec_store (sim_cpu *cpu, uint64_t address, unsigned N)
10554 {
10555   int      all  = uimm (aarch64_get_instr (cpu), 30, 30);
10556   unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10557   unsigned vd   = uimm (aarch64_get_instr (cpu), 4, 0);
10558   unsigned i;
10559
10560   switch (size)
10561     {
10562     case 0: /* 8-bit operations.  */
10563       if (all)
10564         for (i = 0; i < (16 * N); i++)
10565           aarch64_set_mem_u8
10566             (cpu, address + i,
10567              aarch64_get_vec_u8 (cpu, vec_reg (vd, i >> 4), i & 15));
10568       else
10569         for (i = 0; i < (8 * N); i++)
10570           aarch64_set_mem_u8
10571             (cpu, address + i,
10572              aarch64_get_vec_u8 (cpu, vec_reg (vd, i >> 3), i & 7));
10573       return;
10574
10575     case 1: /* 16-bit operations.  */
10576       if (all)
10577         for (i = 0; i < (8 * N); i++)
10578           aarch64_set_mem_u16
10579             (cpu, address + i * 2,
10580              aarch64_get_vec_u16 (cpu, vec_reg (vd, i >> 3), i & 7));
10581       else
10582         for (i = 0; i < (4 * N); i++)
10583           aarch64_set_mem_u16
10584             (cpu, address + i * 2,
10585              aarch64_get_vec_u16 (cpu, vec_reg (vd, i >> 2), i & 3));
10586       return;
10587
10588     case 2: /* 32-bit operations.  */
10589       if (all)
10590         for (i = 0; i < (4 * N); i++)
10591           aarch64_set_mem_u32
10592             (cpu, address + i * 4,
10593              aarch64_get_vec_u32 (cpu, vec_reg (vd, i >> 2), i & 3));
10594       else
10595         for (i = 0; i < (2 * N); i++)
10596           aarch64_set_mem_u32
10597             (cpu, address + i * 4,
10598              aarch64_get_vec_u32 (cpu, vec_reg (vd, i >> 1), i & 1));
10599       return;
10600
10601     case 3: /* 64-bit operations.  */
10602       if (all)
10603         for (i = 0; i < (2 * N); i++)
10604           aarch64_set_mem_u64
10605             (cpu, address + i * 8,
10606              aarch64_get_vec_u64 (cpu, vec_reg (vd, i >> 1), i & 1));
10607       else
10608         for (i = 0; i < N; i++)
10609           aarch64_set_mem_u64
10610             (cpu, address + i * 8,
10611              aarch64_get_vec_u64 (cpu, vec_reg (vd, i), 0));
10612       return;
10613
10614     default:
10615       HALT_UNREACHABLE;
10616     }
10617 }
10618
10619 /* Store multiple 4-element structure to four consecutive registers.  */
10620 static void
10621 ST4 (sim_cpu *cpu, uint64_t address)
10622 {
10623   vec_store (cpu, address, 4);
10624 }
10625
10626 /* Store multiple 3-element structures to three consecutive registers.  */
10627 static void
10628 ST3 (sim_cpu *cpu, uint64_t address)
10629 {
10630   vec_store (cpu, address, 3);
10631 }
10632
10633 /* Store multiple 2-element structures to two consecutive registers.  */
10634 static void
10635 ST2 (sim_cpu *cpu, uint64_t address)
10636 {
10637   vec_store (cpu, address, 2);
10638 }
10639
10640 /* Store multiple 1-element structures into one register.  */
10641 static void
10642 ST1_1 (sim_cpu *cpu, uint64_t address)
10643 {
10644   int      all  = uimm (aarch64_get_instr (cpu), 30, 30);
10645   unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10646   unsigned vd   = uimm (aarch64_get_instr (cpu), 4, 0);
10647   unsigned i;
10648
10649   switch (size)
10650     {
10651     case 0:
10652       for (i = 0; i < (all ? 16 : 8); i++)
10653         aarch64_set_mem_u8 (cpu, address + i,
10654                             aarch64_get_vec_u8 (cpu, vd, i));
10655       return;
10656
10657     case 1:
10658       for (i = 0; i < (all ? 8 : 4); i++)
10659         aarch64_set_mem_u16 (cpu, address + i * 2,
10660                              aarch64_get_vec_u16 (cpu, vd, i));
10661       return;
10662
10663     case 2:
10664       for (i = 0; i < (all ? 4 : 2); i++)
10665         aarch64_set_mem_u32 (cpu, address + i * 4,
10666                              aarch64_get_vec_u32 (cpu, vd, i));
10667       return;
10668
10669     case 3:
10670       for (i = 0; i < (all ? 2 : 1); i++)
10671         aarch64_set_mem_u64 (cpu, address + i * 8,
10672                              aarch64_get_vec_u64 (cpu, vd, i));
10673       return;
10674
10675     default:
10676       HALT_UNREACHABLE;
10677     }
10678 }
10679
10680 /* Store multiple 1-element structures into two registers.  */
10681 static void
10682 ST1_2 (sim_cpu *cpu, uint64_t address)
10683 {
10684   /* FIXME: This algorithm is *exactly* the same as the ST2 version.
10685      So why have two different instructions ?  There must be
10686      something wrong somewhere.  */
10687   vec_store (cpu, address, 2);
10688 }
10689
10690 /* Store multiple 1-element structures into three registers.  */
10691 static void
10692 ST1_3 (sim_cpu *cpu, uint64_t address)
10693 {
10694   /* FIXME: This algorithm is *exactly* the same as the ST3 version.
10695      So why have two different instructions ?  There must be
10696      something wrong somewhere.  */
10697   vec_store (cpu, address, 3);
10698 }
10699
10700 /* Store multiple 1-element structures into four registers.  */
10701 static void
10702 ST1_4 (sim_cpu *cpu, uint64_t address)
10703 {
10704   /* FIXME: This algorithm is *exactly* the same as the ST4 version.
10705      So why have two different instructions ?  There must be
10706      something wrong somewhere.  */
10707   vec_store (cpu, address, 4);
10708 }
10709
10710 static void
10711 do_vec_LDnR (sim_cpu *cpu, uint64_t address)
10712 {
10713   /* instr[31]    = 0
10714      instr[30]    = element selector 0=>half, 1=>all elements
10715      instr[29,24] = 00 1101
10716      instr[23]    = 0=>simple, 1=>post
10717      instr[22]    = 1
10718      instr[21]    = width: LD1R-or-LD3R (0) / LD2R-or-LD4R (1)
10719      instr[20,16] = 0 0000 (simple), Vinc (reg-post-inc, no SP),
10720                       11111 (immediate post inc)
10721      instr[15,14] = 11
10722      instr[13]    = width: LD1R-or-LD2R (0) / LD3R-or-LD4R (1)
10723      instr[12]    = 0
10724      instr[11,10] = element size 00=> byte(b), 01=> half(h),
10725                                  10=> word(s), 11=> double(d)
10726      instr[9,5]   = address
10727      instr[4,0]   = Vd  */
10728
10729   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
10730   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
10731   unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10732   int i;
10733
10734   NYI_assert (29, 24, 0x0D);
10735   NYI_assert (22, 22, 1);
10736   NYI_assert (15, 14, 3);
10737   NYI_assert (12, 12, 0);
10738
10739   switch ((uimm (aarch64_get_instr (cpu), 13, 13) << 1)
10740           | uimm (aarch64_get_instr (cpu), 21, 21))
10741     {
10742     case 0: /* LD1R.  */
10743       switch (size)
10744         {
10745         case 0:
10746           {
10747             uint8_t val = aarch64_get_mem_u8 (cpu, address);
10748             for (i = 0; i < (full ? 16 : 8); i++)
10749               aarch64_set_vec_u8 (cpu, vd, i, val);
10750             break;
10751           }
10752
10753         case 1:
10754           {
10755             uint16_t val = aarch64_get_mem_u16 (cpu, address);
10756             for (i = 0; i < (full ? 8 : 4); i++)
10757               aarch64_set_vec_u16 (cpu, vd, i, val);
10758             break;
10759           }
10760
10761         case 2:
10762           {
10763             uint32_t val = aarch64_get_mem_u32 (cpu, address);
10764             for (i = 0; i < (full ? 4 : 2); i++)
10765               aarch64_set_vec_u32 (cpu, vd, i, val);
10766             break;
10767           }
10768
10769         case 3:
10770           {
10771             uint64_t val = aarch64_get_mem_u64 (cpu, address);
10772             for (i = 0; i < (full ? 2 : 1); i++)
10773               aarch64_set_vec_u64 (cpu, vd, i, val);
10774             break;
10775           }
10776
10777         default:
10778           HALT_UNALLOC;
10779         }
10780       break;
10781
10782     case 1: /* LD2R.  */
10783       switch (size)
10784         {
10785         case 0:
10786           {
10787             uint8_t val1 = aarch64_get_mem_u8 (cpu, address);
10788             uint8_t val2 = aarch64_get_mem_u8 (cpu, address + 1);
10789
10790             for (i = 0; i < (full ? 16 : 8); i++)
10791               {
10792                 aarch64_set_vec_u8 (cpu, vd, 0, val1);
10793                 aarch64_set_vec_u8 (cpu, vd + 1, 0, val2);
10794               }
10795             break;
10796           }
10797
10798         case 1:
10799           {
10800             uint16_t val1 = aarch64_get_mem_u16 (cpu, address);
10801             uint16_t val2 = aarch64_get_mem_u16 (cpu, address + 2);
10802
10803             for (i = 0; i < (full ? 8 : 4); i++)
10804               {
10805                 aarch64_set_vec_u16 (cpu, vd, 0, val1);
10806                 aarch64_set_vec_u16 (cpu, vd + 1, 0, val2);
10807               }
10808             break;
10809           }
10810
10811         case 2:
10812           {
10813             uint32_t val1 = aarch64_get_mem_u32 (cpu, address);
10814             uint32_t val2 = aarch64_get_mem_u32 (cpu, address + 4);
10815
10816             for (i = 0; i < (full ? 4 : 2); i++)
10817               {
10818                 aarch64_set_vec_u32 (cpu, vd, 0, val1);
10819                 aarch64_set_vec_u32 (cpu, vd + 1, 0, val2);
10820               }
10821             break;
10822           }
10823
10824         case 3:
10825           {
10826             uint64_t val1 = aarch64_get_mem_u64 (cpu, address);
10827             uint64_t val2 = aarch64_get_mem_u64 (cpu, address + 8);
10828
10829             for (i = 0; i < (full ? 2 : 1); i++)
10830               {
10831                 aarch64_set_vec_u64 (cpu, vd, 0, val1);
10832                 aarch64_set_vec_u64 (cpu, vd + 1, 0, val2);
10833               }
10834             break;
10835           }
10836
10837         default:
10838           HALT_UNALLOC;
10839         }
10840       break;
10841
10842     case 2: /* LD3R.  */
10843       switch (size)
10844         {
10845         case 0:
10846           {
10847             uint8_t val1 = aarch64_get_mem_u8 (cpu, address);
10848             uint8_t val2 = aarch64_get_mem_u8 (cpu, address + 1);
10849             uint8_t val3 = aarch64_get_mem_u8 (cpu, address + 2);
10850
10851             for (i = 0; i < (full ? 16 : 8); i++)
10852               {
10853                 aarch64_set_vec_u8 (cpu, vd, 0, val1);
10854                 aarch64_set_vec_u8 (cpu, vd + 1, 0, val2);
10855                 aarch64_set_vec_u8 (cpu, vd + 2, 0, val3);
10856               }
10857           }
10858           break;
10859
10860         case 1:
10861           {
10862             uint32_t val1 = aarch64_get_mem_u16 (cpu, address);
10863             uint32_t val2 = aarch64_get_mem_u16 (cpu, address + 2);
10864             uint32_t val3 = aarch64_get_mem_u16 (cpu, address + 4);
10865
10866             for (i = 0; i < (full ? 8 : 4); i++)
10867               {
10868                 aarch64_set_vec_u16 (cpu, vd, 0, val1);
10869                 aarch64_set_vec_u16 (cpu, vd + 1, 0, val2);
10870                 aarch64_set_vec_u16 (cpu, vd + 2, 0, val3);
10871               }
10872           }
10873           break;
10874
10875         case 2:
10876           {
10877             uint32_t val1 = aarch64_get_mem_u32 (cpu, address);
10878             uint32_t val2 = aarch64_get_mem_u32 (cpu, address + 4);
10879             uint32_t val3 = aarch64_get_mem_u32 (cpu, address + 8);
10880
10881             for (i = 0; i < (full ? 4 : 2); i++)
10882               {
10883                 aarch64_set_vec_u32 (cpu, vd, 0, val1);
10884                 aarch64_set_vec_u32 (cpu, vd + 1, 0, val2);
10885                 aarch64_set_vec_u32 (cpu, vd + 2, 0, val3);
10886               }
10887           }
10888           break;
10889
10890         case 3:
10891           {
10892             uint64_t val1 = aarch64_get_mem_u64 (cpu, address);
10893             uint64_t val2 = aarch64_get_mem_u64 (cpu, address + 8);
10894             uint64_t val3 = aarch64_get_mem_u64 (cpu, address + 16);
10895
10896             for (i = 0; i < (full ? 2 : 1); i++)
10897               {
10898                 aarch64_set_vec_u64 (cpu, vd, 0, val1);
10899                 aarch64_set_vec_u64 (cpu, vd + 1, 0, val2);
10900                 aarch64_set_vec_u64 (cpu, vd + 2, 0, val3);
10901               }
10902           }
10903           break;
10904
10905         default:
10906           HALT_UNALLOC;
10907         }
10908       break;
10909
10910     case 3: /* LD4R.  */
10911       switch (size)
10912         {
10913         case 0:
10914           {
10915             uint8_t val1 = aarch64_get_mem_u8 (cpu, address);
10916             uint8_t val2 = aarch64_get_mem_u8 (cpu, address + 1);
10917             uint8_t val3 = aarch64_get_mem_u8 (cpu, address + 2);
10918             uint8_t val4 = aarch64_get_mem_u8 (cpu, address + 3);
10919
10920             for (i = 0; i < (full ? 16 : 8); i++)
10921               {
10922                 aarch64_set_vec_u8 (cpu, vd, 0, val1);
10923                 aarch64_set_vec_u8 (cpu, vd + 1, 0, val2);
10924                 aarch64_set_vec_u8 (cpu, vd + 2, 0, val3);
10925                 aarch64_set_vec_u8 (cpu, vd + 3, 0, val4);
10926               }
10927           }
10928           break;
10929
10930         case 1:
10931           {
10932             uint32_t val1 = aarch64_get_mem_u16 (cpu, address);
10933             uint32_t val2 = aarch64_get_mem_u16 (cpu, address + 2);
10934             uint32_t val3 = aarch64_get_mem_u16 (cpu, address + 4);
10935             uint32_t val4 = aarch64_get_mem_u16 (cpu, address + 6);
10936
10937             for (i = 0; i < (full ? 8 : 4); i++)
10938               {
10939                 aarch64_set_vec_u16 (cpu, vd, 0, val1);
10940                 aarch64_set_vec_u16 (cpu, vd + 1, 0, val2);
10941                 aarch64_set_vec_u16 (cpu, vd + 2, 0, val3);
10942                 aarch64_set_vec_u16 (cpu, vd + 3, 0, val4);
10943               }
10944           }
10945           break;
10946
10947         case 2:
10948           {
10949             uint32_t val1 = aarch64_get_mem_u32 (cpu, address);
10950             uint32_t val2 = aarch64_get_mem_u32 (cpu, address + 4);
10951             uint32_t val3 = aarch64_get_mem_u32 (cpu, address + 8);
10952             uint32_t val4 = aarch64_get_mem_u32 (cpu, address + 12);
10953
10954             for (i = 0; i < (full ? 4 : 2); i++)
10955               {
10956                 aarch64_set_vec_u32 (cpu, vd, 0, val1);
10957                 aarch64_set_vec_u32 (cpu, vd + 1, 0, val2);
10958                 aarch64_set_vec_u32 (cpu, vd + 2, 0, val3);
10959                 aarch64_set_vec_u32 (cpu, vd + 3, 0, val4);
10960               }
10961           }
10962           break;
10963
10964         case 3:
10965           {
10966             uint64_t val1 = aarch64_get_mem_u64 (cpu, address);
10967             uint64_t val2 = aarch64_get_mem_u64 (cpu, address + 8);
10968             uint64_t val3 = aarch64_get_mem_u64 (cpu, address + 16);
10969             uint64_t val4 = aarch64_get_mem_u64 (cpu, address + 24);
10970
10971             for (i = 0; i < (full ? 2 : 1); i++)
10972               {
10973                 aarch64_set_vec_u64 (cpu, vd, 0, val1);
10974                 aarch64_set_vec_u64 (cpu, vd + 1, 0, val2);
10975                 aarch64_set_vec_u64 (cpu, vd + 2, 0, val3);
10976                 aarch64_set_vec_u64 (cpu, vd + 3, 0, val4);
10977               }
10978           }
10979           break;
10980
10981         default:
10982           HALT_UNALLOC;
10983         }
10984       break;
10985
10986     default:
10987       HALT_UNALLOC;
10988     }
10989 }
10990
10991 static void
10992 do_vec_load_store (sim_cpu *cpu)
10993 {
10994   /* {LD|ST}<N>   {Vd..Vd+N}, vaddr
10995
10996      instr[31]    = 0
10997      instr[30]    = element selector 0=>half, 1=>all elements
10998      instr[29,25] = 00110
10999      instr[24]    = ?
11000      instr[23]    = 0=>simple, 1=>post
11001      instr[22]    = 0=>store, 1=>load
11002      instr[21]    = 0 (LDn) / small(0)-large(1) selector (LDnR)
11003      instr[20,16] = 00000 (simple), Vinc (reg-post-inc, no SP),
11004                     11111 (immediate post inc)
11005      instr[15,12] = elements and destinations.  eg for load:
11006                      0000=>LD4 => load multiple 4-element to
11007                      four consecutive registers
11008                      0100=>LD3 => load multiple 3-element to
11009                      three consecutive registers
11010                      1000=>LD2 => load multiple 2-element to
11011                      two consecutive registers
11012                      0010=>LD1 => load multiple 1-element to
11013                      four consecutive registers
11014                      0110=>LD1 => load multiple 1-element to
11015                      three consecutive registers
11016                      1010=>LD1 => load multiple 1-element to
11017                      two consecutive registers
11018                      0111=>LD1 => load multiple 1-element to
11019                      one register
11020                      1100=>LDR1,LDR2
11021                      1110=>LDR3,LDR4
11022      instr[11,10] = element size 00=> byte(b), 01=> half(h),
11023                                  10=> word(s), 11=> double(d)
11024      instr[9,5]   = Vn, can be SP
11025      instr[4,0]   = Vd  */
11026
11027   int post;
11028   int load;
11029   unsigned vn;
11030   uint64_t address;
11031   int type;
11032
11033   if (uimm (aarch64_get_instr (cpu), 31, 31) != 0
11034       || uimm (aarch64_get_instr (cpu), 29, 25) != 0x06)
11035     HALT_NYI;
11036
11037   type = uimm (aarch64_get_instr (cpu), 15, 12);
11038   if (type != 0xE && type != 0xE && uimm (aarch64_get_instr (cpu), 21, 21) != 0)
11039     HALT_NYI;
11040
11041   post = uimm (aarch64_get_instr (cpu), 23, 23);
11042   load = uimm (aarch64_get_instr (cpu), 22, 22);
11043   vn = uimm (aarch64_get_instr (cpu), 9, 5);
11044   address = aarch64_get_reg_u64 (cpu, vn, SP_OK);
11045
11046   if (post)
11047     {
11048       unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
11049
11050       if (vm == R31)
11051         {
11052           unsigned sizeof_operation;
11053
11054           switch (type)
11055             {
11056             case 0: sizeof_operation = 32; break;
11057             case 4: sizeof_operation = 24; break;
11058             case 8: sizeof_operation = 16; break;
11059
11060             case 0xC:
11061               sizeof_operation = uimm (aarch64_get_instr (cpu), 21, 21) ? 2 : 1;
11062               sizeof_operation <<= uimm (aarch64_get_instr (cpu), 11, 10);
11063               break;
11064
11065             case 0xE:
11066               sizeof_operation = uimm (aarch64_get_instr (cpu), 21, 21) ? 8 : 4;
11067               sizeof_operation <<= uimm (aarch64_get_instr (cpu), 11, 10);
11068               break;
11069
11070             case 7:
11071               /* One register, immediate offset variant.  */
11072               sizeof_operation = 8;
11073               break;
11074               
11075             case 10:
11076               /* Two registers, immediate offset variant.  */
11077               sizeof_operation = 16;
11078               break;
11079
11080             case 6:
11081               /* Three registers, immediate offset variant.  */
11082               sizeof_operation = 24;
11083               break;
11084
11085             case 2:
11086               /* Four registers, immediate offset variant.  */
11087               sizeof_operation = 32;
11088               break;
11089
11090             default:
11091               HALT_UNALLOC;
11092             }
11093
11094           if (uimm (aarch64_get_instr (cpu), 30, 30))
11095             sizeof_operation *= 2;
11096
11097           aarch64_set_reg_u64 (cpu, vn, SP_OK, address + sizeof_operation);
11098         }
11099       else
11100         aarch64_set_reg_u64 (cpu, vn, SP_OK,
11101                              address + aarch64_get_reg_u64 (cpu, vm, NO_SP));
11102     }
11103   else
11104     {
11105       NYI_assert (20, 16, 0);
11106     }
11107
11108   if (load)
11109     {
11110       switch (type)
11111         {
11112         case 0:  LD4 (cpu, address); return;
11113         case 4:  LD3 (cpu, address); return;
11114         case 8:  LD2 (cpu, address); return;
11115         case 2:  LD1_4 (cpu, address); return;
11116         case 6:  LD1_3 (cpu, address); return;
11117         case 10: LD1_2 (cpu, address); return;
11118         case 7:  LD1_1 (cpu, address); return;
11119
11120         case 0xE:
11121         case 0xC: do_vec_LDnR (cpu, address); return;
11122
11123         default:
11124           HALT_NYI;
11125         }
11126     }
11127
11128   /* Stores.  */
11129   switch (type)
11130     {
11131     case 0:  ST4 (cpu, address); return;
11132     case 4:  ST3 (cpu, address); return;
11133     case 8:  ST2 (cpu, address); return;
11134     case 2:  ST1_4 (cpu, address); return;
11135     case 6:  ST1_3 (cpu, address); return;
11136     case 10: ST1_2 (cpu, address); return;
11137     case 7:  ST1_1 (cpu, address); return;
11138     default:
11139       HALT_NYI;
11140     }
11141 }
11142
11143 static void
11144 dexLdSt (sim_cpu *cpu)
11145 {
11146   /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
11147      assert  group == GROUP_LDST_0100 || group == GROUP_LDST_0110 ||
11148              group == GROUP_LDST_1100 || group == GROUP_LDST_1110
11149      bits [29,28:26] of a LS are the secondary dispatch vector.  */
11150   uint32_t group2 = dispatchLS (aarch64_get_instr (cpu));
11151
11152   switch (group2)
11153     {
11154     case LS_EXCL_000:
11155       dexLoadExclusive (cpu); return;
11156
11157     case LS_LIT_010:
11158     case LS_LIT_011:
11159       dexLoadLiteral (cpu); return;
11160
11161     case LS_OTHER_110:
11162     case LS_OTHER_111:
11163       dexLoadOther (cpu); return;
11164
11165     case LS_ADVSIMD_001:
11166       do_vec_load_store (cpu); return;
11167
11168     case LS_PAIR_100:
11169       dex_load_store_pair_gr (cpu); return;
11170
11171     case LS_PAIR_101:
11172       dex_load_store_pair_fp (cpu); return;
11173
11174     default:
11175       /* Should never reach here.  */
11176       HALT_NYI;
11177     }
11178 }
11179
11180 /* Specific decode and execute for group Data Processing Register.  */
11181
11182 static void
11183 dexLogicalShiftedRegister (sim_cpu *cpu)
11184 {
11185   /* assert instr[28:24] = 01010
11186      instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11187      instr[30,29:21] = op,N : 000 ==> AND, 001 ==> BIC,
11188                                010 ==> ORR, 011 ==> ORN
11189                                100 ==> EOR, 101 ==> EON,
11190                                110 ==> ANDS, 111 ==> BICS
11191      instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> ROR
11192      instr[15,10] = count : must be 0xxxxx for 32 bit
11193      instr[9,5] = Rn
11194      instr[4,0] = Rd  */
11195
11196   /* unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16); */
11197   uint32_t dispatch;
11198   Shift shiftType;
11199   uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
11200
11201   /* 32 bit operations must have count[5] = 0.  */
11202   /* or else we have an UNALLOC.  */
11203   uint32_t count = uimm (aarch64_get_instr (cpu), 15, 10);
11204
11205   if (!size && uimm (count, 5, 5))
11206     HALT_UNALLOC;
11207
11208   shiftType = shift (aarch64_get_instr (cpu), 22);
11209
11210   /* dispatch on size:op:N i.e aarch64_get_instr (cpu)[31,29:21].  */
11211   dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 29) << 1)
11212               | uimm (aarch64_get_instr (cpu), 21, 21));
11213
11214   switch (dispatch)
11215     {
11216     case 0: and32_shift  (cpu, shiftType, count); return;
11217     case 1: bic32_shift  (cpu, shiftType, count); return;
11218     case 2: orr32_shift  (cpu, shiftType, count); return;
11219     case 3: orn32_shift  (cpu, shiftType, count); return;
11220     case 4: eor32_shift  (cpu, shiftType, count); return;
11221     case 5: eon32_shift  (cpu, shiftType, count); return;
11222     case 6: ands32_shift (cpu, shiftType, count); return;
11223     case 7: bics32_shift (cpu, shiftType, count); return;
11224     case 8: and64_shift  (cpu, shiftType, count); return;
11225     case 9: bic64_shift  (cpu, shiftType, count); return;
11226     case 10:orr64_shift  (cpu, shiftType, count); return;
11227     case 11:orn64_shift  (cpu, shiftType, count); return;
11228     case 12:eor64_shift  (cpu, shiftType, count); return;
11229     case 13:eon64_shift  (cpu, shiftType, count); return;
11230     case 14:ands64_shift (cpu, shiftType, count); return;
11231     case 15:bics64_shift (cpu, shiftType, count); return;
11232     default: HALT_UNALLOC;
11233     }
11234 }
11235
11236 /* 32 bit conditional select.  */
11237 static void
11238 csel32 (sim_cpu *cpu, CondCode cc)
11239 {
11240   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11241   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11242   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11243
11244   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11245                        testConditionCode (cpu, cc)
11246                        ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11247                        : aarch64_get_reg_u32 (cpu, rm, NO_SP));
11248 }
11249
11250 /* 64 bit conditional select.  */
11251 static void
11252 csel64 (sim_cpu *cpu, CondCode cc)
11253 {
11254   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11255   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11256   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11257
11258   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11259                        testConditionCode (cpu, cc)
11260                        ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11261                        : aarch64_get_reg_u64 (cpu, rm, NO_SP));
11262 }
11263
11264 /* 32 bit conditional increment.  */
11265 static void
11266 csinc32 (sim_cpu *cpu, CondCode cc)
11267 {
11268   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11269   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11270   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11271
11272   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11273                        testConditionCode (cpu, cc)
11274                        ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11275                        : aarch64_get_reg_u32 (cpu, rm, NO_SP) + 1);
11276 }
11277
11278 /* 64 bit conditional increment.  */
11279 static void
11280 csinc64 (sim_cpu *cpu, CondCode cc)
11281 {
11282   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11283   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11284   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11285
11286   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11287                        testConditionCode (cpu, cc)
11288                        ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11289                        : aarch64_get_reg_u64 (cpu, rm, NO_SP) + 1);
11290 }
11291
11292 /* 32 bit conditional invert.  */
11293 static void
11294 csinv32 (sim_cpu *cpu, CondCode cc)
11295 {
11296   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11297   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11298   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11299
11300   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11301                        testConditionCode (cpu, cc)
11302                        ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11303                        : ~ aarch64_get_reg_u32 (cpu, rm, NO_SP));
11304 }
11305
11306 /* 64 bit conditional invert.  */
11307 static void
11308 csinv64 (sim_cpu *cpu, CondCode cc)
11309 {
11310   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11311   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11312   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11313
11314   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11315                        testConditionCode (cpu, cc)
11316                        ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11317                        : ~ aarch64_get_reg_u64 (cpu, rm, NO_SP));
11318 }
11319
11320 /* 32 bit conditional negate.  */
11321 static void
11322 csneg32 (sim_cpu *cpu, CondCode cc)
11323 {
11324   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11325   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11326   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11327
11328   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11329                        testConditionCode (cpu, cc)
11330                        ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11331                        : - aarch64_get_reg_u32 (cpu, rm, NO_SP));
11332 }
11333
11334 /* 64 bit conditional negate.  */
11335 static void
11336 csneg64 (sim_cpu *cpu, CondCode cc)
11337 {
11338   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11339   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11340   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11341
11342   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11343                        testConditionCode (cpu, cc)
11344                        ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11345                        : - aarch64_get_reg_u64 (cpu, rm, NO_SP));
11346 }
11347
11348 static void
11349 dexCondSelect (sim_cpu *cpu)
11350 {
11351   /* assert instr[28,21] = 11011011
11352      instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11353      instr[30:11,10] = op : 000 ==> CSEL, 001 ==> CSINC,
11354                             100 ==> CSINV, 101 ==> CSNEG,
11355                             _1_ ==> UNALLOC
11356      instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
11357      instr[15,12] = cond
11358      instr[29] = S : 0 ==> ok, 1 ==> UNALLOC  */
11359
11360   CondCode cc;
11361   uint32_t dispatch;
11362   uint32_t S = uimm (aarch64_get_instr (cpu), 29, 29);
11363   uint32_t op2 = uimm (aarch64_get_instr (cpu), 11, 10);
11364
11365   if (S == 1)
11366     HALT_UNALLOC;
11367
11368   if (op2 & 0x2)
11369     HALT_UNALLOC;
11370
11371   cc = condcode (aarch64_get_instr (cpu), 12);
11372   dispatch = ((uimm (aarch64_get_instr (cpu), 31, 30) << 1) | op2);
11373
11374   switch (dispatch)
11375     {
11376     case 0: csel32  (cpu, cc); return;
11377     case 1: csinc32 (cpu, cc); return;
11378     case 2: csinv32 (cpu, cc); return;
11379     case 3: csneg32 (cpu, cc); return;
11380     case 4: csel64  (cpu, cc); return;
11381     case 5: csinc64 (cpu, cc); return;
11382     case 6: csinv64 (cpu, cc); return;
11383     case 7: csneg64 (cpu, cc); return;
11384     default: HALT_UNALLOC;
11385     }
11386 }
11387
11388 /* Some helpers for counting leading 1 or 0 bits.  */
11389
11390 /* Counts the number of leading bits which are the same
11391    in a 32 bit value in the range 1 to 32.  */
11392 static uint32_t
11393 leading32 (uint32_t value)
11394 {
11395   int32_t mask= 0xffff0000;
11396   uint32_t count= 16; /* Counts number of bits set in mask.  */
11397   uint32_t lo = 1;    /* Lower bound for number of sign bits.  */
11398   uint32_t hi = 32;   /* Upper bound for number of sign bits.  */
11399
11400   while (lo + 1 < hi)
11401     {
11402       int32_t test = (value & mask);
11403
11404       if (test == 0 || test == mask)
11405         {
11406           lo = count;
11407           count = (lo + hi) / 2;
11408           mask >>= (count - lo);
11409         }
11410       else
11411         {
11412           hi = count;
11413           count = (lo + hi) / 2;
11414           mask <<= hi - count;
11415         }
11416     }
11417
11418   if (lo != hi)
11419     {
11420       int32_t test;
11421
11422       mask >>= 1;
11423       test = (value & mask);
11424
11425       if (test == 0 || test == mask)
11426         count = hi;
11427       else
11428         count = lo;
11429     }
11430
11431   return count;
11432 }
11433
11434 /* Counts the number of leading bits which are the same
11435    in a 64 bit value in the range 1 to 64.  */
11436 static uint64_t
11437 leading64 (uint64_t value)
11438 {
11439   int64_t mask= 0xffffffff00000000LL;
11440   uint64_t count = 32; /* Counts number of bits set in mask.  */
11441   uint64_t lo = 1;     /* Lower bound for number of sign bits.  */
11442   uint64_t hi = 64;    /* Upper bound for number of sign bits.  */
11443
11444   while (lo + 1 < hi)
11445     {
11446       int64_t test = (value & mask);
11447
11448       if (test == 0 || test == mask)
11449         {
11450           lo = count;
11451           count = (lo + hi) / 2;
11452           mask >>= (count - lo);
11453         }
11454       else
11455         {
11456           hi = count;
11457           count = (lo + hi) / 2;
11458           mask <<= hi - count;
11459         }
11460     }
11461
11462   if (lo != hi)
11463     {
11464       int64_t test;
11465
11466       mask >>= 1;
11467       test = (value & mask);
11468
11469       if (test == 0 || test == mask)
11470         count = hi;
11471       else
11472         count = lo;
11473     }
11474
11475   return count;
11476 }
11477
11478 /* Bit operations.  */
11479 /* N.B register args may not be SP.  */
11480
11481 /* 32 bit count leading sign bits.  */
11482 static void
11483 cls32 (sim_cpu *cpu)
11484 {
11485   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11486   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11487
11488   /* N.B. the result needs to exclude the leading bit.  */
11489   aarch64_set_reg_u64
11490     (cpu, rd, NO_SP, leading32 (aarch64_get_reg_u32 (cpu, rn, NO_SP)) - 1);
11491 }
11492
11493 /* 64 bit count leading sign bits.  */
11494 static void
11495 cls64 (sim_cpu *cpu)
11496 {
11497   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11498   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11499
11500   /* N.B. the result needs to exclude the leading bit.  */
11501   aarch64_set_reg_u64
11502     (cpu, rd, NO_SP, leading64 (aarch64_get_reg_u64 (cpu, rn, NO_SP)) - 1);
11503 }
11504
11505 /* 32 bit count leading zero bits.  */
11506 static void
11507 clz32 (sim_cpu *cpu)
11508 {
11509   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11510   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11511   uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11512
11513   /* if the sign (top) bit is set then the count is 0.  */
11514   if (pick32 (value, 31, 31))
11515     aarch64_set_reg_u64 (cpu, rd, NO_SP, 0L);
11516   else
11517     aarch64_set_reg_u64 (cpu, rd, NO_SP, leading32 (value));
11518 }
11519
11520 /* 64 bit count leading zero bits.  */
11521 static void
11522 clz64 (sim_cpu *cpu)
11523 {
11524   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11525   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11526   uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11527
11528   /* if the sign (top) bit is set then the count is 0.  */
11529   if (pick64 (value, 63, 63))
11530     aarch64_set_reg_u64 (cpu, rd, NO_SP, 0L);
11531   else
11532     aarch64_set_reg_u64 (cpu, rd, NO_SP, leading64 (value));
11533 }
11534
11535 /* 32 bit reverse bits.  */
11536 static void
11537 rbit32 (sim_cpu *cpu)
11538 {
11539   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11540   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11541   uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11542   uint32_t result = 0;
11543   int i;
11544
11545   for (i = 0; i < 32; i++)
11546     {
11547       result <<= 1;
11548       result |= (value & 1);
11549       value >>= 1;
11550     }
11551   aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11552 }
11553
11554 /* 64 bit reverse bits.  */
11555 static void
11556 rbit64 (sim_cpu *cpu)
11557 {
11558   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11559   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11560   uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11561   uint64_t result = 0;
11562   int i;
11563
11564   for (i = 0; i < 64; i++)
11565     {
11566       result <<= 1;
11567       result |= (value & 1UL);
11568       value >>= 1;
11569     }
11570   aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11571 }
11572
11573 /* 32 bit reverse bytes.  */
11574 static void
11575 rev32 (sim_cpu *cpu)
11576 {
11577   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11578   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11579   uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11580   uint32_t result = 0;
11581   int i;
11582
11583   for (i = 0; i < 4; i++)
11584     {
11585       result <<= 8;
11586       result |= (value & 0xff);
11587       value >>= 8;
11588     }
11589   aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11590 }
11591
11592 /* 64 bit reverse bytes.  */
11593 static void
11594 rev64 (sim_cpu *cpu)
11595 {
11596   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11597   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11598   uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11599   uint64_t result = 0;
11600   int i;
11601
11602   for (i = 0; i < 8; i++)
11603     {
11604       result <<= 8;
11605       result |= (value & 0xffULL);
11606       value >>= 8;
11607     }
11608   aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11609 }
11610
11611 /* 32 bit reverse shorts.  */
11612 /* N.B.this reverses the order of the bytes in each half word.  */
11613 static void
11614 revh32 (sim_cpu *cpu)
11615 {
11616   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11617   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11618   uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11619   uint32_t result = 0;
11620   int i;
11621
11622   for (i = 0; i < 2; i++)
11623     {
11624       result <<= 8;
11625       result |= (value & 0x00ff00ff);
11626       value >>= 8;
11627     }
11628   aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11629 }
11630
11631 /* 64 bit reverse shorts.  */
11632 /* N.B.this reverses the order of the bytes in each half word.  */
11633 static void
11634 revh64 (sim_cpu *cpu)
11635 {
11636   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11637   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11638   uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11639   uint64_t result = 0;
11640   int i;
11641
11642   for (i = 0; i < 2; i++)
11643     {
11644       result <<= 8;
11645       result |= (value & 0x00ff00ff00ff00ffULL);
11646       value >>= 8;
11647     }
11648   aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11649 }
11650
11651 static void
11652 dexDataProc1Source (sim_cpu *cpu)
11653 {
11654   /* assert instr[30] == 1
11655      aarch64_get_instr (cpu)[28,21] == 111010110
11656      instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11657      instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
11658      instr[20,16] = opcode2 : 00000 ==> ok, ow ==> UNALLOC
11659      instr[15,10] = opcode : 000000 ==> RBIT, 000001 ==> REV16,
11660                              000010 ==> REV, 000011 ==> UNALLOC
11661                              000100 ==> CLZ, 000101 ==> CLS
11662                              ow ==> UNALLOC
11663      instr[9,5] = rn : may not be SP
11664      instr[4,0] = rd : may not be SP.  */
11665
11666   uint32_t S = uimm (aarch64_get_instr (cpu), 29, 29);
11667   uint32_t opcode2 = uimm (aarch64_get_instr (cpu), 20, 16);
11668   uint32_t opcode = uimm (aarch64_get_instr (cpu), 15, 10);
11669   uint32_t dispatch = ((uimm (aarch64_get_instr (cpu), 31, 31) << 3) | opcode);
11670
11671   if (S == 1)
11672     HALT_UNALLOC;
11673
11674   if (opcode2 != 0)
11675     HALT_UNALLOC;
11676
11677   if (opcode & 0x38)
11678     HALT_UNALLOC;
11679
11680   switch (dispatch)
11681     {
11682     case 0: rbit32 (cpu); return;
11683     case 1: revh32 (cpu); return;
11684     case 2: rev32 (cpu); return;
11685     case 4: clz32 (cpu); return;
11686     case 5: cls32 (cpu); return;
11687     case 8: rbit64 (cpu); return;
11688     case 9: revh64 (cpu); return;
11689     case 10:rev32 (cpu); return;
11690     case 11:rev64 (cpu); return;
11691     case 12:clz64 (cpu); return;
11692     case 13:cls64 (cpu); return;
11693     default: HALT_UNALLOC;
11694     }
11695 }
11696
11697 /* Variable shift.
11698    Shifts by count supplied in register.
11699    N.B register args may not be SP.
11700    These all use the shifted auxiliary function for
11701    simplicity and clarity.  Writing the actual shift
11702    inline would avoid a branch and so be faster but
11703    would also necessitate getting signs right.  */
11704
11705 /* 32 bit arithmetic shift right.  */
11706 static void
11707 asrv32 (sim_cpu *cpu)
11708 {
11709   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11710   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11711   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11712
11713   aarch64_set_reg_u64
11714     (cpu, rd, NO_SP,
11715      shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), ASR,
11716                 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
11717 }
11718
11719 /* 64 bit arithmetic shift right.  */
11720 static void
11721 asrv64 (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   aarch64_set_reg_u64
11728     (cpu, rd, NO_SP,
11729      shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), ASR,
11730                 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
11731 }
11732
11733 /* 32 bit logical shift left.  */
11734 static void
11735 lslv32 (sim_cpu *cpu)
11736 {
11737   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11738   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11739   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11740
11741   aarch64_set_reg_u64
11742     (cpu, rd, NO_SP,
11743      shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), LSL,
11744                 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
11745 }
11746
11747 /* 64 bit arithmetic shift left.  */
11748 static void
11749 lslv64 (sim_cpu *cpu)
11750 {
11751   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11752   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11753   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11754
11755   aarch64_set_reg_u64
11756     (cpu, rd, NO_SP,
11757      shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), LSL,
11758                 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
11759 }
11760
11761 /* 32 bit logical shift right.  */
11762 static void
11763 lsrv32 (sim_cpu *cpu)
11764 {
11765   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11766   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11767   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11768
11769   aarch64_set_reg_u64
11770     (cpu, rd, NO_SP,
11771      shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), LSR,
11772                 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
11773 }
11774
11775 /* 64 bit logical shift right.  */
11776 static void
11777 lsrv64 (sim_cpu *cpu)
11778 {
11779   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11780   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11781   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11782
11783   aarch64_set_reg_u64
11784     (cpu, rd, NO_SP,
11785      shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), LSR,
11786                 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
11787 }
11788
11789 /* 32 bit rotate right.  */
11790 static void
11791 rorv32 (sim_cpu *cpu)
11792 {
11793   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11794   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11795   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11796
11797   aarch64_set_reg_u64
11798     (cpu, rd, NO_SP,
11799      shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), ROR,
11800                 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
11801 }
11802
11803 /* 64 bit rotate right.  */
11804 static void
11805 rorv64 (sim_cpu *cpu)
11806 {
11807   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11808   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11809   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11810
11811   aarch64_set_reg_u64
11812     (cpu, rd, NO_SP,
11813      shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), ROR,
11814                 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
11815 }
11816
11817
11818 /* divide.  */
11819
11820 /* 32 bit signed divide.  */
11821 static void
11822 cpuiv32 (sim_cpu *cpu)
11823 {
11824   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11825   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11826   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11827   /* N.B. the pseudo-code does the divide using 64 bit data.  */
11828   /* TODO : check that this rounds towards zero as required.  */
11829   int64_t dividend = aarch64_get_reg_s32 (cpu, rn, NO_SP);
11830   int64_t divisor = aarch64_get_reg_s32 (cpu, rm, NO_SP);
11831
11832   aarch64_set_reg_s64 (cpu, rd, NO_SP,
11833                        divisor ? ((int32_t) (dividend / divisor)) : 0);
11834 }
11835
11836 /* 64 bit signed divide.  */
11837 static void
11838 cpuiv64 (sim_cpu *cpu)
11839 {
11840   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11841   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11842   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11843
11844   /* TODO : check that this rounds towards zero as required.  */
11845   int64_t divisor = aarch64_get_reg_s64 (cpu, rm, NO_SP);
11846
11847   aarch64_set_reg_s64
11848     (cpu, rd, NO_SP,
11849      divisor ? (aarch64_get_reg_s64 (cpu, rn, NO_SP) / divisor) : 0);
11850 }
11851
11852 /* 32 bit unsigned divide.  */
11853 static void
11854 udiv32 (sim_cpu *cpu)
11855 {
11856   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11857   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11858   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11859
11860   /* N.B. the pseudo-code does the divide using 64 bit data.  */
11861   uint64_t dividend = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11862   uint64_t divisor  = aarch64_get_reg_u32 (cpu, rm, NO_SP);
11863
11864   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11865                        divisor ? (uint32_t) (dividend / divisor) : 0);
11866 }
11867
11868 /* 64 bit unsigned divide.  */
11869 static void
11870 udiv64 (sim_cpu *cpu)
11871 {
11872   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11873   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11874   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11875
11876   /* TODO : check that this rounds towards zero as required.  */
11877   uint64_t divisor = aarch64_get_reg_u64 (cpu, rm, NO_SP);
11878
11879   aarch64_set_reg_u64
11880     (cpu, rd, NO_SP,
11881      divisor ? (aarch64_get_reg_u64 (cpu, rn, NO_SP) / divisor) : 0);
11882 }
11883
11884 static void
11885 dexDataProc2Source (sim_cpu *cpu)
11886 {
11887   /* assert instr[30] == 0
11888      instr[28,21] == 11010110
11889      instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11890      instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
11891      instr[15,10] = opcode : 000010 ==> UDIV, 000011 ==> CPUIV,
11892                              001000 ==> LSLV, 001001 ==> LSRV
11893                              001010 ==> ASRV, 001011 ==> RORV
11894                              ow ==> UNALLOC.  */
11895
11896   uint32_t dispatch;
11897   uint32_t S = uimm (aarch64_get_instr (cpu), 29, 29);
11898   uint32_t opcode = uimm (aarch64_get_instr (cpu), 15, 10);
11899
11900   if (S == 1)
11901     HALT_UNALLOC;
11902
11903   if (opcode & 0x34)
11904     HALT_UNALLOC;
11905
11906   dispatch = (  (uimm (aarch64_get_instr (cpu), 31, 31) << 3)
11907               | (uimm (opcode, 3, 3) << 2)
11908               |  uimm (opcode, 1, 0));
11909   switch (dispatch)
11910     {
11911     case 2:  udiv32 (cpu); return;
11912     case 3:  cpuiv32 (cpu); return;
11913     case 4:  lslv32 (cpu); return;
11914     case 5:  lsrv32 (cpu); return;
11915     case 6:  asrv32 (cpu); return;
11916     case 7:  rorv32 (cpu); return;
11917     case 10: udiv64 (cpu); return;
11918     case 11: cpuiv64 (cpu); return;
11919     case 12: lslv64 (cpu); return;
11920     case 13: lsrv64 (cpu); return;
11921     case 14: asrv64 (cpu); return;
11922     case 15: rorv64 (cpu); return;
11923     default: HALT_UNALLOC;
11924     }
11925 }
11926
11927
11928 /* Multiply.  */
11929
11930 /* 32 bit multiply and add.  */
11931 static void
11932 madd32 (sim_cpu *cpu)
11933 {
11934   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11935   unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11936   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11937   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11938
11939   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11940                        aarch64_get_reg_u32 (cpu, ra, NO_SP)
11941                        + aarch64_get_reg_u32 (cpu, rn, NO_SP)
11942                        * aarch64_get_reg_u32 (cpu, rm, NO_SP));
11943 }
11944
11945 /* 64 bit multiply and add.  */
11946 static void
11947 madd64 (sim_cpu *cpu)
11948 {
11949   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11950   unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11951   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11952   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11953
11954   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11955                        aarch64_get_reg_u64 (cpu, ra, NO_SP)
11956                        + aarch64_get_reg_u64 (cpu, rn, NO_SP)
11957                        * aarch64_get_reg_u64 (cpu, rm, NO_SP));
11958 }
11959
11960 /* 32 bit multiply and sub.  */
11961 static void
11962 msub32 (sim_cpu *cpu)
11963 {
11964   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11965   unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11966   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11967   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11968
11969   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11970                        aarch64_get_reg_u32 (cpu, ra, NO_SP)
11971                        - aarch64_get_reg_u32 (cpu, rn, NO_SP)
11972                        * aarch64_get_reg_u32 (cpu, rm, NO_SP));
11973 }
11974
11975 /* 64 bit multiply and sub.  */
11976 static void
11977 msub64 (sim_cpu *cpu)
11978 {
11979   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11980   unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11981   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11982   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11983
11984   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11985                        aarch64_get_reg_u64 (cpu, ra, NO_SP)
11986                        - aarch64_get_reg_u64 (cpu, rn, NO_SP)
11987                        * aarch64_get_reg_u64 (cpu, rm, NO_SP));
11988 }
11989
11990 /* Signed multiply add long -- source, source2 : 32 bit, source3 : 64 bit.  */
11991 static void
11992 smaddl (sim_cpu *cpu)
11993 {
11994   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11995   unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11996   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11997   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11998
11999   /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12000      obtain a 64 bit product.  */
12001   aarch64_set_reg_s64
12002     (cpu, rd, NO_SP,
12003      aarch64_get_reg_s64 (cpu, ra, NO_SP)
12004      + ((int64_t) aarch64_get_reg_s32 (cpu, rn, NO_SP))
12005      * ((int64_t) aarch64_get_reg_s32 (cpu, rm, NO_SP)));
12006 }
12007
12008 /* Signed multiply sub long -- source, source2 : 32 bit, source3 : 64 bit.  */
12009 static void
12010 smsubl (sim_cpu *cpu)
12011 {
12012   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12013   unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
12014   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12015   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12016
12017   /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12018      obtain a 64 bit product.  */
12019   aarch64_set_reg_s64
12020     (cpu, rd, NO_SP,
12021      aarch64_get_reg_s64 (cpu, ra, NO_SP)
12022      - ((int64_t) aarch64_get_reg_s32 (cpu, rn, NO_SP))
12023      * ((int64_t) aarch64_get_reg_s32 (cpu, rm, NO_SP)));
12024 }
12025
12026 /* Integer Multiply/Divide.  */
12027
12028 /* First some macros and a helper function.  */
12029 /* Macros to test or access elements of 64 bit words.  */
12030
12031 /* Mask used to access lo 32 bits of 64 bit unsigned int.  */
12032 #define LOW_WORD_MASK ((1ULL << 32) - 1)
12033 /* Return the lo 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int.  */
12034 #define lowWordToU64(_value_u64) ((_value_u64) & LOW_WORD_MASK)
12035 /* Return the hi 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int.  */
12036 #define highWordToU64(_value_u64) ((_value_u64) >> 32)
12037
12038 /* Offset of sign bit in 64 bit signed integger.  */
12039 #define SIGN_SHIFT_U64 63
12040 /* The sign bit itself -- also identifies the minimum negative int value.  */
12041 #define SIGN_BIT_U64 (1UL << SIGN_SHIFT_U64)
12042 /* Return true if a 64 bit signed int presented as an unsigned int is the
12043    most negative value.  */
12044 #define isMinimumU64(_value_u64) ((_value_u64) == SIGN_BIT_U64)
12045 /* Return true (non-zero) if a 64 bit signed int presented as an unsigned
12046    int has its sign bit set to false.  */
12047 #define isSignSetU64(_value_u64) ((_value_u64) & SIGN_BIT_U64)
12048 /* Return 1L or -1L according to whether a 64 bit signed int presented as
12049    an unsigned int has its sign bit set or not.  */
12050 #define signOfU64(_value_u64) (1L + (((value_u64) >> SIGN_SHIFT_U64) * -2L)
12051 /* Clear the sign bit of a 64 bit signed int presented as an unsigned int.  */
12052 #define clearSignU64(_value_u64) ((_value_u64) &= ~SIGN_BIT_U64)
12053
12054 /* Multiply two 64 bit ints and return.
12055    the hi 64 bits of the 128 bit product.  */
12056
12057 static uint64_t
12058 mul64hi (uint64_t value1, uint64_t value2)
12059 {
12060   uint64_t resultmid1;
12061   uint64_t result;
12062   uint64_t value1_lo = lowWordToU64 (value1);
12063   uint64_t value1_hi = highWordToU64 (value1) ;
12064   uint64_t value2_lo = lowWordToU64 (value2);
12065   uint64_t value2_hi = highWordToU64 (value2);
12066
12067   /* Cross-multiply and collect results.  */
12068
12069   uint64_t xproductlo = value1_lo * value2_lo;
12070   uint64_t xproductmid1 = value1_lo * value2_hi;
12071   uint64_t xproductmid2 = value1_hi * value2_lo;
12072   uint64_t xproducthi = value1_hi * value2_hi;
12073   uint64_t carry = 0;
12074   /* Start accumulating 64 bit results.  */
12075   /* Drop bottom half of lowest cross-product.  */
12076   uint64_t resultmid = xproductlo >> 32;
12077   /* Add in middle products.  */
12078   resultmid = resultmid + xproductmid1;
12079
12080   /* Check for overflow.  */
12081   if (resultmid < xproductmid1)
12082     /* Carry over 1 into top cross-product.  */
12083     carry++;
12084
12085   resultmid1  = resultmid + xproductmid2;
12086
12087   /* Check for overflow.  */
12088   if (resultmid1 < xproductmid2)
12089     /* Carry over 1 into top cross-product.  */
12090     carry++;
12091
12092   /* Drop lowest 32 bits of middle cross-product.  */
12093   result = resultmid1 >> 32;
12094
12095   /* Add top cross-product plus and any carry.  */
12096   result += xproducthi + carry;
12097
12098   return result;
12099 }
12100
12101 /* Signed multiply high, source, source2 :
12102    64 bit, dest <-- high 64-bit of result.  */
12103 static void
12104 smulh (sim_cpu *cpu)
12105 {
12106   uint64_t uresult;
12107   int64_t result;
12108   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12109   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12110   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12111   GReg ra = greg (aarch64_get_instr (cpu), 10);
12112   int64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
12113   int64_t value2 = aarch64_get_reg_u64 (cpu, rm, NO_SP);
12114   uint64_t uvalue1;
12115   uint64_t uvalue2;
12116   int64_t signum = 1;
12117
12118   if (ra != R31)
12119     HALT_UNALLOC;
12120
12121   /* Convert to unsigned and use the unsigned mul64hi routine
12122      the fix the sign up afterwards.  */
12123   if (value1 < 0)
12124     {
12125       signum *= -1L;
12126       uvalue1 = -value1;
12127     }
12128   else
12129     {
12130       uvalue1 = value1;
12131     }
12132
12133   if (value2 < 0)
12134     {
12135       signum *= -1L;
12136       uvalue2 = -value2;
12137     }
12138   else
12139     {
12140       uvalue2 = value2;
12141     }
12142
12143   uresult = mul64hi (uvalue1, uvalue2);
12144   result = uresult;
12145   result *= signum;
12146
12147   aarch64_set_reg_s64 (cpu, rd, NO_SP, result);
12148 }
12149
12150 /* Unsigned multiply add long -- source, source2 :
12151    32 bit, source3 : 64 bit.  */
12152 static void
12153 umaddl (sim_cpu *cpu)
12154 {
12155   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12156   unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
12157   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12158   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12159
12160   /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12161      obtain a 64 bit product.  */
12162   aarch64_set_reg_u64
12163     (cpu, rd, NO_SP,
12164      aarch64_get_reg_u64 (cpu, ra, NO_SP)
12165      + ((uint64_t) aarch64_get_reg_u32 (cpu, rn, NO_SP))
12166      * ((uint64_t) aarch64_get_reg_u32 (cpu, rm, NO_SP)));
12167 }
12168
12169 /* Unsigned multiply sub long -- source, source2 : 32 bit, source3 : 64 bit.  */
12170 static void
12171 umsubl (sim_cpu *cpu)
12172 {
12173   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12174   unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
12175   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12176   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12177
12178   /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12179      obtain a 64 bit product.  */
12180   aarch64_set_reg_u64
12181     (cpu, rd, NO_SP,
12182      aarch64_get_reg_u64 (cpu, ra, NO_SP)
12183      - ((uint64_t) aarch64_get_reg_u32 (cpu, rn, NO_SP))
12184      * ((uint64_t) aarch64_get_reg_u32 (cpu, rm, NO_SP)));
12185 }
12186
12187 /* Unsigned multiply high, source, source2 :
12188    64 bit, dest <-- high 64-bit of result.  */
12189 static void
12190 umulh (sim_cpu *cpu)
12191 {
12192   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12193   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12194   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12195   GReg ra = greg (aarch64_get_instr (cpu), 10);
12196
12197   if (ra != R31)
12198     HALT_UNALLOC;
12199
12200   aarch64_set_reg_u64 (cpu, rd, NO_SP,
12201                        mul64hi (aarch64_get_reg_u64 (cpu, rn, NO_SP),
12202                                 aarch64_get_reg_u64 (cpu, rm, NO_SP)));
12203 }
12204
12205 static void
12206 dexDataProc3Source (sim_cpu *cpu)
12207 {
12208   /* assert instr[28,24] == 11011.  */
12209   /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit (for rd at least)
12210      instr[30,29] = op54 : 00 ==> ok, ow ==> UNALLOC
12211      instr[23,21] = op31 : 111 ==> UNALLOC, o2 ==> ok
12212      instr[15] = o0 : 0/1 ==> ok
12213      instr[23,21:15] ==> op : 0000 ==> MADD, 0001 ==> MSUB,     (32/64 bit)
12214                               0010 ==> SMADDL, 0011 ==> SMSUBL, (64 bit only)
12215                               0100 ==> SMULH,                   (64 bit only)
12216                               1010 ==> UMADDL, 1011 ==> UNSUBL, (64 bit only)
12217                               1100 ==> UMULH                    (64 bit only)
12218                               ow ==> UNALLOC.  */
12219
12220   uint32_t dispatch;
12221   uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
12222   uint32_t op54 = uimm (aarch64_get_instr (cpu), 30, 29);
12223   uint32_t op31 = uimm (aarch64_get_instr (cpu), 23, 21);
12224   uint32_t o0 = uimm (aarch64_get_instr (cpu), 15, 15);
12225
12226   if (op54 != 0)
12227     HALT_UNALLOC;
12228
12229   if (size == 0)
12230     {
12231       if (op31 != 0)
12232         HALT_UNALLOC;
12233
12234       if (o0 == 0)
12235         madd32 (cpu);
12236       else
12237         msub32 (cpu);
12238       return;
12239     }
12240
12241   dispatch = (op31 << 1) | o0;
12242
12243   switch (dispatch)
12244     {
12245     case 0:  madd64 (cpu); return;
12246     case 1:  msub64 (cpu); return;
12247     case 2:  smaddl (cpu); return;
12248     case 3:  smsubl (cpu); return;
12249     case 4:  smulh (cpu); return;
12250     case 10: umaddl (cpu); return;
12251     case 11: umsubl (cpu); return;
12252     case 12: umulh (cpu); return;
12253     default: HALT_UNALLOC;
12254     }
12255 }
12256
12257 static void
12258 dexDPReg (sim_cpu *cpu)
12259 {
12260   /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
12261      assert  group == GROUP_DPREG_0101 || group == GROUP_DPREG_1101
12262      bits [28:24:21] of a DPReg are the secondary dispatch vector.  */
12263   uint32_t group2 = dispatchDPReg (aarch64_get_instr (cpu));
12264
12265   switch (group2)
12266     {
12267     case DPREG_LOG_000:
12268     case DPREG_LOG_001:
12269       dexLogicalShiftedRegister (cpu); return;
12270
12271     case DPREG_ADDSHF_010:
12272       dexAddSubtractShiftedRegister (cpu); return;
12273
12274     case DPREG_ADDEXT_011:
12275       dexAddSubtractExtendedRegister (cpu); return;
12276
12277     case DPREG_ADDCOND_100:
12278       {
12279         /* This set bundles a variety of different operations.  */
12280         /* Check for.  */
12281         /* 1) add/sub w carry.  */
12282         uint32_t mask1 = 0x1FE00000U;
12283         uint32_t val1  = 0x1A000000U;
12284         /* 2) cond compare register/immediate.  */
12285         uint32_t mask2 = 0x1FE00000U;
12286         uint32_t val2  = 0x1A400000U;
12287         /* 3) cond select.  */
12288         uint32_t mask3 = 0x1FE00000U;
12289         uint32_t val3  = 0x1A800000U;
12290         /* 4) data proc 1/2 source.  */
12291         uint32_t mask4 = 0x1FE00000U;
12292         uint32_t val4  = 0x1AC00000U;
12293
12294         if ((aarch64_get_instr (cpu) & mask1) == val1)
12295           dexAddSubtractWithCarry (cpu);
12296
12297         else if ((aarch64_get_instr (cpu) & mask2) == val2)
12298           CondCompare (cpu);
12299
12300         else if ((aarch64_get_instr (cpu) & mask3) == val3)
12301           dexCondSelect (cpu);
12302
12303         else if ((aarch64_get_instr (cpu) & mask4) == val4)
12304           {
12305             /* Bit 30 is clear for data proc 2 source
12306                and set for data proc 1 source.  */
12307             if (aarch64_get_instr (cpu)  & (1U << 30))
12308               dexDataProc1Source (cpu);
12309             else
12310               dexDataProc2Source (cpu);
12311           }
12312
12313         else
12314           /* Should not reach here.  */
12315           HALT_NYI;
12316
12317         return;
12318       }
12319
12320     case DPREG_3SRC_110:
12321       dexDataProc3Source (cpu); return;
12322
12323     case DPREG_UNALLOC_101:
12324       HALT_UNALLOC;
12325
12326     case DPREG_3SRC_111:
12327       dexDataProc3Source (cpu); return;
12328
12329     default:
12330       /* Should never reach here.  */
12331       HALT_NYI;
12332     }
12333 }
12334
12335 /* Unconditional Branch immediate.
12336    Offset is a PC-relative byte offset in the range +/- 128MiB.
12337    The offset is assumed to be raw from the decode i.e. the
12338    simulator is expected to scale them from word offsets to byte.  */
12339
12340 /* Unconditional branch.  */
12341 static void
12342 buc (sim_cpu *cpu, int32_t offset)
12343 {
12344   aarch64_set_next_PC_by_offset (cpu, offset);
12345 }
12346
12347 static unsigned stack_depth = 0;
12348
12349 /* Unconditional branch and link -- writes return PC to LR.  */
12350 static void
12351 bl (sim_cpu *cpu, int32_t offset)
12352 {
12353   aarch64_save_LR (cpu);
12354   aarch64_set_next_PC_by_offset (cpu, offset);
12355
12356   if (TRACE_BRANCH_P (cpu))
12357     {
12358       ++ stack_depth;
12359       TRACE_BRANCH (cpu,
12360                     " %*scall %" PRIx64 " [%s]"
12361                     " [args: %" PRIx64 " %" PRIx64 " %" PRIx64 "]",
12362                     stack_depth, " ", aarch64_get_next_PC (cpu),
12363                     aarch64_get_func (aarch64_get_next_PC (cpu)),
12364                     aarch64_get_reg_u64 (cpu, 0, NO_SP),
12365                     aarch64_get_reg_u64 (cpu, 1, NO_SP),
12366                     aarch64_get_reg_u64 (cpu, 2, NO_SP)
12367                     );
12368     }
12369 }
12370
12371 /* Unconditional Branch register.
12372    Branch/return address is in source register.  */
12373
12374 /* Unconditional branch.  */
12375 static void
12376 br (sim_cpu *cpu)
12377 {
12378   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12379   aarch64_set_next_PC (cpu, aarch64_get_reg_u64 (cpu, rn, NO_SP));
12380 }
12381
12382 /* Unconditional branch and link -- writes return PC to LR.  */
12383 static void
12384 blr (sim_cpu *cpu)
12385 {
12386   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12387
12388   /* The pseudo code in the spec says we update LR before fetching.
12389      the value from the rn.  */
12390   aarch64_save_LR (cpu);
12391   aarch64_set_next_PC (cpu, aarch64_get_reg_u64 (cpu, rn, NO_SP));
12392
12393   if (TRACE_BRANCH_P (cpu))
12394     {
12395       ++ stack_depth;
12396       TRACE_BRANCH (cpu,
12397                     " %*scall %" PRIx64 " [%s]"
12398                     " [args: %" PRIx64 " %" PRIx64 " %" PRIx64 "]",
12399                     stack_depth, " ", aarch64_get_next_PC (cpu),
12400                     aarch64_get_func (aarch64_get_next_PC (cpu)),
12401                     aarch64_get_reg_u64 (cpu, 0, NO_SP),
12402                     aarch64_get_reg_u64 (cpu, 1, NO_SP),
12403                     aarch64_get_reg_u64 (cpu, 2, NO_SP)
12404                     );
12405     }
12406 }
12407
12408 /* Return -- assembler will default source to LR this is functionally
12409    equivalent to br but, presumably, unlike br it side effects the
12410    branch predictor.  */
12411 static void
12412 ret (sim_cpu *cpu)
12413 {
12414   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12415   aarch64_set_next_PC (cpu, aarch64_get_reg_u64 (cpu, rn, NO_SP));
12416
12417   if (TRACE_BRANCH_P (cpu))
12418     {
12419       TRACE_BRANCH (cpu,
12420                     " %*sreturn [result: %" PRIx64 "]",
12421                     stack_depth, " ", aarch64_get_reg_u64 (cpu, 0, NO_SP));
12422       -- stack_depth;
12423     }
12424 }
12425
12426 /* NOP -- we implement this and call it from the decode in case we
12427    want to intercept it later.  */
12428
12429 static void
12430 nop (sim_cpu *cpu)
12431 {
12432 }
12433
12434 /* Data synchronization barrier.  */
12435
12436 static void
12437 dsb (sim_cpu *cpu)
12438 {
12439 }
12440
12441 /* Data memory barrier.  */
12442
12443 static void
12444 dmb (sim_cpu *cpu)
12445 {
12446 }
12447
12448 /* Instruction synchronization barrier.  */
12449
12450 static void
12451 isb (sim_cpu *cpu)
12452 {
12453 }
12454
12455 static void
12456 dexBranchImmediate (sim_cpu *cpu)
12457 {
12458   /* assert instr[30,26] == 00101
12459      instr[31] ==> 0 == B, 1 == BL
12460      instr[25,0] == imm26 branch offset counted in words.  */
12461
12462   uint32_t top = uimm (aarch64_get_instr (cpu), 31, 31);
12463   /* We have a 26 byte signed word offset which we need to pass to the
12464      execute routine as a signed byte offset.  */
12465   int32_t offset = simm32 (aarch64_get_instr (cpu), 25, 0) << 2;
12466
12467   if (top)
12468     bl (cpu, offset);
12469   else
12470     buc (cpu, offset);
12471 }
12472
12473 /* Control Flow.  */
12474
12475 /* Conditional branch
12476
12477    Offset is a PC-relative byte offset in the range +/- 1MiB pos is
12478    a bit position in the range 0 .. 63
12479
12480    cc is a CondCode enum value as pulled out of the decode
12481
12482    N.B. any offset register (source) can only be Xn or Wn.  */
12483
12484 static void
12485 bcc (sim_cpu *cpu, int32_t offset, CondCode cc)
12486 {
12487   /* the test returns TRUE if CC is met.  */
12488   if (testConditionCode (cpu, cc))
12489     aarch64_set_next_PC_by_offset (cpu, offset);
12490 }
12491
12492 /* 32 bit branch on register non-zero.  */
12493 static void
12494 cbnz32 (sim_cpu *cpu, int32_t offset)
12495 {
12496   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12497
12498   if (aarch64_get_reg_u32 (cpu, rt, NO_SP) != 0)
12499     aarch64_set_next_PC_by_offset (cpu, offset);
12500 }
12501
12502 /* 64 bit branch on register zero.  */
12503 static void
12504 cbnz (sim_cpu *cpu, int32_t offset)
12505 {
12506   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12507
12508   if (aarch64_get_reg_u64 (cpu, rt, NO_SP) != 0)
12509     aarch64_set_next_PC_by_offset (cpu, offset);
12510 }
12511
12512 /* 32 bit branch on register non-zero.  */
12513 static void
12514 cbz32 (sim_cpu *cpu, int32_t offset)
12515 {
12516   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12517
12518   if (aarch64_get_reg_u32 (cpu, rt, NO_SP) == 0)
12519     aarch64_set_next_PC_by_offset (cpu, offset);
12520 }
12521
12522 /* 64 bit branch on register zero.  */
12523 static void
12524 cbz (sim_cpu *cpu, int32_t offset)
12525 {
12526   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12527
12528   if (aarch64_get_reg_u64 (cpu, rt, NO_SP) == 0)
12529     aarch64_set_next_PC_by_offset (cpu, offset);
12530 }
12531
12532 /* Branch on register bit test non-zero -- one size fits all.  */
12533 static void
12534 tbnz (sim_cpu *cpu, uint32_t  pos, int32_t offset)
12535 {
12536   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12537
12538   if (aarch64_get_reg_u64 (cpu, rt, NO_SP) & (1 << pos))
12539     aarch64_set_next_PC_by_offset (cpu, offset);
12540 }
12541
12542 /* branch on register bit test zero -- one size fits all.  */
12543 static void
12544 tbz (sim_cpu *cpu, uint32_t  pos, int32_t offset)
12545 {
12546   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12547
12548   if (!(aarch64_get_reg_u64 (cpu, rt, NO_SP) & (1 << pos)))
12549     aarch64_set_next_PC_by_offset (cpu, offset);
12550 }
12551
12552 static void
12553 dexCompareBranchImmediate (sim_cpu *cpu)
12554 {
12555   /* instr[30,25] = 01 1010
12556      instr[31]    = size : 0 ==> 32, 1 ==> 64
12557      instr[24]    = op : 0 ==> CBZ, 1 ==> CBNZ
12558      instr[23,5]  = simm19 branch offset counted in words
12559      instr[4,0]   = rt  */
12560
12561   uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
12562   uint32_t op   = uimm (aarch64_get_instr (cpu), 24, 24);
12563   int32_t offset = simm32 (aarch64_get_instr (cpu), 23, 5) << 2;
12564
12565   if (size == 0)
12566     {
12567       if (op == 0)
12568         cbz32 (cpu, offset);
12569       else
12570         cbnz32 (cpu, offset);
12571     }
12572   else
12573     {
12574       if (op == 0)
12575         cbz (cpu, offset);
12576       else
12577         cbnz (cpu, offset);
12578     }
12579 }
12580
12581 static void
12582 dexTestBranchImmediate (sim_cpu *cpu)
12583 {
12584   /* instr[31]    = b5 : bit 5 of test bit idx
12585      instr[30,25] = 01 1011
12586      instr[24]    = op : 0 ==> TBZ, 1 == TBNZ
12587      instr[23,19] = b40 : bits 4 to 0 of test bit idx
12588      instr[18,5]  = simm14 : signed offset counted in words
12589      instr[4,0]   = uimm5  */
12590
12591   uint32_t pos = ((uimm (aarch64_get_instr (cpu), 31, 31) << 4)
12592                   | uimm (aarch64_get_instr (cpu), 23,19));
12593   int32_t offset = simm32 (aarch64_get_instr (cpu), 18, 5) << 2;
12594
12595   NYI_assert (30, 25, 0x1b);
12596
12597   if (uimm (aarch64_get_instr (cpu), 24, 24) == 0)
12598     tbz (cpu, pos, offset);
12599   else
12600     tbnz (cpu, pos, offset);
12601 }
12602
12603 static void
12604 dexCondBranchImmediate (sim_cpu *cpu)
12605 {
12606   /* instr[31,25] = 010 1010
12607      instr[24]    = op1; op => 00 ==> B.cond
12608      instr[23,5]  = simm19 : signed offset counted in words
12609      instr[4]     = op0
12610      instr[3,0]   = cond  */
12611
12612   int32_t offset;
12613   CondCode cc;
12614   uint32_t op = ((uimm (aarch64_get_instr (cpu), 24, 24) << 1)
12615                  | uimm (aarch64_get_instr (cpu), 4, 4));
12616
12617   NYI_assert (31, 25, 0x2a);
12618
12619   if (op != 0)
12620     HALT_UNALLOC;
12621
12622   offset = simm32 (aarch64_get_instr (cpu), 23, 5) << 2;
12623   cc = condcode (aarch64_get_instr (cpu), 0);
12624
12625   bcc (cpu, offset, cc);
12626 }
12627
12628 static void
12629 dexBranchRegister (sim_cpu *cpu)
12630 {
12631   /* instr[31,25] = 110 1011
12632      instr[24,21] = op : 0 ==> BR, 1 => BLR, 2 => RET, 3 => ERET, 4 => DRPS
12633      instr[20,16] = op2 : must be 11111
12634      instr[15,10] = op3 : must be 000000
12635      instr[4,0]   = op2 : must be 11111.  */
12636
12637   uint32_t op = uimm (aarch64_get_instr (cpu), 24, 21);
12638   uint32_t op2 = uimm (aarch64_get_instr (cpu), 20, 16);
12639   uint32_t op3 = uimm (aarch64_get_instr (cpu), 15, 10);
12640   uint32_t op4 = uimm (aarch64_get_instr (cpu), 4, 0);
12641
12642   NYI_assert (31, 25, 0x6b);
12643
12644   if (op2 != 0x1F || op3 != 0 || op4 != 0)
12645     HALT_UNALLOC;
12646
12647   if (op == 0)
12648     br (cpu);
12649
12650   else if (op == 1)
12651     blr (cpu);
12652
12653   else if (op == 2)
12654     ret (cpu);
12655
12656   else
12657     {
12658       /* ERET and DRPS accept 0b11111 for rn = aarch64_get_instr (cpu)[4,0].  */
12659       /* anything else is unallocated.  */
12660       uint32_t rn = greg (aarch64_get_instr (cpu), 0);
12661
12662       if (rn != 0x1f)
12663         HALT_UNALLOC;
12664
12665       if (op == 4 || op == 5)
12666         HALT_NYI;
12667
12668       HALT_UNALLOC;
12669     }
12670 }
12671
12672 /* FIXME: We should get the Angel SWI values from ../../libgloss/aarch64/svc.h
12673    but this may not be available.  So instead we define the values we need
12674    here.  */
12675 #define AngelSVC_Reason_Open            0x01
12676 #define AngelSVC_Reason_Close           0x02
12677 #define AngelSVC_Reason_Write           0x05
12678 #define AngelSVC_Reason_Read            0x06
12679 #define AngelSVC_Reason_IsTTY           0x09
12680 #define AngelSVC_Reason_Seek            0x0A
12681 #define AngelSVC_Reason_FLen            0x0C
12682 #define AngelSVC_Reason_Remove          0x0E
12683 #define AngelSVC_Reason_Rename          0x0F
12684 #define AngelSVC_Reason_Clock           0x10
12685 #define AngelSVC_Reason_Time            0x11
12686 #define AngelSVC_Reason_System          0x12
12687 #define AngelSVC_Reason_Errno           0x13
12688 #define AngelSVC_Reason_GetCmdLine      0x15
12689 #define AngelSVC_Reason_HeapInfo        0x16
12690 #define AngelSVC_Reason_ReportException 0x18
12691 #define AngelSVC_Reason_Elapsed         0x30
12692
12693
12694 static void
12695 handle_halt (sim_cpu *cpu, uint32_t val)
12696 {
12697   uint64_t result = 0;
12698
12699   if (val != 0xf000)
12700     {
12701       TRACE_SYSCALL (cpu, " HLT [0x%x]", val);
12702       sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12703                        sim_stopped, SIM_SIGTRAP);
12704     }
12705
12706   /* We have encountered an Angel SVC call.  See if we can process it.  */
12707   switch (aarch64_get_reg_u32 (cpu, 0, NO_SP))
12708     {
12709     case AngelSVC_Reason_HeapInfo:
12710       {
12711         /* Get the values.  */
12712         uint64_t stack_top = aarch64_get_stack_start (cpu);
12713         uint64_t heap_base = aarch64_get_heap_start (cpu);
12714
12715         /* Get the pointer  */
12716         uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12717         ptr = aarch64_get_mem_u64 (cpu, ptr);
12718
12719         /* Fill in the memory block.  */
12720         /* Start addr of heap.  */
12721         aarch64_set_mem_u64 (cpu, ptr +  0, heap_base);
12722         /* End addr of heap.  */
12723         aarch64_set_mem_u64 (cpu, ptr +  8, stack_top);
12724         /* Lowest stack addr.  */
12725         aarch64_set_mem_u64 (cpu, ptr + 16, heap_base);
12726         /* Initial stack addr.  */
12727         aarch64_set_mem_u64 (cpu, ptr + 24, stack_top);
12728
12729         TRACE_SYSCALL (cpu, " AngelSVC: Get Heap Info");
12730       }
12731       break;
12732
12733     case AngelSVC_Reason_Open:
12734       {
12735         /* Get the pointer  */
12736         /* uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);.  */
12737         /* FIXME: For now we just assume that we will only be asked
12738            to open the standard file descriptors.  */
12739         static int fd = 0;
12740         result = fd ++;
12741
12742         TRACE_SYSCALL (cpu, " AngelSVC: Open file %d", fd - 1);
12743       }
12744       break;
12745
12746     case AngelSVC_Reason_Close:
12747       {
12748         uint64_t fh = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12749         TRACE_SYSCALL (cpu, " AngelSVC: Close file %d", (int) fh);
12750         result = 0;
12751       }
12752       break;
12753
12754     case AngelSVC_Reason_Errno:
12755       result = 0;
12756       TRACE_SYSCALL (cpu, " AngelSVC: Get Errno");
12757       break;
12758
12759     case AngelSVC_Reason_Clock:
12760       result =
12761 #ifdef CLOCKS_PER_SEC
12762         (CLOCKS_PER_SEC >= 100)
12763         ? (clock () / (CLOCKS_PER_SEC / 100))
12764         : ((clock () * 100) / CLOCKS_PER_SEC)
12765 #else
12766         /* Presume unix... clock() returns microseconds.  */
12767         (clock () / 10000)
12768 #endif
12769         ;
12770         TRACE_SYSCALL (cpu, " AngelSVC: Get Clock");
12771       break;
12772
12773     case AngelSVC_Reason_GetCmdLine:
12774       {
12775         /* Get the pointer  */
12776         uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12777         ptr = aarch64_get_mem_u64 (cpu, ptr);
12778
12779         /* FIXME: No command line for now.  */
12780         aarch64_set_mem_u64 (cpu, ptr, 0);
12781         TRACE_SYSCALL (cpu, " AngelSVC: Get Command Line");
12782       }
12783       break;
12784
12785     case AngelSVC_Reason_IsTTY:
12786       result = 1;
12787         TRACE_SYSCALL (cpu, " AngelSVC: IsTTY ?");
12788       break;
12789
12790     case AngelSVC_Reason_Write:
12791       {
12792         /* Get the pointer  */
12793         uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12794         /* Get the write control block.  */
12795         uint64_t fd  = aarch64_get_mem_u64 (cpu, ptr);
12796         uint64_t buf = aarch64_get_mem_u64 (cpu, ptr + 8);
12797         uint64_t len = aarch64_get_mem_u64 (cpu, ptr + 16);
12798
12799         TRACE_SYSCALL (cpu, "write of %" PRIx64 " bytes from %"
12800                        PRIx64 " on descriptor %" PRIx64,
12801                        len, buf, fd);
12802
12803         if (len > 1280)
12804           {
12805             TRACE_SYSCALL (cpu,
12806                            " AngelSVC: Write: Suspiciously long write: %ld",
12807                            (long) len);
12808             sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12809                              sim_stopped, SIM_SIGBUS);
12810           }
12811         else if (fd == 1)
12812           {
12813             printf ("%.*s", (int) len, aarch64_get_mem_ptr (cpu, buf));
12814           }
12815         else if (fd == 2)
12816           {
12817             TRACE (cpu, 0, "\n");
12818             sim_io_eprintf (CPU_STATE (cpu), "%.*s",
12819                             (int) len, aarch64_get_mem_ptr (cpu, buf));
12820             TRACE (cpu, 0, "\n");
12821           }
12822         else
12823           {
12824             TRACE_SYSCALL (cpu,
12825                            " AngelSVC: Write: Unexpected file handle: %d",
12826                            (int) fd);
12827             sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12828                              sim_stopped, SIM_SIGABRT);
12829           }
12830       }
12831       break;
12832
12833     case AngelSVC_Reason_ReportException:
12834       {
12835         /* Get the pointer  */
12836         uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12837         /*ptr = aarch64_get_mem_u64 (cpu, ptr);.  */
12838         uint64_t type = aarch64_get_mem_u64 (cpu, ptr);
12839         uint64_t state = aarch64_get_mem_u64 (cpu, ptr + 8);
12840
12841         TRACE_SYSCALL (cpu,
12842                        "Angel Exception: type 0x%" PRIx64 " state %" PRIx64,
12843                        type, state);
12844
12845         if (type == 0x20026)
12846           sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12847                            sim_exited, state);
12848         else
12849           sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12850                            sim_stopped, SIM_SIGINT);
12851       }
12852       break;
12853
12854     case AngelSVC_Reason_Read:
12855     case AngelSVC_Reason_FLen:
12856     case AngelSVC_Reason_Seek:
12857     case AngelSVC_Reason_Remove:
12858     case AngelSVC_Reason_Time:
12859     case AngelSVC_Reason_System:
12860     case AngelSVC_Reason_Rename:
12861     case AngelSVC_Reason_Elapsed:
12862     default:
12863       TRACE_SYSCALL (cpu, " HLT [Unknown angel %x]",
12864                      aarch64_get_reg_u32 (cpu, 0, NO_SP));
12865       sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12866                        sim_stopped, SIM_SIGTRAP);
12867     }
12868
12869   aarch64_set_reg_u64 (cpu, 0, NO_SP, result);
12870 }
12871
12872 static void
12873 dexExcpnGen (sim_cpu *cpu)
12874 {
12875   /* instr[31:24] = 11010100
12876      instr[23,21] = opc : 000 ==> GEN EXCPN, 001 ==> BRK
12877                           010 ==> HLT,       101 ==> DBG GEN EXCPN
12878      instr[20,5]  = imm16
12879      instr[4,2]   = opc2 000 ==> OK, ow ==> UNALLOC
12880      instr[1,0]   = LL : discriminates opc  */
12881
12882   uint32_t opc = uimm (aarch64_get_instr (cpu), 23, 21);
12883   uint32_t imm16 = uimm (aarch64_get_instr (cpu), 20, 5);
12884   uint32_t opc2 = uimm (aarch64_get_instr (cpu), 4, 2);
12885   uint32_t LL;
12886
12887   NYI_assert (31, 24, 0xd4);
12888
12889   if (opc2 != 0)
12890     HALT_UNALLOC;
12891
12892   LL = uimm (aarch64_get_instr (cpu), 1, 0);
12893
12894   /* We only implement HLT and BRK for now.  */
12895   if (opc == 1 && LL == 0)
12896     {
12897       TRACE_EVENTS (cpu, " BRK [0x%x]", imm16);
12898       sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12899                        sim_exited, aarch64_get_reg_s32 (cpu, R0, SP_OK));
12900     }
12901
12902   if (opc == 2 && LL == 0)
12903     handle_halt (cpu, imm16);
12904
12905   else if (opc == 0 || opc == 5)
12906     HALT_NYI;
12907
12908   else
12909     HALT_UNALLOC;
12910 }
12911
12912 /* Stub for accessing system registers.
12913    We implement support for the DCZID register since this is used
12914    by the C library's memset function.  */
12915
12916 static uint64_t
12917 system_get (sim_cpu *cpu, unsigned op0, unsigned op1, unsigned crn,
12918             unsigned crm, unsigned op2)
12919 {
12920   if (crn == 0 && op1 == 3 && crm == 0 && op2 == 7)
12921     /* DCZID_EL0 - the Data Cache Zero ID register.
12922        We do not support DC ZVA at the moment, so
12923        we return a value with the disable bit set.  */
12924     return ((uint64_t) 1) << 4;
12925
12926   HALT_NYI;
12927 }
12928
12929 static void
12930 do_mrs (sim_cpu *cpu)
12931 {
12932   /* instr[31:20] = 1101 01010 0011
12933      instr[19]    = op0
12934      instr[18,16] = op1
12935      instr[15,12] = CRn
12936      instr[11,8]  = CRm
12937      instr[7,5]   = op2
12938      instr[4,0]   = Rt  */
12939   unsigned sys_op0 = uimm (aarch64_get_instr (cpu), 19, 19) + 2;
12940   unsigned sys_op1 = uimm (aarch64_get_instr (cpu), 18, 16);
12941   unsigned sys_crn = uimm (aarch64_get_instr (cpu), 15, 12);
12942   unsigned sys_crm = uimm (aarch64_get_instr (cpu), 11, 8);
12943   unsigned sys_op2 = uimm (aarch64_get_instr (cpu), 7, 5);
12944   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12945
12946   aarch64_set_reg_u64 (cpu, rt, NO_SP,
12947                        system_get (cpu, sys_op0, sys_op1, sys_crn, sys_crm, sys_op2));
12948 }
12949
12950 static void
12951 dexSystem (sim_cpu *cpu)
12952 {
12953   /* instr[31:22] = 1101 01010 0
12954      instr[21]    = L
12955      instr[20,19] = op0
12956      instr[18,16] = op1
12957      instr[15,12] = CRn
12958      instr[11,8]  = CRm
12959      instr[7,5]   = op2
12960      instr[4,0]   = uimm5  */
12961
12962   /* We are interested in HINT, DSB, DMB and ISB
12963
12964      Hint #0 encodes NOOP (this is the only hint we care about)
12965      L == 0, op0 == 0, op1 = 011, CRn = 0010, Rt = 11111,
12966      CRm op2  != 0000 000 OR CRm op2 == 0000 000 || CRm op > 0000 101
12967
12968      DSB, DMB, ISB are data store barrier, data memory barrier and
12969      instruction store barrier, respectively, where
12970
12971      L == 0, op0 == 0, op1 = 011, CRn = 0011, Rt = 11111,
12972      op2 : DSB ==> 100, DMB ==> 101, ISB ==> 110
12973      CRm<3:2> ==> domain, CRm<1:0> ==> types,
12974      domain : 00 ==> OuterShareable, 01 ==> Nonshareable,
12975               10 ==> InerShareable, 11 ==> FullSystem
12976      types :  01 ==> Reads, 10 ==> Writes,
12977               11 ==> All, 00 ==> All (domain == FullSystem).  */
12978
12979   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12980   uint32_t l_op0_op1_crn = uimm (aarch64_get_instr (cpu), 21, 12);
12981
12982   NYI_assert (31, 22, 0x354);
12983
12984   switch (l_op0_op1_crn)
12985     {
12986     case 0x032:
12987       if (rt == 0x1F)
12988         {
12989           /* NOP has CRm != 0000 OR.  */
12990           /*         (CRm == 0000 AND (op2 == 000 OR op2 > 101)).  */
12991           uint32_t crm = uimm (aarch64_get_instr (cpu), 11, 8);
12992           uint32_t op2 = uimm (aarch64_get_instr (cpu), 7, 5);
12993
12994           if (crm != 0 || (op2 == 0 || op2 > 5))
12995             {
12996               /* Actually call nop method so we can reimplement it later.  */
12997               nop (cpu);
12998               return;
12999             }
13000         }
13001       HALT_NYI;
13002
13003     case 0x033:
13004       {
13005         uint32_t op2 =  uimm (aarch64_get_instr (cpu), 7, 5);
13006
13007         switch (op2)
13008           {
13009           case 2: HALT_NYI;
13010           case 4: dsb (cpu); return;
13011           case 5: dmb (cpu); return;
13012           case 6: isb (cpu); return;
13013           case 7:
13014           default: HALT_UNALLOC;
13015         }
13016       }
13017
13018     case 0x3B0:
13019       /* MRS Wt, sys-reg.  */
13020       do_mrs (cpu);
13021       return;
13022
13023     case 0x3B4:
13024     case 0x3BD:
13025       /* MRS Xt, sys-reg.  */
13026       do_mrs (cpu);
13027       return;
13028
13029     case 0x0B7:
13030       /* DC <type>, x<n>.  */
13031       HALT_NYI;
13032       return;
13033
13034     default:
13035       /* if (uimm (aarch64_get_instr (cpu), 21, 20) == 0x1)
13036          MRS Xt, sys-reg.  */
13037       HALT_NYI;
13038       return;
13039     }
13040 }
13041
13042 static void
13043 dexBr (sim_cpu *cpu)
13044 {
13045   /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
13046      assert  group == GROUP_BREXSYS_1010 || group == GROUP_BREXSYS_1011
13047      bits [31,29] of a BrExSys are the secondary dispatch vector.  */
13048   uint32_t group2 = dispatchBrExSys (aarch64_get_instr (cpu));
13049
13050   switch (group2)
13051     {
13052     case BR_IMM_000:
13053       return dexBranchImmediate (cpu);
13054
13055     case BR_IMMCMP_001:
13056       /* Compare has bit 25 clear while test has it set.  */
13057       if (!uimm (aarch64_get_instr (cpu), 25, 25))
13058         dexCompareBranchImmediate (cpu);
13059       else
13060         dexTestBranchImmediate (cpu);
13061       return;
13062
13063     case BR_IMMCOND_010:
13064       /* This is a conditional branch if bit 25 is clear otherwise
13065          unallocated.  */
13066       if (!uimm (aarch64_get_instr (cpu), 25, 25))
13067         dexCondBranchImmediate (cpu);
13068       else
13069         HALT_UNALLOC;
13070       return;
13071
13072     case BR_UNALLOC_011:
13073       HALT_UNALLOC;
13074
13075     case BR_IMM_100:
13076       dexBranchImmediate (cpu);
13077       return;
13078
13079     case BR_IMMCMP_101:
13080       /* Compare has bit 25 clear while test has it set.  */
13081       if (!uimm (aarch64_get_instr (cpu), 25, 25))
13082         dexCompareBranchImmediate (cpu);
13083       else
13084         dexTestBranchImmediate (cpu);
13085       return;
13086
13087     case BR_REG_110:
13088       /* Unconditional branch reg has bit 25 set.  */
13089       if (uimm (aarch64_get_instr (cpu), 25, 25))
13090         dexBranchRegister (cpu);
13091
13092       /* This includes both Excpn Gen, System and unalloc operations.
13093          We need to decode the Excpn Gen operation BRK so we can plant
13094          debugger entry points.
13095          Excpn Gen operations have aarch64_get_instr (cpu)[24] = 0.
13096          we need to decode at least one of the System operations NOP
13097          which is an alias for HINT #0.
13098          System operations have aarch64_get_instr (cpu)[24,22] = 100.  */
13099       else if (uimm (aarch64_get_instr (cpu), 24, 24) == 0)
13100         dexExcpnGen (cpu);
13101
13102       else if (uimm (aarch64_get_instr (cpu), 24, 22) == 4)
13103         dexSystem (cpu);
13104
13105       else
13106         HALT_UNALLOC;
13107
13108       return;
13109
13110     case BR_UNALLOC_111:
13111       HALT_UNALLOC;
13112
13113     default:
13114       /* Should never reach here.  */
13115       HALT_NYI;
13116     }
13117 }
13118
13119 static void
13120 aarch64_decode_and_execute (sim_cpu *cpu, uint64_t pc)
13121 {
13122   /* We need to check if gdb wants an in here.  */
13123   /* checkBreak (cpu);.  */
13124
13125   uint64_t group = dispatchGroup (aarch64_get_instr (cpu));
13126
13127   switch (group)
13128     {
13129     case GROUP_PSEUDO_0000:   dexPseudo (cpu); break;
13130     case GROUP_LDST_0100:     dexLdSt (cpu); break;
13131     case GROUP_DPREG_0101:    dexDPReg (cpu); break;
13132     case GROUP_LDST_0110:     dexLdSt (cpu); break;
13133     case GROUP_ADVSIMD_0111:  dexAdvSIMD0 (cpu); break;
13134     case GROUP_DPIMM_1000:    dexDPImm (cpu); break;
13135     case GROUP_DPIMM_1001:    dexDPImm (cpu); break;
13136     case GROUP_BREXSYS_1010:  dexBr (cpu); break;
13137     case GROUP_BREXSYS_1011:  dexBr (cpu); break;
13138     case GROUP_LDST_1100:     dexLdSt (cpu); break;
13139     case GROUP_DPREG_1101:    dexDPReg (cpu); break;
13140     case GROUP_LDST_1110:     dexLdSt (cpu); break;
13141     case GROUP_ADVSIMD_1111:  dexAdvSIMD1 (cpu); break;
13142
13143     case GROUP_UNALLOC_0001:
13144     case GROUP_UNALLOC_0010:
13145     case GROUP_UNALLOC_0011:
13146       HALT_UNALLOC;
13147
13148     default:
13149       /* Should never reach here.  */
13150       HALT_NYI;
13151     }
13152 }
13153
13154 static bfd_boolean
13155 aarch64_step (sim_cpu *cpu)
13156 {
13157   uint64_t pc = aarch64_get_PC (cpu);
13158
13159   if (pc == TOP_LEVEL_RETURN_PC)
13160     return FALSE;
13161
13162   aarch64_set_next_PC (cpu, pc + 4);
13163   aarch64_get_instr (cpu) = aarch64_get_mem_u32 (cpu, pc);
13164
13165   TRACE_INSN (cpu, " pc = %" PRIx64 " instr = %08x", pc,
13166               aarch64_get_instr (cpu));
13167   TRACE_DISASM (cpu, pc);
13168
13169   aarch64_decode_and_execute (cpu, pc);
13170
13171   return TRUE;
13172 }
13173
13174 void
13175 aarch64_run (SIM_DESC sd)
13176 {
13177   sim_cpu *cpu = STATE_CPU (sd, 0);
13178
13179   while (aarch64_step (cpu))
13180     aarch64_update_PC (cpu);
13181
13182   sim_engine_halt (sd, NULL, NULL, aarch64_get_PC (cpu),
13183                    sim_exited, aarch64_get_reg_s32 (cpu, R0, SP_OK));
13184 }
13185
13186 void
13187 aarch64_init (sim_cpu *cpu, uint64_t pc)
13188 {
13189   uint64_t sp = aarch64_get_stack_start (cpu);
13190
13191   /* Install SP, FP and PC and set LR to -20
13192      so we can detect a top-level return.  */
13193   aarch64_set_reg_u64 (cpu, SP, SP_OK, sp);
13194   aarch64_set_reg_u64 (cpu, FP, SP_OK, sp);
13195   aarch64_set_reg_u64 (cpu, LR, SP_OK, TOP_LEVEL_RETURN_PC);
13196   aarch64_set_next_PC (cpu, pc);
13197   aarch64_update_PC (cpu);
13198   aarch64_init_LIT_table ();
13199 }