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