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