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