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