Add an AArch64 simulator to GDB.
[external/binutils.git] / sim / aarch64 / simulator.c
1 /* simulator.c -- Interface for the AArch64 simulator.
2
3    Copyright (C) 2015 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 <syscall.h>
28 #include <math.h>
29 #include <time.h>
30 #include <limits.h>
31
32 #include "dis-asm.h"
33
34 #include "simulator.h"
35 #include "cpustate.h"
36 #include "memory.h"
37
38 #define NO_SP 0
39 #define SP_OK 1
40
41 bfd_boolean disas = FALSE;
42
43 #define TST(_flag)   (aarch64_test_CPSR_bit (cpu, _flag))
44 #define IS_SET(_X)   ( TST (( _X )))
45 #define IS_CLEAR(_X) (!TST (( _X )))
46
47 #define HALT_UNALLOC                                                    \
48   do                                                                    \
49     {                                                                   \
50       if (TRACE_INSN_P (cpu))                                           \
51         {                                                               \
52           aarch64_print_insn (CPU_STATE (cpu), aarch64_get_PC (cpu));   \
53           TRACE_INSN (cpu,                                              \
54                       "Unallocated instruction detected at sim line %d,"\
55                       " exe addr %" PRIx64,                             \
56                       __LINE__, aarch64_get_PC (cpu));                  \
57         }                                                               \
58       sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),\
59                        sim_stopped, SIM_SIGILL);                        \
60     }                                                                   \
61   while (0)
62
63 #define HALT_NYI                                                        \
64   do                                                                    \
65     {                                                                   \
66       if (TRACE_INSN_P (cpu))                                           \
67         {                                                               \
68           aarch64_print_insn (CPU_STATE (cpu), aarch64_get_PC (cpu));   \
69           TRACE_INSN (cpu,                                              \
70                       "Unimplemented instruction detected at sim line %d,"\
71                       " exe addr %" PRIx64,                             \
72                       __LINE__, aarch64_get_PC (cpu));                  \
73         }                                                               \
74       sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),\
75                        sim_stopped, SIM_SIGABRT);                       \
76     }                                                                   \
77   while (0)
78
79 #define NYI_assert(HI, LO, EXPECTED)                                    \
80   do                                                                    \
81     {                                                                   \
82       if (uimm (aarch64_get_instr (cpu), (HI), (LO)) != (EXPECTED))     \
83         HALT_NYI;                                                       \
84     }                                                                   \
85   while (0)
86
87 #define HALT_UNREACHABLE                                                \
88   do                                                                    \
89     {                                                                   \
90       TRACE_EVENTS (cpu, "ISE: unreachable code point");                \
91       sim_engine_abort (NULL, cpu, aarch64_get_PC (cpu), "Internal Error"); \
92     }                                                                   \
93   while (0)
94
95 /* Helper functions used by expandLogicalImmediate.  */
96
97 /* for i = 1, ... N result<i-1> = 1 other bits are zero  */
98 static inline uint64_t
99 ones (int N)
100 {
101   return (N == 64 ? (uint64_t)-1UL : ((1UL << N) - 1));
102 }
103
104 /* result<0> to val<N>  */
105 static inline uint64_t
106 pickbit (uint64_t val, int N)
107 {
108   return pickbits64 (val, N, N);
109 }
110
111 static uint64_t
112 expand_logical_immediate (uint32_t S, uint32_t R, uint32_t N)
113 {
114   uint64_t mask;
115   uint64_t imm;
116   unsigned simd_size;
117
118   /* The immediate value is S+1 bits to 1, left rotated by SIMDsize - R
119      (in other words, right rotated by R), then replicated. */
120   if (N != 0)
121     {
122       simd_size = 64;
123       mask = 0xffffffffffffffffull;
124     }
125   else
126     {
127       switch (S)
128         {
129         case 0x00 ... 0x1f: /* 0xxxxx */ simd_size = 32;           break;
130         case 0x20 ... 0x2f: /* 10xxxx */ simd_size = 16; S &= 0xf; break;
131         case 0x30 ... 0x37: /* 110xxx */ simd_size =  8; S &= 0x7; break;
132         case 0x38 ... 0x3b: /* 1110xx */ simd_size =  4; S &= 0x3; break;
133         case 0x3c ... 0x3d: /* 11110x */ simd_size =  2; S &= 0x1; break;
134         default: return 0;
135         }
136       mask = (1ull << simd_size) - 1;
137       /* Top bits are IGNORED.  */
138       R &= simd_size - 1;
139     }
140
141   /* NOTE: if S = simd_size - 1 we get 0xf..f which is rejected.  */
142   if (S == simd_size - 1)
143     return 0;
144
145   /* S+1 consecutive bits to 1.  */
146   /* NOTE: S can't be 63 due to detection above.  */
147   imm = (1ull << (S + 1)) - 1;
148
149   /* Rotate to the left by simd_size - R.  */
150   if (R != 0)
151     imm = ((imm << (simd_size - R)) & mask) | (imm >> R);
152
153   /* Replicate the value according to SIMD size.  */
154   switch (simd_size)
155     {
156     case  2: imm = (imm <<  2) | imm;
157     case  4: imm = (imm <<  4) | imm;
158     case  8: imm = (imm <<  8) | imm;
159     case 16: imm = (imm << 16) | imm;
160     case 32: imm = (imm << 32) | imm;
161     case 64: break;
162     default: return 0;
163     }
164
165   return imm;
166 }
167
168 /* Instr[22,10] encodes N immr and imms. we want a lookup table
169    for each possible combination i.e. 13 bits worth of int entries.  */
170 #define  LI_TABLE_SIZE  (1 << 13)
171 static uint64_t LITable[LI_TABLE_SIZE];
172
173 void
174 aarch64_init_LIT_table (void)
175 {
176   unsigned index;
177
178   for (index = 0; index < LI_TABLE_SIZE; index++)
179     {
180       uint32_t N    = uimm (index, 12, 12);
181       uint32_t immr = uimm (index, 11, 6);
182       uint32_t imms = uimm (index, 5, 0);
183
184       LITable [index] = expand_logical_immediate (imms, immr, N);
185     }
186 }
187
188 static void
189 dexNotify (sim_cpu *cpu)
190 {
191   /* instr[14,0] == type : 0 ==> method entry, 1 ==> method reentry
192                            2 ==> exit Java, 3 ==> start next bytecode.  */
193   uint32_t type = uimm (aarch64_get_instr (cpu), 14, 0);
194
195   TRACE_EVENTS (cpu, "Notify Insn encountered, type = 0x%x", type);
196
197   switch (type)
198     {
199     case 0:
200       /* aarch64_notifyMethodEntry (aarch64_get_reg_u64 (cpu, R23, 0),
201          aarch64_get_reg_u64 (cpu, R22, 0));  */
202       break;
203     case 1:
204       /* aarch64_notifyMethodReentry (aarch64_get_reg_u64 (cpu, R23, 0),
205          aarch64_get_reg_u64 (cpu, R22, 0));  */
206       break;
207     case 2:
208       /* aarch64_notifyMethodExit ();  */
209       break;
210     case 3:
211       /* aarch64_notifyBCStart (aarch64_get_reg_u64 (cpu, R23, 0),
212          aarch64_get_reg_u64 (cpu, R22, 0));  */
213       break;
214     }
215 }
216
217 /* secondary decode within top level groups  */
218
219 static void
220 dexPseudo (sim_cpu *cpu)
221 {
222   /* assert instr[28,27] = 00
223
224      We provide 2 pseudo instructions:
225
226      HALT stops execution of the simulator causing an immediate
227      return to the x86 code which entered it.
228
229      CALLOUT initiates recursive entry into x86 code.  A register
230      argument holds the address of the x86 routine.  Immediate
231      values in the instruction identify the number of general
232      purpose and floating point register arguments to be passed
233      and the type of any value to be returned.  */
234
235   uint32_t PSEUDO_HALT      =  0xE0000000U;
236   uint32_t PSEUDO_CALLOUT   =  0x00018000U;
237   uint32_t PSEUDO_CALLOUTR  =  0x00018001U;
238   uint32_t PSEUDO_NOTIFY    =  0x00014000U;
239   uint32_t dispatch;
240
241   if (aarch64_get_instr (cpu) == PSEUDO_HALT)
242     {
243       TRACE_EVENTS (cpu, " Pseudo Halt Instruction");
244       sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
245                        sim_stopped, SIM_SIGTRAP);
246     }
247
248   dispatch = uimm (aarch64_get_instr (cpu), 31, 15);
249
250   /* We do not handle callouts at the moment.  */
251   if (dispatch == PSEUDO_CALLOUT || dispatch == PSEUDO_CALLOUTR)
252     {
253       TRACE_EVENTS (cpu, " Callout");
254       sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
255                        sim_stopped, SIM_SIGABRT);
256     }
257
258   else if (dispatch == PSEUDO_NOTIFY)
259     dexNotify (cpu);
260
261   else
262     HALT_UNALLOC;
263 }
264
265 /* Load-store single register (unscaled offset)
266    These instructions employ a base register plus an unscaled signed
267    9 bit offset.
268
269    N.B. the base register (source) can be Xn or SP. all other
270    registers may not be SP.  */
271
272 /* 32 bit load 32 bit unscaled signed 9 bit.  */
273 static void
274 ldur32 (sim_cpu *cpu, int32_t offset)
275 {
276   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
277   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
278
279   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32
280                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
281                         + offset));
282 }
283
284 /* 64 bit load 64 bit unscaled signed 9 bit.  */
285 static void
286 ldur64 (sim_cpu *cpu, int32_t offset)
287 {
288   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
289   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
290
291   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64
292                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
293                         + offset));
294 }
295
296 /* 32 bit load zero-extended byte unscaled signed 9 bit.  */
297 static void
298 ldurb32 (sim_cpu *cpu, int32_t offset)
299 {
300   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
301   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
302
303   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u8
304                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
305                         + offset));
306 }
307
308 /* 32 bit load sign-extended byte unscaled signed 9 bit.  */
309 static void
310 ldursb32 (sim_cpu *cpu, int32_t offset)
311 {
312   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
313   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
314
315   aarch64_set_reg_u64 (cpu, rt, NO_SP, (uint32_t) aarch64_get_mem_s8
316                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
317                         + offset));
318 }
319
320 /* 64 bit load sign-extended byte unscaled signed 9 bit.  */
321 static void
322 ldursb64 (sim_cpu *cpu, int32_t offset)
323 {
324   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
325   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
326
327   aarch64_set_reg_s64 (cpu, rt, NO_SP, aarch64_get_mem_s8
328                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
329                         + offset));
330 }
331
332 /* 32 bit load zero-extended short unscaled signed 9 bit  */
333 static void
334 ldurh32 (sim_cpu *cpu, int32_t offset)
335 {
336   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
337   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
338
339   aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_mem_u16
340                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
341                         + offset));
342 }
343
344 /* 32 bit load sign-extended short unscaled signed 9 bit  */
345 static void
346 ldursh32 (sim_cpu *cpu, int32_t offset)
347 {
348   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
349   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
350
351   aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) aarch64_get_mem_s16
352                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
353                         + offset));
354 }
355
356 /* 64 bit load sign-extended short unscaled signed 9 bit  */
357 static void
358 ldursh64 (sim_cpu *cpu, int32_t offset)
359 {
360   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
361   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
362
363   aarch64_set_reg_s64 (cpu, rt, NO_SP, aarch64_get_mem_s16
364                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
365                         + offset));
366 }
367
368 /* 64 bit load sign-extended word unscaled signed 9 bit  */
369 static void
370 ldursw (sim_cpu *cpu, int32_t offset)
371 {
372   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
373   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
374
375   aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) aarch64_get_mem_s32
376                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
377                         + offset));
378 }
379
380 /* N.B. with stores the value in source is written to the address
381    identified by source2 modified by offset.  */
382
383 /* 32 bit store 32 bit unscaled signed 9 bit.  */
384 static void
385 stur32 (sim_cpu *cpu, int32_t offset)
386 {
387   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
388   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
389
390   aarch64_set_mem_u32 (cpu,
391                        aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
392                        aarch64_get_reg_u32 (cpu, rd, NO_SP));
393 }
394
395 /* 64 bit store 64 bit unscaled signed 9 bit  */
396 static void
397 stur64 (sim_cpu *cpu, int32_t offset)
398 {
399   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
400   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
401
402   aarch64_set_mem_u64 (cpu,
403                        aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
404                        aarch64_get_reg_u64 (cpu, rd, NO_SP));
405 }
406
407 /* 32 bit store byte unscaled signed 9 bit  */
408 static void
409 sturb (sim_cpu *cpu, int32_t offset)
410 {
411   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
412   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
413
414   aarch64_set_mem_u8 (cpu,
415                       aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
416                       aarch64_get_reg_u8 (cpu, rd, NO_SP));
417 }
418
419 /* 32 bit store short unscaled signed 9 bit  */
420 static void
421 sturh (sim_cpu *cpu, int32_t offset)
422 {
423   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
424   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
425
426   aarch64_set_mem_u16 (cpu,
427                        aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
428                        aarch64_get_reg_u16 (cpu, rd, NO_SP));
429 }
430
431 /* Load single register pc-relative label
432    Offset is a signed 19 bit immediate count in words
433    rt may not be SP.  */
434
435 /* 32 bit pc-relative load  */
436 static void
437 ldr32_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_u32
443                        (cpu, aarch64_get_PC (cpu) + offset * 4));
444 }
445
446 /* 64 bit pc-relative load  */
447 static void
448 ldr_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_u64
454                        (cpu, aarch64_get_PC (cpu) + offset * 4));
455 }
456
457 /* sign extended 32 bit pc-relative load  */
458 static void
459 ldrsw_pcrel (sim_cpu *cpu, int32_t offset)
460 {
461   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
462
463   aarch64_set_reg_u64 (cpu, rd, NO_SP,
464                        aarch64_get_mem_s32
465                        (cpu, aarch64_get_PC (cpu) + offset * 4));
466 }
467
468 /* float pc-relative load  */
469 static void
470 fldrs_pcrel (sim_cpu *cpu, int32_t offset)
471 {
472   unsigned int rd = uimm (aarch64_get_instr (cpu), 4, 0);
473
474   aarch64_set_FP_float (cpu, rd,
475                         aarch64_get_mem_float
476                         (cpu, aarch64_get_PC (cpu) + offset * 4));
477 }
478
479 /* double pc-relative load  */
480 static void
481 fldrd_pcrel (sim_cpu *cpu, int32_t offset)
482 {
483   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
484
485   aarch64_set_FP_double (cpu, st,
486                          aarch64_get_mem_double
487                          (cpu, aarch64_get_PC (cpu) + offset * 4));
488 }
489
490 /* long double pc-relative load.  */
491 static void
492 fldrq_pcrel (sim_cpu *cpu, int32_t offset)
493 {
494   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
495   uint64_t addr = aarch64_get_PC (cpu) + offset * 4;
496   FRegister a;
497
498   aarch64_get_mem_long_double (cpu, addr, & a);
499   aarch64_set_FP_long_double (cpu, st, a);
500 }
501
502 /* This can be used to scale an offset by applying
503    the requisite shift. the second argument is either
504    16, 32 or 64.  */
505
506 #define SCALE(_offset, _elementSize) \
507     ((_offset) << ScaleShift ## _elementSize)
508
509 /* This can be used to optionally scale a register derived offset
510    by applying the requisite shift as indicated by the Scaling
511    argument. the second argument is either Byte, Short, Word
512    or Long. The third argument is either Scaled or Unscaled.
513    N.B. when _Scaling is Scaled the shift gets ANDed with
514    all 1s while when it is Unscaled it gets ANDed with 0.  */
515
516 #define OPT_SCALE(_offset, _elementType, _Scaling) \
517   ((_offset) << (_Scaling ? ScaleShift ## _elementType : 0))
518
519 /* This can be used to zero or sign extend a 32 bit register derived
520    value to a 64 bit value.  the first argument must be the value as
521    a uint32_t and the second must be either UXTW or SXTW. The result
522    is returned as an int64_t.  */
523
524 static inline int64_t
525 extend (uint32_t value, Extension extension)
526 {
527   union
528   {
529     uint32_t u;
530     int32_t   n;
531   } x;
532
533   /* A branchless variant of this ought to be possible.  */
534   if (extension == UXTW || extension == NoExtension)
535     return value;
536
537   x.u = value;
538   return x.n;
539 }
540
541 /* Scalar Floating Point
542
543    FP load/store single register (4 addressing modes)
544
545    N.B. the base register (source) can be the stack pointer.
546    The secondary source register (source2) can only be an Xn register.  */
547
548 /* Load 32 bit unscaled signed 9 bit with pre- or post-writeback.  */
549 static void
550 fldrs_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
551 {
552   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
553   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
554   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
555
556   if (wb != Post)
557     address += offset;
558
559   aarch64_set_FP_float (cpu, st, aarch64_get_mem_float (cpu, address));
560   if (wb == Post)
561     address += offset;
562
563   if (wb != NoWriteBack)
564     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
565 }
566
567 /* Load 32 bit scaled unsigned 12 bit.  */
568 static void
569 fldrs_abs (sim_cpu *cpu, uint32_t offset)
570 {
571   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
572   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
573
574   aarch64_set_FP_float (cpu, st,
575                         aarch64_get_mem_float
576                         (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
577                          + SCALE (offset, 32)));
578 }
579
580 /* Load 32 bit scaled or unscaled zero- or sign-extended
581    32-bit register offset.  */
582 static void
583 fldrs_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
584 {
585   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
586   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
587   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
588   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
589   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
590   uint64_t displacement = OPT_SCALE (extended, 32, scaling);
591
592   aarch64_set_FP_float (cpu, st,
593                         aarch64_get_mem_float
594                         (cpu, address + displacement));
595 }
596
597 /* Load 64 bit unscaled signed 9 bit with pre- or post-writeback.  */
598 static void
599 fldrd_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
600 {
601   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
602   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
603   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
604
605   if (wb != Post)
606     address += offset;
607
608   aarch64_set_FP_double (cpu, st, aarch64_get_mem_double (cpu, address));
609
610   if (wb == Post)
611     address += offset;
612
613   if (wb != NoWriteBack)
614     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
615 }
616
617 /* Load 64 bit scaled unsigned 12 bit.  */
618 static void
619 fldrd_abs (sim_cpu *cpu, uint32_t offset)
620 {
621   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
622   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
623   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 64);
624
625   aarch64_set_FP_double (cpu, st, aarch64_get_mem_double (cpu, address));
626 }
627
628 /* Load 64 bit scaled or unscaled zero- or sign-extended 32-bit register offset.  */
629 static void
630 fldrd_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
631 {
632   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
633   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
634   uint64_t displacement = OPT_SCALE (extended, 64, scaling);
635
636   fldrd_wb (cpu, displacement, NoWriteBack);
637 }
638
639 /* Load 128 bit unscaled signed 9 bit with pre- or post-writeback.  */
640 static void
641 fldrq_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
642 {
643   FRegister a;
644   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
645   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
646   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
647
648   if (wb != Post)
649     address += offset;
650
651   aarch64_get_mem_long_double (cpu, address, & a);
652   aarch64_set_FP_long_double (cpu, st, a);
653
654   if (wb == Post)
655     address += offset;
656
657   if (wb != NoWriteBack)
658     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
659 }
660
661 /* Load 128 bit scaled unsigned 12 bit.  */
662 static void
663 fldrq_abs (sim_cpu *cpu, uint32_t offset)
664 {
665   FRegister a;
666   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
667   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
668   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 128);
669
670   aarch64_get_mem_long_double (cpu, address, & a);
671   aarch64_set_FP_long_double (cpu, st, a);
672 }
673
674 /* Load 128 bit scaled or unscaled zero- or sign-extended 32-bit register offset  */
675 static void
676 fldrq_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
677 {
678   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
679   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
680   uint64_t displacement = OPT_SCALE (extended, 128, scaling);
681
682   fldrq_wb (cpu, displacement, NoWriteBack);
683 }
684
685 /* Memory Access
686
687    load-store single register
688    There are four addressing modes available here which all employ a
689    64 bit source (base) register.
690
691    N.B. the base register (source) can be the stack pointer.
692    The secondary source register (source2)can only be an Xn register.
693
694    Scaled, 12-bit, unsigned immediate offset, without pre- and
695    post-index options.
696    Unscaled, 9-bit, signed immediate offset with pre- or post-index
697    writeback.
698    scaled or unscaled 64-bit register offset.
699    scaled or unscaled 32-bit extended register offset.
700
701    All offsets are assumed to be raw from the decode i.e. the
702    simulator is expected to adjust scaled offsets based on the
703    accessed data size with register or extended register offset
704    versions the same applies except that in the latter case the
705    operation may also require a sign extend.
706
707    A separate method is provided for each possible addressing mode.  */
708
709 /* 32 bit load 32 bit scaled unsigned 12 bit  */
710 static void
711 ldr32_abs (sim_cpu *cpu, uint32_t offset)
712 {
713   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
714   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
715
716   /* The target register may not be SP but the source may be.  */
717   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32
718                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
719                         + SCALE (offset, 32)));
720 }
721
722 /* 32 bit load 32 bit unscaled signed 9 bit with pre- or post-writeback.  */
723 static void
724 ldr32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
725 {
726   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
727   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
728   uint64_t address;
729
730   if (rn == rt && wb != NoWriteBack)
731     HALT_UNALLOC;
732
733   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
734
735   if (wb != Post)
736     address += offset;
737
738   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32 (cpu, address));
739
740   if (wb == Post)
741     address += offset;
742
743   if (wb != NoWriteBack)
744     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
745 }
746
747 /* 32 bit load 32 bit scaled or unscaled
748    zero- or sign-extended 32-bit register offset  */
749 static void
750 ldr32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
751 {
752   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
753   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
754   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
755   /* rn may reference SP, rm and rt must reference ZR  */
756
757   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
758   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
759   uint64_t displacement =  OPT_SCALE (extended, 32, scaling);
760
761   aarch64_set_reg_u64 (cpu, rt, NO_SP,
762                        aarch64_get_mem_u32 (cpu, address + displacement));
763 }
764
765 /* 64 bit load 64 bit scaled unsigned 12 bit  */
766 static void
767 ldr_abs (sim_cpu *cpu, uint32_t offset)
768 {
769   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
770   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
771
772   /* The target register may not be SP but the source may be.  */
773   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64
774                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
775                         + SCALE (offset, 64)));
776 }
777
778 /* 64 bit load 64 bit unscaled signed 9 bit with pre- or post-writeback.  */
779 static void
780 ldr_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
781 {
782   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
783   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
784   uint64_t address;
785
786   if (rn == rt && wb != NoWriteBack)
787     HALT_UNALLOC;
788
789   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
790
791   if (wb != Post)
792     address += offset;
793
794   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64 (cpu, address));
795
796   if (wb == Post)
797     address += offset;
798
799   if (wb != NoWriteBack)
800     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
801 }
802
803 /* 64 bit load 64 bit scaled or unscaled zero-
804    or sign-extended 32-bit register offset.  */
805 static void
806 ldr_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
807 {
808   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
809   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
810   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
811   /* rn may reference SP, rm and rt must reference ZR  */
812
813   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
814   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
815   uint64_t displacement =  OPT_SCALE (extended, 64, scaling);
816
817   aarch64_set_reg_u64 (cpu, rt, NO_SP,
818                        aarch64_get_mem_u64 (cpu, address + displacement));
819 }
820
821 /* 32 bit load zero-extended byte scaled unsigned 12 bit.  */
822 static void
823 ldrb32_abs (sim_cpu *cpu, uint32_t offset)
824 {
825   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
826   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
827
828   /* The target register may not be SP but the source may be
829      there is no scaling required for a byte load.  */
830   aarch64_set_reg_u64 (cpu, rt, NO_SP,
831                        aarch64_get_mem_u8
832                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset));
833 }
834
835 /* 32 bit load zero-extended byte unscaled signed 9 bit with pre- or post-writeback.  */
836 static void
837 ldrb32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
838 {
839   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
840   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
841   uint64_t address;
842
843   if (rn == rt && wb != NoWriteBack)
844     HALT_UNALLOC;
845
846   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
847
848   if (wb != Post)
849     address += offset;
850
851   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u8 (cpu, address));
852
853   if (wb == Post)
854     address += offset;
855
856   if (wb != NoWriteBack)
857     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
858 }
859
860 /* 32 bit load zero-extended byte scaled or unscaled zero-
861    or sign-extended 32-bit register offset.  */
862 static void
863 ldrb32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
864 {
865   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
866   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
867   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
868   /* rn may reference SP, rm and rt must reference ZR  */
869
870   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
871   int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
872                                  extension);
873
874   /* There is no scaling required for a byte load.  */
875   aarch64_set_reg_u64 (cpu, rt, NO_SP,
876                        aarch64_get_mem_u8 (cpu, address + displacement));
877 }
878
879 /* 64 bit load sign-extended byte unscaled signed 9 bit
880    with pre- or post-writeback.  */
881 static void
882 ldrsb_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
883 {
884   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
885   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
886   uint64_t address;
887
888   if (rn == rt && wb != NoWriteBack)
889     HALT_UNALLOC;
890
891   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
892
893   if (wb != Post)
894     address += offset;
895
896   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_s8 (cpu, address));
897
898   if (wb == Post)
899     address += offset;
900
901   if (wb != NoWriteBack)
902     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
903 }
904
905 /* 64 bit load sign-extended byte scaled unsigned 12 bit.  */
906 static void
907 ldrsb_abs (sim_cpu *cpu, uint32_t offset)
908 {
909   ldrsb_wb (cpu, offset, NoWriteBack);
910 }
911
912 /* 64 bit load sign-extended byte scaled or unscaled zero-
913    or sign-extended 32-bit register offset.  */
914 static void
915 ldrsb_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
916 {
917   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
918   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
919   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
920   /* rn may reference SP, rm and rt must reference ZR  */
921
922   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
923   int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
924                                  extension);
925   /* There is no scaling required for a byte load.  */
926   aarch64_set_reg_u64 (cpu, rt, NO_SP,
927                        aarch64_get_mem_s8 (cpu, address + displacement));
928 }
929
930 /* 32 bit load zero-extended short scaled unsigned 12 bit.  */
931 static void
932 ldrh32_abs (sim_cpu *cpu, uint32_t offset)
933 {
934   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
935   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
936
937   /* The target register may not be SP but the source may be.  */
938   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u16
939                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
940                         + SCALE (offset, 16)));
941 }
942
943 /* 32 bit load zero-extended short unscaled signed 9 bit
944    with pre- or post-writeback.  */
945 static void
946 ldrh32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
947 {
948   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
949   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
950   uint64_t address;
951
952   if (rn == rt && wb != NoWriteBack)
953     HALT_UNALLOC;
954
955   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
956
957   if (wb != Post)
958     address += offset;
959
960   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u16 (cpu, address));
961
962   if (wb == Post)
963     address += offset;
964
965   if (wb != NoWriteBack)
966     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
967 }
968
969 /* 32 bit load zero-extended short scaled or unscaled zero-
970    or sign-extended 32-bit register offset.  */
971 static void
972 ldrh32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
973 {
974   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
975   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
976   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
977   /* rn may reference SP, rm and rt must reference ZR  */
978
979   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
980   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
981   uint64_t displacement =  OPT_SCALE (extended, 16, scaling);
982
983   aarch64_set_reg_u64 (cpu, rt, NO_SP,
984                        aarch64_get_mem_u16 (cpu, address + displacement));
985 }
986
987 /* 32 bit load sign-extended short scaled unsigned 12 bit.  */
988 static void
989 ldrsh32_abs (sim_cpu *cpu, uint32_t offset)
990 {
991   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
992   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
993
994   /* The target register may not be SP but the source may be.  */
995   aarch64_set_reg_u64 (cpu, rt, NO_SP, (uint32_t) aarch64_get_mem_s16
996                        (cpu,
997                         aarch64_get_reg_u64 (cpu, rn, SP_OK)
998                         + SCALE (offset, 16)));
999 }
1000
1001 /* 32 bit load sign-extended short unscaled signed 9 bit
1002    with pre- or post-writeback.  */
1003 static void
1004 ldrsh32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1005 {
1006   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1007   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1008   uint64_t address;
1009
1010   if (rn == rt && wb != NoWriteBack)
1011     HALT_UNALLOC;
1012
1013   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1014
1015   if (wb != Post)
1016     address += offset;
1017
1018   aarch64_set_reg_u64 (cpu, rt, NO_SP,
1019                        (uint32_t) aarch64_get_mem_s16 (cpu, address));
1020
1021   if (wb == Post)
1022     address += offset;
1023
1024   if (wb != NoWriteBack)
1025     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1026 }
1027
1028 /* 32 bit load sign-extended short scaled or unscaled zero-
1029    or sign-extended 32-bit register offset.  */
1030 static void
1031 ldrsh32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1032 {
1033   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1034   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1035   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1036   /* rn may reference SP, rm and rt must reference ZR  */
1037
1038   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1039   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1040   uint64_t displacement =  OPT_SCALE (extended, 16, scaling);
1041
1042   aarch64_set_reg_u64 (cpu, rt, NO_SP,
1043                        (uint32_t) aarch64_get_mem_s16
1044                        (cpu, address + displacement));
1045 }
1046
1047 /* 64 bit load sign-extended short scaled unsigned 12 bit.  */
1048 static void
1049 ldrsh_abs (sim_cpu *cpu, uint32_t offset)
1050 {
1051   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1052   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1053
1054   /* The target register may not be SP but the source may be.  */
1055   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_s16
1056                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
1057                         + SCALE (offset, 16)));
1058 }
1059
1060 /* 64 bit load sign-extended short unscaled signed 9 bit
1061    with pre- or post-writeback.  */
1062 static void
1063 ldrsh64_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1064 {
1065   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1066   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1067   uint64_t address;
1068
1069   if (rn == rt && wb != NoWriteBack)
1070     HALT_UNALLOC;
1071
1072   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1073
1074   if (wb != Post)
1075     address += offset;
1076
1077   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_s16 (cpu, address));
1078
1079   if (wb == Post)
1080     address += offset;
1081
1082   if (wb != NoWriteBack)
1083     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1084 }
1085
1086 /* 64 bit load sign-extended short scaled or unscaled zero-
1087    or sign-extended 32-bit register offset.  */
1088 static void
1089 ldrsh_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1090 {
1091   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1092   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1093   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1094   /* rn may reference SP, rm and rt must reference ZR  */
1095
1096   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1097   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1098   uint64_t displacement = OPT_SCALE (extended, 16, scaling);
1099
1100   aarch64_set_reg_u64 (cpu, rt, NO_SP,
1101                        aarch64_get_mem_s16 (cpu, address + displacement));
1102 }
1103
1104 /* 64 bit load sign-extended 32 bit scaled unsigned 12 bit.  */
1105 static void
1106 ldrsw_abs (sim_cpu *cpu, uint32_t offset)
1107 {
1108   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1109   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1110
1111   /* The target register may not be SP but the source may be.  */
1112   return aarch64_set_reg_s64 (cpu, rt, NO_SP, aarch64_get_mem_s32
1113                               (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
1114                                + SCALE (offset, 32)));
1115 }
1116
1117 /* 64 bit load sign-extended 32 bit unscaled signed 9 bit
1118    with pre- or post-writeback.  */
1119 static void
1120 ldrsw_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1121 {
1122   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1123   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1124   uint64_t address;
1125
1126   if (rn == rt && wb != NoWriteBack)
1127     HALT_UNALLOC;
1128
1129   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1130
1131   if (wb != Post)
1132     address += offset;
1133
1134   aarch64_set_reg_s64 (cpu, rt, NO_SP, aarch64_get_mem_s32 (cpu, address));
1135
1136   if (wb == Post)
1137     address += offset;
1138
1139   if (wb != NoWriteBack)
1140     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1141 }
1142
1143 /* 64 bit load sign-extended 32 bit scaled or unscaled zero-
1144    or sign-extended 32-bit register offset.  */
1145 static void
1146 ldrsw_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1147 {
1148   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1149   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1150   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1151   /* rn may reference SP, rm and rt must reference ZR  */
1152
1153   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1154   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1155   uint64_t displacement =  OPT_SCALE (extended, 32, scaling);
1156
1157   aarch64_set_reg_s64 (cpu, rt, NO_SP,
1158                        aarch64_get_mem_s32 (cpu, address + displacement));
1159 }
1160
1161 /* N.B. with stores the value in source is written to the
1162    address identified by source2 modified by source3/offset.  */
1163
1164 /* 32 bit store scaled unsigned 12 bit.  */
1165 static void
1166 str32_abs (sim_cpu *cpu, uint32_t offset)
1167 {
1168   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1169   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1170
1171   /* The target register may not be SP but the source may be.  */
1172   aarch64_set_mem_u32 (cpu, (aarch64_get_reg_u64 (cpu, rn, SP_OK)
1173                              + SCALE (offset, 32)),
1174                        aarch64_get_reg_u32 (cpu, rt, NO_SP));
1175 }
1176
1177 /* 32 bit store unscaled signed 9 bit with pre- or post-writeback.  */
1178 static void
1179 str32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1180 {
1181   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1182   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1183   uint64_t address;
1184
1185   if (rn == rt && wb != NoWriteBack)
1186     HALT_UNALLOC;
1187
1188   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1189   if (wb != Post)
1190     address += offset;
1191
1192   aarch64_set_mem_u32 (cpu, address, aarch64_get_reg_u32 (cpu, rt, NO_SP));
1193
1194   if (wb == Post)
1195     address += offset;
1196
1197   if (wb != NoWriteBack)
1198     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1199 }
1200
1201 /* 32 bit store scaled or unscaled zero- or
1202    sign-extended 32-bit register offset.  */
1203 static void
1204 str32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1205 {
1206   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1207   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1208   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1209
1210   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1211   int64_t  extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1212   uint64_t displacement = OPT_SCALE (extended, 32, scaling);
1213
1214   aarch64_set_mem_u32 (cpu, address + displacement,
1215                        aarch64_get_reg_u64 (cpu, rt, NO_SP));
1216 }
1217
1218 /* 64 bit store scaled unsigned 12 bit.  */
1219 static void
1220 str_abs (sim_cpu *cpu, uint32_t offset)
1221 {
1222   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1223   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1224
1225   aarch64_set_mem_u64 (cpu,
1226                        aarch64_get_reg_u64 (cpu, rn, SP_OK)
1227                        + SCALE (offset, 64),
1228                        aarch64_get_reg_u64 (cpu, rt, NO_SP));
1229 }
1230
1231 /* 64 bit store unscaled signed 9 bit with pre- or post-writeback.  */
1232 static void
1233 str_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1234 {
1235   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1236   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1237   uint64_t address;
1238
1239   if (rn == rt && wb != NoWriteBack)
1240     HALT_UNALLOC;
1241
1242   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1243
1244   if (wb != Post)
1245     address += offset;
1246
1247   aarch64_set_mem_u64 (cpu, address, aarch64_get_reg_u64 (cpu, rt, NO_SP));
1248
1249   if (wb == Post)
1250     address += offset;
1251
1252   if (wb != NoWriteBack)
1253     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1254 }
1255
1256 /* 64 bit store scaled or unscaled zero-
1257    or sign-extended 32-bit register offset.  */
1258 static void
1259 str_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1260 {
1261   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1262   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1263   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1264   /* rn may reference SP, rm and rt must reference ZR  */
1265
1266   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1267   int64_t   extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1268                                extension);
1269   uint64_t displacement = OPT_SCALE (extended, 64, scaling);
1270
1271   aarch64_set_mem_u64 (cpu, address + displacement,
1272                        aarch64_get_reg_u64 (cpu, rt, NO_SP));
1273 }
1274
1275 /* 32 bit store byte scaled unsigned 12 bit.  */
1276 static void
1277 strb_abs (sim_cpu *cpu, uint32_t offset)
1278 {
1279   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1280   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1281
1282   /* The target register may not be SP but the source may be.
1283      There is no scaling required for a byte load.  */
1284   aarch64_set_mem_u8 (cpu,
1285                       aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
1286                       aarch64_get_reg_u8 (cpu, rt, NO_SP));
1287 }
1288
1289 /* 32 bit store byte unscaled signed 9 bit with pre- or post-writeback.  */
1290 static void
1291 strb_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1292 {
1293   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1294   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1295   uint64_t address;
1296
1297   if (rn == rt && wb != NoWriteBack)
1298     HALT_UNALLOC;
1299
1300   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1301
1302   if (wb != Post)
1303     address += offset;
1304
1305   aarch64_set_mem_u8 (cpu, address, aarch64_get_reg_u8 (cpu, rt, NO_SP));
1306
1307   if (wb == Post)
1308     address += offset;
1309
1310   if (wb != NoWriteBack)
1311     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1312 }
1313
1314 /* 32 bit store byte scaled or unscaled zero-
1315    or sign-extended 32-bit register offset.  */
1316 static void
1317 strb_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1318 {
1319   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1320   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1321   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1322   /* rn may reference SP, rm and rt must reference ZR  */
1323
1324   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1325   int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1326                                  extension);
1327
1328   /* There is no scaling required for a byte load.  */
1329   aarch64_set_mem_u8 (cpu, address + displacement,
1330                       aarch64_get_reg_u8 (cpu, rt, NO_SP));
1331 }
1332
1333 /* 32 bit store short scaled unsigned 12 bit.  */
1334 static void
1335 strh_abs (sim_cpu *cpu, uint32_t offset)
1336 {
1337   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1338   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1339
1340   /* The target register may not be SP but the source may be.  */
1341   aarch64_set_mem_u16 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
1342                        + SCALE (offset, 16),
1343                        aarch64_get_reg_u16 (cpu, rt, NO_SP));
1344 }
1345
1346 /* 32 bit store short unscaled signed 9 bit with pre- or post-writeback.  */
1347 static void
1348 strh_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1349 {
1350   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1351   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1352   uint64_t address;
1353
1354   if (rn == rt && wb != NoWriteBack)
1355     HALT_UNALLOC;
1356
1357   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1358
1359   if (wb != Post)
1360     address += offset;
1361
1362   aarch64_set_mem_u16 (cpu, address, aarch64_get_reg_u16 (cpu, rt, NO_SP));
1363
1364   if (wb == Post)
1365     address += offset;
1366
1367   if (wb != NoWriteBack)
1368     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1369 }
1370
1371 /* 32 bit store short scaled or unscaled zero-
1372    or sign-extended 32-bit register offset.  */
1373 static void
1374 strh_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1375 {
1376   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1377   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1378   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1379   /* rn may reference SP, rm and rt must reference ZR  */
1380
1381   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1382   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1383   uint64_t displacement =  OPT_SCALE (extended, 16, scaling);
1384
1385   aarch64_set_mem_u16 (cpu, address + displacement,
1386                        aarch64_get_reg_u16 (cpu, rt, NO_SP));
1387 }
1388
1389 /* Prefetch unsigned 12 bit.  */
1390 static void
1391 prfm_abs (sim_cpu *cpu, uint32_t offset)
1392 {
1393   /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1394                           00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1395                           00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1396                           10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1397                           10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1398                           10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1399                           ow ==> UNALLOC
1400      PrfOp prfop = prfop (aarch64_get_instr (cpu), 4, 0);
1401      uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK)
1402      + SCALE (offset, 64).  */
1403
1404   /* TODO : implement prefetch of address.  */
1405 }
1406
1407 /* Prefetch scaled or unscaled zero- or sign-extended 32-bit register offset.  */
1408 static void
1409 prfm_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1410 {
1411   /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1412                           00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1413                           00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1414                           10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1415                           10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1416                           10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1417                           ow ==> UNALLOC
1418      rn may reference SP, rm may only reference ZR
1419      PrfOp prfop = prfop (aarch64_get_instr (cpu), 4, 0);
1420      uint64_t base = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1421      int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1422                                 extension);
1423      uint64_t displacement =  OPT_SCALE (extended, 64, scaling);
1424      uint64_t address = base + displacement.  */
1425
1426   /* TODO : implement prefetch of address  */
1427 }
1428
1429 /* 64 bit pc-relative prefetch.  */
1430 static void
1431 prfm_pcrel (sim_cpu *cpu, int32_t offset)
1432 {
1433   /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1434                           00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1435                           00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1436                           10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1437                           10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1438                           10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1439                           ow ==> UNALLOC
1440      PrfOp prfop = prfop (aarch64_get_instr (cpu), 4, 0);
1441      uint64_t address = aarch64_get_PC (cpu) + offset.  */
1442
1443   /* TODO : implement this  */
1444 }
1445
1446 /* Load-store exclusive.  */
1447
1448 static void
1449 ldxr (sim_cpu *cpu)
1450 {
1451   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1452   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1453   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1454   int size = uimm (aarch64_get_instr (cpu), 31, 30);
1455   /* int ordered = uimm (aarch64_get_instr (cpu), 15, 15);  */
1456   /* int exclusive = ! uimm (aarch64_get_instr (cpu), 23, 23);  */
1457
1458   switch (size)
1459     {
1460     case 0:
1461       aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u8 (cpu, address));
1462       break;
1463     case 1:
1464       aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u16 (cpu, address));
1465       break;
1466     case 2:
1467       aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32 (cpu, address));
1468       break;
1469     case 3:
1470       aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64 (cpu, address));
1471       break;
1472     default:
1473       HALT_UNALLOC;
1474     }
1475 }
1476
1477 static void
1478 stxr (sim_cpu *cpu)
1479 {
1480   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1481   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1482   unsigned rs = uimm (aarch64_get_instr (cpu), 20, 16);
1483   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1484   int      size = uimm (aarch64_get_instr (cpu), 31, 30);
1485   uint64_t data = aarch64_get_reg_u64 (cpu, rt, NO_SP);
1486
1487   switch (size)
1488     {
1489     case 0: aarch64_set_mem_u8 (cpu, address, data); break;
1490     case 1: aarch64_set_mem_u16 (cpu, address, data); break;
1491     case 2: aarch64_set_mem_u32 (cpu, address, data); break;
1492     case 3: aarch64_set_mem_u64 (cpu, address, data); break;
1493     default: HALT_UNALLOC;
1494     }
1495
1496   aarch64_set_reg_u64 (cpu, rs, NO_SP, 0); /* Always exclusive...  */
1497 }
1498
1499 static void
1500 dexLoadLiteral (sim_cpu *cpu)
1501 {
1502   /* instr[29,27] == 011
1503      instr[25,24] == 00
1504      instr[31,30:26] = opc: 000 ==> LDRW,  001 ==> FLDRS
1505                             010 ==> LDRX,  011 ==> FLDRD
1506                             100 ==> LDRSW, 101 ==> FLDRQ
1507                             110 ==> PRFM, 111 ==> UNALLOC
1508      instr[26] ==> V : 0 ==> GReg, 1 ==> FReg
1509      instr[23, 5] == simm19  */
1510
1511   /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);  */
1512   uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 1)
1513                         | uimm (aarch64_get_instr (cpu), 26, 26));
1514   int32_t imm = simm32 (aarch64_get_instr (cpu), 23, 5);
1515
1516   switch (dispatch)
1517     {
1518     case 0: ldr32_pcrel (cpu, imm); break;
1519     case 1: fldrs_pcrel (cpu, imm); break;
1520     case 2: ldr_pcrel   (cpu, imm); break;
1521     case 3: fldrd_pcrel (cpu, imm); break;
1522     case 4: ldrsw_pcrel (cpu, imm); break;
1523     case 5: fldrq_pcrel (cpu, imm); break;
1524     case 6: prfm_pcrel  (cpu, imm); break;
1525     case 7:
1526     default:
1527       HALT_UNALLOC;
1528     }
1529 }
1530
1531 /* Immediate arithmetic
1532    The aimm argument is a 12 bit unsigned value or a 12 bit unsigned
1533    value left shifted by 12 bits (done at decode).
1534
1535    N.B. the register args (dest, source) can normally be Xn or SP.
1536    the exception occurs for flag setting instructions which may
1537    only use Xn for the output (dest).  */
1538
1539 /* 32 bit add immediate.  */
1540 static void
1541 add32 (sim_cpu *cpu, uint32_t aimm)
1542 {
1543   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1544   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1545
1546   aarch64_set_reg_u64 (cpu, rd, SP_OK,
1547                        aarch64_get_reg_u32 (cpu, rn, SP_OK) + aimm);
1548 }
1549
1550 /* 64 bit add immediate.  */
1551 static void
1552 add64 (sim_cpu *cpu, uint32_t aimm)
1553 {
1554   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1555   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1556
1557   aarch64_set_reg_u64 (cpu, rd, SP_OK,
1558                        aarch64_get_reg_u64 (cpu, rn, SP_OK) + aimm);
1559 }
1560
1561 static void
1562 set_flags_for_add32 (sim_cpu *cpu, int32_t value1, int32_t value2)
1563 {
1564   int32_t   result = value1 + value2;
1565   int64_t   sresult = (int64_t) value1 + (int64_t) value2;
1566   uint64_t  uresult = (uint64_t)(uint32_t) value1
1567     + (uint64_t)(uint32_t) value2;
1568   uint32_t  flags = 0;
1569
1570   if (result == 0)
1571     flags |= Z;
1572
1573   if (result & (1 << 31))
1574     flags |= N;
1575
1576   if (uresult != result)
1577     flags |= C;
1578
1579   if (sresult != result)
1580     flags |= V;
1581
1582   aarch64_set_CPSR (cpu, flags);
1583 }
1584
1585 static void
1586 set_flags_for_add64 (sim_cpu *cpu, uint64_t value1, uint64_t value2)
1587 {
1588   int64_t   sval1 = value1;
1589   int64_t   sval2 = value2;
1590   uint64_t  result = value1 + value2;
1591   int64_t   sresult = sval1 + sval2;
1592   uint32_t  flags = 0;
1593
1594   if (result == 0)
1595     flags |= Z;
1596
1597   if (result & (1ULL << 63))
1598     flags |= N;
1599
1600   if (sval1 < 0)
1601     {
1602       if (sval2 < 0)
1603         {
1604           /* Negative plus a negative.  Overflow happens if
1605              the result is greater than either of the operands.  */
1606           if (sresult > sval1 || sresult > sval2)
1607             flags |= V;
1608         }
1609       /* else Negative plus a positive.  Overflow cannot happen.  */
1610     }
1611   else /* value1 is +ve.  */
1612     {
1613       if (sval2 < 0)
1614         {
1615           /* Overflow can only occur if we computed "0 - MININT".  */
1616           if (sval1 == 0 && sval2 == (1LL << 63))
1617             flags |= V;
1618         }
1619       else
1620         {
1621           /* Postive plus positive - overflow has happened if the
1622              result is smaller than either of the operands.  */
1623           if (result < value1 || result < value2)
1624             flags |= V | C;
1625         }
1626     }
1627
1628   aarch64_set_CPSR (cpu, flags);
1629 }
1630
1631 #define NEG(a) (((a) & signbit) == signbit)
1632 #define POS(a) (((a) & signbit) == 0)
1633
1634 static void
1635 set_flags_for_sub32 (sim_cpu *cpu, uint32_t value1, uint32_t value2)
1636 {
1637   uint32_t result = value1 - value2;
1638   uint32_t flags = 0;
1639   uint32_t signbit = 1ULL << 31;
1640
1641   if (result == 0)
1642     flags |= Z;
1643
1644   if (NEG (result))
1645     flags |= N;
1646
1647   if (   (NEG (value1) && POS (value2))
1648       || (NEG (value1) && POS (result))
1649       || (POS (value2) && POS (result)))
1650     flags |= C;
1651
1652   if (   (NEG (value1) && POS (value2) && POS (result))
1653       || (POS (value1) && NEG (value2) && NEG (result)))
1654     flags |= V;
1655
1656   aarch64_set_CPSR (cpu, flags);
1657 }
1658
1659 static void
1660 set_flags_for_sub64 (sim_cpu *cpu, uint64_t value1, uint64_t value2)
1661 {
1662   uint64_t result = value1 - value2;
1663   uint32_t flags = 0;
1664   uint64_t signbit = 1ULL << 63;
1665
1666   if (result == 0)
1667     flags |= Z;
1668
1669   if (NEG (result))
1670     flags |= N;
1671
1672   if (   (NEG (value1) && POS (value2))
1673       || (NEG (value1) && POS (result))
1674       || (POS (value2) && POS (result)))
1675     flags |= C;
1676
1677   if (   (NEG (value1) && POS (value2) && POS (result))
1678       || (POS (value1) && NEG (value2) && NEG (result)))
1679     flags |= V;
1680
1681   aarch64_set_CPSR (cpu, flags);
1682 }
1683
1684 static void
1685 set_flags_for_binop32 (sim_cpu *cpu, uint32_t result)
1686 {
1687   uint32_t flags = 0;
1688
1689   if (result == 0)
1690     flags |= Z;
1691   else
1692     flags &= ~ Z;
1693
1694   if (result & (1 << 31))
1695     flags |= N;
1696   else
1697     flags &= ~ N;
1698
1699   aarch64_set_CPSR (cpu, flags);
1700 }
1701
1702 static void
1703 set_flags_for_binop64 (sim_cpu *cpu, uint64_t result)
1704 {
1705   uint32_t flags = 0;
1706
1707   if (result == 0)
1708     flags |= Z;
1709   else
1710     flags &= ~ Z;
1711
1712   if (result & (1ULL << 63))
1713     flags |= N;
1714   else
1715     flags &= ~ N;
1716
1717   aarch64_set_CPSR (cpu, flags);
1718 }
1719
1720 /* 32 bit add immediate set flags.  */
1721 static void
1722 adds32 (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   /* TODO : do we need to worry about signs here?  */
1727   int32_t value1 = aarch64_get_reg_s32 (cpu, rn, SP_OK);
1728
1729   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + aimm);
1730   set_flags_for_add32 (cpu, value1, aimm);
1731 }
1732
1733 /* 64 bit add immediate set flags.  */
1734 static void
1735 adds64 (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   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1740   uint64_t value2 = aimm;
1741
1742   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
1743   set_flags_for_add64 (cpu, value1, value2);
1744 }
1745
1746 /* 32 bit sub immediate.  */
1747 static void
1748 sub32 (sim_cpu *cpu, uint32_t aimm)
1749 {
1750   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1751   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1752
1753   aarch64_set_reg_u64 (cpu, rd, SP_OK,
1754                        aarch64_get_reg_u32 (cpu, rn, SP_OK) - aimm);
1755 }
1756
1757 /* 64 bit sub immediate.  */
1758 static void
1759 sub64 (sim_cpu *cpu, uint32_t aimm)
1760 {
1761   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1762   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1763
1764   aarch64_set_reg_u64 (cpu, rd, SP_OK,
1765                        aarch64_get_reg_u64 (cpu, rn, SP_OK) - aimm);
1766 }
1767
1768 /* 32 bit sub immediate set flags.  */
1769 static void
1770 subs32 (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   uint32_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_sub32 (cpu, value1, value2);
1779 }
1780
1781 /* 64 bit sub immediate set flags.  */
1782 static void
1783 subs64 (sim_cpu *cpu, uint32_t aimm)
1784 {
1785   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1786   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1787   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1788   uint32_t value2 = aimm;
1789
1790   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1791   set_flags_for_sub64 (cpu, value1, value2);
1792 }
1793
1794 /* Data Processing Register.  */
1795
1796 /* First two helpers to perform the shift operations.  */
1797
1798 static inline uint32_t
1799 shifted32 (uint32_t value, Shift shift, uint32_t count)
1800 {
1801   switch (shift)
1802     {
1803     default:
1804     case LSL:
1805       return (value << count);
1806     case LSR:
1807       return (value >> count);
1808     case ASR:
1809       {
1810         int32_t svalue = value;
1811         return (svalue >> count);
1812       }
1813     case ROR:
1814       {
1815         uint32_t top = value >> count;
1816         uint32_t bottom = value << (32 - count);
1817         return (bottom | top);
1818       }
1819     }
1820 }
1821
1822 static inline uint64_t
1823 shifted64 (uint64_t value, Shift shift, uint32_t count)
1824 {
1825   switch (shift)
1826     {
1827     default:
1828     case LSL:
1829       return (value << count);
1830     case LSR:
1831       return (value >> count);
1832     case ASR:
1833       {
1834         int64_t svalue = value;
1835         return (svalue >> count);
1836       }
1837     case ROR:
1838       {
1839         uint64_t top = value >> count;
1840         uint64_t bottom = value << (64 - count);
1841         return (bottom | top);
1842       }
1843     }
1844 }
1845
1846 /* Arithmetic shifted register.
1847    These allow an optional LSL, ASR or LSR to the second source
1848    register with a count up to the register bit count.
1849
1850    N.B register args may not be SP.  */
1851
1852 /* 32 bit ADD shifted register.  */
1853 static void
1854 add32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1855 {
1856   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1857   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1858   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1859
1860   aarch64_set_reg_u64 (cpu, rd, NO_SP,
1861                        aarch64_get_reg_u32 (cpu, rn, NO_SP)
1862                        + shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1863                                     shift, count));
1864 }
1865
1866 /* 64 bit ADD shifted register.  */
1867 static void
1868 add64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1869 {
1870   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1871   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1872   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1873
1874   aarch64_set_reg_u64 (cpu, rd, NO_SP,
1875                        aarch64_get_reg_u64 (cpu, rn, NO_SP)
1876                        + shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1877                                     shift, count));
1878 }
1879
1880 /* 32 bit ADD shifted register setting flags.  */
1881 static void
1882 adds32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1883 {
1884   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1885   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1886   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1887
1888   uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
1889   uint32_t value2 = shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1890                                shift, count);
1891
1892   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
1893   set_flags_for_add32 (cpu, value1, value2);
1894 }
1895
1896 /* 64 bit ADD shifted register setting flags.  */
1897 static void
1898 adds64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1899 {
1900   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1901   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1902   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1903
1904   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
1905   uint64_t value2 = shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1906                                shift, count);
1907
1908   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
1909   set_flags_for_add64 (cpu, value1, value2);
1910 }
1911
1912 /* 32 bit SUB shifted register.  */
1913 static void
1914 sub32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1915 {
1916   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1917   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1918   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1919
1920   aarch64_set_reg_u64 (cpu, rd, NO_SP,
1921                        aarch64_get_reg_u32 (cpu, rn, NO_SP)
1922                        - shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1923                                     shift, count));
1924 }
1925
1926 /* 64 bit SUB shifted register.  */
1927 static void
1928 sub64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1929 {
1930   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1931   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1932   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1933
1934   aarch64_set_reg_u64 (cpu, rd, NO_SP,
1935                        aarch64_get_reg_u64 (cpu, rn, NO_SP)
1936                        - shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1937                                     shift, count));
1938 }
1939
1940 /* 32 bit SUB shifted register setting flags.  */
1941 static void
1942 subs32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1943 {
1944   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1945   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1946   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1947
1948   uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
1949   uint32_t value2 = shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1950                               shift, count);
1951
1952   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1953   set_flags_for_sub32 (cpu, value1, value2);
1954 }
1955
1956 /* 64 bit SUB shifted register setting flags.  */
1957 static void
1958 subs64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1959 {
1960   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1961   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1962   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1963
1964   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
1965   uint64_t value2 = shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1966                                shift, count);
1967
1968   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1969   set_flags_for_sub64 (cpu, value1, value2);
1970 }
1971
1972 /* First a couple more helpers to fetch the
1973    relevant source register element either
1974    sign or zero extended as required by the
1975    extension value.  */
1976
1977 static uint32_t
1978 extreg32 (sim_cpu *cpu, unsigned int lo, Extension extension)
1979 {
1980   switch (extension)
1981     {
1982     case UXTB: return aarch64_get_reg_u8  (cpu, lo, NO_SP);
1983     case UXTH: return aarch64_get_reg_u16 (cpu, lo, NO_SP);
1984     case UXTW: /* Fall through.  */
1985     case UXTX: return aarch64_get_reg_u32 (cpu, lo, NO_SP);
1986     case SXTB: return aarch64_get_reg_s8  (cpu, lo, NO_SP);
1987     case SXTH: return aarch64_get_reg_s16 (cpu, lo, NO_SP);
1988     case SXTW: /* Fall through.  */
1989     case SXTX: /* Fall through.  */
1990     default:   return aarch64_get_reg_s32 (cpu, lo, NO_SP);
1991   }
1992 }
1993
1994 static uint64_t
1995 extreg64 (sim_cpu *cpu, unsigned int lo, Extension extension)
1996 {
1997   switch (extension)
1998     {
1999     case UXTB: return aarch64_get_reg_u8  (cpu, lo, NO_SP);
2000     case UXTH: return aarch64_get_reg_u16 (cpu, lo, NO_SP);
2001     case UXTW: return aarch64_get_reg_u32 (cpu, lo, NO_SP);
2002     case UXTX: return aarch64_get_reg_u64 (cpu, lo, NO_SP);
2003     case SXTB: return aarch64_get_reg_s8  (cpu, lo, NO_SP);
2004     case SXTH: return aarch64_get_reg_s16 (cpu, lo, NO_SP);
2005     case SXTW: return aarch64_get_reg_s32 (cpu, lo, NO_SP);
2006     case SXTX:
2007     default:   return aarch64_get_reg_s64 (cpu, lo, NO_SP);
2008     }
2009 }
2010
2011 /* Arithmetic extending register
2012    These allow an optional sign extension of some portion of the
2013    second source register followed by an optional left shift of
2014    between 1 and 4 bits (i.e. a shift of 0-4 bits???)
2015
2016    N.B output (dest) and first input arg (source) may normally be Xn
2017    or SP. However, for flag setting operations dest can only be
2018    Xn. Second input registers are always Xn.  */
2019
2020 /* 32 bit ADD extending register.  */
2021 static void
2022 add32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2023 {
2024   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2025   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2026   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2027
2028   aarch64_set_reg_u64 (cpu, rd, SP_OK,
2029                        aarch64_get_reg_u32 (cpu, rn, SP_OK)
2030                        + (extreg32 (cpu, rm, extension) << shift));
2031 }
2032
2033 /* 64 bit ADD extending register.
2034    N.B. This subsumes the case with 64 bit source2 and UXTX #n or LSL #0.  */
2035 static void
2036 add64_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   aarch64_set_reg_u64 (cpu, rd, SP_OK,
2043                        aarch64_get_reg_u64 (cpu, rn, SP_OK)
2044                        + (extreg64 (cpu, rm, extension) << shift));
2045 }
2046
2047 /* 32 bit ADD extending register setting flags.  */
2048 static void
2049 adds32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2050 {
2051   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2052   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2053   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2054
2055   uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, SP_OK);
2056   uint32_t value2 = extreg32 (cpu, rm, extension) << shift;
2057
2058   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
2059   set_flags_for_add32 (cpu, value1, value2);
2060 }
2061
2062 /* 64 bit ADD extending register setting flags  */
2063 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0  */
2064 static void
2065 adds64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2066 {
2067   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2068   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2069   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2070
2071   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
2072   uint64_t value2 = extreg64 (cpu, rm, extension) << shift;
2073
2074   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
2075   set_flags_for_add64 (cpu, value1, value2);
2076 }
2077
2078 /* 32 bit SUB extending register.  */
2079 static void
2080 sub32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2081 {
2082   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2083   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2084   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2085
2086   aarch64_set_reg_u64 (cpu, rd, SP_OK,
2087                        aarch64_get_reg_u32 (cpu, rn, SP_OK)
2088                        - (extreg32 (cpu, rm, extension) << shift));
2089 }
2090
2091 /* 64 bit SUB extending register.  */
2092 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0.  */
2093 static void
2094 sub64_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   aarch64_set_reg_u64 (cpu, rd, SP_OK,
2101                        aarch64_get_reg_u64 (cpu, rn, SP_OK)
2102                        - (extreg64 (cpu, rm, extension) << shift));
2103 }
2104
2105 /* 32 bit SUB extending register setting flags.  */
2106 static void
2107 subs32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2108 {
2109   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2110   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2111   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2112
2113   uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, SP_OK);
2114   uint32_t value2 = extreg32 (cpu, rm, extension) << shift;
2115
2116   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
2117   set_flags_for_sub32 (cpu, value1, value2);
2118 }
2119
2120 /* 64 bit SUB extending register setting flags  */
2121 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0  */
2122 static void
2123 subs64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2124 {
2125   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2126   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2127   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2128
2129   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
2130   uint64_t value2 = extreg64 (cpu, rm, extension) << shift;
2131
2132   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
2133   set_flags_for_sub64 (cpu, value1, value2);
2134 }
2135
2136 static void
2137 dexAddSubtractImmediate (sim_cpu *cpu)
2138 {
2139   /* instr[31]    = size : 0 ==> 32 bit, 1 ==> 64 bit
2140      instr[30]    = op : 0 ==> ADD, 1 ==> SUB
2141      instr[29]    = set : 0 ==> no flags, 1 ==> set flags
2142      instr[28,24] = 10001
2143      instr[23,22] = shift : 00 == LSL#0, 01 = LSL#12 1x = UNALLOC
2144      instr[21,10] = uimm12
2145      instr[9,5]   = Rn
2146      instr[4,0]   = Rd  */
2147
2148   /* N.B. the shift is applied at decode before calling the add/sub routine.  */
2149   uint32_t shift = uimm (aarch64_get_instr (cpu), 23, 22);
2150   uint32_t imm = uimm (aarch64_get_instr (cpu), 21, 10);
2151   uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2152
2153   NYI_assert (28, 24, 0x11);
2154
2155   if (shift > 1)
2156     HALT_UNALLOC;
2157
2158   if (shift)
2159     imm <<= 12;
2160
2161   switch (dispatch)
2162     {
2163     case 0: add32 (cpu, imm); break;
2164     case 1: adds32 (cpu, imm); break;
2165     case 2: sub32 (cpu, imm); break;
2166     case 3: subs32 (cpu, imm); break;
2167     case 4: add64 (cpu, imm); break;
2168     case 5: adds64 (cpu, imm); break;
2169     case 6: sub64 (cpu, imm); break;
2170     case 7: subs64 (cpu, imm); break;
2171     default:
2172       HALT_UNALLOC;
2173     }
2174 }
2175
2176 static void
2177 dexAddSubtractShiftedRegister (sim_cpu *cpu)
2178 {
2179   /* instr[31]    = size : 0 ==> 32 bit, 1 ==> 64 bit
2180      instr[30,29] = op : 00 ==> ADD, 01 ==> ADDS, 10 ==> SUB, 11 ==> SUBS
2181      instr[28,24] = 01011
2182      instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> UNALLOC
2183      instr[21]    = 0
2184      instr[20,16] = Rm
2185      instr[15,10] = count : must be 0xxxxx for 32 bit
2186      instr[9,5]   = Rn
2187      instr[4,0]   = Rd  */
2188
2189   uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
2190   /* 32 bit operations must have count[5] = 0
2191      or else we have an UNALLOC.  */
2192   uint32_t count = uimm (aarch64_get_instr (cpu), 15, 10);
2193   /* Shift encoded as ROR is unallocated.  */
2194   Shift shiftType = shift (aarch64_get_instr (cpu), 22);
2195   /* Dispatch on size:op i.e aarch64_get_instr (cpu)[31,29].  */
2196   uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2197
2198   NYI_assert (28, 24, 0x0B);
2199   NYI_assert (21, 21, 0);
2200
2201   if (shiftType == ROR)
2202     HALT_UNALLOC;
2203
2204   if (!size && uimm (count, 5, 5))
2205     HALT_UNALLOC;
2206
2207   switch (dispatch)
2208     {
2209     case 0: add32_shift  (cpu, shiftType, count); break;
2210     case 1: adds32_shift (cpu, shiftType, count); break;
2211     case 2: sub32_shift  (cpu, shiftType, count); break;
2212     case 3: subs32_shift (cpu, shiftType, count); break;
2213     case 4: add64_shift  (cpu, shiftType, count); break;
2214     case 5: adds64_shift (cpu, shiftType, count); break;
2215     case 6: sub64_shift  (cpu, shiftType, count); break;
2216     case 7: subs64_shift (cpu, shiftType, count); break;
2217     default:
2218       HALT_UNALLOC;
2219     }
2220 }
2221
2222 static void
2223 dexAddSubtractExtendedRegister (sim_cpu *cpu)
2224 {
2225   /* instr[31]    = size : 0 ==> 32 bit, 1 ==> 64 bit
2226      instr[30]    = op : 0 ==> ADD, 1 ==> SUB
2227      instr[29]    = set? : 0 ==> no flags, 1 ==> set flags
2228      instr[28,24] = 01011
2229      instr[23,22] = opt : 0 ==> ok, 1,2,3 ==> UNALLOC
2230      instr[21]    = 1
2231      instr[20,16] = Rm
2232      instr[15,13] = option : 000 ==> UXTB, 001 ==> UXTH,
2233                              000 ==> LSL|UXTW, 001 ==> UXTZ,
2234                              000 ==> SXTB, 001 ==> SXTH,
2235                              000 ==> SXTW, 001 ==> SXTX,
2236      instr[12,10] = shift : 0,1,2,3,4 ==> ok, 5,6,7 ==> UNALLOC
2237      instr[9,5]   = Rn
2238      instr[4,0]   = Rd  */
2239
2240   Extension extensionType = extension (aarch64_get_instr (cpu), 13);
2241   uint32_t shift = uimm (aarch64_get_instr (cpu), 12, 10);
2242   /* dispatch on size:op:set? i.e aarch64_get_instr (cpu)[31,29]  */
2243   uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2244
2245   NYI_assert (28, 24, 0x0B);
2246   NYI_assert (21, 21, 1);
2247
2248   /* Shift may not exceed 4.  */
2249   if (shift > 4)
2250     HALT_UNALLOC;
2251
2252   switch (dispatch)
2253     {
2254     case 0: add32_ext  (cpu, extensionType, shift); break;
2255     case 1: adds32_ext (cpu, extensionType, shift); break;
2256     case 2: sub32_ext  (cpu, extensionType, shift); break;
2257     case 3: subs32_ext (cpu, extensionType, shift); break;
2258     case 4: add64_ext  (cpu, extensionType, shift); break;
2259     case 5: adds64_ext (cpu, extensionType, shift); break;
2260     case 6: sub64_ext  (cpu, extensionType, shift); break;
2261     case 7: subs64_ext (cpu, extensionType, shift); break;
2262     default: HALT_UNALLOC;
2263     }
2264 }
2265
2266 /* Conditional data processing
2267    Condition register is implicit 3rd source.  */
2268
2269 /* 32 bit add with carry.  */
2270 /* N.B register args may not be SP.  */
2271
2272 static void
2273 adc32 (sim_cpu *cpu)
2274 {
2275   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2276   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2277   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2278
2279   aarch64_set_reg_u64 (cpu, rd, NO_SP,
2280                        aarch64_get_reg_u32 (cpu, rn, NO_SP)
2281                        + aarch64_get_reg_u32 (cpu, rm, NO_SP)
2282                        + IS_SET (C));
2283 }
2284
2285 /* 64 bit add with carry  */
2286 static void
2287 adc64 (sim_cpu *cpu)
2288 {
2289   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2290   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2291   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2292
2293   aarch64_set_reg_u64 (cpu, rd, NO_SP,
2294                        aarch64_get_reg_u64 (cpu, rn, NO_SP)
2295                        + aarch64_get_reg_u64 (cpu, rm, NO_SP)
2296                        + IS_SET (C));
2297 }
2298
2299 /* 32 bit add with carry setting flags.  */
2300 static void
2301 adcs32 (sim_cpu *cpu)
2302 {
2303   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2304   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2305   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2306
2307   uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
2308   uint32_t value2 = aarch64_get_reg_u32 (cpu, rm, NO_SP);
2309   uint32_t carry = IS_SET (C);
2310
2311   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2 + carry);
2312   set_flags_for_add32 (cpu, value1, value2 + carry);
2313 }
2314
2315 /* 64 bit add with carry setting flags.  */
2316 static void
2317 adcs64 (sim_cpu *cpu)
2318 {
2319   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2320   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2321   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2322
2323   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
2324   uint64_t value2 = aarch64_get_reg_u64 (cpu, rm, NO_SP);
2325   uint64_t carry = IS_SET (C);
2326
2327   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2 + carry);
2328   set_flags_for_add64 (cpu, value1, value2 + carry);
2329 }
2330
2331 /* 32 bit sub with carry.  */
2332 static void
2333 sbc32 (sim_cpu *cpu)
2334 {
2335   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2336   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2337   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2338
2339   aarch64_set_reg_u64 (cpu, rd, NO_SP,
2340                        aarch64_get_reg_u32 (cpu, rn, NO_SP)
2341                        - aarch64_get_reg_u32 (cpu, rm, NO_SP)
2342                        - 1 + IS_SET (C));
2343 }
2344
2345 /* 64 bit sub with carry  */
2346 static void
2347 sbc64 (sim_cpu *cpu)
2348 {
2349   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2350   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2351   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2352
2353   aarch64_set_reg_u64 (cpu, rd, NO_SP,
2354                        aarch64_get_reg_u64 (cpu, rn, NO_SP)
2355                        - aarch64_get_reg_u64 (cpu, rm, NO_SP)
2356                        - 1 + IS_SET (C));
2357 }
2358
2359 /* 32 bit sub with carry setting flags  */
2360 static void
2361 sbcs32 (sim_cpu *cpu)
2362 {
2363   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2364   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2365   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2366
2367   uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
2368   uint32_t value2 = aarch64_get_reg_u32 (cpu, rm, NO_SP);
2369   uint32_t carry  = IS_SET (C);
2370   uint32_t result = value1 - value2 + 1 - carry;
2371
2372   aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
2373   set_flags_for_sub32 (cpu, value1, value2 + 1 - carry);
2374 }
2375
2376 /* 64 bit sub with carry setting flags  */
2377 static void
2378 sbcs64 (sim_cpu *cpu)
2379 {
2380   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2381   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2382   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2383
2384   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
2385   uint64_t value2 = aarch64_get_reg_u64 (cpu, rm, NO_SP);
2386   uint64_t carry  = IS_SET (C);
2387   uint64_t result = value1 - value2 + 1 - carry;
2388
2389   aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
2390   set_flags_for_sub64 (cpu, value1, value2 + 1 - carry);
2391 }
2392
2393 static void
2394 dexAddSubtractWithCarry (sim_cpu *cpu)
2395 {
2396   /* instr[31]    = size : 0 ==> 32 bit, 1 ==> 64 bit
2397      instr[30]    = op : 0 ==> ADC, 1 ==> SBC
2398      instr[29]    = set? : 0 ==> no flags, 1 ==> set flags
2399      instr[28,21] = 1 1010 000
2400      instr[20,16] = Rm
2401      instr[15,10] = op2 : 00000 ==> ok, ow ==> UNALLOC
2402      instr[9,5]   = Rn
2403      instr[4,0]   = Rd  */
2404
2405   uint32_t op2 = uimm (aarch64_get_instr (cpu), 15, 10);
2406   /* Dispatch on size:op:set? i.e aarch64_get_instr (cpu)[31,29]  */
2407   uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2408
2409   NYI_assert (28, 21, 0xD0);
2410
2411   if (op2 != 0)
2412     HALT_UNALLOC;
2413
2414   switch (dispatch)
2415     {
2416     case 0: adc32 (cpu); break;
2417     case 1: adcs32 (cpu); break;
2418     case 2: sbc32 (cpu); break;
2419     case 3: sbcs32 (cpu); break;
2420     case 4: adc64 (cpu); break;
2421     case 5: adcs64 (cpu); break;
2422     case 6: sbc64 (cpu); break;
2423     case 7: sbcs64 (cpu); break;
2424     default: HALT_UNALLOC;
2425     }
2426 }
2427
2428 static uint32_t
2429 testConditionCode (sim_cpu *cpu, CondCode cc)
2430 {
2431   /* This should be reduceable to branchless logic
2432      by some careful testing of bits in CC followed
2433      by the requisite masking and combining of bits
2434      from the flag register.
2435
2436      For now we do it with a switch.  */
2437   int res;
2438
2439   switch (cc)
2440     {
2441     case EQ:  res = IS_SET (Z);    break;
2442     case NE:  res = IS_CLEAR (Z);  break;
2443     case CS:  res = IS_SET (C);    break;
2444     case CC:  res = IS_CLEAR (C);  break;
2445     case MI:  res = IS_SET (N);    break;
2446     case PL:  res = IS_CLEAR (N);  break;
2447     case VS:  res = IS_SET (V);    break;
2448     case VC:  res = IS_CLEAR (V);  break;
2449     case HI:  res = IS_SET (C) && IS_CLEAR (Z);  break;
2450     case LS:  res = IS_CLEAR (C) || IS_SET (Z);  break;
2451     case GE:  res = IS_SET (N) == IS_SET (V);    break;
2452     case LT:  res = IS_SET (N) != IS_SET (V);    break;
2453     case GT:  res = IS_CLEAR (Z) && (IS_SET (N) == IS_SET (V));  break;
2454     case LE:  res = IS_SET (Z) || (IS_SET (N) != IS_SET (V));    break;
2455     case AL:
2456     case NV:
2457     default:
2458       res = 1;
2459       break;
2460     }
2461   return res;
2462 }
2463
2464 static void
2465 CondCompare (sim_cpu *cpu) /* aka: ccmp and ccmn  */
2466 {
2467   /* instr[31]    = size : 0 ==> 32 bit, 1 ==> 64 bit
2468      instr[30]    = compare with positive (0) or negative value (1)
2469      instr[29,21] = 1 1101 0010
2470      instr[20,16] = Rm or const
2471      instr[15,12] = cond
2472      instr[11]    = compare reg (0) or const (1)
2473      instr[10]    = 0
2474      instr[9,5]   = Rn
2475      instr[4]     = 0
2476      instr[3,0]   = value for CPSR bits if the comparison does not take place.  */
2477   signed int negate;
2478   unsigned rm;
2479   unsigned rn;
2480
2481   NYI_assert (29, 21, 0x1d2);
2482   NYI_assert (10, 10, 0);
2483   NYI_assert (4, 4, 0);
2484
2485   if (! testConditionCode (cpu, uimm (aarch64_get_instr (cpu), 15, 12)))
2486     {
2487       aarch64_set_CPSR (cpu, uimm (aarch64_get_instr (cpu), 3, 0));
2488       return;
2489     }
2490
2491   negate = uimm (aarch64_get_instr (cpu), 30, 30) ? -1 : 1;
2492   rm = uimm (aarch64_get_instr (cpu), 20, 16);
2493   rn = uimm (aarch64_get_instr (cpu),  9,  5);
2494
2495   if (uimm (aarch64_get_instr (cpu), 31, 31))
2496     {
2497       if (uimm (aarch64_get_instr (cpu), 11, 11))
2498         set_flags_for_sub64 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK),
2499                              negate * (uint64_t) rm);
2500       else
2501         set_flags_for_sub64 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK),
2502                              negate * aarch64_get_reg_u64 (cpu, rm, SP_OK));
2503     }
2504   else
2505     {
2506       if (uimm (aarch64_get_instr (cpu), 11, 11))
2507         set_flags_for_sub32 (cpu, aarch64_get_reg_u32 (cpu, rn, SP_OK),
2508                              negate * rm);
2509       else
2510         set_flags_for_sub32 (cpu, aarch64_get_reg_u32 (cpu, rn, SP_OK),
2511                              negate * aarch64_get_reg_u32 (cpu, rm, SP_OK));
2512     }
2513 }
2514
2515 static void
2516 do_vec_MOV_whole_vector (sim_cpu *cpu)
2517 {
2518   /* MOV Vd.T, Vs.T  (alias for ORR Vd.T, Vn.T, Vm.T where Vn == Vm)
2519
2520      instr[31]    = 0
2521      instr[30]    = half(0)/full(1)
2522      instr[29,21] = 001110101
2523      instr[20,16] = Vs
2524      instr[15,10] = 000111
2525      instr[9,5]   = Vs
2526      instr[4,0]   = Vd  */
2527
2528   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
2529   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2530
2531   NYI_assert (29, 21, 0x075);
2532   NYI_assert (15, 10, 0x07);
2533
2534   if (uimm (aarch64_get_instr (cpu), 20, 16) != vs)
2535     HALT_NYI;
2536
2537   if (uimm (aarch64_get_instr (cpu), 30, 30))
2538     aarch64_set_vec_u64 (cpu, vd, 1, aarch64_get_vec_u64 (cpu, vs, 1));
2539
2540   aarch64_set_vec_u64 (cpu, vd, 0, aarch64_get_vec_u64 (cpu, vs, 0));
2541 }
2542
2543 static void
2544 do_vec_MOV_into_scalar (sim_cpu *cpu)
2545 {
2546   /* instr[31]    = 0
2547      instr[30]    = word(0)/long(1)
2548      instr[29,21] = 00 1110 000
2549      instr[20,18] = element size and index
2550      instr[17,10] = 00 0011 11
2551      instr[9,5]   = V source
2552      instr[4,0]   = R dest  */
2553
2554   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
2555   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2556
2557   NYI_assert (29, 21, 0x070);
2558   NYI_assert (17, 10, 0x0F);
2559
2560   switch (uimm (aarch64_get_instr (cpu), 20, 18))
2561     {
2562     case 0x2:
2563       aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u64 (cpu, vs, 0));
2564       break;
2565
2566     case 0x6:
2567       aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u64 (cpu, vs, 1));
2568       break;
2569
2570     case 0x1:
2571     case 0x3:
2572     case 0x5:
2573     case 0x7:
2574       aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u32
2575                            (cpu, vs, uimm (aarch64_get_instr (cpu), 20, 19)));
2576       break;
2577
2578     default:
2579       HALT_NYI;
2580     }
2581 }
2582
2583 static void
2584 do_vec_INS (sim_cpu *cpu)
2585 {
2586   /* instr[31,21] = 01001110000
2587      instr[20,16] = element size and index
2588      instr[15,10] = 000111
2589      instr[9,5]   = W source
2590      instr[4,0]   = V dest  */
2591
2592   int index;
2593   unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
2594   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2595
2596   NYI_assert (31, 21, 0x270);
2597   NYI_assert (15, 10, 0x07);
2598
2599   if (uimm (aarch64_get_instr (cpu), 16, 16))
2600     {
2601       index = uimm (aarch64_get_instr (cpu), 20, 17);
2602       aarch64_set_vec_u8 (cpu, vd, index,
2603                           aarch64_get_reg_u8 (cpu, rs, NO_SP));
2604     }
2605   else if (uimm (aarch64_get_instr (cpu), 17, 17))
2606     {
2607       index = uimm (aarch64_get_instr (cpu), 20, 18);
2608       aarch64_set_vec_u16 (cpu, vd, index,
2609                            aarch64_get_reg_u16 (cpu, rs, NO_SP));
2610     }
2611   else if (uimm (aarch64_get_instr (cpu), 18, 18))
2612     {
2613       index = uimm (aarch64_get_instr (cpu), 20, 19);
2614       aarch64_set_vec_u32 (cpu, vd, index,
2615                            aarch64_get_reg_u32 (cpu, rs, NO_SP));
2616     }
2617   else if (uimm (aarch64_get_instr (cpu), 19, 19))
2618     {
2619       index = uimm (aarch64_get_instr (cpu), 20, 20);
2620       aarch64_set_vec_u64 (cpu, vd, index,
2621                            aarch64_get_reg_u64 (cpu, rs, NO_SP));
2622     }
2623   else
2624     HALT_NYI;
2625 }
2626
2627 static void
2628 do_vec_DUP_vector_into_vector (sim_cpu *cpu)
2629 {
2630   /* instr[31]    = 0
2631      instr[30]    = half(0)/full(1)
2632      instr[29,21] = 00 1110 000
2633      instr[20,16] = element size and index
2634      instr[15,10] = 0000 01
2635      instr[9,5]   = V source
2636      instr[4,0]   = V dest.  */
2637
2638   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
2639   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
2640   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2641   int i, index;
2642
2643   NYI_assert (29, 21, 0x070);
2644   NYI_assert (15, 10, 0x01);
2645
2646   if (uimm (aarch64_get_instr (cpu), 16, 16))
2647     {
2648       index = uimm (aarch64_get_instr (cpu), 20, 17);
2649
2650       for (i = 0; i < (full ? 16 : 8); i++)
2651         aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vs, index));
2652     }
2653   else if (uimm (aarch64_get_instr (cpu), 17, 17))
2654     {
2655       index = uimm (aarch64_get_instr (cpu), 20, 18);
2656
2657       for (i = 0; i < (full ? 8 : 4); i++)
2658         aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vs, index));
2659     }
2660   else if (uimm (aarch64_get_instr (cpu), 18, 18))
2661     {
2662       index = uimm (aarch64_get_instr (cpu), 20, 19);
2663
2664       for (i = 0; i < (full ? 4 : 2); i++)
2665         aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vs, index));
2666     }
2667   else
2668     {
2669       if (uimm (aarch64_get_instr (cpu), 19, 19) == 0)
2670         HALT_UNALLOC;
2671
2672       if (! full)
2673         HALT_UNALLOC;
2674
2675       index = uimm (aarch64_get_instr (cpu), 20, 20);
2676
2677       for (i = 0; i < 2; i++)
2678         aarch64_set_vec_u64 (cpu, vd, i, aarch64_get_vec_u64 (cpu, vs, index));
2679     }
2680 }
2681
2682 static void
2683 do_vec_TBL (sim_cpu *cpu)
2684 {
2685   /* instr[31]    = 0
2686      instr[30]    = half(0)/full(1)
2687      instr[29,21] = 00 1110 000
2688      instr[20,16] = Vm
2689      instr[15]    = 0
2690      instr[14,13] = vec length
2691      instr[12,10] = 000
2692      instr[9,5]   = V start
2693      instr[4,0]   = V dest  */
2694
2695   int full    = uimm (aarch64_get_instr (cpu), 30, 30);
2696   int len     = uimm (aarch64_get_instr (cpu), 14, 13) + 1;
2697   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2698   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2699   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2700   unsigned i;
2701
2702   NYI_assert (29, 21, 0x070);
2703   NYI_assert (12, 10, 0);
2704
2705   for (i = 0; i < (full ? 16 : 8); i++)
2706     {
2707       unsigned int selector = aarch64_get_vec_u8 (cpu, vm, i);
2708       uint8_t val;
2709
2710       if (selector < 16)
2711         val = aarch64_get_vec_u8 (cpu, vn, selector);
2712       else if (selector < 32)
2713         val = len < 2 ? 0 : aarch64_get_vec_u8 (cpu, vn + 1, selector - 16);
2714       else if (selector < 48)
2715         val = len < 3 ? 0 : aarch64_get_vec_u8 (cpu, vn + 2, selector - 32);
2716       else if (selector < 64)
2717         val = len < 4 ? 0 : aarch64_get_vec_u8 (cpu, vn + 3, selector - 48);
2718       else
2719         val = 0;
2720
2721       aarch64_set_vec_u8 (cpu, vd, i, val);
2722     }
2723 }
2724
2725 static void
2726 do_vec_TRN (sim_cpu *cpu)
2727 {
2728   /* instr[31]    = 0
2729      instr[30]    = half(0)/full(1)
2730      instr[29,24] = 00 1110
2731      instr[23,22] = size
2732      instr[21]    = 0
2733      instr[20,16] = Vm
2734      instr[15]    = 0
2735      instr[14]    = TRN1 (0) / TRN2 (1)
2736      instr[13,10] = 1010
2737      instr[9,5]   = V source
2738      instr[4,0]   = V dest.  */
2739
2740   int full    = uimm (aarch64_get_instr (cpu), 30, 30);
2741   int second  = uimm (aarch64_get_instr (cpu), 14, 14);
2742   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2743   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2744   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2745   unsigned i;
2746
2747   NYI_assert (29, 24, 0x0E);
2748   NYI_assert (13, 10, 0xA);
2749
2750   switch (uimm (aarch64_get_instr (cpu), 23, 22))
2751     {
2752     case 0:
2753       for (i = 0; i < (full ? 8 : 4); i++)
2754         {
2755           aarch64_set_vec_u8
2756             (cpu, vd, i * 2,
2757              aarch64_get_vec_u8 (cpu, second ? vm : vn, i * 2));
2758           aarch64_set_vec_u8
2759             (cpu, vd, 1 * 2 + 1,
2760              aarch64_get_vec_u8 (cpu, second ? vn : vm, i * 2 + 1));
2761         }
2762       break;
2763
2764     case 1:
2765       for (i = 0; i < (full ? 4 : 2); i++)
2766         {
2767           aarch64_set_vec_u16
2768             (cpu, vd, i * 2,
2769              aarch64_get_vec_u16 (cpu, second ? vm : vn, i * 2));
2770           aarch64_set_vec_u16
2771             (cpu, vd, 1 * 2 + 1,
2772              aarch64_get_vec_u16 (cpu, second ? vn : vm, i * 2 + 1));
2773         }
2774       break;
2775
2776     case 2:
2777       aarch64_set_vec_u32
2778         (cpu, vd, 0, aarch64_get_vec_u32 (cpu, second ? vm : vn, 0));
2779       aarch64_set_vec_u32
2780         (cpu, vd, 1, aarch64_get_vec_u32 (cpu, second ? vn : vm, 1));
2781       aarch64_set_vec_u32
2782         (cpu, vd, 2, aarch64_get_vec_u32 (cpu, second ? vm : vn, 2));
2783       aarch64_set_vec_u32
2784         (cpu, vd, 3, aarch64_get_vec_u32 (cpu, second ? vn : vm, 3));
2785       break;
2786
2787     case 3:
2788       if (! full)
2789         HALT_UNALLOC;
2790
2791       aarch64_set_vec_u64 (cpu, vd, 0,
2792                            aarch64_get_vec_u64 (cpu, second ? vm : vn, 0));
2793       aarch64_set_vec_u64 (cpu, vd, 1,
2794                            aarch64_get_vec_u64 (cpu, second ? vn : vm, 1));
2795       break;
2796
2797     default:
2798       HALT_UNALLOC;
2799     }
2800 }
2801
2802 static void
2803 do_vec_DUP_scalar_into_vector (sim_cpu *cpu)
2804 {
2805   /* instr[31]    = 0
2806      instr[30]    = 0=> zero top 64-bits, 1=> duplicate into top 64-bits
2807                     [must be 1 for 64-bit xfer]
2808      instr[29,20] = 00 1110 0000
2809      instr[19,16] = element size: 0001=> 8-bits, 0010=> 16-bits,
2810                                   0100=> 32-bits. 1000=>64-bits
2811      instr[15,10] = 0000 11
2812      instr[9,5]   = W source
2813      instr[4,0]   = V dest.  */
2814
2815   unsigned i;
2816   unsigned Vd = uimm (aarch64_get_instr (cpu), 4, 0);
2817   unsigned Rs = uimm (aarch64_get_instr (cpu), 9, 5);
2818   int both    = uimm (aarch64_get_instr (cpu), 30, 30);
2819
2820   NYI_assert (29, 20, 0x0E0);
2821   NYI_assert (15, 10, 0x03);
2822
2823   switch (uimm (aarch64_get_instr (cpu), 19, 16))
2824     {
2825     case 1:
2826       for (i = 0; i < (both ? 16 : 8); i++)
2827         aarch64_set_vec_u8 (cpu, Vd, i, aarch64_get_reg_u8 (cpu, Rs, NO_SP));
2828       break;
2829
2830     case 2:
2831       for (i = 0; i < (both ? 8 : 4); i++)
2832         aarch64_set_vec_u16 (cpu, Vd, i, aarch64_get_reg_u16 (cpu, Rs, NO_SP));
2833       break;
2834
2835     case 4:
2836       for (i = 0; i < (both ? 4 : 2); i++)
2837         aarch64_set_vec_u32 (cpu, Vd, i, aarch64_get_reg_u32 (cpu, Rs, NO_SP));
2838       break;
2839
2840     case 8:
2841       if (!both)
2842         HALT_NYI;
2843       aarch64_set_vec_u64 (cpu, Vd, 0, aarch64_get_reg_u64 (cpu, Rs, NO_SP));
2844       aarch64_set_vec_u64 (cpu, Vd, 1, aarch64_get_reg_u64 (cpu, Rs, NO_SP));
2845       break;
2846
2847     default:
2848       HALT_NYI;
2849     }
2850 }
2851
2852 static void
2853 do_vec_UZP (sim_cpu *cpu)
2854 {
2855   /* instr[31]    = 0
2856      instr[30]    = half(0)/full(1)
2857      instr[29,24] = 00 1110
2858      instr[23,22] = size: byte(00), half(01), word (10), long (11)
2859      instr[21]    = 0
2860      instr[20,16] = Vm
2861      instr[15]    = 0
2862      instr[14]    = lower (0) / upper (1)
2863      instr[13,10] = 0110
2864      instr[9,5]   = Vn
2865      instr[4,0]   = Vd.  */
2866
2867   int full = uimm (aarch64_get_instr (cpu), 30, 30);
2868   int upper = uimm (aarch64_get_instr (cpu), 14, 14);
2869
2870   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2871   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2872   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2873
2874   uint64_t val_m1 = aarch64_get_vec_u64 (cpu, vm, 0);
2875   uint64_t val_m2 = aarch64_get_vec_u64 (cpu, vm, 1);
2876   uint64_t val_n1 = aarch64_get_vec_u64 (cpu, vn, 0);
2877   uint64_t val_n2 = aarch64_get_vec_u64 (cpu, vn, 1);
2878
2879   uint64_t val1 = 0;
2880   uint64_t val2 = 0;
2881
2882   uint64_t input1 = upper ? val_n1 : val_m1;
2883   uint64_t input2 = upper ? val_n2 : val_m2;
2884   unsigned i;
2885
2886   NYI_assert (29, 24, 0x0E);
2887   NYI_assert (21, 21, 0);
2888   NYI_assert (15, 15, 0);
2889   NYI_assert (13, 10, 6);
2890
2891   switch (uimm (aarch64_get_instr (cpu), 23, 23))
2892     {
2893     case 0:
2894       for (i = 0; i < 8; i++)
2895         {
2896           val1 |= (input1 >> (i * 8)) & (0xFFULL << (i * 8));
2897           val2 |= (input2 >> (i * 8)) & (0xFFULL << (i * 8));
2898         }
2899       break;
2900
2901     case 1:
2902       for (i = 0; i < 4; i++)
2903         {
2904           val1 |= (input1 >> (i * 16)) & (0xFFFFULL << (i * 16));
2905           val2 |= (input2 >> (i * 16)) & (0xFFFFULL << (i * 16));
2906         }
2907       break;
2908
2909     case 2:
2910       val1 = ((input1 & 0xFFFFFFFF) | ((input1 >> 32) & 0xFFFFFFFF00000000ULL));
2911       val2 = ((input2 & 0xFFFFFFFF) | ((input2 >> 32) & 0xFFFFFFFF00000000ULL));
2912
2913     case 3:
2914       val1 = input1;
2915       val2 = input2;
2916            break;
2917     }
2918
2919   aarch64_set_vec_u64 (cpu, vd, 0, val1);
2920   if (full)
2921     aarch64_set_vec_u64 (cpu, vd, 1, val2);
2922 }
2923
2924 static void
2925 do_vec_ZIP (sim_cpu *cpu)
2926 {
2927   /* instr[31]    = 0
2928      instr[30]    = half(0)/full(1)
2929      instr[29,24] = 00 1110
2930      instr[23,22] = size: byte(00), hald(01), word (10), long (11)
2931      instr[21]    = 0
2932      instr[20,16] = Vm
2933      instr[15]    = 0
2934      instr[14]    = lower (0) / upper (1)
2935      instr[13,10] = 1110
2936      instr[9,5]   = Vn
2937      instr[4,0]   = Vd.  */
2938
2939   int full = uimm (aarch64_get_instr (cpu), 30, 30);
2940   int upper = uimm (aarch64_get_instr (cpu), 14, 14);
2941
2942   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2943   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2944   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2945
2946   uint64_t val_m1 = aarch64_get_vec_u64 (cpu, vm, 0);
2947   uint64_t val_m2 = aarch64_get_vec_u64 (cpu, vm, 1);
2948   uint64_t val_n1 = aarch64_get_vec_u64 (cpu, vn, 0);
2949   uint64_t val_n2 = aarch64_get_vec_u64 (cpu, vn, 1);
2950
2951   uint64_t val1 = 0;
2952   uint64_t val2 = 0;
2953
2954   uint64_t input1 = upper ? val_n1 : val_m1;
2955   uint64_t input2 = upper ? val_n2 : val_m2;
2956
2957   NYI_assert (29, 24, 0x0E);
2958   NYI_assert (21, 21, 0);
2959   NYI_assert (15, 15, 0);
2960   NYI_assert (13, 10, 0xE);
2961
2962   switch (uimm (aarch64_get_instr (cpu), 23, 23))
2963     {
2964     case 0:
2965       val1 =
2966           ((input1 <<  0) & (0xFF    <<  0))
2967         | ((input2 <<  8) & (0xFF    <<  8))
2968         | ((input1 <<  8) & (0xFF    << 16))
2969         | ((input2 << 16) & (0xFF    << 24))
2970         | ((input1 << 16) & (0xFFULL << 32))
2971         | ((input2 << 24) & (0xFFULL << 40))
2972         | ((input1 << 24) & (0xFFULL << 48))
2973         | ((input2 << 32) & (0xFFULL << 56));
2974
2975       val2 =
2976           ((input1 >> 32) & (0xFF    <<  0))
2977         | ((input2 >> 24) & (0xFF    <<  8))
2978         | ((input1 >> 24) & (0xFF    << 16))
2979         | ((input2 >> 16) & (0xFF    << 24))
2980         | ((input1 >> 16) & (0xFFULL << 32))
2981         | ((input2 >>  8) & (0xFFULL << 40))
2982         | ((input1 >>  8) & (0xFFULL << 48))
2983         | ((input2 >>  0) & (0xFFULL << 56));
2984       break;
2985
2986     case 1:
2987       val1 =
2988           ((input1 <<  0) & (0xFFFF    <<  0))
2989         | ((input2 << 16) & (0xFFFF    << 16))
2990         | ((input1 << 16) & (0xFFFFULL << 32))
2991         | ((input2 << 32) & (0xFFFFULL << 48));
2992
2993       val2 =
2994           ((input1 >> 32) & (0xFFFF    <<  0))
2995         | ((input2 >> 16) & (0xFFFF    << 16))
2996         | ((input1 >> 16) & (0xFFFFULL << 32))
2997         | ((input2 >>  0) & (0xFFFFULL << 48));
2998       break;
2999
3000     case 2:
3001       val1 = (input1 & 0xFFFFFFFFULL) | (input2 << 32);
3002       val2 = (input2 & 0xFFFFFFFFULL) | (input1 << 32);
3003       break;
3004
3005     case 3:
3006       val1 = input1;
3007       val2 = input2;
3008       break;
3009     }
3010
3011   aarch64_set_vec_u64 (cpu, vd, 0, val1);
3012   if (full)
3013     aarch64_set_vec_u64 (cpu, vd, 1, val2);
3014 }
3015
3016 /* Floating point immediates are encoded in 8 bits.
3017    fpimm[7] = sign bit.
3018    fpimm[6:4] = signed exponent.
3019    fpimm[3:0] = fraction (assuming leading 1).
3020    i.e. F = s * 1.f * 2^(e - b).  */
3021
3022 static float
3023 fp_immediate_for_encoding_32 (uint32_t imm8)
3024 {
3025   float u;
3026   uint32_t s, e, f, i;
3027
3028   s = (imm8 >> 7) & 0x1;
3029   e = (imm8 >> 4) & 0x7;
3030   f = imm8 & 0xf;
3031
3032   /* The fp value is s * n/16 * 2r where n is 16+e.  */
3033   u = (16.0 + f) / 16.0;
3034
3035   /* N.B. exponent is signed.  */
3036   if (e < 4)
3037     {
3038       int epos = e;
3039
3040       for (i = 0; i <= epos; i++)
3041         u *= 2.0;
3042     }
3043   else
3044     {
3045       int eneg = 7 - e;
3046
3047       for (i = 0; i < eneg; i++)
3048         u /= 2.0;
3049     }
3050
3051   if (s)
3052     u = - u;
3053
3054   return u;
3055 }
3056
3057 static double
3058 fp_immediate_for_encoding_64 (uint32_t imm8)
3059 {
3060   double u;
3061   uint32_t s, e, f, i;
3062
3063   s = (imm8 >> 7) & 0x1;
3064   e = (imm8 >> 4) & 0x7;
3065   f = imm8 & 0xf;
3066
3067   /* The fp value is s * n/16 * 2r where n is 16+e.  */
3068   u = (16.0 + f) / 16.0;
3069
3070   /* N.B. exponent is signed.  */
3071   if (e < 4)
3072     {
3073       int epos = e;
3074
3075       for (i = 0; i <= epos; i++)
3076         u *= 2.0;
3077     }
3078   else
3079     {
3080       int eneg = 7 - e;
3081
3082       for (i = 0; i < eneg; i++)
3083         u /= 2.0;
3084     }
3085
3086   if (s)
3087     u = - u;
3088
3089   return u;
3090 }
3091
3092 static void
3093 do_vec_MOV_immediate (sim_cpu *cpu)
3094 {
3095   /* instr[31]    = 0
3096      instr[30]    = full/half selector
3097      instr[29,19] = 00111100000
3098      instr[18,16] = high 3 bits of uimm8
3099      instr[15,12] = size & shift:
3100                                   0000 => 32-bit
3101                                   0010 => 32-bit + LSL#8
3102                                   0100 => 32-bit + LSL#16
3103                                   0110 => 32-bit + LSL#24
3104                                   1010 => 16-bit + LSL#8
3105                                   1000 => 16-bit
3106                                   1101 => 32-bit + MSL#16
3107                                   1100 => 32-bit + MSL#8
3108                                   1110 => 8-bit
3109                                   1111 => double
3110      instr[11,10] = 01
3111      instr[9,5]   = low 5-bits of uimm8
3112      instr[4,0]   = Vd.  */
3113
3114   int full     = uimm (aarch64_get_instr (cpu), 30, 30);
3115   unsigned vd  = uimm (aarch64_get_instr (cpu), 4, 0);
3116   unsigned val = uimm (aarch64_get_instr (cpu), 18, 16) << 5
3117     | uimm (aarch64_get_instr (cpu), 9, 5);
3118   unsigned i;
3119
3120   NYI_assert (29, 19, 0x1E0);
3121   NYI_assert (11, 10, 1);
3122
3123   switch (uimm (aarch64_get_instr (cpu), 15, 12))
3124     {
3125     case 0x0: /* 32-bit, no shift.  */
3126     case 0x2: /* 32-bit, shift by 8.  */
3127     case 0x4: /* 32-bit, shift by 16.  */
3128     case 0x6: /* 32-bit, shift by 24.  */
3129       val <<= (8 * uimm (aarch64_get_instr (cpu), 14, 13));
3130       for (i = 0; i < (full ? 4 : 2); i++)
3131         aarch64_set_vec_u32 (cpu, vd, i, val);
3132       break;
3133
3134     case 0xa: /* 16-bit, shift by 8.  */
3135       val <<= 8;
3136       /* Fall through.  */
3137     case 0x8: /* 16-bit, no shift.  */
3138       for (i = 0; i < (full ? 8 : 4); i++)
3139         aarch64_set_vec_u16 (cpu, vd, i, val);
3140       /* Fall through.  */
3141     case 0xd: /* 32-bit, mask shift by 16.  */
3142       val <<= 8;
3143       val |= 0xFF;
3144       /* Fall through.  */
3145     case 0xc: /* 32-bit, mask shift by 8. */
3146       val <<= 8;
3147       val |= 0xFF;
3148       for (i = 0; i < (full ? 4 : 2); i++)
3149         aarch64_set_vec_u32 (cpu, vd, i, val);
3150       break;
3151
3152     case 0xe: /* 8-bit, no shift.  */
3153       for (i = 0; i < (full ? 16 : 8); i++)
3154         aarch64_set_vec_u8 (cpu, vd, i, val);
3155       break;
3156
3157     case 0xf: /* FMOV Vs.{2|4}S, #fpimm.  */
3158       {
3159         float u = fp_immediate_for_encoding_32 (val);
3160         for (i = 0; i < (full ? 4 : 2); i++)
3161           aarch64_set_vec_float (cpu, vd, i, u);
3162         break;
3163       }
3164
3165     default:
3166       HALT_NYI;
3167     }
3168 }
3169
3170 static void
3171 do_vec_MVNI (sim_cpu *cpu)
3172 {
3173   /* instr[31]    = 0
3174      instr[30]    = full/half selector
3175      instr[29,19] = 10111100000
3176      instr[18,16] = high 3 bits of uimm8
3177      instr[15,12] = selector
3178      instr[11,10] = 01
3179      instr[9,5]   = low 5-bits of uimm8
3180      instr[4,0]   = Vd.  */
3181
3182   int full     = uimm (aarch64_get_instr (cpu), 30, 30);
3183   unsigned vd  = uimm (aarch64_get_instr (cpu), 4, 0);
3184   unsigned val = uimm (aarch64_get_instr (cpu), 18, 16) << 5
3185     | uimm (aarch64_get_instr (cpu), 9, 5);
3186   unsigned i;
3187
3188   NYI_assert (29, 19, 0x5E0);
3189   NYI_assert (11, 10, 1);
3190
3191   switch (uimm (aarch64_get_instr (cpu), 15, 12))
3192     {
3193     case 0x0: /* 32-bit, no shift.  */
3194     case 0x2: /* 32-bit, shift by 8.  */
3195     case 0x4: /* 32-bit, shift by 16.  */
3196     case 0x6: /* 32-bit, shift by 24.  */
3197       val <<= (8 * uimm (aarch64_get_instr (cpu), 14, 13));
3198       val = ~ val;
3199       for (i = 0; i < (full ? 4 : 2); i++)
3200         aarch64_set_vec_u32 (cpu, vd, i, val);
3201       return;
3202
3203     case 0xa: /* 16-bit, 8 bit shift. */
3204       val <<= 8;
3205     case 0x8: /* 16-bit, no shift. */
3206       val = ~ val;
3207       for (i = 0; i < (full ? 8 : 4); i++)
3208         aarch64_set_vec_u16 (cpu, vd, i, val);
3209       return;
3210
3211     case 0xd: /* 32-bit, mask shift by 16.  */
3212       val <<= 8;
3213       val |= 0xFF;
3214     case 0xc: /* 32-bit, mask shift by 8. */
3215       val <<= 8;
3216       val |= 0xFF;
3217       val = ~ val;
3218       for (i = 0; i < (full ? 4 : 2); i++)
3219         aarch64_set_vec_u32 (cpu, vd, i, val);
3220       return;
3221
3222     case 0xE: /* MOVI Dn, #mask64 */
3223       {
3224         uint64_t mask = 0;
3225
3226         for (i = 0; i < 8; i++)
3227           if (val & (1 << i))
3228             mask |= (0xF << (i * 4));
3229         aarch64_set_vec_u64 (cpu, vd, 0, mask);
3230         aarch64_set_vec_u64 (cpu, vd, 1, 0);
3231         return;
3232       }
3233
3234     case 0xf: /* FMOV Vd.2D, #fpimm.  */
3235       {
3236         double u = fp_immediate_for_encoding_64 (val);
3237
3238         if (! full)
3239           HALT_UNALLOC;
3240
3241         aarch64_set_vec_double (cpu, vd, 0, u);
3242         aarch64_set_vec_double (cpu, vd, 1, u);
3243         return;
3244       }
3245
3246     default:
3247       HALT_NYI;
3248     }
3249 }
3250
3251 #define ABS(A) ((A) < 0 ? - (A) : (A))
3252
3253 static void
3254 do_vec_ABS (sim_cpu *cpu)
3255 {
3256   /* instr[31]    = 0
3257      instr[30]    = half(0)/full(1)
3258      instr[29,24] = 00 1110
3259      instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3260      instr[21,10] = 10 0000 1011 10
3261      instr[9,5]   = Vn
3262      instr[4.0]   = Vd.  */
3263
3264   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3265   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3266   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
3267   unsigned i;
3268
3269   NYI_assert (29, 24, 0x0E);
3270   NYI_assert (21, 10, 0x82E);
3271
3272   switch (uimm (aarch64_get_instr (cpu), 23, 22))
3273     {
3274     case 0:
3275       for (i = 0; i < (full ? 16 : 8); i++)
3276         aarch64_set_vec_s8 (cpu, vd, i,
3277                             ABS (aarch64_get_vec_s8 (cpu, vn, i)));
3278       break;
3279
3280     case 1:
3281       for (i = 0; i < (full ? 8 : 4); i++)
3282         aarch64_set_vec_s16 (cpu, vd, i,
3283                              ABS (aarch64_get_vec_s16 (cpu, vn, i)));
3284       break;
3285
3286     case 2:
3287       for (i = 0; i < (full ? 4 : 2); i++)
3288         aarch64_set_vec_s32 (cpu, vd, i,
3289                              ABS (aarch64_get_vec_s32 (cpu, vn, i)));
3290       break;
3291
3292     case 3:
3293       if (! full)
3294         HALT_NYI;
3295       for (i = 0; i < 2; i++)
3296         aarch64_set_vec_s64 (cpu, vd, i,
3297                              ABS (aarch64_get_vec_s64 (cpu, vn, i)));
3298       break;
3299     }
3300 }
3301
3302 static void
3303 do_vec_ADDV (sim_cpu *cpu)
3304 {
3305   /* instr[31]    = 0
3306      instr[30]    = full/half selector
3307      instr[29,24] = 00 1110
3308      instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3309      instr[21,10] = 11 0001 1011 10
3310      instr[9,5]   = Vm
3311      instr[4.0]   = Rd.  */
3312
3313   unsigned vm = uimm (aarch64_get_instr (cpu), 9, 5);
3314   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
3315   unsigned i;
3316   uint64_t val = 0;
3317   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3318
3319   NYI_assert (29, 24, 0x0E);
3320   NYI_assert (21, 10, 0xC6E);
3321
3322   switch (uimm (aarch64_get_instr (cpu), 23, 22))
3323     {
3324     case 0:
3325       for (i = 0; i < (full ? 16 : 8); i++)
3326         val += aarch64_get_vec_u8 (cpu, vm, i);
3327       aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3328       return;
3329
3330     case 1:
3331       for (i = 0; i < (full ? 8 : 4); i++)
3332         val += aarch64_get_vec_u16 (cpu, vm, i);
3333       aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3334       return;
3335
3336     case 2:
3337       for (i = 0; i < (full ? 4 : 2); i++)
3338         val += aarch64_get_vec_u32 (cpu, vm, i);
3339       aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3340       return;
3341
3342     case 3:
3343       if (! full)
3344         HALT_UNALLOC;
3345       val = aarch64_get_vec_u64 (cpu, vm, 0);
3346       val += aarch64_get_vec_u64 (cpu, vm, 1);
3347       aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3348       return;
3349
3350     default:
3351       HALT_UNREACHABLE;
3352     }
3353 }
3354
3355 static void
3356 do_vec_ins_2 (sim_cpu *cpu)
3357 {
3358   /* instr[31,21] = 01001110000
3359      instr[20,18] = size & element selector
3360      instr[17,14] = 0000
3361      instr[13]    = direction: to vec(0), from vec (1)
3362      instr[12,10] = 111
3363      instr[9,5]   = Vm
3364      instr[4,0]   = Vd.  */
3365
3366   unsigned elem;
3367   unsigned vm = uimm (aarch64_get_instr (cpu), 9, 5);
3368   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3369
3370   NYI_assert (31, 21, 0x270);
3371   NYI_assert (17, 14, 0);
3372   NYI_assert (12, 10, 7);
3373
3374   if (uimm (aarch64_get_instr (cpu), 13, 13) == 1)
3375     {
3376       if (uimm (aarch64_get_instr (cpu), 18, 18) == 1)
3377         {
3378           /* 32-bit moves.  */
3379           elem = uimm (aarch64_get_instr (cpu), 20, 19);
3380           aarch64_set_reg_u64 (cpu, vd, NO_SP,
3381                                aarch64_get_vec_u32 (cpu, vm, elem));
3382         }
3383       else
3384         {
3385           /* 64-bit moves.  */
3386           if (uimm (aarch64_get_instr (cpu), 19, 19) != 1)
3387             HALT_NYI;
3388
3389           elem = uimm (aarch64_get_instr (cpu), 20, 20);
3390           aarch64_set_reg_u64 (cpu, vd, NO_SP,
3391                                aarch64_get_vec_u64 (cpu, vm, elem));
3392         }
3393     }
3394   else
3395     {
3396       if (uimm (aarch64_get_instr (cpu), 18, 18) == 1)
3397         {
3398           /* 32-bit moves.  */
3399           elem = uimm (aarch64_get_instr (cpu), 20, 19);
3400           aarch64_set_vec_u32 (cpu, vd, elem,
3401                                aarch64_get_reg_u32 (cpu, vm, NO_SP));
3402         }
3403       else
3404         {
3405           /* 64-bit moves.  */
3406           if (uimm (aarch64_get_instr (cpu), 19, 19) != 1)
3407             HALT_NYI;
3408
3409           elem = uimm (aarch64_get_instr (cpu), 20, 20);
3410           aarch64_set_vec_u64 (cpu, vd, elem,
3411                                aarch64_get_reg_u64 (cpu, vm, NO_SP));
3412         }
3413     }
3414 }
3415
3416 static void
3417 do_vec_mull (sim_cpu *cpu)
3418 {
3419   /* instr[31]    = 0
3420      instr[30]    = lower(0)/upper(1) selector
3421      instr[29]    = signed(0)/unsigned(1)
3422      instr[28,24] = 0 1110
3423      instr[23,22] = size: 8-bit (00), 16-bit (01), 32-bit (10)
3424      instr[21]    = 1
3425      instr[20,16] = Vm
3426      instr[15,10] = 11 0000
3427      instr[9,5]   = Vn
3428      instr[4.0]   = Vd.  */
3429
3430   int    unsign = uimm (aarch64_get_instr (cpu), 29, 29);
3431   int    bias = uimm (aarch64_get_instr (cpu), 30, 30);
3432   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3433   unsigned vn = uimm (aarch64_get_instr (cpu),  9,  5);
3434   unsigned vd = uimm (aarch64_get_instr (cpu),  4,  0);
3435   unsigned i;
3436
3437   NYI_assert (28, 24, 0x0E);
3438   NYI_assert (15, 10, 0x30);
3439
3440   switch (uimm (aarch64_get_instr (cpu), 23, 22))
3441     {
3442     case 0:
3443       if (bias)
3444         bias = 8;
3445       if (unsign)
3446         for (i = 0; i < 8; i++)
3447           aarch64_set_vec_u16 (cpu, vd, i,
3448                                aarch64_get_vec_u8 (cpu, vn, i + bias)
3449                                * aarch64_get_vec_u8 (cpu, vm, i + bias));
3450       else
3451         for (i = 0; i < 8; i++)
3452           aarch64_set_vec_s16 (cpu, vd, i,
3453                                aarch64_get_vec_s8 (cpu, vn, i + bias)
3454                                * aarch64_get_vec_s8 (cpu, vm, i + bias));
3455       return;
3456
3457     case 1:
3458       if (bias)
3459         bias = 4;
3460       if (unsign)
3461         for (i = 0; i < 4; i++)
3462           aarch64_set_vec_u32 (cpu, vd, i,
3463                                aarch64_get_vec_u16 (cpu, vn, i + bias)
3464                                * aarch64_get_vec_u16 (cpu, vm, i + bias));
3465       else
3466         for (i = 0; i < 4; i++)
3467           aarch64_set_vec_s32 (cpu, vd, i,
3468                                aarch64_get_vec_s16 (cpu, vn, i + bias)
3469                                * aarch64_get_vec_s16 (cpu, vm, i + bias));
3470       return;
3471
3472     case 2:
3473       if (bias)
3474         bias = 2;
3475       if (unsign)
3476         for (i = 0; i < 2; i++)
3477           aarch64_set_vec_u64 (cpu, vd, i,
3478                                (uint64_t) aarch64_get_vec_u32 (cpu, vn,
3479                                                                i + bias)
3480                                * (uint64_t) aarch64_get_vec_u32 (cpu, vm,
3481                                                                  i + bias));
3482       else
3483         for (i = 0; i < 2; i++)
3484           aarch64_set_vec_s64 (cpu, vd, i,
3485                                aarch64_get_vec_s32 (cpu, vn, i + bias)
3486                                * aarch64_get_vec_s32 (cpu, vm, i + bias));
3487       return;
3488
3489     case 3:
3490     default:
3491       HALT_NYI;
3492     }
3493 }
3494
3495 static void
3496 do_vec_fadd (sim_cpu *cpu)
3497 {
3498   /* instr[31]    = 0
3499      instr[30]    = half(0)/full(1)
3500      instr[29,24] = 001110
3501      instr[23]    = FADD(0)/FSUB(1)
3502      instr[22]    = float (0)/double(1)
3503      instr[21]    = 1
3504      instr[20,16] = Vm
3505      instr[15,10] = 110101
3506      instr[9,5]   = Vn
3507      instr[4.0]   = Vd.  */
3508
3509   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3510   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3511   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3512   unsigned i;
3513   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3514
3515   NYI_assert (29, 24, 0x0E);
3516   NYI_assert (21, 21, 1);
3517   NYI_assert (15, 10, 0x35);
3518
3519   if (uimm (aarch64_get_instr (cpu), 23, 23))
3520     {
3521       if (uimm (aarch64_get_instr (cpu), 22, 22))
3522         {
3523           if (! full)
3524             HALT_NYI;
3525
3526           for (i = 0; i < 2; i++)
3527             aarch64_set_vec_double (cpu, vd, i,
3528                                     aarch64_get_vec_double (cpu, vn, i)
3529                                     - aarch64_get_vec_double (cpu, vm, i));
3530         }
3531       else
3532         {
3533           for (i = 0; i < (full ? 4 : 2); i++)
3534             aarch64_set_vec_float (cpu, vd, i,
3535                                    aarch64_get_vec_float (cpu, vn, i)
3536                                    - aarch64_get_vec_float (cpu, vm, i));
3537         }
3538     }
3539   else
3540     {
3541       if (uimm (aarch64_get_instr (cpu), 22, 22))
3542         {
3543           if (! full)
3544             HALT_NYI;
3545
3546           for (i = 0; i < 2; i++)
3547             aarch64_set_vec_double (cpu, vd, i,
3548                                     aarch64_get_vec_double (cpu, vm, i)
3549                                     + aarch64_get_vec_double (cpu, vn, i));
3550         }
3551       else
3552         {
3553           for (i = 0; i < (full ? 4 : 2); i++)
3554             aarch64_set_vec_float (cpu, vd, i,
3555                                    aarch64_get_vec_float (cpu, vm, i)
3556                                    + aarch64_get_vec_float (cpu, vn, i));
3557         }
3558     }
3559 }
3560
3561 static void
3562 do_vec_add (sim_cpu *cpu)
3563 {
3564   /* instr[31]    = 0
3565      instr[30]    = full/half selector
3566      instr[29,24] = 001110
3567      instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3568      instr[21]    = 1
3569      instr[20,16] = Vn
3570      instr[15,10] = 100001
3571      instr[9,5]   = Vm
3572      instr[4.0]   = Vd.  */
3573
3574   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3575   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3576   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3577   unsigned i;
3578   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3579
3580   NYI_assert (29, 24, 0x0E);
3581   NYI_assert (21, 21, 1);
3582   NYI_assert (15, 10, 0x21);
3583
3584   switch (uimm (aarch64_get_instr (cpu), 23, 22))
3585     {
3586     case 0:
3587       for (i = 0; i < (full ? 16 : 8); i++)
3588         aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vn, i)
3589                             + aarch64_get_vec_u8 (cpu, vm, i));
3590       return;
3591
3592     case 1:
3593       for (i = 0; i < (full ? 8 : 4); i++)
3594         aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vn, i)
3595                              + aarch64_get_vec_u16 (cpu, vm, i));
3596       return;
3597
3598     case 2:
3599       for (i = 0; i < (full ? 4 : 2); i++)
3600         aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vn, i)
3601                              + aarch64_get_vec_u32 (cpu, vm, i));
3602       return;
3603
3604     case 3:
3605       if (! full)
3606         HALT_UNALLOC;
3607       aarch64_set_vec_u64 (cpu, vd, 0, aarch64_get_vec_u64 (cpu, vn, 0)
3608                            + aarch64_get_vec_u64 (cpu, vm, 0));
3609       aarch64_set_vec_u64 (cpu, vd, 1,
3610                            aarch64_get_vec_u64 (cpu, vn, 1)
3611                            + aarch64_get_vec_u64 (cpu, vm, 1));
3612       return;
3613
3614     default:
3615       HALT_UNREACHABLE;
3616     }
3617 }
3618
3619 static void
3620 do_vec_mul (sim_cpu *cpu)
3621 {
3622   /* instr[31]    = 0
3623      instr[30]    = full/half selector
3624      instr[29,24] = 00 1110
3625      instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3626      instr[21]    = 1
3627      instr[20,16] = Vn
3628      instr[15,10] = 10 0111
3629      instr[9,5]   = Vm
3630      instr[4.0]   = Vd.  */
3631
3632   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3633   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3634   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3635   unsigned i;
3636   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3637
3638   NYI_assert (29, 24, 0x0E);
3639   NYI_assert (21, 21, 1);
3640   NYI_assert (15, 10, 0x27);
3641
3642   switch (uimm (aarch64_get_instr (cpu), 23, 22))
3643     {
3644     case 0:
3645       for (i = 0; i < (full ? 16 : 8); i++)
3646         {
3647           uint16_t val = aarch64_get_vec_u8 (cpu, vn, i);
3648           val *= aarch64_get_vec_u8 (cpu, vm, i);
3649
3650           aarch64_set_vec_u16 (cpu, vd, i, val);
3651         }
3652       return;
3653
3654     case 1:
3655       for (i = 0; i < (full ? 8 : 4); i++)
3656         {
3657           uint32_t val = aarch64_get_vec_u16 (cpu, vn, i);
3658           val *= aarch64_get_vec_u16 (cpu, vm, i);
3659
3660           aarch64_set_vec_u32 (cpu, vd, i, val);
3661         }
3662       return;
3663
3664     case 2:
3665       for (i = 0; i < (full ? 4 : 2); i++)
3666         {
3667           uint64_t val = aarch64_get_vec_u32 (cpu, vn, i);
3668           val *= aarch64_get_vec_u32 (cpu, vm, i);
3669
3670           aarch64_set_vec_u64 (cpu, vd, i, val);
3671         }
3672       return;
3673
3674     default:
3675     case 3:
3676       HALT_UNALLOC;
3677     }
3678 }
3679
3680 static void
3681 do_vec_MLA (sim_cpu *cpu)
3682 {
3683   /* instr[31]    = 0
3684      instr[30]    = full/half selector
3685      instr[29,24] = 00 1110
3686      instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3687      instr[21]    = 1
3688      instr[20,16] = Vn
3689      instr[15,10] = 1001 01
3690      instr[9,5]   = Vm
3691      instr[4.0]   = Vd.  */
3692
3693   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3694   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3695   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3696   unsigned i;
3697   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3698
3699   NYI_assert (29, 24, 0x0E);
3700   NYI_assert (21, 21, 1);
3701   NYI_assert (15, 10, 0x25);
3702
3703   switch (uimm (aarch64_get_instr (cpu), 23, 22))
3704     {
3705     case 0:
3706       for (i = 0; i < (full ? 16 : 8); i++)
3707         {
3708           uint16_t val = aarch64_get_vec_u8 (cpu, vn, i);
3709           val *= aarch64_get_vec_u8 (cpu, vm, i);
3710           val += aarch64_get_vec_u8 (cpu, vd, i);
3711
3712           aarch64_set_vec_u16 (cpu, vd, i, val);
3713         }
3714       return;
3715
3716     case 1:
3717       for (i = 0; i < (full ? 8 : 4); i++)
3718         {
3719           uint32_t val = aarch64_get_vec_u16 (cpu, vn, i);
3720           val *= aarch64_get_vec_u16 (cpu, vm, i);
3721           val += aarch64_get_vec_u16 (cpu, vd, i);
3722
3723           aarch64_set_vec_u32 (cpu, vd, i, val);
3724         }
3725       return;
3726
3727     case 2:
3728       for (i = 0; i < (full ? 4 : 2); i++)
3729         {
3730           uint64_t val = aarch64_get_vec_u32 (cpu, vn, i);
3731           val *= aarch64_get_vec_u32 (cpu, vm, i);
3732           val += aarch64_get_vec_u32 (cpu, vd, i);
3733
3734           aarch64_set_vec_u64 (cpu, vd, i, val);
3735         }
3736       return;
3737
3738     default:
3739     case 3:
3740       HALT_UNALLOC;
3741     }
3742 }
3743
3744 static float
3745 fmaxnm (float a, float b)
3746 {
3747   if (fpclassify (a) == FP_NORMAL)
3748     {
3749       if (fpclassify (b) == FP_NORMAL)
3750         return a > b ? a : b;
3751       return a;
3752     }
3753   else if (fpclassify (b) == FP_NORMAL)
3754     return b;
3755   return a;
3756 }
3757
3758 static float
3759 fminnm (float a, float b)
3760 {
3761   if (fpclassify (a) == FP_NORMAL)
3762     {
3763       if (fpclassify (b) == FP_NORMAL)
3764         return a < b ? a : b;
3765       return a;
3766     }
3767   else if (fpclassify (b) == FP_NORMAL)
3768     return b;
3769   return a;
3770 }
3771
3772 static double
3773 dmaxnm (double a, double b)
3774 {
3775   if (fpclassify (a) == FP_NORMAL)
3776     {
3777       if (fpclassify (b) == FP_NORMAL)
3778         return a > b ? a : b;
3779       return a;
3780     }
3781   else if (fpclassify (b) == FP_NORMAL)
3782     return b;
3783   return a;
3784 }
3785
3786 static double
3787 dminnm (double a, double b)
3788 {
3789   if (fpclassify (a) == FP_NORMAL)
3790     {
3791       if (fpclassify (b) == FP_NORMAL)
3792         return a < b ? a : b;
3793       return a;
3794     }
3795   else if (fpclassify (b) == FP_NORMAL)
3796     return b;
3797   return a;
3798 }
3799
3800 static void
3801 do_vec_FminmaxNMP (sim_cpu *cpu)
3802 {
3803   /* aarch64_get_instr (cpu)[31]    = 0
3804      aarch64_get_instr (cpu)[30]    = half (0)/full (1)
3805      aarch64_get_instr (cpu)[29,24] = 10 1110
3806      aarch64_get_instr (cpu)[23]    = max(0)/min(1)
3807      aarch64_get_instr (cpu)[22]    = float (0)/double (1)
3808      aarch64_get_instr (cpu)[21]    = 1
3809      aarch64_get_instr (cpu)[20,16] = Vn
3810      aarch64_get_instr (cpu)[15,10] = 1100 01
3811      aarch64_get_instr (cpu)[9,5]   = Vm
3812      aarch64_get_instr (cpu)[4.0]   = Vd.  */
3813
3814   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3815   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3816   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3817   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3818
3819   NYI_assert (29, 24, 0x2E);
3820   NYI_assert (21, 21, 1);
3821   NYI_assert (15, 10, 0x31);
3822
3823   if (uimm (aarch64_get_instr (cpu), 22, 22))
3824     {
3825       double (* fn)(double, double) = uimm (aarch64_get_instr (cpu), 23, 23)
3826         ? dminnm : dmaxnm;
3827
3828       if (! full)
3829         HALT_NYI;
3830       aarch64_set_vec_double (cpu, vd, 0,
3831                               fn (aarch64_get_vec_double (cpu, vn, 0),
3832                                   aarch64_get_vec_double (cpu, vn, 1)));
3833       aarch64_set_vec_double (cpu, vd, 0,
3834                               fn (aarch64_get_vec_double (cpu, vm, 0),
3835                                   aarch64_get_vec_double (cpu, vm, 1)));
3836     }
3837   else
3838     {
3839       float (* fn)(float, float) = uimm (aarch64_get_instr (cpu), 23, 23)
3840         ? fminnm : fmaxnm;
3841
3842       aarch64_set_vec_float (cpu, vd, 0,
3843                              fn (aarch64_get_vec_float (cpu, vn, 0),
3844                                  aarch64_get_vec_float (cpu, vn, 1)));
3845       if (full)
3846         aarch64_set_vec_float (cpu, vd, 1,
3847                                fn (aarch64_get_vec_float (cpu, vn, 2),
3848                                    aarch64_get_vec_float (cpu, vn, 3)));
3849
3850       aarch64_set_vec_float (cpu, vd, (full ? 2 : 1),
3851                              fn (aarch64_get_vec_float (cpu, vm, 0),
3852                                  aarch64_get_vec_float (cpu, vm, 1)));
3853       if (full)
3854         aarch64_set_vec_float (cpu, vd, 3,
3855                                fn (aarch64_get_vec_float (cpu, vm, 2),
3856                                    aarch64_get_vec_float (cpu, vm, 3)));
3857     }
3858 }
3859
3860 static void
3861 do_vec_AND (sim_cpu *cpu)
3862 {
3863   /* instr[31]    = 0
3864      instr[30]    = half (0)/full (1)
3865      instr[29,21] = 001110001
3866      instr[20,16] = Vm
3867      instr[15,10] = 000111
3868      instr[9,5]   = Vn
3869      instr[4.0]   = Vd.  */
3870
3871   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3872   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3873   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3874   unsigned i;
3875   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3876
3877   NYI_assert (29, 21, 0x071);
3878   NYI_assert (15, 10, 0x07);
3879
3880   for (i = 0; i < (full ? 4 : 2); i++)
3881     aarch64_set_vec_u32 (cpu, vd, i,
3882                          aarch64_get_vec_u32 (cpu, vn, i)
3883                          & aarch64_get_vec_u32 (cpu, vm, i));
3884 }
3885
3886 static void
3887 do_vec_BSL (sim_cpu *cpu)
3888 {
3889   /* instr[31]    = 0
3890      instr[30]    = half (0)/full (1)
3891      instr[29,21] = 101110011
3892      instr[20,16] = Vm
3893      instr[15,10] = 000111
3894      instr[9,5]   = Vn
3895      instr[4.0]   = Vd.  */
3896
3897   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3898   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3899   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3900   unsigned i;
3901   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3902
3903   NYI_assert (29, 21, 0x173);
3904   NYI_assert (15, 10, 0x07);
3905
3906   for (i = 0; i < (full ? 16 : 8); i++)
3907     aarch64_set_vec_u8 (cpu, vd, i,
3908                         (    aarch64_get_vec_u8 (cpu, vd, i)
3909                            & aarch64_get_vec_u8 (cpu, vn, i))
3910                         | ((~ aarch64_get_vec_u8 (cpu, vd, i))
3911                            & aarch64_get_vec_u8 (cpu, vm, i)));
3912 }
3913
3914 static void
3915 do_vec_EOR (sim_cpu *cpu)
3916 {
3917   /* instr[31]    = 0
3918      instr[30]    = half (0)/full (1)
3919      instr[29,21] = 10 1110 001
3920      instr[20,16] = Vm
3921      instr[15,10] = 000111
3922      instr[9,5]   = Vn
3923      instr[4.0]   = Vd.  */
3924
3925   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3926   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3927   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3928   unsigned i;
3929   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3930
3931   NYI_assert (29, 21, 0x171);
3932   NYI_assert (15, 10, 0x07);
3933
3934   for (i = 0; i < (full ? 4 : 2); i++)
3935     aarch64_set_vec_u32 (cpu, vd, i,
3936                          aarch64_get_vec_u32 (cpu, vn, i)
3937                          ^ aarch64_get_vec_u32 (cpu, vm, i));
3938 }
3939
3940 static void
3941 do_vec_bit (sim_cpu *cpu)
3942 {
3943   /* instr[31]    = 0
3944      instr[30]    = half (0)/full (1)
3945      instr[29,23] = 10 1110 1
3946      instr[22]    = BIT (0) / BIF (1)
3947      instr[21]    = 1
3948      instr[20,16] = Vm
3949      instr[15,10] = 0001 11
3950      instr[9,5]   = Vn
3951      instr[4.0]   = Vd.  */
3952
3953   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3954   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3955   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3956   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
3957   unsigned test_false = uimm (aarch64_get_instr (cpu), 22, 22);
3958   unsigned i;
3959
3960   NYI_assert (29, 23, 0x5D);
3961   NYI_assert (21, 21, 1);
3962   NYI_assert (15, 10, 0x07);
3963
3964   if (test_false)
3965     {
3966       for (i = 0; i < (full ? 16 : 8); i++)
3967         if (aarch64_get_vec_u32 (cpu, vn, i) == 0)
3968           aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vm, i));
3969     }
3970   else
3971     {
3972       for (i = 0; i < (full ? 16 : 8); i++)
3973         if (aarch64_get_vec_u32 (cpu, vn, i) != 0)
3974           aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vm, i));
3975     }
3976 }
3977
3978 static void
3979 do_vec_ORN (sim_cpu *cpu)
3980 {
3981   /* instr[31]    = 0
3982      instr[30]    = half (0)/full (1)
3983      instr[29,21] = 00 1110 111
3984      instr[20,16] = Vm
3985      instr[15,10] = 00 0111
3986      instr[9,5]   = Vn
3987      instr[4.0]   = Vd.  */
3988
3989   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3990   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3991   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3992   unsigned i;
3993   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3994
3995   NYI_assert (29, 21, 0x077);
3996   NYI_assert (15, 10, 0x07);
3997
3998   for (i = 0; i < (full ? 16 : 8); i++)
3999     aarch64_set_vec_u8 (cpu, vd, i,
4000                         aarch64_get_vec_u8 (cpu, vn, i)
4001                         | ~ aarch64_get_vec_u8 (cpu, vm, i));
4002 }
4003
4004 static void
4005 do_vec_ORR (sim_cpu *cpu)
4006 {
4007   /* instr[31]    = 0
4008      instr[30]    = half (0)/full (1)
4009      instr[29,21] = 00 1110 101
4010      instr[20,16] = Vm
4011      instr[15,10] = 0001 11
4012      instr[9,5]   = Vn
4013      instr[4.0]   = Vd.  */
4014
4015   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4016   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4017   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4018   unsigned i;
4019   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
4020
4021   NYI_assert (29, 21, 0x075);
4022   NYI_assert (15, 10, 0x07);
4023
4024   for (i = 0; i < (full ? 16 : 8); i++)
4025     aarch64_set_vec_u8 (cpu, vd, i,
4026                         aarch64_get_vec_u8 (cpu, vn, i)
4027                         | aarch64_get_vec_u8 (cpu, vm, i));
4028 }
4029
4030 static void
4031 do_vec_BIC (sim_cpu *cpu)
4032 {
4033   /* instr[31]    = 0
4034      instr[30]    = half (0)/full (1)
4035      instr[29,21] = 00 1110 011
4036      instr[20,16] = Vm
4037      instr[15,10] = 00 0111
4038      instr[9,5]   = Vn
4039      instr[4.0]   = Vd.  */
4040
4041   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4042   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4043   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4044   unsigned i;
4045   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
4046
4047   NYI_assert (29, 21, 0x073);
4048   NYI_assert (15, 10, 0x07);
4049
4050   for (i = 0; i < (full ? 16 : 8); i++)
4051     aarch64_set_vec_u8 (cpu, vd, i,
4052                         aarch64_get_vec_u8 (cpu, vn, i)
4053                         & ~ aarch64_get_vec_u8 (cpu, vm, i));
4054 }
4055
4056 static void
4057 do_vec_XTN (sim_cpu *cpu)
4058 {
4059   /* instr[31]    = 0
4060      instr[30]    = first part (0)/ second part (1)
4061      instr[29,24] = 00 1110
4062      instr[23,22] = size: byte(00), half(01), word (10)
4063      instr[21,10] = 1000 0100 1010
4064      instr[9,5]   = Vs
4065      instr[4,0]   = Vd.  */
4066
4067   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
4068   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4069   unsigned bias = uimm (aarch64_get_instr (cpu), 30, 30);
4070   unsigned i;
4071
4072   NYI_assert (29, 24, 0x0E);
4073   NYI_assert (21, 10, 0x84A);
4074
4075   switch (uimm (aarch64_get_instr (cpu), 23, 22))
4076     {
4077     case 0:
4078       if (bias)
4079         for (i = 0; i < 8; i++)
4080           aarch64_set_vec_u8 (cpu, vd, i + 8,
4081                               aarch64_get_vec_u16 (cpu, vs, i) >> 8);
4082       else
4083         for (i = 0; i < 8; i++)
4084           aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vs, i));
4085       return;
4086
4087     case 1:
4088       if (bias)
4089         for (i = 0; i < 4; i++)
4090           aarch64_set_vec_u16 (cpu, vd, i + 4,
4091                                aarch64_get_vec_u32 (cpu, vs, i) >> 16);
4092       else
4093         for (i = 0; i < 4; i++)
4094           aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vs, i));
4095       return;
4096
4097     case 2:
4098       if (bias)
4099         for (i = 0; i < 2; i++)
4100           aarch64_set_vec_u32 (cpu, vd, i + 4,
4101                                aarch64_get_vec_u64 (cpu, vs, i) >> 32);
4102       else
4103         for (i = 0; i < 2; i++)
4104           aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u64 (cpu, vs, i));
4105       return;
4106
4107     default:
4108       HALT_UNALLOC;
4109     }
4110 }
4111
4112 #define MAX(A,B) ((A) > (B) ? (A) : (B))
4113 #define MIN(A,B) ((A) < (B) ? (A) : (B))
4114
4115 static void
4116 do_vec_maxv (sim_cpu *cpu)
4117 {
4118   /* instr[31]    = 0
4119      instr[30]    = half(0)/full(1)
4120      instr[29]    = signed (0)/unsigned(1)
4121      instr[28,24] = 0 1110
4122      instr[23,22] = size: byte(00), half(01), word (10)
4123      instr[21]    = 1
4124      instr[20,17] = 1 000
4125      instr[16]    = max(0)/min(1)
4126      instr[15,10] = 1010 10
4127      instr[9,5]   = V source
4128      instr[4.0]   = R dest.  */
4129
4130   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
4131   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
4132   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4133   unsigned i;
4134
4135   NYI_assert (28, 24, 0x0E);
4136   NYI_assert (21, 21, 1);
4137   NYI_assert (20, 17, 8);
4138   NYI_assert (15, 10, 0x2A);
4139
4140   switch ((uimm (aarch64_get_instr (cpu), 29, 29) << 1)
4141           | uimm (aarch64_get_instr (cpu), 16, 16))
4142     {
4143     case 0: /* SMAXV.  */
4144        {
4145         int64_t smax;
4146         switch (uimm (aarch64_get_instr (cpu), 23, 22))
4147           {
4148           case 0:
4149             smax = aarch64_get_vec_s8 (cpu, vs, 0);
4150             for (i = 1; i < (full ? 16 : 8); i++)
4151               smax = MAX (smax, aarch64_get_vec_s8 (cpu, vs, i));
4152             break;
4153           case 1:
4154             smax = aarch64_get_vec_s16 (cpu, vs, 0);
4155             for (i = 1; i < (full ? 8 : 4); i++)
4156               smax = MAX (smax, aarch64_get_vec_s16 (cpu, vs, i));
4157             break;
4158           case 2:
4159             smax = aarch64_get_vec_s32 (cpu, vs, 0);
4160             for (i = 1; i < (full ? 4 : 2); i++)
4161               smax = MAX (smax, aarch64_get_vec_s32 (cpu, vs, i));
4162             break;
4163           default:
4164           case 3:
4165             HALT_UNALLOC;
4166           }
4167         aarch64_set_reg_s64 (cpu, rd, NO_SP, smax);
4168         return;
4169       }
4170
4171     case 1: /* SMINV.  */
4172       {
4173         int64_t smin;
4174         switch (uimm (aarch64_get_instr (cpu), 23, 22))
4175           {
4176           case 0:
4177             smin = aarch64_get_vec_s8 (cpu, vs, 0);
4178             for (i = 1; i < (full ? 16 : 8); i++)
4179               smin = MIN (smin, aarch64_get_vec_s8 (cpu, vs, i));
4180             break;
4181           case 1:
4182             smin = aarch64_get_vec_s16 (cpu, vs, 0);
4183             for (i = 1; i < (full ? 8 : 4); i++)
4184               smin = MIN (smin, aarch64_get_vec_s16 (cpu, vs, i));
4185             break;
4186           case 2:
4187             smin = aarch64_get_vec_s32 (cpu, vs, 0);
4188             for (i = 1; i < (full ? 4 : 2); i++)
4189               smin = MIN (smin, aarch64_get_vec_s32 (cpu, vs, i));
4190             break;
4191           default:
4192           case 3:
4193             HALT_UNALLOC;
4194           }
4195         aarch64_set_reg_s64 (cpu, rd, NO_SP, smin);
4196         return;
4197       }
4198
4199     case 2: /* UMAXV.  */
4200       {
4201         uint64_t umax;
4202         switch (uimm (aarch64_get_instr (cpu), 23, 22))
4203           {
4204           case 0:
4205             umax = aarch64_get_vec_u8 (cpu, vs, 0);
4206             for (i = 1; i < (full ? 16 : 8); i++)
4207               umax = MAX (umax, aarch64_get_vec_u8 (cpu, vs, i));
4208             break;
4209           case 1:
4210             umax = aarch64_get_vec_u16 (cpu, vs, 0);
4211             for (i = 1; i < (full ? 8 : 4); i++)
4212               umax = MAX (umax, aarch64_get_vec_u16 (cpu, vs, i));
4213             break;
4214           case 2:
4215             umax = aarch64_get_vec_u32 (cpu, vs, 0);
4216             for (i = 1; i < (full ? 4 : 2); i++)
4217               umax = MAX (umax, aarch64_get_vec_u32 (cpu, vs, i));
4218             break;
4219           default:
4220           case 3:
4221             HALT_UNALLOC;
4222           }
4223         aarch64_set_reg_u64 (cpu, rd, NO_SP, umax);
4224         return;
4225       }
4226
4227     case 3: /* UMINV.  */
4228       {
4229         uint64_t umin;
4230         switch (uimm (aarch64_get_instr (cpu), 23, 22))
4231           {
4232           case 0:
4233             umin = aarch64_get_vec_u8 (cpu, vs, 0);
4234             for (i = 1; i < (full ? 16 : 8); i++)
4235               umin = MIN (umin, aarch64_get_vec_u8 (cpu, vs, i));
4236             break;
4237           case 1:
4238             umin = aarch64_get_vec_u16 (cpu, vs, 0);
4239             for (i = 1; i < (full ? 8 : 4); i++)
4240               umin = MIN (umin, aarch64_get_vec_u16 (cpu, vs, i));
4241             break;
4242           case 2:
4243             umin = aarch64_get_vec_u32 (cpu, vs, 0);
4244             for (i = 1; i < (full ? 4 : 2); i++)
4245               umin = MIN (umin, aarch64_get_vec_u32 (cpu, vs, i));
4246             break;
4247           default:
4248           case 3:
4249             HALT_UNALLOC;
4250           }
4251         aarch64_set_reg_u64 (cpu, rd, NO_SP, umin);
4252         return;
4253       }
4254
4255     default:
4256       HALT_UNALLOC;
4257     }
4258 }
4259
4260 static void
4261 do_vec_fminmaxV (sim_cpu *cpu)
4262 {
4263   /* instr[31,24] = 0110 1110
4264      instr[23]    = max(0)/min(1)
4265      instr[22,14] = 011 0000 11
4266      instr[13,12] = nm(00)/normal(11)
4267      instr[11,10] = 10
4268      instr[9,5]   = V source
4269      instr[4.0]   = R dest.  */
4270
4271   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
4272   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
4273   unsigned i;
4274   float res   = aarch64_get_vec_float (cpu, vs, 0);
4275
4276   NYI_assert (31, 24, 0x6E);
4277   NYI_assert (22, 14, 0x0C3);
4278   NYI_assert (11, 10, 2);
4279
4280   if (uimm (aarch64_get_instr (cpu), 23, 23))
4281     {
4282       switch (uimm (aarch64_get_instr (cpu), 13, 12))
4283         {
4284         case 0: /* FMNINNMV.  */
4285           for (i = 1; i < 4; i++)
4286             res = fminnm (res, aarch64_get_vec_float (cpu, vs, i));
4287           break;
4288
4289         case 3: /* FMINV.  */
4290           for (i = 1; i < 4; i++)
4291             res = MIN (res, aarch64_get_vec_float (cpu, vs, i));
4292           break;
4293
4294         default:
4295           HALT_NYI;
4296         }
4297     }
4298   else
4299     {
4300       switch (uimm (aarch64_get_instr (cpu), 13, 12))
4301         {
4302         case 0: /* FMNAXNMV.  */
4303           for (i = 1; i < 4; i++)
4304             res = fmaxnm (res, aarch64_get_vec_float (cpu, vs, i));
4305           break;
4306
4307         case 3: /* FMAXV.  */
4308           for (i = 1; i < 4; i++)
4309             res = MAX (res, aarch64_get_vec_float (cpu, vs, i));
4310           break;
4311
4312         default:
4313           HALT_NYI;
4314         }
4315     }
4316
4317   aarch64_set_FP_float (cpu, rd, res);
4318 }
4319
4320 static void
4321 do_vec_Fminmax (sim_cpu *cpu)
4322 {
4323   /* instr[31]    = 0
4324      instr[30]    = half(0)/full(1)
4325      instr[29,24] = 00 1110
4326      instr[23]    = max(0)/min(1)
4327      instr[22]    = float(0)/double(1)
4328      instr[21]    = 1
4329      instr[20,16] = Vm
4330      instr[15,14] = 11
4331      instr[13,12] = nm(00)/normal(11)
4332      instr[11,10] = 01
4333      instr[9,5]   = Vn
4334      instr[4,0]   = Vd.  */
4335
4336   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4337   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4338   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4339   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4340   unsigned min = uimm (aarch64_get_instr (cpu), 23, 23);
4341   unsigned i;
4342
4343   NYI_assert (29, 24, 0x0E);
4344   NYI_assert (21, 21, 1);
4345   NYI_assert (15, 14, 3);
4346   NYI_assert (11, 10, 1);
4347
4348   if (uimm (aarch64_get_instr (cpu), 22, 22))
4349     {
4350       double (* func)(double, double);
4351
4352       if (! full)
4353         HALT_NYI;
4354
4355       if (uimm (aarch64_get_instr (cpu), 13, 12) == 0)
4356         func = min ? dminnm : dmaxnm;
4357       else if (uimm (aarch64_get_instr (cpu), 13, 12) == 3)
4358         func = min ? fmin : fmax;
4359       else
4360         HALT_NYI;
4361
4362       for (i = 0; i < 2; i++)
4363         aarch64_set_vec_double (cpu, vd, i,
4364                                 func (aarch64_get_vec_double (cpu, vn, i),
4365                                       aarch64_get_vec_double (cpu, vm, i)));
4366     }
4367   else
4368     {
4369       float (* func)(float, float);
4370
4371       if (uimm (aarch64_get_instr (cpu), 13, 12) == 0)
4372         func = min ? fminnm : fmaxnm;
4373       else if (uimm (aarch64_get_instr (cpu), 13, 12) == 3)
4374         func = min ? fminf : fmaxf;
4375       else
4376         HALT_NYI;
4377
4378       for (i = 0; i < (full ? 4 : 2); i++)
4379         aarch64_set_vec_float (cpu, vd, i,
4380                                func (aarch64_get_vec_float (cpu, vn, i),
4381                                      aarch64_get_vec_float (cpu, vm, i)));
4382     }
4383 }
4384
4385 static void
4386 do_vec_SCVTF (sim_cpu *cpu)
4387 {
4388   /* instr[31]    = 0
4389      instr[30]    = Q
4390      instr[29,23] = 00 1110 0
4391      instr[22]    = float(0)/double(1)
4392      instr[21,10] = 10 0001 1101 10
4393      instr[9,5]   = Vn
4394      instr[4,0]   = Vd.  */
4395
4396   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4397   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4398   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4399   unsigned size = uimm (aarch64_get_instr (cpu), 22, 22);
4400   unsigned i;
4401
4402   NYI_assert (29, 23, 0x1C);
4403   NYI_assert (21, 10, 0x876);
4404
4405   if (size)
4406     {
4407       if (! full)
4408         HALT_UNALLOC;
4409
4410       for (i = 0; i < 2; i++)
4411         {
4412           double val = (double) aarch64_get_vec_u64 (cpu, vn, i);
4413           aarch64_set_vec_double (cpu, vd, i, val);
4414         }
4415     }
4416   else
4417     {
4418       for (i = 0; i < (full ? 4 : 2); i++)
4419         {
4420           float val = (float) aarch64_get_vec_u32 (cpu, vn, i);
4421           aarch64_set_vec_float (cpu, vd, i, val);
4422         }
4423     }
4424 }
4425
4426 #define VEC_CMP(SOURCE, CMP)                                            \
4427   do                                                                    \
4428     {                                                                   \
4429       switch (size)                                                     \
4430         {                                                               \
4431         case 0:                                                         \
4432           for (i = 0; i < (full ? 16 : 8); i++)                         \
4433             aarch64_set_vec_u8 (cpu, vd, i,                             \
4434                                 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4435                                 CMP                                     \
4436                                 aarch64_get_vec_##SOURCE##8 (cpu, vm, i) \
4437                                 ? -1 : 0);                              \
4438           return;                                                       \
4439         case 1:                                                         \
4440           for (i = 0; i < (full ? 8 : 4); i++)                          \
4441             aarch64_set_vec_u16 (cpu, vd, i,                            \
4442                                  aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4443                                  CMP                                    \
4444                                  aarch64_get_vec_##SOURCE##16 (cpu, vm, i) \
4445                                  ? -1 : 0);                             \
4446           return;                                                       \
4447         case 2:                                                         \
4448           for (i = 0; i < (full ? 4 : 2); i++)                          \
4449             aarch64_set_vec_u32 (cpu, vd, i, \
4450                                  aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4451                                  CMP                                    \
4452                                  aarch64_get_vec_##SOURCE##32 (cpu, vm, i) \
4453                                  ? -1 : 0);                             \
4454           return;                                                       \
4455         case 3:                                                         \
4456           if (! full)                                                   \
4457             HALT_UNALLOC;                                               \
4458           for (i = 0; i < 2; i++)                                       \
4459             aarch64_set_vec_u64 (cpu, vd, i, \
4460                                  aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4461                                  CMP                                    \
4462                                  aarch64_get_vec_##SOURCE##64 (cpu, vm, i) \
4463                                  ? -1ULL : 0);                          \
4464           return;                                                       \
4465         default:                                                        \
4466         HALT_UNALLOC;                                                   \
4467         }                                                               \
4468     }                                                                   \
4469   while (0)
4470
4471 #define VEC_CMP0(SOURCE, CMP)                                           \
4472   do                                                                    \
4473     {                                                                   \
4474       switch (size)                                                     \
4475         {                                                               \
4476         case 0:                                                         \
4477           for (i = 0; i < (full ? 16 : 8); i++)                         \
4478             aarch64_set_vec_u8 (cpu, vd, i,                             \
4479                                 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4480                                 CMP 0 ? -1 : 0);                        \
4481           return;                                                       \
4482         case 1:                                                         \
4483           for (i = 0; i < (full ? 8 : 4); i++)                          \
4484             aarch64_set_vec_u16 (cpu, vd, i,                            \
4485                                  aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4486                                  CMP 0 ? -1 : 0);                       \
4487           return;                                                       \
4488         case 2:                                                         \
4489           for (i = 0; i < (full ? 4 : 2); i++)                          \
4490             aarch64_set_vec_u32 (cpu, vd, i,                            \
4491                                  aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4492                                  CMP 0 ? -1 : 0);                       \
4493           return;                                                       \
4494         case 3:                                                         \
4495           if (! full)                                                   \
4496             HALT_UNALLOC;                                               \
4497           for (i = 0; i < 2; i++)                                       \
4498             aarch64_set_vec_u64 (cpu, vd, i,                            \
4499                                  aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4500                                  CMP 0 ? -1ULL : 0);                    \
4501           return;                                                       \
4502         default:                                                        \
4503           HALT_UNALLOC;                                                 \
4504         }                                                               \
4505     }                                                                   \
4506   while (0)
4507
4508 #define VEC_FCMP0(CMP)                                                  \
4509   do                                                                    \
4510     {                                                                   \
4511       if (vm != 0)                                                      \
4512         HALT_NYI;                                                       \
4513       if (uimm (aarch64_get_instr (cpu), 22, 22))                       \
4514         {                                                               \
4515           if (! full)                                                   \
4516             HALT_NYI;                                                   \
4517           for (i = 0; i < 2; i++)                                       \
4518             aarch64_set_vec_u64 (cpu, vd, i,                            \
4519                                  aarch64_get_vec_double (cpu, vn, i)    \
4520                                  CMP 0.0 ? -1 : 0);                     \
4521         }                                                               \
4522       else                                                              \
4523         {                                                               \
4524           for (i = 0; i < (full ? 4 : 2); i++)                          \
4525             aarch64_set_vec_u32 (cpu, vd, i,                            \
4526                                  aarch64_get_vec_float (cpu, vn, i)     \
4527                                  CMP 0.0 ? -1 : 0);                     \
4528         }                                                               \
4529       return;                                                           \
4530     }                                                                   \
4531   while (0)
4532
4533 #define VEC_FCMP(CMP)                                                   \
4534   do                                                                    \
4535     {                                                                   \
4536       if (uimm (aarch64_get_instr (cpu), 22, 22))                       \
4537         {                                                               \
4538           if (! full)                                                   \
4539             HALT_NYI;                                                   \
4540           for (i = 0; i < 2; i++)                                       \
4541             aarch64_set_vec_u64 (cpu, vd, i,                            \
4542                                  aarch64_get_vec_double (cpu, vn, i)    \
4543                                  CMP                                    \
4544                                  aarch64_get_vec_double (cpu, vm, i)    \
4545                                  ? -1 : 0);                             \
4546         }                                                               \
4547       else                                                              \
4548         {                                                               \
4549           for (i = 0; i < (full ? 4 : 2); i++)                          \
4550             aarch64_set_vec_u32 (cpu, vd, i,                            \
4551                                  aarch64_get_vec_float (cpu, vn, i)     \
4552                                  CMP                                    \
4553                                  aarch64_get_vec_float (cpu, vm, i)     \
4554                                  ? -1 : 0);                             \
4555         }                                                               \
4556       return;                                                           \
4557     }                                                                   \
4558   while (0)
4559
4560 static void
4561 do_vec_compare (sim_cpu *cpu)
4562 {
4563   /* instr[31]    = 0
4564      instr[30]    = half(0)/full(1)
4565      instr[29]    = part-of-comparison-type
4566      instr[28,24] = 0 1110
4567      instr[23,22] = size of integer compares: byte(00), half(01), word (10), long (11)
4568                     type of float compares: single (-0) / double (-1)
4569      instr[21]    = 1
4570      instr[20,16] = Vm or 00000 (compare vs 0)
4571      instr[15,10] = part-of-comparison-type
4572      instr[9,5]   = Vn
4573      instr[4.0]   = Vd.  */
4574
4575   int full = uimm (aarch64_get_instr (cpu), 30, 30);
4576   int size = uimm (aarch64_get_instr (cpu), 23, 22);
4577   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4578   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4579   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4580   unsigned i;
4581
4582   NYI_assert (28, 24, 0x0E);
4583   NYI_assert (21, 21, 1);
4584
4585   if ((uimm (aarch64_get_instr (cpu), 11, 11)
4586        && uimm (aarch64_get_instr (cpu), 14, 14))
4587       || ((uimm (aarch64_get_instr (cpu), 11, 11) == 0
4588            && uimm (aarch64_get_instr (cpu), 10, 10) == 0)))
4589     {
4590       /* A compare vs 0.  */
4591       if (vm != 0)
4592         {
4593           if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x2A)
4594             do_vec_maxv (cpu);
4595           else if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x32
4596                    || uimm (aarch64_get_instr (cpu), 15, 10) == 0x3E)
4597             do_vec_fminmaxV (cpu);
4598           else if (uimm (aarch64_get_instr (cpu), 29, 23) == 0x1C
4599                    && uimm (aarch64_get_instr (cpu), 21, 10) == 0x876)
4600             do_vec_SCVTF (cpu);
4601           else
4602             HALT_NYI;
4603           return;
4604         }
4605     }
4606
4607   if (uimm (aarch64_get_instr (cpu), 14, 14))
4608     {
4609       /* A floating point compare.  */
4610       unsigned decode = (uimm (aarch64_get_instr (cpu), 29, 29) << 5)
4611         | (uimm (aarch64_get_instr (cpu), 23, 23) << 4)
4612         | uimm (aarch64_get_instr (cpu), 13, 10);
4613
4614       NYI_assert (15, 15, 1);
4615
4616       switch (decode)
4617         {
4618         case /* 0b010010: GT#0 */ 0x12: VEC_FCMP0 (>);
4619         case /* 0b110010: GE#0 */ 0x32: VEC_FCMP0 (>=);
4620         case /* 0b010110: EQ#0 */ 0x16: VEC_FCMP0 (==);
4621         case /* 0b110110: LE#0 */ 0x36: VEC_FCMP0 (<=);
4622         case /* 0b011010: LT#0 */ 0x1A: VEC_FCMP0 (<);
4623         case /* 0b111001: GT */   0x39: VEC_FCMP  (>);
4624         case /* 0b101001: GE */   0x29: VEC_FCMP  (>=);
4625         case /* 0b001001: EQ */   0x09: VEC_FCMP  (==);
4626
4627         default:
4628           HALT_NYI;
4629         }
4630     }
4631   else
4632     {
4633       unsigned decode = (uimm (aarch64_get_instr (cpu), 29, 29) << 6)
4634         | uimm (aarch64_get_instr (cpu), 15, 10);
4635
4636       switch (decode)
4637         {
4638         case 0x0D: /* 0001101 GT */     VEC_CMP  (s, > );
4639         case 0x0F: /* 0001111 GE */     VEC_CMP  (s, >= );
4640         case 0x22: /* 0100010 GT #0 */  VEC_CMP0 (s, > );
4641         case 0x26: /* 0100110 EQ #0 */  VEC_CMP0 (s, == );
4642         case 0x2A: /* 0101010 LT #0 */  VEC_CMP0 (s, < );
4643         case 0x4D: /* 1001101 HI */     VEC_CMP  (u, > );
4644         case 0x4F: /* 1001111 HS */     VEC_CMP  (u, >= );
4645         case 0x62: /* 1100010 GE #0 */  VEC_CMP0 (s, >= );
4646         case 0x63: /* 1100011 EQ */     VEC_CMP  (u, == );
4647         case 0x66: /* 1100110 LE #0 */  VEC_CMP0 (s, <= );
4648         default:
4649           if (vm == 0)
4650             HALT_NYI;
4651           do_vec_maxv (cpu);
4652         }
4653     }
4654 }
4655
4656 static void
4657 do_vec_SSHL (sim_cpu *cpu)
4658 {
4659   /* instr[31]    = 0
4660      instr[30]    = first part (0)/ second part (1)
4661      instr[29,24] = 00 1110
4662      instr[23,22] = size: byte(00), half(01), word (10), long (11)
4663      instr[21]    = 1
4664      instr[20,16] = Vm
4665      instr[15,10] = 0100 01
4666      instr[9,5]   = Vn
4667      instr[4,0]   = Vd.  */
4668
4669   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4670   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4671   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4672   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4673   unsigned i;
4674
4675   NYI_assert (29, 24, 0x0E);
4676   NYI_assert (21, 21, 1);
4677   NYI_assert (15, 10, 0x11);
4678
4679   /* FIXME: What is a signed shift left in this context ?.  */
4680
4681   switch (uimm (aarch64_get_instr (cpu), 23, 22))
4682     {
4683     case 0:
4684       for (i = 0; i < (full ? 16 : 8); i++)
4685         aarch64_set_vec_s8 (cpu, vd, i, aarch64_get_vec_s8 (cpu, vn, i)
4686                             << aarch64_get_vec_s8 (cpu, vm, i));
4687       return;
4688
4689     case 1:
4690       for (i = 0; i < (full ? 8 : 4); i++)
4691         aarch64_set_vec_s16 (cpu, vd, i, aarch64_get_vec_s16 (cpu, vn, i)
4692                              << aarch64_get_vec_s16 (cpu, vm, i));
4693       return;
4694
4695     case 2:
4696       for (i = 0; i < (full ? 4 : 2); i++)
4697         aarch64_set_vec_s32 (cpu, vd, i, aarch64_get_vec_s32 (cpu, vn, i)
4698                              << aarch64_get_vec_s32 (cpu, vm, i));
4699       return;
4700
4701     case 3:
4702       if (! full)
4703         HALT_UNALLOC;
4704       for (i = 0; i < 2; i++)
4705         aarch64_set_vec_s64 (cpu, vd, i, aarch64_get_vec_s64 (cpu, vn, i)
4706                              << aarch64_get_vec_s64 (cpu, vm, i));
4707       return;
4708
4709     default:
4710       HALT_NYI;
4711     }
4712 }
4713
4714 static void
4715 do_vec_USHL (sim_cpu *cpu)
4716 {
4717   /* instr[31]    = 0
4718      instr[30]    = first part (0)/ second part (1)
4719      instr[29,24] = 10 1110
4720      instr[23,22] = size: byte(00), half(01), word (10), long (11)
4721      instr[21]    = 1
4722      instr[20,16] = Vm
4723      instr[15,10] = 0100 01
4724      instr[9,5]   = Vn
4725      instr[4,0]   = Vd  */
4726
4727   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4728   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4729   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4730   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4731   unsigned i;
4732
4733   NYI_assert (29, 24, 0x2E);
4734   NYI_assert (15, 10, 0x11);
4735
4736   switch (uimm (aarch64_get_instr (cpu), 23, 22))
4737     {
4738     case 0:
4739       for (i = 0; i < (full ? 16 : 8); i++)
4740         aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vn, i)
4741                             << aarch64_get_vec_u8 (cpu, vm, i));
4742       return;
4743
4744     case 1:
4745       for (i = 0; i < (full ? 8 : 4); i++)
4746         aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vn, i)
4747                              << aarch64_get_vec_u16 (cpu, vm, i));
4748       return;
4749
4750     case 2:
4751       for (i = 0; i < (full ? 4 : 2); i++)
4752         aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vn, i)
4753                              << aarch64_get_vec_u32 (cpu, vm, i));
4754       return;
4755
4756     case 3:
4757       if (! full)
4758         HALT_UNALLOC;
4759       for (i = 0; i < 2; i++)
4760         aarch64_set_vec_u64 (cpu, vd, i, aarch64_get_vec_u64 (cpu, vn, i)
4761                              << aarch64_get_vec_u64 (cpu, vm, i));
4762       return;
4763
4764     default:
4765       HALT_NYI;
4766     }
4767 }
4768
4769 static void
4770 do_vec_FMLA (sim_cpu *cpu)
4771 {
4772   /* instr[31]    = 0
4773      instr[30]    = full/half selector
4774      instr[29,23] = 0011100
4775      instr[22]    = size: 0=>float, 1=>double
4776      instr[21]    = 1
4777      instr[20,16] = Vn
4778      instr[15,10] = 1100 11
4779      instr[9,5]   = Vm
4780      instr[4.0]   = Vd.  */
4781
4782   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4783   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4784   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4785   unsigned i;
4786   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
4787
4788   NYI_assert (29, 23, 0x1C);
4789   NYI_assert (21, 21, 1);
4790   NYI_assert (15, 10, 0x33);
4791
4792   if (uimm (aarch64_get_instr (cpu), 22, 22))
4793     {
4794       if (! full)
4795         HALT_UNALLOC;
4796       for (i = 0; i < 2; i++)
4797         aarch64_set_vec_double (cpu, vd, i,
4798                                 aarch64_get_vec_double (cpu, vn, i) *
4799                                 aarch64_get_vec_double (cpu, vm, i) +
4800                                 aarch64_get_vec_double (cpu, vd, i));
4801     }
4802   else
4803     {
4804       for (i = 0; i < (full ? 4 : 2); i++)
4805         aarch64_set_vec_float (cpu, vd, i,
4806                                aarch64_get_vec_float (cpu, vn, i) *
4807                                aarch64_get_vec_float (cpu, vm, i) +
4808                                aarch64_get_vec_float (cpu, vd, i));
4809     }
4810 }
4811
4812 static void
4813 do_vec_max (sim_cpu *cpu)
4814 {
4815   /* instr[31]    = 0
4816      instr[30]    = full/half selector
4817      instr[29]    = SMAX (0) / UMAX (1)
4818      instr[28,24] = 0 1110
4819      instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
4820      instr[21]    = 1
4821      instr[20,16] = Vn
4822      instr[15,10] = 0110 01
4823      instr[9,5]   = Vm
4824      instr[4.0]   = Vd.  */
4825
4826   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4827   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4828   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4829   unsigned i;
4830   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
4831
4832   NYI_assert (28, 24, 0x0E);
4833   NYI_assert (21, 21, 1);
4834   NYI_assert (15, 10, 0x19);
4835
4836   if (uimm (aarch64_get_instr (cpu), 29, 29))
4837     {
4838       switch (uimm (aarch64_get_instr (cpu), 23, 22))
4839         {
4840         case 0:
4841           for (i = 0; i < (full ? 16 : 8); i++)
4842             aarch64_set_vec_u8 (cpu, vd, i,
4843                                 aarch64_get_vec_u8 (cpu, vn, i)
4844                                 > aarch64_get_vec_u8 (cpu, vm, i)
4845                                 ? aarch64_get_vec_u8 (cpu, vn, i)
4846                                 : aarch64_get_vec_u8 (cpu, vm, i));
4847           return;
4848
4849         case 1:
4850           for (i = 0; i < (full ? 8 : 4); i++)
4851             aarch64_set_vec_u16 (cpu, vd, i,
4852                                  aarch64_get_vec_u16 (cpu, vn, i)
4853                                  > aarch64_get_vec_u16 (cpu, vm, i)
4854                                  ? aarch64_get_vec_u16 (cpu, vn, i)
4855                                  : aarch64_get_vec_u16 (cpu, vm, i));
4856           return;
4857
4858         case 2:
4859           for (i = 0; i < (full ? 4 : 2); i++)
4860             aarch64_set_vec_u32 (cpu, vd, i,
4861                                  aarch64_get_vec_u32 (cpu, vn, i)
4862                                  > aarch64_get_vec_u32 (cpu, vm, i)
4863                                  ? aarch64_get_vec_u32 (cpu, vn, i)
4864                                  : aarch64_get_vec_u32 (cpu, vm, i));
4865           return;
4866
4867         default:
4868         case 3:
4869           HALT_UNALLOC;
4870         }
4871     }
4872   else
4873     {
4874       switch (uimm (aarch64_get_instr (cpu), 23, 22))
4875         {
4876         case 0:
4877           for (i = 0; i < (full ? 16 : 8); i++)
4878             aarch64_set_vec_s8 (cpu, vd, i,
4879                                 aarch64_get_vec_s8 (cpu, vn, i)
4880                                 > aarch64_get_vec_s8 (cpu, vm, i)
4881                                 ? aarch64_get_vec_s8 (cpu, vn, i)
4882                                 : aarch64_get_vec_s8 (cpu, vm, i));
4883           return;
4884
4885         case 1:
4886           for (i = 0; i < (full ? 8 : 4); i++)
4887             aarch64_set_vec_s16 (cpu, vd, i,
4888                                  aarch64_get_vec_s16 (cpu, vn, i)
4889                                  > aarch64_get_vec_s16 (cpu, vm, i)
4890                                  ? aarch64_get_vec_s16 (cpu, vn, i)
4891                                  : aarch64_get_vec_s16 (cpu, vm, i));
4892           return;
4893
4894         case 2:
4895           for (i = 0; i < (full ? 4 : 2); i++)
4896             aarch64_set_vec_s32 (cpu, vd, i,
4897                                  aarch64_get_vec_s32 (cpu, vn, i)
4898                                  > aarch64_get_vec_s32 (cpu, vm, i)
4899                                  ? aarch64_get_vec_s32 (cpu, vn, i)
4900                                  : aarch64_get_vec_s32 (cpu, vm, i));
4901           return;
4902
4903         default:
4904         case 3:
4905           HALT_UNALLOC;
4906         }
4907     }
4908 }
4909
4910 static void
4911 do_vec_min (sim_cpu *cpu)
4912 {
4913   /* instr[31]    = 0
4914      instr[30]    = full/half selector
4915      instr[29]    = SMIN (0) / UMIN (1)
4916      instr[28,24] = 0 1110
4917      instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
4918      instr[21]    = 1
4919      instr[20,16] = Vn
4920      instr[15,10] = 0110 11
4921      instr[9,5]   = Vm
4922      instr[4.0]   = Vd.  */
4923
4924   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4925   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4926   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4927   unsigned i;
4928   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
4929
4930   NYI_assert (28, 24, 0x0E);
4931   NYI_assert (21, 21, 1);
4932   NYI_assert (15, 10, 0x1B);
4933
4934   if (uimm (aarch64_get_instr (cpu), 29, 29))
4935     {
4936       switch (uimm (aarch64_get_instr (cpu), 23, 22))
4937         {
4938         case 0:
4939           for (i = 0; i < (full ? 16 : 8); i++)
4940             aarch64_set_vec_u8 (cpu, vd, i,
4941                                 aarch64_get_vec_u8 (cpu, vn, i)
4942                                 < aarch64_get_vec_u8 (cpu, vm, i)
4943                                 ? aarch64_get_vec_u8 (cpu, vn, i)
4944                                 : aarch64_get_vec_u8 (cpu, vm, i));
4945           return;
4946
4947         case 1:
4948           for (i = 0; i < (full ? 8 : 4); i++)
4949             aarch64_set_vec_u16 (cpu, vd, i,
4950                                  aarch64_get_vec_u16 (cpu, vn, i)
4951                                  < aarch64_get_vec_u16 (cpu, vm, i)
4952                                  ? aarch64_get_vec_u16 (cpu, vn, i)
4953                                  : aarch64_get_vec_u16 (cpu, vm, i));
4954           return;
4955
4956         case 2:
4957           for (i = 0; i < (full ? 4 : 2); i++)
4958             aarch64_set_vec_u32 (cpu, vd, i,
4959                                  aarch64_get_vec_u32 (cpu, vn, i)
4960                                  < aarch64_get_vec_u32 (cpu, vm, i)
4961                                  ? aarch64_get_vec_u32 (cpu, vn, i)
4962                                  : aarch64_get_vec_u32 (cpu, vm, i));
4963           return;
4964
4965         default:
4966         case 3:
4967           HALT_UNALLOC;
4968         }
4969     }
4970   else
4971     {
4972       switch (uimm (aarch64_get_instr (cpu), 23, 22))
4973         {
4974         case 0:
4975           for (i = 0; i < (full ? 16 : 8); i++)
4976             aarch64_set_vec_s8 (cpu, vd, i,
4977                                 aarch64_get_vec_s8 (cpu, vn, i)
4978                                 < aarch64_get_vec_s8 (cpu, vm, i)
4979                                 ? aarch64_get_vec_s8 (cpu, vn, i)
4980                                 : aarch64_get_vec_s8 (cpu, vm, i));
4981           return;
4982
4983         case 1:
4984           for (i = 0; i < (full ? 8 : 4); i++)
4985             aarch64_set_vec_s16 (cpu, vd, i,
4986                                  aarch64_get_vec_s16 (cpu, vn, i)
4987                                  < aarch64_get_vec_s16 (cpu, vm, i)
4988                                  ? aarch64_get_vec_s16 (cpu, vn, i)
4989                                  : aarch64_get_vec_s16 (cpu, vm, i));
4990           return;
4991
4992         case 2:
4993           for (i = 0; i < (full ? 4 : 2); i++)
4994             aarch64_set_vec_s32 (cpu, vd, i,
4995                                  aarch64_get_vec_s32 (cpu, vn, i)
4996                                  < aarch64_get_vec_s32 (cpu, vm, i)
4997                                  ? aarch64_get_vec_s32 (cpu, vn, i)
4998                                  : aarch64_get_vec_s32 (cpu, vm, i));
4999           return;
5000
5001         default:
5002         case 3:
5003           HALT_UNALLOC;
5004         }
5005     }
5006 }
5007
5008 static void
5009 do_vec_sub_long (sim_cpu *cpu)
5010 {
5011   /* instr[31]    = 0
5012      instr[30]    = lower (0) / upper (1)
5013      instr[29]    = signed (0) / unsigned (1)
5014      instr[28,24] = 0 1110
5015      instr[23,22] = size: bytes (00), half (01), word (10)
5016      instr[21]    = 1
5017      insrt[20,16] = Vm
5018      instr[15,10] = 0010 00
5019      instr[9,5]   = Vn
5020      instr[4,0]   = V dest.  */
5021
5022   unsigned size = uimm (aarch64_get_instr (cpu), 23, 22);
5023   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5024   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5025   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5026   unsigned bias = 0;
5027   unsigned i;
5028
5029   NYI_assert (28, 24, 0x0E);
5030   NYI_assert (21, 21, 1);
5031   NYI_assert (15, 10, 0x08);
5032
5033   if (size == 3)
5034     HALT_UNALLOC;
5035
5036   switch (uimm (aarch64_get_instr (cpu), 30, 29))
5037     {
5038     case 2: /* SSUBL2.  */
5039       bias = 2;
5040     case 0: /* SSUBL.  */
5041       switch (size)
5042         {
5043         case 0:
5044           bias *= 3;
5045           for (i = 0; i < 8; i++)
5046             aarch64_set_vec_s16 (cpu, vd, i,
5047                                  aarch64_get_vec_s8 (cpu, vn, i + bias)
5048                                  - aarch64_get_vec_s8 (cpu, vm, i + bias));
5049           break;
5050
5051         case 1:
5052           bias *= 2;
5053           for (i = 0; i < 4; i++)
5054             aarch64_set_vec_s32 (cpu, vd, i,
5055                                  aarch64_get_vec_s16 (cpu, vn, i + bias)
5056                                  - aarch64_get_vec_s16 (cpu, vm, i + bias));
5057           break;
5058
5059         case 2:
5060           for (i = 0; i < 2; i++)
5061             aarch64_set_vec_s64 (cpu, vd, i,
5062                                  aarch64_get_vec_s32 (cpu, vn, i + bias)
5063                                  - aarch64_get_vec_s32 (cpu, vm, i + bias));
5064           break;
5065
5066         default:
5067           HALT_UNALLOC;
5068         }
5069       break;
5070
5071     case 3: /* USUBL2.  */
5072       bias = 2;
5073     case 1: /* USUBL.  */
5074       switch (size)
5075         {
5076         case 0:
5077           bias *= 3;
5078           for (i = 0; i < 8; i++)
5079             aarch64_set_vec_u16 (cpu, vd, i,
5080                                  aarch64_get_vec_u8 (cpu, vn, i + bias)
5081                                  - aarch64_get_vec_u8 (cpu, vm, i + bias));
5082           break;
5083
5084         case 1:
5085           bias *= 2;
5086           for (i = 0; i < 4; i++)
5087             aarch64_set_vec_u32 (cpu, vd, i,
5088                                  aarch64_get_vec_u16 (cpu, vn, i + bias)
5089                                  - aarch64_get_vec_u16 (cpu, vm, i + bias));
5090           break;
5091
5092         case 2:
5093           for (i = 0; i < 2; i++)
5094             aarch64_set_vec_u64 (cpu, vd, i,
5095                                  aarch64_get_vec_u32 (cpu, vn, i + bias)
5096                                  - aarch64_get_vec_u32 (cpu, vm, i + bias));
5097           break;
5098
5099         default:
5100           HALT_UNALLOC;
5101         }
5102       break;
5103     }
5104 }
5105
5106 #define DO_ADDP(FN)                                                     \
5107   do                                                                    \
5108     {                                                                   \
5109       for (i = 0; i < range; i++)                                       \
5110         {                                                               \
5111           aarch64_set_vec_##FN (cpu, vd, i,                             \
5112                                 aarch64_get_vec_##FN (cpu, vn, i * 2)   \
5113                                 + aarch64_get_vec_##FN (cpu, vn, i * 2 + 1)); \
5114           aarch64_set_vec_##FN (cpu, vd, i + range,                     \
5115                                 aarch64_get_vec_##FN (cpu, vm, i * 2)   \
5116                                 + aarch64_get_vec_##FN (cpu, vm, i * 2 + 1)); \
5117         }                                                               \
5118       }                                                                 \
5119     while (0)
5120
5121 static void
5122 do_vec_ADDP (sim_cpu *cpu)
5123 {
5124   /* instr[31]    = 0
5125      instr[30]    = half(0)/full(1)
5126      instr[29,24] = 00 1110
5127      instr[23,22] = size: bytes (00), half (01), word (10), long (11)
5128      instr[21]    = 1
5129      insrt[20,16] = Vm
5130      instr[15,10] = 1011 11
5131      instr[9,5]   = Vn
5132      instr[4,0]   = V dest.  */
5133
5134   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5135   unsigned size = uimm (aarch64_get_instr (cpu), 23, 22);
5136   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5137   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5138   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5139   unsigned i, range;
5140
5141   NYI_assert (29, 24, 0x0E);
5142   NYI_assert (21, 21, 1);
5143   NYI_assert (15, 10, 0x2F);
5144
5145   switch (size)
5146     {
5147     case 0:
5148       range = full ? 8 : 4;
5149       DO_ADDP (u8);
5150       return;
5151
5152     case 1:
5153       range = full ? 4 : 2;
5154       DO_ADDP (u16);
5155       return;
5156
5157     case 2:
5158       range = full ? 2 : 1;
5159       DO_ADDP (u32);
5160       return;
5161
5162     case 3:
5163       if (! full)
5164         HALT_UNALLOC;
5165       range = 1;
5166       DO_ADDP (u64);
5167       return;
5168
5169     default:
5170       HALT_NYI;
5171     }
5172 }
5173
5174 static void
5175 do_vec_UMOV (sim_cpu *cpu)
5176 {
5177   /* instr[31]    = 0
5178      instr[30]    = 32-bit(0)/64-bit(1)
5179      instr[29,21] = 00 1110 000
5180      insrt[20,16] = size & index
5181      instr[15,10] = 0011 11
5182      instr[9,5]   = V source
5183      instr[4,0]   = R dest.  */
5184
5185   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5186   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
5187   unsigned index;
5188
5189   NYI_assert (29, 21, 0x070);
5190   NYI_assert (15, 10, 0x0F);
5191
5192   if (uimm (aarch64_get_instr (cpu), 16, 16))
5193     {
5194       /* Byte transfer.  */
5195       index = uimm (aarch64_get_instr (cpu), 20, 17);
5196       aarch64_set_reg_u64 (cpu, rd, NO_SP,
5197                            aarch64_get_vec_u8 (cpu, vs, index));
5198     }
5199   else if (uimm (aarch64_get_instr (cpu), 17, 17))
5200     {
5201       index = uimm (aarch64_get_instr (cpu), 20, 18);
5202       aarch64_set_reg_u64 (cpu, rd, NO_SP,
5203                            aarch64_get_vec_u16 (cpu, vs, index));
5204     }
5205   else if (uimm (aarch64_get_instr (cpu), 18, 18))
5206     {
5207       index = uimm (aarch64_get_instr (cpu), 20, 19);
5208       aarch64_set_reg_u64 (cpu, rd, NO_SP,
5209                            aarch64_get_vec_u32 (cpu, vs, index));
5210     }
5211   else
5212     {
5213       if (uimm (aarch64_get_instr (cpu), 30, 30) != 1)
5214         HALT_UNALLOC;
5215
5216       index = uimm (aarch64_get_instr (cpu), 20, 20);
5217       aarch64_set_reg_u64 (cpu, rd, NO_SP,
5218                            aarch64_get_vec_u64 (cpu, vs, index));
5219     }
5220 }
5221
5222 static void
5223 do_vec_FABS (sim_cpu *cpu)
5224 {
5225   /* instr[31]    = 0
5226      instr[30]    = half(0)/full(1)
5227      instr[29,23] = 00 1110 1
5228      instr[22]    = float(0)/double(1)
5229      instr[21,16] = 10 0000
5230      instr[15,10] = 1111 10
5231      instr[9,5]   = Vn
5232      instr[4,0]   = Vd.  */
5233
5234   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5235   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5236   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5237   unsigned i;
5238
5239   NYI_assert (29, 23, 0x1D);
5240   NYI_assert (21, 10, 0x83E);
5241
5242   if (uimm (aarch64_get_instr (cpu), 22, 22))
5243     {
5244       if (! full)
5245         HALT_NYI;
5246
5247       for (i = 0; i < 2; i++)
5248         aarch64_set_vec_double (cpu, vd, i,
5249                                 fabs (aarch64_get_vec_double (cpu, vn, i)));
5250     }
5251   else
5252     {
5253       for (i = 0; i < (full ? 4 : 2); i++)
5254         aarch64_set_vec_float (cpu, vd, i,
5255                                fabsf (aarch64_get_vec_float (cpu, vn, i)));
5256     }
5257 }
5258
5259 static void
5260 do_vec_FCVTZS (sim_cpu *cpu)
5261 {
5262   /* instr[31]    = 0
5263      instr[30]    = half (0) / all (1)
5264      instr[29,23] = 00 1110 1
5265      instr[22]    = single (0) / double (1)
5266      instr[21,10] = 10 0001 1011 10
5267      instr[9,5]   = Rn
5268      instr[4,0]   = Rd.  */
5269
5270   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
5271   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
5272   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5273   unsigned i;
5274
5275   NYI_assert (31, 31, 0);
5276   NYI_assert (29, 23, 0x1D);
5277   NYI_assert (21, 10, 0x86E);
5278
5279   if (uimm (aarch64_get_instr (cpu), 22, 22))
5280     {
5281       if (! full)
5282         HALT_UNALLOC;
5283
5284       for (i = 0; i < 2; i++)
5285         aarch64_set_vec_s64 (cpu, rd, i,
5286                              (int64_t) aarch64_get_vec_double (cpu, rn, i));
5287     }
5288   else
5289     for (i = 0; i < (full ? 4 : 2); i++)
5290       aarch64_set_vec_s32 (cpu, rd, i,
5291                            (int32_t) aarch64_get_vec_float (cpu, rn, i));
5292 }
5293
5294 static void
5295 do_vec_op1 (sim_cpu *cpu)
5296 {
5297   /* instr[31]    = 0
5298      instr[30]    = half/full
5299      instr[29,24] = 00 1110
5300      instr[23,21] = ???
5301      instr[20,16] = Vm
5302      instr[15,10] = sub-opcode
5303      instr[9,5]   = Vn
5304      instr[4,0]   = Vd  */
5305   NYI_assert (29, 24, 0x0E);
5306
5307   if (uimm (aarch64_get_instr (cpu), 21, 21) == 0)
5308     {
5309       if (uimm (aarch64_get_instr (cpu), 23, 22) == 0)
5310         {
5311           if (uimm (aarch64_get_instr (cpu), 30, 30) == 1
5312               && uimm (aarch64_get_instr (cpu), 17, 14) == 0
5313               && uimm (aarch64_get_instr (cpu), 12, 10) == 7)
5314             return do_vec_ins_2 (cpu);
5315
5316           switch (uimm (aarch64_get_instr (cpu), 15, 10))
5317             {
5318             case 0x01: do_vec_DUP_vector_into_vector (cpu); return;
5319             case 0x03: do_vec_DUP_scalar_into_vector (cpu); return;
5320             case 0x07: do_vec_INS (cpu); return;
5321             case 0x0A: do_vec_TRN (cpu); return;
5322
5323             case 0x0F:
5324               if (uimm (aarch64_get_instr (cpu), 17, 16) == 0)
5325                 {
5326                   do_vec_MOV_into_scalar (cpu);
5327                   return;
5328                 }
5329               break;
5330
5331             case 0x00:
5332             case 0x08:
5333             case 0x10:
5334             case 0x18:
5335               do_vec_TBL (cpu); return;
5336
5337             case 0x06:
5338             case 0x16:
5339               do_vec_UZP (cpu); return;
5340
5341             case 0x0E:
5342             case 0x1E:
5343               do_vec_ZIP (cpu); return;
5344
5345             default:
5346               HALT_NYI;
5347             }
5348         }
5349
5350       switch (uimm (aarch64_get_instr (cpu), 13, 10))
5351         {
5352         case 0x6: do_vec_UZP (cpu); return;
5353         case 0xE: do_vec_ZIP (cpu); return;
5354         case 0xA: do_vec_TRN (cpu); return;
5355         case 0xF: do_vec_UMOV (cpu); return;
5356         default:  HALT_NYI;
5357         }
5358     }
5359
5360   switch (uimm (aarch64_get_instr (cpu), 15, 10))
5361     {
5362     case 0x07:
5363       switch (uimm (aarch64_get_instr (cpu), 23, 21))
5364         {
5365         case 1: do_vec_AND (cpu); return;
5366         case 3: do_vec_BIC (cpu); return;
5367         case 5: do_vec_ORR (cpu); return;
5368         case 7: do_vec_ORN (cpu); return;
5369         default: HALT_NYI;
5370         }
5371
5372     case 0x08: do_vec_sub_long (cpu); return;
5373     case 0x0a: do_vec_XTN (cpu); return;
5374     case 0x11: do_vec_SSHL (cpu); return;
5375     case 0x19: do_vec_max (cpu); return;
5376     case 0x1B: do_vec_min (cpu); return;
5377     case 0x21: do_vec_add (cpu); return;
5378     case 0x25: do_vec_MLA (cpu); return;
5379     case 0x27: do_vec_mul (cpu); return;
5380     case 0x2F: do_vec_ADDP (cpu); return;
5381     case 0x30: do_vec_mull (cpu); return;
5382     case 0x33: do_vec_FMLA (cpu); return;
5383     case 0x35: do_vec_fadd (cpu); return;
5384
5385     case 0x2E:
5386       switch (uimm (aarch64_get_instr (cpu), 20, 16))
5387         {
5388         case 0x00: do_vec_ABS (cpu); return;
5389         case 0x01: do_vec_FCVTZS (cpu); return;
5390         case 0x11: do_vec_ADDV (cpu); return;
5391         default: HALT_NYI;
5392         }
5393
5394     case 0x31:
5395     case 0x3B:
5396       do_vec_Fminmax (cpu); return;
5397
5398     case 0x0D:
5399     case 0x0F:
5400     case 0x22:
5401     case 0x23:
5402     case 0x26:
5403     case 0x2A:
5404     case 0x32:
5405     case 0x36:
5406     case 0x39:
5407     case 0x3A:
5408       do_vec_compare (cpu); return;
5409
5410     case 0x3E:
5411       do_vec_FABS (cpu); return;
5412
5413     default:
5414       HALT_NYI;
5415     }
5416 }
5417
5418 static void
5419 do_vec_xtl (sim_cpu *cpu)
5420 {
5421   /* instr[31]    = 0
5422      instr[30,29] = SXTL (00), UXTL (01), SXTL2 (10), UXTL2 (11)
5423      instr[28,22] = 0 1111 00
5424      instr[21,16] = size & shift (USHLL, SSHLL, USHLL2, SSHLL2)
5425      instr[15,10] = 1010 01
5426      instr[9,5]   = V source
5427      instr[4,0]   = V dest.  */
5428
5429   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5430   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5431   unsigned i, shift, bias = 0;
5432
5433   NYI_assert (28, 22, 0x3C);
5434   NYI_assert (15, 10, 0x29);
5435
5436   switch (uimm (aarch64_get_instr (cpu), 30, 29))
5437     {
5438     case 2: /* SXTL2, SSHLL2.  */
5439       bias = 2;
5440     case 0: /* SXTL, SSHLL.  */
5441       if (uimm (aarch64_get_instr (cpu), 21, 21))
5442         {
5443           shift = uimm (aarch64_get_instr (cpu), 20, 16);
5444           aarch64_set_vec_s64
5445             (cpu, vd, 0, aarch64_get_vec_s32 (cpu, vs, bias) << shift);
5446           aarch64_set_vec_s64
5447             (cpu, vd, 1, aarch64_get_vec_s32 (cpu, vs, bias + 1) << shift);
5448         }
5449       else if (uimm (aarch64_get_instr (cpu), 20, 20))
5450         {
5451           shift = uimm (aarch64_get_instr (cpu), 19, 16);
5452           bias *= 2;
5453           for (i = 0; i < 4; i++)
5454             aarch64_set_vec_s32
5455               (cpu, vd, i, aarch64_get_vec_s16 (cpu, vs, i + bias) << shift);
5456         }
5457       else
5458         {
5459           NYI_assert (19, 19, 1);
5460
5461           shift = uimm (aarch64_get_instr (cpu), 18, 16);
5462           bias *= 3;
5463           for (i = 0; i < 8; i++)
5464             aarch64_set_vec_s16
5465               (cpu, vd, i, aarch64_get_vec_s8 (cpu, vs, i + bias) << shift);
5466         }
5467       return;
5468
5469     case 3: /* UXTL2, USHLL2.  */
5470       bias = 2;
5471     case 1: /* UXTL, USHLL.  */
5472       if (uimm (aarch64_get_instr (cpu), 21, 21))
5473         {
5474           shift = uimm (aarch64_get_instr (cpu), 20, 16);
5475           aarch64_set_vec_u64
5476             (cpu, vd, 0, aarch64_get_vec_u32 (cpu, vs, bias) << shift);
5477           aarch64_set_vec_u64
5478             (cpu, vd, 1, aarch64_get_vec_u32 (cpu, vs, bias + 1) << shift);
5479         }
5480       else if (uimm (aarch64_get_instr (cpu), 20, 20))
5481         {
5482           shift = uimm (aarch64_get_instr (cpu), 19, 16);
5483           bias *= 2;
5484           for (i = 0; i < 4; i++)
5485             aarch64_set_vec_u32
5486               (cpu, vd, i, aarch64_get_vec_u16 (cpu, vs, i + bias) << shift);
5487         }
5488       else
5489         {
5490           NYI_assert (19, 19, 1);
5491
5492           shift = uimm (aarch64_get_instr (cpu), 18, 16);
5493           bias *= 3;
5494           for (i = 0; i < 8; i++)
5495             aarch64_set_vec_u16
5496               (cpu, vd, i, aarch64_get_vec_u8 (cpu, vs, i + bias) << shift);
5497         }
5498       return;
5499
5500     default:
5501       HALT_NYI;
5502     }
5503 }
5504
5505 static void
5506 do_vec_SHL (sim_cpu *cpu)
5507 {
5508   /* instr [31]    = 0
5509      instr [30]    = half(0)/full(1)
5510      instr [29,23] = 001 1110
5511      instr [22,16] = size and shift amount
5512      instr [15,10] = 01 0101
5513      instr [9, 5]  = Vs
5514      instr [4, 0]  = Vd.  */
5515
5516   int shift;
5517   int full = uimm (aarch64_get_instr (cpu), 30, 30);
5518   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5519   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5520   unsigned i;
5521
5522   NYI_assert (29, 23, 0x1E);
5523   NYI_assert (15, 10, 0x15);
5524
5525   if (uimm (aarch64_get_instr (cpu), 22, 22))
5526     {
5527       shift = uimm (aarch64_get_instr (cpu), 21, 16) - 1;
5528
5529       if (full == 0)
5530         HALT_UNALLOC;
5531
5532       for (i = 0; i < 2; i++)
5533         {
5534           uint64_t val = aarch64_get_vec_u64 (cpu, vs, i);
5535           aarch64_set_vec_u64 (cpu, vd, i, val << shift);
5536         }
5537
5538       return;
5539     }
5540
5541   if (uimm (aarch64_get_instr (cpu), 21, 21))
5542     {
5543       shift = uimm (aarch64_get_instr (cpu), 20, 16) - 1;
5544
5545       for (i = 0; i < (full ? 4 : 2); i++)
5546         {
5547           uint32_t val = aarch64_get_vec_u32 (cpu, vs, i);
5548           aarch64_set_vec_u32 (cpu, vd, i, val << shift);
5549         }
5550
5551       return;
5552     }
5553
5554   if (uimm (aarch64_get_instr (cpu), 20, 20))
5555     {
5556       shift = uimm (aarch64_get_instr (cpu), 19, 16) - 1;
5557
5558       for (i = 0; i < (full ? 8 : 4); i++)
5559         {
5560           uint16_t val = aarch64_get_vec_u16 (cpu, vs, i);
5561           aarch64_set_vec_u16 (cpu, vd, i, val << shift);
5562         }
5563
5564       return;
5565     }
5566
5567   if (uimm (aarch64_get_instr (cpu), 19, 19) == 0)
5568     HALT_UNALLOC;
5569
5570   shift = uimm (aarch64_get_instr (cpu), 18, 16) - 1;
5571
5572   for (i = 0; i < (full ? 16 : 8); i++)
5573     {
5574       uint8_t val = aarch64_get_vec_u8 (cpu, vs, i);
5575       aarch64_set_vec_u8 (cpu, vd, i, val << shift);
5576     }
5577 }
5578
5579 static void
5580 do_vec_SSHR_USHR (sim_cpu *cpu)
5581 {
5582   /* instr [31]    = 0
5583      instr [30]    = half(0)/full(1)
5584      instr [29]    = signed(0)/unsigned(1)
5585      instr [28,23] = 01 1110
5586      instr [22,16] = size and shift amount
5587      instr [15,10] = 0000 01
5588      instr [9, 5]  = Vs
5589      instr [4, 0]  = Vd.  */
5590
5591   int shift;
5592   int full = uimm (aarch64_get_instr (cpu), 30, 30);
5593   int sign = uimm (aarch64_get_instr (cpu), 29, 29);
5594   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5595   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5596   unsigned i;
5597
5598   NYI_assert (28, 23, 0x1E);
5599   NYI_assert (15, 10, 0x01);
5600
5601   if (uimm (aarch64_get_instr (cpu), 22, 22))
5602     {
5603       shift = uimm (aarch64_get_instr (cpu), 21, 16);
5604
5605       if (full == 0)
5606         HALT_UNALLOC;
5607
5608       if (sign)
5609         for (i = 0; i < 2; i++)
5610           {
5611             int64_t val = aarch64_get_vec_s64 (cpu, vs, i);
5612             aarch64_set_vec_s64 (cpu, vd, i, val >> shift);
5613           }
5614       else
5615         for (i = 0; i < 2; i++)
5616           {
5617             uint64_t val = aarch64_get_vec_u64 (cpu, vs, i);
5618             aarch64_set_vec_u64 (cpu, vd, i, val >> shift);
5619           }
5620
5621       return;
5622     }
5623
5624   if (uimm (aarch64_get_instr (cpu), 21, 21))
5625     {
5626       shift = uimm (aarch64_get_instr (cpu), 20, 16);
5627
5628       if (sign)
5629         for (i = 0; i < (full ? 4 : 2); i++)
5630           {
5631             int32_t val = aarch64_get_vec_s32 (cpu, vs, i);
5632             aarch64_set_vec_s32 (cpu, vd, i, val >> shift);
5633           }
5634       else
5635         for (i = 0; i < (full ? 4 : 2); i++)
5636           {
5637             uint32_t val = aarch64_get_vec_u32 (cpu, vs, i);
5638             aarch64_set_vec_u32 (cpu, vd, i, val >> shift);
5639           }
5640
5641       return;
5642     }
5643
5644   if (uimm (aarch64_get_instr (cpu), 20, 20))
5645     {
5646       shift = uimm (aarch64_get_instr (cpu), 19, 16);
5647
5648       if (sign)
5649         for (i = 0; i < (full ? 8 : 4); i++)
5650           {
5651             int16_t val = aarch64_get_vec_s16 (cpu, vs, i);
5652             aarch64_set_vec_s16 (cpu, vd, i, val >> shift);
5653           }
5654       else
5655         for (i = 0; i < (full ? 8 : 4); i++)
5656           {
5657             uint16_t val = aarch64_get_vec_u16 (cpu, vs, i);
5658             aarch64_set_vec_u16 (cpu, vd, i, val >> shift);
5659           }
5660
5661       return;
5662     }
5663
5664   if (uimm (aarch64_get_instr (cpu), 19, 19) == 0)
5665     HALT_UNALLOC;
5666
5667   shift = uimm (aarch64_get_instr (cpu), 18, 16);
5668
5669   if (sign)
5670     for (i = 0; i < (full ? 16 : 8); i++)
5671       {
5672         int8_t val = aarch64_get_vec_s8 (cpu, vs, i);
5673         aarch64_set_vec_s8 (cpu, vd, i, val >> shift);
5674       }
5675   else
5676     for (i = 0; i < (full ? 16 : 8); i++)
5677       {
5678         uint8_t val = aarch64_get_vec_u8 (cpu, vs, i);
5679         aarch64_set_vec_u8 (cpu, vd, i, val >> shift);
5680       }
5681 }
5682
5683 static void
5684 do_vec_op2 (sim_cpu *cpu)
5685 {
5686   /* instr[31]    = 0
5687      instr[30]    = half/full
5688      instr[29,24] = 00 1111
5689      instr[23]    = ?
5690      instr[22,16] = element size & index
5691      instr[15,10] = sub-opcode
5692      instr[9,5]   = Vm
5693      instr[4.0]   = Vd  */
5694
5695   NYI_assert (29, 24, 0x0F);
5696
5697   if (uimm (aarch64_get_instr (cpu), 23, 23) != 0)
5698     HALT_NYI;
5699
5700   switch (uimm (aarch64_get_instr (cpu), 15, 10))
5701     {
5702     case 0x01: do_vec_SSHR_USHR (cpu); return;
5703     case 0x15: do_vec_SHL (cpu); return;
5704     case 0x29: do_vec_xtl (cpu); return;
5705     default:   HALT_NYI;
5706     }
5707 }
5708
5709 static void
5710 do_vec_neg (sim_cpu *cpu)
5711 {
5712   /* instr[31]    = 0
5713      instr[30]    = full(1)/half(0)
5714      instr[29,24] = 10 1110
5715      instr[23,22] = size: byte(00), half (01), word (10), long (11)
5716      instr[21,10] = 1000 0010 1110
5717      instr[9,5]   = Vs
5718      instr[4,0]   = Vd  */
5719
5720   int    full = uimm (aarch64_get_instr (cpu), 30, 30);
5721   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5722   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5723   unsigned i;
5724
5725   NYI_assert (29, 24, 0x2E);
5726   NYI_assert (21, 10, 0x82E);
5727
5728   switch (uimm (aarch64_get_instr (cpu), 23, 22))
5729     {
5730     case 0:
5731       for (i = 0; i < (full ? 16 : 8); i++)
5732         aarch64_set_vec_s8 (cpu, vd, i, - aarch64_get_vec_s8 (cpu, vs, i));
5733       return;
5734
5735     case 1:
5736       for (i = 0; i < (full ? 8 : 4); i++)
5737         aarch64_set_vec_s16 (cpu, vd, i, - aarch64_get_vec_s16 (cpu, vs, i));
5738       return;
5739
5740     case 2:
5741       for (i = 0; i < (full ? 4 : 2); i++)
5742         aarch64_set_vec_s32 (cpu, vd, i, - aarch64_get_vec_s32 (cpu, vs, i));
5743       return;
5744
5745     case 3:
5746       if (! full)
5747         HALT_NYI;
5748       for (i = 0; i < 2; i++)
5749         aarch64_set_vec_s64 (cpu, vd, i, - aarch64_get_vec_s64 (cpu, vs, i));
5750       return;
5751
5752     default:
5753       HALT_UNREACHABLE;
5754     }
5755 }
5756
5757 static void
5758 do_vec_sqrt (sim_cpu *cpu)
5759 {
5760   /* instr[31]    = 0
5761      instr[30]    = full(1)/half(0)
5762      instr[29,23] = 101 1101
5763      instr[22]    = single(0)/double(1)
5764      instr[21,10] = 1000 0111 1110
5765      instr[9,5]   = Vs
5766      instr[4,0]   = Vd.  */
5767
5768   int    full = uimm (aarch64_get_instr (cpu), 30, 30);
5769   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5770   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5771   unsigned i;
5772
5773   NYI_assert (29, 23, 0x5B);
5774   NYI_assert (21, 10, 0x87E);
5775
5776   if (uimm (aarch64_get_instr (cpu), 22, 22) == 0)
5777     for (i = 0; i < (full ? 4 : 2); i++)
5778       aarch64_set_vec_float (cpu, vd, i,
5779                              sqrtf (aarch64_get_vec_float (cpu, vs, i)));
5780   else
5781     for (i = 0; i < 2; i++)
5782       aarch64_set_vec_double (cpu, vd, i,
5783                               sqrt (aarch64_get_vec_double (cpu, vs, i)));
5784 }
5785
5786 static void
5787 do_vec_mls_indexed (sim_cpu *cpu)
5788 {
5789   /* instr[31]       = 0
5790      instr[30]       = half(0)/full(1)
5791      instr[29,24]    = 10 1111
5792      instr[23,22]    = 16-bit(01)/32-bit(10)
5793      instr[21,20+11] = index (if 16-bit)
5794      instr[21+11]    = index (if 32-bit)
5795      instr[20,16]    = Vm
5796      instr[15,12]    = 0100
5797      instr[11]       = part of index
5798      instr[10]       = 0
5799      instr[9,5]      = Vs
5800      instr[4,0]      = Vd.  */
5801
5802   int    full = uimm (aarch64_get_instr (cpu), 30, 30);
5803   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5804   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5805   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5806   unsigned i;
5807
5808   NYI_assert (15, 12, 4);
5809   NYI_assert (10, 10, 0);
5810
5811   switch (uimm (aarch64_get_instr (cpu), 23, 22))
5812     {
5813     case 1:
5814       {
5815         unsigned elem;
5816         uint32_t val;
5817
5818         if (vm > 15)
5819           HALT_NYI;
5820
5821         elem = (uimm (aarch64_get_instr (cpu), 21, 20) << 1)
5822           | uimm (aarch64_get_instr (cpu), 11, 11);
5823         val = aarch64_get_vec_u16 (cpu, vm, elem);
5824
5825         for (i = 0; i < (full ? 8 : 4); i++)
5826           aarch64_set_vec_u32 (cpu, vd, i,
5827                                aarch64_get_vec_u32 (cpu, vd, i) -
5828                                (aarch64_get_vec_u32 (cpu, vs, i) * val));
5829         return;
5830       }
5831
5832     case 2:
5833       {
5834         unsigned elem = (uimm (aarch64_get_instr (cpu), 21, 21) << 1)
5835           | uimm (aarch64_get_instr (cpu), 11, 11);
5836         uint64_t val = aarch64_get_vec_u32 (cpu, vm, elem);
5837
5838         for (i = 0; i < (full ? 4 : 2); i++)
5839           aarch64_set_vec_u64 (cpu, vd, i,
5840                                aarch64_get_vec_u64 (cpu, vd, i) -
5841                                (aarch64_get_vec_u64 (cpu, vs, i) * val));
5842         return;
5843       }
5844
5845     case 0:
5846     case 3:
5847     default:
5848       HALT_NYI;
5849     }
5850 }
5851
5852 static void
5853 do_vec_SUB (sim_cpu *cpu)
5854 {
5855   /* instr [31]    = 0
5856      instr [30]    = half(0)/full(1)
5857      instr [29,24] = 10 1110
5858      instr [23,22] = size: byte(00, half(01), word (10), long (11)
5859      instr [21]    = 1
5860      instr [20,16] = Vm
5861      instr [15,10] = 10 0001
5862      instr [9, 5]  = Vn
5863      instr [4, 0]  = Vd.  */
5864
5865   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5866   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5867   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5868   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5869   unsigned i;
5870
5871   NYI_assert (29, 24, 0x2E);
5872   NYI_assert (21, 21, 1);
5873   NYI_assert (15, 10, 0x21);
5874
5875   switch (uimm (aarch64_get_instr (cpu), 23, 22))
5876     {
5877     case 0:
5878       for (i = 0; i < (full ? 16 : 8); i++)
5879         aarch64_set_vec_s8 (cpu, vd, i,
5880                             aarch64_get_vec_s8 (cpu, vn, i)
5881                             - aarch64_get_vec_s8 (cpu, vm, i));
5882       return;
5883
5884     case 1:
5885       for (i = 0; i < (full ? 8 : 4); i++)
5886         aarch64_set_vec_s16 (cpu, vd, i,
5887                              aarch64_get_vec_s16 (cpu, vn, i)
5888                              - aarch64_get_vec_s16 (cpu, vm, i));
5889       return;
5890
5891     case 2:
5892       for (i = 0; i < (full ? 4 : 2); i++)
5893         aarch64_set_vec_s32 (cpu, vd, i,
5894                              aarch64_get_vec_s32 (cpu, vn, i)
5895                              - aarch64_get_vec_s32 (cpu, vm, i));
5896       return;
5897
5898     case 3:
5899       if (full == 0)
5900         HALT_UNALLOC;
5901
5902       for (i = 0; i < 2; i++)
5903         aarch64_set_vec_s64 (cpu, vd, i,
5904                              aarch64_get_vec_s64 (cpu, vn, i)
5905                              - aarch64_get_vec_s64 (cpu, vm, i));
5906       return;
5907
5908     default:
5909       HALT_UNREACHABLE;
5910     }
5911 }
5912
5913 static void
5914 do_vec_MLS (sim_cpu *cpu)
5915 {
5916   /* instr [31]    = 0
5917      instr [30]    = half(0)/full(1)
5918      instr [29,24] = 10 1110
5919      instr [23,22] = size: byte(00, half(01), word (10)
5920      instr [21]    = 1
5921      instr [20,16] = Vm
5922      instr [15,10] = 10 0101
5923      instr [9, 5]  = Vn
5924      instr [4, 0]  = Vd.  */
5925
5926   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5927   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5928   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5929   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5930   unsigned i;
5931
5932   NYI_assert (29, 24, 0x2E);
5933   NYI_assert (21, 21, 1);
5934   NYI_assert (15, 10, 0x25);
5935
5936   switch (uimm (aarch64_get_instr (cpu), 23, 22))
5937     {
5938     case 0:
5939       for (i = 0; i < (full ? 16 : 8); i++)
5940         aarch64_set_vec_u8 (cpu, vd, i,
5941                             (aarch64_get_vec_u8 (cpu, vn, i)
5942                              * aarch64_get_vec_u8 (cpu, vm, i))
5943                             - aarch64_get_vec_u8 (cpu, vd, i));
5944       return;
5945
5946     case 1:
5947       for (i = 0; i < (full ? 8 : 4); i++)
5948         aarch64_set_vec_u16 (cpu, vd, i,
5949                              (aarch64_get_vec_u16 (cpu, vn, i)
5950                               * aarch64_get_vec_u16 (cpu, vm, i))
5951                              - aarch64_get_vec_u16 (cpu, vd, i));
5952       return;
5953
5954     case 2:
5955       for (i = 0; i < (full ? 4 : 2); i++)
5956         aarch64_set_vec_u32 (cpu, vd, i,
5957                              (aarch64_get_vec_u32 (cpu, vn, i)
5958                               * aarch64_get_vec_u32 (cpu, vm, i))
5959                              - aarch64_get_vec_u32 (cpu, vd, i));
5960       return;
5961
5962     default:
5963       HALT_UNALLOC;
5964     }
5965 }
5966
5967 static void
5968 do_vec_FDIV (sim_cpu *cpu)
5969 {
5970   /* instr [31]    = 0
5971      instr [30]    = half(0)/full(1)
5972      instr [29,23] = 10 1110 0
5973      instr [22]    = float()/double(1)
5974      instr [21]    = 1
5975      instr [20,16] = Vm
5976      instr [15,10] = 1111 11
5977      instr [9, 5]  = Vn
5978      instr [4, 0]  = Vd.  */
5979
5980   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5981   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5982   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5983   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5984   unsigned i;
5985
5986   NYI_assert (29, 23, 0x5C);
5987   NYI_assert (21, 21, 1);
5988   NYI_assert (15, 10, 0x3F);
5989
5990   if (uimm (aarch64_get_instr (cpu), 22, 22))
5991     {
5992       if (! full)
5993         HALT_UNALLOC;
5994
5995       for (i = 0; i < 2; i++)
5996         aarch64_set_vec_double (cpu, vd, i,
5997                                 aarch64_get_vec_double (cpu, vn, i)
5998                                 / aarch64_get_vec_double (cpu, vm, i));
5999     }
6000   else
6001     for (i = 0; i < (full ? 4 : 2); i++)
6002       aarch64_set_vec_float (cpu, vd, i,
6003                              aarch64_get_vec_float (cpu, vn, i)
6004                              / aarch64_get_vec_float (cpu, vm, i));
6005 }
6006
6007 static void
6008 do_vec_FMUL (sim_cpu *cpu)
6009 {
6010   /* instr [31]    = 0
6011      instr [30]    = half(0)/full(1)
6012      instr [29,23] = 10 1110 0
6013      instr [22]    = float(0)/double(1)
6014      instr [21]    = 1
6015      instr [20,16] = Vm
6016      instr [15,10] = 1101 11
6017      instr [9, 5]  = Vn
6018      instr [4, 0]  = Vd.  */
6019
6020   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6021   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
6022   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6023   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6024   unsigned i;
6025
6026   NYI_assert (29, 23, 0x5C);
6027   NYI_assert (21, 21, 1);
6028   NYI_assert (15, 10, 0x37);
6029
6030   if (uimm (aarch64_get_instr (cpu), 22, 22))
6031     {
6032       if (! full)
6033         HALT_UNALLOC;
6034
6035       for (i = 0; i < 2; i++)
6036         aarch64_set_vec_double (cpu, vd, i,
6037                                 aarch64_get_vec_double (cpu, vn, i)
6038                                 * aarch64_get_vec_double (cpu, vm, i));
6039     }
6040   else
6041     for (i = 0; i < (full ? 4 : 2); i++)
6042       aarch64_set_vec_float (cpu, vd, i,
6043                              aarch64_get_vec_float (cpu, vn, i)
6044                              * aarch64_get_vec_float (cpu, vm, i));
6045 }
6046
6047 static void
6048 do_vec_FADDP (sim_cpu *cpu)
6049 {
6050   /* instr [31]    = 0
6051      instr [30]    = half(0)/full(1)
6052      instr [29,23] = 10 1110 0
6053      instr [22]    = float(0)/double(1)
6054      instr [21]    = 1
6055      instr [20,16] = Vm
6056      instr [15,10] = 1101 01
6057      instr [9, 5]  = Vn
6058      instr [4, 0]  = Vd.  */
6059
6060   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6061   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
6062   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6063   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6064
6065   NYI_assert (29, 23, 0x5C);
6066   NYI_assert (21, 21, 1);
6067   NYI_assert (15, 10, 0x35);
6068
6069   if (uimm (aarch64_get_instr (cpu), 22, 22))
6070     {
6071       if (! full)
6072         HALT_UNALLOC;
6073
6074       aarch64_set_vec_double (cpu, vd, 0, aarch64_get_vec_double (cpu, vn, 0)
6075                               + aarch64_get_vec_double (cpu, vn, 1));
6076       aarch64_set_vec_double (cpu, vd, 1, aarch64_get_vec_double (cpu, vm, 0)
6077                               + aarch64_get_vec_double (cpu, vm, 1));
6078     }
6079   else
6080     {
6081       aarch64_set_vec_float (cpu, vd, 0, aarch64_get_vec_float (cpu, vn, 0)
6082                              + aarch64_get_vec_float (cpu, vn, 1));
6083       if (full)
6084         aarch64_set_vec_float (cpu, vd, 1, aarch64_get_vec_float (cpu, vn, 2)
6085                                + aarch64_get_vec_float (cpu, vn, 3));
6086       aarch64_set_vec_float (cpu, vd, full ? 2 : 1,
6087                              aarch64_get_vec_float (cpu, vm, 0)
6088                              + aarch64_get_vec_float (cpu, vm, 1));
6089       if (full)
6090         aarch64_set_vec_float (cpu, vd, 3,
6091                                aarch64_get_vec_float (cpu, vm, 2)
6092                                + aarch64_get_vec_float (cpu, vm, 3));
6093     }
6094 }
6095
6096 static void
6097 do_vec_FSQRT (sim_cpu *cpu)
6098 {
6099   /* instr[31]    = 0
6100      instr[30]    = half(0)/full(1)
6101      instr[29,23] = 10 1110 1
6102      instr[22]    = single(0)/double(1)
6103      instr[21,10] = 10 0001 1111 10
6104      instr[9,5]   = Vsrc
6105      instr[4,0]   = Vdest.  */
6106
6107   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6108   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6109   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6110   int i;
6111
6112   NYI_assert (29, 23, 0x5D);
6113   NYI_assert (21, 10, 0x87E);
6114
6115   if (uimm (aarch64_get_instr (cpu), 22, 22))
6116     {
6117       if (! full)
6118         HALT_UNALLOC;
6119
6120       for (i = 0; i < 2; i++)
6121         aarch64_set_vec_double (cpu, vd, i,
6122                                 sqrt (aarch64_get_vec_double (cpu, vn, i)));
6123     }
6124   else
6125     {
6126       for (i = 0; i < (full ? 4 : 2); i++)
6127         aarch64_set_vec_float (cpu, vd, i,
6128                                sqrtf (aarch64_get_vec_float (cpu, vn, i)));
6129     }
6130 }
6131
6132 static void
6133 do_vec_FNEG (sim_cpu *cpu)
6134 {
6135   /* instr[31]    = 0
6136      instr[30]    = half (0)/full (1)
6137      instr[29,23] = 10 1110 1
6138      instr[22]    = single (0)/double (1)
6139      instr[21,10] = 10 0000 1111 10
6140      instr[9,5]   = Vsrc
6141      instr[4,0]   = Vdest.  */
6142
6143   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6144   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6145   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6146   int i;
6147
6148   NYI_assert (29, 23, 0x5D);
6149   NYI_assert (21, 10, 0x83E);
6150
6151   if (uimm (aarch64_get_instr (cpu), 22, 22))
6152     {
6153       if (! full)
6154         HALT_UNALLOC;
6155
6156       for (i = 0; i < 2; i++)
6157         aarch64_set_vec_double (cpu, vd, i,
6158                                 - aarch64_get_vec_double (cpu, vn, i));
6159     }
6160   else
6161     {
6162       for (i = 0; i < (full ? 4 : 2); i++)
6163         aarch64_set_vec_float (cpu, vd, i,
6164                                - aarch64_get_vec_float (cpu, vn, i));
6165     }
6166 }
6167
6168 static void
6169 do_vec_NOT (sim_cpu *cpu)
6170 {
6171   /* instr[31]    = 0
6172      instr[30]    = half (0)/full (1)
6173      instr[29,21] = 10 1110 001
6174      instr[20,16] = 0 0000
6175      instr[15,10] = 0101 10
6176      instr[9,5]   = Vn
6177      instr[4.0]   = Vd.  */
6178
6179   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6180   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6181   unsigned i;
6182   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
6183
6184   NYI_assert (29, 10, 0xB8816);
6185
6186   for (i = 0; i < (full ? 16 : 8); i++)
6187     aarch64_set_vec_u8 (cpu, vd, i, ~ aarch64_get_vec_u8 (cpu, vn, i));
6188 }
6189
6190 static void
6191 do_vec_MOV_element (sim_cpu *cpu)
6192 {
6193   /* instr[31,21] = 0110 1110 000
6194      instr[20,16] = size & dest index
6195      instr[15]    = 0
6196      instr[14,11] = source index
6197      instr[10]    = 1
6198      instr[9,5]   = Vs
6199      instr[4.0]   = Vd.  */
6200
6201   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
6202   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6203   unsigned src_index;
6204   unsigned dst_index;
6205
6206   NYI_assert (31, 21, 0x370);
6207   NYI_assert (15, 15, 0);
6208   NYI_assert (10, 10, 1);
6209
6210   if (uimm (aarch64_get_instr (cpu), 16, 16))
6211     {
6212       /* Move a byte.  */
6213       src_index = uimm (aarch64_get_instr (cpu), 14, 11);
6214       dst_index = uimm (aarch64_get_instr (cpu), 20, 17);
6215       aarch64_set_vec_u8 (cpu, vd, dst_index,
6216                           aarch64_get_vec_u8 (cpu, vs, src_index));
6217     }
6218   else if (uimm (aarch64_get_instr (cpu), 17, 17))
6219     {
6220       /* Move 16-bits.  */
6221       NYI_assert (11, 11, 0);
6222       src_index = uimm (aarch64_get_instr (cpu), 14, 12);
6223       dst_index = uimm (aarch64_get_instr (cpu), 20, 18);
6224       aarch64_set_vec_u16 (cpu, vd, dst_index,
6225                            aarch64_get_vec_u16 (cpu, vs, src_index));
6226     }
6227   else if (uimm (aarch64_get_instr (cpu), 18, 18))
6228     {
6229       /* Move 32-bits.  */
6230       NYI_assert (12, 11, 0);
6231       src_index = uimm (aarch64_get_instr (cpu), 14, 13);
6232       dst_index = uimm (aarch64_get_instr (cpu), 20, 19);
6233       aarch64_set_vec_u32 (cpu, vd, dst_index,
6234                            aarch64_get_vec_u32 (cpu, vs, src_index));
6235     }
6236   else
6237     {
6238       NYI_assert (19, 19, 1);
6239       NYI_assert (13, 11, 0);
6240       src_index = uimm (aarch64_get_instr (cpu), 14, 14);
6241       dst_index = uimm (aarch64_get_instr (cpu), 20, 20);
6242       aarch64_set_vec_u64 (cpu, vd, dst_index,
6243                            aarch64_get_vec_u64 (cpu, vs, src_index));
6244     }
6245 }
6246
6247 static void
6248 dexAdvSIMD0 (sim_cpu *cpu)
6249 {
6250   /* instr [28,25] = 0 111.  */
6251   if (    uimm (aarch64_get_instr (cpu), 15, 10) == 0x07
6252       && (uimm (aarch64_get_instr (cpu), 9, 5) ==
6253           uimm (aarch64_get_instr (cpu), 20, 16)))
6254     {
6255       if (uimm (aarch64_get_instr (cpu), 31, 21) == 0x075
6256           || uimm (aarch64_get_instr (cpu), 31, 21) == 0x275)
6257         {
6258           do_vec_MOV_whole_vector (cpu);
6259           return;
6260         }
6261     }
6262
6263   if (uimm (aarch64_get_instr (cpu), 29, 19) == 0x1E0)
6264     {
6265       do_vec_MOV_immediate (cpu);
6266       return;
6267     }
6268
6269   if (uimm (aarch64_get_instr (cpu), 29, 19) == 0x5E0)
6270     {
6271       do_vec_MVNI (cpu);
6272       return;
6273     }
6274
6275   if (uimm (aarch64_get_instr (cpu), 29, 19) == 0x1C0
6276       || uimm (aarch64_get_instr (cpu), 29, 19) == 0x1C1)
6277     {
6278       if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x03)
6279         {
6280           do_vec_DUP_scalar_into_vector (cpu);
6281           return;
6282         }
6283     }
6284
6285   switch (uimm (aarch64_get_instr (cpu), 29, 24))
6286     {
6287     case 0x0E: do_vec_op1 (cpu); return;
6288     case 0x0F: do_vec_op2 (cpu); return;
6289
6290     case 0x2f:
6291       switch (uimm (aarch64_get_instr (cpu), 15, 10))
6292         {
6293         case 0x01: do_vec_SSHR_USHR (cpu); return;
6294         case 0x10:
6295         case 0x12: do_vec_mls_indexed (cpu); return;
6296         case 0x29: do_vec_xtl (cpu); return;
6297         default:
6298           HALT_NYI;
6299         }
6300
6301     case 0x2E:
6302       if (uimm (aarch64_get_instr (cpu), 21, 21) == 1)
6303         {
6304           switch (uimm (aarch64_get_instr (cpu), 15, 10))
6305             {
6306             case 0x07:
6307               switch (uimm (aarch64_get_instr (cpu), 23, 22))
6308                 {
6309                 case 0: do_vec_EOR (cpu); return;
6310                 case 1: do_vec_BSL (cpu); return;
6311                 case 2:
6312                 case 3: do_vec_bit (cpu); return;
6313                 }
6314               break;
6315
6316             case 0x08: do_vec_sub_long (cpu); return;
6317             case 0x11: do_vec_USHL (cpu); return;
6318             case 0x16: do_vec_NOT (cpu); return;
6319             case 0x19: do_vec_max (cpu); return;
6320             case 0x1B: do_vec_min (cpu); return;
6321             case 0x21: do_vec_SUB (cpu); return;
6322             case 0x25: do_vec_MLS (cpu); return;
6323             case 0x31: do_vec_FminmaxNMP (cpu); return;
6324             case 0x35: do_vec_FADDP (cpu); return;
6325             case 0x37: do_vec_FMUL (cpu); return;
6326             case 0x3F: do_vec_FDIV (cpu); return;
6327
6328             case 0x3E:
6329               switch (uimm (aarch64_get_instr (cpu), 20, 16))
6330                 {
6331                 case 0x00: do_vec_FNEG (cpu); return;
6332                 case 0x01: do_vec_FSQRT (cpu); return;
6333                 default:   HALT_NYI;
6334                 }
6335
6336             case 0x0D:
6337             case 0x0F:
6338             case 0x22:
6339             case 0x23:
6340             case 0x26:
6341             case 0x2A:
6342             case 0x32:
6343             case 0x36:
6344             case 0x39:
6345             case 0x3A:
6346               do_vec_compare (cpu); return;
6347
6348             default: break;
6349             }
6350         }
6351
6352       if (uimm (aarch64_get_instr (cpu), 31, 21) == 0x370)
6353         {
6354           do_vec_MOV_element (cpu);
6355           return;
6356         }
6357
6358       switch (uimm (aarch64_get_instr (cpu), 21, 10))
6359         {
6360         case 0x82E: do_vec_neg (cpu); return;
6361         case 0x87E: do_vec_sqrt (cpu); return;
6362         default:
6363           if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x30)
6364             {
6365               do_vec_mull (cpu);
6366               return;
6367             }
6368           break;
6369         }
6370       break;
6371
6372     default:
6373       break;
6374     }
6375
6376   HALT_NYI;
6377 }
6378
6379 /* 3 sources.  */
6380
6381 /* Float multiply add.  */
6382 static void
6383 fmadds (sim_cpu *cpu)
6384 {
6385   unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6386   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6387   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6388   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6389
6390   aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sa)
6391                         + aarch64_get_FP_float (cpu, sn)
6392                         * aarch64_get_FP_float (cpu, sm));
6393 }
6394
6395 /* Double multiply add.  */
6396 static void
6397 fmaddd (sim_cpu *cpu)
6398 {
6399   unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6400   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6401   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6402   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6403
6404   aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sa)
6405                          + aarch64_get_FP_double (cpu, sn)
6406                          * aarch64_get_FP_double (cpu, sm));
6407 }
6408
6409 /* Float multiply subtract.  */
6410 static void
6411 fmsubs (sim_cpu *cpu)
6412 {
6413   unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6414   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6415   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6416   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6417
6418   aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sa)
6419                         - aarch64_get_FP_float (cpu, sn)
6420                         * aarch64_get_FP_float (cpu, sm));
6421 }
6422
6423 /* Double multiply subtract.  */
6424 static void
6425 fmsubd (sim_cpu *cpu)
6426 {
6427   unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6428   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6429   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6430   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6431
6432   aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sa)
6433                          - aarch64_get_FP_double (cpu, sn)
6434                          * aarch64_get_FP_double (cpu, sm));
6435 }
6436
6437 /* Float negative multiply add.  */
6438 static void
6439 fnmadds (sim_cpu *cpu)
6440 {
6441   unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6442   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6443   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6444   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6445
6446   aarch64_set_FP_float (cpu, sd, - aarch64_get_FP_float (cpu, sa)
6447                         + (- aarch64_get_FP_float (cpu, sn))
6448                         * aarch64_get_FP_float (cpu, sm));
6449 }
6450
6451 /* Double negative multiply add.  */
6452 static void
6453 fnmaddd (sim_cpu *cpu)
6454 {
6455   unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6456   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6457   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6458   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6459
6460   aarch64_set_FP_double (cpu, sd, - aarch64_get_FP_double (cpu, sa)
6461                          + (- aarch64_get_FP_double (cpu, sn))
6462                          * aarch64_get_FP_double (cpu, sm));
6463 }
6464
6465 /* Float negative multiply subtract.  */
6466 static void
6467 fnmsubs (sim_cpu *cpu)
6468 {
6469   unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6470   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6471   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6472   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6473
6474   aarch64_set_FP_float (cpu, sd, - aarch64_get_FP_float (cpu, sa)
6475                         + aarch64_get_FP_float (cpu, sn)
6476                         * aarch64_get_FP_float (cpu, sm));
6477 }
6478
6479 /* Double negative multiply subtract.  */
6480 static void
6481 fnmsubd (sim_cpu *cpu)
6482 {
6483   unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6484   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6485   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6486   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6487
6488   aarch64_set_FP_double (cpu, sd, - aarch64_get_FP_double (cpu, sa)
6489                          + aarch64_get_FP_double (cpu, sn)
6490                          * aarch64_get_FP_double (cpu, sm));
6491 }
6492
6493 static void
6494 dexSimpleFPDataProc3Source (sim_cpu *cpu)
6495 {
6496   /* instr[31]    ==> M : 0 ==> OK, 1 ==> UNALLOC
6497      instr[30]    = 0
6498      instr[29]    ==> S :  0 ==> OK, 1 ==> UNALLOC
6499      instr[28,25] = 1111
6500      instr[24]    = 1
6501      instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
6502      instr[21]    ==> o1 : 0 ==> unnegated, 1 ==> negated
6503      instr[15]    ==> o2 : 0 ==> ADD, 1 ==> SUB  */
6504
6505   uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
6506     | uimm (aarch64_get_instr (cpu), 29, 29);
6507   /* dispatch on combined type:o1:o2.  */
6508   uint32_t dispatch = (uimm (aarch64_get_instr (cpu), 23, 21) << 1)
6509     | uimm (aarch64_get_instr (cpu), 15, 15);
6510
6511   if (M_S != 0)
6512     HALT_UNALLOC;
6513
6514   switch (dispatch)
6515     {
6516     case 0: fmadds (cpu); return;
6517     case 1: fmsubs (cpu); return;
6518     case 2: fnmadds (cpu); return;
6519     case 3: fnmsubs (cpu); return;
6520     case 4: fmaddd (cpu); return;
6521     case 5: fmsubd (cpu); return;
6522     case 6: fnmaddd (cpu); return;
6523     case 7: fnmsubd (cpu); return;
6524     default:
6525       /* type > 1 is currently unallocated.  */
6526       HALT_UNALLOC;
6527     }
6528 }
6529
6530 static void
6531 dexSimpleFPFixedConvert (sim_cpu *cpu)
6532 {
6533   HALT_NYI;
6534 }
6535
6536 static void
6537 dexSimpleFPCondCompare (sim_cpu *cpu)
6538 {
6539   HALT_NYI;
6540 }
6541
6542 /* 2 sources.  */
6543
6544 /* Float add.  */
6545 static void
6546 fadds (sim_cpu *cpu)
6547 {
6548   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6549   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6550   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6551
6552   aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6553                         + aarch64_get_FP_float (cpu, sm));
6554 }
6555
6556 /* Double add.  */
6557 static void
6558 faddd (sim_cpu *cpu)
6559 {
6560   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6561   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6562   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6563
6564   aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6565                          + aarch64_get_FP_double (cpu, sm));
6566 }
6567
6568 /* Float divide.  */
6569 static void
6570 fdivs (sim_cpu *cpu)
6571 {
6572   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6573   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6574   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6575
6576   aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6577                         / aarch64_get_FP_float (cpu, sm));
6578 }
6579
6580 /* Double divide.  */
6581 static void
6582 fdivd (sim_cpu *cpu)
6583 {
6584   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6585   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6586   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6587
6588   aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6589                          / aarch64_get_FP_double (cpu, sm));
6590 }
6591
6592 /* Float multiply.  */
6593 static void
6594 fmuls (sim_cpu *cpu)
6595 {
6596   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6597   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6598   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6599
6600   aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6601                         * aarch64_get_FP_float (cpu, sm));
6602 }
6603
6604 /* Double multiply.  */
6605 static void
6606 fmuld (sim_cpu *cpu)
6607 {
6608   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6609   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6610   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6611
6612   aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6613                          * aarch64_get_FP_double (cpu, sm));
6614 }
6615
6616 /* Float negate and multiply.  */
6617 static void
6618 fnmuls (sim_cpu *cpu)
6619 {
6620   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6621   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6622   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6623
6624   aarch64_set_FP_float (cpu, sd, - (aarch64_get_FP_float (cpu, sn)
6625                                     * aarch64_get_FP_float (cpu, sm)));
6626 }
6627
6628 /* Double negate and multiply.  */
6629 static void
6630 fnmuld (sim_cpu *cpu)
6631 {
6632   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6633   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6634   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6635
6636   aarch64_set_FP_double (cpu, sd, - (aarch64_get_FP_double (cpu, sn)
6637                                      * aarch64_get_FP_double (cpu, sm)));
6638 }
6639
6640 /* Float subtract.  */
6641 static void
6642 fsubs (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 subtract.  */
6653 static void
6654 fsubd (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 static void
6665 do_FMINNM (sim_cpu *cpu)
6666 {
6667   /* instr[31,23] = 0 0011 1100
6668      instr[22]    = float(0)/double(1)
6669      instr[21]    = 1
6670      instr[20,16] = Sm
6671      instr[15,10] = 01 1110
6672      instr[9,5]   = Sn
6673      instr[4,0]   = Cpu  */
6674
6675   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6676   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6677   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6678
6679   NYI_assert (31, 23, 0x03C);
6680   NYI_assert (15, 10, 0x1E);
6681
6682   if (uimm (aarch64_get_instr (cpu), 22, 22))
6683     aarch64_set_FP_double (cpu, sd,
6684                            dminnm (aarch64_get_FP_double (cpu, sn),
6685                                    aarch64_get_FP_double (cpu, sm)));
6686   else
6687     aarch64_set_FP_float (cpu, sd,
6688                           fminnm (aarch64_get_FP_float (cpu, sn),
6689                                   aarch64_get_FP_float (cpu, sm)));
6690 }
6691
6692 static void
6693 do_FMAXNM (sim_cpu *cpu)
6694 {
6695   /* instr[31,23] = 0 0011 1100
6696      instr[22]    = float(0)/double(1)
6697      instr[21]    = 1
6698      instr[20,16] = Sm
6699      instr[15,10] = 01 1010
6700      instr[9,5]   = Sn
6701      instr[4,0]   = Cpu  */
6702
6703   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6704   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6705   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6706
6707   NYI_assert (31, 23, 0x03C);
6708   NYI_assert (15, 10, 0x1A);
6709
6710   if (uimm (aarch64_get_instr (cpu), 22, 22))
6711     aarch64_set_FP_double (cpu, sd,
6712                            dmaxnm (aarch64_get_FP_double (cpu, sn),
6713                                    aarch64_get_FP_double (cpu, sm)));
6714   else
6715     aarch64_set_FP_float (cpu, sd,
6716                           fmaxnm (aarch64_get_FP_float (cpu, sn),
6717                                   aarch64_get_FP_float (cpu, sm)));
6718 }
6719
6720 static void
6721 dexSimpleFPDataProc2Source (sim_cpu *cpu)
6722 {
6723   /* instr[31]    ==> M : 0 ==> OK, 1 ==> UNALLOC
6724      instr[30]    = 0
6725      instr[29]    ==> S :  0 ==> OK, 1 ==> UNALLOC
6726      instr[28,25] = 1111
6727      instr[24]    = 0
6728      instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
6729      instr[21]    = 1
6730      instr[20,16] = Vm
6731      instr[15,12] ==> opcode : 0000 ==> FMUL, 0001 ==> FDIV
6732                                0010 ==> FADD, 0011 ==> FSUB,
6733                                0100 ==> FMAX, 0101 ==> FMIN
6734                                0110 ==> FMAXNM, 0111 ==> FMINNM
6735                                1000 ==> FNMUL, ow ==> UNALLOC
6736      instr[11,10] = 10
6737      instr[9,5]   = Vn
6738      instr[4,0]   = Vd  */
6739
6740   uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
6741     | uimm (aarch64_get_instr (cpu), 29, 29);
6742   uint32_t type = uimm (aarch64_get_instr (cpu), 23, 22);
6743   /* Dispatch on opcode.  */
6744   uint32_t dispatch = uimm (aarch64_get_instr (cpu), 15, 12);
6745
6746   if (type > 1)
6747     HALT_UNALLOC;
6748
6749   if (M_S != 0)
6750     HALT_UNALLOC;
6751
6752   if (type)
6753     switch (dispatch)
6754       {
6755       case 0: fmuld (cpu); return;
6756       case 1: fdivd (cpu); return;
6757       case 2: faddd (cpu); return;
6758       case 3: fsubd (cpu); return;
6759       case 6: do_FMAXNM (cpu); return;
6760       case 7: do_FMINNM (cpu); return;
6761       case 8: fnmuld (cpu); return;
6762
6763         /* Have not yet implemented fmax and fmin.  */
6764       case 4:
6765       case 5:
6766         HALT_NYI;
6767
6768       default:
6769         HALT_UNALLOC;
6770       }
6771   else /* type == 0 => floats.  */
6772     switch (dispatch)
6773       {
6774       case 0: fmuls (cpu); return;
6775       case 1: fdivs (cpu); return;
6776       case 2: fadds (cpu); return;
6777       case 3: fsubs (cpu); return;
6778       case 6: do_FMAXNM (cpu); return;
6779       case 7: do_FMINNM (cpu); return;
6780       case 8: fnmuls (cpu); return;
6781
6782       case 4:
6783       case 5:
6784         HALT_NYI;
6785
6786       default:
6787         HALT_UNALLOC;
6788       }
6789 }
6790
6791 static void
6792 dexSimpleFPCondSelect (sim_cpu *cpu)
6793 {
6794   /* FCSEL
6795      instr[31,23] = 0 0011 1100
6796      instr[22]    = 0=>single 1=>double
6797      instr[21]    = 1
6798      instr[20,16] = Sm
6799      instr[15,12] = cond
6800      instr[11,10] = 11
6801      instr[9,5]   = Sn
6802      instr[4,0]   = Cpu  */
6803   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6804   unsigned sn = uimm (aarch64_get_instr (cpu),  9, 5);
6805   unsigned sd = uimm (aarch64_get_instr (cpu),  4, 0);
6806   uint32_t set = testConditionCode (cpu, uimm (aarch64_get_instr (cpu), 15, 12));
6807
6808   NYI_assert (31, 23, 0x03C);
6809   NYI_assert (11, 10, 0x3);
6810
6811   if (uimm (aarch64_get_instr (cpu), 22, 22))
6812     aarch64_set_FP_double (cpu, sd, set ? sn : sm);
6813   else
6814     aarch64_set_FP_float (cpu, sd, set ? sn : sm);
6815 }
6816
6817 /* Store 32 bit unscaled signed 9 bit.  */
6818 static void
6819 fsturs (sim_cpu *cpu, int32_t offset)
6820 {
6821   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6822   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6823
6824   aarch64_set_mem_float (cpu, aarch64_get_reg_u64 (cpu, st, 1) + offset,
6825                          aarch64_get_FP_float (cpu, rn));
6826 }
6827
6828 /* Store 64 bit unscaled signed 9 bit.  */
6829 static void
6830 fsturd (sim_cpu *cpu, int32_t offset)
6831 {
6832   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6833   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6834
6835   aarch64_set_mem_double (cpu, aarch64_get_reg_u64 (cpu, st, 1) + offset,
6836                           aarch64_get_FP_double (cpu, rn));
6837 }
6838
6839 /* Store 128 bit unscaled signed 9 bit.  */
6840 static void
6841 fsturq (sim_cpu *cpu, int32_t offset)
6842 {
6843   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6844   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6845   FRegister a;
6846
6847   aarch64_get_FP_long_double (cpu, rn, & a);
6848   aarch64_set_mem_long_double (cpu,
6849                                aarch64_get_reg_u64 (cpu, st, 1)
6850                                + offset, a);
6851 }
6852
6853 /* TODO FP move register.  */
6854
6855 /* 32 bit fp to fp move register.  */
6856 static void
6857 ffmovs (sim_cpu *cpu)
6858 {
6859   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6860   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6861
6862   aarch64_set_FP_float (cpu, st, aarch64_get_FP_float (cpu, rn));
6863 }
6864
6865 /* 64 bit fp to fp move register.  */
6866 static void
6867 ffmovd (sim_cpu *cpu)
6868 {
6869   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6870   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6871
6872   aarch64_set_FP_double (cpu, st, aarch64_get_FP_double (cpu, rn));
6873 }
6874
6875 /* 32 bit GReg to Vec move register.  */
6876 static void
6877 fgmovs (sim_cpu *cpu)
6878 {
6879   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6880   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6881
6882   aarch64_set_vec_u32 (cpu, st, 0, aarch64_get_reg_u32 (cpu, rn, NO_SP));
6883 }
6884
6885 /* 64 bit g to fp move register.  */
6886 static void
6887 fgmovd (sim_cpu *cpu)
6888 {
6889   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6890   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6891
6892   aarch64_set_vec_u64 (cpu, st, 0, aarch64_get_reg_u64 (cpu, rn, NO_SP));
6893 }
6894
6895 /* 32 bit fp to g move register.  */
6896 static void
6897 gfmovs (sim_cpu *cpu)
6898 {
6899   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6900   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6901
6902   aarch64_set_reg_u64 (cpu, st, NO_SP, aarch64_get_vec_u32 (cpu, rn, 0));
6903 }
6904
6905 /* 64 bit fp to g move register.  */
6906 static void
6907 gfmovd (sim_cpu *cpu)
6908 {
6909   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6910   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6911
6912   aarch64_set_reg_u64 (cpu, st, NO_SP, aarch64_get_vec_u64 (cpu, rn, 0));
6913 }
6914
6915 /* FP move immediate
6916
6917    These install an immediate 8 bit value in the target register
6918    where the 8 bits comprise 1 sign bit, 4 bits of fraction and a 3
6919    bit exponent.  */
6920
6921 static void
6922 fmovs (sim_cpu *cpu)
6923 {
6924   unsigned int sd = uimm (aarch64_get_instr (cpu), 4, 0);
6925   uint32_t imm = uimm (aarch64_get_instr (cpu), 20, 13);
6926   float f = fp_immediate_for_encoding_32 (imm);
6927
6928   aarch64_set_FP_float (cpu, sd, f);
6929 }
6930
6931 static void
6932 fmovd (sim_cpu *cpu)
6933 {
6934   unsigned int sd = uimm (aarch64_get_instr (cpu), 4, 0);
6935   uint32_t imm = uimm (aarch64_get_instr (cpu), 20, 13);
6936   double d = fp_immediate_for_encoding_64 (imm);
6937
6938   aarch64_set_FP_double (cpu, sd, d);
6939 }
6940
6941 static void
6942 dexSimpleFPImmediate (sim_cpu *cpu)
6943 {
6944   /* instr[31,23] == 00111100
6945      instr[22]    == type : single(0)/double(1)
6946      instr[21]    == 1
6947      instr[20,13] == imm8
6948      instr[12,10] == 100
6949      instr[9,5]   == imm5 : 00000 ==> PK, ow ==> UNALLOC
6950      instr[4,0]   == Rd  */
6951   uint32_t imm5 = uimm (aarch64_get_instr (cpu), 9, 5);
6952
6953   NYI_assert (31, 23, 0x3C);
6954
6955   if (imm5 != 0)
6956     HALT_UNALLOC;
6957
6958   if (uimm (aarch64_get_instr (cpu), 22, 22))
6959     fmovd (cpu);
6960   else
6961     fmovs (cpu);
6962 }
6963
6964 /* TODO specific decode and execute for group Load Store.  */
6965
6966 /* TODO FP load/store single register (unscaled offset).  */
6967
6968 /* TODO load 8 bit unscaled signed 9 bit.  */
6969 /* TODO load 16 bit unscaled signed 9 bit.  */
6970
6971 /* Load 32 bit unscaled signed 9 bit.  */
6972 static void
6973 fldurs (sim_cpu *cpu, int32_t offset)
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_FP_float (cpu, st, aarch64_get_mem_float
6979                         (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset));
6980 }
6981
6982 /* Load 64 bit unscaled signed 9 bit.  */
6983 static void
6984 fldurd (sim_cpu *cpu, int32_t offset)
6985 {
6986   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6987   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6988
6989   aarch64_set_FP_double (cpu, st, aarch64_get_mem_double
6990                          (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset));
6991 }
6992
6993 /* Load 128 bit unscaled signed 9 bit.  */
6994 static void
6995 fldurq (sim_cpu *cpu, int32_t offset)
6996 {
6997   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
6998   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
6999   FRegister a;
7000   uint64_t addr = aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset;
7001
7002   aarch64_get_mem_long_double (cpu, addr, & a);
7003   aarch64_set_FP_long_double (cpu, st, a);
7004 }
7005
7006 /* TODO store 8 bit unscaled signed 9 bit.  */
7007 /* TODO store 16 bit unscaled signed 9 bit.  */
7008
7009
7010 /* 1 source.  */
7011
7012 /* Float absolute value.  */
7013 static void
7014 fabss (sim_cpu *cpu)
7015 {
7016   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7017   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7018   float value = aarch64_get_FP_float (cpu, sn);
7019
7020   aarch64_set_FP_float (cpu, sd, fabsf (value));
7021 }
7022
7023 /* Double absolute value.  */
7024 static void
7025 fabcpu (sim_cpu *cpu)
7026 {
7027   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7028   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7029   double value = aarch64_get_FP_double (cpu, sn);
7030
7031   aarch64_set_FP_double (cpu, sd, fabs (value));
7032 }
7033
7034 /* Float negative value.  */
7035 static void
7036 fnegs (sim_cpu *cpu)
7037 {
7038   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7039   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7040
7041   aarch64_set_FP_float (cpu, sd, - aarch64_get_FP_float (cpu, sn));
7042 }
7043
7044 /* Double negative value.  */
7045 static void
7046 fnegd (sim_cpu *cpu)
7047 {
7048   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7049   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7050
7051   aarch64_set_FP_double (cpu, sd, - aarch64_get_FP_double (cpu, sn));
7052 }
7053
7054 /* Float square root.  */
7055 static void
7056 fsqrts (sim_cpu *cpu)
7057 {
7058   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7059   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7060
7061   aarch64_set_FP_float (cpu, sd, sqrt (aarch64_get_FP_float (cpu, sn)));
7062 }
7063
7064 /* Double square root.  */
7065 static void
7066 fsqrtd (sim_cpu *cpu)
7067 {
7068   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7069   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7070
7071   aarch64_set_FP_double (cpu, sd,
7072                          sqrt (aarch64_get_FP_double (cpu, sn)));
7073 }
7074
7075 /* Convert double to float.  */
7076 static void
7077 fcvtds (sim_cpu *cpu)
7078 {
7079   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7080   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7081
7082   aarch64_set_FP_float (cpu, sd, (float) aarch64_get_FP_double (cpu, sn));
7083 }
7084
7085 /* Convert float to double.  */
7086 static void
7087 fcvtcpu (sim_cpu *cpu)
7088 {
7089   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7090   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7091
7092   aarch64_set_FP_double (cpu, sd, (double) aarch64_get_FP_float (cpu, sn));
7093 }
7094
7095 static void
7096 do_FRINT (sim_cpu *cpu)
7097 {
7098   /* instr[31,23] = 0001 1110 0
7099      instr[22]    = single(0)/double(1)
7100      instr[21,18] = 1001
7101      instr[17,15] = rounding mode
7102      instr[14,10] = 10000
7103      instr[9,5]   = source
7104      instr[4,0]   = dest  */
7105
7106   float val;
7107   unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
7108   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7109   unsigned int rmode = uimm (aarch64_get_instr (cpu), 17, 15);
7110
7111   NYI_assert (31, 23, 0x03C);
7112   NYI_assert (21, 18, 0x9);
7113   NYI_assert (14, 10, 0x10);
7114
7115   if (rmode == 6 || rmode == 7)
7116     /* FIXME: Add support for rmode == 6 exactness check.  */
7117     rmode = uimm (aarch64_get_FPSR (cpu), 23, 22);
7118
7119   if (uimm (aarch64_get_instr (cpu), 22, 22))
7120     {
7121       double val = aarch64_get_FP_double (cpu, rs);
7122
7123       switch (rmode)
7124         {
7125         case 0: /* mode N: nearest or even.  */
7126           {
7127             double rval = round (val);
7128
7129             if (val - rval == 0.5)
7130               {
7131                 if (((rval / 2.0) * 2.0) != rval)
7132                   rval += 1.0;
7133               }
7134
7135             aarch64_set_FP_double (cpu, rd, round (val));
7136             return;
7137           }
7138
7139         case 1: /* mode P: towards +inf.  */
7140           if (val < 0.0)
7141             aarch64_set_FP_double (cpu, rd, trunc (val));
7142           else
7143             aarch64_set_FP_double (cpu, rd, round (val));
7144           return;
7145
7146         case 2: /* mode M: towards -inf.  */
7147           if (val < 0.0)
7148             aarch64_set_FP_double (cpu, rd, round (val));
7149           else
7150             aarch64_set_FP_double (cpu, rd, trunc (val));
7151           return;
7152
7153         case 3: /* mode Z: towards 0.  */
7154           aarch64_set_FP_double (cpu, rd, trunc (val));
7155           return;
7156
7157         case 4: /* mode A: away from 0.  */
7158           aarch64_set_FP_double (cpu, rd, round (val));
7159           return;
7160
7161         case 6: /* mode X: use FPCR with exactness check.  */
7162         case 7: /* mode I: use FPCR mode.  */
7163           HALT_NYI;
7164
7165         default:
7166           HALT_UNALLOC;
7167         }
7168     }
7169
7170   val = aarch64_get_FP_float (cpu, rs);
7171
7172   switch (rmode)
7173     {
7174     case 0: /* mode N: nearest or even.  */
7175       {
7176         float rval = roundf (val);
7177
7178         if (val - rval == 0.5)
7179           {
7180             if (((rval / 2.0) * 2.0) != rval)
7181               rval += 1.0;
7182           }
7183
7184         aarch64_set_FP_float (cpu, rd, rval);
7185         return;
7186       }
7187
7188     case 1: /* mode P: towards +inf.  */
7189       if (val < 0.0)
7190         aarch64_set_FP_float (cpu, rd, truncf (val));
7191       else
7192         aarch64_set_FP_float (cpu, rd, roundf (val));
7193       return;
7194
7195     case 2: /* mode M: towards -inf.  */
7196       if (val < 0.0)
7197         aarch64_set_FP_float (cpu, rd, truncf (val));
7198       else
7199         aarch64_set_FP_float (cpu, rd, roundf (val));
7200       return;
7201
7202     case 3: /* mode Z: towards 0.  */
7203       aarch64_set_FP_float (cpu, rd, truncf (val));
7204       return;
7205
7206     case 4: /* mode A: away from 0.  */
7207       aarch64_set_FP_float (cpu, rd, roundf (val));
7208       return;
7209
7210     case 6: /* mode X: use FPCR with exactness check.  */
7211     case 7: /* mode I: use FPCR mode.  */
7212       HALT_NYI;
7213
7214     default:
7215       HALT_UNALLOC;
7216     }
7217 }
7218
7219 static void
7220 dexSimpleFPDataProc1Source (sim_cpu *cpu)
7221 {
7222   /* instr[31]    ==> M : 0 ==> OK, 1 ==> UNALLOC
7223      instr[30]    = 0
7224      instr[29]    ==> S :  0 ==> OK, 1 ==> UNALLOC
7225      instr[28,25] = 1111
7226      instr[24]    = 0
7227      instr[23,22] ==> type : 00 ==> source is single,
7228                              01 ==> source is double
7229                              10 ==> UNALLOC
7230                              11 ==> UNALLOC or source is half
7231      instr[21]    = 1
7232      instr[20,15] ==> opcode : with type 00 or 01
7233                                000000 ==> FMOV, 000001 ==> FABS,
7234                                000010 ==> FNEG, 000011 ==> FSQRT,
7235                                000100 ==> UNALLOC, 000101 ==> FCVT,(to single/double)
7236                                000110 ==> UNALLOC, 000111 ==> FCVT (to half)
7237                                001000 ==> FRINTN, 001001 ==> FRINTP,
7238                                001010 ==> FRINTM, 001011 ==> FRINTZ,
7239                                001100 ==> FRINTA, 001101 ==> UNALLOC
7240                                001110 ==> FRINTX, 001111 ==> FRINTI
7241                                with type 11
7242                                000100 ==> FCVT (half-to-single)
7243                                000101 ==> FCVT (half-to-double)
7244                                instr[14,10] = 10000.  */
7245
7246   uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
7247     | uimm (aarch64_get_instr (cpu), 29, 29);
7248   uint32_t type   = uimm (aarch64_get_instr (cpu), 23, 22);
7249   uint32_t opcode = uimm (aarch64_get_instr (cpu), 20, 15);
7250
7251   if (M_S != 0)
7252     HALT_UNALLOC;
7253
7254   if (type == 3)
7255     {
7256       if (opcode == 4 || opcode == 5)
7257         HALT_NYI;
7258       else
7259         HALT_UNALLOC;
7260     }
7261
7262   if (type == 2)
7263     HALT_UNALLOC;
7264
7265   switch (opcode)
7266     {
7267     case 0:
7268       if (type)
7269         ffmovd (cpu);
7270       else
7271         ffmovs (cpu);
7272       return;
7273
7274     case 1:
7275       if (type)
7276         fabcpu (cpu);
7277       else
7278         fabss (cpu);
7279       return;
7280
7281     case 2:
7282       if (type)
7283         fnegd (cpu);
7284       else
7285         fnegs (cpu);
7286       return;
7287
7288     case 3:
7289       if (type)
7290         fsqrtd (cpu);
7291       else
7292         fsqrts (cpu);
7293       return;
7294
7295     case 4:
7296       if (type)
7297         fcvtds (cpu);
7298       else
7299         HALT_UNALLOC;
7300       return;
7301
7302     case 5:
7303       if (type)
7304         HALT_UNALLOC;
7305       fcvtcpu (cpu);
7306       return;
7307
7308     case 8:             /* FRINTN etc.  */
7309     case 9:
7310     case 10:
7311     case 11:
7312     case 12:
7313     case 14:
7314     case 15:
7315        do_FRINT (cpu);
7316        return;
7317
7318     case 7:             /* FCVT double/single to half precision.  */
7319     case 13:
7320       HALT_NYI;
7321
7322     default:
7323       HALT_UNALLOC;
7324     }
7325 }
7326
7327 /* 32 bit signed int to float.  */
7328 static void
7329 scvtf32 (sim_cpu *cpu)
7330 {
7331   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7332   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7333
7334   aarch64_set_FP_float
7335     (cpu, sd, (float) aarch64_get_reg_s32 (cpu, rn, NO_SP));
7336 }
7337
7338 /* signed int to float.  */
7339 static void
7340 scvtf (sim_cpu *cpu)
7341 {
7342   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7343   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7344
7345   aarch64_set_FP_float
7346     (cpu, sd, (float) aarch64_get_reg_s64 (cpu, rn, NO_SP));
7347 }
7348
7349 /* 32 bit signed int to double.  */
7350 static void
7351 scvtd32 (sim_cpu *cpu)
7352 {
7353   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7354   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7355
7356   aarch64_set_FP_double
7357     (cpu, sd, (double) aarch64_get_reg_s32 (cpu, rn, NO_SP));
7358 }
7359
7360 /* signed int to double.  */
7361 static void
7362 scvtd (sim_cpu *cpu)
7363 {
7364   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7365   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7366
7367   aarch64_set_FP_double
7368     (cpu, sd, (double) aarch64_get_reg_s64 (cpu, rn, NO_SP));
7369 }
7370
7371 static const float  FLOAT_INT_MAX   = (float)  INT_MAX;
7372 static const float  FLOAT_INT_MIN   = (float)  INT_MIN;
7373 static const double DOUBLE_INT_MAX  = (double) INT_MAX;
7374 static const double DOUBLE_INT_MIN  = (double) INT_MIN;
7375 static const float  FLOAT_LONG_MAX  = (float)  LONG_MAX;
7376 static const float  FLOAT_LONG_MIN  = (float)  LONG_MIN;
7377 static const double DOUBLE_LONG_MAX = (double) LONG_MAX;
7378 static const double DOUBLE_LONG_MIN = (double) LONG_MIN;
7379
7380 /* Check for FP exception conditions:
7381      NaN raises IO
7382      Infinity raises IO
7383      Out of Range raises IO and IX and saturates value
7384      Denormal raises ID and IX and sets to zero.  */
7385 #define RAISE_EXCEPTIONS(F, VALUE, FTYPE, ITYPE)        \
7386   do                                                    \
7387     {                                                   \
7388       switch (fpclassify (F))                           \
7389         {                                               \
7390         case FP_INFINITE:                               \
7391         case FP_NAN:                                    \
7392           aarch64_set_FPSR (cpu, IO);                   \
7393           if (signbit (F))                              \
7394             VALUE = ITYPE##_MAX;                        \
7395           else                                          \
7396             VALUE = ITYPE##_MIN;                        \
7397           break;                                        \
7398                                                         \
7399         case FP_NORMAL:                                 \
7400           if (F >= FTYPE##_##ITYPE##_MAX)               \
7401             {                                           \
7402               aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX);    \
7403               VALUE = ITYPE##_MAX;                      \
7404             }                                           \
7405           else if (F <= FTYPE##_##ITYPE##_MIN)          \
7406             {                                           \
7407               aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX);    \
7408               VALUE = ITYPE##_MIN;                      \
7409             }                                           \
7410           break;                                        \
7411                                                         \
7412         case FP_SUBNORMAL:                              \
7413           aarch64_set_FPSR_bits (cpu, IO | IX | ID, IX | ID);   \
7414           VALUE = 0;                                    \
7415           break;                                        \
7416                                                         \
7417         default:                                        \
7418         case FP_ZERO:                                   \
7419           VALUE = 0;                                    \
7420           break;                                        \
7421         }                                               \
7422     }                                                   \
7423   while (0)
7424
7425 /* 32 bit convert float to signed int truncate towards zero.  */
7426 static void
7427 fcvtszs32 (sim_cpu *cpu)
7428 {
7429   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7430   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7431   /* TODO : check that this rounds toward zero.  */
7432   float   f = aarch64_get_FP_float (cpu, sn);
7433   int32_t value = (int32_t) f;
7434
7435   RAISE_EXCEPTIONS (f, value, FLOAT, INT);
7436
7437   /* Avoid sign extension to 64 bit.  */
7438   aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) value);
7439 }
7440
7441 /* 64 bit convert float to signed int truncate towards zero.  */
7442 static void
7443 fcvtszs (sim_cpu *cpu)
7444 {
7445   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7446   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7447   float f = aarch64_get_FP_float (cpu, sn);
7448   int64_t value = (int64_t) f;
7449
7450   RAISE_EXCEPTIONS (f, value, FLOAT, LONG);
7451
7452   aarch64_set_reg_s64 (cpu, rd, NO_SP, value);
7453 }
7454
7455 /* 32 bit convert double to signed int truncate towards zero.  */
7456 static void
7457 fcvtszd32 (sim_cpu *cpu)
7458 {
7459   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7460   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7461   /* TODO : check that this rounds toward zero.  */
7462   double   d = aarch64_get_FP_double (cpu, sn);
7463   int32_t  value = (int32_t) d;
7464
7465   RAISE_EXCEPTIONS (d, value, DOUBLE, INT);
7466
7467   /* Avoid sign extension to 64 bit.  */
7468   aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) value);
7469 }
7470
7471 /* 64 bit convert double to signed int truncate towards zero.  */
7472 static void
7473 fcvtszd (sim_cpu *cpu)
7474 {
7475   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7476   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7477   /* TODO : check that this rounds toward zero.  */
7478   double  d = aarch64_get_FP_double (cpu, sn);
7479   int64_t value;
7480
7481   value = (int64_t) d;
7482
7483   RAISE_EXCEPTIONS (d, value, DOUBLE, LONG);
7484
7485   aarch64_set_reg_s64 (cpu, rd, NO_SP, value);
7486 }
7487
7488 static void
7489 do_fcvtzu (sim_cpu *cpu)
7490 {
7491   /* instr[31]    = size: 32-bit (0), 64-bit (1)
7492      instr[30,23] = 00111100
7493      instr[22]    = type: single (0)/ double (1)
7494      instr[21]    = enable (0)/disable(1) precision
7495      instr[20,16] = 11001
7496      instr[15,10] = precision
7497      instr[9,5]   = Rs
7498      instr[4,0]   = Rd.  */
7499
7500   unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
7501   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7502
7503   NYI_assert (30, 23, 0x3C);
7504   NYI_assert (20, 16, 0x19);
7505
7506   if (uimm (aarch64_get_instr (cpu), 21, 21) != 1)
7507     /* Convert to fixed point.  */
7508     HALT_NYI;
7509
7510   if (uimm (aarch64_get_instr (cpu), 31, 31))
7511     {
7512       /* Convert to unsigned 64-bit integer.  */
7513       if (uimm (aarch64_get_instr (cpu), 22, 22))
7514         {
7515           double  d = aarch64_get_FP_double (cpu, rs);
7516           uint64_t value = (uint64_t) d;
7517
7518           /* Do not raise an exception if we have reached ULONG_MAX.  */
7519           if (value != (1UL << 63))
7520             RAISE_EXCEPTIONS (d, value, DOUBLE, LONG);
7521
7522           aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
7523         }
7524       else
7525         {
7526           float  f = aarch64_get_FP_float (cpu, rs);
7527           uint64_t value = (uint64_t) f;
7528
7529           /* Do not raise an exception if we have reached ULONG_MAX.  */
7530           if (value != (1UL << 63))
7531             RAISE_EXCEPTIONS (f, value, FLOAT, LONG);
7532
7533           aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
7534         }
7535     }
7536   else
7537     {
7538       uint32_t value;
7539
7540       /* Convert to unsigned 32-bit integer.  */
7541       if (uimm (aarch64_get_instr (cpu), 22, 22))
7542         {
7543           double  d = aarch64_get_FP_double (cpu, rs);
7544
7545           value = (uint32_t) d;
7546           /* Do not raise an exception if we have reached UINT_MAX.  */
7547           if (value != (1UL << 31))
7548             RAISE_EXCEPTIONS (d, value, DOUBLE, INT);
7549         }
7550       else
7551         {
7552           float  f = aarch64_get_FP_float (cpu, rs);
7553
7554           value = (uint32_t) f;
7555           /* Do not raise an exception if we have reached UINT_MAX.  */
7556           if (value != (1UL << 31))
7557             RAISE_EXCEPTIONS (f, value, FLOAT, INT);
7558         }
7559
7560       aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
7561     }
7562 }
7563
7564 static void
7565 do_UCVTF (sim_cpu *cpu)
7566 {
7567   /* instr[31]    = size: 32-bit (0), 64-bit (1)
7568      instr[30,23] = 001 1110 0
7569      instr[22]    = type: single (0)/ double (1)
7570      instr[21]    = enable (0)/disable(1) precision
7571      instr[20,16] = 0 0011
7572      instr[15,10] = precision
7573      instr[9,5]   = Rs
7574      instr[4,0]   = Rd.  */
7575
7576   unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
7577   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7578
7579   NYI_assert (30, 23, 0x3C);
7580   NYI_assert (20, 16, 0x03);
7581
7582   if (uimm (aarch64_get_instr (cpu), 21, 21) != 1)
7583     HALT_NYI;
7584
7585   /* FIXME: Add exception raising.  */
7586   if (uimm (aarch64_get_instr (cpu), 31, 31))
7587     {
7588       uint64_t value = aarch64_get_reg_u64 (cpu, rs, NO_SP);
7589
7590       if (uimm (aarch64_get_instr (cpu), 22, 22))
7591         aarch64_set_FP_double (cpu, rd, (double) value);
7592       else
7593         aarch64_set_FP_float (cpu, rd, (float) value);
7594     }
7595   else
7596     {
7597       uint32_t value =  aarch64_get_reg_u32 (cpu, rs, NO_SP);
7598
7599       if (uimm (aarch64_get_instr (cpu), 22, 22))
7600         aarch64_set_FP_double (cpu, rd, (double) value);
7601       else
7602         aarch64_set_FP_float (cpu, rd, (float) value);
7603     }
7604 }
7605
7606 static void
7607 float_vector_move (sim_cpu *cpu)
7608 {
7609   /* instr[31,17] == 100 1111 0101 0111
7610      instr[16]    ==> direction 0=> to GR, 1=> from GR
7611      instr[15,10] => ???
7612      instr[9,5]   ==> source
7613      instr[4,0]   ==> dest.  */
7614
7615   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7616   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7617
7618   NYI_assert (31, 17, 0x4F57);
7619
7620   if (uimm (aarch64_get_instr (cpu), 15, 10) != 0)
7621     HALT_UNALLOC;
7622
7623   if (uimm (aarch64_get_instr (cpu), 16, 16))
7624     aarch64_set_vec_u64 (cpu, rd, 1, aarch64_get_reg_u64 (cpu, rn, NO_SP));
7625   else
7626     aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u64 (cpu, rn, 1));
7627 }
7628
7629 static void
7630 dexSimpleFPIntegerConvert (sim_cpu *cpu)
7631 {
7632   /* instr[31]    = size : 0 ==> 32 bit, 1 ==> 64 bit
7633      instr[30     = 0
7634      instr[29]    = S :  0 ==> OK, 1 ==> UNALLOC
7635      instr[28,25] = 1111
7636      instr[24]    = 0
7637      instr[23,22] = type : 00 ==> single, 01 ==> double, 1x ==> UNALLOC
7638      instr[21]    = 1
7639      instr[20,19] = rmode
7640      instr[18,16] = opcode
7641      instr[15,10] = 10 0000  */
7642
7643   uint32_t rmode_opcode;
7644   uint32_t size_type;
7645   uint32_t type;
7646   uint32_t size;
7647   uint32_t S;
7648
7649   if (uimm (aarch64_get_instr (cpu), 31, 17) == 0x4F57)
7650     {
7651       float_vector_move (cpu);
7652       return;
7653     }
7654
7655   size = uimm (aarch64_get_instr (cpu), 31, 31);
7656   S = uimm (aarch64_get_instr (cpu), 29, 29);
7657   if (S != 0)
7658     HALT_UNALLOC;
7659
7660   type = uimm (aarch64_get_instr (cpu), 23, 22);
7661   if (type > 1)
7662     HALT_UNALLOC;
7663
7664   rmode_opcode = uimm (aarch64_get_instr (cpu), 20, 16);
7665   size_type = (size << 1) | type; /* 0==32f, 1==32d, 2==64f, 3==64d.  */
7666
7667   switch (rmode_opcode)
7668     {
7669     case 2:                     /* SCVTF.  */
7670       switch (size_type)
7671         {
7672         case 0: scvtf32 (cpu); return;
7673         case 1: scvtd32 (cpu); return;
7674         case 2: scvtf (cpu); return;
7675         case 3: scvtd (cpu); return;
7676         default:
7677           HALT_UNREACHABLE;
7678         }
7679
7680     case 6:                     /* FMOV GR, Vec.  */
7681       switch (size_type)
7682         {
7683         case 0:  gfmovs (cpu); return;
7684         case 3:  gfmovd (cpu); return;
7685         default: HALT_UNALLOC;
7686         }
7687
7688     case 7:                     /* FMOV vec, GR.  */
7689       switch (size_type)
7690         {
7691         case 0:  fgmovs (cpu); return;
7692         case 3:  fgmovd (cpu); return;
7693         default: HALT_UNALLOC;
7694         }
7695
7696     case 24:                    /* FCVTZS.  */
7697       switch (size_type)
7698         {
7699         case 0: fcvtszs32 (cpu); return;
7700         case 1: fcvtszd32 (cpu); return;
7701         case 2: fcvtszs (cpu); return;
7702         case 3: fcvtszd (cpu); return;
7703         default: HALT_UNREACHABLE;
7704         }
7705
7706     case 25: do_fcvtzu (cpu); return;
7707     case 3:  do_UCVTF (cpu); return;
7708
7709     case 0:     /* FCVTNS.  */
7710     case 1:     /* FCVTNU.  */
7711     case 4:     /* FCVTAS.  */
7712     case 5:     /* FCVTAU.  */
7713     case 8:     /* FCVPTS.  */
7714     case 9:     /* FCVTPU.  */
7715     case 16:    /* FCVTMS.  */
7716     case 17:    /* FCVTMU.  */
7717     default:
7718       HALT_NYI;
7719     }
7720 }
7721
7722 static void
7723 set_flags_for_float_compare (sim_cpu *cpu, float fvalue1, float fvalue2)
7724 {
7725   uint32_t flags;
7726
7727   if (isnan (fvalue1) || isnan (fvalue2))
7728     flags = C|V;
7729   else
7730     {
7731       float result = fvalue1 - fvalue2;
7732
7733       if (result == 0.0)
7734         flags = Z|C;
7735       else if (result < 0)
7736         flags = N;
7737       else /* (result > 0).  */
7738         flags = C;
7739     }
7740
7741   aarch64_set_CPSR (cpu, flags);
7742 }
7743
7744 static void
7745 fcmps (sim_cpu *cpu)
7746 {
7747   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
7748   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
7749
7750   float fvalue1 = aarch64_get_FP_float (cpu, sn);
7751   float fvalue2 = aarch64_get_FP_float (cpu, sm);
7752
7753   set_flags_for_float_compare (cpu, fvalue1, fvalue2);
7754 }
7755
7756 /* Float compare to zero -- Invalid Operation exception
7757    only on signaling NaNs.  */
7758 static void
7759 fcmpzs (sim_cpu *cpu)
7760 {
7761   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
7762   float fvalue1 = aarch64_get_FP_float (cpu, sn);
7763
7764   set_flags_for_float_compare (cpu, fvalue1, 0.0f);
7765 }
7766
7767 /* Float compare -- Invalid Operation exception on all NaNs.  */
7768 static void
7769 fcmpes (sim_cpu *cpu)
7770 {
7771   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
7772   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
7773
7774   float fvalue1 = aarch64_get_FP_float (cpu, sn);
7775   float fvalue2 = aarch64_get_FP_float (cpu, sm);
7776
7777   set_flags_for_float_compare (cpu, fvalue1, fvalue2);
7778 }
7779
7780 /* Float compare to zero -- Invalid Operation exception on all NaNs.  */
7781 static void
7782 fcmpzes (sim_cpu *cpu)
7783 {
7784   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
7785   float fvalue1 = aarch64_get_FP_float (cpu, sn);
7786
7787   set_flags_for_float_compare (cpu, fvalue1, 0.0f);
7788 }
7789
7790 static void
7791 set_flags_for_double_compare (sim_cpu *cpu, double dval1, double dval2)
7792 {
7793   uint32_t flags;
7794
7795   if (isnan (dval1) || isnan (dval2))
7796     flags = C|V;
7797   else
7798     {
7799       double result = dval1 - dval2;
7800
7801       if (result == 0.0)
7802         flags = Z|C;
7803       else if (result < 0)
7804         flags = N;
7805       else /* (result > 0).  */
7806         flags = C;
7807     }
7808
7809   aarch64_set_CPSR (cpu, flags);
7810 }
7811
7812 /* Double compare -- Invalid Operation exception only on signaling NaNs.  */
7813 static void
7814 fcmpd (sim_cpu *cpu)
7815 {
7816   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
7817   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
7818
7819   double dvalue1 = aarch64_get_FP_double (cpu, sn);
7820   double dvalue2 = aarch64_get_FP_double (cpu, sm);
7821
7822   set_flags_for_double_compare (cpu, dvalue1, dvalue2);
7823 }
7824
7825 /* Double compare to zero -- Invalid Operation exception
7826    only on signaling NaNs.  */
7827 static void
7828 fcmpzd (sim_cpu *cpu)
7829 {
7830   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
7831   double dvalue1 = aarch64_get_FP_double (cpu, sn);
7832
7833   set_flags_for_double_compare (cpu, dvalue1, 0.0);
7834 }
7835
7836 /* Double compare -- Invalid Operation exception on all NaNs.  */
7837 static void
7838 fcmped (sim_cpu *cpu)
7839 {
7840   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
7841   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
7842
7843   double dvalue1 = aarch64_get_FP_double (cpu, sn);
7844   double dvalue2 = aarch64_get_FP_double (cpu, sm);
7845
7846   set_flags_for_double_compare (cpu, dvalue1, dvalue2);
7847 }
7848
7849 /* Double compare to zero -- Invalid Operation exception on all NaNs.  */
7850 static void
7851 fcmpzed (sim_cpu *cpu)
7852 {
7853   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
7854   double dvalue1 = aarch64_get_FP_double (cpu, sn);
7855
7856   set_flags_for_double_compare (cpu, dvalue1, 0.0);
7857 }
7858
7859 static void
7860 dexSimpleFPCompare (sim_cpu *cpu)
7861 {
7862   /* assert instr[28,25] == 1111
7863      instr[30:24:21:13,10] = 0011000
7864      instr[31] = M : 0 ==> OK, 1 ==> UNALLOC
7865      instr[29] ==> S :  0 ==> OK, 1 ==> UNALLOC
7866      instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
7867      instr[15,14] ==> op : 00 ==> OK, ow ==> UNALLOC
7868      instr[4,0] ==> opcode2 : 00000 ==> FCMP, 10000 ==> FCMPE,
7869                               01000 ==> FCMPZ, 11000 ==> FCMPEZ,
7870                               ow ==> UNALLOC  */
7871   uint32_t dispatch;
7872   uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
7873     | uimm (aarch64_get_instr (cpu), 29, 29);
7874   uint32_t type = uimm (aarch64_get_instr (cpu), 23, 22);
7875   uint32_t op = uimm (aarch64_get_instr (cpu), 15, 14);
7876   uint32_t op2_2_0 = uimm (aarch64_get_instr (cpu), 2, 0);
7877
7878   if (op2_2_0 != 0)
7879     HALT_UNALLOC;
7880
7881   if (M_S != 0)
7882     HALT_UNALLOC;
7883
7884   if (type > 1)
7885     HALT_UNALLOC;
7886
7887   if (op != 0)
7888     HALT_UNALLOC;
7889
7890   /* dispatch on type and top 2 bits of opcode.  */
7891   dispatch = (type << 2) | uimm (aarch64_get_instr (cpu), 4, 3);
7892
7893   switch (dispatch)
7894     {
7895     case 0: fcmps (cpu); return;
7896     case 1: fcmpzs (cpu); return;
7897     case 2: fcmpes (cpu); return;
7898     case 3: fcmpzes (cpu); return;
7899     case 4: fcmpd (cpu); return;
7900     case 5: fcmpzd (cpu); return;
7901     case 6: fcmped (cpu); return;
7902     case 7: fcmpzed (cpu); return;
7903     default: HALT_UNREACHABLE;
7904     }
7905 }
7906
7907 static void
7908 do_scalar_FADDP (sim_cpu *cpu)
7909 {
7910   /* instr [31,23] = 011111100
7911      instr [22]    = single(0)/double(1)
7912      instr [21,10] = 1100 0011 0110
7913      instr [9,5]   = Fn
7914      instr [4,0]   = Fd.  */
7915
7916   unsigned Fn = uimm (aarch64_get_instr (cpu), 9, 5);
7917   unsigned Fd = uimm (aarch64_get_instr (cpu), 4, 0);
7918
7919   NYI_assert (31, 23, 0x0FC);
7920   NYI_assert (21, 10, 0xC36);
7921
7922   if (uimm (aarch64_get_instr (cpu), 22, 22))
7923     {
7924       double val1 = aarch64_get_vec_double (cpu, Fn, 0);
7925       double val2 = aarch64_get_vec_double (cpu, Fn, 1);
7926
7927       aarch64_set_FP_double (cpu, Fd, val1 + val2);
7928     }
7929   else
7930     {
7931       float val1 = aarch64_get_vec_float (cpu, Fn, 0);
7932       float val2 = aarch64_get_vec_float (cpu, Fn, 1);
7933
7934       aarch64_set_FP_float (cpu, Fd, val1 + val2);
7935     }
7936 }
7937
7938 /* Floating point absolute difference.  */
7939
7940 static void
7941 do_scalar_FABD (sim_cpu *cpu)
7942 {
7943   /* instr [31,23] = 0111 1110 1
7944      instr [22]    = float(0)/double(1)
7945      instr [21]    = 1
7946      instr [20,16] = Rm
7947      instr [15,10] = 1101 01
7948      instr [9, 5]  = Rn
7949      instr [4, 0]  = Rd.  */
7950
7951   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
7952   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7953   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7954
7955   NYI_assert (31, 23, 0x0FD);
7956   NYI_assert (21, 21, 1);
7957   NYI_assert (15, 10, 0x35);
7958
7959   if (uimm (aarch64_get_instr (cpu), 22, 22))
7960     aarch64_set_FP_double (cpu, rd,
7961                            fabs (aarch64_get_FP_double (cpu, rn)
7962                                  - aarch64_get_FP_double (cpu, rm)));
7963   else
7964     aarch64_set_FP_float (cpu, rd,
7965                           fabsf (aarch64_get_FP_float (cpu, rn)
7966                                  - aarch64_get_FP_float (cpu, rm)));
7967 }
7968
7969 static void
7970 do_scalar_CMGT (sim_cpu *cpu)
7971 {
7972   /* instr [31,21] = 0101 1110 111
7973      instr [20,16] = Rm
7974      instr [15,10] = 00 1101
7975      instr [9, 5]  = Rn
7976      instr [4, 0]  = Rd.  */
7977
7978   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
7979   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7980   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7981
7982   NYI_assert (31, 21, 0x2F7);
7983   NYI_assert (15, 10, 0x0D);
7984
7985   aarch64_set_vec_u64 (cpu, rd, 0,
7986                        aarch64_get_vec_u64 (cpu, rn, 0) >
7987                        aarch64_get_vec_u64 (cpu, rm, 0) ? -1L : 0L);
7988 }
7989
7990 static void
7991 do_scalar_USHR (sim_cpu *cpu)
7992 {
7993   /* instr [31,23] = 0111 1111 0
7994      instr [22,16] = shift amount
7995      instr [15,10] = 0000 01
7996      instr [9, 5]  = Rn
7997      instr [4, 0]  = Rd.  */
7998
7999   unsigned amount = 128 - uimm (aarch64_get_instr (cpu), 22, 16);
8000   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8001   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8002
8003   NYI_assert (31, 23, 0x0FE);
8004   NYI_assert (15, 10, 0x01);
8005
8006   aarch64_set_vec_u64 (cpu, rd, 0,
8007                        aarch64_get_vec_u64 (cpu, rn, 0) >> amount);
8008 }
8009
8010 static void
8011 do_scalar_SHL (sim_cpu *cpu)
8012 {
8013   /* instr [31,23] = 0111 1101 0
8014      instr [22,16] = shift amount
8015      instr [15,10] = 0101 01
8016      instr [9, 5]  = Rn
8017      instr [4, 0]  = Rd.  */
8018
8019   unsigned amount = uimm (aarch64_get_instr (cpu), 22, 16) - 64;
8020   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8021   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8022
8023   NYI_assert (31, 23, 0x0BE);
8024   NYI_assert (15, 10, 0x15);
8025
8026   if (uimm (aarch64_get_instr (cpu), 22, 22) == 0)
8027     HALT_UNALLOC;
8028
8029   aarch64_set_vec_u64 (cpu, rd, 0,
8030                        aarch64_get_vec_u64 (cpu, rn, 0) << amount);
8031 }
8032
8033 /* FCMEQ FCMGT FCMGE.  */
8034 static void
8035 do_scalar_FCM (sim_cpu *cpu)
8036 {
8037   /* instr [31,30] = 01
8038      instr [29]    = U
8039      instr [28,24] = 1 1110
8040      instr [23]    = E
8041      instr [22]    = size
8042      instr [21]    = 1
8043      instr [20,16] = Rm
8044      instr [15,12] = 1110
8045      instr [11]    = AC
8046      instr [10]    = 1
8047      instr [9, 5]  = Rn
8048      instr [4, 0]  = Rd.  */
8049
8050   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8051   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8052   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8053   unsigned EUac = (uimm (aarch64_get_instr (cpu), 23, 23) << 2)
8054     | (uimm (aarch64_get_instr (cpu), 29, 29) << 1)
8055     | uimm (aarch64_get_instr (cpu), 11, 11);
8056   unsigned result;
8057   float val1;
8058   float val2;
8059
8060   NYI_assert (31, 30, 1);
8061   NYI_assert (28, 24, 0x1E);
8062   NYI_assert (21, 21, 1);
8063   NYI_assert (15, 12, 0xE);
8064   NYI_assert (10, 10, 1);
8065
8066   if (uimm (aarch64_get_instr (cpu), 22, 22))
8067     {
8068       double val1 = aarch64_get_FP_double (cpu, rn);
8069       double val2 = aarch64_get_FP_double (cpu, rm);
8070
8071       switch (EUac)
8072         {
8073         case 0: /* 000 */
8074           result = val1 == val2;
8075           break;
8076
8077         case 3: /* 011 */
8078           val1 = fabs (val1);
8079           val2 = fabs (val2);
8080           /* Fall through. */
8081         case 2: /* 010 */
8082           result = val1 >= val2;
8083           break;
8084
8085         case 7: /* 111 */
8086           val1 = fabs (val1);
8087           val2 = fabs (val2);
8088           /* Fall through. */
8089         case 6: /* 110 */
8090           result = val1 > val2;
8091           break;
8092
8093         default:
8094           HALT_UNALLOC;
8095         }
8096
8097       aarch64_set_vec_u32 (cpu, rd, 0, result ? -1 : 0);
8098       return;
8099     }
8100
8101   val1 = aarch64_get_FP_float (cpu, rn);
8102   val2 = aarch64_get_FP_float (cpu, rm);
8103
8104   switch (EUac)
8105     {
8106     case 0: /* 000 */
8107       result = val1 == val2;
8108       break;
8109
8110     case 3: /* 011 */
8111       val1 = fabsf (val1);
8112       val2 = fabsf (val2);
8113       /* Fall through. */
8114     case 2: /* 010 */
8115       result = val1 >= val2;
8116       break;
8117
8118     case 7: /* 111 */
8119       val1 = fabsf (val1);
8120       val2 = fabsf (val2);
8121       /* Fall through. */
8122     case 6: /* 110 */
8123       result = val1 > val2;
8124       break;
8125
8126     default:
8127       HALT_UNALLOC;
8128     }
8129
8130   aarch64_set_vec_u32 (cpu, rd, 0, result ? -1 : 0);
8131 }
8132
8133 /* An alias of DUP.  */
8134 static void
8135 do_scalar_MOV (sim_cpu *cpu)
8136 {
8137   /* instr [31,21] = 0101 1110 000
8138      instr [20,16] = imm5
8139      instr [15,10] = 0000 01
8140      instr [9, 5]  = Rn
8141      instr [4, 0]  = Rd.  */
8142
8143   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8144   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8145   unsigned index;
8146
8147   NYI_assert (31, 21, 0x2F0);
8148   NYI_assert (15, 10, 0x01);
8149
8150   if (uimm (aarch64_get_instr (cpu), 16, 16))
8151     {
8152       /* 8-bit.  */
8153       index = uimm (aarch64_get_instr (cpu), 20, 17);
8154       aarch64_set_vec_u8
8155         (cpu, rd, 0, aarch64_get_vec_u8 (cpu, rn, index));
8156     }
8157   else if (uimm (aarch64_get_instr (cpu), 17, 17))
8158     {
8159       /* 16-bit.  */
8160       index = uimm (aarch64_get_instr (cpu), 20, 18);
8161       aarch64_set_vec_u16
8162         (cpu, rd, 0, aarch64_get_vec_u16 (cpu, rn, index));
8163     }
8164   else if (uimm (aarch64_get_instr (cpu), 18, 18))
8165     {
8166       /* 32-bit.  */
8167       index = uimm (aarch64_get_instr (cpu), 20, 19);
8168       aarch64_set_vec_u32
8169         (cpu, rd, 0, aarch64_get_vec_u32 (cpu, rn, index));
8170     }
8171   else if (uimm (aarch64_get_instr (cpu), 19, 19))
8172     {
8173       /* 64-bit.  */
8174       index = uimm (aarch64_get_instr (cpu), 20, 20);
8175       aarch64_set_vec_u64
8176         (cpu, rd, 0, aarch64_get_vec_u64 (cpu, rn, index));
8177     }
8178   else
8179     HALT_UNALLOC;
8180 }
8181
8182 static void
8183 do_double_add (sim_cpu *cpu)
8184 {
8185   /* instr [28,25] = 1111.  */
8186   unsigned Fd;
8187   unsigned Fm;
8188   unsigned Fn;
8189   double val1;
8190   double val2;
8191
8192   switch (uimm (aarch64_get_instr (cpu), 31, 23))
8193     {
8194     case 0xBC:
8195       switch (uimm (aarch64_get_instr (cpu), 15, 10))
8196         {
8197         case 0x01: do_scalar_MOV (cpu); return;
8198         case 0x39: do_scalar_FCM (cpu); return;
8199         case 0x3B: do_scalar_FCM (cpu); return;
8200         }
8201       break;
8202
8203     case 0xBE: do_scalar_SHL (cpu); return;
8204
8205     case 0xFC:
8206       switch (uimm (aarch64_get_instr (cpu), 15, 10))
8207         {
8208         case 0x36: do_scalar_FADDP (cpu); return;
8209         case 0x39: do_scalar_FCM (cpu); return;
8210         case 0x3B: do_scalar_FCM (cpu); return;
8211         }
8212       break;
8213
8214     case 0xFD:
8215       switch (uimm (aarch64_get_instr (cpu), 15, 10))
8216         {
8217         case 0x0D: do_scalar_CMGT (cpu); return;
8218         case 0x35: do_scalar_FABD (cpu); return;
8219         case 0x39: do_scalar_FCM (cpu); return;
8220         case 0x3B: do_scalar_FCM (cpu); return;
8221         default:
8222           HALT_NYI;
8223         }
8224
8225     case 0xFE: do_scalar_USHR (cpu); return;
8226     default:
8227       break;
8228     }
8229
8230   /* instr [31,21] = 0101 1110 111
8231      instr [20,16] = Fn
8232      instr [15,10] = 1000 01
8233      instr [9,5]   = Fm
8234      instr [4,0]   = Fd.  */
8235   if (uimm (aarch64_get_instr (cpu), 31, 21) != 0x2F7
8236       || uimm (aarch64_get_instr (cpu), 15, 10) != 0x21)
8237     HALT_NYI;
8238
8239   Fd = uimm (aarch64_get_instr (cpu), 4, 0);
8240   Fm = uimm (aarch64_get_instr (cpu), 9, 5);
8241   Fn = uimm (aarch64_get_instr (cpu), 20, 16);
8242
8243   val1 = aarch64_get_FP_double (cpu, Fm);
8244   val2 = aarch64_get_FP_double (cpu, Fn);
8245
8246   aarch64_set_FP_double (cpu, Fd, val1 + val2);
8247 }
8248
8249 static void
8250 dexAdvSIMD1 (sim_cpu *cpu)
8251 {
8252   /* instr [28,25] = 1 111.  */
8253
8254   /* we are currently only interested in the basic
8255      scalar fp routines which all have bit 30 = 0.  */
8256   if (uimm (aarch64_get_instr (cpu), 30, 30))
8257     do_double_add (cpu);
8258
8259   /* instr[24] is set for FP data processing 3-source and clear for
8260      all other basic scalar fp instruction groups.  */
8261   else if (uimm (aarch64_get_instr (cpu), 24, 24))
8262     dexSimpleFPDataProc3Source (cpu);
8263
8264   /* instr[21] is clear for floating <-> fixed conversions and set for
8265      all other basic scalar fp instruction groups.  */
8266   else if (!uimm (aarch64_get_instr (cpu), 21, 21))
8267     dexSimpleFPFixedConvert (cpu);
8268
8269   /* instr[11,10] : 01 ==> cond compare, 10 ==> Data Proc 2 Source
8270      11 ==> cond select,  00 ==> other.  */
8271   else
8272     switch (uimm (aarch64_get_instr (cpu), 11, 10))
8273       {
8274       case 1: dexSimpleFPCondCompare (cpu); return;
8275       case 2: dexSimpleFPDataProc2Source (cpu); return;
8276       case 3: dexSimpleFPCondSelect (cpu); return;
8277
8278       default:
8279         /* Now an ordered cascade of tests.
8280            FP immediate has aarch64_get_instr (cpu)[12] == 1.
8281            FP compare has aarch64_get_instr (cpu)[13] == 1.
8282            FP Data Proc 1 Source has aarch64_get_instr (cpu)[14] == 1.
8283            FP floating <--> integer conversions has aarch64_get_instr (cpu)[15] == 0.  */
8284         if (uimm (aarch64_get_instr (cpu), 12, 12))
8285           dexSimpleFPImmediate (cpu);
8286
8287         else if (uimm (aarch64_get_instr (cpu), 13, 13))
8288           dexSimpleFPCompare (cpu);
8289
8290         else if (uimm (aarch64_get_instr (cpu), 14, 14))
8291           dexSimpleFPDataProc1Source (cpu);
8292
8293         else if (!uimm (aarch64_get_instr (cpu), 15, 15))
8294           dexSimpleFPIntegerConvert (cpu);
8295
8296         else
8297           /* If we get here then instr[15] == 1 which means UNALLOC.  */
8298           HALT_UNALLOC;
8299       }
8300 }
8301
8302 /* PC relative addressing.  */
8303
8304 static void
8305 pcadr (sim_cpu *cpu)
8306 {
8307   /* instr[31] = op : 0 ==> ADR, 1 ==> ADRP
8308      instr[30,29] = immlo
8309      instr[23,5] = immhi.  */
8310   uint64_t address;
8311   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8312   uint32_t isPage = uimm (aarch64_get_instr (cpu), 31, 31);
8313   union { int64_t u64; uint64_t s64; } imm;
8314   uint64_t offset;
8315
8316   imm.s64 = simm64 (aarch64_get_instr (cpu), 23, 5);
8317   offset = imm.u64;
8318   offset = (offset << 2) | uimm (aarch64_get_instr (cpu), 30, 29);
8319
8320   address = aarch64_get_PC (cpu);
8321
8322   if (isPage)
8323     {
8324       offset <<= 12;
8325       address &= ~0xfff;
8326     }
8327
8328   aarch64_set_reg_u64 (cpu, rd, NO_SP, address + offset);
8329 }
8330
8331 /* Specific decode and execute for group Data Processing Immediate.  */
8332
8333 static void
8334 dexPCRelAddressing (sim_cpu *cpu)
8335 {
8336   /* assert instr[28,24] = 10000.  */
8337   pcadr (cpu);
8338 }
8339
8340 /* Immediate logical.
8341    The bimm32/64 argument is constructed by replicating a 2, 4, 8,
8342    16, 32 or 64 bit sequence pulled out at decode and possibly
8343    inverting it..
8344
8345    N.B. the output register (dest) can normally be Xn or SP
8346    the exception occurs for flag setting instructions which may
8347    only use Xn for the output (dest).  The input register can
8348    never be SP.  */
8349
8350 /* 32 bit and immediate.  */
8351 static void
8352 and32 (sim_cpu *cpu, uint32_t bimm)
8353 {
8354   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8355   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8356
8357   aarch64_set_reg_u64 (cpu, rd, SP_OK,
8358                        aarch64_get_reg_u32 (cpu, rn, NO_SP) & bimm);
8359 }
8360
8361 /* 64 bit and immediate.  */
8362 static void
8363 and64 (sim_cpu *cpu, uint64_t bimm)
8364 {
8365   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8366   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8367
8368   aarch64_set_reg_u64 (cpu, rd, SP_OK,
8369                        aarch64_get_reg_u64 (cpu, rn, NO_SP) & bimm);
8370 }
8371
8372 /* 32 bit and immediate set flags.  */
8373 static void
8374 ands32 (sim_cpu *cpu, uint32_t bimm)
8375 {
8376   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8377   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8378
8379   uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8380   uint32_t value2 = bimm;
8381
8382   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8383   set_flags_for_binop32 (cpu, value1 & value2);
8384 }
8385
8386 /* 64 bit and immediate set flags.  */
8387 static void
8388 ands64 (sim_cpu *cpu, uint64_t bimm)
8389 {
8390   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8391   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8392
8393   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
8394   uint64_t value2 = bimm;
8395
8396   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8397   set_flags_for_binop64 (cpu, value1 & value2);
8398 }
8399
8400 /* 32 bit exclusive or immediate.  */
8401 static void
8402 eor32 (sim_cpu *cpu, uint32_t bimm)
8403 {
8404   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8405   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8406
8407   aarch64_set_reg_u64 (cpu, rd, SP_OK,
8408                        aarch64_get_reg_u32 (cpu, rn, NO_SP) ^ bimm);
8409 }
8410
8411 /* 64 bit exclusive or immediate.  */
8412 static void
8413 eor64 (sim_cpu *cpu, uint64_t bimm)
8414 {
8415   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8416   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8417
8418   aarch64_set_reg_u64 (cpu, rd, SP_OK,
8419                        aarch64_get_reg_u64 (cpu, rn, NO_SP) ^ bimm);
8420 }
8421
8422 /* 32 bit or immediate.  */
8423 static void
8424 orr32 (sim_cpu *cpu, uint32_t bimm)
8425 {
8426   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8427   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8428
8429   aarch64_set_reg_u64 (cpu, rd, SP_OK,
8430                        aarch64_get_reg_u32 (cpu, rn, NO_SP) | bimm);
8431 }
8432
8433 /* 64 bit or immediate.  */
8434 static void
8435 orr64 (sim_cpu *cpu, uint64_t bimm)
8436 {
8437   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8438   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8439
8440   aarch64_set_reg_u64 (cpu, rd, SP_OK,
8441                        aarch64_get_reg_u64 (cpu, rn, NO_SP) | bimm);
8442 }
8443
8444 /* Logical shifted register.
8445    These allow an optional LSL, ASR, LSR or ROR to the second source
8446    register with a count up to the register bit count.
8447    N.B register args may not be SP.  */
8448
8449 /* 32 bit AND shifted register.  */
8450 static void
8451 and32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8452 {
8453   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8454   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8455   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8456
8457   aarch64_set_reg_u64
8458     (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8459      & shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8460 }
8461
8462 /* 64 bit AND shifted register.  */
8463 static void
8464 and64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8465 {
8466   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8467   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8468   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8469
8470   aarch64_set_reg_u64
8471     (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8472      & shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8473 }
8474
8475 /* 32 bit AND shifted register setting flags.  */
8476 static void
8477 ands32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8478 {
8479   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8480   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8481   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8482
8483   uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8484   uint32_t value2 = shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
8485                                shift, count);
8486
8487   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8488   set_flags_for_binop32 (cpu, value1 & value2);
8489 }
8490
8491 /* 64 bit AND shifted register setting flags.  */
8492 static void
8493 ands64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8494 {
8495   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8496   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8497   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8498
8499   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
8500   uint64_t value2 = shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
8501                                shift, count);
8502
8503   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8504   set_flags_for_binop64 (cpu, value1 & value2);
8505 }
8506
8507 /* 32 bit BIC shifted register.  */
8508 static void
8509 bic32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8510 {
8511   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8512   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8513   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8514
8515   aarch64_set_reg_u64
8516     (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8517      & ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8518 }
8519
8520 /* 64 bit BIC shifted register.  */
8521 static void
8522 bic64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8523 {
8524   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8525   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8526   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8527
8528   aarch64_set_reg_u64
8529     (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8530      & ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8531 }
8532
8533 /* 32 bit BIC shifted register setting flags.  */
8534 static void
8535 bics32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8536 {
8537   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8538   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8539   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8540
8541   uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8542   uint32_t value2 = ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
8543                                  shift, count);
8544
8545   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8546   set_flags_for_binop32 (cpu, value1 & value2);
8547 }
8548
8549 /* 64 bit BIC shifted register setting flags.  */
8550 static void
8551 bics64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8552 {
8553   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8554   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8555   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8556
8557   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
8558   uint64_t value2 = ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
8559                                  shift, count);
8560
8561   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8562   set_flags_for_binop64 (cpu, value1 & value2);
8563 }
8564
8565 /* 32 bit EON shifted register.  */
8566 static void
8567 eon32_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 EON shifted register.  */
8579 static void
8580 eon64_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 EOR shifted register.  */
8592 static void
8593 eor32_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   aarch64_set_reg_u64
8600     (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8601      ^ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8602 }
8603
8604 /* 64 bit EOR shifted register.  */
8605 static void
8606 eor64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8607 {
8608   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8609   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8610   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8611
8612   aarch64_set_reg_u64
8613     (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8614      ^ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8615 }
8616
8617 /* 32 bit ORR shifted register.  */
8618 static void
8619 orr32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8620 {
8621   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8622   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8623   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8624
8625   aarch64_set_reg_u64
8626     (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8627      | shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8628 }
8629
8630 /* 64 bit ORR shifted register.  */
8631 static void
8632 orr64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8633 {
8634   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8635   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8636   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8637
8638   aarch64_set_reg_u64
8639     (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8640      | shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8641 }
8642
8643 /* 32 bit ORN shifted register.  */
8644 static void
8645 orn32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8646 {
8647   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8648   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8649   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8650
8651   aarch64_set_reg_u64
8652     (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8653      | ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8654 }
8655
8656 /* 64 bit ORN shifted register.  */
8657 static void
8658 orn64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8659 {
8660   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8661   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8662   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8663
8664   aarch64_set_reg_u64
8665     (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8666      | ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8667 }
8668
8669 static void
8670 dexLogicalImmediate (sim_cpu *cpu)
8671 {
8672   /* assert instr[28,23] = 1001000
8673      instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
8674      instr[30,29] = op : 0 ==> AND, 1 ==> ORR, 2 ==> EOR, 3 ==> ANDS
8675      instr[22] = N : used to construct immediate mask
8676      instr[21,16] = immr
8677      instr[15,10] = imms
8678      instr[9,5] = Rn
8679      instr[4,0] = Rd  */
8680
8681   /* 32 bit operations must have N = 0 or else we have an UNALLOC.  */
8682   uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
8683   uint32_t N = uimm (aarch64_get_instr (cpu), 22, 22);
8684   /* uint32_t immr = uimm (aarch64_get_instr (cpu), 21, 16);.  */
8685   /* uint32_t imms = uimm (aarch64_get_instr (cpu), 15, 10);.  */
8686   uint32_t index = uimm (aarch64_get_instr (cpu), 22, 10);
8687   uint64_t bimm64 = LITable [index];
8688   uint32_t dispatch = uimm (aarch64_get_instr (cpu), 30, 29);
8689
8690   if (~size & N)
8691     HALT_UNALLOC;
8692
8693   if (!bimm64)
8694     HALT_UNALLOC;
8695
8696   if (size == 0)
8697     {
8698       uint32_t bimm = (uint32_t) bimm64;
8699
8700       switch (dispatch)
8701         {
8702         case 0: and32 (cpu, bimm); return;
8703         case 1: orr32 (cpu, bimm); return;
8704         case 2: eor32 (cpu, bimm); return;
8705         case 3: ands32 (cpu, bimm); return;
8706         }
8707     }
8708   else
8709     {
8710       switch (dispatch)
8711         {
8712         case 0: and64 (cpu, bimm64); return;
8713         case 1: orr64 (cpu, bimm64); return;
8714         case 2: eor64 (cpu, bimm64); return;
8715         case 3: ands64 (cpu, bimm64); return;
8716         }
8717     }
8718   HALT_UNALLOC;
8719 }
8720
8721 /* Immediate move.
8722    The uimm argument is a 16 bit value to be inserted into the
8723    target register the pos argument locates the 16 bit word in the
8724    dest register i.e. it is in {0, 1} for 32 bit and {0, 1, 2,
8725    3} for 64 bit.
8726    N.B register arg may not be SP so it should be.
8727    accessed using the setGZRegisterXXX accessors.  */
8728
8729 /* 32 bit move 16 bit immediate zero remaining shorts.  */
8730 static void
8731 movz32 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8732 {
8733   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8734
8735   aarch64_set_reg_u64 (cpu, rd, NO_SP, val << (pos * 16));
8736 }
8737
8738 /* 64 bit move 16 bit immediate zero remaining shorts.  */
8739 static void
8740 movz64 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8741 {
8742   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8743
8744   aarch64_set_reg_u64 (cpu, rd, NO_SP, ((uint64_t) val) << (pos * 16));
8745 }
8746
8747 /* 32 bit move 16 bit immediate negated.  */
8748 static void
8749 movn32 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8750 {
8751   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8752
8753   aarch64_set_reg_u64 (cpu, rd, NO_SP, ((val << (pos * 16)) ^ 0xffffffffU));
8754 }
8755
8756 /* 64 bit move 16 bit immediate negated.  */
8757 static void
8758 movn64 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8759 {
8760   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8761
8762   aarch64_set_reg_u64
8763     (cpu, rd, NO_SP, ((((uint64_t) val) << (pos * 16))
8764                       ^ 0xffffffffffffffffULL));
8765 }
8766
8767 /* 32 bit move 16 bit immediate keep remaining shorts.  */
8768 static void
8769 movk32 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8770 {
8771   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8772   uint32_t current = aarch64_get_reg_u32 (cpu, rd, NO_SP);
8773   uint32_t value = val << (pos * 16);
8774   uint32_t mask = ~(0xffffU << (pos * 16));
8775
8776   aarch64_set_reg_u64 (cpu, rd, NO_SP, (value | (current & mask)));
8777 }
8778
8779 /* 64 bit move 16 it immediate keep remaining shorts.  */
8780 static void
8781 movk64 (sim_cpu *cpu, uint32_t val, uint32_t pos)
8782 {
8783   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8784   uint64_t current = aarch64_get_reg_u64 (cpu, rd, NO_SP);
8785   uint64_t value = (uint64_t) val << (pos * 16);
8786   uint64_t mask = ~(0xffffULL << (pos * 16));
8787
8788   aarch64_set_reg_u64 (cpu, rd, NO_SP, (value | (current & mask)));
8789 }
8790
8791 static void
8792 dexMoveWideImmediate (sim_cpu *cpu)
8793 {
8794   /* assert instr[28:23] = 100101
8795      instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
8796      instr[30,29] = op : 0 ==> MOVN, 1 ==> UNALLOC, 2 ==> MOVZ, 3 ==> MOVK
8797      instr[22,21] = shift : 00 == LSL#0, 01 = LSL#16, 10 = LSL#32, 11 = LSL#48
8798      instr[20,5] = uimm16
8799      instr[4,0] = Rd  */
8800
8801   /* N.B. the (multiple of 16) shift is applied by the called routine,
8802      we just pass the multiplier.  */
8803
8804   uint32_t imm;
8805   uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
8806   uint32_t op = uimm (aarch64_get_instr (cpu), 30, 29);
8807   uint32_t shift = uimm (aarch64_get_instr (cpu), 22, 21);
8808
8809   /* 32 bit can only shift 0 or 1 lot of 16.
8810      anything else is an unallocated instruction.  */
8811   if (size == 0 && (shift > 1))
8812     HALT_UNALLOC;
8813
8814   if (op == 1)
8815     HALT_UNALLOC;
8816
8817   imm = uimm (aarch64_get_instr (cpu), 20, 5);
8818
8819   if (size == 0)
8820     {
8821       if (op == 0)
8822         movn32 (cpu, imm, shift);
8823       else if (op == 2)
8824         movz32 (cpu, imm, shift);
8825       else
8826         movk32 (cpu, imm, shift);
8827     }
8828   else
8829     {
8830       if (op == 0)
8831         movn64 (cpu, imm, shift);
8832       else if (op == 2)
8833         movz64 (cpu, imm, shift);
8834       else
8835         movk64 (cpu, imm, shift);
8836     }
8837 }
8838
8839 /* Bitfield operations.
8840    These take a pair of bit positions r and s which are in {0..31}
8841    or {0..63} depending on the instruction word size.
8842    N.B register args may not be SP.  */
8843
8844 /* OK, we start with ubfm which just needs to pick
8845    some bits out of source zero the rest and write
8846    the result to dest.  Just need two logical shifts.  */
8847
8848 /* 32 bit bitfield move, left and right of affected zeroed
8849    if r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>.  */
8850 static void
8851 ubfm32 (sim_cpu *cpu, uint32_t r, uint32_t s)
8852 {
8853   unsigned rd;
8854   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8855   uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8856
8857   /* Pick either s+1-r or s+1 consecutive bits out of the original word.  */
8858   if (r <= s)
8859     {
8860       /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
8861          We want only bits s:xxx:r at the bottom of the word
8862          so we LSL bit s up to bit 31 i.e. by 31 - s
8863          and then we LSR to bring bit 31 down to bit s - r
8864          i.e. by 31 + r - s.  */
8865       value <<= 31 - s;
8866       value >>= 31 + r - s;
8867     }
8868   else
8869     {
8870       /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0
8871          We want only bits s:xxx:0 starting at it 31-(r-1)
8872          so we LSL bit s up to bit 31 i.e. by 31 - s
8873          and then we LSL to bring bit 31 down to 31-(r-1)+s
8874          i.e. by r - (s + 1).  */
8875       value <<= 31 - s;
8876       value >>= r - (s + 1);
8877     }
8878
8879   rd = uimm (aarch64_get_instr (cpu), 4, 0);
8880   aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
8881 }
8882
8883 /* 64 bit bitfield move, left and right of affected zeroed
8884    if r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>.  */
8885 static void
8886 ubfm (sim_cpu *cpu, uint32_t r, uint32_t s)
8887 {
8888   unsigned rd;
8889   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8890   uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
8891
8892   if (r <= s)
8893     {
8894       /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
8895          We want only bits s:xxx:r at the bottom of the word.
8896          So we LSL bit s up to bit 63 i.e. by 63 - s
8897          and then we LSR to bring bit 63 down to bit s - r
8898          i.e. by 63 + r - s.  */
8899       value <<= 63 - s;
8900       value >>= 63 + r - s;
8901     }
8902   else
8903     {
8904       /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0.
8905          We want only bits s:xxx:0 starting at it 63-(r-1).
8906          So we LSL bit s up to bit 63 i.e. by 63 - s
8907          and then we LSL to bring bit 63 down to 63-(r-1)+s
8908          i.e. by r - (s + 1).  */
8909       value <<= 63 - s;
8910       value >>= r - (s + 1);
8911     }
8912
8913   rd = uimm (aarch64_get_instr (cpu), 4, 0);
8914   aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
8915 }
8916
8917 /* The signed versions need to insert sign bits
8918    on the left of the inserted bit field. so we do
8919    much the same as the unsigned version except we
8920    use an arithmetic shift right -- this just means
8921    we need to operate on signed values.  */
8922
8923 /* 32 bit bitfield move, left of affected sign-extended, right zeroed.  */
8924 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>.  */
8925 static void
8926 sbfm32 (sim_cpu *cpu, uint32_t r, uint32_t s)
8927 {
8928   unsigned rd;
8929   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8930   /* as per ubfm32 but use an ASR instead of an LSR.  */
8931   int32_t value = aarch64_get_reg_s32 (cpu, rn, NO_SP);
8932
8933   if (r <= s)
8934     {
8935       value <<= 31 - s;
8936       value >>= 31 + r - s;
8937     }
8938   else
8939     {
8940       value <<= 31 - s;
8941       value >>= r - (s + 1);
8942     }
8943
8944   rd = uimm (aarch64_get_instr (cpu), 4, 0);
8945   aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) value);
8946 }
8947
8948 /* 64 bit bitfield move, left of affected sign-extended, right zeroed.  */
8949 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>.  */
8950 static void
8951 sbfm (sim_cpu *cpu, uint32_t r, uint32_t s)
8952 {
8953   unsigned rd;
8954   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8955   /* acpu per ubfm but use an ASR instead of an LSR.  */
8956   int64_t value = aarch64_get_reg_s64 (cpu, rn, NO_SP);
8957
8958   if (r <= s)
8959     {
8960       value <<= 63 - s;
8961       value >>= 63 + r - s;
8962     }
8963   else
8964     {
8965       value <<= 63 - s;
8966       value >>= r - (s + 1);
8967     }
8968
8969   rd = uimm (aarch64_get_instr (cpu), 4, 0);
8970   aarch64_set_reg_s64 (cpu, rd, NO_SP, value);
8971 }
8972
8973 /* Finally, these versions leave non-affected bits
8974    as is. so we need to generate the bits as per
8975    ubfm and also generate a mask to pick the
8976    bits from the original and computed values.  */
8977
8978 /* 32 bit bitfield move, non-affected bits left as is.
8979    If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>.  */
8980 static void
8981 bfm32 (sim_cpu *cpu, uint32_t r, uint32_t s)
8982 {
8983   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8984   uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8985   uint32_t mask = -1;
8986   unsigned rd;
8987   uint32_t value2;
8988
8989   /* Pick either s+1-r or s+1 consecutive bits out of the original word.  */
8990   if (r <= s)
8991     {
8992       /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
8993          We want only bits s:xxx:r at the bottom of the word
8994          so we LSL bit s up to bit 31 i.e. by 31 - s
8995          and then we LSR to bring bit 31 down to bit s - r
8996          i.e. by 31 + r - s.  */
8997       value <<= 31 - s;
8998       value >>= 31 + r - s;
8999       /* the mask must include the same bits.  */
9000       mask <<= 31 - s;
9001       mask >>= 31 + r - s;
9002     }
9003   else
9004     {
9005       /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0.
9006          We want only bits s:xxx:0 starting at it 31-(r-1)
9007          so we LSL bit s up to bit 31 i.e. by 31 - s
9008          and then we LSL to bring bit 31 down to 31-(r-1)+s
9009          i.e. by r - (s + 1).  */
9010       value <<= 31 - s;
9011       value >>= r - (s + 1);
9012       /* The mask must include the same bits.  */
9013       mask <<= 31 - s;
9014       mask >>= r - (s + 1);
9015     }
9016
9017   rd = uimm (aarch64_get_instr (cpu), 4, 0);
9018   value2 = aarch64_get_reg_u32 (cpu, rd, NO_SP);
9019
9020   value2 &= ~mask;
9021   value2 |= value;
9022
9023   aarch64_set_reg_u64
9024     (cpu, rd, NO_SP, (aarch64_get_reg_u32 (cpu, rd, NO_SP) & ~mask) | value);
9025 }
9026
9027 /* 64 bit bitfield move, non-affected bits left as is.
9028    If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>.  */
9029 static void
9030 bfm (sim_cpu *cpu, uint32_t r, uint32_t s)
9031 {
9032   unsigned rd;
9033   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9034   uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
9035   uint64_t mask = 0xffffffffffffffffULL;
9036
9037   if (r <= s)
9038     {
9039       /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
9040          We want only bits s:xxx:r at the bottom of the word
9041          so we LSL bit s up to bit 63 i.e. by 63 - s
9042          and then we LSR to bring bit 63 down to bit s - r
9043          i.e. by 63 + r - s.  */
9044       value <<= 63 - s;
9045       value >>= 63 + r - s;
9046       /* The mask must include the same bits.  */
9047       mask <<= 63 - s;
9048       mask >>= 63 + r - s;
9049     }
9050   else
9051     {
9052       /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0
9053          We want only bits s:xxx:0 starting at it 63-(r-1)
9054          so we LSL bit s up to bit 63 i.e. by 63 - s
9055          and then we LSL to bring bit 63 down to 63-(r-1)+s
9056          i.e. by r - (s + 1).  */
9057       value <<= 63 - s;
9058       value >>= r - (s + 1);
9059       /* The mask must include the same bits.  */
9060       mask <<= 63 - s;
9061       mask >>= r - (s + 1);
9062     }
9063
9064   rd = uimm (aarch64_get_instr (cpu), 4, 0);
9065   aarch64_set_reg_u64
9066     (cpu, rd, NO_SP, (aarch64_get_reg_u64 (cpu, rd, NO_SP) & ~mask) | value);
9067 }
9068
9069 static void
9070 dexBitfieldImmediate (sim_cpu *cpu)
9071 {
9072   /* assert instr[28:23] = 100110
9073      instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9074      instr[30,29] = op : 0 ==> SBFM, 1 ==> BFM, 2 ==> UBFM, 3 ==> UNALLOC
9075      instr[22] = N : must be 0 for 32 bit, 1 for 64 bit ow UNALLOC
9076      instr[21,16] = immr : 0xxxxx for 32 bit, xxxxxx for 64 bit
9077      instr[15,10] = imms :  0xxxxx for 32 bit, xxxxxx for 64 bit
9078      instr[9,5] = Rn
9079      instr[4,0] = Rd  */
9080
9081   /* 32 bit operations must have N = 0 or else we have an UNALLOC.  */
9082   uint32_t dispatch;
9083   uint32_t imms;
9084   uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
9085   uint32_t N = uimm (aarch64_get_instr (cpu), 22, 22);
9086   /* 32 bit operations must have immr[5] = 0 and imms[5] = 0.  */
9087   /* or else we have an UNALLOC.  */
9088   uint32_t immr = uimm (aarch64_get_instr (cpu), 21, 16);
9089
9090   if (~size & N)
9091     HALT_UNALLOC;
9092
9093   if (!size && uimm (immr, 5, 5))
9094     HALT_UNALLOC;
9095
9096   imms = uimm (aarch64_get_instr (cpu), 15, 10);
9097   if (!size && uimm (imms, 5, 5))
9098     HALT_UNALLOC;
9099
9100   /* Switch on combined size and op.  */
9101   dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
9102   switch (dispatch)
9103     {
9104     case 0: sbfm32 (cpu, immr, imms); return;
9105     case 1: bfm32 (cpu, immr, imms); return;
9106     case 2: ubfm32 (cpu, immr, imms); return;
9107     case 4: sbfm (cpu, immr, imms); return;
9108     case 5: bfm (cpu, immr, imms); return;
9109     case 6: ubfm (cpu, immr, imms); return;
9110     default: HALT_UNALLOC;
9111     }
9112 }
9113
9114 static void
9115 do_EXTR_32 (sim_cpu *cpu)
9116 {
9117   /* instr[31:21] = 00010011100
9118      instr[20,16] = Rm
9119      instr[15,10] = imms :  0xxxxx for 32 bit
9120      instr[9,5]   = Rn
9121      instr[4,0]   = Rd  */
9122   unsigned rm   = uimm (aarch64_get_instr (cpu), 20, 16);
9123   unsigned imms = uimm (aarch64_get_instr (cpu), 15, 10) & 31;
9124   unsigned rn   = uimm (aarch64_get_instr (cpu),  9,  5);
9125   unsigned rd   = uimm (aarch64_get_instr (cpu),  4,  0);
9126   uint64_t val1;
9127   uint64_t val2;
9128
9129   val1 = aarch64_get_reg_u32 (cpu, rm, NO_SP);
9130   val1 >>= imms;
9131   val2 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
9132   val2 <<= (32 - imms);
9133
9134   aarch64_set_reg_u64 (cpu, rd, NO_SP, val1 | val2);
9135 }
9136
9137 static void
9138 do_EXTR_64 (sim_cpu *cpu)
9139 {
9140   /* instr[31:21] = 10010011100
9141      instr[20,16] = Rm
9142      instr[15,10] = imms
9143      instr[9,5]   = Rn
9144      instr[4,0]   = Rd  */
9145   unsigned rm   = uimm (aarch64_get_instr (cpu), 20, 16);
9146   unsigned imms = uimm (aarch64_get_instr (cpu), 15, 10) & 63;
9147   unsigned rn   = uimm (aarch64_get_instr (cpu),  9,  5);
9148   unsigned rd   = uimm (aarch64_get_instr (cpu),  4,  0);
9149   uint64_t val;
9150
9151   val = aarch64_get_reg_u64 (cpu, rm, NO_SP);
9152   val >>= imms;
9153   val |= (aarch64_get_reg_u64 (cpu, rn, NO_SP) << (64 - imms));
9154
9155   aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
9156 }
9157
9158 static void
9159 dexExtractImmediate (sim_cpu *cpu)
9160 {
9161   /* assert instr[28:23] = 100111
9162      instr[31]    = size : 0 ==> 32 bit, 1 ==> 64 bit
9163      instr[30,29] = op21 : 0 ==> EXTR, 1,2,3 ==> UNALLOC
9164      instr[22]    = N : must be 0 for 32 bit, 1 for 64 bit or UNALLOC
9165      instr[21]    = op0 : must be 0 or UNALLOC
9166      instr[20,16] = Rm
9167      instr[15,10] = imms :  0xxxxx for 32 bit, xxxxxx for 64 bit
9168      instr[9,5]   = Rn
9169      instr[4,0]   = Rd  */
9170
9171   /* 32 bit operations must have N = 0 or else we have an UNALLOC.  */
9172   /* 64 bit operations must have N = 1 or else we have an UNALLOC.  */
9173   uint32_t dispatch;
9174   uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
9175   uint32_t N = uimm (aarch64_get_instr (cpu), 22, 22);
9176   /* 32 bit operations must have imms[5] = 0
9177      or else we have an UNALLOC.  */
9178   uint32_t imms = uimm (aarch64_get_instr (cpu), 15, 10);
9179
9180   if (size ^ N)
9181     HALT_UNALLOC;
9182
9183   if (!size && uimm (imms, 5, 5))
9184     HALT_UNALLOC;
9185
9186   /* Switch on combined size and op.  */
9187   dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
9188
9189   if (dispatch == 0)
9190     do_EXTR_32 (cpu);
9191
9192   else if (dispatch == 4)
9193     do_EXTR_64 (cpu);
9194
9195   else if (dispatch == 1)
9196     HALT_NYI;
9197   else
9198     HALT_UNALLOC;
9199 }
9200
9201 static void
9202 dexDPImm (sim_cpu *cpu)
9203 {
9204   /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
9205      assert  group == GROUP_DPIMM_1000 || grpoup == GROUP_DPIMM_1001
9206      bits [25,23] of a DPImm are the secondary dispatch vector.  */
9207   uint32_t group2 = dispatchDPImm (aarch64_get_instr (cpu));
9208
9209   switch (group2)
9210     {
9211     case DPIMM_PCADR_000:
9212     case DPIMM_PCADR_001:
9213       dexPCRelAddressing (cpu);
9214       return;
9215
9216     case DPIMM_ADDSUB_010:
9217     case DPIMM_ADDSUB_011:
9218       dexAddSubtractImmediate (cpu);
9219       return;
9220
9221     case DPIMM_LOG_100:
9222       dexLogicalImmediate (cpu);
9223       return;
9224
9225     case DPIMM_MOV_101:
9226       dexMoveWideImmediate (cpu);
9227       return;
9228
9229     case DPIMM_BITF_110:
9230       dexBitfieldImmediate (cpu);
9231       return;
9232
9233     case DPIMM_EXTR_111:
9234       dexExtractImmediate (cpu);
9235       return;
9236
9237     default:
9238       /* Should never reach here.  */
9239       HALT_NYI;
9240     }
9241 }
9242
9243 static void
9244 dexLoadUnscaledImmediate (sim_cpu *cpu)
9245 {
9246   /* instr[29,24] == 111_00
9247      instr[21] == 0
9248      instr[11,10] == 00
9249      instr[31,30] = size
9250      instr[26] = V
9251      instr[23,22] = opc
9252      instr[20,12] = simm9
9253      instr[9,5] = rn may be SP.  */
9254   /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);  */
9255   uint32_t V = uimm (aarch64_get_instr (cpu), 26, 26);
9256   uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
9257                         | uimm (aarch64_get_instr (cpu), 23, 22));
9258   int32_t imm = simm32 (aarch64_get_instr (cpu), 20, 12);
9259
9260   if (!V)
9261     {
9262       /* GReg operations.  */
9263       switch (dispatch)
9264         {
9265         case 0:  sturb (cpu, imm); return;
9266         case 1:  ldurb32 (cpu, imm); return;
9267         case 2:  ldursb64 (cpu, imm); return;
9268         case 3:  ldursb32 (cpu, imm); return;
9269         case 4:  sturh (cpu, imm); return;
9270         case 5:  ldurh32 (cpu, imm); return;
9271         case 6:  ldursh64 (cpu, imm); return;
9272         case 7:  ldursh32 (cpu, imm); return;
9273         case 8:  stur32 (cpu, imm); return;
9274         case 9:  ldur32 (cpu, imm); return;
9275         case 10: ldursw (cpu, imm); return;
9276         case 12: stur64 (cpu, imm); return;
9277         case 13: ldur64 (cpu, imm); return;
9278
9279         case 14:
9280           /* PRFUM NYI.  */
9281           HALT_NYI;
9282
9283         default:
9284         case 11:
9285         case 15:
9286           HALT_UNALLOC;
9287         }
9288     }
9289
9290   /* FReg operations.  */
9291   switch (dispatch)
9292     {
9293     case 2:  fsturq (cpu, imm); return;
9294     case 3:  fldurq (cpu, imm); return;
9295     case 8:  fsturs (cpu, imm); return;
9296     case 9:  fldurs (cpu, imm); return;
9297     case 12: fsturd (cpu, imm); return;
9298     case 13: fldurd (cpu, imm); return;
9299
9300     case 0: /* STUR 8 bit FP.  */
9301     case 1: /* LDUR 8 bit FP.  */
9302     case 4: /* STUR 16 bit FP.  */
9303     case 5: /* LDUR 8 bit FP.  */
9304       HALT_NYI;
9305
9306     default:
9307     case 6:
9308     case 7:
9309     case 10:
9310     case 11:
9311     case 14:
9312     case 15:
9313       HALT_UNALLOC;
9314     }
9315 }
9316
9317 /*  N.B. A preliminary note regarding all the ldrs<x>32
9318     instructions
9319
9320    The signed value loaded by these instructions is cast to unsigned
9321    before being assigned to aarch64_get_reg_u64 (cpu, N) i.e. to the
9322    64 bit element of the GReg union. this performs a 32 bit sign extension
9323    (as required) but avoids 64 bit sign extension, thus ensuring that the
9324    top half of the register word is zero. this is what the spec demands
9325    when a 32 bit load occurs.  */
9326
9327 /* 32 bit load sign-extended byte scaled unsigned 12 bit.  */
9328 static void
9329 ldrsb32_abs (sim_cpu *cpu, uint32_t offset)
9330 {
9331   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
9332   unsigned int rt = uimm (aarch64_get_instr (cpu), 4, 0);
9333
9334   /* The target register may not be SP but the source may be
9335      there is no scaling required for a byte load.  */
9336   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset;
9337   aarch64_set_reg_u64 (cpu, rt, NO_SP,
9338                        (int64_t) aarch64_get_mem_s8 (cpu, address));
9339 }
9340
9341 /* 32 bit load sign-extended byte scaled or unscaled zero-
9342    or sign-extended 32-bit register offset.  */
9343 static void
9344 ldrsb32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9345 {
9346   unsigned int rm = uimm (aarch64_get_instr (cpu), 20, 16);
9347   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
9348   unsigned int rt = uimm (aarch64_get_instr (cpu), 4, 0);
9349
9350   /* rn may reference SP, rm and rt must reference ZR.  */
9351
9352   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9353   int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9354                                  extension);
9355
9356   /* There is no scaling required for a byte load.  */
9357   aarch64_set_reg_u64
9358     (cpu, rt, NO_SP, (int64_t) aarch64_get_mem_s8 (cpu, address
9359                                                    + displacement));
9360 }
9361
9362 /* 32 bit load sign-extended byte unscaled signed 9 bit with
9363    pre- or post-writeback.  */
9364 static void
9365 ldrsb32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9366 {
9367   uint64_t address;
9368   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
9369   unsigned int rt = uimm (aarch64_get_instr (cpu), 4, 0);
9370
9371   if (rn == rt && wb != NoWriteBack)
9372     HALT_UNALLOC;
9373
9374   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9375
9376   if (wb == Pre)
9377       address += offset;
9378
9379   aarch64_set_reg_u64 (cpu, rt, NO_SP,
9380                        (int64_t) aarch64_get_mem_s8 (cpu, address));
9381
9382   if (wb == Post)
9383     address += offset;
9384
9385   if (wb != NoWriteBack)
9386     aarch64_set_reg_u64 (cpu, rn, NO_SP, address);
9387 }
9388
9389 /* 8 bit store scaled.  */
9390 static void
9391 fstrb_abs (sim_cpu *cpu, uint32_t offset)
9392 {
9393   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9394   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9395
9396   aarch64_set_mem_u8 (cpu,
9397                       aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
9398                       aarch64_get_vec_u8 (cpu, st, 0));
9399 }
9400
9401 /* 8 bit store scaled or unscaled zero- or
9402    sign-extended 8-bit register offset.  */
9403 static void
9404 fstrb_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9405 {
9406   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9407   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9408   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9409
9410   uint64_t  address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9411   int64_t   extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9412                                extension);
9413   uint64_t  displacement = OPT_SCALE (extended, 32, scaling);
9414
9415   aarch64_set_mem_u8
9416     (cpu, address + displacement, aarch64_get_vec_u8 (cpu, st, 0));
9417 }
9418
9419 /* 16 bit store scaled.  */
9420 static void
9421 fstrh_abs (sim_cpu *cpu, uint32_t offset)
9422 {
9423   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9424   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9425
9426   aarch64_set_mem_u16
9427     (cpu,
9428      aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 16),
9429      aarch64_get_vec_u16 (cpu, st, 0));
9430 }
9431
9432 /* 16 bit store scaled or unscaled zero-
9433    or sign-extended 16-bit register offset.  */
9434 static void
9435 fstrh_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9436 {
9437   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9438   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9439   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9440
9441   uint64_t  address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9442   int64_t   extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9443                                extension);
9444   uint64_t  displacement = OPT_SCALE (extended, 32, scaling);
9445
9446   aarch64_set_mem_u16
9447     (cpu, address + displacement, aarch64_get_vec_u16 (cpu, st, 0));
9448 }
9449
9450 /* 32 bit store scaled unsigned 12 bit.  */
9451 static void
9452 fstrs_abs (sim_cpu *cpu, uint32_t offset)
9453 {
9454   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9455   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9456
9457   aarch64_set_mem_float
9458     (cpu,
9459      aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 32),
9460      aarch64_get_FP_float (cpu, st));
9461 }
9462
9463 /* 32 bit store unscaled signed 9 bit with pre- or post-writeback.  */
9464 static void
9465 fstrs_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9466 {
9467   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9468   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9469
9470   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9471
9472   if (wb != Post)
9473     address += offset;
9474
9475   aarch64_set_mem_float (cpu, address, aarch64_get_FP_float (cpu, st));
9476
9477   if (wb == Post)
9478     address += offset;
9479
9480   if (wb != NoWriteBack)
9481     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
9482 }
9483
9484 /* 32 bit store scaled or unscaled zero-
9485    or sign-extended 32-bit register offset.  */
9486 static void
9487 fstrs_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9488 {
9489   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9490   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9491   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9492
9493   uint64_t  address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9494   int64_t   extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9495                                extension);
9496   uint64_t  displacement = OPT_SCALE (extended, 32, scaling);
9497
9498   aarch64_set_mem_float
9499     (cpu, address + displacement, aarch64_get_FP_float (cpu, st));
9500 }
9501
9502 /* 64 bit store scaled unsigned 12 bit.  */
9503 static void
9504 fstrd_abs (sim_cpu *cpu, uint32_t offset)
9505 {
9506   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9507   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9508
9509   aarch64_set_mem_double
9510     (cpu,
9511      aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 64),
9512      aarch64_get_FP_double (cpu, st));
9513 }
9514
9515 /* 64 bit store unscaled signed 9 bit with pre- or post-writeback.  */
9516 static void
9517 fstrd_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9518 {
9519   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9520   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9521
9522   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9523
9524   if (wb != Post)
9525     address += offset;
9526
9527   aarch64_set_mem_double (cpu, address, aarch64_get_FP_double (cpu, st));
9528
9529   if (wb == Post)
9530     address += offset;
9531
9532   if (wb != NoWriteBack)
9533     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
9534 }
9535
9536 /* 64 bit store scaled or unscaled zero-
9537    or sign-extended 32-bit register offset.  */
9538 static void
9539 fstrd_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9540 {
9541   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9542   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9543   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9544
9545   uint64_t  address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9546   int64_t   extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9547                                extension);
9548   uint64_t  displacement = OPT_SCALE (extended, 64, scaling);
9549
9550   aarch64_set_mem_double
9551     (cpu, address + displacement, aarch64_get_FP_double (cpu, st));
9552 }
9553
9554 /* 128 bit store scaled unsigned 12 bit.  */
9555 static void
9556 fstrq_abs (sim_cpu *cpu, uint32_t offset)
9557 {
9558   FRegister a;
9559   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9560   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9561   uint64_t addr;
9562
9563   aarch64_get_FP_long_double (cpu, st, & a);
9564
9565   addr = aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 128);
9566   aarch64_set_mem_long_double (cpu, addr, a);
9567 }
9568
9569 /* 128 bit store unscaled signed 9 bit with pre- or post-writeback.  */
9570 static void
9571 fstrq_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9572 {
9573   FRegister a;
9574   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9575   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9576   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9577
9578   if (wb != Post)
9579     address += offset;
9580
9581   aarch64_get_FP_long_double (cpu, st, & a);
9582   aarch64_set_mem_long_double (cpu, address, a);
9583
9584   if (wb == Post)
9585     address += offset;
9586
9587   if (wb != NoWriteBack)
9588     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
9589 }
9590
9591 /* 128 bit store scaled or unscaled zero-
9592    or sign-extended 32-bit register offset.  */
9593 static void
9594 fstrq_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9595 {
9596   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9597   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9598   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9599
9600   uint64_t  address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9601   int64_t   extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9602                                extension);
9603   uint64_t  displacement = OPT_SCALE (extended, 128, scaling);
9604
9605   FRegister a;
9606
9607   aarch64_get_FP_long_double (cpu, st, & a);
9608   aarch64_set_mem_long_double (cpu, address + displacement, a);
9609 }
9610
9611 static void
9612 dexLoadImmediatePrePost (sim_cpu *cpu)
9613 {
9614   /* instr[29,24] == 111_00
9615      instr[21] == 0
9616      instr[11,10] == 00
9617      instr[31,30] = size
9618      instr[26] = V
9619      instr[23,22] = opc
9620      instr[20,12] = simm9
9621      instr[11] = wb : 0 ==> Post, 1 ==> Pre
9622      instr[9,5] = rn may be SP.  */
9623   /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0); */
9624   uint32_t V = uimm (aarch64_get_instr (cpu), 26, 26);
9625   uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
9626                        | uimm (aarch64_get_instr (cpu), 23, 22));
9627   int32_t imm = simm32 (aarch64_get_instr (cpu), 20, 12);
9628   WriteBack wb = writeback (aarch64_get_instr (cpu), 11);
9629
9630   if (!V)
9631     {
9632       /* GReg operations.  */
9633       switch (dispatch)
9634         {
9635         case 0:  strb_wb (cpu, imm, wb); return;
9636         case 1:  ldrb32_wb (cpu, imm, wb); return;
9637         case 2:  ldrsb_wb (cpu, imm, wb); return;
9638         case 3:  ldrsb32_wb (cpu, imm, wb); return;
9639         case 4:  strh_wb (cpu, imm, wb); return;
9640         case 5:  ldrh32_wb (cpu, imm, wb); return;
9641         case 6:  ldrsh64_wb (cpu, imm, wb); return;
9642         case 7:  ldrsh32_wb (cpu, imm, wb); return;
9643         case 8:  str32_wb (cpu, imm, wb); return;
9644         case 9:  ldr32_wb (cpu, imm, wb); return;
9645         case 10: ldrsw_wb (cpu, imm, wb); return;
9646         case 12: str_wb (cpu, imm, wb); return;
9647         case 13: ldr_wb (cpu, imm, wb); return;
9648
9649         default:
9650         case 11:
9651         case 14:
9652         case 15:
9653           HALT_UNALLOC;
9654         }
9655     }
9656
9657   /* FReg operations.  */
9658   switch (dispatch)
9659     {
9660     case 2:  fstrq_wb (cpu, imm, wb); return;
9661     case 3:  fldrq_wb (cpu, imm, wb); return;
9662     case 8:  fstrs_wb (cpu, imm, wb); return;
9663     case 9:  fldrs_wb (cpu, imm, wb); return;
9664     case 12: fstrd_wb (cpu, imm, wb); return;
9665     case 13: fldrd_wb (cpu, imm, wb); return;
9666
9667     case 0:       /* STUR 8 bit FP.  */
9668     case 1:       /* LDUR 8 bit FP.  */
9669     case 4:       /* STUR 16 bit FP.  */
9670     case 5:       /* LDUR 8 bit FP.  */
9671       HALT_NYI;
9672
9673     default:
9674     case 6:
9675     case 7:
9676     case 10:
9677     case 11:
9678     case 14:
9679     case 15:
9680       HALT_UNALLOC;
9681     }
9682 }
9683
9684 static void
9685 dexLoadRegisterOffset (sim_cpu *cpu)
9686 {
9687   /* instr[31,30] = size
9688      instr[29,27] = 111
9689      instr[26]    = V
9690      instr[25,24] = 00
9691      instr[23,22] = opc
9692      instr[21]    = 1
9693      instr[20,16] = rm
9694      instr[15,13] = option : 010 ==> UXTW, 011 ==> UXTX/LSL,
9695                              110 ==> SXTW, 111 ==> SXTX,
9696                              ow ==> RESERVED
9697      instr[12]    = scaled
9698      instr[11,10] = 10
9699      instr[9,5]   = rn
9700      instr[4,0]   = rt.  */
9701
9702   uint32_t V = uimm (aarch64_get_instr (cpu), 26,26);
9703   uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
9704                        | uimm (aarch64_get_instr (cpu), 23, 22));
9705   Scaling scale = scaling (aarch64_get_instr (cpu), 12);
9706   Extension extensionType = extension (aarch64_get_instr (cpu), 13);
9707
9708   /* Check for illegal extension types.  */
9709   if (uimm (extensionType, 1, 1) == 0)
9710     HALT_UNALLOC;
9711
9712   if (extensionType == UXTX || extensionType == SXTX)
9713     extensionType = NoExtension;
9714
9715   if (!V)
9716     {
9717       /* GReg operations.  */
9718       switch (dispatch)
9719         {
9720         case 0:  strb_scale_ext (cpu, scale, extensionType); return;
9721         case 1:  ldrb32_scale_ext (cpu, scale, extensionType); return;
9722         case 2:  ldrsb_scale_ext (cpu, scale, extensionType); return;
9723         case 3:  ldrsb32_scale_ext (cpu, scale, extensionType); return;
9724         case 4:  strh_scale_ext (cpu, scale, extensionType); return;
9725         case 5:  ldrh32_scale_ext (cpu, scale, extensionType); return;
9726         case 6:  ldrsh_scale_ext (cpu, scale, extensionType); return;
9727         case 7:  ldrsh32_scale_ext (cpu, scale, extensionType); return;
9728         case 8:  str32_scale_ext (cpu, scale, extensionType); return;
9729         case 9:  ldr32_scale_ext (cpu, scale, extensionType); return;
9730         case 10: ldrsw_scale_ext (cpu, scale, extensionType); return;
9731         case 12: str_scale_ext (cpu, scale, extensionType); return;
9732         case 13: ldr_scale_ext (cpu, scale, extensionType); return;
9733         case 14: prfm_scale_ext (cpu, scale, extensionType); return;
9734
9735         default:
9736         case 11:
9737         case 15:
9738           HALT_UNALLOC;
9739         }
9740     }
9741
9742   /* FReg operations.  */
9743   switch (dispatch)
9744     {
9745     case 1: /* LDUR 8 bit FP.  */
9746       HALT_NYI;
9747     case 3:  fldrq_scale_ext (cpu, scale, extensionType); return;
9748     case 5: /* LDUR 8 bit FP.  */
9749       HALT_NYI;
9750     case 9:  fldrs_scale_ext (cpu, scale, extensionType); return;
9751     case 13: fldrd_scale_ext (cpu, scale, extensionType); return;
9752
9753     case 0:  fstrb_scale_ext (cpu, scale, extensionType); return;
9754     case 2:  fstrq_scale_ext (cpu, scale, extensionType); return;
9755     case 4:  fstrh_scale_ext (cpu, scale, extensionType); return;
9756     case 8:  fstrs_scale_ext (cpu, scale, extensionType); return;
9757     case 12: fstrd_scale_ext (cpu, scale, extensionType); return;
9758
9759     default:
9760     case 6:
9761     case 7:
9762     case 10:
9763     case 11:
9764     case 14:
9765     case 15:
9766       HALT_UNALLOC;
9767     }
9768 }
9769
9770 static void
9771 dexLoadUnsignedImmediate (sim_cpu *cpu)
9772 {
9773   /* assert instr[29,24] == 111_01
9774      instr[31,30] = size
9775      instr[26] = V
9776      instr[23,22] = opc
9777      instr[21,10] = uimm12 : unsigned immediate offset
9778      instr[9,5] = rn may be SP.  */
9779   /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0); */
9780   uint32_t V = uimm (aarch64_get_instr (cpu), 26,26);
9781   uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
9782                        | uimm (aarch64_get_instr (cpu), 23, 22));
9783   uint32_t imm = uimm (aarch64_get_instr (cpu), 21, 10);
9784
9785   if (!V)
9786     {
9787       /* GReg operations.  */
9788       switch (dispatch)
9789         {
9790         case 0:  strb_abs (cpu, imm); return;
9791         case 1:  ldrb32_abs (cpu, imm); return;
9792         case 2:  ldrsb_abs (cpu, imm); return;
9793         case 3:  ldrsb32_abs (cpu, imm); return;
9794         case 4:  strh_abs (cpu, imm); return;
9795         case 5:  ldrh32_abs (cpu, imm); return;
9796         case 6:  ldrsh_abs (cpu, imm); return;
9797         case 7:  ldrsh32_abs (cpu, imm); return;
9798         case 8:  str32_abs (cpu, imm); return;
9799         case 9:  ldr32_abs (cpu, imm); return;
9800         case 10: ldrsw_abs (cpu, imm); return;
9801         case 12: str_abs (cpu, imm); return;
9802         case 13: ldr_abs (cpu, imm); return;
9803         case 14: prfm_abs (cpu, imm); return;
9804
9805         default:
9806         case 11:
9807         case 15:
9808           HALT_UNALLOC;
9809         }
9810     }
9811
9812   /* FReg operations.  */
9813   switch (dispatch)
9814     {
9815     case 3:  fldrq_abs (cpu, imm); return;
9816     case 9:  fldrs_abs (cpu, imm); return;
9817     case 13: fldrd_abs (cpu, imm); return;
9818
9819     case 0:  fstrb_abs (cpu, imm); return;
9820     case 2:  fstrq_abs (cpu, imm); return;
9821     case 4:  fstrh_abs (cpu, imm); return;
9822     case 8:  fstrs_abs (cpu, imm); return;
9823     case 12: fstrd_abs (cpu, imm); return;
9824
9825     case 1: /* LDR 8 bit FP.  */
9826     case 5: /* LDR 8 bit FP.  */
9827       HALT_NYI;
9828
9829     default:
9830     case 6:
9831     case 7:
9832     case 10:
9833     case 11:
9834     case 14:
9835     case 15:
9836       HALT_UNALLOC;
9837     }
9838 }
9839
9840 static void
9841 dexLoadExclusive (sim_cpu *cpu)
9842 {
9843   /* assert instr[29:24] = 001000;
9844      instr[31,30] = size
9845      instr[23] = 0 if exclusive
9846      instr[22] = L : 1 if load, 0 if store
9847      instr[21] = 1 if pair
9848      instr[20,16] = Rs
9849      instr[15] = o0 : 1 if ordered
9850      instr[14,10] = Rt2
9851      instr[9,5] = Rn
9852      instr[4.0] = Rt.  */
9853
9854   switch (uimm (aarch64_get_instr (cpu), 22, 21))
9855     {
9856     case 2:   ldxr (cpu); return;
9857     case 0:   stxr (cpu); return;
9858     default:  HALT_NYI;
9859     }
9860 }
9861
9862 static void
9863 dexLoadOther (sim_cpu *cpu)
9864 {
9865   uint32_t dispatch;
9866
9867   /* instr[29,25] = 111_0
9868      instr[24] == 0 ==> dispatch, 1 ==> ldst reg unsigned immediate
9869      instr[21:11,10] is the secondary dispatch.  */
9870   if (uimm (aarch64_get_instr (cpu), 24, 24))
9871     {
9872       dexLoadUnsignedImmediate (cpu);
9873       return;
9874     }
9875
9876   dispatch = ( (uimm (aarch64_get_instr (cpu), 21, 21) << 2)
9877               | uimm (aarch64_get_instr (cpu), 11, 10));
9878   switch (dispatch)
9879     {
9880     case 0: dexLoadUnscaledImmediate (cpu); return;
9881     case 1: dexLoadImmediatePrePost (cpu); return;
9882     case 3: dexLoadImmediatePrePost (cpu); return;
9883     case 6: dexLoadRegisterOffset (cpu); return;
9884
9885     default:
9886     case 2:
9887     case 4:
9888     case 5:
9889     case 7:
9890       HALT_NYI;
9891     }
9892 }
9893
9894 static void
9895 store_pair_u32 (sim_cpu *cpu, int32_t offset, WriteBack wb)
9896 {
9897   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
9898   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
9899   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
9900   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
9901
9902   if ((rn == rd || rm == rd) && wb != NoWriteBack)
9903     HALT_UNALLOC; /* ??? */
9904
9905   offset <<= 2;
9906
9907   if (wb != Post)
9908     address += offset;
9909
9910   aarch64_set_mem_u32 (cpu, address,
9911                        aarch64_get_reg_u32 (cpu, rm, NO_SP));
9912   aarch64_set_mem_u32 (cpu, address + 4,
9913                        aarch64_get_reg_u32 (cpu, rn, NO_SP));
9914
9915   if (wb == Post)
9916     address += offset;
9917
9918   if (wb != NoWriteBack)
9919     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
9920 }
9921
9922 static void
9923 store_pair_u64 (sim_cpu *cpu, int32_t offset, WriteBack wb)
9924 {
9925   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
9926   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
9927   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
9928   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
9929
9930   if ((rn == rd || rm == rd) && wb != NoWriteBack)
9931     HALT_UNALLOC; /* ??? */
9932
9933   offset <<= 3;
9934
9935   if (wb != Post)
9936     address += offset;
9937
9938   aarch64_set_mem_u64 (cpu, address,
9939                        aarch64_get_reg_u64 (cpu, rm, SP_OK));
9940   aarch64_set_mem_u64 (cpu, address + 8,
9941                        aarch64_get_reg_u64 (cpu, rn, SP_OK));
9942
9943   if (wb == Post)
9944     address += offset;
9945
9946   if (wb != NoWriteBack)
9947     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
9948 }
9949
9950 static void
9951 load_pair_u32 (sim_cpu *cpu, int32_t offset, WriteBack wb)
9952 {
9953   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
9954   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
9955   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
9956   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
9957
9958   /* treat this as unalloc to make sure we don't do it.  */
9959   if (rn == rm)
9960     HALT_UNALLOC;
9961
9962   offset <<= 2;
9963
9964   if (wb != Post)
9965     address += offset;
9966
9967   aarch64_set_reg_u64 (cpu, rm, SP_OK, aarch64_get_mem_u32 (cpu, address));
9968   aarch64_set_reg_u64 (cpu, rn, SP_OK, aarch64_get_mem_u32 (cpu, address + 4));
9969
9970   if (wb == Post)
9971     address += offset;
9972
9973   if (wb != NoWriteBack)
9974     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
9975 }
9976
9977 static void
9978 load_pair_s32 (sim_cpu *cpu, int32_t offset, WriteBack wb)
9979 {
9980   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
9981   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
9982   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
9983   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
9984
9985   /* Treat this as unalloc to make sure we don't do it.  */
9986   if (rn == rm)
9987     HALT_UNALLOC;
9988
9989   offset <<= 2;
9990
9991   if (wb != Post)
9992     address += offset;
9993
9994   aarch64_set_reg_s64 (cpu, rm, SP_OK, aarch64_get_mem_s32 (cpu, address));
9995   aarch64_set_reg_s64 (cpu, rn, SP_OK, aarch64_get_mem_s32 (cpu, address + 4));
9996
9997   if (wb == Post)
9998     address += offset;
9999
10000   if (wb != NoWriteBack)
10001     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10002 }
10003
10004 static void
10005 load_pair_u64 (sim_cpu *cpu, int32_t offset, WriteBack wb)
10006 {
10007   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10008   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10009   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10010   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10011
10012   /* Treat this as unalloc to make sure we don't do it.  */
10013   if (rn == rm)
10014     HALT_UNALLOC;
10015
10016   offset <<= 3;
10017
10018   if (wb != Post)
10019     address += offset;
10020
10021   aarch64_set_reg_u64 (cpu, rm, SP_OK, aarch64_get_mem_u64 (cpu, address));
10022   aarch64_set_reg_u64 (cpu, rn, SP_OK, aarch64_get_mem_u64 (cpu, address + 8));
10023
10024   if (wb == Post)
10025     address += offset;
10026
10027   if (wb != NoWriteBack)
10028     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10029 }
10030
10031 static void
10032 dex_load_store_pair_gr (sim_cpu *cpu)
10033 {
10034   /* instr[31,30] = size (10=> 64-bit, 01=> signed 32-bit, 00=> 32-bit)
10035      instr[29,25] = instruction encoding: 101_0
10036      instr[26]    = V : 1 if fp 0 if gp
10037      instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
10038      instr[22]    = load/store (1=> load)
10039      instr[21,15] = signed, scaled, offset
10040      instr[14,10] = Rn
10041      instr[ 9, 5] = Rd
10042      instr[ 4, 0] = Rm.  */
10043
10044   uint32_t dispatch = ((uimm (aarch64_get_instr (cpu), 31, 30) << 3)
10045                         | uimm (aarch64_get_instr (cpu), 24, 22));
10046   int32_t offset = simm32 (aarch64_get_instr (cpu), 21, 15);
10047
10048   switch (dispatch)
10049     {
10050     case 2: store_pair_u32 (cpu, offset, Post); return;
10051     case 3: load_pair_u32  (cpu, offset, Post); return;
10052     case 4: store_pair_u32 (cpu, offset, NoWriteBack); return;
10053     case 5: load_pair_u32  (cpu, offset, NoWriteBack); return;
10054     case 6: store_pair_u32 (cpu, offset, Pre); return;
10055     case 7: load_pair_u32  (cpu, offset, Pre); return;
10056
10057     case 11: load_pair_s32  (cpu, offset, Post); return;
10058     case 13: load_pair_s32  (cpu, offset, NoWriteBack); return;
10059     case 15: load_pair_s32  (cpu, offset, Pre); return;
10060
10061     case 18: store_pair_u64 (cpu, offset, Post); return;
10062     case 19: load_pair_u64  (cpu, offset, Post); return;
10063     case 20: store_pair_u64 (cpu, offset, NoWriteBack); return;
10064     case 21: load_pair_u64  (cpu, offset, NoWriteBack); return;
10065     case 22: store_pair_u64 (cpu, offset, Pre); return;
10066     case 23: load_pair_u64  (cpu, offset, Pre); return;
10067
10068     default:
10069       HALT_UNALLOC;
10070     }
10071 }
10072
10073 static void
10074 store_pair_float (sim_cpu *cpu, int32_t offset, WriteBack wb)
10075 {
10076   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10077   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10078   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10079   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10080
10081   offset <<= 2;
10082
10083   if (wb != Post)
10084     address += offset;
10085
10086   aarch64_set_mem_float (cpu, address,     aarch64_get_FP_float (cpu, rm));
10087   aarch64_set_mem_float (cpu, address + 4, aarch64_get_FP_float (cpu, rn));
10088
10089   if (wb == Post)
10090     address += offset;
10091
10092   if (wb != NoWriteBack)
10093     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10094 }
10095
10096 static void
10097 store_pair_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10098 {
10099   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10100   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10101   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10102   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10103
10104   offset <<= 3;
10105
10106   if (wb != Post)
10107     address += offset;
10108
10109   aarch64_set_mem_double (cpu, address,     aarch64_get_FP_double (cpu, rm));
10110   aarch64_set_mem_double (cpu, address + 8, aarch64_get_FP_double (cpu, rn));
10111
10112   if (wb == Post)
10113     address += offset;
10114
10115   if (wb != NoWriteBack)
10116     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10117 }
10118
10119 static void
10120 store_pair_long_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10121 {
10122   FRegister a;
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   offset <<= 4;
10129
10130   if (wb != Post)
10131     address += offset;
10132
10133   aarch64_get_FP_long_double (cpu, rm, & a);
10134   aarch64_set_mem_long_double (cpu, address, a);
10135   aarch64_get_FP_long_double (cpu, rn, & a);
10136   aarch64_set_mem_long_double (cpu, address + 16, a);
10137
10138   if (wb == Post)
10139     address += offset;
10140
10141   if (wb != NoWriteBack)
10142     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10143 }
10144
10145 static void
10146 load_pair_float (sim_cpu *cpu, int32_t offset, WriteBack wb)
10147 {
10148   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10149   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10150   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10151   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10152
10153   if (rm == rn)
10154     HALT_UNALLOC;
10155
10156   offset <<= 2;
10157
10158   if (wb != Post)
10159     address += offset;
10160
10161   aarch64_set_FP_float (cpu, rm, aarch64_get_mem_float (cpu, address));
10162   aarch64_set_FP_float (cpu, rn, aarch64_get_mem_float (cpu, address + 4));
10163
10164   if (wb == Post)
10165     address += offset;
10166
10167   if (wb != NoWriteBack)
10168     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10169 }
10170
10171 static void
10172 load_pair_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10173 {
10174   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10175   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10176   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10177   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10178
10179   if (rm == rn)
10180     HALT_UNALLOC;
10181
10182   offset <<= 3;
10183
10184   if (wb != Post)
10185     address += offset;
10186
10187   aarch64_set_FP_double (cpu, rm, aarch64_get_mem_double (cpu, address));
10188   aarch64_set_FP_double (cpu, rn, aarch64_get_mem_double (cpu, address + 8));
10189
10190   if (wb == Post)
10191     address += offset;
10192
10193   if (wb != NoWriteBack)
10194     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10195 }
10196
10197 static void
10198 load_pair_long_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10199 {
10200   FRegister a;
10201   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10202   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10203   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10204   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10205
10206   if (rm == rn)
10207     HALT_UNALLOC;
10208
10209   offset <<= 4;
10210
10211   if (wb != Post)
10212     address += offset;
10213
10214   aarch64_get_mem_long_double (cpu, address, & a);
10215   aarch64_set_FP_long_double (cpu, rm, a);
10216   aarch64_get_mem_long_double (cpu, address + 16, & a);
10217   aarch64_set_FP_long_double (cpu, rn, a);
10218
10219   if (wb == Post)
10220     address += offset;
10221
10222   if (wb != NoWriteBack)
10223     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10224 }
10225
10226 static void
10227 dex_load_store_pair_fp (sim_cpu *cpu)
10228 {
10229   /* instr[31,30] = size (10=> 128-bit, 01=> 64-bit, 00=> 32-bit)
10230      instr[29,25] = instruction encoding
10231      instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
10232      instr[22]    = load/store (1=> load)
10233      instr[21,15] = signed, scaled, offset
10234      instr[14,10] = Rn
10235      instr[ 9, 5] = Rd
10236      instr[ 4, 0] = Rm  */
10237
10238   uint32_t dispatch = ((uimm (aarch64_get_instr (cpu), 31, 30) << 3)
10239                         | uimm (aarch64_get_instr (cpu), 24, 22));
10240   int32_t offset = simm32 (aarch64_get_instr (cpu), 21, 15);
10241
10242   switch (dispatch)
10243     {
10244     case 2: store_pair_float (cpu, offset, Post); return;
10245     case 3: load_pair_float  (cpu, offset, Post); return;
10246     case 4: store_pair_float (cpu, offset, NoWriteBack); return;
10247     case 5: load_pair_float  (cpu, offset, NoWriteBack); return;
10248     case 6: store_pair_float (cpu, offset, Pre); return;
10249     case 7: load_pair_float  (cpu, offset, Pre); return;
10250
10251     case 10: store_pair_double (cpu, offset, Post); return;
10252     case 11: load_pair_double  (cpu, offset, Post); return;
10253     case 12: store_pair_double (cpu, offset, NoWriteBack); return;
10254     case 13: load_pair_double  (cpu, offset, NoWriteBack); return;
10255     case 14: store_pair_double (cpu, offset, Pre); return;
10256     case 15: load_pair_double  (cpu, offset, Pre); return;
10257
10258     case 18: store_pair_long_double (cpu, offset, Post); return;
10259     case 19: load_pair_long_double  (cpu, offset, Post); return;
10260     case 20: store_pair_long_double (cpu, offset, NoWriteBack); return;
10261     case 21: load_pair_long_double  (cpu, offset, NoWriteBack); return;
10262     case 22: store_pair_long_double (cpu, offset, Pre); return;
10263     case 23: load_pair_long_double  (cpu, offset, Pre); return;
10264
10265     default:
10266       HALT_UNALLOC;
10267     }
10268 }
10269
10270 static inline unsigned
10271 vec_reg (unsigned v, unsigned o)
10272 {
10273   return (v + o) & 0x3F;
10274 }
10275
10276 /* Load multiple N-element structures to N consecutive registers.  */
10277 static void
10278 vec_load (sim_cpu *cpu, uint64_t address, unsigned N)
10279 {
10280   int      all  = uimm (aarch64_get_instr (cpu), 30, 30);
10281   unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10282   unsigned vd   = uimm (aarch64_get_instr (cpu), 4, 0);
10283   unsigned i;
10284
10285   switch (size)
10286     {
10287     case 0: /* 8-bit operations.  */
10288       if (all)
10289         for (i = 0; i < (16 * N); i++)
10290           aarch64_set_vec_u8 (cpu, vec_reg (vd, i >> 4), i & 15,
10291                               aarch64_get_mem_u8 (cpu, address + i));
10292       else
10293         for (i = 0; i < (8 * N); i++)
10294           aarch64_set_vec_u8 (cpu, vec_reg (vd, i >> 3), i & 7,
10295                               aarch64_get_mem_u8 (cpu, address + i));
10296       return;
10297
10298     case 1: /* 16-bit operations.  */
10299       if (all)
10300         for (i = 0; i < (8 * N); i++)
10301           aarch64_set_vec_u16 (cpu, vec_reg (vd, i >> 3), i & 7,
10302                                aarch64_get_mem_u16 (cpu, address + i * 2));
10303       else
10304         for (i = 0; i < (4 * N); i++)
10305           aarch64_set_vec_u16 (cpu, vec_reg (vd, i >> 2), i & 3,
10306                                aarch64_get_mem_u16 (cpu, address + i * 2));
10307       return;
10308
10309     case 2: /* 32-bit operations.  */
10310       if (all)
10311         for (i = 0; i < (4 * N); i++)
10312           aarch64_set_vec_u32 (cpu, vec_reg (vd, i >> 2), i & 3,
10313                                aarch64_get_mem_u32 (cpu, address + i * 4));
10314       else
10315         for (i = 0; i < (2 * N); i++)
10316           aarch64_set_vec_u32 (cpu, vec_reg (vd, i >> 1), i & 1,
10317                                aarch64_get_mem_u32 (cpu, address + i * 4));
10318       return;
10319
10320     case 3: /* 64-bit operations.  */
10321       if (all)
10322         for (i = 0; i < (2 * N); i++)
10323           aarch64_set_vec_u64 (cpu, vec_reg (vd, i >> 1), i & 1,
10324                                aarch64_get_mem_u64 (cpu, address + i * 8));
10325       else
10326         for (i = 0; i < N; i++)
10327           aarch64_set_vec_u64 (cpu, vec_reg (vd, i), 0,
10328                                aarch64_get_mem_u64 (cpu, address + i * 8));
10329       return;
10330
10331     default:
10332       HALT_UNREACHABLE;
10333     }
10334 }
10335
10336 /* LD4: load multiple 4-element to four consecutive registers.  */
10337 static void
10338 LD4 (sim_cpu *cpu, uint64_t address)
10339 {
10340   vec_load (cpu, address, 4);
10341 }
10342
10343 /* LD3: load multiple 3-element structures to three consecutive registers.  */
10344 static void
10345 LD3 (sim_cpu *cpu, uint64_t address)
10346 {
10347   vec_load (cpu, address, 3);
10348 }
10349
10350 /* LD2: load multiple 2-element structures to two consecutive registers.  */
10351 static void
10352 LD2 (sim_cpu *cpu, uint64_t address)
10353 {
10354   vec_load (cpu, address, 2);
10355 }
10356
10357 /* Load multiple 1-element structures into one register.  */
10358 static void
10359 LD1_1 (sim_cpu *cpu, uint64_t address)
10360 {
10361   int      all  = uimm (aarch64_get_instr (cpu), 30, 30);
10362   unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10363   unsigned vd   = uimm (aarch64_get_instr (cpu), 4, 0);
10364   unsigned i;
10365
10366   switch (size)
10367     {
10368     case 0:
10369       /* LD1 {Vd.16b}, addr, #16 */
10370       /* LD1 {Vd.8b}, addr, #8 */
10371       for (i = 0; i < (all ? 16 : 8); i++)
10372         aarch64_set_vec_u8 (cpu, vd, i,
10373                             aarch64_get_mem_u8 (cpu, address + i));
10374       return;
10375
10376     case 1:
10377       /* LD1 {Vd.8h}, addr, #16 */
10378       /* LD1 {Vd.4h}, addr, #8 */
10379       for (i = 0; i < (all ? 8 : 4); i++)
10380         aarch64_set_vec_u16 (cpu, vd, i,
10381                              aarch64_get_mem_u16 (cpu, address + i * 2));
10382       return;
10383
10384     case 2:
10385       /* LD1 {Vd.4s}, addr, #16 */
10386       /* LD1 {Vd.2s}, addr, #8 */
10387       for (i = 0; i < (all ? 4 : 2); i++)
10388         aarch64_set_vec_u32 (cpu, vd, i,
10389                              aarch64_get_mem_u32 (cpu, address + i * 4));
10390       return;
10391
10392     case 3:
10393       /* LD1 {Vd.2d}, addr, #16 */
10394       /* LD1 {Vd.1d}, addr, #8 */
10395       for (i = 0; i < (all ? 2 : 1); i++)
10396         aarch64_set_vec_u64 (cpu, vd, i,
10397                              aarch64_get_mem_u64 (cpu, address + i * 8));
10398       return;
10399
10400     default:
10401       HALT_UNREACHABLE;
10402     }
10403 }
10404
10405 /* Load multiple 1-element structures into two registers.  */
10406 static void
10407 LD1_2 (sim_cpu *cpu, uint64_t address)
10408 {
10409   /* FIXME: This algorithm is *exactly* the same as the LD2 version.
10410      So why have two different instructions ?  There must be something
10411      wrong somewhere.  */
10412   vec_load (cpu, address, 2);
10413 }
10414
10415 /* Load multiple 1-element structures into three registers.  */
10416 static void
10417 LD1_3 (sim_cpu *cpu, uint64_t address)
10418 {
10419   /* FIXME: This algorithm is *exactly* the same as the LD3 version.
10420      So why have two different instructions ?  There must be something
10421      wrong somewhere.  */
10422   vec_load (cpu, address, 3);
10423 }
10424
10425 /* Load multiple 1-element structures into four registers.  */
10426 static void
10427 LD1_4 (sim_cpu *cpu, uint64_t address)
10428 {
10429   /* FIXME: This algorithm is *exactly* the same as the LD4 version.
10430      So why have two different instructions ?  There must be something
10431      wrong somewhere.  */
10432   vec_load (cpu, address, 4);
10433 }
10434
10435 /* Store multiple N-element structures to N consecutive registers.  */
10436 static void
10437 vec_store (sim_cpu *cpu, uint64_t address, unsigned N)
10438 {
10439   int      all  = uimm (aarch64_get_instr (cpu), 30, 30);
10440   unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10441   unsigned vd   = uimm (aarch64_get_instr (cpu), 4, 0);
10442   unsigned i;
10443
10444   switch (size)
10445     {
10446     case 0: /* 8-bit operations.  */
10447       if (all)
10448         for (i = 0; i < (16 * N); i++)
10449           aarch64_set_mem_u8
10450             (cpu, address + i,
10451              aarch64_get_vec_u8 (cpu, vec_reg (vd, i >> 4), i & 15));
10452       else
10453         for (i = 0; i < (8 * N); i++)
10454           aarch64_set_mem_u8
10455             (cpu, address + i,
10456              aarch64_get_vec_u8 (cpu, vec_reg (vd, i >> 3), i & 7));
10457       return;
10458
10459     case 1: /* 16-bit operations.  */
10460       if (all)
10461         for (i = 0; i < (8 * N); i++)
10462           aarch64_set_mem_u16
10463             (cpu, address + i * 2,
10464              aarch64_get_vec_u16 (cpu, vec_reg (vd, i >> 3), i & 7));
10465       else
10466         for (i = 0; i < (4 * N); i++)
10467           aarch64_set_mem_u16
10468             (cpu, address + i * 2,
10469              aarch64_get_vec_u16 (cpu, vec_reg (vd, i >> 2), i & 3));
10470       return;
10471
10472     case 2: /* 32-bit operations.  */
10473       if (all)
10474         for (i = 0; i < (4 * N); i++)
10475           aarch64_set_mem_u32
10476             (cpu, address + i * 4,
10477              aarch64_get_vec_u32 (cpu, vec_reg (vd, i >> 2), i & 3));
10478       else
10479         for (i = 0; i < (2 * N); i++)
10480           aarch64_set_mem_u32
10481             (cpu, address + i * 4,
10482              aarch64_get_vec_u32 (cpu, vec_reg (vd, i >> 1), i & 1));
10483       return;
10484
10485     case 3: /* 64-bit operations.  */
10486       if (all)
10487         for (i = 0; i < (2 * N); i++)
10488           aarch64_set_mem_u64
10489             (cpu, address + i * 8,
10490              aarch64_get_vec_u64 (cpu, vec_reg (vd, i >> 1), i & 1));
10491       else
10492         for (i = 0; i < N; i++)
10493           aarch64_set_mem_u64
10494             (cpu, address + i * 8,
10495              aarch64_get_vec_u64 (cpu, vec_reg (vd, i), 0));
10496       return;
10497
10498     default:
10499       HALT_UNREACHABLE;
10500     }
10501 }
10502
10503 /* Store multiple 4-element structure to four consecutive registers.  */
10504 static void
10505 ST4 (sim_cpu *cpu, uint64_t address)
10506 {
10507   vec_store (cpu, address, 4);
10508 }
10509
10510 /* Store multiple 3-element structures to three consecutive registers.  */
10511 static void
10512 ST3 (sim_cpu *cpu, uint64_t address)
10513 {
10514   vec_store (cpu, address, 3);
10515 }
10516
10517 /* Store multiple 2-element structures to two consecutive registers.  */
10518 static void
10519 ST2 (sim_cpu *cpu, uint64_t address)
10520 {
10521   vec_store (cpu, address, 2);
10522 }
10523
10524 /* Store multiple 1-element structures into one register.  */
10525 static void
10526 ST1_1 (sim_cpu *cpu, uint64_t address)
10527 {
10528   int      all  = uimm (aarch64_get_instr (cpu), 30, 30);
10529   unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10530   unsigned vd   = uimm (aarch64_get_instr (cpu), 4, 0);
10531   unsigned i;
10532
10533   switch (size)
10534     {
10535     case 0:
10536       for (i = 0; i < (all ? 16 : 8); i++)
10537         aarch64_set_mem_u8 (cpu, address + i,
10538                             aarch64_get_vec_u8 (cpu, vd, i));
10539       return;
10540
10541     case 1:
10542       for (i = 0; i < (all ? 8 : 4); i++)
10543         aarch64_set_mem_u16 (cpu, address + i * 2,
10544                              aarch64_get_vec_u16 (cpu, vd, i));
10545       return;
10546
10547     case 2:
10548       for (i = 0; i < (all ? 4 : 2); i++)
10549         aarch64_set_mem_u32 (cpu, address + i * 4,
10550                              aarch64_get_vec_u32 (cpu, vd, i));
10551       return;
10552
10553     case 3:
10554       for (i = 0; i < (all ? 2 : 1); i++)
10555         aarch64_set_mem_u64 (cpu, address + i * 8,
10556                              aarch64_get_vec_u64 (cpu, vd, i));
10557       return;
10558
10559     default:
10560       HALT_UNREACHABLE;
10561     }
10562 }
10563
10564 /* Store multiple 1-element structures into two registers.  */
10565 static void
10566 ST1_2 (sim_cpu *cpu, uint64_t address)
10567 {
10568   /* FIXME: This algorithm is *exactly* the same as the ST2 version.
10569      So why have two different instructions ?  There must be
10570      something wrong somewhere.  */
10571   vec_store (cpu, address, 2);
10572 }
10573
10574 /* Store multiple 1-element structures into three registers.  */
10575 static void
10576 ST1_3 (sim_cpu *cpu, uint64_t address)
10577 {
10578   /* FIXME: This algorithm is *exactly* the same as the ST3 version.
10579      So why have two different instructions ?  There must be
10580      something wrong somewhere.  */
10581   vec_store (cpu, address, 3);
10582 }
10583
10584 /* Store multiple 1-element structures into four registers.  */
10585 static void
10586 ST1_4 (sim_cpu *cpu, uint64_t address)
10587 {
10588   /* FIXME: This algorithm is *exactly* the same as the ST4 version.
10589      So why have two different instructions ?  There must be
10590      something wrong somewhere.  */
10591   vec_store (cpu, address, 4);
10592 }
10593
10594 static void
10595 do_vec_LDnR (sim_cpu *cpu, uint64_t address)
10596 {
10597   /* instr[31]    = 0
10598      instr[30]    = element selector 0=>half, 1=>all elements
10599      instr[29,24] = 00 1101
10600      instr[23]    = 0=>simple, 1=>post
10601      instr[22]    = 1
10602      instr[21]    = width: LD1R-or-LD3R (0) / LD2R-or-LD4R (1)
10603      instr[20,16] = 0 0000 (simple), Vinc (reg-post-inc, no SP),
10604                       11111 (immediate post inc)
10605      instr[15,14] = 11
10606      instr[13]    = width: LD1R-or-LD2R (0) / LD3R-or-LD4R (1)
10607      instr[12]    = 0
10608      instr[11,10] = element size 00=> byte(b), 01=> half(h),
10609                                  10=> word(s), 11=> double(d)
10610      instr[9,5]   = address
10611      instr[4,0]   = Vd  */
10612
10613   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
10614   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
10615   unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10616   int i;
10617
10618   NYI_assert (29, 24, 0x0D);
10619   NYI_assert (22, 22, 1);
10620   NYI_assert (15, 14, 3);
10621   NYI_assert (12, 12, 0);
10622
10623   switch ((uimm (aarch64_get_instr (cpu), 13, 13) << 1)
10624           | uimm (aarch64_get_instr (cpu), 21, 21))
10625     {
10626     case 0: /* LD1R.  */
10627       switch (size)
10628         {
10629         case 0:
10630           {
10631             uint8_t val = aarch64_get_mem_u8 (cpu, address);
10632             for (i = 0; i < (full ? 16 : 8); i++)
10633               aarch64_set_vec_u8 (cpu, vd, i, val);
10634             break;
10635           }
10636
10637         case 1:
10638           {
10639             uint16_t val = aarch64_get_mem_u16 (cpu, address);
10640             for (i = 0; i < (full ? 8 : 4); i++)
10641               aarch64_set_vec_u16 (cpu, vd, i, val);
10642             break;
10643           }
10644
10645         case 2:
10646           {
10647             uint32_t val = aarch64_get_mem_u32 (cpu, address);
10648             for (i = 0; i < (full ? 4 : 2); i++)
10649               aarch64_set_vec_u32 (cpu, vd, i, val);
10650             break;
10651           }
10652
10653         case 3:
10654           {
10655             uint64_t val = aarch64_get_mem_u64 (cpu, address);
10656             for (i = 0; i < (full ? 2 : 1); i++)
10657               aarch64_set_vec_u64 (cpu, vd, i, val);
10658             break;
10659           }
10660
10661         default:
10662           HALT_UNALLOC;
10663         }
10664       break;
10665
10666     case 1: /* LD2R.  */
10667       switch (size)
10668         {
10669         case 0:
10670           {
10671             uint8_t val1 = aarch64_get_mem_u8 (cpu, address);
10672             uint8_t val2 = aarch64_get_mem_u8 (cpu, address + 1);
10673
10674             for (i = 0; i < (full ? 16 : 8); i++)
10675               {
10676                 aarch64_set_vec_u8 (cpu, vd, 0, val1);
10677                 aarch64_set_vec_u8 (cpu, vd + 1, 0, val2);
10678               }
10679             break;
10680           }
10681
10682         case 1:
10683           {
10684             uint16_t val1 = aarch64_get_mem_u16 (cpu, address);
10685             uint16_t val2 = aarch64_get_mem_u16 (cpu, address + 2);
10686
10687             for (i = 0; i < (full ? 8 : 4); i++)
10688               {
10689                 aarch64_set_vec_u16 (cpu, vd, 0, val1);
10690                 aarch64_set_vec_u16 (cpu, vd + 1, 0, val2);
10691               }
10692             break;
10693           }
10694
10695         case 2:
10696           {
10697             uint32_t val1 = aarch64_get_mem_u32 (cpu, address);
10698             uint32_t val2 = aarch64_get_mem_u32 (cpu, address + 4);
10699
10700             for (i = 0; i < (full ? 4 : 2); i++)
10701               {
10702                 aarch64_set_vec_u32 (cpu, vd, 0, val1);
10703                 aarch64_set_vec_u32 (cpu, vd + 1, 0, val2);
10704               }
10705             break;
10706           }
10707
10708         case 3:
10709           {
10710             uint64_t val1 = aarch64_get_mem_u64 (cpu, address);
10711             uint64_t val2 = aarch64_get_mem_u64 (cpu, address + 8);
10712
10713             for (i = 0; i < (full ? 2 : 1); i++)
10714               {
10715                 aarch64_set_vec_u64 (cpu, vd, 0, val1);
10716                 aarch64_set_vec_u64 (cpu, vd + 1, 0, val2);
10717               }
10718             break;
10719           }
10720
10721         default:
10722           HALT_UNALLOC;
10723         }
10724       break;
10725
10726     case 2: /* LD3R.  */
10727       switch (size)
10728         {
10729         case 0:
10730           {
10731             uint8_t val1 = aarch64_get_mem_u8 (cpu, address);
10732             uint8_t val2 = aarch64_get_mem_u8 (cpu, address + 1);
10733             uint8_t val3 = aarch64_get_mem_u8 (cpu, address + 2);
10734
10735             for (i = 0; i < (full ? 16 : 8); i++)
10736               {
10737                 aarch64_set_vec_u8 (cpu, vd, 0, val1);
10738                 aarch64_set_vec_u8 (cpu, vd + 1, 0, val2);
10739                 aarch64_set_vec_u8 (cpu, vd + 2, 0, val3);
10740               }
10741           }
10742           break;
10743
10744         case 1:
10745           {
10746             uint32_t val1 = aarch64_get_mem_u16 (cpu, address);
10747             uint32_t val2 = aarch64_get_mem_u16 (cpu, address + 2);
10748             uint32_t val3 = aarch64_get_mem_u16 (cpu, address + 4);
10749
10750             for (i = 0; i < (full ? 8 : 4); i++)
10751               {
10752                 aarch64_set_vec_u16 (cpu, vd, 0, val1);
10753                 aarch64_set_vec_u16 (cpu, vd + 1, 0, val2);
10754                 aarch64_set_vec_u16 (cpu, vd + 2, 0, val3);
10755               }
10756           }
10757           break;
10758
10759         case 2:
10760           {
10761             uint32_t val1 = aarch64_get_mem_u32 (cpu, address);
10762             uint32_t val2 = aarch64_get_mem_u32 (cpu, address + 4);
10763             uint32_t val3 = aarch64_get_mem_u32 (cpu, address + 8);
10764
10765             for (i = 0; i < (full ? 4 : 2); i++)
10766               {
10767                 aarch64_set_vec_u32 (cpu, vd, 0, val1);
10768                 aarch64_set_vec_u32 (cpu, vd + 1, 0, val2);
10769                 aarch64_set_vec_u32 (cpu, vd + 2, 0, val3);
10770               }
10771           }
10772           break;
10773
10774         case 3:
10775           {
10776             uint64_t val1 = aarch64_get_mem_u64 (cpu, address);
10777             uint64_t val2 = aarch64_get_mem_u64 (cpu, address + 8);
10778             uint64_t val3 = aarch64_get_mem_u64 (cpu, address + 16);
10779
10780             for (i = 0; i < (full ? 2 : 1); i++)
10781               {
10782                 aarch64_set_vec_u64 (cpu, vd, 0, val1);
10783                 aarch64_set_vec_u64 (cpu, vd + 1, 0, val2);
10784                 aarch64_set_vec_u64 (cpu, vd + 2, 0, val3);
10785               }
10786           }
10787           break;
10788
10789         default:
10790           HALT_UNALLOC;
10791         }
10792       break;
10793
10794     case 3: /* LD4R.  */
10795       switch (size)
10796         {
10797         case 0:
10798           {
10799             uint8_t val1 = aarch64_get_mem_u8 (cpu, address);
10800             uint8_t val2 = aarch64_get_mem_u8 (cpu, address + 1);
10801             uint8_t val3 = aarch64_get_mem_u8 (cpu, address + 2);
10802             uint8_t val4 = aarch64_get_mem_u8 (cpu, address + 3);
10803
10804             for (i = 0; i < (full ? 16 : 8); i++)
10805               {
10806                 aarch64_set_vec_u8 (cpu, vd, 0, val1);
10807                 aarch64_set_vec_u8 (cpu, vd + 1, 0, val2);
10808                 aarch64_set_vec_u8 (cpu, vd + 2, 0, val3);
10809                 aarch64_set_vec_u8 (cpu, vd + 3, 0, val4);
10810               }
10811           }
10812           break;
10813
10814         case 1:
10815           {
10816             uint32_t val1 = aarch64_get_mem_u16 (cpu, address);
10817             uint32_t val2 = aarch64_get_mem_u16 (cpu, address + 2);
10818             uint32_t val3 = aarch64_get_mem_u16 (cpu, address + 4);
10819             uint32_t val4 = aarch64_get_mem_u16 (cpu, address + 6);
10820
10821             for (i = 0; i < (full ? 8 : 4); i++)
10822               {
10823                 aarch64_set_vec_u16 (cpu, vd, 0, val1);
10824                 aarch64_set_vec_u16 (cpu, vd + 1, 0, val2);
10825                 aarch64_set_vec_u16 (cpu, vd + 2, 0, val3);
10826                 aarch64_set_vec_u16 (cpu, vd + 3, 0, val4);
10827               }
10828           }
10829           break;
10830
10831         case 2:
10832           {
10833             uint32_t val1 = aarch64_get_mem_u32 (cpu, address);
10834             uint32_t val2 = aarch64_get_mem_u32 (cpu, address + 4);
10835             uint32_t val3 = aarch64_get_mem_u32 (cpu, address + 8);
10836             uint32_t val4 = aarch64_get_mem_u32 (cpu, address + 12);
10837
10838             for (i = 0; i < (full ? 4 : 2); i++)
10839               {
10840                 aarch64_set_vec_u32 (cpu, vd, 0, val1);
10841                 aarch64_set_vec_u32 (cpu, vd + 1, 0, val2);
10842                 aarch64_set_vec_u32 (cpu, vd + 2, 0, val3);
10843                 aarch64_set_vec_u32 (cpu, vd + 3, 0, val4);
10844               }
10845           }
10846           break;
10847
10848         case 3:
10849           {
10850             uint64_t val1 = aarch64_get_mem_u64 (cpu, address);
10851             uint64_t val2 = aarch64_get_mem_u64 (cpu, address + 8);
10852             uint64_t val3 = aarch64_get_mem_u64 (cpu, address + 16);
10853             uint64_t val4 = aarch64_get_mem_u64 (cpu, address + 24);
10854
10855             for (i = 0; i < (full ? 2 : 1); i++)
10856               {
10857                 aarch64_set_vec_u64 (cpu, vd, 0, val1);
10858                 aarch64_set_vec_u64 (cpu, vd + 1, 0, val2);
10859                 aarch64_set_vec_u64 (cpu, vd + 2, 0, val3);
10860                 aarch64_set_vec_u64 (cpu, vd + 3, 0, val4);
10861               }
10862           }
10863           break;
10864
10865         default:
10866           HALT_UNALLOC;
10867         }
10868       break;
10869
10870     default:
10871       HALT_UNALLOC;
10872     }
10873 }
10874
10875 static void
10876 do_vec_load_store (sim_cpu *cpu)
10877 {
10878   /* {LD|ST}<N>   {Vd..Vd+N}, vaddr
10879
10880      instr[31]    = 0
10881      instr[30]    = element selector 0=>half, 1=>all elements
10882      instr[29,25] = 00110
10883      instr[24]    = ?
10884      instr[23]    = 0=>simple, 1=>post
10885      instr[22]    = 0=>store, 1=>load
10886      instr[21]    = 0 (LDn) / small(0)-large(1) selector (LDnR)
10887      instr[20,16] = 00000 (simple), Vinc (reg-post-inc, no SP),
10888                     11111 (immediate post inc)
10889      instr[15,12] = elements and destinations.  eg for load:
10890                      0000=>LD4 => load multiple 4-element to
10891                      four consecutive registers
10892                      0100=>LD3 => load multiple 3-element to
10893                      three consecutive registers
10894                      1000=>LD2 => load multiple 2-element to
10895                      two consecutive registers
10896                      0010=>LD1 => load multiple 1-element to
10897                      four consecutive registers
10898                      0110=>LD1 => load multiple 1-element to
10899                      three consecutive registers
10900                      1010=>LD1 => load multiple 1-element to
10901                      two consecutive registers
10902                      0111=>LD1 => load multiple 1-element to
10903                      one register
10904                      1100=>LDR1,LDR2
10905                      1110=>LDR3,LDR4
10906      instr[11,10] = element size 00=> byte(b), 01=> half(h),
10907                                  10=> word(s), 11=> double(d)
10908      instr[9,5]   = Vn, can be SP
10909      instr[4,0]   = Vd  */
10910
10911   int post;
10912   int load;
10913   unsigned vn;
10914   uint64_t address;
10915   int type;
10916
10917   if (uimm (aarch64_get_instr (cpu), 31, 31) != 0
10918       || uimm (aarch64_get_instr (cpu), 29, 25) != 0x06)
10919     HALT_NYI;
10920
10921   type = uimm (aarch64_get_instr (cpu), 15, 12);
10922   if (type != 0xE && type != 0xE && uimm (aarch64_get_instr (cpu), 21, 21) != 0)
10923     HALT_NYI;
10924
10925   post = uimm (aarch64_get_instr (cpu), 23, 23);
10926   load = uimm (aarch64_get_instr (cpu), 22, 22);
10927   vn = uimm (aarch64_get_instr (cpu), 9, 5);
10928   address = aarch64_get_reg_u64 (cpu, vn, SP_OK);
10929
10930   if (post)
10931     {
10932       unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
10933
10934       if (vm == R31)
10935         {
10936           unsigned sizeof_operation;
10937
10938           switch (type)
10939             {
10940             case 0: sizeof_operation = 32; break;
10941             case 4: sizeof_operation = 24; break;
10942             case 8: sizeof_operation = 16; break;
10943
10944             case 0xC:
10945               sizeof_operation = uimm (aarch64_get_instr (cpu), 21, 21) ? 2 : 1;
10946               sizeof_operation <<= uimm (aarch64_get_instr (cpu), 11, 10);
10947               break;
10948
10949             case 0xE:
10950               sizeof_operation = uimm (aarch64_get_instr (cpu), 21, 21) ? 8 : 4;
10951               sizeof_operation <<= uimm (aarch64_get_instr (cpu), 11, 10);
10952               break;
10953
10954             case 2:
10955             case 6:
10956             case 10:
10957             case 7:
10958               sizeof_operation = 2 << uimm (aarch64_get_instr (cpu), 11, 10);
10959               break;
10960
10961             default:
10962               HALT_UNALLOC;
10963             }
10964
10965           if (uimm (aarch64_get_instr (cpu), 30, 30))
10966             sizeof_operation *= 2;
10967
10968           aarch64_set_reg_u64 (cpu, vn, SP_OK, address + sizeof_operation);
10969         }
10970       else
10971         aarch64_set_reg_u64 (cpu, vn, SP_OK,
10972                              address + aarch64_get_reg_u64 (cpu, vm, NO_SP));
10973     }
10974   else
10975     {
10976       NYI_assert (20, 16, 0);
10977     }
10978
10979   if (load)
10980     {
10981       switch (type)
10982         {
10983         case 0:  LD4 (cpu, address); return;
10984         case 4:  LD3 (cpu, address); return;
10985         case 8:  LD2 (cpu, address); return;
10986         case 2:  LD1_4 (cpu, address); return;
10987         case 6:  LD1_3 (cpu, address); return;
10988         case 10: LD1_2 (cpu, address); return;
10989         case 7:  LD1_1 (cpu, address); return;
10990
10991         case 0xE:
10992         case 0xC: do_vec_LDnR (cpu, address); return;
10993
10994         default:
10995           HALT_NYI;
10996         }
10997     }
10998
10999   /* Stores.  */
11000   switch (type)
11001     {
11002     case 0:  ST4 (cpu, address); return;
11003     case 4:  ST3 (cpu, address); return;
11004     case 8:  ST2 (cpu, address); return;
11005     case 2:  ST1_4 (cpu, address); return;
11006     case 6:  ST1_3 (cpu, address); return;
11007     case 10: ST1_2 (cpu, address); return;
11008     case 7:  ST1_1 (cpu, address); return;
11009     default:
11010       HALT_NYI;
11011     }
11012 }
11013
11014 static void
11015 dexLdSt (sim_cpu *cpu)
11016 {
11017   /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
11018      assert  group == GROUP_LDST_0100 || group == GROUP_LDST_0110 ||
11019              group == GROUP_LDST_1100 || group == GROUP_LDST_1110
11020      bits [29,28:26] of a LS are the secondary dispatch vector.  */
11021   uint32_t group2 = dispatchLS (aarch64_get_instr (cpu));
11022
11023   switch (group2)
11024     {
11025     case LS_EXCL_000:
11026       dexLoadExclusive (cpu); return;
11027
11028     case LS_LIT_010:
11029     case LS_LIT_011:
11030       dexLoadLiteral (cpu); return;
11031
11032     case LS_OTHER_110:
11033     case LS_OTHER_111:
11034       dexLoadOther (cpu); return;
11035
11036     case LS_ADVSIMD_001:
11037       do_vec_load_store (cpu); return;
11038
11039     case LS_PAIR_100:
11040       dex_load_store_pair_gr (cpu); return;
11041
11042     case LS_PAIR_101:
11043       dex_load_store_pair_fp (cpu); return;
11044
11045     default:
11046       /* Should never reach here.  */
11047       HALT_NYI;
11048     }
11049 }
11050
11051 /* Specific decode and execute for group Data Processing Register.  */
11052
11053 static void
11054 dexLogicalShiftedRegister (sim_cpu *cpu)
11055 {
11056   /* assert instr[28:24] = 01010
11057      instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11058      instr[30,29:21] = op,N : 000 ==> AND, 001 ==> BIC,
11059                                010 ==> ORR, 011 ==> ORN
11060                                100 ==> EOR, 101 ==> EON,
11061                                110 ==> ANDS, 111 ==> BICS
11062      instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> ROR
11063      instr[15,10] = count : must be 0xxxxx for 32 bit
11064      instr[9,5] = Rn
11065      instr[4,0] = Rd  */
11066
11067   /* unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16); */
11068   uint32_t dispatch;
11069   Shift shiftType;
11070   uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
11071
11072   /* 32 bit operations must have count[5] = 0.  */
11073   /* or else we have an UNALLOC.  */
11074   uint32_t count = uimm (aarch64_get_instr (cpu), 15, 10);
11075
11076   if (!size && uimm (count, 5, 5))
11077     HALT_UNALLOC;
11078
11079   shiftType = shift (aarch64_get_instr (cpu), 22);
11080
11081   /* dispatch on size:op:N i.e aarch64_get_instr (cpu)[31,29:21].  */
11082   dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 29) << 1)
11083               | uimm (aarch64_get_instr (cpu), 21, 21));
11084
11085   switch (dispatch)
11086     {
11087     case 0: and32_shift  (cpu, shiftType, count); return;
11088     case 1: bic32_shift  (cpu, shiftType, count); return;
11089     case 2: orr32_shift  (cpu, shiftType, count); return;
11090     case 3: orn32_shift  (cpu, shiftType, count); return;
11091     case 4: eor32_shift  (cpu, shiftType, count); return;
11092     case 5: eon32_shift  (cpu, shiftType, count); return;
11093     case 6: ands32_shift (cpu, shiftType, count); return;
11094     case 7: bics32_shift (cpu, shiftType, count); return;
11095     case 8: and64_shift  (cpu, shiftType, count); return;
11096     case 9: bic64_shift  (cpu, shiftType, count); return;
11097     case 10:orr64_shift  (cpu, shiftType, count); return;
11098     case 11:orn64_shift  (cpu, shiftType, count); return;
11099     case 12:eor64_shift  (cpu, shiftType, count); return;
11100     case 13:eon64_shift  (cpu, shiftType, count); return;
11101     case 14:ands64_shift (cpu, shiftType, count); return;
11102     case 15:bics64_shift (cpu, shiftType, count); return;
11103     default: HALT_UNALLOC;
11104     }
11105 }
11106
11107 /* 32 bit conditional select.  */
11108 static void
11109 csel32 (sim_cpu *cpu, CondCode cc)
11110 {
11111   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11112   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11113   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11114
11115   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11116                        testConditionCode (cpu, cc)
11117                        ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11118                        : aarch64_get_reg_u32 (cpu, rm, NO_SP));
11119 }
11120
11121 /* 64 bit conditional select.  */
11122 static void
11123 csel64 (sim_cpu *cpu, CondCode cc)
11124 {
11125   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11126   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11127   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11128
11129   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11130                        testConditionCode (cpu, cc)
11131                        ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11132                        : aarch64_get_reg_u64 (cpu, rm, NO_SP));
11133 }
11134
11135 /* 32 bit conditional increment.  */
11136 static void
11137 csinc32 (sim_cpu *cpu, CondCode cc)
11138 {
11139   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11140   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11141   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11142
11143   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11144                        testConditionCode (cpu, cc)
11145                        ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11146                        : aarch64_get_reg_u32 (cpu, rm, NO_SP) + 1);
11147 }
11148
11149 /* 64 bit conditional increment.  */
11150 static void
11151 csinc64 (sim_cpu *cpu, CondCode cc)
11152 {
11153   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11154   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11155   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11156
11157   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11158                        testConditionCode (cpu, cc)
11159                        ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11160                        : aarch64_get_reg_u64 (cpu, rm, NO_SP) + 1);
11161 }
11162
11163 /* 32 bit conditional invert.  */
11164 static void
11165 csinv32 (sim_cpu *cpu, CondCode cc)
11166 {
11167   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11168   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11169   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11170
11171   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11172                        testConditionCode (cpu, cc)
11173                        ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11174                        : ~ aarch64_get_reg_u32 (cpu, rm, NO_SP));
11175 }
11176
11177 /* 64 bit conditional invert.  */
11178 static void
11179 csinv64 (sim_cpu *cpu, CondCode cc)
11180 {
11181   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11182   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11183   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11184
11185   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11186                        testConditionCode (cpu, cc)
11187                        ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11188                        : ~ aarch64_get_reg_u64 (cpu, rm, NO_SP));
11189 }
11190
11191 /* 32 bit conditional negate.  */
11192 static void
11193 csneg32 (sim_cpu *cpu, CondCode cc)
11194 {
11195   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11196   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11197   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11198
11199   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11200                        testConditionCode (cpu, cc)
11201                        ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11202                        : - aarch64_get_reg_u32 (cpu, rm, NO_SP));
11203 }
11204
11205 /* 64 bit conditional negate.  */
11206 static void
11207 csneg64 (sim_cpu *cpu, CondCode cc)
11208 {
11209   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11210   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11211   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11212
11213   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11214                        testConditionCode (cpu, cc)
11215                        ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11216                        : - aarch64_get_reg_u64 (cpu, rm, NO_SP));
11217 }
11218
11219 static void
11220 dexCondSelect (sim_cpu *cpu)
11221 {
11222   /* assert instr[28,21] = 11011011
11223      instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11224      instr[30:11,10] = op : 000 ==> CSEL, 001 ==> CSINC,
11225                             100 ==> CSINV, 101 ==> CSNEG,
11226                             _1_ ==> UNALLOC
11227      instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
11228      instr[15,12] = cond
11229      instr[29] = S : 0 ==> ok, 1 ==> UNALLOC  */
11230
11231   CondCode cc;
11232   uint32_t dispatch;
11233   uint32_t S = uimm (aarch64_get_instr (cpu), 29, 29);
11234   uint32_t op2 = uimm (aarch64_get_instr (cpu), 11, 10);
11235
11236   if (S == 1)
11237     HALT_UNALLOC;
11238
11239   if (op2 & 0x2)
11240     HALT_UNALLOC;
11241
11242   cc = condcode (aarch64_get_instr (cpu), 12);
11243   dispatch = ((uimm (aarch64_get_instr (cpu), 31, 30) << 1) | op2);
11244
11245   switch (dispatch)
11246     {
11247     case 0: csel32  (cpu, cc); return;
11248     case 1: csinc32 (cpu, cc); return;
11249     case 2: csinv32 (cpu, cc); return;
11250     case 3: csneg32 (cpu, cc); return;
11251     case 4: csel64  (cpu, cc); return;
11252     case 5: csinc64 (cpu, cc); return;
11253     case 6: csinv64 (cpu, cc); return;
11254     case 7: csneg64 (cpu, cc); return;
11255     default: HALT_UNALLOC;
11256     }
11257 }
11258
11259 /* Some helpers for counting leading 1 or 0 bits.  */
11260
11261 /* Counts the number of leading bits which are the same
11262    in a 32 bit value in the range 1 to 32.  */
11263 static uint32_t
11264 leading32 (uint32_t value)
11265 {
11266   int32_t mask= 0xffff0000;
11267   uint32_t count= 16; /* Counts number of bits set in mask.  */
11268   uint32_t lo = 1;    /* Lower bound for number of sign bits.  */
11269   uint32_t hi = 32;   /* Upper bound for number of sign bits.  */
11270
11271   while (lo + 1 < hi)
11272     {
11273       int32_t test = (value & mask);
11274
11275       if (test == 0 || test == mask)
11276         {
11277           lo = count;
11278           count = (lo + hi) / 2;
11279           mask >>= (count - lo);
11280         }
11281       else
11282         {
11283           hi = count;
11284           count = (lo + hi) / 2;
11285           mask <<= hi - count;
11286         }
11287     }
11288
11289   if (lo != hi)
11290     {
11291       int32_t test;
11292
11293       mask >>= 1;
11294       test = (value & mask);
11295
11296       if (test == 0 || test == mask)
11297         count = hi;
11298       else
11299         count = lo;
11300     }
11301
11302   return count;
11303 }
11304
11305 /* Counts the number of leading bits which are the same
11306    in a 64 bit value in the range 1 to 64.  */
11307 static uint64_t
11308 leading64 (uint64_t value)
11309 {
11310   int64_t mask= 0xffffffff00000000LL;
11311   uint64_t count = 32; /* Counts number of bits set in mask.  */
11312   uint64_t lo = 1;     /* Lower bound for number of sign bits.  */
11313   uint64_t hi = 64;    /* Upper bound for number of sign bits.  */
11314
11315   while (lo + 1 < hi)
11316     {
11317       int64_t test = (value & mask);
11318
11319       if (test == 0 || test == mask)
11320         {
11321           lo = count;
11322           count = (lo + hi) / 2;
11323           mask >>= (count - lo);
11324         }
11325       else
11326         {
11327           hi = count;
11328           count = (lo + hi) / 2;
11329           mask <<= hi - count;
11330         }
11331     }
11332
11333   if (lo != hi)
11334     {
11335       int64_t test;
11336
11337       mask >>= 1;
11338       test = (value & mask);
11339
11340       if (test == 0 || test == mask)
11341         count = hi;
11342       else
11343         count = lo;
11344     }
11345
11346   return count;
11347 }
11348
11349 /* Bit operations.  */
11350 /* N.B register args may not be SP.  */
11351
11352 /* 32 bit count leading sign bits.  */
11353 static void
11354 cls32 (sim_cpu *cpu)
11355 {
11356   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11357   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11358
11359   /* N.B. the result needs to exclude the leading bit.  */
11360   aarch64_set_reg_u64
11361     (cpu, rd, NO_SP, leading32 (aarch64_get_reg_u32 (cpu, rn, NO_SP)) - 1);
11362 }
11363
11364 /* 64 bit count leading sign bits.  */
11365 static void
11366 cls64 (sim_cpu *cpu)
11367 {
11368   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11369   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11370
11371   /* N.B. the result needs to exclude the leading bit.  */
11372   aarch64_set_reg_u64
11373     (cpu, rd, NO_SP, leading64 (aarch64_get_reg_u64 (cpu, rn, NO_SP)) - 1);
11374 }
11375
11376 /* 32 bit count leading zero bits.  */
11377 static void
11378 clz32 (sim_cpu *cpu)
11379 {
11380   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11381   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11382   uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11383
11384   /* if the sign (top) bit is set then the count is 0.  */
11385   if (pick32 (value, 31, 31))
11386     aarch64_set_reg_u64 (cpu, rd, NO_SP, 0L);
11387   else
11388     aarch64_set_reg_u64 (cpu, rd, NO_SP, leading32 (value));
11389 }
11390
11391 /* 64 bit count leading zero bits.  */
11392 static void
11393 clz64 (sim_cpu *cpu)
11394 {
11395   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11396   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11397   uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11398
11399   /* if the sign (top) bit is set then the count is 0.  */
11400   if (pick64 (value, 63, 63))
11401     aarch64_set_reg_u64 (cpu, rd, NO_SP, 0L);
11402   else
11403     aarch64_set_reg_u64 (cpu, rd, NO_SP, leading64 (value));
11404 }
11405
11406 /* 32 bit reverse bits.  */
11407 static void
11408 rbit32 (sim_cpu *cpu)
11409 {
11410   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11411   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11412   uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11413   uint32_t result = 0;
11414   int i;
11415
11416   for (i = 0; i < 32; i++)
11417     {
11418       result <<= 1;
11419       result |= (value & 1);
11420       value >>= 1;
11421     }
11422   aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11423 }
11424
11425 /* 64 bit reverse bits.  */
11426 static void
11427 rbit64 (sim_cpu *cpu)
11428 {
11429   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11430   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11431   uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11432   uint64_t result = 0;
11433   int i;
11434
11435   for (i = 0; i < 64; i++)
11436     {
11437       result <<= 1;
11438       result |= (value & 1L);
11439       value >>= 1;
11440     }
11441   aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11442 }
11443
11444 /* 32 bit reverse bytes.  */
11445 static void
11446 rev32 (sim_cpu *cpu)
11447 {
11448   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11449   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11450   uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11451   uint32_t result = 0;
11452   int i;
11453
11454   for (i = 0; i < 4; i++)
11455     {
11456       result <<= 8;
11457       result |= (value & 0xff);
11458       value >>= 8;
11459     }
11460   aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11461 }
11462
11463 /* 64 bit reverse bytes.  */
11464 static void
11465 rev64 (sim_cpu *cpu)
11466 {
11467   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11468   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11469   uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11470   uint64_t result = 0;
11471   int i;
11472
11473   for (i = 0; i < 8; i++)
11474     {
11475       result <<= 8;
11476       result |= (value & 0xffULL);
11477       value >>= 8;
11478     }
11479   aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11480 }
11481
11482 /* 32 bit reverse shorts.  */
11483 /* N.B.this reverses the order of the bytes in each half word.  */
11484 static void
11485 revh32 (sim_cpu *cpu)
11486 {
11487   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11488   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11489   uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11490   uint32_t result = 0;
11491   int i;
11492
11493   for (i = 0; i < 2; i++)
11494     {
11495       result <<= 8;
11496       result |= (value & 0x00ff00ff);
11497       value >>= 8;
11498     }
11499   aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11500 }
11501
11502 /* 64 bit reverse shorts.  */
11503 /* N.B.this reverses the order of the bytes in each half word.  */
11504 static void
11505 revh64 (sim_cpu *cpu)
11506 {
11507   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11508   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11509   uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11510   uint64_t result = 0;
11511   int i;
11512
11513   for (i = 0; i < 2; i++)
11514     {
11515       result <<= 8;
11516       result |= (value & 0x00ff00ff00ff00ffULL);
11517       value >>= 8;
11518     }
11519   aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11520 }
11521
11522 static void
11523 dexDataProc1Source (sim_cpu *cpu)
11524 {
11525   /* assert instr[30] == 1
11526      aarch64_get_instr (cpu)[28,21] == 111010110
11527      instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11528      instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
11529      instr[20,16] = opcode2 : 00000 ==> ok, ow ==> UNALLOC
11530      instr[15,10] = opcode : 000000 ==> RBIT, 000001 ==> REV16,
11531                              000010 ==> REV, 000011 ==> UNALLOC
11532                              000100 ==> CLZ, 000101 ==> CLS
11533                              ow ==> UNALLOC
11534      instr[9,5] = rn : may not be SP
11535      instr[4,0] = rd : may not be SP.  */
11536
11537   uint32_t S = uimm (aarch64_get_instr (cpu), 29, 29);
11538   uint32_t opcode2 = uimm (aarch64_get_instr (cpu), 20, 16);
11539   uint32_t opcode = uimm (aarch64_get_instr (cpu), 15, 10);
11540   uint32_t dispatch = ((uimm (aarch64_get_instr (cpu), 31, 31) << 3) | opcode);
11541
11542   if (S == 1)
11543     HALT_UNALLOC;
11544
11545   if (opcode2 != 0)
11546     HALT_UNALLOC;
11547
11548   if (opcode & 0x38)
11549     HALT_UNALLOC;
11550
11551   switch (dispatch)
11552     {
11553     case 0: rbit32 (cpu); return;
11554     case 1: revh32 (cpu); return;
11555     case 2: rev32 (cpu); return;
11556     case 4: clz32 (cpu); return;
11557     case 5: cls32 (cpu); return;
11558     case 8: rbit64 (cpu); return;
11559     case 9: revh64 (cpu); return;
11560     case 10:rev32 (cpu); return;
11561     case 11:rev64 (cpu); return;
11562     case 12:clz64 (cpu); return;
11563     case 13:cls64 (cpu); return;
11564     default: HALT_UNALLOC;
11565     }
11566 }
11567
11568 /* Variable shift.
11569    Shifts by count supplied in register.
11570    N.B register args may not be SP.
11571    These all use the shifted auxiliary function for
11572    simplicity and clarity.  Writing the actual shift
11573    inline would avoid a branch and so be faster but
11574    would also necessitate getting signs right.  */
11575
11576 /* 32 bit arithmetic shift right.  */
11577 static void
11578 asrv32 (sim_cpu *cpu)
11579 {
11580   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11581   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11582   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11583
11584   aarch64_set_reg_u64
11585     (cpu, rd, NO_SP,
11586      shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), ASR,
11587                 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
11588 }
11589
11590 /* 64 bit arithmetic shift right.  */
11591 static void
11592 asrv64 (sim_cpu *cpu)
11593 {
11594   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11595   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11596   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11597
11598   aarch64_set_reg_u64
11599     (cpu, rd, NO_SP,
11600      shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), ASR,
11601                 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
11602 }
11603
11604 /* 32 bit logical shift left.  */
11605 static void
11606 lslv32 (sim_cpu *cpu)
11607 {
11608   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11609   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11610   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11611
11612   aarch64_set_reg_u64
11613     (cpu, rd, NO_SP,
11614      shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), LSL,
11615                 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
11616 }
11617
11618 /* 64 bit arithmetic shift left.  */
11619 static void
11620 lslv64 (sim_cpu *cpu)
11621 {
11622   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11623   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11624   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11625
11626   aarch64_set_reg_u64
11627     (cpu, rd, NO_SP,
11628      shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), LSL,
11629                 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
11630 }
11631
11632 /* 32 bit logical shift right.  */
11633 static void
11634 lsrv32 (sim_cpu *cpu)
11635 {
11636   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11637   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11638   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11639
11640   aarch64_set_reg_u64
11641     (cpu, rd, NO_SP,
11642      shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), LSR,
11643                 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
11644 }
11645
11646 /* 64 bit logical shift right.  */
11647 static void
11648 lsrv64 (sim_cpu *cpu)
11649 {
11650   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11651   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11652   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11653
11654   aarch64_set_reg_u64
11655     (cpu, rd, NO_SP,
11656      shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), LSR,
11657                 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
11658 }
11659
11660 /* 32 bit rotate right.  */
11661 static void
11662 rorv32 (sim_cpu *cpu)
11663 {
11664   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11665   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11666   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11667
11668   aarch64_set_reg_u64
11669     (cpu, rd, NO_SP,
11670      shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), ROR,
11671                 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
11672 }
11673
11674 /* 64 bit rotate right.  */
11675 static void
11676 rorv64 (sim_cpu *cpu)
11677 {
11678   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11679   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11680   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11681
11682   aarch64_set_reg_u64
11683     (cpu, rd, NO_SP,
11684      shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), ROR,
11685                 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
11686 }
11687
11688
11689 /* divide.  */
11690
11691 /* 32 bit signed divide.  */
11692 static void
11693 cpuiv32 (sim_cpu *cpu)
11694 {
11695   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11696   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11697   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11698   /* N.B. the pseudo-code does the divide using 64 bit data.  */
11699   /* TODO : check that this rounds towards zero as required.  */
11700   int64_t dividend = aarch64_get_reg_s32 (cpu, rn, NO_SP);
11701   int64_t divisor = aarch64_get_reg_s32 (cpu, rm, NO_SP);
11702
11703   aarch64_set_reg_s64 (cpu, rd, NO_SP,
11704                        divisor ? ((int32_t) (dividend / divisor)) : 0);
11705 }
11706
11707 /* 64 bit signed divide.  */
11708 static void
11709 cpuiv64 (sim_cpu *cpu)
11710 {
11711   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11712   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11713   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11714
11715   /* TODO : check that this rounds towards zero as required.  */
11716   int64_t divisor = aarch64_get_reg_s64 (cpu, rm, NO_SP);
11717
11718   aarch64_set_reg_s64
11719     (cpu, rd, NO_SP,
11720      divisor ? (aarch64_get_reg_s64 (cpu, rn, NO_SP) / divisor) : 0);
11721 }
11722
11723 /* 32 bit unsigned divide.  */
11724 static void
11725 udiv32 (sim_cpu *cpu)
11726 {
11727   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11728   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11729   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11730
11731   /* N.B. the pseudo-code does the divide using 64 bit data.  */
11732   uint64_t dividend = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11733   uint64_t divisor  = aarch64_get_reg_u32 (cpu, rm, NO_SP);
11734
11735   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11736                        divisor ? (uint32_t) (dividend / divisor) : 0);
11737 }
11738
11739 /* 64 bit unsigned divide.  */
11740 static void
11741 udiv64 (sim_cpu *cpu)
11742 {
11743   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11744   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11745   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11746
11747   /* TODO : check that this rounds towards zero as required.  */
11748   uint64_t divisor = aarch64_get_reg_u64 (cpu, rm, NO_SP);
11749
11750   aarch64_set_reg_u64
11751     (cpu, rd, NO_SP,
11752      divisor ? (aarch64_get_reg_u64 (cpu, rn, NO_SP) / divisor) : 0);
11753 }
11754
11755 static void
11756 dexDataProc2Source (sim_cpu *cpu)
11757 {
11758   /* assert instr[30] == 0
11759      instr[28,21] == 11010110
11760      instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11761      instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
11762      instr[15,10] = opcode : 000010 ==> UDIV, 000011 ==> CPUIV,
11763                              001000 ==> LSLV, 001001 ==> LSRV
11764                              001010 ==> ASRV, 001011 ==> RORV
11765                              ow ==> UNALLOC.  */
11766
11767   uint32_t dispatch;
11768   uint32_t S = uimm (aarch64_get_instr (cpu), 29, 29);
11769   uint32_t opcode = uimm (aarch64_get_instr (cpu), 15, 10);
11770
11771   if (S == 1)
11772     HALT_UNALLOC;
11773
11774   if (opcode & 0x34)
11775     HALT_UNALLOC;
11776
11777   dispatch = (  (uimm (aarch64_get_instr (cpu), 31, 31) << 3)
11778               | (uimm (opcode, 3, 3) << 2)
11779               |  uimm (opcode, 1, 0));
11780   switch (dispatch)
11781     {
11782     case 2:  udiv32 (cpu); return;
11783     case 3:  cpuiv32 (cpu); return;
11784     case 4:  lslv32 (cpu); return;
11785     case 5:  lsrv32 (cpu); return;
11786     case 6:  asrv32 (cpu); return;
11787     case 7:  rorv32 (cpu); return;
11788     case 10: udiv64 (cpu); return;
11789     case 11: cpuiv64 (cpu); return;
11790     case 12: lslv64 (cpu); return;
11791     case 13: lsrv64 (cpu); return;
11792     case 14: asrv64 (cpu); return;
11793     case 15: rorv64 (cpu); return;
11794     default: HALT_UNALLOC;
11795     }
11796 }
11797
11798
11799 /* Multiply.  */
11800
11801 /* 32 bit multiply and add.  */
11802 static void
11803 madd32 (sim_cpu *cpu)
11804 {
11805   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11806   unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11807   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11808   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11809
11810   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11811                        aarch64_get_reg_u32 (cpu, ra, NO_SP)
11812                        + aarch64_get_reg_u32 (cpu, rn, NO_SP)
11813                        * aarch64_get_reg_u32 (cpu, rm, NO_SP));
11814 }
11815
11816 /* 64 bit multiply and add.  */
11817 static void
11818 madd64 (sim_cpu *cpu)
11819 {
11820   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11821   unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11822   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11823   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11824
11825   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11826                        aarch64_get_reg_u64 (cpu, ra, NO_SP)
11827                        + aarch64_get_reg_u64 (cpu, rn, NO_SP)
11828                        * aarch64_get_reg_u64 (cpu, rm, NO_SP));
11829 }
11830
11831 /* 32 bit multiply and sub.  */
11832 static void
11833 msub32 (sim_cpu *cpu)
11834 {
11835   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11836   unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11837   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11838   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11839
11840   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11841                        aarch64_get_reg_u32 (cpu, ra, NO_SP)
11842                        - aarch64_get_reg_u32 (cpu, rn, NO_SP)
11843                        * aarch64_get_reg_u32 (cpu, rm, NO_SP));
11844 }
11845
11846 /* 64 bit multiply and sub.  */
11847 static void
11848 msub64 (sim_cpu *cpu)
11849 {
11850   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11851   unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11852   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11853   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11854
11855   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11856                        aarch64_get_reg_u64 (cpu, ra, NO_SP)
11857                        - aarch64_get_reg_u64 (cpu, rn, NO_SP)
11858                        * aarch64_get_reg_u64 (cpu, rm, NO_SP));
11859 }
11860
11861 /* Signed multiply add long -- source, source2 : 32 bit, source3 : 64 bit.  */
11862 static void
11863 smaddl (sim_cpu *cpu)
11864 {
11865   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11866   unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11867   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11868   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11869
11870   /* N.B. we need to multiply the signed 32 bit values in rn, rm to
11871      obtain a 64 bit product.  */
11872   aarch64_set_reg_s64
11873     (cpu, rd, NO_SP,
11874      aarch64_get_reg_s64 (cpu, ra, NO_SP)
11875      + ((int64_t) aarch64_get_reg_s32 (cpu, rn, NO_SP))
11876      * ((int64_t) aarch64_get_reg_s32 (cpu, rm, NO_SP)));
11877 }
11878
11879 /* Signed multiply sub long -- source, source2 : 32 bit, source3 : 64 bit.  */
11880 static void
11881 smsubl (sim_cpu *cpu)
11882 {
11883   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11884   unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
11885   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11886   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11887
11888   /* N.B. we need to multiply the signed 32 bit values in rn, rm to
11889      obtain a 64 bit product.  */
11890   aarch64_set_reg_s64
11891     (cpu, rd, NO_SP,
11892      aarch64_get_reg_s64 (cpu, ra, NO_SP)
11893      - ((int64_t) aarch64_get_reg_s32 (cpu, rn, NO_SP))
11894      * ((int64_t) aarch64_get_reg_s32 (cpu, rm, NO_SP)));
11895 }
11896
11897 /* Integer Multiply/Divide.  */
11898
11899 /* First some macros and a helper function.  */
11900 /* Macros to test or access elements of 64 bit words.  */
11901
11902 /* Mask used to access lo 32 bits of 64 bit unsigned int.  */
11903 #define LOW_WORD_MASK ((1ULL << 32) - 1)
11904 /* Return the lo 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int.  */
11905 #define lowWordToU64(_value_u64) ((_value_u64) & LOW_WORD_MASK)
11906 /* Return the hi 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int.  */
11907 #define highWordToU64(_value_u64) ((_value_u64) >> 32)
11908
11909 /* Offset of sign bit in 64 bit signed integger.  */
11910 #define SIGN_SHIFT_U64 63
11911 /* The sign bit itself -- also identifies the minimum negative int value.  */
11912 #define SIGN_BIT_U64 (1UL << SIGN_SHIFT_U64)
11913 /* Return true if a 64 bit signed int presented as an unsigned int is the
11914    most negative value.  */
11915 #define isMinimumU64(_value_u64) ((_value_u64) == SIGN_BIT_U64)
11916 /* Return true (non-zero) if a 64 bit signed int presented as an unsigned
11917    int has its sign bit set to false.  */
11918 #define isSignSetU64(_value_u64) ((_value_u64) & SIGN_BIT_U64)
11919 /* Return 1L or -1L according to whether a 64 bit signed int presented as
11920    an unsigned int has its sign bit set or not.  */
11921 #define signOfU64(_value_u64) (1L + (((value_u64) >> SIGN_SHIFT_U64) * -2L)
11922 /* Clear the sign bit of a 64 bit signed int presented as an unsigned int.  */
11923 #define clearSignU64(_value_u64) ((_value_u64) &= ~SIGN_BIT_U64)
11924
11925 /* Multiply two 64 bit ints and return.
11926    the hi 64 bits of the 128 bit product.  */
11927
11928 static uint64_t
11929 mul64hi (uint64_t value1, uint64_t value2)
11930 {
11931   uint64_t resultmid1;
11932   uint64_t result;
11933   uint64_t value1_lo = lowWordToU64 (value1);
11934   uint64_t value1_hi = highWordToU64 (value1) ;
11935   uint64_t value2_lo = lowWordToU64 (value2);
11936   uint64_t value2_hi = highWordToU64 (value2);
11937
11938   /* Cross-multiply and collect results.  */
11939
11940   uint64_t xproductlo = value1_lo * value2_lo;
11941   uint64_t xproductmid1 = value1_lo * value2_hi;
11942   uint64_t xproductmid2 = value1_hi * value2_lo;
11943   uint64_t xproducthi = value1_hi * value2_hi;
11944   uint64_t carry = 0;
11945   /* Start accumulating 64 bit results.  */
11946   /* Drop bottom half of lowest cross-product.  */
11947   uint64_t resultmid = xproductlo >> 32;
11948   /* Add in middle products.  */
11949   resultmid = resultmid + xproductmid1;
11950
11951   /* Check for overflow.  */
11952   if (resultmid < xproductmid1)
11953     /* Carry over 1 into top cross-product.  */
11954     carry++;
11955
11956   resultmid1  = resultmid + xproductmid2;
11957
11958   /* Check for overflow.  */
11959   if (resultmid1 < xproductmid2)
11960     /* Carry over 1 into top cross-product.  */
11961     carry++;
11962
11963   /* Drop lowest 32 bits of middle cross-product.  */
11964   result = resultmid1 >> 32;
11965
11966   /* Add top cross-product plus and any carry.  */
11967   result += xproducthi + carry;
11968
11969   return result;
11970 }
11971
11972 /* Signed multiply high, source, source2 :
11973    64 bit, dest <-- high 64-bit of result.  */
11974 static void
11975 smulh (sim_cpu *cpu)
11976 {
11977   uint64_t uresult;
11978   int64_t result;
11979   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11980   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11981   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11982   GReg ra = greg (aarch64_get_instr (cpu), 10);
11983   int64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11984   int64_t value2 = aarch64_get_reg_u64 (cpu, rm, NO_SP);
11985   uint64_t uvalue1;
11986   uint64_t uvalue2;
11987   int64_t signum = 1;
11988
11989   if (ra != R31)
11990     HALT_UNALLOC;
11991
11992   /* Convert to unsigned and use the unsigned mul64hi routine
11993      the fix the sign up afterwards.  */
11994   if (value1 < 0)
11995     {
11996       signum *= -1L;
11997       uvalue1 = -value1;
11998     }
11999   else
12000     {
12001       uvalue1 = value1;
12002     }
12003
12004   if (value2 < 0)
12005     {
12006       signum *= -1L;
12007       uvalue2 = -value2;
12008     }
12009   else
12010     {
12011       uvalue2 = value2;
12012     }
12013
12014   uresult = mul64hi (uvalue1, uvalue2);
12015   result = uresult;
12016   result *= signum;
12017
12018   aarch64_set_reg_s64 (cpu, rd, NO_SP, result);
12019 }
12020
12021 /* Unsigned multiply add long -- source, source2 :
12022    32 bit, source3 : 64 bit.  */
12023 static void
12024 umaddl (sim_cpu *cpu)
12025 {
12026   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12027   unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
12028   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12029   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12030
12031   /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12032      obtain a 64 bit product.  */
12033   aarch64_set_reg_u64
12034     (cpu, rd, NO_SP,
12035      aarch64_get_reg_u64 (cpu, ra, NO_SP)
12036      + ((uint64_t) aarch64_get_reg_u32 (cpu, rn, NO_SP))
12037      * ((uint64_t) aarch64_get_reg_u32 (cpu, rm, NO_SP)));
12038 }
12039
12040 /* Unsigned multiply sub long -- source, source2 : 32 bit, source3 : 64 bit.  */
12041 static void
12042 umsubl (sim_cpu *cpu)
12043 {
12044   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12045   unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
12046   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12047   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12048
12049   /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12050      obtain a 64 bit product.  */
12051   aarch64_set_reg_u64
12052     (cpu, rd, NO_SP,
12053      aarch64_get_reg_u64 (cpu, ra, NO_SP)
12054      - ((uint64_t) aarch64_get_reg_u32 (cpu, rn, NO_SP))
12055      * ((uint64_t) aarch64_get_reg_u32 (cpu, rm, NO_SP)));
12056 }
12057
12058 /* Unsigned multiply high, source, source2 :
12059    64 bit, dest <-- high 64-bit of result.  */
12060 static void
12061 umulh (sim_cpu *cpu)
12062 {
12063   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12064   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12065   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12066   GReg ra = greg (aarch64_get_instr (cpu), 10);
12067
12068   if (ra != R31)
12069     HALT_UNALLOC;
12070
12071   aarch64_set_reg_u64 (cpu, rd, NO_SP,
12072                        mul64hi (aarch64_get_reg_u64 (cpu, rn, NO_SP),
12073                                 aarch64_get_reg_u64 (cpu, rm, NO_SP)));
12074 }
12075
12076 static void
12077 dexDataProc3Source (sim_cpu *cpu)
12078 {
12079   /* assert instr[28,24] == 11011.  */
12080   /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit (for rd at least)
12081      instr[30,29] = op54 : 00 ==> ok, ow ==> UNALLOC
12082      instr[23,21] = op31 : 111 ==> UNALLOC, o2 ==> ok
12083      instr[15] = o0 : 0/1 ==> ok
12084      instr[23,21:15] ==> op : 0000 ==> MADD, 0001 ==> MSUB,     (32/64 bit)
12085                               0010 ==> SMADDL, 0011 ==> SMSUBL, (64 bit only)
12086                               0100 ==> SMULH,                   (64 bit only)
12087                               1010 ==> UMADDL, 1011 ==> UNSUBL, (64 bit only)
12088                               1100 ==> UMULH                    (64 bit only)
12089                               ow ==> UNALLOC.  */
12090
12091   uint32_t dispatch;
12092   uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
12093   uint32_t op54 = uimm (aarch64_get_instr (cpu), 30, 29);
12094   uint32_t op31 = uimm (aarch64_get_instr (cpu), 23, 21);
12095   uint32_t o0 = uimm (aarch64_get_instr (cpu), 15, 15);
12096
12097   if (op54 != 0)
12098     HALT_UNALLOC;
12099
12100   if (size == 0)
12101     {
12102       if (op31 != 0)
12103         HALT_UNALLOC;
12104
12105       if (o0 == 0)
12106         madd32 (cpu);
12107       else
12108         msub32 (cpu);
12109       return;
12110     }
12111
12112   dispatch = (op31 << 1) | o0;
12113
12114   switch (dispatch)
12115     {
12116     case 0:  madd64 (cpu); return;
12117     case 1:  msub64 (cpu); return;
12118     case 2:  smaddl (cpu); return;
12119     case 3:  smsubl (cpu); return;
12120     case 4:  smulh (cpu); return;
12121     case 10: umaddl (cpu); return;
12122     case 11: umsubl (cpu); return;
12123     case 12: umulh (cpu); return;
12124     default: HALT_UNALLOC;
12125     }
12126 }
12127
12128 static void
12129 dexDPReg (sim_cpu *cpu)
12130 {
12131   /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
12132      assert  group == GROUP_DPREG_0101 || group == GROUP_DPREG_1101
12133      bits [28:24:21] of a DPReg are the secondary dispatch vector.  */
12134   uint32_t group2 = dispatchDPReg (aarch64_get_instr (cpu));
12135
12136   switch (group2)
12137     {
12138     case DPREG_LOG_000:
12139     case DPREG_LOG_001:
12140       dexLogicalShiftedRegister (cpu); return;
12141
12142     case DPREG_ADDSHF_010:
12143       dexAddSubtractShiftedRegister (cpu); return;
12144
12145     case DPREG_ADDEXT_011:
12146       dexAddSubtractExtendedRegister (cpu); return;
12147
12148     case DPREG_ADDCOND_100:
12149       {
12150         /* This set bundles a variety of different operations.  */
12151         /* Check for.  */
12152         /* 1) add/sub w carry.  */
12153         uint32_t mask1 = 0x1FE00000U;
12154         uint32_t val1  = 0x1A000000U;
12155         /* 2) cond compare register/immediate.  */
12156         uint32_t mask2 = 0x1FE00000U;
12157         uint32_t val2  = 0x1A400000U;
12158         /* 3) cond select.  */
12159         uint32_t mask3 = 0x1FE00000U;
12160         uint32_t val3  = 0x1A800000U;
12161         /* 4) data proc 1/2 source.  */
12162         uint32_t mask4 = 0x1FE00000U;
12163         uint32_t val4  = 0x1AC00000U;
12164
12165         if ((aarch64_get_instr (cpu) & mask1) == val1)
12166           dexAddSubtractWithCarry (cpu);
12167
12168         else if ((aarch64_get_instr (cpu) & mask2) == val2)
12169           CondCompare (cpu);
12170
12171         else if ((aarch64_get_instr (cpu) & mask3) == val3)
12172           dexCondSelect (cpu);
12173
12174         else if ((aarch64_get_instr (cpu) & mask4) == val4)
12175           {
12176             /* Bit 30 is clear for data proc 2 source
12177                and set for data proc 1 source.  */
12178             if (aarch64_get_instr (cpu)  & (1U << 30))
12179               dexDataProc1Source (cpu);
12180             else
12181               dexDataProc2Source (cpu);
12182           }
12183
12184         else
12185           /* Should not reach here.  */
12186           HALT_NYI;
12187
12188         return;
12189       }
12190
12191     case DPREG_3SRC_110:
12192       dexDataProc3Source (cpu); return;
12193
12194     case DPREG_UNALLOC_101:
12195       HALT_UNALLOC;
12196
12197     case DPREG_3SRC_111:
12198       dexDataProc3Source (cpu); return;
12199
12200     default:
12201       /* Should never reach here.  */
12202       HALT_NYI;
12203     }
12204 }
12205
12206 /* Unconditional Branch immediate.
12207    Offset is a PC-relative byte offset in the range +/- 128MiB.
12208    The offset is assumed to be raw from the decode i.e. the
12209    simulator is expected to scale them from word offsets to byte.  */
12210
12211 /* Unconditional branch.  */
12212 static void
12213 buc (sim_cpu *cpu, int32_t offset)
12214 {
12215   aarch64_set_next_PC_by_offset (cpu, offset);
12216 }
12217
12218 static unsigned stack_depth = 0;
12219
12220 /* Unconditional branch and link -- writes return PC to LR.  */
12221 static void
12222 bl (sim_cpu *cpu, int32_t offset)
12223 {
12224   aarch64_save_LR (cpu);
12225   aarch64_set_next_PC_by_offset (cpu, offset);
12226
12227   if (TRACE_BRANCH_P (cpu))
12228     {
12229       ++ stack_depth;
12230       TRACE_BRANCH (cpu,
12231                     " %*scall %" PRIx64 " [%s]"
12232                     " [args: %" PRIx64 " %" PRIx64 " %" PRIx64 "]",
12233                     stack_depth, " ", aarch64_get_next_PC (cpu),
12234                     aarch64_get_func (aarch64_get_next_PC (cpu)),
12235                     aarch64_get_reg_u64 (cpu, 0, NO_SP),
12236                     aarch64_get_reg_u64 (cpu, 1, NO_SP),
12237                     aarch64_get_reg_u64 (cpu, 2, NO_SP)
12238                     );
12239     }
12240 }
12241
12242 /* Unconditional Branch register.
12243    Branch/return address is in source register.  */
12244
12245 /* Unconditional branch.  */
12246 static void
12247 br (sim_cpu *cpu)
12248 {
12249   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12250   aarch64_set_next_PC (cpu, aarch64_get_reg_u64 (cpu, rn, NO_SP));
12251 }
12252
12253 /* Unconditional branch and link -- writes return PC to LR.  */
12254 static void
12255 blr (sim_cpu *cpu)
12256 {
12257   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12258
12259   /* The pseudo code in the spec says we update LR before fetching.
12260      the value from the rn.  */
12261   aarch64_save_LR (cpu);
12262   aarch64_set_next_PC (cpu, aarch64_get_reg_u64 (cpu, rn, NO_SP));
12263
12264   if (TRACE_BRANCH_P (cpu))
12265     {
12266       ++ stack_depth;
12267       TRACE_BRANCH (cpu,
12268                     " %*scall %" PRIx64 " [%s]"
12269                     " [args: %" PRIx64 " %" PRIx64 " %" PRIx64 "]",
12270                     stack_depth, " ", aarch64_get_next_PC (cpu),
12271                     aarch64_get_func (aarch64_get_next_PC (cpu)),
12272                     aarch64_get_reg_u64 (cpu, 0, NO_SP),
12273                     aarch64_get_reg_u64 (cpu, 1, NO_SP),
12274                     aarch64_get_reg_u64 (cpu, 2, NO_SP)
12275                     );
12276     }
12277 }
12278
12279 /* Return -- assembler will default source to LR this is functionally
12280    equivalent to br but, presumably, unlike br it side effects the
12281    branch predictor.  */
12282 static void
12283 ret (sim_cpu *cpu)
12284 {
12285   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12286   aarch64_set_next_PC (cpu, aarch64_get_reg_u64 (cpu, rn, NO_SP));
12287
12288   if (TRACE_BRANCH_P (cpu))
12289     {
12290       TRACE_BRANCH (cpu,
12291                     " %*sreturn [result: %" PRIx64 "]",
12292                     stack_depth, " ", aarch64_get_reg_u64 (cpu, 0, NO_SP));
12293       -- stack_depth;
12294     }
12295 }
12296
12297 /* NOP -- we implement this and call it from the decode in case we
12298    want to intercept it later.  */
12299
12300 static void
12301 nop (sim_cpu *cpu)
12302 {
12303 }
12304
12305 /* Data synchronization barrier.  */
12306
12307 static void
12308 dsb (sim_cpu *cpu)
12309 {
12310 }
12311
12312 /* Data memory barrier.  */
12313
12314 static void
12315 dmb (sim_cpu *cpu)
12316 {
12317 }
12318
12319 /* Instruction synchronization barrier.  */
12320
12321 static void
12322 isb (sim_cpu *cpu)
12323 {
12324 }
12325
12326 static void
12327 dexBranchImmediate (sim_cpu *cpu)
12328 {
12329   /* assert instr[30,26] == 00101
12330      instr[31] ==> 0 == B, 1 == BL
12331      instr[25,0] == imm26 branch offset counted in words.  */
12332
12333   uint32_t top = uimm (aarch64_get_instr (cpu), 31, 31);
12334   /* We have a 26 byte signed word offset which we need to pass to the
12335      execute routine as a signed byte offset.  */
12336   int32_t offset = simm32 (aarch64_get_instr (cpu), 25, 0) << 2;
12337
12338   if (top)
12339     bl (cpu, offset);
12340   else
12341     buc (cpu, offset);
12342 }
12343
12344 /* Control Flow.  */
12345
12346 /* Conditional branch
12347
12348    Offset is a PC-relative byte offset in the range +/- 1MiB pos is
12349    a bit position in the range 0 .. 63
12350
12351    cc is a CondCode enum value as pulled out of the decode
12352
12353    N.B. any offset register (source) can only be Xn or Wn.  */
12354
12355 static void
12356 bcc (sim_cpu *cpu, int32_t offset, CondCode cc)
12357 {
12358   /* the test returns TRUE if CC is met.  */
12359   if (testConditionCode (cpu, cc))
12360     aarch64_set_next_PC_by_offset (cpu, offset);
12361 }
12362
12363 /* 32 bit branch on register non-zero.  */
12364 static void
12365 cbnz32 (sim_cpu *cpu, int32_t offset)
12366 {
12367   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12368
12369   if (aarch64_get_reg_u32 (cpu, rt, NO_SP) != 0)
12370     aarch64_set_next_PC_by_offset (cpu, offset);
12371 }
12372
12373 /* 64 bit branch on register zero.  */
12374 static void
12375 cbnz (sim_cpu *cpu, int32_t offset)
12376 {
12377   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12378
12379   if (aarch64_get_reg_u64 (cpu, rt, NO_SP) != 0)
12380     aarch64_set_next_PC_by_offset (cpu, offset);
12381 }
12382
12383 /* 32 bit branch on register non-zero.  */
12384 static void
12385 cbz32 (sim_cpu *cpu, int32_t offset)
12386 {
12387   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12388
12389   if (aarch64_get_reg_u32 (cpu, rt, NO_SP) == 0)
12390     aarch64_set_next_PC_by_offset (cpu, offset);
12391 }
12392
12393 /* 64 bit branch on register zero.  */
12394 static void
12395 cbz (sim_cpu *cpu, int32_t offset)
12396 {
12397   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12398
12399   if (aarch64_get_reg_u64 (cpu, rt, NO_SP) == 0)
12400     aarch64_set_next_PC_by_offset (cpu, offset);
12401 }
12402
12403 /* Branch on register bit test non-zero -- one size fits all.  */
12404 static void
12405 tbnz (sim_cpu *cpu, uint32_t  pos, int32_t offset)
12406 {
12407   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12408
12409   if (aarch64_get_reg_u64 (cpu, rt, NO_SP) & (1 << pos))
12410     aarch64_set_next_PC_by_offset (cpu, offset);
12411 }
12412
12413 /* branch on register bit test zero -- one size fits all.  */
12414 static void
12415 tbz (sim_cpu *cpu, uint32_t  pos, int32_t offset)
12416 {
12417   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12418
12419   if (!(aarch64_get_reg_u64 (cpu, rt, NO_SP) & (1 << pos)))
12420     aarch64_set_next_PC_by_offset (cpu, offset);
12421 }
12422
12423 static void
12424 dexCompareBranchImmediate (sim_cpu *cpu)
12425 {
12426   /* instr[30,25] = 01 1010
12427      instr[31]    = size : 0 ==> 32, 1 ==> 64
12428      instr[24]    = op : 0 ==> CBZ, 1 ==> CBNZ
12429      instr[23,5]  = simm19 branch offset counted in words
12430      instr[4,0]   = rt  */
12431
12432   uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
12433   uint32_t op   = uimm (aarch64_get_instr (cpu), 24, 24);
12434   int32_t offset = simm32 (aarch64_get_instr (cpu), 23, 5) << 2;
12435
12436   if (size == 0)
12437     {
12438       if (op == 0)
12439         cbz32 (cpu, offset);
12440       else
12441         cbnz32 (cpu, offset);
12442     }
12443   else
12444     {
12445       if (op == 0)
12446         cbz (cpu, offset);
12447       else
12448         cbnz (cpu, offset);
12449     }
12450 }
12451
12452 static void
12453 dexTestBranchImmediate (sim_cpu *cpu)
12454 {
12455   /* instr[31]    = b5 : bit 5 of test bit idx
12456      instr[30,25] = 01 1011
12457      instr[24]    = op : 0 ==> TBZ, 1 == TBNZ
12458      instr[23,19] = b40 : bits 4 to 0 of test bit idx
12459      instr[18,5]  = simm14 : signed offset counted in words
12460      instr[4,0]   = uimm5  */
12461
12462   uint32_t pos = ((uimm (aarch64_get_instr (cpu), 31, 31) << 4)
12463                   | uimm (aarch64_get_instr (cpu), 23,19));
12464   int32_t offset = simm32 (aarch64_get_instr (cpu), 18, 5) << 2;
12465
12466   NYI_assert (30, 25, 0x1b);
12467
12468   if (uimm (aarch64_get_instr (cpu), 24, 24) == 0)
12469     tbz (cpu, pos, offset);
12470   else
12471     tbnz (cpu, pos, offset);
12472 }
12473
12474 static void
12475 dexCondBranchImmediate (sim_cpu *cpu)
12476 {
12477   /* instr[31,25] = 010 1010
12478      instr[24]    = op1; op => 00 ==> B.cond
12479      instr[23,5]  = simm19 : signed offset counted in words
12480      instr[4]     = op0
12481      instr[3,0]   = cond  */
12482
12483   int32_t offset;
12484   CondCode cc;
12485   uint32_t op = ((uimm (aarch64_get_instr (cpu), 24, 24) << 1)
12486                  | uimm (aarch64_get_instr (cpu), 4, 4));
12487
12488   NYI_assert (31, 25, 0x2a);
12489
12490   if (op != 0)
12491     HALT_UNALLOC;
12492
12493   offset = simm32 (aarch64_get_instr (cpu), 23, 5) << 2;
12494   cc = condcode (aarch64_get_instr (cpu), 0);
12495
12496   bcc (cpu, offset, cc);
12497 }
12498
12499 static void
12500 dexBranchRegister (sim_cpu *cpu)
12501 {
12502   /* instr[31,25] = 110 1011
12503      instr[24,21] = op : 0 ==> BR, 1 => BLR, 2 => RET, 3 => ERET, 4 => DRPS
12504      instr[20,16] = op2 : must be 11111
12505      instr[15,10] = op3 : must be 000000
12506      instr[4,0]   = op2 : must be 11111.  */
12507
12508   uint32_t op = uimm (aarch64_get_instr (cpu), 24, 21);
12509   uint32_t op2 = uimm (aarch64_get_instr (cpu), 20, 16);
12510   uint32_t op3 = uimm (aarch64_get_instr (cpu), 15, 10);
12511   uint32_t op4 = uimm (aarch64_get_instr (cpu), 4, 0);
12512
12513   NYI_assert (31, 25, 0x6b);
12514
12515   if (op2 != 0x1F || op3 != 0 || op4 != 0)
12516     HALT_UNALLOC;
12517
12518   if (op == 0)
12519     br (cpu);
12520
12521   else if (op == 1)
12522     blr (cpu);
12523
12524   else if (op == 2)
12525     ret (cpu);
12526
12527   else
12528     {
12529       /* ERET and DRPS accept 0b11111 for rn = aarch64_get_instr (cpu)[4,0].  */
12530       /* anything else is unallocated.  */
12531       uint32_t rn = greg (aarch64_get_instr (cpu), 0);
12532
12533       if (rn != 0x1f)
12534         HALT_UNALLOC;
12535
12536       if (op == 4 || op == 5)
12537         HALT_NYI;
12538
12539       HALT_UNALLOC;
12540     }
12541 }
12542
12543 /* FIXME: We should get the Angel SWI values from ../../libgloss/aarch64/svc.h
12544    but this may not be available.  So instead we define the values we need
12545    here.  */
12546 #define AngelSVC_Reason_Open            0x01
12547 #define AngelSVC_Reason_Close           0x02
12548 #define AngelSVC_Reason_Write           0x05
12549 #define AngelSVC_Reason_Read            0x06
12550 #define AngelSVC_Reason_IsTTY           0x09
12551 #define AngelSVC_Reason_Seek            0x0A
12552 #define AngelSVC_Reason_FLen            0x0C
12553 #define AngelSVC_Reason_Remove          0x0E
12554 #define AngelSVC_Reason_Rename          0x0F
12555 #define AngelSVC_Reason_Clock           0x10
12556 #define AngelSVC_Reason_Time            0x11
12557 #define AngelSVC_Reason_System          0x12
12558 #define AngelSVC_Reason_Errno           0x13
12559 #define AngelSVC_Reason_GetCmdLine      0x15
12560 #define AngelSVC_Reason_HeapInfo        0x16
12561 #define AngelSVC_Reason_ReportException 0x18
12562 #define AngelSVC_Reason_Elapsed         0x30
12563
12564
12565 static void
12566 handle_halt (sim_cpu *cpu, uint32_t val)
12567 {
12568   uint64_t result = 0;
12569
12570   if (val != 0xf000)
12571     {
12572       TRACE_SYSCALL (cpu, " HLT [0x%x]", val);
12573       sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12574                        sim_stopped, SIM_SIGTRAP);
12575     }
12576
12577   /* We have encountered an Angel SVC call.  See if we can process it.  */
12578   switch (aarch64_get_reg_u32 (cpu, 0, NO_SP))
12579     {
12580     case AngelSVC_Reason_HeapInfo:
12581       {
12582         /* Get the values.  */
12583         uint64_t stack_top = aarch64_get_stack_start (cpu);
12584         uint64_t heap_base = aarch64_get_heap_start (cpu);
12585
12586         /* Get the pointer  */
12587         uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12588         ptr = aarch64_get_mem_u64 (cpu, ptr);
12589
12590         /* Fill in the memory block.  */
12591         /* Start addr of heap.  */
12592         aarch64_set_mem_u64 (cpu, ptr +  0, heap_base);
12593         /* End addr of heap.  */
12594         aarch64_set_mem_u64 (cpu, ptr +  8, stack_top);
12595         /* Lowest stack addr.  */
12596         aarch64_set_mem_u64 (cpu, ptr + 16, heap_base);
12597         /* Initial stack addr.  */
12598         aarch64_set_mem_u64 (cpu, ptr + 24, stack_top);
12599
12600         TRACE_SYSCALL (cpu, " AngelSVC: Get Heap Info");
12601       }
12602       break;
12603
12604     case AngelSVC_Reason_Open:
12605       {
12606         /* Get the pointer  */
12607         /* uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);.  */
12608         /* FIXME: For now we just assume that we will only be asked
12609            to open the standard file descriptors.  */
12610         static int fd = 0;
12611         result = fd ++;
12612
12613         TRACE_SYSCALL (cpu, " AngelSVC: Open file %d", fd - 1);
12614       }
12615       break;
12616
12617     case AngelSVC_Reason_Close:
12618       {
12619         uint64_t fh = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12620         TRACE_SYSCALL (cpu, " AngelSVC: Close file %d", (int) fh);
12621         result = 0;
12622       }
12623       break;
12624
12625     case AngelSVC_Reason_Errno:
12626       result = 0;
12627       TRACE_SYSCALL (cpu, " AngelSVC: Get Errno");
12628       break;
12629
12630     case AngelSVC_Reason_Clock:
12631       result =
12632 #ifdef CLOCKS_PER_SEC
12633         (CLOCKS_PER_SEC >= 100)
12634         ? (clock () / (CLOCKS_PER_SEC / 100))
12635         : ((clock () * 100) / CLOCKS_PER_SEC)
12636 #else
12637         /* Presume unix... clock() returns microseconds.  */
12638         (clock () / 10000)
12639 #endif
12640         ;
12641         TRACE_SYSCALL (cpu, " AngelSVC: Get Clock");
12642       break;
12643
12644     case AngelSVC_Reason_GetCmdLine:
12645       {
12646         /* Get the pointer  */
12647         uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12648         ptr = aarch64_get_mem_u64 (cpu, ptr);
12649
12650         /* FIXME: No command line for now.  */
12651         aarch64_set_mem_u64 (cpu, ptr, 0);
12652         TRACE_SYSCALL (cpu, " AngelSVC: Get Command Line");
12653       }
12654       break;
12655
12656     case AngelSVC_Reason_IsTTY:
12657       result = 1;
12658         TRACE_SYSCALL (cpu, " AngelSVC: IsTTY ?");
12659       break;
12660
12661     case AngelSVC_Reason_Write:
12662       {
12663         /* Get the pointer  */
12664         uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12665         /* Get the write control block.  */
12666         uint64_t fd  = aarch64_get_mem_u64 (cpu, ptr);
12667         uint64_t buf = aarch64_get_mem_u64 (cpu, ptr + 8);
12668         uint64_t len = aarch64_get_mem_u64 (cpu, ptr + 16);
12669
12670         TRACE_SYSCALL (cpu, "write of %" PRIx64 " bytes from %"
12671                        PRIx64 " on descriptor %" PRIx64,
12672                        len, buf, fd);
12673
12674         if (len > 1280)
12675           {
12676             TRACE_SYSCALL (cpu,
12677                            " AngelSVC: Write: Suspiciously long write: %ld",
12678                            (long) len);
12679             sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12680                              sim_stopped, SIM_SIGBUS);
12681           }
12682         else if (fd == 1)
12683           {
12684             printf ("%.*s", (int) len, aarch64_get_mem_ptr (cpu, buf));
12685             if (disas)
12686               /* So that the output stays in sync with trace output.  */
12687               fflush (stdout);
12688           }
12689         else if (fd == 2)
12690           {
12691             TRACE (cpu, 0, "\n");
12692             sim_io_eprintf (CPU_STATE (cpu), "%.*s",
12693                             (int) len, aarch64_get_mem_ptr (cpu, buf));
12694             TRACE (cpu, 0, "\n");
12695           }
12696         else
12697           {
12698             TRACE_SYSCALL (cpu,
12699                            " AngelSVC: Write: Unexpected file handle: %d",
12700                            (int) fd);
12701             sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12702                              sim_stopped, SIM_SIGABRT);
12703           }
12704       }
12705       break;
12706
12707     case AngelSVC_Reason_ReportException:
12708       {
12709         /* Get the pointer  */
12710         uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12711         /*ptr = aarch64_get_mem_u64 (cpu, ptr);.  */
12712         uint64_t type = aarch64_get_mem_u64 (cpu, ptr);
12713         uint64_t state = aarch64_get_mem_u64 (cpu, ptr + 8);
12714
12715         TRACE_SYSCALL (cpu,
12716                        "Angel Exception: type 0x%" PRIx64 " state %" PRIx64,
12717                        type, state);
12718
12719         if (type == 0x20026)
12720           sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12721                            sim_exited, state);
12722         else
12723           sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12724                            sim_stopped, SIM_SIGINT);
12725       }
12726       break;
12727
12728     case AngelSVC_Reason_Read:
12729     case AngelSVC_Reason_FLen:
12730     case AngelSVC_Reason_Seek:
12731     case AngelSVC_Reason_Remove:
12732     case AngelSVC_Reason_Time:
12733     case AngelSVC_Reason_System:
12734     case AngelSVC_Reason_Rename:
12735     case AngelSVC_Reason_Elapsed:
12736     default:
12737       TRACE_SYSCALL (cpu, " HLT [Unknown angel %x]",
12738                      aarch64_get_reg_u32 (cpu, 0, NO_SP));
12739       sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12740                        sim_stopped, SIM_SIGTRAP);
12741     }
12742
12743   aarch64_set_reg_u64 (cpu, 0, NO_SP, result);
12744 }
12745
12746 static void
12747 dexExcpnGen (sim_cpu *cpu)
12748 {
12749   /* instr[31:24] = 11010100
12750      instr[23,21] = opc : 000 ==> GEN EXCPN, 001 ==> BRK
12751                           010 ==> HLT,       101 ==> DBG GEN EXCPN
12752      instr[20,5]  = imm16
12753      instr[4,2]   = opc2 000 ==> OK, ow ==> UNALLOC
12754      instr[1,0]   = LL : discriminates opc  */
12755
12756   uint32_t opc = uimm (aarch64_get_instr (cpu), 23, 21);
12757   uint32_t imm16 = uimm (aarch64_get_instr (cpu), 20, 5);
12758   uint32_t opc2 = uimm (aarch64_get_instr (cpu), 4, 2);
12759   uint32_t LL;
12760
12761   NYI_assert (31, 24, 0xd4);
12762
12763   if (opc2 != 0)
12764     HALT_UNALLOC;
12765
12766   LL = uimm (aarch64_get_instr (cpu), 1, 0);
12767
12768   /* We only implement HLT and BRK for now.  */
12769   if (opc == 1 && LL == 0)
12770     {
12771       TRACE_EVENTS (cpu, " BRK [0x%x]", imm16);
12772       sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12773                        sim_exited, aarch64_get_reg_s32 (cpu, R0, SP_OK));
12774     }
12775
12776   if (opc == 2 && LL == 0)
12777     handle_halt (cpu, imm16);
12778
12779   else if (opc == 0 || opc == 5)
12780     HALT_NYI;
12781
12782   else
12783     HALT_UNALLOC;
12784 }
12785
12786 static void
12787 dexSystem (sim_cpu *cpu)
12788 {
12789   /* instr[31:22] = 1101 01010 0
12790      instr[21]    = L
12791      instr[20,19] = op0
12792      instr[18,16] = op1
12793      instr[15,12] = CRn
12794      instr[11,8]  = CRm
12795      instr[7,5]   = op2
12796      instr[4,0]   = uimm5  */
12797
12798   /* We are interested in HINT, DSB, DMB and ISB
12799
12800      Hint #0 encodes NOOP (this is the only hint we care about)
12801      L == 0, op0 == 0, op1 = 011, CRn = 0010, Rt = 11111,
12802      CRm op2  != 0000 000 OR CRm op2 == 0000 000 || CRm op > 0000 101
12803
12804      DSB, DMB, ISB are data store barrier, data memory barrier and
12805      instruction store barrier, respectively, where
12806
12807      L == 0, op0 == 0, op1 = 011, CRn = 0011, Rt = 11111,
12808      op2 : DSB ==> 100, DMB ==> 101, ISB ==> 110
12809      CRm<3:2> ==> domain, CRm<1:0> ==> types,
12810      domain : 00 ==> OuterShareable, 01 ==> Nonshareable,
12811               10 ==> InerShareable, 11 ==> FullSystem
12812      types :  01 ==> Reads, 10 ==> Writes,
12813               11 ==> All, 00 ==> All (domain == FullSystem).  */
12814
12815   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12816   uint32_t l_op0_op1_crn = uimm (aarch64_get_instr (cpu), 21, 12);
12817
12818   NYI_assert (31, 22, 0x354);
12819
12820   switch (l_op0_op1_crn)
12821     {
12822     case 0x032:
12823       if (rt == 0x1F)
12824         {
12825           /* NOP has CRm != 0000 OR.  */
12826           /*         (CRm == 0000 AND (op2 == 000 OR op2 > 101)).  */
12827           uint32_t crm = uimm (aarch64_get_instr (cpu), 11, 8);
12828           uint32_t op2 = uimm (aarch64_get_instr (cpu), 7, 5);
12829
12830           if (crm != 0 || (op2 == 0 || op2 > 5))
12831             {
12832               /* Actually call nop method so we can reimplement it later.  */
12833               nop (cpu);
12834               return;
12835             }
12836         }
12837       HALT_NYI;
12838
12839     case 0x033:
12840       {
12841         uint32_t op2 =  uimm (aarch64_get_instr (cpu), 7, 5);
12842
12843         switch (op2)
12844           {
12845           case 2:
12846             HALT_NYI;
12847
12848           case 4: dsb (cpu); return;
12849           case 5: dmb (cpu); return;
12850           case 6: isb (cpu); return;
12851           case 7:
12852           default: HALT_UNALLOC;
12853         }
12854       }
12855
12856     case 0x3B0:
12857       /* MRS Wt, sys-reg.  */
12858       /* FIXME: Ignore for now.  */
12859       return;
12860
12861     case 0x3B4:
12862     case 0x3BD:
12863       /* MRS Xt, sys-reg.  */
12864       /* FIXME: Ignore for now.  */
12865       return;
12866
12867     case 0x0B7:
12868       /* DC <type>, x<n>.  */
12869       /* FIXME: Ignore for now.  */
12870       return;
12871
12872     default:
12873       if (uimm (aarch64_get_instr (cpu), 21, 20) == 0x1)
12874         /* MSR <sys-reg>, <Xreg>.  */
12875         return;
12876       HALT_NYI;
12877     }
12878 }
12879
12880 static void
12881 dexBr (sim_cpu *cpu)
12882 {
12883   /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
12884      assert  group == GROUP_BREXSYS_1010 || group == GROUP_BREXSYS_1011
12885      bits [31,29] of a BrExSys are the secondary dispatch vector.  */
12886   uint32_t group2 = dispatchBrExSys (aarch64_get_instr (cpu));
12887
12888   switch (group2)
12889     {
12890     case BR_IMM_000:
12891       return dexBranchImmediate (cpu);
12892
12893     case BR_IMMCMP_001:
12894       /* Compare has bit 25 clear while test has it set.  */
12895       if (!uimm (aarch64_get_instr (cpu), 25, 25))
12896         dexCompareBranchImmediate (cpu);
12897       else
12898         dexTestBranchImmediate (cpu);
12899       return;
12900
12901     case BR_IMMCOND_010:
12902       /* This is a conditional branch if bit 25 is clear otherwise
12903          unallocated.  */
12904       if (!uimm (aarch64_get_instr (cpu), 25, 25))
12905         dexCondBranchImmediate (cpu);
12906       else
12907         HALT_UNALLOC;
12908       return;
12909
12910     case BR_UNALLOC_011:
12911       HALT_UNALLOC;
12912
12913     case BR_IMM_100:
12914       dexBranchImmediate (cpu);
12915       return;
12916
12917     case BR_IMMCMP_101:
12918       /* Compare has bit 25 clear while test has it set.  */
12919       if (!uimm (aarch64_get_instr (cpu), 25, 25))
12920         dexCompareBranchImmediate (cpu);
12921       else
12922         dexTestBranchImmediate (cpu);
12923       return;
12924
12925     case BR_REG_110:
12926       /* Unconditional branch reg has bit 25 set.  */
12927       if (uimm (aarch64_get_instr (cpu), 25, 25))
12928         dexBranchRegister (cpu);
12929
12930       /* This includes both Excpn Gen, System and unalloc operations.
12931          We need to decode the Excpn Gen operation BRK so we can plant
12932          debugger entry points.
12933          Excpn Gen operations have aarch64_get_instr (cpu)[24] = 0.
12934          we need to decode at least one of the System operations NOP
12935          which is an alias for HINT #0.
12936          System operations have aarch64_get_instr (cpu)[24,22] = 100.  */
12937       else if (uimm (aarch64_get_instr (cpu), 24, 24) == 0)
12938         dexExcpnGen (cpu);
12939
12940       else if (uimm (aarch64_get_instr (cpu), 24, 22) == 4)
12941         dexSystem (cpu);
12942
12943       else
12944         HALT_UNALLOC;
12945
12946       return;
12947
12948     case BR_UNALLOC_111:
12949       HALT_UNALLOC;
12950
12951     default:
12952       /* Should never reach here.  */
12953       HALT_NYI;
12954     }
12955 }
12956
12957 static void
12958 aarch64_decode_and_execute (sim_cpu *cpu, uint64_t pc)
12959 {
12960   /* We need to check if gdb wants an in here.  */
12961   /* checkBreak (cpu);.  */
12962
12963   uint64_t group = dispatchGroup (aarch64_get_instr (cpu));
12964
12965   switch (group)
12966     {
12967     case GROUP_PSEUDO_0000:   dexPseudo (cpu); break;
12968     case GROUP_LDST_0100:     dexLdSt (cpu); break;
12969     case GROUP_DPREG_0101:    dexDPReg (cpu); break;
12970     case GROUP_LDST_0110:     dexLdSt (cpu); break;
12971     case GROUP_ADVSIMD_0111:  dexAdvSIMD0 (cpu); break;
12972     case GROUP_DPIMM_1000:    dexDPImm (cpu); break;
12973     case GROUP_DPIMM_1001:    dexDPImm (cpu); break;
12974     case GROUP_BREXSYS_1010:  dexBr (cpu); break;
12975     case GROUP_BREXSYS_1011:  dexBr (cpu); break;
12976     case GROUP_LDST_1100:     dexLdSt (cpu); break;
12977     case GROUP_DPREG_1101:    dexDPReg (cpu); break;
12978     case GROUP_LDST_1110:     dexLdSt (cpu); break;
12979     case GROUP_ADVSIMD_1111:  dexAdvSIMD1 (cpu); break;
12980
12981     case GROUP_UNALLOC_0001:
12982     case GROUP_UNALLOC_0010:
12983     case GROUP_UNALLOC_0011:
12984       HALT_UNALLOC;
12985
12986     default:
12987       /* Should never reach here.  */
12988       HALT_NYI;
12989     }
12990 }
12991
12992 static bfd_boolean
12993 aarch64_step (sim_cpu *cpu)
12994 {
12995   uint64_t pc = aarch64_get_PC (cpu);
12996
12997   if (pc == TOP_LEVEL_RETURN_PC)
12998     return FALSE;
12999
13000   aarch64_set_next_PC (cpu, pc + 4);
13001   aarch64_get_instr (cpu) = aarch64_get_mem_u32 (cpu, pc);
13002
13003   if (TRACE_INSN_P (cpu))
13004     {
13005       if (disas)
13006         TRACE_INSN (cpu, " pc = %" PRIx64 " ", pc);
13007       else
13008         TRACE_INSN (cpu, " pc = %" PRIx64 " instr = %x", pc,
13009                     aarch64_get_instr (cpu));
13010     }
13011   else if (disas)
13012     sim_io_eprintf (CPU_STATE (cpu), " %" PRIx64 " ", pc);
13013
13014   if (disas)
13015     aarch64_print_insn (CPU_STATE (cpu), pc);
13016
13017   aarch64_decode_and_execute (cpu, pc);
13018
13019   return TRUE;
13020 }
13021
13022 void
13023 aarch64_run (SIM_DESC sd)
13024 {
13025   sim_cpu *cpu = STATE_CPU (sd, 0);
13026
13027   while (aarch64_step (cpu))
13028     aarch64_update_PC (cpu);
13029
13030   sim_engine_halt (sd, NULL, NULL, aarch64_get_PC (cpu),
13031                    sim_exited, aarch64_get_reg_s32 (cpu, R0, SP_OK));
13032 }
13033
13034 void
13035 aarch64_init (sim_cpu *cpu, uint64_t pc)
13036 {
13037   uint64_t sp = aarch64_get_stack_start (cpu);
13038
13039   /* Install SP, FP and PC and set LR to -20
13040      so we can detect a top-level return.  */
13041   aarch64_set_reg_u64 (cpu, SP, SP_OK, sp);
13042   aarch64_set_reg_u64 (cpu, FP, SP_OK, sp);
13043   aarch64_set_reg_u64 (cpu, LR, SP_OK, TOP_LEVEL_RETURN_PC);
13044   aarch64_set_next_PC (cpu, pc);
13045   aarch64_update_PC (cpu);
13046   aarch64_init_LIT_table ();
13047 }