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