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