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