1 /* Simulator for Analog Devices Blackfin processors.
3 Copyright (C) 2005-2021 Free Software Foundation, Inc.
4 Contributed by Analog Devices, Inc.
6 This file is part of simulators.
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.
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.
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/>. */
29 #include "opcode/bfin.h"
31 #include "dv-bfin_cec.h"
32 #include "dv-bfin_mmu.h"
34 #define HOST_LONG_WORD_SIZE (sizeof (long) * 8)
36 #define SIGNEXTEND(v, n) \
37 (((bs32)(v) << (HOST_LONG_WORD_SIZE - (n))) >> (HOST_LONG_WORD_SIZE - (n)))
39 static ATTRIBUTE_NORETURN
void
40 illegal_instruction (SIM_CPU
*cpu
)
42 TRACE_INSN (cpu
, "ILLEGAL INSTRUCTION");
44 cec_exception (cpu
, VEC_UNDEF_I
);
47 static ATTRIBUTE_NORETURN
void
48 illegal_instruction_combination (SIM_CPU
*cpu
)
50 TRACE_INSN (cpu
, "ILLEGAL INSTRUCTION COMBINATION");
52 cec_exception (cpu
, VEC_ILGAL_I
);
55 static ATTRIBUTE_NORETURN
void
56 illegal_instruction_or_combination (SIM_CPU
*cpu
)
58 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
59 illegal_instruction_combination (cpu
);
61 illegal_instruction (cpu
);
64 static ATTRIBUTE_NORETURN
void
65 unhandled_instruction (SIM_CPU
*cpu
, const char *insn
)
67 SIM_DESC sd
= CPU_STATE (cpu
);
71 TRACE_EVENTS (cpu
, "unhandled instruction");
74 iw1
= IFETCH (PCREG
+ 2);
75 iw2
= ((bu32
)iw0
<< 16) | iw1
;
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
);
81 sim_io_eprintf (sd
, "%04x", iw0
);
83 sim_io_eprintf (sd
, ") ... aborting\n");
85 illegal_instruction (cpu
);
88 static const char * const astat_names
[] =
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
,
148 } constant_formats
[] =
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},
196 fmtconst_str (const_forms_t cf
, bs32 x
, bu32 pc
)
200 if (constant_formats
[cf
].reloc
)
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
)
206 /*if (outf->symbol_at_address_func (ea, outf) || !constant_formats[cf].exact)
208 outf->print_address_func (ea, outf);
213 sprintf (buf
, "%#x", x
);
218 /* Negative constants have an implied sign bit. */
219 if (constant_formats
[cf
].negative
)
221 int nb
= constant_formats
[cf
].nbits
+ 1;
223 x
= x
| (1 << constant_formats
[cf
].nbits
);
224 x
= SIGNEXTEND (x
, nb
);
227 x
= constant_formats
[cf
].issigned
? SIGNEXTEND (x
, constant_formats
[cf
].nbits
) : x
;
229 if (constant_formats
[cf
].offset
)
230 x
+= constant_formats
[cf
].offset
;
232 if (constant_formats
[cf
].scale
)
233 x
<<= constant_formats
[cf
].scale
;
235 if (constant_formats
[cf
].decimal
)
236 sprintf (buf
, "%*i", constant_formats
[cf
].leading
, x
);
239 if (constant_formats
[cf
].issigned
&& x
< 0)
240 sprintf (buf
, "-0x%x", abs (x
));
242 sprintf (buf
, "0x%x", x
);
249 fmtconst_val (const_forms_t cf
, bu32 x
, bu32 pc
)
251 if (0 && constant_formats
[cf
].reloc
)
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
)
263 /* Negative constants have an implied sign bit. */
264 if (constant_formats
[cf
].negative
)
266 int nb
= constant_formats
[cf
].nbits
+ 1;
267 x
= x
| (1 << constant_formats
[cf
].nbits
);
268 x
= SIGNEXTEND (x
, nb
);
270 else if (constant_formats
[cf
].issigned
)
271 x
= SIGNEXTEND (x
, constant_formats
[cf
].nbits
);
273 x
+= constant_formats
[cf
].offset
;
274 x
<<= constant_formats
[cf
].scale
;
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)
333 /* Table C-4. Core Register Encoding Map. */
334 const char * const greg_names
[] =
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",
346 get_allreg_name (int grp
, int reg
)
348 return greg_names
[(grp
<< 3) | reg
];
351 get_preg_name (int reg
)
353 return get_allreg_name (1, reg
);
357 reg_is_reserved (int grp
, int reg
)
359 return (grp
== 4 && (reg
== 4 || reg
== 5)) || (grp
== 5);
363 get_allreg (SIM_CPU
*cpu
, int grp
, int reg
)
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,
372 REG_LC0, REG_LT0, REG_LB0, REG_LC1, REG_LT1, REG_LB1, REG_CYCLES,
374 REG_USP, REG_SEQSTAT, REG_SYSCFG, REG_RETI, REG_RETX, REG_RETN, REG_RETE,
376 switch (fullreg
>> 2)
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);
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 <REG (0);
394 case 50: return &LBREG (0);
395 case 51: return &LCREG (1);
396 case 52: return <REG (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
;
409 illegal_instruction (cpu
);
414 amod0 (int s0
, int x0
)
416 static const char * const mod0
[] = {
417 "", " (S)", " (CO)", " (SCO)",
419 int i
= s0
+ (x0
<< 1);
421 if (i
< ARRAY_SIZE (mod0
))
428 amod0amod2 (int s0
, int x0
, int aop0
)
430 static const char * const mod02
[] = {
431 "", " (S)", " (CO)", " (SCO)",
433 " (ASR)", " (S, ASR)", " (CO, ASR)", " (SCO, ASR)",
434 " (ASL)", " (S, ASL)", " (CO, ASL)", " (SCO, ASL)",
436 int i
= s0
+ (x0
<< 1) + (aop0
<< 2);
438 if (i
< ARRAY_SIZE (mod02
))
445 amod1 (int s0
, int x0
)
447 static const char * const mod1
[] = {
450 int i
= s0
+ (x0
<< 1);
452 if (i
< ARRAY_SIZE (mod1
))
459 mac_optmode (int mmod
, int MM
)
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)",
481 int i
= MM
+ (mmod
<< 1);
483 if (i
< ARRAY_SIZE (omode
) && omode
[i
])
490 get_store_name (SIM_CPU
*cpu
, bu32
*p
)
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
))
504 else if (p
== &ASTATREG (av0s
))
505 return "ASTAT[av0s]";
506 else if (p
== &ASTATREG (av1
))
508 else if (p
== &ASTATREG (av1s
))
509 return "ASTAT[av1s]";
510 else if (p
== &ASTATREG (v
))
512 else if (p
== &ASTATREG (vs
))
514 else if (p
== &ASTATREG (v_copy
))
515 return "ASTAT[v_copy]";
516 else if (p
== &ASTATREG (az
))
518 else if (p
== &ASTATREG (an
))
520 else if (p
== &ASTATREG (az
))
522 else if (p
== &ASTATREG (ac0
))
524 else if (p
== &ASTATREG (ac0_copy
))
525 return "ASTAT[ac0_copy]";
528 /* Worry about this when we start to STORE() it. */
529 sim_io_eprintf (CPU_STATE (cpu
), "STORE(): unknown register\n");
535 queue_store (SIM_CPU
*cpu
, bu32
*addr
, bu32 val
)
537 struct store
*s
= &BFIN_CPU_STATE
.stores
[BFIN_CPU_STATE
.n_stores
];
540 TRACE_REGISTER (cpu
, "queuing write %s = %#x",
541 get_store_name (cpu
, addr
), val
);
542 ++BFIN_CPU_STATE
.n_stores
;
544 #define STORE(X, Y) \
546 if (BFIN_CPU_STATE.n_stores == 20) abort (); \
547 queue_store (cpu, &(X), (Y)); \
551 setflags_nz (SIM_CPU
*cpu
, bu32 val
)
553 SET_ASTATREG (az
, val
== 0);
554 SET_ASTATREG (an
, val
>> 31);
558 setflags_nz_2x16 (SIM_CPU
*cpu
, bu32 val
)
560 SET_ASTATREG (an
, (bs16
)val
< 0 || (bs16
)(val
>> 16) < 0);
561 SET_ASTATREG (az
, (bs16
)val
== 0 || (bs16
)(val
>> 16) == 0);
565 setflags_logical (SIM_CPU
*cpu
, bu32 val
)
567 setflags_nz (cpu
, val
);
568 SET_ASTATREG (ac0
, 0);
573 add_brev (bu32 addend1
, bu32 addend2
)
582 for (i
= 31; i
>= 0; --i
)
584 b
= ((addend1
& mask
) >> i
) + ((addend2
& mask
) >> i
);
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(). */
600 dagadd (SIM_CPU
*cpu
, int dagno
, bs32 M
)
602 bu64 i
= IREG (dagno
);
603 bu64 l
= LREG (dagno
);
604 bu64 b
= BREG (dagno
);
608 bu32 im32
, iml32
, lb32
, res
;
611 /* A naïve implementation that mostly works:
613 if (l && res >= b + l)
615 STORE (IREG (dagno), res);
630 if ((i
& msb
) || (IM
& car
))
631 res
= (im32
< b
) ? iml32
: im32
;
633 res
= (im32
< b
) ? im32
: iml32
;
639 if ((IM
& car
) == (LB
& car
))
640 res
= (im32
< lb32
) ? im32
: iml32
;
642 res
= (im32
< lb32
) ? iml32
: im32
;
645 STORE (IREG (dagno
), res
);
649 /* See dagadd() notes above. */
651 dagsub (SIM_CPU
*cpu
, int dagno
, bs32 M
)
653 bu64 i
= IREG (dagno
);
654 bu64 l
= LREG (dagno
);
655 bu64 b
= BREG (dagno
);
658 bu64 mbar
= (bu32
)(~m
+ 1);
660 bu32 b32
, im32
, iml32
, lb32
, res
;
663 /* A naïve implementation that mostly works:
667 STORE (IREG (dagno), newi);
682 if (!!((i
& msb
) && (IM
& car
)) == !!(LB
& car
))
683 res
= (im32
< lb32
) ? im32
: iml32
;
685 res
= (im32
< lb32
) ? iml32
: im32
;
692 if (M
== 0 || IM
& car
)
693 res
= (im32
< b32
) ? iml32
: im32
;
695 res
= (im32
< b32
) ? im32
: iml32
;
698 STORE (IREG (dagno
), res
);
703 ashiftrt (SIM_CPU
*cpu
, bu40 val
, int cnt
, int size
)
705 int real_cnt
= cnt
> size
? size
: cnt
;
706 bu40 sgn
= ~(((val
& 0xFFFFFFFFFFull
) >> (size
- 1)) - 1);
707 int sgncnt
= size
- real_cnt
;
709 sgn
<<= 16, sgncnt
-= 16;
712 val
>>= 16, real_cnt
-= 16;
715 SET_ASTATREG (an
, val
>> (size
- 1));
716 SET_ASTATREG (az
, val
== 0);
723 lshiftrt (SIM_CPU
*cpu
, bu64 val
, int cnt
, int size
)
725 int real_cnt
= cnt
> size
? size
: cnt
;
727 val
>>= 16, real_cnt
-= 16;
738 val
&= 0xFFFFFFFFFFull
;
741 illegal_instruction (cpu
);
744 SET_ASTATREG (an
, val
>> (size
- 1));
745 SET_ASTATREG (az
, val
== 0);
752 lshift (SIM_CPU
*cpu
, bu64 val
, int cnt
, int size
, bool saturate
, bool overflow
)
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
;
765 new_val
<<= 16, real_cnt
-= 16;
767 new_val
<<= real_cnt
;
769 masked
= new_val
& mask
;
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.
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.
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)))
792 if (saturate
&& (v_i
|| ((val
>> (size
- 1)) != (new_val
>> (size
- 1)))))
794 new_val
= (val
>> (size
- 1)) == 0 ? 0x7fff : 0x8000;
799 new_val
&= 0xFFFFFFFF;
800 masked
&= 0xFFFFFFFF;
805 || (!sgn
&& new_val
== 0 && val
!= 0)))
807 new_val
= sgn
== 0 ? 0x7fffffff : 0x80000000;
812 new_val
&= 0xFFFFFFFFFFull
;
813 masked
&= 0xFFFFFFFFFFull
;
816 illegal_instruction (cpu
);
820 SET_ASTATREG (an
, new_val
>> (size
- 1));
821 SET_ASTATREG (az
, new_val
== 0);
824 SET_ASTATREG (v
, overflow
&& v_i
);
826 SET_ASTATREG (vs
, 1);
833 algn (bu32 l
, bu32 h
, bu32 aln
)
838 return (l
>> (8 * aln
)) | (h
<< (32 - 8 * aln
));
842 saturate_s16 (bu64 val
, bu32
*overflow
)
844 if ((bs64
)val
< -0x8000ll
)
850 if ((bs64
)val
> 0x7fff)
860 rot40 (bu40 val
, int shift
, bu32
*cc
)
862 const int nbits
= 40;
865 shift
= CLAMP (shift
, -nbits
, nbits
);
869 /* Reduce everything to rotate left. */
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;
882 rot32 (bu32 val
, int shift
, bu32
*cc
)
884 const int nbits
= 32;
887 shift
= CLAMP (shift
, -nbits
, nbits
);
891 /* Reduce everything to rotate left. */
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;
904 add32 (SIM_CPU
*cpu
, bu32 a
, bu32 b
, int carry
, int sat
)
906 int flgs
= (a
>> 31) & 1;
907 int flgo
= (b
>> 31) & 1;
909 int flgn
= (v
>> 31) & 1;
910 int overflow
= (flgs
^ flgn
) & (flgo
^ flgn
);
917 flgn
= (v
>> 31) & 1;
920 SET_ASTATREG (an
, flgn
);
922 SET_ASTATREG (vs
, 1);
923 SET_ASTATREG (v
, overflow
);
924 ASTATREG (v_internal
) |= overflow
;
925 SET_ASTATREG (az
, v
== 0);
927 SET_ASTATREG (ac0
, ~a
< b
);
933 sub32 (SIM_CPU
*cpu
, bu32 a
, bu32 b
, int carry
, int sat
, int parallel
)
935 int flgs
= (a
>> 31) & 1;
936 int flgo
= (b
>> 31) & 1;
938 int flgn
= (v
>> 31) & 1;
939 int overflow
= (flgs
^ flgo
) & (flgn
^ flgs
);
946 flgn
= (v
>> 31) & 1;
949 if (!parallel
|| flgn
)
950 SET_ASTATREG (an
, flgn
);
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
);
966 add16 (SIM_CPU
*cpu
, bu16 a
, bu16 b
, bu32
*carry
, bu32
*overfl
,
967 bu32
*zero
, bu32
*neg
, int sat
, int scale
)
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
);
981 v
= (a
>> 1) + (a
& 0x8000) + (b
>> 1) + (b
& 0x8000)
982 + (((a
& 1) + (b
& 1)) >> 1);
990 illegal_instruction (cpu
);
993 flgn
= (v
>> 15) & 1;
994 overflow
= (flgs
^ flgn
) & (flgo
^ flgn
);
996 if (v
> (bs64
)0xffff)
1000 v
= saturate_s16 (v
, 0);
1003 *neg
|= (v
>> 15) & 1;
1005 *overfl
|= overflow
;
1007 *zero
|= (v
& 0xFFFF) == 0;
1009 *carry
|= ((bu16
)~a
< (bu16
)b
);
1015 sub16 (SIM_CPU
*cpu
, bu16 a
, bu16 b
, bu32
*carry
, bu32
*overfl
,
1016 bu32
*zero
, bu32
*neg
, int sat
, int scale
)
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
);
1031 v
= ((a
>> 1) + (a
& 0x8000)) - ( (b
>> 1) + (b
& 0x8000))
1032 + (((a
& 1)-(b
& 1)));
1035 v
= ((v
& 0xFFFF) >> 1);
1036 if ((!flgs
& !flgo
& flgn
)
1037 || (flgs
& !flgo
& !flgn
)
1038 || (flgs
& flgo
& flgn
)
1039 || (flgs
& !flgo
& flgn
))
1043 flgn
= (v
>> 15) & 1;
1044 overflow
= (flgs
^ flgo
) & (flgn
^ flgs
);
1049 if (v
> (bs64
)0x7fff || v
< (bs64
)-0xffff)
1053 illegal_instruction (cpu
);
1058 v
= saturate_s16 (v
, 0);
1061 *neg
|= (v
>> 15) & 1;
1063 *zero
|= (v
& 0xFFFF) == 0;
1065 *overfl
|= overflow
;
1067 *carry
|= (bu16
)b
<= (bu16
)a
;
1072 min32 (SIM_CPU
*cpu
, bu32 a
, bu32 b
)
1075 if ((bs32
)a
> (bs32
)b
)
1077 setflags_nz (cpu
, val
);
1078 SET_ASTATREG (v
, 0);
1083 max32 (SIM_CPU
*cpu
, bu32 a
, bu32 b
)
1086 if ((bs32
)a
< (bs32
)b
)
1088 setflags_nz (cpu
, val
);
1089 SET_ASTATREG (v
, 0);
1094 min2x16 (SIM_CPU
*cpu
, bu32 a
, bu32 b
)
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);
1107 max2x16 (SIM_CPU
*cpu
, bu32 a
, bu32 b
)
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);
1120 add_and_shift (SIM_CPU
*cpu
, bu32 a
, bu32 b
, int shift
)
1123 ASTATREG (v_internal
) = 0;
1124 v
= add32 (cpu
, a
, b
, 0, 0);
1127 int x
= (v
>> 30) & 0x3;
1128 if (x
== 1 || x
== 2)
1129 ASTATREG (v_internal
) = 1;
1132 SET_ASTATREG (az
, v
== 0);
1133 SET_ASTATREG (an
, v
& 0x80000000);
1134 SET_ASTATREG (v
, ASTATREG (v_internal
));
1136 SET_ASTATREG (vs
, 1);
1141 xor_reduce (bu64 acc0
, bu64 acc1
)
1145 for (i
= 0; i
< 40; ++i
)
1147 v
^= (acc0
& acc1
& 1);
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. */
1159 divs (SIM_CPU
*cpu
, bu32 pquo
, bu16 divisor
)
1161 bu16 r
= pquo
>> 16;
1164 aq
= (r
^ divisor
) >> 15; /* Extract msb's and compute quotient bit. */
1165 SET_ASTATREG (aq
, aq
); /* Update global quotient state. */
1169 pquo
= (pquo
& 0x1FFFF) | (r
<< 17);
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. */
1179 divq (SIM_CPU
*cpu
, bu32 pquo
, bu16 divisor
)
1181 unsigned short af
= pquo
>> 16;
1190 aq
= (r
^ divisor
) >> 15; /* Extract msb's and compute quotient bit. */
1191 SET_ASTATREG (aq
, aq
); /* Update global quotient state. */
1195 pquo
= (pquo
& 0x1FFFF) | (r
<< 17);
1200 Count the number of bits set to 1 in the 32bit value. */
1208 for (i
= 0; i
< 32; ++i
)
1209 ret
+= !!(val
& (1 << i
));
1215 reg_check_sup (SIM_CPU
*cpu
, int grp
, int reg
)
1218 cec_require_supervisor (cpu
);
1222 reg_write (SIM_CPU
*cpu
, int grp
, int reg
, bu32 value
)
1226 /* ASTAT is special! */
1227 if (grp
== 4 && reg
== 6)
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
);
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. */
1243 else if (whichreg
== &EMUDAT_INREG
)
1244 /* Writes to EMUDAT goes to the output. */
1245 whichreg
= &EMUDAT_OUTREG
;
1246 else if (whichreg
== <REG (0) || whichreg
== <REG (1))
1247 /* Writes to LT clears LSB automatically. */
1249 else if (whichreg
== &AXREG (0) || whichreg
== &AXREG (1))
1252 TRACE_REGISTER (cpu
, "wrote %s = %#x", get_allreg_name (grp
, reg
), value
);
1258 reg_read (SIM_CPU
*cpu
, int grp
, int reg
)
1263 /* ASTAT is special! */
1264 if (grp
== 4 && reg
== 6)
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
);
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;
1284 get_extended_cycles (SIM_CPU
*cpu
)
1286 return ((bu64
)CYCLES2SHDREG
<< 32) | CYCLESREG
;
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. */
1292 cycles_inc (SIM_CPU
*cpu
, bu32 inc
)
1297 if (!(SYSCFGREG
& SYSCFG_CCEN
))
1300 cycles
= get_extended_cycles (cpu
) + inc
;
1301 SET_CYCLESREG (cycles
);
1302 cycles2
= cycles
>> 32;
1303 if (CYCLES2SHDREG
!= cycles2
)
1304 SET_CYCLES2SHDREG (cycles2
);
1308 get_unextended_acc (SIM_CPU
*cpu
, int which
)
1310 return ((bu64
)(AXREG (which
) & 0xff) << 32) | AWREG (which
);
1314 get_extended_acc (SIM_CPU
*cpu
, int which
)
1316 bu64 acc
= AXREG (which
);
1317 /* Sign extend accumulator values before adding. */
1323 acc
|= AWREG (which
);
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. */
1332 decode_multfunc (SIM_CPU
*cpu
, int h0
, int h1
, int src0
, int src1
, int mmod
,
1335 bu32 s0
= DREG (src0
), s1
= DREG (src1
);
1349 sgn0
= -(s0
& 0x8000);
1350 sgn1
= -(s1
& 0x8000);
1372 illegal_instruction (cpu
);
1376 /* Perform shift correction if appropriate for the mode. */
1378 if (!MM
&& (mmod
== 0 || mmod
== M_T
|| mmod
== M_S2RND
|| mmod
== M_W32
))
1380 if (val
== 0x40000000)
1393 /* In signed modes, sign extend. */
1394 if (is_macmod_signed (mmod
) || MM
)
1395 val1
|= -(val1
& 0x80000000);
1398 val1
&= 0xFFFFFFFFull
;
1404 saturate_s40_astat (bu64 val
, bu32
*v
)
1406 if ((bs64
)val
< -((bs64
)1 << 39))
1409 return -((bs64
)1 << 39);
1411 else if ((bs64
)val
> ((bs64
)1 << 39) - 1)
1414 return ((bu64
)1 << 39) - 1;
1416 *v
= 0; /* No overflow. */
1421 saturate_s40 (bu64 val
)
1424 return saturate_s40_astat (val
, &v
);
1428 saturate_s32 (bu64 val
, bu32
*overflow
)
1430 if ((bs64
)val
< -0x80000000ll
)
1436 if ((bs64
)val
> 0x7fffffff)
1446 saturate_u32 (bu64 val
, bu32
*overflow
)
1448 if (val
> 0xffffffff)
1458 saturate_u16 (bu64 val
, bu32
*overflow
)
1474 /* FIXME: Should honour rounding mode. */
1475 if ((val
& 0xffff) > 0x8000
1476 || ((val
& 0xffff) == 0x8000 && (val
& 0x10000)))
1479 sgnbits
= val
& 0xffff000000000000ull
;
1481 return val
| sgnbits
;
1487 bu64 sgnbits
= val
& 0xffff000000000000ull
;
1489 return val
| sgnbits
;
1493 signbits (bu64 val
, int size
)
1495 bu64 mask
= (bu64
)1 << (size
- 1);
1496 bu64 bit
= val
& mask
;
1504 if ((val
& mask
) != bit
)
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. */
1519 extract_mult (SIM_CPU
*cpu
, bu64 res
, int mmod
, int MM
,
1520 int fullword
, bu32
*overflow
)
1527 return saturate_s32 (res
, overflow
);
1530 return saturate_s32 (res
, overflow
);
1531 return saturate_u32 (res
, overflow
);
1534 return saturate_s32 (res
, overflow
);
1535 return saturate_u32 (res
, overflow
);
1538 return saturate_s32 (res
<< 1, overflow
);
1540 illegal_instruction (cpu
);
1548 return saturate_s16 (rnd16 (res
), overflow
);
1550 return saturate_s16 (res
, overflow
);
1553 return saturate_s16 (rnd16 (res
), overflow
);
1554 return saturate_u16 (rnd16 (res
), overflow
);
1557 return saturate_s16 (res
, overflow
);
1558 return saturate_u16 (res
, overflow
);
1561 return saturate_s16 (trunc16 (res
), overflow
);
1564 return saturate_s16 (trunc16 (res
), overflow
);
1565 return saturate_u16 (trunc16 (res
), overflow
);
1568 return saturate_s16 (rnd16 (res
<< 1), overflow
);
1570 return saturate_s16 (res
<< 1, overflow
);
1572 illegal_instruction (cpu
);
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
,
1582 bu32 sat
= 0, tsat
, ret
;
1584 /* Sign extend accumulator if necessary, otherwise unsigned. */
1585 if (is_macmod_signed (mmod
) || MM
)
1586 acc
= get_extended_acc (cpu
, which
);
1588 acc
= get_unextended_acc (cpu
, which
);
1592 bu8 sgn0
= (acc
>> 31) & 1;
1593 bu8 sgn40
= (acc
>> 39) & 1;
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
,
1600 /* Perform accumulation. */
1605 sgn0
= (acc
>> 31) & 1;
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;
1632 if ((bs64
)acc
< -((bs64
)1 << 39))
1633 acc
= -((bu64
)1 << 39), sat
= 1;
1634 if ((bs64
)acc
> 0x7FFFFFFFFFll
)
1635 acc
= 0x7FFFFFFFFFull
, sat
= 1;
1641 if ((bs64
)acc
> 0xFFFFFFFFFFull
)
1642 acc
= 0xFFFFFFFFFFull
, sat
= 1;
1646 if (!MM
&& acc
& 0x8000000000000000ull
)
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
;
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
;
1669 else if ((bs64
)acc
> (bs64
)0xFFFFFFFFFFll
)
1670 acc
= 0xFFFFFFFFFFull
, sat
= 1;
1674 if ((bs64
)acc
< -0x80000000ll
)
1675 acc
= -0x80000000ull
, sat
= 1;
1676 else if ((bs64
)acc
> 0x7fffffffll
)
1677 acc
= 0x7fffffffull
, sat
= 1;
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;
1688 if (acc
& 0x80000000)
1689 acc
|= 0xffffffff00000000ull
;
1694 illegal_instruction (cpu
);
1697 if (acc
& 0x8000000000ull
)
1700 STORE (AXREG (which
), (acc
>> 32) & 0xff);
1701 STORE (AWREG (which
), acc
& 0xffffffff);
1702 STORE (ASTATREG (av
[which
]), sat
);
1704 STORE (ASTATREG (avs
[which
]), sat
);
1706 /* Figure out the overflow bit. */
1712 ret
= extract_mult (cpu
, nosat_acc
, mmod
, MM
, fullword
, overflow
);
1716 ret
= extract_mult (cpu
, acc
, mmod
, MM
, fullword
, overflow
);
1725 if (ret
& 0x80000000)
1733 hwloop_get_next_pc (SIM_CPU
*cpu
, bu32 pc
, bu32 insn_len
)
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
))
1745 BFIN_TRACE_BRANCH (cpu
, pc
, LTREG (i
), i
, "Hardware loop %i", i
);
1749 return pc
+ insn_len
;
1753 decode_ProgCtrl_0 (SIM_CPU
*cpu
, bu16 iw0
, bu32 pc
)
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
);
1762 TRACE_EXTRACT (cpu
, "%s: poprnd:%i prgfunc:%i", __func__
, poprnd
, prgfunc
);
1764 if (prgfunc
== 0 && poprnd
== 0)
1766 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_nop
);
1767 TRACE_INSN (cpu
, "NOP;");
1769 else if (prgfunc
== 1 && poprnd
== 0)
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");
1779 BFIN_CPU_STATE
.did_jump
= true;
1782 else if (prgfunc
== 1 && poprnd
== 1)
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);
1792 else if (prgfunc
== 1 && poprnd
== 2)
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
);
1804 else if (prgfunc
== 1 && poprnd
== 3)
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
);
1816 else if (prgfunc
== 1 && poprnd
== 4)
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
);
1825 else if (prgfunc
== 2 && poprnd
== 0)
1827 SIM_DESC sd
= CPU_STATE (cpu
);
1828 sim_events
*events
= STATE_EVENTS (sd
);
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;");
1835 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1836 illegal_instruction_combination (cpu
);
1840 CYCLE_DELAY
= events
->time_from_event
;
1842 abort (); /* XXX: Should this ever happen ? */
1844 else if (prgfunc
== 2 && poprnd
== 3)
1846 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_sync
);
1848 TRACE_INSN (cpu
, "CSYNC;");
1849 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1850 illegal_instruction_combination (cpu
);
1853 else if (prgfunc
== 2 && poprnd
== 4)
1855 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_sync
);
1857 TRACE_INSN (cpu
, "SSYNC;");
1858 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1859 illegal_instruction_combination (cpu
);
1861 /* Really 10+, but no model info for this. */
1864 else if (prgfunc
== 2 && poprnd
== 5)
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
);
1872 else if (prgfunc
== 3 && poprnd
< 8)
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
));
1880 else if (prgfunc
== 4 && poprnd
< 8)
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
));
1889 else if (prgfunc
== 5 && poprnd
< 8)
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)");
1899 BFIN_CPU_STATE
.did_jump
= true;
1900 PROFILE_BRANCH_TAKEN (cpu
);
1903 else if (prgfunc
== 6 && poprnd
< 8)
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));
1916 BFIN_CPU_STATE
.did_jump
= true;
1917 PROFILE_BRANCH_TAKEN (cpu
);
1920 else if (prgfunc
== 7 && poprnd
< 8)
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));
1931 BFIN_CPU_STATE
.did_jump
= true;
1932 PROFILE_BRANCH_TAKEN (cpu
);
1935 else if (prgfunc
== 8 && poprnd
< 8)
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)");
1945 BFIN_CPU_STATE
.did_jump
= true;
1946 PROFILE_BRANCH_TAKEN (cpu
);
1949 else if (prgfunc
== 9)
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
);
1960 cec_latch (cpu
, raise
);
1961 CYCLE_DELAY
= 3; /* XXX: Only if IVG is unmasked. */
1963 else if (prgfunc
== 10)
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
);
1973 else if (prgfunc
== 11 && poprnd
< 6)
1975 bu32 addr
= PREG (poprnd
);
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. */
1988 illegal_instruction_or_combination (cpu
);
1992 decode_CaCTRL_0 (SIM_CPU
*cpu
, bu16 iw0
)
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", };
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
? "++" : "");
2008 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2009 /* None of these can be part of a parallel instruction. */
2010 illegal_instruction_combination (cpu
);
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 ? */
2019 mmu_check_cache_addr (cpu
, preg
, false, false);
2023 mmu_check_cache_addr (cpu
, preg
, true, false);
2027 mmu_check_cache_addr (cpu
, preg
, true, false);
2031 mmu_check_cache_addr (cpu
, preg
, false, true);
2035 SET_PREG (reg
, preg
+ BFIN_L1_CACHE_BYTES
);
2039 decode_PushPopReg_0 (SIM_CPU
*cpu
, bu16 iw0
)
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
);
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
);
2056 /* Can't push/pop reserved registers */
2057 if (reg_is_reserved (grp
, reg
))
2058 illegal_instruction_or_combination (cpu
);
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)
2081 TRACE_INSN (cpu
, "[--SP] = %s;", reg_name
);
2082 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2083 illegal_instruction_combination (cpu
);
2086 value
= reg_read (cpu
, grp
, reg
);
2087 if (grp
== 7 && reg
== 3)
2088 cec_push_reti (cpu
);
2090 PUT_LONG (sp
, value
);
2093 /* Note: SP update must be delayed until after all reads/writes; see
2094 comments in decode_PushPopMultiple_0() for more info. */
2099 decode_PushPopMultiple_0 (SIM_CPU
*cpu
, bu16 iw0
)
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
);
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
);
2117 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2118 illegal_instruction_combination (cpu
);
2120 if ((d
== 0 && p
== 0) || (p
&& imm5 (pr
) > 5)
2121 || (d
&& !p
&& pr
) || (p
&& !d
&& dr
))
2122 illegal_instruction (cpu
);
2127 TRACE_INSN (cpu
, "[--SP] = (R7:%i, P5:%i);", dr
, pr
);
2129 TRACE_INSN (cpu
, "[--SP] = (R7:%i);", dr
);
2131 TRACE_INSN (cpu
, "[--SP] = (P5:%i);", pr
);
2134 for (i
= dr
; i
< 8; i
++)
2137 PUT_LONG (sp
, DREG (i
));
2140 for (i
= pr
; i
< 6; i
++)
2143 PUT_LONG (sp
, PREG (i
));
2151 TRACE_INSN (cpu
, "(R7:%i, P5:%i) = [SP++];", dr
, pr
);
2153 TRACE_INSN (cpu
, "(R7:%i) = [SP++];", dr
);
2155 TRACE_INSN (cpu
, "(P5:%i) = [SP++];", pr
);
2158 for (i
= 5; i
>= pr
; i
--)
2160 SET_PREG (i
, GET_LONG (sp
));
2164 for (i
= 7; i
>= dr
; i
--)
2166 SET_DREG (i
, GET_LONG (sp
));
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. */
2180 decode_ccMV_0 (SIM_CPU
*cpu
, bu16 iw0
)
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
;
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
);
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
);
2204 reg_write (cpu
, d
, dst
, reg_read (cpu
, s
, src
));
2208 decode_CCflag_0 (SIM_CPU
*cpu
, bu16 iw0
)
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
);
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
);
2226 bs64 acc0
= get_extended_acc (cpu
, 0);
2227 bs64 acc1
= get_extended_acc (cpu
, 1);
2228 bs64 diff
= acc0
- acc1
;
2230 if (x
!= 0 || y
!= 0)
2231 illegal_instruction_or_combination (cpu
);
2233 if (opc
== 5 && I
== 0 && G
== 0)
2235 TRACE_INSN (cpu
, "CC = A0 == A1;");
2236 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2237 illegal_instruction_combination (cpu
);
2238 SET_CCREG (acc0
== acc1
);
2240 else if (opc
== 6 && I
== 0 && G
== 0)
2242 TRACE_INSN (cpu
, "CC = A0 < A1");
2243 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2244 illegal_instruction_combination (cpu
);
2245 SET_CCREG (acc0
< acc1
);
2247 else if (opc
== 7 && I
== 0 && G
== 0)
2249 TRACE_INSN (cpu
, "CC = A0 <= A1");
2250 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2251 illegal_instruction_combination (cpu
);
2252 SET_CCREG (acc0
<= acc1
);
2255 illegal_instruction_or_combination (cpu
);
2257 SET_ASTATREG (az
, diff
== 0);
2258 SET_ASTATREG (an
, diff
< 0);
2259 SET_ASTATREG (ac0
, (bu40
)acc1
<= (bu40
)acc0
);
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
);
2269 char d
= G
? 'P' : 'R';
2270 int flgs
= srcop
>> 31;
2271 int flgo
= dstop
>> 31;
2273 bu32 result
= srcop
- dstop
;
2275 int flgn
= result
>> 31;
2276 int overflow
= (flgs
^ flgo
) & (flgn
^ flgs
);
2277 int az
= result
== 0;
2278 int ac0
= dstop
<= srcop
;
2281 an
= (flgn
&& !overflow
) || (!flgn
&& overflow
);
2287 default: /* Shutup useless gcc warnings. */
2288 case 0: /* signed */
2292 case 1: /* signed */
2296 case 2: /* signed */
2300 case 3: /* unsigned */
2304 case 4: /* unsigned */
2311 TRACE_INSN (cpu
, "CC = %c%i %s %s%s;", s
, x
, op
,
2312 issigned
? imm3_str (y
) : uimm3_str (y
), sign
);
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
);
2320 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2321 illegal_instruction_combination (cpu
);
2324 /* Pointer compares only touch CC. */
2327 SET_ASTATREG (az
, az
);
2328 SET_ASTATREG (an
, an
);
2329 SET_ASTATREG (ac0
, ac0
);
2335 decode_CC2dreg_0 (SIM_CPU
*cpu
, bu16 iw0
)
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
);
2344 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CC2dreg
);
2345 TRACE_EXTRACT (cpu
, "%s: op:%i reg:%i", __func__
, op
, reg
);
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
);
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);
2361 else if (op
== 3 && reg
== 0)
2363 TRACE_INSN (cpu
, "CC = !CC;");
2364 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2365 illegal_instruction_combination (cpu
);
2369 illegal_instruction_or_combination (cpu
);
2373 decode_CC2stat_0 (SIM_CPU
*cpu
, bu16 iw0
)
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
);
2384 const char * const op_names
[] = { "", "|", "&", "^" } ;
2386 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CC2stat
);
2387 TRACE_EXTRACT (cpu
, "%s: D:%i op:%i cbit:%i", __func__
, D
, op
, cbit
);
2389 TRACE_INSN (cpu
, "%s %s= %s;", D
? astat_names
[cbit
] : "CC",
2390 op_names
[op
], D
? "CC" : astat_names
[cbit
]);
2392 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2393 illegal_instruction_combination (cpu
);
2395 /* CC = CC; is invalid. */
2397 illegal_instruction (cpu
);
2399 pval
= !!(ASTAT
& (1 << cbit
));
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;
2412 case 0: pval
= CCREG
; break;
2413 case 1: pval
|= CCREG
; break;
2414 case 2: pval
&= CCREG
; break;
2415 case 3: pval
^= CCREG
; break;
2417 TRACE_REGISTER (cpu
, "wrote ASTAT[%s] = %i", astat_names
[cbit
], pval
);
2418 SET_ASTAT ((ASTAT
& ~(1 << cbit
)) | (pval
<< cbit
));
2423 decode_BRCC_0 (SIM_CPU
*cpu
, bu16 iw0
, bu32 pc
)
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
);
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
);
2439 TRACE_INSN (cpu
, "IF %sCC JUMP %#x%s;", T
? "" : "! ",
2440 pcrel
, B
? " (bp)" : "");
2442 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2443 illegal_instruction_combination (cpu
);
2447 bu32 newpc
= pc
+ pcrel
;
2448 BFIN_TRACE_BRANCH (cpu
, pc
, newpc
, -1, "Conditional JUMP");
2450 BFIN_CPU_STATE
.did_jump
= true;
2451 PROFILE_BRANCH_TAKEN (cpu
);
2452 CYCLE_DELAY
= B
? 5 : 9;
2456 PROFILE_BRANCH_UNTAKEN (cpu
);
2457 CYCLE_DELAY
= B
? 9 : 1;
2462 decode_UJUMP_0 (SIM_CPU
*cpu
, bu16 iw0
, bu32 pc
)
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
;
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
);
2476 TRACE_INSN (cpu
, "JUMP.S %#x;", pcrel
);
2478 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2479 illegal_instruction_combination (cpu
);
2481 BFIN_TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP.S");
2484 BFIN_CPU_STATE
.did_jump
= true;
2485 PROFILE_BRANCH_TAKEN (cpu
);
2490 decode_REGMV_0 (SIM_CPU
*cpu
, bu16 iw0
)
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
);
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
);
2508 TRACE_INSN (cpu
, "%s = %s;", dstreg_name
, srcreg_name
);
2510 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2511 illegal_instruction_combination (cpu
);
2513 /* Reserved slots cannot be a src/dst. */
2514 if (reg_is_reserved (gs
, src
) || reg_is_reserved (gd
, dst
))
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 */
2526 /* dareg = dareg (IMBL) */
2527 if (gs
< 4 && gd
< 4)
2530 /* USP can be src to sysregs, but not dagregs. */
2531 if ((gs
== 7 && src
== 0) && (gd
>= 4))
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)))
2539 /* Still here ? Invalid reg pair. */
2541 illegal_instruction (cpu
);
2544 reg_write (cpu
, gd
, dst
, reg_read (cpu
, gs
, src
));
2548 decode_ALU2op_0 (SIM_CPU
*cpu
, bu16 iw0
)
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
);
2558 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ALU2op
);
2559 TRACE_EXTRACT (cpu
, "%s: opc:%i src:%i dst:%i", __func__
, opc
, src
, dst
);
2561 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2562 illegal_instruction_combination (cpu
);
2566 TRACE_INSN (cpu
, "R%i >>>= R%i;", dst
, src
);
2567 SET_DREG (dst
, ashiftrt (cpu
, DREG (dst
), DREG (src
), 32));
2572 TRACE_INSN (cpu
, "R%i >>= R%i;", dst
, src
);
2573 if (DREG (src
) <= 0x1F)
2574 val
= lshiftrt (cpu
, DREG (dst
), DREG (src
), 32);
2577 SET_DREG (dst
, val
);
2581 TRACE_INSN (cpu
, "R%i <<= R%i;", dst
, src
);
2582 SET_DREG (dst
, lshift (cpu
, DREG (dst
), DREG (src
), 32, 0, 0));
2586 TRACE_INSN (cpu
, "R%i *= R%i;", dst
, src
);
2587 SET_DREG (dst
, DREG (dst
) * DREG (src
));
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));
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));
2602 TRACE_INSN (cpu
, "DIVQ ( R%i, R%i );", dst
, src
);
2603 SET_DREG (dst
, divq (cpu
, DREG (dst
), (bu16
)DREG (src
)));
2607 TRACE_INSN (cpu
, "DIVS ( R%i, R%i );", dst
, src
);
2608 SET_DREG (dst
, divs (cpu
, DREG (dst
), (bu16
)DREG (src
)));
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
));
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
));
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
));
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
));
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);
2642 SET_ASTATREG (vs
, 1);
2643 SET_ASTATREG (ac0
, val
== 0x0);
2644 /* XXX: Documentation isn't entirely clear about av0 and av1. */
2648 TRACE_INSN (cpu
, "R%i = ~ R%i;", dst
, src
);
2649 SET_DREG (dst
, ~DREG (src
));
2650 setflags_logical (cpu
, DREG (dst
));
2653 illegal_instruction (cpu
);
2657 decode_PTR2op_0 (SIM_CPU
*cpu
, bu16 iw0
)
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
);
2669 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_PTR2op
);
2670 TRACE_EXTRACT (cpu
, "%s: opc:%i src:%i dst:%i", __func__
, opc
, src
, dst
);
2672 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2673 illegal_instruction_combination (cpu
);
2677 TRACE_INSN (cpu
, "%s -= %s", dst_name
, src_name
);
2678 SET_PREG (dst
, PREG (dst
) - PREG (src
));
2682 TRACE_INSN (cpu
, "%s = %s << 2", dst_name
, src_name
);
2683 SET_PREG (dst
, PREG (src
) << 2);
2687 TRACE_INSN (cpu
, "%s = %s >> 2", dst_name
, src_name
);
2688 SET_PREG (dst
, PREG (src
) >> 2);
2692 TRACE_INSN (cpu
, "%s = %s >> 1", dst_name
, src_name
);
2693 SET_PREG (dst
, PREG (src
) >> 1);
2697 TRACE_INSN (cpu
, "%s += %s (BREV)", dst_name
, src_name
);
2698 SET_PREG (dst
, add_brev (PREG (dst
), PREG (src
)));
2702 TRACE_INSN (cpu
, "%s = (%s + %s) << 1", dst_name
, dst_name
, src_name
);
2703 SET_PREG (dst
, (PREG (dst
) + PREG (src
)) << 1);
2707 TRACE_INSN (cpu
, "%s = (%s + %s) << 2", dst_name
, dst_name
, src_name
);
2708 SET_PREG (dst
, (PREG (dst
) + PREG (src
)) << 2);
2711 illegal_instruction (cpu
);
2715 decode_LOGI2op_0 (SIM_CPU
*cpu
, bu16 iw0
)
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
);
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
);
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);
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);
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
));
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
));
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
));
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));
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));
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));
2793 decode_COMP3op_0 (SIM_CPU
*cpu
, bu16 iw0
)
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
);
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
);
2808 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2809 illegal_instruction_combination (cpu
);
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));
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));
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
));
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
));
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
));
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
);
2846 /* If src0 == src1 this is disassembled as a shift by 1, but this
2847 distinction doesn't matter for our purposes. */
2849 TRACE_INSN (cpu
, "%s = (%s + %s) << %#x;",
2850 dst_name
, src0_name
, src1_name
, shift
);
2852 TRACE_INSN (cpu
, "%s = %s + %s",
2853 dst_name
, src0_name
, src1_name
);
2854 SET_PREG (dst
, PREG (src0
) + (PREG (src1
) << shift
));
2859 decode_COMPI2opD_0 (SIM_CPU
*cpu
, bu16 iw0
)
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
);
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
);
2874 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2875 illegal_instruction_combination (cpu
);
2879 TRACE_INSN (cpu
, "R%i = %s (X);", dst
, imm7_str (imm
));
2880 SET_DREG (dst
, imm
);
2884 TRACE_INSN (cpu
, "R%i += %s;", dst
, imm7_str (imm
));
2885 SET_DREG (dst
, add32 (cpu
, DREG (dst
), imm
, 1, 0));
2890 decode_COMPI2opP_0 (SIM_CPU
*cpu
, bu16 iw0
)
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
);
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
);
2906 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2907 illegal_instruction_combination (cpu
);
2911 TRACE_INSN (cpu
, "%s = %s;", dst_name
, imm7_str (imm
));
2912 SET_PREG (dst
, imm
);
2916 TRACE_INSN (cpu
, "%s += %s;", dst_name
, imm7_str (imm
));
2917 SET_PREG (dst
, PREG (dst
) + imm
);
2922 decode_LDSTpmod_0 (SIM_CPU
*cpu
, bu16 iw0
)
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
);
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
);
2941 if (PARALLEL_GROUP
== BFIN_PARALLEL_GROUP2
)
2942 illegal_instruction_combination (cpu
);
2944 if (aop
== 1 && W
== 0 && idx
== ptr
)
2946 TRACE_INSN (cpu
, "R%i.L = W[%s];", reg
, ptr_name
);
2948 val
= GET_WORD (addr
);
2949 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | val
);
2951 else if (aop
== 2 && W
== 0 && idx
== ptr
)
2953 TRACE_INSN (cpu
, "R%i.H = W[%s];", reg
, ptr_name
);
2955 val
= GET_WORD (addr
);
2956 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (val
<< 16));
2958 else if (aop
== 1 && W
== 1 && idx
== ptr
)
2960 TRACE_INSN (cpu
, "W[%s] = R%i.L;", ptr_name
, reg
);
2962 PUT_WORD (addr
, DREG (reg
));
2964 else if (aop
== 2 && W
== 1 && idx
== ptr
)
2966 TRACE_INSN (cpu
, "W[%s] = R%i.H;", ptr_name
, reg
);
2968 PUT_WORD (addr
, DREG (reg
) >> 16);
2970 else if (aop
== 0 && W
== 0)
2972 TRACE_INSN (cpu
, "R%i = [%s ++ %s];", reg
, ptr_name
, idx_name
);
2974 val
= GET_LONG (addr
);
2975 STORE (DREG (reg
), val
);
2977 STORE (PREG (ptr
), addr
+ PREG (idx
));
2979 else if (aop
== 1 && W
== 0)
2981 TRACE_INSN (cpu
, "R%i.L = W[%s ++ %s];", reg
, ptr_name
, idx_name
);
2983 val
= GET_WORD (addr
);
2984 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | val
);
2986 STORE (PREG (ptr
), addr
+ PREG (idx
));
2988 else if (aop
== 2 && W
== 0)
2990 TRACE_INSN (cpu
, "R%i.H = W[%s ++ %s];", reg
, ptr_name
, idx_name
);
2992 val
= GET_WORD (addr
);
2993 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (val
<< 16));
2995 STORE (PREG (ptr
), addr
+ PREG (idx
));
2997 else if (aop
== 3 && W
== 0)
2999 TRACE_INSN (cpu
, "R%i = W[%s ++ %s] (Z);", reg
, ptr_name
, idx_name
);
3001 val
= GET_WORD (addr
);
3002 STORE (DREG (reg
), val
);
3004 STORE (PREG (ptr
), addr
+ PREG (idx
));
3006 else if (aop
== 3 && W
== 1)
3008 TRACE_INSN (cpu
, "R%i = W[%s ++ %s] (X);", reg
, ptr_name
, idx_name
);
3010 val
= GET_WORD (addr
);
3011 STORE (DREG (reg
), (bs32
) (bs16
) val
);
3013 STORE (PREG (ptr
), addr
+ PREG (idx
));
3015 else if (aop
== 0 && W
== 1)
3017 TRACE_INSN (cpu
, "[%s ++ %s] = R%i;", ptr_name
, idx_name
, reg
);
3019 PUT_LONG (addr
, DREG (reg
));
3021 STORE (PREG (ptr
), addr
+ PREG (idx
));
3023 else if (aop
== 1 && W
== 1)
3025 TRACE_INSN (cpu
, "W[%s ++ %s] = R%i.L;", ptr_name
, idx_name
, reg
);
3027 PUT_WORD (addr
, DREG (reg
));
3029 STORE (PREG (ptr
), addr
+ PREG (idx
));
3031 else if (aop
== 2 && W
== 1)
3033 TRACE_INSN (cpu
, "W[%s ++ %s] = R%i.H;", ptr_name
, idx_name
, reg
);
3035 PUT_WORD (addr
, DREG (reg
) >> 16);
3037 STORE (PREG (ptr
), addr
+ PREG (idx
));
3040 illegal_instruction_or_combination (cpu
);
3044 decode_dagMODim_0 (SIM_CPU
*cpu
, bu16 iw0
)
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
);
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
);
3058 if (PARALLEL_GROUP
== BFIN_PARALLEL_GROUP2
)
3059 illegal_instruction_combination (cpu
);
3061 if (op
== 0 && br
== 1)
3063 TRACE_INSN (cpu
, "I%i += M%i (BREV);", i
, m
);
3064 SET_IREG (i
, add_brev (IREG (i
), MREG (m
)));
3068 TRACE_INSN (cpu
, "I%i += M%i;", i
, m
);
3069 dagadd (cpu
, i
, MREG (m
));
3071 else if (op
== 1 && br
== 0)
3073 TRACE_INSN (cpu
, "I%i -= M%i;", i
, m
);
3074 dagsub (cpu
, i
, MREG (m
));
3077 illegal_instruction_or_combination (cpu
);
3081 decode_dagMODik_0 (SIM_CPU
*cpu
, bu16 iw0
)
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
);
3090 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dagMODik
);
3091 TRACE_EXTRACT (cpu
, "%s: op:%i i:%i", __func__
, op
, i
);
3093 if (PARALLEL_GROUP
== BFIN_PARALLEL_GROUP2
)
3094 illegal_instruction_combination (cpu
);
3098 TRACE_INSN (cpu
, "I%i += 2;", i
);
3103 TRACE_INSN (cpu
, "I%i -= 2;", i
);
3108 TRACE_INSN (cpu
, "I%i += 4;", i
);
3113 TRACE_INSN (cpu
, "I%i -= 4;", i
);
3117 illegal_instruction_or_combination (cpu
);
3121 decode_dspLDST_0 (SIM_CPU
*cpu
, bu16 iw0
)
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
);
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
);
3137 if (aop
== 0 && W
== 0 && m
== 0)
3139 TRACE_INSN (cpu
, "R%i = [I%i++];", reg
, i
);
3141 if (DIS_ALGN_EXPT
& 0x1)
3144 STORE (DREG (reg
), GET_LONG (addr
));
3146 else if (aop
== 0 && W
== 0 && m
== 1)
3148 TRACE_INSN (cpu
, "R%i.L = W[I%i++];", reg
, i
);
3151 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | GET_WORD (addr
));
3153 else if (aop
== 0 && W
== 0 && m
== 2)
3155 TRACE_INSN (cpu
, "R%i.H = W[I%i++];", reg
, i
);
3158 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (GET_WORD (addr
) << 16));
3160 else if (aop
== 1 && W
== 0 && m
== 0)
3162 TRACE_INSN (cpu
, "R%i = [I%i--];", reg
, i
);
3164 if (DIS_ALGN_EXPT
& 0x1)
3167 STORE (DREG (reg
), GET_LONG (addr
));
3169 else if (aop
== 1 && W
== 0 && m
== 1)
3171 TRACE_INSN (cpu
, "R%i.L = W[I%i--];", reg
, i
);
3174 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | GET_WORD (addr
));
3176 else if (aop
== 1 && W
== 0 && m
== 2)
3178 TRACE_INSN (cpu
, "R%i.H = W[I%i--];", reg
, i
);
3181 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (GET_WORD (addr
) << 16));
3183 else if (aop
== 2 && W
== 0 && m
== 0)
3185 TRACE_INSN (cpu
, "R%i = [I%i];", reg
, i
);
3187 if (DIS_ALGN_EXPT
& 0x1)
3189 STORE (DREG (reg
), GET_LONG (addr
));
3191 else if (aop
== 2 && W
== 0 && m
== 1)
3193 TRACE_INSN (cpu
, "R%i.L = W[I%i];", reg
, i
);
3195 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | GET_WORD (addr
));
3197 else if (aop
== 2 && W
== 0 && m
== 2)
3199 TRACE_INSN (cpu
, "R%i.H = W[I%i];", reg
, i
);
3201 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (GET_WORD (addr
) << 16));
3203 else if (aop
== 0 && W
== 1 && m
== 0)
3205 TRACE_INSN (cpu
, "[I%i++] = R%i;", i
, reg
);
3208 PUT_LONG (addr
, DREG (reg
));
3210 else if (aop
== 0 && W
== 1 && m
== 1)
3212 TRACE_INSN (cpu
, "W[I%i++] = R%i.L;", i
, reg
);
3215 PUT_WORD (addr
, DREG (reg
));
3217 else if (aop
== 0 && W
== 1 && m
== 2)
3219 TRACE_INSN (cpu
, "W[I%i++] = R%i.H;", i
, reg
);
3222 PUT_WORD (addr
, DREG (reg
) >> 16);
3224 else if (aop
== 1 && W
== 1 && m
== 0)
3226 TRACE_INSN (cpu
, "[I%i--] = R%i;", i
, reg
);
3229 PUT_LONG (addr
, DREG (reg
));
3231 else if (aop
== 1 && W
== 1 && m
== 1)
3233 TRACE_INSN (cpu
, "W[I%i--] = R%i.L;", i
, reg
);
3236 PUT_WORD (addr
, DREG (reg
));
3238 else if (aop
== 1 && W
== 1 && m
== 2)
3240 TRACE_INSN (cpu
, "W[I%i--] = R%i.H;", i
, reg
);
3243 PUT_WORD (addr
, DREG (reg
) >> 16);
3245 else if (aop
== 2 && W
== 1 && m
== 0)
3247 TRACE_INSN (cpu
, "[I%i] = R%i;", i
, reg
);
3249 PUT_LONG (addr
, DREG (reg
));
3251 else if (aop
== 2 && W
== 1 && m
== 1)
3253 TRACE_INSN (cpu
, "W[I%i] = R%i.L;", i
, reg
);
3255 PUT_WORD (addr
, DREG (reg
));
3257 else if (aop
== 2 && W
== 1 && m
== 2)
3259 TRACE_INSN (cpu
, "W[I%i] = R%i.H;", i
, reg
);
3261 PUT_WORD (addr
, DREG (reg
) >> 16);
3263 else if (aop
== 3 && W
== 0)
3265 TRACE_INSN (cpu
, "R%i = [I%i ++ M%i];", reg
, i
, m
);
3267 if (DIS_ALGN_EXPT
& 0x1)
3269 dagadd (cpu
, i
, MREG (m
));
3270 STORE (DREG (reg
), GET_LONG (addr
));
3272 else if (aop
== 3 && W
== 1)
3274 TRACE_INSN (cpu
, "[I%i ++ M%i] = R%i;", i
, m
, reg
);
3276 dagadd (cpu
, i
, MREG (m
));
3277 PUT_LONG (addr
, DREG (reg
));
3280 illegal_instruction_or_combination (cpu
);
3284 decode_LDST_0 (SIM_CPU
*cpu
, bu16 iw0
)
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
);
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
);
3304 if (aop
== 3 || PARALLEL_GROUP
== BFIN_PARALLEL_GROUP2
)
3305 illegal_instruction_or_combination (cpu
);
3309 if (sz
== 0 && Z
== 0)
3311 TRACE_INSN (cpu
, "R%i = [%s%s];", reg
, ptr_name
, post
);
3312 SET_DREG (reg
, GET_LONG (PREG (ptr
)));
3314 else if (sz
== 0 && Z
== 1)
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
)));
3321 else if (sz
== 1 && Z
== 0)
3323 TRACE_INSN (cpu
, "R%i = W[%s%s] (Z);", reg
, ptr_name
, post
);
3324 SET_DREG (reg
, GET_WORD (PREG (ptr
)));
3326 else if (sz
== 1 && Z
== 1)
3328 TRACE_INSN (cpu
, "R%i = W[%s%s] (X);", reg
, ptr_name
, post
);
3329 SET_DREG (reg
, (bs32
) (bs16
) GET_WORD (PREG (ptr
)));
3331 else if (sz
== 2 && Z
== 0)
3333 TRACE_INSN (cpu
, "R%i = B[%s%s] (Z);", reg
, ptr_name
, post
);
3334 SET_DREG (reg
, GET_BYTE (PREG (ptr
)));
3336 else if (sz
== 2 && Z
== 1)
3338 TRACE_INSN (cpu
, "R%i = B[%s%s] (X);", reg
, ptr_name
, post
);
3339 SET_DREG (reg
, (bs32
) (bs8
) GET_BYTE (PREG (ptr
)));
3342 illegal_instruction_or_combination (cpu
);
3346 if (sz
== 0 && Z
== 0)
3348 TRACE_INSN (cpu
, "[%s%s] = R%i;", ptr_name
, post
, reg
);
3349 PUT_LONG (PREG (ptr
), DREG (reg
));
3351 else if (sz
== 0 && Z
== 1)
3353 TRACE_INSN (cpu
, "[%s%s] = %s;", ptr_name
, post
, get_preg_name (reg
));
3354 PUT_LONG (PREG (ptr
), PREG (reg
));
3356 else if (sz
== 1 && Z
== 0)
3358 TRACE_INSN (cpu
, "W[%s%s] = R%i;", ptr_name
, post
, reg
);
3359 PUT_WORD (PREG (ptr
), DREG (reg
));
3361 else if (sz
== 2 && Z
== 0)
3363 TRACE_INSN (cpu
, "B[%s%s] = R%i;", ptr_name
, post
, reg
);
3364 PUT_BYTE (PREG (ptr
), DREG (reg
));
3367 illegal_instruction_or_combination (cpu
);
3371 SET_PREG (ptr
, PREG (ptr
) + (1 << (2 - sz
)));
3373 SET_PREG (ptr
, PREG (ptr
) - (1 << (2 - sz
)));
3377 decode_LDSTiiFP_0 (SIM_CPU
*cpu
, bu16 iw0
)
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
);
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
);
3399 if (PARALLEL_GROUP
== BFIN_PARALLEL_GROUP2
)
3400 illegal_instruction_or_combination (cpu
);
3404 TRACE_INSN (cpu
, "%s = [FP + %s];", reg_name
, imm_str
);
3405 reg_write (cpu
, grp
, reg
, GET_LONG (ea
));
3409 TRACE_INSN (cpu
, "[FP + %s] = %s;", imm_str
, reg_name
);
3410 PUT_LONG (ea
, reg_read (cpu
, grp
, reg
));
3415 decode_LDSTii_0 (SIM_CPU
*cpu
, bu16 iw0
)
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
);
3427 const char *imm_str
;
3428 const char *ptr_name
= get_preg_name (ptr
);
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
);
3434 if (op
== 0 || op
== 3)
3435 imm
= uimm4s4 (offset
), imm_str
= uimm4s4_str (offset
);
3437 imm
= uimm4s2 (offset
), imm_str
= uimm4s2_str (offset
);
3438 ea
= PREG (ptr
) + imm
;
3440 TRACE_DECODE (cpu
, "%s: uimm4s4/uimm4s2:%#x", __func__
, imm
);
3442 if (PARALLEL_GROUP
== BFIN_PARALLEL_GROUP2
)
3443 illegal_instruction_combination (cpu
);
3445 if (W
== 1 && op
== 2)
3446 illegal_instruction (cpu
);
3452 TRACE_INSN (cpu
, "R%i = [%s + %s];", reg
, ptr_name
, imm_str
);
3453 SET_DREG (reg
, GET_LONG (ea
));
3457 TRACE_INSN (cpu
, "R%i = W[%s + %s] (Z);", reg
, ptr_name
, imm_str
);
3458 SET_DREG (reg
, GET_WORD (ea
));
3462 TRACE_INSN (cpu
, "R%i = W[%s + %s] (X);", reg
, ptr_name
, imm_str
);
3463 SET_DREG (reg
, (bs32
) (bs16
) GET_WORD (ea
));
3467 TRACE_INSN (cpu
, "%s = [%s + %s];",
3468 get_preg_name (reg
), ptr_name
, imm_str
);
3469 SET_PREG (reg
, GET_LONG (ea
));
3476 TRACE_INSN (cpu
, "[%s + %s] = R%i;", ptr_name
, imm_str
, reg
);
3477 PUT_LONG (ea
, DREG (reg
));
3481 TRACE_INSN (cpu
, "W[%s + %s] = R%i;", ptr_name
, imm_str
, reg
);
3482 PUT_WORD (ea
, DREG (reg
));
3486 TRACE_INSN (cpu
, "[%s + %s] = %s;",
3487 ptr_name
, imm_str
, get_preg_name (reg
));
3488 PUT_LONG (ea
, PREG (reg
));
3494 decode_LoopSetup_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
, bu32 pc
)
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
);
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
);
3516 illegal_instruction (cpu
);
3518 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
3519 illegal_instruction_combination (cpu
);
3523 TRACE_INSN (cpu
, "LSETUP (%#x, %#x) LC%i;", spcrel
, epcrel
, c
);
3525 else if (rop
== 1 && reg
<= 7)
3527 TRACE_INSN (cpu
, "LSETUP (%#x, %#x) LC%i = %s;",
3528 spcrel
, epcrel
, c
, get_preg_name (reg
));
3529 SET_LCREG (c
, PREG (reg
));
3531 else if (rop
== 3 && reg
<= 7)
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);
3538 illegal_instruction (cpu
);
3540 SET_LTREG (c
, pc
+ spcrel
);
3541 SET_LBREG (c
, pc
+ epcrel
);
3545 decode_LDIMMhalf_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
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
);
3559 const char *val_str
;
3560 const char *reg_name
= get_allreg_name (grp
, reg
);
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
);
3566 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
3567 illegal_instruction_combination (cpu
);
3570 val
= imm16 (hword
), val_str
= imm16_str (hword
);
3572 val
= luimm16 (hword
), val_str
= luimm16_str (hword
);
3574 if (H
== 0 && S
== 1 && Z
== 0)
3576 TRACE_INSN (cpu
, "%s = %s (X);", reg_name
, val_str
);
3578 else if (H
== 0 && S
== 0 && Z
== 1)
3580 TRACE_INSN (cpu
, "%s = %s (Z);", reg_name
, val_str
);
3582 else if (H
== 0 && S
== 0 && Z
== 0)
3584 TRACE_INSN (cpu
, "%s.L = %s;", reg_name
, val_str
);
3585 val
= REG_H_L (reg_read (cpu
, grp
, reg
), val
);
3587 else if (H
== 1 && S
== 0 && Z
== 0)
3589 TRACE_INSN (cpu
, "%s.H = %s;", reg_name
, val_str
);
3590 val
= REG_H_L (val
<< 16, reg_read (cpu
, grp
, reg
));
3593 illegal_instruction (cpu
);
3595 reg_write (cpu
, grp
, reg
, val
);
3599 decode_CALLa_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
, bu32 pc
)
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
;
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
);
3616 TRACE_INSN (cpu
, "%s %#x;", S
? "CALL" : "JUMP.L", pcrel
);
3618 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
3619 illegal_instruction_combination (cpu
);
3623 BFIN_TRACE_BRANCH (cpu
, pc
, newpc
, -1, "CALL");
3624 SET_RETSREG (hwloop_get_next_pc (cpu
, pc
, 4));
3627 BFIN_TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP.L");
3630 BFIN_CPU_STATE
.did_jump
= true;
3631 PROFILE_BRANCH_TAKEN (cpu
);
3636 decode_LDSTidxI_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
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
);
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
);
3659 illegal_instruction (cpu
);
3663 if (sz
== 0 && Z
== 0)
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
));
3669 else if (sz
== 0 && Z
== 1)
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
));
3675 else if (sz
== 1 && Z
== 0)
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
));
3681 else if (sz
== 1 && Z
== 1)
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
));
3687 else if (sz
== 2 && Z
== 0)
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
));
3693 else if (sz
== 2 && Z
== 1)
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
));
3702 if (sz
!= 0 && Z
!= 0)
3703 illegal_instruction (cpu
);
3705 if (sz
== 0 && Z
== 0)
3707 TRACE_INSN (cpu
, "[%s + %s] = R%i;", ptr_name
,
3708 imm16s4_str (offset
), reg
);
3709 PUT_LONG (PREG (ptr
) + imm_16s4
, DREG (reg
));
3711 else if (sz
== 0 && Z
== 1)
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
));
3717 else if (sz
== 1 && Z
== 0)
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
));
3723 else if (sz
== 2 && Z
== 0)
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
));
3733 decode_linkage_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
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
);
3744 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_linkage
);
3745 TRACE_EXTRACT (cpu
, "%s: R:%i framesize:%#x", __func__
, R
, framesize
);
3749 int size
= uimm16s4 (framesize
);
3751 TRACE_INSN (cpu
, "LINK %s;", uimm16s4_str (framesize
));
3752 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
3753 illegal_instruction_combination (cpu
);
3755 PUT_LONG (sp
, RETSREG
);
3757 PUT_LONG (sp
, FPREG
);
3764 /* Restore SP from FP. */
3766 TRACE_INSN (cpu
, "UNLINK;");
3767 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
3768 illegal_instruction_combination (cpu
);
3769 SET_FPREG (GET_LONG (sp
));
3771 SET_RETSREG (GET_LONG (sp
));
3780 decode_dsp32mac_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
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
);
3803 bu32 res
= DREG (dst
);
3804 bu32 v_0
= 0, v_1
= 0, zero
= 0, n_1
= 0, n_0
= 0;
3806 static const char * const ops
[] = { "=", "+=", "-=" };
3807 char _buf
[128], *buf
= _buf
;
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
,
3816 if (w0
== 0 && w1
== 0 && op1
== 3 && op0
== 3)
3817 illegal_instruction (cpu
);
3819 if ((w1
|| w0
) && mmod
== M_W32
)
3820 illegal_instruction (cpu
);
3822 if (((1 << mmod
) & (P
? 0x131b : 0x1b5f)) == 0)
3823 illegal_instruction (cpu
);
3825 /* First handle MAC1 side. */
3826 if (w1
== 1 || op1
!= 3)
3828 bu32 res1
= decode_macfunc (cpu
, 1, op1
, h01
, h11
, src0
,
3829 src1
, mmod
, MM
, P
, &v_1
, &n_1
);
3832 buf
+= sprintf (buf
, P
? "R%i" : "R%i.H", dst
+ P
);
3836 buf
+= sprintf (buf
, " = A1");
3837 zero
= !!(res1
== 0);
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');
3847 buf
+= sprintf (buf
, ")");
3853 STORE (DREG (dst
+ 1), res1
);
3856 if (res1
& 0xffff0000)
3857 illegal_instruction (cpu
);
3858 res
= REG_H_L (res1
<< 16, res
);
3864 if (w0
== 1 || op0
!= 3)
3867 buf
+= sprintf (buf
, " (M)");
3869 buf
+= sprintf (buf
, ", ");
3873 /* Then handle MAC0 side. */
3874 if (w0
== 1 || op0
!= 3)
3876 bu32 res0
= decode_macfunc (cpu
, 0, op0
, h00
, h10
, src0
,
3877 src1
, mmod
, 0, P
, &v_0
, &n_0
);
3880 buf
+= sprintf (buf
, P
? "R%i" : "R%i.L", dst
);
3884 buf
+= sprintf (buf
, " = A0");
3885 zero
|= !!(res0
== 0);
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');
3895 buf
+= sprintf (buf
, ")");
3901 STORE (DREG (dst
), res0
);
3904 if (res0
& 0xffff0000)
3905 illegal_instruction (cpu
);
3906 res
= REG_H_L (res
, res0
);
3913 TRACE_INSN (cpu
, "%s%s;", _buf
, mac_optmode (mmod
, _MM
));
3915 if (!P
&& (w0
|| w1
))
3917 STORE (DREG (dst
), res
);
3918 SET_ASTATREG (v
, v_0
| v_1
);
3920 SET_ASTATREG (vs
, 1);
3924 SET_ASTATREG (v
, v_0
| v_1
);
3926 SET_ASTATREG (vs
, 1);
3929 if ((w0
== 1 && op0
== 3) || (w1
== 1 && op1
== 3))
3931 SET_ASTATREG (az
, zero
);
3932 if (!(w0
== 1 && op0
== 3))
3934 if (!(w1
== 1 && op1
== 3))
3936 SET_ASTATREG (an
, n_1
| n_0
);
3941 decode_dsp32mult_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
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
);
3964 bu32 res
= DREG (dst
);
3965 bu32 sat0
= 0, sat1
= 0, v_i0
= 0, v_i1
= 0;
3966 char _buf
[128], *buf
= _buf
;
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
,
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
);
3984 /* First handle MAC1 side. */
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
);
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');
3997 buf
+= sprintf (buf
, " (M)");
3999 buf
+= sprintf (buf
, ", ");
4003 STORE (DREG (dst
+ 1), res1
);
4006 if (res1
& 0xFFFF0000)
4007 illegal_instruction (cpu
);
4008 res
= REG_H_L (res1
<< 16, res
);
4012 /* First handle MAC0 side. */
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
);
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');
4024 STORE (DREG (dst
), res0
);
4027 if (res0
& 0xFFFF0000)
4028 illegal_instruction (cpu
);
4029 res
= REG_H_L (res
, res0
);
4033 TRACE_INSN (cpu
, "%s%s;", _buf
, mac_optmode (mmod
, _MM
));
4035 if (!P
&& (w0
|| w1
))
4036 STORE (DREG (dst
), res
);
4040 bu32 v
= sat0
| sat1
| v_i0
| v_i1
;
4042 STORE (ASTATREG (v
), v
);
4043 STORE (ASTATREG (v_copy
), v
);
4045 STORE (ASTATREG (vs
), v
);
4050 decode_dsp32alu_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
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
);
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
);
4073 if ((aop
== 0 || aop
== 2) && aopcde
== 9 && x
== 0 && s
== 0 && HL
== 0)
4076 TRACE_INSN (cpu
, "A%i.L = R%i.L;", a
, src0
);
4077 SET_AWREG (a
, REG_H_L (AWREG (a
), DREG (src0
)));
4079 else if ((aop
== 0 || aop
== 2) && aopcde
== 9 && x
== 0 && s
== 0 && HL
== 1)
4082 TRACE_INSN (cpu
, "A%i.H = R%i.H;", a
, src0
);
4083 SET_AWREG (a
, REG_H_L (DREG (src0
), AWREG (a
)));
4085 else if ((aop
== 1 || aop
== 0) && aopcde
== 5 && x
== 0 && s
== 0)
4087 bs32 val0
= DREG (src0
);
4088 bs32 val1
= DREG (src1
);
4091 bs32 ovX
, sBit1
, sBit2
, sBitRes1
, sBitRes2
;
4093 TRACE_INSN (cpu
, "R%i.%s = R%i %s R%i (RND12)", dst0
, HL
? "L" : "H",
4094 src0
, aop
& 0x1 ? "-" : "+", src1
);
4096 /* If subtract, just invert and add one. */
4099 if (val1
== 0x80000000)
4105 /* Get the sign bits, since we need them later. */
4106 sBit1
= !!(val0
& 0x80000000);
4107 sBit2
= !!(val1
& 0x80000000);
4111 sBitRes1
= !!(res
& 0x80000000);
4112 /* Round to the 12th bit. */
4114 sBitRes2
= !!(res
& 0x80000000);
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)))
4128 /* Both X1 and X2 Neg res is neg overflow. */
4131 /* Both X1 and X2 Pos res is pos overflow. */
4132 else if (!sBit1
&& !sBit2
)
4134 /* Pos+Neg or Neg+Pos take the sign of the result. */
4144 /* Shift up now after overflow detection. */
4152 STORE (DREG (dst0
), REG_H_L (res
<< 16, DREG (dst0
)));
4154 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), res
));
4156 SET_ASTATREG (az
, res
== 0);
4157 SET_ASTATREG (an
, res
& 0x8000);
4158 SET_ASTATREG (v
, ovX
);
4160 SET_ASTATREG (vs
, ovX
);
4162 else if ((aop
== 2 || aop
== 3) && aopcde
== 5 && x
== 1 && s
== 0)
4164 bs32 val0
= DREG (src0
);
4165 bs32 val1
= DREG (src1
);
4168 TRACE_INSN (cpu
, "R%i.%s = R%i %s R%i (RND20)", dst0
, HL
? "L" : "H",
4169 src0
, aop
& 0x1 ? "-" : "+", src1
);
4171 /* If subtract, just invert and add one. */
4175 res
= (val0
>> 4) + (val1
>> 4) + (((val0
& 0xf) + (val1
& 0xf)) >> 4);
4177 /* Don't sign extend during the shift. */
4178 res
= ((bu32
)res
>> 16);
4180 /* Don't worry about overflows, since we are shifting right. */
4183 STORE (DREG (dst0
), REG_H_L (res
<< 16, DREG (dst0
)));
4185 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), res
));
4187 SET_ASTATREG (az
, res
== 0);
4188 SET_ASTATREG (an
, res
& 0x8000);
4189 SET_ASTATREG (v
, 0);
4191 else if ((aopcde
== 2 || aopcde
== 3) && x
== 0)
4193 bu32 s1
, s2
, val
, ac0_i
= 0, v_i
= 0;
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',
4210 val
= add16 (cpu
, s1
, s2
, &ac0_i
, &v_i
, 0, 0, s
, 0);
4212 val
= sub16 (cpu
, s1
, s2
, &ac0_i
, &v_i
, 0, 0, s
, 0);
4214 SET_ASTATREG (ac0
, ac0_i
);
4215 SET_ASTATREG (v
, v_i
);
4217 SET_ASTATREG (vs
, v_i
);
4220 SET_DREG_H (dst0
, val
<< 16);
4222 SET_DREG_L (dst0
, val
);
4224 SET_ASTATREG (an
, val
& 0x8000);
4225 SET_ASTATREG (az
, val
== 0);
4227 else if ((aop
== 0 || aop
== 2) && aopcde
== 9 && x
== 0 && s
== 1 && HL
== 0)
4230 TRACE_INSN (cpu
, "A%i = R%i;", a
, src0
);
4231 SET_AREG32 (a
, DREG (src0
));
4233 else if ((aop
== 1 || aop
== 3) && aopcde
== 9 && x
== 0 && s
== 0 && HL
== 0)
4236 TRACE_INSN (cpu
, "A%i.X = R%i.L;", a
, src0
);
4237 SET_AXREG (a
, (bs8
)DREG (src0
));
4239 else if (aop
== 3 && aopcde
== 11 && x
== 0 && HL
== 0)
4241 bu64 acc0
= get_extended_acc (cpu
, 0);
4242 bu64 acc1
= get_extended_acc (cpu
, 1);
4243 bu32 carry
= (bu40
)acc1
< (bu40
)acc0
;
4246 TRACE_INSN (cpu
, "A0 -= A1%s;", s
? " (W32)" : "");
4249 if ((bs64
)acc0
< -0x8000000000ll
)
4250 acc0
= -0x8000000000ull
, sat
= 1;
4251 else if ((bs64
)acc0
>= 0x7fffffffffll
)
4252 acc0
= 0x7fffffffffull
, sat
= 1;
4256 /* A0 -= A1 (W32) */
4257 if (acc0
& (bu64
)0x8000000000ll
)
4258 acc0
&= 0x80ffffffffll
, sat
= 1;
4260 acc0
&= 0xffffffffll
;
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
);
4270 STORE (ASTATREG (av0s
), sat
);
4272 else if ((aop
== 0 || aop
== 1) && aopcde
== 22 && x
== 0)
4274 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4276 const char * const opts
[] = { "rndl", "rndh", "tl", "th" };
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)],
4282 if ((src1
!= 0 && src1
!= 2) || (src0
!= 0 && src0
!= 2))
4283 illegal_instruction (cpu
);
4286 s0H
= DREG (src0
+ 1);
4288 s1H
= DREG (src1
+ 1);
4291 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4292 s1
= algn (s1H
, s1L
, IREG (0) & 3);
4296 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4297 s1
= algn (s1L
, s1H
, IREG (0) & 3);
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)));
4307 /* Implicit DISALGNEXCPT in parallel. */
4310 else if ((aop
== 0 || aop
== 1) && aopcde
== 8 && x
== 0 && s
== 0 && HL
== 0)
4312 TRACE_INSN (cpu
, "A%i = 0;", aop
);
4315 else if (aop
== 2 && aopcde
== 8 && x
== 0 && s
== 0 && HL
== 0)
4317 TRACE_INSN (cpu
, "A1 = A0 = 0;");
4321 else if ((aop
== 0 || aop
== 1 || aop
== 2) && s
== 1 && aopcde
== 8
4322 && x
== 0 && HL
== 0)
4324 bs40 acc0
= get_extended_acc (cpu
, 0);
4325 bs40 acc1
= get_extended_acc (cpu
, 1);
4328 if (aop
== 0 || aop
== 1)
4329 TRACE_INSN (cpu
, "A%i = A%i (S);", aop
, aop
);
4331 TRACE_INSN (cpu
, "A1 = A1 (S), A0 = A0 (S);");
4333 if (aop
== 0 || aop
== 2)
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
);
4342 SET_ASTATREG (av0s
, sat
);
4347 if (aop
== 1 || aop
== 2)
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
);
4356 SET_ASTATREG (av1s
, sat
);
4361 SET_ASTATREG (az
, (acc0
== 0) || (acc1
== 0));
4362 SET_ASTATREG (an
, ((acc0
>> 31) & 1) || ((acc1
>> 31) & 1));
4364 else if (aop
== 3 && aopcde
== 8 && x
== 0 && HL
== 0)
4366 TRACE_INSN (cpu
, "A%i = A%i;", s
, !s
);
4367 SET_AXREG (s
, AXREG (!s
));
4368 SET_AWREG (s
, AWREG (!s
));
4370 else if (aop
== 3 && HL
== 0 && aopcde
== 16 && x
== 0 && s
== 0)
4375 TRACE_INSN (cpu
, "A1 = ABS A1 , A0 = ABS A0;");
4378 for (i
= 0; i
< 2; ++i
)
4381 bs40 acc
= get_extended_acc (cpu
, i
);
4385 av
= acc
== ((bs40
)1 << 39);
4387 acc
= ((bs40
)1 << 39) - 1;
4390 SET_ASTATREG (av
[i
], av
);
4392 SET_ASTATREG (avs
[i
], av
);
4395 SET_ASTATREG (az
, az
);
4396 SET_ASTATREG (an
, 0);
4398 else if (aop
== 0 && aopcde
== 23 && x
== 0)
4400 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
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",
4407 if ((src1
!= 0 && src1
!= 2) || (src0
!= 0 && src0
!= 2))
4408 illegal_instruction (cpu
);
4411 s0H
= DREG (src0
+ 1);
4413 s1H
= DREG (src1
+ 1);
4416 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4417 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4421 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4422 s1
= algn (s1L
, s1H
, IREG (1) & 3);
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
))));
4430 /* Implicit DISALGNEXCPT in parallel. */
4433 else if ((aop
== 0 || aop
== 1) && aopcde
== 16 && x
== 0 && s
== 0)
4438 TRACE_INSN (cpu
, "A%i = ABS A%i;", HL
, aop
);
4440 acc
= get_extended_acc (cpu
, aop
);
4443 av
= acc
== ((bs40
)1 << 39);
4445 acc
= ((bs40
)1 << 39) - 1;
4448 SET_ASTATREG (av
[HL
], av
);
4450 SET_ASTATREG (avs
[HL
], av
);
4451 SET_ASTATREG (az
, acc
== 0);
4452 SET_ASTATREG (an
, 0);
4454 else if (aop
== 3 && aopcde
== 12 && x
== 0 && s
== 0)
4456 bs32 res
= DREG (src0
);
4458 bool sBit_a
, sBit_b
;
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
);
4464 sBit_b
= !!(res
& 0x80000000);
4467 sBit_a
= !!(res
& 0x80000000);
4469 /* Overflow if the sign bit changed when we rounded. */
4470 if ((res
>> 16) && (sBit_b
!= sBit_a
))
4485 SET_DREG (dst0
, REG_H_L (DREG (dst0
), res
));
4487 SET_DREG (dst0
, REG_H_L (res
<< 16, DREG (dst0
)));
4489 SET_ASTATREG (az
, res
== 0);
4490 SET_ASTATREG (an
, res
< 0);
4491 SET_ASTATREG (v
, ovX
);
4493 SET_ASTATREG (vs
, ovX
);
4495 else if (aop
== 3 && HL
== 0 && aopcde
== 15 && x
== 0 && s
== 0)
4497 bu32 hi
= (-(bs16
)(DREG (src0
) >> 16)) << 16;
4498 bu32 lo
= (-(bs16
)(DREG (src0
) & 0xFFFF)) & 0xFFFF;
4501 TRACE_INSN (cpu
, "R%i = -R%i (V);", dst0
, src0
);
4505 if (hi
== 0x80000000)
4521 SET_DREG (dst0
, hi
| lo
);
4523 SET_ASTATREG (v
, v
);
4525 SET_ASTATREG (vs
, 1);
4526 SET_ASTATREG (ac0
, ac0
);
4527 SET_ASTATREG (ac1
, ac1
);
4528 setflags_nz_2x16 (cpu
, DREG (dst0
));
4530 else if (aop
== 3 && HL
== 0 && aopcde
== 14 && x
== 0 && s
== 0)
4532 TRACE_INSN (cpu
, "A1 = - A1 , A0 = - A0;");
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 ? */
4538 else if ((aop
== 0 || aop
== 1) && aopcde
== 14 && x
== 0 && s
== 0)
4540 bs40 src_acc
= get_extended_acc (cpu
, aop
);
4543 TRACE_INSN (cpu
, "A%i = - A%i;", HL
, aop
);
4545 SET_AREG (HL
, saturate_s40_astat (-src_acc
, &v
));
4547 SET_ASTATREG (az
, AWREG (HL
) == 0 && AXREG (HL
) == 0);
4548 SET_ASTATREG (an
, AXREG (HL
) >> 7);
4551 SET_ASTATREG (ac0
, !src_acc
);
4552 SET_ASTATREG (av0
, v
);
4554 SET_ASTATREG (av0s
, 1);
4558 SET_ASTATREG (ac1
, !src_acc
);
4559 SET_ASTATREG (av1
, v
);
4561 SET_ASTATREG (av1s
, 1);
4564 else if (aop
== 0 && aopcde
== 12 && x
== 0 && s
== 0 && HL
== 0)
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
);
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
);
4574 if ((tmp0_hi
>> 15) & 1)
4575 tmp1_hi
= ~tmp1_hi
+ 1;
4577 if ((tmp0_lo
>> 15) & 1)
4578 tmp1_lo
= ~tmp1_lo
+ 1;
4580 tmp1_hi
= tmp1_hi
+ tmp1_lo
;
4582 STORE (DREG (dst0
), REG_H_L (tmp1_hi
<< 16, tmp1_hi
));
4584 else if (aopcde
== 0 && HL
== 0)
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;
4593 bu32 ac1_i
= 0, ac0_i
= 0, v_i
= 0, z_i
= 0, n_i
= 0;
4595 TRACE_INSN (cpu
, "R%i = R%i %c|%c R%i%s;", dst0
, src0
,
4596 (aop
& 2) ? '-' : '+', (aop
& 1) ? '-' : '+', src1
,
4599 t0
= sub16 (cpu
, s0h
, s1h
, &ac1_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4601 t0
= add16 (cpu
, s0h
, s1h
, &ac1_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4604 t1
= sub16 (cpu
, s0l
, s1l
, &ac0_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4606 t1
= add16 (cpu
, s0l
, s1l
, &ac0_i
, &v_i
, &z_i
, &n_i
, s
, 0);
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
);
4614 SET_ASTATREG (vs
, v_i
);
4619 SET_DREG (dst0
, (t1
<< 16) | t0
);
4621 SET_DREG (dst0
, (t0
<< 16) | t1
);
4623 else if (aop
== 1 && aopcde
== 12 && x
== 0 && s
== 0 && HL
== 0)
4625 bs32 val0
= (bs16
)(AWREG (0) >> 16) + (bs16
)AWREG (0);
4626 bs32 val1
= (bs16
)(AWREG (1) >> 16) + (bs16
)AWREG (1);
4628 TRACE_INSN (cpu
, "R%i = A1.L + A1.H, R%i = A0.L + A0.H;", dst1
, dst0
);
4631 illegal_instruction_combination (cpu
);
4633 SET_DREG (dst0
, val0
);
4634 SET_DREG (dst1
, val1
);
4636 else if ((aop
== 0 || aop
== 2 || aop
== 3) && aopcde
== 1)
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;
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
));
4652 illegal_instruction_combination (cpu
);
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
;
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;
4663 d0
= (x0
<< 16) | x1
;
4665 d0
= (x1
<< 16) | x0
;
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
;
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;
4676 d0
= (x0
<< 16) | x1
;
4678 d0
= (x1
<< 16) | x0
;
4680 SET_ASTATREG (az
, z_i
);
4681 SET_ASTATREG (an
, n_i
);
4682 SET_ASTATREG (v
, v_i
);
4684 SET_ASTATREG (vs
, v_i
);
4686 STORE (DREG (dst0
), d0
);
4687 STORE (DREG (dst1
), d1
);
4689 else if ((aop
== 0 || aop
== 1 || aop
== 2) && aopcde
== 11 && x
== 0)
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
);
4698 if (s
!= 0 || HL
!= 0)
4699 illegal_instruction (cpu
);
4700 TRACE_INSN (cpu
, "R%i = (A0 += A1);", dst0
);
4705 illegal_instruction (cpu
);
4706 TRACE_INSN (cpu
, "R%i.%c = (A0 += A1);", dst0
, HL
? 'H' : 'L');
4711 illegal_instruction (cpu
);
4712 TRACE_INSN (cpu
, "A0 += A1%s;", s
? " (W32)" : "");
4716 acc0
= saturate_s40_astat (acc0
, &v
);
4718 if (aop
== 2 && s
== 1) /* A0 += A1 (W32) */
4720 if (acc0
& (bs40
)0x8000000000ll
)
4721 acc0
&= 0x80ffffffffll
;
4723 acc0
&= 0xffffffffll
;
4726 STORE (AXREG (0), acc0
>> 32);
4727 STORE (AWREG (0), acc0
);
4728 SET_ASTATREG (av0
, v
&& acc1
);
4730 SET_ASTATREG (av0s
, v
);
4732 if (aop
== 0 || aop
== 1)
4734 if (aop
) /* Dregs_lo = A0 += A1 */
4736 dreg
= saturate_s32 (rnd16 (acc0
) << 16, &sat
);
4738 STORE (DREG (dst0
), REG_H_L (dreg
, DREG (dst0
)));
4740 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), dreg
>> 16));
4742 else /* Dregs = A0 += A1 */
4744 dreg
= saturate_s32 (acc0
, &sat
);
4745 STORE (DREG (dst0
), dreg
);
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
);
4755 STORE (ASTATREG (vs
), sat
);
4759 STORE (ASTATREG (az
), acc0
== 0);
4760 STORE (ASTATREG (an
), !!(acc0
& 0x8000000000ull
));
4761 STORE (ASTATREG (ac0
), carry
);
4762 STORE (ASTATREG (ac0_copy
), carry
);
4765 else if ((aop
== 0 || aop
== 1) && aopcde
== 10 && x
== 0 && s
== 0 && HL
== 0)
4767 TRACE_INSN (cpu
, "R%i.L = A%i.X;", dst0
, aop
);
4768 SET_DREG_L (dst0
, (bs8
)AXREG (aop
));
4770 else if (aop
== 0 && aopcde
== 4 && x
== 0 && HL
== 0)
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
));
4775 else if (aop
== 1 && aopcde
== 4 && x
== 0 && HL
== 0)
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));
4780 else if (aop
== 2 && aopcde
== 4 && x
== 0 && HL
== 0)
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
));
4786 illegal_instruction_combination (cpu
);
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));
4791 else if ((aop
== 0 || aop
== 1) && aopcde
== 17 && x
== 0 && HL
== 0)
4793 bs40 acc0
= get_extended_acc (cpu
, 0);
4794 bs40 acc1
= get_extended_acc (cpu
, 1);
4795 bs40 val0
, val1
, sval0
, sval1
;
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
,
4807 illegal_instruction_combination (cpu
);
4815 sval0
= saturate_s32 (val0
, &sat
);
4817 sval1
= saturate_s32 (val1
, &sat
);
4825 STORE (DREG (dst0
), val0
);
4826 STORE (DREG (dst1
), val1
);
4827 SET_ASTATREG (v
, 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
);
4834 SET_ASTATREG (ac0
, !!((bu40
)acc1
<= (bu40
)acc0
));
4836 SET_ASTATREG (ac0
, !!((bu40
)acc0
<= (bu40
)acc1
));
4838 else if (aop
== 0 && aopcde
== 18 && x
== 0 && HL
== 0)
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);
4847 bs16 tmp0
, tmp1
, tmp2
, tmp3
;
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
);
4853 TRACE_INSN (cpu
, "SAA (R%i:%i, R%i:%i)%s", src0
+ 1, src0
,
4854 src1
+ 1, src1
, s
? " (R)" :"");
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. */
4862 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4863 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4867 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4868 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4871 /* Find the absolute difference between pairs, make it
4872 absolute, then add it to the existing accumulator half. */
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);
4879 tmp0
= (tmp0
< 0) ? -tmp0
: tmp0
;
4880 tmp1
= (tmp1
< 0) ? -tmp1
: tmp1
;
4881 tmp2
= (tmp2
< 0) ? -tmp2
: tmp2
;
4882 tmp3
= (tmp3
< 0) ? -tmp3
: tmp3
;
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);
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);
4894 /* Implicit DISALGNEXCPT in parallel. */
4897 else if (aop
== 3 && aopcde
== 18 && x
== 0 && s
== 0 && HL
== 0)
4899 TRACE_INSN (cpu
, "DISALGNEXCPT");
4902 else if ((aop
== 0 || aop
== 1) && aopcde
== 20 && x
== 0 && HL
== 0)
4904 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4905 const char * const opts
[] = { "", " (R)", " (T)", " (T, R)" };
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)]);
4910 if ((src1
!= 0 && src1
!= 2) || (src0
!= 0 && src0
!= 2))
4911 illegal_instruction (cpu
);
4914 s0H
= DREG (src0
+ 1);
4916 s1H
= DREG (src1
+ 1);
4919 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4920 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4924 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4925 s1
= algn (s1L
, s1H
, IREG (1) & 3);
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));
4934 /* Implicit DISALGNEXCPT in parallel. */
4937 else if (aop
== 0 && aopcde
== 21 && x
== 0 && HL
== 0)
4939 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
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)" : "");
4944 if ((src1
!= 0 && src1
!= 2) || (src0
!= 0 && src0
!= 2))
4945 illegal_instruction (cpu
);
4948 illegal_instruction_combination (cpu
);
4951 s0H
= DREG (src0
+ 1);
4953 s1H
= DREG (src1
+ 1);
4956 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4957 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4961 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4962 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4966 ((((s0
>> 0) & 0xff) + ((s1
>> 0) & 0xff)) << 0) |
4967 ((((s0
>> 8) & 0xff) + ((s1
>> 8) & 0xff)) << 16));
4969 ((((s0
>> 16) & 0xff) + ((s1
>> 16) & 0xff)) << 0) |
4970 ((((s0
>> 24) & 0xff) + ((s1
>> 24) & 0xff)) << 16));
4972 /* Implicit DISALGNEXCPT in parallel. */
4975 else if (aop
== 1 && aopcde
== 21 && x
== 0 && HL
== 0)
4977 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
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)" : "");
4982 if ((src1
!= 0 && src1
!= 2) || (src0
!= 0 && src0
!= 2))
4983 illegal_instruction (cpu
);
4986 illegal_instruction_combination (cpu
);
4989 s0H
= DREG (src0
+ 1);
4991 s1H
= DREG (src1
+ 1);
4994 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4995 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4999 s0
= algn (s0L
, s0H
, IREG (0) & 3);
5000 s1
= algn (s1L
, s1H
, IREG (1) & 3);
5004 (((((s0
>> 0) & 0xff) - ((s1
>> 0) & 0xff)) << 0) & 0xffff) |
5005 (((((s0
>> 8) & 0xff) - ((s1
>> 8) & 0xff)) << 16)));
5007 (((((s0
>> 16) & 0xff) - ((s1
>> 16) & 0xff)) << 0) & 0xffff) |
5008 (((((s0
>> 24) & 0xff) - ((s1
>> 24) & 0xff)) << 16)));
5010 /* Implicit DISALGNEXCPT in parallel. */
5013 else if (aop
== 1 && aopcde
== 7 && x
== 0 && s
== 0 && HL
== 0)
5015 TRACE_INSN (cpu
, "R%i = MIN (R%i, R%i);", dst0
, src0
, src1
);
5016 SET_DREG (dst0
, min32 (cpu
, DREG (src0
), DREG (src1
)));
5018 else if (aop
== 0 && aopcde
== 7 && x
== 0 && s
== 0 && HL
== 0)
5020 TRACE_INSN (cpu
, "R%i = MAX (R%i, R%i);", dst0
, src0
, src1
);
5021 SET_DREG (dst0
, max32 (cpu
, DREG (src0
), DREG (src1
)));
5023 else if (aop
== 2 && aopcde
== 7 && x
== 0 && s
== 0 && HL
== 0)
5025 bu32 val
= DREG (src0
);
5028 TRACE_INSN (cpu
, "R%i = ABS R%i;", dst0
, src0
);
5032 v
= (val
== 0x80000000);
5035 SET_DREG (dst0
, val
);
5037 SET_ASTATREG (v
, v
);
5039 SET_ASTATREG (vs
, 1);
5040 setflags_nz (cpu
, val
);
5042 else if (aop
== 3 && aopcde
== 7 && x
== 0 && HL
== 0)
5044 bu32 val
= DREG (src0
);
5046 TRACE_INSN (cpu
, "R%i = - R%i%s;", dst0
, src0
, amod1 (s
, 0));
5048 if (s
&& val
== 0x80000000)
5051 SET_ASTATREG (v
, 1);
5052 SET_ASTATREG (vs
, 1);
5054 else if (val
== 0x80000000)
5058 SET_DREG (dst0
, val
);
5060 SET_ASTATREG (az
, val
== 0);
5061 SET_ASTATREG (an
, val
& 0x80000000);
5063 else if (aop
== 2 && aopcde
== 6 && x
== 0 && s
== 0 && HL
== 0)
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;
5070 TRACE_INSN (cpu
, "R%i = ABS R%i (V);", dst0
, src0
);
5073 if (hi
== 0x80000000)
5083 SET_DREG (dst0
, hi
| lo
);
5085 SET_ASTATREG (v
, v
);
5087 SET_ASTATREG (vs
, 1);
5088 setflags_nz_2x16 (cpu
, DREG (dst0
));
5090 else if (aop
== 1 && aopcde
== 6 && x
== 0 && s
== 0 && HL
== 0)
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
)));
5095 else if (aop
== 0 && aopcde
== 6 && x
== 0 && s
== 0 && HL
== 0)
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
)));
5100 else if (aop
== 0 && aopcde
== 24 && x
== 0 && s
== 0 && HL
== 0)
5102 TRACE_INSN (cpu
, "R%i = BYTEPACK (R%i, R%i);", dst0
, src0
, src1
);
5104 (((DREG (src0
) >> 0) & 0xff) << 0) |
5105 (((DREG (src0
) >> 16) & 0xff) << 8) |
5106 (((DREG (src1
) >> 0) & 0xff) << 16) |
5107 (((DREG (src1
) >> 16) & 0xff) << 24));
5109 /* Implicit DISALGNEXCPT in parallel. */
5112 else if (aop
== 1 && aopcde
== 24 && x
== 0 && HL
== 0)
5116 bu8 bytea
, byteb
, bytec
, byted
;
5118 TRACE_INSN (cpu
, "(R%i, R%i) = BYTEUNPACK R%i:%i%s;",
5119 dst1
, dst0
, src0
+ 1, src0
, s
? " (R)" : "");
5121 if ((src1
!= 0 && src1
!= 2) || (src0
!= 0 && src0
!= 2))
5122 illegal_instruction (cpu
);
5125 illegal_instruction_combination (cpu
);
5127 order
= IREG (0) & 0x3;
5129 hi
= src0
, lo
= src0
+ 1;
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));
5140 /* Implicit DISALGNEXCPT in parallel. */
5143 else if (aopcde
== 13 && HL
== 0 && x
== 0 && s
== 0)
5145 const char *searchmodes
[] = { "GT", "GE", "LT", "LE" };
5147 bs16 a0_lo
, a1_lo
, src_hi
, src_lo
;
5149 TRACE_INSN (cpu
, "(R%i, R%i) = SEARCH R%i (%s);",
5150 dst1
, dst0
, src0
, searchmodes
[aop
]);
5152 /* XXX: The parallel version is a bit weird in its limits:
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
5162 Unfortunately, our parallel insn state doesn't (currently) track enough
5163 details to be able to check this. */
5166 illegal_instruction_combination (cpu
);
5168 up_hi
= up_lo
= false;
5171 src_lo
= DREG (src0
);
5172 src_hi
= DREG (src0
) >> 16;
5177 up_hi
= (src_hi
> a1_lo
);
5178 up_lo
= (src_lo
> a0_lo
);
5181 up_hi
= (src_hi
>= a1_lo
);
5182 up_lo
= (src_lo
>= a0_lo
);
5185 up_hi
= (src_hi
< a1_lo
);
5186 up_lo
= (src_lo
< a0_lo
);
5189 up_hi
= (src_hi
<= a1_lo
);
5190 up_lo
= (src_lo
<= a0_lo
);
5196 SET_AREG (1, src_hi
);
5197 SET_DREG (dst1
, PREG (0));
5200 SET_AREG (1, a1_lo
);
5204 SET_AREG (0, src_lo
);
5205 SET_DREG (dst0
, PREG (0));
5208 SET_AREG (0, a0_lo
);
5211 illegal_instruction (cpu
);
5215 decode_dsp32shift_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
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
);
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
);
5234 if ((sop
== 0 || sop
== 1) && sopcde
== 0)
5237 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
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)" : "");
5245 val
= (bu16
)(DREG (src1
) & 0xFFFF);
5247 val
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5249 /* Positive shift magnitudes produce Logical Left shifts.
5250 Negative shift magnitudes produce Arithmetic Right shifts. */
5252 val
= ashiftrt (cpu
, val
, -shft
, 16);
5255 int sgn
= (val
>> 15) & 0x1;
5257 val
= lshift (cpu
, val
, shft
, 16, sop
== 1, 1);
5258 if (((val
>> 15) & 0x1) != sgn
)
5260 SET_ASTATREG (v
, 1);
5261 SET_ASTATREG (vs
, 1);
5266 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), val
));
5268 STORE (DREG (dst0
), REG_H_L (val
<< 16, DREG (dst0
)));
5270 else if (sop
== 2 && sopcde
== 0)
5272 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
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
);
5280 val
= (bu16
)(DREG (src1
) & 0xFFFF);
5282 val
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5285 val
= val
>> (-1 * shft
);
5290 SET_DREG (dst0
, REG_H_L (DREG (dst0
), val
));
5292 SET_DREG (dst0
, REG_H_L (val
<< 16, DREG (dst0
)));
5294 SET_ASTATREG (az
, !((val
& 0xFFFF0000) == 0) || ((val
& 0xFFFF) == 0));
5295 SET_ASTATREG (an
, (!!(val
& 0x80000000)) ^ (!!(val
& 0x8000)));
5296 SET_ASTATREG (v
, 0);
5298 else if (sop
== 2 && sopcde
== 3 && (HLs
== 1 || HLs
== 0))
5300 int shift
= imm6 (DREG (src0
) & 0xFFFF);
5302 bu40 acc
= get_unextended_acc (cpu
, HLs
);
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
);
5307 acc
= rot40 (acc
, shift
, &cc
);
5308 SET_AREG (HLs
, acc
);
5312 else if (sop
== 0 && sopcde
== 3 && (HLs
== 0 || HLs
== 1))
5314 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5315 bu64 acc
= get_extended_acc (cpu
, 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
);
5323 val
= ashiftrt (cpu
, acc
, -shft
, 40);
5325 val
= lshift (cpu
, acc
, shft
, 40, 0, 0);
5327 STORE (AXREG (HLs
), (val
>> 32) & 0xff);
5328 STORE (AWREG (HLs
), (val
& 0xffffffff));
5329 STORE (ASTATREG (av
[HLs
]), 0);
5331 else if (sop
== 1 && sopcde
== 3 && (HLs
== 0 || HLs
== 1))
5333 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5334 bu64 acc
= get_unextended_acc (cpu
, 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
);
5342 val
= lshiftrt (cpu
, acc
, -shft
, 40);
5344 val
= lshift (cpu
, acc
, shft
, 40, 0, 0);
5346 STORE (AXREG (HLs
), (val
>> 32) & 0xff);
5347 STORE (AWREG (HLs
), (val
& 0xffffffff));
5348 STORE (ASTATREG (av
[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)
5355 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5359 TRACE_INSN (cpu
, "R%i = ASHIFT R%i BY R%i.L (V%s);",
5360 dst0
, src1
, src0
, sop
== 1 ? ",S" : "");
5362 val0
= (bu16
)DREG (src1
) & 0xFFFF;
5363 val1
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5367 val0
= ashiftrt (cpu
, val0
, -shft
, 16);
5369 val1
= ashiftrt (cpu
, val1
, -shft
, 16);
5373 int sgn0
= (val0
>> 15) & 0x1;
5374 int sgn1
= (val1
>> 15) & 0x1;
5376 val0
= lshift (cpu
, val0
, shft
, 16, sop
== 1, 1);
5378 val1
= lshift (cpu
, val1
, shft
, 16, sop
== 1, 1);
5380 if ((sgn0
!= ((val0
>> 15) & 0x1)) || (sgn1
!= ((val1
>> 15) & 0x1)))
5382 SET_ASTATREG (v
, 1);
5383 SET_ASTATREG (vs
, 1);
5386 SET_ASTAT (ASTAT
| astat
);
5387 STORE (DREG (dst0
), (val1
<< 16) | val0
);
5389 else if ((sop
== 0 || sop
== 1 || sop
== 2) && sopcde
== 2)
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;
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)" : "");
5404 STORE (DREG (dst0
), lshiftrt (cpu
, v
, -shft
, 32));
5406 STORE (DREG (dst0
), ashiftrt (cpu
, v
, -shft
, 32));
5410 bu32 val
= lshift (cpu
, v
, shft
, 32, sop
== 1, 1);
5412 STORE (DREG (dst0
), val
);
5413 if (((v
>> 31) & 0x1) != ((val
>> 31) & 0x1))
5415 SET_ASTATREG (v
, 1);
5416 SET_ASTATREG (vs
, 1);
5420 else if (sop
== 3 && sopcde
== 2)
5422 int shift
= imm6 (DREG (src0
) & 0xFFFF);
5423 bu32 src
= DREG (src1
);
5424 bu32 ret
, cc
= CCREG
;
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
);
5430 ret
= rot32 (src
, shift
, &cc
);
5431 STORE (DREG (dst0
), ret
);
5435 else if (sop
== 2 && sopcde
== 1 && HLs
== 0)
5437 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5441 TRACE_INSN (cpu
, "R%i = LSHIFT R%i BY R%i.L (V);", dst0
, src1
, src0
);
5443 val0
= (bu16
)DREG (src1
) & 0xFFFF;
5444 val1
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5448 val0
= lshiftrt (cpu
, val0
, -shft
, 16);
5450 val1
= lshiftrt (cpu
, val1
, -shft
, 16);
5454 val0
= lshift (cpu
, val0
, shft
, 16, 0, 0);
5456 val1
= lshift (cpu
, val1
, shft
, 16, 0, 0);
5458 SET_ASTAT (ASTAT
| astat
);
5459 STORE (DREG (dst0
), (val1
<< 16) | val0
);
5461 else if (sopcde
== 4)
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');
5472 STORE (DREG (dst0
), (sv1
<< 16) | (sv0
& 0xFFFF));
5474 else if (sop
== 0 && sopcde
== 5)
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));
5480 else if (sop
== 1 && sopcde
== 5)
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));
5486 else if (sop
== 2 && sopcde
== 5)
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));
5492 else if ((sop
== 0 || sop
== 1) && sopcde
== 6)
5494 bu64 acc
= AXREG (sop
);
5495 TRACE_INSN (cpu
, "R%i.L = SIGNBITS A%i;", dst0
, sop
);
5498 SET_DREG_L (dst0
, signbits (acc
, 40) & 0xFFFF);
5500 else if (sop
== 3 && sopcde
== 6)
5502 bu32 v
= ones (DREG (src1
));
5503 TRACE_INSN (cpu
, "R%i.L = ONES R%i;", dst0
, src1
);
5504 SET_DREG_L (dst0
, v
);
5506 else if (sop
== 0 && sopcde
== 7)
5508 bu16 sv1
= (bu16
)signbits (DREG (src1
), 32);
5509 bu16 sv0
= (bu16
)DREG (src0
);
5512 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i, R%i.L);", dst0
, src1
, src0
);
5514 if ((sv1
& 0x1f) < (sv0
& 0x1f))
5518 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), dst_lo
));
5520 else if (sop
== 1 && sopcde
== 7)
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
;
5529 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i, R%i.L) (V);", dst0
, src1
, src0
);
5531 tmp_hi
= signbits (src1_hi
, 16);
5532 tmp_lo
= signbits (src1_lo
, 16);
5534 if ((tmp_hi
& 0xf) < (tmp_lo
& 0xf))
5535 if ((tmp_hi
& 0xf) < (src0_lo
& 0xf))
5540 if ((tmp_lo
& 0xf) < (src0_lo
& 0xf))
5544 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), tmp
));
5546 else if (sop
== 2 && sopcde
== 7)
5548 /* Exponent adjust on single 16-bit register. */
5550 bu16 src0_lo
= (bu16
)(DREG (src0
) & 0xFFFF);
5552 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i.L, R%i.L);", dst0
, src1
, src0
);
5554 tmp
= signbits (DREG (src1
) & 0xFFFF, 16);
5556 if ((tmp
& 0xf) < (src0_lo
& 0xf))
5557 SET_DREG_L (dst0
, tmp
);
5559 SET_DREG_L (dst0
, src0_lo
);
5561 else if (sop
== 3 && sopcde
== 7)
5564 bu16 src0_lo
= (bu16
)(DREG (src0
) & 0xFFFF);
5566 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i.H, R%i.L);", dst0
, src1
, src0
);
5568 tmp
= signbits ((DREG (src1
) & 0xFFFF0000) >> 16, 16);
5570 if ((tmp
& 0xf) < (src0_lo
& 0xf))
5571 SET_DREG_L (dst0
, tmp
);
5573 SET_DREG_L (dst0
, src0_lo
);
5575 else if (sop
== 0 && sopcde
== 8)
5577 bu64 acc
= get_unextended_acc (cpu
, 0);
5580 TRACE_INSN (cpu
, "BITMUX (R%i, R%i, A0) (ASR);", src0
, src1
);
5583 illegal_instruction_combination (cpu
);
5588 (((bu64
)s0
& 1) << 38) |
5589 (((bu64
)s1
& 1) << 39);
5590 STORE (DREG (src0
), s0
>> 1);
5591 STORE (DREG (src1
), s1
>> 1);
5595 else if (sop
== 1 && sopcde
== 8)
5597 bu64 acc
= get_unextended_acc (cpu
, 0);
5600 TRACE_INSN (cpu
, "BITMUX (R%i, R%i, A0) (ASL);", src0
, src1
);
5603 illegal_instruction_combination (cpu
);
5610 STORE (DREG (src0
), s0
<< 1);
5611 STORE (DREG (src1
), s1
<< 1);
5615 else if ((sop
== 0 || sop
== 1) && sopcde
== 9)
5617 bs40 acc0
= get_unextended_acc (cpu
, 0);
5620 TRACE_INSN (cpu
, "R%i.L = VIT_MAX (R%i) (AS%c);",
5621 dst0
, src1
, sop
& 1 ? 'R' : 'L');
5624 sH
= DREG (src1
) >> 16;
5627 acc0
= (acc0
& 0xfeffffffffull
) >> 1;
5631 if (((sH
- sL
) & 0x8000) == 0)
5634 acc0
|= (sop
& 1) ? 0x80000000 : 1;
5640 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), out
));
5642 else if ((sop
== 2 || sop
== 3) && sopcde
== 9)
5644 bs40 acc0
= get_extended_acc (cpu
, 0);
5645 bs16 s0L
, s0H
, s1L
, s1H
, out0
, out1
;
5647 TRACE_INSN (cpu
, "R%i = VIT_MAX (R%i, R%i) (AS%c);",
5648 dst0
, src1
, src0
, sop
& 1 ? 'R' : 'L');
5651 s0H
= DREG (src0
) >> 16;
5653 s1H
= DREG (src1
) >> 16;
5660 if (((s0H
- s0L
) & 0x8000) == 0)
5663 acc0
|= (sop
& 1) ? 0x40000000 : 2;
5668 if (((s1H
- s1L
) & 0x8000) == 0)
5671 acc0
|= (sop
& 1) ? 0x80000000 : 1;
5677 STORE (DREG (dst0
), REG_H_L (out1
<< 16, out0
));
5679 else if (sop
== 0 && sopcde
== 10)
5681 bu32 v
= DREG (src0
);
5682 bu32 x
= DREG (src1
);
5683 bu32 mask
= (1 << (v
& 0x1f)) - 1;
5685 TRACE_INSN (cpu
, "R%i = EXTRACT (R%i, R%i.L) (Z);", dst0
, src1
, src0
);
5687 x
>>= ((v
>> 8) & 0x1f);
5689 STORE (DREG (dst0
), x
);
5690 setflags_logical (cpu
, x
);
5692 else if (sop
== 1 && sopcde
== 10)
5694 bu32 v
= DREG (src0
);
5695 bu32 x
= DREG (src1
);
5696 bu32 sgn
= (1 << (v
& 0x1f)) >> 1;
5697 bu32 mask
= (1 << (v
& 0x1f)) - 1;
5699 TRACE_INSN (cpu
, "R%i = EXTRACT (R%i, R%i.L) (X);", dst0
, src1
, src0
);
5701 x
>>= ((v
>> 8) & 0x1f);
5705 STORE (DREG (dst0
), x
);
5706 setflags_logical (cpu
, x
);
5708 else if ((sop
== 2 || sop
== 3) && sopcde
== 10)
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);
5724 TRACE_INSN (cpu
, "R%i = DEPOSIT (R%i, R%i)%s;", dst0
, src1
, src0
,
5725 sop
== 3 ? " (X)" : "");
5729 /* Sign extend the fg bit field. */
5731 fgnd
= ((bs32
)(bs16
)(fgnd
<< (16 - len
))) >> (16 - len
);
5738 STORE (DREG (dst0
), bg
);
5739 setflags_logical (cpu
, bg
);
5741 else if (sop
== 0 && sopcde
== 11)
5743 bu64 acc0
= get_unextended_acc (cpu
, 0);
5745 TRACE_INSN (cpu
, "R%i.L = CC = BXORSHIFT (A0, R%i);", dst0
, src0
);
5748 SET_CCREG (xor_reduce (acc0
, DREG (src0
)));
5749 SET_DREG (dst0
, REG_H_L (DREG (dst0
), CCREG
));
5752 else if (sop
== 1 && sopcde
== 11)
5754 bu64 acc0
= get_unextended_acc (cpu
, 0);
5756 TRACE_INSN (cpu
, "R%i.L = CC = BXOR (A0, R%i);", dst0
, src0
);
5758 SET_CCREG (xor_reduce (acc0
, DREG (src0
)));
5759 SET_DREG (dst0
, REG_H_L (DREG (dst0
), CCREG
));
5761 else if (sop
== 0 && sopcde
== 12)
5763 bu64 acc0
= get_unextended_acc (cpu
, 0);
5764 bu64 acc1
= get_unextended_acc (cpu
, 1);
5766 TRACE_INSN (cpu
, "A0 = BXORSHIFT (A0, A1, CC);");
5768 acc0
= (acc0
<< 1) | (CCREG
^ xor_reduce (acc0
, acc1
));
5771 else if (sop
== 1 && sopcde
== 12)
5773 bu64 acc0
= get_unextended_acc (cpu
, 0);
5774 bu64 acc1
= get_unextended_acc (cpu
, 1);
5776 TRACE_INSN (cpu
, "R%i.L = CC = BXOR (A0, A1, CC);", dst0
);
5778 SET_CCREG (CCREG
^ xor_reduce (acc0
, acc1
));
5779 acc0
= (acc0
<< 1) | CCREG
;
5780 SET_DREG (dst0
, REG_H_L (DREG (dst0
), CCREG
));
5782 else if ((sop
== 0 || sop
== 1 || sop
== 2) && sopcde
== 13)
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
));
5789 illegal_instruction (cpu
);
5793 sgn_extend (bu40 org
, bu40 val
, int size
)
5797 if (org
& (1ULL << (size
- 1)))
5799 /* We need to shift in to the MSB which is set. */
5802 for (n
= 40; n
>= 0; n
--)
5803 if (ret
& (1ULL << n
))
5805 ret
|= (-1ULL << n
);
5808 ret
&= ~(-1ULL << 39);
5813 decode_dsp32shiftimm_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
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
);
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
);
5836 bu16 in
= DREG (src1
) >> ((HLs
& 1) ? 16 : 0);
5842 TRACE_INSN (cpu
, "R%i.%c = R%i.%c >>> %i;",
5843 dst0
, (HLs
& 2) ? 'H' : 'L',
5844 src1
, (HLs
& 1) ? 'H' : 'L', newimmag
);
5847 result
= lshift (cpu
, in
, 16 - (newimmag
& 0xF), 16, 0, 1);
5848 if (((result
>> 15) & 0x1) != ((in
>> 15) & 0x1))
5850 SET_ASTATREG (v
, 1);
5851 SET_ASTATREG (vs
, 1);
5855 result
= ashiftrt (cpu
, in
, newimmag
, 16);
5857 else if (sop
== 1 && bit8
== 0)
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);
5864 else if (sop
== 1 && bit8
)
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
);
5871 int shift
= 32 - newimmag
;
5872 bu16 inshift
= in
<< shift
;
5874 if (((inshift
& ~0xFFFF)
5875 && ((inshift
& ~0xFFFF) >> 16) != ~(~0 << shift
))
5876 || (inshift
& 0x8000) != (in
& 0x8000))
5882 SET_ASTATREG (v
, 1);
5883 SET_ASTATREG (vs
, 1);
5888 SET_ASTATREG (v
, 0);
5891 SET_ASTATREG (az
, !result
);
5892 SET_ASTATREG (an
, !!(result
& 0x8000));
5896 result
= ashiftrt (cpu
, in
, newimmag
, 16);
5897 result
= sgn_extend (in
, result
, 16);
5900 else if (sop
== 2 && bit8
)
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);
5907 else if (sop
== 2 && bit8
== 0)
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);
5915 illegal_instruction (cpu
);
5919 STORE (DREG (dst0
), (v
& 0xFFFF) | (result
<< 16));
5921 STORE (DREG (dst0
), (v
& 0xFFFF0000) | result
);
5923 else if (sop
== 2 && sopcde
== 3 && (HLs
== 1 || HLs
== 0))
5925 int shift
= imm6 (immag
);
5927 bu40 acc
= get_unextended_acc (cpu
, HLs
);
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
);
5932 acc
= rot40 (acc
, shift
, &cc
);
5933 SET_AREG (HLs
, acc
);
5937 else if (sop
== 0 && sopcde
== 3 && bit8
== 1 && HLs
< 2)
5939 /* Arithmetic shift, so shift in sign bit copies. */
5941 int shift
= uimm5 (newimmag
);
5943 TRACE_INSN (cpu
, "A%i = A%i >>> %i;", HLs
, HLs
, shift
);
5945 acc
= get_extended_acc (cpu
, HLs
);
5948 /* Sign extend again. */
5949 val
= sgn_extend (acc
, val
, 40);
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);
5957 else if (((sop
== 0 && sopcde
== 3 && bit8
== 0)
5958 || (sop
== 1 && sopcde
== 3)) && HLs
< 2)
5961 int shiftup
= uimm5 (immag
);
5962 int shiftdn
= uimm5 (newimmag
);
5964 TRACE_INSN (cpu
, "A%i = A%i %s %i;", HLs
, HLs
,
5965 sop
== 0 ? "<<" : ">>",
5966 sop
== 0 ? shiftup
: shiftdn
);
5969 /* Logical shift, so shift in zeroes. */
5981 acc
<<= 32 - (shiftdn
& 0x1f);
5984 SET_AREG (HLs
, acc
);
5985 SET_ASTATREG (av
[HLs
], 0);
5986 SET_ASTATREG (an
, !!(acc
& 0x8000000000ull
));
5987 SET_ASTATREG (az
, (acc
& 0xFFFFFFFFFF) == 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)
5994 int count
= imm5 (immag
);
5995 bu16 val0
= DREG (src1
) >> 16;
5996 bu16 val1
= DREG (src1
) & 0xFFFF;
5999 TRACE_INSN (cpu
, "R%i = R%i << %i (V,S);", dst0
, src1
, count
);
6002 val0
= lshift (cpu
, val0
, count
, 16, 1, 1);
6004 val1
= lshift (cpu
, val1
, count
, 16, 1, 1);
6008 val0
= ashiftrt (cpu
, val0
, -count
, 16);
6010 val1
= ashiftrt (cpu
, val1
, -count
, 16);
6012 SET_ASTAT (ASTAT
| astat
);
6014 STORE (DREG (dst0
), (val0
<< 16) | val1
);
6016 else if (sop
== 2 && sopcde
== 1 && bit8
== 1)
6018 int count
= imm5 (newimmag
);
6019 bu16 val0
= DREG (src1
) & 0xFFFF;
6020 bu16 val1
= DREG (src1
) >> 16;
6023 TRACE_INSN (cpu
, "R%i = R%i >> %i (V);", dst0
, src1
, count
);
6024 val0
= lshiftrt (cpu
, val0
, count
, 16);
6026 val1
= lshiftrt (cpu
, val1
, count
, 16);
6027 SET_ASTAT (ASTAT
| astat
);
6029 STORE (DREG (dst0
), val0
| (val1
<< 16));
6031 else if (sop
== 2 && sopcde
== 1 && bit8
== 0)
6033 int count
= imm5 (immag
);
6034 bu16 val0
= DREG (src1
) & 0xFFFF;
6035 bu16 val1
= DREG (src1
) >> 16;
6038 TRACE_INSN (cpu
, "R%i = R%i << %i (V);", dst0
, src1
, count
);
6039 val0
= lshift (cpu
, val0
, count
, 16, 0, 1);
6041 val1
= lshift (cpu
, val1
, count
, 16, 0, 1);
6042 SET_ASTAT (ASTAT
| astat
);
6044 STORE (DREG (dst0
), val0
| (val1
<< 16));
6046 else if (sopcde
== 1 && (sop
== 0 || (sop
== 1 && bit8
== 1)))
6048 int count
= uimm5 (newimmag
);
6049 bu16 val0
= DREG (src1
) & 0xFFFF;
6050 bu16 val1
= DREG (src1
) >> 16;
6053 TRACE_INSN (cpu
, "R%i = R%i >>> %i %s;", dst0
, src1
, count
,
6054 sop
== 0 ? "(V)" : "(V,S)");
6058 int sgn0
= (val0
>> 15) & 0x1;
6059 int sgn1
= (val1
>> 15) & 0x1;
6061 val0
= lshift (cpu
, val0
, 16 - (count
& 0xF), 16, 0, 1);
6063 val1
= lshift (cpu
, val1
, 16 - (count
& 0xF), 16, 0, 1);
6065 if ((sgn0
!= ((val0
>> 15) & 0x1)) || (sgn1
!= ((val1
>> 15) & 0x1)))
6067 SET_ASTATREG (v
, 1);
6068 SET_ASTATREG (vs
, 1);
6073 val0
= ashiftrt (cpu
, val0
, count
, 16);
6075 val1
= ashiftrt (cpu
, val1
, count
, 16);
6078 SET_ASTAT (ASTAT
| astat
);
6080 STORE (DREG (dst0
), REG_H_L (val1
<< 16, val0
));
6082 else if (sop
== 1 && sopcde
== 2)
6084 int count
= imm6 (immag
);
6086 TRACE_INSN (cpu
, "R%i = R%i << %i (S);", dst0
, src1
, count
);
6089 STORE (DREG (dst0
), ashiftrt (cpu
, DREG (src1
), -count
, 32));
6091 STORE (DREG (dst0
), lshift (cpu
, DREG (src1
), count
, 32, 1, 1));
6093 else if (sop
== 2 && sopcde
== 2)
6095 int count
= imm6 (newimmag
);
6097 TRACE_INSN (cpu
, "R%i = R%i >> %i;", dst0
, src1
, count
);
6100 STORE (DREG (dst0
), lshift (cpu
, DREG (src1
), -count
, 32, 0, 1));
6102 STORE (DREG (dst0
), lshiftrt (cpu
, DREG (src1
), count
, 32));
6104 else if (sop
== 3 && sopcde
== 2)
6106 int shift
= imm6 (immag
);
6107 bu32 src
= DREG (src1
);
6108 bu32 ret
, cc
= CCREG
;
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
);
6114 ret
= rot32 (src
, shift
, &cc
);
6115 STORE (DREG (dst0
), ret
);
6119 else if (sop
== 0 && sopcde
== 2)
6121 int count
= imm6 (newimmag
);
6123 TRACE_INSN (cpu
, "R%i = R%i >>> %i;", dst0
, src1
, count
);
6126 STORE (DREG (dst0
), lshift (cpu
, DREG (src1
), -count
, 32, 0, 1));
6128 STORE (DREG (dst0
), ashiftrt (cpu
, DREG (src1
), count
, 32));
6131 illegal_instruction (cpu
);
6135 outc (SIM_CPU
*cpu
, char ch
)
6137 SIM_DESC sd
= CPU_STATE (cpu
);
6138 sim_io_printf (sd
, "%c", ch
);
6140 sim_io_flush_stdout (sd
);
6144 decode_psedoDEBUG_0 (SIM_CPU
*cpu
, bu16 iw0
)
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
);
6155 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_psedoDEBUG
);
6156 TRACE_EXTRACT (cpu
, "%s: fn:%i grp:%i reg:%i", __func__
, fn
, grp
, reg
);
6158 if ((reg
== 0 || reg
== 1) && fn
== 3)
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
));
6164 else if (reg
== 3 && fn
== 3)
6166 TRACE_INSN (cpu
, "ABORT;");
6167 cec_exception (cpu
, VEC_SIM_ABORT
);
6170 else if (reg
== 4 && fn
== 3)
6172 TRACE_INSN (cpu
, "HLT;");
6173 cec_exception (cpu
, VEC_SIM_HLT
);
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)
6184 TRACE_INSN (cpu
, "OUTC R%i;", reg
);
6185 outc (cpu
, DREG (reg
));
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
));
6195 unhandled_instruction (cpu
, "PRNT allregs");
6197 illegal_instruction (cpu
);
6201 decode_psedoOChar_0 (SIM_CPU
*cpu
, bu16 iw0
)
6204 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
6205 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |.ch............................|
6206 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
6207 int ch
= ((iw0
>> PseudoChr_ch_bits
) & PseudoChr_ch_mask
);
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
);
6217 decode_psedodbg_assert_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
, bu32 pc
)
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
);
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
;
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
);
6239 if (dbgop
== 0 || dbgop
== 2)
6241 dbg_name
= dbgop
== 0 ? "DBGA" : "DBGAL";
6242 dbg_appd
= dbgop
== 0 ? ".L" : "";
6245 else if (dbgop
== 1 || dbgop
== 3)
6247 dbg_name
= dbgop
== 1 ? "DBGA" : "DBGAH";
6248 dbg_appd
= dbgop
== 1 ? ".H" : "";
6252 illegal_instruction (cpu
);
6254 actual
= val
>> offset
;
6256 TRACE_INSN (cpu
, "%s (%s%s, 0x%x);", dbg_name
, reg_name
, dbg_appd
, expected
);
6257 if (actual
!= expected
)
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
);
6262 /* Decode the actual ASTAT bits that are different. */
6263 if (grp
== 4 && regtest
== 6)
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))
6273 (expected
>> i
) & 1,
6274 i
== 7 ? "\n" : "");
6275 sim_io_printf (sd
, "\n");
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))
6284 i
== 7 ? "\n" : "");
6285 sim_io_printf (sd
, "\n");
6288 cec_exception (cpu
, VEC_SIM_DBGA
);
6294 _interp_insn_bfin (SIM_CPU
*cpu
, bu32 pc
)
6299 BFIN_CPU_STATE
.multi_pc
= pc
;
6301 if ((iw0
& 0xc000) != 0xc000)
6303 /* 16-bit opcode. */
6306 INSN_LEN
= insn_len
;
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
);
6359 TRACE_EXTRACT (cpu
, "%s: no matching 16-bit pattern", __func__
);
6360 illegal_instruction_or_combination (cpu
);
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 */)
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
));
6373 PARALLEL_GROUP
= BFIN_PARALLEL_GROUP0
;
6378 TRACE_EXTRACT (cpu
, "%s: iw0:%#x iw1:%#x insn_len:%i", __func__
,
6379 iw0
, iw1
, insn_len
);
6381 /* Only cache on first run through (in case of parallel insns). */
6383 INSN_LEN
= insn_len
;
6385 /* Once you're past the first slot, only 16bit insns are valid. */
6386 illegal_instruction_combination (cpu
);
6388 if ((iw0
& 0xf7ff) == 0xc003 && (iw1
& 0xfe00) == 0x1800)
6390 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32mac
);
6391 TRACE_INSN (cpu
, "MNOP;");
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
);
6421 TRACE_EXTRACT (cpu
, "%s: no matching 32-bit pattern", __func__
);
6422 illegal_instruction (cpu
);
6429 interp_insn_bfin (SIM_CPU
*cpu
, bu32 pc
)
6434 BFIN_CPU_STATE
.n_stores
= 0;
6435 PARALLEL_GROUP
= BFIN_PARALLEL_NONE
;
6436 DIS_ALGN_EXPT
&= ~1;
6440 insn_len
= _interp_insn_bfin (cpu
, pc
);
6442 /* Proper display of multiple issue instructions. */
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);
6450 for (i
= 0; i
< BFIN_CPU_STATE
.n_stores
; i
++)
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
);
6458 cycles_inc (cpu
, CYCLE_DELAY
);
6460 /* Set back to zero in case a pending CEC event occurs
6461 after this this insn. */