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