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