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