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