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