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