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