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