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