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