sim: bfin: stricter insn decoding
[external/binutils.git] / sim / bfin / bfin-sim.c
1 /* Simulator for Analog Devices Blackfin processors.
2
3    Copyright (C) 2005-2013 Free Software Foundation, Inc.
4    Contributed by Analog Devices, Inc.
5
6    This file is part of simulators.
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
21 #include "config.h"
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <inttypes.h>
27
28 #include "opcode/bfin.h"
29 #include "sim-main.h"
30 #include "dv-bfin_cec.h"
31 #include "dv-bfin_mmu.h"
32
33 #define HOST_LONG_WORD_SIZE (sizeof (long) * 8)
34
35 #define SIGNEXTEND(v, n) \
36   (((bs32)(v) << (HOST_LONG_WORD_SIZE - (n))) >> (HOST_LONG_WORD_SIZE - (n)))
37
38 static __attribute__ ((noreturn)) void
39 illegal_instruction (SIM_CPU *cpu)
40 {
41   TRACE_INSN (cpu, "ILLEGAL INSTRUCTION");
42   while (1)
43     cec_exception (cpu, VEC_UNDEF_I);
44 }
45
46 static __attribute__ ((noreturn)) void
47 illegal_instruction_combination (SIM_CPU *cpu)
48 {
49   TRACE_INSN (cpu, "ILLEGAL INSTRUCTION COMBINATION");
50   while (1)
51     cec_exception (cpu, VEC_ILGAL_I);
52 }
53
54 static __attribute__ ((noreturn)) void
55 illegal_instruction_or_combination (SIM_CPU *cpu)
56 {
57   if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
58     illegal_instruction_combination (cpu);
59   else
60     illegal_instruction (cpu);
61 }
62
63 static __attribute__ ((noreturn)) void
64 unhandled_instruction (SIM_CPU *cpu, const char *insn)
65 {
66   SIM_DESC sd = CPU_STATE (cpu);
67   bu16 iw0, iw1;
68   bu32 iw2;
69
70   TRACE_EVENTS (cpu, "unhandled instruction");
71
72   iw0 = IFETCH (PCREG);
73   iw1 = IFETCH (PCREG + 2);
74   iw2 = ((bu32)iw0 << 16) | iw1;
75
76   sim_io_eprintf (sd, "Unhandled instruction at 0x%08x (%s opcode 0x", PCREG, insn);
77   if ((iw0 & 0xc000) == 0xc000)
78     sim_io_eprintf (sd, "%08x", iw2);
79   else
80     sim_io_eprintf (sd, "%04x", iw0);
81
82   sim_io_eprintf (sd, ") ... aborting\n");
83
84   illegal_instruction (cpu);
85 }
86
87 static const char * const astat_names[] =
88 {
89   [ 0] = "AZ",
90   [ 1] = "AN",
91   [ 2] = "AC0_COPY",
92   [ 3] = "V_COPY",
93   [ 4] = "ASTAT_4",
94   [ 5] = "CC",
95   [ 6] = "AQ",
96   [ 7] = "ASTAT_7",
97   [ 8] = "RND_MOD",
98   [ 9] = "ASTAT_9",
99   [10] = "ASTAT_10",
100   [11] = "ASTAT_11",
101   [12] = "AC0",
102   [13] = "AC1",
103   [14] = "ASTAT_14",
104   [15] = "ASTAT_15",
105   [16] = "AV0",
106   [17] = "AV0S",
107   [18] = "AV1",
108   [19] = "AV1S",
109   [20] = "ASTAT_20",
110   [21] = "ASTAT_21",
111   [22] = "ASTAT_22",
112   [23] = "ASTAT_23",
113   [24] = "V",
114   [25] = "VS",
115   [26] = "ASTAT_26",
116   [27] = "ASTAT_27",
117   [28] = "ASTAT_28",
118   [29] = "ASTAT_29",
119   [30] = "ASTAT_30",
120   [31] = "ASTAT_31",
121 };
122
123 typedef enum
124 {
125   c_0, c_1, c_4, c_2, c_uimm2, c_uimm3, c_imm3, c_pcrel4,
126   c_imm4, c_uimm4s4, c_uimm4s4d, c_uimm4, c_uimm4s2, c_negimm5s4, c_imm5,
127   c_imm5d, c_uimm5, c_imm6, c_imm7, c_imm7d, c_imm8, c_uimm8, c_pcrel8,
128   c_uimm8s4, c_pcrel8s4, c_lppcrel10, c_pcrel10, c_pcrel12, c_imm16s4,
129   c_luimm16, c_imm16, c_imm16d, c_huimm16, c_rimm16, c_imm16s2, c_uimm16s4,
130   c_uimm16s4d, c_uimm16, c_pcrel24, c_uimm32, c_imm32, c_huimm32, c_huimm32e,
131 } const_forms_t;
132
133 static const struct
134 {
135   const char *name;
136   const int nbits;
137   const char reloc;
138   const char issigned;
139   const char pcrel;
140   const char scale;
141   const char offset;
142   const char negative;
143   const char positive;
144   const char decimal;
145   const char leading;
146   const char exact;
147 } constant_formats[] =
148 {
149   { "0",          0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
150   { "1",          0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
151   { "4",          0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
152   { "2",          0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
153   { "uimm2",      2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
154   { "uimm3",      3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
155   { "imm3",       3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
156   { "pcrel4",     4, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0},
157   { "imm4",       4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
158   { "uimm4s4",    4, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0},
159   { "uimm4s4d",   4, 0, 0, 0, 2, 0, 0, 1, 1, 0, 0},
160   { "uimm4",      4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
161   { "uimm4s2",    4, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0},
162   { "negimm5s4",  5, 0, 1, 0, 2, 0, 1, 0, 0, 0, 0},
163   { "imm5",       5, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
164   { "imm5d",      5, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0},
165   { "uimm5",      5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
166   { "imm6",       6, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
167   { "imm7",       7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
168   { "imm7d",      7, 0, 1, 0, 0, 0, 0, 0, 1, 3, 0},
169   { "imm8",       8, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
170   { "uimm8",      8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
171   { "pcrel8",     8, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0},
172   { "uimm8s4",    8, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0},
173   { "pcrel8s4",   8, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0},
174   { "lppcrel10", 10, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0},
175   { "pcrel10",   10, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
176   { "pcrel12",   12, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
177   { "imm16s4",   16, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0},
178   { "luimm16",   16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
179   { "imm16",     16, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
180   { "imm16d",    16, 0, 1, 0, 0, 0, 0, 0, 1, 3, 0},
181   { "huimm16",   16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
182   { "rimm16",    16, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0},
183   { "imm16s2",   16, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0},
184   { "uimm16s4",  16, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0},
185   { "uimm16s4d", 16, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0},
186   { "uimm16",    16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
187   { "pcrel24",   24, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
188   { "uimm32",    32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
189   { "imm32",     32, 0, 1, 0, 0, 0, 0, 0, 1, 3, 0},
190   { "huimm32",   32, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
191   { "huimm32e",  32, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
192 };
193
194 static const char *
195 fmtconst_str (const_forms_t cf, bs32 x, bu32 pc)
196 {
197   static char buf[60];
198
199   if (constant_formats[cf].reloc)
200     {
201       bu32 ea = (((constant_formats[cf].pcrel ? SIGNEXTEND (x, constant_formats[cf].nbits)
202                       : x) + constant_formats[cf].offset) << constant_formats[cf].scale);
203       if (constant_formats[cf].pcrel)
204         ea += pc;
205      /*if (outf->symbol_at_address_func (ea, outf) || !constant_formats[cf].exact)
206        {
207           outf->print_address_func (ea, outf);
208           return "";
209        }
210      else*/
211        {
212           sprintf (buf, "%#x", x);
213           return buf;
214        }
215     }
216
217   /* Negative constants have an implied sign bit.  */
218   if (constant_formats[cf].negative)
219     {
220       int nb = constant_formats[cf].nbits + 1;
221
222       x = x | (1 << constant_formats[cf].nbits);
223       x = SIGNEXTEND (x, nb);
224     }
225   else
226     x = constant_formats[cf].issigned ? SIGNEXTEND (x, constant_formats[cf].nbits) : x;
227
228   if (constant_formats[cf].offset)
229     x += constant_formats[cf].offset;
230
231   if (constant_formats[cf].scale)
232     x <<= constant_formats[cf].scale;
233
234   if (constant_formats[cf].decimal)
235     sprintf (buf, "%*i", constant_formats[cf].leading, x);
236   else
237     {
238       if (constant_formats[cf].issigned && x < 0)
239         sprintf (buf, "-0x%x", abs (x));
240       else
241         sprintf (buf, "0x%x", x);
242     }
243
244   return buf;
245 }
246
247 static bu32
248 fmtconst_val (const_forms_t cf, bu32 x, bu32 pc)
249 {
250   if (0 && constant_formats[cf].reloc)
251     {
252       bu32 ea = (((constant_formats[cf].pcrel
253                    ? (bu32)SIGNEXTEND (x, constant_formats[cf].nbits)
254                    : x) + constant_formats[cf].offset)
255                  << constant_formats[cf].scale);
256       if (constant_formats[cf].pcrel)
257         ea += pc;
258
259       return ea;
260     }
261
262   /* Negative constants have an implied sign bit.  */
263   if (constant_formats[cf].negative)
264     {
265       int nb = constant_formats[cf].nbits + 1;
266       x = x | (1 << constant_formats[cf].nbits);
267       x = SIGNEXTEND (x, nb);
268     }
269   else if (constant_formats[cf].issigned)
270     x = SIGNEXTEND (x, constant_formats[cf].nbits);
271
272   x += constant_formats[cf].offset;
273   x <<= constant_formats[cf].scale;
274
275   return x;
276 }
277
278 #define uimm16s4(x)     fmtconst_val (c_uimm16s4, x, 0)
279 #define uimm16s4_str(x) fmtconst_str (c_uimm16s4, x, 0)
280 #define uimm16s4d(x)    fmtconst_val (c_uimm16s4d, x, 0)
281 #define pcrel4(x)       fmtconst_val (c_pcrel4, x, pc)
282 #define pcrel8(x)       fmtconst_val (c_pcrel8, x, pc)
283 #define pcrel8s4(x)     fmtconst_val (c_pcrel8s4, x, pc)
284 #define pcrel10(x)      fmtconst_val (c_pcrel10, x, pc)
285 #define pcrel12(x)      fmtconst_val (c_pcrel12, x, pc)
286 #define negimm5s4(x)    fmtconst_val (c_negimm5s4, x, 0)
287 #define negimm5s4_str(x)        fmtconst_str (c_negimm5s4, x, 0)
288 #define rimm16(x)       fmtconst_val (c_rimm16, x, 0)
289 #define huimm16(x)      fmtconst_val (c_huimm16, x, 0)
290 #define imm16(x)        fmtconst_val (c_imm16, x, 0)
291 #define imm16_str(x)    fmtconst_str (c_imm16, x, 0)
292 #define imm16d(x)       fmtconst_val (c_imm16d, x, 0)
293 #define uimm2(x)        fmtconst_val (c_uimm2, x, 0)
294 #define uimm3(x)        fmtconst_val (c_uimm3, x, 0)
295 #define uimm3_str(x)    fmtconst_str (c_uimm3, x, 0)
296 #define luimm16(x)      fmtconst_val (c_luimm16, x, 0)
297 #define luimm16_str(x)  fmtconst_str (c_luimm16, x, 0)
298 #define uimm4(x)        fmtconst_val (c_uimm4, x, 0)
299 #define uimm4_str(x)    fmtconst_str (c_uimm4, x, 0)
300 #define uimm5(x)        fmtconst_val (c_uimm5, x, 0)
301 #define uimm5_str(x)    fmtconst_str (c_uimm5, x, 0)
302 #define imm16s2(x)      fmtconst_val (c_imm16s2, x, 0)
303 #define imm16s2_str(x)  fmtconst_str (c_imm16s2, x, 0)
304 #define uimm8(x)        fmtconst_val (c_uimm8, x, 0)
305 #define imm16s4(x)      fmtconst_val (c_imm16s4, x, 0)
306 #define imm16s4_str(x)  fmtconst_str (c_imm16s4, x, 0)
307 #define uimm4s2(x)      fmtconst_val (c_uimm4s2, x, 0)
308 #define uimm4s2_str(x)  fmtconst_str (c_uimm4s2, x, 0)
309 #define uimm4s4(x)      fmtconst_val (c_uimm4s4, x, 0)
310 #define uimm4s4_str(x)  fmtconst_str (c_uimm4s4, x, 0)
311 #define uimm4s4d(x)     fmtconst_val (c_uimm4s4d, x, 0)
312 #define lppcrel10(x)    fmtconst_val (c_lppcrel10, x, pc)
313 #define imm3(x)         fmtconst_val (c_imm3, x, 0)
314 #define imm3_str(x)     fmtconst_str (c_imm3, x, 0)
315 #define imm4(x)         fmtconst_val (c_imm4, x, 0)
316 #define uimm8s4(x)      fmtconst_val (c_uimm8s4, x, 0)
317 #define imm5(x)         fmtconst_val (c_imm5, x, 0)
318 #define imm5d(x)        fmtconst_val (c_imm5d, x, 0)
319 #define imm6(x)         fmtconst_val (c_imm6, x, 0)
320 #define imm7(x)         fmtconst_val (c_imm7, x, 0)
321 #define imm7_str(x)     fmtconst_str (c_imm7, x, 0)
322 #define imm7d(x)        fmtconst_val (c_imm7d, x, 0)
323 #define imm8(x)         fmtconst_val (c_imm8, x, 0)
324 #define pcrel24(x)      fmtconst_val (c_pcrel24, x, pc)
325 #define pcrel24_str(x)  fmtconst_str (c_pcrel24, x, pc)
326 #define uimm16(x)       fmtconst_val (c_uimm16, x, 0)
327 #define uimm32(x)       fmtconst_val (c_uimm32, x, 0)
328 #define imm32(x)        fmtconst_val (c_imm32, x, 0)
329 #define huimm32(x)      fmtconst_val (c_huimm32, x, 0)
330 #define huimm32e(x)     fmtconst_val (c_huimm32e, x, 0)
331
332 /* Table C-4. Core Register Encoding Map.  */
333 const char * const greg_names[] =
334 {
335   "R0",    "R1",      "R2",     "R3",    "R4",    "R5",    "R6",     "R7",
336   "P0",    "P1",      "P2",     "P3",    "P4",    "P5",    "SP",     "FP",
337   "I0",    "I1",      "I2",     "I3",    "M0",    "M1",    "M2",     "M3",
338   "B0",    "B1",      "B2",     "B3",    "L0",    "L1",    "L2",     "L3",
339   "A0.X",  "A0.W",    "A1.X",   "A1.W",  "<res>", "<res>", "ASTAT",  "RETS",
340   "<res>", "<res>",   "<res>",  "<res>", "<res>", "<res>", "<res>",  "<res>",
341   "LC0",   "LT0",     "LB0",    "LC1",   "LT1",   "LB1",   "CYCLES", "CYCLES2",
342   "USP",   "SEQSTAT", "SYSCFG", "RETI",  "RETX",  "RETN",  "RETE",   "EMUDAT",
343 };
344 static const char *
345 get_allreg_name (int grp, int reg)
346 {
347   return greg_names[(grp << 3) | reg];
348 }
349 static const char *
350 get_preg_name (int reg)
351 {
352   return get_allreg_name (1, reg);
353 }
354
355 static bool
356 reg_is_reserved (int grp, int reg)
357 {
358   return (grp == 4 && (reg == 4 || reg == 5)) || (grp == 5);
359 }
360
361 static bu32 *
362 get_allreg (SIM_CPU *cpu, int grp, int reg)
363 {
364   int fullreg = (grp << 3) | reg;
365   /* REG_R0, REG_R1, REG_R2, REG_R3, REG_R4, REG_R5, REG_R6, REG_R7,
366      REG_P0, REG_P1, REG_P2, REG_P3, REG_P4, REG_P5, REG_SP, REG_FP,
367      REG_I0, REG_I1, REG_I2, REG_I3, REG_M0, REG_M1, REG_M2, REG_M3,
368      REG_B0, REG_B1, REG_B2, REG_B3, REG_L0, REG_L1, REG_L2, REG_L3,
369      REG_A0x, REG_A0w, REG_A1x, REG_A1w, , , REG_ASTAT, REG_RETS,
370      , , , , , , , ,
371      REG_LC0, REG_LT0, REG_LB0, REG_LC1, REG_LT1, REG_LB1, REG_CYCLES,
372      REG_CYCLES2,
373      REG_USP, REG_SEQSTAT, REG_SYSCFG, REG_RETI, REG_RETX, REG_RETN, REG_RETE,
374      REG_LASTREG  */
375   switch (fullreg >> 2)
376     {
377     case 0: case 1: return &DREG (reg);
378     case 2: case 3: return &PREG (reg);
379     case 4: return &IREG (reg & 3);
380     case 5: return &MREG (reg & 3);
381     case 6: return &BREG (reg & 3);
382     case 7: return &LREG (reg & 3);
383     default:
384       switch (fullreg)
385         {
386         case 32: return &AXREG (0);
387         case 33: return &AWREG (0);
388         case 34: return &AXREG (1);
389         case 35: return &AWREG (1);
390         case 39: return &RETSREG;
391         case 48: return &LCREG (0);
392         case 49: return &LTREG (0);
393         case 50: return &LBREG (0);
394         case 51: return &LCREG (1);
395         case 52: return &LTREG (1);
396         case 53: return &LBREG (1);
397         case 54: return &CYCLESREG;
398         case 55: return &CYCLES2REG;
399         case 56: return &USPREG;
400         case 57: return &SEQSTATREG;
401         case 58: return &SYSCFGREG;
402         case 59: return &RETIREG;
403         case 60: return &RETXREG;
404         case 61: return &RETNREG;
405         case 62: return &RETEREG;
406         case 63: return &EMUDAT_INREG;
407         }
408       illegal_instruction (cpu);
409     }
410 }
411
412 static const char *
413 amod0 (int s0, int x0)
414 {
415   static const char * const mod0[] = {
416     "", " (S)", " (CO)", " (SCO)",
417   };
418   int i = s0 + (x0 << 1);
419
420   if (i < ARRAY_SIZE (mod0))
421     return mod0[i];
422   else
423     return "";
424 }
425
426 static const char *
427 amod0amod2 (int s0, int x0, int aop0)
428 {
429   static const char * const mod02[] = {
430     "", " (S)", " (CO)", " (SCO)",
431     "", "", "", "",
432     " (ASR)", " (S, ASR)", " (CO, ASR)", " (SCO, ASR)",
433     " (ASL)", " (S, ASL)", " (CO, ASL)", " (SCO, ASL)",
434   };
435   int i = s0 + (x0 << 1) + (aop0 << 2);
436
437   if (i < ARRAY_SIZE (mod02))
438     return mod02[i];
439   else
440     return "";
441 }
442
443 static const char *
444 amod1 (int s0, int x0)
445 {
446   static const char * const mod1[] = {
447     " (NS)", " (S)",
448   };
449   int i = s0 + (x0 << 1);
450
451   if (i < ARRAY_SIZE (mod1))
452     return mod1[i];
453   else
454     return "";
455 }
456
457 static const char *
458 mac_optmode (int mmod, int MM)
459 {
460   static const char * const omode[] = {
461     [(M_S2RND << 1) + 0] = " (S2RND)",
462     [(M_T     << 1) + 0] = " (T)",
463     [(M_W32   << 1) + 0] = " (W32)",
464     [(M_FU    << 1) + 0] = " (FU)",
465     [(M_TFU   << 1) + 0] = " (TFU)",
466     [(M_IS    << 1) + 0] = " (IS)",
467     [(M_ISS2  << 1) + 0] = " (ISS2)",
468     [(M_IH    << 1) + 0] = " (IH)",
469     [(M_IU    << 1) + 0] = " (IU)",
470     [(M_S2RND << 1) + 1] = " (M, S2RND)",
471     [(M_T     << 1) + 1] = " (M, T)",
472     [(M_W32   << 1) + 1] = " (M, W32)",
473     [(M_FU    << 1) + 1] = " (M, FU)",
474     [(M_TFU   << 1) + 1] = " (M, TFU)",
475     [(M_IS    << 1) + 1] = " (M, IS)",
476     [(M_ISS2  << 1) + 1] = " (M, ISS2)",
477     [(M_IH    << 1) + 1] = " (M, IH)",
478     [(M_IU    << 1) + 1] = " (M, IU)",
479   };
480   int i = MM + (mmod << 1);
481
482   if (i < ARRAY_SIZE (omode) && omode[i])
483     return omode[i];
484   else
485     return "";
486 }
487
488 static const char *
489 get_store_name (SIM_CPU *cpu, bu32 *p)
490 {
491   if (p >= &DREG (0) && p <= &CYCLESREG)
492     return greg_names[p - &DREG (0)];
493   else if (p == &AXREG (0))
494     return greg_names[4 * 8 + 0];
495   else if (p == &AWREG (0))
496     return greg_names[4 * 8 + 1];
497   else if (p == &AXREG (1))
498     return greg_names[4 * 8 + 2];
499   else if (p == &AWREG (1))
500     return greg_names[4 * 8 + 3];
501   else if (p == &ASTATREG (av0))
502     return "ASTAT[av0]";
503   else if (p == &ASTATREG (av0s))
504     return "ASTAT[av0s]";
505   else if (p == &ASTATREG (av1))
506     return "ASTAT[av1]";
507   else if (p == &ASTATREG (av1s))
508     return "ASTAT[av1s]";
509   else if (p == &ASTATREG (v))
510     return "ASTAT[v]";
511   else if (p == &ASTATREG (vs))
512     return "ASTAT[vs]";
513   else if (p == &ASTATREG (v_copy))
514     return "ASTAT[v_copy]";
515   else if (p == &ASTATREG (az))
516     return "ASTAT[az]";
517   else if (p == &ASTATREG (an))
518     return "ASTAT[an]";
519   else if (p == &ASTATREG (az))
520     return "ASTAT[az]";
521   else if (p == &ASTATREG (ac0))
522     return "ASTAT[ac0]";
523   else if (p == &ASTATREG (ac0_copy))
524     return "ASTAT[ac0_copy]";
525   else
526     {
527       /* Worry about this when we start to STORE() it.  */
528       sim_io_eprintf (CPU_STATE (cpu), "STORE(): unknown register\n");
529       abort ();
530     }
531 }
532
533 static void
534 queue_store (SIM_CPU *cpu, bu32 *addr, bu32 val)
535 {
536   struct store *s = &BFIN_CPU_STATE.stores[BFIN_CPU_STATE.n_stores];
537   s->addr = addr;
538   s->val = val;
539   TRACE_REGISTER (cpu, "queuing write %s = %#x",
540                   get_store_name (cpu, addr), val);
541   ++BFIN_CPU_STATE.n_stores;
542 }
543 #define STORE(X, Y) \
544   do { \
545     if (BFIN_CPU_STATE.n_stores == 20) abort (); \
546     queue_store (cpu, &(X), (Y)); \
547   } while (0)
548
549 static void
550 setflags_nz (SIM_CPU *cpu, bu32 val)
551 {
552   SET_ASTATREG (az, val == 0);
553   SET_ASTATREG (an, val >> 31);
554 }
555
556 static void
557 setflags_nz_2x16 (SIM_CPU *cpu, bu32 val)
558 {
559   SET_ASTATREG (an, (bs16)val < 0 || (bs16)(val >> 16) < 0);
560   SET_ASTATREG (az, (bs16)val == 0 || (bs16)(val >> 16) == 0);
561 }
562
563 static void
564 setflags_logical (SIM_CPU *cpu, bu32 val)
565 {
566   setflags_nz (cpu, val);
567   SET_ASTATREG (ac0, 0);
568   SET_ASTATREG (v, 0);
569 }
570
571 static bu32
572 add_brev (bu32 addend1, bu32 addend2)
573 {
574   bu32 mask, b, r;
575   int i, cy;
576
577   mask = 0x80000000;
578   r = 0;
579   cy = 0;
580
581   for (i = 31; i >= 0; --i)
582     {
583       b = ((addend1 & mask) >> i) + ((addend2 & mask) >> i);
584       b += cy;
585       cy = b >> 1;
586       b &= 1;
587       r |= b << i;
588       mask >>= 1;
589     }
590
591   return r;
592 }
593
594 /* This is a bit crazy, but we want to simulate the hardware behavior exactly
595    rather than worry about the circular buffers being used correctly.  Which
596    isn't to say there isn't room for improvement here, just that we want to
597    be conservative.  See also dagsub().  */
598 static bu32
599 dagadd (SIM_CPU *cpu, int dagno, bs32 M)
600 {
601   bu64 i = IREG (dagno);
602   bu64 l = LREG (dagno);
603   bu64 b = BREG (dagno);
604   bu64 m = (bu32)M;
605
606   bu64 LB, IM, IML;
607   bu32 im32, iml32, lb32, res;
608   bu64 msb, car;
609
610   /* A naïve implementation that mostly works:
611   res = i + m;
612   if (l && res >= b + l)
613     res -= l;
614   STORE (IREG (dagno), res);
615    */
616
617   msb = (bu64)1 << 31;
618   car = (bu64)1 << 32;
619
620   IM = i + m;
621   im32 = IM;
622   LB = l + b;
623   lb32 = LB;
624
625   if (M < 0)
626     {
627       IML = i + m + l;
628       iml32 = IML;
629       if ((i & msb) || (IM & car))
630         res = (im32 < b) ? iml32 : im32;
631       else
632         res = (im32 < b) ? im32 : iml32;
633     }
634   else
635     {
636       IML = i + m - l;
637       iml32 = IML;
638       if ((IM & car) == (LB & car))
639         res = (im32 < lb32) ? im32 : iml32;
640       else
641         res = (im32 < lb32) ? iml32 : im32;
642     }
643
644   STORE (IREG (dagno), res);
645   return res;
646 }
647
648 /* See dagadd() notes above.  */
649 static bu32
650 dagsub (SIM_CPU *cpu, int dagno, bs32 M)
651 {
652   bu64 i = IREG (dagno);
653   bu64 l = LREG (dagno);
654   bu64 b = BREG (dagno);
655   bu64 m = (bu32)M;
656
657   bu64 mbar = (bu32)(~m + 1);
658   bu64 LB, IM, IML;
659   bu32 b32, im32, iml32, lb32, res;
660   bu64 msb, car;
661
662   /* A naïve implementation that mostly works:
663   res = i - m;
664   if (l && newi < b)
665     newi += l;
666   STORE (IREG (dagno), newi);
667    */
668
669   msb = (bu64)1 << 31;
670   car = (bu64)1 << 32;
671
672   IM = i + mbar;
673   im32 = IM;
674   LB = l + b;
675   lb32 = LB;
676
677   if (M < 0)
678     {
679       IML = i + mbar - l;
680       iml32 = IML;
681       if (!!((i & msb) && (IM & car)) == !!(LB & car))
682         res = (im32 < lb32) ? im32 : iml32;
683       else
684         res = (im32 < lb32) ? iml32 : im32;
685     }
686   else
687     {
688       IML = i + mbar + l;
689       iml32 = IML;
690       b32 = b;
691       if (M == 0 || IM & car)
692         res = (im32 < b32) ? iml32 : im32;
693       else
694         res = (im32 < b32) ? im32 : iml32;
695     }
696
697   STORE (IREG (dagno), res);
698   return res;
699 }
700
701 static bu40
702 ashiftrt (SIM_CPU *cpu, bu40 val, int cnt, int size)
703 {
704   int real_cnt = cnt > size ? size : cnt;
705   bu40 sgn = ~(((val & 0xFFFFFFFFFFull) >> (size - 1)) - 1);
706   int sgncnt = size - real_cnt;
707   if (sgncnt > 16)
708     sgn <<= 16, sgncnt -= 16;
709   sgn <<= sgncnt;
710   if (real_cnt > 16)
711     val >>= 16, real_cnt -= 16;
712   val >>= real_cnt;
713   val |= sgn;
714   SET_ASTATREG (an, val >> (size - 1));
715   SET_ASTATREG (az, val == 0);
716   if (size != 40)
717     SET_ASTATREG (v, 0);
718   return val;
719 }
720
721 static bu64
722 lshiftrt (SIM_CPU *cpu, bu64 val, int cnt, int size)
723 {
724   int real_cnt = cnt > size ? size : cnt;
725   if (real_cnt > 16)
726     val >>= 16, real_cnt -= 16;
727   val >>= real_cnt;
728   switch (size)
729     {
730     case 16:
731       val &= 0xFFFF;
732       break;
733     case 32:
734       val &= 0xFFFFFFFF;
735       break;
736     case 40:
737       val &= 0xFFFFFFFFFFull;
738       break;
739     default:
740       illegal_instruction (cpu);
741       break;
742     }
743   SET_ASTATREG (an, val >> (size - 1));
744   SET_ASTATREG (az, val == 0);
745   if (size != 40)
746     SET_ASTATREG (v, 0);
747   return val;
748 }
749
750 static bu64
751 lshift (SIM_CPU *cpu, bu64 val, int cnt, int size, bool saturate, bool overflow)
752 {
753   int v_i, real_cnt = cnt > size ? size : cnt;
754   bu64 sgn = ~((val >> (size - 1)) - 1);
755   int mask_cnt = size - 1;
756   bu64 masked, new_val = val;
757   bu64 mask = ~0;
758
759   mask <<= mask_cnt;
760   sgn <<= mask_cnt;
761   masked = val & mask;
762
763   if (real_cnt > 16)
764     new_val <<= 16, real_cnt -= 16;
765
766   new_val <<= real_cnt;
767
768   masked = new_val & mask;
769
770   /* If an operation would otherwise cause a positive value to overflow
771      and become negative, instead, saturation limits the result to the
772      maximum positive value for the size register being used.
773
774      Conversely, if an operation would otherwise cause a negative value
775      to overflow and become positive, saturation limits the result to the
776      maximum negative value for the register size.
777
778      However, it's a little more complex than looking at sign bits, we need
779      to see if we are shifting the sign information away...  */
780   if (((val << cnt) >> size) == 0
781       || (((val << cnt) >> size) == ~(~0 << cnt)
782           && ((new_val >> (size - 1)) & 0x1)))
783     v_i = 0;
784   else
785     v_i = 1;
786
787   switch (size)
788     {
789     case 16:
790       new_val &= 0xFFFF;
791       if (saturate && (v_i || ((val >> (size - 1)) != (new_val >> (size - 1)))))
792         {
793           new_val = (val >> (size - 1)) == 0 ? 0x7fff : 0x8000;
794           v_i = 1;
795         }
796       break;
797     case 32:
798       new_val &= 0xFFFFFFFF;
799       masked &= 0xFFFFFFFF;
800       sgn &= 0xFFFFFFFF;
801       if (saturate
802           && (v_i
803               || (sgn != masked)
804               || (!sgn && new_val == 0 && val != 0)))
805         {
806           new_val = sgn == 0 ? 0x7fffffff : 0x80000000;
807           v_i = 1;
808         }
809       break;
810     case 40:
811       new_val &= 0xFFFFFFFFFFull;
812       masked &= 0xFFFFFFFFFFull;
813       break;
814     default:
815       illegal_instruction (cpu);
816       break;
817     }
818
819   SET_ASTATREG (an, new_val >> (size - 1));
820   SET_ASTATREG (az, new_val == 0);
821   if (size != 40)
822     {
823       SET_ASTATREG (v, overflow && v_i);
824       if (overflow && v_i)
825         SET_ASTATREG (vs, 1);
826     }
827
828   return new_val;
829 }
830
831 static bu32
832 algn (bu32 l, bu32 h, bu32 aln)
833 {
834   if (aln == 0)
835     return l;
836   else
837     return (l >> (8 * aln)) | (h << (32 - 8 * aln));
838 }
839
840 static bu32
841 saturate_s16 (bu64 val, bu32 *overflow)
842 {
843   if ((bs64)val < -0x8000ll)
844     {
845       if (overflow)
846         *overflow = 1;
847       return 0x8000;
848     }
849   if ((bs64)val > 0x7fff)
850     {
851       if (overflow)
852         *overflow = 1;
853       return 0x7fff;
854     }
855   return val & 0xffff;
856 }
857
858 static bu40
859 rot40 (bu40 val, int shift, bu32 *cc)
860 {
861   const int nbits = 40;
862   bu40 ret;
863
864   shift = CLAMP (shift, -nbits, nbits);
865   if (shift == 0)
866     return val;
867
868   /* Reduce everything to rotate left.  */
869   if (shift < 0)
870     shift += nbits + 1;
871
872   ret = shift == nbits ? 0 : val << shift;
873   ret |= shift == 1 ? 0 : val >> ((nbits + 1) - shift);
874   ret |= (bu40)*cc << (shift - 1);
875   *cc = (val >> (nbits - shift)) & 1;
876
877   return ret;
878 }
879
880 static bu32
881 rot32 (bu32 val, int shift, bu32 *cc)
882 {
883   const int nbits = 32;
884   bu32 ret;
885
886   shift = CLAMP (shift, -nbits, nbits);
887   if (shift == 0)
888     return val;
889
890   /* Reduce everything to rotate left.  */
891   if (shift < 0)
892     shift += nbits + 1;
893
894   ret = shift == nbits ? 0 : val << shift;
895   ret |= shift == 1 ? 0 : val >> ((nbits + 1) - shift);
896   ret |= (bu32)*cc << (shift - 1);
897   *cc = (val >> (nbits - shift)) & 1;
898
899   return ret;
900 }
901
902 static bu32
903 add32 (SIM_CPU *cpu, bu32 a, bu32 b, int carry, int sat)
904 {
905   int flgs = (a >> 31) & 1;
906   int flgo = (b >> 31) & 1;
907   bu32 v = a + b;
908   int flgn = (v >> 31) & 1;
909   int overflow = (flgs ^ flgn) & (flgo ^ flgn);
910
911   if (sat && overflow)
912     {
913       v = (bu32)1 << 31;
914       if (flgn)
915         v -= 1;
916       flgn = (v >> 31) & 1;
917     }
918
919   SET_ASTATREG (an, flgn);
920   if (overflow)
921     SET_ASTATREG (vs, 1);
922   SET_ASTATREG (v, overflow);
923   ASTATREG (v_internal) |= overflow;
924   SET_ASTATREG (az, v == 0);
925   if (carry)
926     SET_ASTATREG (ac0, ~a < b);
927
928   return v;
929 }
930
931 static bu32
932 sub32 (SIM_CPU *cpu, bu32 a, bu32 b, int carry, int sat, int parallel)
933 {
934   int flgs = (a >> 31) & 1;
935   int flgo = (b >> 31) & 1;
936   bu32 v = a - b;
937   int flgn = (v >> 31) & 1;
938   int overflow = (flgs ^ flgo) & (flgn ^ flgs);
939
940   if (sat && overflow)
941     {
942       v = (bu32)1 << 31;
943       if (flgn)
944         v -= 1;
945       flgn = (v >> 31) & 1;
946     }
947
948   if (!parallel || flgn)
949     SET_ASTATREG (an, flgn);
950   if (overflow)
951     SET_ASTATREG (vs, 1);
952   if (!parallel || overflow)
953     SET_ASTATREG (v, overflow);
954   if (!parallel || overflow)
955     ASTATREG (v_internal) |= overflow;
956   if (!parallel || v == 0)
957     SET_ASTATREG (az, v == 0);
958   if (carry && (!parallel || b <= a))
959     SET_ASTATREG (ac0, b <= a);
960
961   return v;
962 }
963
964 static bu32
965 add16 (SIM_CPU *cpu, bu16 a, bu16 b, bu32 *carry, bu32 *overfl,
966        bu32 *zero, bu32 *neg, int sat, int scale)
967 {
968   int flgs = (a >> 15) & 1;
969   int flgo = (b >> 15) & 1;
970   bs64 v = (bs16)a + (bs16)b;
971   int flgn = (v >> 15) & 1;
972   int overflow = (flgs ^ flgn) & (flgo ^ flgn);
973
974   switch (scale)
975     {
976     case 0:
977       break;
978     case 2:
979       /* (ASR)  */
980       v = (a >> 1) + (a & 0x8000) + (b >> 1) + (b & 0x8000)
981           + (((a & 1) + (b & 1)) >> 1);
982       v |= -(v & 0x8000);
983       break;
984     case 3:
985       /* (ASL)  */
986       v = (v << 1);
987       break;
988     default:
989       illegal_instruction (cpu);
990     }
991
992   flgn = (v >> 15) & 1;
993   overflow = (flgs ^ flgn) & (flgo ^ flgn);
994
995   if (v > (bs64)0xffff)
996     overflow = 1;
997
998   if (sat)
999     v = saturate_s16 (v, 0);
1000
1001   if (neg)
1002     *neg |= (v >> 15) & 1;
1003   if (overfl)
1004     *overfl |= overflow;
1005   if (zero)
1006     *zero |= (v & 0xFFFF) == 0;
1007   if (carry)
1008       *carry |= ((bu16)~a < (bu16)b);
1009
1010   return v & 0xffff;
1011 }
1012
1013 static bu32
1014 sub16 (SIM_CPU *cpu, bu16 a, bu16 b, bu32 *carry, bu32 *overfl,
1015        bu32 *zero, bu32 *neg, int sat, int scale)
1016 {
1017   int flgs = (a >> 15) & 1;
1018   int flgo = (b >> 15) & 1;
1019   bs64 v = (bs16)a - (bs16)b;
1020   int flgn = (v >> 15) & 1;
1021   int overflow = (flgs ^ flgo) & (flgn ^ flgs);
1022
1023   switch (scale)
1024     {
1025     case 0:
1026       break;
1027     case 2:
1028       /* (ASR)  */
1029       if (sat)
1030         v = ((a >> 1) + (a & 0x8000)) - ( (b >> 1) + (b & 0x8000))
1031             + (((a & 1)-(b & 1)));
1032       else
1033         {
1034           v = ((v & 0xFFFF) >> 1);
1035           if ((!flgs & !flgo & flgn)
1036               || (flgs & !flgo & !flgn)
1037               || (flgs & flgo & flgn)
1038               || (flgs & !flgo & flgn))
1039             v |= 0x8000;
1040         }
1041       v |= -(v & 0x8000);
1042       flgn = (v >> 15) & 1;
1043       overflow = (flgs ^ flgo) & (flgn ^ flgs);
1044       break;
1045     case 3:
1046       /* (ASL)  */
1047       v <<= 1;
1048       if (v > (bs64)0x7fff || v < (bs64)-0xffff)
1049         overflow = 1;
1050       break;
1051     default:
1052       illegal_instruction (cpu);
1053     }
1054
1055   if (sat)
1056     {
1057       v = saturate_s16 (v, 0);
1058     }
1059   if (neg)
1060     *neg |= (v >> 15) & 1;
1061   if (zero)
1062     *zero |= (v & 0xFFFF) == 0;
1063   if (overfl)
1064     *overfl |= overflow;
1065   if (carry)
1066     *carry |= (bu16)b <= (bu16)a;
1067   return v;
1068 }
1069
1070 static bu32
1071 min32 (SIM_CPU *cpu, bu32 a, bu32 b)
1072 {
1073   int val = a;
1074   if ((bs32)a > (bs32)b)
1075     val = b;
1076   setflags_nz (cpu, val);
1077   SET_ASTATREG (v, 0);
1078   return val;
1079 }
1080
1081 static bu32
1082 max32 (SIM_CPU *cpu, bu32 a, bu32 b)
1083 {
1084   int val = a;
1085   if ((bs32)a < (bs32)b)
1086     val = b;
1087   setflags_nz (cpu, val);
1088   SET_ASTATREG (v, 0);
1089   return val;
1090 }
1091
1092 static bu32
1093 min2x16 (SIM_CPU *cpu, bu32 a, bu32 b)
1094 {
1095   int val = a;
1096   if ((bs16)a > (bs16)b)
1097     val = (val & 0xFFFF0000) | (b & 0xFFFF);
1098   if ((bs16)(a >> 16) > (bs16)(b >> 16))
1099     val = (val & 0xFFFF) | (b & 0xFFFF0000);
1100   setflags_nz_2x16 (cpu, val);
1101   SET_ASTATREG (v, 0);
1102   return val;
1103 }
1104
1105 static bu32
1106 max2x16 (SIM_CPU *cpu, bu32 a, bu32 b)
1107 {
1108   int val = a;
1109   if ((bs16)a < (bs16)b)
1110     val = (val & 0xFFFF0000) | (b & 0xFFFF);
1111   if ((bs16)(a >> 16) < (bs16)(b >> 16))
1112     val = (val & 0xFFFF) | (b & 0xFFFF0000);
1113   setflags_nz_2x16 (cpu, val);
1114   SET_ASTATREG (v, 0);
1115   return val;
1116 }
1117
1118 static bu32
1119 add_and_shift (SIM_CPU *cpu, bu32 a, bu32 b, int shift)
1120 {
1121   int v;
1122   ASTATREG (v_internal) = 0;
1123   v = add32 (cpu, a, b, 0, 0);
1124   while (shift-- > 0)
1125     {
1126       int x = (v >> 30) & 0x3;
1127       if (x == 1 || x == 2)
1128         ASTATREG (v_internal) = 1;
1129       v <<= 1;
1130     }
1131   SET_ASTATREG (az, v == 0);
1132   SET_ASTATREG (an, v & 0x80000000);
1133   SET_ASTATREG (v, ASTATREG (v_internal));
1134   if (ASTATREG (v))
1135     SET_ASTATREG (vs, 1);
1136   return v;
1137 }
1138
1139 static bu32
1140 xor_reduce (bu64 acc0, bu64 acc1)
1141 {
1142   int i;
1143   bu32 v = 0;
1144   for (i = 0; i < 40; ++i)
1145     {
1146       v ^= (acc0 & acc1 & 1);
1147       acc0 >>= 1;
1148       acc1 >>= 1;
1149     }
1150   return v;
1151 }
1152
1153 /* DIVS ( Dreg, Dreg ) ;
1154    Initialize for DIVQ.  Set the AQ status bit based on the signs of
1155    the 32-bit dividend and the 16-bit divisor.  Left shift the dividend
1156    one bit.  Copy AQ into the dividend LSB.  */
1157 static bu32
1158 divs (SIM_CPU *cpu, bu32 pquo, bu16 divisor)
1159 {
1160   bu16 r = pquo >> 16;
1161   int aq;
1162
1163   aq = (r ^ divisor) >> 15;  /* Extract msb's and compute quotient bit.  */
1164   SET_ASTATREG (aq, aq);     /* Update global quotient state.  */
1165
1166   pquo <<= 1;
1167   pquo |= aq;
1168   pquo = (pquo & 0x1FFFF) | (r << 17);
1169   return pquo;
1170 }
1171
1172 /* DIVQ ( Dreg, Dreg ) ;
1173    Based on AQ status bit, either add or subtract the divisor from
1174    the dividend.  Then set the AQ status bit based on the MSBs of the
1175    32-bit dividend and the 16-bit divisor.  Left shift the dividend one
1176    bit.  Copy the logical inverse of AQ into the dividend LSB.  */
1177 static bu32
1178 divq (SIM_CPU *cpu, bu32 pquo, bu16 divisor)
1179 {
1180   unsigned short af = pquo >> 16;
1181   unsigned short r;
1182   int aq;
1183
1184   if (ASTATREG (aq))
1185     r = divisor + af;
1186   else
1187     r = af - divisor;
1188
1189   aq = (r ^ divisor) >> 15;  /* Extract msb's and compute quotient bit.  */
1190   SET_ASTATREG (aq, aq);     /* Update global quotient state.  */
1191
1192   pquo <<= 1;
1193   pquo |= !aq;
1194   pquo = (pquo & 0x1FFFF) | (r << 17);
1195   return pquo;
1196 }
1197
1198 /* ONES ( Dreg ) ;
1199    Count the number of bits set to 1 in the 32bit value.  */
1200 static bu32
1201 ones (bu32 val)
1202 {
1203   bu32 i;
1204   bu32 ret;
1205
1206   ret = 0;
1207   for (i = 0; i < 32; ++i)
1208     ret += !!(val & (1 << i));
1209
1210   return ret;
1211 }
1212
1213 static void
1214 reg_check_sup (SIM_CPU *cpu, int grp, int reg)
1215 {
1216   if (grp == 7)
1217     cec_require_supervisor (cpu);
1218 }
1219
1220 static void
1221 reg_write (SIM_CPU *cpu, int grp, int reg, bu32 value)
1222 {
1223   bu32 *whichreg;
1224
1225   /* ASTAT is special!  */
1226   if (grp == 4 && reg == 6)
1227     {
1228       SET_ASTAT (value);
1229       return;
1230     }
1231
1232   /* Check supervisor after get_allreg() so exception order is correct.  */
1233   whichreg = get_allreg (cpu, grp, reg);
1234   reg_check_sup (cpu, grp, reg);
1235
1236   if (whichreg == &CYCLES2REG)
1237     /* Writes to CYCLES2 goes to the shadow.  */
1238     whichreg = &CYCLES2SHDREG;
1239   else if (whichreg == &SEQSTATREG)
1240     /* Register is read only -- discard writes.  */
1241     return;
1242   else if (whichreg == &EMUDAT_INREG)
1243     /* Writes to EMUDAT goes to the output.  */
1244     whichreg = &EMUDAT_OUTREG;
1245   else if (whichreg == &LTREG (0) || whichreg == &LTREG (1))
1246     /* Writes to LT clears LSB automatically.  */
1247     value &= ~0x1;
1248   else if (whichreg == &AXREG (0) || whichreg == &AXREG (1))
1249     value &= 0xFF;
1250
1251   TRACE_REGISTER (cpu, "wrote %s = %#x", get_allreg_name (grp, reg), value);
1252
1253   *whichreg = value;
1254 }
1255
1256 static bu32
1257 reg_read (SIM_CPU *cpu, int grp, int reg)
1258 {
1259   bu32 *whichreg;
1260   bu32 value;
1261
1262   /* ASTAT is special!  */
1263   if (grp == 4 && reg == 6)
1264     return ASTAT;
1265
1266   /* Check supervisor after get_allreg() so exception order is correct.  */
1267   whichreg = get_allreg (cpu, grp, reg);
1268   reg_check_sup (cpu, grp, reg);
1269
1270   value = *whichreg;
1271
1272   if (whichreg == &CYCLESREG)
1273     /* Reads of CYCLES reloads CYCLES2 from the shadow.  */
1274     SET_CYCLES2REG (CYCLES2SHDREG);
1275   else if ((whichreg == &AXREG (1) || whichreg == &AXREG (0)) && (value & 0x80))
1276     /* Sign extend if necessary.  */
1277     value |= 0xFFFFFF00;
1278
1279   return value;
1280 }
1281
1282 static bu64
1283 get_extended_cycles (SIM_CPU *cpu)
1284 {
1285   return ((bu64)CYCLES2SHDREG << 32) | CYCLESREG;
1286 }
1287
1288 /* We can't re-use sim_events_time() because the CYCLES registers may be
1289    written/cleared/reset/stopped/started at any time by software.  */
1290 static void
1291 cycles_inc (SIM_CPU *cpu, bu32 inc)
1292 {
1293   bu64 cycles;
1294   bu32 cycles2;
1295
1296   if (!(SYSCFGREG & SYSCFG_CCEN))
1297     return;
1298
1299   cycles = get_extended_cycles (cpu) + inc;
1300   SET_CYCLESREG (cycles);
1301   cycles2 = cycles >> 32;
1302   if (CYCLES2SHDREG != cycles2)
1303     SET_CYCLES2SHDREG (cycles2);
1304 }
1305
1306 static bu64
1307 get_unextended_acc (SIM_CPU *cpu, int which)
1308 {
1309   return ((bu64)(AXREG (which) & 0xff) << 32) | AWREG (which);
1310 }
1311
1312 static bu64
1313 get_extended_acc (SIM_CPU *cpu, int which)
1314 {
1315   bu64 acc = AXREG (which);
1316   /* Sign extend accumulator values before adding.  */
1317   if (acc & 0x80)
1318     acc |= -0x80;
1319   else
1320     acc &= 0xFF;
1321   acc <<= 32;
1322   acc |= AWREG (which);
1323   return acc;
1324 }
1325
1326 /* Perform a multiplication of D registers SRC0 and SRC1, sign- or
1327    zero-extending the result to 64 bit.  H0 and H1 determine whether the
1328    high part or the low part of the source registers is used.  Store 1 in
1329    *PSAT if saturation occurs, 0 otherwise.  */
1330 static bu64
1331 decode_multfunc (SIM_CPU *cpu, int h0, int h1, int src0, int src1, int mmod,
1332                  int MM, bu32 *psat)
1333 {
1334   bu32 s0 = DREG (src0), s1 = DREG (src1);
1335   bu32 sgn0, sgn1;
1336   bu32 val;
1337   bu64 val1;
1338
1339   if (h0)
1340     s0 >>= 16;
1341
1342   if (h1)
1343     s1 >>= 16;
1344
1345   s0 &= 0xffff;
1346   s1 &= 0xffff;
1347
1348   sgn0 = -(s0 & 0x8000);
1349   sgn1 = -(s1 & 0x8000);
1350
1351   if (MM)
1352     s0 |= sgn0;
1353   else
1354     switch (mmod)
1355       {
1356       case 0:
1357       case M_S2RND:
1358       case M_T:
1359       case M_IS:
1360       case M_ISS2:
1361       case M_IH:
1362       case M_W32:
1363         s0 |= sgn0;
1364         s1 |= sgn1;
1365         break;
1366       case M_FU:
1367       case M_IU:
1368       case M_TFU:
1369         break;
1370       default:
1371         illegal_instruction (cpu);
1372       }
1373
1374   val = s0 * s1;
1375   /* Perform shift correction if appropriate for the mode.  */
1376   *psat = 0;
1377   if (!MM && (mmod == 0 || mmod == M_T || mmod == M_S2RND || mmod == M_W32))
1378     {
1379       if (val == 0x40000000)
1380         {
1381           if (mmod == M_W32)
1382             val = 0x7fffffff;
1383           else
1384             val = 0x80000000;
1385           *psat = 1;
1386         }
1387       else
1388         val <<= 1;
1389     }
1390   val1 = val;
1391
1392   /* In signed modes, sign extend.  */
1393   if (is_macmod_signed (mmod) || MM)
1394     val1 |= -(val1 & 0x80000000);
1395
1396   if (*psat)
1397     val1 &= 0xFFFFFFFFull;
1398
1399   return val1;
1400 }
1401
1402 static bu40
1403 saturate_s40_astat (bu64 val, bu32 *v)
1404 {
1405   if ((bs64)val < -((bs64)1 << 39))
1406     {
1407       *v = 1;
1408       return -((bs64)1 << 39);
1409     }
1410   else if ((bs64)val > ((bs64)1 << 39) - 1)
1411     {
1412       *v = 1;
1413       return ((bu64)1 << 39) - 1;
1414     }
1415   *v = 0; /* No overflow.  */
1416   return val;
1417 }
1418
1419 static bu40
1420 saturate_s40 (bu64 val)
1421 {
1422   bu32 v;
1423   return saturate_s40_astat (val, &v);
1424 }
1425
1426 static bu32
1427 saturate_s32 (bu64 val, bu32 *overflow)
1428 {
1429   if ((bs64)val < -0x80000000ll)
1430     {
1431       if (overflow)
1432         *overflow = 1;
1433       return 0x80000000;
1434     }
1435   if ((bs64)val > 0x7fffffff)
1436     {
1437       if (overflow)
1438         *overflow = 1;
1439       return 0x7fffffff;
1440     }
1441   return val;
1442 }
1443
1444 static bu32
1445 saturate_u32 (bu64 val, bu32 *overflow)
1446 {
1447   if (val > 0xffffffff)
1448     {
1449       if (overflow)
1450         *overflow = 1;
1451       return 0xffffffff;
1452     }
1453   return val;
1454 }
1455
1456 static bu32
1457 saturate_u16 (bu64 val, bu32 *overflow)
1458 {
1459   if (val > 0xffff)
1460     {
1461       if (overflow)
1462         *overflow = 1;
1463       return 0xffff;
1464     }
1465   return val;
1466 }
1467
1468 static bu64
1469 rnd16 (bu64 val)
1470 {
1471   bu64 sgnbits;
1472
1473   /* FIXME: Should honour rounding mode.  */
1474   if ((val & 0xffff) > 0x8000
1475       || ((val & 0xffff) == 0x8000 && (val & 0x10000)))
1476     val += 0x8000;
1477
1478   sgnbits = val & 0xffff000000000000ull;
1479   val >>= 16;
1480   return val | sgnbits;
1481 }
1482
1483 static bu64
1484 trunc16 (bu64 val)
1485 {
1486   bu64 sgnbits = val & 0xffff000000000000ull;
1487   val >>= 16;
1488   return val | sgnbits;
1489 }
1490
1491 static int
1492 signbits (bu64 val, int size)
1493 {
1494   bu64 mask = (bu64)1 << (size - 1);
1495   bu64 bit = val & mask;
1496   int count = 0;
1497   for (;;)
1498     {
1499       mask >>= 1;
1500       bit >>= 1;
1501       if (mask == 0)
1502         break;
1503       if ((val & mask) != bit)
1504         break;
1505       count++;
1506     }
1507   if (size == 40)
1508     count -= 8;
1509
1510   return count;
1511 }
1512
1513 /* Extract a 16 or 32 bit value from a 64 bit multiplication result.
1514    These 64 bits must be sign- or zero-extended properly from the source
1515    we want to extract, either a 32 bit multiply or a 40 bit accumulator.  */
1516
1517 static bu32
1518 extract_mult (SIM_CPU *cpu, bu64 res, int mmod, int MM,
1519               int fullword, bu32 *overflow)
1520 {
1521   if (fullword)
1522     switch (mmod)
1523       {
1524       case 0:
1525       case M_IS:
1526         return saturate_s32 (res, overflow);
1527       case M_IU:
1528         if (MM)
1529           return saturate_s32 (res, overflow);
1530         return saturate_u32 (res, overflow);
1531       case M_FU:
1532         if (MM)
1533           return saturate_s32 (res, overflow);
1534         return saturate_u32 (res, overflow);
1535       case M_S2RND:
1536       case M_ISS2:
1537         return saturate_s32 (res << 1, overflow);
1538       default:
1539         illegal_instruction (cpu);
1540       }
1541   else
1542     switch (mmod)
1543       {
1544       case 0:
1545       case M_W32:
1546       case M_IH:
1547         return saturate_s16 (rnd16 (res), overflow);
1548       case M_IS:
1549         return saturate_s16 (res, overflow);
1550       case M_FU:
1551         if (MM)
1552           return saturate_s16 (rnd16 (res), overflow);
1553         return saturate_u16 (rnd16 (res), overflow);
1554       case M_IU:
1555         if (MM)
1556           return saturate_s16 (res, overflow);
1557         return saturate_u16 (res, overflow);
1558
1559       case M_T:
1560         return saturate_s16 (trunc16 (res), overflow);
1561       case M_TFU:
1562         if (MM)
1563           return saturate_s16 (trunc16 (res), overflow);
1564         return saturate_u16 (trunc16 (res), overflow);
1565
1566       case M_S2RND:
1567         return saturate_s16 (rnd16 (res << 1), overflow);
1568       case M_ISS2:
1569         return saturate_s16 (res << 1, overflow);
1570       default:
1571         illegal_instruction (cpu);
1572       }
1573 }
1574
1575 static bu32
1576 decode_macfunc (SIM_CPU *cpu, int which, int op, int h0, int h1, int src0,
1577                 int src1, int mmod, int MM, int fullword, bu32 *overflow,
1578                 bu32 *neg)
1579 {
1580   bu64 acc;
1581   bu32 sat = 0, tsat, ret;
1582
1583   /* Sign extend accumulator if necessary, otherwise unsigned.  */
1584   if (is_macmod_signed (mmod) || MM)
1585     acc = get_extended_acc (cpu, which);
1586   else
1587     acc = get_unextended_acc (cpu, which);
1588
1589   if (op != 3)
1590     {
1591       bu8 sgn0 = (acc >> 31) & 1;
1592       bu8 sgn40 = (acc >> 39) & 1;
1593       bu40 nosat_acc;
1594
1595       /* This can't saturate, so we don't keep track of the sat flag.  */
1596       bu64 res = decode_multfunc (cpu, h0, h1, src0, src1, mmod,
1597                                   MM, &tsat);
1598
1599       /* Perform accumulation.  */
1600       switch (op)
1601         {
1602         case 0:
1603           acc = res;
1604           sgn0 = (acc >> 31) & 1;
1605           break;
1606         case 1:
1607           acc = acc + res;
1608           break;
1609         case 2:
1610           acc = acc - res;
1611           break;
1612         }
1613
1614       nosat_acc = acc;
1615       /* Saturate.  */
1616       switch (mmod)
1617         {
1618         case 0:
1619         case M_T:
1620         case M_IS:
1621         case M_ISS2:
1622         case M_S2RND:
1623           if ((bs64)acc < -((bs64)1 << 39))
1624             acc = -((bu64)1 << 39), sat = 1;
1625           else if ((bs64)acc > 0x7fffffffffll)
1626             acc = 0x7fffffffffull, sat = 1;
1627           break;
1628         case M_TFU:
1629           if (MM)
1630             {
1631               if ((bs64)acc < -((bs64)1 << 39))
1632                 acc = -((bu64)1 << 39), sat = 1;
1633               if ((bs64)acc > 0x7FFFFFFFFFll)
1634                 acc = 0x7FFFFFFFFFull, sat = 1;
1635             }
1636           else
1637             {
1638               if ((bs64)acc < 0)
1639                 acc = 0, sat = 1;
1640               if ((bs64)acc > 0xFFFFFFFFFFull)
1641                 acc = 0xFFFFFFFFFFull, sat = 1;
1642             }
1643           break;
1644         case M_IU:
1645           if (!MM && acc & 0x8000000000000000ull)
1646             acc = 0x0, sat = 1;
1647           if (!MM && acc > 0xFFFFFFFFFFull)
1648             acc = 0xFFFFFFFFFFull, sat = 1;
1649           if (MM && acc > 0xFFFFFFFFFFull)
1650             acc &= 0xFFFFFFFFFFull;
1651           if (acc & 0x8000000000ull)
1652             acc |= 0xffffff0000000000ull;
1653           break;
1654         case M_FU:
1655           if (MM)
1656             {
1657               if ((bs64)acc < -((bs64)1 << 39))
1658                 acc = -((bu64)1 << 39), sat = 1;
1659               if ((bs64)acc > 0x7FFFFFFFFFll)
1660                 acc = 0x7FFFFFFFFFull, sat = 1;
1661               else if (acc & 0x8000000000ull)
1662                 acc |= 0xffffff0000000000ull;
1663             }
1664           else
1665             {
1666               if ((bs64)acc < 0)
1667                 acc = 0x0, sat = 1;
1668               else if ((bs64)acc > (bs64)0xFFFFFFFFFFll)
1669                 acc = 0xFFFFFFFFFFull, sat = 1;
1670             }
1671           break;
1672         case M_IH:
1673           if ((bs64)acc < -0x80000000ll)
1674             acc = -0x80000000ull, sat = 1;
1675           else if ((bs64)acc > 0x7fffffffll)
1676             acc = 0x7fffffffull, sat = 1;
1677           break;
1678         case M_W32:
1679           /* check max negative value */
1680           if (sgn40 && ((acc >> 31) != 0x1ffffffff)
1681               && ((acc >> 31) != 0x0))
1682             acc = 0x80000000, sat = 1;
1683           if (!sat && !sgn40 && ((acc >> 31) != 0x0)
1684               && ((acc >> 31) != 0x1ffffffff))
1685             acc = 0x7FFFFFFF, sat = 1;
1686           acc &= 0xffffffff;
1687           if (acc & 0x80000000)
1688             acc |= 0xffffffff00000000ull;
1689           if (tsat)
1690             sat = 1;
1691           break;
1692         default:
1693           illegal_instruction (cpu);
1694         }
1695
1696       if (acc & 0x8000000000ull)
1697         *neg = 1;
1698
1699       STORE (AXREG (which), (acc >> 32) & 0xff);
1700       STORE (AWREG (which), acc & 0xffffffff);
1701       STORE (ASTATREG (av[which]), sat);
1702       if (sat)
1703         STORE (ASTATREG (avs[which]), sat);
1704
1705       /* Figure out the overflow bit.  */
1706       if (sat)
1707         {
1708           if (fullword)
1709             *overflow = 1;
1710           else
1711             ret = extract_mult (cpu, nosat_acc, mmod, MM, fullword, overflow);
1712         }
1713     }
1714
1715   ret = extract_mult (cpu, acc, mmod, MM, fullword, overflow);
1716
1717   if (!fullword)
1718     {
1719       if (ret & 0x8000)
1720         *neg = 1;
1721     }
1722   else
1723     {
1724       if (ret & 0x80000000)
1725         *neg = 1;
1726     }
1727
1728   return ret;
1729 }
1730
1731 bu32
1732 hwloop_get_next_pc (SIM_CPU *cpu, bu32 pc, bu32 insn_len)
1733 {
1734   int i;
1735
1736   if (insn_len == 0)
1737     return pc;
1738
1739   /* If our PC has reached the bottom of a hardware loop,
1740      move back up to the top of the hardware loop.  */
1741   for (i = 1; i >= 0; --i)
1742     if (LCREG (i) > 1 && pc == LBREG (i))
1743       {
1744         TRACE_BRANCH (cpu, pc, LTREG (i), i, "Hardware loop %i", i);
1745         return LTREG (i);
1746       }
1747
1748   return pc + insn_len;
1749 }
1750
1751 static void
1752 decode_ProgCtrl_0 (SIM_CPU *cpu, bu16 iw0, bu32 pc)
1753 {
1754   /* ProgCtrl
1755      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
1756      | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |.prgfunc.......|.poprnd........|
1757      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
1758   int poprnd  = ((iw0 >> ProgCtrl_poprnd_bits) & ProgCtrl_poprnd_mask);
1759   int prgfunc = ((iw0 >> ProgCtrl_prgfunc_bits) & ProgCtrl_prgfunc_mask);
1760
1761   TRACE_EXTRACT (cpu, "%s: poprnd:%i prgfunc:%i", __func__, poprnd, prgfunc);
1762
1763   if (prgfunc == 0 && poprnd == 0)
1764     {
1765       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_nop);
1766       TRACE_INSN (cpu, "NOP;");
1767     }
1768   else if (prgfunc == 1 && poprnd == 0)
1769     {
1770       bu32 newpc = RETSREG;
1771       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
1772       TRACE_INSN (cpu, "RTS;");
1773       IFETCH_CHECK (newpc);
1774       if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
1775         illegal_instruction_combination (cpu);
1776       TRACE_BRANCH (cpu, pc, newpc, -1, "RTS");
1777       SET_PCREG (newpc);
1778       BFIN_CPU_STATE.did_jump = true;
1779       CYCLE_DELAY = 5;
1780     }
1781   else if (prgfunc == 1 && poprnd == 1)
1782     {
1783       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
1784       TRACE_INSN (cpu, "RTI;");
1785       /* Do not do IFETCH_CHECK here -- LSB has special meaning.  */
1786       if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
1787         illegal_instruction_combination (cpu);
1788       cec_return (cpu, -1);
1789       CYCLE_DELAY = 5;
1790     }
1791   else if (prgfunc == 1 && poprnd == 2)
1792     {
1793       bu32 newpc = RETXREG;
1794       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
1795       TRACE_INSN (cpu, "RTX;");
1796       /* XXX: Not sure if this is what the hardware does.  */
1797       IFETCH_CHECK (newpc);
1798       if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
1799         illegal_instruction_combination (cpu);
1800       cec_return (cpu, IVG_EVX);
1801       CYCLE_DELAY = 5;
1802     }
1803   else if (prgfunc == 1 && poprnd == 3)
1804     {
1805       bu32 newpc = RETNREG;
1806       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
1807       TRACE_INSN (cpu, "RTN;");
1808       /* XXX: Not sure if this is what the hardware does.  */
1809       IFETCH_CHECK (newpc);
1810       if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
1811         illegal_instruction_combination (cpu);
1812       cec_return (cpu, IVG_NMI);
1813       CYCLE_DELAY = 5;
1814     }
1815   else if (prgfunc == 1 && poprnd == 4)
1816     {
1817       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
1818       TRACE_INSN (cpu, "RTE;");
1819       if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
1820         illegal_instruction_combination (cpu);
1821       cec_return (cpu, IVG_EMU);
1822       CYCLE_DELAY = 5;
1823     }
1824   else if (prgfunc == 2 && poprnd == 0)
1825     {
1826       SIM_DESC sd = CPU_STATE (cpu);
1827       sim_events *events = STATE_EVENTS (sd);
1828
1829       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_sync);
1830       /* XXX: in supervisor mode, utilizes wake up sources
1831          in user mode, it's a NOP ...  */
1832       TRACE_INSN (cpu, "IDLE;");
1833
1834       if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
1835         illegal_instruction_combination (cpu);
1836
1837       /* Timewarp !  */
1838       if (events->queue)
1839         CYCLE_DELAY = events->time_from_event;
1840       else
1841         abort (); /* XXX: Should this ever happen ?  */
1842     }
1843   else if (prgfunc == 2 && poprnd == 3)
1844     {
1845       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_sync);
1846       /* Just NOP it.  */
1847       TRACE_INSN (cpu, "CSYNC;");
1848       if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
1849         illegal_instruction_combination (cpu);
1850       CYCLE_DELAY = 10;
1851     }
1852   else if (prgfunc == 2 && poprnd == 4)
1853     {
1854       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_sync);
1855       /* Just NOP it.  */
1856       TRACE_INSN (cpu, "SSYNC;");
1857       if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
1858         illegal_instruction_combination (cpu);
1859
1860       /* Really 10+, but no model info for this.  */
1861       CYCLE_DELAY = 10;
1862     }
1863   else if (prgfunc == 2 && poprnd == 5)
1864     {
1865       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_cec);
1866       TRACE_INSN (cpu, "EMUEXCPT;");
1867       if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
1868         illegal_instruction_combination (cpu);
1869       cec_exception (cpu, VEC_SIM_TRAP);
1870     }
1871   else if (prgfunc == 3 && poprnd < 8)
1872     {
1873       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_cec);
1874       TRACE_INSN (cpu, "CLI R%i;", poprnd);
1875       if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
1876         illegal_instruction_combination (cpu);
1877       SET_DREG (poprnd, cec_cli (cpu));
1878     }
1879   else if (prgfunc == 4 && poprnd < 8)
1880     {
1881       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_cec);
1882       TRACE_INSN (cpu, "STI R%i;", poprnd);
1883       if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
1884         illegal_instruction_combination (cpu);
1885       cec_sti (cpu, DREG (poprnd));
1886       CYCLE_DELAY = 3;
1887     }
1888   else if (prgfunc == 5 && poprnd < 8)
1889     {
1890       bu32 newpc = PREG (poprnd);
1891       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
1892       TRACE_INSN (cpu, "JUMP (%s);", get_preg_name (poprnd));
1893       IFETCH_CHECK (newpc);
1894       if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
1895         illegal_instruction_combination (cpu);
1896       TRACE_BRANCH (cpu, pc, newpc, -1, "JUMP (Preg)");
1897       SET_PCREG (newpc);
1898       BFIN_CPU_STATE.did_jump = true;
1899       PROFILE_BRANCH_TAKEN (cpu);
1900       CYCLE_DELAY = 5;
1901     }
1902   else if (prgfunc == 6 && poprnd < 8)
1903     {
1904       bu32 newpc = PREG (poprnd);
1905       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
1906       TRACE_INSN (cpu, "CALL (%s);", get_preg_name (poprnd));
1907       IFETCH_CHECK (newpc);
1908       if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
1909         illegal_instruction_combination (cpu);
1910       TRACE_BRANCH (cpu, pc, newpc, -1, "CALL (Preg)");
1911       /* If we're at the end of a hardware loop, RETS is going to be
1912          the top of the loop rather than the next instruction.  */
1913       SET_RETSREG (hwloop_get_next_pc (cpu, pc, 2));
1914       SET_PCREG (newpc);
1915       BFIN_CPU_STATE.did_jump = true;
1916       PROFILE_BRANCH_TAKEN (cpu);
1917       CYCLE_DELAY = 5;
1918     }
1919   else if (prgfunc == 7 && poprnd < 8)
1920     {
1921       bu32 newpc = pc + PREG (poprnd);
1922       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
1923       TRACE_INSN (cpu, "CALL (PC + %s);", get_preg_name (poprnd));
1924       IFETCH_CHECK (newpc);
1925       if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
1926         illegal_instruction_combination (cpu);
1927       TRACE_BRANCH (cpu, pc, newpc, -1, "CALL (PC + Preg)");
1928       SET_RETSREG (hwloop_get_next_pc (cpu, pc, 2));
1929       SET_PCREG (newpc);
1930       BFIN_CPU_STATE.did_jump = true;
1931       PROFILE_BRANCH_TAKEN (cpu);
1932       CYCLE_DELAY = 5;
1933     }
1934   else if (prgfunc == 8 && poprnd < 8)
1935     {
1936       bu32 newpc = pc + PREG (poprnd);
1937       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
1938       TRACE_INSN (cpu, "JUMP (PC + %s);", get_preg_name (poprnd));
1939       IFETCH_CHECK (newpc);
1940       if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
1941         illegal_instruction_combination (cpu);
1942       TRACE_BRANCH (cpu, pc, newpc, -1, "JUMP (PC + Preg)");
1943       SET_PCREG (newpc);
1944       BFIN_CPU_STATE.did_jump = true;
1945       PROFILE_BRANCH_TAKEN (cpu);
1946       CYCLE_DELAY = 5;
1947     }
1948   else if (prgfunc == 9)
1949     {
1950       int raise = uimm4 (poprnd);
1951       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_cec);
1952       TRACE_INSN (cpu, "RAISE %s;", uimm4_str (raise));
1953       if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
1954         illegal_instruction_combination (cpu);
1955       cec_require_supervisor (cpu);
1956       if (raise == IVG_IVHW)
1957         cec_hwerr (cpu, HWERR_RAISE_5);
1958       else
1959         cec_latch (cpu, raise);
1960       CYCLE_DELAY = 3; /* XXX: Only if IVG is unmasked.  */
1961     }
1962   else if (prgfunc == 10)
1963     {
1964       int excpt = uimm4 (poprnd);
1965       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_cec);
1966       TRACE_INSN (cpu, "EXCPT %s;", uimm4_str (excpt));
1967       if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
1968         illegal_instruction_combination (cpu);
1969       cec_exception (cpu, excpt);
1970       CYCLE_DELAY = 3;
1971     }
1972   else if (prgfunc == 11 && poprnd < 6)
1973     {
1974       bu32 addr = PREG (poprnd);
1975       bu8 byte;
1976       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_atomic);
1977       TRACE_INSN (cpu, "TESTSET (%s);", get_preg_name (poprnd));
1978       if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
1979         illegal_instruction_combination (cpu);
1980       byte = GET_WORD (addr);
1981       SET_CCREG (byte == 0);
1982       PUT_BYTE (addr, byte | 0x80);
1983       /* Also includes memory stalls, but we don't model that.  */
1984       CYCLE_DELAY = 2;
1985     }
1986   else
1987     illegal_instruction_or_combination (cpu);
1988 }
1989
1990 static void
1991 decode_CaCTRL_0 (SIM_CPU *cpu, bu16 iw0)
1992 {
1993   /* CaCTRL
1994      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
1995      | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 |.a.|.op....|.reg.......|
1996      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
1997   int a   = ((iw0 >> CaCTRL_a_bits) & CaCTRL_a_mask);
1998   int op  = ((iw0 >> CaCTRL_op_bits) & CaCTRL_op_mask);
1999   int reg = ((iw0 >> CaCTRL_reg_bits) & CaCTRL_reg_mask);
2000   bu32 preg = PREG (reg);
2001   const char * const sinsn[] = { "PREFETCH", "FLUSHINV", "FLUSH", "IFLUSH", };
2002
2003   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_CaCTRL);
2004   TRACE_EXTRACT (cpu, "%s: a:%i op:%i reg:%i", __func__, a, op, reg);
2005   TRACE_INSN (cpu, "%s [%s%s];", sinsn[op], get_preg_name (reg), a ? "++" : "");
2006
2007   if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2008     /* None of these can be part of a parallel instruction.  */
2009     illegal_instruction_combination (cpu);
2010
2011   /* No cache simulation, so these are (mostly) all NOPs.
2012      XXX: The hardware takes care of masking to cache lines, but need
2013      to check behavior of the post increment.  Should we be aligning
2014      the value to the cache line before adding the cache line size, or
2015      do we just add the cache line size ?  */
2016   if (op == 0)
2017     {   /* PREFETCH  */
2018       mmu_check_cache_addr (cpu, preg, false, false);
2019     }
2020   else if (op == 1)
2021     {   /* FLUSHINV  */
2022       mmu_check_cache_addr (cpu, preg, true, false);
2023     }
2024   else if (op == 2)
2025     {   /* FLUSH  */
2026       mmu_check_cache_addr (cpu, preg, true, false);
2027     }
2028   else if (op == 3)
2029     {   /* IFLUSH  */
2030       mmu_check_cache_addr (cpu, preg, false, true);
2031     }
2032
2033   if (a)
2034     SET_PREG (reg, preg + BFIN_L1_CACHE_BYTES);
2035 }
2036
2037 static void
2038 decode_PushPopReg_0 (SIM_CPU *cpu, bu16 iw0)
2039 {
2040   /* PushPopReg
2041      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2042      | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |.W.|.grp.......|.reg.......|
2043      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
2044   int W   = ((iw0 >> PushPopReg_W_bits) & PushPopReg_W_mask);
2045   int grp = ((iw0 >> PushPopReg_grp_bits) & PushPopReg_grp_mask);
2046   int reg = ((iw0 >> PushPopReg_reg_bits) & PushPopReg_reg_mask);
2047   const char *reg_name = get_allreg_name (grp, reg);
2048   bu32 value;
2049   bu32 sp = SPREG;
2050
2051   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_PushPopReg);
2052   TRACE_EXTRACT (cpu, "%s: W:%i grp:%i reg:%i", __func__, W, grp, reg);
2053   TRACE_DECODE (cpu, "%s: reg:%s", __func__, reg_name);
2054
2055   /* Can't push/pop reserved registers  */
2056   if (reg_is_reserved (grp, reg))
2057     illegal_instruction_or_combination (cpu);
2058
2059   if (W == 0)
2060     {
2061       /* Dreg and Preg are not supported by this instruction.  */
2062       if (grp == 0 || grp == 1)
2063         illegal_instruction_or_combination (cpu);
2064       TRACE_INSN (cpu, "%s = [SP++];", reg_name);
2065       /* Can't pop USP while in userspace.  */
2066       if (PARALLEL_GROUP != BFIN_PARALLEL_NONE
2067           || (grp == 7 && reg == 0 && cec_is_user_mode(cpu)))
2068         illegal_instruction_combination (cpu);
2069       /* XXX: The valid register check is in reg_write(), so we might
2070               incorrectly do a GET_LONG() here ...  */
2071       value = GET_LONG (sp);
2072       reg_write (cpu, grp, reg, value);
2073       if (grp == 7 && reg == 3)
2074         cec_pop_reti (cpu);
2075
2076       sp += 4;
2077     }
2078   else
2079     {
2080       TRACE_INSN (cpu, "[--SP] = %s;", reg_name);
2081       if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2082         illegal_instruction_combination (cpu);
2083
2084       sp -= 4;
2085       value = reg_read (cpu, grp, reg);
2086       if (grp == 7 && reg == 3)
2087         cec_push_reti (cpu);
2088
2089       PUT_LONG (sp, value);
2090     }
2091
2092   /* Note: SP update must be delayed until after all reads/writes; see
2093            comments in decode_PushPopMultiple_0() for more info.  */
2094   SET_SPREG (sp);
2095 }
2096
2097 static void
2098 decode_PushPopMultiple_0 (SIM_CPU *cpu, bu16 iw0)
2099 {
2100   /* PushPopMultiple
2101      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2102      | 0 | 0 | 0 | 0 | 0 | 1 | 0 |.d.|.p.|.W.|.dr........|.pr........|
2103      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
2104   int p  = ((iw0 >> PushPopMultiple_p_bits) & PushPopMultiple_p_mask);
2105   int d  = ((iw0 >> PushPopMultiple_d_bits) & PushPopMultiple_d_mask);
2106   int W  = ((iw0 >> PushPopMultiple_W_bits) & PushPopMultiple_W_mask);
2107   int dr = ((iw0 >> PushPopMultiple_dr_bits) & PushPopMultiple_dr_mask);
2108   int pr = ((iw0 >> PushPopMultiple_pr_bits) & PushPopMultiple_pr_mask);
2109   int i;
2110   bu32 sp = SPREG;
2111
2112   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_PushPopMultiple);
2113   TRACE_EXTRACT (cpu, "%s: d:%i p:%i W:%i dr:%i pr:%i",
2114                  __func__, d, p, W, dr, pr);
2115
2116   if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2117     illegal_instruction_combination (cpu);
2118
2119   if ((d == 0 && p == 0) || (p && imm5 (pr) > 5)
2120       || (d && !p && pr) || (p && !d && dr))
2121     illegal_instruction (cpu);
2122
2123   if (W == 1)
2124     {
2125       if (d && p)
2126         TRACE_INSN (cpu, "[--SP] = (R7:%i, P5:%i);", dr, pr);
2127       else if (d)
2128         TRACE_INSN (cpu, "[--SP] = (R7:%i);", dr);
2129       else
2130         TRACE_INSN (cpu, "[--SP] = (P5:%i);", pr);
2131
2132       if (d)
2133         for (i = dr; i < 8; i++)
2134           {
2135             sp -= 4;
2136             PUT_LONG (sp, DREG (i));
2137           }
2138       if (p)
2139         for (i = pr; i < 6; i++)
2140           {
2141             sp -= 4;
2142             PUT_LONG (sp, PREG (i));
2143           }
2144
2145       CYCLE_DELAY = 14;
2146     }
2147   else
2148     {
2149       if (d && p)
2150         TRACE_INSN (cpu, "(R7:%i, P5:%i) = [SP++];", dr, pr);
2151       else if (d)
2152         TRACE_INSN (cpu, "(R7:%i) = [SP++];", dr);
2153       else
2154         TRACE_INSN (cpu, "(P5:%i) = [SP++];", pr);
2155
2156       if (p)
2157         for (i = 5; i >= pr; i--)
2158           {
2159             SET_PREG (i, GET_LONG (sp));
2160             sp += 4;
2161           }
2162       if (d)
2163         for (i = 7; i >= dr; i--)
2164           {
2165             SET_DREG (i, GET_LONG (sp));
2166             sp += 4;
2167           }
2168
2169       CYCLE_DELAY = 11;
2170     }
2171
2172   /* Note: SP update must be delayed until after all reads/writes so that
2173            if an exception does occur, the insn may be re-executed as the
2174            SP has not yet changed.  */
2175   SET_SPREG (sp);
2176 }
2177
2178 static void
2179 decode_ccMV_0 (SIM_CPU *cpu, bu16 iw0)
2180 {
2181   /* ccMV
2182      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2183      | 0 | 0 | 0 | 0 | 0 | 1 | 1 |.T.|.d.|.s.|.dst.......|.src.......|
2184      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
2185   int s  = ((iw0 >> CCmv_s_bits) & CCmv_s_mask);
2186   int d  = ((iw0 >> CCmv_d_bits) & CCmv_d_mask);
2187   int T  = ((iw0 >> CCmv_T_bits) & CCmv_T_mask);
2188   int src = ((iw0 >> CCmv_src_bits) & CCmv_src_mask);
2189   int dst = ((iw0 >> CCmv_dst_bits) & CCmv_dst_mask);
2190   int cond = T ? CCREG : ! CCREG;
2191
2192   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ccMV);
2193   TRACE_EXTRACT (cpu, "%s: T:%i d:%i s:%i dst:%i src:%i",
2194                  __func__, T, d, s, dst, src);
2195
2196   TRACE_INSN (cpu, "IF %sCC %s = %s;", T ? "" : "! ",
2197               get_allreg_name (d, dst),
2198               get_allreg_name (s, src));
2199   if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2200     illegal_instruction_combination (cpu);
2201
2202   if (cond)
2203     reg_write (cpu, d, dst, reg_read (cpu, s, src));
2204 }
2205
2206 static void
2207 decode_CCflag_0 (SIM_CPU *cpu, bu16 iw0)
2208 {
2209   /* CCflag
2210      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2211      | 0 | 0 | 0 | 0 | 1 |.I.|.opc.......|.G.|.y.........|.x.........|
2212      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
2213   int x = ((iw0 >> CCflag_x_bits) & CCflag_x_mask);
2214   int y = ((iw0 >> CCflag_y_bits) & CCflag_y_mask);
2215   int I = ((iw0 >> CCflag_I_bits) & CCflag_I_mask);
2216   int G = ((iw0 >> CCflag_G_bits) & CCflag_G_mask);
2217   int opc = ((iw0 >> CCflag_opc_bits) & CCflag_opc_mask);
2218
2219   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_CCflag);
2220   TRACE_EXTRACT (cpu, "%s: I:%i opc:%i G:%i y:%i x:%i",
2221                  __func__, I, opc, G, y, x);
2222
2223   if (opc > 4)
2224     {
2225       bs64 acc0 = get_extended_acc (cpu, 0);
2226       bs64 acc1 = get_extended_acc (cpu, 1);
2227       bs64 diff = acc0 - acc1;
2228
2229       if (x != 0 || y != 0)
2230         illegal_instruction_or_combination (cpu);
2231
2232       if (opc == 5 && I == 0 && G == 0)
2233         {
2234           TRACE_INSN (cpu, "CC = A0 == A1;");
2235           if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2236             illegal_instruction_combination (cpu);
2237           SET_CCREG (acc0 == acc1);
2238         }
2239       else if (opc == 6 && I == 0 && G == 0)
2240         {
2241           TRACE_INSN (cpu, "CC = A0 < A1");
2242           if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2243             illegal_instruction_combination (cpu);
2244           SET_CCREG (acc0 < acc1);
2245         }
2246       else if (opc == 7 && I == 0 && G == 0)
2247         {
2248           TRACE_INSN (cpu, "CC = A0 <= A1");
2249           if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2250             illegal_instruction_combination (cpu);
2251           SET_CCREG (acc0 <= acc1);
2252         }
2253       else
2254         illegal_instruction_or_combination (cpu);
2255
2256       SET_ASTATREG (az, diff == 0);
2257       SET_ASTATREG (an, diff < 0);
2258       SET_ASTATREG (ac0, (bu40)acc1 <= (bu40)acc0);
2259     }
2260   else
2261     {
2262       int issigned = opc < 3;
2263       const char *sign = issigned ? "" : " (IU)";
2264       bu32 srcop = G ? PREG (x) : DREG (x);
2265       char s = G ? 'P' : 'R';
2266       bu32 dstop = I ? (issigned ? imm3 (y) : uimm3 (y)) : G ? PREG (y) : DREG (y);
2267       const char *op;
2268       char d = G ? 'P' : 'R';
2269       int flgs = srcop >> 31;
2270       int flgo = dstop >> 31;
2271
2272       bu32 result = srcop - dstop;
2273       int cc;
2274       int flgn = result >> 31;
2275       int overflow = (flgs ^ flgo) & (flgn ^ flgs);
2276       int az = result == 0;
2277       int ac0 = dstop <= srcop;
2278       int an;
2279       if (issigned)
2280         an = (flgn && !overflow) || (!flgn && overflow);
2281       else
2282         an = dstop > srcop;
2283
2284       switch (opc)
2285         {
2286         default: /* Shutup useless gcc warnings.  */
2287         case 0: /* signed  */
2288           op = "==";
2289           cc = az;
2290           break;
2291         case 1: /* signed  */
2292           op = "<";
2293           cc = an;
2294           break;
2295         case 2: /* signed  */
2296           op = "<=";
2297           cc = an || az;
2298           break;
2299         case 3: /* unsigned  */
2300           op = "<";
2301           cc = !ac0;
2302           break;
2303         case 4: /* unsigned  */
2304           op = "<=";
2305           cc = !ac0 || az;
2306           break;
2307         }
2308
2309       if (I)
2310         TRACE_INSN (cpu, "CC = %c%i %s %s%s;", s, x, op,
2311                     issigned ? imm3_str (y) : uimm3_str (y), sign);
2312       else
2313         {
2314           TRACE_DECODE (cpu, "%s %c%i:%x %c%i:%x", __func__,
2315                         s, x, srcop,  d, y, dstop);
2316           TRACE_INSN (cpu, "CC = %c%i %s %c%i%s;", s, x, op, d, y, sign);
2317         }
2318
2319       if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2320         illegal_instruction_combination (cpu);
2321
2322       SET_CCREG (cc);
2323       /* Pointer compares only touch CC.  */
2324       if (!G)
2325         {
2326           SET_ASTATREG (az, az);
2327           SET_ASTATREG (an, an);
2328           SET_ASTATREG (ac0, ac0);
2329         }
2330     }
2331 }
2332
2333 static void
2334 decode_CC2dreg_0 (SIM_CPU *cpu, bu16 iw0)
2335 {
2336   /* CC2dreg
2337      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2338      | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |.op....|.reg.......|
2339      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
2340   int op  = ((iw0 >> CC2dreg_op_bits) & CC2dreg_op_mask);
2341   int reg = ((iw0 >> CC2dreg_reg_bits) & CC2dreg_reg_mask);
2342
2343   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_CC2dreg);
2344   TRACE_EXTRACT (cpu, "%s: op:%i reg:%i", __func__, op, reg);
2345
2346   if (op == 0)
2347     {
2348       TRACE_INSN (cpu, "R%i = CC;", reg);
2349       if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2350         illegal_instruction_combination (cpu);
2351       SET_DREG (reg, CCREG);
2352     }
2353   else if (op == 1)
2354     {
2355       TRACE_INSN (cpu, "CC = R%i;", reg);
2356       if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2357         illegal_instruction_combination (cpu);
2358       SET_CCREG (DREG (reg) != 0);
2359     }
2360   else if (op == 3 && reg == 0)
2361     {
2362       TRACE_INSN (cpu, "CC = !CC;");
2363       if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2364         illegal_instruction_combination (cpu);
2365       SET_CCREG (!CCREG);
2366     }
2367   else
2368     illegal_instruction_or_combination (cpu);
2369 }
2370
2371 static void
2372 decode_CC2stat_0 (SIM_CPU *cpu, bu16 iw0)
2373 {
2374   /* CC2stat
2375      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2376      | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |.D.|.op....|.cbit..............|
2377      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
2378   int D    = ((iw0 >> CC2stat_D_bits) & CC2stat_D_mask);
2379   int op   = ((iw0 >> CC2stat_op_bits) & CC2stat_op_mask);
2380   int cbit = ((iw0 >> CC2stat_cbit_bits) & CC2stat_cbit_mask);
2381   bu32 pval;
2382
2383   const char * const op_names[] = { "", "|", "&", "^" } ;
2384
2385   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_CC2stat);
2386   TRACE_EXTRACT (cpu, "%s: D:%i op:%i cbit:%i", __func__, D, op, cbit);
2387
2388   TRACE_INSN (cpu, "%s %s= %s;", D ? astat_names[cbit] : "CC",
2389               op_names[op], D ? "CC" : astat_names[cbit]);
2390
2391   if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2392     illegal_instruction_combination (cpu);
2393
2394   /* CC = CC; is invalid.  */
2395   if (cbit == 5)
2396     illegal_instruction (cpu);
2397
2398   pval = !!(ASTAT & (1 << cbit));
2399   if (D == 0)
2400     switch (op)
2401       {
2402       case 0: SET_CCREG (pval); break;
2403       case 1: SET_CCREG (CCREG | pval); break;
2404       case 2: SET_CCREG (CCREG & pval); break;
2405       case 3: SET_CCREG (CCREG ^ pval); break;
2406       }
2407   else
2408     {
2409       switch (op)
2410         {
2411         case 0: pval  = CCREG; break;
2412         case 1: pval |= CCREG; break;
2413         case 2: pval &= CCREG; break;
2414         case 3: pval ^= CCREG; break;
2415         }
2416       TRACE_REGISTER (cpu, "wrote ASTAT[%s] = %i", astat_names[cbit], pval);
2417       SET_ASTAT ((ASTAT & ~(1 << cbit)) | (pval << cbit));
2418     }
2419 }
2420
2421 static void
2422 decode_BRCC_0 (SIM_CPU *cpu, bu16 iw0, bu32 pc)
2423 {
2424   /* BRCC
2425      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2426      | 0 | 0 | 0 | 1 |.T.|.B.|.offset................................|
2427      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
2428   int B = ((iw0 >> BRCC_B_bits) & BRCC_B_mask);
2429   int T = ((iw0 >> BRCC_T_bits) & BRCC_T_mask);
2430   int offset = ((iw0 >> BRCC_offset_bits) & BRCC_offset_mask);
2431   int cond = T ? CCREG : ! CCREG;
2432   int pcrel = pcrel10 (offset);
2433
2434   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_BRCC);
2435   TRACE_EXTRACT (cpu, "%s: T:%i B:%i offset:%#x", __func__, T, B, offset);
2436   TRACE_DECODE (cpu, "%s: pcrel10:%#x", __func__, pcrel);
2437
2438   TRACE_INSN (cpu, "IF %sCC JUMP %#x%s;", T ? "" : "! ",
2439               pcrel, B ? " (bp)" : "");
2440
2441   if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2442     illegal_instruction_combination (cpu);
2443
2444   if (cond)
2445     {
2446       bu32 newpc = pc + pcrel;
2447       TRACE_BRANCH (cpu, pc, newpc, -1, "Conditional JUMP");
2448       SET_PCREG (newpc);
2449       BFIN_CPU_STATE.did_jump = true;
2450       PROFILE_BRANCH_TAKEN (cpu);
2451       CYCLE_DELAY = B ? 5 : 9;
2452     }
2453   else
2454     {
2455       PROFILE_BRANCH_UNTAKEN (cpu);
2456       CYCLE_DELAY = B ? 9 : 1;
2457     }
2458 }
2459
2460 static void
2461 decode_UJUMP_0 (SIM_CPU *cpu, bu16 iw0, bu32 pc)
2462 {
2463   /* UJUMP
2464      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2465      | 0 | 0 | 1 | 0 |.offset........................................|
2466      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
2467   int offset = ((iw0 >> UJump_offset_bits) & UJump_offset_mask);
2468   int pcrel = pcrel12 (offset);
2469   bu32 newpc = pc + pcrel;
2470
2471   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_UJUMP);
2472   TRACE_EXTRACT (cpu, "%s: offset:%#x", __func__, offset);
2473   TRACE_DECODE (cpu, "%s: pcrel12:%#x", __func__, pcrel);
2474
2475   TRACE_INSN (cpu, "JUMP.S %#x;", pcrel);
2476
2477   if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2478     illegal_instruction_combination (cpu);
2479
2480   TRACE_BRANCH (cpu, pc, newpc, -1, "JUMP.S");
2481
2482   SET_PCREG (newpc);
2483   BFIN_CPU_STATE.did_jump = true;
2484   PROFILE_BRANCH_TAKEN (cpu);
2485   CYCLE_DELAY = 5;
2486 }
2487
2488 static void
2489 decode_REGMV_0 (SIM_CPU *cpu, bu16 iw0)
2490 {
2491   /* REGMV
2492      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2493      | 0 | 0 | 1 | 1 |.gd........|.gs........|.dst.......|.src.......|
2494      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
2495   int gs  = ((iw0 >> RegMv_gs_bits) & RegMv_gs_mask);
2496   int gd  = ((iw0 >> RegMv_gd_bits) & RegMv_gd_mask);
2497   int src = ((iw0 >> RegMv_src_bits) & RegMv_src_mask);
2498   int dst = ((iw0 >> RegMv_dst_bits) & RegMv_dst_mask);
2499   const char *srcreg_name = get_allreg_name (gs, src);
2500   const char *dstreg_name = get_allreg_name (gd, dst);
2501
2502   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_REGMV);
2503   TRACE_EXTRACT (cpu, "%s: gd:%i gs:%i dst:%i src:%i",
2504                  __func__, gd, gs, dst, src);
2505   TRACE_DECODE (cpu, "%s: dst:%s src:%s", __func__, dstreg_name, srcreg_name);
2506
2507   TRACE_INSN (cpu, "%s = %s;", dstreg_name, srcreg_name);
2508
2509   if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2510     illegal_instruction_combination (cpu);
2511
2512   /* Reserved slots cannot be a src/dst.  */
2513   if (reg_is_reserved (gs, src) || reg_is_reserved (gd, dst))
2514     goto invalid_move;
2515
2516   /* Standard register moves.  */
2517   if ((gs < 2)                                          /* Dregs/Pregs src  */
2518       || (gd < 2)                                       /* Dregs/Pregs dst  */
2519       || (gs == 4 && src < 4)                           /* Accumulators src  */
2520       || (gd == 4 && dst < 4 && (gs < 4))               /* Accumulators dst  */
2521       || (gs == 7 && src == 7 && !(gd == 4 && dst < 4)) /* EMUDAT src  */
2522       || (gd == 7 && dst == 7))                         /* EMUDAT dst  */
2523     goto valid_move;
2524
2525   /* dareg = dareg (IMBL)  */
2526   if (gs < 4 && gd < 4)
2527     goto valid_move;
2528
2529   /* USP can be src to sysregs, but not dagregs.  */
2530   if ((gs == 7 && src == 0) && (gd >= 4))
2531     goto valid_move;
2532
2533   /* USP can move between genregs (only check Accumulators).  */
2534   if (((gs == 7 && src == 0) && (gd == 4 && dst < 4))
2535       || ((gd == 7 && dst == 0) && (gs == 4 && src < 4)))
2536     goto valid_move;
2537
2538   /* Still here ?  Invalid reg pair.  */
2539  invalid_move:
2540   illegal_instruction (cpu);
2541
2542  valid_move:
2543   reg_write (cpu, gd, dst, reg_read (cpu, gs, src));
2544 }
2545
2546 static void
2547 decode_ALU2op_0 (SIM_CPU *cpu, bu16 iw0)
2548 {
2549   /* ALU2op
2550      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2551      | 0 | 1 | 0 | 0 | 0 | 0 |.opc...........|.src.......|.dst.......|
2552      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
2553   int src = ((iw0 >> ALU2op_src_bits) & ALU2op_src_mask);
2554   int opc = ((iw0 >> ALU2op_opc_bits) & ALU2op_opc_mask);
2555   int dst = ((iw0 >> ALU2op_dst_bits) & ALU2op_dst_mask);
2556
2557   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ALU2op);
2558   TRACE_EXTRACT (cpu, "%s: opc:%i src:%i dst:%i", __func__, opc, src, dst);
2559
2560   if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2561     illegal_instruction_combination (cpu);
2562
2563   if (opc == 0)
2564     {
2565       TRACE_INSN (cpu, "R%i >>>= R%i;", dst, src);
2566       SET_DREG (dst, ashiftrt (cpu, DREG (dst), DREG (src), 32));
2567     }
2568   else if (opc == 1)
2569     {
2570       bu32 val;
2571       TRACE_INSN (cpu, "R%i >>= R%i;", dst, src);
2572       if (DREG (src) <= 0x1F)
2573         val = lshiftrt (cpu, DREG (dst), DREG (src), 32);
2574       else
2575         val = 0;
2576       SET_DREG (dst, val);
2577     }
2578   else if (opc == 2)
2579     {
2580       TRACE_INSN (cpu, "R%i <<= R%i;", dst, src);
2581       SET_DREG (dst, lshift (cpu, DREG (dst), DREG (src), 32, 0, 0));
2582     }
2583   else if (opc == 3)
2584     {
2585       TRACE_INSN (cpu, "R%i *= R%i;", dst, src);
2586       SET_DREG (dst, DREG (dst) * DREG (src));
2587       CYCLE_DELAY = 3;
2588     }
2589   else if (opc == 4)
2590     {
2591       TRACE_INSN (cpu, "R%i = (R%i + R%i) << 1;", dst, dst, src);
2592       SET_DREG (dst, add_and_shift (cpu, DREG (dst), DREG (src), 1));
2593     }
2594   else if (opc == 5)
2595     {
2596       TRACE_INSN (cpu, "R%i = (R%i + R%i) << 2;", dst, dst, src);
2597       SET_DREG (dst, add_and_shift (cpu, DREG (dst), DREG (src), 2));
2598     }
2599   else if (opc == 8)
2600     {
2601       TRACE_INSN (cpu, "DIVQ ( R%i, R%i );", dst, src);
2602       SET_DREG (dst, divq (cpu, DREG (dst), (bu16)DREG (src)));
2603     }
2604   else if (opc == 9)
2605     {
2606       TRACE_INSN (cpu, "DIVS ( R%i, R%i );", dst, src);
2607       SET_DREG (dst, divs (cpu, DREG (dst), (bu16)DREG (src)));
2608     }
2609   else if (opc == 10)
2610     {
2611       TRACE_INSN (cpu, "R%i = R%i.L (X);", dst, src);
2612       SET_DREG (dst, (bs32) (bs16) DREG (src));
2613       setflags_logical (cpu, DREG (dst));
2614     }
2615   else if (opc == 11)
2616     {
2617       TRACE_INSN (cpu, "R%i = R%i.L (Z);", dst, src);
2618       SET_DREG (dst, (bu32) (bu16) DREG (src));
2619       setflags_logical (cpu, DREG (dst));
2620     }
2621   else if (opc == 12)
2622     {
2623       TRACE_INSN (cpu, "R%i = R%i.B (X);", dst, src);
2624       SET_DREG (dst, (bs32) (bs8) DREG (src));
2625       setflags_logical (cpu, DREG (dst));
2626     }
2627   else if (opc == 13)
2628     {
2629       TRACE_INSN (cpu, "R%i = R%i.B (Z);", dst, src);
2630       SET_DREG (dst, (bu32) (bu8) DREG (src));
2631       setflags_logical (cpu, DREG (dst));
2632     }
2633   else if (opc == 14)
2634     {
2635       bu32 val = DREG (src);
2636       TRACE_INSN (cpu, "R%i = - R%i;", dst, src);
2637       SET_DREG (dst, -val);
2638       setflags_nz (cpu, DREG (dst));
2639       SET_ASTATREG (v, val == 0x80000000);
2640       if (ASTATREG (v))
2641         SET_ASTATREG (vs, 1);
2642       SET_ASTATREG (ac0, val == 0x0);
2643       /* XXX: Documentation isn't entirely clear about av0 and av1.  */
2644     }
2645   else if (opc == 15)
2646     {
2647       TRACE_INSN (cpu, "R%i = ~ R%i;", dst, src);
2648       SET_DREG (dst, ~DREG (src));
2649       setflags_logical (cpu, DREG (dst));
2650     }
2651   else
2652     illegal_instruction (cpu);
2653 }
2654
2655 static void
2656 decode_PTR2op_0 (SIM_CPU *cpu, bu16 iw0)
2657 {
2658   /* PTR2op
2659      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2660      | 0 | 1 | 0 | 0 | 0 | 1 | 0 |.opc.......|.src.......|.dst.......|
2661      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
2662   int src = ((iw0 >> PTR2op_src_bits) & PTR2op_dst_mask);
2663   int opc = ((iw0 >> PTR2op_opc_bits) & PTR2op_opc_mask);
2664   int dst = ((iw0 >> PTR2op_dst_bits) & PTR2op_dst_mask);
2665   const char *src_name = get_preg_name (src);
2666   const char *dst_name = get_preg_name (dst);
2667
2668   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_PTR2op);
2669   TRACE_EXTRACT (cpu, "%s: opc:%i src:%i dst:%i", __func__, opc, src, dst);
2670
2671   if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2672     illegal_instruction_combination (cpu);
2673
2674   if (opc == 0)
2675     {
2676       TRACE_INSN (cpu, "%s -= %s", dst_name, src_name);
2677       SET_PREG (dst, PREG (dst) - PREG (src));
2678     }
2679   else if (opc == 1)
2680     {
2681       TRACE_INSN (cpu, "%s = %s << 2", dst_name, src_name);
2682       SET_PREG (dst, PREG (src) << 2);
2683     }
2684   else if (opc == 3)
2685     {
2686       TRACE_INSN (cpu, "%s = %s >> 2", dst_name, src_name);
2687       SET_PREG (dst, PREG (src) >> 2);
2688     }
2689   else if (opc == 4)
2690     {
2691       TRACE_INSN (cpu, "%s = %s >> 1", dst_name, src_name);
2692       SET_PREG (dst, PREG (src) >> 1);
2693     }
2694   else if (opc == 5)
2695     {
2696       TRACE_INSN (cpu, "%s += %s (BREV)", dst_name, src_name);
2697       SET_PREG (dst, add_brev (PREG (dst), PREG (src)));
2698     }
2699   else if (opc == 6)
2700     {
2701       TRACE_INSN (cpu, "%s = (%s + %s) << 1", dst_name, dst_name, src_name);
2702       SET_PREG (dst, (PREG (dst) + PREG (src)) << 1);
2703     }
2704   else if (opc == 7)
2705     {
2706       TRACE_INSN (cpu, "%s = (%s + %s) << 2", dst_name, dst_name, src_name);
2707       SET_PREG (dst, (PREG (dst) + PREG (src)) << 2);
2708     }
2709   else
2710     illegal_instruction (cpu);
2711 }
2712
2713 static void
2714 decode_LOGI2op_0 (SIM_CPU *cpu, bu16 iw0)
2715 {
2716   /* LOGI2op
2717      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2718      | 0 | 1 | 0 | 0 | 1 |.opc.......|.src...............|.dst.......|
2719      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
2720   int src = ((iw0 >> LOGI2op_src_bits) & LOGI2op_src_mask);
2721   int opc = ((iw0 >> LOGI2op_opc_bits) & LOGI2op_opc_mask);
2722   int dst = ((iw0 >> LOGI2op_dst_bits) & LOGI2op_dst_mask);
2723   int uimm = uimm5 (src);
2724   const char *uimm_str = uimm5_str (uimm);
2725
2726   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LOGI2op);
2727   TRACE_EXTRACT (cpu, "%s: opc:%i src:%i dst:%i", __func__, opc, src, dst);
2728   TRACE_DECODE (cpu, "%s: uimm5:%#x", __func__, uimm);
2729
2730   if (opc == 0)
2731     {
2732       TRACE_INSN (cpu, "CC = ! BITTST (R%i, %s);", dst, uimm_str);
2733       if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2734         illegal_instruction_combination (cpu);
2735       SET_CCREG ((~DREG (dst) >> uimm) & 1);
2736     }
2737   else if (opc == 1)
2738     {
2739       TRACE_INSN (cpu, "CC = BITTST (R%i, %s);", dst, uimm_str);
2740       if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2741         illegal_instruction_combination (cpu);
2742       SET_CCREG ((DREG (dst) >> uimm) & 1);
2743     }
2744   else if (opc == 2)
2745     {
2746       TRACE_INSN (cpu, "BITSET (R%i, %s);", dst, uimm_str);
2747       if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2748         illegal_instruction_combination (cpu);
2749       SET_DREG (dst, DREG (dst) | (1 << uimm));
2750       setflags_logical (cpu, DREG (dst));
2751     }
2752   else if (opc == 3)
2753     {
2754       TRACE_INSN (cpu, "BITTGL (R%i, %s);", dst, uimm_str);
2755       if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2756         illegal_instruction_combination (cpu);
2757       SET_DREG (dst, DREG (dst) ^ (1 << uimm));
2758       setflags_logical (cpu, DREG (dst));
2759     }
2760   else if (opc == 4)
2761     {
2762       TRACE_INSN (cpu, "BITCLR (R%i, %s);", dst, uimm_str);
2763       if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2764         illegal_instruction_combination (cpu);
2765       SET_DREG (dst, DREG (dst) & ~(1 << uimm));
2766       setflags_logical (cpu, DREG (dst));
2767     }
2768   else if (opc == 5)
2769     {
2770       TRACE_INSN (cpu, "R%i >>>= %s;", dst, uimm_str);
2771       if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2772         illegal_instruction_combination (cpu);
2773       SET_DREG (dst, ashiftrt (cpu, DREG (dst), uimm, 32));
2774     }
2775   else if (opc == 6)
2776     {
2777       TRACE_INSN (cpu, "R%i >>= %s;", dst, uimm_str);
2778       if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2779         illegal_instruction_combination (cpu);
2780       SET_DREG (dst, lshiftrt (cpu, DREG (dst), uimm, 32));
2781     }
2782   else if (opc == 7)
2783     {
2784       TRACE_INSN (cpu, "R%i <<= %s;", dst, uimm_str);
2785       if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2786         illegal_instruction_combination (cpu);
2787       SET_DREG (dst, lshift (cpu, DREG (dst), uimm, 32, 0, 0));
2788     }
2789 }
2790
2791 static void
2792 decode_COMP3op_0 (SIM_CPU *cpu, bu16 iw0)
2793 {
2794   /* COMP3op
2795      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2796      | 0 | 1 | 0 | 1 |.opc.......|.dst.......|.src1......|.src0......|
2797      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
2798   int opc  = ((iw0 >> COMP3op_opc_bits) & COMP3op_opc_mask);
2799   int dst  = ((iw0 >> COMP3op_dst_bits) & COMP3op_dst_mask);
2800   int src0 = ((iw0 >> COMP3op_src0_bits) & COMP3op_src0_mask);
2801   int src1 = ((iw0 >> COMP3op_src1_bits) & COMP3op_src1_mask);
2802
2803   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_COMP3op);
2804   TRACE_EXTRACT (cpu, "%s: opc:%i dst:%i src1:%i src0:%i",
2805                  __func__, opc, dst, src1, src0);
2806
2807   if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2808     illegal_instruction_combination (cpu);
2809
2810   if (opc == 0)
2811     {
2812       TRACE_INSN (cpu, "R%i = R%i + R%i;", dst, src0, src1);
2813       SET_DREG (dst, add32 (cpu, DREG (src0), DREG (src1), 1, 0));
2814     }
2815   else if (opc == 1)
2816     {
2817       TRACE_INSN (cpu, "R%i = R%i - R%i;", dst, src0, src1);
2818       SET_DREG (dst, sub32 (cpu, DREG (src0), DREG (src1), 1, 0, 0));
2819     }
2820   else if (opc == 2)
2821     {
2822       TRACE_INSN (cpu, "R%i = R%i & R%i;", dst, src0, src1);
2823       SET_DREG (dst, DREG (src0) & DREG (src1));
2824       setflags_logical (cpu, DREG (dst));
2825     }
2826   else if (opc == 3)
2827     {
2828       TRACE_INSN (cpu, "R%i = R%i | R%i;", dst, src0, src1);
2829       SET_DREG (dst, DREG (src0) | DREG (src1));
2830       setflags_logical (cpu, DREG (dst));
2831     }
2832   else if (opc == 4)
2833     {
2834       TRACE_INSN (cpu, "R%i = R%i ^ R%i;", dst, src0, src1);
2835       SET_DREG (dst, DREG (src0) ^ DREG (src1));
2836       setflags_logical (cpu, DREG (dst));
2837     }
2838   else
2839     {
2840       int shift = opc - 5;
2841       const char *dst_name = get_preg_name (dst);
2842       const char *src0_name = get_preg_name (src0);
2843       const char *src1_name = get_preg_name (src1);
2844
2845       /* If src0 == src1 this is disassembled as a shift by 1, but this
2846          distinction doesn't matter for our purposes.  */
2847       if (shift)
2848         TRACE_INSN (cpu, "%s = (%s + %s) << %#x;",
2849                     dst_name, src0_name, src1_name, shift);
2850       else
2851         TRACE_INSN (cpu, "%s = %s + %s",
2852                     dst_name, src0_name, src1_name);
2853       SET_PREG (dst, PREG (src0) + (PREG (src1) << shift));
2854     }
2855 }
2856
2857 static void
2858 decode_COMPI2opD_0 (SIM_CPU *cpu, bu16 iw0)
2859 {
2860   /* COMPI2opD
2861      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2862      | 0 | 1 | 1 | 0 | 0 |.op|..src......................|.dst.......|
2863      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
2864   int op  = ((iw0 >> COMPI2opD_op_bits) & COMPI2opD_op_mask);
2865   int dst = ((iw0 >> COMPI2opD_dst_bits) & COMPI2opD_dst_mask);
2866   int src = ((iw0 >> COMPI2opD_src_bits) & COMPI2opD_src_mask);
2867   int imm = imm7 (src);
2868
2869   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_COMPI2opD);
2870   TRACE_EXTRACT (cpu, "%s: op:%i src:%i dst:%i", __func__, op, src, dst);
2871   TRACE_DECODE (cpu, "%s: imm7:%#x", __func__, imm);
2872
2873   if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2874     illegal_instruction_combination (cpu);
2875
2876   if (op == 0)
2877     {
2878       TRACE_INSN (cpu, "R%i = %s (X);", dst, imm7_str (imm));
2879       SET_DREG (dst, imm);
2880     }
2881   else if (op == 1)
2882     {
2883       TRACE_INSN (cpu, "R%i += %s;", dst, imm7_str (imm));
2884       SET_DREG (dst, add32 (cpu, DREG (dst), imm, 1, 0));
2885     }
2886 }
2887
2888 static void
2889 decode_COMPI2opP_0 (SIM_CPU *cpu, bu16 iw0)
2890 {
2891   /* COMPI2opP
2892      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2893      | 0 | 1 | 1 | 0 | 1 |.op|.src.......................|.dst.......|
2894      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
2895   int op  = ((iw0 >> COMPI2opP_op_bits) & COMPI2opP_op_mask);
2896   int src = ((iw0 >> COMPI2opP_src_bits) & COMPI2opP_src_mask);
2897   int dst = ((iw0 >> COMPI2opP_dst_bits) & COMPI2opP_dst_mask);
2898   int imm = imm7 (src);
2899   const char *dst_name = get_preg_name (dst);
2900
2901   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_COMPI2opP);
2902   TRACE_EXTRACT (cpu, "%s: op:%i src:%i dst:%i", __func__, op, src, dst);
2903   TRACE_DECODE (cpu, "%s: imm:%#x", __func__, imm);
2904
2905   if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2906     illegal_instruction_combination (cpu);
2907
2908   if (op == 0)
2909     {
2910       TRACE_INSN (cpu, "%s = %s;", dst_name, imm7_str (imm));
2911       SET_PREG (dst, imm);
2912     }
2913   else if (op == 1)
2914     {
2915       TRACE_INSN (cpu, "%s += %s;", dst_name, imm7_str (imm));
2916       SET_PREG (dst, PREG (dst) + imm);
2917     }
2918 }
2919
2920 static void
2921 decode_LDSTpmod_0 (SIM_CPU *cpu, bu16 iw0)
2922 {
2923   /* LDSTpmod
2924      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2925      | 1 | 0 | 0 | 0 |.W.|.aop...|.reg.......|.idx.......|.ptr.......|
2926      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
2927   int W   = ((iw0 >> LDSTpmod_W_bits) & LDSTpmod_W_mask);
2928   int aop = ((iw0 >> LDSTpmod_aop_bits) & LDSTpmod_aop_mask);
2929   int idx = ((iw0 >> LDSTpmod_idx_bits) & LDSTpmod_idx_mask);
2930   int ptr = ((iw0 >> LDSTpmod_ptr_bits) & LDSTpmod_ptr_mask);
2931   int reg = ((iw0 >> LDSTpmod_reg_bits) & LDSTpmod_reg_mask);
2932   const char *ptr_name = get_preg_name (ptr);
2933   const char *idx_name = get_preg_name (idx);
2934   bu32 addr, val;
2935
2936   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LDSTpmod);
2937   TRACE_EXTRACT (cpu, "%s: W:%i aop:%i reg:%i idx:%i ptr:%i",
2938                  __func__, W, aop, reg, idx, ptr);
2939
2940   if (PARALLEL_GROUP == BFIN_PARALLEL_GROUP2)
2941     illegal_instruction_combination (cpu);
2942
2943   if (aop == 1 && W == 0 && idx == ptr)
2944     {
2945       TRACE_INSN (cpu, "R%i.L = W[%s];", reg, ptr_name);
2946       addr = PREG (ptr);
2947       val = GET_WORD (addr);
2948       STORE (DREG (reg), (DREG (reg) & 0xFFFF0000) | val);
2949     }
2950   else if (aop == 2 && W == 0 && idx == ptr)
2951     {
2952       TRACE_INSN (cpu, "R%i.H = W[%s];", reg, ptr_name);
2953       addr = PREG (ptr);
2954       val = GET_WORD (addr);
2955       STORE (DREG (reg), (DREG (reg) & 0xFFFF) | (val << 16));
2956     }
2957   else if (aop == 1 && W == 1 && idx == ptr)
2958     {
2959       TRACE_INSN (cpu, "W[%s] = R%i.L;", ptr_name, reg);
2960       addr = PREG (ptr);
2961       PUT_WORD (addr, DREG (reg));
2962     }
2963   else if (aop == 2 && W == 1 && idx == ptr)
2964     {
2965       TRACE_INSN (cpu, "W[%s] = R%i.H;", ptr_name, reg);
2966       addr = PREG (ptr);
2967       PUT_WORD (addr, DREG (reg) >> 16);
2968     }
2969   else if (aop == 0 && W == 0)
2970     {
2971       TRACE_INSN (cpu, "R%i = [%s ++ %s];", reg, ptr_name, idx_name);
2972       addr = PREG (ptr);
2973       val = GET_LONG (addr);
2974       STORE (DREG (reg), val);
2975       if (ptr != idx)
2976         STORE (PREG (ptr), addr + PREG (idx));
2977     }
2978   else if (aop == 1 && W == 0)
2979     {
2980       TRACE_INSN (cpu, "R%i.L = W[%s ++ %s];", reg, ptr_name, idx_name);
2981       addr = PREG (ptr);
2982       val = GET_WORD (addr);
2983       STORE (DREG (reg), (DREG (reg) & 0xFFFF0000) | val);
2984       if (ptr != idx)
2985         STORE (PREG (ptr), addr + PREG (idx));
2986     }
2987   else if (aop == 2 && W == 0)
2988     {
2989       TRACE_INSN (cpu, "R%i.H = W[%s ++ %s];", reg, ptr_name, idx_name);
2990       addr = PREG (ptr);
2991       val = GET_WORD (addr);
2992       STORE (DREG (reg), (DREG (reg) & 0xFFFF) | (val << 16));
2993       if (ptr != idx)
2994         STORE (PREG (ptr), addr + PREG (idx));
2995     }
2996   else if (aop == 3 && W == 0)
2997     {
2998       TRACE_INSN (cpu, "R%i = W[%s ++ %s] (Z);", reg, ptr_name, idx_name);
2999       addr = PREG (ptr);
3000       val = GET_WORD (addr);
3001       STORE (DREG (reg), val);
3002       if (ptr != idx)
3003         STORE (PREG (ptr), addr + PREG (idx));
3004     }
3005   else if (aop == 3 && W == 1)
3006     {
3007       TRACE_INSN (cpu, "R%i = W[%s ++ %s] (X);", reg, ptr_name, idx_name);
3008       addr = PREG (ptr);
3009       val = GET_WORD (addr);
3010       STORE (DREG (reg), (bs32) (bs16) val);
3011       if (ptr != idx)
3012         STORE (PREG (ptr), addr + PREG (idx));
3013     }
3014   else if (aop == 0 && W == 1)
3015     {
3016       TRACE_INSN (cpu, "[%s ++ %s] = R%i;", ptr_name, idx_name, reg);
3017       addr = PREG (ptr);
3018       PUT_LONG (addr, DREG (reg));
3019       if (ptr != idx)
3020         STORE (PREG (ptr), addr + PREG (idx));
3021     }
3022   else if (aop == 1 && W == 1)
3023     {
3024       TRACE_INSN (cpu, "W[%s ++ %s] = R%i.L;", ptr_name, idx_name, reg);
3025       addr = PREG (ptr);
3026       PUT_WORD (addr, DREG (reg));
3027       if (ptr != idx)
3028         STORE (PREG (ptr), addr + PREG (idx));
3029     }
3030   else if (aop == 2 && W == 1)
3031     {
3032       TRACE_INSN (cpu, "W[%s ++ %s] = R%i.H;", ptr_name, idx_name, reg);
3033       addr = PREG (ptr);
3034       PUT_WORD (addr, DREG (reg) >> 16);
3035       if (ptr != idx)
3036         STORE (PREG (ptr), addr + PREG (idx));
3037     }
3038   else
3039     illegal_instruction_or_combination (cpu);
3040 }
3041
3042 static void
3043 decode_dagMODim_0 (SIM_CPU *cpu, bu16 iw0)
3044 {
3045   /* dagMODim
3046      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3047      | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 0 |.br| 1 | 1 |.op|.m.....|.i.....|
3048      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
3049   int i  = ((iw0 >> DagMODim_i_bits) & DagMODim_i_mask);
3050   int m  = ((iw0 >> DagMODim_m_bits) & DagMODim_m_mask);
3051   int br = ((iw0 >> DagMODim_br_bits) & DagMODim_br_mask);
3052   int op = ((iw0 >> DagMODim_op_bits) & DagMODim_op_mask);
3053
3054   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dagMODim);
3055   TRACE_EXTRACT (cpu, "%s: br:%i op:%i m:%i i:%i", __func__, br, op, m, i);
3056
3057   if (PARALLEL_GROUP == BFIN_PARALLEL_GROUP2)
3058     illegal_instruction_combination (cpu);
3059
3060   if (op == 0 && br == 1)
3061     {
3062       TRACE_INSN (cpu, "I%i += M%i (BREV);", i, m);
3063       SET_IREG (i, add_brev (IREG (i), MREG (m)));
3064     }
3065   else if (op == 0)
3066     {
3067       TRACE_INSN (cpu, "I%i += M%i;", i, m);
3068       dagadd (cpu, i, MREG (m));
3069     }
3070   else if (op == 1 && br == 0)
3071     {
3072       TRACE_INSN (cpu, "I%i -= M%i;", i, m);
3073       dagsub (cpu, i, MREG (m));
3074     }
3075   else
3076     illegal_instruction_or_combination (cpu);
3077 }
3078
3079 static void
3080 decode_dagMODik_0 (SIM_CPU *cpu, bu16 iw0)
3081 {
3082   /* dagMODik
3083      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3084      | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 0 |.op....|.i.....|
3085      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
3086   int i  = ((iw0 >> DagMODik_i_bits) & DagMODik_i_mask);
3087   int op = ((iw0 >> DagMODik_op_bits) & DagMODik_op_mask);
3088
3089   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dagMODik);
3090   TRACE_EXTRACT (cpu, "%s: op:%i i:%i", __func__, op, i);
3091
3092   if (PARALLEL_GROUP == BFIN_PARALLEL_GROUP2)
3093     illegal_instruction_combination (cpu);
3094
3095   if (op == 0)
3096     {
3097       TRACE_INSN (cpu, "I%i += 2;", i);
3098       dagadd (cpu, i, 2);
3099     }
3100   else if (op == 1)
3101     {
3102       TRACE_INSN (cpu, "I%i -= 2;", i);
3103       dagsub (cpu, i, 2);
3104     }
3105   else if (op == 2)
3106     {
3107       TRACE_INSN (cpu, "I%i += 4;", i);
3108       dagadd (cpu, i, 4);
3109     }
3110   else if (op == 3)
3111     {
3112       TRACE_INSN (cpu, "I%i -= 4;", i);
3113       dagsub (cpu, i, 4);
3114     }
3115   else
3116     illegal_instruction_or_combination (cpu);
3117 }
3118
3119 static void
3120 decode_dspLDST_0 (SIM_CPU *cpu, bu16 iw0)
3121 {
3122   /* dspLDST
3123      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3124      | 1 | 0 | 0 | 1 | 1 | 1 |.W.|.aop...|.m.....|.i.....|.reg.......|
3125      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
3126   int i   = ((iw0 >> DspLDST_i_bits) & DspLDST_i_mask);
3127   int m   = ((iw0 >> DspLDST_m_bits) & DspLDST_m_mask);
3128   int W   = ((iw0 >> DspLDST_W_bits) & DspLDST_W_mask);
3129   int aop = ((iw0 >> DspLDST_aop_bits) & DspLDST_aop_mask);
3130   int reg = ((iw0 >> DspLDST_reg_bits) & DspLDST_reg_mask);
3131   bu32 addr;
3132
3133   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dspLDST);
3134   TRACE_EXTRACT (cpu, "%s: aop:%i m:%i i:%i reg:%i", __func__, aop, m, i, reg);
3135
3136   if (aop == 0 && W == 0 && m == 0)
3137     {
3138       TRACE_INSN (cpu, "R%i = [I%i++];", reg, i);
3139       addr = IREG (i);
3140       if (DIS_ALGN_EXPT & 0x1)
3141         addr &= ~3;
3142       dagadd (cpu, i, 4);
3143       STORE (DREG (reg), GET_LONG (addr));
3144     }
3145   else if (aop == 0 && W == 0 && m == 1)
3146     {
3147       TRACE_INSN (cpu, "R%i.L = W[I%i++];", reg, i);
3148       addr = IREG (i);
3149       dagadd (cpu, i, 2);
3150       STORE (DREG (reg), (DREG (reg) & 0xFFFF0000) | GET_WORD (addr));
3151     }
3152   else if (aop == 0 && W == 0 && m == 2)
3153     {
3154       TRACE_INSN (cpu, "R%i.H = W[I%i++];", reg, i);
3155       addr = IREG (i);
3156       dagadd (cpu, i, 2);
3157       STORE (DREG (reg), (DREG (reg) & 0xFFFF) | (GET_WORD (addr) << 16));
3158     }
3159   else if (aop == 1 && W == 0 && m == 0)
3160     {
3161       TRACE_INSN (cpu, "R%i = [I%i--];", reg, i);
3162       addr = IREG (i);
3163       if (DIS_ALGN_EXPT & 0x1)
3164         addr &= ~3;
3165       dagsub (cpu, i, 4);
3166       STORE (DREG (reg), GET_LONG (addr));
3167     }
3168   else if (aop == 1 && W == 0 && m == 1)
3169     {
3170       TRACE_INSN (cpu, "R%i.L = W[I%i--];", reg, i);
3171       addr = IREG (i);
3172       dagsub (cpu, i, 2);
3173       STORE (DREG (reg), (DREG (reg) & 0xFFFF0000) | GET_WORD (addr));
3174     }
3175   else if (aop == 1 && W == 0 && m == 2)
3176     {
3177       TRACE_INSN (cpu, "R%i.H = W[I%i--];", reg, i);
3178       addr = IREG (i);
3179       dagsub (cpu, i, 2);
3180       STORE (DREG (reg), (DREG (reg) & 0xFFFF) | (GET_WORD (addr) << 16));
3181     }
3182   else if (aop == 2 && W == 0 && m == 0)
3183     {
3184       TRACE_INSN (cpu, "R%i = [I%i];", reg, i);
3185       addr = IREG (i);
3186       if (DIS_ALGN_EXPT & 0x1)
3187         addr &= ~3;
3188       STORE (DREG (reg), GET_LONG (addr));
3189     }
3190   else if (aop == 2 && W == 0 && m == 1)
3191     {
3192       TRACE_INSN (cpu, "R%i.L = W[I%i];", reg, i);
3193       addr = IREG (i);
3194       STORE (DREG (reg), (DREG (reg) & 0xFFFF0000) | GET_WORD (addr));
3195     }
3196   else if (aop == 2 && W == 0 && m == 2)
3197     {
3198       TRACE_INSN (cpu, "R%i.H = W[I%i];", reg, i);
3199       addr = IREG (i);
3200       STORE (DREG (reg), (DREG (reg) & 0xFFFF) | (GET_WORD (addr) << 16));
3201     }
3202   else if (aop == 0 && W == 1 && m == 0)
3203     {
3204       TRACE_INSN (cpu, "[I%i++] = R%i;", i, reg);
3205       addr = IREG (i);
3206       dagadd (cpu, i, 4);
3207       PUT_LONG (addr, DREG (reg));
3208     }
3209   else if (aop == 0 && W == 1 && m == 1)
3210     {
3211       TRACE_INSN (cpu, "W[I%i++] = R%i.L;", i, reg);
3212       addr = IREG (i);
3213       dagadd (cpu, i, 2);
3214       PUT_WORD (addr, DREG (reg));
3215     }
3216   else if (aop == 0 && W == 1 && m == 2)
3217     {
3218       TRACE_INSN (cpu, "W[I%i++] = R%i.H;", i, reg);
3219       addr = IREG (i);
3220       dagadd (cpu, i, 2);
3221       PUT_WORD (addr, DREG (reg) >> 16);
3222     }
3223   else if (aop == 1 && W == 1 && m == 0)
3224     {
3225       TRACE_INSN (cpu, "[I%i--] = R%i;", i, reg);
3226       addr = IREG (i);
3227       dagsub (cpu, i, 4);
3228       PUT_LONG (addr, DREG (reg));
3229     }
3230   else if (aop == 1 && W == 1 && m == 1)
3231     {
3232       TRACE_INSN (cpu, "W[I%i--] = R%i.L;", i, reg);
3233       addr = IREG (i);
3234       dagsub (cpu, i, 2);
3235       PUT_WORD (addr, DREG (reg));
3236     }
3237   else if (aop == 1 && W == 1 && m == 2)
3238     {
3239       TRACE_INSN (cpu, "W[I%i--] = R%i.H;", i, reg);
3240       addr = IREG (i);
3241       dagsub (cpu, i, 2);
3242       PUT_WORD (addr, DREG (reg) >> 16);
3243     }
3244   else if (aop == 2 && W == 1 && m == 0)
3245     {
3246       TRACE_INSN (cpu, "[I%i] = R%i;", i, reg);
3247       addr = IREG (i);
3248       PUT_LONG (addr, DREG (reg));
3249     }
3250   else if (aop == 2 && W == 1 && m == 1)
3251     {
3252       TRACE_INSN (cpu, "W[I%i] = R%i.L;", i, reg);
3253       addr = IREG (i);
3254       PUT_WORD (addr, DREG (reg));
3255     }
3256   else if (aop == 2 && W == 1 && m == 2)
3257     {
3258       TRACE_INSN (cpu, "W[I%i] = R%i.H;", i, reg);
3259       addr = IREG (i);
3260       PUT_WORD (addr, DREG (reg) >> 16);
3261     }
3262   else if (aop == 3 && W == 0)
3263     {
3264       TRACE_INSN (cpu, "R%i = [I%i ++ M%i];", reg, i, m);
3265       addr = IREG (i);
3266       if (DIS_ALGN_EXPT & 0x1)
3267         addr &= ~3;
3268       dagadd (cpu, i, MREG (m));
3269       STORE (DREG (reg), GET_LONG (addr));
3270     }
3271   else if (aop == 3 && W == 1)
3272     {
3273       TRACE_INSN (cpu, "[I%i ++ M%i] = R%i;", i, m, reg);
3274       addr = IREG (i);
3275       dagadd (cpu, i, MREG (m));
3276       PUT_LONG (addr, DREG (reg));
3277     }
3278   else
3279     illegal_instruction_or_combination (cpu);
3280 }
3281
3282 static void
3283 decode_LDST_0 (SIM_CPU *cpu, bu16 iw0)
3284 {
3285   /* LDST
3286      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3287      | 1 | 0 | 0 | 1 |.sz....|.W.|.aop...|.Z.|.ptr.......|.reg.......|
3288      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
3289   int Z   = ((iw0 >> LDST_Z_bits) & LDST_Z_mask);
3290   int W   = ((iw0 >> LDST_W_bits) & LDST_W_mask);
3291   int sz  = ((iw0 >> LDST_sz_bits) & LDST_sz_mask);
3292   int aop = ((iw0 >> LDST_aop_bits) & LDST_aop_mask);
3293   int reg = ((iw0 >> LDST_reg_bits) & LDST_reg_mask);
3294   int ptr = ((iw0 >> LDST_ptr_bits) & LDST_ptr_mask);
3295   const char * const posts[] = { "++", "--", "" };
3296   const char *post = posts[aop];
3297   const char *ptr_name = get_preg_name (ptr);
3298
3299   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LDST);
3300   TRACE_EXTRACT (cpu, "%s: sz:%i W:%i aop:%i Z:%i ptr:%i reg:%i",
3301                  __func__, sz, W, aop, Z, ptr, reg);
3302
3303   if (aop == 3 || PARALLEL_GROUP == BFIN_PARALLEL_GROUP2)
3304     illegal_instruction_or_combination (cpu);
3305
3306   if (W == 0)
3307     {
3308       if (sz == 0 && Z == 0)
3309         {
3310           TRACE_INSN (cpu, "R%i = [%s%s];", reg, ptr_name, post);
3311           SET_DREG (reg, GET_LONG (PREG (ptr)));
3312         }
3313       else if (sz == 0 && Z == 1)
3314         {
3315           TRACE_INSN (cpu, "%s = [%s%s];", get_preg_name (reg), ptr_name, post);
3316           if (aop < 2 && ptr == reg)
3317             illegal_instruction_combination (cpu);
3318           SET_PREG (reg, GET_LONG (PREG (ptr)));
3319         }
3320       else if (sz == 1 && Z == 0)
3321         {
3322           TRACE_INSN (cpu, "R%i = W[%s%s] (Z);", reg, ptr_name, post);
3323           SET_DREG (reg, GET_WORD (PREG (ptr)));
3324         }
3325       else if (sz == 1 && Z == 1)
3326         {
3327           TRACE_INSN (cpu, "R%i = W[%s%s] (X);", reg, ptr_name, post);
3328           SET_DREG (reg, (bs32) (bs16) GET_WORD (PREG (ptr)));
3329         }
3330       else if (sz == 2 && Z == 0)
3331         {
3332           TRACE_INSN (cpu, "R%i = B[%s%s] (Z);", reg, ptr_name, post);
3333           SET_DREG (reg, GET_BYTE (PREG (ptr)));
3334         }
3335       else if (sz == 2 && Z == 1)
3336         {
3337           TRACE_INSN (cpu, "R%i = B[%s%s] (X);", reg, ptr_name, post);
3338           SET_DREG (reg, (bs32) (bs8) GET_BYTE (PREG (ptr)));
3339         }
3340       else
3341         illegal_instruction_or_combination (cpu);
3342     }
3343   else
3344     {
3345       if (sz == 0 && Z == 0)
3346         {
3347           TRACE_INSN (cpu, "[%s%s] = R%i;", ptr_name, post, reg);
3348           PUT_LONG (PREG (ptr), DREG (reg));
3349         }
3350       else if (sz == 0 && Z == 1)
3351         {
3352           TRACE_INSN (cpu, "[%s%s] = %s;", ptr_name, post, get_preg_name (reg));
3353           PUT_LONG (PREG (ptr), PREG (reg));
3354         }
3355       else if (sz == 1 && Z == 0)
3356         {
3357           TRACE_INSN (cpu, "W[%s%s] = R%i;", ptr_name, post, reg);
3358           PUT_WORD (PREG (ptr), DREG (reg));
3359         }
3360       else if (sz == 2 && Z == 0)
3361         {
3362           TRACE_INSN (cpu, "B[%s%s] = R%i;", ptr_name, post, reg);
3363           PUT_BYTE (PREG (ptr), DREG (reg));
3364         }
3365       else
3366         illegal_instruction_or_combination (cpu);
3367     }
3368
3369   if (aop == 0)
3370     SET_PREG (ptr, PREG (ptr) + (1 << (2 - sz)));
3371   if (aop == 1)
3372     SET_PREG (ptr, PREG (ptr) - (1 << (2 - sz)));
3373 }
3374
3375 static void
3376 decode_LDSTiiFP_0 (SIM_CPU *cpu, bu16 iw0)
3377 {
3378   /* LDSTiiFP
3379      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3380      | 1 | 0 | 1 | 1 | 1 | 0 |.W.|.offset............|.reg...........|
3381      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
3382   /* This isn't exactly a grp:reg as this insn only supports Dregs & Pregs,
3383      but for our usage, its functionality the same thing.  */
3384   int grp = ((iw0 >> 3) & 0x1);
3385   int reg = ((iw0 >> LDSTiiFP_reg_bits) & 0x7 /*LDSTiiFP_reg_mask*/);
3386   int offset = ((iw0 >> LDSTiiFP_offset_bits) & LDSTiiFP_offset_mask);
3387   int W = ((iw0 >> LDSTiiFP_W_bits) & LDSTiiFP_W_mask);
3388   bu32 imm = negimm5s4 (offset);
3389   bu32 ea = FPREG + imm;
3390   const char *imm_str = negimm5s4_str (offset);
3391   const char *reg_name = get_allreg_name (grp, reg);
3392
3393   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LDSTiiFP);
3394   TRACE_EXTRACT (cpu, "%s: W:%i offset:%#x grp:%i reg:%i", __func__,
3395                  W, offset, grp, reg);
3396   TRACE_DECODE (cpu, "%s: negimm5s4:%#x", __func__, imm);
3397
3398   if (PARALLEL_GROUP == BFIN_PARALLEL_GROUP2)
3399     illegal_instruction_or_combination (cpu);
3400
3401   if (W == 0)
3402     {
3403       TRACE_INSN (cpu, "%s = [FP + %s];", reg_name, imm_str);
3404       reg_write (cpu, grp, reg, GET_LONG (ea));
3405     }
3406   else
3407     {
3408       TRACE_INSN (cpu, "[FP + %s] = %s;", imm_str, reg_name);
3409       PUT_LONG (ea, reg_read (cpu, grp, reg));
3410     }
3411 }
3412
3413 static void
3414 decode_LDSTii_0 (SIM_CPU *cpu, bu16 iw0)
3415 {
3416   /* LDSTii
3417      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3418      | 1 | 0 | 1 |.W.|.op....|.offset........|.ptr.......|.reg.......|
3419      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
3420   int reg = ((iw0 >> LDSTii_reg_bit) & LDSTii_reg_mask);
3421   int ptr = ((iw0 >> LDSTii_ptr_bit) & LDSTii_ptr_mask);
3422   int offset = ((iw0 >> LDSTii_offset_bit) & LDSTii_offset_mask);
3423   int op = ((iw0 >> LDSTii_op_bit) & LDSTii_op_mask);
3424   int W = ((iw0 >> LDSTii_W_bit) & LDSTii_W_mask);
3425   bu32 imm, ea;
3426   const char *imm_str;
3427   const char *ptr_name = get_preg_name (ptr);
3428
3429   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LDSTii);
3430   TRACE_EXTRACT (cpu, "%s: W:%i op:%i offset:%#x ptr:%i reg:%i",
3431                  __func__, W, op, offset, ptr, reg);
3432
3433   if (op == 0 || op == 3)
3434     imm = uimm4s4 (offset), imm_str = uimm4s4_str (offset);
3435   else
3436     imm = uimm4s2 (offset), imm_str = uimm4s2_str (offset);
3437   ea = PREG (ptr) + imm;
3438
3439   TRACE_DECODE (cpu, "%s: uimm4s4/uimm4s2:%#x", __func__, imm);
3440
3441   if (PARALLEL_GROUP == BFIN_PARALLEL_GROUP2)
3442     illegal_instruction_combination (cpu);
3443
3444   if (W == 1 && op == 2)
3445     illegal_instruction (cpu);
3446
3447   if (W == 0)
3448     {
3449       if (op == 0)
3450         {
3451           TRACE_INSN (cpu, "R%i = [%s + %s];", reg, ptr_name, imm_str);
3452           SET_DREG (reg, GET_LONG (ea));
3453         }
3454       else if (op == 1)
3455         {
3456           TRACE_INSN (cpu, "R%i = W[%s + %s] (Z);", reg, ptr_name, imm_str);
3457           SET_DREG (reg, GET_WORD (ea));
3458         }
3459       else if (op == 2)
3460         {
3461           TRACE_INSN (cpu, "R%i = W[%s + %s] (X);", reg, ptr_name, imm_str);
3462           SET_DREG (reg, (bs32) (bs16) GET_WORD (ea));
3463         }
3464       else if (op == 3)
3465         {
3466           TRACE_INSN (cpu, "%s = [%s + %s];",
3467                       get_preg_name (reg), ptr_name, imm_str);
3468           SET_PREG (reg, GET_LONG (ea));
3469         }
3470     }
3471   else
3472     {
3473       if (op == 0)
3474         {
3475           TRACE_INSN (cpu, "[%s + %s] = R%i;", ptr_name, imm_str, reg);
3476           PUT_LONG (ea, DREG (reg));
3477         }
3478       else if (op == 1)
3479         {
3480           TRACE_INSN (cpu, "W[%s + %s] = R%i;", ptr_name, imm_str, reg);
3481           PUT_WORD (ea, DREG (reg));
3482         }
3483       else if (op == 3)
3484         {
3485           TRACE_INSN (cpu, "[%s + %s] = %s;",
3486                       ptr_name, imm_str, get_preg_name (reg));
3487           PUT_LONG (ea, PREG (reg));
3488         }
3489     }
3490 }
3491
3492 static void
3493 decode_LoopSetup_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1, bu32 pc)
3494 {
3495   /* LoopSetup
3496      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3497      | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |.rop...|.c.|.soffset.......|
3498      |.reg...........| - | - |.eoffset...............................|
3499      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
3500   int c   = ((iw0 >> (LoopSetup_c_bits - 16)) & LoopSetup_c_mask);
3501   int reg = ((iw1 >> LoopSetup_reg_bits) & LoopSetup_reg_mask);
3502   int rop = ((iw0 >> (LoopSetup_rop_bits - 16)) & LoopSetup_rop_mask);
3503   int soffset = ((iw0 >> (LoopSetup_soffset_bits - 16)) & LoopSetup_soffset_mask);
3504   int eoffset = ((iw1 >> LoopSetup_eoffset_bits) & LoopSetup_eoffset_mask);
3505   int spcrel = pcrel4 (soffset);
3506   int epcrel = lppcrel10 (eoffset);
3507
3508   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LoopSetup);
3509   TRACE_EXTRACT (cpu, "%s: rop:%i c:%i soffset:%i reg:%i eoffset:%i",
3510                  __func__, rop, c, soffset, reg, eoffset);
3511   TRACE_DECODE (cpu, "%s: s_pcrel4:%#x e_lppcrel10:%#x",
3512                 __func__, spcrel, epcrel);
3513
3514   if (reg > 7)
3515     illegal_instruction (cpu);
3516
3517   if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
3518     illegal_instruction_combination (cpu);
3519
3520   if (rop == 0)
3521     {
3522       TRACE_INSN (cpu, "LSETUP (%#x, %#x) LC%i;", spcrel, epcrel, c);
3523     }
3524   else if (rop == 1 && reg <= 7)
3525     {
3526       TRACE_INSN (cpu, "LSETUP (%#x, %#x) LC%i = %s;",
3527                   spcrel, epcrel, c, get_preg_name (reg));
3528       SET_LCREG (c, PREG (reg));
3529     }
3530   else if (rop == 3 && reg <= 7)
3531     {
3532       TRACE_INSN (cpu, "LSETUP (%#x, %#x) LC%i = %s >> 1;",
3533                   spcrel, epcrel, c, get_preg_name (reg));
3534       SET_LCREG (c, PREG (reg) >> 1);
3535     }
3536   else
3537     illegal_instruction (cpu);
3538
3539   SET_LTREG (c, pc + spcrel);
3540   SET_LBREG (c, pc + epcrel);
3541 }
3542
3543 static void
3544 decode_LDIMMhalf_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
3545 {
3546   /* LDIMMhalf
3547      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3548      | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 |.Z.|.H.|.S.|.grp...|.reg.......|
3549      |.hword.........................................................|
3550      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
3551   int H = ((iw0 >> (LDIMMhalf_H_bits - 16)) & LDIMMhalf_H_mask);
3552   int Z = ((iw0 >> (LDIMMhalf_Z_bits - 16)) & LDIMMhalf_Z_mask);
3553   int S = ((iw0 >> (LDIMMhalf_S_bits - 16)) & LDIMMhalf_S_mask);
3554   int reg = ((iw0 >> (LDIMMhalf_reg_bits - 16)) & LDIMMhalf_reg_mask);
3555   int grp = ((iw0 >> (LDIMMhalf_grp_bits - 16)) & LDIMMhalf_grp_mask);
3556   int hword = ((iw1 >> LDIMMhalf_hword_bits) & LDIMMhalf_hword_mask);
3557   bu32 val;
3558   const char *val_str;
3559   const char *reg_name = get_allreg_name (grp, reg);
3560
3561   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LDIMMhalf);
3562   TRACE_EXTRACT (cpu, "%s: Z:%i H:%i S:%i grp:%i reg:%i hword:%#x",
3563                  __func__, Z, H, S, grp, reg, hword);
3564
3565   if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
3566     illegal_instruction_combination (cpu);
3567
3568   if (S == 1)
3569     val = imm16 (hword), val_str = imm16_str (hword);
3570   else
3571     val = luimm16 (hword), val_str = luimm16_str (hword);
3572
3573   if (H == 0 && S == 1 && Z == 0)
3574     {
3575       TRACE_INSN (cpu, "%s = %s (X);", reg_name, val_str);
3576     }
3577   else if (H == 0 && S == 0 && Z == 1)
3578     {
3579       TRACE_INSN (cpu, "%s = %s (Z);", reg_name, val_str);
3580     }
3581   else if (H == 0 && S == 0 && Z == 0)
3582     {
3583       TRACE_INSN (cpu, "%s.L = %s;", reg_name, val_str);
3584       val = REG_H_L (reg_read (cpu, grp, reg), val);
3585     }
3586   else if (H == 1 && S == 0 && Z == 0)
3587     {
3588       TRACE_INSN (cpu, "%s.H = %s;", reg_name, val_str);
3589       val = REG_H_L (val << 16, reg_read (cpu, grp, reg));
3590     }
3591   else
3592     illegal_instruction (cpu);
3593
3594   reg_write (cpu, grp, reg, val);
3595 }
3596
3597 static void
3598 decode_CALLa_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1, bu32 pc)
3599 {
3600   /* CALLa
3601      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3602      | 1 | 1 | 1 | 0 | 0 | 0 | 1 |.S.|.msw...........................|
3603      |.lsw...........................................................|
3604      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
3605   int S   = ((iw0 >> (CALLa_S_bits - 16)) & CALLa_S_mask);
3606   int lsw = ((iw1 >> 0) & 0xffff);
3607   int msw = ((iw0 >> 0) & 0xff);
3608   int pcrel = pcrel24 ((msw << 16) | lsw);
3609   bu32 newpc = pc + pcrel;
3610
3611   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_CALLa);
3612   TRACE_EXTRACT (cpu, "%s: S:%i msw:%#x lsw:%#x", __func__, S, msw, lsw);
3613   TRACE_DECODE (cpu, "%s: pcrel24:%#x", __func__, pcrel);
3614
3615   TRACE_INSN (cpu, "%s %#x;", S ? "CALL" : "JUMP.L", pcrel);
3616
3617   if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
3618     illegal_instruction_combination (cpu);
3619
3620   if (S == 1)
3621     {
3622       TRACE_BRANCH (cpu, pc, newpc, -1, "CALL");
3623       SET_RETSREG (hwloop_get_next_pc (cpu, pc, 4));
3624     }
3625   else
3626     TRACE_BRANCH (cpu, pc, newpc, -1, "JUMP.L");
3627
3628   SET_PCREG (newpc);
3629   BFIN_CPU_STATE.did_jump = true;
3630   PROFILE_BRANCH_TAKEN (cpu);
3631   CYCLE_DELAY = 5;
3632 }
3633
3634 static void
3635 decode_LDSTidxI_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
3636 {
3637   /* LDSTidxI
3638      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3639      | 1 | 1 | 1 | 0 | 0 | 1 |.W.|.Z.|.sz....|.ptr.......|.reg.......|
3640      |.offset........................................................|
3641      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
3642   int Z = ((iw0 >> (LDSTidxI_Z_bits - 16)) & LDSTidxI_Z_mask);
3643   int W = ((iw0 >> (LDSTidxI_W_bits - 16)) & LDSTidxI_W_mask);
3644   int sz = ((iw0 >> (LDSTidxI_sz_bits - 16)) & LDSTidxI_sz_mask);
3645   int reg = ((iw0 >> (LDSTidxI_reg_bits - 16)) & LDSTidxI_reg_mask);
3646   int ptr = ((iw0 >> (LDSTidxI_ptr_bits - 16)) & LDSTidxI_ptr_mask);
3647   int offset = ((iw1 >> LDSTidxI_offset_bits) & LDSTidxI_offset_mask);
3648   const char *ptr_name = get_preg_name (ptr);
3649   bu32 imm_16s4 = imm16s4 (offset);
3650   bu32 imm_16s2 = imm16s2 (offset);
3651   bu32 imm_16 = imm16 (offset);
3652
3653   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LDSTidxI);
3654   TRACE_EXTRACT (cpu, "%s: W:%i Z:%i sz:%i ptr:%i reg:%i offset:%#x",
3655                  __func__, W, Z, sz, ptr, reg, offset);
3656
3657   if (sz == 3)
3658     illegal_instruction (cpu);
3659
3660   if (W == 0)
3661     {
3662       if (sz == 0 && Z == 0)
3663         {
3664           TRACE_INSN (cpu, "R%i = [%s + %s];",
3665                       reg, ptr_name, imm16s4_str (offset));
3666           SET_DREG (reg, GET_LONG (PREG (ptr) + imm_16s4));
3667         }
3668       else if (sz == 0 && Z == 1)
3669         {
3670           TRACE_INSN (cpu, "%s = [%s + %s];",
3671                       get_preg_name (reg), ptr_name, imm16s4_str (offset));
3672           SET_PREG (reg, GET_LONG (PREG (ptr) + imm_16s4));
3673         }
3674       else if (sz == 1 && Z == 0)
3675         {
3676           TRACE_INSN (cpu, "R%i = W[%s + %s] (Z);",
3677                       reg, ptr_name, imm16s2_str (offset));
3678           SET_DREG (reg, GET_WORD (PREG (ptr) + imm_16s2));
3679         }
3680       else if (sz == 1 && Z == 1)
3681         {
3682           TRACE_INSN (cpu, "R%i = W[%s + %s] (X);",
3683                       reg, ptr_name, imm16s2_str (offset));
3684           SET_DREG (reg, (bs32) (bs16) GET_WORD (PREG (ptr) + imm_16s2));
3685         }
3686       else if (sz == 2 && Z == 0)
3687         {
3688           TRACE_INSN (cpu, "R%i = B[%s + %s] (Z);",
3689                       reg, ptr_name, imm16_str (offset));
3690           SET_DREG (reg, GET_BYTE (PREG (ptr) + imm_16));
3691         }
3692       else if (sz == 2 && Z == 1)
3693         {
3694           TRACE_INSN (cpu, "R%i = B[%s + %s] (X);",
3695                       reg, ptr_name, imm16_str (offset));
3696           SET_DREG (reg, (bs32) (bs8) GET_BYTE (PREG (ptr) + imm_16));
3697         }
3698     }
3699   else
3700     {
3701       if (sz != 0 && Z != 0)
3702         illegal_instruction (cpu);
3703
3704       if (sz == 0 && Z == 0)
3705         {
3706           TRACE_INSN (cpu, "[%s + %s] = R%i;", ptr_name,
3707                       imm16s4_str (offset), reg);
3708           PUT_LONG (PREG (ptr) + imm_16s4, DREG (reg));
3709         }
3710       else if (sz == 0 && Z == 1)
3711         {
3712           TRACE_INSN (cpu, "[%s + %s] = %s;",
3713                       ptr_name, imm16s4_str (offset), get_preg_name (reg));
3714           PUT_LONG (PREG (ptr) + imm_16s4, PREG (reg));
3715         }
3716       else if (sz == 1 && Z == 0)
3717         {
3718           TRACE_INSN (cpu, "W[%s + %s] = R%i;",
3719                       ptr_name, imm16s2_str (offset), reg);
3720           PUT_WORD (PREG (ptr) + imm_16s2, DREG (reg));
3721         }
3722       else if (sz == 2 && Z == 0)
3723         {
3724           TRACE_INSN (cpu, "B[%s + %s] = R%i;",
3725                       ptr_name, imm16_str (offset), reg);
3726           PUT_BYTE (PREG (ptr) + imm_16, DREG (reg));
3727         }
3728     }
3729 }
3730
3731 static void
3732 decode_linkage_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
3733 {
3734   /* linkage
3735      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3736      | 1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |.R.|
3737      |.framesize.....................................................|
3738      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
3739   int R = ((iw0 >> (Linkage_R_bits - 16)) & Linkage_R_mask);
3740   int framesize = ((iw1 >> Linkage_framesize_bits) & Linkage_framesize_mask);
3741   bu32 sp;
3742
3743   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_linkage);
3744   TRACE_EXTRACT (cpu, "%s: R:%i framesize:%#x", __func__, R, framesize);
3745
3746   if (R == 0)
3747     {
3748       int size = uimm16s4 (framesize);
3749       sp = SPREG;
3750       TRACE_INSN (cpu, "LINK %s;", uimm16s4_str (framesize));
3751       if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
3752         illegal_instruction_combination (cpu);
3753       sp -= 4;
3754       PUT_LONG (sp, RETSREG);
3755       sp -= 4;
3756       PUT_LONG (sp, FPREG);
3757       SET_FPREG (sp);
3758       sp -= size;
3759       CYCLE_DELAY = 3;
3760     }
3761   else
3762     {
3763       /* Restore SP from FP.  */
3764       sp = FPREG;
3765       TRACE_INSN (cpu, "UNLINK;");
3766       if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
3767         illegal_instruction_combination (cpu);
3768       SET_FPREG (GET_LONG (sp));
3769       sp += 4;
3770       SET_RETSREG (GET_LONG (sp));
3771       sp += 4;
3772       CYCLE_DELAY = 2;
3773     }
3774
3775   SET_SPREG (sp);
3776 }
3777
3778 static void
3779 decode_dsp32mac_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
3780 {
3781   /* dsp32mac
3782      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3783      | 1 | 1 | 0 | 0 |.M.| 0 | 0 |.mmod..........|.MM|.P.|.w1|.op1...|
3784      |.h01|.h11|.w0|.op0...|.h00|.h10|.dst.......|.src0......|.src1..|
3785      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
3786   int op1  = ((iw0 >> (DSP32Mac_op1_bits - 16)) & DSP32Mac_op1_mask);
3787   int w1   = ((iw0 >> (DSP32Mac_w1_bits - 16)) & DSP32Mac_w1_mask);
3788   int P    = ((iw0 >> (DSP32Mac_p_bits - 16)) & DSP32Mac_p_mask);
3789   int MM   = ((iw0 >> (DSP32Mac_MM_bits - 16)) & DSP32Mac_MM_mask);
3790   int mmod = ((iw0 >> (DSP32Mac_mmod_bits - 16)) & DSP32Mac_mmod_mask);
3791   int M    = ((iw0 >> (DSP32Mac_M_bits - 16)) & DSP32Mac_M_mask);
3792   int w0   = ((iw1 >> DSP32Mac_w0_bits) & DSP32Mac_w0_mask);
3793   int src0 = ((iw1 >> DSP32Mac_src0_bits) & DSP32Mac_src0_mask);
3794   int src1 = ((iw1 >> DSP32Mac_src1_bits) & DSP32Mac_src1_mask);
3795   int dst  = ((iw1 >> DSP32Mac_dst_bits) & DSP32Mac_dst_mask);
3796   int h10  = ((iw1 >> DSP32Mac_h10_bits) & DSP32Mac_h10_mask);
3797   int h00  = ((iw1 >> DSP32Mac_h00_bits) & DSP32Mac_h00_mask);
3798   int op0  = ((iw1 >> DSP32Mac_op0_bits) & DSP32Mac_op0_mask);
3799   int h11  = ((iw1 >> DSP32Mac_h11_bits) & DSP32Mac_h11_mask);
3800   int h01  = ((iw1 >> DSP32Mac_h01_bits) & DSP32Mac_h01_mask);
3801
3802   bu32 res = DREG (dst);
3803   bu32 v_0 = 0, v_1 = 0, zero = 0, n_1 = 0, n_0 = 0;
3804
3805   static const char * const ops[] = { "=", "+=", "-=" };
3806   char _buf[128], *buf = _buf;
3807   int _MM = MM;
3808
3809   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dsp32mac);
3810   TRACE_EXTRACT (cpu, "%s: M:%i mmod:%i MM:%i P:%i w1:%i op1:%i h01:%i h11:%i "
3811                       "w0:%i op0:%i h00:%i h10:%i dst:%i src0:%i src1:%i",
3812                  __func__, M, mmod, MM, P, w1, op1, h01, h11, w0, op0, h00, h10,
3813                  dst, src0, src1);
3814
3815   if (w0 == 0 && w1 == 0 && op1 == 3 && op0 == 3)
3816     illegal_instruction (cpu);
3817
3818   if ((w1 || w0) && mmod == M_W32)
3819     illegal_instruction (cpu);
3820
3821   if (((1 << mmod) & (P ? 0x131b : 0x1b5f)) == 0)
3822     illegal_instruction (cpu);
3823
3824   /* First handle MAC1 side.  */
3825   if (w1 == 1 || op1 != 3)
3826     {
3827       bu32 res1 = decode_macfunc (cpu, 1, op1, h01, h11, src0,
3828                                   src1, mmod, MM, P, &v_1, &n_1);
3829
3830       if (w1)
3831         buf += sprintf (buf, P ? "R%i" : "R%i.H", dst + P);
3832
3833       if (op1 == 3)
3834         {
3835           buf += sprintf (buf, " = A1");
3836           zero = !!(res1 == 0);
3837         }
3838       else
3839         {
3840           if (w1)
3841             buf += sprintf (buf, " = (");
3842           buf += sprintf (buf, "A1 %s R%i.%c * R%i.%c", ops[op1],
3843                           src0, h01 ? 'H' : 'L',
3844                           src1, h11 ? 'H' : 'L');
3845           if (w1)
3846             buf += sprintf (buf, ")");
3847         }
3848
3849       if (w1)
3850         {
3851           if (P)
3852             STORE (DREG (dst + 1), res1);
3853           else
3854             {
3855               if (res1 & 0xffff0000)
3856                 illegal_instruction (cpu);
3857               res = REG_H_L (res1 << 16, res);
3858             }
3859         }
3860       else
3861         v_1 = 0;
3862
3863       if (w0 == 1 || op0 != 3)
3864         {
3865           if (_MM)
3866             buf += sprintf (buf, " (M)");
3867           _MM = 0;
3868           buf += sprintf (buf, ", ");
3869         }
3870     }
3871
3872   /* Then handle MAC0 side.  */
3873   if (w0 == 1 || op0 != 3)
3874     {
3875       bu32 res0 = decode_macfunc (cpu, 0, op0, h00, h10, src0,
3876                                   src1, mmod, 0, P, &v_0, &n_0);
3877
3878       if (w0)
3879         buf += sprintf (buf, P ? "R%i" : "R%i.L", dst);
3880
3881       if (op0 == 3)
3882         {
3883           buf += sprintf (buf, " = A0");
3884           zero |= !!(res0 == 0);
3885         }
3886       else
3887         {
3888           if (w0)
3889             buf += sprintf (buf, " = (");
3890           buf += sprintf (buf, "A0 %s R%i.%c * R%i.%c", ops[op0],
3891                           src0, h00 ? 'H' : 'L',
3892                           src1, h10 ? 'H' : 'L');
3893           if (w0)
3894             buf += sprintf (buf, ")");
3895         }
3896
3897       if (w0)
3898         {
3899           if (P)
3900             STORE (DREG (dst), res0);
3901           else
3902             {
3903               if (res0 & 0xffff0000)
3904                 illegal_instruction (cpu);
3905               res = REG_H_L (res, res0);
3906             }
3907         }
3908       else
3909         v_0 = 0;
3910     }
3911
3912   TRACE_INSN (cpu, "%s%s;", _buf, mac_optmode (mmod, _MM));
3913
3914   if (!P && (w0 || w1))
3915     {
3916       STORE (DREG (dst), res);
3917       SET_ASTATREG (v, v_0 | v_1);
3918       if (v_0 || v_1)
3919         SET_ASTATREG (vs, 1);
3920     }
3921   else if (P)
3922     {
3923       SET_ASTATREG (v, v_0 | v_1);
3924       if (v_0 || v_1)
3925         SET_ASTATREG (vs, 1);
3926     }
3927
3928   if ((w0 == 1 && op0 == 3) || (w1 == 1 && op1 == 3))
3929     {
3930       SET_ASTATREG (az, zero);
3931       if (!(w0 == 1 && op0 == 3))
3932         n_0 = 0;
3933       if (!(w1 == 1 && op1 == 3))
3934         n_1 = 0;
3935       SET_ASTATREG (an, n_1 | n_0);
3936     }
3937 }
3938
3939 static void
3940 decode_dsp32mult_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
3941 {
3942   /* dsp32mult
3943      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3944      | 1 | 1 | 0 | 0 |.M.| 0 | 1 |.mmod..........|.MM|.P.|.w1|.op1...|
3945      |.h01|.h11|.w0|.op0...|.h00|.h10|.dst.......|.src0......|.src1..|
3946      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
3947   int op1  = ((iw0 >> (DSP32Mac_op1_bits - 16)) & DSP32Mac_op1_mask);
3948   int w1   = ((iw0 >> (DSP32Mac_w1_bits - 16)) & DSP32Mac_w1_mask);
3949   int P    = ((iw0 >> (DSP32Mac_p_bits - 16)) & DSP32Mac_p_mask);
3950   int MM   = ((iw0 >> (DSP32Mac_MM_bits - 16)) & DSP32Mac_MM_mask);
3951   int mmod = ((iw0 >> (DSP32Mac_mmod_bits - 16)) & DSP32Mac_mmod_mask);
3952   int M    = ((iw0 >> (DSP32Mac_M_bits - 16)) & DSP32Mac_M_mask);
3953   int w0   = ((iw1 >> DSP32Mac_w0_bits) & DSP32Mac_w0_mask);
3954   int src0 = ((iw1 >> DSP32Mac_src0_bits) & DSP32Mac_src0_mask);
3955   int src1 = ((iw1 >> DSP32Mac_src1_bits) & DSP32Mac_src1_mask);
3956   int dst  = ((iw1 >> DSP32Mac_dst_bits) & DSP32Mac_dst_mask);
3957   int h10  = ((iw1 >> DSP32Mac_h10_bits) & DSP32Mac_h10_mask);
3958   int h00  = ((iw1 >> DSP32Mac_h00_bits) & DSP32Mac_h00_mask);
3959   int op0  = ((iw1 >> DSP32Mac_op0_bits) & DSP32Mac_op0_mask);
3960   int h11  = ((iw1 >> DSP32Mac_h11_bits) & DSP32Mac_h11_mask);
3961   int h01  = ((iw1 >> DSP32Mac_h01_bits) & DSP32Mac_h01_mask);
3962
3963   bu32 res = DREG (dst);
3964   bu32 sat0 = 0, sat1 = 0, v_i0 = 0, v_i1 = 0;
3965   char _buf[128], *buf = _buf;
3966   int _MM = MM;
3967
3968   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dsp32mult);
3969   TRACE_EXTRACT (cpu, "%s: M:%i mmod:%i MM:%i P:%i w1:%i op1:%i h01:%i h11:%i "
3970                       "w0:%i op0:%i h00:%i h10:%i dst:%i src0:%i src1:%i",
3971                  __func__, M, mmod, MM, P, w1, op1, h01, h11, w0, op0, h00, h10,
3972                  dst, src0, src1);
3973
3974   if (w1 == 0 && w0 == 0)
3975     illegal_instruction (cpu);
3976   if (((1 << mmod) & (P ? 0x313 : 0x1b57)) == 0)
3977     illegal_instruction (cpu);
3978   if (P && ((dst & 1) || (op1 != 0) || (op0 != 0) || !is_macmod_pmove (mmod)))
3979     illegal_instruction (cpu);
3980   if (!P && ((op1 != 0) || (op0 != 0) || !is_macmod_hmove (mmod)))
3981     illegal_instruction (cpu);
3982
3983   /* First handle MAC1 side.  */
3984   if (w1)
3985     {
3986       bu64 r = decode_multfunc (cpu, h01, h11, src0, src1, mmod, MM, &sat1);
3987       bu32 res1 = extract_mult (cpu, r, mmod, MM, P, &v_i1);
3988
3989       buf += sprintf (buf, P ? "R%i" : "R%i.H", dst + P);
3990       buf += sprintf (buf, " = R%i.%c * R%i.%c",
3991                       src0, h01 ? 'H' : 'L',
3992                       src1, h11 ? 'H' : 'L');
3993       if (w0)
3994         {
3995           if (_MM)
3996             buf += sprintf (buf, " (M)");
3997           _MM = 0;
3998           buf += sprintf (buf, ", ");
3999         }
4000
4001       if (P)
4002         STORE (DREG (dst + 1), res1);
4003       else
4004         {
4005           if (res1 & 0xFFFF0000)
4006             illegal_instruction (cpu);
4007           res = REG_H_L (res1 << 16, res);
4008         }
4009     }
4010
4011   /* First handle MAC0 side.  */
4012   if (w0)
4013     {
4014       bu64 r = decode_multfunc (cpu, h00, h10, src0, src1, mmod, 0, &sat0);
4015       bu32 res0 = extract_mult (cpu, r, mmod, 0, P, &v_i0);
4016
4017       buf += sprintf (buf, P ? "R%i" : "R%i.L", dst);
4018       buf += sprintf (buf, " = R%i.%c * R%i.%c",
4019                       src0, h01 ? 'H' : 'L',
4020                       src1, h11 ? 'H' : 'L');
4021
4022       if (P)
4023         STORE (DREG (dst), res0);
4024       else
4025         {
4026           if (res0 & 0xFFFF0000)
4027             illegal_instruction (cpu);
4028           res = REG_H_L (res, res0);
4029         }
4030     }
4031
4032   TRACE_INSN (cpu, "%s%s;", _buf, mac_optmode (mmod, _MM));
4033
4034   if (!P && (w0 || w1))
4035     STORE (DREG (dst), res);
4036
4037   if (w0 || w1)
4038     {
4039       bu32 v = sat0 | sat1 | v_i0 | v_i1;
4040
4041       STORE (ASTATREG (v), v);
4042       STORE (ASTATREG (v_copy), v);
4043       if (v)
4044         STORE (ASTATREG (vs), v);
4045     }
4046 }
4047
4048 static void
4049 decode_dsp32alu_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
4050 {
4051   /* dsp32alu
4052      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
4053      | 1 | 1 | 0 | 0 |.M.| 1 | 0 | - | - | - |.HL|.aopcde............|
4054      |.aop...|.s.|.x.|.dst0......|.dst1......|.src0......|.src1......|
4055      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
4056   int s    = ((iw1 >> DSP32Alu_s_bits) & DSP32Alu_s_mask);
4057   int x    = ((iw1 >> DSP32Alu_x_bits) & DSP32Alu_x_mask);
4058   int aop  = ((iw1 >> DSP32Alu_aop_bits) & DSP32Alu_aop_mask);
4059   int src0 = ((iw1 >> DSP32Alu_src0_bits) & DSP32Alu_src0_mask);
4060   int src1 = ((iw1 >> DSP32Alu_src1_bits) & DSP32Alu_src1_mask);
4061   int dst0 = ((iw1 >> DSP32Alu_dst0_bits) & DSP32Alu_dst0_mask);
4062   int dst1 = ((iw1 >> DSP32Alu_dst1_bits) & DSP32Alu_dst1_mask);
4063   int M    = ((iw0 >> (DSP32Alu_M_bits - 16)) & DSP32Alu_M_mask);
4064   int HL   = ((iw0 >> (DSP32Alu_HL_bits - 16)) & DSP32Alu_HL_mask);
4065   int aopcde = ((iw0 >> (DSP32Alu_aopcde_bits - 16)) & DSP32Alu_aopcde_mask);
4066
4067   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dsp32alu);
4068   TRACE_EXTRACT (cpu, "%s: M:%i HL:%i aopcde:%i aop:%i s:%i x:%i dst0:%i "
4069                       "dst1:%i src0:%i src1:%i",
4070                  __func__, M, HL, aopcde, aop, s, x, dst0, dst1, src0, src1);
4071
4072   if ((aop == 0 || aop == 2) && aopcde == 9 && x == 0 && s == 0 && HL == 0)
4073     {
4074       int a = aop >> 1;
4075       TRACE_INSN (cpu, "A%i.L = R%i.L;", a, src0);
4076       SET_AWREG (a, REG_H_L (AWREG (a), DREG (src0)));
4077     }
4078   else if ((aop == 0 || aop == 2) && aopcde == 9 && x == 0 && s == 0 && HL == 1)
4079     {
4080       int a = aop >> 1;
4081       TRACE_INSN (cpu, "A%i.H = R%i.H;", a, src0);
4082       SET_AWREG (a, REG_H_L (DREG (src0), AWREG (a)));
4083     }
4084   else if ((aop == 1 || aop == 0) && aopcde == 5 && x == 0 && s == 0)
4085     {
4086       bs32 val0 = DREG (src0);
4087       bs32 val1 = DREG (src1);
4088       bs32 res;
4089       bs32 signRes;
4090       bs32 ovX, sBit1, sBit2, sBitRes1, sBitRes2;
4091
4092       TRACE_INSN (cpu, "R%i.%s = R%i %s R%i (RND12)", dst0, HL ? "L" : "H",
4093                   src0, aop & 0x1 ? "-" : "+", src1);
4094
4095       /* If subtract, just invert and add one.  */
4096       if (aop & 0x1)
4097         {
4098           if (val1 == 0x80000000)
4099             val1 = 0x7FFFFFFF;
4100           else
4101             val1 = ~val1 + 1;
4102         }
4103
4104       /* Get the sign bits, since we need them later.  */
4105       sBit1 = !!(val0 & 0x80000000);
4106       sBit2 = !!(val1 & 0x80000000);
4107
4108       res = val0 + val1;
4109
4110       sBitRes1 = !!(res & 0x80000000);
4111       /* Round to the 12th bit.  */
4112       res += 0x0800;
4113       sBitRes2 = !!(res & 0x80000000);
4114
4115       signRes = res;
4116       signRes >>= 27;
4117
4118       /* Overflow if
4119            pos + pos = neg
4120            neg + neg = pos
4121            positive_res + positive_round = neg
4122          Shift and upper 4 bits where not the same.  */
4123       if ((!(sBit1 ^ sBit2) && (sBit1 ^ sBitRes1))
4124           || (!sBit1 && !sBit2 && sBitRes2)
4125           || ((signRes != 0) && (signRes != -1)))
4126         {
4127           /* Both X1 and X2 Neg res is neg overflow.  */
4128           if (sBit1 && sBit2)
4129             res = 0x80000000;
4130           /* Both X1 and X2 Pos res is pos overflow.  */
4131           else if (!sBit1 && !sBit2)
4132             res = 0x7FFFFFFF;
4133           /* Pos+Neg or Neg+Pos take the sign of the result.  */
4134           else if (sBitRes1)
4135             res = 0x80000000;
4136           else
4137             res = 0x7FFFFFFF;
4138
4139           ovX = 1;
4140         }
4141       else
4142         {
4143           /* Shift up now after overflow detection.  */
4144           ovX = 0;
4145           res <<= 4;
4146         }
4147
4148       res >>= 16;
4149
4150       if (HL)
4151         STORE (DREG (dst0), REG_H_L (res << 16, DREG (dst0)));
4152       else
4153         STORE (DREG (dst0), REG_H_L (DREG (dst0), res));
4154
4155       SET_ASTATREG (az, res == 0);
4156       SET_ASTATREG (an, res & 0x8000);
4157       SET_ASTATREG (v, ovX);
4158       if (ovX)
4159         SET_ASTATREG (vs, ovX);
4160     }
4161   else if ((aop == 2 || aop == 3) && aopcde == 5 && x == 1 && s == 0)
4162     {
4163       bs32 val0 = DREG (src0);
4164       bs32 val1 = DREG (src1);
4165       bs32 res;
4166
4167       TRACE_INSN (cpu, "R%i.%s = R%i %s R%i (RND20)", dst0, HL ? "L" : "H",
4168                   src0, aop & 0x1 ? "-" : "+", src1);
4169
4170       /* If subtract, just invert and add one.  */
4171       if (aop & 0x1)
4172         val1 = ~val1 + 1;
4173
4174       res = (val0 >> 4) + (val1 >> 4) + (((val0 & 0xf) + (val1 & 0xf)) >> 4);
4175       res += 0x8000;
4176       /* Don't sign extend during the shift.  */
4177       res = ((bu32)res >> 16);
4178
4179       /* Don't worry about overflows, since we are shifting right.  */
4180
4181       if (HL)
4182         STORE (DREG (dst0), REG_H_L (res << 16, DREG (dst0)));
4183       else
4184         STORE (DREG (dst0), REG_H_L (DREG (dst0), res));
4185
4186       SET_ASTATREG (az, res == 0);
4187       SET_ASTATREG (an, res & 0x8000);
4188       SET_ASTATREG (v, 0);
4189     }
4190   else if ((aopcde == 2 || aopcde == 3) && x == 0)
4191     {
4192       bu32 s1, s2, val, ac0_i = 0, v_i = 0;
4193
4194       TRACE_INSN (cpu, "R%i.%c = R%i.%c %c R%i.%c%s;",
4195                   dst0, HL ? 'H' : 'L',
4196                   src0, aop & 2 ? 'H' : 'L',
4197                   aopcde == 2 ? '+' : '-',
4198                   src1, aop & 1 ? 'H' : 'L',
4199                   amod1 (s, x));
4200
4201       s1 = DREG (src0);
4202       s2 = DREG (src1);
4203       if (aop & 1)
4204         s2 >>= 16;
4205       if (aop & 2)
4206         s1 >>= 16;
4207
4208       if (aopcde == 2)
4209         val = add16 (cpu, s1, s2, &ac0_i, &v_i, 0, 0, s, 0);
4210       else
4211         val = sub16 (cpu, s1, s2, &ac0_i, &v_i, 0, 0, s, 0);
4212
4213       SET_ASTATREG (ac0, ac0_i);
4214       SET_ASTATREG (v, v_i);
4215       if (v_i)
4216         SET_ASTATREG (vs, v_i);
4217
4218       if (HL)
4219         SET_DREG_H (dst0, val << 16);
4220       else
4221         SET_DREG_L (dst0, val);
4222
4223       SET_ASTATREG (an, val & 0x8000);
4224       SET_ASTATREG (az, val == 0);
4225     }
4226   else if ((aop == 0 || aop == 2) && aopcde == 9 && x == 0 && s == 1 && HL == 0)
4227     {
4228       int a = aop >> 1;
4229       TRACE_INSN (cpu, "A%i = R%i;", a, src0);
4230       SET_AREG32 (a, DREG (src0));
4231     }
4232   else if ((aop == 1 || aop == 3) && aopcde == 9 && x == 0 && s == 0 && HL == 0)
4233     {
4234       int a = aop >> 1;
4235       TRACE_INSN (cpu, "A%i.X = R%i.L;", a, src0);
4236       SET_AXREG (a, (bs8)DREG (src0));
4237     }
4238   else if (aop == 3 && aopcde == 11 && x == 0 && HL == 0)
4239     {
4240       bu64 acc0 = get_extended_acc (cpu, 0);
4241       bu64 acc1 = get_extended_acc (cpu, 1);
4242       bu32 carry = (bu40)acc1 < (bu40)acc0;
4243       bu32 sat = 0;
4244
4245       TRACE_INSN (cpu, "A0 -= A1%s;", s ? " (W32)" : "");
4246
4247       acc0 -= acc1;
4248       if ((bs64)acc0 < -0x8000000000ll)
4249         acc0 = -0x8000000000ull, sat = 1;
4250       else if ((bs64)acc0 >= 0x7fffffffffll)
4251         acc0 = 0x7fffffffffull, sat = 1;
4252
4253       if (s == 1)
4254         {
4255           /* A0 -= A1 (W32)  */
4256           if (acc0 & (bu64)0x8000000000ll)
4257             acc0 &= 0x80ffffffffll, sat = 1;
4258           else
4259             acc0 &= 0xffffffffll;
4260         }
4261       STORE (AXREG (0), (acc0 >> 32) & 0xff);
4262       STORE (AWREG (0), acc0 & 0xffffffff);
4263       STORE (ASTATREG (az), acc0 == 0);
4264       STORE (ASTATREG (an), !!(acc0 & (bu64)0x8000000000ll));
4265       STORE (ASTATREG (ac0), carry);
4266       STORE (ASTATREG (ac0_copy), carry);
4267       STORE (ASTATREG (av0), sat);
4268       if (sat)
4269         STORE (ASTATREG (av0s), sat);
4270     }
4271   else if ((aop == 0 || aop == 1) && aopcde == 22 && x == 0)
4272     {
4273       bu32 s0, s0L, s0H, s1, s1L, s1H;
4274       bu32 tmp0, tmp1, i;
4275       const char * const opts[] = { "rndl", "rndh", "tl", "th" };
4276
4277       TRACE_INSN (cpu, "R%i = BYTEOP2P (R%i:%i, R%i:%i) (%s%s);", dst0,
4278                   src0 + 1, src0, src1 + 1, src1, opts[HL + (aop << 1)],
4279                   s ? ", r" : "");
4280
4281       if ((src1 != 0 && src1 != 2) || (src0 != 0 && src0 != 2))
4282         illegal_instruction (cpu);
4283
4284       s0L = DREG (src0);
4285       s0H = DREG (src0 + 1);
4286       s1L = DREG (src1);
4287       s1H = DREG (src1 + 1);
4288       if (s)
4289         {
4290           s0 = algn (s0H, s0L, IREG (0) & 3);
4291           s1 = algn (s1H, s1L, IREG (0) & 3);
4292         }
4293       else
4294         {
4295           s0 = algn (s0L, s0H, IREG (0) & 3);
4296           s1 = algn (s1L, s1H, IREG (0) & 3);
4297         }
4298
4299       i = !aop * 2;
4300       tmp0 = ((((s1 >>  8) & 0xff) + ((s1 >>  0) & 0xff) +
4301                ((s0 >>  8) & 0xff) + ((s0 >>  0) & 0xff) + i) >> 2) & 0xff;
4302       tmp1 = ((((s1 >> 24) & 0xff) + ((s1 >> 16) & 0xff) +
4303                ((s0 >> 24) & 0xff) + ((s0 >> 16) & 0xff) + i) >> 2) & 0xff;
4304       STORE (DREG (dst0), (tmp1 << (16 + (HL * 8))) | (tmp0 << (HL * 8)));
4305
4306       /* Implicit DISALGNEXCPT in parallel.  */
4307       DIS_ALGN_EXPT |= 1;
4308     }
4309   else if ((aop == 0 || aop == 1) && aopcde == 8 && x == 0 && s == 0 && HL == 0)
4310     {
4311       TRACE_INSN (cpu, "A%i = 0;", aop);
4312       SET_AREG (aop, 0);
4313     }
4314   else if (aop == 2 && aopcde == 8 && x == 0 && s == 0 && HL == 0)
4315     {
4316       TRACE_INSN (cpu, "A1 = A0 = 0;");
4317       SET_AREG (0, 0);
4318       SET_AREG (1, 0);
4319     }
4320   else if ((aop == 0 || aop == 1 || aop == 2) && s == 1 && aopcde == 8
4321            && x == 0 && s == 1 && HL == 0)
4322     {
4323       bs40 acc0 = get_extended_acc (cpu, 0);
4324       bs40 acc1 = get_extended_acc (cpu, 1);
4325       bu32 sat;
4326
4327       if (aop == 0 || aop == 1)
4328         TRACE_INSN (cpu, "A%i = A%i (S);", aop, aop);
4329       else
4330         TRACE_INSN (cpu, "A1 = A1 (S), A0 = A0 (S);");
4331
4332       if (aop == 0 || aop == 2)
4333         {
4334           sat = 0;
4335           acc0 = saturate_s32 (acc0, &sat);
4336           acc0 |= -(acc0 & 0x80000000ull);
4337           SET_AXREG (0, (acc0 >> 31) & 0xFF);
4338           SET_AWREG (0, acc0 & 0xFFFFFFFF);
4339           SET_ASTATREG (av0, sat);
4340           if (sat)
4341             SET_ASTATREG (av0s, sat);
4342         }
4343       else
4344         acc0 = 1;
4345
4346       if (aop == 1 || aop == 2)
4347         {
4348           sat = 0;
4349           acc1 = saturate_s32 (acc1, &sat);
4350           acc1 |= -(acc1 & 0x80000000ull);
4351           SET_AXREG (1, (acc1 >> 31) & 0xFF);
4352           SET_AWREG (1, acc1 & 0xFFFFFFFF);
4353           SET_ASTATREG (av1, sat);
4354           if (sat)
4355             SET_ASTATREG (av1s, sat);
4356         }
4357       else
4358         acc1 = 1;
4359
4360       SET_ASTATREG (az, (acc0 == 0) || (acc1 == 0));
4361       SET_ASTATREG (an, ((acc0 >> 31) & 1) || ((acc1 >> 31) & 1));
4362     }
4363   else if (aop == 3 && aopcde == 8 && x == 0 && HL == 0)
4364     {
4365       TRACE_INSN (cpu, "A%i = A%i;", s, !s);
4366       SET_AXREG (s, AXREG (!s));
4367       SET_AWREG (s, AWREG (!s));
4368     }
4369   else if (aop == 3 && HL == 0 && aopcde == 16 && x == 0 && s == 0)
4370     {
4371       int i;
4372       bu32 az;
4373
4374       TRACE_INSN (cpu, "A1 = ABS A1 , A0 = ABS A0;");
4375
4376       az = 0;
4377       for (i = 0; i < 2; ++i)
4378         {
4379           bu32 av;
4380           bs40 acc = get_extended_acc (cpu, i);
4381
4382           if (acc >> 39)
4383             acc = -acc;
4384           av = acc == ((bs40)1 << 39);
4385           if (av)
4386             acc = ((bs40)1 << 39) - 1;
4387
4388           SET_AREG (i, acc);
4389           SET_ASTATREG (av[i], av);
4390           if (av)
4391             SET_ASTATREG (avs[i], av);
4392           az |= (acc == 0);
4393         }
4394       SET_ASTATREG (az, az);
4395       SET_ASTATREG (an, 0);
4396     }
4397   else if (aop == 0 && aopcde == 23 && x == 0)
4398     {
4399       bu32 s0, s0L, s0H, s1, s1L, s1H;
4400       bs32 tmp0, tmp1;
4401
4402       TRACE_INSN (cpu, "R%i = BYTEOP3P (R%i:%i, R%i:%i) (%s%s);", dst0,
4403                   src0 + 1, src0, src1 + 1, src1, HL ? "HI" : "LO",
4404                   s ? ", R" : "");
4405
4406       if ((src1 != 0 && src1 != 2) || (src0 != 0 && src0 != 2))
4407         illegal_instruction (cpu);
4408
4409       s0L = DREG (src0);
4410       s0H = DREG (src0 + 1);
4411       s1L = DREG (src1);
4412       s1H = DREG (src1 + 1);
4413       if (s)
4414         {
4415           s0 = algn (s0H, s0L, IREG (0) & 3);
4416           s1 = algn (s1H, s1L, IREG (1) & 3);
4417         }
4418       else
4419         {
4420           s0 = algn (s0L, s0H, IREG (0) & 3);
4421           s1 = algn (s1L, s1H, IREG (1) & 3);
4422         }
4423
4424       tmp0 = (bs32)(bs16)(s0 >>  0) + ((s1 >> ( 0 + (8 * !HL))) & 0xff);
4425       tmp1 = (bs32)(bs16)(s0 >> 16) + ((s1 >> (16 + (8 * !HL))) & 0xff);
4426       STORE (DREG (dst0), (CLAMP (tmp0, 0, 255) << ( 0 + (8 * HL))) |
4427                           (CLAMP (tmp1, 0, 255) << (16 + (8 * HL))));
4428
4429       /* Implicit DISALGNEXCPT in parallel.  */
4430       DIS_ALGN_EXPT |= 1;
4431     }
4432   else if ((aop == 0 || aop == 1) && aopcde == 16 && x == 0 && s == 0)
4433     {
4434       bu32 av;
4435       bs40 acc;
4436
4437       TRACE_INSN (cpu, "A%i = ABS A%i;", HL, aop);
4438
4439       acc = get_extended_acc (cpu, aop);
4440       if (acc >> 39)
4441         acc = -acc;
4442       av = acc == ((bs40)1 << 39);
4443       if (av)
4444         acc = ((bs40)1 << 39) - 1;
4445       SET_AREG (HL, acc);
4446
4447       SET_ASTATREG (av[HL], av);
4448       if (av)
4449         SET_ASTATREG (avs[HL], av);
4450       SET_ASTATREG (az, acc == 0);
4451       SET_ASTATREG (an, 0);
4452     }
4453   else if (aop == 3 && aopcde == 12 && x == 0 && s == 0)
4454     {
4455       bs32 res = DREG (src0);
4456       bs32 ovX;
4457       bool sBit_a, sBit_b;
4458
4459       TRACE_INSN (cpu, "R%i.%s = R%i (RND);", dst0, HL == 0 ? "L" : "H", src0);
4460       TRACE_DECODE (cpu, "R%i.%s = R%i:%#x (RND);", dst0,
4461                     HL == 0 ? "L" : "H", src0, res);
4462
4463       sBit_b = !!(res & 0x80000000);
4464
4465       res += 0x8000;
4466       sBit_a = !!(res & 0x80000000);
4467
4468       /* Overflow if the sign bit changed when we rounded.  */
4469       if ((res >> 16) && (sBit_b != sBit_a))
4470         {
4471           ovX = 1;
4472           if (!sBit_b)
4473             res = 0x7FFF;
4474           else
4475             res = 0x8000;
4476         }
4477       else
4478         {
4479           res = res >> 16;
4480           ovX = 0;
4481         }
4482
4483       if (!HL)
4484         SET_DREG (dst0, REG_H_L (DREG (dst0), res));
4485       else
4486         SET_DREG (dst0, REG_H_L (res << 16, DREG (dst0)));
4487
4488       SET_ASTATREG (az, res == 0);
4489       SET_ASTATREG (an, res < 0);
4490       SET_ASTATREG (v, ovX);
4491       if (ovX)
4492         SET_ASTATREG (vs, ovX);
4493     }
4494   else if (aop == 3 && HL == 0 && aopcde == 15 && x == 0 && s == 0)
4495     {
4496       bu32 hi = (-(bs16)(DREG (src0) >> 16)) << 16;
4497       bu32 lo = (-(bs16)(DREG (src0) & 0xFFFF)) & 0xFFFF;
4498       int v, ac0, ac1;
4499
4500       TRACE_INSN (cpu, "R%i = -R%i (V);", dst0, src0);
4501
4502       v = ac0 = ac1 = 0;
4503
4504       if (hi == 0x80000000)
4505         {
4506           hi = 0x7fff0000;
4507           v = 1;
4508         }
4509       else if (hi == 0)
4510         ac1 = 1;
4511
4512       if (lo == 0x8000)
4513         {
4514           lo = 0x7fff;
4515           v = 1;
4516         }
4517       else if (lo == 0)
4518         ac0 = 1;
4519
4520       SET_DREG (dst0, hi | lo);
4521
4522       SET_ASTATREG (v, v);
4523       if (v)
4524         SET_ASTATREG (vs, 1);
4525       SET_ASTATREG (ac0, ac0);
4526       SET_ASTATREG (ac1, ac1);
4527       setflags_nz_2x16 (cpu, DREG (dst0));
4528     }
4529   else if (aop == 3 && HL == 0 && aopcde == 14 && x == 0 && s == 0)
4530     {
4531       TRACE_INSN (cpu, "A1 = - A1 , A0 = - A0;");
4532
4533       SET_AREG (0, saturate_s40 (-get_extended_acc (cpu, 0)));
4534       SET_AREG (1, saturate_s40 (-get_extended_acc (cpu, 1)));
4535       /* XXX: what ASTAT flags need updating ?  */
4536     }
4537   else if ((aop == 0 || aop == 1) && aopcde == 14 && x == 0 && s == 0)
4538     {
4539       bs40 src_acc = get_extended_acc (cpu, aop);
4540       int v = 0;
4541
4542       TRACE_INSN (cpu, "A%i = - A%i;", HL, aop);
4543
4544       SET_AREG (HL, saturate_s40_astat (-src_acc, &v));
4545
4546       SET_ASTATREG (az, AWREG (HL) == 0 && AXREG (HL) == 0);
4547       SET_ASTATREG (an, AXREG (HL) >> 7);
4548       if (HL == 0)
4549         {
4550           SET_ASTATREG (ac0, !src_acc);
4551           SET_ASTATREG (av0, v);
4552           if (v)
4553             SET_ASTATREG (av0s, 1);
4554         }
4555       else
4556         {
4557           SET_ASTATREG (ac1, !src_acc);
4558           SET_ASTATREG (av1, v);
4559           if (v)
4560             SET_ASTATREG (av1s, 1);
4561         }
4562     }
4563   else if (aop == 0 && aopcde == 12 && x == 0 && s == 0 && HL == 0)
4564     {
4565       bs16 tmp0_hi = DREG (src0) >> 16;
4566       bs16 tmp0_lo = DREG (src0);
4567       bs16 tmp1_hi = DREG (src1) >> 16;
4568       bs16 tmp1_lo = DREG (src1);
4569
4570       TRACE_INSN (cpu, "R%i.L = R%i.H = SIGN(R%i.H) * R%i.H + SIGN(R%i.L) * R%i.L;",
4571                   dst0, dst0, src0, src1, src0, src1);
4572
4573       if ((tmp0_hi >> 15) & 1)
4574         tmp1_hi = ~tmp1_hi + 1;
4575
4576       if ((tmp0_lo >> 15) & 1)
4577         tmp1_lo = ~tmp1_lo + 1;
4578
4579       tmp1_hi = tmp1_hi + tmp1_lo;
4580
4581       STORE (DREG (dst0), REG_H_L (tmp1_hi << 16, tmp1_hi));
4582     }
4583   else if (aopcde == 0 && HL == 0)
4584     {
4585       bu32 s0 = DREG (src0);
4586       bu32 s1 = DREG (src1);
4587       bu32 s0h = s0 >> 16;
4588       bu32 s0l = s0 & 0xFFFF;
4589       bu32 s1h = s1 >> 16;
4590       bu32 s1l = s1 & 0xFFFF;
4591       bu32 t0, t1;
4592       bu32 ac1_i = 0, ac0_i = 0, v_i = 0, z_i = 0, n_i = 0;
4593
4594       TRACE_INSN (cpu, "R%i = R%i %c|%c R%i%s;", dst0, src0,
4595                   (aop & 2) ? '-' : '+', (aop & 1) ? '-' : '+', src1,
4596                   amod0 (s, x));
4597       if (aop & 2)
4598         t0 = sub16 (cpu, s0h, s1h, &ac1_i, &v_i, &z_i, &n_i, s, 0);
4599       else
4600         t0 = add16 (cpu, s0h, s1h, &ac1_i, &v_i, &z_i, &n_i, s, 0);
4601
4602       if (aop & 1)
4603         t1 = sub16 (cpu, s0l, s1l, &ac0_i, &v_i, &z_i, &n_i, s, 0);
4604       else
4605         t1 = add16 (cpu, s0l, s1l, &ac0_i, &v_i, &z_i, &n_i, s, 0);
4606
4607       SET_ASTATREG (ac1, ac1_i);
4608       SET_ASTATREG (ac0, ac0_i);
4609       SET_ASTATREG (az, z_i);
4610       SET_ASTATREG (an, n_i);
4611       SET_ASTATREG (v, v_i);
4612       if (v_i)
4613         SET_ASTATREG (vs, v_i);
4614
4615       t0 &= 0xFFFF;
4616       t1 &= 0xFFFF;
4617       if (x)
4618         SET_DREG (dst0, (t1 << 16) | t0);
4619       else
4620         SET_DREG (dst0, (t0 << 16) | t1);
4621     }
4622   else if (aop == 1 && aopcde == 12 && x == 0 && s == 0 && HL == 0)
4623     {
4624       bs32 val0 = (bs16)(AWREG (0) >> 16) + (bs16)AWREG (0);
4625       bs32 val1 = (bs16)(AWREG (1) >> 16) + (bs16)AWREG (1);
4626
4627       TRACE_INSN (cpu, "R%i = A1.L + A1.H, R%i = A0.L + A0.H;", dst1, dst0);
4628
4629       if (dst0 == dst1)
4630         illegal_instruction_combination (cpu);
4631
4632       SET_DREG (dst0, val0);
4633       SET_DREG (dst1, val1);
4634     }
4635   else if ((aop == 0 || aop == 2 || aop == 3) && aopcde == 1)
4636     {
4637       bu32 d0, d1;
4638       bu32 x0, x1;
4639       bu16 s0L = DREG (src0);
4640       bu16 s0H = DREG (src0) >> 16;
4641       bu16 s1L = DREG (src1);
4642       bu16 s1H = DREG (src1) >> 16;
4643       bu32 v_i = 0, n_i = 0, z_i = 0;
4644
4645       TRACE_INSN (cpu, "R%i = R%i %s R%i, R%i = R%i %s R%i%s;",
4646                   dst1, src0, HL ? "+|-" : "+|+", src1,
4647                   dst0, src0, HL ? "-|+" : "-|-", src1,
4648                   amod0amod2 (s, x, aop));
4649
4650       if (dst0 == dst1)
4651         illegal_instruction_combination (cpu);
4652
4653       if (HL == 0)
4654         {
4655           x0 = add16 (cpu, s0H, s1H, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
4656           x1 = add16 (cpu, s0L, s1L, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
4657           d1 = (x0 << 16) | x1;
4658
4659           x0 = sub16 (cpu, s0H, s1H, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
4660           x1 = sub16 (cpu, s0L, s1L, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
4661           if (x == 0)
4662             d0 = (x0 << 16) | x1;
4663           else
4664             d0 = (x1 << 16) | x0;
4665         }
4666       else
4667         {
4668           x0 = add16 (cpu, s0H, s1H, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
4669           x1 = sub16 (cpu, s0L, s1L, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
4670           d1 = (x0 << 16) | x1;
4671
4672           x0 = sub16 (cpu, s0H, s1H, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
4673           x1 = add16 (cpu, s0L, s1L, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
4674           if (x == 0)
4675             d0 = (x0 << 16) | x1;
4676           else
4677             d0 = (x1 << 16) | x0;
4678         }
4679       SET_ASTATREG (az, z_i);
4680       SET_ASTATREG (an, n_i);
4681       SET_ASTATREG (v, v_i);
4682       if (v_i)
4683         SET_ASTATREG (vs, v_i);
4684
4685       STORE (DREG (dst0), d0);
4686       STORE (DREG (dst1), d1);
4687     }
4688   else if ((aop == 0 || aop == 1 || aop == 2) && aopcde == 11 && x == 0)
4689     {
4690       bs40 acc0 = get_extended_acc (cpu, 0);
4691       bs40 acc1 = get_extended_acc (cpu, 1);
4692       bu32 v, dreg, sat = 0;
4693       bu32 carry = !!((bu40)~acc1 < (bu40)acc0);
4694
4695       if (aop == 0)
4696         {
4697           if (s != 0 || HL != 0)
4698             illegal_instruction (cpu);
4699           TRACE_INSN (cpu, "R%i = (A0 += A1);", dst0);
4700         }
4701       else if (aop == 1)
4702         {
4703           if (s != 0)
4704             illegal_instruction (cpu);
4705           TRACE_INSN (cpu, "R%i.%c = (A0 += A1);", dst0, HL ? 'H' : 'L');
4706         }
4707       else
4708         {
4709           if (HL != 0)
4710             illegal_instruction (cpu);
4711           TRACE_INSN (cpu, "A0 += A1%s;", s ? " (W32)" : "");
4712         }
4713
4714       acc0 += acc1;
4715       acc0 = saturate_s40_astat (acc0, &v);
4716
4717       if (aop == 2 && s == 1)   /* A0 += A1 (W32)  */
4718         {
4719           if (acc0 & (bs40)0x8000000000ll)
4720             acc0 &= 0x80ffffffffll;
4721           else
4722             acc0 &= 0xffffffffll;
4723         }
4724
4725       STORE (AXREG (0), acc0 >> 32);
4726       STORE (AWREG (0), acc0);
4727       SET_ASTATREG (av0, v && acc1);
4728       if (v)
4729         SET_ASTATREG (av0s, v);
4730
4731       if (aop == 0 || aop == 1)
4732         {
4733           if (aop)      /* Dregs_lo = A0 += A1  */
4734             {
4735               dreg = saturate_s32 (rnd16 (acc0) << 16, &sat);
4736               if (HL)
4737                 STORE (DREG (dst0), REG_H_L (dreg, DREG (dst0)));
4738               else
4739                 STORE (DREG (dst0), REG_H_L (DREG (dst0), dreg >> 16));
4740             }
4741           else          /* Dregs = A0 += A1  */
4742             {
4743               dreg = saturate_s32 (acc0, &sat);
4744               STORE (DREG (dst0), dreg);
4745             }
4746
4747           STORE (ASTATREG (az), dreg == 0);
4748           STORE (ASTATREG (an), !!(dreg & 0x80000000));
4749           STORE (ASTATREG (ac0), carry);
4750           STORE (ASTATREG (ac0_copy), carry);
4751           STORE (ASTATREG (v), sat);
4752           STORE (ASTATREG (v_copy), sat);
4753           if (sat)
4754             STORE (ASTATREG (vs), sat);
4755         }
4756       else
4757         {
4758           STORE (ASTATREG (az), acc0 == 0);
4759           STORE (ASTATREG (an), !!(acc0 & 0x8000000000ull));
4760           STORE (ASTATREG (ac0), carry);
4761           STORE (ASTATREG (ac0_copy), carry);
4762         }
4763     }
4764   else if ((aop == 0 || aop == 1) && aopcde == 10 && x == 0 && s == 0 && HL == 0)
4765     {
4766       TRACE_INSN (cpu, "R%i.L = A%i.X;", dst0, aop);
4767       SET_DREG_L (dst0, (bs8)AXREG (aop));
4768     }
4769   else if (aop == 0 && aopcde == 4 && x == 0 && HL == 0)
4770     {
4771       TRACE_INSN (cpu, "R%i = R%i + R%i%s;", dst0, src0, src1, amod1 (s, x));
4772       SET_DREG (dst0, add32 (cpu, DREG (src0), DREG (src1), 1, s));
4773     }
4774   else if (aop == 1 && aopcde == 4 && x == 0 && HL == 0)
4775     {
4776       TRACE_INSN (cpu, "R%i = R%i - R%i%s;", dst0, src0, src1, amod1 (s, x));
4777       SET_DREG (dst0, sub32 (cpu, DREG (src0), DREG (src1), 1, s, 0));
4778     }
4779   else if (aop == 2 && aopcde == 4 && x == 0 && HL == 0)
4780     {
4781       TRACE_INSN (cpu, "R%i = R%i + R%i, R%i = R%i - R%i%s;",
4782                   dst1, src0, src1, dst0, src0, src1, amod1 (s, x));
4783
4784       if (dst0 == dst1)
4785         illegal_instruction_combination (cpu);
4786
4787       STORE (DREG (dst1), add32 (cpu, DREG (src0), DREG (src1), 1, s));
4788       STORE (DREG (dst0), sub32 (cpu, DREG (src0), DREG (src1), 1, s, 1));
4789     }
4790   else if ((aop == 0 || aop == 1) && aopcde == 17 && x == 0 && HL == 0)
4791     {
4792       bs40 acc0 = get_extended_acc (cpu, 0);
4793       bs40 acc1 = get_extended_acc (cpu, 1);
4794       bs40 val0, val1, sval0, sval1;
4795       bu32 sat, sat_i;
4796
4797       TRACE_INSN (cpu, "R%i = A%i + A%i, R%i = A%i - A%i%s",
4798                   dst1, !aop, aop, dst0, !aop, aop, amod1 (s, x));
4799       TRACE_DECODE (cpu, "R%i = A%i:%#"PRIx64" + A%i:%#"PRIx64", "
4800                          "R%i = A%i:%#"PRIx64" - A%i:%#"PRIx64"%s",
4801                     dst1, !aop, aop ? acc0 : acc1, aop, aop ? acc1 : acc0,
4802                     dst0, !aop, aop ? acc0 : acc1, aop, aop ? acc1 : acc0,
4803                     amod1 (s, x));
4804
4805       if (dst0 == dst1)
4806         illegal_instruction_combination (cpu);
4807
4808       val1 = acc0 + acc1;
4809       if (aop)
4810         val0 = acc0 - acc1;
4811       else
4812         val0 = acc1 - acc0;
4813
4814       sval0 = saturate_s32 (val0, &sat);
4815       sat_i = sat;
4816       sval1 = saturate_s32 (val1, &sat);
4817       sat_i |= sat;
4818       if (s)
4819         {
4820           val0 = sval0;
4821           val1 = sval1;
4822         }
4823
4824       STORE (DREG (dst0), val0);
4825       STORE (DREG (dst1), val1);
4826       SET_ASTATREG (v, sat_i);
4827       if (sat_i)
4828         SET_ASTATREG (vs, sat_i);
4829       SET_ASTATREG (an, val0 & 0x80000000 || val1 & 0x80000000);
4830       SET_ASTATREG (az, val0 == 0 || val1 == 0);
4831       SET_ASTATREG (ac1, (bu40)~acc0 < (bu40)acc1);
4832       if (aop)
4833         SET_ASTATREG (ac0, !!((bu40)acc1 <= (bu40)acc0));
4834       else
4835         SET_ASTATREG (ac0, !!((bu40)acc0 <= (bu40)acc1));
4836     }
4837   else if (aop == 0 && aopcde == 18 && x == 0 && HL == 0)
4838     {
4839       bu40 acc0 = get_extended_acc (cpu, 0);
4840       bu40 acc1 = get_extended_acc (cpu, 1);
4841       bu32 s0L = DREG (src0);
4842       bu32 s0H = DREG (src0 + 1);
4843       bu32 s1L = DREG (src1);
4844       bu32 s1H = DREG (src1 + 1);
4845       bu32 s0, s1;
4846       bs16 tmp0, tmp1, tmp2, tmp3;
4847
4848       /* This instruction is only defined for register pairs R1:0 and R3:2.  */
4849       if (!((src0 == 0 || src0 == 2) && (src1 == 0 || src1 == 2)))
4850         illegal_instruction (cpu);
4851
4852       TRACE_INSN (cpu, "SAA (R%i:%i, R%i:%i)%s", src0 + 1, src0,
4853                   src1 + 1, src1, s ? " (R)" :"");
4854
4855       /* Bit s determines the order of the two registers from a pair:
4856          if s=0 the low-order bytes come from the low reg in the pair,
4857          and if s=1 the low-order bytes come from the high reg.  */
4858
4859       if (s)
4860         {
4861           s0 = algn (s0H, s0L, IREG (0) & 3);
4862           s1 = algn (s1H, s1L, IREG (1) & 3);
4863         }
4864       else
4865         {
4866           s0 = algn (s0L, s0H, IREG (0) & 3);
4867           s1 = algn (s1L, s1H, IREG (1) & 3);
4868         }
4869
4870       /* Find the absolute difference between pairs, make it
4871          absolute, then add it to the existing accumulator half.  */
4872       /* Byte 0  */
4873       tmp0  = ((s0 << 24) >> 24) - ((s1 << 24) >> 24);
4874       tmp1  = ((s0 << 16) >> 24) - ((s1 << 16) >> 24);
4875       tmp2  = ((s0 <<  8) >> 24) - ((s1 <<  8) >> 24);
4876       tmp3  = ((s0 <<  0) >> 24) - ((s1 <<  0) >> 24);
4877
4878       tmp0  = (tmp0 < 0) ? -tmp0 : tmp0;
4879       tmp1  = (tmp1 < 0) ? -tmp1 : tmp1;
4880       tmp2  = (tmp2 < 0) ? -tmp2 : tmp2;
4881       tmp3  = (tmp3 < 0) ? -tmp3 : tmp3;
4882
4883       s0L = saturate_u16 ((bu32)tmp0 + ((acc0 >>  0) & 0xffff), 0);
4884       s0H = saturate_u16 ((bu32)tmp1 + ((acc0 >> 16) & 0xffff), 0);
4885       s1L = saturate_u16 ((bu32)tmp2 + ((acc1 >>  0) & 0xffff), 0);
4886       s1H = saturate_u16 ((bu32)tmp3 + ((acc1 >> 16) & 0xffff), 0);
4887
4888       STORE (AWREG (0), (s0H << 16) | (s0L & 0xFFFF));
4889       STORE (AXREG (0), 0);
4890       STORE (AWREG (1), (s1H << 16) | (s1L & 0xFFFF));
4891       STORE (AXREG (1), 0);
4892
4893       /* Implicit DISALGNEXCPT in parallel.  */
4894       DIS_ALGN_EXPT |= 1;
4895     }
4896   else if (aop == 3 && aopcde == 18 && x == 0 && s == 0 && HL == 0)
4897     {
4898       TRACE_INSN (cpu, "DISALGNEXCPT");
4899       DIS_ALGN_EXPT |= 1;
4900     }
4901   else if ((aop == 0 || aop == 1) && aopcde == 20 && x == 0 && HL == 0)
4902     {
4903       bu32 s0, s0L, s0H, s1, s1L, s1H;
4904       const char * const opts[] = { "", " (R)", " (T)", " (T, R)" };
4905
4906       TRACE_INSN (cpu, "R%i = BYTEOP1P (R%i:%i, R%i:%i)%s;", dst0,
4907                   src0 + 1, src0, src1 + 1, src1, opts[s + (aop << 1)]);
4908
4909       if ((src1 != 0 && src1 != 2) || (src0 != 0 && src0 != 2))
4910         illegal_instruction (cpu);
4911
4912       s0L = DREG (src0);
4913       s0H = DREG (src0 + 1);
4914       s1L = DREG (src1);
4915       s1H = DREG (src1 + 1);
4916       if (s)
4917         {
4918           s0 = algn (s0H, s0L, IREG (0) & 3);
4919           s1 = algn (s1H, s1L, IREG (1) & 3);
4920         }
4921       else
4922         {
4923           s0 = algn (s0L, s0H, IREG (0) & 3);
4924           s1 = algn (s1L, s1H, IREG (1) & 3);
4925         }
4926
4927       STORE (DREG (dst0),
4928                 (((((s0 >>  0) & 0xff) + ((s1 >>  0) & 0xff) + !aop) >> 1) <<  0) |
4929                 (((((s0 >>  8) & 0xff) + ((s1 >>  8) & 0xff) + !aop) >> 1) <<  8) |
4930                 (((((s0 >> 16) & 0xff) + ((s1 >> 16) & 0xff) + !aop) >> 1) << 16) |
4931                 (((((s0 >> 24) & 0xff) + ((s1 >> 24) & 0xff) + !aop) >> 1) << 24));
4932
4933       /* Implicit DISALGNEXCPT in parallel.  */
4934       DIS_ALGN_EXPT |= 1;
4935     }
4936   else if (aop == 0 && aopcde == 21 && x == 0 && HL == 0)
4937     {
4938       bu32 s0, s0L, s0H, s1, s1L, s1H;
4939
4940       TRACE_INSN (cpu, "(R%i, R%i) = BYTEOP16P (R%i:%i, R%i:%i)%s;", dst1, dst0,
4941                   src0 + 1, src0, src1 + 1, src1, s ? " (R)" : "");
4942
4943       if ((src1 != 0 && src1 != 2) || (src0 != 0 && src0 != 2))
4944         illegal_instruction (cpu);
4945
4946       if (dst0 == dst1)
4947         illegal_instruction_combination (cpu);
4948
4949       s0L = DREG (src0);
4950       s0H = DREG (src0 + 1);
4951       s1L = DREG (src1);
4952       s1H = DREG (src1 + 1);
4953       if (s)
4954         {
4955           s0 = algn (s0H, s0L, IREG (0) & 3);
4956           s1 = algn (s1H, s1L, IREG (1) & 3);
4957         }
4958       else
4959         {
4960           s0 = algn (s0L, s0H, IREG (0) & 3);
4961           s1 = algn (s1L, s1H, IREG (1) & 3);
4962         }
4963
4964       STORE (DREG (dst0),
4965                 ((((s0 >>  0) & 0xff) + ((s1 >>  0) & 0xff)) <<  0) |
4966                 ((((s0 >>  8) & 0xff) + ((s1 >>  8) & 0xff)) << 16));
4967       STORE (DREG (dst1),
4968                 ((((s0 >> 16) & 0xff) + ((s1 >> 16) & 0xff)) <<  0) |
4969                 ((((s0 >> 24) & 0xff) + ((s1 >> 24) & 0xff)) << 16));
4970
4971       /* Implicit DISALGNEXCPT in parallel.  */
4972       DIS_ALGN_EXPT |= 1;
4973     }
4974   else if (aop == 1 && aopcde == 21 && x == 0 && HL == 0)
4975     {
4976       bu32 s0, s0L, s0H, s1, s1L, s1H;
4977
4978       TRACE_INSN (cpu, "(R%i, R%i) = BYTEOP16M (R%i:%i, R%i:%i)%s;", dst1, dst0,
4979                   src0 + 1, src0, src1 + 1, src1, s ? " (R)" : "");
4980
4981       if ((src1 != 0 && src1 != 2) || (src0 != 0 && src0 != 2))
4982         illegal_instruction (cpu);
4983
4984       if (dst0 == dst1)
4985         illegal_instruction_combination (cpu);
4986
4987       s0L = DREG (src0);
4988       s0H = DREG (src0 + 1);
4989       s1L = DREG (src1);
4990       s1H = DREG (src1 + 1);
4991       if (s)
4992         {
4993           s0 = algn (s0H, s0L, IREG (0) & 3);
4994           s1 = algn (s1H, s1L, IREG (1) & 3);
4995         }
4996       else
4997         {
4998           s0 = algn (s0L, s0H, IREG (0) & 3);
4999           s1 = algn (s1L, s1H, IREG (1) & 3);
5000         }
5001
5002       STORE (DREG (dst0),
5003                 (((((s0 >>  0) & 0xff) - ((s1 >>  0) & 0xff)) <<  0) & 0xffff) |
5004                 (((((s0 >>  8) & 0xff) - ((s1 >>  8) & 0xff)) << 16)));
5005       STORE (DREG (dst1),
5006                 (((((s0 >> 16) & 0xff) - ((s1 >> 16) & 0xff)) <<  0) & 0xffff) |
5007                 (((((s0 >> 24) & 0xff) - ((s1 >> 24) & 0xff)) << 16)));
5008
5009       /* Implicit DISALGNEXCPT in parallel.  */
5010       DIS_ALGN_EXPT |= 1;
5011     }
5012   else if (aop == 1 && aopcde == 7 && x == 0 && s == 0 && HL == 0)
5013     {
5014       TRACE_INSN (cpu, "R%i = MIN (R%i, R%i);", dst0, src0, src1);
5015       SET_DREG (dst0, min32 (cpu, DREG (src0), DREG (src1)));
5016     }
5017   else if (aop == 0 && aopcde == 7 && x == 0 && s == 0 && HL == 0)
5018     {
5019       TRACE_INSN (cpu, "R%i = MAX (R%i, R%i);", dst0, src0, src1);
5020       SET_DREG (dst0, max32 (cpu, DREG (src0), DREG (src1)));
5021     }
5022   else if (aop == 2 && aopcde == 7 && x == 0 && s == 0 && HL == 0)
5023     {
5024       bu32 val = DREG (src0);
5025       int v;
5026
5027       TRACE_INSN (cpu, "R%i = ABS R%i;", dst0, src0);
5028
5029       if (val >> 31)
5030         val = -val;
5031       v = (val == 0x80000000);
5032       if (v)
5033         val = 0x7fffffff;
5034       SET_DREG (dst0, val);
5035
5036       SET_ASTATREG (v, v);
5037       if (v)
5038         SET_ASTATREG (vs, 1);
5039       setflags_nz (cpu, val);
5040     }
5041   else if (aop == 3 && aopcde == 7 && x == 0 && HL == 0)
5042     {
5043       bu32 val = DREG (src0);
5044
5045       TRACE_INSN (cpu, "R%i = - R%i%s;", dst0, src0, amod1 (s, 0));
5046
5047       if (s && val == 0x80000000)
5048         {
5049           val = 0x7fffffff;
5050           SET_ASTATREG (v, 1);
5051           SET_ASTATREG (vs, 1);
5052         }
5053       else if (val == 0x80000000)
5054         val = 0x80000000;
5055       else
5056         val = -val;
5057       SET_DREG (dst0, val);
5058
5059       SET_ASTATREG (az, val == 0);
5060       SET_ASTATREG (an, val & 0x80000000);
5061     }
5062   else if (aop == 2 && aopcde == 6 && x == 0 && s == 0 && HL == 0)
5063     {
5064       bu32 in = DREG (src0);
5065       bu32 hi = (in & 0x80000000 ? (bu32)-(bs16)(in >> 16) : in >> 16) << 16;
5066       bu32 lo = (in & 0x8000 ? (bu32)-(bs16)(in & 0xFFFF) : in) & 0xFFFF;
5067       int v;
5068
5069       TRACE_INSN (cpu, "R%i = ABS R%i (V);", dst0, src0);
5070
5071       v = 0;
5072       if (hi == 0x80000000)
5073         {
5074           hi = 0x7fff0000;
5075           v = 1;
5076         }
5077       if (lo == 0x8000)
5078         {
5079           lo = 0x7fff;
5080           v = 1;
5081         }
5082       SET_DREG (dst0, hi | lo);
5083
5084       SET_ASTATREG (v, v);
5085       if (v)
5086         SET_ASTATREG (vs, 1);
5087       setflags_nz_2x16 (cpu, DREG (dst0));
5088     }
5089   else if (aop == 1 && aopcde == 6 && x == 0 && s == 0 && HL == 0)
5090     {
5091       TRACE_INSN (cpu, "R%i = MIN (R%i, R%i) (V);", dst0, src0, src1);
5092       SET_DREG (dst0, min2x16 (cpu, DREG (src0), DREG (src1)));
5093     }
5094   else if (aop == 0 && aopcde == 6 && x == 0 && s == 0 && HL == 0)
5095     {
5096       TRACE_INSN (cpu, "R%i = MAX (R%i, R%i) (V);", dst0, src0, src1);
5097       SET_DREG (dst0, max2x16 (cpu, DREG (src0), DREG (src1)));
5098     }
5099   else if (aop == 0 && aopcde == 24 && x == 0 && s == 0 && HL == 0)
5100     {
5101       TRACE_INSN (cpu, "R%i = BYTEPACK (R%i, R%i);", dst0, src0, src1);
5102       STORE (DREG (dst0),
5103         (((DREG (src0) >>  0) & 0xff) <<  0) |
5104         (((DREG (src0) >> 16) & 0xff) <<  8) |
5105         (((DREG (src1) >>  0) & 0xff) << 16) |
5106         (((DREG (src1) >> 16) & 0xff) << 24));
5107
5108       /* Implicit DISALGNEXCPT in parallel.  */
5109       DIS_ALGN_EXPT |= 1;
5110     }
5111   else if (aop == 1 && aopcde == 24 && x == 0 && HL == 0)
5112     {
5113       int order, lo, hi;
5114       bu64 comb_src;
5115       bu8 bytea, byteb, bytec, byted;
5116
5117       TRACE_INSN (cpu, "(R%i, R%i) = BYTEUNPACK R%i:%i%s;",
5118                   dst1, dst0, src0 + 1, src0, s ? " (R)" : "");
5119
5120       if ((src1 != 0 && src1 != 2) || (src0 != 0 && src0 != 2))
5121         illegal_instruction (cpu);
5122
5123       if (dst0 == dst1)
5124         illegal_instruction_combination (cpu);
5125
5126       order = IREG (0) & 0x3;
5127       if (s)
5128         hi = src0, lo = src0 + 1;
5129       else
5130         hi = src0 + 1, lo = src0;
5131       comb_src = (((bu64)DREG (hi)) << 32) | DREG (lo);
5132       bytea = (comb_src >> (0 + 8 * order));
5133       byteb = (comb_src >> (8 + 8 * order));
5134       bytec = (comb_src >> (16 + 8 * order));
5135       byted = (comb_src >> (24 + 8 * order));
5136       STORE (DREG (dst0), bytea | ((bu32)byteb << 16));
5137       STORE (DREG (dst1), bytec | ((bu32)byted << 16));
5138
5139       /* Implicit DISALGNEXCPT in parallel.  */
5140       DIS_ALGN_EXPT |= 1;
5141     }
5142   else if (aopcde == 13 && HL == 0 && x == 0 && s == 0)
5143     {
5144       const char *searchmodes[] = { "GT", "GE", "LT", "LE" };
5145       bool up_hi, up_lo;
5146       bs16 a0_lo, a1_lo, src_hi, src_lo;
5147
5148       TRACE_INSN (cpu, "(R%i, R%i) = SEARCH R%i (%s);",
5149                   dst1, dst0, src0, searchmodes[aop]);
5150
5151       if (dst0 == dst1)
5152         illegal_instruction_combination (cpu);
5153
5154       up_hi = up_lo = false;
5155       a0_lo = AWREG (0);
5156       a1_lo = AWREG (1);
5157       src_lo = DREG (src0);
5158       src_hi = DREG (src0) >> 16;
5159
5160       switch (aop)
5161         {
5162         case 0:
5163           up_hi = (src_hi > a1_lo);
5164           up_lo = (src_lo > a0_lo);
5165           break;
5166         case 1:
5167           up_hi = (src_hi >= a1_lo);
5168           up_lo = (src_lo >= a0_lo);
5169           break;
5170         case 2:
5171           up_hi = (src_hi < a1_lo);
5172           up_lo = (src_lo < a0_lo);
5173           break;
5174         case 3:
5175           up_hi = (src_hi <= a1_lo);
5176           up_lo = (src_lo <= a0_lo);
5177           break;
5178         }
5179
5180       if (up_hi)
5181         {
5182           SET_AREG (1, src_hi);
5183           SET_DREG (dst1, PREG (0));
5184         }
5185       else
5186         SET_AREG (1, a1_lo);
5187
5188       if (up_lo)
5189         {
5190           SET_AREG (0, src_lo);
5191           SET_DREG (dst0, PREG (0));
5192         }
5193       else
5194         SET_AREG (0, a0_lo);
5195     }
5196   else
5197     illegal_instruction (cpu);
5198 }
5199
5200 static void
5201 decode_dsp32shift_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
5202 {
5203   /* dsp32shift
5204      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5205      | 1 | 1 | 0 | 0 |.M.| 1 | 1 | 0 | 0 | - | - |.sopcde............|
5206      |.sop...|.HLs...|.dst0......| - | - | - |.src0......|.src1......|
5207      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
5208   int HLs  = ((iw1 >> DSP32Shift_HLs_bits) & DSP32Shift_HLs_mask);
5209   int sop  = ((iw1 >> DSP32Shift_sop_bits) & DSP32Shift_sop_mask);
5210   int src0 = ((iw1 >> DSP32Shift_src0_bits) & DSP32Shift_src0_mask);
5211   int src1 = ((iw1 >> DSP32Shift_src1_bits) & DSP32Shift_src1_mask);
5212   int dst0 = ((iw1 >> DSP32Shift_dst0_bits) & DSP32Shift_dst0_mask);
5213   int sopcde = ((iw0 >> (DSP32Shift_sopcde_bits - 16)) & DSP32Shift_sopcde_mask);
5214   int M = ((iw0 >> (DSP32Shift_M_bits - 16)) & DSP32Shift_M_mask);
5215
5216   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dsp32shift);
5217   TRACE_EXTRACT (cpu, "%s: M:%i sopcde:%i sop:%i HLs:%i dst0:%i src0:%i src1:%i",
5218                  __func__, M, sopcde, sop, HLs, dst0, src0, src1);
5219
5220   if ((sop == 0 || sop == 1) && sopcde == 0)
5221     {
5222       bu16 val;
5223       bs32 shft = (bs8)(DREG (src0) << 2) >> 2;
5224
5225       TRACE_INSN (cpu, "R%i.%c = ASHIFT R%i.%c BY R%i.L%s;",
5226                   dst0, HLs < 2 ? 'L' : 'H',
5227                   src1, HLs & 1 ? 'H' : 'L',
5228                   src0, sop == 1 ? " (S)" : "");
5229
5230       if ((HLs & 1) == 0)
5231         val = (bu16)(DREG (src1) & 0xFFFF);
5232       else
5233         val = (bu16)((DREG (src1) & 0xFFFF0000) >> 16);
5234
5235       /* Positive shift magnitudes produce Logical Left shifts.
5236          Negative shift magnitudes produce Arithmetic Right shifts.  */
5237       if (shft <= 0)
5238         val = ashiftrt (cpu, val, -shft, 16);
5239       else
5240         {
5241           int sgn = (val >> 15) & 0x1;
5242
5243           val = lshift (cpu, val, shft, 16, sop == 1, 1);
5244           if (((val >> 15) & 0x1) != sgn)
5245             {
5246               SET_ASTATREG (v, 1);
5247               SET_ASTATREG (vs, 1);
5248             }
5249         }
5250
5251       if ((HLs & 2) == 0)
5252         STORE (DREG (dst0), REG_H_L (DREG (dst0), val));
5253       else
5254         STORE (DREG (dst0), REG_H_L (val << 16, DREG (dst0)));
5255     }
5256   else if (sop == 2 && sopcde == 0)
5257     {
5258       bs32 shft = (bs8)(DREG (src0) << 2) >> 2;
5259       bu16 val;
5260
5261       TRACE_INSN (cpu, "R%i.%c = LSHIFT R%i.%c BY R%i.L;",
5262                   dst0, HLs < 2 ? 'L' : 'H',
5263                   src1, HLs & 1 ? 'H' : 'L', src0);
5264
5265       if ((HLs & 1) == 0)
5266         val = (bu16)(DREG (src1) & 0xFFFF);
5267       else
5268         val = (bu16)((DREG (src1) & 0xFFFF0000) >> 16);
5269
5270       if (shft < 0)
5271         val = val >> (-1 * shft);
5272       else
5273         val = val << shft;
5274
5275       if ((HLs & 2) == 0)
5276         SET_DREG (dst0, REG_H_L (DREG (dst0), val));
5277       else
5278         SET_DREG (dst0, REG_H_L (val << 16, DREG (dst0)));
5279
5280       SET_ASTATREG (az, !((val & 0xFFFF0000) == 0) || ((val & 0xFFFF) == 0));
5281       SET_ASTATREG (an, (!!(val & 0x80000000)) ^ (!!(val & 0x8000)));
5282       SET_ASTATREG (v, 0);
5283     }
5284   else if (sop == 2 && sopcde == 3 && (HLs == 1 || HLs == 0))
5285     {
5286       int shift = imm6 (DREG (src0) & 0xFFFF);
5287       bu32 cc = CCREG;
5288       bu40 acc = get_unextended_acc (cpu, HLs);
5289
5290       TRACE_INSN (cpu, "A%i = ROT A%i BY R%i.L;", HLs, HLs, src0);
5291       TRACE_DECODE (cpu, "A%i:%#"PRIx64" shift:%i CC:%i", HLs, acc, shift, cc);
5292
5293       acc = rot40 (acc, shift, &cc);
5294       SET_AREG (HLs, acc);
5295       if (shift)
5296         SET_CCREG (cc);
5297     }
5298   else if (sop == 0 && sopcde == 3 && (HLs == 0 || HLs == 1))
5299     {
5300       bs32 shft = (bs8)(DREG (src0) << 2) >> 2;
5301       bu64 acc = get_extended_acc (cpu, HLs);
5302       bu64 val;
5303
5304       HLs = !!HLs;
5305       TRACE_INSN (cpu, "A%i = ASHIFT A%i BY R%i.L;", HLs, HLs, src0);
5306       TRACE_DECODE (cpu, "A%i:%#"PRIx64" shift:%i", HLs, acc, shft);
5307
5308       if (shft <= 0)
5309         val = ashiftrt (cpu, acc, -shft, 40);
5310       else
5311         val = lshift (cpu, acc, shft, 40, 0, 0);
5312
5313       STORE (AXREG (HLs), (val >> 32) & 0xff);
5314       STORE (AWREG (HLs), (val & 0xffffffff));
5315       STORE (ASTATREG (av[HLs]), 0);
5316     }
5317   else if (sop == 1 && sopcde == 3 && (HLs == 0 || HLs == 1))
5318     {
5319       bs32 shft = (bs8)(DREG (src0) << 2) >> 2;
5320       bu64 acc = get_unextended_acc (cpu, HLs);
5321       bu64 val;
5322
5323       HLs = !!HLs;
5324       TRACE_INSN (cpu, "A%i = LSHIFT A%i BY R%i.L;", HLs, HLs, src0);
5325       TRACE_DECODE (cpu, "A%i:%#"PRIx64" shift:%i", HLs, acc, shft);
5326
5327       if (shft <= 0)
5328         val = lshiftrt (cpu, acc, -shft, 40);
5329       else
5330         val = lshift (cpu, acc, shft, 40, 0, 0);
5331
5332       STORE (AXREG (HLs), (val >> 32) & 0xff);
5333       STORE (AWREG (HLs), (val & 0xffffffff));
5334       STORE (ASTATREG (av[HLs]), 0);
5335     }
5336   else if ((sop == 0 || sop == 1) && sopcde == 1 && HLs == 0)
5337     {
5338       bs32 shft = (bs8)(DREG (src0) << 2) >> 2;
5339       bu16 val0, val1;
5340       bu32 astat;
5341
5342       TRACE_INSN (cpu, "R%i = ASHIFT R%i BY R%i.L (V%s);",
5343                   dst0, src1, src0, sop == 1 ? ",S" : "");
5344
5345       val0 = (bu16)DREG (src1) & 0xFFFF;
5346       val1 = (bu16)((DREG (src1) & 0xFFFF0000) >> 16);
5347
5348       if (shft <= 0)
5349         {
5350           val0 = ashiftrt (cpu, val0, -shft, 16);
5351           astat = ASTAT;
5352           val1 = ashiftrt (cpu, val1, -shft, 16);
5353         }
5354       else
5355         {
5356           int sgn0 = (val0 >> 15) & 0x1;
5357           int sgn1 = (val1 >> 15) & 0x1;
5358
5359           val0 = lshift (cpu, val0, shft, 16, sop == 1, 1);
5360           astat = ASTAT;
5361           val1 = lshift (cpu, val1, shft, 16, sop == 1, 1);
5362
5363           if ((sgn0 != ((val0 >> 15) & 0x1)) || (sgn1 != ((val1 >> 15) & 0x1)))
5364             {
5365               SET_ASTATREG (v, 1);
5366               SET_ASTATREG (vs, 1);
5367             }
5368         }
5369       SET_ASTAT (ASTAT | astat);
5370       STORE (DREG (dst0), (val1 << 16) | val0);
5371     }
5372   else if ((sop == 0 || sop == 1 || sop == 2) && sopcde == 2)
5373     {
5374       /* dregs = [LA]SHIFT dregs BY dregs_lo (opt_S)  */
5375       /* sop == 1 : opt_S  */
5376       bu32 v = DREG (src1);
5377       /* LSHIFT uses sign extended low 6 bits of dregs_lo.  */
5378       bs32 shft = (bs8)(DREG (src0) << 2) >> 2;
5379
5380       TRACE_INSN (cpu, "R%i = %cSHIFT R%i BY R%i.L%s;", dst0,
5381                   shft && sop != 2 ? 'A' : 'L', src1, src0,
5382                   sop == 1 ? " (S)" : "");
5383
5384       if (shft < 0)
5385         {
5386           if (sop == 2)
5387             STORE (DREG (dst0), lshiftrt (cpu, v, -shft, 32));
5388           else
5389             STORE (DREG (dst0), ashiftrt (cpu, v, -shft, 32));
5390         }
5391       else
5392         {
5393           bu32 val = lshift (cpu, v, shft, 32, sop == 1, 1);
5394
5395           STORE (DREG (dst0), val);
5396           if (((v >> 31) & 0x1) != ((val >> 31) & 0x1))
5397             {
5398               SET_ASTATREG (v, 1);
5399               SET_ASTATREG (vs, 1);
5400             }
5401         }
5402     }
5403   else if (sop == 3 && sopcde == 2)
5404     {
5405       int shift = imm6 (DREG (src0) & 0xFFFF);
5406       bu32 src = DREG (src1);
5407       bu32 ret, cc = CCREG;
5408
5409       TRACE_INSN (cpu, "R%i = ROT R%i BY R%i.L;", dst0, src1, src0);
5410       TRACE_DECODE (cpu, "R%i:%#x R%i:%#x shift:%i CC:%i",
5411                     dst0, DREG (dst0), src1, src, shift, cc);
5412
5413       ret = rot32 (src, shift, &cc);
5414       STORE (DREG (dst0), ret);
5415       if (shift)
5416         SET_CCREG (cc);
5417     }
5418   else if (sop == 2 && sopcde == 1 && HLs == 0)
5419     {
5420       bs32 shft = (bs8)(DREG (src0) << 2) >> 2;
5421       bu16 val0, val1;
5422       bu32 astat;
5423
5424       TRACE_INSN (cpu, "R%i = LSHIFT R%i BY R%i.L (V);", dst0, src1, src0);
5425
5426       val0 = (bu16)DREG (src1) & 0xFFFF;
5427       val1 = (bu16)((DREG (src1) & 0xFFFF0000) >> 16);
5428
5429       if (shft <= 0)
5430         {
5431           val0 = lshiftrt (cpu, val0, -shft, 16);
5432           astat = ASTAT;
5433           val1 = lshiftrt (cpu, val1, -shft, 16);
5434         }
5435       else
5436         {
5437           val0 = lshift (cpu, val0, shft, 16, 0, 0);
5438           astat = ASTAT;
5439           val1 = lshift (cpu, val1, shft, 16, 0, 0);
5440         }
5441       SET_ASTAT (ASTAT | astat);
5442       STORE (DREG (dst0), (val1 << 16) | val0);
5443     }
5444   else if (sopcde == 4)
5445     {
5446       bu32 sv0 = DREG (src0);
5447       bu32 sv1 = DREG (src1);
5448       TRACE_INSN (cpu, "R%i = PACK (R%i.%c, R%i.%c);", dst0,
5449                   src1, sop & 2 ? 'H' : 'L',
5450                   src0, sop & 1 ? 'H' : 'L');
5451       if (sop & 1)
5452         sv0 >>= 16;
5453       if (sop & 2)
5454         sv1 >>= 16;
5455       STORE (DREG (dst0), (sv1 << 16) | (sv0 & 0xFFFF));
5456     }
5457   else if (sop == 0 && sopcde == 5)
5458     {
5459       bu32 sv1 = DREG (src1);
5460       TRACE_INSN (cpu, "R%i.L = SIGNBITS R%i;", dst0, src1);
5461       SET_DREG_L (dst0, signbits (sv1, 32));
5462     }
5463   else if (sop == 1 && sopcde == 5)
5464     {
5465       bu32 sv1 = DREG (src1);
5466       TRACE_INSN (cpu, "R%i.L = SIGNBITS R%i.L;", dst0, src1);
5467       SET_DREG_L (dst0, signbits (sv1, 16));
5468     }
5469   else if (sop == 2 && sopcde == 5)
5470     {
5471       bu32 sv1 = DREG (src1);
5472       TRACE_INSN (cpu, "R%i.L = SIGNBITS R%i.H;", dst0, src1);
5473       SET_DREG_L (dst0, signbits (sv1 >> 16, 16));
5474     }
5475   else if ((sop == 0 || sop == 1) && sopcde == 6)
5476     {
5477       bu64 acc = AXREG (sop);
5478       TRACE_INSN (cpu, "R%i.L = SIGNBITS A%i;", dst0, sop);
5479       acc <<= 32;
5480       acc |= AWREG (sop);
5481       SET_DREG_L (dst0, signbits (acc, 40) & 0xFFFF);
5482     }
5483   else if (sop == 3 && sopcde == 6)
5484     {
5485       bu32 v = ones (DREG (src1));
5486       TRACE_INSN (cpu, "R%i.L = ONES R%i;", dst0, src1);
5487       SET_DREG_L (dst0, v);
5488     }
5489   else if (sop == 0 && sopcde == 7)
5490     {
5491       bu16 sv1 = (bu16)signbits (DREG (src1), 32);
5492       bu16 sv0 = (bu16)DREG (src0);
5493       bu16 dst_lo;
5494
5495       TRACE_INSN (cpu, "R%i.L = EXPADJ (R%i, R%i.L);", dst0, src1, src0);
5496
5497       if ((sv1 & 0x1f) < (sv0 & 0x1f))
5498         dst_lo = sv1;
5499       else
5500         dst_lo = sv0;
5501       STORE (DREG (dst0), REG_H_L (DREG (dst0), dst_lo));
5502     }
5503   else if (sop == 1 && sopcde == 7)
5504     {
5505       /* Exponent adjust on two 16-bit inputs.  Select
5506          smallest norm among 3 inputs.  */
5507       bs16 src1_hi = (DREG (src1) & 0xFFFF0000) >> 16;
5508       bs16 src1_lo = (DREG (src1) & 0xFFFF);
5509       bu16 src0_lo = (DREG (src0) & 0xFFFF);
5510       bu16 tmp_hi, tmp_lo, tmp;
5511
5512       TRACE_INSN (cpu, "R%i.L = EXPADJ (R%i, R%i.L) (V);", dst0, src1, src0);
5513
5514       tmp_hi = signbits (src1_hi, 16);
5515       tmp_lo = signbits (src1_lo, 16);
5516
5517       if ((tmp_hi & 0xf) < (tmp_lo & 0xf))
5518         if ((tmp_hi & 0xf) < (src0_lo & 0xf))
5519           tmp = tmp_hi;
5520         else
5521           tmp = src0_lo;
5522       else
5523         if ((tmp_lo & 0xf) < (src0_lo & 0xf))
5524           tmp = tmp_lo;
5525         else
5526           tmp = src0_lo;
5527       STORE (DREG (dst0), REG_H_L (DREG (dst0), tmp));
5528     }
5529   else if (sop == 2 && sopcde == 7)
5530     {
5531       /* Exponent adjust on single 16-bit register.  */
5532       bu16 tmp;
5533       bu16 src0_lo = (bu16)(DREG (src0) & 0xFFFF);
5534
5535       TRACE_INSN (cpu, "R%i.L = EXPADJ (R%i.L, R%i.L);", dst0, src1, src0);
5536
5537       tmp = signbits (DREG (src1) & 0xFFFF, 16);
5538
5539       if ((tmp & 0xf) < (src0_lo & 0xf))
5540         SET_DREG_L (dst0, tmp);
5541       else
5542         SET_DREG_L (dst0, src0_lo);
5543     }
5544   else if (sop == 3 && sopcde == 7)
5545     {
5546       bu16 tmp;
5547       bu16 src0_lo = (bu16)(DREG (src0) & 0xFFFF);
5548
5549       TRACE_INSN (cpu, "R%i.L = EXPADJ (R%i.H, R%i.L);", dst0, src1, src0);
5550
5551       tmp = signbits ((DREG (src1) & 0xFFFF0000) >> 16, 16);
5552
5553       if ((tmp & 0xf) < (src0_lo & 0xf))
5554         SET_DREG_L (dst0, tmp);
5555       else
5556         SET_DREG_L (dst0, src0_lo);
5557     }
5558   else if (sop == 0 && sopcde == 8)
5559     {
5560       bu64 acc = get_unextended_acc (cpu, 0);
5561       bu32 s0, s1;
5562
5563       TRACE_INSN (cpu, "BITMUX (R%i, R%i, A0) (ASR);", src0, src1);
5564
5565       if (src0 == src1)
5566         illegal_instruction_combination (cpu);
5567
5568       s0 = DREG (src0);
5569       s1 = DREG (src1);
5570       acc = (acc >> 2) |
5571         (((bu64)s0 & 1) << 38) |
5572         (((bu64)s1 & 1) << 39);
5573       STORE (DREG (src0), s0 >> 1);
5574       STORE (DREG (src1), s1 >> 1);
5575
5576       SET_AREG (0, acc);
5577     }
5578   else if (sop == 1 && sopcde == 8)
5579     {
5580       bu64 acc = get_unextended_acc (cpu, 0);
5581       bu32 s0, s1;
5582
5583       TRACE_INSN (cpu, "BITMUX (R%i, R%i, A0) (ASL);", src0, src1);
5584
5585       if (src0 == src1)
5586         illegal_instruction_combination (cpu);
5587
5588       s0 = DREG (src0);
5589       s1 = DREG (src1);
5590       acc = (acc << 2) |
5591         ((s0 >> 31) & 1) |
5592         ((s1 >> 30) & 2);
5593       STORE (DREG (src0), s0 << 1);
5594       STORE (DREG (src1), s1 << 1);
5595
5596       SET_AREG (0, acc);
5597     }
5598   else if ((sop == 0 || sop == 1) && sopcde == 9)
5599     {
5600       bs40 acc0 = get_unextended_acc (cpu, 0);
5601       bs16 sL, sH, out;
5602
5603       TRACE_INSN (cpu, "R%i.L = VIT_MAX (R%i) (AS%c);",
5604                   dst0, src1, sop & 1 ? 'R' : 'L');
5605
5606       sL = DREG (src1);
5607       sH = DREG (src1) >> 16;
5608
5609       if (sop & 1)
5610         acc0 = (acc0 & 0xfeffffffffull) >> 1;
5611       else
5612         acc0 <<= 1;
5613
5614       if (((sH - sL) & 0x8000) == 0)
5615         {
5616           out = sH;
5617           acc0 |= (sop & 1) ? 0x80000000 : 1;
5618         }
5619       else
5620         out = sL;
5621
5622       SET_AREG (0, acc0);
5623       STORE (DREG (dst0), REG_H_L (DREG (dst0), out));
5624     }
5625   else if ((sop == 2 || sop == 3) && sopcde == 9)
5626     {
5627       bs40 acc0 = get_extended_acc (cpu, 0);
5628       bs16 s0L, s0H, s1L, s1H, out0, out1;
5629
5630       TRACE_INSN (cpu, "R%i = VIT_MAX (R%i, R%i) (AS%c);",
5631                   dst0, src1, src0, sop & 1 ? 'R' : 'L');
5632
5633       s0L = DREG (src0);
5634       s0H = DREG (src0) >> 16;
5635       s1L = DREG (src1);
5636       s1H = DREG (src1) >> 16;
5637
5638       if (sop & 1)
5639         acc0 >>= 2;
5640       else
5641         acc0 <<= 2;
5642
5643       if (((s0H - s0L) & 0x8000) == 0)
5644         {
5645           out0 = s0H;
5646           acc0 |= (sop & 1) ? 0x40000000 : 2;
5647         }
5648       else
5649         out0 = s0L;
5650
5651       if (((s1H - s1L) & 0x8000) == 0)
5652         {
5653           out1 = s1H;
5654           acc0 |= (sop & 1) ? 0x80000000 : 1;
5655         }
5656       else
5657         out1 = s1L;
5658
5659       SET_AREG (0, acc0);
5660       STORE (DREG (dst0), REG_H_L (out1 << 16, out0));
5661     }
5662   else if (sop == 0 && sopcde == 10)
5663     {
5664       bu32 v = DREG (src0);
5665       bu32 x = DREG (src1);
5666       bu32 mask = (1 << (v & 0x1f)) - 1;
5667
5668       TRACE_INSN (cpu, "R%i = EXTRACT (R%i, R%i.L) (Z);", dst0, src1, src0);
5669
5670       x >>= ((v >> 8) & 0x1f);
5671       x &= mask;
5672       STORE (DREG (dst0), x);
5673       setflags_logical (cpu, x);
5674     }
5675   else if (sop == 1 && sopcde == 10)
5676     {
5677       bu32 v = DREG (src0);
5678       bu32 x = DREG (src1);
5679       bu32 sgn = (1 << (v & 0x1f)) >> 1;
5680       bu32 mask = (1 << (v & 0x1f)) - 1;
5681
5682       TRACE_INSN (cpu, "R%i = EXTRACT (R%i, R%i.L) (X);", dst0, src1, src0);
5683
5684       x >>= ((v >> 8) & 0x1f);
5685       x &= mask;
5686       if (x & sgn)
5687         x |= ~mask;
5688       STORE (DREG (dst0), x);
5689       setflags_logical (cpu, x);
5690     }
5691   else if ((sop == 2 || sop == 3) && sopcde == 10)
5692     {
5693       /* The first dregs is the "background" while the second dregs is the
5694          "foreground".  The fg reg is used to overlay the bg reg and is:
5695          | nnnn nnnn | nnnn nnnn | xxxp pppp | xxxL LLLL |
5696            n = the fg bit field
5697            p = bit position in bg reg to start LSB of fg field
5698            L = number of fg bits to extract
5699          Using (X) sign-extends the fg bit field.  */
5700       bu32 fg = DREG (src0);
5701       bu32 bg = DREG (src1);
5702       bu32 len = fg & 0x1f;
5703       bu32 mask = (1 << MIN (16, len)) - 1;
5704       bu32 fgnd = (fg >> 16) & mask;
5705       int shft = ((fg >> 8) & 0x1f);
5706
5707       TRACE_INSN (cpu, "R%i = DEPOSIT (R%i, R%i)%s;", dst0, src1, src0,
5708                   sop == 3 ? " (X)" : "");
5709
5710       if (sop == 3)
5711         {
5712           /* Sign extend the fg bit field.  */
5713           mask = -1;
5714           fgnd = ((bs32)(bs16)(fgnd << (16 - len))) >> (16 - len);
5715         }
5716       fgnd <<= shft;
5717       mask <<= shft;
5718       bg &= ~mask;
5719
5720       bg |= fgnd;
5721       STORE (DREG (dst0), bg);
5722       setflags_logical (cpu, bg);
5723     }
5724   else if (sop == 0 && sopcde == 11)
5725     {
5726       bu64 acc0 = get_unextended_acc (cpu, 0);
5727
5728       TRACE_INSN (cpu, "R%i.L = CC = BXORSHIFT (A0, R%i);", dst0, src0);
5729
5730       acc0 <<= 1;
5731       SET_CCREG (xor_reduce (acc0, DREG (src0)));
5732       SET_DREG (dst0, REG_H_L (DREG (dst0), CCREG));
5733       SET_AREG (0, acc0);
5734     }
5735   else if (sop == 1 && sopcde == 11)
5736     {
5737       bu64 acc0 = get_unextended_acc (cpu, 0);
5738
5739       TRACE_INSN (cpu, "R%i.L = CC = BXOR (A0, R%i);", dst0, src0);
5740
5741       SET_CCREG (xor_reduce (acc0, DREG (src0)));
5742       SET_DREG (dst0, REG_H_L (DREG (dst0), CCREG));
5743     }
5744   else if (sop == 0 && sopcde == 12)
5745     {
5746       bu64 acc0 = get_unextended_acc (cpu, 0);
5747       bu64 acc1 = get_unextended_acc (cpu, 1);
5748
5749       TRACE_INSN (cpu, "A0 = BXORSHIFT (A0, A1, CC);");
5750
5751       acc0 = (acc0 << 1) | (CCREG ^ xor_reduce (acc0, acc1));
5752       SET_AREG (0, acc0);
5753     }
5754   else if (sop == 1 && sopcde == 12)
5755     {
5756       bu64 acc0 = get_unextended_acc (cpu, 0);
5757       bu64 acc1 = get_unextended_acc (cpu, 1);
5758
5759       TRACE_INSN (cpu, "R%i.L = CC = BXOR (A0, A1, CC);", dst0);
5760
5761       SET_CCREG (CCREG ^ xor_reduce (acc0, acc1));
5762       acc0 = (acc0 << 1) | CCREG;
5763       SET_DREG (dst0, REG_H_L (DREG (dst0), CCREG));
5764     }
5765   else if ((sop == 0 || sop == 1 || sop == 2) && sopcde == 13)
5766     {
5767       int shift = (sop + 1) * 8;
5768       TRACE_INSN (cpu, "R%i = ALIGN%i (R%i, R%i);", dst0, shift, src1, src0);
5769       STORE (DREG (dst0), (DREG (src1) << (32 - shift)) | (DREG (src0) >> shift));
5770     }
5771   else
5772     illegal_instruction (cpu);
5773 }
5774
5775 static bu64
5776 sgn_extend (bu40 org, bu40 val, int size)
5777 {
5778   bu64 ret = val;
5779
5780   if (org & (1ULL << (size - 1)))
5781     {
5782       /* We need to shift in to the MSB which is set.  */
5783       int n;
5784
5785       for (n = 40; n >= 0; n--)
5786         if (ret & (1ULL << n))
5787           break;
5788       ret |= (-1ULL << n);
5789     }
5790   else
5791     ret &= ~(-1ULL << 39);
5792
5793   return ret;
5794 }
5795 static void
5796 decode_dsp32shiftimm_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
5797 {
5798   /* dsp32shiftimm
5799      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5800      | 1 | 1 | 0 | 0 |.M.| 1 | 1 | 0 | 1 | - | - |.sopcde............|
5801      |.sop...|.HLs...|.dst0......|.immag.................|.src1......|
5802      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
5803   int src1     = ((iw1 >> DSP32ShiftImm_src1_bits) & DSP32ShiftImm_src1_mask);
5804   int sop      = ((iw1 >> DSP32ShiftImm_sop_bits) & DSP32ShiftImm_sop_mask);
5805   int bit8     = ((iw1 >> 8) & 0x1);
5806   int immag    = ((iw1 >> DSP32ShiftImm_immag_bits) & DSP32ShiftImm_immag_mask);
5807   int newimmag = (-(iw1 >> DSP32ShiftImm_immag_bits) & DSP32ShiftImm_immag_mask);
5808   int dst0     = ((iw1 >> DSP32ShiftImm_dst0_bits) & DSP32ShiftImm_dst0_mask);
5809   int M        = ((iw0 >> (DSP32ShiftImm_M_bits - 16)) & DSP32ShiftImm_M_mask);
5810   int sopcde   = ((iw0 >> (DSP32ShiftImm_sopcde_bits - 16)) & DSP32ShiftImm_sopcde_mask);
5811   int HLs      = ((iw1 >> DSP32ShiftImm_HLs_bits) & DSP32ShiftImm_HLs_mask);
5812
5813   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dsp32shiftimm);
5814   TRACE_EXTRACT (cpu, "%s: M:%i sopcde:%i sop:%i HLs:%i dst0:%i immag:%#x src1:%i",
5815                  __func__, M, sopcde, sop, HLs, dst0, immag, src1);
5816
5817   if (sopcde == 0)
5818     {
5819       bu16 in = DREG (src1) >> ((HLs & 1) ? 16 : 0);
5820       bu16 result;
5821       bu32 v;
5822
5823       if (sop == 0)
5824         {
5825           TRACE_INSN (cpu, "R%i.%c = R%i.%c >>> %i;",
5826                       dst0, (HLs & 2) ? 'H' : 'L',
5827                       src1, (HLs & 1) ? 'H' : 'L', newimmag);
5828           if (newimmag > 16)
5829             {
5830               result = lshift (cpu, in, 16 - (newimmag & 0xF), 16, 0, 1);
5831               if (((result >> 15) & 0x1) != ((in >> 15) & 0x1))
5832                 {
5833                   SET_ASTATREG (v, 1);
5834                   SET_ASTATREG (vs, 1);
5835                 }
5836             }
5837           else
5838             result = ashiftrt (cpu, in, newimmag, 16);
5839         }
5840       else if (sop == 1 && bit8 == 0)
5841         {
5842           TRACE_INSN (cpu, "R%i.%c = R%i.%c << %i (S);",
5843                       dst0, (HLs & 2) ? 'H' : 'L',
5844                       src1, (HLs & 1) ? 'H' : 'L', immag);
5845           result = lshift (cpu, in, immag, 16, 1, 1);
5846         }
5847       else if (sop == 1 && bit8)
5848         {
5849           TRACE_INSN (cpu, "R%i.%c = R%i.%c >>> %i (S);",
5850                       dst0, (HLs & 2) ? 'H' : 'L',
5851                       src1, (HLs & 1) ? 'H' : 'L', newimmag);
5852           if (newimmag > 16)
5853             {
5854               int shift = 32 - newimmag;
5855               bu16 inshift = in << shift;
5856
5857               if (((inshift & ~0xFFFF)
5858                    && ((inshift & ~0xFFFF) >> 16) != ~(~0 << shift))
5859                   || (inshift & 0x8000) != (in & 0x8000))
5860                 {
5861                   if (in & 0x8000)
5862                     result = 0x8000;
5863                   else
5864                     result = 0x7fff;
5865                   SET_ASTATREG (v, 1);
5866                   SET_ASTATREG (vs, 1);
5867                 }
5868               else
5869                 {
5870                   result = inshift;
5871                   SET_ASTATREG (v, 0);
5872                 }
5873
5874               SET_ASTATREG (az, !result);
5875               SET_ASTATREG (an, !!(result & 0x8000));
5876             }
5877           else
5878             {
5879               result = ashiftrt (cpu, in, newimmag, 16);
5880               result = sgn_extend (in, result, 16);
5881             }
5882         }
5883       else if (sop == 2 && bit8)
5884         {
5885           TRACE_INSN (cpu, "R%i.%c = R%i.%c >> %i;",
5886                       dst0, (HLs & 2) ? 'H' : 'L',
5887                       src1, (HLs & 1) ? 'H' : 'L', newimmag);
5888           result = lshiftrt (cpu, in, newimmag, 16);
5889         }
5890       else if (sop == 2 && bit8 == 0)
5891         {
5892           TRACE_INSN (cpu, "R%i.%c = R%i.%c << %i;",
5893                       dst0, (HLs & 2) ? 'H' : 'L',
5894                       src1, (HLs & 1) ? 'H' : 'L', immag);
5895           result = lshift (cpu, in, immag, 16, 0, 1);
5896         }
5897       else
5898         illegal_instruction (cpu);
5899
5900       v = DREG (dst0);
5901       if (HLs & 2)
5902         STORE (DREG (dst0), (v & 0xFFFF) | (result << 16));
5903       else
5904         STORE (DREG (dst0), (v & 0xFFFF0000) | result);
5905     }
5906   else if (sop == 2 && sopcde == 3 && (HLs == 1 || HLs == 0))
5907     {
5908       int shift = imm6 (immag);
5909       bu32 cc = CCREG;
5910       bu40 acc = get_unextended_acc (cpu, HLs);
5911
5912       TRACE_INSN (cpu, "A%i = ROT A%i BY %i;", HLs, HLs, shift);
5913       TRACE_DECODE (cpu, "A%i:%#"PRIx64" shift:%i CC:%i", HLs, acc, shift, cc);
5914
5915       acc = rot40 (acc, shift, &cc);
5916       SET_AREG (HLs, acc);
5917       if (shift)
5918         SET_CCREG (cc);
5919     }
5920   else if (sop == 0 && sopcde == 3 && bit8 == 1)
5921     {
5922       /* Arithmetic shift, so shift in sign bit copies.  */
5923       bu64 acc, val;
5924       int shift = uimm5 (newimmag);
5925       HLs = !!HLs;
5926
5927       TRACE_INSN (cpu, "A%i = A%i >>> %i;", HLs, HLs, shift);
5928
5929       acc = get_extended_acc (cpu, HLs);
5930       val = acc >> shift;
5931
5932       /* Sign extend again.  */
5933       val = sgn_extend (acc, val, 40);
5934
5935       STORE (AXREG (HLs), (val >> 32) & 0xFF);
5936       STORE (AWREG (HLs), val & 0xFFFFFFFF);
5937       STORE (ASTATREG (an), !!(val & (1ULL << 39)));
5938       STORE (ASTATREG (az), !val);
5939       STORE (ASTATREG (av[HLs]), 0);
5940     }
5941   else if ((sop == 0 && sopcde == 3 && bit8 == 0)
5942            || (sop == 1 && sopcde == 3))
5943     {
5944       bu64 acc;
5945       int shiftup = uimm5 (immag);
5946       int shiftdn = uimm5 (newimmag);
5947       HLs = !!HLs;
5948
5949       TRACE_INSN (cpu, "A%i = A%i %s %i;", HLs, HLs,
5950                   sop == 0 ? "<<" : ">>",
5951                   sop == 0 ? shiftup : shiftdn);
5952
5953       acc = AXREG (HLs);
5954       /* Logical shift, so shift in zeroes.  */
5955       acc &= 0xFF;
5956       acc <<= 32;
5957       acc |= AWREG (HLs);
5958
5959       if (sop == 0)
5960         acc <<= shiftup;
5961       else
5962         {
5963           if (shiftdn <= 32)
5964             acc >>= shiftdn;
5965           else
5966             acc <<= 32 - (shiftdn & 0x1f);
5967         }
5968
5969       SET_AREG (HLs, acc);
5970       SET_ASTATREG (av[HLs], 0);
5971       SET_ASTATREG (an, !!(acc & 0x8000000000ull));
5972       SET_ASTATREG (az, (acc & 0xFFFFFFFFFF) == 0);
5973     }
5974   else if (sop == 1 && sopcde == 1 && bit8 == 0)
5975     {
5976       int count = imm5 (immag);
5977       bu16 val0 = DREG (src1) >> 16;
5978       bu16 val1 = DREG (src1) & 0xFFFF;
5979       bu32 astat;
5980
5981       TRACE_INSN (cpu, "R%i = R%i << %i (V,S);", dst0, src1, count);
5982       if (count >= 0)
5983         {
5984           val0 = lshift (cpu, val0, count, 16, 1, 1);
5985           astat = ASTAT;
5986           val1 = lshift (cpu, val1, count, 16, 1, 1);
5987         }
5988       else
5989         {
5990           val0 = ashiftrt (cpu, val0, -count, 16);
5991           astat = ASTAT;
5992           val1 = ashiftrt (cpu, val1, -count, 16);
5993         }
5994       SET_ASTAT (ASTAT | astat);
5995
5996       STORE (DREG (dst0), (val0 << 16) | val1);
5997     }
5998   else if (sop == 2 && sopcde == 1 && bit8 == 1)
5999     {
6000       int count = imm5 (newimmag);
6001       bu16 val0 = DREG (src1) & 0xFFFF;
6002       bu16 val1 = DREG (src1) >> 16;
6003       bu32 astat;
6004
6005       TRACE_INSN (cpu, "R%i = R%i >> %i (V);", dst0, src1, count);
6006       val0 = lshiftrt (cpu, val0, count, 16);
6007       astat = ASTAT;
6008       val1 = lshiftrt (cpu, val1, count, 16);
6009       SET_ASTAT (ASTAT | astat);
6010
6011       STORE (DREG (dst0), val0 | (val1 << 16));
6012     }
6013   else if (sop == 2 && sopcde == 1 && bit8 == 0)
6014     {
6015       int count = imm5 (immag);
6016       bu16 val0 = DREG (src1) & 0xFFFF;
6017       bu16 val1 = DREG (src1) >> 16;
6018       bu32 astat;
6019
6020       TRACE_INSN (cpu, "R%i = R%i << %i (V);", dst0, src1, count);
6021       val0 = lshift (cpu, val0, count, 16, 0, 1);
6022       astat = ASTAT;
6023       val1 = lshift (cpu, val1, count, 16, 0, 1);
6024       SET_ASTAT (ASTAT | astat);
6025
6026       STORE (DREG (dst0), val0 | (val1 << 16));
6027     }
6028   else if (sopcde == 1 && (sop == 0 || (sop == 1 && bit8 == 1)))
6029     {
6030       int count = uimm5 (newimmag);
6031       bu16 val0 = DREG (src1) & 0xFFFF;
6032       bu16 val1 = DREG (src1) >> 16;
6033       bu32 astat;
6034
6035       TRACE_INSN (cpu, "R%i = R%i >>> %i %s;", dst0, src1, count,
6036                   sop == 0 ? "(V)" : "(V,S)");
6037
6038       if (count > 16)
6039         {
6040           int sgn0 = (val0 >> 15) & 0x1;
6041           int sgn1 = (val1 >> 15) & 0x1;
6042
6043           val0 = lshift (cpu, val0, 16 - (count & 0xF), 16, 0, 1);
6044           astat = ASTAT;
6045           val1 = lshift (cpu, val1, 16 - (count & 0xF), 16, 0, 1);
6046
6047           if ((sgn0 != ((val0 >> 15) & 0x1)) || (sgn1 != ((val1 >> 15) & 0x1)))
6048             {
6049               SET_ASTATREG (v, 1);
6050               SET_ASTATREG (vs, 1);
6051             }
6052         }
6053       else
6054         {
6055           val0 = ashiftrt (cpu, val0, count, 16);
6056           astat = ASTAT;
6057           val1 = ashiftrt (cpu, val1, count, 16);
6058         }
6059
6060       SET_ASTAT (ASTAT | astat);
6061
6062       STORE (DREG (dst0), REG_H_L (val1 << 16, val0));
6063     }
6064   else if (sop == 1 && sopcde == 2)
6065     {
6066       int count = imm6 (immag);
6067
6068       TRACE_INSN (cpu, "R%i = R%i << %i (S);", dst0, src1, count);
6069       STORE (DREG (dst0), lshift (cpu, DREG (src1), count, 32, 1, 1));
6070     }
6071   else if (sop == 2 && sopcde == 2)
6072     {
6073       int count = imm6 (newimmag);
6074
6075       TRACE_INSN (cpu, "R%i = R%i >> %i;", dst0, src1, count);
6076
6077       if (count < 0)
6078         STORE (DREG (dst0), lshift (cpu, DREG (src1), -count, 32, 0, 1));
6079       else
6080         STORE (DREG (dst0), lshiftrt (cpu, DREG (src1), count, 32));
6081     }
6082   else if (sop == 3 && sopcde == 2)
6083     {
6084       int shift = imm6 (immag);
6085       bu32 src = DREG (src1);
6086       bu32 ret, cc = CCREG;
6087
6088       TRACE_INSN (cpu, "R%i = ROT R%i BY %i;", dst0, src1, shift);
6089       TRACE_DECODE (cpu, "R%i:%#x R%i:%#x shift:%i CC:%i",
6090                     dst0, DREG (dst0), src1, src, shift, cc);
6091
6092       ret = rot32 (src, shift, &cc);
6093       STORE (DREG (dst0), ret);
6094       if (shift)
6095         SET_CCREG (cc);
6096     }
6097   else if (sop == 0 && sopcde == 2)
6098     {
6099       int count = imm6 (newimmag);
6100
6101       TRACE_INSN (cpu, "R%i = R%i >>> %i;", dst0, src1, count);
6102
6103       if (count < 0)
6104         STORE (DREG (dst0), lshift (cpu, DREG (src1), -count, 32, 0, 1));
6105       else
6106         STORE (DREG (dst0), ashiftrt (cpu, DREG (src1), count, 32));
6107     }
6108   else
6109     illegal_instruction (cpu);
6110 }
6111
6112 static void
6113 outc (SIM_CPU *cpu, char ch)
6114 {
6115   SIM_DESC sd = CPU_STATE (cpu);
6116   sim_io_printf (sd, "%c", ch);
6117   if (ch == '\n')
6118     sim_io_flush_stdout (sd);
6119 }
6120
6121 static void
6122 decode_psedoDEBUG_0 (SIM_CPU *cpu, bu16 iw0)
6123 {
6124   /* psedoDEBUG
6125      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
6126      | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 |.fn....|.grp.......|.reg.......|
6127      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
6128   SIM_DESC sd = CPU_STATE (cpu);
6129   int fn  = ((iw0 >> PseudoDbg_fn_bits) & PseudoDbg_fn_mask);
6130   int grp = ((iw0 >> PseudoDbg_grp_bits) & PseudoDbg_grp_mask);
6131   int reg = ((iw0 >> PseudoDbg_reg_bits) & PseudoDbg_reg_mask);
6132
6133   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_psedoDEBUG);
6134   TRACE_EXTRACT (cpu, "%s: fn:%i grp:%i reg:%i", __func__, fn, grp, reg);
6135
6136   if ((reg == 0 || reg == 1) && fn == 3)
6137     {
6138       TRACE_INSN (cpu, "DBG A%i;", reg);
6139       sim_io_printf (sd, "DBG : A%i = %#"PRIx64"\n", reg,
6140                      get_unextended_acc (cpu, reg));
6141     }
6142   else if (reg == 3 && fn == 3)
6143     {
6144       TRACE_INSN (cpu, "ABORT;");
6145       cec_exception (cpu, VEC_SIM_ABORT);
6146       SET_DREG (0, 1);
6147     }
6148   else if (reg == 4 && fn == 3)
6149     {
6150       TRACE_INSN (cpu, "HLT;");
6151       cec_exception (cpu, VEC_SIM_HLT);
6152       SET_DREG (0, 0);
6153     }
6154   else if (reg == 5 && fn == 3)
6155     unhandled_instruction (cpu, "DBGHALT");
6156   else if (reg == 6 && fn == 3)
6157     unhandled_instruction (cpu, "DBGCMPLX (dregs)");
6158   else if (reg == 7 && fn == 3)
6159     unhandled_instruction (cpu, "DBG");
6160   else if (grp == 0 && fn == 2)
6161     {
6162       TRACE_INSN (cpu, "OUTC R%i;", reg);
6163       outc (cpu, DREG (reg));
6164     }
6165   else if (fn == 0)
6166     {
6167       const char *reg_name = get_allreg_name (grp, reg);
6168       TRACE_INSN (cpu, "DBG %s;", reg_name);
6169       sim_io_printf (sd, "DBG : %s = 0x%08x\n", reg_name,
6170                      reg_read (cpu, grp, reg));
6171     }
6172   else if (fn == 1)
6173     unhandled_instruction (cpu, "PRNT allregs");
6174   else
6175     illegal_instruction (cpu);
6176 }
6177
6178 static void
6179 decode_psedoOChar_0 (SIM_CPU *cpu, bu16 iw0)
6180 {
6181   /* psedoOChar
6182      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
6183      | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |.ch............................|
6184      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
6185   int ch = ((iw0 >> PseudoChr_ch_bits) & PseudoChr_ch_mask);
6186
6187   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_psedoOChar);
6188   TRACE_EXTRACT (cpu, "%s: ch:%#x", __func__, ch);
6189   TRACE_INSN (cpu, "OUTC %#x;", ch);
6190
6191   outc (cpu, ch);
6192 }
6193
6194 static void
6195 decode_psedodbg_assert_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1, bu32 pc)
6196 {
6197   /* psedodbg_assert
6198      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
6199      | 1 | 1 | 1 | 1 | 0 | - | - | - | dbgop |.grp.......|.regtest...|
6200      |.expected......................................................|
6201      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
6202   SIM_DESC sd = CPU_STATE (cpu);
6203   int expected = ((iw1 >> PseudoDbg_Assert_expected_bits) & PseudoDbg_Assert_expected_mask);
6204   int dbgop    = ((iw0 >> (PseudoDbg_Assert_dbgop_bits - 16)) & PseudoDbg_Assert_dbgop_mask);
6205   int grp      = ((iw0 >> (PseudoDbg_Assert_grp_bits - 16)) & PseudoDbg_Assert_grp_mask);
6206   int regtest  = ((iw0 >> (PseudoDbg_Assert_regtest_bits - 16)) & PseudoDbg_Assert_regtest_mask);
6207   int offset;
6208   bu16 actual;
6209   bu32 val = reg_read (cpu, grp, regtest);
6210   const char *reg_name = get_allreg_name (grp, regtest);
6211   const char *dbg_name, *dbg_appd;
6212
6213   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_psedodbg_assert);
6214   TRACE_EXTRACT (cpu, "%s: dbgop:%i grp:%i regtest:%i expected:%#x",
6215                  __func__, dbgop, grp, regtest, expected);
6216
6217   if (dbgop == 0 || dbgop == 2)
6218     {
6219       dbg_name = dbgop == 0 ? "DBGA" : "DBGAL";
6220       dbg_appd = dbgop == 0 ? ".L" : "";
6221       offset = 0;
6222     }
6223   else if (dbgop == 1 || dbgop == 3)
6224     {
6225       dbg_name = dbgop == 1 ? "DBGA" : "DBGAH";
6226       dbg_appd = dbgop == 1 ? ".H" : "";
6227       offset = 16;
6228     }
6229   else
6230     illegal_instruction (cpu);
6231
6232   actual = val >> offset;
6233
6234   TRACE_INSN (cpu, "%s (%s%s, 0x%x);", dbg_name, reg_name, dbg_appd, expected);
6235   if (actual != expected)
6236     {
6237       sim_io_printf (sd, "FAIL at %#x: %s (%s%s, 0x%04x); actual value %#x\n",
6238                      pc, dbg_name, reg_name, dbg_appd, expected, actual);
6239
6240       /* Decode the actual ASTAT bits that are different.  */
6241       if (grp == 4 && regtest == 6)
6242         {
6243           int i;
6244
6245           sim_io_printf (sd, "Expected ASTAT:\n");
6246           for (i = 0; i < 16; ++i)
6247             sim_io_printf (sd, " %8s%c%i%s",
6248                            astat_names[i + offset],
6249                            (((expected >> i) & 1) != ((actual >> i) & 1))
6250                                 ? '!' : ' ',
6251                            (expected >> i) & 1,
6252                            i == 7 ? "\n" : "");
6253           sim_io_printf (sd, "\n");
6254
6255           sim_io_printf (sd, "Actual ASTAT:\n");
6256           for (i = 0; i < 16; ++i)
6257             sim_io_printf (sd, " %8s%c%i%s",
6258                            astat_names[i + offset],
6259                            (((expected >> i) & 1) != ((actual >> i) & 1))
6260                                 ? '!' : ' ',
6261                            (actual >> i) & 1,
6262                            i == 7 ? "\n" : "");
6263           sim_io_printf (sd, "\n");
6264         }
6265
6266       cec_exception (cpu, VEC_SIM_DBGA);
6267       SET_DREG (0, 1);
6268     }
6269 }
6270
6271 static bu32
6272 _interp_insn_bfin (SIM_CPU *cpu, bu32 pc)
6273 {
6274   bu32 insn_len;
6275   bu16 iw0, iw1;
6276
6277   BFIN_CPU_STATE.multi_pc = pc;
6278   iw0 = IFETCH (pc);
6279   if ((iw0 & 0xc000) != 0xc000)
6280     {
6281       /* 16-bit opcode.  */
6282       insn_len = 2;
6283       if (INSN_LEN == 0)
6284         INSN_LEN = insn_len;
6285
6286       TRACE_EXTRACT (cpu, "%s: iw0:%#x", __func__, iw0);
6287       if ((iw0 & 0xFF00) == 0x0000)
6288         decode_ProgCtrl_0 (cpu, iw0, pc);
6289       else if ((iw0 & 0xFFC0) == 0x0240)
6290         decode_CaCTRL_0 (cpu, iw0);
6291       else if ((iw0 & 0xFF80) == 0x0100)
6292         decode_PushPopReg_0 (cpu, iw0);
6293       else if ((iw0 & 0xFE00) == 0x0400)
6294         decode_PushPopMultiple_0 (cpu, iw0);
6295       else if ((iw0 & 0xFE00) == 0x0600)
6296         decode_ccMV_0 (cpu, iw0);
6297       else if ((iw0 & 0xF800) == 0x0800)
6298         decode_CCflag_0 (cpu, iw0);
6299       else if ((iw0 & 0xFFE0) == 0x0200)
6300         decode_CC2dreg_0 (cpu, iw0);
6301       else if ((iw0 & 0xFF00) == 0x0300)
6302         decode_CC2stat_0 (cpu, iw0);
6303       else if ((iw0 & 0xF000) == 0x1000)
6304         decode_BRCC_0 (cpu, iw0, pc);
6305       else if ((iw0 & 0xF000) == 0x2000)
6306         decode_UJUMP_0 (cpu, iw0, pc);
6307       else if ((iw0 & 0xF000) == 0x3000)
6308         decode_REGMV_0 (cpu, iw0);
6309       else if ((iw0 & 0xFC00) == 0x4000)
6310         decode_ALU2op_0 (cpu, iw0);
6311       else if ((iw0 & 0xFE00) == 0x4400)
6312         decode_PTR2op_0 (cpu, iw0);
6313       else if ((iw0 & 0xF800) == 0x4800)
6314         decode_LOGI2op_0 (cpu, iw0);
6315       else if ((iw0 & 0xF000) == 0x5000)
6316         decode_COMP3op_0 (cpu, iw0);
6317       else if ((iw0 & 0xF800) == 0x6000)
6318         decode_COMPI2opD_0 (cpu, iw0);
6319       else if ((iw0 & 0xF800) == 0x6800)
6320         decode_COMPI2opP_0 (cpu, iw0);
6321       else if ((iw0 & 0xF000) == 0x8000)
6322         decode_LDSTpmod_0 (cpu, iw0);
6323       else if ((iw0 & 0xFF60) == 0x9E60)
6324         decode_dagMODim_0 (cpu, iw0);
6325       else if ((iw0 & 0xFFF0) == 0x9F60)
6326         decode_dagMODik_0 (cpu, iw0);
6327       else if ((iw0 & 0xFC00) == 0x9C00)
6328         decode_dspLDST_0 (cpu, iw0);
6329       else if ((iw0 & 0xF000) == 0x9000)
6330         decode_LDST_0 (cpu, iw0);
6331       else if ((iw0 & 0xFC00) == 0xB800)
6332         decode_LDSTiiFP_0 (cpu, iw0);
6333       else if ((iw0 & 0xE000) == 0xA000)
6334         decode_LDSTii_0 (cpu, iw0);
6335       else
6336         {
6337           TRACE_EXTRACT (cpu, "%s: no matching 16-bit pattern", __func__);
6338           illegal_instruction_or_combination (cpu);
6339         }
6340       return insn_len;
6341     }
6342
6343   /* Grab the next 16 bits to determine if it's a 32-bit or 64-bit opcode.  */
6344   iw1 = IFETCH (pc + 2);
6345   if ((iw0 & BIT_MULTI_INS) && (iw0 & 0xe800) != 0xe800 /* not linkage  */)
6346     {
6347       SIM_DESC sd = CPU_STATE (cpu);
6348       trace_prefix (sd, cpu, NULL_CIA, pc, TRACE_LINENUM_P (cpu),
6349                         NULL, 0, "|| %#"PRIx64, sim_events_time (sd));
6350       insn_len = 8;
6351       PARALLEL_GROUP = BFIN_PARALLEL_GROUP0;
6352     }
6353   else
6354     insn_len = 4;
6355
6356   TRACE_EXTRACT (cpu, "%s: iw0:%#x iw1:%#x insn_len:%i", __func__,
6357                      iw0, iw1, insn_len);
6358
6359   /* Only cache on first run through (in case of parallel insns).  */
6360   if (INSN_LEN == 0)
6361     INSN_LEN = insn_len;
6362   else
6363     /* Once you're past the first slot, only 16bit insns are valid.  */
6364     illegal_instruction_combination (cpu);
6365
6366   if ((iw0 & 0xf7ff) == 0xc003 && (iw1 & 0xfe00) == 0x1800)
6367     {
6368       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dsp32mac);
6369       TRACE_INSN (cpu, "MNOP;");
6370     }
6371   else if (((iw0 & 0xFF80) == 0xE080) && ((iw1 & 0x0C00) == 0x0000))
6372     decode_LoopSetup_0 (cpu, iw0, iw1, pc);
6373   else if (((iw0 & 0xFF00) == 0xE100) && ((iw1 & 0x0000) == 0x0000))
6374     decode_LDIMMhalf_0 (cpu, iw0, iw1);
6375   else if (((iw0 & 0xFE00) == 0xE200) && ((iw1 & 0x0000) == 0x0000))
6376     decode_CALLa_0 (cpu, iw0, iw1, pc);
6377   else if (((iw0 & 0xFC00) == 0xE400) && ((iw1 & 0x0000) == 0x0000))
6378     decode_LDSTidxI_0 (cpu, iw0, iw1);
6379   else if (((iw0 & 0xFFFE) == 0xE800) && ((iw1 & 0x0000) == 0x0000))
6380     decode_linkage_0 (cpu, iw0, iw1);
6381   else if (((iw0 & 0xF600) == 0xC000) && ((iw1 & 0x0000) == 0x0000))
6382     decode_dsp32mac_0 (cpu, iw0, iw1);
6383   else if (((iw0 & 0xF600) == 0xC200) && ((iw1 & 0x0000) == 0x0000))
6384     decode_dsp32mult_0 (cpu, iw0, iw1);
6385   else if (((iw0 & 0xF7C0) == 0xC400) && ((iw1 & 0x0000) == 0x0000))
6386     decode_dsp32alu_0 (cpu, iw0, iw1);
6387   else if (((iw0 & 0xF7E0) == 0xC600) && ((iw1 & 0x01C0) == 0x0000))
6388     decode_dsp32shift_0 (cpu, iw0, iw1);
6389   else if (((iw0 & 0xF7E0) == 0xC680) && ((iw1 & 0x0000) == 0x0000))
6390     decode_dsp32shiftimm_0 (cpu, iw0, iw1);
6391   else if ((iw0 & 0xFF00) == 0xF800)
6392     decode_psedoDEBUG_0 (cpu, iw0), insn_len = 2;
6393   else if ((iw0 & 0xFF00) == 0xF900)
6394     decode_psedoOChar_0 (cpu, iw0), insn_len = 2;
6395   else if (((iw0 & 0xFF00) == 0xF000) && ((iw1 & 0x0000) == 0x0000))
6396     decode_psedodbg_assert_0 (cpu, iw0, iw1, pc);
6397   else
6398     {
6399       TRACE_EXTRACT (cpu, "%s: no matching 32-bit pattern", __func__);
6400       illegal_instruction (cpu);
6401     }
6402
6403   return insn_len;
6404 }
6405
6406 bu32
6407 interp_insn_bfin (SIM_CPU *cpu, bu32 pc)
6408 {
6409   int i;
6410   bu32 insn_len;
6411
6412   BFIN_CPU_STATE.n_stores = 0;
6413   PARALLEL_GROUP = BFIN_PARALLEL_NONE;
6414   DIS_ALGN_EXPT &= ~1;
6415   CYCLE_DELAY = 1;
6416   INSN_LEN = 0;
6417
6418   insn_len = _interp_insn_bfin (cpu, pc);
6419
6420   /* Proper display of multiple issue instructions.  */
6421   if (insn_len == 8)
6422     {
6423       PARALLEL_GROUP = BFIN_PARALLEL_GROUP1;
6424       _interp_insn_bfin (cpu, pc + 4);
6425       PARALLEL_GROUP = BFIN_PARALLEL_GROUP2;
6426       _interp_insn_bfin (cpu, pc + 6);
6427     }
6428   for (i = 0; i < BFIN_CPU_STATE.n_stores; i++)
6429     {
6430       bu32 *addr = BFIN_CPU_STATE.stores[i].addr;
6431       *addr = BFIN_CPU_STATE.stores[i].val;
6432       TRACE_REGISTER (cpu, "dequeuing write %s = %#x",
6433                       get_store_name (cpu, addr), *addr);
6434     }
6435
6436   cycles_inc (cpu, CYCLE_DELAY);
6437
6438   /* Set back to zero in case a pending CEC event occurs
6439      after this this insn.  */
6440   INSN_LEN = 0;
6441
6442   return insn_len;
6443 }