More AArch64 simulator improvements.
[external/binutils.git] / sim / aarch64 / simulator.c
1 /* simulator.c -- Interface for the AArch64 simulator.
2
3    Copyright (C) 2015-2016 Free Software Foundation, Inc.
4
5    Contributed by Red Hat.
6
7    This file is part of GDB.
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
21
22 #include "config.h"
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <sys/types.h>
27 #include <math.h>
28 #include <time.h>
29 #include <limits.h>
30
31 #include "simulator.h"
32 #include "cpustate.h"
33 #include "memory.h"
34
35 #define NO_SP 0
36 #define SP_OK 1
37
38 #define TST(_flag)   (aarch64_test_CPSR_bit (cpu, _flag))
39 #define IS_SET(_X)   (TST (( _X )) ? 1 : 0)
40 #define IS_CLEAR(_X) (TST (( _X )) ? 0 : 1)
41
42 #define HALT_UNALLOC                                                    \
43   do                                                                    \
44     {                                                                   \
45       TRACE_DISASM (cpu, aarch64_get_PC (cpu));                         \
46       TRACE_INSN (cpu,                                                  \
47                   "Unallocated instruction detected at sim line %d,"    \
48                   " exe addr %" PRIx64,                                 \
49                   __LINE__, aarch64_get_PC (cpu));                      \
50       sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),\
51                        sim_stopped, SIM_SIGILL);                        \
52     }                                                                   \
53   while (0)
54
55 #define HALT_NYI                                                        \
56   do                                                                    \
57     {                                                                   \
58       TRACE_DISASM (cpu, aarch64_get_PC (cpu));                         \
59       TRACE_INSN (cpu,                                                  \
60                   "Unimplemented instruction detected at sim line %d,"  \
61                   " exe addr %" PRIx64,                                 \
62                   __LINE__, aarch64_get_PC (cpu));                      \
63       if (! TRACE_ANY_P (cpu))                                          \
64         {                                                               \
65           fprintf (stderr, "SIM Error: Unimplemented instruction: ");   \
66           trace_disasm (CPU_STATE (cpu), cpu, aarch64_get_PC (cpu));    \
67         }                                                               \
68       sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),\
69                        sim_stopped, SIM_SIGABRT);                       \
70     }                                                                   \
71   while (0)
72
73 #define NYI_assert(HI, LO, EXPECTED)                                    \
74   do                                                                    \
75     {                                                                   \
76       if (uimm (aarch64_get_instr (cpu), (HI), (LO)) != (EXPECTED))     \
77         HALT_NYI;                                                       \
78     }                                                                   \
79   while (0)
80
81 /* Space saver macro.  */
82 #define INSTR(HIGH, LOW) uimm (aarch64_get_instr (cpu), (HIGH), (LOW))
83
84 /* Helper functions used by expandLogicalImmediate.  */
85
86 /* for i = 1, ... N result<i-1> = 1 other bits are zero  */
87 static inline uint64_t
88 ones (int N)
89 {
90   return (N == 64 ? (uint64_t)-1UL : ((1UL << N) - 1));
91 }
92
93 /* result<0> to val<N>  */
94 static inline uint64_t
95 pickbit (uint64_t val, int N)
96 {
97   return pickbits64 (val, N, N);
98 }
99
100 static uint64_t
101 expand_logical_immediate (uint32_t S, uint32_t R, uint32_t N)
102 {
103   uint64_t mask;
104   uint64_t imm;
105   unsigned simd_size;
106
107   /* The immediate value is S+1 bits to 1, left rotated by SIMDsize - R
108      (in other words, right rotated by R), then replicated. */
109   if (N != 0)
110     {
111       simd_size = 64;
112       mask = 0xffffffffffffffffull;
113     }
114   else
115     {
116       switch (S)
117         {
118         case 0x00 ... 0x1f: /* 0xxxxx */ simd_size = 32;           break;
119         case 0x20 ... 0x2f: /* 10xxxx */ simd_size = 16; S &= 0xf; break;
120         case 0x30 ... 0x37: /* 110xxx */ simd_size =  8; S &= 0x7; break;
121         case 0x38 ... 0x3b: /* 1110xx */ simd_size =  4; S &= 0x3; break;
122         case 0x3c ... 0x3d: /* 11110x */ simd_size =  2; S &= 0x1; break;
123         default: return 0;
124         }
125       mask = (1ull << simd_size) - 1;
126       /* Top bits are IGNORED.  */
127       R &= simd_size - 1;
128     }
129
130   /* NOTE: if S = simd_size - 1 we get 0xf..f which is rejected.  */
131   if (S == simd_size - 1)
132     return 0;
133
134   /* S+1 consecutive bits to 1.  */
135   /* NOTE: S can't be 63 due to detection above.  */
136   imm = (1ull << (S + 1)) - 1;
137
138   /* Rotate to the left by simd_size - R.  */
139   if (R != 0)
140     imm = ((imm << (simd_size - R)) & mask) | (imm >> R);
141
142   /* Replicate the value according to SIMD size.  */
143   switch (simd_size)
144     {
145     case  2: imm = (imm <<  2) | imm;
146     case  4: imm = (imm <<  4) | imm;
147     case  8: imm = (imm <<  8) | imm;
148     case 16: imm = (imm << 16) | imm;
149     case 32: imm = (imm << 32) | imm;
150     case 64: break;
151     default: return 0;
152     }
153
154   return imm;
155 }
156
157 /* Instr[22,10] encodes N immr and imms. we want a lookup table
158    for each possible combination i.e. 13 bits worth of int entries.  */
159 #define  LI_TABLE_SIZE  (1 << 13)
160 static uint64_t LITable[LI_TABLE_SIZE];
161
162 void
163 aarch64_init_LIT_table (void)
164 {
165   unsigned index;
166
167   for (index = 0; index < LI_TABLE_SIZE; index++)
168     {
169       uint32_t N    = uimm (index, 12, 12);
170       uint32_t immr = uimm (index, 11, 6);
171       uint32_t imms = uimm (index, 5, 0);
172
173       LITable [index] = expand_logical_immediate (imms, immr, N);
174     }
175 }
176
177 static void
178 dexNotify (sim_cpu *cpu)
179 {
180   /* instr[14,0] == type : 0 ==> method entry, 1 ==> method reentry
181                            2 ==> exit Java, 3 ==> start next bytecode.  */
182   uint32_t type = uimm (aarch64_get_instr (cpu), 14, 0);
183
184   TRACE_EVENTS (cpu, "Notify Insn encountered, type = 0x%x", type);
185
186   switch (type)
187     {
188     case 0:
189       /* aarch64_notifyMethodEntry (aarch64_get_reg_u64 (cpu, R23, 0),
190          aarch64_get_reg_u64 (cpu, R22, 0));  */
191       break;
192     case 1:
193       /* aarch64_notifyMethodReentry (aarch64_get_reg_u64 (cpu, R23, 0),
194          aarch64_get_reg_u64 (cpu, R22, 0));  */
195       break;
196     case 2:
197       /* aarch64_notifyMethodExit ();  */
198       break;
199     case 3:
200       /* aarch64_notifyBCStart (aarch64_get_reg_u64 (cpu, R23, 0),
201          aarch64_get_reg_u64 (cpu, R22, 0));  */
202       break;
203     }
204 }
205
206 /* secondary decode within top level groups  */
207
208 static void
209 dexPseudo (sim_cpu *cpu)
210 {
211   /* assert instr[28,27] = 00
212
213      We provide 2 pseudo instructions:
214
215      HALT stops execution of the simulator causing an immediate
216      return to the x86 code which entered it.
217
218      CALLOUT initiates recursive entry into x86 code.  A register
219      argument holds the address of the x86 routine.  Immediate
220      values in the instruction identify the number of general
221      purpose and floating point register arguments to be passed
222      and the type of any value to be returned.  */
223
224   uint32_t PSEUDO_HALT      =  0xE0000000U;
225   uint32_t PSEUDO_CALLOUT   =  0x00018000U;
226   uint32_t PSEUDO_CALLOUTR  =  0x00018001U;
227   uint32_t PSEUDO_NOTIFY    =  0x00014000U;
228   uint32_t dispatch;
229
230   if (aarch64_get_instr (cpu) == PSEUDO_HALT)
231     {
232       TRACE_EVENTS (cpu, " Pseudo Halt Instruction");
233       sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
234                        sim_stopped, SIM_SIGTRAP);
235     }
236
237   dispatch = uimm (aarch64_get_instr (cpu), 31, 15);
238
239   /* We do not handle callouts at the moment.  */
240   if (dispatch == PSEUDO_CALLOUT || dispatch == PSEUDO_CALLOUTR)
241     {
242       TRACE_EVENTS (cpu, " Callout");
243       sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
244                        sim_stopped, SIM_SIGABRT);
245     }
246
247   else if (dispatch == PSEUDO_NOTIFY)
248     dexNotify (cpu);
249
250   else
251     HALT_UNALLOC;
252 }
253
254 /* Load-store single register (unscaled offset)
255    These instructions employ a base register plus an unscaled signed
256    9 bit offset.
257
258    N.B. the base register (source) can be Xn or SP. all other
259    registers may not be SP.  */
260
261 /* 32 bit load 32 bit unscaled signed 9 bit.  */
262 static void
263 ldur32 (sim_cpu *cpu, int32_t offset)
264 {
265   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
266   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
267
268   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32
269                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
270                         + offset));
271 }
272
273 /* 64 bit load 64 bit unscaled signed 9 bit.  */
274 static void
275 ldur64 (sim_cpu *cpu, int32_t offset)
276 {
277   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
278   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
279
280   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64
281                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
282                         + offset));
283 }
284
285 /* 32 bit load zero-extended byte unscaled signed 9 bit.  */
286 static void
287 ldurb32 (sim_cpu *cpu, int32_t offset)
288 {
289   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
290   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
291
292   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u8
293                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
294                         + offset));
295 }
296
297 /* 32 bit load sign-extended byte unscaled signed 9 bit.  */
298 static void
299 ldursb32 (sim_cpu *cpu, int32_t offset)
300 {
301   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
302   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
303
304   aarch64_set_reg_u64 (cpu, rt, NO_SP, (uint32_t) aarch64_get_mem_s8
305                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
306                         + offset));
307 }
308
309 /* 64 bit load sign-extended byte unscaled signed 9 bit.  */
310 static void
311 ldursb64 (sim_cpu *cpu, int32_t offset)
312 {
313   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
314   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
315
316   aarch64_set_reg_s64 (cpu, rt, NO_SP, aarch64_get_mem_s8
317                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
318                         + offset));
319 }
320
321 /* 32 bit load zero-extended short unscaled signed 9 bit  */
322 static void
323 ldurh32 (sim_cpu *cpu, int32_t offset)
324 {
325   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
326   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
327
328   aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_mem_u16
329                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
330                         + offset));
331 }
332
333 /* 32 bit load sign-extended short unscaled signed 9 bit  */
334 static void
335 ldursh32 (sim_cpu *cpu, int32_t offset)
336 {
337   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
338   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
339
340   aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) aarch64_get_mem_s16
341                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
342                         + offset));
343 }
344
345 /* 64 bit load sign-extended short unscaled signed 9 bit  */
346 static void
347 ldursh64 (sim_cpu *cpu, int32_t offset)
348 {
349   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
350   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
351
352   aarch64_set_reg_s64 (cpu, rt, NO_SP, aarch64_get_mem_s16
353                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
354                         + offset));
355 }
356
357 /* 64 bit load sign-extended word unscaled signed 9 bit  */
358 static void
359 ldursw (sim_cpu *cpu, int32_t offset)
360 {
361   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
362   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
363
364   aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) aarch64_get_mem_s32
365                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
366                         + offset));
367 }
368
369 /* N.B. with stores the value in source is written to the address
370    identified by source2 modified by offset.  */
371
372 /* 32 bit store 32 bit unscaled signed 9 bit.  */
373 static void
374 stur32 (sim_cpu *cpu, int32_t offset)
375 {
376   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
377   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
378
379   aarch64_set_mem_u32 (cpu,
380                        aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
381                        aarch64_get_reg_u32 (cpu, rd, NO_SP));
382 }
383
384 /* 64 bit store 64 bit unscaled signed 9 bit  */
385 static void
386 stur64 (sim_cpu *cpu, int32_t offset)
387 {
388   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
389   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
390
391   aarch64_set_mem_u64 (cpu,
392                        aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
393                        aarch64_get_reg_u64 (cpu, rd, NO_SP));
394 }
395
396 /* 32 bit store byte unscaled signed 9 bit  */
397 static void
398 sturb (sim_cpu *cpu, int32_t offset)
399 {
400   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
401   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
402
403   aarch64_set_mem_u8 (cpu,
404                       aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
405                       aarch64_get_reg_u8 (cpu, rd, NO_SP));
406 }
407
408 /* 32 bit store short unscaled signed 9 bit  */
409 static void
410 sturh (sim_cpu *cpu, int32_t offset)
411 {
412   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
413   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
414
415   aarch64_set_mem_u16 (cpu,
416                        aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
417                        aarch64_get_reg_u16 (cpu, rd, NO_SP));
418 }
419
420 /* Load single register pc-relative label
421    Offset is a signed 19 bit immediate count in words
422    rt may not be SP.  */
423
424 /* 32 bit pc-relative load  */
425 static void
426 ldr32_pcrel (sim_cpu *cpu, int32_t offset)
427 {
428   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
429
430   aarch64_set_reg_u64 (cpu, rd, NO_SP,
431                        aarch64_get_mem_u32
432                        (cpu, aarch64_get_PC (cpu) + offset * 4));
433 }
434
435 /* 64 bit pc-relative load  */
436 static void
437 ldr_pcrel (sim_cpu *cpu, int32_t offset)
438 {
439   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
440
441   aarch64_set_reg_u64 (cpu, rd, NO_SP,
442                        aarch64_get_mem_u64
443                        (cpu, aarch64_get_PC (cpu) + offset * 4));
444 }
445
446 /* sign extended 32 bit pc-relative load  */
447 static void
448 ldrsw_pcrel (sim_cpu *cpu, int32_t offset)
449 {
450   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
451
452   aarch64_set_reg_u64 (cpu, rd, NO_SP,
453                        aarch64_get_mem_s32
454                        (cpu, aarch64_get_PC (cpu) + offset * 4));
455 }
456
457 /* float pc-relative load  */
458 static void
459 fldrs_pcrel (sim_cpu *cpu, int32_t offset)
460 {
461   unsigned int rd = uimm (aarch64_get_instr (cpu), 4, 0);
462
463   aarch64_set_vec_u32 (cpu, rd, 0,
464                        aarch64_get_mem_u32
465                        (cpu, aarch64_get_PC (cpu) + offset * 4));
466 }
467
468 /* double pc-relative load  */
469 static void
470 fldrd_pcrel (sim_cpu *cpu, int32_t offset)
471 {
472   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
473
474   aarch64_set_vec_u64 (cpu, st, 0,
475                        aarch64_get_mem_u64
476                        (cpu, aarch64_get_PC (cpu) + offset * 4));
477 }
478
479 /* long double pc-relative load.  */
480 static void
481 fldrq_pcrel (sim_cpu *cpu, int32_t offset)
482 {
483   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
484   uint64_t addr = aarch64_get_PC (cpu) + offset * 4;
485   FRegister a;
486
487   aarch64_get_mem_long_double (cpu, addr, & a);
488   aarch64_set_FP_long_double (cpu, st, a);
489 }
490
491 /* This can be used to scale an offset by applying
492    the requisite shift. the second argument is either
493    16, 32 or 64.  */
494
495 #define SCALE(_offset, _elementSize) \
496     ((_offset) << ScaleShift ## _elementSize)
497
498 /* This can be used to optionally scale a register derived offset
499    by applying the requisite shift as indicated by the Scaling
500    argument. the second argument is either Byte, Short, Word
501    or Long. The third argument is either Scaled or Unscaled.
502    N.B. when _Scaling is Scaled the shift gets ANDed with
503    all 1s while when it is Unscaled it gets ANDed with 0.  */
504
505 #define OPT_SCALE(_offset, _elementType, _Scaling) \
506   ((_offset) << (_Scaling ? ScaleShift ## _elementType : 0))
507
508 /* This can be used to zero or sign extend a 32 bit register derived
509    value to a 64 bit value.  the first argument must be the value as
510    a uint32_t and the second must be either UXTW or SXTW. The result
511    is returned as an int64_t.  */
512
513 static inline int64_t
514 extend (uint32_t value, Extension extension)
515 {
516   union
517   {
518     uint32_t u;
519     int32_t   n;
520   } x;
521
522   /* A branchless variant of this ought to be possible.  */
523   if (extension == UXTW || extension == NoExtension)
524     return value;
525
526   x.u = value;
527   return x.n;
528 }
529
530 /* Scalar Floating Point
531
532    FP load/store single register (4 addressing modes)
533
534    N.B. the base register (source) can be the stack pointer.
535    The secondary source register (source2) can only be an Xn register.  */
536
537 /* Load 32 bit unscaled signed 9 bit with pre- or post-writeback.  */
538 static void
539 fldrs_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
540 {
541   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
542   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
543   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
544
545   if (wb != Post)
546     address += offset;
547
548   aarch64_set_vec_u32 (cpu, st, 0, aarch64_get_mem_u32 (cpu, address));
549   if (wb == Post)
550     address += offset;
551
552   if (wb != NoWriteBack)
553     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
554 }
555
556 /* Load 8 bit with unsigned 12 bit offset.  */
557 static void
558 fldrb_abs (sim_cpu *cpu, uint32_t offset)
559 {
560   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
561   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
562   uint64_t addr = aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset;
563
564   aarch64_set_vec_u8 (cpu, rd, 0, aarch64_get_mem_u32 (cpu, addr));
565 }
566
567 /* Load 16 bit scaled unsigned 12 bit.  */
568 static void
569 fldrh_abs (sim_cpu *cpu, uint32_t offset)
570 {
571   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
572   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
573   uint64_t addr = aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 16);
574
575   aarch64_set_vec_u16 (cpu, rd, 0, aarch64_get_mem_u16 (cpu, addr));
576 }
577
578 /* Load 32 bit scaled unsigned 12 bit.  */
579 static void
580 fldrs_abs (sim_cpu *cpu, uint32_t offset)
581 {
582   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
583   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
584   uint64_t addr = aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 32);
585
586   aarch64_set_vec_u32 (cpu, rd, 0, aarch64_get_mem_u32 (cpu, addr));
587 }
588
589 /* Load 64 bit scaled unsigned 12 bit.  */
590 static void
591 fldrd_abs (sim_cpu *cpu, uint32_t offset)
592 {
593   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
594   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
595   uint64_t addr = aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 64);
596
597   aarch64_set_vec_u64 (cpu, rd, 0, aarch64_get_mem_u64 (cpu, addr));
598 }
599
600 /* Load 128 bit scaled unsigned 12 bit.  */
601 static void
602 fldrq_abs (sim_cpu *cpu, uint32_t offset)
603 {
604   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
605   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
606   uint64_t addr = aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 128);
607
608   aarch64_set_vec_u64 (cpu, rd, 0, aarch64_get_mem_u64 (cpu, addr));
609   aarch64_set_vec_u64 (cpu, rd, 1, aarch64_get_mem_u64 (cpu, addr + 8));
610 }
611
612 /* Load 32 bit scaled or unscaled zero- or sign-extended
613    32-bit register offset.  */
614 static void
615 fldrs_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
616 {
617   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
618   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
619   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
620   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
621   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
622   uint64_t displacement = OPT_SCALE (extended, 32, scaling);
623
624   aarch64_set_vec_u32 (cpu, st, 0, aarch64_get_mem_u32
625                        (cpu, address + displacement));
626 }
627
628 /* Load 64 bit unscaled signed 9 bit with pre- or post-writeback.  */
629 static void
630 fldrd_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
631 {
632   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
633   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
634   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
635
636   if (wb != Post)
637     address += offset;
638
639   aarch64_set_vec_u64 (cpu, st, 0, aarch64_get_mem_u64 (cpu, address));
640
641   if (wb == Post)
642     address += offset;
643
644   if (wb != NoWriteBack)
645     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
646 }
647
648 /* Load 64 bit scaled or unscaled zero- or sign-extended 32-bit register offset.  */
649 static void
650 fldrd_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
651 {
652   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
653   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
654   uint64_t displacement = OPT_SCALE (extended, 64, scaling);
655
656   fldrd_wb (cpu, displacement, NoWriteBack);
657 }
658
659 /* Load 128 bit unscaled signed 9 bit with pre- or post-writeback.  */
660 static void
661 fldrq_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
662 {
663   FRegister a;
664   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
665   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
666   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
667
668   if (wb != Post)
669     address += offset;
670
671   aarch64_get_mem_long_double (cpu, address, & a);
672   aarch64_set_FP_long_double (cpu, st, a);
673
674   if (wb == Post)
675     address += offset;
676
677   if (wb != NoWriteBack)
678     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
679 }
680
681 /* Load 128 bit scaled or unscaled zero- or sign-extended 32-bit register offset  */
682 static void
683 fldrq_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
684 {
685   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
686   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
687   uint64_t displacement = OPT_SCALE (extended, 128, scaling);
688
689   fldrq_wb (cpu, displacement, NoWriteBack);
690 }
691
692 /* Memory Access
693
694    load-store single register
695    There are four addressing modes available here which all employ a
696    64 bit source (base) register.
697
698    N.B. the base register (source) can be the stack pointer.
699    The secondary source register (source2)can only be an Xn register.
700
701    Scaled, 12-bit, unsigned immediate offset, without pre- and
702    post-index options.
703    Unscaled, 9-bit, signed immediate offset with pre- or post-index
704    writeback.
705    scaled or unscaled 64-bit register offset.
706    scaled or unscaled 32-bit extended register offset.
707
708    All offsets are assumed to be raw from the decode i.e. the
709    simulator is expected to adjust scaled offsets based on the
710    accessed data size with register or extended register offset
711    versions the same applies except that in the latter case the
712    operation may also require a sign extend.
713
714    A separate method is provided for each possible addressing mode.  */
715
716 /* 32 bit load 32 bit scaled unsigned 12 bit  */
717 static void
718 ldr32_abs (sim_cpu *cpu, uint32_t offset)
719 {
720   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
721   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
722
723   /* The target register may not be SP but the source may be.  */
724   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32
725                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
726                         + SCALE (offset, 32)));
727 }
728
729 /* 32 bit load 32 bit unscaled signed 9 bit with pre- or post-writeback.  */
730 static void
731 ldr32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
732 {
733   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
734   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
735   uint64_t address;
736
737   if (rn == rt && wb != NoWriteBack)
738     HALT_UNALLOC;
739
740   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
741
742   if (wb != Post)
743     address += offset;
744
745   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32 (cpu, address));
746
747   if (wb == Post)
748     address += offset;
749
750   if (wb != NoWriteBack)
751     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
752 }
753
754 /* 32 bit load 32 bit scaled or unscaled
755    zero- or sign-extended 32-bit register offset  */
756 static void
757 ldr32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
758 {
759   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
760   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
761   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
762   /* rn may reference SP, rm and rt must reference ZR  */
763
764   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
765   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
766   uint64_t displacement =  OPT_SCALE (extended, 32, scaling);
767
768   aarch64_set_reg_u64 (cpu, rt, NO_SP,
769                        aarch64_get_mem_u32 (cpu, address + displacement));
770 }
771
772 /* 64 bit load 64 bit scaled unsigned 12 bit  */
773 static void
774 ldr_abs (sim_cpu *cpu, uint32_t offset)
775 {
776   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
777   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
778
779   /* The target register may not be SP but the source may be.  */
780   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64
781                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
782                         + SCALE (offset, 64)));
783 }
784
785 /* 64 bit load 64 bit unscaled signed 9 bit with pre- or post-writeback.  */
786 static void
787 ldr_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
788 {
789   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
790   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
791   uint64_t address;
792
793   if (rn == rt && wb != NoWriteBack)
794     HALT_UNALLOC;
795
796   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
797
798   if (wb != Post)
799     address += offset;
800
801   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64 (cpu, address));
802
803   if (wb == Post)
804     address += offset;
805
806   if (wb != NoWriteBack)
807     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
808 }
809
810 /* 64 bit load 64 bit scaled or unscaled zero-
811    or sign-extended 32-bit register offset.  */
812 static void
813 ldr_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
814 {
815   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
816   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
817   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
818   /* rn may reference SP, rm and rt must reference ZR  */
819
820   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
821   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
822   uint64_t displacement =  OPT_SCALE (extended, 64, scaling);
823
824   aarch64_set_reg_u64 (cpu, rt, NO_SP,
825                        aarch64_get_mem_u64 (cpu, address + displacement));
826 }
827
828 /* 32 bit load zero-extended byte scaled unsigned 12 bit.  */
829 static void
830 ldrb32_abs (sim_cpu *cpu, uint32_t offset)
831 {
832   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
833   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
834
835   /* The target register may not be SP but the source may be
836      there is no scaling required for a byte load.  */
837   aarch64_set_reg_u64 (cpu, rt, NO_SP,
838                        aarch64_get_mem_u8
839                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset));
840 }
841
842 /* 32 bit load zero-extended byte unscaled signed 9 bit with pre- or post-writeback.  */
843 static void
844 ldrb32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
845 {
846   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
847   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
848   uint64_t address;
849
850   if (rn == rt && wb != NoWriteBack)
851     HALT_UNALLOC;
852
853   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
854
855   if (wb != Post)
856     address += offset;
857
858   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u8 (cpu, address));
859
860   if (wb == Post)
861     address += offset;
862
863   if (wb != NoWriteBack)
864     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
865 }
866
867 /* 32 bit load zero-extended byte scaled or unscaled zero-
868    or sign-extended 32-bit register offset.  */
869 static void
870 ldrb32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
871 {
872   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
873   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
874   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
875   /* rn may reference SP, rm and rt must reference ZR  */
876
877   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
878   int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
879                                  extension);
880
881   /* There is no scaling required for a byte load.  */
882   aarch64_set_reg_u64 (cpu, rt, NO_SP,
883                        aarch64_get_mem_u8 (cpu, address + displacement));
884 }
885
886 /* 64 bit load sign-extended byte unscaled signed 9 bit
887    with pre- or post-writeback.  */
888 static void
889 ldrsb_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
890 {
891   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
892   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
893   uint64_t address;
894
895   if (rn == rt && wb != NoWriteBack)
896     HALT_UNALLOC;
897
898   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
899
900   if (wb != Post)
901     address += offset;
902
903   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_s8 (cpu, address));
904
905   if (wb == Post)
906     address += offset;
907
908   if (wb != NoWriteBack)
909     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
910 }
911
912 /* 64 bit load sign-extended byte scaled unsigned 12 bit.  */
913 static void
914 ldrsb_abs (sim_cpu *cpu, uint32_t offset)
915 {
916   ldrsb_wb (cpu, offset, NoWriteBack);
917 }
918
919 /* 64 bit load sign-extended byte scaled or unscaled zero-
920    or sign-extended 32-bit register offset.  */
921 static void
922 ldrsb_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
923 {
924   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
925   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
926   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
927   /* rn may reference SP, rm and rt must reference ZR  */
928
929   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
930   int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
931                                  extension);
932   /* There is no scaling required for a byte load.  */
933   aarch64_set_reg_u64 (cpu, rt, NO_SP,
934                        aarch64_get_mem_s8 (cpu, address + displacement));
935 }
936
937 /* 32 bit load zero-extended short scaled unsigned 12 bit.  */
938 static void
939 ldrh32_abs (sim_cpu *cpu, uint32_t offset)
940 {
941   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
942   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
943
944   /* The target register may not be SP but the source may be.  */
945   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u16
946                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
947                         + SCALE (offset, 16)));
948 }
949
950 /* 32 bit load zero-extended short unscaled signed 9 bit
951    with pre- or post-writeback.  */
952 static void
953 ldrh32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
954 {
955   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
956   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
957   uint64_t address;
958
959   if (rn == rt && wb != NoWriteBack)
960     HALT_UNALLOC;
961
962   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
963
964   if (wb != Post)
965     address += offset;
966
967   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u16 (cpu, address));
968
969   if (wb == Post)
970     address += offset;
971
972   if (wb != NoWriteBack)
973     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
974 }
975
976 /* 32 bit load zero-extended short scaled or unscaled zero-
977    or sign-extended 32-bit register offset.  */
978 static void
979 ldrh32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
980 {
981   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
982   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
983   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
984   /* rn may reference SP, rm and rt must reference ZR  */
985
986   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
987   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
988   uint64_t displacement =  OPT_SCALE (extended, 16, scaling);
989
990   aarch64_set_reg_u64 (cpu, rt, NO_SP,
991                        aarch64_get_mem_u16 (cpu, address + displacement));
992 }
993
994 /* 32 bit load sign-extended short scaled unsigned 12 bit.  */
995 static void
996 ldrsh32_abs (sim_cpu *cpu, uint32_t offset)
997 {
998   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
999   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1000
1001   /* The target register may not be SP but the source may be.  */
1002   aarch64_set_reg_u64 (cpu, rt, NO_SP, (uint32_t) aarch64_get_mem_s16
1003                        (cpu,
1004                         aarch64_get_reg_u64 (cpu, rn, SP_OK)
1005                         + SCALE (offset, 16)));
1006 }
1007
1008 /* 32 bit load sign-extended short unscaled signed 9 bit
1009    with pre- or post-writeback.  */
1010 static void
1011 ldrsh32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1012 {
1013   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1014   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1015   uint64_t address;
1016
1017   if (rn == rt && wb != NoWriteBack)
1018     HALT_UNALLOC;
1019
1020   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1021
1022   if (wb != Post)
1023     address += offset;
1024
1025   aarch64_set_reg_u64 (cpu, rt, NO_SP,
1026                        (uint32_t) aarch64_get_mem_s16 (cpu, address));
1027
1028   if (wb == Post)
1029     address += offset;
1030
1031   if (wb != NoWriteBack)
1032     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1033 }
1034
1035 /* 32 bit load sign-extended short scaled or unscaled zero-
1036    or sign-extended 32-bit register offset.  */
1037 static void
1038 ldrsh32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1039 {
1040   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1041   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1042   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1043   /* rn may reference SP, rm and rt must reference ZR  */
1044
1045   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1046   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1047   uint64_t displacement =  OPT_SCALE (extended, 16, scaling);
1048
1049   aarch64_set_reg_u64 (cpu, rt, NO_SP,
1050                        (uint32_t) aarch64_get_mem_s16
1051                        (cpu, address + displacement));
1052 }
1053
1054 /* 64 bit load sign-extended short scaled unsigned 12 bit.  */
1055 static void
1056 ldrsh_abs (sim_cpu *cpu, uint32_t offset)
1057 {
1058   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1059   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1060
1061   /* The target register may not be SP but the source may be.  */
1062   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_s16
1063                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
1064                         + SCALE (offset, 16)));
1065 }
1066
1067 /* 64 bit load sign-extended short unscaled signed 9 bit
1068    with pre- or post-writeback.  */
1069 static void
1070 ldrsh64_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1071 {
1072   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1073   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1074   uint64_t address;
1075
1076   if (rn == rt && wb != NoWriteBack)
1077     HALT_UNALLOC;
1078
1079   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1080
1081   if (wb != Post)
1082     address += offset;
1083
1084   aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_s16 (cpu, address));
1085
1086   if (wb == Post)
1087     address += offset;
1088
1089   if (wb != NoWriteBack)
1090     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1091 }
1092
1093 /* 64 bit load sign-extended short scaled or unscaled zero-
1094    or sign-extended 32-bit register offset.  */
1095 static void
1096 ldrsh_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1097 {
1098   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1099   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1100   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1101   /* rn may reference SP, rm and rt must reference ZR  */
1102
1103   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1104   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1105   uint64_t displacement = OPT_SCALE (extended, 16, scaling);
1106
1107   aarch64_set_reg_u64 (cpu, rt, NO_SP,
1108                        aarch64_get_mem_s16 (cpu, address + displacement));
1109 }
1110
1111 /* 64 bit load sign-extended 32 bit scaled unsigned 12 bit.  */
1112 static void
1113 ldrsw_abs (sim_cpu *cpu, uint32_t offset)
1114 {
1115   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1116   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1117
1118   /* The target register may not be SP but the source may be.  */
1119   return aarch64_set_reg_s64 (cpu, rt, NO_SP, aarch64_get_mem_s32
1120                               (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
1121                                + SCALE (offset, 32)));
1122 }
1123
1124 /* 64 bit load sign-extended 32 bit unscaled signed 9 bit
1125    with pre- or post-writeback.  */
1126 static void
1127 ldrsw_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1128 {
1129   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1130   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1131   uint64_t address;
1132
1133   if (rn == rt && wb != NoWriteBack)
1134     HALT_UNALLOC;
1135
1136   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1137
1138   if (wb != Post)
1139     address += offset;
1140
1141   aarch64_set_reg_s64 (cpu, rt, NO_SP, aarch64_get_mem_s32 (cpu, address));
1142
1143   if (wb == Post)
1144     address += offset;
1145
1146   if (wb != NoWriteBack)
1147     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1148 }
1149
1150 /* 64 bit load sign-extended 32 bit scaled or unscaled zero-
1151    or sign-extended 32-bit register offset.  */
1152 static void
1153 ldrsw_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1154 {
1155   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1156   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1157   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1158   /* rn may reference SP, rm and rt must reference ZR  */
1159
1160   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1161   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1162   uint64_t displacement =  OPT_SCALE (extended, 32, scaling);
1163
1164   aarch64_set_reg_s64 (cpu, rt, NO_SP,
1165                        aarch64_get_mem_s32 (cpu, address + displacement));
1166 }
1167
1168 /* N.B. with stores the value in source is written to the
1169    address identified by source2 modified by source3/offset.  */
1170
1171 /* 32 bit store scaled unsigned 12 bit.  */
1172 static void
1173 str32_abs (sim_cpu *cpu, uint32_t offset)
1174 {
1175   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1176   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1177
1178   /* The target register may not be SP but the source may be.  */
1179   aarch64_set_mem_u32 (cpu, (aarch64_get_reg_u64 (cpu, rn, SP_OK)
1180                              + SCALE (offset, 32)),
1181                        aarch64_get_reg_u32 (cpu, rt, NO_SP));
1182 }
1183
1184 /* 32 bit store unscaled signed 9 bit with pre- or post-writeback.  */
1185 static void
1186 str32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1187 {
1188   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1189   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1190   uint64_t address;
1191
1192   if (rn == rt && wb != NoWriteBack)
1193     HALT_UNALLOC;
1194
1195   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1196   if (wb != Post)
1197     address += offset;
1198
1199   aarch64_set_mem_u32 (cpu, address, aarch64_get_reg_u32 (cpu, rt, NO_SP));
1200
1201   if (wb == Post)
1202     address += offset;
1203
1204   if (wb != NoWriteBack)
1205     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1206 }
1207
1208 /* 32 bit store scaled or unscaled zero- or
1209    sign-extended 32-bit register offset.  */
1210 static void
1211 str32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1212 {
1213   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1214   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1215   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1216
1217   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1218   int64_t  extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1219   uint64_t displacement = OPT_SCALE (extended, 32, scaling);
1220
1221   aarch64_set_mem_u32 (cpu, address + displacement,
1222                        aarch64_get_reg_u64 (cpu, rt, NO_SP));
1223 }
1224
1225 /* 64 bit store scaled unsigned 12 bit.  */
1226 static void
1227 str_abs (sim_cpu *cpu, uint32_t offset)
1228 {
1229   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1230   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1231
1232   aarch64_set_mem_u64 (cpu,
1233                        aarch64_get_reg_u64 (cpu, rn, SP_OK)
1234                        + SCALE (offset, 64),
1235                        aarch64_get_reg_u64 (cpu, rt, NO_SP));
1236 }
1237
1238 /* 64 bit store unscaled signed 9 bit with pre- or post-writeback.  */
1239 static void
1240 str_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1241 {
1242   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1243   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1244   uint64_t address;
1245
1246   if (rn == rt && wb != NoWriteBack)
1247     HALT_UNALLOC;
1248
1249   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1250
1251   if (wb != Post)
1252     address += offset;
1253
1254   aarch64_set_mem_u64 (cpu, address, aarch64_get_reg_u64 (cpu, rt, NO_SP));
1255
1256   if (wb == Post)
1257     address += offset;
1258
1259   if (wb != NoWriteBack)
1260     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1261 }
1262
1263 /* 64 bit store scaled or unscaled zero-
1264    or sign-extended 32-bit register offset.  */
1265 static void
1266 str_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1267 {
1268   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1269   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1270   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1271   /* rn may reference SP, rm and rt must reference ZR  */
1272
1273   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1274   int64_t   extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1275                                extension);
1276   uint64_t displacement = OPT_SCALE (extended, 64, scaling);
1277
1278   aarch64_set_mem_u64 (cpu, address + displacement,
1279                        aarch64_get_reg_u64 (cpu, rt, NO_SP));
1280 }
1281
1282 /* 32 bit store byte scaled unsigned 12 bit.  */
1283 static void
1284 strb_abs (sim_cpu *cpu, uint32_t offset)
1285 {
1286   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1287   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1288
1289   /* The target register may not be SP but the source may be.
1290      There is no scaling required for a byte load.  */
1291   aarch64_set_mem_u8 (cpu,
1292                       aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
1293                       aarch64_get_reg_u8 (cpu, rt, NO_SP));
1294 }
1295
1296 /* 32 bit store byte unscaled signed 9 bit with pre- or post-writeback.  */
1297 static void
1298 strb_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1299 {
1300   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1301   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1302   uint64_t address;
1303
1304   if (rn == rt && wb != NoWriteBack)
1305     HALT_UNALLOC;
1306
1307   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1308
1309   if (wb != Post)
1310     address += offset;
1311
1312   aarch64_set_mem_u8 (cpu, address, aarch64_get_reg_u8 (cpu, rt, NO_SP));
1313
1314   if (wb == Post)
1315     address += offset;
1316
1317   if (wb != NoWriteBack)
1318     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1319 }
1320
1321 /* 32 bit store byte scaled or unscaled zero-
1322    or sign-extended 32-bit register offset.  */
1323 static void
1324 strb_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1325 {
1326   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1327   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1328   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1329   /* rn may reference SP, rm and rt must reference ZR  */
1330
1331   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1332   int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1333                                  extension);
1334
1335   /* There is no scaling required for a byte load.  */
1336   aarch64_set_mem_u8 (cpu, address + displacement,
1337                       aarch64_get_reg_u8 (cpu, rt, NO_SP));
1338 }
1339
1340 /* 32 bit store short scaled unsigned 12 bit.  */
1341 static void
1342 strh_abs (sim_cpu *cpu, uint32_t offset)
1343 {
1344   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1345   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1346
1347   /* The target register may not be SP but the source may be.  */
1348   aarch64_set_mem_u16 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK)
1349                        + SCALE (offset, 16),
1350                        aarch64_get_reg_u16 (cpu, rt, NO_SP));
1351 }
1352
1353 /* 32 bit store short unscaled signed 9 bit with pre- or post-writeback.  */
1354 static void
1355 strh_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
1356 {
1357   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1358   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1359   uint64_t address;
1360
1361   if (rn == rt && wb != NoWriteBack)
1362     HALT_UNALLOC;
1363
1364   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1365
1366   if (wb != Post)
1367     address += offset;
1368
1369   aarch64_set_mem_u16 (cpu, address, aarch64_get_reg_u16 (cpu, rt, NO_SP));
1370
1371   if (wb == Post)
1372     address += offset;
1373
1374   if (wb != NoWriteBack)
1375     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
1376 }
1377
1378 /* 32 bit store short scaled or unscaled zero-
1379    or sign-extended 32-bit register offset.  */
1380 static void
1381 strh_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1382 {
1383   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1384   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1385   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1386   /* rn may reference SP, rm and rt must reference ZR  */
1387
1388   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1389   int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP), extension);
1390   uint64_t displacement =  OPT_SCALE (extended, 16, scaling);
1391
1392   aarch64_set_mem_u16 (cpu, address + displacement,
1393                        aarch64_get_reg_u16 (cpu, rt, NO_SP));
1394 }
1395
1396 /* Prefetch unsigned 12 bit.  */
1397 static void
1398 prfm_abs (sim_cpu *cpu, uint32_t offset)
1399 {
1400   /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1401                           00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1402                           00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1403                           10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1404                           10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1405                           10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1406                           ow ==> UNALLOC
1407      PrfOp prfop = prfop (aarch64_get_instr (cpu), 4, 0);
1408      uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK)
1409      + SCALE (offset, 64).  */
1410
1411   /* TODO : implement prefetch of address.  */
1412 }
1413
1414 /* Prefetch scaled or unscaled zero- or sign-extended 32-bit register offset.  */
1415 static void
1416 prfm_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
1417 {
1418   /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1419                           00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1420                           00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1421                           10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1422                           10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1423                           10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1424                           ow ==> UNALLOC
1425      rn may reference SP, rm may only reference ZR
1426      PrfOp prfop = prfop (aarch64_get_instr (cpu), 4, 0);
1427      uint64_t base = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1428      int64_t extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1429                                 extension);
1430      uint64_t displacement =  OPT_SCALE (extended, 64, scaling);
1431      uint64_t address = base + displacement.  */
1432
1433   /* TODO : implement prefetch of address  */
1434 }
1435
1436 /* 64 bit pc-relative prefetch.  */
1437 static void
1438 prfm_pcrel (sim_cpu *cpu, int32_t offset)
1439 {
1440   /* instr[4,0] = prfop : 00000 ==> PLDL1KEEP, 00001 ==> PLDL1STRM,
1441                           00010 ==> PLDL2KEEP, 00001 ==> PLDL2STRM,
1442                           00100 ==> PLDL3KEEP, 00101 ==> PLDL3STRM,
1443                           10000 ==> PSTL1KEEP, 10001 ==> PSTL1STRM,
1444                           10010 ==> PSTL2KEEP, 10001 ==> PSTL2STRM,
1445                           10100 ==> PSTL3KEEP, 10101 ==> PSTL3STRM,
1446                           ow ==> UNALLOC
1447      PrfOp prfop = prfop (aarch64_get_instr (cpu), 4, 0);
1448      uint64_t address = aarch64_get_PC (cpu) + offset.  */
1449
1450   /* TODO : implement this  */
1451 }
1452
1453 /* Load-store exclusive.  */
1454
1455 static void
1456 ldxr (sim_cpu *cpu)
1457 {
1458   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1459   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1460   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1461   int size = uimm (aarch64_get_instr (cpu), 31, 30);
1462   /* int ordered = uimm (aarch64_get_instr (cpu), 15, 15);  */
1463   /* int exclusive = ! uimm (aarch64_get_instr (cpu), 23, 23);  */
1464
1465   switch (size)
1466     {
1467     case 0:
1468       aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u8 (cpu, address));
1469       break;
1470     case 1:
1471       aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u16 (cpu, address));
1472       break;
1473     case 2:
1474       aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u32 (cpu, address));
1475       break;
1476     case 3:
1477       aarch64_set_reg_u64 (cpu, rt, NO_SP, aarch64_get_mem_u64 (cpu, address));
1478       break;
1479     }
1480 }
1481
1482 static void
1483 stxr (sim_cpu *cpu)
1484 {
1485   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1486   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
1487   unsigned rs = uimm (aarch64_get_instr (cpu), 20, 16);
1488   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1489   int      size = uimm (aarch64_get_instr (cpu), 31, 30);
1490   uint64_t data = aarch64_get_reg_u64 (cpu, rt, NO_SP);
1491
1492   switch (size)
1493     {
1494     case 0: aarch64_set_mem_u8 (cpu, address, data); break;
1495     case 1: aarch64_set_mem_u16 (cpu, address, data); break;
1496     case 2: aarch64_set_mem_u32 (cpu, address, data); break;
1497     case 3: aarch64_set_mem_u64 (cpu, address, data); break;
1498     }
1499
1500   aarch64_set_reg_u64 (cpu, rs, NO_SP, 0); /* Always exclusive...  */
1501 }
1502
1503 static void
1504 dexLoadLiteral (sim_cpu *cpu)
1505 {
1506   /* instr[29,27] == 011
1507      instr[25,24] == 00
1508      instr[31,30:26] = opc: 000 ==> LDRW,  001 ==> FLDRS
1509                             010 ==> LDRX,  011 ==> FLDRD
1510                             100 ==> LDRSW, 101 ==> FLDRQ
1511                             110 ==> PRFM, 111 ==> UNALLOC
1512      instr[26] ==> V : 0 ==> GReg, 1 ==> FReg
1513      instr[23, 5] == simm19  */
1514
1515   /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);  */
1516   uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 1)
1517                         | uimm (aarch64_get_instr (cpu), 26, 26));
1518   int32_t imm = simm32 (aarch64_get_instr (cpu), 23, 5);
1519
1520   switch (dispatch)
1521     {
1522     case 0: ldr32_pcrel (cpu, imm); break;
1523     case 1: fldrs_pcrel (cpu, imm); break;
1524     case 2: ldr_pcrel   (cpu, imm); break;
1525     case 3: fldrd_pcrel (cpu, imm); break;
1526     case 4: ldrsw_pcrel (cpu, imm); break;
1527     case 5: fldrq_pcrel (cpu, imm); break;
1528     case 6: prfm_pcrel  (cpu, imm); break;
1529     case 7:
1530     default:
1531       HALT_UNALLOC;
1532     }
1533 }
1534
1535 /* Immediate arithmetic
1536    The aimm argument is a 12 bit unsigned value or a 12 bit unsigned
1537    value left shifted by 12 bits (done at decode).
1538
1539    N.B. the register args (dest, source) can normally be Xn or SP.
1540    the exception occurs for flag setting instructions which may
1541    only use Xn for the output (dest).  */
1542
1543 /* 32 bit add immediate.  */
1544 static void
1545 add32 (sim_cpu *cpu, uint32_t aimm)
1546 {
1547   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1548   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1549
1550   aarch64_set_reg_u64 (cpu, rd, SP_OK,
1551                        aarch64_get_reg_u32 (cpu, rn, SP_OK) + aimm);
1552 }
1553
1554 /* 64 bit add immediate.  */
1555 static void
1556 add64 (sim_cpu *cpu, uint32_t aimm)
1557 {
1558   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1559   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1560
1561   aarch64_set_reg_u64 (cpu, rd, SP_OK,
1562                        aarch64_get_reg_u64 (cpu, rn, SP_OK) + aimm);
1563 }
1564
1565 static void
1566 set_flags_for_add32 (sim_cpu *cpu, int32_t value1, int32_t value2)
1567 {
1568   int32_t   result = value1 + value2;
1569   int64_t   sresult = (int64_t) value1 + (int64_t) value2;
1570   uint64_t  uresult = (uint64_t)(uint32_t) value1
1571     + (uint64_t)(uint32_t) value2;
1572   uint32_t  flags = 0;
1573
1574   if (result == 0)
1575     flags |= Z;
1576
1577   if (result & (1 << 31))
1578     flags |= N;
1579
1580   if (uresult != result)
1581     flags |= C;
1582
1583   if (sresult != result)
1584     flags |= V;
1585
1586   aarch64_set_CPSR (cpu, flags);
1587 }
1588
1589 static void
1590 set_flags_for_add64 (sim_cpu *cpu, uint64_t value1, uint64_t value2)
1591 {
1592   int64_t   sval1 = value1;
1593   int64_t   sval2 = value2;
1594   uint64_t  result = value1 + value2;
1595   int64_t   sresult = sval1 + sval2;
1596   uint32_t  flags = 0;
1597
1598   if (result == 0)
1599     flags |= Z;
1600
1601   if (result & (1ULL << 63))
1602     flags |= N;
1603
1604   if (sval1 < 0)
1605     {
1606       if (sval2 < 0)
1607         {
1608           /* Negative plus a negative.  Overflow happens if
1609              the result is greater than either of the operands.  */
1610           if (sresult > sval1 || sresult > sval2)
1611             flags |= V;
1612         }
1613       /* else Negative plus a positive.  Overflow cannot happen.  */
1614     }
1615   else /* value1 is +ve.  */
1616     {
1617       if (sval2 < 0)
1618         {
1619           /* Overflow can only occur if we computed "0 - MININT".  */
1620           if (sval1 == 0 && sval2 == (1LL << 63))
1621             flags |= V;
1622         }
1623       else
1624         {
1625           /* Postive plus positive - overflow has happened if the
1626              result is smaller than either of the operands.  */
1627           if (result < value1 || result < value2)
1628             flags |= V | C;
1629         }
1630     }
1631
1632   aarch64_set_CPSR (cpu, flags);
1633 }
1634
1635 #define NEG(a) (((a) & signbit) == signbit)
1636 #define POS(a) (((a) & signbit) == 0)
1637
1638 static void
1639 set_flags_for_sub32 (sim_cpu *cpu, uint32_t value1, uint32_t value2)
1640 {
1641   uint32_t result = value1 - value2;
1642   uint32_t flags = 0;
1643   uint32_t signbit = 1U << 31;
1644
1645   if (result == 0)
1646     flags |= Z;
1647
1648   if (NEG (result))
1649     flags |= N;
1650
1651   if (   (NEG (value1) && POS (value2))
1652       || (NEG (value1) && POS (result))
1653       || (POS (value2) && POS (result)))
1654     flags |= C;
1655
1656   if (   (NEG (value1) && POS (value2) && POS (result))
1657       || (POS (value1) && NEG (value2) && NEG (result)))
1658     flags |= V;
1659
1660   aarch64_set_CPSR (cpu, flags);
1661 }
1662
1663 static void
1664 set_flags_for_sub64 (sim_cpu *cpu, uint64_t value1, uint64_t value2)
1665 {
1666   uint64_t result = value1 - value2;
1667   uint32_t flags = 0;
1668   uint64_t signbit = 1ULL << 63;
1669
1670   if (result == 0)
1671     flags |= Z;
1672
1673   if (NEG (result))
1674     flags |= N;
1675
1676   if (   (NEG (value1) && POS (value2))
1677       || (NEG (value1) && POS (result))
1678       || (POS (value2) && POS (result)))
1679     flags |= C;
1680
1681   if (   (NEG (value1) && POS (value2) && POS (result))
1682       || (POS (value1) && NEG (value2) && NEG (result)))
1683     flags |= V;
1684
1685   aarch64_set_CPSR (cpu, flags);
1686 }
1687
1688 static void
1689 set_flags_for_binop32 (sim_cpu *cpu, uint32_t result)
1690 {
1691   uint32_t flags = 0;
1692
1693   if (result == 0)
1694     flags |= Z;
1695   else
1696     flags &= ~ Z;
1697
1698   if (result & (1 << 31))
1699     flags |= N;
1700   else
1701     flags &= ~ N;
1702
1703   aarch64_set_CPSR (cpu, flags);
1704 }
1705
1706 static void
1707 set_flags_for_binop64 (sim_cpu *cpu, uint64_t result)
1708 {
1709   uint32_t flags = 0;
1710
1711   if (result == 0)
1712     flags |= Z;
1713   else
1714     flags &= ~ Z;
1715
1716   if (result & (1ULL << 63))
1717     flags |= N;
1718   else
1719     flags &= ~ N;
1720
1721   aarch64_set_CPSR (cpu, flags);
1722 }
1723
1724 /* 32 bit add immediate set flags.  */
1725 static void
1726 adds32 (sim_cpu *cpu, uint32_t aimm)
1727 {
1728   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1729   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1730   /* TODO : do we need to worry about signs here?  */
1731   int32_t value1 = aarch64_get_reg_s32 (cpu, rn, SP_OK);
1732
1733   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + aimm);
1734   set_flags_for_add32 (cpu, value1, aimm);
1735 }
1736
1737 /* 64 bit add immediate set flags.  */
1738 static void
1739 adds64 (sim_cpu *cpu, uint32_t aimm)
1740 {
1741   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1742   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1743   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1744   uint64_t value2 = aimm;
1745
1746   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
1747   set_flags_for_add64 (cpu, value1, value2);
1748 }
1749
1750 /* 32 bit sub immediate.  */
1751 static void
1752 sub32 (sim_cpu *cpu, uint32_t aimm)
1753 {
1754   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1755   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1756
1757   aarch64_set_reg_u64 (cpu, rd, SP_OK,
1758                        aarch64_get_reg_u32 (cpu, rn, SP_OK) - aimm);
1759 }
1760
1761 /* 64 bit sub immediate.  */
1762 static void
1763 sub64 (sim_cpu *cpu, uint32_t aimm)
1764 {
1765   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1766   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1767
1768   aarch64_set_reg_u64 (cpu, rd, SP_OK,
1769                        aarch64_get_reg_u64 (cpu, rn, SP_OK) - aimm);
1770 }
1771
1772 /* 32 bit sub immediate set flags.  */
1773 static void
1774 subs32 (sim_cpu *cpu, uint32_t aimm)
1775 {
1776   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1777   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1778   uint32_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1779   uint32_t value2 = aimm;
1780
1781   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1782   set_flags_for_sub32 (cpu, value1, value2);
1783 }
1784
1785 /* 64 bit sub immediate set flags.  */
1786 static void
1787 subs64 (sim_cpu *cpu, uint32_t aimm)
1788 {
1789   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1790   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1791   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
1792   uint32_t value2 = aimm;
1793
1794   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1795   set_flags_for_sub64 (cpu, value1, value2);
1796 }
1797
1798 /* Data Processing Register.  */
1799
1800 /* First two helpers to perform the shift operations.  */
1801
1802 static inline uint32_t
1803 shifted32 (uint32_t value, Shift shift, uint32_t count)
1804 {
1805   switch (shift)
1806     {
1807     default:
1808     case LSL:
1809       return (value << count);
1810     case LSR:
1811       return (value >> count);
1812     case ASR:
1813       {
1814         int32_t svalue = value;
1815         return (svalue >> count);
1816       }
1817     case ROR:
1818       {
1819         uint32_t top = value >> count;
1820         uint32_t bottom = value << (32 - count);
1821         return (bottom | top);
1822       }
1823     }
1824 }
1825
1826 static inline uint64_t
1827 shifted64 (uint64_t value, Shift shift, uint32_t count)
1828 {
1829   switch (shift)
1830     {
1831     default:
1832     case LSL:
1833       return (value << count);
1834     case LSR:
1835       return (value >> count);
1836     case ASR:
1837       {
1838         int64_t svalue = value;
1839         return (svalue >> count);
1840       }
1841     case ROR:
1842       {
1843         uint64_t top = value >> count;
1844         uint64_t bottom = value << (64 - count);
1845         return (bottom | top);
1846       }
1847     }
1848 }
1849
1850 /* Arithmetic shifted register.
1851    These allow an optional LSL, ASR or LSR to the second source
1852    register with a count up to the register bit count.
1853
1854    N.B register args may not be SP.  */
1855
1856 /* 32 bit ADD shifted register.  */
1857 static void
1858 add32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1859 {
1860   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1861   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1862   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1863
1864   aarch64_set_reg_u64 (cpu, rd, NO_SP,
1865                        aarch64_get_reg_u32 (cpu, rn, NO_SP)
1866                        + shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1867                                     shift, count));
1868 }
1869
1870 /* 64 bit ADD shifted register.  */
1871 static void
1872 add64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1873 {
1874   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1875   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1876   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1877
1878   aarch64_set_reg_u64 (cpu, rd, NO_SP,
1879                        aarch64_get_reg_u64 (cpu, rn, NO_SP)
1880                        + shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1881                                     shift, count));
1882 }
1883
1884 /* 32 bit ADD shifted register setting flags.  */
1885 static void
1886 adds32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1887 {
1888   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1889   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1890   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1891
1892   uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
1893   uint32_t value2 = shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1894                                shift, count);
1895
1896   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
1897   set_flags_for_add32 (cpu, value1, value2);
1898 }
1899
1900 /* 64 bit ADD shifted register setting flags.  */
1901 static void
1902 adds64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1903 {
1904   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1905   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1906   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1907
1908   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
1909   uint64_t value2 = shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1910                                shift, count);
1911
1912   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
1913   set_flags_for_add64 (cpu, value1, value2);
1914 }
1915
1916 /* 32 bit SUB shifted register.  */
1917 static void
1918 sub32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1919 {
1920   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1921   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1922   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1923
1924   aarch64_set_reg_u64 (cpu, rd, NO_SP,
1925                        aarch64_get_reg_u32 (cpu, rn, NO_SP)
1926                        - shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1927                                     shift, count));
1928 }
1929
1930 /* 64 bit SUB shifted register.  */
1931 static void
1932 sub64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1933 {
1934   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1935   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1936   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1937
1938   aarch64_set_reg_u64 (cpu, rd, NO_SP,
1939                        aarch64_get_reg_u64 (cpu, rn, NO_SP)
1940                        - shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1941                                     shift, count));
1942 }
1943
1944 /* 32 bit SUB shifted register setting flags.  */
1945 static void
1946 subs32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1947 {
1948   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1949   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1950   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1951
1952   uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
1953   uint32_t value2 = shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
1954                               shift, count);
1955
1956   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1957   set_flags_for_sub32 (cpu, value1, value2);
1958 }
1959
1960 /* 64 bit SUB shifted register setting flags.  */
1961 static void
1962 subs64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
1963 {
1964   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
1965   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
1966   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
1967
1968   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
1969   uint64_t value2 = shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
1970                                shift, count);
1971
1972   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
1973   set_flags_for_sub64 (cpu, value1, value2);
1974 }
1975
1976 /* First a couple more helpers to fetch the
1977    relevant source register element either
1978    sign or zero extended as required by the
1979    extension value.  */
1980
1981 static uint32_t
1982 extreg32 (sim_cpu *cpu, unsigned int lo, Extension extension)
1983 {
1984   switch (extension)
1985     {
1986     case UXTB: return aarch64_get_reg_u8  (cpu, lo, NO_SP);
1987     case UXTH: return aarch64_get_reg_u16 (cpu, lo, NO_SP);
1988     case UXTW: /* Fall through.  */
1989     case UXTX: return aarch64_get_reg_u32 (cpu, lo, NO_SP);
1990     case SXTB: return aarch64_get_reg_s8  (cpu, lo, NO_SP);
1991     case SXTH: return aarch64_get_reg_s16 (cpu, lo, NO_SP);
1992     case SXTW: /* Fall through.  */
1993     case SXTX: /* Fall through.  */
1994     default:   return aarch64_get_reg_s32 (cpu, lo, NO_SP);
1995   }
1996 }
1997
1998 static uint64_t
1999 extreg64 (sim_cpu *cpu, unsigned int lo, Extension extension)
2000 {
2001   switch (extension)
2002     {
2003     case UXTB: return aarch64_get_reg_u8  (cpu, lo, NO_SP);
2004     case UXTH: return aarch64_get_reg_u16 (cpu, lo, NO_SP);
2005     case UXTW: return aarch64_get_reg_u32 (cpu, lo, NO_SP);
2006     case UXTX: return aarch64_get_reg_u64 (cpu, lo, NO_SP);
2007     case SXTB: return aarch64_get_reg_s8  (cpu, lo, NO_SP);
2008     case SXTH: return aarch64_get_reg_s16 (cpu, lo, NO_SP);
2009     case SXTW: return aarch64_get_reg_s32 (cpu, lo, NO_SP);
2010     case SXTX:
2011     default:   return aarch64_get_reg_s64 (cpu, lo, NO_SP);
2012     }
2013 }
2014
2015 /* Arithmetic extending register
2016    These allow an optional sign extension of some portion of the
2017    second source register followed by an optional left shift of
2018    between 1 and 4 bits (i.e. a shift of 0-4 bits???)
2019
2020    N.B output (dest) and first input arg (source) may normally be Xn
2021    or SP. However, for flag setting operations dest can only be
2022    Xn. Second input registers are always Xn.  */
2023
2024 /* 32 bit ADD extending register.  */
2025 static void
2026 add32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2027 {
2028   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2029   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2030   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2031
2032   aarch64_set_reg_u64 (cpu, rd, SP_OK,
2033                        aarch64_get_reg_u32 (cpu, rn, SP_OK)
2034                        + (extreg32 (cpu, rm, extension) << shift));
2035 }
2036
2037 /* 64 bit ADD extending register.
2038    N.B. This subsumes the case with 64 bit source2 and UXTX #n or LSL #0.  */
2039 static void
2040 add64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2041 {
2042   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2043   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2044   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2045
2046   aarch64_set_reg_u64 (cpu, rd, SP_OK,
2047                        aarch64_get_reg_u64 (cpu, rn, SP_OK)
2048                        + (extreg64 (cpu, rm, extension) << shift));
2049 }
2050
2051 /* 32 bit ADD extending register setting flags.  */
2052 static void
2053 adds32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2054 {
2055   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2056   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2057   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2058
2059   uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, SP_OK);
2060   uint32_t value2 = extreg32 (cpu, rm, extension) << shift;
2061
2062   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
2063   set_flags_for_add32 (cpu, value1, value2);
2064 }
2065
2066 /* 64 bit ADD extending register setting flags  */
2067 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0  */
2068 static void
2069 adds64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2070 {
2071   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2072   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2073   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2074
2075   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
2076   uint64_t value2 = extreg64 (cpu, rm, extension) << shift;
2077
2078   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2);
2079   set_flags_for_add64 (cpu, value1, value2);
2080 }
2081
2082 /* 32 bit SUB extending register.  */
2083 static void
2084 sub32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2085 {
2086   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2087   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2088   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2089
2090   aarch64_set_reg_u64 (cpu, rd, SP_OK,
2091                        aarch64_get_reg_u32 (cpu, rn, SP_OK)
2092                        - (extreg32 (cpu, rm, extension) << shift));
2093 }
2094
2095 /* 64 bit SUB extending register.  */
2096 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0.  */
2097 static void
2098 sub64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2099 {
2100   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2101   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2102   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2103
2104   aarch64_set_reg_u64 (cpu, rd, SP_OK,
2105                        aarch64_get_reg_u64 (cpu, rn, SP_OK)
2106                        - (extreg64 (cpu, rm, extension) << shift));
2107 }
2108
2109 /* 32 bit SUB extending register setting flags.  */
2110 static void
2111 subs32_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2112 {
2113   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2114   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2115   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2116
2117   uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, SP_OK);
2118   uint32_t value2 = extreg32 (cpu, rm, extension) << shift;
2119
2120   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
2121   set_flags_for_sub32 (cpu, value1, value2);
2122 }
2123
2124 /* 64 bit SUB extending register setting flags  */
2125 /* N.B. this subsumes the case with 64 bit source2 and UXTX #n or LSL #0  */
2126 static void
2127 subs64_ext (sim_cpu *cpu, Extension extension, uint32_t shift)
2128 {
2129   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2130   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2131   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2132
2133   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, SP_OK);
2134   uint64_t value2 = extreg64 (cpu, rm, extension) << shift;
2135
2136   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 - value2);
2137   set_flags_for_sub64 (cpu, value1, value2);
2138 }
2139
2140 static void
2141 dexAddSubtractImmediate (sim_cpu *cpu)
2142 {
2143   /* instr[31]    = size : 0 ==> 32 bit, 1 ==> 64 bit
2144      instr[30]    = op : 0 ==> ADD, 1 ==> SUB
2145      instr[29]    = set : 0 ==> no flags, 1 ==> set flags
2146      instr[28,24] = 10001
2147      instr[23,22] = shift : 00 == LSL#0, 01 = LSL#12 1x = UNALLOC
2148      instr[21,10] = uimm12
2149      instr[9,5]   = Rn
2150      instr[4,0]   = Rd  */
2151
2152   /* N.B. the shift is applied at decode before calling the add/sub routine.  */
2153   uint32_t shift = uimm (aarch64_get_instr (cpu), 23, 22);
2154   uint32_t imm = uimm (aarch64_get_instr (cpu), 21, 10);
2155   uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2156
2157   NYI_assert (28, 24, 0x11);
2158
2159   if (shift > 1)
2160     HALT_UNALLOC;
2161
2162   if (shift)
2163     imm <<= 12;
2164
2165   switch (dispatch)
2166     {
2167     case 0: add32 (cpu, imm); break;
2168     case 1: adds32 (cpu, imm); break;
2169     case 2: sub32 (cpu, imm); break;
2170     case 3: subs32 (cpu, imm); break;
2171     case 4: add64 (cpu, imm); break;
2172     case 5: adds64 (cpu, imm); break;
2173     case 6: sub64 (cpu, imm); break;
2174     case 7: subs64 (cpu, imm); break;
2175     }
2176 }
2177
2178 static void
2179 dexAddSubtractShiftedRegister (sim_cpu *cpu)
2180 {
2181   /* instr[31]    = size : 0 ==> 32 bit, 1 ==> 64 bit
2182      instr[30,29] = op : 00 ==> ADD, 01 ==> ADDS, 10 ==> SUB, 11 ==> SUBS
2183      instr[28,24] = 01011
2184      instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> UNALLOC
2185      instr[21]    = 0
2186      instr[20,16] = Rm
2187      instr[15,10] = count : must be 0xxxxx for 32 bit
2188      instr[9,5]   = Rn
2189      instr[4,0]   = Rd  */
2190
2191   uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
2192   /* 32 bit operations must have count[5] = 0
2193      or else we have an UNALLOC.  */
2194   uint32_t count = uimm (aarch64_get_instr (cpu), 15, 10);
2195   /* Shift encoded as ROR is unallocated.  */
2196   Shift shiftType = shift (aarch64_get_instr (cpu), 22);
2197   /* Dispatch on size:op i.e aarch64_get_instr (cpu)[31,29].  */
2198   uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2199
2200   NYI_assert (28, 24, 0x0B);
2201   NYI_assert (21, 21, 0);
2202
2203   if (shiftType == ROR)
2204     HALT_UNALLOC;
2205
2206   if (!size && uimm (count, 5, 5))
2207     HALT_UNALLOC;
2208
2209   switch (dispatch)
2210     {
2211     case 0: add32_shift  (cpu, shiftType, count); break;
2212     case 1: adds32_shift (cpu, shiftType, count); break;
2213     case 2: sub32_shift  (cpu, shiftType, count); break;
2214     case 3: subs32_shift (cpu, shiftType, count); break;
2215     case 4: add64_shift  (cpu, shiftType, count); break;
2216     case 5: adds64_shift (cpu, shiftType, count); break;
2217     case 6: sub64_shift  (cpu, shiftType, count); break;
2218     case 7: subs64_shift (cpu, shiftType, count); break;
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     }
2263 }
2264
2265 /* Conditional data processing
2266    Condition register is implicit 3rd source.  */
2267
2268 /* 32 bit add with carry.  */
2269 /* N.B register args may not be SP.  */
2270
2271 static void
2272 adc32 (sim_cpu *cpu)
2273 {
2274   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2275   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2276   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2277
2278   aarch64_set_reg_u64 (cpu, rd, NO_SP,
2279                        aarch64_get_reg_u32 (cpu, rn, NO_SP)
2280                        + aarch64_get_reg_u32 (cpu, rm, NO_SP)
2281                        + IS_SET (C));
2282 }
2283
2284 /* 64 bit add with carry  */
2285 static void
2286 adc64 (sim_cpu *cpu)
2287 {
2288   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2289   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2290   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2291
2292   aarch64_set_reg_u64 (cpu, rd, NO_SP,
2293                        aarch64_get_reg_u64 (cpu, rn, NO_SP)
2294                        + aarch64_get_reg_u64 (cpu, rm, NO_SP)
2295                        + IS_SET (C));
2296 }
2297
2298 /* 32 bit add with carry setting flags.  */
2299 static void
2300 adcs32 (sim_cpu *cpu)
2301 {
2302   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2303   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2304   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2305
2306   uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
2307   uint32_t value2 = aarch64_get_reg_u32 (cpu, rm, NO_SP);
2308   uint32_t carry = IS_SET (C);
2309
2310   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2 + carry);
2311   set_flags_for_add32 (cpu, value1, value2 + carry);
2312 }
2313
2314 /* 64 bit add with carry setting flags.  */
2315 static void
2316 adcs64 (sim_cpu *cpu)
2317 {
2318   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2319   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2320   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2321
2322   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
2323   uint64_t value2 = aarch64_get_reg_u64 (cpu, rm, NO_SP);
2324   uint64_t carry = IS_SET (C);
2325
2326   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 + value2 + carry);
2327   set_flags_for_add64 (cpu, value1, value2 + carry);
2328 }
2329
2330 /* 32 bit sub with carry.  */
2331 static void
2332 sbc32 (sim_cpu *cpu)
2333 {
2334   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2335   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5); /* ngc iff rn == 31.  */
2336   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2337
2338   aarch64_set_reg_u64 (cpu, rd, NO_SP,
2339                        aarch64_get_reg_u32 (cpu, rn, NO_SP)
2340                        - aarch64_get_reg_u32 (cpu, rm, NO_SP)
2341                        - 1 + IS_SET (C));
2342 }
2343
2344 /* 64 bit sub with carry  */
2345 static void
2346 sbc64 (sim_cpu *cpu)
2347 {
2348   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2349   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2350   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2351
2352   aarch64_set_reg_u64 (cpu, rd, NO_SP,
2353                        aarch64_get_reg_u64 (cpu, rn, NO_SP)
2354                        - aarch64_get_reg_u64 (cpu, rm, NO_SP)
2355                        - 1 + IS_SET (C));
2356 }
2357
2358 /* 32 bit sub with carry setting flags  */
2359 static void
2360 sbcs32 (sim_cpu *cpu)
2361 {
2362   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2363   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2364   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2365
2366   uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
2367   uint32_t value2 = aarch64_get_reg_u32 (cpu, rm, NO_SP);
2368   uint32_t carry  = IS_SET (C);
2369   uint32_t result = value1 - value2 + 1 - carry;
2370
2371   aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
2372   set_flags_for_sub32 (cpu, value1, value2 + 1 - carry);
2373 }
2374
2375 /* 64 bit sub with carry setting flags  */
2376 static void
2377 sbcs64 (sim_cpu *cpu)
2378 {
2379   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
2380   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
2381   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2382
2383   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
2384   uint64_t value2 = aarch64_get_reg_u64 (cpu, rm, NO_SP);
2385   uint64_t carry  = IS_SET (C);
2386   uint64_t result = value1 - value2 + 1 - carry;
2387
2388   aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
2389   set_flags_for_sub64 (cpu, value1, value2 + 1 - carry);
2390 }
2391
2392 static void
2393 dexAddSubtractWithCarry (sim_cpu *cpu)
2394 {
2395   /* instr[31]    = size : 0 ==> 32 bit, 1 ==> 64 bit
2396      instr[30]    = op : 0 ==> ADC, 1 ==> SBC
2397      instr[29]    = set? : 0 ==> no flags, 1 ==> set flags
2398      instr[28,21] = 1 1010 000
2399      instr[20,16] = Rm
2400      instr[15,10] = op2 : 00000 ==> ok, ow ==> UNALLOC
2401      instr[9,5]   = Rn
2402      instr[4,0]   = Rd  */
2403
2404   uint32_t op2 = uimm (aarch64_get_instr (cpu), 15, 10);
2405   /* Dispatch on size:op:set? i.e aarch64_get_instr (cpu)[31,29]  */
2406   uint32_t dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
2407
2408   NYI_assert (28, 21, 0xD0);
2409
2410   if (op2 != 0)
2411     HALT_UNALLOC;
2412
2413   switch (dispatch)
2414     {
2415     case 0: adc32 (cpu); break;
2416     case 1: adcs32 (cpu); break;
2417     case 2: sbc32 (cpu); break;
2418     case 3: sbcs32 (cpu); break;
2419     case 4: adc64 (cpu); break;
2420     case 5: adcs64 (cpu); break;
2421     case 6: sbc64 (cpu); break;
2422     case 7: sbcs64 (cpu); break;
2423     }
2424 }
2425
2426 static uint32_t
2427 testConditionCode (sim_cpu *cpu, CondCode cc)
2428 {
2429   /* This should be reduceable to branchless logic
2430      by some careful testing of bits in CC followed
2431      by the requisite masking and combining of bits
2432      from the flag register.
2433
2434      For now we do it with a switch.  */
2435   int res;
2436
2437   switch (cc)
2438     {
2439     case EQ:  res = IS_SET (Z);    break;
2440     case NE:  res = IS_CLEAR (Z);  break;
2441     case CS:  res = IS_SET (C);    break;
2442     case CC:  res = IS_CLEAR (C);  break;
2443     case MI:  res = IS_SET (N);    break;
2444     case PL:  res = IS_CLEAR (N);  break;
2445     case VS:  res = IS_SET (V);    break;
2446     case VC:  res = IS_CLEAR (V);  break;
2447     case HI:  res = IS_SET (C) && IS_CLEAR (Z);  break;
2448     case LS:  res = IS_CLEAR (C) || IS_SET (Z);  break;
2449     case GE:  res = IS_SET (N) == IS_SET (V);    break;
2450     case LT:  res = IS_SET (N) != IS_SET (V);    break;
2451     case GT:  res = IS_CLEAR (Z) && (IS_SET (N) == IS_SET (V));  break;
2452     case LE:  res = IS_SET (Z) || (IS_SET (N) != IS_SET (V));    break;
2453     case AL:
2454     case NV:
2455     default:
2456       res = 1;
2457       break;
2458     }
2459   return res;
2460 }
2461
2462 static void
2463 CondCompare (sim_cpu *cpu) /* aka: ccmp and ccmn  */
2464 {
2465   /* instr[31]    = size : 0 ==> 32 bit, 1 ==> 64 bit
2466      instr[30]    = compare with positive (1) or negative value (0)
2467      instr[29,21] = 1 1101 0010
2468      instr[20,16] = Rm or const
2469      instr[15,12] = cond
2470      instr[11]    = compare reg (0) or const (1)
2471      instr[10]    = 0
2472      instr[9,5]   = Rn
2473      instr[4]     = 0
2474      instr[3,0]   = value for CPSR bits if the comparison does not take place.  */
2475   signed int negate;
2476   unsigned rm;
2477   unsigned rn;
2478
2479   NYI_assert (29, 21, 0x1d2);
2480   NYI_assert (10, 10, 0);
2481   NYI_assert (4, 4, 0);
2482
2483   if (! testConditionCode (cpu, uimm (aarch64_get_instr (cpu), 15, 12)))
2484     {
2485       aarch64_set_CPSR (cpu, uimm (aarch64_get_instr (cpu), 3, 0));
2486       return;
2487     }
2488
2489   negate = uimm (aarch64_get_instr (cpu), 30, 30) ? 1 : -1;
2490   rm = uimm (aarch64_get_instr (cpu), 20, 16);
2491   rn = uimm (aarch64_get_instr (cpu),  9,  5);
2492
2493   if (uimm (aarch64_get_instr (cpu), 31, 31))
2494     {
2495       if (uimm (aarch64_get_instr (cpu), 11, 11))
2496         set_flags_for_sub64 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK),
2497                              negate * (uint64_t) rm);
2498       else
2499         set_flags_for_sub64 (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK),
2500                              negate * aarch64_get_reg_u64 (cpu, rm, SP_OK));
2501     }
2502   else
2503     {
2504       if (uimm (aarch64_get_instr (cpu), 11, 11))
2505         set_flags_for_sub32 (cpu, aarch64_get_reg_u32 (cpu, rn, SP_OK),
2506                              negate * rm);
2507       else
2508         set_flags_for_sub32 (cpu, aarch64_get_reg_u32 (cpu, rn, SP_OK),
2509                              negate * aarch64_get_reg_u32 (cpu, rm, SP_OK));
2510     }
2511 }
2512
2513 static void
2514 do_vec_MOV_whole_vector (sim_cpu *cpu)
2515 {
2516   /* MOV Vd.T, Vs.T  (alias for ORR Vd.T, Vn.T, Vm.T where Vn == Vm)
2517
2518      instr[31]    = 0
2519      instr[30]    = half(0)/full(1)
2520      instr[29,21] = 001110101
2521      instr[20,16] = Vs
2522      instr[15,10] = 000111
2523      instr[9,5]   = Vs
2524      instr[4,0]   = Vd  */
2525
2526   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
2527   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2528
2529   NYI_assert (29, 21, 0x075);
2530   NYI_assert (15, 10, 0x07);
2531
2532   if (uimm (aarch64_get_instr (cpu), 20, 16) != vs)
2533     HALT_NYI;
2534
2535   if (uimm (aarch64_get_instr (cpu), 30, 30))
2536     aarch64_set_vec_u64 (cpu, vd, 1, aarch64_get_vec_u64 (cpu, vs, 1));
2537
2538   aarch64_set_vec_u64 (cpu, vd, 0, aarch64_get_vec_u64 (cpu, vs, 0));
2539 }
2540
2541 static void
2542 do_vec_MOV_into_scalar (sim_cpu *cpu)
2543 {
2544   /* instr[31]    = 0
2545      instr[30]    = word(0)/long(1)
2546      instr[29,21] = 00 1110 000
2547      instr[20,18] = element size and index
2548      instr[17,10] = 00 0011 11
2549      instr[9,5]   = V source
2550      instr[4,0]   = R dest  */
2551
2552   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
2553   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
2554
2555   NYI_assert (29, 21, 0x070);
2556   NYI_assert (17, 10, 0x0F);
2557
2558   switch (uimm (aarch64_get_instr (cpu), 20, 18))
2559     {
2560     case 0x2:
2561       aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u64 (cpu, vs, 0));
2562       break;
2563
2564     case 0x6:
2565       aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u64 (cpu, vs, 1));
2566       break;
2567
2568     case 0x1:
2569     case 0x3:
2570     case 0x5:
2571     case 0x7:
2572       aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u32
2573                            (cpu, vs, uimm (aarch64_get_instr (cpu), 20, 19)));
2574       break;
2575
2576     default:
2577       HALT_NYI;
2578     }
2579 }
2580
2581 static void
2582 do_vec_INS (sim_cpu *cpu)
2583 {
2584   /* instr[31,21] = 01001110000
2585      instr[20,16] = element size and index
2586      instr[15,10] = 000111
2587      instr[9,5]   = W source
2588      instr[4,0]   = V dest  */
2589
2590   int index;
2591   unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
2592   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2593
2594   NYI_assert (31, 21, 0x270);
2595   NYI_assert (15, 10, 0x07);
2596
2597   if (uimm (aarch64_get_instr (cpu), 16, 16))
2598     {
2599       index = uimm (aarch64_get_instr (cpu), 20, 17);
2600       aarch64_set_vec_u8 (cpu, vd, index,
2601                           aarch64_get_reg_u8 (cpu, rs, NO_SP));
2602     }
2603   else if (uimm (aarch64_get_instr (cpu), 17, 17))
2604     {
2605       index = uimm (aarch64_get_instr (cpu), 20, 18);
2606       aarch64_set_vec_u16 (cpu, vd, index,
2607                            aarch64_get_reg_u16 (cpu, rs, NO_SP));
2608     }
2609   else if (uimm (aarch64_get_instr (cpu), 18, 18))
2610     {
2611       index = uimm (aarch64_get_instr (cpu), 20, 19);
2612       aarch64_set_vec_u32 (cpu, vd, index,
2613                            aarch64_get_reg_u32 (cpu, rs, NO_SP));
2614     }
2615   else if (uimm (aarch64_get_instr (cpu), 19, 19))
2616     {
2617       index = uimm (aarch64_get_instr (cpu), 20, 20);
2618       aarch64_set_vec_u64 (cpu, vd, index,
2619                            aarch64_get_reg_u64 (cpu, rs, NO_SP));
2620     }
2621   else
2622     HALT_NYI;
2623 }
2624
2625 static void
2626 do_vec_DUP_vector_into_vector (sim_cpu *cpu)
2627 {
2628   /* instr[31]    = 0
2629      instr[30]    = half(0)/full(1)
2630      instr[29,21] = 00 1110 000
2631      instr[20,16] = element size and index
2632      instr[15,10] = 0000 01
2633      instr[9,5]   = V source
2634      instr[4,0]   = V dest.  */
2635
2636   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
2637   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
2638   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2639   int i, index;
2640
2641   NYI_assert (29, 21, 0x070);
2642   NYI_assert (15, 10, 0x01);
2643
2644   if (uimm (aarch64_get_instr (cpu), 16, 16))
2645     {
2646       index = uimm (aarch64_get_instr (cpu), 20, 17);
2647
2648       for (i = 0; i < (full ? 16 : 8); i++)
2649         aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vs, index));
2650     }
2651   else if (uimm (aarch64_get_instr (cpu), 17, 17))
2652     {
2653       index = uimm (aarch64_get_instr (cpu), 20, 18);
2654
2655       for (i = 0; i < (full ? 8 : 4); i++)
2656         aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vs, index));
2657     }
2658   else if (uimm (aarch64_get_instr (cpu), 18, 18))
2659     {
2660       index = uimm (aarch64_get_instr (cpu), 20, 19);
2661
2662       for (i = 0; i < (full ? 4 : 2); i++)
2663         aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vs, index));
2664     }
2665   else
2666     {
2667       if (uimm (aarch64_get_instr (cpu), 19, 19) == 0)
2668         HALT_UNALLOC;
2669
2670       if (! full)
2671         HALT_UNALLOC;
2672
2673       index = uimm (aarch64_get_instr (cpu), 20, 20);
2674
2675       for (i = 0; i < 2; i++)
2676         aarch64_set_vec_u64 (cpu, vd, i, aarch64_get_vec_u64 (cpu, vs, index));
2677     }
2678 }
2679
2680 static void
2681 do_vec_TBL (sim_cpu *cpu)
2682 {
2683   /* instr[31]    = 0
2684      instr[30]    = half(0)/full(1)
2685      instr[29,21] = 00 1110 000
2686      instr[20,16] = Vm
2687      instr[15]    = 0
2688      instr[14,13] = vec length
2689      instr[12,10] = 000
2690      instr[9,5]   = V start
2691      instr[4,0]   = V dest  */
2692
2693   int full    = uimm (aarch64_get_instr (cpu), 30, 30);
2694   int len     = uimm (aarch64_get_instr (cpu), 14, 13) + 1;
2695   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2696   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2697   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2698   unsigned i;
2699
2700   NYI_assert (29, 21, 0x070);
2701   NYI_assert (12, 10, 0);
2702
2703   for (i = 0; i < (full ? 16 : 8); i++)
2704     {
2705       unsigned int selector = aarch64_get_vec_u8 (cpu, vm, i);
2706       uint8_t val;
2707
2708       if (selector < 16)
2709         val = aarch64_get_vec_u8 (cpu, vn, selector);
2710       else if (selector < 32)
2711         val = len < 2 ? 0 : aarch64_get_vec_u8 (cpu, vn + 1, selector - 16);
2712       else if (selector < 48)
2713         val = len < 3 ? 0 : aarch64_get_vec_u8 (cpu, vn + 2, selector - 32);
2714       else if (selector < 64)
2715         val = len < 4 ? 0 : aarch64_get_vec_u8 (cpu, vn + 3, selector - 48);
2716       else
2717         val = 0;
2718
2719       aarch64_set_vec_u8 (cpu, vd, i, val);
2720     }
2721 }
2722
2723 static void
2724 do_vec_TRN (sim_cpu *cpu)
2725 {
2726   /* instr[31]    = 0
2727      instr[30]    = half(0)/full(1)
2728      instr[29,24] = 00 1110
2729      instr[23,22] = size
2730      instr[21]    = 0
2731      instr[20,16] = Vm
2732      instr[15]    = 0
2733      instr[14]    = TRN1 (0) / TRN2 (1)
2734      instr[13,10] = 1010
2735      instr[9,5]   = V source
2736      instr[4,0]   = V dest.  */
2737
2738   int full    = uimm (aarch64_get_instr (cpu), 30, 30);
2739   int second  = uimm (aarch64_get_instr (cpu), 14, 14);
2740   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2741   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2742   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2743   unsigned i;
2744
2745   NYI_assert (29, 24, 0x0E);
2746   NYI_assert (13, 10, 0xA);
2747
2748   switch (uimm (aarch64_get_instr (cpu), 23, 22))
2749     {
2750     case 0:
2751       for (i = 0; i < (full ? 8 : 4); i++)
2752         {
2753           aarch64_set_vec_u8
2754             (cpu, vd, i * 2,
2755              aarch64_get_vec_u8 (cpu, second ? vm : vn, i * 2));
2756           aarch64_set_vec_u8
2757             (cpu, vd, 1 * 2 + 1,
2758              aarch64_get_vec_u8 (cpu, second ? vn : vm, i * 2 + 1));
2759         }
2760       break;
2761
2762     case 1:
2763       for (i = 0; i < (full ? 4 : 2); i++)
2764         {
2765           aarch64_set_vec_u16
2766             (cpu, vd, i * 2,
2767              aarch64_get_vec_u16 (cpu, second ? vm : vn, i * 2));
2768           aarch64_set_vec_u16
2769             (cpu, vd, 1 * 2 + 1,
2770              aarch64_get_vec_u16 (cpu, second ? vn : vm, i * 2 + 1));
2771         }
2772       break;
2773
2774     case 2:
2775       aarch64_set_vec_u32
2776         (cpu, vd, 0, aarch64_get_vec_u32 (cpu, second ? vm : vn, 0));
2777       aarch64_set_vec_u32
2778         (cpu, vd, 1, aarch64_get_vec_u32 (cpu, second ? vn : vm, 1));
2779       aarch64_set_vec_u32
2780         (cpu, vd, 2, aarch64_get_vec_u32 (cpu, second ? vm : vn, 2));
2781       aarch64_set_vec_u32
2782         (cpu, vd, 3, aarch64_get_vec_u32 (cpu, second ? vn : vm, 3));
2783       break;
2784
2785     case 3:
2786       if (! full)
2787         HALT_UNALLOC;
2788
2789       aarch64_set_vec_u64 (cpu, vd, 0,
2790                            aarch64_get_vec_u64 (cpu, second ? vm : vn, 0));
2791       aarch64_set_vec_u64 (cpu, vd, 1,
2792                            aarch64_get_vec_u64 (cpu, second ? vn : vm, 1));
2793       break;
2794     }
2795 }
2796
2797 static void
2798 do_vec_DUP_scalar_into_vector (sim_cpu *cpu)
2799 {
2800   /* instr[31]    = 0
2801      instr[30]    = 0=> zero top 64-bits, 1=> duplicate into top 64-bits
2802                     [must be 1 for 64-bit xfer]
2803      instr[29,20] = 00 1110 0000
2804      instr[19,16] = element size: 0001=> 8-bits, 0010=> 16-bits,
2805                                   0100=> 32-bits. 1000=>64-bits
2806      instr[15,10] = 0000 11
2807      instr[9,5]   = W source
2808      instr[4,0]   = V dest.  */
2809
2810   unsigned i;
2811   unsigned Vd = uimm (aarch64_get_instr (cpu), 4, 0);
2812   unsigned Rs = uimm (aarch64_get_instr (cpu), 9, 5);
2813   int both    = uimm (aarch64_get_instr (cpu), 30, 30);
2814
2815   NYI_assert (29, 20, 0x0E0);
2816   NYI_assert (15, 10, 0x03);
2817
2818   switch (uimm (aarch64_get_instr (cpu), 19, 16))
2819     {
2820     case 1:
2821       for (i = 0; i < (both ? 16 : 8); i++)
2822         aarch64_set_vec_u8 (cpu, Vd, i, aarch64_get_reg_u8 (cpu, Rs, NO_SP));
2823       break;
2824
2825     case 2:
2826       for (i = 0; i < (both ? 8 : 4); i++)
2827         aarch64_set_vec_u16 (cpu, Vd, i, aarch64_get_reg_u16 (cpu, Rs, NO_SP));
2828       break;
2829
2830     case 4:
2831       for (i = 0; i < (both ? 4 : 2); i++)
2832         aarch64_set_vec_u32 (cpu, Vd, i, aarch64_get_reg_u32 (cpu, Rs, NO_SP));
2833       break;
2834
2835     case 8:
2836       if (!both)
2837         HALT_NYI;
2838       aarch64_set_vec_u64 (cpu, Vd, 0, aarch64_get_reg_u64 (cpu, Rs, NO_SP));
2839       aarch64_set_vec_u64 (cpu, Vd, 1, aarch64_get_reg_u64 (cpu, Rs, NO_SP));
2840       break;
2841
2842     default:
2843       HALT_NYI;
2844     }
2845 }
2846
2847 static void
2848 do_vec_UZP (sim_cpu *cpu)
2849 {
2850   /* instr[31]    = 0
2851      instr[30]    = half(0)/full(1)
2852      instr[29,24] = 00 1110
2853      instr[23,22] = size: byte(00), half(01), word (10), long (11)
2854      instr[21]    = 0
2855      instr[20,16] = Vm
2856      instr[15]    = 0
2857      instr[14]    = lower (0) / upper (1)
2858      instr[13,10] = 0110
2859      instr[9,5]   = Vn
2860      instr[4,0]   = Vd.  */
2861
2862   int full = uimm (aarch64_get_instr (cpu), 30, 30);
2863   int upper = uimm (aarch64_get_instr (cpu), 14, 14);
2864
2865   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2866   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2867   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2868
2869   uint64_t val_m1 = aarch64_get_vec_u64 (cpu, vm, 0);
2870   uint64_t val_m2 = aarch64_get_vec_u64 (cpu, vm, 1);
2871   uint64_t val_n1 = aarch64_get_vec_u64 (cpu, vn, 0);
2872   uint64_t val_n2 = aarch64_get_vec_u64 (cpu, vn, 1);
2873
2874   uint64_t val1 = 0;
2875   uint64_t val2 = 0;
2876
2877   uint64_t input1 = upper ? val_n1 : val_m1;
2878   uint64_t input2 = upper ? val_n2 : val_m2;
2879   unsigned i;
2880
2881   NYI_assert (29, 24, 0x0E);
2882   NYI_assert (21, 21, 0);
2883   NYI_assert (15, 15, 0);
2884   NYI_assert (13, 10, 6);
2885
2886   switch (uimm (aarch64_get_instr (cpu), 23, 23))
2887     {
2888     case 0:
2889       for (i = 0; i < 8; i++)
2890         {
2891           val1 |= (input1 >> (i * 8)) & (0xFFULL << (i * 8));
2892           val2 |= (input2 >> (i * 8)) & (0xFFULL << (i * 8));
2893         }
2894       break;
2895
2896     case 1:
2897       for (i = 0; i < 4; i++)
2898         {
2899           val1 |= (input1 >> (i * 16)) & (0xFFFFULL << (i * 16));
2900           val2 |= (input2 >> (i * 16)) & (0xFFFFULL << (i * 16));
2901         }
2902       break;
2903
2904     case 2:
2905       val1 = ((input1 & 0xFFFFFFFF) | ((input1 >> 32) & 0xFFFFFFFF00000000ULL));
2906       val2 = ((input2 & 0xFFFFFFFF) | ((input2 >> 32) & 0xFFFFFFFF00000000ULL));
2907
2908     case 3:
2909       val1 = input1;
2910       val2 = input2;
2911            break;
2912     }
2913
2914   aarch64_set_vec_u64 (cpu, vd, 0, val1);
2915   if (full)
2916     aarch64_set_vec_u64 (cpu, vd, 1, val2);
2917 }
2918
2919 static void
2920 do_vec_ZIP (sim_cpu *cpu)
2921 {
2922   /* instr[31]    = 0
2923      instr[30]    = half(0)/full(1)
2924      instr[29,24] = 00 1110
2925      instr[23,22] = size: byte(00), hald(01), word (10), long (11)
2926      instr[21]    = 0
2927      instr[20,16] = Vm
2928      instr[15]    = 0
2929      instr[14]    = lower (0) / upper (1)
2930      instr[13,10] = 1110
2931      instr[9,5]   = Vn
2932      instr[4,0]   = Vd.  */
2933
2934   int full = uimm (aarch64_get_instr (cpu), 30, 30);
2935   int upper = uimm (aarch64_get_instr (cpu), 14, 14);
2936
2937   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
2938   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
2939   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
2940
2941   uint64_t val_m1 = aarch64_get_vec_u64 (cpu, vm, 0);
2942   uint64_t val_m2 = aarch64_get_vec_u64 (cpu, vm, 1);
2943   uint64_t val_n1 = aarch64_get_vec_u64 (cpu, vn, 0);
2944   uint64_t val_n2 = aarch64_get_vec_u64 (cpu, vn, 1);
2945
2946   uint64_t val1 = 0;
2947   uint64_t val2 = 0;
2948
2949   uint64_t input1 = upper ? val_n1 : val_m1;
2950   uint64_t input2 = upper ? val_n2 : val_m2;
2951
2952   NYI_assert (29, 24, 0x0E);
2953   NYI_assert (21, 21, 0);
2954   NYI_assert (15, 15, 0);
2955   NYI_assert (13, 10, 0xE);
2956
2957   switch (uimm (aarch64_get_instr (cpu), 23, 23))
2958     {
2959     case 0:
2960       val1 =
2961           ((input1 <<  0) & (0xFF    <<  0))
2962         | ((input2 <<  8) & (0xFF    <<  8))
2963         | ((input1 <<  8) & (0xFF    << 16))
2964         | ((input2 << 16) & (0xFF    << 24))
2965         | ((input1 << 16) & (0xFFULL << 32))
2966         | ((input2 << 24) & (0xFFULL << 40))
2967         | ((input1 << 24) & (0xFFULL << 48))
2968         | ((input2 << 32) & (0xFFULL << 56));
2969
2970       val2 =
2971           ((input1 >> 32) & (0xFF    <<  0))
2972         | ((input2 >> 24) & (0xFF    <<  8))
2973         | ((input1 >> 24) & (0xFF    << 16))
2974         | ((input2 >> 16) & (0xFF    << 24))
2975         | ((input1 >> 16) & (0xFFULL << 32))
2976         | ((input2 >>  8) & (0xFFULL << 40))
2977         | ((input1 >>  8) & (0xFFULL << 48))
2978         | ((input2 >>  0) & (0xFFULL << 56));
2979       break;
2980
2981     case 1:
2982       val1 =
2983           ((input1 <<  0) & (0xFFFF    <<  0))
2984         | ((input2 << 16) & (0xFFFF    << 16))
2985         | ((input1 << 16) & (0xFFFFULL << 32))
2986         | ((input2 << 32) & (0xFFFFULL << 48));
2987
2988       val2 =
2989           ((input1 >> 32) & (0xFFFF    <<  0))
2990         | ((input2 >> 16) & (0xFFFF    << 16))
2991         | ((input1 >> 16) & (0xFFFFULL << 32))
2992         | ((input2 >>  0) & (0xFFFFULL << 48));
2993       break;
2994
2995     case 2:
2996       val1 = (input1 & 0xFFFFFFFFULL) | (input2 << 32);
2997       val2 = (input2 & 0xFFFFFFFFULL) | (input1 << 32);
2998       break;
2999
3000     case 3:
3001       val1 = input1;
3002       val2 = input2;
3003       break;
3004     }
3005
3006   aarch64_set_vec_u64 (cpu, vd, 0, val1);
3007   if (full)
3008     aarch64_set_vec_u64 (cpu, vd, 1, val2);
3009 }
3010
3011 /* Floating point immediates are encoded in 8 bits.
3012    fpimm[7] = sign bit.
3013    fpimm[6:4] = signed exponent.
3014    fpimm[3:0] = fraction (assuming leading 1).
3015    i.e. F = s * 1.f * 2^(e - b).  */
3016
3017 static float
3018 fp_immediate_for_encoding_32 (uint32_t imm8)
3019 {
3020   float u;
3021   uint32_t s, e, f, i;
3022
3023   s = (imm8 >> 7) & 0x1;
3024   e = (imm8 >> 4) & 0x7;
3025   f = imm8 & 0xf;
3026
3027   /* The fp value is s * n/16 * 2r where n is 16+e.  */
3028   u = (16.0 + f) / 16.0;
3029
3030   /* N.B. exponent is signed.  */
3031   if (e < 4)
3032     {
3033       int epos = e;
3034
3035       for (i = 0; i <= epos; i++)
3036         u *= 2.0;
3037     }
3038   else
3039     {
3040       int eneg = 7 - e;
3041
3042       for (i = 0; i < eneg; i++)
3043         u /= 2.0;
3044     }
3045
3046   if (s)
3047     u = - u;
3048
3049   return u;
3050 }
3051
3052 static double
3053 fp_immediate_for_encoding_64 (uint32_t imm8)
3054 {
3055   double u;
3056   uint32_t s, e, f, i;
3057
3058   s = (imm8 >> 7) & 0x1;
3059   e = (imm8 >> 4) & 0x7;
3060   f = imm8 & 0xf;
3061
3062   /* The fp value is s * n/16 * 2r where n is 16+e.  */
3063   u = (16.0 + f) / 16.0;
3064
3065   /* N.B. exponent is signed.  */
3066   if (e < 4)
3067     {
3068       int epos = e;
3069
3070       for (i = 0; i <= epos; i++)
3071         u *= 2.0;
3072     }
3073   else
3074     {
3075       int eneg = 7 - e;
3076
3077       for (i = 0; i < eneg; i++)
3078         u /= 2.0;
3079     }
3080
3081   if (s)
3082     u = - u;
3083
3084   return u;
3085 }
3086
3087 static void
3088 do_vec_MOV_immediate (sim_cpu *cpu)
3089 {
3090   /* instr[31]    = 0
3091      instr[30]    = full/half selector
3092      instr[29,19] = 00111100000
3093      instr[18,16] = high 3 bits of uimm8
3094      instr[15,12] = size & shift:
3095                                   0000 => 32-bit
3096                                   0010 => 32-bit + LSL#8
3097                                   0100 => 32-bit + LSL#16
3098                                   0110 => 32-bit + LSL#24
3099                                   1010 => 16-bit + LSL#8
3100                                   1000 => 16-bit
3101                                   1101 => 32-bit + MSL#16
3102                                   1100 => 32-bit + MSL#8
3103                                   1110 => 8-bit
3104                                   1111 => double
3105      instr[11,10] = 01
3106      instr[9,5]   = low 5-bits of uimm8
3107      instr[4,0]   = Vd.  */
3108
3109   int full     = uimm (aarch64_get_instr (cpu), 30, 30);
3110   unsigned vd  = uimm (aarch64_get_instr (cpu), 4, 0);
3111   unsigned val = uimm (aarch64_get_instr (cpu), 18, 16) << 5
3112     | uimm (aarch64_get_instr (cpu), 9, 5);
3113   unsigned i;
3114
3115   NYI_assert (29, 19, 0x1E0);
3116   NYI_assert (11, 10, 1);
3117
3118   switch (uimm (aarch64_get_instr (cpu), 15, 12))
3119     {
3120     case 0x0: /* 32-bit, no shift.  */
3121     case 0x2: /* 32-bit, shift by 8.  */
3122     case 0x4: /* 32-bit, shift by 16.  */
3123     case 0x6: /* 32-bit, shift by 24.  */
3124       val <<= (8 * uimm (aarch64_get_instr (cpu), 14, 13));
3125       for (i = 0; i < (full ? 4 : 2); i++)
3126         aarch64_set_vec_u32 (cpu, vd, i, val);
3127       break;
3128
3129     case 0xa: /* 16-bit, shift by 8.  */
3130       val <<= 8;
3131       /* Fall through.  */
3132     case 0x8: /* 16-bit, no shift.  */
3133       for (i = 0; i < (full ? 8 : 4); i++)
3134         aarch64_set_vec_u16 (cpu, vd, i, val);
3135       /* Fall through.  */
3136     case 0xd: /* 32-bit, mask shift by 16.  */
3137       val <<= 8;
3138       val |= 0xFF;
3139       /* Fall through.  */
3140     case 0xc: /* 32-bit, mask shift by 8. */
3141       val <<= 8;
3142       val |= 0xFF;
3143       for (i = 0; i < (full ? 4 : 2); i++)
3144         aarch64_set_vec_u32 (cpu, vd, i, val);
3145       break;
3146
3147     case 0xe: /* 8-bit, no shift.  */
3148       for (i = 0; i < (full ? 16 : 8); i++)
3149         aarch64_set_vec_u8 (cpu, vd, i, val);
3150       break;
3151
3152     case 0xf: /* FMOV Vs.{2|4}S, #fpimm.  */
3153       {
3154         float u = fp_immediate_for_encoding_32 (val);
3155         for (i = 0; i < (full ? 4 : 2); i++)
3156           aarch64_set_vec_float (cpu, vd, i, u);
3157         break;
3158       }
3159
3160     default:
3161       HALT_NYI;
3162     }
3163 }
3164
3165 static void
3166 do_vec_MVNI (sim_cpu *cpu)
3167 {
3168   /* instr[31]    = 0
3169      instr[30]    = full/half selector
3170      instr[29,19] = 10111100000
3171      instr[18,16] = high 3 bits of uimm8
3172      instr[15,12] = selector
3173      instr[11,10] = 01
3174      instr[9,5]   = low 5-bits of uimm8
3175      instr[4,0]   = Vd.  */
3176
3177   int full     = uimm (aarch64_get_instr (cpu), 30, 30);
3178   unsigned vd  = uimm (aarch64_get_instr (cpu), 4, 0);
3179   unsigned val = uimm (aarch64_get_instr (cpu), 18, 16) << 5
3180     | uimm (aarch64_get_instr (cpu), 9, 5);
3181   unsigned i;
3182
3183   NYI_assert (29, 19, 0x5E0);
3184   NYI_assert (11, 10, 1);
3185
3186   switch (uimm (aarch64_get_instr (cpu), 15, 12))
3187     {
3188     case 0x0: /* 32-bit, no shift.  */
3189     case 0x2: /* 32-bit, shift by 8.  */
3190     case 0x4: /* 32-bit, shift by 16.  */
3191     case 0x6: /* 32-bit, shift by 24.  */
3192       val <<= (8 * uimm (aarch64_get_instr (cpu), 14, 13));
3193       val = ~ val;
3194       for (i = 0; i < (full ? 4 : 2); i++)
3195         aarch64_set_vec_u32 (cpu, vd, i, val);
3196       return;
3197
3198     case 0xa: /* 16-bit, 8 bit shift. */
3199       val <<= 8;
3200     case 0x8: /* 16-bit, no shift. */
3201       val = ~ val;
3202       for (i = 0; i < (full ? 8 : 4); i++)
3203         aarch64_set_vec_u16 (cpu, vd, i, val);
3204       return;
3205
3206     case 0xd: /* 32-bit, mask shift by 16.  */
3207       val <<= 8;
3208       val |= 0xFF;
3209     case 0xc: /* 32-bit, mask shift by 8. */
3210       val <<= 8;
3211       val |= 0xFF;
3212       val = ~ val;
3213       for (i = 0; i < (full ? 4 : 2); i++)
3214         aarch64_set_vec_u32 (cpu, vd, i, val);
3215       return;
3216
3217     case 0xE: /* MOVI Dn, #mask64 */
3218       {
3219         uint64_t mask = 0;
3220
3221         for (i = 0; i < 8; i++)
3222           if (val & (1 << i))
3223             mask |= (0xF << (i * 4));
3224         aarch64_set_vec_u64 (cpu, vd, 0, mask);
3225         aarch64_set_vec_u64 (cpu, vd, 1, 0);
3226         return;
3227       }
3228
3229     case 0xf: /* FMOV Vd.2D, #fpimm.  */
3230       {
3231         double u = fp_immediate_for_encoding_64 (val);
3232
3233         if (! full)
3234           HALT_UNALLOC;
3235
3236         aarch64_set_vec_double (cpu, vd, 0, u);
3237         aarch64_set_vec_double (cpu, vd, 1, u);
3238         return;
3239       }
3240
3241     default:
3242       HALT_NYI;
3243     }
3244 }
3245
3246 #define ABS(A) ((A) < 0 ? - (A) : (A))
3247
3248 static void
3249 do_vec_ABS (sim_cpu *cpu)
3250 {
3251   /* instr[31]    = 0
3252      instr[30]    = half(0)/full(1)
3253      instr[29,24] = 00 1110
3254      instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3255      instr[21,10] = 10 0000 1011 10
3256      instr[9,5]   = Vn
3257      instr[4.0]   = Vd.  */
3258
3259   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3260   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3261   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
3262   unsigned i;
3263
3264   NYI_assert (29, 24, 0x0E);
3265   NYI_assert (21, 10, 0x82E);
3266
3267   switch (uimm (aarch64_get_instr (cpu), 23, 22))
3268     {
3269     case 0:
3270       for (i = 0; i < (full ? 16 : 8); i++)
3271         aarch64_set_vec_s8 (cpu, vd, i,
3272                             ABS (aarch64_get_vec_s8 (cpu, vn, i)));
3273       break;
3274
3275     case 1:
3276       for (i = 0; i < (full ? 8 : 4); i++)
3277         aarch64_set_vec_s16 (cpu, vd, i,
3278                              ABS (aarch64_get_vec_s16 (cpu, vn, i)));
3279       break;
3280
3281     case 2:
3282       for (i = 0; i < (full ? 4 : 2); i++)
3283         aarch64_set_vec_s32 (cpu, vd, i,
3284                              ABS (aarch64_get_vec_s32 (cpu, vn, i)));
3285       break;
3286
3287     case 3:
3288       if (! full)
3289         HALT_NYI;
3290       for (i = 0; i < 2; i++)
3291         aarch64_set_vec_s64 (cpu, vd, i,
3292                              ABS (aarch64_get_vec_s64 (cpu, vn, i)));
3293       break;
3294     }
3295 }
3296
3297 static void
3298 do_vec_ADDV (sim_cpu *cpu)
3299 {
3300   /* instr[31]    = 0
3301      instr[30]    = full/half selector
3302      instr[29,24] = 00 1110
3303      instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3304      instr[21,10] = 11 0001 1011 10
3305      instr[9,5]   = Vm
3306      instr[4.0]   = Rd.  */
3307
3308   unsigned vm = uimm (aarch64_get_instr (cpu), 9, 5);
3309   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
3310   unsigned i;
3311   uint64_t val = 0;
3312   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3313
3314   NYI_assert (29, 24, 0x0E);
3315   NYI_assert (21, 10, 0xC6E);
3316
3317   switch (uimm (aarch64_get_instr (cpu), 23, 22))
3318     {
3319     case 0:
3320       for (i = 0; i < (full ? 16 : 8); i++)
3321         val += aarch64_get_vec_u8 (cpu, vm, i);
3322       aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3323       return;
3324
3325     case 1:
3326       for (i = 0; i < (full ? 8 : 4); i++)
3327         val += aarch64_get_vec_u16 (cpu, vm, i);
3328       aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3329       return;
3330
3331     case 2:
3332       for (i = 0; i < (full ? 4 : 2); i++)
3333         val += aarch64_get_vec_u32 (cpu, vm, i);
3334       aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3335       return;
3336
3337     case 3:
3338       if (! full)
3339         HALT_UNALLOC;
3340       val = aarch64_get_vec_u64 (cpu, vm, 0);
3341       val += aarch64_get_vec_u64 (cpu, vm, 1);
3342       aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
3343       return;
3344     }
3345 }
3346
3347 static void
3348 do_vec_ins_2 (sim_cpu *cpu)
3349 {
3350   /* instr[31,21] = 01001110000
3351      instr[20,18] = size & element selector
3352      instr[17,14] = 0000
3353      instr[13]    = direction: to vec(0), from vec (1)
3354      instr[12,10] = 111
3355      instr[9,5]   = Vm
3356      instr[4,0]   = Vd.  */
3357
3358   unsigned elem;
3359   unsigned vm = uimm (aarch64_get_instr (cpu), 9, 5);
3360   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3361
3362   NYI_assert (31, 21, 0x270);
3363   NYI_assert (17, 14, 0);
3364   NYI_assert (12, 10, 7);
3365
3366   if (uimm (aarch64_get_instr (cpu), 13, 13) == 1)
3367     {
3368       if (uimm (aarch64_get_instr (cpu), 18, 18) == 1)
3369         {
3370           /* 32-bit moves.  */
3371           elem = uimm (aarch64_get_instr (cpu), 20, 19);
3372           aarch64_set_reg_u64 (cpu, vd, NO_SP,
3373                                aarch64_get_vec_u32 (cpu, vm, elem));
3374         }
3375       else
3376         {
3377           /* 64-bit moves.  */
3378           if (uimm (aarch64_get_instr (cpu), 19, 19) != 1)
3379             HALT_NYI;
3380
3381           elem = uimm (aarch64_get_instr (cpu), 20, 20);
3382           aarch64_set_reg_u64 (cpu, vd, NO_SP,
3383                                aarch64_get_vec_u64 (cpu, vm, elem));
3384         }
3385     }
3386   else
3387     {
3388       if (uimm (aarch64_get_instr (cpu), 18, 18) == 1)
3389         {
3390           /* 32-bit moves.  */
3391           elem = uimm (aarch64_get_instr (cpu), 20, 19);
3392           aarch64_set_vec_u32 (cpu, vd, elem,
3393                                aarch64_get_reg_u32 (cpu, vm, NO_SP));
3394         }
3395       else
3396         {
3397           /* 64-bit moves.  */
3398           if (uimm (aarch64_get_instr (cpu), 19, 19) != 1)
3399             HALT_NYI;
3400
3401           elem = uimm (aarch64_get_instr (cpu), 20, 20);
3402           aarch64_set_vec_u64 (cpu, vd, elem,
3403                                aarch64_get_reg_u64 (cpu, vm, NO_SP));
3404         }
3405     }
3406 }
3407
3408 static void
3409 do_vec_mull (sim_cpu *cpu)
3410 {
3411   /* instr[31]    = 0
3412      instr[30]    = lower(0)/upper(1) selector
3413      instr[29]    = signed(0)/unsigned(1)
3414      instr[28,24] = 0 1110
3415      instr[23,22] = size: 8-bit (00), 16-bit (01), 32-bit (10)
3416      instr[21]    = 1
3417      instr[20,16] = Vm
3418      instr[15,10] = 11 0000
3419      instr[9,5]   = Vn
3420      instr[4.0]   = Vd.  */
3421
3422   int    unsign = uimm (aarch64_get_instr (cpu), 29, 29);
3423   int    bias = uimm (aarch64_get_instr (cpu), 30, 30);
3424   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3425   unsigned vn = uimm (aarch64_get_instr (cpu),  9,  5);
3426   unsigned vd = uimm (aarch64_get_instr (cpu),  4,  0);
3427   unsigned i;
3428
3429   NYI_assert (28, 24, 0x0E);
3430   NYI_assert (15, 10, 0x30);
3431
3432   switch (uimm (aarch64_get_instr (cpu), 23, 22))
3433     {
3434     case 0:
3435       if (bias)
3436         bias = 8;
3437       if (unsign)
3438         for (i = 0; i < 8; i++)
3439           aarch64_set_vec_u16 (cpu, vd, i,
3440                                aarch64_get_vec_u8 (cpu, vn, i + bias)
3441                                * aarch64_get_vec_u8 (cpu, vm, i + bias));
3442       else
3443         for (i = 0; i < 8; i++)
3444           aarch64_set_vec_s16 (cpu, vd, i,
3445                                aarch64_get_vec_s8 (cpu, vn, i + bias)
3446                                * aarch64_get_vec_s8 (cpu, vm, i + bias));
3447       return;
3448
3449     case 1:
3450       if (bias)
3451         bias = 4;
3452       if (unsign)
3453         for (i = 0; i < 4; i++)
3454           aarch64_set_vec_u32 (cpu, vd, i,
3455                                aarch64_get_vec_u16 (cpu, vn, i + bias)
3456                                * aarch64_get_vec_u16 (cpu, vm, i + bias));
3457       else
3458         for (i = 0; i < 4; i++)
3459           aarch64_set_vec_s32 (cpu, vd, i,
3460                                aarch64_get_vec_s16 (cpu, vn, i + bias)
3461                                * aarch64_get_vec_s16 (cpu, vm, i + bias));
3462       return;
3463
3464     case 2:
3465       if (bias)
3466         bias = 2;
3467       if (unsign)
3468         for (i = 0; i < 2; i++)
3469           aarch64_set_vec_u64 (cpu, vd, i,
3470                                (uint64_t) aarch64_get_vec_u32 (cpu, vn,
3471                                                                i + bias)
3472                                * (uint64_t) aarch64_get_vec_u32 (cpu, vm,
3473                                                                  i + bias));
3474       else
3475         for (i = 0; i < 2; i++)
3476           aarch64_set_vec_s64 (cpu, vd, i,
3477                                aarch64_get_vec_s32 (cpu, vn, i + bias)
3478                                * aarch64_get_vec_s32 (cpu, vm, i + bias));
3479       return;
3480
3481     case 3:
3482       HALT_NYI;
3483     }
3484 }
3485
3486 static void
3487 do_vec_fadd (sim_cpu *cpu)
3488 {
3489   /* instr[31]    = 0
3490      instr[30]    = half(0)/full(1)
3491      instr[29,24] = 001110
3492      instr[23]    = FADD(0)/FSUB(1)
3493      instr[22]    = float (0)/double(1)
3494      instr[21]    = 1
3495      instr[20,16] = Vm
3496      instr[15,10] = 110101
3497      instr[9,5]   = Vn
3498      instr[4.0]   = Vd.  */
3499
3500   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3501   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3502   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3503   unsigned i;
3504   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3505
3506   NYI_assert (29, 24, 0x0E);
3507   NYI_assert (21, 21, 1);
3508   NYI_assert (15, 10, 0x35);
3509
3510   if (uimm (aarch64_get_instr (cpu), 23, 23))
3511     {
3512       if (uimm (aarch64_get_instr (cpu), 22, 22))
3513         {
3514           if (! full)
3515             HALT_NYI;
3516
3517           for (i = 0; i < 2; i++)
3518             aarch64_set_vec_double (cpu, vd, i,
3519                                     aarch64_get_vec_double (cpu, vn, i)
3520                                     - aarch64_get_vec_double (cpu, vm, i));
3521         }
3522       else
3523         {
3524           for (i = 0; i < (full ? 4 : 2); i++)
3525             aarch64_set_vec_float (cpu, vd, i,
3526                                    aarch64_get_vec_float (cpu, vn, i)
3527                                    - aarch64_get_vec_float (cpu, vm, i));
3528         }
3529     }
3530   else
3531     {
3532       if (uimm (aarch64_get_instr (cpu), 22, 22))
3533         {
3534           if (! full)
3535             HALT_NYI;
3536
3537           for (i = 0; i < 2; i++)
3538             aarch64_set_vec_double (cpu, vd, i,
3539                                     aarch64_get_vec_double (cpu, vm, i)
3540                                     + aarch64_get_vec_double (cpu, vn, i));
3541         }
3542       else
3543         {
3544           for (i = 0; i < (full ? 4 : 2); i++)
3545             aarch64_set_vec_float (cpu, vd, i,
3546                                    aarch64_get_vec_float (cpu, vm, i)
3547                                    + aarch64_get_vec_float (cpu, vn, i));
3548         }
3549     }
3550 }
3551
3552 static void
3553 do_vec_add (sim_cpu *cpu)
3554 {
3555   /* instr[31]    = 0
3556      instr[30]    = full/half selector
3557      instr[29,24] = 001110
3558      instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit, 11=> 64-bit
3559      instr[21]    = 1
3560      instr[20,16] = Vn
3561      instr[15,10] = 100001
3562      instr[9,5]   = Vm
3563      instr[4.0]   = Vd.  */
3564
3565   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3566   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3567   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3568   unsigned i;
3569   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3570
3571   NYI_assert (29, 24, 0x0E);
3572   NYI_assert (21, 21, 1);
3573   NYI_assert (15, 10, 0x21);
3574
3575   switch (uimm (aarch64_get_instr (cpu), 23, 22))
3576     {
3577     case 0:
3578       for (i = 0; i < (full ? 16 : 8); i++)
3579         aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vn, i)
3580                             + aarch64_get_vec_u8 (cpu, vm, i));
3581       return;
3582
3583     case 1:
3584       for (i = 0; i < (full ? 8 : 4); i++)
3585         aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vn, i)
3586                              + aarch64_get_vec_u16 (cpu, vm, i));
3587       return;
3588
3589     case 2:
3590       for (i = 0; i < (full ? 4 : 2); i++)
3591         aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vn, i)
3592                              + aarch64_get_vec_u32 (cpu, vm, i));
3593       return;
3594
3595     case 3:
3596       if (! full)
3597         HALT_UNALLOC;
3598       aarch64_set_vec_u64 (cpu, vd, 0, aarch64_get_vec_u64 (cpu, vn, 0)
3599                            + aarch64_get_vec_u64 (cpu, vm, 0));
3600       aarch64_set_vec_u64 (cpu, vd, 1,
3601                            aarch64_get_vec_u64 (cpu, vn, 1)
3602                            + aarch64_get_vec_u64 (cpu, vm, 1));
3603       return;
3604     }
3605 }
3606
3607 static void
3608 do_vec_mul (sim_cpu *cpu)
3609 {
3610   /* instr[31]    = 0
3611      instr[30]    = full/half selector
3612      instr[29,24] = 00 1110
3613      instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3614      instr[21]    = 1
3615      instr[20,16] = Vn
3616      instr[15,10] = 10 0111
3617      instr[9,5]   = Vm
3618      instr[4.0]   = Vd.  */
3619
3620   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3621   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3622   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3623   unsigned i;
3624   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3625
3626   NYI_assert (29, 24, 0x0E);
3627   NYI_assert (21, 21, 1);
3628   NYI_assert (15, 10, 0x27);
3629
3630   switch (uimm (aarch64_get_instr (cpu), 23, 22))
3631     {
3632     case 0:
3633       for (i = 0; i < (full ? 16 : 8); i++)
3634         {
3635           uint16_t val = aarch64_get_vec_u8 (cpu, vn, i);
3636           val *= aarch64_get_vec_u8 (cpu, vm, i);
3637
3638           aarch64_set_vec_u16 (cpu, vd, i, val);
3639         }
3640       return;
3641
3642     case 1:
3643       for (i = 0; i < (full ? 8 : 4); i++)
3644         {
3645           uint32_t val = aarch64_get_vec_u16 (cpu, vn, i);
3646           val *= aarch64_get_vec_u16 (cpu, vm, i);
3647
3648           aarch64_set_vec_u32 (cpu, vd, i, val);
3649         }
3650       return;
3651
3652     case 2:
3653       for (i = 0; i < (full ? 4 : 2); i++)
3654         {
3655           uint64_t val = aarch64_get_vec_u32 (cpu, vn, i);
3656           val *= aarch64_get_vec_u32 (cpu, vm, i);
3657
3658           aarch64_set_vec_u64 (cpu, vd, i, val);
3659         }
3660       return;
3661
3662     case 3:
3663       HALT_UNALLOC;
3664     }
3665 }
3666
3667 static void
3668 do_vec_MLA (sim_cpu *cpu)
3669 {
3670   /* instr[31]    = 0
3671      instr[30]    = full/half selector
3672      instr[29,24] = 00 1110
3673      instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
3674      instr[21]    = 1
3675      instr[20,16] = Vn
3676      instr[15,10] = 1001 01
3677      instr[9,5]   = Vm
3678      instr[4.0]   = Vd.  */
3679
3680   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3681   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3682   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3683   unsigned i;
3684   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3685
3686   NYI_assert (29, 24, 0x0E);
3687   NYI_assert (21, 21, 1);
3688   NYI_assert (15, 10, 0x25);
3689
3690   switch (uimm (aarch64_get_instr (cpu), 23, 22))
3691     {
3692     case 0:
3693       for (i = 0; i < (full ? 16 : 8); i++)
3694         {
3695           uint16_t val = aarch64_get_vec_u8 (cpu, vn, i);
3696           val *= aarch64_get_vec_u8 (cpu, vm, i);
3697           val += aarch64_get_vec_u8 (cpu, vd, i);
3698
3699           aarch64_set_vec_u16 (cpu, vd, i, val);
3700         }
3701       return;
3702
3703     case 1:
3704       for (i = 0; i < (full ? 8 : 4); i++)
3705         {
3706           uint32_t val = aarch64_get_vec_u16 (cpu, vn, i);
3707           val *= aarch64_get_vec_u16 (cpu, vm, i);
3708           val += aarch64_get_vec_u16 (cpu, vd, i);
3709
3710           aarch64_set_vec_u32 (cpu, vd, i, val);
3711         }
3712       return;
3713
3714     case 2:
3715       for (i = 0; i < (full ? 4 : 2); i++)
3716         {
3717           uint64_t val = aarch64_get_vec_u32 (cpu, vn, i);
3718           val *= aarch64_get_vec_u32 (cpu, vm, i);
3719           val += aarch64_get_vec_u32 (cpu, vd, i);
3720
3721           aarch64_set_vec_u64 (cpu, vd, i, val);
3722         }
3723       return;
3724
3725     case 3:
3726       HALT_UNALLOC;
3727     }
3728 }
3729
3730 static float
3731 fmaxnm (float a, float b)
3732 {
3733   if (fpclassify (a) == FP_NORMAL)
3734     {
3735       if (fpclassify (b) == FP_NORMAL)
3736         return a > b ? a : b;
3737       return a;
3738     }
3739   else if (fpclassify (b) == FP_NORMAL)
3740     return b;
3741   return a;
3742 }
3743
3744 static float
3745 fminnm (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 double
3759 dmaxnm (double a, double 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 dminnm (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 void
3787 do_vec_FminmaxNMP (sim_cpu *cpu)
3788 {
3789   /* aarch64_get_instr (cpu)[31]    = 0
3790      aarch64_get_instr (cpu)[30]    = half (0)/full (1)
3791      aarch64_get_instr (cpu)[29,24] = 10 1110
3792      aarch64_get_instr (cpu)[23]    = max(0)/min(1)
3793      aarch64_get_instr (cpu)[22]    = float (0)/double (1)
3794      aarch64_get_instr (cpu)[21]    = 1
3795      aarch64_get_instr (cpu)[20,16] = Vn
3796      aarch64_get_instr (cpu)[15,10] = 1100 01
3797      aarch64_get_instr (cpu)[9,5]   = Vm
3798      aarch64_get_instr (cpu)[4.0]   = Vd.  */
3799
3800   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3801   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3802   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3803   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3804
3805   NYI_assert (29, 24, 0x2E);
3806   NYI_assert (21, 21, 1);
3807   NYI_assert (15, 10, 0x31);
3808
3809   if (uimm (aarch64_get_instr (cpu), 22, 22))
3810     {
3811       double (* fn)(double, double) = uimm (aarch64_get_instr (cpu), 23, 23)
3812         ? dminnm : dmaxnm;
3813
3814       if (! full)
3815         HALT_NYI;
3816       aarch64_set_vec_double (cpu, vd, 0,
3817                               fn (aarch64_get_vec_double (cpu, vn, 0),
3818                                   aarch64_get_vec_double (cpu, vn, 1)));
3819       aarch64_set_vec_double (cpu, vd, 0,
3820                               fn (aarch64_get_vec_double (cpu, vm, 0),
3821                                   aarch64_get_vec_double (cpu, vm, 1)));
3822     }
3823   else
3824     {
3825       float (* fn)(float, float) = uimm (aarch64_get_instr (cpu), 23, 23)
3826         ? fminnm : fmaxnm;
3827
3828       aarch64_set_vec_float (cpu, vd, 0,
3829                              fn (aarch64_get_vec_float (cpu, vn, 0),
3830                                  aarch64_get_vec_float (cpu, vn, 1)));
3831       if (full)
3832         aarch64_set_vec_float (cpu, vd, 1,
3833                                fn (aarch64_get_vec_float (cpu, vn, 2),
3834                                    aarch64_get_vec_float (cpu, vn, 3)));
3835
3836       aarch64_set_vec_float (cpu, vd, (full ? 2 : 1),
3837                              fn (aarch64_get_vec_float (cpu, vm, 0),
3838                                  aarch64_get_vec_float (cpu, vm, 1)));
3839       if (full)
3840         aarch64_set_vec_float (cpu, vd, 3,
3841                                fn (aarch64_get_vec_float (cpu, vm, 2),
3842                                    aarch64_get_vec_float (cpu, vm, 3)));
3843     }
3844 }
3845
3846 static void
3847 do_vec_AND (sim_cpu *cpu)
3848 {
3849   /* instr[31]    = 0
3850      instr[30]    = half (0)/full (1)
3851      instr[29,21] = 001110001
3852      instr[20,16] = Vm
3853      instr[15,10] = 000111
3854      instr[9,5]   = Vn
3855      instr[4.0]   = Vd.  */
3856
3857   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3858   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3859   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3860   unsigned i;
3861   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3862
3863   NYI_assert (29, 21, 0x071);
3864   NYI_assert (15, 10, 0x07);
3865
3866   for (i = 0; i < (full ? 4 : 2); i++)
3867     aarch64_set_vec_u32 (cpu, vd, i,
3868                          aarch64_get_vec_u32 (cpu, vn, i)
3869                          & aarch64_get_vec_u32 (cpu, vm, i));
3870 }
3871
3872 static void
3873 do_vec_BSL (sim_cpu *cpu)
3874 {
3875   /* instr[31]    = 0
3876      instr[30]    = half (0)/full (1)
3877      instr[29,21] = 101110011
3878      instr[20,16] = Vm
3879      instr[15,10] = 000111
3880      instr[9,5]   = Vn
3881      instr[4.0]   = Vd.  */
3882
3883   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3884   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3885   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3886   unsigned i;
3887   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3888
3889   NYI_assert (29, 21, 0x173);
3890   NYI_assert (15, 10, 0x07);
3891
3892   for (i = 0; i < (full ? 16 : 8); i++)
3893     aarch64_set_vec_u8 (cpu, vd, i,
3894                         (    aarch64_get_vec_u8 (cpu, vd, i)
3895                            & aarch64_get_vec_u8 (cpu, vn, i))
3896                         | ((~ aarch64_get_vec_u8 (cpu, vd, i))
3897                            & aarch64_get_vec_u8 (cpu, vm, i)));
3898 }
3899
3900 static void
3901 do_vec_EOR (sim_cpu *cpu)
3902 {
3903   /* instr[31]    = 0
3904      instr[30]    = half (0)/full (1)
3905      instr[29,21] = 10 1110 001
3906      instr[20,16] = Vm
3907      instr[15,10] = 000111
3908      instr[9,5]   = Vn
3909      instr[4.0]   = Vd.  */
3910
3911   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3912   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3913   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3914   unsigned i;
3915   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3916
3917   NYI_assert (29, 21, 0x171);
3918   NYI_assert (15, 10, 0x07);
3919
3920   for (i = 0; i < (full ? 4 : 2); i++)
3921     aarch64_set_vec_u32 (cpu, vd, i,
3922                          aarch64_get_vec_u32 (cpu, vn, i)
3923                          ^ aarch64_get_vec_u32 (cpu, vm, i));
3924 }
3925
3926 static void
3927 do_vec_bit (sim_cpu *cpu)
3928 {
3929   /* instr[31]    = 0
3930      instr[30]    = half (0)/full (1)
3931      instr[29,23] = 10 1110 1
3932      instr[22]    = BIT (0) / BIF (1)
3933      instr[21]    = 1
3934      instr[20,16] = Vm
3935      instr[15,10] = 0001 11
3936      instr[9,5]   = Vn
3937      instr[4.0]   = Vd.  */
3938
3939   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3940   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3941   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3942   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
3943   unsigned test_false = uimm (aarch64_get_instr (cpu), 22, 22);
3944   unsigned i;
3945
3946   NYI_assert (29, 23, 0x5D);
3947   NYI_assert (21, 21, 1);
3948   NYI_assert (15, 10, 0x07);
3949
3950   if (test_false)
3951     {
3952       for (i = 0; i < (full ? 16 : 8); i++)
3953         if (aarch64_get_vec_u32 (cpu, vn, i) == 0)
3954           aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vm, i));
3955     }
3956   else
3957     {
3958       for (i = 0; i < (full ? 16 : 8); i++)
3959         if (aarch64_get_vec_u32 (cpu, vn, i) != 0)
3960           aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vm, i));
3961     }
3962 }
3963
3964 static void
3965 do_vec_ORN (sim_cpu *cpu)
3966 {
3967   /* instr[31]    = 0
3968      instr[30]    = half (0)/full (1)
3969      instr[29,21] = 00 1110 111
3970      instr[20,16] = Vm
3971      instr[15,10] = 00 0111
3972      instr[9,5]   = Vn
3973      instr[4.0]   = Vd.  */
3974
3975   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
3976   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
3977   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
3978   unsigned i;
3979   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
3980
3981   NYI_assert (29, 21, 0x077);
3982   NYI_assert (15, 10, 0x07);
3983
3984   for (i = 0; i < (full ? 16 : 8); i++)
3985     aarch64_set_vec_u8 (cpu, vd, i,
3986                         aarch64_get_vec_u8 (cpu, vn, i)
3987                         | ~ aarch64_get_vec_u8 (cpu, vm, i));
3988 }
3989
3990 static void
3991 do_vec_ORR (sim_cpu *cpu)
3992 {
3993   /* instr[31]    = 0
3994      instr[30]    = half (0)/full (1)
3995      instr[29,21] = 00 1110 101
3996      instr[20,16] = Vm
3997      instr[15,10] = 0001 11
3998      instr[9,5]   = Vn
3999      instr[4.0]   = Vd.  */
4000
4001   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4002   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4003   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4004   unsigned i;
4005   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
4006
4007   NYI_assert (29, 21, 0x075);
4008   NYI_assert (15, 10, 0x07);
4009
4010   for (i = 0; i < (full ? 16 : 8); i++)
4011     aarch64_set_vec_u8 (cpu, vd, i,
4012                         aarch64_get_vec_u8 (cpu, vn, i)
4013                         | aarch64_get_vec_u8 (cpu, vm, i));
4014 }
4015
4016 static void
4017 do_vec_BIC (sim_cpu *cpu)
4018 {
4019   /* instr[31]    = 0
4020      instr[30]    = half (0)/full (1)
4021      instr[29,21] = 00 1110 011
4022      instr[20,16] = Vm
4023      instr[15,10] = 00 0111
4024      instr[9,5]   = Vn
4025      instr[4.0]   = Vd.  */
4026
4027   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4028   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4029   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4030   unsigned i;
4031   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
4032
4033   NYI_assert (29, 21, 0x073);
4034   NYI_assert (15, 10, 0x07);
4035
4036   for (i = 0; i < (full ? 16 : 8); i++)
4037     aarch64_set_vec_u8 (cpu, vd, i,
4038                         aarch64_get_vec_u8 (cpu, vn, i)
4039                         & ~ aarch64_get_vec_u8 (cpu, vm, i));
4040 }
4041
4042 static void
4043 do_vec_XTN (sim_cpu *cpu)
4044 {
4045   /* instr[31]    = 0
4046      instr[30]    = first part (0)/ second part (1)
4047      instr[29,24] = 00 1110
4048      instr[23,22] = size: byte(00), half(01), word (10)
4049      instr[21,10] = 1000 0100 1010
4050      instr[9,5]   = Vs
4051      instr[4,0]   = Vd.  */
4052
4053   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
4054   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4055   unsigned bias = uimm (aarch64_get_instr (cpu), 30, 30);
4056   unsigned i;
4057
4058   NYI_assert (29, 24, 0x0E);
4059   NYI_assert (21, 10, 0x84A);
4060
4061   switch (uimm (aarch64_get_instr (cpu), 23, 22))
4062     {
4063     case 0:
4064       if (bias)
4065         for (i = 0; i < 8; i++)
4066           aarch64_set_vec_u8 (cpu, vd, i + 8,
4067                               aarch64_get_vec_u16 (cpu, vs, i) >> 8);
4068       else
4069         for (i = 0; i < 8; i++)
4070           aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vs, i));
4071       return;
4072
4073     case 1:
4074       if (bias)
4075         for (i = 0; i < 4; i++)
4076           aarch64_set_vec_u16 (cpu, vd, i + 4,
4077                                aarch64_get_vec_u32 (cpu, vs, i) >> 16);
4078       else
4079         for (i = 0; i < 4; i++)
4080           aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vs, i));
4081       return;
4082
4083     case 2:
4084       if (bias)
4085         for (i = 0; i < 2; i++)
4086           aarch64_set_vec_u32 (cpu, vd, i + 4,
4087                                aarch64_get_vec_u64 (cpu, vs, i) >> 32);
4088       else
4089         for (i = 0; i < 2; i++)
4090           aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u64 (cpu, vs, i));
4091       return;
4092     }
4093 }
4094
4095 static void
4096 do_vec_maxv (sim_cpu *cpu)
4097 {
4098   /* instr[31]    = 0
4099      instr[30]    = half(0)/full(1)
4100      instr[29]    = signed (0)/unsigned(1)
4101      instr[28,24] = 0 1110
4102      instr[23,22] = size: byte(00), half(01), word (10)
4103      instr[21]    = 1
4104      instr[20,17] = 1 000
4105      instr[16]    = max(0)/min(1)
4106      instr[15,10] = 1010 10
4107      instr[9,5]   = V source
4108      instr[4.0]   = R dest.  */
4109
4110   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
4111   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
4112   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4113   unsigned i;
4114
4115   NYI_assert (28, 24, 0x0E);
4116   NYI_assert (21, 21, 1);
4117   NYI_assert (20, 17, 8);
4118   NYI_assert (15, 10, 0x2A);
4119
4120   switch ((uimm (aarch64_get_instr (cpu), 29, 29) << 1)
4121           | uimm (aarch64_get_instr (cpu), 16, 16))
4122     {
4123     case 0: /* SMAXV.  */
4124        {
4125         int64_t smax;
4126         switch (uimm (aarch64_get_instr (cpu), 23, 22))
4127           {
4128           case 0:
4129             smax = aarch64_get_vec_s8 (cpu, vs, 0);
4130             for (i = 1; i < (full ? 16 : 8); i++)
4131               smax = max (smax, aarch64_get_vec_s8 (cpu, vs, i));
4132             break;
4133           case 1:
4134             smax = aarch64_get_vec_s16 (cpu, vs, 0);
4135             for (i = 1; i < (full ? 8 : 4); i++)
4136               smax = max (smax, aarch64_get_vec_s16 (cpu, vs, i));
4137             break;
4138           case 2:
4139             smax = aarch64_get_vec_s32 (cpu, vs, 0);
4140             for (i = 1; i < (full ? 4 : 2); i++)
4141               smax = max (smax, aarch64_get_vec_s32 (cpu, vs, i));
4142             break;
4143           case 3:
4144             HALT_UNALLOC;
4145           }
4146         aarch64_set_reg_s64 (cpu, rd, NO_SP, smax);
4147         return;
4148       }
4149
4150     case 1: /* SMINV.  */
4151       {
4152         int64_t smin;
4153         switch (uimm (aarch64_get_instr (cpu), 23, 22))
4154           {
4155           case 0:
4156             smin = aarch64_get_vec_s8 (cpu, vs, 0);
4157             for (i = 1; i < (full ? 16 : 8); i++)
4158               smin = min (smin, aarch64_get_vec_s8 (cpu, vs, i));
4159             break;
4160           case 1:
4161             smin = aarch64_get_vec_s16 (cpu, vs, 0);
4162             for (i = 1; i < (full ? 8 : 4); i++)
4163               smin = min (smin, aarch64_get_vec_s16 (cpu, vs, i));
4164             break;
4165           case 2:
4166             smin = aarch64_get_vec_s32 (cpu, vs, 0);
4167             for (i = 1; i < (full ? 4 : 2); i++)
4168               smin = min (smin, aarch64_get_vec_s32 (cpu, vs, i));
4169             break;
4170
4171           case 3:
4172             HALT_UNALLOC;
4173           }
4174         aarch64_set_reg_s64 (cpu, rd, NO_SP, smin);
4175         return;
4176       }
4177
4178     case 2: /* UMAXV.  */
4179       {
4180         uint64_t umax;
4181         switch (uimm (aarch64_get_instr (cpu), 23, 22))
4182           {
4183           case 0:
4184             umax = aarch64_get_vec_u8 (cpu, vs, 0);
4185             for (i = 1; i < (full ? 16 : 8); i++)
4186               umax = max (umax, aarch64_get_vec_u8 (cpu, vs, i));
4187             break;
4188           case 1:
4189             umax = aarch64_get_vec_u16 (cpu, vs, 0);
4190             for (i = 1; i < (full ? 8 : 4); i++)
4191               umax = max (umax, aarch64_get_vec_u16 (cpu, vs, i));
4192             break;
4193           case 2:
4194             umax = aarch64_get_vec_u32 (cpu, vs, 0);
4195             for (i = 1; i < (full ? 4 : 2); i++)
4196               umax = max (umax, aarch64_get_vec_u32 (cpu, vs, i));
4197             break;
4198
4199           case 3:
4200             HALT_UNALLOC;
4201           }
4202         aarch64_set_reg_u64 (cpu, rd, NO_SP, umax);
4203         return;
4204       }
4205
4206     case 3: /* UMINV.  */
4207       {
4208         uint64_t umin;
4209         switch (uimm (aarch64_get_instr (cpu), 23, 22))
4210           {
4211           case 0:
4212             umin = aarch64_get_vec_u8 (cpu, vs, 0);
4213             for (i = 1; i < (full ? 16 : 8); i++)
4214               umin = min (umin, aarch64_get_vec_u8 (cpu, vs, i));
4215             break;
4216           case 1:
4217             umin = aarch64_get_vec_u16 (cpu, vs, 0);
4218             for (i = 1; i < (full ? 8 : 4); i++)
4219               umin = min (umin, aarch64_get_vec_u16 (cpu, vs, i));
4220             break;
4221           case 2:
4222             umin = aarch64_get_vec_u32 (cpu, vs, 0);
4223             for (i = 1; i < (full ? 4 : 2); i++)
4224               umin = min (umin, aarch64_get_vec_u32 (cpu, vs, i));
4225             break;
4226
4227           case 3:
4228             HALT_UNALLOC;
4229           }
4230         aarch64_set_reg_u64 (cpu, rd, NO_SP, umin);
4231         return;
4232       }
4233     }
4234 }
4235
4236 static void
4237 do_vec_fminmaxV (sim_cpu *cpu)
4238 {
4239   /* instr[31,24] = 0110 1110
4240      instr[23]    = max(0)/min(1)
4241      instr[22,14] = 011 0000 11
4242      instr[13,12] = nm(00)/normal(11)
4243      instr[11,10] = 10
4244      instr[9,5]   = V source
4245      instr[4.0]   = R dest.  */
4246
4247   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
4248   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
4249   unsigned i;
4250   float res   = aarch64_get_vec_float (cpu, vs, 0);
4251
4252   NYI_assert (31, 24, 0x6E);
4253   NYI_assert (22, 14, 0x0C3);
4254   NYI_assert (11, 10, 2);
4255
4256   if (uimm (aarch64_get_instr (cpu), 23, 23))
4257     {
4258       switch (uimm (aarch64_get_instr (cpu), 13, 12))
4259         {
4260         case 0: /* FMNINNMV.  */
4261           for (i = 1; i < 4; i++)
4262             res = fminnm (res, aarch64_get_vec_float (cpu, vs, i));
4263           break;
4264
4265         case 3: /* FMINV.  */
4266           for (i = 1; i < 4; i++)
4267             res = min (res, aarch64_get_vec_float (cpu, vs, i));
4268           break;
4269
4270         default:
4271           HALT_NYI;
4272         }
4273     }
4274   else
4275     {
4276       switch (uimm (aarch64_get_instr (cpu), 13, 12))
4277         {
4278         case 0: /* FMNAXNMV.  */
4279           for (i = 1; i < 4; i++)
4280             res = fmaxnm (res, aarch64_get_vec_float (cpu, vs, i));
4281           break;
4282
4283         case 3: /* FMAXV.  */
4284           for (i = 1; i < 4; i++)
4285             res = max (res, aarch64_get_vec_float (cpu, vs, i));
4286           break;
4287
4288         default:
4289           HALT_NYI;
4290         }
4291     }
4292
4293   aarch64_set_FP_float (cpu, rd, res);
4294 }
4295
4296 static void
4297 do_vec_Fminmax (sim_cpu *cpu)
4298 {
4299   /* instr[31]    = 0
4300      instr[30]    = half(0)/full(1)
4301      instr[29,24] = 00 1110
4302      instr[23]    = max(0)/min(1)
4303      instr[22]    = float(0)/double(1)
4304      instr[21]    = 1
4305      instr[20,16] = Vm
4306      instr[15,14] = 11
4307      instr[13,12] = nm(00)/normal(11)
4308      instr[11,10] = 01
4309      instr[9,5]   = Vn
4310      instr[4,0]   = Vd.  */
4311
4312   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4313   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4314   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4315   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4316   unsigned min = uimm (aarch64_get_instr (cpu), 23, 23);
4317   unsigned i;
4318
4319   NYI_assert (29, 24, 0x0E);
4320   NYI_assert (21, 21, 1);
4321   NYI_assert (15, 14, 3);
4322   NYI_assert (11, 10, 1);
4323
4324   if (uimm (aarch64_get_instr (cpu), 22, 22))
4325     {
4326       double (* func)(double, double);
4327
4328       if (! full)
4329         HALT_NYI;
4330
4331       if (uimm (aarch64_get_instr (cpu), 13, 12) == 0)
4332         func = min ? dminnm : dmaxnm;
4333       else if (uimm (aarch64_get_instr (cpu), 13, 12) == 3)
4334         func = min ? fmin : fmax;
4335       else
4336         HALT_NYI;
4337
4338       for (i = 0; i < 2; i++)
4339         aarch64_set_vec_double (cpu, vd, i,
4340                                 func (aarch64_get_vec_double (cpu, vn, i),
4341                                       aarch64_get_vec_double (cpu, vm, i)));
4342     }
4343   else
4344     {
4345       float (* func)(float, float);
4346
4347       if (uimm (aarch64_get_instr (cpu), 13, 12) == 0)
4348         func = min ? fminnm : fmaxnm;
4349       else if (uimm (aarch64_get_instr (cpu), 13, 12) == 3)
4350         func = min ? fminf : fmaxf;
4351       else
4352         HALT_NYI;
4353
4354       for (i = 0; i < (full ? 4 : 2); i++)
4355         aarch64_set_vec_float (cpu, vd, i,
4356                                func (aarch64_get_vec_float (cpu, vn, i),
4357                                      aarch64_get_vec_float (cpu, vm, i)));
4358     }
4359 }
4360
4361 static void
4362 do_vec_SCVTF (sim_cpu *cpu)
4363 {
4364   /* instr[31]    = 0
4365      instr[30]    = Q
4366      instr[29,23] = 00 1110 0
4367      instr[22]    = float(0)/double(1)
4368      instr[21,10] = 10 0001 1101 10
4369      instr[9,5]   = Vn
4370      instr[4,0]   = Vd.  */
4371
4372   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4373   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4374   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4375   unsigned size = uimm (aarch64_get_instr (cpu), 22, 22);
4376   unsigned i;
4377
4378   NYI_assert (29, 23, 0x1C);
4379   NYI_assert (21, 10, 0x876);
4380
4381   if (size)
4382     {
4383       if (! full)
4384         HALT_UNALLOC;
4385
4386       for (i = 0; i < 2; i++)
4387         {
4388           double val = (double) aarch64_get_vec_u64 (cpu, vn, i);
4389           aarch64_set_vec_double (cpu, vd, i, val);
4390         }
4391     }
4392   else
4393     {
4394       for (i = 0; i < (full ? 4 : 2); i++)
4395         {
4396           float val = (float) aarch64_get_vec_u32 (cpu, vn, i);
4397           aarch64_set_vec_float (cpu, vd, i, val);
4398         }
4399     }
4400 }
4401
4402 #define VEC_CMP(SOURCE, CMP)                                            \
4403   do                                                                    \
4404     {                                                                   \
4405       switch (size)                                                     \
4406         {                                                               \
4407         case 0:                                                         \
4408           for (i = 0; i < (full ? 16 : 8); i++)                         \
4409             aarch64_set_vec_u8 (cpu, vd, i,                             \
4410                                 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4411                                 CMP                                     \
4412                                 aarch64_get_vec_##SOURCE##8 (cpu, vm, i) \
4413                                 ? -1 : 0);                              \
4414           return;                                                       \
4415         case 1:                                                         \
4416           for (i = 0; i < (full ? 8 : 4); i++)                          \
4417             aarch64_set_vec_u16 (cpu, vd, i,                            \
4418                                  aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4419                                  CMP                                    \
4420                                  aarch64_get_vec_##SOURCE##16 (cpu, vm, i) \
4421                                  ? -1 : 0);                             \
4422           return;                                                       \
4423         case 2:                                                         \
4424           for (i = 0; i < (full ? 4 : 2); i++)                          \
4425             aarch64_set_vec_u32 (cpu, vd, i, \
4426                                  aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4427                                  CMP                                    \
4428                                  aarch64_get_vec_##SOURCE##32 (cpu, vm, i) \
4429                                  ? -1 : 0);                             \
4430           return;                                                       \
4431         case 3:                                                         \
4432           if (! full)                                                   \
4433             HALT_UNALLOC;                                               \
4434           for (i = 0; i < 2; i++)                                       \
4435             aarch64_set_vec_u64 (cpu, vd, i, \
4436                                  aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4437                                  CMP                                    \
4438                                  aarch64_get_vec_##SOURCE##64 (cpu, vm, i) \
4439                                  ? -1ULL : 0);                          \
4440           return;                                                       \
4441         }                                                               \
4442     }                                                                   \
4443   while (0)
4444
4445 #define VEC_CMP0(SOURCE, CMP)                                           \
4446   do                                                                    \
4447     {                                                                   \
4448       switch (size)                                                     \
4449         {                                                               \
4450         case 0:                                                         \
4451           for (i = 0; i < (full ? 16 : 8); i++)                         \
4452             aarch64_set_vec_u8 (cpu, vd, i,                             \
4453                                 aarch64_get_vec_##SOURCE##8 (cpu, vn, i) \
4454                                 CMP 0 ? -1 : 0);                        \
4455           return;                                                       \
4456         case 1:                                                         \
4457           for (i = 0; i < (full ? 8 : 4); i++)                          \
4458             aarch64_set_vec_u16 (cpu, vd, i,                            \
4459                                  aarch64_get_vec_##SOURCE##16 (cpu, vn, i) \
4460                                  CMP 0 ? -1 : 0);                       \
4461           return;                                                       \
4462         case 2:                                                         \
4463           for (i = 0; i < (full ? 4 : 2); i++)                          \
4464             aarch64_set_vec_u32 (cpu, vd, i,                            \
4465                                  aarch64_get_vec_##SOURCE##32 (cpu, vn, i) \
4466                                  CMP 0 ? -1 : 0);                       \
4467           return;                                                       \
4468         case 3:                                                         \
4469           if (! full)                                                   \
4470             HALT_UNALLOC;                                               \
4471           for (i = 0; i < 2; i++)                                       \
4472             aarch64_set_vec_u64 (cpu, vd, i,                            \
4473                                  aarch64_get_vec_##SOURCE##64 (cpu, vn, i) \
4474                                  CMP 0 ? -1ULL : 0);                    \
4475           return;                                                       \
4476         }                                                               \
4477     }                                                                   \
4478   while (0)
4479
4480 #define VEC_FCMP0(CMP)                                                  \
4481   do                                                                    \
4482     {                                                                   \
4483       if (vm != 0)                                                      \
4484         HALT_NYI;                                                       \
4485       if (uimm (aarch64_get_instr (cpu), 22, 22))                       \
4486         {                                                               \
4487           if (! full)                                                   \
4488             HALT_NYI;                                                   \
4489           for (i = 0; i < 2; i++)                                       \
4490             aarch64_set_vec_u64 (cpu, vd, i,                            \
4491                                  aarch64_get_vec_double (cpu, vn, i)    \
4492                                  CMP 0.0 ? -1 : 0);                     \
4493         }                                                               \
4494       else                                                              \
4495         {                                                               \
4496           for (i = 0; i < (full ? 4 : 2); i++)                          \
4497             aarch64_set_vec_u32 (cpu, vd, i,                            \
4498                                  aarch64_get_vec_float (cpu, vn, i)     \
4499                                  CMP 0.0 ? -1 : 0);                     \
4500         }                                                               \
4501       return;                                                           \
4502     }                                                                   \
4503   while (0)
4504
4505 #define VEC_FCMP(CMP)                                                   \
4506   do                                                                    \
4507     {                                                                   \
4508       if (uimm (aarch64_get_instr (cpu), 22, 22))                       \
4509         {                                                               \
4510           if (! full)                                                   \
4511             HALT_NYI;                                                   \
4512           for (i = 0; i < 2; i++)                                       \
4513             aarch64_set_vec_u64 (cpu, vd, i,                            \
4514                                  aarch64_get_vec_double (cpu, vn, i)    \
4515                                  CMP                                    \
4516                                  aarch64_get_vec_double (cpu, vm, i)    \
4517                                  ? -1 : 0);                             \
4518         }                                                               \
4519       else                                                              \
4520         {                                                               \
4521           for (i = 0; i < (full ? 4 : 2); i++)                          \
4522             aarch64_set_vec_u32 (cpu, vd, i,                            \
4523                                  aarch64_get_vec_float (cpu, vn, i)     \
4524                                  CMP                                    \
4525                                  aarch64_get_vec_float (cpu, vm, i)     \
4526                                  ? -1 : 0);                             \
4527         }                                                               \
4528       return;                                                           \
4529     }                                                                   \
4530   while (0)
4531
4532 static void
4533 do_vec_compare (sim_cpu *cpu)
4534 {
4535   /* instr[31]    = 0
4536      instr[30]    = half(0)/full(1)
4537      instr[29]    = part-of-comparison-type
4538      instr[28,24] = 0 1110
4539      instr[23,22] = size of integer compares: byte(00), half(01), word (10), long (11)
4540                     type of float compares: single (-0) / double (-1)
4541      instr[21]    = 1
4542      instr[20,16] = Vm or 00000 (compare vs 0)
4543      instr[15,10] = part-of-comparison-type
4544      instr[9,5]   = Vn
4545      instr[4.0]   = Vd.  */
4546
4547   int full = uimm (aarch64_get_instr (cpu), 30, 30);
4548   int size = uimm (aarch64_get_instr (cpu), 23, 22);
4549   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4550   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4551   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4552   unsigned i;
4553
4554   NYI_assert (28, 24, 0x0E);
4555   NYI_assert (21, 21, 1);
4556
4557   if ((uimm (aarch64_get_instr (cpu), 11, 11)
4558        && uimm (aarch64_get_instr (cpu), 14, 14))
4559       || ((uimm (aarch64_get_instr (cpu), 11, 11) == 0
4560            && uimm (aarch64_get_instr (cpu), 10, 10) == 0)))
4561     {
4562       /* A compare vs 0.  */
4563       if (vm != 0)
4564         {
4565           if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x2A)
4566             do_vec_maxv (cpu);
4567           else if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x32
4568                    || uimm (aarch64_get_instr (cpu), 15, 10) == 0x3E)
4569             do_vec_fminmaxV (cpu);
4570           else if (uimm (aarch64_get_instr (cpu), 29, 23) == 0x1C
4571                    && uimm (aarch64_get_instr (cpu), 21, 10) == 0x876)
4572             do_vec_SCVTF (cpu);
4573           else
4574             HALT_NYI;
4575           return;
4576         }
4577     }
4578
4579   if (uimm (aarch64_get_instr (cpu), 14, 14))
4580     {
4581       /* A floating point compare.  */
4582       unsigned decode = (uimm (aarch64_get_instr (cpu), 29, 29) << 5)
4583         | (uimm (aarch64_get_instr (cpu), 23, 23) << 4)
4584         | uimm (aarch64_get_instr (cpu), 13, 10);
4585
4586       NYI_assert (15, 15, 1);
4587
4588       switch (decode)
4589         {
4590         case /* 0b010010: GT#0 */ 0x12: VEC_FCMP0 (>);
4591         case /* 0b110010: GE#0 */ 0x32: VEC_FCMP0 (>=);
4592         case /* 0b010110: EQ#0 */ 0x16: VEC_FCMP0 (==);
4593         case /* 0b110110: LE#0 */ 0x36: VEC_FCMP0 (<=);
4594         case /* 0b011010: LT#0 */ 0x1A: VEC_FCMP0 (<);
4595         case /* 0b111001: GT */   0x39: VEC_FCMP  (>);
4596         case /* 0b101001: GE */   0x29: VEC_FCMP  (>=);
4597         case /* 0b001001: EQ */   0x09: VEC_FCMP  (==);
4598
4599         default:
4600           HALT_NYI;
4601         }
4602     }
4603   else
4604     {
4605       unsigned decode = (uimm (aarch64_get_instr (cpu), 29, 29) << 6)
4606         | uimm (aarch64_get_instr (cpu), 15, 10);
4607
4608       switch (decode)
4609         {
4610         case 0x0D: /* 0001101 GT */     VEC_CMP  (s, > );
4611         case 0x0F: /* 0001111 GE */     VEC_CMP  (s, >= );
4612         case 0x22: /* 0100010 GT #0 */  VEC_CMP0 (s, > );
4613         case 0x26: /* 0100110 EQ #0 */  VEC_CMP0 (s, == );
4614         case 0x2A: /* 0101010 LT #0 */  VEC_CMP0 (s, < );
4615         case 0x4D: /* 1001101 HI */     VEC_CMP  (u, > );
4616         case 0x4F: /* 1001111 HS */     VEC_CMP  (u, >= );
4617         case 0x62: /* 1100010 GE #0 */  VEC_CMP0 (s, >= );
4618         case 0x63: /* 1100011 EQ */     VEC_CMP  (u, == );
4619         case 0x66: /* 1100110 LE #0 */  VEC_CMP0 (s, <= );
4620         default:
4621           if (vm == 0)
4622             HALT_NYI;
4623           do_vec_maxv (cpu);
4624         }
4625     }
4626 }
4627
4628 static void
4629 do_vec_SSHL (sim_cpu *cpu)
4630 {
4631   /* instr[31]    = 0
4632      instr[30]    = first part (0)/ second part (1)
4633      instr[29,24] = 00 1110
4634      instr[23,22] = size: byte(00), half(01), word (10), long (11)
4635      instr[21]    = 1
4636      instr[20,16] = Vm
4637      instr[15,10] = 0100 01
4638      instr[9,5]   = Vn
4639      instr[4,0]   = Vd.  */
4640
4641   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4642   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4643   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4644   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4645   unsigned i;
4646   signed int shift;
4647
4648   NYI_assert (29, 24, 0x0E);
4649   NYI_assert (21, 21, 1);
4650   NYI_assert (15, 10, 0x11);
4651
4652   /* FIXME: What is a signed shift left in this context ?.  */
4653
4654   switch (uimm (aarch64_get_instr (cpu), 23, 22))
4655     {
4656     case 0:
4657       for (i = 0; i < (full ? 16 : 8); i++)
4658         {
4659           shift = aarch64_get_vec_s8 (cpu, vm, i);
4660           if (shift >= 0)
4661             aarch64_set_vec_s8 (cpu, vd, i, aarch64_get_vec_s8 (cpu, vn, i)
4662                                 << shift);
4663           else
4664             aarch64_set_vec_s8 (cpu, vd, i, aarch64_get_vec_s8 (cpu, vn, i)
4665                                 >> - shift);
4666         }
4667       return;
4668
4669     case 1:
4670       for (i = 0; i < (full ? 8 : 4); i++)
4671         {
4672           shift = aarch64_get_vec_s8 (cpu, vm, i);
4673           if (shift >= 0)
4674             aarch64_set_vec_s16 (cpu, vd, i, aarch64_get_vec_s16 (cpu, vn, i)
4675                                  << shift);
4676           else
4677             aarch64_set_vec_s16 (cpu, vd, i, aarch64_get_vec_s16 (cpu, vn, i)
4678                                  >> - shift);
4679         }
4680       return;
4681
4682     case 2:
4683       for (i = 0; i < (full ? 4 : 2); i++)
4684         {
4685           shift = aarch64_get_vec_s8 (cpu, vm, i);
4686           if (shift >= 0)
4687             aarch64_set_vec_s32 (cpu, vd, i, aarch64_get_vec_s32 (cpu, vn, i)
4688                                  << shift);
4689           else
4690             aarch64_set_vec_s32 (cpu, vd, i, aarch64_get_vec_s32 (cpu, vn, i)
4691                                  >> - shift);
4692         }
4693       return;
4694
4695     case 3:
4696       if (! full)
4697         HALT_UNALLOC;
4698       for (i = 0; i < 2; i++)
4699         {
4700           shift = aarch64_get_vec_s8 (cpu, vm, i);
4701           if (shift >= 0)
4702             aarch64_set_vec_s64 (cpu, vd, i, aarch64_get_vec_s64 (cpu, vn, i)
4703                                  << shift);
4704           else
4705             aarch64_set_vec_s64 (cpu, vd, i, aarch64_get_vec_s64 (cpu, vn, i)
4706                                  >> - shift);
4707         }
4708       return;
4709     }
4710 }
4711
4712 static void
4713 do_vec_USHL (sim_cpu *cpu)
4714 {
4715   /* instr[31]    = 0
4716      instr[30]    = first part (0)/ second part (1)
4717      instr[29,24] = 10 1110
4718      instr[23,22] = size: byte(00), half(01), word (10), long (11)
4719      instr[21]    = 1
4720      instr[20,16] = Vm
4721      instr[15,10] = 0100 01
4722      instr[9,5]   = Vn
4723      instr[4,0]   = Vd  */
4724
4725   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
4726   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4727   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4728   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4729   unsigned i;
4730   signed int shift;
4731
4732   NYI_assert (29, 24, 0x2E);
4733   NYI_assert (15, 10, 0x11);
4734
4735   switch (uimm (aarch64_get_instr (cpu), 23, 22))
4736     {
4737     case 0:
4738         for (i = 0; i < (full ? 16 : 8); i++)
4739           {
4740             shift = aarch64_get_vec_s8 (cpu, vm, i);
4741             if (shift >= 0)
4742               aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vn, i)
4743                                   << shift);
4744             else
4745               aarch64_set_vec_u8 (cpu, vd, i, aarch64_get_vec_u8 (cpu, vn, i)
4746                                   >> - shift);
4747           }
4748       return;
4749
4750     case 1:
4751       for (i = 0; i < (full ? 8 : 4); i++)
4752         {
4753           shift = aarch64_get_vec_s8 (cpu, vm, i);
4754           if (shift >= 0)
4755             aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vn, i)
4756                                  << shift);
4757           else
4758             aarch64_set_vec_u16 (cpu, vd, i, aarch64_get_vec_u16 (cpu, vn, i)
4759                                  >> - shift);
4760         }
4761       return;
4762
4763     case 2:
4764       for (i = 0; i < (full ? 4 : 2); i++)
4765         {
4766           shift = aarch64_get_vec_s8 (cpu, vm, i);
4767           if (shift >= 0)
4768             aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vn, i)
4769                                  << shift);
4770           else
4771             aarch64_set_vec_u32 (cpu, vd, i, aarch64_get_vec_u32 (cpu, vn, i)
4772                                  >> - shift);
4773         }
4774       return;
4775
4776     case 3:
4777       if (! full)
4778         HALT_UNALLOC;
4779       for (i = 0; i < 2; i++)
4780         {
4781           shift = aarch64_get_vec_s8 (cpu, vm, i);
4782           if (shift >= 0)
4783             aarch64_set_vec_u64 (cpu, vd, i, aarch64_get_vec_u64 (cpu, vn, i)
4784                                  << shift);
4785           else
4786             aarch64_set_vec_u64 (cpu, vd, i, aarch64_get_vec_u64 (cpu, vn, i)
4787                                  >> - shift);
4788         }
4789       return;
4790     }
4791 }
4792
4793 static void
4794 do_vec_FMLA (sim_cpu *cpu)
4795 {
4796   /* instr[31]    = 0
4797      instr[30]    = full/half selector
4798      instr[29,23] = 0011100
4799      instr[22]    = size: 0=>float, 1=>double
4800      instr[21]    = 1
4801      instr[20,16] = Vn
4802      instr[15,10] = 1100 11
4803      instr[9,5]   = Vm
4804      instr[4.0]   = Vd.  */
4805
4806   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4807   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4808   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4809   unsigned i;
4810   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
4811
4812   NYI_assert (29, 23, 0x1C);
4813   NYI_assert (21, 21, 1);
4814   NYI_assert (15, 10, 0x33);
4815
4816   if (uimm (aarch64_get_instr (cpu), 22, 22))
4817     {
4818       if (! full)
4819         HALT_UNALLOC;
4820       for (i = 0; i < 2; i++)
4821         aarch64_set_vec_double (cpu, vd, i,
4822                                 aarch64_get_vec_double (cpu, vn, i) *
4823                                 aarch64_get_vec_double (cpu, vm, i) +
4824                                 aarch64_get_vec_double (cpu, vd, i));
4825     }
4826   else
4827     {
4828       for (i = 0; i < (full ? 4 : 2); i++)
4829         aarch64_set_vec_float (cpu, vd, i,
4830                                aarch64_get_vec_float (cpu, vn, i) *
4831                                aarch64_get_vec_float (cpu, vm, i) +
4832                                aarch64_get_vec_float (cpu, vd, i));
4833     }
4834 }
4835
4836 static void
4837 do_vec_max (sim_cpu *cpu)
4838 {
4839   /* instr[31]    = 0
4840      instr[30]    = full/half selector
4841      instr[29]    = SMAX (0) / UMAX (1)
4842      instr[28,24] = 0 1110
4843      instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
4844      instr[21]    = 1
4845      instr[20,16] = Vn
4846      instr[15,10] = 0110 01
4847      instr[9,5]   = Vm
4848      instr[4.0]   = Vd.  */
4849
4850   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4851   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4852   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4853   unsigned i;
4854   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
4855
4856   NYI_assert (28, 24, 0x0E);
4857   NYI_assert (21, 21, 1);
4858   NYI_assert (15, 10, 0x19);
4859
4860   if (uimm (aarch64_get_instr (cpu), 29, 29))
4861     {
4862       switch (uimm (aarch64_get_instr (cpu), 23, 22))
4863         {
4864         case 0:
4865           for (i = 0; i < (full ? 16 : 8); i++)
4866             aarch64_set_vec_u8 (cpu, vd, i,
4867                                 aarch64_get_vec_u8 (cpu, vn, i)
4868                                 > aarch64_get_vec_u8 (cpu, vm, i)
4869                                 ? aarch64_get_vec_u8 (cpu, vn, i)
4870                                 : aarch64_get_vec_u8 (cpu, vm, i));
4871           return;
4872
4873         case 1:
4874           for (i = 0; i < (full ? 8 : 4); i++)
4875             aarch64_set_vec_u16 (cpu, vd, i,
4876                                  aarch64_get_vec_u16 (cpu, vn, i)
4877                                  > aarch64_get_vec_u16 (cpu, vm, i)
4878                                  ? aarch64_get_vec_u16 (cpu, vn, i)
4879                                  : aarch64_get_vec_u16 (cpu, vm, i));
4880           return;
4881
4882         case 2:
4883           for (i = 0; i < (full ? 4 : 2); i++)
4884             aarch64_set_vec_u32 (cpu, vd, i,
4885                                  aarch64_get_vec_u32 (cpu, vn, i)
4886                                  > aarch64_get_vec_u32 (cpu, vm, i)
4887                                  ? aarch64_get_vec_u32 (cpu, vn, i)
4888                                  : aarch64_get_vec_u32 (cpu, vm, i));
4889           return;
4890
4891         case 3:
4892           HALT_UNALLOC;
4893         }
4894     }
4895   else
4896     {
4897       switch (uimm (aarch64_get_instr (cpu), 23, 22))
4898         {
4899         case 0:
4900           for (i = 0; i < (full ? 16 : 8); i++)
4901             aarch64_set_vec_s8 (cpu, vd, i,
4902                                 aarch64_get_vec_s8 (cpu, vn, i)
4903                                 > aarch64_get_vec_s8 (cpu, vm, i)
4904                                 ? aarch64_get_vec_s8 (cpu, vn, i)
4905                                 : aarch64_get_vec_s8 (cpu, vm, i));
4906           return;
4907
4908         case 1:
4909           for (i = 0; i < (full ? 8 : 4); i++)
4910             aarch64_set_vec_s16 (cpu, vd, i,
4911                                  aarch64_get_vec_s16 (cpu, vn, i)
4912                                  > aarch64_get_vec_s16 (cpu, vm, i)
4913                                  ? aarch64_get_vec_s16 (cpu, vn, i)
4914                                  : aarch64_get_vec_s16 (cpu, vm, i));
4915           return;
4916
4917         case 2:
4918           for (i = 0; i < (full ? 4 : 2); i++)
4919             aarch64_set_vec_s32 (cpu, vd, i,
4920                                  aarch64_get_vec_s32 (cpu, vn, i)
4921                                  > aarch64_get_vec_s32 (cpu, vm, i)
4922                                  ? aarch64_get_vec_s32 (cpu, vn, i)
4923                                  : aarch64_get_vec_s32 (cpu, vm, i));
4924           return;
4925
4926         case 3:
4927           HALT_UNALLOC;
4928         }
4929     }
4930 }
4931
4932 static void
4933 do_vec_min (sim_cpu *cpu)
4934 {
4935   /* instr[31]    = 0
4936      instr[30]    = full/half selector
4937      instr[29]    = SMIN (0) / UMIN (1)
4938      instr[28,24] = 0 1110
4939      instr[23,22] = size: 00=> 8-bit, 01=> 16-bit, 10=> 32-bit
4940      instr[21]    = 1
4941      instr[20,16] = Vn
4942      instr[15,10] = 0110 11
4943      instr[9,5]   = Vm
4944      instr[4.0]   = Vd.  */
4945
4946   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
4947   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
4948   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
4949   unsigned i;
4950   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
4951
4952   NYI_assert (28, 24, 0x0E);
4953   NYI_assert (21, 21, 1);
4954   NYI_assert (15, 10, 0x1B);
4955
4956   if (uimm (aarch64_get_instr (cpu), 29, 29))
4957     {
4958       switch (uimm (aarch64_get_instr (cpu), 23, 22))
4959         {
4960         case 0:
4961           for (i = 0; i < (full ? 16 : 8); i++)
4962             aarch64_set_vec_u8 (cpu, vd, i,
4963                                 aarch64_get_vec_u8 (cpu, vn, i)
4964                                 < aarch64_get_vec_u8 (cpu, vm, i)
4965                                 ? aarch64_get_vec_u8 (cpu, vn, i)
4966                                 : aarch64_get_vec_u8 (cpu, vm, i));
4967           return;
4968
4969         case 1:
4970           for (i = 0; i < (full ? 8 : 4); i++)
4971             aarch64_set_vec_u16 (cpu, vd, i,
4972                                  aarch64_get_vec_u16 (cpu, vn, i)
4973                                  < aarch64_get_vec_u16 (cpu, vm, i)
4974                                  ? aarch64_get_vec_u16 (cpu, vn, i)
4975                                  : aarch64_get_vec_u16 (cpu, vm, i));
4976           return;
4977
4978         case 2:
4979           for (i = 0; i < (full ? 4 : 2); i++)
4980             aarch64_set_vec_u32 (cpu, vd, i,
4981                                  aarch64_get_vec_u32 (cpu, vn, i)
4982                                  < aarch64_get_vec_u32 (cpu, vm, i)
4983                                  ? aarch64_get_vec_u32 (cpu, vn, i)
4984                                  : aarch64_get_vec_u32 (cpu, vm, i));
4985           return;
4986
4987         case 3:
4988           HALT_UNALLOC;
4989         }
4990     }
4991   else
4992     {
4993       switch (uimm (aarch64_get_instr (cpu), 23, 22))
4994         {
4995         case 0:
4996           for (i = 0; i < (full ? 16 : 8); i++)
4997             aarch64_set_vec_s8 (cpu, vd, i,
4998                                 aarch64_get_vec_s8 (cpu, vn, i)
4999                                 < aarch64_get_vec_s8 (cpu, vm, i)
5000                                 ? aarch64_get_vec_s8 (cpu, vn, i)
5001                                 : aarch64_get_vec_s8 (cpu, vm, i));
5002           return;
5003
5004         case 1:
5005           for (i = 0; i < (full ? 8 : 4); i++)
5006             aarch64_set_vec_s16 (cpu, vd, i,
5007                                  aarch64_get_vec_s16 (cpu, vn, i)
5008                                  < aarch64_get_vec_s16 (cpu, vm, i)
5009                                  ? aarch64_get_vec_s16 (cpu, vn, i)
5010                                  : aarch64_get_vec_s16 (cpu, vm, i));
5011           return;
5012
5013         case 2:
5014           for (i = 0; i < (full ? 4 : 2); i++)
5015             aarch64_set_vec_s32 (cpu, vd, i,
5016                                  aarch64_get_vec_s32 (cpu, vn, i)
5017                                  < aarch64_get_vec_s32 (cpu, vm, i)
5018                                  ? aarch64_get_vec_s32 (cpu, vn, i)
5019                                  : aarch64_get_vec_s32 (cpu, vm, i));
5020           return;
5021
5022         case 3:
5023           HALT_UNALLOC;
5024         }
5025     }
5026 }
5027
5028 static void
5029 do_vec_sub_long (sim_cpu *cpu)
5030 {
5031   /* instr[31]    = 0
5032      instr[30]    = lower (0) / upper (1)
5033      instr[29]    = signed (0) / unsigned (1)
5034      instr[28,24] = 0 1110
5035      instr[23,22] = size: bytes (00), half (01), word (10)
5036      instr[21]    = 1
5037      insrt[20,16] = Vm
5038      instr[15,10] = 0010 00
5039      instr[9,5]   = Vn
5040      instr[4,0]   = V dest.  */
5041
5042   unsigned size = uimm (aarch64_get_instr (cpu), 23, 22);
5043   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5044   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5045   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5046   unsigned bias = 0;
5047   unsigned i;
5048
5049   NYI_assert (28, 24, 0x0E);
5050   NYI_assert (21, 21, 1);
5051   NYI_assert (15, 10, 0x08);
5052
5053   if (size == 3)
5054     HALT_UNALLOC;
5055
5056   switch (uimm (aarch64_get_instr (cpu), 30, 29))
5057     {
5058     case 2: /* SSUBL2.  */
5059       bias = 2;
5060     case 0: /* SSUBL.  */
5061       switch (size)
5062         {
5063         case 0:
5064           bias *= 3;
5065           for (i = 0; i < 8; i++)
5066             aarch64_set_vec_s16 (cpu, vd, i,
5067                                  aarch64_get_vec_s8 (cpu, vn, i + bias)
5068                                  - aarch64_get_vec_s8 (cpu, vm, i + bias));
5069           break;
5070
5071         case 1:
5072           bias *= 2;
5073           for (i = 0; i < 4; i++)
5074             aarch64_set_vec_s32 (cpu, vd, i,
5075                                  aarch64_get_vec_s16 (cpu, vn, i + bias)
5076                                  - aarch64_get_vec_s16 (cpu, vm, i + bias));
5077           break;
5078
5079         case 2:
5080           for (i = 0; i < 2; i++)
5081             aarch64_set_vec_s64 (cpu, vd, i,
5082                                  aarch64_get_vec_s32 (cpu, vn, i + bias)
5083                                  - aarch64_get_vec_s32 (cpu, vm, i + bias));
5084           break;
5085
5086         default:
5087           HALT_UNALLOC;
5088         }
5089       break;
5090
5091     case 3: /* USUBL2.  */
5092       bias = 2;
5093     case 1: /* USUBL.  */
5094       switch (size)
5095         {
5096         case 0:
5097           bias *= 3;
5098           for (i = 0; i < 8; i++)
5099             aarch64_set_vec_u16 (cpu, vd, i,
5100                                  aarch64_get_vec_u8 (cpu, vn, i + bias)
5101                                  - aarch64_get_vec_u8 (cpu, vm, i + bias));
5102           break;
5103
5104         case 1:
5105           bias *= 2;
5106           for (i = 0; i < 4; i++)
5107             aarch64_set_vec_u32 (cpu, vd, i,
5108                                  aarch64_get_vec_u16 (cpu, vn, i + bias)
5109                                  - aarch64_get_vec_u16 (cpu, vm, i + bias));
5110           break;
5111
5112         case 2:
5113           for (i = 0; i < 2; i++)
5114             aarch64_set_vec_u64 (cpu, vd, i,
5115                                  aarch64_get_vec_u32 (cpu, vn, i + bias)
5116                                  - aarch64_get_vec_u32 (cpu, vm, i + bias));
5117           break;
5118
5119         default:
5120           HALT_UNALLOC;
5121         }
5122       break;
5123     }
5124 }
5125
5126 static void
5127 do_vec_ADDP (sim_cpu *cpu)
5128 {
5129   /* instr[31]    = 0
5130      instr[30]    = half(0)/full(1)
5131      instr[29,24] = 00 1110
5132      instr[23,22] = size: bytes (00), half (01), word (10), long (11)
5133      instr[21]    = 1
5134      insrt[20,16] = Vm
5135      instr[15,10] = 1011 11
5136      instr[9,5]   = Vn
5137      instr[4,0]   = V dest.  */
5138
5139   FRegister copy_vn;
5140   FRegister copy_vm;
5141   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5142   unsigned size = uimm (aarch64_get_instr (cpu), 23, 22);
5143   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5144   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5145   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5146   unsigned i, range;
5147
5148   NYI_assert (29, 24, 0x0E);
5149   NYI_assert (21, 21, 1);
5150   NYI_assert (15, 10, 0x2F);
5151
5152   /* Make copies of the source registers in case vd == vn/vm.  */
5153   copy_vn = cpu->fr[vn];
5154   copy_vm = cpu->fr[vm];
5155
5156   switch (size)
5157     {
5158     case 0:
5159       range = full ? 8 : 4;
5160       for (i = 0; i < range; i++)
5161         {
5162           aarch64_set_vec_u8 (cpu, vd, i,
5163                               copy_vn.b[i * 2] + copy_vn.b[i * 2 + 1]);
5164           aarch64_set_vec_u8 (cpu, vd, i + range,
5165                               copy_vm.b[i * 2] + copy_vm.b[i * 2 + 1]);
5166         }
5167       return;
5168
5169     case 1:
5170       range = full ? 4 : 2;
5171       for (i = 0; i < range; i++)
5172         {
5173           aarch64_set_vec_u16 (cpu, vd, i,
5174                                copy_vn.h[i * 2] + copy_vn.h[i * 2 + 1]);
5175           aarch64_set_vec_u16 (cpu, vd, i + range,
5176                                copy_vm.h[i * 2] + copy_vm.h[i * 2 + 1]);
5177         }
5178       return;
5179
5180     case 2:
5181       range = full ? 2 : 1;
5182       for (i = 0; i < range; i++)
5183         {
5184           aarch64_set_vec_u32 (cpu, vd, i,
5185                                copy_vn.w[i * 2] + copy_vn.w[i * 2 + 1]);
5186           aarch64_set_vec_u32 (cpu, vd, i + range,
5187                                copy_vm.w[i * 2] + copy_vm.w[i * 2 + 1]);
5188         }
5189       return;
5190
5191     case 3:
5192       if (! full)
5193         HALT_UNALLOC;
5194       aarch64_set_vec_u64 (cpu, vd, 0, copy_vn.v[0] + copy_vn.v[1]);
5195       aarch64_set_vec_u64 (cpu, vd, 1, copy_vm.v[0] + copy_vm.v[1]);
5196       return;
5197     }
5198 }
5199
5200 static void
5201 do_vec_UMOV (sim_cpu *cpu)
5202 {
5203   /* instr[31]    = 0
5204      instr[30]    = 32-bit(0)/64-bit(1)
5205      instr[29,21] = 00 1110 000
5206      insrt[20,16] = size & index
5207      instr[15,10] = 0011 11
5208      instr[9,5]   = V source
5209      instr[4,0]   = R dest.  */
5210
5211   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5212   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
5213   unsigned index;
5214
5215   NYI_assert (29, 21, 0x070);
5216   NYI_assert (15, 10, 0x0F);
5217
5218   if (uimm (aarch64_get_instr (cpu), 16, 16))
5219     {
5220       /* Byte transfer.  */
5221       index = uimm (aarch64_get_instr (cpu), 20, 17);
5222       aarch64_set_reg_u64 (cpu, rd, NO_SP,
5223                            aarch64_get_vec_u8 (cpu, vs, index));
5224     }
5225   else if (uimm (aarch64_get_instr (cpu), 17, 17))
5226     {
5227       index = uimm (aarch64_get_instr (cpu), 20, 18);
5228       aarch64_set_reg_u64 (cpu, rd, NO_SP,
5229                            aarch64_get_vec_u16 (cpu, vs, index));
5230     }
5231   else if (uimm (aarch64_get_instr (cpu), 18, 18))
5232     {
5233       index = uimm (aarch64_get_instr (cpu), 20, 19);
5234       aarch64_set_reg_u64 (cpu, rd, NO_SP,
5235                            aarch64_get_vec_u32 (cpu, vs, index));
5236     }
5237   else
5238     {
5239       if (uimm (aarch64_get_instr (cpu), 30, 30) != 1)
5240         HALT_UNALLOC;
5241
5242       index = uimm (aarch64_get_instr (cpu), 20, 20);
5243       aarch64_set_reg_u64 (cpu, rd, NO_SP,
5244                            aarch64_get_vec_u64 (cpu, vs, index));
5245     }
5246 }
5247
5248 static void
5249 do_vec_FABS (sim_cpu *cpu)
5250 {
5251   /* instr[31]    = 0
5252      instr[30]    = half(0)/full(1)
5253      instr[29,23] = 00 1110 1
5254      instr[22]    = float(0)/double(1)
5255      instr[21,16] = 10 0000
5256      instr[15,10] = 1111 10
5257      instr[9,5]   = Vn
5258      instr[4,0]   = Vd.  */
5259
5260   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5261   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5262   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5263   unsigned i;
5264
5265   NYI_assert (29, 23, 0x1D);
5266   NYI_assert (21, 10, 0x83E);
5267
5268   if (uimm (aarch64_get_instr (cpu), 22, 22))
5269     {
5270       if (! full)
5271         HALT_NYI;
5272
5273       for (i = 0; i < 2; i++)
5274         aarch64_set_vec_double (cpu, vd, i,
5275                                 fabs (aarch64_get_vec_double (cpu, vn, i)));
5276     }
5277   else
5278     {
5279       for (i = 0; i < (full ? 4 : 2); i++)
5280         aarch64_set_vec_float (cpu, vd, i,
5281                                fabsf (aarch64_get_vec_float (cpu, vn, i)));
5282     }
5283 }
5284
5285 static void
5286 do_vec_FCVTZS (sim_cpu *cpu)
5287 {
5288   /* instr[31]    = 0
5289      instr[30]    = half (0) / all (1)
5290      instr[29,23] = 00 1110 1
5291      instr[22]    = single (0) / double (1)
5292      instr[21,10] = 10 0001 1011 10
5293      instr[9,5]   = Rn
5294      instr[4,0]   = Rd.  */
5295
5296   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
5297   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
5298   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5299   unsigned i;
5300
5301   NYI_assert (31, 31, 0);
5302   NYI_assert (29, 23, 0x1D);
5303   NYI_assert (21, 10, 0x86E);
5304
5305   if (uimm (aarch64_get_instr (cpu), 22, 22))
5306     {
5307       if (! full)
5308         HALT_UNALLOC;
5309
5310       for (i = 0; i < 2; i++)
5311         aarch64_set_vec_s64 (cpu, rd, i,
5312                              (int64_t) aarch64_get_vec_double (cpu, rn, i));
5313     }
5314   else
5315     for (i = 0; i < (full ? 4 : 2); i++)
5316       aarch64_set_vec_s32 (cpu, rd, i,
5317                            (int32_t) aarch64_get_vec_float (cpu, rn, i));
5318 }
5319
5320 static void
5321 do_vec_op1 (sim_cpu *cpu)
5322 {
5323   /* instr[31]    = 0
5324      instr[30]    = half/full
5325      instr[29,24] = 00 1110
5326      instr[23,21] = ???
5327      instr[20,16] = Vm
5328      instr[15,10] = sub-opcode
5329      instr[9,5]   = Vn
5330      instr[4,0]   = Vd  */
5331   NYI_assert (29, 24, 0x0E);
5332
5333   if (uimm (aarch64_get_instr (cpu), 21, 21) == 0)
5334     {
5335       if (uimm (aarch64_get_instr (cpu), 23, 22) == 0)
5336         {
5337           if (uimm (aarch64_get_instr (cpu), 30, 30) == 1
5338               && uimm (aarch64_get_instr (cpu), 17, 14) == 0
5339               && uimm (aarch64_get_instr (cpu), 12, 10) == 7)
5340             return do_vec_ins_2 (cpu);
5341
5342           switch (uimm (aarch64_get_instr (cpu), 15, 10))
5343             {
5344             case 0x01: do_vec_DUP_vector_into_vector (cpu); return;
5345             case 0x03: do_vec_DUP_scalar_into_vector (cpu); return;
5346             case 0x07: do_vec_INS (cpu); return;
5347             case 0x0A: do_vec_TRN (cpu); return;
5348
5349             case 0x0F:
5350               if (uimm (aarch64_get_instr (cpu), 17, 16) == 0)
5351                 {
5352                   do_vec_MOV_into_scalar (cpu);
5353                   return;
5354                 }
5355               break;
5356
5357             case 0x00:
5358             case 0x08:
5359             case 0x10:
5360             case 0x18:
5361               do_vec_TBL (cpu); return;
5362
5363             case 0x06:
5364             case 0x16:
5365               do_vec_UZP (cpu); return;
5366
5367             case 0x0E:
5368             case 0x1E:
5369               do_vec_ZIP (cpu); return;
5370
5371             default:
5372               HALT_NYI;
5373             }
5374         }
5375
5376       switch (uimm (aarch64_get_instr (cpu), 13, 10))
5377         {
5378         case 0x6: do_vec_UZP (cpu); return;
5379         case 0xE: do_vec_ZIP (cpu); return;
5380         case 0xA: do_vec_TRN (cpu); return;
5381         case 0xF: do_vec_UMOV (cpu); return;
5382         default:  HALT_NYI;
5383         }
5384     }
5385
5386   switch (uimm (aarch64_get_instr (cpu), 15, 10))
5387     {
5388     case 0x07:
5389       switch (uimm (aarch64_get_instr (cpu), 23, 21))
5390         {
5391         case 1: do_vec_AND (cpu); return;
5392         case 3: do_vec_BIC (cpu); return;
5393         case 5: do_vec_ORR (cpu); return;
5394         case 7: do_vec_ORN (cpu); return;
5395         default: HALT_NYI;
5396         }
5397
5398     case 0x08: do_vec_sub_long (cpu); return;
5399     case 0x0a: do_vec_XTN (cpu); return;
5400     case 0x11: do_vec_SSHL (cpu); return;
5401     case 0x19: do_vec_max (cpu); return;
5402     case 0x1B: do_vec_min (cpu); return;
5403     case 0x21: do_vec_add (cpu); return;
5404     case 0x25: do_vec_MLA (cpu); return;
5405     case 0x27: do_vec_mul (cpu); return;
5406     case 0x2F: do_vec_ADDP (cpu); return;
5407     case 0x30: do_vec_mull (cpu); return;
5408     case 0x33: do_vec_FMLA (cpu); return;
5409     case 0x35: do_vec_fadd (cpu); return;
5410
5411     case 0x2E:
5412       switch (uimm (aarch64_get_instr (cpu), 20, 16))
5413         {
5414         case 0x00: do_vec_ABS (cpu); return;
5415         case 0x01: do_vec_FCVTZS (cpu); return;
5416         case 0x11: do_vec_ADDV (cpu); return;
5417         default: HALT_NYI;
5418         }
5419
5420     case 0x31:
5421     case 0x3B:
5422       do_vec_Fminmax (cpu); return;
5423
5424     case 0x0D:
5425     case 0x0F:
5426     case 0x22:
5427     case 0x23:
5428     case 0x26:
5429     case 0x2A:
5430     case 0x32:
5431     case 0x36:
5432     case 0x39:
5433     case 0x3A:
5434       do_vec_compare (cpu); return;
5435
5436     case 0x3E:
5437       do_vec_FABS (cpu); return;
5438
5439     default:
5440       HALT_NYI;
5441     }
5442 }
5443
5444 static void
5445 do_vec_xtl (sim_cpu *cpu)
5446 {
5447   /* instr[31]    = 0
5448      instr[30,29] = SXTL (00), UXTL (01), SXTL2 (10), UXTL2 (11)
5449      instr[28,22] = 0 1111 00
5450      instr[21,16] = size & shift (USHLL, SSHLL, USHLL2, SSHLL2)
5451      instr[15,10] = 1010 01
5452      instr[9,5]   = V source
5453      instr[4,0]   = V dest.  */
5454
5455   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5456   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5457   unsigned i, shift, bias = 0;
5458
5459   NYI_assert (28, 22, 0x3C);
5460   NYI_assert (15, 10, 0x29);
5461
5462   switch (uimm (aarch64_get_instr (cpu), 30, 29))
5463     {
5464     case 2: /* SXTL2, SSHLL2.  */
5465       bias = 2;
5466     case 0: /* SXTL, SSHLL.  */
5467       if (uimm (aarch64_get_instr (cpu), 21, 21))
5468         {
5469           shift = uimm (aarch64_get_instr (cpu), 20, 16);
5470           aarch64_set_vec_s64
5471             (cpu, vd, 0, aarch64_get_vec_s32 (cpu, vs, bias) << shift);
5472           aarch64_set_vec_s64
5473             (cpu, vd, 1, aarch64_get_vec_s32 (cpu, vs, bias + 1) << shift);
5474         }
5475       else if (uimm (aarch64_get_instr (cpu), 20, 20))
5476         {
5477           shift = uimm (aarch64_get_instr (cpu), 19, 16);
5478           bias *= 2;
5479           for (i = 0; i < 4; i++)
5480             aarch64_set_vec_s32
5481               (cpu, vd, i, aarch64_get_vec_s16 (cpu, vs, i + bias) << shift);
5482         }
5483       else
5484         {
5485           NYI_assert (19, 19, 1);
5486
5487           shift = uimm (aarch64_get_instr (cpu), 18, 16);
5488           bias *= 3;
5489           for (i = 0; i < 8; i++)
5490             aarch64_set_vec_s16
5491               (cpu, vd, i, aarch64_get_vec_s8 (cpu, vs, i + bias) << shift);
5492         }
5493       return;
5494
5495     case 3: /* UXTL2, USHLL2.  */
5496       bias = 2;
5497     case 1: /* UXTL, USHLL.  */
5498       if (uimm (aarch64_get_instr (cpu), 21, 21))
5499         {
5500           shift = uimm (aarch64_get_instr (cpu), 20, 16);
5501           aarch64_set_vec_u64
5502             (cpu, vd, 0, aarch64_get_vec_u32 (cpu, vs, bias) << shift);
5503           aarch64_set_vec_u64
5504             (cpu, vd, 1, aarch64_get_vec_u32 (cpu, vs, bias + 1) << shift);
5505         }
5506       else if (uimm (aarch64_get_instr (cpu), 20, 20))
5507         {
5508           shift = uimm (aarch64_get_instr (cpu), 19, 16);
5509           bias *= 2;
5510           for (i = 0; i < 4; i++)
5511             aarch64_set_vec_u32
5512               (cpu, vd, i, aarch64_get_vec_u16 (cpu, vs, i + bias) << shift);
5513         }
5514       else
5515         {
5516           NYI_assert (19, 19, 1);
5517
5518           shift = uimm (aarch64_get_instr (cpu), 18, 16);
5519           bias *= 3;
5520           for (i = 0; i < 8; i++)
5521             aarch64_set_vec_u16
5522               (cpu, vd, i, aarch64_get_vec_u8 (cpu, vs, i + bias) << shift);
5523         }
5524       return;
5525     }
5526 }
5527
5528 static void
5529 do_vec_SHL (sim_cpu *cpu)
5530 {
5531   /* instr [31]    = 0
5532      instr [30]    = half(0)/full(1)
5533      instr [29,23] = 001 1110
5534      instr [22,16] = size and shift amount
5535      instr [15,10] = 01 0101
5536      instr [9, 5]  = Vs
5537      instr [4, 0]  = Vd.  */
5538
5539   int shift;
5540   int full    = uimm (aarch64_get_instr (cpu), 30, 30);
5541   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5542   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5543   unsigned i;
5544
5545   NYI_assert (29, 23, 0x1E);
5546   NYI_assert (15, 10, 0x15);
5547
5548   if (uimm (aarch64_get_instr (cpu), 22, 22))
5549     {
5550       shift = uimm (aarch64_get_instr (cpu), 21, 16);
5551
5552       if (full == 0)
5553         HALT_UNALLOC;
5554
5555       for (i = 0; i < 2; i++)
5556         {
5557           uint64_t val = aarch64_get_vec_u64 (cpu, vs, i);
5558           aarch64_set_vec_u64 (cpu, vd, i, val << shift);
5559         }
5560
5561       return;
5562     }
5563
5564   if (uimm (aarch64_get_instr (cpu), 21, 21))
5565     {
5566       shift = uimm (aarch64_get_instr (cpu), 20, 16);
5567
5568       for (i = 0; i < (full ? 4 : 2); i++)
5569         {
5570           uint32_t val = aarch64_get_vec_u32 (cpu, vs, i);
5571           aarch64_set_vec_u32 (cpu, vd, i, val << shift);
5572         }
5573
5574       return;
5575     }
5576
5577   if (uimm (aarch64_get_instr (cpu), 20, 20))
5578     {
5579       shift = uimm (aarch64_get_instr (cpu), 19, 16);
5580
5581       for (i = 0; i < (full ? 8 : 4); i++)
5582         {
5583           uint16_t val = aarch64_get_vec_u16 (cpu, vs, i);
5584           aarch64_set_vec_u16 (cpu, vd, i, val << shift);
5585         }
5586
5587       return;
5588     }
5589
5590   if (uimm (aarch64_get_instr (cpu), 19, 19) == 0)
5591     HALT_UNALLOC;
5592
5593   shift = uimm (aarch64_get_instr (cpu), 18, 16);
5594
5595   for (i = 0; i < (full ? 16 : 8); i++)
5596     {
5597       uint8_t val = aarch64_get_vec_u8 (cpu, vs, i);
5598       aarch64_set_vec_u8 (cpu, vd, i, val << shift);
5599     }
5600 }
5601
5602 static void
5603 do_vec_SSHR_USHR (sim_cpu *cpu)
5604 {
5605   /* instr [31]    = 0
5606      instr [30]    = half(0)/full(1)
5607      instr [29]    = signed(0)/unsigned(1)
5608      instr [28,23] = 0 1111 0
5609      instr [22,16] = size and shift amount
5610      instr [15,10] = 0000 01
5611      instr [9, 5]  = Vs
5612      instr [4, 0]  = Vd.  */
5613
5614   int full       = INSTR (30, 30);
5615   int sign       = ! INSTR (29, 29);
5616   unsigned shift = INSTR (22, 16);
5617   unsigned vs    = INSTR (9, 5);
5618   unsigned vd    = INSTR (4, 0);
5619   unsigned i;
5620
5621   NYI_assert (28, 23, 0x1E);
5622   NYI_assert (15, 10, 0x01);
5623
5624   if (uimm (aarch64_get_instr (cpu), 22, 22))
5625     {
5626       shift = 128 - shift;
5627
5628       if (full == 0)
5629         HALT_UNALLOC;
5630
5631       if (sign)
5632         for (i = 0; i < 2; i++)
5633           {
5634             int64_t val = aarch64_get_vec_s64 (cpu, vs, i);
5635             aarch64_set_vec_s64 (cpu, vd, i, val >> shift);
5636           }
5637       else
5638         for (i = 0; i < 2; i++)
5639           {
5640             uint64_t val = aarch64_get_vec_u64 (cpu, vs, i);
5641             aarch64_set_vec_u64 (cpu, vd, i, val >> shift);
5642           }
5643
5644       return;
5645     }
5646
5647   if (uimm (aarch64_get_instr (cpu), 21, 21))
5648     {
5649       shift = 64 - shift;
5650
5651       if (sign)
5652         for (i = 0; i < (full ? 4 : 2); i++)
5653           {
5654             int32_t val = aarch64_get_vec_s32 (cpu, vs, i);
5655             aarch64_set_vec_s32 (cpu, vd, i, val >> shift);
5656           }
5657       else
5658         for (i = 0; i < (full ? 4 : 2); i++)
5659           {
5660             uint32_t val = aarch64_get_vec_u32 (cpu, vs, i);
5661             aarch64_set_vec_u32 (cpu, vd, i, val >> shift);
5662           }
5663
5664       return;
5665     }
5666
5667   if (uimm (aarch64_get_instr (cpu), 20, 20))
5668     {
5669       shift = 32 - shift;
5670
5671       if (sign)
5672         for (i = 0; i < (full ? 8 : 4); i++)
5673           {
5674             int16_t val = aarch64_get_vec_s16 (cpu, vs, i);
5675             aarch64_set_vec_s16 (cpu, vd, i, val >> shift);
5676           }
5677       else
5678         for (i = 0; i < (full ? 8 : 4); i++)
5679           {
5680             uint16_t val = aarch64_get_vec_u16 (cpu, vs, i);
5681             aarch64_set_vec_u16 (cpu, vd, i, val >> shift);
5682           }
5683
5684       return;
5685     }
5686
5687   if (uimm (aarch64_get_instr (cpu), 19, 19) == 0)
5688     HALT_UNALLOC;
5689
5690   shift = 16 - shift;
5691
5692   if (sign)
5693     for (i = 0; i < (full ? 16 : 8); i++)
5694       {
5695         int8_t val = aarch64_get_vec_s8 (cpu, vs, i);
5696         aarch64_set_vec_s8 (cpu, vd, i, val >> shift);
5697       }
5698   else
5699     for (i = 0; i < (full ? 16 : 8); i++)
5700       {
5701         uint8_t val = aarch64_get_vec_u8 (cpu, vs, i);
5702         aarch64_set_vec_u8 (cpu, vd, i, val >> shift);
5703       }
5704 }
5705
5706 static void
5707 do_vec_MUL_by_element (sim_cpu *cpu)
5708 {
5709   /* instr[31]    = 0
5710      instr[30]    = half/full
5711      instr[29,24] = 00 1111
5712      instr[23,22] = size
5713      instr[21]    = L
5714      instr[20]    = M
5715      instr[19,16] = m
5716      instr[15,12] = 1000
5717      instr[11]    = H
5718      instr[10]    = 0
5719      instr[9,5]   = Vn
5720      instr[4,0]   = Vd  */
5721
5722   unsigned full     = uimm (aarch64_get_instr (cpu), 30, 30);
5723   unsigned L        = uimm (aarch64_get_instr (cpu), 21, 21);
5724   unsigned H        = uimm (aarch64_get_instr (cpu), 11, 11);
5725   unsigned vn       = uimm (aarch64_get_instr (cpu), 9, 5);
5726   unsigned vd       = uimm (aarch64_get_instr (cpu), 4, 0);
5727   unsigned size     = uimm (aarch64_get_instr (cpu), 23, 22);
5728   unsigned index;
5729   unsigned vm;
5730   unsigned e;
5731
5732   NYI_assert (29, 24, 0x0F);
5733   NYI_assert (15, 12, 0x8);
5734   NYI_assert (10, 10, 0);
5735
5736   switch (size)
5737     {
5738     case 1:
5739       {
5740         /* 16 bit products.  */
5741         uint16_t product;
5742         uint16_t element1;
5743         uint16_t element2;
5744
5745         index = (H << 2) | (L << 1) | uimm (aarch64_get_instr (cpu), 20, 20);
5746         vm = uimm (aarch64_get_instr (cpu), 19, 16);
5747         element2 = aarch64_get_vec_u16 (cpu, vm, index);
5748
5749         for (e = 0; e < (full ? 8 : 4); e ++)
5750           {
5751             element1 = aarch64_get_vec_u16 (cpu, vn, e);
5752             product  = element1 * element2;
5753             aarch64_set_vec_u16 (cpu, vd, e, product);
5754           }
5755       }
5756       break;
5757
5758     case 2:
5759       {
5760         /* 32 bit products.  */
5761         uint32_t product;
5762         uint32_t element1;
5763         uint32_t element2;
5764
5765         index = (H << 1) | L;
5766         vm = uimm (aarch64_get_instr (cpu), 20, 16);
5767         element2 = aarch64_get_vec_u32 (cpu, vm, index);
5768
5769         for (e = 0; e < (full ? 4 : 2); e ++)
5770           {
5771             element1 = aarch64_get_vec_u32 (cpu, vn, e);
5772             product  = element1 * element2;
5773             aarch64_set_vec_u32 (cpu, vd, e, product);
5774           }
5775       }
5776       break;
5777
5778     default:
5779       HALT_UNALLOC;
5780     }
5781 }
5782
5783 static void
5784 do_vec_op2 (sim_cpu *cpu)
5785 {
5786   /* instr[31]    = 0
5787      instr[30]    = half/full
5788      instr[29,24] = 00 1111
5789      instr[23]    = ?
5790      instr[22,16] = element size & index
5791      instr[15,10] = sub-opcode
5792      instr[9,5]   = Vm
5793      instr[4,0]   = Vd  */
5794
5795   NYI_assert (29, 24, 0x0F);
5796
5797   if (uimm (aarch64_get_instr (cpu), 23, 23) != 0)
5798     {
5799       switch (uimm (aarch64_get_instr (cpu), 15, 10))
5800         {
5801         case 0x20:
5802         case 0x22: do_vec_MUL_by_element (cpu); return;
5803         default:   HALT_NYI;
5804         }
5805     }
5806   else
5807     {
5808       switch (uimm (aarch64_get_instr (cpu), 15, 10))
5809         {
5810         case 0x01: do_vec_SSHR_USHR (cpu); return;
5811         case 0x15: do_vec_SHL (cpu); return;
5812         case 0x20:
5813         case 0x22: do_vec_MUL_by_element (cpu); return;
5814         case 0x29: do_vec_xtl (cpu); return;
5815         default:   HALT_NYI;
5816         }
5817     }
5818 }
5819
5820 static void
5821 do_vec_neg (sim_cpu *cpu)
5822 {
5823   /* instr[31]    = 0
5824      instr[30]    = full(1)/half(0)
5825      instr[29,24] = 10 1110
5826      instr[23,22] = size: byte(00), half (01), word (10), long (11)
5827      instr[21,10] = 1000 0010 1110
5828      instr[9,5]   = Vs
5829      instr[4,0]   = Vd  */
5830
5831   int    full = uimm (aarch64_get_instr (cpu), 30, 30);
5832   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5833   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5834   unsigned i;
5835
5836   NYI_assert (29, 24, 0x2E);
5837   NYI_assert (21, 10, 0x82E);
5838
5839   switch (uimm (aarch64_get_instr (cpu), 23, 22))
5840     {
5841     case 0:
5842       for (i = 0; i < (full ? 16 : 8); i++)
5843         aarch64_set_vec_s8 (cpu, vd, i, - aarch64_get_vec_s8 (cpu, vs, i));
5844       return;
5845
5846     case 1:
5847       for (i = 0; i < (full ? 8 : 4); i++)
5848         aarch64_set_vec_s16 (cpu, vd, i, - aarch64_get_vec_s16 (cpu, vs, i));
5849       return;
5850
5851     case 2:
5852       for (i = 0; i < (full ? 4 : 2); i++)
5853         aarch64_set_vec_s32 (cpu, vd, i, - aarch64_get_vec_s32 (cpu, vs, i));
5854       return;
5855
5856     case 3:
5857       if (! full)
5858         HALT_NYI;
5859       for (i = 0; i < 2; i++)
5860         aarch64_set_vec_s64 (cpu, vd, i, - aarch64_get_vec_s64 (cpu, vs, i));
5861       return;
5862     }
5863 }
5864
5865 static void
5866 do_vec_sqrt (sim_cpu *cpu)
5867 {
5868   /* instr[31]    = 0
5869      instr[30]    = full(1)/half(0)
5870      instr[29,23] = 101 1101
5871      instr[22]    = single(0)/double(1)
5872      instr[21,10] = 1000 0111 1110
5873      instr[9,5]   = Vs
5874      instr[4,0]   = Vd.  */
5875
5876   int    full = uimm (aarch64_get_instr (cpu), 30, 30);
5877   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5878   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5879   unsigned i;
5880
5881   NYI_assert (29, 23, 0x5B);
5882   NYI_assert (21, 10, 0x87E);
5883
5884   if (uimm (aarch64_get_instr (cpu), 22, 22) == 0)
5885     for (i = 0; i < (full ? 4 : 2); i++)
5886       aarch64_set_vec_float (cpu, vd, i,
5887                              sqrtf (aarch64_get_vec_float (cpu, vs, i)));
5888   else
5889     for (i = 0; i < 2; i++)
5890       aarch64_set_vec_double (cpu, vd, i,
5891                               sqrt (aarch64_get_vec_double (cpu, vs, i)));
5892 }
5893
5894 static void
5895 do_vec_mls_indexed (sim_cpu *cpu)
5896 {
5897   /* instr[31]       = 0
5898      instr[30]       = half(0)/full(1)
5899      instr[29,24]    = 10 1111
5900      instr[23,22]    = 16-bit(01)/32-bit(10)
5901      instr[21,20+11] = index (if 16-bit)
5902      instr[21+11]    = index (if 32-bit)
5903      instr[20,16]    = Vm
5904      instr[15,12]    = 0100
5905      instr[11]       = part of index
5906      instr[10]       = 0
5907      instr[9,5]      = Vs
5908      instr[4,0]      = Vd.  */
5909
5910   int    full = uimm (aarch64_get_instr (cpu), 30, 30);
5911   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
5912   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5913   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5914   unsigned i;
5915
5916   NYI_assert (15, 12, 4);
5917   NYI_assert (10, 10, 0);
5918
5919   switch (uimm (aarch64_get_instr (cpu), 23, 22))
5920     {
5921     case 1:
5922       {
5923         unsigned elem;
5924         uint32_t val;
5925
5926         if (vm > 15)
5927           HALT_NYI;
5928
5929         elem = (uimm (aarch64_get_instr (cpu), 21, 20) << 1)
5930           | uimm (aarch64_get_instr (cpu), 11, 11);
5931         val = aarch64_get_vec_u16 (cpu, vm, elem);
5932
5933         for (i = 0; i < (full ? 8 : 4); i++)
5934           aarch64_set_vec_u32 (cpu, vd, i,
5935                                aarch64_get_vec_u32 (cpu, vd, i) -
5936                                (aarch64_get_vec_u32 (cpu, vs, i) * val));
5937         return;
5938       }
5939
5940     case 2:
5941       {
5942         unsigned elem = (uimm (aarch64_get_instr (cpu), 21, 21) << 1)
5943           | uimm (aarch64_get_instr (cpu), 11, 11);
5944         uint64_t val = aarch64_get_vec_u32 (cpu, vm, elem);
5945
5946         for (i = 0; i < (full ? 4 : 2); i++)
5947           aarch64_set_vec_u64 (cpu, vd, i,
5948                                aarch64_get_vec_u64 (cpu, vd, i) -
5949                                (aarch64_get_vec_u64 (cpu, vs, i) * val));
5950         return;
5951       }
5952
5953     case 0:
5954     case 3:
5955     default:
5956       HALT_NYI;
5957     }
5958 }
5959
5960 static void
5961 do_vec_SUB (sim_cpu *cpu)
5962 {
5963   /* instr [31]    = 0
5964      instr [30]    = half(0)/full(1)
5965      instr [29,24] = 10 1110
5966      instr [23,22] = size: byte(00, half(01), word (10), long (11)
5967      instr [21]    = 1
5968      instr [20,16] = Vm
5969      instr [15,10] = 10 0001
5970      instr [9, 5]  = Vn
5971      instr [4, 0]  = Vd.  */
5972
5973   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
5974   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
5975   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
5976   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
5977   unsigned i;
5978
5979   NYI_assert (29, 24, 0x2E);
5980   NYI_assert (21, 21, 1);
5981   NYI_assert (15, 10, 0x21);
5982
5983   switch (uimm (aarch64_get_instr (cpu), 23, 22))
5984     {
5985     case 0:
5986       for (i = 0; i < (full ? 16 : 8); i++)
5987         aarch64_set_vec_s8 (cpu, vd, i,
5988                             aarch64_get_vec_s8 (cpu, vn, i)
5989                             - aarch64_get_vec_s8 (cpu, vm, i));
5990       return;
5991
5992     case 1:
5993       for (i = 0; i < (full ? 8 : 4); i++)
5994         aarch64_set_vec_s16 (cpu, vd, i,
5995                              aarch64_get_vec_s16 (cpu, vn, i)
5996                              - aarch64_get_vec_s16 (cpu, vm, i));
5997       return;
5998
5999     case 2:
6000       for (i = 0; i < (full ? 4 : 2); i++)
6001         aarch64_set_vec_s32 (cpu, vd, i,
6002                              aarch64_get_vec_s32 (cpu, vn, i)
6003                              - aarch64_get_vec_s32 (cpu, vm, i));
6004       return;
6005
6006     case 3:
6007       if (full == 0)
6008         HALT_UNALLOC;
6009
6010       for (i = 0; i < 2; i++)
6011         aarch64_set_vec_s64 (cpu, vd, i,
6012                              aarch64_get_vec_s64 (cpu, vn, i)
6013                              - aarch64_get_vec_s64 (cpu, vm, i));
6014       return;
6015     }
6016 }
6017
6018 static void
6019 do_vec_MLS (sim_cpu *cpu)
6020 {
6021   /* instr [31]    = 0
6022      instr [30]    = half(0)/full(1)
6023      instr [29,24] = 10 1110
6024      instr [23,22] = size: byte(00, half(01), word (10)
6025      instr [21]    = 1
6026      instr [20,16] = Vm
6027      instr [15,10] = 10 0101
6028      instr [9, 5]  = Vn
6029      instr [4, 0]  = Vd.  */
6030
6031   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6032   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
6033   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6034   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6035   unsigned i;
6036
6037   NYI_assert (29, 24, 0x2E);
6038   NYI_assert (21, 21, 1);
6039   NYI_assert (15, 10, 0x25);
6040
6041   switch (uimm (aarch64_get_instr (cpu), 23, 22))
6042     {
6043     case 0:
6044       for (i = 0; i < (full ? 16 : 8); i++)
6045         aarch64_set_vec_u8 (cpu, vd, i,
6046                             (aarch64_get_vec_u8 (cpu, vn, i)
6047                              * aarch64_get_vec_u8 (cpu, vm, i))
6048                             - aarch64_get_vec_u8 (cpu, vd, i));
6049       return;
6050
6051     case 1:
6052       for (i = 0; i < (full ? 8 : 4); i++)
6053         aarch64_set_vec_u16 (cpu, vd, i,
6054                              (aarch64_get_vec_u16 (cpu, vn, i)
6055                               * aarch64_get_vec_u16 (cpu, vm, i))
6056                              - aarch64_get_vec_u16 (cpu, vd, i));
6057       return;
6058
6059     case 2:
6060       for (i = 0; i < (full ? 4 : 2); i++)
6061         aarch64_set_vec_u32 (cpu, vd, i,
6062                              (aarch64_get_vec_u32 (cpu, vn, i)
6063                               * aarch64_get_vec_u32 (cpu, vm, i))
6064                              - aarch64_get_vec_u32 (cpu, vd, i));
6065       return;
6066
6067     default:
6068       HALT_UNALLOC;
6069     }
6070 }
6071
6072 static void
6073 do_vec_FDIV (sim_cpu *cpu)
6074 {
6075   /* instr [31]    = 0
6076      instr [30]    = half(0)/full(1)
6077      instr [29,23] = 10 1110 0
6078      instr [22]    = float()/double(1)
6079      instr [21]    = 1
6080      instr [20,16] = Vm
6081      instr [15,10] = 1111 11
6082      instr [9, 5]  = Vn
6083      instr [4, 0]  = Vd.  */
6084
6085   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6086   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
6087   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6088   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6089   unsigned i;
6090
6091   NYI_assert (29, 23, 0x5C);
6092   NYI_assert (21, 21, 1);
6093   NYI_assert (15, 10, 0x3F);
6094
6095   if (uimm (aarch64_get_instr (cpu), 22, 22))
6096     {
6097       if (! full)
6098         HALT_UNALLOC;
6099
6100       for (i = 0; i < 2; i++)
6101         aarch64_set_vec_double (cpu, vd, i,
6102                                 aarch64_get_vec_double (cpu, vn, i)
6103                                 / aarch64_get_vec_double (cpu, vm, i));
6104     }
6105   else
6106     for (i = 0; i < (full ? 4 : 2); i++)
6107       aarch64_set_vec_float (cpu, vd, i,
6108                              aarch64_get_vec_float (cpu, vn, i)
6109                              / aarch64_get_vec_float (cpu, vm, i));
6110 }
6111
6112 static void
6113 do_vec_FMUL (sim_cpu *cpu)
6114 {
6115   /* instr [31]    = 0
6116      instr [30]    = half(0)/full(1)
6117      instr [29,23] = 10 1110 0
6118      instr [22]    = float(0)/double(1)
6119      instr [21]    = 1
6120      instr [20,16] = Vm
6121      instr [15,10] = 1101 11
6122      instr [9, 5]  = Vn
6123      instr [4, 0]  = Vd.  */
6124
6125   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6126   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
6127   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6128   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6129   unsigned i;
6130
6131   NYI_assert (29, 23, 0x5C);
6132   NYI_assert (21, 21, 1);
6133   NYI_assert (15, 10, 0x37);
6134
6135   if (uimm (aarch64_get_instr (cpu), 22, 22))
6136     {
6137       if (! full)
6138         HALT_UNALLOC;
6139
6140       for (i = 0; i < 2; i++)
6141         aarch64_set_vec_double (cpu, vd, i,
6142                                 aarch64_get_vec_double (cpu, vn, i)
6143                                 * aarch64_get_vec_double (cpu, vm, i));
6144     }
6145   else
6146     for (i = 0; i < (full ? 4 : 2); i++)
6147       aarch64_set_vec_float (cpu, vd, i,
6148                              aarch64_get_vec_float (cpu, vn, i)
6149                              * aarch64_get_vec_float (cpu, vm, i));
6150 }
6151
6152 static void
6153 do_vec_FADDP (sim_cpu *cpu)
6154 {
6155   /* instr [31]    = 0
6156      instr [30]    = half(0)/full(1)
6157      instr [29,23] = 10 1110 0
6158      instr [22]    = float(0)/double(1)
6159      instr [21]    = 1
6160      instr [20,16] = Vm
6161      instr [15,10] = 1101 01
6162      instr [9, 5]  = Vn
6163      instr [4, 0]  = Vd.  */
6164
6165   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6166   unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
6167   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6168   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6169
6170   NYI_assert (29, 23, 0x5C);
6171   NYI_assert (21, 21, 1);
6172   NYI_assert (15, 10, 0x35);
6173
6174   if (uimm (aarch64_get_instr (cpu), 22, 22))
6175     {
6176       /* Extract values before adding them incase vd == vn/vm.  */
6177       double tmp1 = aarch64_get_vec_double (cpu, vn, 0);
6178       double tmp2 = aarch64_get_vec_double (cpu, vn, 1);
6179       double tmp3 = aarch64_get_vec_double (cpu, vm, 0);
6180       double tmp4 = aarch64_get_vec_double (cpu, vm, 1);
6181
6182       if (! full)
6183         HALT_UNALLOC;
6184
6185       aarch64_set_vec_double (cpu, vd, 0, tmp1 + tmp2);
6186       aarch64_set_vec_double (cpu, vd, 1, tmp3 + tmp4);
6187     }
6188   else
6189     {
6190       /* Extract values before adding them incase vd == vn/vm.  */
6191       float tmp1 = aarch64_get_vec_float (cpu, vn, 0);
6192       float tmp2 = aarch64_get_vec_float (cpu, vn, 1);
6193       float tmp5 = aarch64_get_vec_float (cpu, vm, 0);
6194       float tmp6 = aarch64_get_vec_float (cpu, vm, 1);
6195
6196       if (full)
6197         {
6198           float tmp3 = aarch64_get_vec_float (cpu, vn, 2);
6199           float tmp4 = aarch64_get_vec_float (cpu, vn, 3);
6200           float tmp7 = aarch64_get_vec_float (cpu, vm, 2);
6201           float tmp8 = aarch64_get_vec_float (cpu, vm, 3);
6202
6203           aarch64_set_vec_float (cpu, vd, 0, tmp1 + tmp2);
6204           aarch64_set_vec_float (cpu, vd, 1, tmp3 + tmp4);
6205           aarch64_set_vec_float (cpu, vd, 2, tmp5 + tmp6);
6206           aarch64_set_vec_float (cpu, vd, 3, tmp7 + tmp8);
6207         }
6208       else
6209         {
6210           aarch64_set_vec_float (cpu, vd, 0, tmp1 + tmp2);
6211           aarch64_set_vec_float (cpu, vd, 1, tmp5 + tmp6);
6212         }
6213     }
6214 }
6215
6216 static void
6217 do_vec_FSQRT (sim_cpu *cpu)
6218 {
6219   /* instr[31]    = 0
6220      instr[30]    = half(0)/full(1)
6221      instr[29,23] = 10 1110 1
6222      instr[22]    = single(0)/double(1)
6223      instr[21,10] = 10 0001 1111 10
6224      instr[9,5]   = Vsrc
6225      instr[4,0]   = Vdest.  */
6226
6227   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6228   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6229   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6230   int i;
6231
6232   NYI_assert (29, 23, 0x5D);
6233   NYI_assert (21, 10, 0x87E);
6234
6235   if (uimm (aarch64_get_instr (cpu), 22, 22))
6236     {
6237       if (! full)
6238         HALT_UNALLOC;
6239
6240       for (i = 0; i < 2; i++)
6241         aarch64_set_vec_double (cpu, vd, i,
6242                                 sqrt (aarch64_get_vec_double (cpu, vn, i)));
6243     }
6244   else
6245     {
6246       for (i = 0; i < (full ? 4 : 2); i++)
6247         aarch64_set_vec_float (cpu, vd, i,
6248                                sqrtf (aarch64_get_vec_float (cpu, vn, i)));
6249     }
6250 }
6251
6252 static void
6253 do_vec_FNEG (sim_cpu *cpu)
6254 {
6255   /* instr[31]    = 0
6256      instr[30]    = half (0)/full (1)
6257      instr[29,23] = 10 1110 1
6258      instr[22]    = single (0)/double (1)
6259      instr[21,10] = 10 0000 1111 10
6260      instr[9,5]   = Vsrc
6261      instr[4,0]   = Vdest.  */
6262
6263   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6264   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6265   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
6266   int i;
6267
6268   NYI_assert (29, 23, 0x5D);
6269   NYI_assert (21, 10, 0x83E);
6270
6271   if (uimm (aarch64_get_instr (cpu), 22, 22))
6272     {
6273       if (! full)
6274         HALT_UNALLOC;
6275
6276       for (i = 0; i < 2; i++)
6277         aarch64_set_vec_double (cpu, vd, i,
6278                                 - aarch64_get_vec_double (cpu, vn, i));
6279     }
6280   else
6281     {
6282       for (i = 0; i < (full ? 4 : 2); i++)
6283         aarch64_set_vec_float (cpu, vd, i,
6284                                - aarch64_get_vec_float (cpu, vn, i));
6285     }
6286 }
6287
6288 static void
6289 do_vec_NOT (sim_cpu *cpu)
6290 {
6291   /* instr[31]    = 0
6292      instr[30]    = half (0)/full (1)
6293      instr[29,10] = 10 1110 0010 0000 0101 10
6294      instr[9,5]   = Vn
6295      instr[4.0]   = Vd.  */
6296
6297   unsigned vn = uimm (aarch64_get_instr (cpu), 9, 5);
6298   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6299   unsigned i;
6300   int      full = uimm (aarch64_get_instr (cpu), 30, 30);
6301
6302   NYI_assert (29, 10, 0xB8816);
6303
6304   for (i = 0; i < (full ? 16 : 8); i++)
6305     aarch64_set_vec_u8 (cpu, vd, i, ~ aarch64_get_vec_u8 (cpu, vn, i));
6306 }
6307
6308 static unsigned int
6309 clz (uint64_t val, unsigned size)
6310 {
6311   uint64_t mask = 1;
6312   int      count;
6313
6314   mask <<= (size - 1);
6315   count = 0;
6316   do
6317     {
6318       if (val & mask)
6319         break;
6320       mask >>= 1;
6321       count ++;
6322     }
6323   while (mask);
6324
6325   return count;
6326 }
6327
6328 static void
6329 do_vec_CLZ (sim_cpu *cpu)
6330 {
6331   /* instr[31]    = 0
6332      instr[30]    = half (0)/full (1)
6333      instr[29,24] = 10 1110
6334      instr[23,22] = size
6335      instr[21,10] = 10 0000 0100 10
6336      instr[9,5]   = Vn
6337      instr[4.0]   = Vd.  */
6338
6339   unsigned vn = INSTR (9, 5);
6340   unsigned vd = INSTR (4, 0);
6341   unsigned i;
6342   int      full = INSTR (30,30);
6343
6344   NYI_assert (29, 24, 0x2E);
6345   NYI_assert (21, 10, 0x812);
6346
6347   switch (INSTR (23, 22))
6348     {
6349     case 0:
6350       for (i = 0; i < (full ? 16 : 8); i++)
6351         aarch64_set_vec_u8 (cpu, vd, i, clz (aarch64_get_vec_u8 (cpu, vn, i), 8));
6352       break;
6353     case 1:
6354       for (i = 0; i < (full ? 8 : 4); i++)
6355         aarch64_set_vec_u16 (cpu, vd, i, clz (aarch64_get_vec_u16 (cpu, vn, i), 16));
6356       break;
6357     case 2:
6358       for (i = 0; i < (full ? 4 : 2); i++)
6359         aarch64_set_vec_u32 (cpu, vd, i, clz (aarch64_get_vec_u32 (cpu, vn, i), 32));
6360       break;
6361     case 3:
6362       if (! full)
6363         HALT_UNALLOC;
6364       aarch64_set_vec_u64 (cpu, vd, 0, clz (aarch64_get_vec_u64 (cpu, vn, 0), 64));
6365       aarch64_set_vec_u64 (cpu, vd, 1, clz (aarch64_get_vec_u64 (cpu, vn, 1), 64));
6366       break;
6367     }
6368 }
6369
6370 static void
6371 do_vec_MOV_element (sim_cpu *cpu)
6372 {
6373   /* instr[31,21] = 0110 1110 000
6374      instr[20,16] = size & dest index
6375      instr[15]    = 0
6376      instr[14,11] = source index
6377      instr[10]    = 1
6378      instr[9,5]   = Vs
6379      instr[4.0]   = Vd.  */
6380
6381   unsigned vs = uimm (aarch64_get_instr (cpu), 9, 5);
6382   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
6383   unsigned src_index;
6384   unsigned dst_index;
6385
6386   NYI_assert (31, 21, 0x370);
6387   NYI_assert (15, 15, 0);
6388   NYI_assert (10, 10, 1);
6389
6390   if (uimm (aarch64_get_instr (cpu), 16, 16))
6391     {
6392       /* Move a byte.  */
6393       src_index = uimm (aarch64_get_instr (cpu), 14, 11);
6394       dst_index = uimm (aarch64_get_instr (cpu), 20, 17);
6395       aarch64_set_vec_u8 (cpu, vd, dst_index,
6396                           aarch64_get_vec_u8 (cpu, vs, src_index));
6397     }
6398   else if (uimm (aarch64_get_instr (cpu), 17, 17))
6399     {
6400       /* Move 16-bits.  */
6401       NYI_assert (11, 11, 0);
6402       src_index = uimm (aarch64_get_instr (cpu), 14, 12);
6403       dst_index = uimm (aarch64_get_instr (cpu), 20, 18);
6404       aarch64_set_vec_u16 (cpu, vd, dst_index,
6405                            aarch64_get_vec_u16 (cpu, vs, src_index));
6406     }
6407   else if (uimm (aarch64_get_instr (cpu), 18, 18))
6408     {
6409       /* Move 32-bits.  */
6410       NYI_assert (12, 11, 0);
6411       src_index = uimm (aarch64_get_instr (cpu), 14, 13);
6412       dst_index = uimm (aarch64_get_instr (cpu), 20, 19);
6413       aarch64_set_vec_u32 (cpu, vd, dst_index,
6414                            aarch64_get_vec_u32 (cpu, vs, src_index));
6415     }
6416   else
6417     {
6418       NYI_assert (19, 19, 1);
6419       NYI_assert (13, 11, 0);
6420       src_index = uimm (aarch64_get_instr (cpu), 14, 14);
6421       dst_index = uimm (aarch64_get_instr (cpu), 20, 20);
6422       aarch64_set_vec_u64 (cpu, vd, dst_index,
6423                            aarch64_get_vec_u64 (cpu, vs, src_index));
6424     }
6425 }
6426
6427 static void
6428 dexAdvSIMD0 (sim_cpu *cpu)
6429 {
6430   /* instr [28,25] = 0 111.  */
6431   if (    uimm (aarch64_get_instr (cpu), 15, 10) == 0x07
6432       && (uimm (aarch64_get_instr (cpu), 9, 5) ==
6433           uimm (aarch64_get_instr (cpu), 20, 16)))
6434     {
6435       if (uimm (aarch64_get_instr (cpu), 31, 21) == 0x075
6436           || uimm (aarch64_get_instr (cpu), 31, 21) == 0x275)
6437         {
6438           do_vec_MOV_whole_vector (cpu);
6439           return;
6440         }
6441     }
6442
6443   if (uimm (aarch64_get_instr (cpu), 29, 19) == 0x1E0)
6444     {
6445       do_vec_MOV_immediate (cpu);
6446       return;
6447     }
6448
6449   if (uimm (aarch64_get_instr (cpu), 29, 19) == 0x5E0)
6450     {
6451       do_vec_MVNI (cpu);
6452       return;
6453     }
6454
6455   if (uimm (aarch64_get_instr (cpu), 29, 19) == 0x1C0
6456       || uimm (aarch64_get_instr (cpu), 29, 19) == 0x1C1)
6457     {
6458       if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x03)
6459         {
6460           do_vec_DUP_scalar_into_vector (cpu);
6461           return;
6462         }
6463     }
6464
6465   switch (uimm (aarch64_get_instr (cpu), 29, 24))
6466     {
6467     case 0x0E: do_vec_op1 (cpu); return;
6468     case 0x0F: do_vec_op2 (cpu); return;
6469
6470     case 0x2f:
6471       switch (uimm (aarch64_get_instr (cpu), 15, 10))
6472         {
6473         case 0x01: do_vec_SSHR_USHR (cpu); return;
6474         case 0x10:
6475         case 0x12: do_vec_mls_indexed (cpu); return;
6476         case 0x29: do_vec_xtl (cpu); return;
6477         default:
6478           HALT_NYI;
6479         }
6480
6481     case 0x2E:
6482       if (uimm (aarch64_get_instr (cpu), 21, 21) == 1)
6483         {
6484           switch (uimm (aarch64_get_instr (cpu), 15, 10))
6485             {
6486             case 0x07:
6487               switch (uimm (aarch64_get_instr (cpu), 23, 22))
6488                 {
6489                 case 0: do_vec_EOR (cpu); return;
6490                 case 1: do_vec_BSL (cpu); return;
6491                 case 2:
6492                 case 3: do_vec_bit (cpu); return;
6493                 }
6494               break;
6495
6496             case 0x08: do_vec_sub_long (cpu); return;
6497             case 0x11: do_vec_USHL (cpu); return;
6498             case 0x12: do_vec_CLZ (cpu); return;
6499             case 0x16: do_vec_NOT (cpu); return;
6500             case 0x19: do_vec_max (cpu); return;
6501             case 0x1B: do_vec_min (cpu); return;
6502             case 0x21: do_vec_SUB (cpu); return;
6503             case 0x25: do_vec_MLS (cpu); return;
6504             case 0x31: do_vec_FminmaxNMP (cpu); return;
6505             case 0x35: do_vec_FADDP (cpu); return;
6506             case 0x37: do_vec_FMUL (cpu); return;
6507             case 0x3F: do_vec_FDIV (cpu); return;
6508
6509             case 0x3E:
6510               switch (uimm (aarch64_get_instr (cpu), 20, 16))
6511                 {
6512                 case 0x00: do_vec_FNEG (cpu); return;
6513                 case 0x01: do_vec_FSQRT (cpu); return;
6514                 default:   HALT_NYI;
6515                 }
6516
6517             case 0x0D:
6518             case 0x0F:
6519             case 0x22:
6520             case 0x23:
6521             case 0x26:
6522             case 0x2A:
6523             case 0x32:
6524             case 0x36:
6525             case 0x39:
6526             case 0x3A:
6527               do_vec_compare (cpu); return;
6528
6529             default:
6530               break;
6531             }
6532         }
6533
6534       if (uimm (aarch64_get_instr (cpu), 31, 21) == 0x370)
6535         {
6536           do_vec_MOV_element (cpu);
6537           return;
6538         }
6539
6540       switch (uimm (aarch64_get_instr (cpu), 21, 10))
6541         {
6542         case 0x82E: do_vec_neg (cpu); return;
6543         case 0x87E: do_vec_sqrt (cpu); return;
6544         default:
6545           if (uimm (aarch64_get_instr (cpu), 15, 10) == 0x30)
6546             {
6547               do_vec_mull (cpu);
6548               return;
6549             }
6550           break;
6551         }
6552       break;
6553
6554     default:
6555       break;
6556     }
6557
6558   HALT_NYI;
6559 }
6560
6561 /* 3 sources.  */
6562
6563 /* Float multiply add.  */
6564 static void
6565 fmadds (sim_cpu *cpu)
6566 {
6567   unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6568   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6569   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6570   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6571
6572   aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sa)
6573                         + aarch64_get_FP_float (cpu, sn)
6574                         * aarch64_get_FP_float (cpu, sm));
6575 }
6576
6577 /* Double multiply add.  */
6578 static void
6579 fmaddd (sim_cpu *cpu)
6580 {
6581   unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6582   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6583   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6584   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6585
6586   aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sa)
6587                          + aarch64_get_FP_double (cpu, sn)
6588                          * aarch64_get_FP_double (cpu, sm));
6589 }
6590
6591 /* Float multiply subtract.  */
6592 static void
6593 fmsubs (sim_cpu *cpu)
6594 {
6595   unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
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, sa)
6601                         - aarch64_get_FP_float (cpu, sn)
6602                         * aarch64_get_FP_float (cpu, sm));
6603 }
6604
6605 /* Double multiply subtract.  */
6606 static void
6607 fmsubd (sim_cpu *cpu)
6608 {
6609   unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6610   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6611   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6612   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6613
6614   aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sa)
6615                          - aarch64_get_FP_double (cpu, sn)
6616                          * aarch64_get_FP_double (cpu, sm));
6617 }
6618
6619 /* Float negative multiply add.  */
6620 static void
6621 fnmadds (sim_cpu *cpu)
6622 {
6623   unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6624   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6625   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6626   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6627
6628   aarch64_set_FP_float (cpu, sd, - aarch64_get_FP_float (cpu, sa)
6629                         + (- aarch64_get_FP_float (cpu, sn))
6630                         * aarch64_get_FP_float (cpu, sm));
6631 }
6632
6633 /* Double negative multiply add.  */
6634 static void
6635 fnmaddd (sim_cpu *cpu)
6636 {
6637   unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6638   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6639   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6640   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6641
6642   aarch64_set_FP_double (cpu, sd, - aarch64_get_FP_double (cpu, sa)
6643                          + (- aarch64_get_FP_double (cpu, sn))
6644                          * aarch64_get_FP_double (cpu, sm));
6645 }
6646
6647 /* Float negative multiply subtract.  */
6648 static void
6649 fnmsubs (sim_cpu *cpu)
6650 {
6651   unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6652   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6653   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6654   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6655
6656   aarch64_set_FP_float (cpu, sd, - aarch64_get_FP_float (cpu, sa)
6657                         + aarch64_get_FP_float (cpu, sn)
6658                         * aarch64_get_FP_float (cpu, sm));
6659 }
6660
6661 /* Double negative multiply subtract.  */
6662 static void
6663 fnmsubd (sim_cpu *cpu)
6664 {
6665   unsigned sa = uimm (aarch64_get_instr (cpu), 14, 10);
6666   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6667   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6668   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6669
6670   aarch64_set_FP_double (cpu, sd, - aarch64_get_FP_double (cpu, sa)
6671                          + aarch64_get_FP_double (cpu, sn)
6672                          * aarch64_get_FP_double (cpu, sm));
6673 }
6674
6675 static void
6676 dexSimpleFPDataProc3Source (sim_cpu *cpu)
6677 {
6678   /* instr[31]    ==> M : 0 ==> OK, 1 ==> UNALLOC
6679      instr[30]    = 0
6680      instr[29]    ==> S :  0 ==> OK, 1 ==> UNALLOC
6681      instr[28,25] = 1111
6682      instr[24]    = 1
6683      instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
6684      instr[21]    ==> o1 : 0 ==> unnegated, 1 ==> negated
6685      instr[15]    ==> o2 : 0 ==> ADD, 1 ==> SUB  */
6686
6687   uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
6688     | uimm (aarch64_get_instr (cpu), 29, 29);
6689   /* dispatch on combined type:o1:o2.  */
6690   uint32_t dispatch = (uimm (aarch64_get_instr (cpu), 23, 21) << 1)
6691     | uimm (aarch64_get_instr (cpu), 15, 15);
6692
6693   if (M_S != 0)
6694     HALT_UNALLOC;
6695
6696   switch (dispatch)
6697     {
6698     case 0: fmadds (cpu); return;
6699     case 1: fmsubs (cpu); return;
6700     case 2: fnmadds (cpu); return;
6701     case 3: fnmsubs (cpu); return;
6702     case 4: fmaddd (cpu); return;
6703     case 5: fmsubd (cpu); return;
6704     case 6: fnmaddd (cpu); return;
6705     case 7: fnmsubd (cpu); return;
6706     default:
6707       /* type > 1 is currently unallocated.  */
6708       HALT_UNALLOC;
6709     }
6710 }
6711
6712 static void
6713 dexSimpleFPFixedConvert (sim_cpu *cpu)
6714 {
6715   HALT_NYI;
6716 }
6717
6718 static void
6719 dexSimpleFPCondCompare (sim_cpu *cpu)
6720 {
6721   /* instr [31,23] = 0001 1110 0
6722      instr [22]    = type
6723      instr [21]    = 1
6724      instr [20,16] = Rm
6725      instr [15,12] = condition
6726      instr [11,10] = 01
6727      instr [9,5]   = Rn
6728      instr [4]     = 0
6729      instr [3,0]   = nzcv  */
6730
6731   unsigned rm = INSTR (20, 16);
6732   unsigned rn = INSTR (9, 5);
6733
6734   NYI_assert (31, 23, 0x3C);
6735   NYI_assert (11, 10, 0x1);
6736   NYI_assert (4,  4,  0);
6737
6738   if (! testConditionCode (cpu, INSTR (15, 12)))
6739     {
6740       aarch64_set_CPSR (cpu, INSTR (3, 0));
6741       return;
6742     }
6743
6744   if (INSTR (22, 22))
6745     {
6746       /* Double precision.  */
6747       double val1 = aarch64_get_vec_double (cpu, rn, 0);
6748       double val2 = aarch64_get_vec_double (cpu, rm, 0);
6749
6750       /* FIXME: Check for NaNs.  */
6751       if (val1 == val2)
6752         aarch64_set_CPSR (cpu, (Z | C));
6753       else if (val1 < val2)
6754         aarch64_set_CPSR (cpu, N);
6755       else /* val1 > val2 */
6756         aarch64_set_CPSR (cpu, C);
6757     }
6758   else
6759     {
6760       /* Single precision.  */
6761       float val1 = aarch64_get_vec_float (cpu, rn, 0);
6762       float val2 = aarch64_get_vec_float (cpu, rm, 0);
6763       
6764       /* FIXME: Check for NaNs.  */
6765       if (val1 == val2)
6766         aarch64_set_CPSR (cpu, (Z | C));
6767       else if (val1 < val2)
6768         aarch64_set_CPSR (cpu, N);
6769       else /* val1 > val2 */
6770         aarch64_set_CPSR (cpu, C);
6771     }
6772 }
6773
6774 /* 2 sources.  */
6775
6776 /* Float add.  */
6777 static void
6778 fadds (sim_cpu *cpu)
6779 {
6780   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6781   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6782   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6783
6784   aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6785                         + aarch64_get_FP_float (cpu, sm));
6786 }
6787
6788 /* Double add.  */
6789 static void
6790 faddd (sim_cpu *cpu)
6791 {
6792   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6793   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6794   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6795
6796   aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6797                          + aarch64_get_FP_double (cpu, sm));
6798 }
6799
6800 /* Float divide.  */
6801 static void
6802 fdivs (sim_cpu *cpu)
6803 {
6804   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6805   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6806   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6807
6808   aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6809                         / aarch64_get_FP_float (cpu, sm));
6810 }
6811
6812 /* Double divide.  */
6813 static void
6814 fdivd (sim_cpu *cpu)
6815 {
6816   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6817   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6818   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6819
6820   aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6821                          / aarch64_get_FP_double (cpu, sm));
6822 }
6823
6824 /* Float multiply.  */
6825 static void
6826 fmuls (sim_cpu *cpu)
6827 {
6828   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6829   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6830   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6831
6832   aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6833                         * aarch64_get_FP_float (cpu, sm));
6834 }
6835
6836 /* Double multiply.  */
6837 static void
6838 fmuld (sim_cpu *cpu)
6839 {
6840   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6841   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6842   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6843
6844   aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6845                          * aarch64_get_FP_double (cpu, sm));
6846 }
6847
6848 /* Float negate and multiply.  */
6849 static void
6850 fnmuls (sim_cpu *cpu)
6851 {
6852   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6853   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6854   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6855
6856   aarch64_set_FP_float (cpu, sd, - (aarch64_get_FP_float (cpu, sn)
6857                                     * aarch64_get_FP_float (cpu, sm)));
6858 }
6859
6860 /* Double negate and multiply.  */
6861 static void
6862 fnmuld (sim_cpu *cpu)
6863 {
6864   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6865   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6866   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6867
6868   aarch64_set_FP_double (cpu, sd, - (aarch64_get_FP_double (cpu, sn)
6869                                      * aarch64_get_FP_double (cpu, sm)));
6870 }
6871
6872 /* Float subtract.  */
6873 static void
6874 fsubs (sim_cpu *cpu)
6875 {
6876   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6877   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6878   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6879
6880   aarch64_set_FP_float (cpu, sd, aarch64_get_FP_float (cpu, sn)
6881                         - aarch64_get_FP_float (cpu, sm));
6882 }
6883
6884 /* Double subtract.  */
6885 static void
6886 fsubd (sim_cpu *cpu)
6887 {
6888   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6889   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6890   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6891
6892   aarch64_set_FP_double (cpu, sd, aarch64_get_FP_double (cpu, sn)
6893                          - aarch64_get_FP_double (cpu, sm));
6894 }
6895
6896 static void
6897 do_FMINNM (sim_cpu *cpu)
6898 {
6899   /* instr[31,23] = 0 0011 1100
6900      instr[22]    = float(0)/double(1)
6901      instr[21]    = 1
6902      instr[20,16] = Sm
6903      instr[15,10] = 01 1110
6904      instr[9,5]   = Sn
6905      instr[4,0]   = Cpu  */
6906
6907   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6908   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6909   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6910
6911   NYI_assert (31, 23, 0x03C);
6912   NYI_assert (15, 10, 0x1E);
6913
6914   if (uimm (aarch64_get_instr (cpu), 22, 22))
6915     aarch64_set_FP_double (cpu, sd,
6916                            dminnm (aarch64_get_FP_double (cpu, sn),
6917                                    aarch64_get_FP_double (cpu, sm)));
6918   else
6919     aarch64_set_FP_float (cpu, sd,
6920                           fminnm (aarch64_get_FP_float (cpu, sn),
6921                                   aarch64_get_FP_float (cpu, sm)));
6922 }
6923
6924 static void
6925 do_FMAXNM (sim_cpu *cpu)
6926 {
6927   /* instr[31,23] = 0 0011 1100
6928      instr[22]    = float(0)/double(1)
6929      instr[21]    = 1
6930      instr[20,16] = Sm
6931      instr[15,10] = 01 1010
6932      instr[9,5]   = Sn
6933      instr[4,0]   = Cpu  */
6934
6935   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
6936   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
6937   unsigned sd = uimm (aarch64_get_instr (cpu),  4,  0);
6938
6939   NYI_assert (31, 23, 0x03C);
6940   NYI_assert (15, 10, 0x1A);
6941
6942   if (uimm (aarch64_get_instr (cpu), 22, 22))
6943     aarch64_set_FP_double (cpu, sd,
6944                            dmaxnm (aarch64_get_FP_double (cpu, sn),
6945                                    aarch64_get_FP_double (cpu, sm)));
6946   else
6947     aarch64_set_FP_float (cpu, sd,
6948                           fmaxnm (aarch64_get_FP_float (cpu, sn),
6949                                   aarch64_get_FP_float (cpu, sm)));
6950 }
6951
6952 static void
6953 dexSimpleFPDataProc2Source (sim_cpu *cpu)
6954 {
6955   /* instr[31]    ==> M : 0 ==> OK, 1 ==> UNALLOC
6956      instr[30]    = 0
6957      instr[29]    ==> S :  0 ==> OK, 1 ==> UNALLOC
6958      instr[28,25] = 1111
6959      instr[24]    = 0
6960      instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
6961      instr[21]    = 1
6962      instr[20,16] = Vm
6963      instr[15,12] ==> opcode : 0000 ==> FMUL, 0001 ==> FDIV
6964                                0010 ==> FADD, 0011 ==> FSUB,
6965                                0100 ==> FMAX, 0101 ==> FMIN
6966                                0110 ==> FMAXNM, 0111 ==> FMINNM
6967                                1000 ==> FNMUL, ow ==> UNALLOC
6968      instr[11,10] = 10
6969      instr[9,5]   = Vn
6970      instr[4,0]   = Vd  */
6971
6972   uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
6973     | uimm (aarch64_get_instr (cpu), 29, 29);
6974   uint32_t type = uimm (aarch64_get_instr (cpu), 23, 22);
6975   /* Dispatch on opcode.  */
6976   uint32_t dispatch = uimm (aarch64_get_instr (cpu), 15, 12);
6977
6978   if (type > 1)
6979     HALT_UNALLOC;
6980
6981   if (M_S != 0)
6982     HALT_UNALLOC;
6983
6984   if (type)
6985     switch (dispatch)
6986       {
6987       case 0: fmuld (cpu); return;
6988       case 1: fdivd (cpu); return;
6989       case 2: faddd (cpu); return;
6990       case 3: fsubd (cpu); return;
6991       case 6: do_FMAXNM (cpu); return;
6992       case 7: do_FMINNM (cpu); return;
6993       case 8: fnmuld (cpu); return;
6994
6995         /* Have not yet implemented fmax and fmin.  */
6996       case 4:
6997       case 5:
6998         HALT_NYI;
6999
7000       default:
7001         HALT_UNALLOC;
7002       }
7003   else /* type == 0 => floats.  */
7004     switch (dispatch)
7005       {
7006       case 0: fmuls (cpu); return;
7007       case 1: fdivs (cpu); return;
7008       case 2: fadds (cpu); return;
7009       case 3: fsubs (cpu); return;
7010       case 6: do_FMAXNM (cpu); return;
7011       case 7: do_FMINNM (cpu); return;
7012       case 8: fnmuls (cpu); return;
7013
7014       case 4:
7015       case 5:
7016         HALT_NYI;
7017
7018       default:
7019         HALT_UNALLOC;
7020       }
7021 }
7022
7023 static void
7024 dexSimpleFPCondSelect (sim_cpu *cpu)
7025 {
7026   /* FCSEL
7027      instr[31,23] = 0 0011 1100
7028      instr[22]    = 0=>single 1=>double
7029      instr[21]    = 1
7030      instr[20,16] = Sm
7031      instr[15,12] = cond
7032      instr[11,10] = 11
7033      instr[9,5]   = Sn
7034      instr[4,0]   = Cpu  */
7035   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
7036   unsigned sn = uimm (aarch64_get_instr (cpu),  9, 5);
7037   unsigned sd = uimm (aarch64_get_instr (cpu),  4, 0);
7038   uint32_t set = testConditionCode (cpu, uimm (aarch64_get_instr (cpu), 15, 12));
7039
7040   NYI_assert (31, 23, 0x03C);
7041   NYI_assert (11, 10, 0x3);
7042
7043   if (uimm (aarch64_get_instr (cpu), 22, 22))
7044     aarch64_set_FP_double (cpu, sd, set ? sn : sm);
7045   else
7046     aarch64_set_FP_float (cpu, sd, set ? sn : sm);
7047 }
7048
7049 /* Store 32 bit unscaled signed 9 bit.  */
7050 static void
7051 fsturs (sim_cpu *cpu, int32_t offset)
7052 {
7053   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
7054   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
7055
7056   aarch64_set_mem_u32 (cpu, aarch64_get_reg_u64 (cpu, st, 1) + offset,
7057                        aarch64_get_vec_u32 (cpu, rn, 0));
7058 }
7059
7060 /* Store 64 bit unscaled signed 9 bit.  */
7061 static void
7062 fsturd (sim_cpu *cpu, int32_t offset)
7063 {
7064   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
7065   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
7066
7067   aarch64_set_mem_u64 (cpu, aarch64_get_reg_u64 (cpu, st, 1) + offset,
7068                        aarch64_get_vec_u64 (cpu, rn, 0));
7069 }
7070
7071 /* Store 128 bit unscaled signed 9 bit.  */
7072 static void
7073 fsturq (sim_cpu *cpu, int32_t offset)
7074 {
7075   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
7076   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
7077   FRegister a;
7078
7079   aarch64_get_FP_long_double (cpu, rn, & a);
7080   aarch64_set_mem_long_double (cpu,
7081                                aarch64_get_reg_u64 (cpu, st, 1)
7082                                + offset, a);
7083 }
7084
7085 /* TODO FP move register.  */
7086
7087 /* 32 bit fp to fp move register.  */
7088 static void
7089 ffmovs (sim_cpu *cpu)
7090 {
7091   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
7092   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
7093
7094   aarch64_set_FP_float (cpu, st, aarch64_get_FP_float (cpu, rn));
7095 }
7096
7097 /* 64 bit fp to fp move register.  */
7098 static void
7099 ffmovd (sim_cpu *cpu)
7100 {
7101   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
7102   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
7103
7104   aarch64_set_FP_double (cpu, st, aarch64_get_FP_double (cpu, rn));
7105 }
7106
7107 /* 32 bit GReg to Vec move register.  */
7108 static void
7109 fgmovs (sim_cpu *cpu)
7110 {
7111   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
7112   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
7113
7114   aarch64_set_vec_u32 (cpu, st, 0, aarch64_get_reg_u32 (cpu, rn, NO_SP));
7115 }
7116
7117 /* 64 bit g to fp move register.  */
7118 static void
7119 fgmovd (sim_cpu *cpu)
7120 {
7121   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
7122   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
7123
7124   aarch64_set_vec_u64 (cpu, st, 0, aarch64_get_reg_u64 (cpu, rn, NO_SP));
7125 }
7126
7127 /* 32 bit fp to g move register.  */
7128 static void
7129 gfmovs (sim_cpu *cpu)
7130 {
7131   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
7132   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
7133
7134   aarch64_set_reg_u64 (cpu, st, NO_SP, aarch64_get_vec_u32 (cpu, rn, 0));
7135 }
7136
7137 /* 64 bit fp to g move register.  */
7138 static void
7139 gfmovd (sim_cpu *cpu)
7140 {
7141   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
7142   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
7143
7144   aarch64_set_reg_u64 (cpu, st, NO_SP, aarch64_get_vec_u64 (cpu, rn, 0));
7145 }
7146
7147 /* FP move immediate
7148
7149    These install an immediate 8 bit value in the target register
7150    where the 8 bits comprise 1 sign bit, 4 bits of fraction and a 3
7151    bit exponent.  */
7152
7153 static void
7154 fmovs (sim_cpu *cpu)
7155 {
7156   unsigned int sd = uimm (aarch64_get_instr (cpu), 4, 0);
7157   uint32_t imm = uimm (aarch64_get_instr (cpu), 20, 13);
7158   float f = fp_immediate_for_encoding_32 (imm);
7159
7160   aarch64_set_FP_float (cpu, sd, f);
7161 }
7162
7163 static void
7164 fmovd (sim_cpu *cpu)
7165 {
7166   unsigned int sd = uimm (aarch64_get_instr (cpu), 4, 0);
7167   uint32_t imm = uimm (aarch64_get_instr (cpu), 20, 13);
7168   double d = fp_immediate_for_encoding_64 (imm);
7169
7170   aarch64_set_FP_double (cpu, sd, d);
7171 }
7172
7173 static void
7174 dexSimpleFPImmediate (sim_cpu *cpu)
7175 {
7176   /* instr[31,23] == 00111100
7177      instr[22]    == type : single(0)/double(1)
7178      instr[21]    == 1
7179      instr[20,13] == imm8
7180      instr[12,10] == 100
7181      instr[9,5]   == imm5 : 00000 ==> PK, ow ==> UNALLOC
7182      instr[4,0]   == Rd  */
7183   uint32_t imm5 = uimm (aarch64_get_instr (cpu), 9, 5);
7184
7185   NYI_assert (31, 23, 0x3C);
7186
7187   if (imm5 != 0)
7188     HALT_UNALLOC;
7189
7190   if (uimm (aarch64_get_instr (cpu), 22, 22))
7191     fmovd (cpu);
7192   else
7193     fmovs (cpu);
7194 }
7195
7196 /* TODO specific decode and execute for group Load Store.  */
7197
7198 /* TODO FP load/store single register (unscaled offset).  */
7199
7200 /* TODO load 8 bit unscaled signed 9 bit.  */
7201 /* TODO load 16 bit unscaled signed 9 bit.  */
7202
7203 /* Load 32 bit unscaled signed 9 bit.  */
7204 static void
7205 fldurs (sim_cpu *cpu, int32_t offset)
7206 {
7207   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
7208   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
7209
7210   aarch64_set_vec_u32 (cpu, st, 0, aarch64_get_mem_u32
7211                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset));
7212 }
7213
7214 /* Load 64 bit unscaled signed 9 bit.  */
7215 static void
7216 fldurd (sim_cpu *cpu, int32_t offset)
7217 {
7218   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
7219   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
7220
7221   aarch64_set_vec_u64 (cpu, st, 0, aarch64_get_mem_u64
7222                        (cpu, aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset));
7223 }
7224
7225 /* Load 128 bit unscaled signed 9 bit.  */
7226 static void
7227 fldurq (sim_cpu *cpu, int32_t offset)
7228 {
7229   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
7230   unsigned int st = uimm (aarch64_get_instr (cpu), 4, 0);
7231   FRegister a;
7232   uint64_t addr = aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset;
7233
7234   aarch64_get_mem_long_double (cpu, addr, & a);
7235   aarch64_set_FP_long_double (cpu, st, a);
7236 }
7237
7238 /* TODO store 8 bit unscaled signed 9 bit.  */
7239 /* TODO store 16 bit unscaled signed 9 bit.  */
7240
7241
7242 /* 1 source.  */
7243
7244 /* Float absolute value.  */
7245 static void
7246 fabss (sim_cpu *cpu)
7247 {
7248   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7249   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7250   float value = aarch64_get_FP_float (cpu, sn);
7251
7252   aarch64_set_FP_float (cpu, sd, fabsf (value));
7253 }
7254
7255 /* Double absolute value.  */
7256 static void
7257 fabcpu (sim_cpu *cpu)
7258 {
7259   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7260   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7261   double value = aarch64_get_FP_double (cpu, sn);
7262
7263   aarch64_set_FP_double (cpu, sd, fabs (value));
7264 }
7265
7266 /* Float negative value.  */
7267 static void
7268 fnegs (sim_cpu *cpu)
7269 {
7270   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7271   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7272
7273   aarch64_set_FP_float (cpu, sd, - aarch64_get_FP_float (cpu, sn));
7274 }
7275
7276 /* Double negative value.  */
7277 static void
7278 fnegd (sim_cpu *cpu)
7279 {
7280   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7281   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7282
7283   aarch64_set_FP_double (cpu, sd, - aarch64_get_FP_double (cpu, sn));
7284 }
7285
7286 /* Float square root.  */
7287 static void
7288 fsqrts (sim_cpu *cpu)
7289 {
7290   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7291   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7292
7293   aarch64_set_FP_float (cpu, sd, sqrt (aarch64_get_FP_float (cpu, sn)));
7294 }
7295
7296 /* Double square root.  */
7297 static void
7298 fsqrtd (sim_cpu *cpu)
7299 {
7300   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7301   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7302
7303   aarch64_set_FP_double (cpu, sd,
7304                          sqrt (aarch64_get_FP_double (cpu, sn)));
7305 }
7306
7307 /* Convert double to float.  */
7308 static void
7309 fcvtds (sim_cpu *cpu)
7310 {
7311   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7312   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7313
7314   aarch64_set_FP_float (cpu, sd, (float) aarch64_get_FP_double (cpu, sn));
7315 }
7316
7317 /* Convert float to double.  */
7318 static void
7319 fcvtcpu (sim_cpu *cpu)
7320 {
7321   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7322   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7323
7324   aarch64_set_FP_double (cpu, sd, (double) aarch64_get_FP_float (cpu, sn));
7325 }
7326
7327 static void
7328 do_FRINT (sim_cpu *cpu)
7329 {
7330   /* instr[31,23] = 0001 1110 0
7331      instr[22]    = single(0)/double(1)
7332      instr[21,18] = 1001
7333      instr[17,15] = rounding mode
7334      instr[14,10] = 10000
7335      instr[9,5]   = source
7336      instr[4,0]   = dest  */
7337
7338   float val;
7339   unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
7340   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7341   unsigned int rmode = uimm (aarch64_get_instr (cpu), 17, 15);
7342
7343   NYI_assert (31, 23, 0x03C);
7344   NYI_assert (21, 18, 0x9);
7345   NYI_assert (14, 10, 0x10);
7346
7347   if (rmode == 6 || rmode == 7)
7348     /* FIXME: Add support for rmode == 6 exactness check.  */
7349     rmode = uimm (aarch64_get_FPSR (cpu), 23, 22);
7350
7351   if (uimm (aarch64_get_instr (cpu), 22, 22))
7352     {
7353       double val = aarch64_get_FP_double (cpu, rs);
7354
7355       switch (rmode)
7356         {
7357         case 0: /* mode N: nearest or even.  */
7358           {
7359             double rval = round (val);
7360
7361             if (val - rval == 0.5)
7362               {
7363                 if (((rval / 2.0) * 2.0) != rval)
7364                   rval += 1.0;
7365               }
7366
7367             aarch64_set_FP_double (cpu, rd, round (val));
7368             return;
7369           }
7370
7371         case 1: /* mode P: towards +inf.  */
7372           if (val < 0.0)
7373             aarch64_set_FP_double (cpu, rd, trunc (val));
7374           else
7375             aarch64_set_FP_double (cpu, rd, round (val));
7376           return;
7377
7378         case 2: /* mode M: towards -inf.  */
7379           if (val < 0.0)
7380             aarch64_set_FP_double (cpu, rd, round (val));
7381           else
7382             aarch64_set_FP_double (cpu, rd, trunc (val));
7383           return;
7384
7385         case 3: /* mode Z: towards 0.  */
7386           aarch64_set_FP_double (cpu, rd, trunc (val));
7387           return;
7388
7389         case 4: /* mode A: away from 0.  */
7390           aarch64_set_FP_double (cpu, rd, round (val));
7391           return;
7392
7393         case 6: /* mode X: use FPCR with exactness check.  */
7394         case 7: /* mode I: use FPCR mode.  */
7395           HALT_NYI;
7396
7397         default:
7398           HALT_UNALLOC;
7399         }
7400     }
7401
7402   val = aarch64_get_FP_float (cpu, rs);
7403
7404   switch (rmode)
7405     {
7406     case 0: /* mode N: nearest or even.  */
7407       {
7408         float rval = roundf (val);
7409
7410         if (val - rval == 0.5)
7411           {
7412             if (((rval / 2.0) * 2.0) != rval)
7413               rval += 1.0;
7414           }
7415
7416         aarch64_set_FP_float (cpu, rd, rval);
7417         return;
7418       }
7419
7420     case 1: /* mode P: towards +inf.  */
7421       if (val < 0.0)
7422         aarch64_set_FP_float (cpu, rd, truncf (val));
7423       else
7424         aarch64_set_FP_float (cpu, rd, roundf (val));
7425       return;
7426
7427     case 2: /* mode M: towards -inf.  */
7428       if (val < 0.0)
7429         aarch64_set_FP_float (cpu, rd, truncf (val));
7430       else
7431         aarch64_set_FP_float (cpu, rd, roundf (val));
7432       return;
7433
7434     case 3: /* mode Z: towards 0.  */
7435       aarch64_set_FP_float (cpu, rd, truncf (val));
7436       return;
7437
7438     case 4: /* mode A: away from 0.  */
7439       aarch64_set_FP_float (cpu, rd, roundf (val));
7440       return;
7441
7442     case 6: /* mode X: use FPCR with exactness check.  */
7443     case 7: /* mode I: use FPCR mode.  */
7444       HALT_NYI;
7445
7446     default:
7447       HALT_UNALLOC;
7448     }
7449 }
7450
7451 /* Convert half to float.  */
7452 static void
7453 do_FCVT_half_to_single (sim_cpu * cpu)
7454 {
7455   unsigned rn = INSTR (9, 5);
7456   unsigned rd = INSTR (4, 0);
7457
7458   NYI_assert (31, 10, 0x7B890);
7459
7460   aarch64_set_FP_float (cpu, rd, (float) aarch64_get_FP_half  (cpu, rn));
7461 }
7462
7463 /* Convert half to float.  */
7464 static void
7465 do_FCVT_half_to_double (sim_cpu * cpu)
7466 {
7467   unsigned rn = INSTR (9, 5);
7468   unsigned rd = INSTR (4, 0);
7469
7470   NYI_assert (31, 10, 0x7B8B0);
7471   
7472   aarch64_set_FP_double (cpu, rd, (double) aarch64_get_FP_half  (cpu, rn));
7473 }
7474
7475 static void
7476 do_FCVT_single_to_half (sim_cpu * cpu)
7477 {
7478   unsigned rn = INSTR (9, 5);
7479   unsigned rd = INSTR (4, 0);
7480
7481   NYI_assert (31, 10, 0x788F0);
7482
7483   aarch64_set_FP_half (cpu, rd, aarch64_get_FP_float  (cpu, rn));
7484 }
7485
7486 /* Convert half to float.  */
7487 static void
7488 do_FCVT_double_to_half (sim_cpu * cpu)
7489 {
7490   unsigned rn = INSTR (9, 5);
7491   unsigned rd = INSTR (4, 0);
7492
7493   NYI_assert (31, 10, 0x798F0);
7494   
7495   aarch64_set_FP_half (cpu, rd, (float) aarch64_get_FP_double  (cpu, rn));
7496 }
7497
7498 static void
7499 dexSimpleFPDataProc1Source (sim_cpu *cpu)
7500 {
7501   /* instr[31]    ==> M : 0 ==> OK, 1 ==> UNALLOC
7502      instr[30]    = 0
7503      instr[29]    ==> S :  0 ==> OK, 1 ==> UNALLOC
7504      instr[28,25] = 1111
7505      instr[24]    = 0
7506      instr[23,22] ==> type : 00 ==> source is single,
7507                              01 ==> source is double
7508                              10 ==> UNALLOC
7509                              11 ==> UNALLOC or source is half
7510      instr[21]    = 1
7511      instr[20,15] ==> opcode : with type 00 or 01
7512                                000000 ==> FMOV, 000001 ==> FABS,
7513                                000010 ==> FNEG, 000011 ==> FSQRT,
7514                                000100 ==> UNALLOC, 000101 ==> FCVT,(to single/double)
7515                                000110 ==> UNALLOC, 000111 ==> FCVT (to half)
7516                                001000 ==> FRINTN, 001001 ==> FRINTP,
7517                                001010 ==> FRINTM, 001011 ==> FRINTZ,
7518                                001100 ==> FRINTA, 001101 ==> UNALLOC
7519                                001110 ==> FRINTX, 001111 ==> FRINTI
7520                                with type 11
7521                                000100 ==> FCVT (half-to-single)
7522                                000101 ==> FCVT (half-to-double)
7523                                instr[14,10] = 10000.  */
7524
7525   uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
7526     | uimm (aarch64_get_instr (cpu), 29, 29);
7527   uint32_t type   = uimm (aarch64_get_instr (cpu), 23, 22);
7528   uint32_t opcode = uimm (aarch64_get_instr (cpu), 20, 15);
7529
7530   if (M_S != 0)
7531     HALT_UNALLOC;
7532
7533   if (type == 3)
7534     {
7535       if (opcode == 4)
7536         do_FCVT_half_to_single (cpu);
7537       else if (opcode == 5)
7538         do_FCVT_half_to_double (cpu);
7539       else
7540         HALT_UNALLOC;
7541       return;
7542     }
7543
7544   if (type == 2)
7545     HALT_UNALLOC;
7546
7547   switch (opcode)
7548     {
7549     case 0:
7550       if (type)
7551         ffmovd (cpu);
7552       else
7553         ffmovs (cpu);
7554       return;
7555
7556     case 1:
7557       if (type)
7558         fabcpu (cpu);
7559       else
7560         fabss (cpu);
7561       return;
7562
7563     case 2:
7564       if (type)
7565         fnegd (cpu);
7566       else
7567         fnegs (cpu);
7568       return;
7569
7570     case 3:
7571       if (type)
7572         fsqrtd (cpu);
7573       else
7574         fsqrts (cpu);
7575       return;
7576
7577     case 4:
7578       if (type)
7579         fcvtds (cpu);
7580       else
7581         HALT_UNALLOC;
7582       return;
7583
7584     case 5:
7585       if (type)
7586         HALT_UNALLOC;
7587       fcvtcpu (cpu);
7588       return;
7589
7590     case 8:             /* FRINTN etc.  */
7591     case 9:
7592     case 10:
7593     case 11:
7594     case 12:
7595     case 14:
7596     case 15:
7597        do_FRINT (cpu);
7598        return;
7599
7600     case 7:
7601       if (INSTR (22, 22))
7602         do_FCVT_double_to_half (cpu);
7603       else
7604         do_FCVT_single_to_half (cpu);
7605       return;
7606
7607     case 13:
7608       HALT_NYI;
7609
7610     default:
7611       HALT_UNALLOC;
7612     }
7613 }
7614
7615 /* 32 bit signed int to float.  */
7616 static void
7617 scvtf32 (sim_cpu *cpu)
7618 {
7619   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7620   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7621
7622   aarch64_set_FP_float
7623     (cpu, sd, (float) aarch64_get_reg_s32 (cpu, rn, NO_SP));
7624 }
7625
7626 /* signed int to float.  */
7627 static void
7628 scvtf (sim_cpu *cpu)
7629 {
7630   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7631   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7632
7633   aarch64_set_FP_float
7634     (cpu, sd, (float) aarch64_get_reg_s64 (cpu, rn, NO_SP));
7635 }
7636
7637 /* 32 bit signed int to double.  */
7638 static void
7639 scvtd32 (sim_cpu *cpu)
7640 {
7641   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7642   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7643
7644   aarch64_set_FP_double
7645     (cpu, sd, (double) aarch64_get_reg_s32 (cpu, rn, NO_SP));
7646 }
7647
7648 /* signed int to double.  */
7649 static void
7650 scvtd (sim_cpu *cpu)
7651 {
7652   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7653   unsigned sd = uimm (aarch64_get_instr (cpu), 4, 0);
7654
7655   aarch64_set_FP_double
7656     (cpu, sd, (double) aarch64_get_reg_s64 (cpu, rn, NO_SP));
7657 }
7658
7659 static const float  FLOAT_INT_MAX   = (float)  INT_MAX;
7660 static const float  FLOAT_INT_MIN   = (float)  INT_MIN;
7661 static const double DOUBLE_INT_MAX  = (double) INT_MAX;
7662 static const double DOUBLE_INT_MIN  = (double) INT_MIN;
7663 static const float  FLOAT_LONG_MAX  = (float)  LONG_MAX;
7664 static const float  FLOAT_LONG_MIN  = (float)  LONG_MIN;
7665 static const double DOUBLE_LONG_MAX = (double) LONG_MAX;
7666 static const double DOUBLE_LONG_MIN = (double) LONG_MIN;
7667
7668 /* Check for FP exception conditions:
7669      NaN raises IO
7670      Infinity raises IO
7671      Out of Range raises IO and IX and saturates value
7672      Denormal raises ID and IX and sets to zero.  */
7673 #define RAISE_EXCEPTIONS(F, VALUE, FTYPE, ITYPE)        \
7674   do                                                    \
7675     {                                                   \
7676       switch (fpclassify (F))                           \
7677         {                                               \
7678         case FP_INFINITE:                               \
7679         case FP_NAN:                                    \
7680           aarch64_set_FPSR (cpu, IO);                   \
7681           if (signbit (F))                              \
7682             VALUE = ITYPE##_MAX;                        \
7683           else                                          \
7684             VALUE = ITYPE##_MIN;                        \
7685           break;                                        \
7686                                                         \
7687         case FP_NORMAL:                                 \
7688           if (F >= FTYPE##_##ITYPE##_MAX)               \
7689             {                                           \
7690               aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX);    \
7691               VALUE = ITYPE##_MAX;                      \
7692             }                                           \
7693           else if (F <= FTYPE##_##ITYPE##_MIN)          \
7694             {                                           \
7695               aarch64_set_FPSR_bits (cpu, IO | IX, IO | IX);    \
7696               VALUE = ITYPE##_MIN;                      \
7697             }                                           \
7698           break;                                        \
7699                                                         \
7700         case FP_SUBNORMAL:                              \
7701           aarch64_set_FPSR_bits (cpu, IO | IX | ID, IX | ID);   \
7702           VALUE = 0;                                    \
7703           break;                                        \
7704                                                         \
7705         default:                                        \
7706         case FP_ZERO:                                   \
7707           VALUE = 0;                                    \
7708           break;                                        \
7709         }                                               \
7710     }                                                   \
7711   while (0)
7712
7713 /* 32 bit convert float to signed int truncate towards zero.  */
7714 static void
7715 fcvtszs32 (sim_cpu *cpu)
7716 {
7717   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7718   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7719   /* TODO : check that this rounds toward zero.  */
7720   float   f = aarch64_get_FP_float (cpu, sn);
7721   int32_t value = (int32_t) f;
7722
7723   RAISE_EXCEPTIONS (f, value, FLOAT, INT);
7724
7725   /* Avoid sign extension to 64 bit.  */
7726   aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) value);
7727 }
7728
7729 /* 64 bit convert float to signed int truncate towards zero.  */
7730 static void
7731 fcvtszs (sim_cpu *cpu)
7732 {
7733   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7734   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7735   float f = aarch64_get_FP_float (cpu, sn);
7736   int64_t value = (int64_t) f;
7737
7738   RAISE_EXCEPTIONS (f, value, FLOAT, LONG);
7739
7740   aarch64_set_reg_s64 (cpu, rd, NO_SP, value);
7741 }
7742
7743 /* 32 bit convert double to signed int truncate towards zero.  */
7744 static void
7745 fcvtszd32 (sim_cpu *cpu)
7746 {
7747   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7748   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7749   /* TODO : check that this rounds toward zero.  */
7750   double   d = aarch64_get_FP_double (cpu, sn);
7751   int32_t  value = (int32_t) d;
7752
7753   RAISE_EXCEPTIONS (d, value, DOUBLE, INT);
7754
7755   /* Avoid sign extension to 64 bit.  */
7756   aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) value);
7757 }
7758
7759 /* 64 bit convert double to signed int truncate towards zero.  */
7760 static void
7761 fcvtszd (sim_cpu *cpu)
7762 {
7763   unsigned sn = uimm (aarch64_get_instr (cpu), 9, 5);
7764   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7765   /* TODO : check that this rounds toward zero.  */
7766   double  d = aarch64_get_FP_double (cpu, sn);
7767   int64_t value;
7768
7769   value = (int64_t) d;
7770
7771   RAISE_EXCEPTIONS (d, value, DOUBLE, LONG);
7772
7773   aarch64_set_reg_s64 (cpu, rd, NO_SP, value);
7774 }
7775
7776 static void
7777 do_fcvtzu (sim_cpu *cpu)
7778 {
7779   /* instr[31]    = size: 32-bit (0), 64-bit (1)
7780      instr[30,23] = 00111100
7781      instr[22]    = type: single (0)/ double (1)
7782      instr[21]    = enable (0)/disable(1) precision
7783      instr[20,16] = 11001
7784      instr[15,10] = precision
7785      instr[9,5]   = Rs
7786      instr[4,0]   = Rd.  */
7787
7788   unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
7789   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7790
7791   NYI_assert (30, 23, 0x3C);
7792   NYI_assert (20, 16, 0x19);
7793
7794   if (uimm (aarch64_get_instr (cpu), 21, 21) != 1)
7795     /* Convert to fixed point.  */
7796     HALT_NYI;
7797
7798   if (uimm (aarch64_get_instr (cpu), 31, 31))
7799     {
7800       /* Convert to unsigned 64-bit integer.  */
7801       if (uimm (aarch64_get_instr (cpu), 22, 22))
7802         {
7803           double  d = aarch64_get_FP_double (cpu, rs);
7804           uint64_t value = (uint64_t) d;
7805
7806           /* Do not raise an exception if we have reached ULONG_MAX.  */
7807           if (value != (1UL << 63))
7808             RAISE_EXCEPTIONS (d, value, DOUBLE, LONG);
7809
7810           aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
7811         }
7812       else
7813         {
7814           float  f = aarch64_get_FP_float (cpu, rs);
7815           uint64_t value = (uint64_t) f;
7816
7817           /* Do not raise an exception if we have reached ULONG_MAX.  */
7818           if (value != (1UL << 63))
7819             RAISE_EXCEPTIONS (f, value, FLOAT, LONG);
7820
7821           aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
7822         }
7823     }
7824   else
7825     {
7826       uint32_t value;
7827
7828       /* Convert to unsigned 32-bit integer.  */
7829       if (uimm (aarch64_get_instr (cpu), 22, 22))
7830         {
7831           double  d = aarch64_get_FP_double (cpu, rs);
7832
7833           value = (uint32_t) d;
7834           /* Do not raise an exception if we have reached UINT_MAX.  */
7835           if (value != (1UL << 31))
7836             RAISE_EXCEPTIONS (d, value, DOUBLE, INT);
7837         }
7838       else
7839         {
7840           float  f = aarch64_get_FP_float (cpu, rs);
7841
7842           value = (uint32_t) f;
7843           /* Do not raise an exception if we have reached UINT_MAX.  */
7844           if (value != (1UL << 31))
7845             RAISE_EXCEPTIONS (f, value, FLOAT, INT);
7846         }
7847
7848       aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
7849     }
7850 }
7851
7852 static void
7853 do_UCVTF (sim_cpu *cpu)
7854 {
7855   /* instr[31]    = size: 32-bit (0), 64-bit (1)
7856      instr[30,23] = 001 1110 0
7857      instr[22]    = type: single (0)/ double (1)
7858      instr[21]    = enable (0)/disable(1) precision
7859      instr[20,16] = 0 0011
7860      instr[15,10] = precision
7861      instr[9,5]   = Rs
7862      instr[4,0]   = Rd.  */
7863
7864   unsigned rs = uimm (aarch64_get_instr (cpu), 9, 5);
7865   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7866
7867   NYI_assert (30, 23, 0x3C);
7868   NYI_assert (20, 16, 0x03);
7869
7870   if (uimm (aarch64_get_instr (cpu), 21, 21) != 1)
7871     HALT_NYI;
7872
7873   /* FIXME: Add exception raising.  */
7874   if (uimm (aarch64_get_instr (cpu), 31, 31))
7875     {
7876       uint64_t value = aarch64_get_reg_u64 (cpu, rs, NO_SP);
7877
7878       if (uimm (aarch64_get_instr (cpu), 22, 22))
7879         aarch64_set_FP_double (cpu, rd, (double) value);
7880       else
7881         aarch64_set_FP_float (cpu, rd, (float) value);
7882     }
7883   else
7884     {
7885       uint32_t value =  aarch64_get_reg_u32 (cpu, rs, NO_SP);
7886
7887       if (uimm (aarch64_get_instr (cpu), 22, 22))
7888         aarch64_set_FP_double (cpu, rd, (double) value);
7889       else
7890         aarch64_set_FP_float (cpu, rd, (float) value);
7891     }
7892 }
7893
7894 static void
7895 float_vector_move (sim_cpu *cpu)
7896 {
7897   /* instr[31,17] == 100 1111 0101 0111
7898      instr[16]    ==> direction 0=> to GR, 1=> from GR
7899      instr[15,10] => ???
7900      instr[9,5]   ==> source
7901      instr[4,0]   ==> dest.  */
7902
7903   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
7904   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
7905
7906   NYI_assert (31, 17, 0x4F57);
7907
7908   if (uimm (aarch64_get_instr (cpu), 15, 10) != 0)
7909     HALT_UNALLOC;
7910
7911   if (uimm (aarch64_get_instr (cpu), 16, 16))
7912     aarch64_set_vec_u64 (cpu, rd, 1, aarch64_get_reg_u64 (cpu, rn, NO_SP));
7913   else
7914     aarch64_set_reg_u64 (cpu, rd, NO_SP, aarch64_get_vec_u64 (cpu, rn, 1));
7915 }
7916
7917 static void
7918 dexSimpleFPIntegerConvert (sim_cpu *cpu)
7919 {
7920   /* instr[31]    = size : 0 ==> 32 bit, 1 ==> 64 bit
7921      instr[30     = 0
7922      instr[29]    = S :  0 ==> OK, 1 ==> UNALLOC
7923      instr[28,25] = 1111
7924      instr[24]    = 0
7925      instr[23,22] = type : 00 ==> single, 01 ==> double, 1x ==> UNALLOC
7926      instr[21]    = 1
7927      instr[20,19] = rmode
7928      instr[18,16] = opcode
7929      instr[15,10] = 10 0000  */
7930
7931   uint32_t rmode_opcode;
7932   uint32_t size_type;
7933   uint32_t type;
7934   uint32_t size;
7935   uint32_t S;
7936
7937   if (uimm (aarch64_get_instr (cpu), 31, 17) == 0x4F57)
7938     {
7939       float_vector_move (cpu);
7940       return;
7941     }
7942
7943   size = uimm (aarch64_get_instr (cpu), 31, 31);
7944   S = uimm (aarch64_get_instr (cpu), 29, 29);
7945   if (S != 0)
7946     HALT_UNALLOC;
7947
7948   type = uimm (aarch64_get_instr (cpu), 23, 22);
7949   if (type > 1)
7950     HALT_UNALLOC;
7951
7952   rmode_opcode = uimm (aarch64_get_instr (cpu), 20, 16);
7953   size_type = (size << 1) | type; /* 0==32f, 1==32d, 2==64f, 3==64d.  */
7954
7955   switch (rmode_opcode)
7956     {
7957     case 2:                     /* SCVTF.  */
7958       switch (size_type)
7959         {
7960         case 0: scvtf32 (cpu); return;
7961         case 1: scvtd32 (cpu); return;
7962         case 2: scvtf (cpu); return;
7963         case 3: scvtd (cpu); return;
7964         }
7965
7966     case 6:                     /* FMOV GR, Vec.  */
7967       switch (size_type)
7968         {
7969         case 0:  gfmovs (cpu); return;
7970         case 3:  gfmovd (cpu); return;
7971         default: HALT_UNALLOC;
7972         }
7973
7974     case 7:                     /* FMOV vec, GR.  */
7975       switch (size_type)
7976         {
7977         case 0:  fgmovs (cpu); return;
7978         case 3:  fgmovd (cpu); return;
7979         default: HALT_UNALLOC;
7980         }
7981
7982     case 24:                    /* FCVTZS.  */
7983       switch (size_type)
7984         {
7985         case 0: fcvtszs32 (cpu); return;
7986         case 1: fcvtszd32 (cpu); return;
7987         case 2: fcvtszs (cpu); return;
7988         case 3: fcvtszd (cpu); return;
7989         }
7990
7991     case 25: do_fcvtzu (cpu); return;
7992     case 3:  do_UCVTF (cpu); return;
7993
7994     case 0:     /* FCVTNS.  */
7995     case 1:     /* FCVTNU.  */
7996     case 4:     /* FCVTAS.  */
7997     case 5:     /* FCVTAU.  */
7998     case 8:     /* FCVPTS.  */
7999     case 9:     /* FCVTPU.  */
8000     case 16:    /* FCVTMS.  */
8001     case 17:    /* FCVTMU.  */
8002     default:
8003       HALT_NYI;
8004     }
8005 }
8006
8007 static void
8008 set_flags_for_float_compare (sim_cpu *cpu, float fvalue1, float fvalue2)
8009 {
8010   uint32_t flags;
8011
8012   if (isnan (fvalue1) || isnan (fvalue2))
8013     flags = C|V;
8014   else
8015     {
8016       float result = fvalue1 - fvalue2;
8017
8018       if (result == 0.0)
8019         flags = Z|C;
8020       else if (result < 0)
8021         flags = N;
8022       else /* (result > 0).  */
8023         flags = C;
8024     }
8025
8026   aarch64_set_CPSR (cpu, flags);
8027 }
8028
8029 static void
8030 fcmps (sim_cpu *cpu)
8031 {
8032   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
8033   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
8034
8035   float fvalue1 = aarch64_get_FP_float (cpu, sn);
8036   float fvalue2 = aarch64_get_FP_float (cpu, sm);
8037
8038   set_flags_for_float_compare (cpu, fvalue1, fvalue2);
8039 }
8040
8041 /* Float compare to zero -- Invalid Operation exception
8042    only on signaling NaNs.  */
8043 static void
8044 fcmpzs (sim_cpu *cpu)
8045 {
8046   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
8047   float fvalue1 = aarch64_get_FP_float (cpu, sn);
8048
8049   set_flags_for_float_compare (cpu, fvalue1, 0.0f);
8050 }
8051
8052 /* Float compare -- Invalid Operation exception on all NaNs.  */
8053 static void
8054 fcmpes (sim_cpu *cpu)
8055 {
8056   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
8057   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
8058
8059   float fvalue1 = aarch64_get_FP_float (cpu, sn);
8060   float fvalue2 = aarch64_get_FP_float (cpu, sm);
8061
8062   set_flags_for_float_compare (cpu, fvalue1, fvalue2);
8063 }
8064
8065 /* Float compare to zero -- Invalid Operation exception on all NaNs.  */
8066 static void
8067 fcmpzes (sim_cpu *cpu)
8068 {
8069   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
8070   float fvalue1 = aarch64_get_FP_float (cpu, sn);
8071
8072   set_flags_for_float_compare (cpu, fvalue1, 0.0f);
8073 }
8074
8075 static void
8076 set_flags_for_double_compare (sim_cpu *cpu, double dval1, double dval2)
8077 {
8078   uint32_t flags;
8079
8080   if (isnan (dval1) || isnan (dval2))
8081     flags = C|V;
8082   else
8083     {
8084       double result = dval1 - dval2;
8085
8086       if (result == 0.0)
8087         flags = Z|C;
8088       else if (result < 0)
8089         flags = N;
8090       else /* (result > 0).  */
8091         flags = C;
8092     }
8093
8094   aarch64_set_CPSR (cpu, flags);
8095 }
8096
8097 /* Double compare -- Invalid Operation exception only on signaling NaNs.  */
8098 static void
8099 fcmpd (sim_cpu *cpu)
8100 {
8101   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
8102   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
8103
8104   double dvalue1 = aarch64_get_FP_double (cpu, sn);
8105   double dvalue2 = aarch64_get_FP_double (cpu, sm);
8106
8107   set_flags_for_double_compare (cpu, dvalue1, dvalue2);
8108 }
8109
8110 /* Double compare to zero -- Invalid Operation exception
8111    only on signaling NaNs.  */
8112 static void
8113 fcmpzd (sim_cpu *cpu)
8114 {
8115   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
8116   double dvalue1 = aarch64_get_FP_double (cpu, sn);
8117
8118   set_flags_for_double_compare (cpu, dvalue1, 0.0);
8119 }
8120
8121 /* Double compare -- Invalid Operation exception on all NaNs.  */
8122 static void
8123 fcmped (sim_cpu *cpu)
8124 {
8125   unsigned sm = uimm (aarch64_get_instr (cpu), 20, 16);
8126   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
8127
8128   double dvalue1 = aarch64_get_FP_double (cpu, sn);
8129   double dvalue2 = aarch64_get_FP_double (cpu, sm);
8130
8131   set_flags_for_double_compare (cpu, dvalue1, dvalue2);
8132 }
8133
8134 /* Double compare to zero -- Invalid Operation exception on all NaNs.  */
8135 static void
8136 fcmpzed (sim_cpu *cpu)
8137 {
8138   unsigned sn = uimm (aarch64_get_instr (cpu),  9,  5);
8139   double dvalue1 = aarch64_get_FP_double (cpu, sn);
8140
8141   set_flags_for_double_compare (cpu, dvalue1, 0.0);
8142 }
8143
8144 static void
8145 dexSimpleFPCompare (sim_cpu *cpu)
8146 {
8147   /* assert instr[28,25] == 1111
8148      instr[30:24:21:13,10] = 0011000
8149      instr[31] = M : 0 ==> OK, 1 ==> UNALLOC
8150      instr[29] ==> S :  0 ==> OK, 1 ==> UNALLOC
8151      instr[23,22] ==> type : 0 ==> single, 01 ==> double, 1x ==> UNALLOC
8152      instr[15,14] ==> op : 00 ==> OK, ow ==> UNALLOC
8153      instr[4,0] ==> opcode2 : 00000 ==> FCMP, 10000 ==> FCMPE,
8154                               01000 ==> FCMPZ, 11000 ==> FCMPEZ,
8155                               ow ==> UNALLOC  */
8156   uint32_t dispatch;
8157   uint32_t M_S = (uimm (aarch64_get_instr (cpu), 31, 31) << 1)
8158     | uimm (aarch64_get_instr (cpu), 29, 29);
8159   uint32_t type = uimm (aarch64_get_instr (cpu), 23, 22);
8160   uint32_t op = uimm (aarch64_get_instr (cpu), 15, 14);
8161   uint32_t op2_2_0 = uimm (aarch64_get_instr (cpu), 2, 0);
8162
8163   if (op2_2_0 != 0)
8164     HALT_UNALLOC;
8165
8166   if (M_S != 0)
8167     HALT_UNALLOC;
8168
8169   if (type > 1)
8170     HALT_UNALLOC;
8171
8172   if (op != 0)
8173     HALT_UNALLOC;
8174
8175   /* dispatch on type and top 2 bits of opcode.  */
8176   dispatch = (type << 2) | uimm (aarch64_get_instr (cpu), 4, 3);
8177
8178   switch (dispatch)
8179     {
8180     case 0: fcmps (cpu); return;
8181     case 1: fcmpzs (cpu); return;
8182     case 2: fcmpes (cpu); return;
8183     case 3: fcmpzes (cpu); return;
8184     case 4: fcmpd (cpu); return;
8185     case 5: fcmpzd (cpu); return;
8186     case 6: fcmped (cpu); return;
8187     case 7: fcmpzed (cpu); return;
8188     }
8189 }
8190
8191 static void
8192 do_scalar_FADDP (sim_cpu *cpu)
8193 {
8194   /* instr [31,23] = 011111100
8195      instr [22]    = single(0)/double(1)
8196      instr [21,10] = 1100 0011 0110
8197      instr [9,5]   = Fn
8198      instr [4,0]   = Fd.  */
8199
8200   unsigned Fn = uimm (aarch64_get_instr (cpu), 9, 5);
8201   unsigned Fd = uimm (aarch64_get_instr (cpu), 4, 0);
8202
8203   NYI_assert (31, 23, 0x0FC);
8204   NYI_assert (21, 10, 0xC36);
8205
8206   if (uimm (aarch64_get_instr (cpu), 22, 22))
8207     {
8208       double val1 = aarch64_get_vec_double (cpu, Fn, 0);
8209       double val2 = aarch64_get_vec_double (cpu, Fn, 1);
8210
8211       aarch64_set_FP_double (cpu, Fd, val1 + val2);
8212     }
8213   else
8214     {
8215       float val1 = aarch64_get_vec_float (cpu, Fn, 0);
8216       float val2 = aarch64_get_vec_float (cpu, Fn, 1);
8217
8218       aarch64_set_FP_float (cpu, Fd, val1 + val2);
8219     }
8220 }
8221
8222 /* Floating point absolute difference.  */
8223
8224 static void
8225 do_scalar_FABD (sim_cpu *cpu)
8226 {
8227   /* instr [31,23] = 0111 1110 1
8228      instr [22]    = float(0)/double(1)
8229      instr [21]    = 1
8230      instr [20,16] = Rm
8231      instr [15,10] = 1101 01
8232      instr [9, 5]  = Rn
8233      instr [4, 0]  = Rd.  */
8234
8235   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8236   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8237   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8238
8239   NYI_assert (31, 23, 0x0FD);
8240   NYI_assert (21, 21, 1);
8241   NYI_assert (15, 10, 0x35);
8242
8243   if (uimm (aarch64_get_instr (cpu), 22, 22))
8244     aarch64_set_FP_double (cpu, rd,
8245                            fabs (aarch64_get_FP_double (cpu, rn)
8246                                  - aarch64_get_FP_double (cpu, rm)));
8247   else
8248     aarch64_set_FP_float (cpu, rd,
8249                           fabsf (aarch64_get_FP_float (cpu, rn)
8250                                  - aarch64_get_FP_float (cpu, rm)));
8251 }
8252
8253 static void
8254 do_scalar_CMGT (sim_cpu *cpu)
8255 {
8256   /* instr [31,21] = 0101 1110 111
8257      instr [20,16] = Rm
8258      instr [15,10] = 00 1101
8259      instr [9, 5]  = Rn
8260      instr [4, 0]  = Rd.  */
8261
8262   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8263   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8264   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8265
8266   NYI_assert (31, 21, 0x2F7);
8267   NYI_assert (15, 10, 0x0D);
8268
8269   aarch64_set_vec_u64 (cpu, rd, 0,
8270                        aarch64_get_vec_u64 (cpu, rn, 0) >
8271                        aarch64_get_vec_u64 (cpu, rm, 0) ? -1L : 0L);
8272 }
8273
8274 static void
8275 do_scalar_USHR (sim_cpu *cpu)
8276 {
8277   /* instr [31,23] = 0111 1111 0
8278      instr [22,16] = shift amount
8279      instr [15,10] = 0000 01
8280      instr [9, 5]  = Rn
8281      instr [4, 0]  = Rd.  */
8282
8283   unsigned amount = 128 - INSTR (22, 16);
8284   unsigned rn = INSTR (9, 5);
8285   unsigned rd = INSTR (4, 0);
8286
8287   NYI_assert (31, 23, 0x0FE);
8288   NYI_assert (15, 10, 0x01);
8289
8290   aarch64_set_vec_u64 (cpu, rd, 0,
8291                        aarch64_get_vec_u64 (cpu, rn, 0) >> amount);
8292 }
8293
8294 static void
8295 do_scalar_SSHL (sim_cpu *cpu)
8296 {
8297   /* instr [31,21] = 0101 1110 111
8298      instr [20,16] = Rm
8299      instr [15,10] = 0100 01
8300      instr [9, 5]  = Rn
8301      instr [4, 0]  = Rd.  */
8302
8303   unsigned rm = INSTR (20, 16);
8304   unsigned rn = INSTR (9, 5);
8305   unsigned rd = INSTR (4, 0);
8306   signed int shift = aarch64_get_vec_s8 (cpu, rm, 0);
8307
8308   NYI_assert (31, 21, 0x2F7);
8309   NYI_assert (15, 10, 0x11);
8310
8311   if (shift >= 0)
8312     aarch64_set_vec_s64 (cpu, rd, 0,
8313                          aarch64_get_vec_s64 (cpu, rn, 0) << shift);
8314   else
8315     aarch64_set_vec_s64 (cpu, rd, 0,
8316                          aarch64_get_vec_s64 (cpu, rn, 0) >> - shift);    
8317 }
8318
8319 static void
8320 do_scalar_shift (sim_cpu *cpu)
8321 {
8322   /* instr [31,23] = 0101 1111 0
8323      instr [22,16] = shift amount
8324      instr [15,10] = 0101 01   [SHL]
8325      instr [15,10] = 0000 01   [SSHR]
8326      instr [9, 5]  = Rn
8327      instr [4, 0]  = Rd.  */
8328
8329   unsigned rn = INSTR (9, 5);
8330   unsigned rd = INSTR (4, 0);
8331   unsigned amount;
8332
8333   NYI_assert (31, 23, 0x0BE);
8334
8335   if (INSTR (22, 22) == 0)
8336     HALT_UNALLOC;
8337
8338   switch (INSTR (15, 10))
8339     {
8340     case 0x01: /* SSHR */
8341       amount = 128 - INSTR (22, 16);
8342       aarch64_set_vec_s64 (cpu, rd, 0,
8343                            aarch64_get_vec_s64 (cpu, rn, 0) >> amount);
8344       return;
8345     case 0x15: /* SHL */
8346       amount = INSTR (22, 16) - 64;
8347       aarch64_set_vec_u64 (cpu, rd, 0,
8348                            aarch64_get_vec_u64 (cpu, rn, 0) << amount);
8349       return;
8350     default:
8351       HALT_NYI;
8352     }
8353 }
8354
8355 /* FCMEQ FCMGT FCMGE.  */
8356 static void
8357 do_scalar_FCM (sim_cpu *cpu)
8358 {
8359   /* instr [31,30] = 01
8360      instr [29]    = U
8361      instr [28,24] = 1 1110
8362      instr [23]    = E
8363      instr [22]    = size
8364      instr [21]    = 1
8365      instr [20,16] = Rm
8366      instr [15,12] = 1110
8367      instr [11]    = AC
8368      instr [10]    = 1
8369      instr [9, 5]  = Rn
8370      instr [4, 0]  = Rd.  */
8371
8372   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8373   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8374   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8375   unsigned EUac = (uimm (aarch64_get_instr (cpu), 23, 23) << 2)
8376     | (uimm (aarch64_get_instr (cpu), 29, 29) << 1)
8377     | uimm (aarch64_get_instr (cpu), 11, 11);
8378   unsigned result;
8379   float val1;
8380   float val2;
8381
8382   NYI_assert (31, 30, 1);
8383   NYI_assert (28, 24, 0x1E);
8384   NYI_assert (21, 21, 1);
8385   NYI_assert (15, 12, 0xE);
8386   NYI_assert (10, 10, 1);
8387
8388   if (uimm (aarch64_get_instr (cpu), 22, 22))
8389     {
8390       double val1 = aarch64_get_FP_double (cpu, rn);
8391       double val2 = aarch64_get_FP_double (cpu, rm);
8392
8393       switch (EUac)
8394         {
8395         case 0: /* 000 */
8396           result = val1 == val2;
8397           break;
8398
8399         case 3: /* 011 */
8400           val1 = fabs (val1);
8401           val2 = fabs (val2);
8402           /* Fall through. */
8403         case 2: /* 010 */
8404           result = val1 >= val2;
8405           break;
8406
8407         case 7: /* 111 */
8408           val1 = fabs (val1);
8409           val2 = fabs (val2);
8410           /* Fall through. */
8411         case 6: /* 110 */
8412           result = val1 > val2;
8413           break;
8414
8415         default:
8416           HALT_UNALLOC;
8417         }
8418
8419       aarch64_set_vec_u32 (cpu, rd, 0, result ? -1 : 0);
8420       return;
8421     }
8422
8423   val1 = aarch64_get_FP_float (cpu, rn);
8424   val2 = aarch64_get_FP_float (cpu, rm);
8425
8426   switch (EUac)
8427     {
8428     case 0: /* 000 */
8429       result = val1 == val2;
8430       break;
8431
8432     case 3: /* 011 */
8433       val1 = fabsf (val1);
8434       val2 = fabsf (val2);
8435       /* Fall through. */
8436     case 2: /* 010 */
8437       result = val1 >= val2;
8438       break;
8439
8440     case 7: /* 111 */
8441       val1 = fabsf (val1);
8442       val2 = fabsf (val2);
8443       /* Fall through. */
8444     case 6: /* 110 */
8445       result = val1 > val2;
8446       break;
8447
8448     default:
8449       HALT_UNALLOC;
8450     }
8451
8452   aarch64_set_vec_u32 (cpu, rd, 0, result ? -1 : 0);
8453 }
8454
8455 /* An alias of DUP.  */
8456 static void
8457 do_scalar_MOV (sim_cpu *cpu)
8458 {
8459   /* instr [31,21] = 0101 1110 000
8460      instr [20,16] = imm5
8461      instr [15,10] = 0000 01
8462      instr [9, 5]  = Rn
8463      instr [4, 0]  = Rd.  */
8464
8465   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8466   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8467   unsigned index;
8468
8469   NYI_assert (31, 21, 0x2F0);
8470   NYI_assert (15, 10, 0x01);
8471
8472   if (uimm (aarch64_get_instr (cpu), 16, 16))
8473     {
8474       /* 8-bit.  */
8475       index = uimm (aarch64_get_instr (cpu), 20, 17);
8476       aarch64_set_vec_u8
8477         (cpu, rd, 0, aarch64_get_vec_u8 (cpu, rn, index));
8478     }
8479   else if (uimm (aarch64_get_instr (cpu), 17, 17))
8480     {
8481       /* 16-bit.  */
8482       index = uimm (aarch64_get_instr (cpu), 20, 18);
8483       aarch64_set_vec_u16
8484         (cpu, rd, 0, aarch64_get_vec_u16 (cpu, rn, index));
8485     }
8486   else if (uimm (aarch64_get_instr (cpu), 18, 18))
8487     {
8488       /* 32-bit.  */
8489       index = uimm (aarch64_get_instr (cpu), 20, 19);
8490       aarch64_set_vec_u32
8491         (cpu, rd, 0, aarch64_get_vec_u32 (cpu, rn, index));
8492     }
8493   else if (uimm (aarch64_get_instr (cpu), 19, 19))
8494     {
8495       /* 64-bit.  */
8496       index = uimm (aarch64_get_instr (cpu), 20, 20);
8497       aarch64_set_vec_u64
8498         (cpu, rd, 0, aarch64_get_vec_u64 (cpu, rn, index));
8499     }
8500   else
8501     HALT_UNALLOC;
8502 }
8503
8504 static void
8505 do_scalar_NEG (sim_cpu *cpu)
8506 {
8507   /* instr [31,10] = 0111 1110 1110 0000 1011 10
8508      instr [9, 5]  = Rn
8509      instr [4, 0]  = Rd.  */
8510
8511   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8512   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8513
8514   NYI_assert (31, 10, 0x1FB82E);
8515
8516   aarch64_set_vec_u64 (cpu, rd, 0, - aarch64_get_vec_u64 (cpu, rn, 0));
8517 }
8518
8519 static void
8520 do_scalar_USHL (sim_cpu *cpu)
8521 {
8522   /* instr [31,21] = 0111 1110 111
8523      instr [20,16] = Rm
8524      instr [15,10] = 0100 01
8525      instr [9, 5]  = Rn
8526      instr [4, 0]  = Rd.  */
8527
8528   unsigned rm = INSTR (20, 16);
8529   unsigned rn = INSTR (9, 5);
8530   unsigned rd = INSTR (4, 0);
8531   signed int shift = aarch64_get_vec_s8 (cpu, rm, 0);
8532
8533   NYI_assert (31, 21, 0x3F7);
8534   NYI_assert (15, 10, 0x11);
8535
8536   if (shift >= 0)
8537     aarch64_set_vec_u64 (cpu, rd, 0, aarch64_get_vec_u64 (cpu, rn, 0) << shift);
8538   else
8539     aarch64_set_vec_u64 (cpu, rd, 0, aarch64_get_vec_u64 (cpu, rn, 0) >> - shift);
8540 }
8541
8542 static void
8543 do_double_add (sim_cpu *cpu)
8544 {
8545   /* instr [31,21] = 0101 1110 111
8546      instr [20,16] = Fn
8547      instr [15,10] = 1000 01
8548      instr [9,5]   = Fm
8549      instr [4,0]   = Fd.  */
8550   unsigned Fd;
8551   unsigned Fm;
8552   unsigned Fn;
8553   double val1;
8554   double val2;
8555
8556   NYI_assert (31, 21, 0x2F7);
8557   NYI_assert (15, 10, 0x21);
8558
8559   Fd = INSTR (4, 0);
8560   Fm = INSTR (9, 5);
8561   Fn = INSTR (20, 16);
8562
8563   val1 = aarch64_get_FP_double (cpu, Fm);
8564   val2 = aarch64_get_FP_double (cpu, Fn);
8565
8566   aarch64_set_FP_double (cpu, Fd, val1 + val2);
8567 }
8568
8569 static void
8570 do_scalar_vec (sim_cpu *cpu)
8571 {
8572   /* instr [30] = 1.  */
8573   /* instr [28,25] = 1111.  */
8574   switch (uimm (aarch64_get_instr (cpu), 31, 23))
8575     {
8576     case 0xBC:
8577       switch (uimm (aarch64_get_instr (cpu), 15, 10))
8578         {
8579         case 0x01: do_scalar_MOV (cpu); return;
8580         case 0x39: do_scalar_FCM (cpu); return;
8581         case 0x3B: do_scalar_FCM (cpu); return;
8582         }
8583       break;
8584
8585     case 0xBE: do_scalar_shift (cpu); return;
8586
8587     case 0xFC:
8588       switch (uimm (aarch64_get_instr (cpu), 15, 10))
8589         {
8590         case 0x36: do_scalar_FADDP (cpu); return;
8591         case 0x39: do_scalar_FCM (cpu); return;
8592         case 0x3B: do_scalar_FCM (cpu); return;
8593         }
8594       break;
8595
8596     case 0xFD:
8597       switch (uimm (aarch64_get_instr (cpu), 15, 10))
8598         {
8599         case 0x0D: do_scalar_CMGT (cpu); return;
8600         case 0x11: do_scalar_USHL (cpu); return;
8601         case 0x2E: do_scalar_NEG (cpu); return;
8602         case 0x35: do_scalar_FABD (cpu); return;
8603         case 0x39: do_scalar_FCM (cpu); return;
8604         case 0x3B: do_scalar_FCM (cpu); return;
8605         default:
8606           HALT_NYI;
8607         }
8608
8609     case 0xFE: do_scalar_USHR (cpu); return;
8610
8611     case 0xBD:
8612       switch (INSTR (15, 10))
8613         {
8614         case 0x21: do_double_add (cpu); return;
8615         case 0x11: do_scalar_SSHL (cpu); return;
8616         default:
8617           HALT_NYI;
8618         }
8619       
8620     default:
8621       HALT_NYI;
8622     }
8623 }
8624
8625 static void
8626 dexAdvSIMD1 (sim_cpu *cpu)
8627 {
8628   /* instr [28,25] = 1 111.  */
8629
8630   /* We are currently only interested in the basic
8631      scalar fp routines which all have bit 30 = 0.  */
8632   if (uimm (aarch64_get_instr (cpu), 30, 30))
8633     do_scalar_vec (cpu);
8634
8635   /* instr[24] is set for FP data processing 3-source and clear for
8636      all other basic scalar fp instruction groups.  */
8637   else if (uimm (aarch64_get_instr (cpu), 24, 24))
8638     dexSimpleFPDataProc3Source (cpu);
8639
8640   /* instr[21] is clear for floating <-> fixed conversions and set for
8641      all other basic scalar fp instruction groups.  */
8642   else if (!uimm (aarch64_get_instr (cpu), 21, 21))
8643     dexSimpleFPFixedConvert (cpu);
8644
8645   /* instr[11,10] : 01 ==> cond compare, 10 ==> Data Proc 2 Source
8646      11 ==> cond select,  00 ==> other.  */
8647   else
8648     switch (uimm (aarch64_get_instr (cpu), 11, 10))
8649       {
8650       case 1: dexSimpleFPCondCompare (cpu); return;
8651       case 2: dexSimpleFPDataProc2Source (cpu); return;
8652       case 3: dexSimpleFPCondSelect (cpu); return;
8653
8654       default:
8655         /* Now an ordered cascade of tests.
8656            FP immediate has aarch64_get_instr (cpu)[12] == 1.
8657            FP compare has aarch64_get_instr (cpu)[13] == 1.
8658            FP Data Proc 1 Source has aarch64_get_instr (cpu)[14] == 1.
8659            FP floating <--> integer conversions has aarch64_get_instr (cpu)[15] == 0.  */
8660         if (uimm (aarch64_get_instr (cpu), 12, 12))
8661           dexSimpleFPImmediate (cpu);
8662
8663         else if (uimm (aarch64_get_instr (cpu), 13, 13))
8664           dexSimpleFPCompare (cpu);
8665
8666         else if (uimm (aarch64_get_instr (cpu), 14, 14))
8667           dexSimpleFPDataProc1Source (cpu);
8668
8669         else if (!uimm (aarch64_get_instr (cpu), 15, 15))
8670           dexSimpleFPIntegerConvert (cpu);
8671
8672         else
8673           /* If we get here then instr[15] == 1 which means UNALLOC.  */
8674           HALT_UNALLOC;
8675       }
8676 }
8677
8678 /* PC relative addressing.  */
8679
8680 static void
8681 pcadr (sim_cpu *cpu)
8682 {
8683   /* instr[31] = op : 0 ==> ADR, 1 ==> ADRP
8684      instr[30,29] = immlo
8685      instr[23,5] = immhi.  */
8686   uint64_t address;
8687   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8688   uint32_t isPage = uimm (aarch64_get_instr (cpu), 31, 31);
8689   union { int64_t u64; uint64_t s64; } imm;
8690   uint64_t offset;
8691
8692   imm.s64 = simm64 (aarch64_get_instr (cpu), 23, 5);
8693   offset = imm.u64;
8694   offset = (offset << 2) | uimm (aarch64_get_instr (cpu), 30, 29);
8695
8696   address = aarch64_get_PC (cpu);
8697
8698   if (isPage)
8699     {
8700       offset <<= 12;
8701       address &= ~0xfff;
8702     }
8703
8704   aarch64_set_reg_u64 (cpu, rd, NO_SP, address + offset);
8705 }
8706
8707 /* Specific decode and execute for group Data Processing Immediate.  */
8708
8709 static void
8710 dexPCRelAddressing (sim_cpu *cpu)
8711 {
8712   /* assert instr[28,24] = 10000.  */
8713   pcadr (cpu);
8714 }
8715
8716 /* Immediate logical.
8717    The bimm32/64 argument is constructed by replicating a 2, 4, 8,
8718    16, 32 or 64 bit sequence pulled out at decode and possibly
8719    inverting it..
8720
8721    N.B. the output register (dest) can normally be Xn or SP
8722    the exception occurs for flag setting instructions which may
8723    only use Xn for the output (dest).  The input register can
8724    never be SP.  */
8725
8726 /* 32 bit and immediate.  */
8727 static void
8728 and32 (sim_cpu *cpu, uint32_t bimm)
8729 {
8730   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8731   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8732
8733   aarch64_set_reg_u64 (cpu, rd, SP_OK,
8734                        aarch64_get_reg_u32 (cpu, rn, NO_SP) & bimm);
8735 }
8736
8737 /* 64 bit and immediate.  */
8738 static void
8739 and64 (sim_cpu *cpu, uint64_t bimm)
8740 {
8741   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8742   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8743
8744   aarch64_set_reg_u64 (cpu, rd, SP_OK,
8745                        aarch64_get_reg_u64 (cpu, rn, NO_SP) & bimm);
8746 }
8747
8748 /* 32 bit and immediate set flags.  */
8749 static void
8750 ands32 (sim_cpu *cpu, uint32_t bimm)
8751 {
8752   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8753   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8754
8755   uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8756   uint32_t value2 = bimm;
8757
8758   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8759   set_flags_for_binop32 (cpu, value1 & value2);
8760 }
8761
8762 /* 64 bit and immediate set flags.  */
8763 static void
8764 ands64 (sim_cpu *cpu, uint64_t bimm)
8765 {
8766   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8767   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8768
8769   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
8770   uint64_t value2 = bimm;
8771
8772   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8773   set_flags_for_binop64 (cpu, value1 & value2);
8774 }
8775
8776 /* 32 bit exclusive or immediate.  */
8777 static void
8778 eor32 (sim_cpu *cpu, uint32_t bimm)
8779 {
8780   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8781   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8782
8783   aarch64_set_reg_u64 (cpu, rd, SP_OK,
8784                        aarch64_get_reg_u32 (cpu, rn, NO_SP) ^ bimm);
8785 }
8786
8787 /* 64 bit exclusive or immediate.  */
8788 static void
8789 eor64 (sim_cpu *cpu, uint64_t bimm)
8790 {
8791   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8792   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8793
8794   aarch64_set_reg_u64 (cpu, rd, SP_OK,
8795                        aarch64_get_reg_u64 (cpu, rn, NO_SP) ^ bimm);
8796 }
8797
8798 /* 32 bit or immediate.  */
8799 static void
8800 orr32 (sim_cpu *cpu, uint32_t bimm)
8801 {
8802   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8803   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8804
8805   aarch64_set_reg_u64 (cpu, rd, SP_OK,
8806                        aarch64_get_reg_u32 (cpu, rn, NO_SP) | bimm);
8807 }
8808
8809 /* 64 bit or immediate.  */
8810 static void
8811 orr64 (sim_cpu *cpu, uint64_t bimm)
8812 {
8813   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8814   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8815
8816   aarch64_set_reg_u64 (cpu, rd, SP_OK,
8817                        aarch64_get_reg_u64 (cpu, rn, NO_SP) | bimm);
8818 }
8819
8820 /* Logical shifted register.
8821    These allow an optional LSL, ASR, LSR or ROR to the second source
8822    register with a count up to the register bit count.
8823    N.B register args may not be SP.  */
8824
8825 /* 32 bit AND shifted register.  */
8826 static void
8827 and32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8828 {
8829   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8830   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8831   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8832
8833   aarch64_set_reg_u64
8834     (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8835      & shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8836 }
8837
8838 /* 64 bit AND shifted register.  */
8839 static void
8840 and64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8841 {
8842   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8843   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8844   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8845
8846   aarch64_set_reg_u64
8847     (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8848      & shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8849 }
8850
8851 /* 32 bit AND shifted register setting flags.  */
8852 static void
8853 ands32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8854 {
8855   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8856   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8857   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8858
8859   uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8860   uint32_t value2 = shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
8861                                shift, count);
8862
8863   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8864   set_flags_for_binop32 (cpu, value1 & value2);
8865 }
8866
8867 /* 64 bit AND shifted register setting flags.  */
8868 static void
8869 ands64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8870 {
8871   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8872   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8873   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8874
8875   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
8876   uint64_t value2 = shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
8877                                shift, count);
8878
8879   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8880   set_flags_for_binop64 (cpu, value1 & value2);
8881 }
8882
8883 /* 32 bit BIC shifted register.  */
8884 static void
8885 bic32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8886 {
8887   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8888   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8889   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8890
8891   aarch64_set_reg_u64
8892     (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8893      & ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8894 }
8895
8896 /* 64 bit BIC shifted register.  */
8897 static void
8898 bic64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8899 {
8900   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8901   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8902   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8903
8904   aarch64_set_reg_u64
8905     (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8906      & ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8907 }
8908
8909 /* 32 bit BIC shifted register setting flags.  */
8910 static void
8911 bics32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8912 {
8913   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8914   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8915   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8916
8917   uint32_t value1 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
8918   uint32_t value2 = ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP),
8919                                  shift, count);
8920
8921   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8922   set_flags_for_binop32 (cpu, value1 & value2);
8923 }
8924
8925 /* 64 bit BIC shifted register setting flags.  */
8926 static void
8927 bics64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8928 {
8929   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8930   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8931   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8932
8933   uint64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
8934   uint64_t value2 = ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP),
8935                                  shift, count);
8936
8937   aarch64_set_reg_u64 (cpu, rd, NO_SP, value1 & value2);
8938   set_flags_for_binop64 (cpu, value1 & value2);
8939 }
8940
8941 /* 32 bit EON shifted register.  */
8942 static void
8943 eon32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8944 {
8945   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8946   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8947   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8948
8949   aarch64_set_reg_u64
8950     (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8951      ^ ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8952 }
8953
8954 /* 64 bit EON shifted register.  */
8955 static void
8956 eon64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8957 {
8958   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8959   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8960   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8961
8962   aarch64_set_reg_u64
8963     (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8964      ^ ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8965 }
8966
8967 /* 32 bit EOR shifted register.  */
8968 static void
8969 eor32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8970 {
8971   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8972   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8973   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8974
8975   aarch64_set_reg_u64
8976     (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
8977      ^ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
8978 }
8979
8980 /* 64 bit EOR shifted register.  */
8981 static void
8982 eor64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8983 {
8984   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8985   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8986   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
8987
8988   aarch64_set_reg_u64
8989     (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
8990      ^ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
8991 }
8992
8993 /* 32 bit ORR shifted register.  */
8994 static void
8995 orr32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
8996 {
8997   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
8998   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
8999   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
9000
9001   aarch64_set_reg_u64
9002     (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
9003      | shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
9004 }
9005
9006 /* 64 bit ORR shifted register.  */
9007 static void
9008 orr64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
9009 {
9010   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9011   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9012   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
9013
9014   aarch64_set_reg_u64
9015     (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
9016      | shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
9017 }
9018
9019 /* 32 bit ORN shifted register.  */
9020 static void
9021 orn32_shift (sim_cpu *cpu, Shift shift, uint32_t count)
9022 {
9023   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9024   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9025   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
9026
9027   aarch64_set_reg_u64
9028     (cpu, rd, NO_SP, aarch64_get_reg_u32 (cpu, rn, NO_SP)
9029      | ~ shifted32 (aarch64_get_reg_u32 (cpu, rm, NO_SP), shift, count));
9030 }
9031
9032 /* 64 bit ORN shifted register.  */
9033 static void
9034 orn64_shift (sim_cpu *cpu, Shift shift, uint32_t count)
9035 {
9036   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9037   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9038   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
9039
9040   aarch64_set_reg_u64
9041     (cpu, rd, NO_SP, aarch64_get_reg_u64 (cpu, rn, NO_SP)
9042      | ~ shifted64 (aarch64_get_reg_u64 (cpu, rm, NO_SP), shift, count));
9043 }
9044
9045 static void
9046 dexLogicalImmediate (sim_cpu *cpu)
9047 {
9048   /* assert instr[28,23] = 1001000
9049      instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9050      instr[30,29] = op : 0 ==> AND, 1 ==> ORR, 2 ==> EOR, 3 ==> ANDS
9051      instr[22] = N : used to construct immediate mask
9052      instr[21,16] = immr
9053      instr[15,10] = imms
9054      instr[9,5] = Rn
9055      instr[4,0] = Rd  */
9056
9057   /* 32 bit operations must have N = 0 or else we have an UNALLOC.  */
9058   uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
9059   uint32_t N = uimm (aarch64_get_instr (cpu), 22, 22);
9060   /* uint32_t immr = uimm (aarch64_get_instr (cpu), 21, 16);.  */
9061   /* uint32_t imms = uimm (aarch64_get_instr (cpu), 15, 10);.  */
9062   uint32_t index = uimm (aarch64_get_instr (cpu), 22, 10);
9063   uint64_t bimm64 = LITable [index];
9064   uint32_t dispatch = uimm (aarch64_get_instr (cpu), 30, 29);
9065
9066   if (~size & N)
9067     HALT_UNALLOC;
9068
9069   if (!bimm64)
9070     HALT_UNALLOC;
9071
9072   if (size == 0)
9073     {
9074       uint32_t bimm = (uint32_t) bimm64;
9075
9076       switch (dispatch)
9077         {
9078         case 0: and32 (cpu, bimm); return;
9079         case 1: orr32 (cpu, bimm); return;
9080         case 2: eor32 (cpu, bimm); return;
9081         case 3: ands32 (cpu, bimm); return;
9082         }
9083     }
9084   else
9085     {
9086       switch (dispatch)
9087         {
9088         case 0: and64 (cpu, bimm64); return;
9089         case 1: orr64 (cpu, bimm64); return;
9090         case 2: eor64 (cpu, bimm64); return;
9091         case 3: ands64 (cpu, bimm64); return;
9092         }
9093     }
9094   HALT_UNALLOC;
9095 }
9096
9097 /* Immediate move.
9098    The uimm argument is a 16 bit value to be inserted into the
9099    target register the pos argument locates the 16 bit word in the
9100    dest register i.e. it is in {0, 1} for 32 bit and {0, 1, 2,
9101    3} for 64 bit.
9102    N.B register arg may not be SP so it should be.
9103    accessed using the setGZRegisterXXX accessors.  */
9104
9105 /* 32 bit move 16 bit immediate zero remaining shorts.  */
9106 static void
9107 movz32 (sim_cpu *cpu, uint32_t val, uint32_t pos)
9108 {
9109   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
9110
9111   aarch64_set_reg_u64 (cpu, rd, NO_SP, val << (pos * 16));
9112 }
9113
9114 /* 64 bit move 16 bit immediate zero remaining shorts.  */
9115 static void
9116 movz64 (sim_cpu *cpu, uint32_t val, uint32_t pos)
9117 {
9118   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
9119
9120   aarch64_set_reg_u64 (cpu, rd, NO_SP, ((uint64_t) val) << (pos * 16));
9121 }
9122
9123 /* 32 bit move 16 bit immediate negated.  */
9124 static void
9125 movn32 (sim_cpu *cpu, uint32_t val, uint32_t pos)
9126 {
9127   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
9128
9129   aarch64_set_reg_u64 (cpu, rd, NO_SP, ((val << (pos * 16)) ^ 0xffffffffU));
9130 }
9131
9132 /* 64 bit move 16 bit immediate negated.  */
9133 static void
9134 movn64 (sim_cpu *cpu, uint32_t val, uint32_t pos)
9135 {
9136   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
9137
9138   aarch64_set_reg_u64
9139     (cpu, rd, NO_SP, ((((uint64_t) val) << (pos * 16))
9140                       ^ 0xffffffffffffffffULL));
9141 }
9142
9143 /* 32 bit move 16 bit immediate keep remaining shorts.  */
9144 static void
9145 movk32 (sim_cpu *cpu, uint32_t val, uint32_t pos)
9146 {
9147   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
9148   uint32_t current = aarch64_get_reg_u32 (cpu, rd, NO_SP);
9149   uint32_t value = val << (pos * 16);
9150   uint32_t mask = ~(0xffffU << (pos * 16));
9151
9152   aarch64_set_reg_u64 (cpu, rd, NO_SP, (value | (current & mask)));
9153 }
9154
9155 /* 64 bit move 16 it immediate keep remaining shorts.  */
9156 static void
9157 movk64 (sim_cpu *cpu, uint32_t val, uint32_t pos)
9158 {
9159   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
9160   uint64_t current = aarch64_get_reg_u64 (cpu, rd, NO_SP);
9161   uint64_t value = (uint64_t) val << (pos * 16);
9162   uint64_t mask = ~(0xffffULL << (pos * 16));
9163
9164   aarch64_set_reg_u64 (cpu, rd, NO_SP, (value | (current & mask)));
9165 }
9166
9167 static void
9168 dexMoveWideImmediate (sim_cpu *cpu)
9169 {
9170   /* assert instr[28:23] = 100101
9171      instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9172      instr[30,29] = op : 0 ==> MOVN, 1 ==> UNALLOC, 2 ==> MOVZ, 3 ==> MOVK
9173      instr[22,21] = shift : 00 == LSL#0, 01 = LSL#16, 10 = LSL#32, 11 = LSL#48
9174      instr[20,5] = uimm16
9175      instr[4,0] = Rd  */
9176
9177   /* N.B. the (multiple of 16) shift is applied by the called routine,
9178      we just pass the multiplier.  */
9179
9180   uint32_t imm;
9181   uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
9182   uint32_t op = uimm (aarch64_get_instr (cpu), 30, 29);
9183   uint32_t shift = uimm (aarch64_get_instr (cpu), 22, 21);
9184
9185   /* 32 bit can only shift 0 or 1 lot of 16.
9186      anything else is an unallocated instruction.  */
9187   if (size == 0 && (shift > 1))
9188     HALT_UNALLOC;
9189
9190   if (op == 1)
9191     HALT_UNALLOC;
9192
9193   imm = uimm (aarch64_get_instr (cpu), 20, 5);
9194
9195   if (size == 0)
9196     {
9197       if (op == 0)
9198         movn32 (cpu, imm, shift);
9199       else if (op == 2)
9200         movz32 (cpu, imm, shift);
9201       else
9202         movk32 (cpu, imm, shift);
9203     }
9204   else
9205     {
9206       if (op == 0)
9207         movn64 (cpu, imm, shift);
9208       else if (op == 2)
9209         movz64 (cpu, imm, shift);
9210       else
9211         movk64 (cpu, imm, shift);
9212     }
9213 }
9214
9215 /* Bitfield operations.
9216    These take a pair of bit positions r and s which are in {0..31}
9217    or {0..63} depending on the instruction word size.
9218    N.B register args may not be SP.  */
9219
9220 /* OK, we start with ubfm which just needs to pick
9221    some bits out of source zero the rest and write
9222    the result to dest.  Just need two logical shifts.  */
9223
9224 /* 32 bit bitfield move, left and right of affected zeroed
9225    if r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>.  */
9226 static void
9227 ubfm32 (sim_cpu *cpu, uint32_t r, uint32_t s)
9228 {
9229   unsigned rd;
9230   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9231   uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
9232
9233   /* Pick either s+1-r or s+1 consecutive bits out of the original word.  */
9234   if (r <= s)
9235     {
9236       /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
9237          We want only bits s:xxx:r at the bottom of the word
9238          so we LSL bit s up to bit 31 i.e. by 31 - s
9239          and then we LSR to bring bit 31 down to bit s - r
9240          i.e. by 31 + r - s.  */
9241       value <<= 31 - s;
9242       value >>= 31 + r - s;
9243     }
9244   else
9245     {
9246       /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0
9247          We want only bits s:xxx:0 starting at it 31-(r-1)
9248          so we LSL bit s up to bit 31 i.e. by 31 - s
9249          and then we LSL to bring bit 31 down to 31-(r-1)+s
9250          i.e. by r - (s + 1).  */
9251       value <<= 31 - s;
9252       value >>= r - (s + 1);
9253     }
9254
9255   rd = uimm (aarch64_get_instr (cpu), 4, 0);
9256   aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
9257 }
9258
9259 /* 64 bit bitfield move, left and right of affected zeroed
9260    if r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>.  */
9261 static void
9262 ubfm (sim_cpu *cpu, uint32_t r, uint32_t s)
9263 {
9264   unsigned rd;
9265   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9266   uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
9267
9268   if (r <= s)
9269     {
9270       /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
9271          We want only bits s:xxx:r at the bottom of the word.
9272          So we LSL bit s up to bit 63 i.e. by 63 - s
9273          and then we LSR to bring bit 63 down to bit s - r
9274          i.e. by 63 + r - s.  */
9275       value <<= 63 - s;
9276       value >>= 63 + r - s;
9277     }
9278   else
9279     {
9280       /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0.
9281          We want only bits s:xxx:0 starting at it 63-(r-1).
9282          So we LSL bit s up to bit 63 i.e. by 63 - s
9283          and then we LSL to bring bit 63 down to 63-(r-1)+s
9284          i.e. by r - (s + 1).  */
9285       value <<= 63 - s;
9286       value >>= r - (s + 1);
9287     }
9288
9289   rd = uimm (aarch64_get_instr (cpu), 4, 0);
9290   aarch64_set_reg_u64 (cpu, rd, NO_SP, value);
9291 }
9292
9293 /* The signed versions need to insert sign bits
9294    on the left of the inserted bit field. so we do
9295    much the same as the unsigned version except we
9296    use an arithmetic shift right -- this just means
9297    we need to operate on signed values.  */
9298
9299 /* 32 bit bitfield move, left of affected sign-extended, right zeroed.  */
9300 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>.  */
9301 static void
9302 sbfm32 (sim_cpu *cpu, uint32_t r, uint32_t s)
9303 {
9304   unsigned rd;
9305   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9306   /* as per ubfm32 but use an ASR instead of an LSR.  */
9307   int32_t value = aarch64_get_reg_s32 (cpu, rn, NO_SP);
9308
9309   if (r <= s)
9310     {
9311       value <<= 31 - s;
9312       value >>= 31 + r - s;
9313     }
9314   else
9315     {
9316       value <<= 31 - s;
9317       value >>= r - (s + 1);
9318     }
9319
9320   rd = uimm (aarch64_get_instr (cpu), 4, 0);
9321   aarch64_set_reg_u64 (cpu, rd, NO_SP, (uint32_t) value);
9322 }
9323
9324 /* 64 bit bitfield move, left of affected sign-extended, right zeroed.  */
9325 /* If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>.  */
9326 static void
9327 sbfm (sim_cpu *cpu, uint32_t r, uint32_t s)
9328 {
9329   unsigned rd;
9330   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9331   /* acpu per ubfm but use an ASR instead of an LSR.  */
9332   int64_t value = aarch64_get_reg_s64 (cpu, rn, NO_SP);
9333
9334   if (r <= s)
9335     {
9336       value <<= 63 - s;
9337       value >>= 63 + r - s;
9338     }
9339   else
9340     {
9341       value <<= 63 - s;
9342       value >>= r - (s + 1);
9343     }
9344
9345   rd = uimm (aarch64_get_instr (cpu), 4, 0);
9346   aarch64_set_reg_s64 (cpu, rd, NO_SP, value);
9347 }
9348
9349 /* Finally, these versions leave non-affected bits
9350    as is. so we need to generate the bits as per
9351    ubfm and also generate a mask to pick the
9352    bits from the original and computed values.  */
9353
9354 /* 32 bit bitfield move, non-affected bits left as is.
9355    If r <= s Wd<s-r:0> = Wn<s:r> else Wd<32+s-r,32-r> = Wn<s:0>.  */
9356 static void
9357 bfm32 (sim_cpu *cpu, uint32_t r, uint32_t s)
9358 {
9359   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9360   uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
9361   uint32_t mask = -1;
9362   unsigned rd;
9363   uint32_t value2;
9364
9365   /* Pick either s+1-r or s+1 consecutive bits out of the original word.  */
9366   if (r <= s)
9367     {
9368       /* 31:...:s:xxx:r:...:0 ==> 31:...:s-r:xxx:0.
9369          We want only bits s:xxx:r at the bottom of the word
9370          so we LSL bit s up to bit 31 i.e. by 31 - s
9371          and then we LSR to bring bit 31 down to bit s - r
9372          i.e. by 31 + r - s.  */
9373       value <<= 31 - s;
9374       value >>= 31 + r - s;
9375       /* the mask must include the same bits.  */
9376       mask <<= 31 - s;
9377       mask >>= 31 + r - s;
9378     }
9379   else
9380     {
9381       /* 31:...:s:xxx:0 ==> 31:...:31-(r-1)+s:xxx:31-(r-1):...:0.
9382          We want only bits s:xxx:0 starting at it 31-(r-1)
9383          so we LSL bit s up to bit 31 i.e. by 31 - s
9384          and then we LSL to bring bit 31 down to 31-(r-1)+s
9385          i.e. by r - (s + 1).  */
9386       value <<= 31 - s;
9387       value >>= r - (s + 1);
9388       /* The mask must include the same bits.  */
9389       mask <<= 31 - s;
9390       mask >>= r - (s + 1);
9391     }
9392
9393   rd = uimm (aarch64_get_instr (cpu), 4, 0);
9394   value2 = aarch64_get_reg_u32 (cpu, rd, NO_SP);
9395
9396   value2 &= ~mask;
9397   value2 |= value;
9398
9399   aarch64_set_reg_u64
9400     (cpu, rd, NO_SP, (aarch64_get_reg_u32 (cpu, rd, NO_SP) & ~mask) | value);
9401 }
9402
9403 /* 64 bit bitfield move, non-affected bits left as is.
9404    If r <= s Wd<s-r:0> = Wn<s:r> else Wd<64+s-r,64-r> = Wn<s:0>.  */
9405 static void
9406 bfm (sim_cpu *cpu, uint32_t r, uint32_t s)
9407 {
9408   unsigned rd;
9409   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9410   uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
9411   uint64_t mask = 0xffffffffffffffffULL;
9412
9413   if (r <= s)
9414     {
9415       /* 63:...:s:xxx:r:...:0 ==> 63:...:s-r:xxx:0.
9416          We want only bits s:xxx:r at the bottom of the word
9417          so we LSL bit s up to bit 63 i.e. by 63 - s
9418          and then we LSR to bring bit 63 down to bit s - r
9419          i.e. by 63 + r - s.  */
9420       value <<= 63 - s;
9421       value >>= 63 + r - s;
9422       /* The mask must include the same bits.  */
9423       mask <<= 63 - s;
9424       mask >>= 63 + r - s;
9425     }
9426   else
9427     {
9428       /* 63:...:s:xxx:0 ==> 63:...:63-(r-1)+s:xxx:63-(r-1):...:0
9429          We want only bits s:xxx:0 starting at it 63-(r-1)
9430          so we LSL bit s up to bit 63 i.e. by 63 - s
9431          and then we LSL to bring bit 63 down to 63-(r-1)+s
9432          i.e. by r - (s + 1).  */
9433       value <<= 63 - s;
9434       value >>= r - (s + 1);
9435       /* The mask must include the same bits.  */
9436       mask <<= 63 - s;
9437       mask >>= r - (s + 1);
9438     }
9439
9440   rd = uimm (aarch64_get_instr (cpu), 4, 0);
9441   aarch64_set_reg_u64
9442     (cpu, rd, NO_SP, (aarch64_get_reg_u64 (cpu, rd, NO_SP) & ~mask) | value);
9443 }
9444
9445 static void
9446 dexBitfieldImmediate (sim_cpu *cpu)
9447 {
9448   /* assert instr[28:23] = 100110
9449      instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
9450      instr[30,29] = op : 0 ==> SBFM, 1 ==> BFM, 2 ==> UBFM, 3 ==> UNALLOC
9451      instr[22] = N : must be 0 for 32 bit, 1 for 64 bit ow UNALLOC
9452      instr[21,16] = immr : 0xxxxx for 32 bit, xxxxxx for 64 bit
9453      instr[15,10] = imms :  0xxxxx for 32 bit, xxxxxx for 64 bit
9454      instr[9,5] = Rn
9455      instr[4,0] = Rd  */
9456
9457   /* 32 bit operations must have N = 0 or else we have an UNALLOC.  */
9458   uint32_t dispatch;
9459   uint32_t imms;
9460   uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
9461   uint32_t N = uimm (aarch64_get_instr (cpu), 22, 22);
9462   /* 32 bit operations must have immr[5] = 0 and imms[5] = 0.  */
9463   /* or else we have an UNALLOC.  */
9464   uint32_t immr = uimm (aarch64_get_instr (cpu), 21, 16);
9465
9466   if (~size & N)
9467     HALT_UNALLOC;
9468
9469   if (!size && uimm (immr, 5, 5))
9470     HALT_UNALLOC;
9471
9472   imms = uimm (aarch64_get_instr (cpu), 15, 10);
9473   if (!size && uimm (imms, 5, 5))
9474     HALT_UNALLOC;
9475
9476   /* Switch on combined size and op.  */
9477   dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
9478   switch (dispatch)
9479     {
9480     case 0: sbfm32 (cpu, immr, imms); return;
9481     case 1: bfm32 (cpu, immr, imms); return;
9482     case 2: ubfm32 (cpu, immr, imms); return;
9483     case 4: sbfm (cpu, immr, imms); return;
9484     case 5: bfm (cpu, immr, imms); return;
9485     case 6: ubfm (cpu, immr, imms); return;
9486     default: HALT_UNALLOC;
9487     }
9488 }
9489
9490 static void
9491 do_EXTR_32 (sim_cpu *cpu)
9492 {
9493   /* instr[31:21] = 00010011100
9494      instr[20,16] = Rm
9495      instr[15,10] = imms :  0xxxxx for 32 bit
9496      instr[9,5]   = Rn
9497      instr[4,0]   = Rd  */
9498   unsigned rm   = uimm (aarch64_get_instr (cpu), 20, 16);
9499   unsigned imms = uimm (aarch64_get_instr (cpu), 15, 10) & 31;
9500   unsigned rn   = uimm (aarch64_get_instr (cpu),  9,  5);
9501   unsigned rd   = uimm (aarch64_get_instr (cpu),  4,  0);
9502   uint64_t val1;
9503   uint64_t val2;
9504
9505   val1 = aarch64_get_reg_u32 (cpu, rm, NO_SP);
9506   val1 >>= imms;
9507   val2 = aarch64_get_reg_u32 (cpu, rn, NO_SP);
9508   val2 <<= (32 - imms);
9509
9510   aarch64_set_reg_u64 (cpu, rd, NO_SP, val1 | val2);
9511 }
9512
9513 static void
9514 do_EXTR_64 (sim_cpu *cpu)
9515 {
9516   /* instr[31:21] = 10010011100
9517      instr[20,16] = Rm
9518      instr[15,10] = imms
9519      instr[9,5]   = Rn
9520      instr[4,0]   = Rd  */
9521   unsigned rm   = uimm (aarch64_get_instr (cpu), 20, 16);
9522   unsigned imms = uimm (aarch64_get_instr (cpu), 15, 10) & 63;
9523   unsigned rn   = uimm (aarch64_get_instr (cpu),  9,  5);
9524   unsigned rd   = uimm (aarch64_get_instr (cpu),  4,  0);
9525   uint64_t val;
9526
9527   val = aarch64_get_reg_u64 (cpu, rm, NO_SP);
9528   val >>= imms;
9529   val |= (aarch64_get_reg_u64 (cpu, rn, NO_SP) << (64 - imms));
9530
9531   aarch64_set_reg_u64 (cpu, rd, NO_SP, val);
9532 }
9533
9534 static void
9535 dexExtractImmediate (sim_cpu *cpu)
9536 {
9537   /* assert instr[28:23] = 100111
9538      instr[31]    = size : 0 ==> 32 bit, 1 ==> 64 bit
9539      instr[30,29] = op21 : 0 ==> EXTR, 1,2,3 ==> UNALLOC
9540      instr[22]    = N : must be 0 for 32 bit, 1 for 64 bit or UNALLOC
9541      instr[21]    = op0 : must be 0 or UNALLOC
9542      instr[20,16] = Rm
9543      instr[15,10] = imms :  0xxxxx for 32 bit, xxxxxx for 64 bit
9544      instr[9,5]   = Rn
9545      instr[4,0]   = Rd  */
9546
9547   /* 32 bit operations must have N = 0 or else we have an UNALLOC.  */
9548   /* 64 bit operations must have N = 1 or else we have an UNALLOC.  */
9549   uint32_t dispatch;
9550   uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
9551   uint32_t N = uimm (aarch64_get_instr (cpu), 22, 22);
9552   /* 32 bit operations must have imms[5] = 0
9553      or else we have an UNALLOC.  */
9554   uint32_t imms = uimm (aarch64_get_instr (cpu), 15, 10);
9555
9556   if (size ^ N)
9557     HALT_UNALLOC;
9558
9559   if (!size && uimm (imms, 5, 5))
9560     HALT_UNALLOC;
9561
9562   /* Switch on combined size and op.  */
9563   dispatch = uimm (aarch64_get_instr (cpu), 31, 29);
9564
9565   if (dispatch == 0)
9566     do_EXTR_32 (cpu);
9567
9568   else if (dispatch == 4)
9569     do_EXTR_64 (cpu);
9570
9571   else if (dispatch == 1)
9572     HALT_NYI;
9573   else
9574     HALT_UNALLOC;
9575 }
9576
9577 static void
9578 dexDPImm (sim_cpu *cpu)
9579 {
9580   /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
9581      assert  group == GROUP_DPIMM_1000 || grpoup == GROUP_DPIMM_1001
9582      bits [25,23] of a DPImm are the secondary dispatch vector.  */
9583   uint32_t group2 = dispatchDPImm (aarch64_get_instr (cpu));
9584
9585   switch (group2)
9586     {
9587     case DPIMM_PCADR_000:
9588     case DPIMM_PCADR_001:
9589       dexPCRelAddressing (cpu);
9590       return;
9591
9592     case DPIMM_ADDSUB_010:
9593     case DPIMM_ADDSUB_011:
9594       dexAddSubtractImmediate (cpu);
9595       return;
9596
9597     case DPIMM_LOG_100:
9598       dexLogicalImmediate (cpu);
9599       return;
9600
9601     case DPIMM_MOV_101:
9602       dexMoveWideImmediate (cpu);
9603       return;
9604
9605     case DPIMM_BITF_110:
9606       dexBitfieldImmediate (cpu);
9607       return;
9608
9609     case DPIMM_EXTR_111:
9610       dexExtractImmediate (cpu);
9611       return;
9612
9613     default:
9614       /* Should never reach here.  */
9615       HALT_NYI;
9616     }
9617 }
9618
9619 static void
9620 dexLoadUnscaledImmediate (sim_cpu *cpu)
9621 {
9622   /* instr[29,24] == 111_00
9623      instr[21] == 0
9624      instr[11,10] == 00
9625      instr[31,30] = size
9626      instr[26] = V
9627      instr[23,22] = opc
9628      instr[20,12] = simm9
9629      instr[9,5] = rn may be SP.  */
9630   /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);  */
9631   uint32_t V = uimm (aarch64_get_instr (cpu), 26, 26);
9632   uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
9633                         | uimm (aarch64_get_instr (cpu), 23, 22));
9634   int32_t imm = simm32 (aarch64_get_instr (cpu), 20, 12);
9635
9636   if (!V)
9637     {
9638       /* GReg operations.  */
9639       switch (dispatch)
9640         {
9641         case 0:  sturb (cpu, imm); return;
9642         case 1:  ldurb32 (cpu, imm); return;
9643         case 2:  ldursb64 (cpu, imm); return;
9644         case 3:  ldursb32 (cpu, imm); return;
9645         case 4:  sturh (cpu, imm); return;
9646         case 5:  ldurh32 (cpu, imm); return;
9647         case 6:  ldursh64 (cpu, imm); return;
9648         case 7:  ldursh32 (cpu, imm); return;
9649         case 8:  stur32 (cpu, imm); return;
9650         case 9:  ldur32 (cpu, imm); return;
9651         case 10: ldursw (cpu, imm); return;
9652         case 12: stur64 (cpu, imm); return;
9653         case 13: ldur64 (cpu, imm); return;
9654
9655         case 14:
9656           /* PRFUM NYI.  */
9657           HALT_NYI;
9658
9659         default:
9660         case 11:
9661         case 15:
9662           HALT_UNALLOC;
9663         }
9664     }
9665
9666   /* FReg operations.  */
9667   switch (dispatch)
9668     {
9669     case 2:  fsturq (cpu, imm); return;
9670     case 3:  fldurq (cpu, imm); return;
9671     case 8:  fsturs (cpu, imm); return;
9672     case 9:  fldurs (cpu, imm); return;
9673     case 12: fsturd (cpu, imm); return;
9674     case 13: fldurd (cpu, imm); return;
9675
9676     case 0: /* STUR 8 bit FP.  */
9677     case 1: /* LDUR 8 bit FP.  */
9678     case 4: /* STUR 16 bit FP.  */
9679     case 5: /* LDUR 8 bit FP.  */
9680       HALT_NYI;
9681
9682     default:
9683     case 6:
9684     case 7:
9685     case 10:
9686     case 11:
9687     case 14:
9688     case 15:
9689       HALT_UNALLOC;
9690     }
9691 }
9692
9693 /*  N.B. A preliminary note regarding all the ldrs<x>32
9694     instructions
9695
9696    The signed value loaded by these instructions is cast to unsigned
9697    before being assigned to aarch64_get_reg_u64 (cpu, N) i.e. to the
9698    64 bit element of the GReg union. this performs a 32 bit sign extension
9699    (as required) but avoids 64 bit sign extension, thus ensuring that the
9700    top half of the register word is zero. this is what the spec demands
9701    when a 32 bit load occurs.  */
9702
9703 /* 32 bit load sign-extended byte scaled unsigned 12 bit.  */
9704 static void
9705 ldrsb32_abs (sim_cpu *cpu, uint32_t offset)
9706 {
9707   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
9708   unsigned int rt = uimm (aarch64_get_instr (cpu), 4, 0);
9709
9710   /* The target register may not be SP but the source may be
9711      there is no scaling required for a byte load.  */
9712   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset;
9713   aarch64_set_reg_u64 (cpu, rt, NO_SP,
9714                        (int64_t) aarch64_get_mem_s8 (cpu, address));
9715 }
9716
9717 /* 32 bit load sign-extended byte scaled or unscaled zero-
9718    or sign-extended 32-bit register offset.  */
9719 static void
9720 ldrsb32_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9721 {
9722   unsigned int rm = uimm (aarch64_get_instr (cpu), 20, 16);
9723   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
9724   unsigned int rt = uimm (aarch64_get_instr (cpu), 4, 0);
9725
9726   /* rn may reference SP, rm and rt must reference ZR.  */
9727
9728   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9729   int64_t displacement = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9730                                  extension);
9731
9732   /* There is no scaling required for a byte load.  */
9733   aarch64_set_reg_u64
9734     (cpu, rt, NO_SP, (int64_t) aarch64_get_mem_s8 (cpu, address
9735                                                    + displacement));
9736 }
9737
9738 /* 32 bit load sign-extended byte unscaled signed 9 bit with
9739    pre- or post-writeback.  */
9740 static void
9741 ldrsb32_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9742 {
9743   uint64_t address;
9744   unsigned int rn = uimm (aarch64_get_instr (cpu), 9, 5);
9745   unsigned int rt = uimm (aarch64_get_instr (cpu), 4, 0);
9746
9747   if (rn == rt && wb != NoWriteBack)
9748     HALT_UNALLOC;
9749
9750   address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9751
9752   if (wb == Pre)
9753       address += offset;
9754
9755   aarch64_set_reg_u64 (cpu, rt, NO_SP,
9756                        (int64_t) aarch64_get_mem_s8 (cpu, address));
9757
9758   if (wb == Post)
9759     address += offset;
9760
9761   if (wb != NoWriteBack)
9762     aarch64_set_reg_u64 (cpu, rn, NO_SP, address);
9763 }
9764
9765 /* 8 bit store scaled.  */
9766 static void
9767 fstrb_abs (sim_cpu *cpu, uint32_t offset)
9768 {
9769   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9770   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9771
9772   aarch64_set_mem_u8 (cpu,
9773                       aarch64_get_reg_u64 (cpu, rn, SP_OK) + offset,
9774                       aarch64_get_vec_u8 (cpu, st, 0));
9775 }
9776
9777 /* 8 bit store scaled or unscaled zero- or
9778    sign-extended 8-bit register offset.  */
9779 static void
9780 fstrb_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9781 {
9782   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9783   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9784   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9785
9786   uint64_t  address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9787   int64_t   extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9788                                extension);
9789   uint64_t  displacement = OPT_SCALE (extended, 32, scaling);
9790
9791   aarch64_set_mem_u8
9792     (cpu, address + displacement, aarch64_get_vec_u8 (cpu, st, 0));
9793 }
9794
9795 /* 16 bit store scaled.  */
9796 static void
9797 fstrh_abs (sim_cpu *cpu, uint32_t offset)
9798 {
9799   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9800   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9801
9802   aarch64_set_mem_u16
9803     (cpu,
9804      aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 16),
9805      aarch64_get_vec_u16 (cpu, st, 0));
9806 }
9807
9808 /* 16 bit store scaled or unscaled zero-
9809    or sign-extended 16-bit register offset.  */
9810 static void
9811 fstrh_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9812 {
9813   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9814   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9815   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9816
9817   uint64_t  address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9818   int64_t   extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9819                                extension);
9820   uint64_t  displacement = OPT_SCALE (extended, 32, scaling);
9821
9822   aarch64_set_mem_u16
9823     (cpu, address + displacement, aarch64_get_vec_u16 (cpu, st, 0));
9824 }
9825
9826 /* 32 bit store scaled unsigned 12 bit.  */
9827 static void
9828 fstrs_abs (sim_cpu *cpu, uint32_t offset)
9829 {
9830   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9831   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9832
9833   aarch64_set_mem_u32
9834     (cpu,
9835      aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 32),
9836      aarch64_get_vec_u32 (cpu, st, 0));
9837 }
9838
9839 /* 32 bit store unscaled signed 9 bit with pre- or post-writeback.  */
9840 static void
9841 fstrs_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9842 {
9843   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9844   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9845
9846   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9847
9848   if (wb != Post)
9849     address += offset;
9850
9851   aarch64_set_mem_u32 (cpu, address, aarch64_get_vec_u32 (cpu, st, 0));
9852
9853   if (wb == Post)
9854     address += offset;
9855
9856   if (wb != NoWriteBack)
9857     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
9858 }
9859
9860 /* 32 bit store scaled or unscaled zero-
9861    or sign-extended 32-bit register offset.  */
9862 static void
9863 fstrs_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9864 {
9865   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9866   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9867   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9868
9869   uint64_t  address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9870   int64_t   extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9871                                extension);
9872   uint64_t  displacement = OPT_SCALE (extended, 32, scaling);
9873
9874   aarch64_set_mem_u32
9875     (cpu, address + displacement, aarch64_get_vec_u32 (cpu, st, 0));
9876 }
9877
9878 /* 64 bit store scaled unsigned 12 bit.  */
9879 static void
9880 fstrd_abs (sim_cpu *cpu, uint32_t offset)
9881 {
9882   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9883   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9884
9885   aarch64_set_mem_u64
9886     (cpu,
9887      aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 64),
9888      aarch64_get_vec_u64 (cpu, st, 0));
9889 }
9890
9891 /* 64 bit store unscaled signed 9 bit with pre- or post-writeback.  */
9892 static void
9893 fstrd_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9894 {
9895   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9896   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9897
9898   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9899
9900   if (wb != Post)
9901     address += offset;
9902
9903   aarch64_set_mem_u64 (cpu, address, aarch64_get_vec_u64 (cpu, st, 0));
9904
9905   if (wb == Post)
9906     address += offset;
9907
9908   if (wb != NoWriteBack)
9909     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
9910 }
9911
9912 /* 64 bit store scaled or unscaled zero-
9913    or sign-extended 32-bit register offset.  */
9914 static void
9915 fstrd_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9916 {
9917   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9918   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9919   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9920
9921   uint64_t  address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9922   int64_t   extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9923                                extension);
9924   uint64_t  displacement = OPT_SCALE (extended, 64, scaling);
9925
9926   aarch64_set_mem_u64
9927     (cpu, address + displacement, aarch64_get_vec_u64 (cpu, st, 0));
9928 }
9929
9930 /* 128 bit store scaled unsigned 12 bit.  */
9931 static void
9932 fstrq_abs (sim_cpu *cpu, uint32_t offset)
9933 {
9934   FRegister a;
9935   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9936   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9937   uint64_t addr;
9938
9939   aarch64_get_FP_long_double (cpu, st, & a);
9940
9941   addr = aarch64_get_reg_u64 (cpu, rn, SP_OK) + SCALE (offset, 128);
9942   aarch64_set_mem_long_double (cpu, addr, a);
9943 }
9944
9945 /* 128 bit store unscaled signed 9 bit with pre- or post-writeback.  */
9946 static void
9947 fstrq_wb (sim_cpu *cpu, int32_t offset, WriteBack wb)
9948 {
9949   FRegister a;
9950   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9951   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9952   uint64_t address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9953
9954   if (wb != Post)
9955     address += offset;
9956
9957   aarch64_get_FP_long_double (cpu, st, & a);
9958   aarch64_set_mem_long_double (cpu, address, a);
9959
9960   if (wb == Post)
9961     address += offset;
9962
9963   if (wb != NoWriteBack)
9964     aarch64_set_reg_u64 (cpu, rn, SP_OK, address);
9965 }
9966
9967 /* 128 bit store scaled or unscaled zero-
9968    or sign-extended 32-bit register offset.  */
9969 static void
9970 fstrq_scale_ext (sim_cpu *cpu, Scaling scaling, Extension extension)
9971 {
9972   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
9973   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
9974   unsigned st = uimm (aarch64_get_instr (cpu), 4, 0);
9975
9976   uint64_t  address = aarch64_get_reg_u64 (cpu, rn, SP_OK);
9977   int64_t   extended = extend (aarch64_get_reg_u32 (cpu, rm, NO_SP),
9978                                extension);
9979   uint64_t  displacement = OPT_SCALE (extended, 128, scaling);
9980
9981   FRegister a;
9982
9983   aarch64_get_FP_long_double (cpu, st, & a);
9984   aarch64_set_mem_long_double (cpu, address + displacement, a);
9985 }
9986
9987 static void
9988 dexLoadImmediatePrePost (sim_cpu *cpu)
9989 {
9990   /* instr[29,24] == 111_00
9991      instr[21] == 0
9992      instr[11,10] == 00
9993      instr[31,30] = size
9994      instr[26] = V
9995      instr[23,22] = opc
9996      instr[20,12] = simm9
9997      instr[11] = wb : 0 ==> Post, 1 ==> Pre
9998      instr[9,5] = rn may be SP.  */
9999   /* unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0); */
10000   uint32_t V = uimm (aarch64_get_instr (cpu), 26, 26);
10001   uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
10002                        | uimm (aarch64_get_instr (cpu), 23, 22));
10003   int32_t imm = simm32 (aarch64_get_instr (cpu), 20, 12);
10004   WriteBack wb = writeback (aarch64_get_instr (cpu), 11);
10005
10006   if (!V)
10007     {
10008       /* GReg operations.  */
10009       switch (dispatch)
10010         {
10011         case 0:  strb_wb (cpu, imm, wb); return;
10012         case 1:  ldrb32_wb (cpu, imm, wb); return;
10013         case 2:  ldrsb_wb (cpu, imm, wb); return;
10014         case 3:  ldrsb32_wb (cpu, imm, wb); return;
10015         case 4:  strh_wb (cpu, imm, wb); return;
10016         case 5:  ldrh32_wb (cpu, imm, wb); return;
10017         case 6:  ldrsh64_wb (cpu, imm, wb); return;
10018         case 7:  ldrsh32_wb (cpu, imm, wb); return;
10019         case 8:  str32_wb (cpu, imm, wb); return;
10020         case 9:  ldr32_wb (cpu, imm, wb); return;
10021         case 10: ldrsw_wb (cpu, imm, wb); return;
10022         case 12: str_wb (cpu, imm, wb); return;
10023         case 13: ldr_wb (cpu, imm, wb); return;
10024
10025         default:
10026         case 11:
10027         case 14:
10028         case 15:
10029           HALT_UNALLOC;
10030         }
10031     }
10032
10033   /* FReg operations.  */
10034   switch (dispatch)
10035     {
10036     case 2:  fstrq_wb (cpu, imm, wb); return;
10037     case 3:  fldrq_wb (cpu, imm, wb); return;
10038     case 8:  fstrs_wb (cpu, imm, wb); return;
10039     case 9:  fldrs_wb (cpu, imm, wb); return;
10040     case 12: fstrd_wb (cpu, imm, wb); return;
10041     case 13: fldrd_wb (cpu, imm, wb); return;
10042
10043     case 0:       /* STUR 8 bit FP.  */
10044     case 1:       /* LDUR 8 bit FP.  */
10045     case 4:       /* STUR 16 bit FP.  */
10046     case 5:       /* LDUR 8 bit FP.  */
10047       HALT_NYI;
10048
10049     default:
10050     case 6:
10051     case 7:
10052     case 10:
10053     case 11:
10054     case 14:
10055     case 15:
10056       HALT_UNALLOC;
10057     }
10058 }
10059
10060 static void
10061 dexLoadRegisterOffset (sim_cpu *cpu)
10062 {
10063   /* instr[31,30] = size
10064      instr[29,27] = 111
10065      instr[26]    = V
10066      instr[25,24] = 00
10067      instr[23,22] = opc
10068      instr[21]    = 1
10069      instr[20,16] = rm
10070      instr[15,13] = option : 010 ==> UXTW, 011 ==> UXTX/LSL,
10071                              110 ==> SXTW, 111 ==> SXTX,
10072                              ow ==> RESERVED
10073      instr[12]    = scaled
10074      instr[11,10] = 10
10075      instr[9,5]   = rn
10076      instr[4,0]   = rt.  */
10077
10078   uint32_t V = uimm (aarch64_get_instr (cpu), 26,26);
10079   uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
10080                        | uimm (aarch64_get_instr (cpu), 23, 22));
10081   Scaling scale = scaling (aarch64_get_instr (cpu), 12);
10082   Extension extensionType = extension (aarch64_get_instr (cpu), 13);
10083
10084   /* Check for illegal extension types.  */
10085   if (uimm (extensionType, 1, 1) == 0)
10086     HALT_UNALLOC;
10087
10088   if (extensionType == UXTX || extensionType == SXTX)
10089     extensionType = NoExtension;
10090
10091   if (!V)
10092     {
10093       /* GReg operations.  */
10094       switch (dispatch)
10095         {
10096         case 0:  strb_scale_ext (cpu, scale, extensionType); return;
10097         case 1:  ldrb32_scale_ext (cpu, scale, extensionType); return;
10098         case 2:  ldrsb_scale_ext (cpu, scale, extensionType); return;
10099         case 3:  ldrsb32_scale_ext (cpu, scale, extensionType); return;
10100         case 4:  strh_scale_ext (cpu, scale, extensionType); return;
10101         case 5:  ldrh32_scale_ext (cpu, scale, extensionType); return;
10102         case 6:  ldrsh_scale_ext (cpu, scale, extensionType); return;
10103         case 7:  ldrsh32_scale_ext (cpu, scale, extensionType); return;
10104         case 8:  str32_scale_ext (cpu, scale, extensionType); return;
10105         case 9:  ldr32_scale_ext (cpu, scale, extensionType); return;
10106         case 10: ldrsw_scale_ext (cpu, scale, extensionType); return;
10107         case 12: str_scale_ext (cpu, scale, extensionType); return;
10108         case 13: ldr_scale_ext (cpu, scale, extensionType); return;
10109         case 14: prfm_scale_ext (cpu, scale, extensionType); return;
10110
10111         default:
10112         case 11:
10113         case 15:
10114           HALT_UNALLOC;
10115         }
10116     }
10117
10118   /* FReg operations.  */
10119   switch (dispatch)
10120     {
10121     case 1: /* LDUR 8 bit FP.  */
10122       HALT_NYI;
10123     case 3:  fldrq_scale_ext (cpu, scale, extensionType); return;
10124     case 5: /* LDUR 8 bit FP.  */
10125       HALT_NYI;
10126     case 9:  fldrs_scale_ext (cpu, scale, extensionType); return;
10127     case 13: fldrd_scale_ext (cpu, scale, extensionType); return;
10128
10129     case 0:  fstrb_scale_ext (cpu, scale, extensionType); return;
10130     case 2:  fstrq_scale_ext (cpu, scale, extensionType); return;
10131     case 4:  fstrh_scale_ext (cpu, scale, extensionType); return;
10132     case 8:  fstrs_scale_ext (cpu, scale, extensionType); return;
10133     case 12: fstrd_scale_ext (cpu, scale, extensionType); return;
10134
10135     default:
10136     case 6:
10137     case 7:
10138     case 10:
10139     case 11:
10140     case 14:
10141     case 15:
10142       HALT_UNALLOC;
10143     }
10144 }
10145
10146 static void
10147 dexLoadUnsignedImmediate (sim_cpu *cpu)
10148 {
10149   /* instr[29,24] == 111_01
10150      instr[31,30] = size
10151      instr[26]    = V
10152      instr[23,22] = opc
10153      instr[21,10] = uimm12 : unsigned immediate offset
10154      instr[9,5]   = rn may be SP.
10155      instr[4,0]   = rt.  */
10156   
10157   uint32_t V = uimm (aarch64_get_instr (cpu), 26,26);
10158   uint32_t dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 30) << 2)
10159                        | uimm (aarch64_get_instr (cpu), 23, 22));
10160   uint32_t imm = uimm (aarch64_get_instr (cpu), 21, 10);
10161
10162   if (!V)
10163     {
10164       /* GReg operations.  */
10165       switch (dispatch)
10166         {
10167         case 0:  strb_abs (cpu, imm); return;
10168         case 1:  ldrb32_abs (cpu, imm); return;
10169         case 2:  ldrsb_abs (cpu, imm); return;
10170         case 3:  ldrsb32_abs (cpu, imm); return;
10171         case 4:  strh_abs (cpu, imm); return;
10172         case 5:  ldrh32_abs (cpu, imm); return;
10173         case 6:  ldrsh_abs (cpu, imm); return;
10174         case 7:  ldrsh32_abs (cpu, imm); return;
10175         case 8:  str32_abs (cpu, imm); return;
10176         case 9:  ldr32_abs (cpu, imm); return;
10177         case 10: ldrsw_abs (cpu, imm); return;
10178         case 12: str_abs (cpu, imm); return;
10179         case 13: ldr_abs (cpu, imm); return;
10180         case 14: prfm_abs (cpu, imm); return;
10181
10182         default:
10183         case 11:
10184         case 15:
10185           HALT_UNALLOC;
10186         }
10187     }
10188
10189   /* FReg operations.  */
10190   switch (dispatch)
10191     {
10192     case 0:  fstrb_abs (cpu, imm); return;
10193     case 4:  fstrh_abs (cpu, imm); return;
10194     case 8:  fstrs_abs (cpu, imm); return;
10195     case 12: fstrd_abs (cpu, imm); return;
10196     case 2:  fstrq_abs (cpu, imm); return;
10197
10198     case 1:  fldrb_abs (cpu, imm); return;
10199     case 5:  fldrh_abs (cpu, imm); return;
10200     case 9:  fldrs_abs (cpu, imm); return;
10201     case 13: fldrd_abs (cpu, imm); return;
10202     case 3:  fldrq_abs (cpu, imm); return;
10203
10204     default:
10205     case 6:
10206     case 7:
10207     case 10:
10208     case 11:
10209     case 14:
10210     case 15:
10211       HALT_UNALLOC;
10212     }
10213 }
10214
10215 static void
10216 dexLoadExclusive (sim_cpu *cpu)
10217 {
10218   /* assert instr[29:24] = 001000;
10219      instr[31,30] = size
10220      instr[23] = 0 if exclusive
10221      instr[22] = L : 1 if load, 0 if store
10222      instr[21] = 1 if pair
10223      instr[20,16] = Rs
10224      instr[15] = o0 : 1 if ordered
10225      instr[14,10] = Rt2
10226      instr[9,5] = Rn
10227      instr[4.0] = Rt.  */
10228
10229   switch (uimm (aarch64_get_instr (cpu), 22, 21))
10230     {
10231     case 2:   ldxr (cpu); return;
10232     case 0:   stxr (cpu); return;
10233     default:  HALT_NYI;
10234     }
10235 }
10236
10237 static void
10238 dexLoadOther (sim_cpu *cpu)
10239 {
10240   uint32_t dispatch;
10241
10242   /* instr[29,25] = 111_0
10243      instr[24] == 0 ==> dispatch, 1 ==> ldst reg unsigned immediate
10244      instr[21:11,10] is the secondary dispatch.  */
10245   if (uimm (aarch64_get_instr (cpu), 24, 24))
10246     {
10247       dexLoadUnsignedImmediate (cpu);
10248       return;
10249     }
10250
10251   dispatch = ( (uimm (aarch64_get_instr (cpu), 21, 21) << 2)
10252               | uimm (aarch64_get_instr (cpu), 11, 10));
10253   switch (dispatch)
10254     {
10255     case 0: dexLoadUnscaledImmediate (cpu); return;
10256     case 1: dexLoadImmediatePrePost (cpu); return;
10257     case 3: dexLoadImmediatePrePost (cpu); return;
10258     case 6: dexLoadRegisterOffset (cpu); return;
10259
10260     default:
10261     case 2:
10262     case 4:
10263     case 5:
10264     case 7:
10265       HALT_NYI;
10266     }
10267 }
10268
10269 static void
10270 store_pair_u32 (sim_cpu *cpu, int32_t offset, WriteBack wb)
10271 {
10272   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10273   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10274   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10275   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10276
10277   if ((rn == rd || rm == rd) && wb != NoWriteBack)
10278     HALT_UNALLOC; /* ??? */
10279
10280   offset <<= 2;
10281
10282   if (wb != Post)
10283     address += offset;
10284
10285   aarch64_set_mem_u32 (cpu, address,
10286                        aarch64_get_reg_u32 (cpu, rm, NO_SP));
10287   aarch64_set_mem_u32 (cpu, address + 4,
10288                        aarch64_get_reg_u32 (cpu, rn, NO_SP));
10289
10290   if (wb == Post)
10291     address += offset;
10292
10293   if (wb != NoWriteBack)
10294     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10295 }
10296
10297 static void
10298 store_pair_u64 (sim_cpu *cpu, int32_t offset, WriteBack wb)
10299 {
10300   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10301   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10302   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10303   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10304
10305   if ((rn == rd || rm == rd) && wb != NoWriteBack)
10306     HALT_UNALLOC; /* ??? */
10307
10308   offset <<= 3;
10309
10310   if (wb != Post)
10311     address += offset;
10312
10313   aarch64_set_mem_u64 (cpu, address,
10314                        aarch64_get_reg_u64 (cpu, rm, SP_OK));
10315   aarch64_set_mem_u64 (cpu, address + 8,
10316                        aarch64_get_reg_u64 (cpu, rn, SP_OK));
10317
10318   if (wb == Post)
10319     address += offset;
10320
10321   if (wb != NoWriteBack)
10322     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10323 }
10324
10325 static void
10326 load_pair_u32 (sim_cpu *cpu, int32_t offset, WriteBack wb)
10327 {
10328   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10329   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10330   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10331   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10332
10333   /* treat this as unalloc to make sure we don't do it.  */
10334   if (rn == rm)
10335     HALT_UNALLOC;
10336
10337   offset <<= 2;
10338
10339   if (wb != Post)
10340     address += offset;
10341
10342   aarch64_set_reg_u64 (cpu, rm, SP_OK, aarch64_get_mem_u32 (cpu, address));
10343   aarch64_set_reg_u64 (cpu, rn, SP_OK, aarch64_get_mem_u32 (cpu, address + 4));
10344
10345   if (wb == Post)
10346     address += offset;
10347
10348   if (wb != NoWriteBack)
10349     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10350 }
10351
10352 static void
10353 load_pair_s32 (sim_cpu *cpu, int32_t offset, WriteBack wb)
10354 {
10355   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10356   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10357   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10358   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10359
10360   /* Treat this as unalloc to make sure we don't do it.  */
10361   if (rn == rm)
10362     HALT_UNALLOC;
10363
10364   offset <<= 2;
10365
10366   if (wb != Post)
10367     address += offset;
10368
10369   aarch64_set_reg_s64 (cpu, rm, SP_OK, aarch64_get_mem_s32 (cpu, address));
10370   aarch64_set_reg_s64 (cpu, rn, SP_OK, aarch64_get_mem_s32 (cpu, address + 4));
10371
10372   if (wb == Post)
10373     address += offset;
10374
10375   if (wb != NoWriteBack)
10376     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10377 }
10378
10379 static void
10380 load_pair_u64 (sim_cpu *cpu, int32_t offset, WriteBack wb)
10381 {
10382   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10383   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10384   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10385   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10386
10387   /* Treat this as unalloc to make sure we don't do it.  */
10388   if (rn == rm)
10389     HALT_UNALLOC;
10390
10391   offset <<= 3;
10392
10393   if (wb != Post)
10394     address += offset;
10395
10396   aarch64_set_reg_u64 (cpu, rm, SP_OK, aarch64_get_mem_u64 (cpu, address));
10397   aarch64_set_reg_u64 (cpu, rn, SP_OK, aarch64_get_mem_u64 (cpu, address + 8));
10398
10399   if (wb == Post)
10400     address += offset;
10401
10402   if (wb != NoWriteBack)
10403     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10404 }
10405
10406 static void
10407 dex_load_store_pair_gr (sim_cpu *cpu)
10408 {
10409   /* instr[31,30] = size (10=> 64-bit, 01=> signed 32-bit, 00=> 32-bit)
10410      instr[29,25] = instruction encoding: 101_0
10411      instr[26]    = V : 1 if fp 0 if gp
10412      instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
10413      instr[22]    = load/store (1=> load)
10414      instr[21,15] = signed, scaled, offset
10415      instr[14,10] = Rn
10416      instr[ 9, 5] = Rd
10417      instr[ 4, 0] = Rm.  */
10418
10419   uint32_t dispatch = ((uimm (aarch64_get_instr (cpu), 31, 30) << 3)
10420                         | uimm (aarch64_get_instr (cpu), 24, 22));
10421   int32_t offset = simm32 (aarch64_get_instr (cpu), 21, 15);
10422
10423   switch (dispatch)
10424     {
10425     case 2: store_pair_u32 (cpu, offset, Post); return;
10426     case 3: load_pair_u32  (cpu, offset, Post); return;
10427     case 4: store_pair_u32 (cpu, offset, NoWriteBack); return;
10428     case 5: load_pair_u32  (cpu, offset, NoWriteBack); return;
10429     case 6: store_pair_u32 (cpu, offset, Pre); return;
10430     case 7: load_pair_u32  (cpu, offset, Pre); return;
10431
10432     case 11: load_pair_s32  (cpu, offset, Post); return;
10433     case 13: load_pair_s32  (cpu, offset, NoWriteBack); return;
10434     case 15: load_pair_s32  (cpu, offset, Pre); return;
10435
10436     case 18: store_pair_u64 (cpu, offset, Post); return;
10437     case 19: load_pair_u64  (cpu, offset, Post); return;
10438     case 20: store_pair_u64 (cpu, offset, NoWriteBack); return;
10439     case 21: load_pair_u64  (cpu, offset, NoWriteBack); return;
10440     case 22: store_pair_u64 (cpu, offset, Pre); return;
10441     case 23: load_pair_u64  (cpu, offset, Pre); return;
10442
10443     default:
10444       HALT_UNALLOC;
10445     }
10446 }
10447
10448 static void
10449 store_pair_float (sim_cpu *cpu, int32_t offset, WriteBack wb)
10450 {
10451   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10452   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10453   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10454   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10455
10456   offset <<= 2;
10457
10458   if (wb != Post)
10459     address += offset;
10460
10461   aarch64_set_mem_u32 (cpu, address,     aarch64_get_vec_u32 (cpu, rm, 0));
10462   aarch64_set_mem_u32 (cpu, address + 4, aarch64_get_vec_u32 (cpu, rn, 0));
10463
10464   if (wb == Post)
10465     address += offset;
10466
10467   if (wb != NoWriteBack)
10468     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10469 }
10470
10471 static void
10472 store_pair_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10473 {
10474   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10475   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10476   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10477   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10478
10479   offset <<= 3;
10480
10481   if (wb != Post)
10482     address += offset;
10483
10484   aarch64_set_mem_u64 (cpu, address,     aarch64_get_vec_u64 (cpu, rm, 0));
10485   aarch64_set_mem_u64 (cpu, address + 8, aarch64_get_vec_u64 (cpu, rn, 0));
10486
10487   if (wb == Post)
10488     address += offset;
10489
10490   if (wb != NoWriteBack)
10491     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10492 }
10493
10494 static void
10495 store_pair_long_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10496 {
10497   FRegister a;
10498   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10499   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10500   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10501   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10502
10503   offset <<= 4;
10504
10505   if (wb != Post)
10506     address += offset;
10507
10508   aarch64_get_FP_long_double (cpu, rm, & a);
10509   aarch64_set_mem_long_double (cpu, address, a);
10510   aarch64_get_FP_long_double (cpu, rn, & a);
10511   aarch64_set_mem_long_double (cpu, address + 16, a);
10512
10513   if (wb == Post)
10514     address += offset;
10515
10516   if (wb != NoWriteBack)
10517     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10518 }
10519
10520 static void
10521 load_pair_float (sim_cpu *cpu, int32_t offset, WriteBack wb)
10522 {
10523   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10524   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10525   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10526   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10527
10528   if (rm == rn)
10529     HALT_UNALLOC;
10530
10531   offset <<= 2;
10532
10533   if (wb != Post)
10534     address += offset;
10535
10536   aarch64_set_vec_u32 (cpu, rm, 0, aarch64_get_mem_u32 (cpu, address));
10537   aarch64_set_vec_u32 (cpu, rn, 0, aarch64_get_mem_u32 (cpu, address + 4));
10538
10539   if (wb == Post)
10540     address += offset;
10541
10542   if (wb != NoWriteBack)
10543     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10544 }
10545
10546 static void
10547 load_pair_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10548 {
10549   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10550   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10551   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10552   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10553
10554   if (rm == rn)
10555     HALT_UNALLOC;
10556
10557   offset <<= 3;
10558
10559   if (wb != Post)
10560     address += offset;
10561
10562   aarch64_set_vec_u64 (cpu, rm, 0, aarch64_get_mem_u64 (cpu, address));
10563   aarch64_set_vec_u64 (cpu, rn, 0, aarch64_get_mem_u64 (cpu, address + 8));
10564
10565   if (wb == Post)
10566     address += offset;
10567
10568   if (wb != NoWriteBack)
10569     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10570 }
10571
10572 static void
10573 load_pair_long_double (sim_cpu *cpu, int32_t offset, WriteBack wb)
10574 {
10575   FRegister a;
10576   unsigned rn = uimm (aarch64_get_instr (cpu), 14, 10);
10577   unsigned rd = uimm (aarch64_get_instr (cpu), 9, 5);
10578   unsigned rm = uimm (aarch64_get_instr (cpu), 4, 0);
10579   uint64_t address = aarch64_get_reg_u64 (cpu, rd, SP_OK);
10580
10581   if (rm == rn)
10582     HALT_UNALLOC;
10583
10584   offset <<= 4;
10585
10586   if (wb != Post)
10587     address += offset;
10588
10589   aarch64_get_mem_long_double (cpu, address, & a);
10590   aarch64_set_FP_long_double (cpu, rm, a);
10591   aarch64_get_mem_long_double (cpu, address + 16, & a);
10592   aarch64_set_FP_long_double (cpu, rn, a);
10593
10594   if (wb == Post)
10595     address += offset;
10596
10597   if (wb != NoWriteBack)
10598     aarch64_set_reg_u64 (cpu, rd, SP_OK, address);
10599 }
10600
10601 static void
10602 dex_load_store_pair_fp (sim_cpu *cpu)
10603 {
10604   /* instr[31,30] = size (10=> 128-bit, 01=> 64-bit, 00=> 32-bit)
10605      instr[29,25] = instruction encoding
10606      instr[24,23] = addressing mode (10=> offset, 01=> post, 11=> pre)
10607      instr[22]    = load/store (1=> load)
10608      instr[21,15] = signed, scaled, offset
10609      instr[14,10] = Rn
10610      instr[ 9, 5] = Rd
10611      instr[ 4, 0] = Rm  */
10612
10613   uint32_t dispatch = ((uimm (aarch64_get_instr (cpu), 31, 30) << 3)
10614                         | uimm (aarch64_get_instr (cpu), 24, 22));
10615   int32_t offset = simm32 (aarch64_get_instr (cpu), 21, 15);
10616
10617   switch (dispatch)
10618     {
10619     case 2: store_pair_float (cpu, offset, Post); return;
10620     case 3: load_pair_float  (cpu, offset, Post); return;
10621     case 4: store_pair_float (cpu, offset, NoWriteBack); return;
10622     case 5: load_pair_float  (cpu, offset, NoWriteBack); return;
10623     case 6: store_pair_float (cpu, offset, Pre); return;
10624     case 7: load_pair_float  (cpu, offset, Pre); return;
10625
10626     case 10: store_pair_double (cpu, offset, Post); return;
10627     case 11: load_pair_double  (cpu, offset, Post); return;
10628     case 12: store_pair_double (cpu, offset, NoWriteBack); return;
10629     case 13: load_pair_double  (cpu, offset, NoWriteBack); return;
10630     case 14: store_pair_double (cpu, offset, Pre); return;
10631     case 15: load_pair_double  (cpu, offset, Pre); return;
10632
10633     case 18: store_pair_long_double (cpu, offset, Post); return;
10634     case 19: load_pair_long_double  (cpu, offset, Post); return;
10635     case 20: store_pair_long_double (cpu, offset, NoWriteBack); return;
10636     case 21: load_pair_long_double  (cpu, offset, NoWriteBack); return;
10637     case 22: store_pair_long_double (cpu, offset, Pre); return;
10638     case 23: load_pair_long_double  (cpu, offset, Pre); return;
10639
10640     default:
10641       HALT_UNALLOC;
10642     }
10643 }
10644
10645 static inline unsigned
10646 vec_reg (unsigned v, unsigned o)
10647 {
10648   return (v + o) & 0x3F;
10649 }
10650
10651 /* Load multiple N-element structures to N consecutive registers.  */
10652 static void
10653 vec_load (sim_cpu *cpu, uint64_t address, unsigned N)
10654 {
10655   int      all  = uimm (aarch64_get_instr (cpu), 30, 30);
10656   unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10657   unsigned vd   = uimm (aarch64_get_instr (cpu), 4, 0);
10658   unsigned i;
10659
10660   switch (size)
10661     {
10662     case 0: /* 8-bit operations.  */
10663       if (all)
10664         for (i = 0; i < (16 * N); i++)
10665           aarch64_set_vec_u8 (cpu, vec_reg (vd, i >> 4), i & 15,
10666                               aarch64_get_mem_u8 (cpu, address + i));
10667       else
10668         for (i = 0; i < (8 * N); i++)
10669           aarch64_set_vec_u8 (cpu, vec_reg (vd, i >> 3), i & 7,
10670                               aarch64_get_mem_u8 (cpu, address + i));
10671       return;
10672
10673     case 1: /* 16-bit operations.  */
10674       if (all)
10675         for (i = 0; i < (8 * N); i++)
10676           aarch64_set_vec_u16 (cpu, vec_reg (vd, i >> 3), i & 7,
10677                                aarch64_get_mem_u16 (cpu, address + i * 2));
10678       else
10679         for (i = 0; i < (4 * N); i++)
10680           aarch64_set_vec_u16 (cpu, vec_reg (vd, i >> 2), i & 3,
10681                                aarch64_get_mem_u16 (cpu, address + i * 2));
10682       return;
10683
10684     case 2: /* 32-bit operations.  */
10685       if (all)
10686         for (i = 0; i < (4 * N); i++)
10687           aarch64_set_vec_u32 (cpu, vec_reg (vd, i >> 2), i & 3,
10688                                aarch64_get_mem_u32 (cpu, address + i * 4));
10689       else
10690         for (i = 0; i < (2 * N); i++)
10691           aarch64_set_vec_u32 (cpu, vec_reg (vd, i >> 1), i & 1,
10692                                aarch64_get_mem_u32 (cpu, address + i * 4));
10693       return;
10694
10695     case 3: /* 64-bit operations.  */
10696       if (all)
10697         for (i = 0; i < (2 * N); i++)
10698           aarch64_set_vec_u64 (cpu, vec_reg (vd, i >> 1), i & 1,
10699                                aarch64_get_mem_u64 (cpu, address + i * 8));
10700       else
10701         for (i = 0; i < N; i++)
10702           aarch64_set_vec_u64 (cpu, vec_reg (vd, i), 0,
10703                                aarch64_get_mem_u64 (cpu, address + i * 8));
10704       return;
10705     }
10706 }
10707
10708 /* LD4: load multiple 4-element to four consecutive registers.  */
10709 static void
10710 LD4 (sim_cpu *cpu, uint64_t address)
10711 {
10712   vec_load (cpu, address, 4);
10713 }
10714
10715 /* LD3: load multiple 3-element structures to three consecutive registers.  */
10716 static void
10717 LD3 (sim_cpu *cpu, uint64_t address)
10718 {
10719   vec_load (cpu, address, 3);
10720 }
10721
10722 /* LD2: load multiple 2-element structures to two consecutive registers.  */
10723 static void
10724 LD2 (sim_cpu *cpu, uint64_t address)
10725 {
10726   vec_load (cpu, address, 2);
10727 }
10728
10729 /* Load multiple 1-element structures into one register.  */
10730 static void
10731 LD1_1 (sim_cpu *cpu, uint64_t address)
10732 {
10733   int      all  = uimm (aarch64_get_instr (cpu), 30, 30);
10734   unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10735   unsigned vd   = uimm (aarch64_get_instr (cpu), 4, 0);
10736   unsigned i;
10737
10738   switch (size)
10739     {
10740     case 0:
10741       /* LD1 {Vd.16b}, addr, #16 */
10742       /* LD1 {Vd.8b}, addr, #8 */
10743       for (i = 0; i < (all ? 16 : 8); i++)
10744         aarch64_set_vec_u8 (cpu, vd, i,
10745                             aarch64_get_mem_u8 (cpu, address + i));
10746       return;
10747
10748     case 1:
10749       /* LD1 {Vd.8h}, addr, #16 */
10750       /* LD1 {Vd.4h}, addr, #8 */
10751       for (i = 0; i < (all ? 8 : 4); i++)
10752         aarch64_set_vec_u16 (cpu, vd, i,
10753                              aarch64_get_mem_u16 (cpu, address + i * 2));
10754       return;
10755
10756     case 2:
10757       /* LD1 {Vd.4s}, addr, #16 */
10758       /* LD1 {Vd.2s}, addr, #8 */
10759       for (i = 0; i < (all ? 4 : 2); i++)
10760         aarch64_set_vec_u32 (cpu, vd, i,
10761                              aarch64_get_mem_u32 (cpu, address + i * 4));
10762       return;
10763
10764     case 3:
10765       /* LD1 {Vd.2d}, addr, #16 */
10766       /* LD1 {Vd.1d}, addr, #8 */
10767       for (i = 0; i < (all ? 2 : 1); i++)
10768         aarch64_set_vec_u64 (cpu, vd, i,
10769                              aarch64_get_mem_u64 (cpu, address + i * 8));
10770       return;
10771     }
10772 }
10773
10774 /* Load multiple 1-element structures into two registers.  */
10775 static void
10776 LD1_2 (sim_cpu *cpu, uint64_t address)
10777 {
10778   /* FIXME: This algorithm is *exactly* the same as the LD2 version.
10779      So why have two different instructions ?  There must be something
10780      wrong somewhere.  */
10781   vec_load (cpu, address, 2);
10782 }
10783
10784 /* Load multiple 1-element structures into three registers.  */
10785 static void
10786 LD1_3 (sim_cpu *cpu, uint64_t address)
10787 {
10788   /* FIXME: This algorithm is *exactly* the same as the LD3 version.
10789      So why have two different instructions ?  There must be something
10790      wrong somewhere.  */
10791   vec_load (cpu, address, 3);
10792 }
10793
10794 /* Load multiple 1-element structures into four registers.  */
10795 static void
10796 LD1_4 (sim_cpu *cpu, uint64_t address)
10797 {
10798   /* FIXME: This algorithm is *exactly* the same as the LD4 version.
10799      So why have two different instructions ?  There must be something
10800      wrong somewhere.  */
10801   vec_load (cpu, address, 4);
10802 }
10803
10804 /* Store multiple N-element structures to N consecutive registers.  */
10805 static void
10806 vec_store (sim_cpu *cpu, uint64_t address, unsigned N)
10807 {
10808   int      all  = uimm (aarch64_get_instr (cpu), 30, 30);
10809   unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10810   unsigned vd   = uimm (aarch64_get_instr (cpu), 4, 0);
10811   unsigned i;
10812
10813   switch (size)
10814     {
10815     case 0: /* 8-bit operations.  */
10816       if (all)
10817         for (i = 0; i < (16 * N); i++)
10818           aarch64_set_mem_u8
10819             (cpu, address + i,
10820              aarch64_get_vec_u8 (cpu, vec_reg (vd, i >> 4), i & 15));
10821       else
10822         for (i = 0; i < (8 * N); i++)
10823           aarch64_set_mem_u8
10824             (cpu, address + i,
10825              aarch64_get_vec_u8 (cpu, vec_reg (vd, i >> 3), i & 7));
10826       return;
10827
10828     case 1: /* 16-bit operations.  */
10829       if (all)
10830         for (i = 0; i < (8 * N); i++)
10831           aarch64_set_mem_u16
10832             (cpu, address + i * 2,
10833              aarch64_get_vec_u16 (cpu, vec_reg (vd, i >> 3), i & 7));
10834       else
10835         for (i = 0; i < (4 * N); i++)
10836           aarch64_set_mem_u16
10837             (cpu, address + i * 2,
10838              aarch64_get_vec_u16 (cpu, vec_reg (vd, i >> 2), i & 3));
10839       return;
10840
10841     case 2: /* 32-bit operations.  */
10842       if (all)
10843         for (i = 0; i < (4 * N); i++)
10844           aarch64_set_mem_u32
10845             (cpu, address + i * 4,
10846              aarch64_get_vec_u32 (cpu, vec_reg (vd, i >> 2), i & 3));
10847       else
10848         for (i = 0; i < (2 * N); i++)
10849           aarch64_set_mem_u32
10850             (cpu, address + i * 4,
10851              aarch64_get_vec_u32 (cpu, vec_reg (vd, i >> 1), i & 1));
10852       return;
10853
10854     case 3: /* 64-bit operations.  */
10855       if (all)
10856         for (i = 0; i < (2 * N); i++)
10857           aarch64_set_mem_u64
10858             (cpu, address + i * 8,
10859              aarch64_get_vec_u64 (cpu, vec_reg (vd, i >> 1), i & 1));
10860       else
10861         for (i = 0; i < N; i++)
10862           aarch64_set_mem_u64
10863             (cpu, address + i * 8,
10864              aarch64_get_vec_u64 (cpu, vec_reg (vd, i), 0));
10865       return;
10866     }
10867 }
10868
10869 /* Store multiple 4-element structure to four consecutive registers.  */
10870 static void
10871 ST4 (sim_cpu *cpu, uint64_t address)
10872 {
10873   vec_store (cpu, address, 4);
10874 }
10875
10876 /* Store multiple 3-element structures to three consecutive registers.  */
10877 static void
10878 ST3 (sim_cpu *cpu, uint64_t address)
10879 {
10880   vec_store (cpu, address, 3);
10881 }
10882
10883 /* Store multiple 2-element structures to two consecutive registers.  */
10884 static void
10885 ST2 (sim_cpu *cpu, uint64_t address)
10886 {
10887   vec_store (cpu, address, 2);
10888 }
10889
10890 /* Store multiple 1-element structures into one register.  */
10891 static void
10892 ST1_1 (sim_cpu *cpu, uint64_t address)
10893 {
10894   int      all  = uimm (aarch64_get_instr (cpu), 30, 30);
10895   unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10896   unsigned vd   = uimm (aarch64_get_instr (cpu), 4, 0);
10897   unsigned i;
10898
10899   switch (size)
10900     {
10901     case 0:
10902       for (i = 0; i < (all ? 16 : 8); i++)
10903         aarch64_set_mem_u8 (cpu, address + i,
10904                             aarch64_get_vec_u8 (cpu, vd, i));
10905       return;
10906
10907     case 1:
10908       for (i = 0; i < (all ? 8 : 4); i++)
10909         aarch64_set_mem_u16 (cpu, address + i * 2,
10910                              aarch64_get_vec_u16 (cpu, vd, i));
10911       return;
10912
10913     case 2:
10914       for (i = 0; i < (all ? 4 : 2); i++)
10915         aarch64_set_mem_u32 (cpu, address + i * 4,
10916                              aarch64_get_vec_u32 (cpu, vd, i));
10917       return;
10918
10919     case 3:
10920       for (i = 0; i < (all ? 2 : 1); i++)
10921         aarch64_set_mem_u64 (cpu, address + i * 8,
10922                              aarch64_get_vec_u64 (cpu, vd, i));
10923       return;
10924     }
10925 }
10926
10927 /* Store multiple 1-element structures into two registers.  */
10928 static void
10929 ST1_2 (sim_cpu *cpu, uint64_t address)
10930 {
10931   /* FIXME: This algorithm is *exactly* the same as the ST2 version.
10932      So why have two different instructions ?  There must be
10933      something wrong somewhere.  */
10934   vec_store (cpu, address, 2);
10935 }
10936
10937 /* Store multiple 1-element structures into three registers.  */
10938 static void
10939 ST1_3 (sim_cpu *cpu, uint64_t address)
10940 {
10941   /* FIXME: This algorithm is *exactly* the same as the ST3 version.
10942      So why have two different instructions ?  There must be
10943      something wrong somewhere.  */
10944   vec_store (cpu, address, 3);
10945 }
10946
10947 /* Store multiple 1-element structures into four registers.  */
10948 static void
10949 ST1_4 (sim_cpu *cpu, uint64_t address)
10950 {
10951   /* FIXME: This algorithm is *exactly* the same as the ST4 version.
10952      So why have two different instructions ?  There must be
10953      something wrong somewhere.  */
10954   vec_store (cpu, address, 4);
10955 }
10956
10957 static void
10958 do_vec_LDnR (sim_cpu *cpu, uint64_t address)
10959 {
10960   /* instr[31]    = 0
10961      instr[30]    = element selector 0=>half, 1=>all elements
10962      instr[29,24] = 00 1101
10963      instr[23]    = 0=>simple, 1=>post
10964      instr[22]    = 1
10965      instr[21]    = width: LD1R-or-LD3R (0) / LD2R-or-LD4R (1)
10966      instr[20,16] = 0 0000 (simple), Vinc (reg-post-inc, no SP),
10967                       11111 (immediate post inc)
10968      instr[15,14] = 11
10969      instr[13]    = width: LD1R-or-LD2R (0) / LD3R-or-LD4R (1)
10970      instr[12]    = 0
10971      instr[11,10] = element size 00=> byte(b), 01=> half(h),
10972                                  10=> word(s), 11=> double(d)
10973      instr[9,5]   = address
10974      instr[4,0]   = Vd  */
10975
10976   unsigned full = uimm (aarch64_get_instr (cpu), 30, 30);
10977   unsigned vd = uimm (aarch64_get_instr (cpu), 4, 0);
10978   unsigned size = uimm (aarch64_get_instr (cpu), 11, 10);
10979   int i;
10980
10981   NYI_assert (29, 24, 0x0D);
10982   NYI_assert (22, 22, 1);
10983   NYI_assert (15, 14, 3);
10984   NYI_assert (12, 12, 0);
10985
10986   switch ((uimm (aarch64_get_instr (cpu), 13, 13) << 1)
10987           | uimm (aarch64_get_instr (cpu), 21, 21))
10988     {
10989     case 0: /* LD1R.  */
10990       switch (size)
10991         {
10992         case 0:
10993           {
10994             uint8_t val = aarch64_get_mem_u8 (cpu, address);
10995             for (i = 0; i < (full ? 16 : 8); i++)
10996               aarch64_set_vec_u8 (cpu, vd, i, val);
10997             break;
10998           }
10999
11000         case 1:
11001           {
11002             uint16_t val = aarch64_get_mem_u16 (cpu, address);
11003             for (i = 0; i < (full ? 8 : 4); i++)
11004               aarch64_set_vec_u16 (cpu, vd, i, val);
11005             break;
11006           }
11007
11008         case 2:
11009           {
11010             uint32_t val = aarch64_get_mem_u32 (cpu, address);
11011             for (i = 0; i < (full ? 4 : 2); i++)
11012               aarch64_set_vec_u32 (cpu, vd, i, val);
11013             break;
11014           }
11015
11016         case 3:
11017           {
11018             uint64_t val = aarch64_get_mem_u64 (cpu, address);
11019             for (i = 0; i < (full ? 2 : 1); i++)
11020               aarch64_set_vec_u64 (cpu, vd, i, val);
11021             break;
11022           }
11023
11024         default:
11025           HALT_UNALLOC;
11026         }
11027       break;
11028
11029     case 1: /* LD2R.  */
11030       switch (size)
11031         {
11032         case 0:
11033           {
11034             uint8_t val1 = aarch64_get_mem_u8 (cpu, address);
11035             uint8_t val2 = aarch64_get_mem_u8 (cpu, address + 1);
11036
11037             for (i = 0; i < (full ? 16 : 8); i++)
11038               {
11039                 aarch64_set_vec_u8 (cpu, vd, 0, val1);
11040                 aarch64_set_vec_u8 (cpu, vd + 1, 0, val2);
11041               }
11042             break;
11043           }
11044
11045         case 1:
11046           {
11047             uint16_t val1 = aarch64_get_mem_u16 (cpu, address);
11048             uint16_t val2 = aarch64_get_mem_u16 (cpu, address + 2);
11049
11050             for (i = 0; i < (full ? 8 : 4); i++)
11051               {
11052                 aarch64_set_vec_u16 (cpu, vd, 0, val1);
11053                 aarch64_set_vec_u16 (cpu, vd + 1, 0, val2);
11054               }
11055             break;
11056           }
11057
11058         case 2:
11059           {
11060             uint32_t val1 = aarch64_get_mem_u32 (cpu, address);
11061             uint32_t val2 = aarch64_get_mem_u32 (cpu, address + 4);
11062
11063             for (i = 0; i < (full ? 4 : 2); i++)
11064               {
11065                 aarch64_set_vec_u32 (cpu, vd, 0, val1);
11066                 aarch64_set_vec_u32 (cpu, vd + 1, 0, val2);
11067               }
11068             break;
11069           }
11070
11071         case 3:
11072           {
11073             uint64_t val1 = aarch64_get_mem_u64 (cpu, address);
11074             uint64_t val2 = aarch64_get_mem_u64 (cpu, address + 8);
11075
11076             for (i = 0; i < (full ? 2 : 1); i++)
11077               {
11078                 aarch64_set_vec_u64 (cpu, vd, 0, val1);
11079                 aarch64_set_vec_u64 (cpu, vd + 1, 0, val2);
11080               }
11081             break;
11082           }
11083
11084         default:
11085           HALT_UNALLOC;
11086         }
11087       break;
11088
11089     case 2: /* LD3R.  */
11090       switch (size)
11091         {
11092         case 0:
11093           {
11094             uint8_t val1 = aarch64_get_mem_u8 (cpu, address);
11095             uint8_t val2 = aarch64_get_mem_u8 (cpu, address + 1);
11096             uint8_t val3 = aarch64_get_mem_u8 (cpu, address + 2);
11097
11098             for (i = 0; i < (full ? 16 : 8); i++)
11099               {
11100                 aarch64_set_vec_u8 (cpu, vd, 0, val1);
11101                 aarch64_set_vec_u8 (cpu, vd + 1, 0, val2);
11102                 aarch64_set_vec_u8 (cpu, vd + 2, 0, val3);
11103               }
11104           }
11105           break;
11106
11107         case 1:
11108           {
11109             uint32_t val1 = aarch64_get_mem_u16 (cpu, address);
11110             uint32_t val2 = aarch64_get_mem_u16 (cpu, address + 2);
11111             uint32_t val3 = aarch64_get_mem_u16 (cpu, address + 4);
11112
11113             for (i = 0; i < (full ? 8 : 4); i++)
11114               {
11115                 aarch64_set_vec_u16 (cpu, vd, 0, val1);
11116                 aarch64_set_vec_u16 (cpu, vd + 1, 0, val2);
11117                 aarch64_set_vec_u16 (cpu, vd + 2, 0, val3);
11118               }
11119           }
11120           break;
11121
11122         case 2:
11123           {
11124             uint32_t val1 = aarch64_get_mem_u32 (cpu, address);
11125             uint32_t val2 = aarch64_get_mem_u32 (cpu, address + 4);
11126             uint32_t val3 = aarch64_get_mem_u32 (cpu, address + 8);
11127
11128             for (i = 0; i < (full ? 4 : 2); i++)
11129               {
11130                 aarch64_set_vec_u32 (cpu, vd, 0, val1);
11131                 aarch64_set_vec_u32 (cpu, vd + 1, 0, val2);
11132                 aarch64_set_vec_u32 (cpu, vd + 2, 0, val3);
11133               }
11134           }
11135           break;
11136
11137         case 3:
11138           {
11139             uint64_t val1 = aarch64_get_mem_u64 (cpu, address);
11140             uint64_t val2 = aarch64_get_mem_u64 (cpu, address + 8);
11141             uint64_t val3 = aarch64_get_mem_u64 (cpu, address + 16);
11142
11143             for (i = 0; i < (full ? 2 : 1); i++)
11144               {
11145                 aarch64_set_vec_u64 (cpu, vd, 0, val1);
11146                 aarch64_set_vec_u64 (cpu, vd + 1, 0, val2);
11147                 aarch64_set_vec_u64 (cpu, vd + 2, 0, val3);
11148               }
11149           }
11150           break;
11151
11152         default:
11153           HALT_UNALLOC;
11154         }
11155       break;
11156
11157     case 3: /* LD4R.  */
11158       switch (size)
11159         {
11160         case 0:
11161           {
11162             uint8_t val1 = aarch64_get_mem_u8 (cpu, address);
11163             uint8_t val2 = aarch64_get_mem_u8 (cpu, address + 1);
11164             uint8_t val3 = aarch64_get_mem_u8 (cpu, address + 2);
11165             uint8_t val4 = aarch64_get_mem_u8 (cpu, address + 3);
11166
11167             for (i = 0; i < (full ? 16 : 8); i++)
11168               {
11169                 aarch64_set_vec_u8 (cpu, vd, 0, val1);
11170                 aarch64_set_vec_u8 (cpu, vd + 1, 0, val2);
11171                 aarch64_set_vec_u8 (cpu, vd + 2, 0, val3);
11172                 aarch64_set_vec_u8 (cpu, vd + 3, 0, val4);
11173               }
11174           }
11175           break;
11176
11177         case 1:
11178           {
11179             uint32_t val1 = aarch64_get_mem_u16 (cpu, address);
11180             uint32_t val2 = aarch64_get_mem_u16 (cpu, address + 2);
11181             uint32_t val3 = aarch64_get_mem_u16 (cpu, address + 4);
11182             uint32_t val4 = aarch64_get_mem_u16 (cpu, address + 6);
11183
11184             for (i = 0; i < (full ? 8 : 4); i++)
11185               {
11186                 aarch64_set_vec_u16 (cpu, vd, 0, val1);
11187                 aarch64_set_vec_u16 (cpu, vd + 1, 0, val2);
11188                 aarch64_set_vec_u16 (cpu, vd + 2, 0, val3);
11189                 aarch64_set_vec_u16 (cpu, vd + 3, 0, val4);
11190               }
11191           }
11192           break;
11193
11194         case 2:
11195           {
11196             uint32_t val1 = aarch64_get_mem_u32 (cpu, address);
11197             uint32_t val2 = aarch64_get_mem_u32 (cpu, address + 4);
11198             uint32_t val3 = aarch64_get_mem_u32 (cpu, address + 8);
11199             uint32_t val4 = aarch64_get_mem_u32 (cpu, address + 12);
11200
11201             for (i = 0; i < (full ? 4 : 2); i++)
11202               {
11203                 aarch64_set_vec_u32 (cpu, vd, 0, val1);
11204                 aarch64_set_vec_u32 (cpu, vd + 1, 0, val2);
11205                 aarch64_set_vec_u32 (cpu, vd + 2, 0, val3);
11206                 aarch64_set_vec_u32 (cpu, vd + 3, 0, val4);
11207               }
11208           }
11209           break;
11210
11211         case 3:
11212           {
11213             uint64_t val1 = aarch64_get_mem_u64 (cpu, address);
11214             uint64_t val2 = aarch64_get_mem_u64 (cpu, address + 8);
11215             uint64_t val3 = aarch64_get_mem_u64 (cpu, address + 16);
11216             uint64_t val4 = aarch64_get_mem_u64 (cpu, address + 24);
11217
11218             for (i = 0; i < (full ? 2 : 1); i++)
11219               {
11220                 aarch64_set_vec_u64 (cpu, vd, 0, val1);
11221                 aarch64_set_vec_u64 (cpu, vd + 1, 0, val2);
11222                 aarch64_set_vec_u64 (cpu, vd + 2, 0, val3);
11223                 aarch64_set_vec_u64 (cpu, vd + 3, 0, val4);
11224               }
11225           }
11226           break;
11227
11228         default:
11229           HALT_UNALLOC;
11230         }
11231       break;
11232
11233     default:
11234       HALT_UNALLOC;
11235     }
11236 }
11237
11238 static void
11239 do_vec_load_store (sim_cpu *cpu)
11240 {
11241   /* {LD|ST}<N>   {Vd..Vd+N}, vaddr
11242
11243      instr[31]    = 0
11244      instr[30]    = element selector 0=>half, 1=>all elements
11245      instr[29,25] = 00110
11246      instr[24]    = ?
11247      instr[23]    = 0=>simple, 1=>post
11248      instr[22]    = 0=>store, 1=>load
11249      instr[21]    = 0 (LDn) / small(0)-large(1) selector (LDnR)
11250      instr[20,16] = 00000 (simple), Vinc (reg-post-inc, no SP),
11251                     11111 (immediate post inc)
11252      instr[15,12] = elements and destinations.  eg for load:
11253                      0000=>LD4 => load multiple 4-element to
11254                      four consecutive registers
11255                      0100=>LD3 => load multiple 3-element to
11256                      three consecutive registers
11257                      1000=>LD2 => load multiple 2-element to
11258                      two consecutive registers
11259                      0010=>LD1 => load multiple 1-element to
11260                      four consecutive registers
11261                      0110=>LD1 => load multiple 1-element to
11262                      three consecutive registers
11263                      1010=>LD1 => load multiple 1-element to
11264                      two consecutive registers
11265                      0111=>LD1 => load multiple 1-element to
11266                      one register
11267                      1100=>LDR1,LDR2
11268                      1110=>LDR3,LDR4
11269      instr[11,10] = element size 00=> byte(b), 01=> half(h),
11270                                  10=> word(s), 11=> double(d)
11271      instr[9,5]   = Vn, can be SP
11272      instr[4,0]   = Vd  */
11273
11274   int post;
11275   int load;
11276   unsigned vn;
11277   uint64_t address;
11278   int type;
11279
11280   if (uimm (aarch64_get_instr (cpu), 31, 31) != 0
11281       || uimm (aarch64_get_instr (cpu), 29, 25) != 0x06)
11282     HALT_NYI;
11283
11284   type = uimm (aarch64_get_instr (cpu), 15, 12);
11285   if (type != 0xE && type != 0xE && uimm (aarch64_get_instr (cpu), 21, 21) != 0)
11286     HALT_NYI;
11287
11288   post = uimm (aarch64_get_instr (cpu), 23, 23);
11289   load = uimm (aarch64_get_instr (cpu), 22, 22);
11290   vn = uimm (aarch64_get_instr (cpu), 9, 5);
11291   address = aarch64_get_reg_u64 (cpu, vn, SP_OK);
11292
11293   if (post)
11294     {
11295       unsigned vm = uimm (aarch64_get_instr (cpu), 20, 16);
11296
11297       if (vm == R31)
11298         {
11299           unsigned sizeof_operation;
11300
11301           switch (type)
11302             {
11303             case 0: sizeof_operation = 32; break;
11304             case 4: sizeof_operation = 24; break;
11305             case 8: sizeof_operation = 16; break;
11306
11307             case 0xC:
11308               sizeof_operation = uimm (aarch64_get_instr (cpu), 21, 21) ? 2 : 1;
11309               sizeof_operation <<= uimm (aarch64_get_instr (cpu), 11, 10);
11310               break;
11311
11312             case 0xE:
11313               sizeof_operation = uimm (aarch64_get_instr (cpu), 21, 21) ? 8 : 4;
11314               sizeof_operation <<= uimm (aarch64_get_instr (cpu), 11, 10);
11315               break;
11316
11317             case 7:
11318               /* One register, immediate offset variant.  */
11319               sizeof_operation = 8;
11320               break;
11321               
11322             case 10:
11323               /* Two registers, immediate offset variant.  */
11324               sizeof_operation = 16;
11325               break;
11326
11327             case 6:
11328               /* Three registers, immediate offset variant.  */
11329               sizeof_operation = 24;
11330               break;
11331
11332             case 2:
11333               /* Four registers, immediate offset variant.  */
11334               sizeof_operation = 32;
11335               break;
11336
11337             default:
11338               HALT_UNALLOC;
11339             }
11340
11341           if (uimm (aarch64_get_instr (cpu), 30, 30))
11342             sizeof_operation *= 2;
11343
11344           aarch64_set_reg_u64 (cpu, vn, SP_OK, address + sizeof_operation);
11345         }
11346       else
11347         aarch64_set_reg_u64 (cpu, vn, SP_OK,
11348                              address + aarch64_get_reg_u64 (cpu, vm, NO_SP));
11349     }
11350   else
11351     {
11352       NYI_assert (20, 16, 0);
11353     }
11354
11355   if (load)
11356     {
11357       switch (type)
11358         {
11359         case 0:  LD4 (cpu, address); return;
11360         case 4:  LD3 (cpu, address); return;
11361         case 8:  LD2 (cpu, address); return;
11362         case 2:  LD1_4 (cpu, address); return;
11363         case 6:  LD1_3 (cpu, address); return;
11364         case 10: LD1_2 (cpu, address); return;
11365         case 7:  LD1_1 (cpu, address); return;
11366
11367         case 0xE:
11368         case 0xC: do_vec_LDnR (cpu, address); return;
11369
11370         default:
11371           HALT_NYI;
11372         }
11373     }
11374
11375   /* Stores.  */
11376   switch (type)
11377     {
11378     case 0:  ST4 (cpu, address); return;
11379     case 4:  ST3 (cpu, address); return;
11380     case 8:  ST2 (cpu, address); return;
11381     case 2:  ST1_4 (cpu, address); return;
11382     case 6:  ST1_3 (cpu, address); return;
11383     case 10: ST1_2 (cpu, address); return;
11384     case 7:  ST1_1 (cpu, address); return;
11385     default:
11386       HALT_NYI;
11387     }
11388 }
11389
11390 static void
11391 dexLdSt (sim_cpu *cpu)
11392 {
11393   /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
11394      assert  group == GROUP_LDST_0100 || group == GROUP_LDST_0110 ||
11395              group == GROUP_LDST_1100 || group == GROUP_LDST_1110
11396      bits [29,28:26] of a LS are the secondary dispatch vector.  */
11397   uint32_t group2 = dispatchLS (aarch64_get_instr (cpu));
11398
11399   switch (group2)
11400     {
11401     case LS_EXCL_000:
11402       dexLoadExclusive (cpu); return;
11403
11404     case LS_LIT_010:
11405     case LS_LIT_011:
11406       dexLoadLiteral (cpu); return;
11407
11408     case LS_OTHER_110:
11409     case LS_OTHER_111:
11410       dexLoadOther (cpu); return;
11411
11412     case LS_ADVSIMD_001:
11413       do_vec_load_store (cpu); return;
11414
11415     case LS_PAIR_100:
11416       dex_load_store_pair_gr (cpu); return;
11417
11418     case LS_PAIR_101:
11419       dex_load_store_pair_fp (cpu); return;
11420
11421     default:
11422       /* Should never reach here.  */
11423       HALT_NYI;
11424     }
11425 }
11426
11427 /* Specific decode and execute for group Data Processing Register.  */
11428
11429 static void
11430 dexLogicalShiftedRegister (sim_cpu *cpu)
11431 {
11432   /* assert instr[28:24] = 01010
11433      instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11434      instr[30,29:21] = op,N : 000 ==> AND, 001 ==> BIC,
11435                                010 ==> ORR, 011 ==> ORN
11436                                100 ==> EOR, 101 ==> EON,
11437                                110 ==> ANDS, 111 ==> BICS
11438      instr[23,22] = shift : 0 ==> LSL, 1 ==> LSR, 2 ==> ASR, 3 ==> ROR
11439      instr[15,10] = count : must be 0xxxxx for 32 bit
11440      instr[9,5] = Rn
11441      instr[4,0] = Rd  */
11442
11443   /* unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16); */
11444   uint32_t dispatch;
11445   Shift shiftType;
11446   uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
11447
11448   /* 32 bit operations must have count[5] = 0.  */
11449   /* or else we have an UNALLOC.  */
11450   uint32_t count = uimm (aarch64_get_instr (cpu), 15, 10);
11451
11452   if (!size && uimm (count, 5, 5))
11453     HALT_UNALLOC;
11454
11455   shiftType = shift (aarch64_get_instr (cpu), 22);
11456
11457   /* dispatch on size:op:N i.e aarch64_get_instr (cpu)[31,29:21].  */
11458   dispatch = ( (uimm (aarch64_get_instr (cpu), 31, 29) << 1)
11459               | uimm (aarch64_get_instr (cpu), 21, 21));
11460
11461   switch (dispatch)
11462     {
11463     case 0: and32_shift  (cpu, shiftType, count); return;
11464     case 1: bic32_shift  (cpu, shiftType, count); return;
11465     case 2: orr32_shift  (cpu, shiftType, count); return;
11466     case 3: orn32_shift  (cpu, shiftType, count); return;
11467     case 4: eor32_shift  (cpu, shiftType, count); return;
11468     case 5: eon32_shift  (cpu, shiftType, count); return;
11469     case 6: ands32_shift (cpu, shiftType, count); return;
11470     case 7: bics32_shift (cpu, shiftType, count); return;
11471     case 8: and64_shift  (cpu, shiftType, count); return;
11472     case 9: bic64_shift  (cpu, shiftType, count); return;
11473     case 10:orr64_shift  (cpu, shiftType, count); return;
11474     case 11:orn64_shift  (cpu, shiftType, count); return;
11475     case 12:eor64_shift  (cpu, shiftType, count); return;
11476     case 13:eon64_shift  (cpu, shiftType, count); return;
11477     case 14:ands64_shift (cpu, shiftType, count); return;
11478     case 15:bics64_shift (cpu, shiftType, count); return;
11479     default: HALT_UNALLOC;
11480     }
11481 }
11482
11483 /* 32 bit conditional select.  */
11484 static void
11485 csel32 (sim_cpu *cpu, CondCode cc)
11486 {
11487   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11488   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11489   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11490
11491   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11492                        testConditionCode (cpu, cc)
11493                        ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11494                        : aarch64_get_reg_u32 (cpu, rm, NO_SP));
11495 }
11496
11497 /* 64 bit conditional select.  */
11498 static void
11499 csel64 (sim_cpu *cpu, CondCode cc)
11500 {
11501   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11502   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11503   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11504
11505   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11506                        testConditionCode (cpu, cc)
11507                        ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11508                        : aarch64_get_reg_u64 (cpu, rm, NO_SP));
11509 }
11510
11511 /* 32 bit conditional increment.  */
11512 static void
11513 csinc32 (sim_cpu *cpu, CondCode cc)
11514 {
11515   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11516   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11517   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11518
11519   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11520                        testConditionCode (cpu, cc)
11521                        ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11522                        : aarch64_get_reg_u32 (cpu, rm, NO_SP) + 1);
11523 }
11524
11525 /* 64 bit conditional increment.  */
11526 static void
11527 csinc64 (sim_cpu *cpu, CondCode cc)
11528 {
11529   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11530   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11531   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11532
11533   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11534                        testConditionCode (cpu, cc)
11535                        ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11536                        : aarch64_get_reg_u64 (cpu, rm, NO_SP) + 1);
11537 }
11538
11539 /* 32 bit conditional invert.  */
11540 static void
11541 csinv32 (sim_cpu *cpu, CondCode cc)
11542 {
11543   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11544   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11545   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11546
11547   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11548                        testConditionCode (cpu, cc)
11549                        ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11550                        : ~ aarch64_get_reg_u32 (cpu, rm, NO_SP));
11551 }
11552
11553 /* 64 bit conditional invert.  */
11554 static void
11555 csinv64 (sim_cpu *cpu, CondCode cc)
11556 {
11557   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11558   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11559   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11560
11561   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11562                        testConditionCode (cpu, cc)
11563                        ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11564                        : ~ aarch64_get_reg_u64 (cpu, rm, NO_SP));
11565 }
11566
11567 /* 32 bit conditional negate.  */
11568 static void
11569 csneg32 (sim_cpu *cpu, CondCode cc)
11570 {
11571   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11572   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11573   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11574
11575   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11576                        testConditionCode (cpu, cc)
11577                        ? aarch64_get_reg_u32 (cpu, rn, NO_SP)
11578                        : - aarch64_get_reg_u32 (cpu, rm, NO_SP));
11579 }
11580
11581 /* 64 bit conditional negate.  */
11582 static void
11583 csneg64 (sim_cpu *cpu, CondCode cc)
11584 {
11585   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11586   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11587   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11588
11589   aarch64_set_reg_u64 (cpu, rd, NO_SP,
11590                        testConditionCode (cpu, cc)
11591                        ? aarch64_get_reg_u64 (cpu, rn, NO_SP)
11592                        : - aarch64_get_reg_u64 (cpu, rm, NO_SP));
11593 }
11594
11595 static void
11596 dexCondSelect (sim_cpu *cpu)
11597 {
11598   /* assert instr[28,21] = 11011011
11599      instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11600      instr[30:11,10] = op : 000 ==> CSEL, 001 ==> CSINC,
11601                             100 ==> CSINV, 101 ==> CSNEG,
11602                             _1_ ==> UNALLOC
11603      instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
11604      instr[15,12] = cond
11605      instr[29] = S : 0 ==> ok, 1 ==> UNALLOC  */
11606
11607   CondCode cc;
11608   uint32_t dispatch;
11609   uint32_t S = uimm (aarch64_get_instr (cpu), 29, 29);
11610   uint32_t op2 = uimm (aarch64_get_instr (cpu), 11, 10);
11611
11612   if (S == 1)
11613     HALT_UNALLOC;
11614
11615   if (op2 & 0x2)
11616     HALT_UNALLOC;
11617
11618   cc = condcode (aarch64_get_instr (cpu), 12);
11619   dispatch = ((uimm (aarch64_get_instr (cpu), 31, 30) << 1) | op2);
11620
11621   switch (dispatch)
11622     {
11623     case 0: csel32  (cpu, cc); return;
11624     case 1: csinc32 (cpu, cc); return;
11625     case 2: csinv32 (cpu, cc); return;
11626     case 3: csneg32 (cpu, cc); return;
11627     case 4: csel64  (cpu, cc); return;
11628     case 5: csinc64 (cpu, cc); return;
11629     case 6: csinv64 (cpu, cc); return;
11630     case 7: csneg64 (cpu, cc); return;
11631     default: HALT_UNALLOC;
11632     }
11633 }
11634
11635 /* Some helpers for counting leading 1 or 0 bits.  */
11636
11637 /* Counts the number of leading bits which are the same
11638    in a 32 bit value in the range 1 to 32.  */
11639 static uint32_t
11640 leading32 (uint32_t value)
11641 {
11642   int32_t mask= 0xffff0000;
11643   uint32_t count= 16; /* Counts number of bits set in mask.  */
11644   uint32_t lo = 1;    /* Lower bound for number of sign bits.  */
11645   uint32_t hi = 32;   /* Upper bound for number of sign bits.  */
11646
11647   while (lo + 1 < hi)
11648     {
11649       int32_t test = (value & mask);
11650
11651       if (test == 0 || test == mask)
11652         {
11653           lo = count;
11654           count = (lo + hi) / 2;
11655           mask >>= (count - lo);
11656         }
11657       else
11658         {
11659           hi = count;
11660           count = (lo + hi) / 2;
11661           mask <<= hi - count;
11662         }
11663     }
11664
11665   if (lo != hi)
11666     {
11667       int32_t test;
11668
11669       mask >>= 1;
11670       test = (value & mask);
11671
11672       if (test == 0 || test == mask)
11673         count = hi;
11674       else
11675         count = lo;
11676     }
11677
11678   return count;
11679 }
11680
11681 /* Counts the number of leading bits which are the same
11682    in a 64 bit value in the range 1 to 64.  */
11683 static uint64_t
11684 leading64 (uint64_t value)
11685 {
11686   int64_t mask= 0xffffffff00000000LL;
11687   uint64_t count = 32; /* Counts number of bits set in mask.  */
11688   uint64_t lo = 1;     /* Lower bound for number of sign bits.  */
11689   uint64_t hi = 64;    /* Upper bound for number of sign bits.  */
11690
11691   while (lo + 1 < hi)
11692     {
11693       int64_t test = (value & mask);
11694
11695       if (test == 0 || test == mask)
11696         {
11697           lo = count;
11698           count = (lo + hi) / 2;
11699           mask >>= (count - lo);
11700         }
11701       else
11702         {
11703           hi = count;
11704           count = (lo + hi) / 2;
11705           mask <<= hi - count;
11706         }
11707     }
11708
11709   if (lo != hi)
11710     {
11711       int64_t test;
11712
11713       mask >>= 1;
11714       test = (value & mask);
11715
11716       if (test == 0 || test == mask)
11717         count = hi;
11718       else
11719         count = lo;
11720     }
11721
11722   return count;
11723 }
11724
11725 /* Bit operations.  */
11726 /* N.B register args may not be SP.  */
11727
11728 /* 32 bit count leading sign bits.  */
11729 static void
11730 cls32 (sim_cpu *cpu)
11731 {
11732   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11733   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11734
11735   /* N.B. the result needs to exclude the leading bit.  */
11736   aarch64_set_reg_u64
11737     (cpu, rd, NO_SP, leading32 (aarch64_get_reg_u32 (cpu, rn, NO_SP)) - 1);
11738 }
11739
11740 /* 64 bit count leading sign bits.  */
11741 static void
11742 cls64 (sim_cpu *cpu)
11743 {
11744   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11745   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11746
11747   /* N.B. the result needs to exclude the leading bit.  */
11748   aarch64_set_reg_u64
11749     (cpu, rd, NO_SP, leading64 (aarch64_get_reg_u64 (cpu, rn, NO_SP)) - 1);
11750 }
11751
11752 /* 32 bit count leading zero bits.  */
11753 static void
11754 clz32 (sim_cpu *cpu)
11755 {
11756   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11757   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11758   uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11759
11760   /* if the sign (top) bit is set then the count is 0.  */
11761   if (pick32 (value, 31, 31))
11762     aarch64_set_reg_u64 (cpu, rd, NO_SP, 0L);
11763   else
11764     aarch64_set_reg_u64 (cpu, rd, NO_SP, leading32 (value));
11765 }
11766
11767 /* 64 bit count leading zero bits.  */
11768 static void
11769 clz64 (sim_cpu *cpu)
11770 {
11771   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11772   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11773   uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11774
11775   /* if the sign (top) bit is set then the count is 0.  */
11776   if (pick64 (value, 63, 63))
11777     aarch64_set_reg_u64 (cpu, rd, NO_SP, 0L);
11778   else
11779     aarch64_set_reg_u64 (cpu, rd, NO_SP, leading64 (value));
11780 }
11781
11782 /* 32 bit reverse bits.  */
11783 static void
11784 rbit32 (sim_cpu *cpu)
11785 {
11786   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11787   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11788   uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11789   uint32_t result = 0;
11790   int i;
11791
11792   for (i = 0; i < 32; i++)
11793     {
11794       result <<= 1;
11795       result |= (value & 1);
11796       value >>= 1;
11797     }
11798   aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11799 }
11800
11801 /* 64 bit reverse bits.  */
11802 static void
11803 rbit64 (sim_cpu *cpu)
11804 {
11805   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11806   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11807   uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11808   uint64_t result = 0;
11809   int i;
11810
11811   for (i = 0; i < 64; i++)
11812     {
11813       result <<= 1;
11814       result |= (value & 1UL);
11815       value >>= 1;
11816     }
11817   aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11818 }
11819
11820 /* 32 bit reverse bytes.  */
11821 static void
11822 rev32 (sim_cpu *cpu)
11823 {
11824   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11825   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11826   uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11827   uint32_t result = 0;
11828   int i;
11829
11830   for (i = 0; i < 4; i++)
11831     {
11832       result <<= 8;
11833       result |= (value & 0xff);
11834       value >>= 8;
11835     }
11836   aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11837 }
11838
11839 /* 64 bit reverse bytes.  */
11840 static void
11841 rev64 (sim_cpu *cpu)
11842 {
11843   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11844   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11845   uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11846   uint64_t result = 0;
11847   int i;
11848
11849   for (i = 0; i < 8; i++)
11850     {
11851       result <<= 8;
11852       result |= (value & 0xffULL);
11853       value >>= 8;
11854     }
11855   aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11856 }
11857
11858 /* 32 bit reverse shorts.  */
11859 /* N.B.this reverses the order of the bytes in each half word.  */
11860 static void
11861 revh32 (sim_cpu *cpu)
11862 {
11863   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11864   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11865   uint32_t value = aarch64_get_reg_u32 (cpu, rn, NO_SP);
11866   uint32_t result = 0;
11867   int i;
11868
11869   for (i = 0; i < 2; i++)
11870     {
11871       result <<= 8;
11872       result |= (value & 0x00ff00ff);
11873       value >>= 8;
11874     }
11875   aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11876 }
11877
11878 /* 64 bit reverse shorts.  */
11879 /* N.B.this reverses the order of the bytes in each half word.  */
11880 static void
11881 revh64 (sim_cpu *cpu)
11882 {
11883   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11884   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11885   uint64_t value = aarch64_get_reg_u64 (cpu, rn, NO_SP);
11886   uint64_t result = 0;
11887   int i;
11888
11889   for (i = 0; i < 2; i++)
11890     {
11891       result <<= 8;
11892       result |= (value & 0x00ff00ff00ff00ffULL);
11893       value >>= 8;
11894     }
11895   aarch64_set_reg_u64 (cpu, rd, NO_SP, result);
11896 }
11897
11898 static void
11899 dexDataProc1Source (sim_cpu *cpu)
11900 {
11901   /* assert instr[30] == 1
11902      aarch64_get_instr (cpu)[28,21] == 111010110
11903      instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
11904      instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
11905      instr[20,16] = opcode2 : 00000 ==> ok, ow ==> UNALLOC
11906      instr[15,10] = opcode : 000000 ==> RBIT, 000001 ==> REV16,
11907                              000010 ==> REV, 000011 ==> UNALLOC
11908                              000100 ==> CLZ, 000101 ==> CLS
11909                              ow ==> UNALLOC
11910      instr[9,5] = rn : may not be SP
11911      instr[4,0] = rd : may not be SP.  */
11912
11913   uint32_t S = uimm (aarch64_get_instr (cpu), 29, 29);
11914   uint32_t opcode2 = uimm (aarch64_get_instr (cpu), 20, 16);
11915   uint32_t opcode = uimm (aarch64_get_instr (cpu), 15, 10);
11916   uint32_t dispatch = ((uimm (aarch64_get_instr (cpu), 31, 31) << 3) | opcode);
11917
11918   if (S == 1)
11919     HALT_UNALLOC;
11920
11921   if (opcode2 != 0)
11922     HALT_UNALLOC;
11923
11924   if (opcode & 0x38)
11925     HALT_UNALLOC;
11926
11927   switch (dispatch)
11928     {
11929     case 0: rbit32 (cpu); return;
11930     case 1: revh32 (cpu); return;
11931     case 2: rev32 (cpu); return;
11932     case 4: clz32 (cpu); return;
11933     case 5: cls32 (cpu); return;
11934     case 8: rbit64 (cpu); return;
11935     case 9: revh64 (cpu); return;
11936     case 10:rev32 (cpu); return;
11937     case 11:rev64 (cpu); return;
11938     case 12:clz64 (cpu); return;
11939     case 13:cls64 (cpu); return;
11940     default: HALT_UNALLOC;
11941     }
11942 }
11943
11944 /* Variable shift.
11945    Shifts by count supplied in register.
11946    N.B register args may not be SP.
11947    These all use the shifted auxiliary function for
11948    simplicity and clarity.  Writing the actual shift
11949    inline would avoid a branch and so be faster but
11950    would also necessitate getting signs right.  */
11951
11952 /* 32 bit arithmetic shift right.  */
11953 static void
11954 asrv32 (sim_cpu *cpu)
11955 {
11956   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11957   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11958   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11959
11960   aarch64_set_reg_u64
11961     (cpu, rd, NO_SP,
11962      shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), ASR,
11963                 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
11964 }
11965
11966 /* 64 bit arithmetic shift right.  */
11967 static void
11968 asrv64 (sim_cpu *cpu)
11969 {
11970   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11971   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11972   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11973
11974   aarch64_set_reg_u64
11975     (cpu, rd, NO_SP,
11976      shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), ASR,
11977                 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
11978 }
11979
11980 /* 32 bit logical shift left.  */
11981 static void
11982 lslv32 (sim_cpu *cpu)
11983 {
11984   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11985   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
11986   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
11987
11988   aarch64_set_reg_u64
11989     (cpu, rd, NO_SP,
11990      shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), LSL,
11991                 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
11992 }
11993
11994 /* 64 bit arithmetic shift left.  */
11995 static void
11996 lslv64 (sim_cpu *cpu)
11997 {
11998   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
11999   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12000   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12001
12002   aarch64_set_reg_u64
12003     (cpu, rd, NO_SP,
12004      shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), LSL,
12005                 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
12006 }
12007
12008 /* 32 bit logical shift right.  */
12009 static void
12010 lsrv32 (sim_cpu *cpu)
12011 {
12012   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12013   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12014   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12015
12016   aarch64_set_reg_u64
12017     (cpu, rd, NO_SP,
12018      shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), LSR,
12019                 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
12020 }
12021
12022 /* 64 bit logical shift right.  */
12023 static void
12024 lsrv64 (sim_cpu *cpu)
12025 {
12026   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12027   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12028   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12029
12030   aarch64_set_reg_u64
12031     (cpu, rd, NO_SP,
12032      shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), LSR,
12033                 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
12034 }
12035
12036 /* 32 bit rotate right.  */
12037 static void
12038 rorv32 (sim_cpu *cpu)
12039 {
12040   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12041   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12042   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12043
12044   aarch64_set_reg_u64
12045     (cpu, rd, NO_SP,
12046      shifted32 (aarch64_get_reg_u32 (cpu, rn, NO_SP), ROR,
12047                 (aarch64_get_reg_u32 (cpu, rm, NO_SP) & 0x1f)));
12048 }
12049
12050 /* 64 bit rotate right.  */
12051 static void
12052 rorv64 (sim_cpu *cpu)
12053 {
12054   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12055   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12056   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12057
12058   aarch64_set_reg_u64
12059     (cpu, rd, NO_SP,
12060      shifted64 (aarch64_get_reg_u64 (cpu, rn, NO_SP), ROR,
12061                 (aarch64_get_reg_u64 (cpu, rm, NO_SP) & 0x3f)));
12062 }
12063
12064
12065 /* divide.  */
12066
12067 /* 32 bit signed divide.  */
12068 static void
12069 cpuiv32 (sim_cpu *cpu)
12070 {
12071   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12072   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12073   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12074   /* N.B. the pseudo-code does the divide using 64 bit data.  */
12075   /* TODO : check that this rounds towards zero as required.  */
12076   int64_t dividend = aarch64_get_reg_s32 (cpu, rn, NO_SP);
12077   int64_t divisor = aarch64_get_reg_s32 (cpu, rm, NO_SP);
12078
12079   aarch64_set_reg_s64 (cpu, rd, NO_SP,
12080                        divisor ? ((int32_t) (dividend / divisor)) : 0);
12081 }
12082
12083 /* 64 bit signed divide.  */
12084 static void
12085 cpuiv64 (sim_cpu *cpu)
12086 {
12087   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12088   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12089   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12090
12091   /* TODO : check that this rounds towards zero as required.  */
12092   int64_t divisor = aarch64_get_reg_s64 (cpu, rm, NO_SP);
12093
12094   aarch64_set_reg_s64
12095     (cpu, rd, NO_SP,
12096      divisor ? (aarch64_get_reg_s64 (cpu, rn, NO_SP) / divisor) : 0);
12097 }
12098
12099 /* 32 bit unsigned divide.  */
12100 static void
12101 udiv32 (sim_cpu *cpu)
12102 {
12103   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12104   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12105   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12106
12107   /* N.B. the pseudo-code does the divide using 64 bit data.  */
12108   uint64_t dividend = aarch64_get_reg_u32 (cpu, rn, NO_SP);
12109   uint64_t divisor  = aarch64_get_reg_u32 (cpu, rm, NO_SP);
12110
12111   aarch64_set_reg_u64 (cpu, rd, NO_SP,
12112                        divisor ? (uint32_t) (dividend / divisor) : 0);
12113 }
12114
12115 /* 64 bit unsigned divide.  */
12116 static void
12117 udiv64 (sim_cpu *cpu)
12118 {
12119   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12120   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12121   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12122
12123   /* TODO : check that this rounds towards zero as required.  */
12124   uint64_t divisor = aarch64_get_reg_u64 (cpu, rm, NO_SP);
12125
12126   aarch64_set_reg_u64
12127     (cpu, rd, NO_SP,
12128      divisor ? (aarch64_get_reg_u64 (cpu, rn, NO_SP) / divisor) : 0);
12129 }
12130
12131 static void
12132 dexDataProc2Source (sim_cpu *cpu)
12133 {
12134   /* assert instr[30] == 0
12135      instr[28,21] == 11010110
12136      instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit
12137      instr[29] = S : 0 ==> ok, 1 ==> UNALLOC
12138      instr[15,10] = opcode : 000010 ==> UDIV, 000011 ==> CPUIV,
12139                              001000 ==> LSLV, 001001 ==> LSRV
12140                              001010 ==> ASRV, 001011 ==> RORV
12141                              ow ==> UNALLOC.  */
12142
12143   uint32_t dispatch;
12144   uint32_t S = uimm (aarch64_get_instr (cpu), 29, 29);
12145   uint32_t opcode = uimm (aarch64_get_instr (cpu), 15, 10);
12146
12147   if (S == 1)
12148     HALT_UNALLOC;
12149
12150   if (opcode & 0x34)
12151     HALT_UNALLOC;
12152
12153   dispatch = (  (uimm (aarch64_get_instr (cpu), 31, 31) << 3)
12154               | (uimm (opcode, 3, 3) << 2)
12155               |  uimm (opcode, 1, 0));
12156   switch (dispatch)
12157     {
12158     case 2:  udiv32 (cpu); return;
12159     case 3:  cpuiv32 (cpu); return;
12160     case 4:  lslv32 (cpu); return;
12161     case 5:  lsrv32 (cpu); return;
12162     case 6:  asrv32 (cpu); return;
12163     case 7:  rorv32 (cpu); return;
12164     case 10: udiv64 (cpu); return;
12165     case 11: cpuiv64 (cpu); return;
12166     case 12: lslv64 (cpu); return;
12167     case 13: lsrv64 (cpu); return;
12168     case 14: asrv64 (cpu); return;
12169     case 15: rorv64 (cpu); return;
12170     default: HALT_UNALLOC;
12171     }
12172 }
12173
12174
12175 /* Multiply.  */
12176
12177 /* 32 bit multiply and add.  */
12178 static void
12179 madd32 (sim_cpu *cpu)
12180 {
12181   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12182   unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
12183   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12184   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12185
12186   aarch64_set_reg_u64 (cpu, rd, NO_SP,
12187                        aarch64_get_reg_u32 (cpu, ra, NO_SP)
12188                        + aarch64_get_reg_u32 (cpu, rn, NO_SP)
12189                        * aarch64_get_reg_u32 (cpu, rm, NO_SP));
12190 }
12191
12192 /* 64 bit multiply and add.  */
12193 static void
12194 madd64 (sim_cpu *cpu)
12195 {
12196   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12197   unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
12198   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12199   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12200
12201   aarch64_set_reg_u64 (cpu, rd, NO_SP,
12202                        aarch64_get_reg_u64 (cpu, ra, NO_SP)
12203                        + aarch64_get_reg_u64 (cpu, rn, NO_SP)
12204                        * aarch64_get_reg_u64 (cpu, rm, NO_SP));
12205 }
12206
12207 /* 32 bit multiply and sub.  */
12208 static void
12209 msub32 (sim_cpu *cpu)
12210 {
12211   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12212   unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
12213   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12214   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12215
12216   aarch64_set_reg_u64 (cpu, rd, NO_SP,
12217                        aarch64_get_reg_u32 (cpu, ra, NO_SP)
12218                        - aarch64_get_reg_u32 (cpu, rn, NO_SP)
12219                        * aarch64_get_reg_u32 (cpu, rm, NO_SP));
12220 }
12221
12222 /* 64 bit multiply and sub.  */
12223 static void
12224 msub64 (sim_cpu *cpu)
12225 {
12226   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12227   unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
12228   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12229   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12230
12231   aarch64_set_reg_u64 (cpu, rd, NO_SP,
12232                        aarch64_get_reg_u64 (cpu, ra, NO_SP)
12233                        - aarch64_get_reg_u64 (cpu, rn, NO_SP)
12234                        * aarch64_get_reg_u64 (cpu, rm, NO_SP));
12235 }
12236
12237 /* Signed multiply add long -- source, source2 : 32 bit, source3 : 64 bit.  */
12238 static void
12239 smaddl (sim_cpu *cpu)
12240 {
12241   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12242   unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
12243   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12244   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12245
12246   /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12247      obtain a 64 bit product.  */
12248   aarch64_set_reg_s64
12249     (cpu, rd, NO_SP,
12250      aarch64_get_reg_s64 (cpu, ra, NO_SP)
12251      + ((int64_t) aarch64_get_reg_s32 (cpu, rn, NO_SP))
12252      * ((int64_t) aarch64_get_reg_s32 (cpu, rm, NO_SP)));
12253 }
12254
12255 /* Signed multiply sub long -- source, source2 : 32 bit, source3 : 64 bit.  */
12256 static void
12257 smsubl (sim_cpu *cpu)
12258 {
12259   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12260   unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
12261   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12262   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12263
12264   /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12265      obtain a 64 bit product.  */
12266   aarch64_set_reg_s64
12267     (cpu, rd, NO_SP,
12268      aarch64_get_reg_s64 (cpu, ra, NO_SP)
12269      - ((int64_t) aarch64_get_reg_s32 (cpu, rn, NO_SP))
12270      * ((int64_t) aarch64_get_reg_s32 (cpu, rm, NO_SP)));
12271 }
12272
12273 /* Integer Multiply/Divide.  */
12274
12275 /* First some macros and a helper function.  */
12276 /* Macros to test or access elements of 64 bit words.  */
12277
12278 /* Mask used to access lo 32 bits of 64 bit unsigned int.  */
12279 #define LOW_WORD_MASK ((1ULL << 32) - 1)
12280 /* Return the lo 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int.  */
12281 #define lowWordToU64(_value_u64) ((_value_u64) & LOW_WORD_MASK)
12282 /* Return the hi 32 bit word of a 64 bit unsigned int as a 64 bit unsigned int.  */
12283 #define highWordToU64(_value_u64) ((_value_u64) >> 32)
12284
12285 /* Offset of sign bit in 64 bit signed integger.  */
12286 #define SIGN_SHIFT_U64 63
12287 /* The sign bit itself -- also identifies the minimum negative int value.  */
12288 #define SIGN_BIT_U64 (1UL << SIGN_SHIFT_U64)
12289 /* Return true if a 64 bit signed int presented as an unsigned int is the
12290    most negative value.  */
12291 #define isMinimumU64(_value_u64) ((_value_u64) == SIGN_BIT_U64)
12292 /* Return true (non-zero) if a 64 bit signed int presented as an unsigned
12293    int has its sign bit set to false.  */
12294 #define isSignSetU64(_value_u64) ((_value_u64) & SIGN_BIT_U64)
12295 /* Return 1L or -1L according to whether a 64 bit signed int presented as
12296    an unsigned int has its sign bit set or not.  */
12297 #define signOfU64(_value_u64) (1L + (((value_u64) >> SIGN_SHIFT_U64) * -2L)
12298 /* Clear the sign bit of a 64 bit signed int presented as an unsigned int.  */
12299 #define clearSignU64(_value_u64) ((_value_u64) &= ~SIGN_BIT_U64)
12300
12301 /* Multiply two 64 bit ints and return.
12302    the hi 64 bits of the 128 bit product.  */
12303
12304 static uint64_t
12305 mul64hi (uint64_t value1, uint64_t value2)
12306 {
12307   uint64_t resultmid1;
12308   uint64_t result;
12309   uint64_t value1_lo = lowWordToU64 (value1);
12310   uint64_t value1_hi = highWordToU64 (value1) ;
12311   uint64_t value2_lo = lowWordToU64 (value2);
12312   uint64_t value2_hi = highWordToU64 (value2);
12313
12314   /* Cross-multiply and collect results.  */
12315
12316   uint64_t xproductlo = value1_lo * value2_lo;
12317   uint64_t xproductmid1 = value1_lo * value2_hi;
12318   uint64_t xproductmid2 = value1_hi * value2_lo;
12319   uint64_t xproducthi = value1_hi * value2_hi;
12320   uint64_t carry = 0;
12321   /* Start accumulating 64 bit results.  */
12322   /* Drop bottom half of lowest cross-product.  */
12323   uint64_t resultmid = xproductlo >> 32;
12324   /* Add in middle products.  */
12325   resultmid = resultmid + xproductmid1;
12326
12327   /* Check for overflow.  */
12328   if (resultmid < xproductmid1)
12329     /* Carry over 1 into top cross-product.  */
12330     carry++;
12331
12332   resultmid1  = resultmid + xproductmid2;
12333
12334   /* Check for overflow.  */
12335   if (resultmid1 < xproductmid2)
12336     /* Carry over 1 into top cross-product.  */
12337     carry++;
12338
12339   /* Drop lowest 32 bits of middle cross-product.  */
12340   result = resultmid1 >> 32;
12341
12342   /* Add top cross-product plus and any carry.  */
12343   result += xproducthi + carry;
12344
12345   return result;
12346 }
12347
12348 /* Signed multiply high, source, source2 :
12349    64 bit, dest <-- high 64-bit of result.  */
12350 static void
12351 smulh (sim_cpu *cpu)
12352 {
12353   uint64_t uresult;
12354   int64_t result;
12355   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12356   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12357   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12358   GReg ra = greg (aarch64_get_instr (cpu), 10);
12359   int64_t value1 = aarch64_get_reg_u64 (cpu, rn, NO_SP);
12360   int64_t value2 = aarch64_get_reg_u64 (cpu, rm, NO_SP);
12361   uint64_t uvalue1;
12362   uint64_t uvalue2;
12363   int64_t signum = 1;
12364
12365   if (ra != R31)
12366     HALT_UNALLOC;
12367
12368   /* Convert to unsigned and use the unsigned mul64hi routine
12369      the fix the sign up afterwards.  */
12370   if (value1 < 0)
12371     {
12372       signum *= -1L;
12373       uvalue1 = -value1;
12374     }
12375   else
12376     {
12377       uvalue1 = value1;
12378     }
12379
12380   if (value2 < 0)
12381     {
12382       signum *= -1L;
12383       uvalue2 = -value2;
12384     }
12385   else
12386     {
12387       uvalue2 = value2;
12388     }
12389
12390   uresult = mul64hi (uvalue1, uvalue2);
12391   result = uresult;
12392   result *= signum;
12393
12394   aarch64_set_reg_s64 (cpu, rd, NO_SP, result);
12395 }
12396
12397 /* Unsigned multiply add long -- source, source2 :
12398    32 bit, source3 : 64 bit.  */
12399 static void
12400 umaddl (sim_cpu *cpu)
12401 {
12402   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12403   unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
12404   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12405   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12406
12407   /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12408      obtain a 64 bit product.  */
12409   aarch64_set_reg_u64
12410     (cpu, rd, NO_SP,
12411      aarch64_get_reg_u64 (cpu, ra, NO_SP)
12412      + ((uint64_t) aarch64_get_reg_u32 (cpu, rn, NO_SP))
12413      * ((uint64_t) aarch64_get_reg_u32 (cpu, rm, NO_SP)));
12414 }
12415
12416 /* Unsigned multiply sub long -- source, source2 : 32 bit, source3 : 64 bit.  */
12417 static void
12418 umsubl (sim_cpu *cpu)
12419 {
12420   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12421   unsigned ra = uimm (aarch64_get_instr (cpu), 14, 10);
12422   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12423   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12424
12425   /* N.B. we need to multiply the signed 32 bit values in rn, rm to
12426      obtain a 64 bit product.  */
12427   aarch64_set_reg_u64
12428     (cpu, rd, NO_SP,
12429      aarch64_get_reg_u64 (cpu, ra, NO_SP)
12430      - ((uint64_t) aarch64_get_reg_u32 (cpu, rn, NO_SP))
12431      * ((uint64_t) aarch64_get_reg_u32 (cpu, rm, NO_SP)));
12432 }
12433
12434 /* Unsigned multiply high, source, source2 :
12435    64 bit, dest <-- high 64-bit of result.  */
12436 static void
12437 umulh (sim_cpu *cpu)
12438 {
12439   unsigned rm = uimm (aarch64_get_instr (cpu), 20, 16);
12440   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12441   unsigned rd = uimm (aarch64_get_instr (cpu), 4, 0);
12442   GReg ra = greg (aarch64_get_instr (cpu), 10);
12443
12444   if (ra != R31)
12445     HALT_UNALLOC;
12446
12447   aarch64_set_reg_u64 (cpu, rd, NO_SP,
12448                        mul64hi (aarch64_get_reg_u64 (cpu, rn, NO_SP),
12449                                 aarch64_get_reg_u64 (cpu, rm, NO_SP)));
12450 }
12451
12452 static void
12453 dexDataProc3Source (sim_cpu *cpu)
12454 {
12455   /* assert instr[28,24] == 11011.  */
12456   /* instr[31] = size : 0 ==> 32 bit, 1 ==> 64 bit (for rd at least)
12457      instr[30,29] = op54 : 00 ==> ok, ow ==> UNALLOC
12458      instr[23,21] = op31 : 111 ==> UNALLOC, o2 ==> ok
12459      instr[15] = o0 : 0/1 ==> ok
12460      instr[23,21:15] ==> op : 0000 ==> MADD, 0001 ==> MSUB,     (32/64 bit)
12461                               0010 ==> SMADDL, 0011 ==> SMSUBL, (64 bit only)
12462                               0100 ==> SMULH,                   (64 bit only)
12463                               1010 ==> UMADDL, 1011 ==> UNSUBL, (64 bit only)
12464                               1100 ==> UMULH                    (64 bit only)
12465                               ow ==> UNALLOC.  */
12466
12467   uint32_t dispatch;
12468   uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
12469   uint32_t op54 = uimm (aarch64_get_instr (cpu), 30, 29);
12470   uint32_t op31 = uimm (aarch64_get_instr (cpu), 23, 21);
12471   uint32_t o0 = uimm (aarch64_get_instr (cpu), 15, 15);
12472
12473   if (op54 != 0)
12474     HALT_UNALLOC;
12475
12476   if (size == 0)
12477     {
12478       if (op31 != 0)
12479         HALT_UNALLOC;
12480
12481       if (o0 == 0)
12482         madd32 (cpu);
12483       else
12484         msub32 (cpu);
12485       return;
12486     }
12487
12488   dispatch = (op31 << 1) | o0;
12489
12490   switch (dispatch)
12491     {
12492     case 0:  madd64 (cpu); return;
12493     case 1:  msub64 (cpu); return;
12494     case 2:  smaddl (cpu); return;
12495     case 3:  smsubl (cpu); return;
12496     case 4:  smulh (cpu); return;
12497     case 10: umaddl (cpu); return;
12498     case 11: umsubl (cpu); return;
12499     case 12: umulh (cpu); return;
12500     default: HALT_UNALLOC;
12501     }
12502 }
12503
12504 static void
12505 dexDPReg (sim_cpu *cpu)
12506 {
12507   /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
12508      assert  group == GROUP_DPREG_0101 || group == GROUP_DPREG_1101
12509      bits [28:24:21] of a DPReg are the secondary dispatch vector.  */
12510   uint32_t group2 = dispatchDPReg (aarch64_get_instr (cpu));
12511
12512   switch (group2)
12513     {
12514     case DPREG_LOG_000:
12515     case DPREG_LOG_001:
12516       dexLogicalShiftedRegister (cpu); return;
12517
12518     case DPREG_ADDSHF_010:
12519       dexAddSubtractShiftedRegister (cpu); return;
12520
12521     case DPREG_ADDEXT_011:
12522       dexAddSubtractExtendedRegister (cpu); return;
12523
12524     case DPREG_ADDCOND_100:
12525       {
12526         /* This set bundles a variety of different operations.  */
12527         /* Check for.  */
12528         /* 1) add/sub w carry.  */
12529         uint32_t mask1 = 0x1FE00000U;
12530         uint32_t val1  = 0x1A000000U;
12531         /* 2) cond compare register/immediate.  */
12532         uint32_t mask2 = 0x1FE00000U;
12533         uint32_t val2  = 0x1A400000U;
12534         /* 3) cond select.  */
12535         uint32_t mask3 = 0x1FE00000U;
12536         uint32_t val3  = 0x1A800000U;
12537         /* 4) data proc 1/2 source.  */
12538         uint32_t mask4 = 0x1FE00000U;
12539         uint32_t val4  = 0x1AC00000U;
12540
12541         if ((aarch64_get_instr (cpu) & mask1) == val1)
12542           dexAddSubtractWithCarry (cpu);
12543
12544         else if ((aarch64_get_instr (cpu) & mask2) == val2)
12545           CondCompare (cpu);
12546
12547         else if ((aarch64_get_instr (cpu) & mask3) == val3)
12548           dexCondSelect (cpu);
12549
12550         else if ((aarch64_get_instr (cpu) & mask4) == val4)
12551           {
12552             /* Bit 30 is clear for data proc 2 source
12553                and set for data proc 1 source.  */
12554             if (aarch64_get_instr (cpu)  & (1U << 30))
12555               dexDataProc1Source (cpu);
12556             else
12557               dexDataProc2Source (cpu);
12558           }
12559
12560         else
12561           /* Should not reach here.  */
12562           HALT_NYI;
12563
12564         return;
12565       }
12566
12567     case DPREG_3SRC_110:
12568       dexDataProc3Source (cpu); return;
12569
12570     case DPREG_UNALLOC_101:
12571       HALT_UNALLOC;
12572
12573     case DPREG_3SRC_111:
12574       dexDataProc3Source (cpu); return;
12575
12576     default:
12577       /* Should never reach here.  */
12578       HALT_NYI;
12579     }
12580 }
12581
12582 /* Unconditional Branch immediate.
12583    Offset is a PC-relative byte offset in the range +/- 128MiB.
12584    The offset is assumed to be raw from the decode i.e. the
12585    simulator is expected to scale them from word offsets to byte.  */
12586
12587 /* Unconditional branch.  */
12588 static void
12589 buc (sim_cpu *cpu, int32_t offset)
12590 {
12591   aarch64_set_next_PC_by_offset (cpu, offset);
12592 }
12593
12594 static unsigned stack_depth = 0;
12595
12596 /* Unconditional branch and link -- writes return PC to LR.  */
12597 static void
12598 bl (sim_cpu *cpu, int32_t offset)
12599 {
12600   aarch64_save_LR (cpu);
12601   aarch64_set_next_PC_by_offset (cpu, offset);
12602
12603   if (TRACE_BRANCH_P (cpu))
12604     {
12605       ++ stack_depth;
12606       TRACE_BRANCH (cpu,
12607                     " %*scall %" PRIx64 " [%s]"
12608                     " [args: %" PRIx64 " %" PRIx64 " %" PRIx64 "]",
12609                     stack_depth, " ", aarch64_get_next_PC (cpu),
12610                     aarch64_get_func (aarch64_get_next_PC (cpu)),
12611                     aarch64_get_reg_u64 (cpu, 0, NO_SP),
12612                     aarch64_get_reg_u64 (cpu, 1, NO_SP),
12613                     aarch64_get_reg_u64 (cpu, 2, NO_SP)
12614                     );
12615     }
12616 }
12617
12618 /* Unconditional Branch register.
12619    Branch/return address is in source register.  */
12620
12621 /* Unconditional branch.  */
12622 static void
12623 br (sim_cpu *cpu)
12624 {
12625   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12626   aarch64_set_next_PC (cpu, aarch64_get_reg_u64 (cpu, rn, NO_SP));
12627 }
12628
12629 /* Unconditional branch and link -- writes return PC to LR.  */
12630 static void
12631 blr (sim_cpu *cpu)
12632 {
12633   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12634
12635   /* The pseudo code in the spec says we update LR before fetching.
12636      the value from the rn.  */
12637   aarch64_save_LR (cpu);
12638   aarch64_set_next_PC (cpu, aarch64_get_reg_u64 (cpu, rn, NO_SP));
12639
12640   if (TRACE_BRANCH_P (cpu))
12641     {
12642       ++ stack_depth;
12643       TRACE_BRANCH (cpu,
12644                     " %*scall %" PRIx64 " [%s]"
12645                     " [args: %" PRIx64 " %" PRIx64 " %" PRIx64 "]",
12646                     stack_depth, " ", aarch64_get_next_PC (cpu),
12647                     aarch64_get_func (aarch64_get_next_PC (cpu)),
12648                     aarch64_get_reg_u64 (cpu, 0, NO_SP),
12649                     aarch64_get_reg_u64 (cpu, 1, NO_SP),
12650                     aarch64_get_reg_u64 (cpu, 2, NO_SP)
12651                     );
12652     }
12653 }
12654
12655 /* Return -- assembler will default source to LR this is functionally
12656    equivalent to br but, presumably, unlike br it side effects the
12657    branch predictor.  */
12658 static void
12659 ret (sim_cpu *cpu)
12660 {
12661   unsigned rn = uimm (aarch64_get_instr (cpu), 9, 5);
12662   aarch64_set_next_PC (cpu, aarch64_get_reg_u64 (cpu, rn, NO_SP));
12663
12664   if (TRACE_BRANCH_P (cpu))
12665     {
12666       TRACE_BRANCH (cpu,
12667                     " %*sreturn [result: %" PRIx64 "]",
12668                     stack_depth, " ", aarch64_get_reg_u64 (cpu, 0, NO_SP));
12669       -- stack_depth;
12670     }
12671 }
12672
12673 /* NOP -- we implement this and call it from the decode in case we
12674    want to intercept it later.  */
12675
12676 static void
12677 nop (sim_cpu *cpu)
12678 {
12679 }
12680
12681 /* Data synchronization barrier.  */
12682
12683 static void
12684 dsb (sim_cpu *cpu)
12685 {
12686 }
12687
12688 /* Data memory barrier.  */
12689
12690 static void
12691 dmb (sim_cpu *cpu)
12692 {
12693 }
12694
12695 /* Instruction synchronization barrier.  */
12696
12697 static void
12698 isb (sim_cpu *cpu)
12699 {
12700 }
12701
12702 static void
12703 dexBranchImmediate (sim_cpu *cpu)
12704 {
12705   /* assert instr[30,26] == 00101
12706      instr[31] ==> 0 == B, 1 == BL
12707      instr[25,0] == imm26 branch offset counted in words.  */
12708
12709   uint32_t top = uimm (aarch64_get_instr (cpu), 31, 31);
12710   /* We have a 26 byte signed word offset which we need to pass to the
12711      execute routine as a signed byte offset.  */
12712   int32_t offset = simm32 (aarch64_get_instr (cpu), 25, 0) << 2;
12713
12714   if (top)
12715     bl (cpu, offset);
12716   else
12717     buc (cpu, offset);
12718 }
12719
12720 /* Control Flow.  */
12721
12722 /* Conditional branch
12723
12724    Offset is a PC-relative byte offset in the range +/- 1MiB pos is
12725    a bit position in the range 0 .. 63
12726
12727    cc is a CondCode enum value as pulled out of the decode
12728
12729    N.B. any offset register (source) can only be Xn or Wn.  */
12730
12731 static void
12732 bcc (sim_cpu *cpu, int32_t offset, CondCode cc)
12733 {
12734   /* the test returns TRUE if CC is met.  */
12735   if (testConditionCode (cpu, cc))
12736     aarch64_set_next_PC_by_offset (cpu, offset);
12737 }
12738
12739 /* 32 bit branch on register non-zero.  */
12740 static void
12741 cbnz32 (sim_cpu *cpu, int32_t offset)
12742 {
12743   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12744
12745   if (aarch64_get_reg_u32 (cpu, rt, NO_SP) != 0)
12746     aarch64_set_next_PC_by_offset (cpu, offset);
12747 }
12748
12749 /* 64 bit branch on register zero.  */
12750 static void
12751 cbnz (sim_cpu *cpu, int32_t offset)
12752 {
12753   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12754
12755   if (aarch64_get_reg_u64 (cpu, rt, NO_SP) != 0)
12756     aarch64_set_next_PC_by_offset (cpu, offset);
12757 }
12758
12759 /* 32 bit branch on register non-zero.  */
12760 static void
12761 cbz32 (sim_cpu *cpu, int32_t offset)
12762 {
12763   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12764
12765   if (aarch64_get_reg_u32 (cpu, rt, NO_SP) == 0)
12766     aarch64_set_next_PC_by_offset (cpu, offset);
12767 }
12768
12769 /* 64 bit branch on register zero.  */
12770 static void
12771 cbz (sim_cpu *cpu, int32_t offset)
12772 {
12773   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12774
12775   if (aarch64_get_reg_u64 (cpu, rt, NO_SP) == 0)
12776     aarch64_set_next_PC_by_offset (cpu, offset);
12777 }
12778
12779 /* Branch on register bit test non-zero -- one size fits all.  */
12780 static void
12781 tbnz (sim_cpu *cpu, uint32_t  pos, int32_t offset)
12782 {
12783   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12784
12785   if (aarch64_get_reg_u64 (cpu, rt, NO_SP) & (1 << pos))
12786     aarch64_set_next_PC_by_offset (cpu, offset);
12787 }
12788
12789 /* branch on register bit test zero -- one size fits all.  */
12790 static void
12791 tbz (sim_cpu *cpu, uint32_t  pos, int32_t offset)
12792 {
12793   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
12794
12795   if (!(aarch64_get_reg_u64 (cpu, rt, NO_SP) & (1 << pos)))
12796     aarch64_set_next_PC_by_offset (cpu, offset);
12797 }
12798
12799 static void
12800 dexCompareBranchImmediate (sim_cpu *cpu)
12801 {
12802   /* instr[30,25] = 01 1010
12803      instr[31]    = size : 0 ==> 32, 1 ==> 64
12804      instr[24]    = op : 0 ==> CBZ, 1 ==> CBNZ
12805      instr[23,5]  = simm19 branch offset counted in words
12806      instr[4,0]   = rt  */
12807
12808   uint32_t size = uimm (aarch64_get_instr (cpu), 31, 31);
12809   uint32_t op   = uimm (aarch64_get_instr (cpu), 24, 24);
12810   int32_t offset = simm32 (aarch64_get_instr (cpu), 23, 5) << 2;
12811
12812   if (size == 0)
12813     {
12814       if (op == 0)
12815         cbz32 (cpu, offset);
12816       else
12817         cbnz32 (cpu, offset);
12818     }
12819   else
12820     {
12821       if (op == 0)
12822         cbz (cpu, offset);
12823       else
12824         cbnz (cpu, offset);
12825     }
12826 }
12827
12828 static void
12829 dexTestBranchImmediate (sim_cpu *cpu)
12830 {
12831   /* instr[31]    = b5 : bit 5 of test bit idx
12832      instr[30,25] = 01 1011
12833      instr[24]    = op : 0 ==> TBZ, 1 == TBNZ
12834      instr[23,19] = b40 : bits 4 to 0 of test bit idx
12835      instr[18,5]  = simm14 : signed offset counted in words
12836      instr[4,0]   = uimm5  */
12837
12838   uint32_t pos = ((uimm (aarch64_get_instr (cpu), 31, 31) << 4)
12839                   | uimm (aarch64_get_instr (cpu), 23,19));
12840   int32_t offset = simm32 (aarch64_get_instr (cpu), 18, 5) << 2;
12841
12842   NYI_assert (30, 25, 0x1b);
12843
12844   if (uimm (aarch64_get_instr (cpu), 24, 24) == 0)
12845     tbz (cpu, pos, offset);
12846   else
12847     tbnz (cpu, pos, offset);
12848 }
12849
12850 static void
12851 dexCondBranchImmediate (sim_cpu *cpu)
12852 {
12853   /* instr[31,25] = 010 1010
12854      instr[24]    = op1; op => 00 ==> B.cond
12855      instr[23,5]  = simm19 : signed offset counted in words
12856      instr[4]     = op0
12857      instr[3,0]   = cond  */
12858
12859   int32_t offset;
12860   CondCode cc;
12861   uint32_t op = ((uimm (aarch64_get_instr (cpu), 24, 24) << 1)
12862                  | uimm (aarch64_get_instr (cpu), 4, 4));
12863
12864   NYI_assert (31, 25, 0x2a);
12865
12866   if (op != 0)
12867     HALT_UNALLOC;
12868
12869   offset = simm32 (aarch64_get_instr (cpu), 23, 5) << 2;
12870   cc = condcode (aarch64_get_instr (cpu), 0);
12871
12872   bcc (cpu, offset, cc);
12873 }
12874
12875 static void
12876 dexBranchRegister (sim_cpu *cpu)
12877 {
12878   /* instr[31,25] = 110 1011
12879      instr[24,21] = op : 0 ==> BR, 1 => BLR, 2 => RET, 3 => ERET, 4 => DRPS
12880      instr[20,16] = op2 : must be 11111
12881      instr[15,10] = op3 : must be 000000
12882      instr[4,0]   = op2 : must be 11111.  */
12883
12884   uint32_t op = uimm (aarch64_get_instr (cpu), 24, 21);
12885   uint32_t op2 = uimm (aarch64_get_instr (cpu), 20, 16);
12886   uint32_t op3 = uimm (aarch64_get_instr (cpu), 15, 10);
12887   uint32_t op4 = uimm (aarch64_get_instr (cpu), 4, 0);
12888
12889   NYI_assert (31, 25, 0x6b);
12890
12891   if (op2 != 0x1F || op3 != 0 || op4 != 0)
12892     HALT_UNALLOC;
12893
12894   if (op == 0)
12895     br (cpu);
12896
12897   else if (op == 1)
12898     blr (cpu);
12899
12900   else if (op == 2)
12901     ret (cpu);
12902
12903   else
12904     {
12905       /* ERET and DRPS accept 0b11111 for rn = aarch64_get_instr (cpu)[4,0].  */
12906       /* anything else is unallocated.  */
12907       uint32_t rn = greg (aarch64_get_instr (cpu), 0);
12908
12909       if (rn != 0x1f)
12910         HALT_UNALLOC;
12911
12912       if (op == 4 || op == 5)
12913         HALT_NYI;
12914
12915       HALT_UNALLOC;
12916     }
12917 }
12918
12919 /* FIXME: We should get the Angel SWI values from ../../libgloss/aarch64/svc.h
12920    but this may not be available.  So instead we define the values we need
12921    here.  */
12922 #define AngelSVC_Reason_Open            0x01
12923 #define AngelSVC_Reason_Close           0x02
12924 #define AngelSVC_Reason_Write           0x05
12925 #define AngelSVC_Reason_Read            0x06
12926 #define AngelSVC_Reason_IsTTY           0x09
12927 #define AngelSVC_Reason_Seek            0x0A
12928 #define AngelSVC_Reason_FLen            0x0C
12929 #define AngelSVC_Reason_Remove          0x0E
12930 #define AngelSVC_Reason_Rename          0x0F
12931 #define AngelSVC_Reason_Clock           0x10
12932 #define AngelSVC_Reason_Time            0x11
12933 #define AngelSVC_Reason_System          0x12
12934 #define AngelSVC_Reason_Errno           0x13
12935 #define AngelSVC_Reason_GetCmdLine      0x15
12936 #define AngelSVC_Reason_HeapInfo        0x16
12937 #define AngelSVC_Reason_ReportException 0x18
12938 #define AngelSVC_Reason_Elapsed         0x30
12939
12940
12941 static void
12942 handle_halt (sim_cpu *cpu, uint32_t val)
12943 {
12944   uint64_t result = 0;
12945
12946   if (val != 0xf000)
12947     {
12948       TRACE_SYSCALL (cpu, " HLT [0x%x]", val);
12949       sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
12950                        sim_stopped, SIM_SIGTRAP);
12951     }
12952
12953   /* We have encountered an Angel SVC call.  See if we can process it.  */
12954   switch (aarch64_get_reg_u32 (cpu, 0, NO_SP))
12955     {
12956     case AngelSVC_Reason_HeapInfo:
12957       {
12958         /* Get the values.  */
12959         uint64_t stack_top = aarch64_get_stack_start (cpu);
12960         uint64_t heap_base = aarch64_get_heap_start (cpu);
12961
12962         /* Get the pointer  */
12963         uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12964         ptr = aarch64_get_mem_u64 (cpu, ptr);
12965
12966         /* Fill in the memory block.  */
12967         /* Start addr of heap.  */
12968         aarch64_set_mem_u64 (cpu, ptr +  0, heap_base);
12969         /* End addr of heap.  */
12970         aarch64_set_mem_u64 (cpu, ptr +  8, stack_top);
12971         /* Lowest stack addr.  */
12972         aarch64_set_mem_u64 (cpu, ptr + 16, heap_base);
12973         /* Initial stack addr.  */
12974         aarch64_set_mem_u64 (cpu, ptr + 24, stack_top);
12975
12976         TRACE_SYSCALL (cpu, " AngelSVC: Get Heap Info");
12977       }
12978       break;
12979
12980     case AngelSVC_Reason_Open:
12981       {
12982         /* Get the pointer  */
12983         /* uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);.  */
12984         /* FIXME: For now we just assume that we will only be asked
12985            to open the standard file descriptors.  */
12986         static int fd = 0;
12987         result = fd ++;
12988
12989         TRACE_SYSCALL (cpu, " AngelSVC: Open file %d", fd - 1);
12990       }
12991       break;
12992
12993     case AngelSVC_Reason_Close:
12994       {
12995         uint64_t fh = aarch64_get_reg_u64 (cpu, 1, SP_OK);
12996         TRACE_SYSCALL (cpu, " AngelSVC: Close file %d", (int) fh);
12997         result = 0;
12998       }
12999       break;
13000
13001     case AngelSVC_Reason_Errno:
13002       result = 0;
13003       TRACE_SYSCALL (cpu, " AngelSVC: Get Errno");
13004       break;
13005
13006     case AngelSVC_Reason_Clock:
13007       result =
13008 #ifdef CLOCKS_PER_SEC
13009         (CLOCKS_PER_SEC >= 100)
13010         ? (clock () / (CLOCKS_PER_SEC / 100))
13011         : ((clock () * 100) / CLOCKS_PER_SEC)
13012 #else
13013         /* Presume unix... clock() returns microseconds.  */
13014         (clock () / 10000)
13015 #endif
13016         ;
13017         TRACE_SYSCALL (cpu, " AngelSVC: Get Clock");
13018       break;
13019
13020     case AngelSVC_Reason_GetCmdLine:
13021       {
13022         /* Get the pointer  */
13023         uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
13024         ptr = aarch64_get_mem_u64 (cpu, ptr);
13025
13026         /* FIXME: No command line for now.  */
13027         aarch64_set_mem_u64 (cpu, ptr, 0);
13028         TRACE_SYSCALL (cpu, " AngelSVC: Get Command Line");
13029       }
13030       break;
13031
13032     case AngelSVC_Reason_IsTTY:
13033       result = 1;
13034         TRACE_SYSCALL (cpu, " AngelSVC: IsTTY ?");
13035       break;
13036
13037     case AngelSVC_Reason_Write:
13038       {
13039         /* Get the pointer  */
13040         uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
13041         /* Get the write control block.  */
13042         uint64_t fd  = aarch64_get_mem_u64 (cpu, ptr);
13043         uint64_t buf = aarch64_get_mem_u64 (cpu, ptr + 8);
13044         uint64_t len = aarch64_get_mem_u64 (cpu, ptr + 16);
13045
13046         TRACE_SYSCALL (cpu, "write of %" PRIx64 " bytes from %"
13047                        PRIx64 " on descriptor %" PRIx64,
13048                        len, buf, fd);
13049
13050         if (len > 1280)
13051           {
13052             TRACE_SYSCALL (cpu,
13053                            " AngelSVC: Write: Suspiciously long write: %ld",
13054                            (long) len);
13055             sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
13056                              sim_stopped, SIM_SIGBUS);
13057           }
13058         else if (fd == 1)
13059           {
13060             printf ("%.*s", (int) len, aarch64_get_mem_ptr (cpu, buf));
13061           }
13062         else if (fd == 2)
13063           {
13064             TRACE (cpu, 0, "\n");
13065             sim_io_eprintf (CPU_STATE (cpu), "%.*s",
13066                             (int) len, aarch64_get_mem_ptr (cpu, buf));
13067             TRACE (cpu, 0, "\n");
13068           }
13069         else
13070           {
13071             TRACE_SYSCALL (cpu,
13072                            " AngelSVC: Write: Unexpected file handle: %d",
13073                            (int) fd);
13074             sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
13075                              sim_stopped, SIM_SIGABRT);
13076           }
13077       }
13078       break;
13079
13080     case AngelSVC_Reason_ReportException:
13081       {
13082         /* Get the pointer  */
13083         uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);
13084         /*ptr = aarch64_get_mem_u64 (cpu, ptr);.  */
13085         uint64_t type = aarch64_get_mem_u64 (cpu, ptr);
13086         uint64_t state = aarch64_get_mem_u64 (cpu, ptr + 8);
13087
13088         TRACE_SYSCALL (cpu,
13089                        "Angel Exception: type 0x%" PRIx64 " state %" PRIx64,
13090                        type, state);
13091
13092         if (type == 0x20026)
13093           sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
13094                            sim_exited, state);
13095         else
13096           sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
13097                            sim_stopped, SIM_SIGINT);
13098       }
13099       break;
13100
13101     case AngelSVC_Reason_Read:
13102     case AngelSVC_Reason_FLen:
13103     case AngelSVC_Reason_Seek:
13104     case AngelSVC_Reason_Remove:
13105     case AngelSVC_Reason_Time:
13106     case AngelSVC_Reason_System:
13107     case AngelSVC_Reason_Rename:
13108     case AngelSVC_Reason_Elapsed:
13109     default:
13110       TRACE_SYSCALL (cpu, " HLT [Unknown angel %x]",
13111                      aarch64_get_reg_u32 (cpu, 0, NO_SP));
13112       sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
13113                        sim_stopped, SIM_SIGTRAP);
13114     }
13115
13116   aarch64_set_reg_u64 (cpu, 0, NO_SP, result);
13117 }
13118
13119 static void
13120 dexExcpnGen (sim_cpu *cpu)
13121 {
13122   /* instr[31:24] = 11010100
13123      instr[23,21] = opc : 000 ==> GEN EXCPN, 001 ==> BRK
13124                           010 ==> HLT,       101 ==> DBG GEN EXCPN
13125      instr[20,5]  = imm16
13126      instr[4,2]   = opc2 000 ==> OK, ow ==> UNALLOC
13127      instr[1,0]   = LL : discriminates opc  */
13128
13129   uint32_t opc = uimm (aarch64_get_instr (cpu), 23, 21);
13130   uint32_t imm16 = uimm (aarch64_get_instr (cpu), 20, 5);
13131   uint32_t opc2 = uimm (aarch64_get_instr (cpu), 4, 2);
13132   uint32_t LL;
13133
13134   NYI_assert (31, 24, 0xd4);
13135
13136   if (opc2 != 0)
13137     HALT_UNALLOC;
13138
13139   LL = uimm (aarch64_get_instr (cpu), 1, 0);
13140
13141   /* We only implement HLT and BRK for now.  */
13142   if (opc == 1 && LL == 0)
13143     {
13144       TRACE_EVENTS (cpu, " BRK [0x%x]", imm16);
13145       sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
13146                        sim_exited, aarch64_get_reg_s32 (cpu, R0, SP_OK));
13147     }
13148
13149   if (opc == 2 && LL == 0)
13150     handle_halt (cpu, imm16);
13151
13152   else if (opc == 0 || opc == 5)
13153     HALT_NYI;
13154
13155   else
13156     HALT_UNALLOC;
13157 }
13158
13159 /* Stub for accessing system registers.  */
13160
13161 static uint64_t
13162 system_get (sim_cpu *cpu, unsigned op0, unsigned op1, unsigned crn,
13163             unsigned crm, unsigned op2)
13164 {
13165   if (crn == 0 && op1 == 3 && crm == 0 && op2 == 7)
13166     /* DCZID_EL0 - the Data Cache Zero ID register.
13167        We do not support DC ZVA at the moment, so
13168        we return a value with the disable bit set.
13169        We implement support for the DCZID register since
13170        it is used by the C library's memset function.  */
13171     return ((uint64_t) 1) << 4;
13172
13173   if (crn == 0 && op1 == 3 && crm == 0 && op2 == 1)
13174     /* Cache Type Register.  */
13175     return 0x80008000UL;
13176
13177   if (crn == 13 && op1 == 3 && crm == 0 && op2 == 2)
13178     /* TPIDR_EL0 - thread pointer id.  */
13179     return aarch64_get_thread_id (cpu);
13180
13181   if (op1 == 3 && crm == 4 && op2 == 0)
13182     return aarch64_get_FPCR (cpu);
13183
13184   if (op1 == 3 && crm == 4 && op2 == 1)
13185     return aarch64_get_FPSR (cpu);
13186
13187   else if (op1 == 3 && crm == 2 && op2 == 0)
13188     return aarch64_get_CPSR (cpu);
13189
13190   HALT_NYI;
13191 }
13192
13193 static void
13194 system_set (sim_cpu *cpu, unsigned op0, unsigned op1, unsigned crn,
13195             unsigned crm, unsigned op2, uint64_t val)
13196 {
13197   if (op1 == 3 && crm == 4 && op2 == 0)
13198     aarch64_set_FPCR (cpu, val);
13199
13200   else if (op1 == 3 && crm == 4 && op2 == 1)
13201     aarch64_set_FPSR (cpu, val);
13202
13203   else if (op1 == 3 && crm == 2 && op2 == 0)
13204     aarch64_set_CPSR (cpu, val);
13205
13206   else
13207     HALT_NYI;
13208 }
13209                                
13210 static void
13211 do_mrs (sim_cpu *cpu)
13212 {
13213   /* instr[31:20] = 1101 0101 0001 1
13214      instr[19]    = op0
13215      instr[18,16] = op1
13216      instr[15,12] = CRn
13217      instr[11,8]  = CRm
13218      instr[7,5]   = op2
13219      instr[4,0]   = Rt  */
13220   unsigned sys_op0 = uimm (aarch64_get_instr (cpu), 19, 19) + 2;
13221   unsigned sys_op1 = uimm (aarch64_get_instr (cpu), 18, 16);
13222   unsigned sys_crn = uimm (aarch64_get_instr (cpu), 15, 12);
13223   unsigned sys_crm = uimm (aarch64_get_instr (cpu), 11, 8);
13224   unsigned sys_op2 = uimm (aarch64_get_instr (cpu), 7, 5);
13225   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
13226
13227   aarch64_set_reg_u64 (cpu, rt, NO_SP,
13228                        system_get (cpu, sys_op0, sys_op1, sys_crn, sys_crm, sys_op2));
13229 }
13230
13231 static void
13232 do_MSR_immediate (sim_cpu *cpu)
13233 {
13234   /* instr[31:19] = 1101 0101 0000 0
13235      instr[18,16] = op1
13236      instr[15,12] = 0100
13237      instr[11,8]  = CRm
13238      instr[7,5]   = op2
13239      instr[4,0]   = 1 1111  */
13240
13241   unsigned op1 = uimm (aarch64_get_instr (cpu), 18, 16);
13242   /*unsigned crm = uimm (aarch64_get_instr (cpu), 11, 8);*/
13243   unsigned op2 = uimm (aarch64_get_instr (cpu), 7, 5);
13244
13245   NYI_assert (31, 19, 0x1AA0);
13246   NYI_assert (15, 12, 0x4);
13247   NYI_assert (4,  0,  0x1F);
13248
13249   if (op1 == 0)
13250     {
13251       if (op2 == 5)
13252         HALT_NYI; /* set SPSel.  */
13253       else
13254         HALT_UNALLOC;
13255     }
13256   else if (op1 == 3)
13257     {
13258       if (op2 == 6)
13259         HALT_NYI; /* set DAIFset.  */
13260       else if (op2 == 7)
13261         HALT_NYI; /* set DAIFclr.  */
13262       else
13263         HALT_UNALLOC;
13264     }
13265   else
13266     HALT_UNALLOC;
13267 }
13268
13269 static void
13270 do_MSR_reg (sim_cpu *cpu)
13271 {
13272   /* instr[31:20] = 1101 0101 0001
13273      instr[19]    = op0
13274      instr[18,16] = op1
13275      instr[15,12] = CRn
13276      instr[11,8]  = CRm
13277      instr[7,5]   = op2
13278      instr[4,0]   = Rt  */
13279
13280   unsigned sys_op0 = uimm (aarch64_get_instr (cpu), 19, 19) + 2;
13281   unsigned sys_op1 = uimm (aarch64_get_instr (cpu), 18, 16);
13282   unsigned sys_crn = uimm (aarch64_get_instr (cpu), 15, 12);
13283   unsigned sys_crm = uimm (aarch64_get_instr (cpu), 11, 8);
13284   unsigned sys_op2 = uimm (aarch64_get_instr (cpu), 7, 5);
13285   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
13286
13287   NYI_assert (31, 20, 0xD51);
13288   
13289   system_set (cpu, sys_op0, sys_op1, sys_crn, sys_crm, sys_op2,
13290               aarch64_get_reg_u64 (cpu, rt, NO_SP));
13291 }
13292
13293 static void
13294 do_SYS (sim_cpu * cpu)
13295 {
13296   /* instr[31,19] = 1101 0101 0000 1
13297      instr[18,16] = op1
13298      instr[15,12] = CRn
13299      instr[11,8]  = CRm
13300      instr[7,5]   = op2
13301      instr[4,0]   = Rt  */
13302   NYI_assert (31, 19, 0x1AA1);
13303
13304   /* FIXME: For now we just silently accept system ops.  */
13305 }
13306                                
13307 static void
13308 dexSystem (sim_cpu *cpu)
13309 {
13310   /* instr[31:22] = 1101 01010 0
13311      instr[21]    = L
13312      instr[20,19] = op0
13313      instr[18,16] = op1
13314      instr[15,12] = CRn
13315      instr[11,8]  = CRm
13316      instr[7,5]   = op2
13317      instr[4,0]   = uimm5  */
13318
13319   /* We are interested in HINT, DSB, DMB and ISB
13320
13321      Hint #0 encodes NOOP (this is the only hint we care about)
13322      L == 0, op0 == 0, op1 = 011, CRn = 0010, Rt = 11111,
13323      CRm op2  != 0000 000 OR CRm op2 == 0000 000 || CRm op > 0000 101
13324
13325      DSB, DMB, ISB are data store barrier, data memory barrier and
13326      instruction store barrier, respectively, where
13327
13328      L == 0, op0 == 0, op1 = 011, CRn = 0011, Rt = 11111,
13329      op2 : DSB ==> 100, DMB ==> 101, ISB ==> 110
13330      CRm<3:2> ==> domain, CRm<1:0> ==> types,
13331      domain : 00 ==> OuterShareable, 01 ==> Nonshareable,
13332               10 ==> InerShareable, 11 ==> FullSystem
13333      types :  01 ==> Reads, 10 ==> Writes,
13334               11 ==> All, 00 ==> All (domain == FullSystem).  */
13335
13336   unsigned rt = uimm (aarch64_get_instr (cpu), 4, 0);
13337
13338   NYI_assert (31, 22, 0x354);
13339
13340   switch (INSTR (21, 12))
13341     {
13342     case 0x032:
13343       if (rt == 0x1F)
13344         {
13345           /* NOP has CRm != 0000 OR.  */
13346           /*         (CRm == 0000 AND (op2 == 000 OR op2 > 101)).  */
13347           uint32_t crm = uimm (aarch64_get_instr (cpu), 11, 8);
13348           uint32_t op2 = uimm (aarch64_get_instr (cpu), 7, 5);
13349
13350           if (crm != 0 || (op2 == 0 || op2 > 5))
13351             {
13352               /* Actually call nop method so we can reimplement it later.  */
13353               nop (cpu);
13354               return;
13355             }
13356         }
13357       HALT_NYI;
13358
13359     case 0x033:
13360       {
13361         uint32_t op2 =  uimm (aarch64_get_instr (cpu), 7, 5);
13362
13363         switch (op2)
13364           {
13365           case 2: HALT_NYI;
13366           case 4: dsb (cpu); return;
13367           case 5: dmb (cpu); return;
13368           case 6: isb (cpu); return;
13369           default: HALT_UNALLOC;
13370         }
13371       }
13372
13373     case 0x3B0:
13374     case 0x3B4:
13375     case 0x3BD:
13376       do_mrs (cpu);
13377       return;
13378
13379     case 0x0B7:
13380       do_SYS (cpu); /* DC is an alias of SYS.  */
13381       return;
13382
13383     default:
13384       if (uimm (aarch64_get_instr (cpu), 21, 20) == 0x1)
13385         do_MSR_reg (cpu);
13386       else if (INSTR (21, 19) == 0 && INSTR (15, 12) == 0x4)
13387         do_MSR_immediate (cpu);
13388       else
13389         HALT_NYI;
13390       return;
13391     }
13392 }
13393
13394 static void
13395 dexBr (sim_cpu *cpu)
13396 {
13397   /* uint32_t group = dispatchGroup (aarch64_get_instr (cpu));
13398      assert  group == GROUP_BREXSYS_1010 || group == GROUP_BREXSYS_1011
13399      bits [31,29] of a BrExSys are the secondary dispatch vector.  */
13400   uint32_t group2 = dispatchBrExSys (aarch64_get_instr (cpu));
13401
13402   switch (group2)
13403     {
13404     case BR_IMM_000:
13405       return dexBranchImmediate (cpu);
13406
13407     case BR_IMMCMP_001:
13408       /* Compare has bit 25 clear while test has it set.  */
13409       if (!uimm (aarch64_get_instr (cpu), 25, 25))
13410         dexCompareBranchImmediate (cpu);
13411       else
13412         dexTestBranchImmediate (cpu);
13413       return;
13414
13415     case BR_IMMCOND_010:
13416       /* This is a conditional branch if bit 25 is clear otherwise
13417          unallocated.  */
13418       if (!uimm (aarch64_get_instr (cpu), 25, 25))
13419         dexCondBranchImmediate (cpu);
13420       else
13421         HALT_UNALLOC;
13422       return;
13423
13424     case BR_UNALLOC_011:
13425       HALT_UNALLOC;
13426
13427     case BR_IMM_100:
13428       dexBranchImmediate (cpu);
13429       return;
13430
13431     case BR_IMMCMP_101:
13432       /* Compare has bit 25 clear while test has it set.  */
13433       if (!uimm (aarch64_get_instr (cpu), 25, 25))
13434         dexCompareBranchImmediate (cpu);
13435       else
13436         dexTestBranchImmediate (cpu);
13437       return;
13438
13439     case BR_REG_110:
13440       /* Unconditional branch reg has bit 25 set.  */
13441       if (uimm (aarch64_get_instr (cpu), 25, 25))
13442         dexBranchRegister (cpu);
13443
13444       /* This includes both Excpn Gen, System and unalloc operations.
13445          We need to decode the Excpn Gen operation BRK so we can plant
13446          debugger entry points.
13447          Excpn Gen operations have aarch64_get_instr (cpu)[24] = 0.
13448          we need to decode at least one of the System operations NOP
13449          which is an alias for HINT #0.
13450          System operations have aarch64_get_instr (cpu)[24,22] = 100.  */
13451       else if (uimm (aarch64_get_instr (cpu), 24, 24) == 0)
13452         dexExcpnGen (cpu);
13453
13454       else if (uimm (aarch64_get_instr (cpu), 24, 22) == 4)
13455         dexSystem (cpu);
13456
13457       else
13458         HALT_UNALLOC;
13459
13460       return;
13461
13462     case BR_UNALLOC_111:
13463       HALT_UNALLOC;
13464
13465     default:
13466       /* Should never reach here.  */
13467       HALT_NYI;
13468     }
13469 }
13470
13471 static void
13472 aarch64_decode_and_execute (sim_cpu *cpu, uint64_t pc)
13473 {
13474   /* We need to check if gdb wants an in here.  */
13475   /* checkBreak (cpu);.  */
13476
13477   uint64_t group = dispatchGroup (aarch64_get_instr (cpu));
13478
13479   switch (group)
13480     {
13481     case GROUP_PSEUDO_0000:   dexPseudo (cpu); break;
13482     case GROUP_LDST_0100:     dexLdSt (cpu); break;
13483     case GROUP_DPREG_0101:    dexDPReg (cpu); break;
13484     case GROUP_LDST_0110:     dexLdSt (cpu); break;
13485     case GROUP_ADVSIMD_0111:  dexAdvSIMD0 (cpu); break;
13486     case GROUP_DPIMM_1000:    dexDPImm (cpu); break;
13487     case GROUP_DPIMM_1001:    dexDPImm (cpu); break;
13488     case GROUP_BREXSYS_1010:  dexBr (cpu); break;
13489     case GROUP_BREXSYS_1011:  dexBr (cpu); break;
13490     case GROUP_LDST_1100:     dexLdSt (cpu); break;
13491     case GROUP_DPREG_1101:    dexDPReg (cpu); break;
13492     case GROUP_LDST_1110:     dexLdSt (cpu); break;
13493     case GROUP_ADVSIMD_1111:  dexAdvSIMD1 (cpu); break;
13494
13495     case GROUP_UNALLOC_0001:
13496     case GROUP_UNALLOC_0010:
13497     case GROUP_UNALLOC_0011:
13498       HALT_UNALLOC;
13499
13500     default:
13501       /* Should never reach here.  */
13502       HALT_NYI;
13503     }
13504 }
13505
13506 static bfd_boolean
13507 aarch64_step (sim_cpu *cpu)
13508 {
13509   uint64_t pc = aarch64_get_PC (cpu);
13510
13511   if (pc == TOP_LEVEL_RETURN_PC)
13512     return FALSE;
13513
13514   aarch64_set_next_PC (cpu, pc + 4);
13515   aarch64_get_instr (cpu) = aarch64_get_mem_u32 (cpu, pc);
13516
13517   TRACE_INSN (cpu, " pc = %" PRIx64 " instr = %08x", pc,
13518               aarch64_get_instr (cpu));
13519   TRACE_DISASM (cpu, pc);
13520
13521   aarch64_decode_and_execute (cpu, pc);
13522
13523   return TRUE;
13524 }
13525
13526 void
13527 aarch64_run (SIM_DESC sd)
13528 {
13529   sim_cpu *cpu = STATE_CPU (sd, 0);
13530
13531   while (aarch64_step (cpu))
13532     aarch64_update_PC (cpu);
13533
13534   sim_engine_halt (sd, NULL, NULL, aarch64_get_PC (cpu),
13535                    sim_exited, aarch64_get_reg_s32 (cpu, R0, SP_OK));
13536 }
13537
13538 void
13539 aarch64_init (sim_cpu *cpu, uint64_t pc)
13540 {
13541   uint64_t sp = aarch64_get_stack_start (cpu);
13542
13543   /* Install SP, FP and PC and set LR to -20
13544      so we can detect a top-level return.  */
13545   aarch64_set_reg_u64 (cpu, SP, SP_OK, sp);
13546   aarch64_set_reg_u64 (cpu, FP, SP_OK, sp);
13547   aarch64_set_reg_u64 (cpu, LR, SP_OK, TOP_LEVEL_RETURN_PC);
13548   aarch64_set_next_PC (cpu, pc);
13549   aarch64_update_PC (cpu);
13550   aarch64_init_LIT_table ();
13551 }