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