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