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