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