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