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