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