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