1 /* Simulator for Analog Devices Blackfin processors.
3 Copyright (C) 2005-2022 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/>. */
21 /* This must come before any other includes. */
30 #include "opcode/bfin.h"
32 #include "dv-bfin_cec.h"
33 #include "dv-bfin_mmu.h"
35 #define HOST_LONG_WORD_SIZE (sizeof (long) * 8)
37 #define SIGNEXTEND(v, n) \
38 (((bs32)(v) << (HOST_LONG_WORD_SIZE - (n))) >> (HOST_LONG_WORD_SIZE - (n)))
40 static ATTRIBUTE_NORETURN
void
41 illegal_instruction (SIM_CPU
*cpu
)
43 TRACE_INSN (cpu
, "ILLEGAL INSTRUCTION");
45 cec_exception (cpu
, VEC_UNDEF_I
);
48 static ATTRIBUTE_NORETURN
void
49 illegal_instruction_combination (SIM_CPU
*cpu
)
51 TRACE_INSN (cpu
, "ILLEGAL INSTRUCTION COMBINATION");
53 cec_exception (cpu
, VEC_ILGAL_I
);
56 static ATTRIBUTE_NORETURN
void
57 illegal_instruction_or_combination (SIM_CPU
*cpu
)
59 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
60 illegal_instruction_combination (cpu
);
62 illegal_instruction (cpu
);
65 static ATTRIBUTE_NORETURN
void
66 unhandled_instruction (SIM_CPU
*cpu
, const char *insn
)
68 SIM_DESC sd
= CPU_STATE (cpu
);
72 TRACE_EVENTS (cpu
, "unhandled instruction");
75 iw1
= IFETCH (PCREG
+ 2);
76 iw2
= ((bu32
)iw0
<< 16) | iw1
;
78 sim_io_eprintf (sd
, "Unhandled instruction at 0x%08x (%s opcode 0x", PCREG
, insn
);
79 if ((iw0
& 0xc000) == 0xc000)
80 sim_io_eprintf (sd
, "%08x", iw2
);
82 sim_io_eprintf (sd
, "%04x", iw0
);
84 sim_io_eprintf (sd
, ") ... aborting\n");
86 illegal_instruction (cpu
);
89 static const char * const astat_names
[] =
127 c_0
, c_1
, c_4
, c_2
, c_uimm2
, c_uimm3
, c_imm3
, c_pcrel4
,
128 c_imm4
, c_uimm4s4
, c_uimm4s4d
, c_uimm4
, c_uimm4s2
, c_negimm5s4
, c_imm5
,
129 c_imm5d
, c_uimm5
, c_imm6
, c_imm7
, c_imm7d
, c_imm8
, c_uimm8
, c_pcrel8
,
130 c_uimm8s4
, c_pcrel8s4
, c_lppcrel10
, c_pcrel10
, c_pcrel12
, c_imm16s4
,
131 c_luimm16
, c_imm16
, c_imm16d
, c_huimm16
, c_rimm16
, c_imm16s2
, c_uimm16s4
,
132 c_uimm16s4d
, c_uimm16
, c_pcrel24
, c_uimm32
, c_imm32
, c_huimm32
, c_huimm32e
,
149 } constant_formats
[] =
151 { "0", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
152 { "1", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
153 { "4", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
154 { "2", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
155 { "uimm2", 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
156 { "uimm3", 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
157 { "imm3", 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
158 { "pcrel4", 4, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0},
159 { "imm4", 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
160 { "uimm4s4", 4, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0},
161 { "uimm4s4d", 4, 0, 0, 0, 2, 0, 0, 1, 1, 0, 0},
162 { "uimm4", 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
163 { "uimm4s2", 4, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0},
164 { "negimm5s4", 5, 0, 1, 0, 2, 0, 1, 0, 0, 0, 0},
165 { "imm5", 5, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
166 { "imm5d", 5, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0},
167 { "uimm5", 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
168 { "imm6", 6, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
169 { "imm7", 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
170 { "imm7d", 7, 0, 1, 0, 0, 0, 0, 0, 1, 3, 0},
171 { "imm8", 8, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
172 { "uimm8", 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
173 { "pcrel8", 8, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0},
174 { "uimm8s4", 8, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0},
175 { "pcrel8s4", 8, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0},
176 { "lppcrel10", 10, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0},
177 { "pcrel10", 10, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
178 { "pcrel12", 12, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
179 { "imm16s4", 16, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0},
180 { "luimm16", 16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
181 { "imm16", 16, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
182 { "imm16d", 16, 0, 1, 0, 0, 0, 0, 0, 1, 3, 0},
183 { "huimm16", 16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
184 { "rimm16", 16, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0},
185 { "imm16s2", 16, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0},
186 { "uimm16s4", 16, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0},
187 { "uimm16s4d", 16, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0},
188 { "uimm16", 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
189 { "pcrel24", 24, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
190 { "uimm32", 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
191 { "imm32", 32, 0, 1, 0, 0, 0, 0, 0, 1, 3, 0},
192 { "huimm32", 32, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
193 { "huimm32e", 32, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
197 fmtconst_str (const_forms_t cf
, bs32 x
, bu32 pc
)
201 if (constant_formats
[cf
].reloc
)
203 bu32 ea
= (((constant_formats
[cf
].pcrel
? SIGNEXTEND (x
, constant_formats
[cf
].nbits
)
204 : x
) + constant_formats
[cf
].offset
) << constant_formats
[cf
].scale
);
205 if (constant_formats
[cf
].pcrel
)
207 /*if (outf->symbol_at_address_func (ea, outf) || !constant_formats[cf].exact)
209 outf->print_address_func (ea, outf);
214 sprintf (buf
, "%#x", x
);
219 /* Negative constants have an implied sign bit. */
220 if (constant_formats
[cf
].negative
)
222 int nb
= constant_formats
[cf
].nbits
+ 1;
224 x
= x
| (1 << constant_formats
[cf
].nbits
);
225 x
= SIGNEXTEND (x
, nb
);
228 x
= constant_formats
[cf
].issigned
? SIGNEXTEND (x
, constant_formats
[cf
].nbits
) : x
;
230 if (constant_formats
[cf
].offset
)
231 x
+= constant_formats
[cf
].offset
;
233 if (constant_formats
[cf
].scale
)
234 x
<<= constant_formats
[cf
].scale
;
236 if (constant_formats
[cf
].decimal
)
237 sprintf (buf
, "%*i", constant_formats
[cf
].leading
, x
);
240 if (constant_formats
[cf
].issigned
&& x
< 0)
241 sprintf (buf
, "-0x%x", abs (x
));
243 sprintf (buf
, "0x%x", x
);
250 fmtconst_val (const_forms_t cf
, bu32 x
, bu32 pc
)
252 if (0 && constant_formats
[cf
].reloc
)
254 bu32 ea
= (((constant_formats
[cf
].pcrel
255 ? (bu32
)SIGNEXTEND (x
, constant_formats
[cf
].nbits
)
256 : x
) + constant_formats
[cf
].offset
)
257 << constant_formats
[cf
].scale
);
258 if (constant_formats
[cf
].pcrel
)
264 /* Negative constants have an implied sign bit. */
265 if (constant_formats
[cf
].negative
)
267 int nb
= constant_formats
[cf
].nbits
+ 1;
268 x
= x
| (1 << constant_formats
[cf
].nbits
);
269 x
= SIGNEXTEND (x
, nb
);
271 else if (constant_formats
[cf
].issigned
)
272 x
= SIGNEXTEND (x
, constant_formats
[cf
].nbits
);
274 x
+= constant_formats
[cf
].offset
;
275 x
<<= constant_formats
[cf
].scale
;
280 #define uimm16s4(x) fmtconst_val (c_uimm16s4, x, 0)
281 #define uimm16s4_str(x) fmtconst_str (c_uimm16s4, x, 0)
282 #define uimm16s4d(x) fmtconst_val (c_uimm16s4d, x, 0)
283 #define pcrel4(x) fmtconst_val (c_pcrel4, x, pc)
284 #define pcrel8(x) fmtconst_val (c_pcrel8, x, pc)
285 #define pcrel8s4(x) fmtconst_val (c_pcrel8s4, x, pc)
286 #define pcrel10(x) fmtconst_val (c_pcrel10, x, pc)
287 #define pcrel12(x) fmtconst_val (c_pcrel12, x, pc)
288 #define negimm5s4(x) fmtconst_val (c_negimm5s4, x, 0)
289 #define negimm5s4_str(x) fmtconst_str (c_negimm5s4, x, 0)
290 #define rimm16(x) fmtconst_val (c_rimm16, x, 0)
291 #define huimm16(x) fmtconst_val (c_huimm16, x, 0)
292 #define imm16(x) fmtconst_val (c_imm16, x, 0)
293 #define imm16_str(x) fmtconst_str (c_imm16, x, 0)
294 #define imm16d(x) fmtconst_val (c_imm16d, x, 0)
295 #define uimm2(x) fmtconst_val (c_uimm2, x, 0)
296 #define uimm3(x) fmtconst_val (c_uimm3, x, 0)
297 #define uimm3_str(x) fmtconst_str (c_uimm3, x, 0)
298 #define luimm16(x) fmtconst_val (c_luimm16, x, 0)
299 #define luimm16_str(x) fmtconst_str (c_luimm16, x, 0)
300 #define uimm4(x) fmtconst_val (c_uimm4, x, 0)
301 #define uimm4_str(x) fmtconst_str (c_uimm4, x, 0)
302 #define uimm5(x) fmtconst_val (c_uimm5, x, 0)
303 #define uimm5_str(x) fmtconst_str (c_uimm5, x, 0)
304 #define imm16s2(x) fmtconst_val (c_imm16s2, x, 0)
305 #define imm16s2_str(x) fmtconst_str (c_imm16s2, x, 0)
306 #define uimm8(x) fmtconst_val (c_uimm8, x, 0)
307 #define imm16s4(x) fmtconst_val (c_imm16s4, x, 0)
308 #define imm16s4_str(x) fmtconst_str (c_imm16s4, x, 0)
309 #define uimm4s2(x) fmtconst_val (c_uimm4s2, x, 0)
310 #define uimm4s2_str(x) fmtconst_str (c_uimm4s2, x, 0)
311 #define uimm4s4(x) fmtconst_val (c_uimm4s4, x, 0)
312 #define uimm4s4_str(x) fmtconst_str (c_uimm4s4, x, 0)
313 #define uimm4s4d(x) fmtconst_val (c_uimm4s4d, x, 0)
314 #define lppcrel10(x) fmtconst_val (c_lppcrel10, x, pc)
315 #define imm3(x) fmtconst_val (c_imm3, x, 0)
316 #define imm3_str(x) fmtconst_str (c_imm3, x, 0)
317 #define imm4(x) fmtconst_val (c_imm4, x, 0)
318 #define uimm8s4(x) fmtconst_val (c_uimm8s4, x, 0)
319 #define imm5(x) fmtconst_val (c_imm5, x, 0)
320 #define imm5d(x) fmtconst_val (c_imm5d, x, 0)
321 #define imm6(x) fmtconst_val (c_imm6, x, 0)
322 #define imm7(x) fmtconst_val (c_imm7, x, 0)
323 #define imm7_str(x) fmtconst_str (c_imm7, x, 0)
324 #define imm7d(x) fmtconst_val (c_imm7d, x, 0)
325 #define imm8(x) fmtconst_val (c_imm8, x, 0)
326 #define pcrel24(x) fmtconst_val (c_pcrel24, x, pc)
327 #define pcrel24_str(x) fmtconst_str (c_pcrel24, x, pc)
328 #define uimm16(x) fmtconst_val (c_uimm16, x, 0)
329 #define uimm32(x) fmtconst_val (c_uimm32, x, 0)
330 #define imm32(x) fmtconst_val (c_imm32, x, 0)
331 #define huimm32(x) fmtconst_val (c_huimm32, x, 0)
332 #define huimm32e(x) fmtconst_val (c_huimm32e, x, 0)
334 /* Table C-4. Core Register Encoding Map. */
335 const char * const greg_names
[] =
337 "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7",
338 "P0", "P1", "P2", "P3", "P4", "P5", "SP", "FP",
339 "I0", "I1", "I2", "I3", "M0", "M1", "M2", "M3",
340 "B0", "B1", "B2", "B3", "L0", "L1", "L2", "L3",
341 "A0.X", "A0.W", "A1.X", "A1.W", "<res>", "<res>", "ASTAT", "RETS",
342 "<res>", "<res>", "<res>", "<res>", "<res>", "<res>", "<res>", "<res>",
343 "LC0", "LT0", "LB0", "LC1", "LT1", "LB1", "CYCLES", "CYCLES2",
344 "USP", "SEQSTAT", "SYSCFG", "RETI", "RETX", "RETN", "RETE", "EMUDAT",
347 get_allreg_name (int grp
, int reg
)
349 return greg_names
[(grp
<< 3) | reg
];
352 get_preg_name (int reg
)
354 return get_allreg_name (1, reg
);
358 reg_is_reserved (int grp
, int reg
)
360 return (grp
== 4 && (reg
== 4 || reg
== 5)) || (grp
== 5);
364 get_allreg (SIM_CPU
*cpu
, int grp
, int reg
)
366 int fullreg
= (grp
<< 3) | reg
;
367 /* REG_R0, REG_R1, REG_R2, REG_R3, REG_R4, REG_R5, REG_R6, REG_R7,
368 REG_P0, REG_P1, REG_P2, REG_P3, REG_P4, REG_P5, REG_SP, REG_FP,
369 REG_I0, REG_I1, REG_I2, REG_I3, REG_M0, REG_M1, REG_M2, REG_M3,
370 REG_B0, REG_B1, REG_B2, REG_B3, REG_L0, REG_L1, REG_L2, REG_L3,
371 REG_A0x, REG_A0w, REG_A1x, REG_A1w, , , REG_ASTAT, REG_RETS,
373 REG_LC0, REG_LT0, REG_LB0, REG_LC1, REG_LT1, REG_LB1, REG_CYCLES,
375 REG_USP, REG_SEQSTAT, REG_SYSCFG, REG_RETI, REG_RETX, REG_RETN, REG_RETE,
377 switch (fullreg
>> 2)
379 case 0: case 1: return &DREG (reg
);
380 case 2: case 3: return &PREG (reg
);
381 case 4: return &IREG (reg
& 3);
382 case 5: return &MREG (reg
& 3);
383 case 6: return &BREG (reg
& 3);
384 case 7: return &LREG (reg
& 3);
388 case 32: return &AXREG (0);
389 case 33: return &AWREG (0);
390 case 34: return &AXREG (1);
391 case 35: return &AWREG (1);
392 case 39: return &RETSREG
;
393 case 48: return &LCREG (0);
394 case 49: return <REG (0);
395 case 50: return &LBREG (0);
396 case 51: return &LCREG (1);
397 case 52: return <REG (1);
398 case 53: return &LBREG (1);
399 case 54: return &CYCLESREG
;
400 case 55: return &CYCLES2REG
;
401 case 56: return &USPREG
;
402 case 57: return &SEQSTATREG
;
403 case 58: return &SYSCFGREG
;
404 case 59: return &RETIREG
;
405 case 60: return &RETXREG
;
406 case 61: return &RETNREG
;
407 case 62: return &RETEREG
;
408 case 63: return &EMUDAT_INREG
;
410 illegal_instruction (cpu
);
415 amod0 (int s0
, int x0
)
417 static const char * const mod0
[] = {
418 "", " (S)", " (CO)", " (SCO)",
420 int i
= s0
+ (x0
<< 1);
422 if (i
< ARRAY_SIZE (mod0
))
429 amod0amod2 (int s0
, int x0
, int aop0
)
431 static const char * const mod02
[] = {
432 "", " (S)", " (CO)", " (SCO)",
434 " (ASR)", " (S, ASR)", " (CO, ASR)", " (SCO, ASR)",
435 " (ASL)", " (S, ASL)", " (CO, ASL)", " (SCO, ASL)",
437 int i
= s0
+ (x0
<< 1) + (aop0
<< 2);
439 if (i
< ARRAY_SIZE (mod02
))
446 amod1 (int s0
, int x0
)
448 static const char * const mod1
[] = {
451 int i
= s0
+ (x0
<< 1);
453 if (i
< ARRAY_SIZE (mod1
))
460 mac_optmode (int mmod
, int MM
)
462 static const char * const omode
[] = {
463 [(M_S2RND
<< 1) + 0] = " (S2RND)",
464 [(M_T
<< 1) + 0] = " (T)",
465 [(M_W32
<< 1) + 0] = " (W32)",
466 [(M_FU
<< 1) + 0] = " (FU)",
467 [(M_TFU
<< 1) + 0] = " (TFU)",
468 [(M_IS
<< 1) + 0] = " (IS)",
469 [(M_ISS2
<< 1) + 0] = " (ISS2)",
470 [(M_IH
<< 1) + 0] = " (IH)",
471 [(M_IU
<< 1) + 0] = " (IU)",
472 [(M_S2RND
<< 1) + 1] = " (M, S2RND)",
473 [(M_T
<< 1) + 1] = " (M, T)",
474 [(M_W32
<< 1) + 1] = " (M, W32)",
475 [(M_FU
<< 1) + 1] = " (M, FU)",
476 [(M_TFU
<< 1) + 1] = " (M, TFU)",
477 [(M_IS
<< 1) + 1] = " (M, IS)",
478 [(M_ISS2
<< 1) + 1] = " (M, ISS2)",
479 [(M_IH
<< 1) + 1] = " (M, IH)",
480 [(M_IU
<< 1) + 1] = " (M, IU)",
482 int i
= MM
+ (mmod
<< 1);
484 if (i
< ARRAY_SIZE (omode
) && omode
[i
])
491 get_store_name (SIM_CPU
*cpu
, bu32
*p
)
493 if (p
>= &DREG (0) && p
<= &CYCLESREG
)
494 return greg_names
[p
- &DREG (0)];
495 else if (p
== &AXREG (0))
496 return greg_names
[4 * 8 + 0];
497 else if (p
== &AWREG (0))
498 return greg_names
[4 * 8 + 1];
499 else if (p
== &AXREG (1))
500 return greg_names
[4 * 8 + 2];
501 else if (p
== &AWREG (1))
502 return greg_names
[4 * 8 + 3];
503 else if (p
== &ASTATREG (av0
))
505 else if (p
== &ASTATREG (av0s
))
506 return "ASTAT[av0s]";
507 else if (p
== &ASTATREG (av1
))
509 else if (p
== &ASTATREG (av1s
))
510 return "ASTAT[av1s]";
511 else if (p
== &ASTATREG (v
))
513 else if (p
== &ASTATREG (vs
))
515 else if (p
== &ASTATREG (v_copy
))
516 return "ASTAT[v_copy]";
517 else if (p
== &ASTATREG (az
))
519 else if (p
== &ASTATREG (an
))
521 else if (p
== &ASTATREG (az
))
523 else if (p
== &ASTATREG (ac0
))
525 else if (p
== &ASTATREG (ac0_copy
))
526 return "ASTAT[ac0_copy]";
529 /* Worry about this when we start to STORE() it. */
530 sim_io_eprintf (CPU_STATE (cpu
), "STORE(): unknown register\n");
536 queue_store (SIM_CPU
*cpu
, bu32
*addr
, bu32 val
)
538 struct store
*s
= &BFIN_CPU_STATE
.stores
[BFIN_CPU_STATE
.n_stores
];
541 TRACE_REGISTER (cpu
, "queuing write %s = %#x",
542 get_store_name (cpu
, addr
), val
);
543 ++BFIN_CPU_STATE
.n_stores
;
545 #define STORE(X, Y) \
547 if (BFIN_CPU_STATE.n_stores == 20) abort (); \
548 queue_store (cpu, &(X), (Y)); \
552 setflags_nz (SIM_CPU
*cpu
, bu32 val
)
554 SET_ASTATREG (az
, val
== 0);
555 SET_ASTATREG (an
, val
>> 31);
559 setflags_nz_2x16 (SIM_CPU
*cpu
, bu32 val
)
561 SET_ASTATREG (an
, (bs16
)val
< 0 || (bs16
)(val
>> 16) < 0);
562 SET_ASTATREG (az
, (bs16
)val
== 0 || (bs16
)(val
>> 16) == 0);
566 setflags_logical (SIM_CPU
*cpu
, bu32 val
)
568 setflags_nz (cpu
, val
);
569 SET_ASTATREG (ac0
, 0);
574 add_brev (bu32 addend1
, bu32 addend2
)
583 for (i
= 31; i
>= 0; --i
)
585 b
= ((addend1
& mask
) >> i
) + ((addend2
& mask
) >> i
);
596 /* This is a bit crazy, but we want to simulate the hardware behavior exactly
597 rather than worry about the circular buffers being used correctly. Which
598 isn't to say there isn't room for improvement here, just that we want to
599 be conservative. See also dagsub(). */
601 dagadd (SIM_CPU
*cpu
, int dagno
, bs32 M
)
603 bu64 i
= IREG (dagno
);
604 bu64 l
= LREG (dagno
);
605 bu64 b
= BREG (dagno
);
609 bu32 im32
, iml32
, lb32
, res
;
612 /* A naïve implementation that mostly works:
614 if (l && res >= b + l)
616 STORE (IREG (dagno), res);
631 if ((i
& msb
) || (IM
& car
))
632 res
= (im32
< b
) ? iml32
: im32
;
634 res
= (im32
< b
) ? im32
: iml32
;
640 if ((IM
& car
) == (LB
& car
))
641 res
= (im32
< lb32
) ? im32
: iml32
;
643 res
= (im32
< lb32
) ? iml32
: im32
;
646 STORE (IREG (dagno
), res
);
650 /* See dagadd() notes above. */
652 dagsub (SIM_CPU
*cpu
, int dagno
, bs32 M
)
654 bu64 i
= IREG (dagno
);
655 bu64 l
= LREG (dagno
);
656 bu64 b
= BREG (dagno
);
659 bu64 mbar
= (bu32
)(~m
+ 1);
661 bu32 b32
, im32
, iml32
, lb32
, res
;
664 /* A naïve implementation that mostly works:
668 STORE (IREG (dagno), newi);
683 if (!!((i
& msb
) && (IM
& car
)) == !!(LB
& car
))
684 res
= (im32
< lb32
) ? im32
: iml32
;
686 res
= (im32
< lb32
) ? iml32
: im32
;
693 if (M
== 0 || IM
& car
)
694 res
= (im32
< b32
) ? iml32
: im32
;
696 res
= (im32
< b32
) ? im32
: iml32
;
699 STORE (IREG (dagno
), res
);
704 ashiftrt (SIM_CPU
*cpu
, bu40 val
, int cnt
, int size
)
706 int real_cnt
= cnt
> size
? size
: cnt
;
707 bu40 sgn
= ~(((val
& 0xFFFFFFFFFFull
) >> (size
- 1)) - 1);
708 int sgncnt
= size
- real_cnt
;
710 sgn
<<= 16, sgncnt
-= 16;
713 val
>>= 16, real_cnt
-= 16;
716 SET_ASTATREG (an
, val
>> (size
- 1));
717 SET_ASTATREG (az
, val
== 0);
724 lshiftrt (SIM_CPU
*cpu
, bu64 val
, int cnt
, int size
)
726 int real_cnt
= cnt
> size
? size
: cnt
;
728 val
>>= 16, real_cnt
-= 16;
739 val
&= 0xFFFFFFFFFFull
;
742 illegal_instruction (cpu
);
745 SET_ASTATREG (an
, val
>> (size
- 1));
746 SET_ASTATREG (az
, val
== 0);
753 lshift (SIM_CPU
*cpu
, bu64 val
, int cnt
, int size
, bool saturate
, bool overflow
)
755 int v_i
, real_cnt
= cnt
> size
? size
: cnt
;
756 bu64 sgn
= ~((val
>> (size
- 1)) - 1);
757 int mask_cnt
= size
- 1;
758 bu64 masked
, new_val
= val
;
766 new_val
<<= 16, real_cnt
-= 16;
768 new_val
<<= real_cnt
;
770 masked
= new_val
& mask
;
772 /* If an operation would otherwise cause a positive value to overflow
773 and become negative, instead, saturation limits the result to the
774 maximum positive value for the size register being used.
776 Conversely, if an operation would otherwise cause a negative value
777 to overflow and become positive, saturation limits the result to the
778 maximum negative value for the register size.
780 However, it's a little more complex than looking at sign bits, we need
781 to see if we are shifting the sign information away... */
782 if (((val
<< cnt
) >> size
) == 0
783 || (((val
<< cnt
) >> size
) == ~(~0 << cnt
)
784 && ((new_val
>> (size
- 1)) & 0x1)))
793 if (saturate
&& (v_i
|| ((val
>> (size
- 1)) != (new_val
>> (size
- 1)))))
795 new_val
= (val
>> (size
- 1)) == 0 ? 0x7fff : 0x8000;
800 new_val
&= 0xFFFFFFFF;
801 masked
&= 0xFFFFFFFF;
806 || (!sgn
&& new_val
== 0 && val
!= 0)))
808 new_val
= sgn
== 0 ? 0x7fffffff : 0x80000000;
813 new_val
&= 0xFFFFFFFFFFull
;
814 masked
&= 0xFFFFFFFFFFull
;
817 illegal_instruction (cpu
);
821 SET_ASTATREG (an
, new_val
>> (size
- 1));
822 SET_ASTATREG (az
, new_val
== 0);
825 SET_ASTATREG (v
, overflow
&& v_i
);
827 SET_ASTATREG (vs
, 1);
834 algn (bu32 l
, bu32 h
, bu32 aln
)
839 return (l
>> (8 * aln
)) | (h
<< (32 - 8 * aln
));
843 saturate_s16 (bu64 val
, bu32
*overflow
)
845 if ((bs64
)val
< -0x8000ll
)
851 if ((bs64
)val
> 0x7fff)
861 rot40 (bu40 val
, int shift
, bu32
*cc
)
863 const int nbits
= 40;
866 shift
= CLAMP (shift
, -nbits
, nbits
);
870 /* Reduce everything to rotate left. */
874 ret
= shift
== nbits
? 0 : val
<< shift
;
875 ret
|= shift
== 1 ? 0 : val
>> ((nbits
+ 1) - shift
);
876 ret
|= (bu40
)*cc
<< (shift
- 1);
877 *cc
= (val
>> (nbits
- shift
)) & 1;
883 rot32 (bu32 val
, int shift
, bu32
*cc
)
885 const int nbits
= 32;
888 shift
= CLAMP (shift
, -nbits
, nbits
);
892 /* Reduce everything to rotate left. */
896 ret
= shift
== nbits
? 0 : val
<< shift
;
897 ret
|= shift
== 1 ? 0 : val
>> ((nbits
+ 1) - shift
);
898 ret
|= (bu32
)*cc
<< (shift
- 1);
899 *cc
= (val
>> (nbits
- shift
)) & 1;
905 add32 (SIM_CPU
*cpu
, bu32 a
, bu32 b
, int carry
, int sat
)
907 int flgs
= (a
>> 31) & 1;
908 int flgo
= (b
>> 31) & 1;
910 int flgn
= (v
>> 31) & 1;
911 int overflow
= (flgs
^ flgn
) & (flgo
^ flgn
);
918 flgn
= (v
>> 31) & 1;
921 SET_ASTATREG (an
, flgn
);
923 SET_ASTATREG (vs
, 1);
924 SET_ASTATREG (v
, overflow
);
925 ASTATREG (v_internal
) |= overflow
;
926 SET_ASTATREG (az
, v
== 0);
928 SET_ASTATREG (ac0
, ~a
< b
);
934 sub32 (SIM_CPU
*cpu
, bu32 a
, bu32 b
, int carry
, int sat
, int parallel
)
936 int flgs
= (a
>> 31) & 1;
937 int flgo
= (b
>> 31) & 1;
939 int flgn
= (v
>> 31) & 1;
940 int overflow
= (flgs
^ flgo
) & (flgn
^ flgs
);
947 flgn
= (v
>> 31) & 1;
950 if (!parallel
|| flgn
)
951 SET_ASTATREG (an
, flgn
);
953 SET_ASTATREG (vs
, 1);
954 if (!parallel
|| overflow
)
955 SET_ASTATREG (v
, overflow
);
956 if (!parallel
|| overflow
)
957 ASTATREG (v_internal
) |= overflow
;
958 if (!parallel
|| v
== 0)
959 SET_ASTATREG (az
, v
== 0);
960 if (carry
&& (!parallel
|| b
<= a
))
961 SET_ASTATREG (ac0
, b
<= a
);
967 add16 (SIM_CPU
*cpu
, bu16 a
, bu16 b
, bu32
*carry
, bu32
*overfl
,
968 bu32
*zero
, bu32
*neg
, int sat
, int scale
)
970 int flgs
= (a
>> 15) & 1;
971 int flgo
= (b
>> 15) & 1;
972 bs64 v
= (bs16
)a
+ (bs16
)b
;
973 int flgn
= (v
>> 15) & 1;
974 int overflow
= (flgs
^ flgn
) & (flgo
^ flgn
);
982 v
= (a
>> 1) + (a
& 0x8000) + (b
>> 1) + (b
& 0x8000)
983 + (((a
& 1) + (b
& 1)) >> 1);
991 illegal_instruction (cpu
);
994 flgn
= (v
>> 15) & 1;
995 overflow
= (flgs
^ flgn
) & (flgo
^ flgn
);
997 if (v
> (bs64
)0xffff)
1001 v
= saturate_s16 (v
, 0);
1004 *neg
|= (v
>> 15) & 1;
1006 *overfl
|= overflow
;
1008 *zero
|= (v
& 0xFFFF) == 0;
1010 *carry
|= ((bu16
)~a
< (bu16
)b
);
1016 sub16 (SIM_CPU
*cpu
, bu16 a
, bu16 b
, bu32
*carry
, bu32
*overfl
,
1017 bu32
*zero
, bu32
*neg
, int sat
, int scale
)
1019 int flgs
= (a
>> 15) & 1;
1020 int flgo
= (b
>> 15) & 1;
1021 bs64 v
= (bs16
)a
- (bs16
)b
;
1022 int flgn
= (v
>> 15) & 1;
1023 int overflow
= (flgs
^ flgo
) & (flgn
^ flgs
);
1032 v
= ((a
>> 1) + (a
& 0x8000)) - ( (b
>> 1) + (b
& 0x8000))
1033 + (((a
& 1)-(b
& 1)));
1036 v
= ((v
& 0xFFFF) >> 1);
1037 if ((!flgs
& !flgo
& flgn
)
1038 || (flgs
& !flgo
& !flgn
)
1039 || (flgs
& flgo
& flgn
)
1040 || (flgs
& !flgo
& flgn
))
1044 flgn
= (v
>> 15) & 1;
1045 overflow
= (flgs
^ flgo
) & (flgn
^ flgs
);
1050 if (v
> (bs64
)0x7fff || v
< (bs64
)-0xffff)
1054 illegal_instruction (cpu
);
1059 v
= saturate_s16 (v
, 0);
1062 *neg
|= (v
>> 15) & 1;
1064 *zero
|= (v
& 0xFFFF) == 0;
1066 *overfl
|= overflow
;
1068 *carry
|= (bu16
)b
<= (bu16
)a
;
1073 min32 (SIM_CPU
*cpu
, bu32 a
, bu32 b
)
1076 if ((bs32
)a
> (bs32
)b
)
1078 setflags_nz (cpu
, val
);
1079 SET_ASTATREG (v
, 0);
1084 max32 (SIM_CPU
*cpu
, bu32 a
, bu32 b
)
1087 if ((bs32
)a
< (bs32
)b
)
1089 setflags_nz (cpu
, val
);
1090 SET_ASTATREG (v
, 0);
1095 min2x16 (SIM_CPU
*cpu
, bu32 a
, bu32 b
)
1098 if ((bs16
)a
> (bs16
)b
)
1099 val
= (val
& 0xFFFF0000) | (b
& 0xFFFF);
1100 if ((bs16
)(a
>> 16) > (bs16
)(b
>> 16))
1101 val
= (val
& 0xFFFF) | (b
& 0xFFFF0000);
1102 setflags_nz_2x16 (cpu
, val
);
1103 SET_ASTATREG (v
, 0);
1108 max2x16 (SIM_CPU
*cpu
, bu32 a
, bu32 b
)
1111 if ((bs16
)a
< (bs16
)b
)
1112 val
= (val
& 0xFFFF0000) | (b
& 0xFFFF);
1113 if ((bs16
)(a
>> 16) < (bs16
)(b
>> 16))
1114 val
= (val
& 0xFFFF) | (b
& 0xFFFF0000);
1115 setflags_nz_2x16 (cpu
, val
);
1116 SET_ASTATREG (v
, 0);
1121 add_and_shift (SIM_CPU
*cpu
, bu32 a
, bu32 b
, int shift
)
1124 ASTATREG (v_internal
) = 0;
1125 v
= add32 (cpu
, a
, b
, 0, 0);
1128 int x
= (v
>> 30) & 0x3;
1129 if (x
== 1 || x
== 2)
1130 ASTATREG (v_internal
) = 1;
1133 SET_ASTATREG (az
, v
== 0);
1134 SET_ASTATREG (an
, v
& 0x80000000);
1135 SET_ASTATREG (v
, ASTATREG (v_internal
));
1137 SET_ASTATREG (vs
, 1);
1142 xor_reduce (bu64 acc0
, bu64 acc1
)
1146 for (i
= 0; i
< 40; ++i
)
1148 v
^= (acc0
& acc1
& 1);
1155 /* DIVS ( Dreg, Dreg ) ;
1156 Initialize for DIVQ. Set the AQ status bit based on the signs of
1157 the 32-bit dividend and the 16-bit divisor. Left shift the dividend
1158 one bit. Copy AQ into the dividend LSB. */
1160 divs (SIM_CPU
*cpu
, bu32 pquo
, bu16 divisor
)
1162 bu16 r
= pquo
>> 16;
1165 aq
= (r
^ divisor
) >> 15; /* Extract msb's and compute quotient bit. */
1166 SET_ASTATREG (aq
, aq
); /* Update global quotient state. */
1170 pquo
= (pquo
& 0x1FFFF) | (r
<< 17);
1174 /* DIVQ ( Dreg, Dreg ) ;
1175 Based on AQ status bit, either add or subtract the divisor from
1176 the dividend. Then set the AQ status bit based on the MSBs of the
1177 32-bit dividend and the 16-bit divisor. Left shift the dividend one
1178 bit. Copy the logical inverse of AQ into the dividend LSB. */
1180 divq (SIM_CPU
*cpu
, bu32 pquo
, bu16 divisor
)
1182 unsigned short af
= pquo
>> 16;
1191 aq
= (r
^ divisor
) >> 15; /* Extract msb's and compute quotient bit. */
1192 SET_ASTATREG (aq
, aq
); /* Update global quotient state. */
1196 pquo
= (pquo
& 0x1FFFF) | (r
<< 17);
1201 Count the number of bits set to 1 in the 32bit value. */
1209 for (i
= 0; i
< 32; ++i
)
1210 ret
+= !!(val
& (1 << i
));
1216 reg_check_sup (SIM_CPU
*cpu
, int grp
, int reg
)
1219 cec_require_supervisor (cpu
);
1223 reg_write (SIM_CPU
*cpu
, int grp
, int reg
, bu32 value
)
1227 /* ASTAT is special! */
1228 if (grp
== 4 && reg
== 6)
1234 /* Check supervisor after get_allreg() so exception order is correct. */
1235 whichreg
= get_allreg (cpu
, grp
, reg
);
1236 reg_check_sup (cpu
, grp
, reg
);
1238 if (whichreg
== &CYCLES2REG
)
1239 /* Writes to CYCLES2 goes to the shadow. */
1240 whichreg
= &CYCLES2SHDREG
;
1241 else if (whichreg
== &SEQSTATREG
)
1242 /* Register is read only -- discard writes. */
1244 else if (whichreg
== &EMUDAT_INREG
)
1245 /* Writes to EMUDAT goes to the output. */
1246 whichreg
= &EMUDAT_OUTREG
;
1247 else if (whichreg
== <REG (0) || whichreg
== <REG (1))
1248 /* Writes to LT clears LSB automatically. */
1250 else if (whichreg
== &AXREG (0) || whichreg
== &AXREG (1))
1253 TRACE_REGISTER (cpu
, "wrote %s = %#x", get_allreg_name (grp
, reg
), value
);
1259 reg_read (SIM_CPU
*cpu
, int grp
, int reg
)
1264 /* ASTAT is special! */
1265 if (grp
== 4 && reg
== 6)
1268 /* Check supervisor after get_allreg() so exception order is correct. */
1269 whichreg
= get_allreg (cpu
, grp
, reg
);
1270 reg_check_sup (cpu
, grp
, reg
);
1274 if (whichreg
== &CYCLESREG
)
1275 /* Reads of CYCLES reloads CYCLES2 from the shadow. */
1276 SET_CYCLES2REG (CYCLES2SHDREG
);
1277 else if ((whichreg
== &AXREG (1) || whichreg
== &AXREG (0)) && (value
& 0x80))
1278 /* Sign extend if necessary. */
1279 value
|= 0xFFFFFF00;
1285 get_extended_cycles (SIM_CPU
*cpu
)
1287 return ((bu64
)CYCLES2SHDREG
<< 32) | CYCLESREG
;
1290 /* We can't re-use sim_events_time() because the CYCLES registers may be
1291 written/cleared/reset/stopped/started at any time by software. */
1293 cycles_inc (SIM_CPU
*cpu
, bu32 inc
)
1298 if (!(SYSCFGREG
& SYSCFG_CCEN
))
1301 cycles
= get_extended_cycles (cpu
) + inc
;
1302 SET_CYCLESREG (cycles
);
1303 cycles2
= cycles
>> 32;
1304 if (CYCLES2SHDREG
!= cycles2
)
1305 SET_CYCLES2SHDREG (cycles2
);
1309 get_unextended_acc (SIM_CPU
*cpu
, int which
)
1311 return ((bu64
)(AXREG (which
) & 0xff) << 32) | AWREG (which
);
1315 get_extended_acc (SIM_CPU
*cpu
, int which
)
1317 bu64 acc
= AXREG (which
);
1318 /* Sign extend accumulator values before adding. */
1324 acc
|= AWREG (which
);
1328 /* Perform a multiplication of D registers SRC0 and SRC1, sign- or
1329 zero-extending the result to 64 bit. H0 and H1 determine whether the
1330 high part or the low part of the source registers is used. Store 1 in
1331 *PSAT if saturation occurs, 0 otherwise. */
1333 decode_multfunc (SIM_CPU
*cpu
, int h0
, int h1
, int src0
, int src1
, int mmod
,
1336 bu32 s0
= DREG (src0
), s1
= DREG (src1
);
1350 sgn0
= -(s0
& 0x8000);
1351 sgn1
= -(s1
& 0x8000);
1373 illegal_instruction (cpu
);
1377 /* Perform shift correction if appropriate for the mode. */
1379 if (!MM
&& (mmod
== 0 || mmod
== M_T
|| mmod
== M_S2RND
|| mmod
== M_W32
))
1381 if (val
== 0x40000000)
1394 /* In signed modes, sign extend. */
1395 if (is_macmod_signed (mmod
) || MM
)
1396 val1
|= -(val1
& 0x80000000);
1399 val1
&= 0xFFFFFFFFull
;
1405 saturate_s40_astat (bu64 val
, bu32
*v
)
1407 if ((bs64
)val
< -((bs64
)1 << 39))
1410 return -((bs64
)1 << 39);
1412 else if ((bs64
)val
> ((bs64
)1 << 39) - 1)
1415 return ((bu64
)1 << 39) - 1;
1417 *v
= 0; /* No overflow. */
1422 saturate_s40 (bu64 val
)
1425 return saturate_s40_astat (val
, &v
);
1429 saturate_s32 (bu64 val
, bu32
*overflow
)
1431 if ((bs64
)val
< -0x80000000ll
)
1437 if ((bs64
)val
> 0x7fffffff)
1447 saturate_u32 (bu64 val
, bu32
*overflow
)
1449 if (val
> 0xffffffff)
1459 saturate_u16 (bu64 val
, bu32
*overflow
)
1475 /* FIXME: Should honour rounding mode. */
1476 if ((val
& 0xffff) > 0x8000
1477 || ((val
& 0xffff) == 0x8000 && (val
& 0x10000)))
1480 sgnbits
= val
& 0xffff000000000000ull
;
1482 return val
| sgnbits
;
1488 bu64 sgnbits
= val
& 0xffff000000000000ull
;
1490 return val
| sgnbits
;
1494 signbits (bu64 val
, int size
)
1496 bu64 mask
= (bu64
)1 << (size
- 1);
1497 bu64 bit
= val
& mask
;
1505 if ((val
& mask
) != bit
)
1515 /* Extract a 16 or 32 bit value from a 64 bit multiplication result.
1516 These 64 bits must be sign- or zero-extended properly from the source
1517 we want to extract, either a 32 bit multiply or a 40 bit accumulator. */
1520 extract_mult (SIM_CPU
*cpu
, bu64 res
, int mmod
, int MM
,
1521 int fullword
, bu32
*overflow
)
1528 return saturate_s32 (res
, overflow
);
1531 return saturate_s32 (res
, overflow
);
1532 return saturate_u32 (res
, overflow
);
1535 return saturate_s32 (res
, overflow
);
1536 return saturate_u32 (res
, overflow
);
1539 return saturate_s32 (res
<< 1, overflow
);
1541 illegal_instruction (cpu
);
1549 return saturate_s16 (rnd16 (res
), overflow
);
1551 return saturate_s16 (res
, overflow
);
1554 return saturate_s16 (rnd16 (res
), overflow
);
1555 return saturate_u16 (rnd16 (res
), overflow
);
1558 return saturate_s16 (res
, overflow
);
1559 return saturate_u16 (res
, overflow
);
1562 return saturate_s16 (trunc16 (res
), overflow
);
1565 return saturate_s16 (trunc16 (res
), overflow
);
1566 return saturate_u16 (trunc16 (res
), overflow
);
1569 return saturate_s16 (rnd16 (res
<< 1), overflow
);
1571 return saturate_s16 (res
<< 1, overflow
);
1573 illegal_instruction (cpu
);
1578 decode_macfunc (SIM_CPU
*cpu
, int which
, int op
, int h0
, int h1
, int src0
,
1579 int src1
, int mmod
, int MM
, int fullword
, bu32
*overflow
,
1583 bu32 sat
= 0, tsat
, ret
;
1585 /* Sign extend accumulator if necessary, otherwise unsigned. */
1586 if (is_macmod_signed (mmod
) || MM
)
1587 acc
= get_extended_acc (cpu
, which
);
1589 acc
= get_unextended_acc (cpu
, which
);
1593 bu8 sgn0
= (acc
>> 31) & 1;
1594 bu8 sgn40
= (acc
>> 39) & 1;
1597 /* This can't saturate, so we don't keep track of the sat flag. */
1598 bu64 res
= decode_multfunc (cpu
, h0
, h1
, src0
, src1
, mmod
,
1601 /* Perform accumulation. */
1606 sgn0
= (acc
>> 31) & 1;
1625 if ((bs64
)acc
< -((bs64
)1 << 39))
1626 acc
= -((bu64
)1 << 39), sat
= 1;
1627 else if ((bs64
)acc
> 0x7fffffffffll
)
1628 acc
= 0x7fffffffffull
, sat
= 1;
1633 if ((bs64
)acc
< -((bs64
)1 << 39))
1634 acc
= -((bu64
)1 << 39), sat
= 1;
1635 if ((bs64
)acc
> 0x7FFFFFFFFFll
)
1636 acc
= 0x7FFFFFFFFFull
, sat
= 1;
1642 if ((bs64
)acc
> 0xFFFFFFFFFFull
)
1643 acc
= 0xFFFFFFFFFFull
, sat
= 1;
1647 if (!MM
&& acc
& 0x8000000000000000ull
)
1649 if (!MM
&& acc
> 0xFFFFFFFFFFull
)
1650 acc
= 0xFFFFFFFFFFull
, sat
= 1;
1651 if (MM
&& acc
> 0xFFFFFFFFFFull
)
1652 acc
&= 0xFFFFFFFFFFull
;
1653 if (acc
& 0x8000000000ull
)
1654 acc
|= 0xffffff0000000000ull
;
1659 if ((bs64
)acc
< -((bs64
)1 << 39))
1660 acc
= -((bu64
)1 << 39), sat
= 1;
1661 if ((bs64
)acc
> 0x7FFFFFFFFFll
)
1662 acc
= 0x7FFFFFFFFFull
, sat
= 1;
1663 else if (acc
& 0x8000000000ull
)
1664 acc
|= 0xffffff0000000000ull
;
1670 else if ((bs64
)acc
> (bs64
)0xFFFFFFFFFFll
)
1671 acc
= 0xFFFFFFFFFFull
, sat
= 1;
1675 if ((bs64
)acc
< -0x80000000ll
)
1676 acc
= -0x80000000ull
, sat
= 1;
1677 else if ((bs64
)acc
> 0x7fffffffll
)
1678 acc
= 0x7fffffffull
, sat
= 1;
1681 /* check max negative value */
1682 if (sgn40
&& ((acc
>> 31) != 0x1ffffffff)
1683 && ((acc
>> 31) != 0x0))
1684 acc
= 0x80000000, sat
= 1;
1685 if (!sat
&& !sgn40
&& ((acc
>> 31) != 0x0)
1686 && ((acc
>> 31) != 0x1ffffffff))
1687 acc
= 0x7FFFFFFF, sat
= 1;
1689 if (acc
& 0x80000000)
1690 acc
|= 0xffffffff00000000ull
;
1695 illegal_instruction (cpu
);
1698 if (acc
& 0x8000000000ull
)
1701 STORE (AXREG (which
), (acc
>> 32) & 0xff);
1702 STORE (AWREG (which
), acc
& 0xffffffff);
1703 STORE (ASTATREG (av
[which
]), sat
);
1705 STORE (ASTATREG (avs
[which
]), sat
);
1707 /* Figure out the overflow bit. */
1713 ret
= extract_mult (cpu
, nosat_acc
, mmod
, MM
, fullword
, overflow
);
1717 ret
= extract_mult (cpu
, acc
, mmod
, MM
, fullword
, overflow
);
1726 if (ret
& 0x80000000)
1734 hwloop_get_next_pc (SIM_CPU
*cpu
, bu32 pc
, bu32 insn_len
)
1741 /* If our PC has reached the bottom of a hardware loop,
1742 move back up to the top of the hardware loop. */
1743 for (i
= 1; i
>= 0; --i
)
1744 if (LCREG (i
) > 1 && pc
== LBREG (i
))
1746 BFIN_TRACE_BRANCH (cpu
, pc
, LTREG (i
), i
, "Hardware loop %i", i
);
1750 return pc
+ insn_len
;
1754 decode_ProgCtrl_0 (SIM_CPU
*cpu
, bu16 iw0
, bu32 pc
)
1757 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
1758 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |.prgfunc.......|.poprnd........|
1759 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
1760 int poprnd
= ((iw0
>> ProgCtrl_poprnd_bits
) & ProgCtrl_poprnd_mask
);
1761 int prgfunc
= ((iw0
>> ProgCtrl_prgfunc_bits
) & ProgCtrl_prgfunc_mask
);
1763 TRACE_EXTRACT (cpu
, "%s: poprnd:%i prgfunc:%i", __func__
, poprnd
, prgfunc
);
1765 if (prgfunc
== 0 && poprnd
== 0)
1767 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_nop
);
1768 TRACE_INSN (cpu
, "NOP;");
1770 else if (prgfunc
== 1 && poprnd
== 0)
1772 bu32 newpc
= RETSREG
;
1773 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1774 TRACE_INSN (cpu
, "RTS;");
1775 IFETCH_CHECK (newpc
);
1776 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1777 illegal_instruction_combination (cpu
);
1778 BFIN_TRACE_BRANCH (cpu
, pc
, newpc
, -1, "RTS");
1780 BFIN_CPU_STATE
.did_jump
= true;
1783 else if (prgfunc
== 1 && poprnd
== 1)
1785 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1786 TRACE_INSN (cpu
, "RTI;");
1787 /* Do not do IFETCH_CHECK here -- LSB has special meaning. */
1788 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1789 illegal_instruction_combination (cpu
);
1790 cec_return (cpu
, -1);
1793 else if (prgfunc
== 1 && poprnd
== 2)
1795 bu32 newpc
= RETXREG
;
1796 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1797 TRACE_INSN (cpu
, "RTX;");
1798 /* XXX: Not sure if this is what the hardware does. */
1799 IFETCH_CHECK (newpc
);
1800 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1801 illegal_instruction_combination (cpu
);
1802 cec_return (cpu
, IVG_EVX
);
1805 else if (prgfunc
== 1 && poprnd
== 3)
1807 bu32 newpc
= RETNREG
;
1808 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1809 TRACE_INSN (cpu
, "RTN;");
1810 /* XXX: Not sure if this is what the hardware does. */
1811 IFETCH_CHECK (newpc
);
1812 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1813 illegal_instruction_combination (cpu
);
1814 cec_return (cpu
, IVG_NMI
);
1817 else if (prgfunc
== 1 && poprnd
== 4)
1819 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1820 TRACE_INSN (cpu
, "RTE;");
1821 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1822 illegal_instruction_combination (cpu
);
1823 cec_return (cpu
, IVG_EMU
);
1826 else if (prgfunc
== 2 && poprnd
== 0)
1828 SIM_DESC sd
= CPU_STATE (cpu
);
1829 sim_events
*events
= STATE_EVENTS (sd
);
1831 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_sync
);
1832 /* XXX: in supervisor mode, utilizes wake up sources
1833 in user mode, it's a NOP ... */
1834 TRACE_INSN (cpu
, "IDLE;");
1836 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1837 illegal_instruction_combination (cpu
);
1841 CYCLE_DELAY
= events
->time_from_event
;
1843 abort (); /* XXX: Should this ever happen ? */
1845 else if (prgfunc
== 2 && poprnd
== 3)
1847 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_sync
);
1849 TRACE_INSN (cpu
, "CSYNC;");
1850 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1851 illegal_instruction_combination (cpu
);
1854 else if (prgfunc
== 2 && poprnd
== 4)
1856 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_sync
);
1858 TRACE_INSN (cpu
, "SSYNC;");
1859 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1860 illegal_instruction_combination (cpu
);
1862 /* Really 10+, but no model info for this. */
1865 else if (prgfunc
== 2 && poprnd
== 5)
1867 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1868 TRACE_INSN (cpu
, "EMUEXCPT;");
1869 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1870 illegal_instruction_combination (cpu
);
1871 cec_exception (cpu
, VEC_SIM_TRAP
);
1873 else if (prgfunc
== 3 && poprnd
< 8)
1875 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1876 TRACE_INSN (cpu
, "CLI R%i;", poprnd
);
1877 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1878 illegal_instruction_combination (cpu
);
1879 SET_DREG (poprnd
, cec_cli (cpu
));
1881 else if (prgfunc
== 4 && poprnd
< 8)
1883 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1884 TRACE_INSN (cpu
, "STI R%i;", poprnd
);
1885 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1886 illegal_instruction_combination (cpu
);
1887 cec_sti (cpu
, DREG (poprnd
));
1890 else if (prgfunc
== 5 && poprnd
< 8)
1892 bu32 newpc
= PREG (poprnd
);
1893 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1894 TRACE_INSN (cpu
, "JUMP (%s);", get_preg_name (poprnd
));
1895 IFETCH_CHECK (newpc
);
1896 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1897 illegal_instruction_combination (cpu
);
1898 BFIN_TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP (Preg)");
1900 BFIN_CPU_STATE
.did_jump
= true;
1901 PROFILE_BRANCH_TAKEN (cpu
);
1904 else if (prgfunc
== 6 && poprnd
< 8)
1906 bu32 newpc
= PREG (poprnd
);
1907 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1908 TRACE_INSN (cpu
, "CALL (%s);", get_preg_name (poprnd
));
1909 IFETCH_CHECK (newpc
);
1910 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1911 illegal_instruction_combination (cpu
);
1912 BFIN_TRACE_BRANCH (cpu
, pc
, newpc
, -1, "CALL (Preg)");
1913 /* If we're at the end of a hardware loop, RETS is going to be
1914 the top of the loop rather than the next instruction. */
1915 SET_RETSREG (hwloop_get_next_pc (cpu
, pc
, 2));
1917 BFIN_CPU_STATE
.did_jump
= true;
1918 PROFILE_BRANCH_TAKEN (cpu
);
1921 else if (prgfunc
== 7 && poprnd
< 8)
1923 bu32 newpc
= pc
+ PREG (poprnd
);
1924 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1925 TRACE_INSN (cpu
, "CALL (PC + %s);", get_preg_name (poprnd
));
1926 IFETCH_CHECK (newpc
);
1927 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1928 illegal_instruction_combination (cpu
);
1929 BFIN_TRACE_BRANCH (cpu
, pc
, newpc
, -1, "CALL (PC + Preg)");
1930 SET_RETSREG (hwloop_get_next_pc (cpu
, pc
, 2));
1932 BFIN_CPU_STATE
.did_jump
= true;
1933 PROFILE_BRANCH_TAKEN (cpu
);
1936 else if (prgfunc
== 8 && poprnd
< 8)
1938 bu32 newpc
= pc
+ PREG (poprnd
);
1939 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1940 TRACE_INSN (cpu
, "JUMP (PC + %s);", get_preg_name (poprnd
));
1941 IFETCH_CHECK (newpc
);
1942 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1943 illegal_instruction_combination (cpu
);
1944 BFIN_TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP (PC + Preg)");
1946 BFIN_CPU_STATE
.did_jump
= true;
1947 PROFILE_BRANCH_TAKEN (cpu
);
1950 else if (prgfunc
== 9)
1952 int raise
= uimm4 (poprnd
);
1953 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1954 TRACE_INSN (cpu
, "RAISE %s;", uimm4_str (raise
));
1955 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1956 illegal_instruction_combination (cpu
);
1957 cec_require_supervisor (cpu
);
1958 if (raise
== IVG_IVHW
)
1959 cec_hwerr (cpu
, HWERR_RAISE_5
);
1961 cec_latch (cpu
, raise
);
1962 CYCLE_DELAY
= 3; /* XXX: Only if IVG is unmasked. */
1964 else if (prgfunc
== 10)
1966 int excpt
= uimm4 (poprnd
);
1967 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1968 TRACE_INSN (cpu
, "EXCPT %s;", uimm4_str (excpt
));
1969 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1970 illegal_instruction_combination (cpu
);
1971 cec_exception (cpu
, excpt
);
1974 else if (prgfunc
== 11 && poprnd
< 6)
1976 bu32 addr
= PREG (poprnd
);
1978 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_atomic
);
1979 TRACE_INSN (cpu
, "TESTSET (%s);", get_preg_name (poprnd
));
1980 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1981 illegal_instruction_combination (cpu
);
1982 byte
= GET_WORD (addr
);
1983 SET_CCREG (byte
== 0);
1984 PUT_BYTE (addr
, byte
| 0x80);
1985 /* Also includes memory stalls, but we don't model that. */
1989 illegal_instruction_or_combination (cpu
);
1993 decode_CaCTRL_0 (SIM_CPU
*cpu
, bu16 iw0
)
1996 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
1997 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 |.a.|.op....|.reg.......|
1998 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
1999 int a
= ((iw0
>> CaCTRL_a_bits
) & CaCTRL_a_mask
);
2000 int op
= ((iw0
>> CaCTRL_op_bits
) & CaCTRL_op_mask
);
2001 int reg
= ((iw0
>> CaCTRL_reg_bits
) & CaCTRL_reg_mask
);
2002 bu32 preg
= PREG (reg
);
2003 const char * const sinsn
[] = { "PREFETCH", "FLUSHINV", "FLUSH", "IFLUSH", };
2005 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CaCTRL
);
2006 TRACE_EXTRACT (cpu
, "%s: a:%i op:%i reg:%i", __func__
, a
, op
, reg
);
2007 TRACE_INSN (cpu
, "%s [%s%s];", sinsn
[op
], get_preg_name (reg
), a
? "++" : "");
2009 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2010 /* None of these can be part of a parallel instruction. */
2011 illegal_instruction_combination (cpu
);
2013 /* No cache simulation, so these are (mostly) all NOPs.
2014 XXX: The hardware takes care of masking to cache lines, but need
2015 to check behavior of the post increment. Should we be aligning
2016 the value to the cache line before adding the cache line size, or
2017 do we just add the cache line size ? */
2020 mmu_check_cache_addr (cpu
, preg
, false, false);
2024 mmu_check_cache_addr (cpu
, preg
, true, false);
2028 mmu_check_cache_addr (cpu
, preg
, true, false);
2032 mmu_check_cache_addr (cpu
, preg
, false, true);
2036 SET_PREG (reg
, preg
+ BFIN_L1_CACHE_BYTES
);
2040 decode_PushPopReg_0 (SIM_CPU
*cpu
, bu16 iw0
)
2043 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2044 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |.W.|.grp.......|.reg.......|
2045 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2046 int W
= ((iw0
>> PushPopReg_W_bits
) & PushPopReg_W_mask
);
2047 int grp
= ((iw0
>> PushPopReg_grp_bits
) & PushPopReg_grp_mask
);
2048 int reg
= ((iw0
>> PushPopReg_reg_bits
) & PushPopReg_reg_mask
);
2049 const char *reg_name
= get_allreg_name (grp
, reg
);
2053 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_PushPopReg
);
2054 TRACE_EXTRACT (cpu
, "%s: W:%i grp:%i reg:%i", __func__
, W
, grp
, reg
);
2055 TRACE_DECODE (cpu
, "%s: reg:%s", __func__
, reg_name
);
2057 /* Can't push/pop reserved registers */
2058 if (reg_is_reserved (grp
, reg
))
2059 illegal_instruction_or_combination (cpu
);
2063 /* Dreg and Preg are not supported by this instruction. */
2064 if (grp
== 0 || grp
== 1)
2065 illegal_instruction_or_combination (cpu
);
2066 TRACE_INSN (cpu
, "%s = [SP++];", reg_name
);
2067 /* Can't pop USP while in userspace. */
2068 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
2069 || (grp
== 7 && reg
== 0 && cec_is_user_mode(cpu
)))
2070 illegal_instruction_combination (cpu
);
2071 /* XXX: The valid register check is in reg_write(), so we might
2072 incorrectly do a GET_LONG() here ... */
2073 value
= GET_LONG (sp
);
2074 reg_write (cpu
, grp
, reg
, value
);
2075 if (grp
== 7 && reg
== 3)
2082 TRACE_INSN (cpu
, "[--SP] = %s;", reg_name
);
2083 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2084 illegal_instruction_combination (cpu
);
2087 value
= reg_read (cpu
, grp
, reg
);
2088 if (grp
== 7 && reg
== 3)
2089 cec_push_reti (cpu
);
2091 PUT_LONG (sp
, value
);
2094 /* Note: SP update must be delayed until after all reads/writes; see
2095 comments in decode_PushPopMultiple_0() for more info. */
2100 decode_PushPopMultiple_0 (SIM_CPU
*cpu
, bu16 iw0
)
2103 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2104 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |.d.|.p.|.W.|.dr........|.pr........|
2105 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2106 int p
= ((iw0
>> PushPopMultiple_p_bits
) & PushPopMultiple_p_mask
);
2107 int d
= ((iw0
>> PushPopMultiple_d_bits
) & PushPopMultiple_d_mask
);
2108 int W
= ((iw0
>> PushPopMultiple_W_bits
) & PushPopMultiple_W_mask
);
2109 int dr
= ((iw0
>> PushPopMultiple_dr_bits
) & PushPopMultiple_dr_mask
);
2110 int pr
= ((iw0
>> PushPopMultiple_pr_bits
) & PushPopMultiple_pr_mask
);
2114 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_PushPopMultiple
);
2115 TRACE_EXTRACT (cpu
, "%s: d:%i p:%i W:%i dr:%i pr:%i",
2116 __func__
, d
, p
, W
, dr
, pr
);
2118 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2119 illegal_instruction_combination (cpu
);
2121 if ((d
== 0 && p
== 0) || (p
&& imm5 (pr
) > 5)
2122 || (d
&& !p
&& pr
) || (p
&& !d
&& dr
))
2123 illegal_instruction (cpu
);
2128 TRACE_INSN (cpu
, "[--SP] = (R7:%i, P5:%i);", dr
, pr
);
2130 TRACE_INSN (cpu
, "[--SP] = (R7:%i);", dr
);
2132 TRACE_INSN (cpu
, "[--SP] = (P5:%i);", pr
);
2135 for (i
= dr
; i
< 8; i
++)
2138 PUT_LONG (sp
, DREG (i
));
2141 for (i
= pr
; i
< 6; i
++)
2144 PUT_LONG (sp
, PREG (i
));
2152 TRACE_INSN (cpu
, "(R7:%i, P5:%i) = [SP++];", dr
, pr
);
2154 TRACE_INSN (cpu
, "(R7:%i) = [SP++];", dr
);
2156 TRACE_INSN (cpu
, "(P5:%i) = [SP++];", pr
);
2159 for (i
= 5; i
>= pr
; i
--)
2161 SET_PREG (i
, GET_LONG (sp
));
2165 for (i
= 7; i
>= dr
; i
--)
2167 SET_DREG (i
, GET_LONG (sp
));
2174 /* Note: SP update must be delayed until after all reads/writes so that
2175 if an exception does occur, the insn may be re-executed as the
2176 SP has not yet changed. */
2181 decode_ccMV_0 (SIM_CPU
*cpu
, bu16 iw0
)
2184 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2185 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |.T.|.d.|.s.|.dst.......|.src.......|
2186 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2187 int s
= ((iw0
>> CCmv_s_bits
) & CCmv_s_mask
);
2188 int d
= ((iw0
>> CCmv_d_bits
) & CCmv_d_mask
);
2189 int T
= ((iw0
>> CCmv_T_bits
) & CCmv_T_mask
);
2190 int src
= ((iw0
>> CCmv_src_bits
) & CCmv_src_mask
);
2191 int dst
= ((iw0
>> CCmv_dst_bits
) & CCmv_dst_mask
);
2192 int cond
= T
? CCREG
: ! CCREG
;
2194 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ccMV
);
2195 TRACE_EXTRACT (cpu
, "%s: T:%i d:%i s:%i dst:%i src:%i",
2196 __func__
, T
, d
, s
, dst
, src
);
2198 TRACE_INSN (cpu
, "IF %sCC %s = %s;", T
? "" : "! ",
2199 get_allreg_name (d
, dst
),
2200 get_allreg_name (s
, src
));
2201 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2202 illegal_instruction_combination (cpu
);
2205 reg_write (cpu
, d
, dst
, reg_read (cpu
, s
, src
));
2209 decode_CCflag_0 (SIM_CPU
*cpu
, bu16 iw0
)
2212 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2213 | 0 | 0 | 0 | 0 | 1 |.I.|.opc.......|.G.|.y.........|.x.........|
2214 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2215 int x
= ((iw0
>> CCflag_x_bits
) & CCflag_x_mask
);
2216 int y
= ((iw0
>> CCflag_y_bits
) & CCflag_y_mask
);
2217 int I
= ((iw0
>> CCflag_I_bits
) & CCflag_I_mask
);
2218 int G
= ((iw0
>> CCflag_G_bits
) & CCflag_G_mask
);
2219 int opc
= ((iw0
>> CCflag_opc_bits
) & CCflag_opc_mask
);
2221 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CCflag
);
2222 TRACE_EXTRACT (cpu
, "%s: I:%i opc:%i G:%i y:%i x:%i",
2223 __func__
, I
, opc
, G
, y
, x
);
2227 bs64 acc0
= get_extended_acc (cpu
, 0);
2228 bs64 acc1
= get_extended_acc (cpu
, 1);
2229 bs64 diff
= acc0
- acc1
;
2231 if (x
!= 0 || y
!= 0)
2232 illegal_instruction_or_combination (cpu
);
2234 if (opc
== 5 && I
== 0 && G
== 0)
2236 TRACE_INSN (cpu
, "CC = A0 == A1;");
2237 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2238 illegal_instruction_combination (cpu
);
2239 SET_CCREG (acc0
== acc1
);
2241 else if (opc
== 6 && I
== 0 && G
== 0)
2243 TRACE_INSN (cpu
, "CC = A0 < A1");
2244 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2245 illegal_instruction_combination (cpu
);
2246 SET_CCREG (acc0
< acc1
);
2248 else if (opc
== 7 && I
== 0 && G
== 0)
2250 TRACE_INSN (cpu
, "CC = A0 <= A1");
2251 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2252 illegal_instruction_combination (cpu
);
2253 SET_CCREG (acc0
<= acc1
);
2256 illegal_instruction_or_combination (cpu
);
2258 SET_ASTATREG (az
, diff
== 0);
2259 SET_ASTATREG (an
, diff
< 0);
2260 SET_ASTATREG (ac0
, (bu40
)acc1
<= (bu40
)acc0
);
2264 int issigned
= opc
< 3;
2265 const char *sign
= issigned
? "" : " (IU)";
2266 bu32 srcop
= G
? PREG (x
) : DREG (x
);
2267 char s
= G
? 'P' : 'R';
2268 bu32 dstop
= I
? (issigned
? imm3 (y
) : uimm3 (y
)) : G
? PREG (y
) : DREG (y
);
2270 char d
= G
? 'P' : 'R';
2271 int flgs
= srcop
>> 31;
2272 int flgo
= dstop
>> 31;
2274 bu32 result
= srcop
- dstop
;
2276 int flgn
= result
>> 31;
2277 int overflow
= (flgs
^ flgo
) & (flgn
^ flgs
);
2278 int az
= result
== 0;
2279 int ac0
= dstop
<= srcop
;
2282 an
= (flgn
&& !overflow
) || (!flgn
&& overflow
);
2288 default: /* Shutup useless gcc warnings. */
2289 case 0: /* signed */
2293 case 1: /* signed */
2297 case 2: /* signed */
2301 case 3: /* unsigned */
2305 case 4: /* unsigned */
2312 TRACE_INSN (cpu
, "CC = %c%i %s %s%s;", s
, x
, op
,
2313 issigned
? imm3_str (y
) : uimm3_str (y
), sign
);
2316 TRACE_DECODE (cpu
, "%s %c%i:%x %c%i:%x", __func__
,
2317 s
, x
, srcop
, d
, y
, dstop
);
2318 TRACE_INSN (cpu
, "CC = %c%i %s %c%i%s;", s
, x
, op
, d
, y
, sign
);
2321 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2322 illegal_instruction_combination (cpu
);
2325 /* Pointer compares only touch CC. */
2328 SET_ASTATREG (az
, az
);
2329 SET_ASTATREG (an
, an
);
2330 SET_ASTATREG (ac0
, ac0
);
2336 decode_CC2dreg_0 (SIM_CPU
*cpu
, bu16 iw0
)
2339 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2340 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |.op....|.reg.......|
2341 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2342 int op
= ((iw0
>> CC2dreg_op_bits
) & CC2dreg_op_mask
);
2343 int reg
= ((iw0
>> CC2dreg_reg_bits
) & CC2dreg_reg_mask
);
2345 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CC2dreg
);
2346 TRACE_EXTRACT (cpu
, "%s: op:%i reg:%i", __func__
, op
, reg
);
2350 TRACE_INSN (cpu
, "R%i = CC;", reg
);
2351 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2352 illegal_instruction_combination (cpu
);
2353 SET_DREG (reg
, CCREG
);
2357 TRACE_INSN (cpu
, "CC = R%i;", reg
);
2358 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2359 illegal_instruction_combination (cpu
);
2360 SET_CCREG (DREG (reg
) != 0);
2362 else if (op
== 3 && reg
== 0)
2364 TRACE_INSN (cpu
, "CC = !CC;");
2365 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2366 illegal_instruction_combination (cpu
);
2370 illegal_instruction_or_combination (cpu
);
2374 decode_CC2stat_0 (SIM_CPU
*cpu
, bu16 iw0
)
2377 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2378 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |.D.|.op....|.cbit..............|
2379 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2380 int D
= ((iw0
>> CC2stat_D_bits
) & CC2stat_D_mask
);
2381 int op
= ((iw0
>> CC2stat_op_bits
) & CC2stat_op_mask
);
2382 int cbit
= ((iw0
>> CC2stat_cbit_bits
) & CC2stat_cbit_mask
);
2385 const char * const op_names
[] = { "", "|", "&", "^" } ;
2387 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CC2stat
);
2388 TRACE_EXTRACT (cpu
, "%s: D:%i op:%i cbit:%i", __func__
, D
, op
, cbit
);
2390 TRACE_INSN (cpu
, "%s %s= %s;", D
? astat_names
[cbit
] : "CC",
2391 op_names
[op
], D
? "CC" : astat_names
[cbit
]);
2393 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2394 illegal_instruction_combination (cpu
);
2396 /* CC = CC; is invalid. */
2398 illegal_instruction (cpu
);
2400 pval
= !!(ASTAT
& (1 << cbit
));
2404 case 0: SET_CCREG (pval
); break;
2405 case 1: SET_CCREG (CCREG
| pval
); break;
2406 case 2: SET_CCREG (CCREG
& pval
); break;
2407 case 3: SET_CCREG (CCREG
^ pval
); break;
2413 case 0: pval
= CCREG
; break;
2414 case 1: pval
|= CCREG
; break;
2415 case 2: pval
&= CCREG
; break;
2416 case 3: pval
^= CCREG
; break;
2418 TRACE_REGISTER (cpu
, "wrote ASTAT[%s] = %i", astat_names
[cbit
], pval
);
2419 SET_ASTAT ((ASTAT
& ~(1 << cbit
)) | (pval
<< cbit
));
2424 decode_BRCC_0 (SIM_CPU
*cpu
, bu16 iw0
, bu32 pc
)
2427 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2428 | 0 | 0 | 0 | 1 |.T.|.B.|.offset................................|
2429 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2430 int B
= ((iw0
>> BRCC_B_bits
) & BRCC_B_mask
);
2431 int T
= ((iw0
>> BRCC_T_bits
) & BRCC_T_mask
);
2432 int offset
= ((iw0
>> BRCC_offset_bits
) & BRCC_offset_mask
);
2433 int cond
= T
? CCREG
: ! CCREG
;
2434 int pcrel
= pcrel10 (offset
);
2436 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_BRCC
);
2437 TRACE_EXTRACT (cpu
, "%s: T:%i B:%i offset:%#x", __func__
, T
, B
, offset
);
2438 TRACE_DECODE (cpu
, "%s: pcrel10:%#x", __func__
, pcrel
);
2440 TRACE_INSN (cpu
, "IF %sCC JUMP %#x%s;", T
? "" : "! ",
2441 pcrel
, B
? " (bp)" : "");
2443 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2444 illegal_instruction_combination (cpu
);
2448 bu32 newpc
= pc
+ pcrel
;
2449 BFIN_TRACE_BRANCH (cpu
, pc
, newpc
, -1, "Conditional JUMP");
2451 BFIN_CPU_STATE
.did_jump
= true;
2452 PROFILE_BRANCH_TAKEN (cpu
);
2453 CYCLE_DELAY
= B
? 5 : 9;
2457 PROFILE_BRANCH_UNTAKEN (cpu
);
2458 CYCLE_DELAY
= B
? 9 : 1;
2463 decode_UJUMP_0 (SIM_CPU
*cpu
, bu16 iw0
, bu32 pc
)
2466 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2467 | 0 | 0 | 1 | 0 |.offset........................................|
2468 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2469 int offset
= ((iw0
>> UJump_offset_bits
) & UJump_offset_mask
);
2470 int pcrel
= pcrel12 (offset
);
2471 bu32 newpc
= pc
+ pcrel
;
2473 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_UJUMP
);
2474 TRACE_EXTRACT (cpu
, "%s: offset:%#x", __func__
, offset
);
2475 TRACE_DECODE (cpu
, "%s: pcrel12:%#x", __func__
, pcrel
);
2477 TRACE_INSN (cpu
, "JUMP.S %#x;", pcrel
);
2479 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2480 illegal_instruction_combination (cpu
);
2482 BFIN_TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP.S");
2485 BFIN_CPU_STATE
.did_jump
= true;
2486 PROFILE_BRANCH_TAKEN (cpu
);
2491 decode_REGMV_0 (SIM_CPU
*cpu
, bu16 iw0
)
2494 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2495 | 0 | 0 | 1 | 1 |.gd........|.gs........|.dst.......|.src.......|
2496 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2497 int gs
= ((iw0
>> RegMv_gs_bits
) & RegMv_gs_mask
);
2498 int gd
= ((iw0
>> RegMv_gd_bits
) & RegMv_gd_mask
);
2499 int src
= ((iw0
>> RegMv_src_bits
) & RegMv_src_mask
);
2500 int dst
= ((iw0
>> RegMv_dst_bits
) & RegMv_dst_mask
);
2501 const char *srcreg_name
= get_allreg_name (gs
, src
);
2502 const char *dstreg_name
= get_allreg_name (gd
, dst
);
2504 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_REGMV
);
2505 TRACE_EXTRACT (cpu
, "%s: gd:%i gs:%i dst:%i src:%i",
2506 __func__
, gd
, gs
, dst
, src
);
2507 TRACE_DECODE (cpu
, "%s: dst:%s src:%s", __func__
, dstreg_name
, srcreg_name
);
2509 TRACE_INSN (cpu
, "%s = %s;", dstreg_name
, srcreg_name
);
2511 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2512 illegal_instruction_combination (cpu
);
2514 /* Reserved slots cannot be a src/dst. */
2515 if (reg_is_reserved (gs
, src
) || reg_is_reserved (gd
, dst
))
2518 /* Standard register moves. */
2519 if ((gs
< 2) /* Dregs/Pregs src */
2520 || (gd
< 2) /* Dregs/Pregs dst */
2521 || (gs
== 4 && src
< 4) /* Accumulators src */
2522 || (gd
== 4 && dst
< 4 && (gs
< 4)) /* Accumulators dst */
2523 || (gs
== 7 && src
== 7 && !(gd
== 4 && dst
< 4)) /* EMUDAT src */
2524 || (gd
== 7 && dst
== 7)) /* EMUDAT dst */
2527 /* dareg = dareg (IMBL) */
2528 if (gs
< 4 && gd
< 4)
2531 /* USP can be src to sysregs, but not dagregs. */
2532 if ((gs
== 7 && src
== 0) && (gd
>= 4))
2535 /* USP can move between genregs (only check Accumulators). */
2536 if (((gs
== 7 && src
== 0) && (gd
== 4 && dst
< 4))
2537 || ((gd
== 7 && dst
== 0) && (gs
== 4 && src
< 4)))
2540 /* Still here ? Invalid reg pair. */
2542 illegal_instruction (cpu
);
2545 reg_write (cpu
, gd
, dst
, reg_read (cpu
, gs
, src
));
2549 decode_ALU2op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2552 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2553 | 0 | 1 | 0 | 0 | 0 | 0 |.opc...........|.src.......|.dst.......|
2554 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2555 int src
= ((iw0
>> ALU2op_src_bits
) & ALU2op_src_mask
);
2556 int opc
= ((iw0
>> ALU2op_opc_bits
) & ALU2op_opc_mask
);
2557 int dst
= ((iw0
>> ALU2op_dst_bits
) & ALU2op_dst_mask
);
2559 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ALU2op
);
2560 TRACE_EXTRACT (cpu
, "%s: opc:%i src:%i dst:%i", __func__
, opc
, src
, dst
);
2562 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2563 illegal_instruction_combination (cpu
);
2567 TRACE_INSN (cpu
, "R%i >>>= R%i;", dst
, src
);
2568 SET_DREG (dst
, ashiftrt (cpu
, DREG (dst
), DREG (src
), 32));
2573 TRACE_INSN (cpu
, "R%i >>= R%i;", dst
, src
);
2574 if (DREG (src
) <= 0x1F)
2575 val
= lshiftrt (cpu
, DREG (dst
), DREG (src
), 32);
2578 SET_DREG (dst
, val
);
2582 TRACE_INSN (cpu
, "R%i <<= R%i;", dst
, src
);
2583 SET_DREG (dst
, lshift (cpu
, DREG (dst
), DREG (src
), 32, 0, 0));
2587 TRACE_INSN (cpu
, "R%i *= R%i;", dst
, src
);
2588 SET_DREG (dst
, DREG (dst
) * DREG (src
));
2593 TRACE_INSN (cpu
, "R%i = (R%i + R%i) << 1;", dst
, dst
, src
);
2594 SET_DREG (dst
, add_and_shift (cpu
, DREG (dst
), DREG (src
), 1));
2598 TRACE_INSN (cpu
, "R%i = (R%i + R%i) << 2;", dst
, dst
, src
);
2599 SET_DREG (dst
, add_and_shift (cpu
, DREG (dst
), DREG (src
), 2));
2603 TRACE_INSN (cpu
, "DIVQ ( R%i, R%i );", dst
, src
);
2604 SET_DREG (dst
, divq (cpu
, DREG (dst
), (bu16
)DREG (src
)));
2608 TRACE_INSN (cpu
, "DIVS ( R%i, R%i );", dst
, src
);
2609 SET_DREG (dst
, divs (cpu
, DREG (dst
), (bu16
)DREG (src
)));
2613 TRACE_INSN (cpu
, "R%i = R%i.L (X);", dst
, src
);
2614 SET_DREG (dst
, (bs32
) (bs16
) DREG (src
));
2615 setflags_logical (cpu
, DREG (dst
));
2619 TRACE_INSN (cpu
, "R%i = R%i.L (Z);", dst
, src
);
2620 SET_DREG (dst
, (bu32
) (bu16
) DREG (src
));
2621 setflags_logical (cpu
, DREG (dst
));
2625 TRACE_INSN (cpu
, "R%i = R%i.B (X);", dst
, src
);
2626 SET_DREG (dst
, (bs32
) (bs8
) DREG (src
));
2627 setflags_logical (cpu
, DREG (dst
));
2631 TRACE_INSN (cpu
, "R%i = R%i.B (Z);", dst
, src
);
2632 SET_DREG (dst
, (bu32
) (bu8
) DREG (src
));
2633 setflags_logical (cpu
, DREG (dst
));
2637 bu32 val
= DREG (src
);
2638 TRACE_INSN (cpu
, "R%i = - R%i;", dst
, src
);
2639 SET_DREG (dst
, -val
);
2640 setflags_nz (cpu
, DREG (dst
));
2641 SET_ASTATREG (v
, val
== 0x80000000);
2643 SET_ASTATREG (vs
, 1);
2644 SET_ASTATREG (ac0
, val
== 0x0);
2645 /* XXX: Documentation isn't entirely clear about av0 and av1. */
2649 TRACE_INSN (cpu
, "R%i = ~ R%i;", dst
, src
);
2650 SET_DREG (dst
, ~DREG (src
));
2651 setflags_logical (cpu
, DREG (dst
));
2654 illegal_instruction (cpu
);
2658 decode_PTR2op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2661 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2662 | 0 | 1 | 0 | 0 | 0 | 1 | 0 |.opc.......|.src.......|.dst.......|
2663 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2664 int src
= ((iw0
>> PTR2op_src_bits
) & PTR2op_dst_mask
);
2665 int opc
= ((iw0
>> PTR2op_opc_bits
) & PTR2op_opc_mask
);
2666 int dst
= ((iw0
>> PTR2op_dst_bits
) & PTR2op_dst_mask
);
2667 const char *src_name
= get_preg_name (src
);
2668 const char *dst_name
= get_preg_name (dst
);
2670 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_PTR2op
);
2671 TRACE_EXTRACT (cpu
, "%s: opc:%i src:%i dst:%i", __func__
, opc
, src
, dst
);
2673 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2674 illegal_instruction_combination (cpu
);
2678 TRACE_INSN (cpu
, "%s -= %s", dst_name
, src_name
);
2679 SET_PREG (dst
, PREG (dst
) - PREG (src
));
2683 TRACE_INSN (cpu
, "%s = %s << 2", dst_name
, src_name
);
2684 SET_PREG (dst
, PREG (src
) << 2);
2688 TRACE_INSN (cpu
, "%s = %s >> 2", dst_name
, src_name
);
2689 SET_PREG (dst
, PREG (src
) >> 2);
2693 TRACE_INSN (cpu
, "%s = %s >> 1", dst_name
, src_name
);
2694 SET_PREG (dst
, PREG (src
) >> 1);
2698 TRACE_INSN (cpu
, "%s += %s (BREV)", dst_name
, src_name
);
2699 SET_PREG (dst
, add_brev (PREG (dst
), PREG (src
)));
2703 TRACE_INSN (cpu
, "%s = (%s + %s) << 1", dst_name
, dst_name
, src_name
);
2704 SET_PREG (dst
, (PREG (dst
) + PREG (src
)) << 1);
2708 TRACE_INSN (cpu
, "%s = (%s + %s) << 2", dst_name
, dst_name
, src_name
);
2709 SET_PREG (dst
, (PREG (dst
) + PREG (src
)) << 2);
2712 illegal_instruction (cpu
);
2716 decode_LOGI2op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2719 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2720 | 0 | 1 | 0 | 0 | 1 |.opc.......|.src...............|.dst.......|
2721 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2722 int src
= ((iw0
>> LOGI2op_src_bits
) & LOGI2op_src_mask
);
2723 int opc
= ((iw0
>> LOGI2op_opc_bits
) & LOGI2op_opc_mask
);
2724 int dst
= ((iw0
>> LOGI2op_dst_bits
) & LOGI2op_dst_mask
);
2725 int uimm
= uimm5 (src
);
2726 const char *uimm_str
= uimm5_str (uimm
);
2728 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LOGI2op
);
2729 TRACE_EXTRACT (cpu
, "%s: opc:%i src:%i dst:%i", __func__
, opc
, src
, dst
);
2730 TRACE_DECODE (cpu
, "%s: uimm5:%#x", __func__
, uimm
);
2734 TRACE_INSN (cpu
, "CC = ! BITTST (R%i, %s);", dst
, uimm_str
);
2735 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2736 illegal_instruction_combination (cpu
);
2737 SET_CCREG ((~DREG (dst
) >> uimm
) & 1);
2741 TRACE_INSN (cpu
, "CC = BITTST (R%i, %s);", dst
, uimm_str
);
2742 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2743 illegal_instruction_combination (cpu
);
2744 SET_CCREG ((DREG (dst
) >> uimm
) & 1);
2748 TRACE_INSN (cpu
, "BITSET (R%i, %s);", dst
, uimm_str
);
2749 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2750 illegal_instruction_combination (cpu
);
2751 SET_DREG (dst
, DREG (dst
) | (1 << uimm
));
2752 setflags_logical (cpu
, DREG (dst
));
2756 TRACE_INSN (cpu
, "BITTGL (R%i, %s);", dst
, uimm_str
);
2757 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2758 illegal_instruction_combination (cpu
);
2759 SET_DREG (dst
, DREG (dst
) ^ (1 << uimm
));
2760 setflags_logical (cpu
, DREG (dst
));
2764 TRACE_INSN (cpu
, "BITCLR (R%i, %s);", dst
, uimm_str
);
2765 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2766 illegal_instruction_combination (cpu
);
2767 SET_DREG (dst
, DREG (dst
) & ~(1 << uimm
));
2768 setflags_logical (cpu
, DREG (dst
));
2772 TRACE_INSN (cpu
, "R%i >>>= %s;", dst
, uimm_str
);
2773 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2774 illegal_instruction_combination (cpu
);
2775 SET_DREG (dst
, ashiftrt (cpu
, DREG (dst
), uimm
, 32));
2779 TRACE_INSN (cpu
, "R%i >>= %s;", dst
, uimm_str
);
2780 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2781 illegal_instruction_combination (cpu
);
2782 SET_DREG (dst
, lshiftrt (cpu
, DREG (dst
), uimm
, 32));
2786 TRACE_INSN (cpu
, "R%i <<= %s;", dst
, uimm_str
);
2787 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2788 illegal_instruction_combination (cpu
);
2789 SET_DREG (dst
, lshift (cpu
, DREG (dst
), uimm
, 32, 0, 0));
2794 decode_COMP3op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2797 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2798 | 0 | 1 | 0 | 1 |.opc.......|.dst.......|.src1......|.src0......|
2799 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2800 int opc
= ((iw0
>> COMP3op_opc_bits
) & COMP3op_opc_mask
);
2801 int dst
= ((iw0
>> COMP3op_dst_bits
) & COMP3op_dst_mask
);
2802 int src0
= ((iw0
>> COMP3op_src0_bits
) & COMP3op_src0_mask
);
2803 int src1
= ((iw0
>> COMP3op_src1_bits
) & COMP3op_src1_mask
);
2805 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_COMP3op
);
2806 TRACE_EXTRACT (cpu
, "%s: opc:%i dst:%i src1:%i src0:%i",
2807 __func__
, opc
, dst
, src1
, src0
);
2809 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2810 illegal_instruction_combination (cpu
);
2814 TRACE_INSN (cpu
, "R%i = R%i + R%i;", dst
, src0
, src1
);
2815 SET_DREG (dst
, add32 (cpu
, DREG (src0
), DREG (src1
), 1, 0));
2819 TRACE_INSN (cpu
, "R%i = R%i - R%i;", dst
, src0
, src1
);
2820 SET_DREG (dst
, sub32 (cpu
, DREG (src0
), DREG (src1
), 1, 0, 0));
2824 TRACE_INSN (cpu
, "R%i = R%i & R%i;", dst
, src0
, src1
);
2825 SET_DREG (dst
, DREG (src0
) & DREG (src1
));
2826 setflags_logical (cpu
, DREG (dst
));
2830 TRACE_INSN (cpu
, "R%i = R%i | R%i;", dst
, src0
, src1
);
2831 SET_DREG (dst
, DREG (src0
) | DREG (src1
));
2832 setflags_logical (cpu
, DREG (dst
));
2836 TRACE_INSN (cpu
, "R%i = R%i ^ R%i;", dst
, src0
, src1
);
2837 SET_DREG (dst
, DREG (src0
) ^ DREG (src1
));
2838 setflags_logical (cpu
, DREG (dst
));
2842 int shift
= opc
- 5;
2843 const char *dst_name
= get_preg_name (dst
);
2844 const char *src0_name
= get_preg_name (src0
);
2845 const char *src1_name
= get_preg_name (src1
);
2847 /* If src0 == src1 this is disassembled as a shift by 1, but this
2848 distinction doesn't matter for our purposes. */
2850 TRACE_INSN (cpu
, "%s = (%s + %s) << %#x;",
2851 dst_name
, src0_name
, src1_name
, shift
);
2853 TRACE_INSN (cpu
, "%s = %s + %s",
2854 dst_name
, src0_name
, src1_name
);
2855 SET_PREG (dst
, PREG (src0
) + (PREG (src1
) << shift
));
2860 decode_COMPI2opD_0 (SIM_CPU
*cpu
, bu16 iw0
)
2863 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2864 | 0 | 1 | 1 | 0 | 0 |.op|..src......................|.dst.......|
2865 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2866 int op
= ((iw0
>> COMPI2opD_op_bits
) & COMPI2opD_op_mask
);
2867 int dst
= ((iw0
>> COMPI2opD_dst_bits
) & COMPI2opD_dst_mask
);
2868 int src
= ((iw0
>> COMPI2opD_src_bits
) & COMPI2opD_src_mask
);
2869 int imm
= imm7 (src
);
2871 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_COMPI2opD
);
2872 TRACE_EXTRACT (cpu
, "%s: op:%i src:%i dst:%i", __func__
, op
, src
, dst
);
2873 TRACE_DECODE (cpu
, "%s: imm7:%#x", __func__
, imm
);
2875 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2876 illegal_instruction_combination (cpu
);
2880 TRACE_INSN (cpu
, "R%i = %s (X);", dst
, imm7_str (imm
));
2881 SET_DREG (dst
, imm
);
2885 TRACE_INSN (cpu
, "R%i += %s;", dst
, imm7_str (imm
));
2886 SET_DREG (dst
, add32 (cpu
, DREG (dst
), imm
, 1, 0));
2891 decode_COMPI2opP_0 (SIM_CPU
*cpu
, bu16 iw0
)
2894 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2895 | 0 | 1 | 1 | 0 | 1 |.op|.src.......................|.dst.......|
2896 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2897 int op
= ((iw0
>> COMPI2opP_op_bits
) & COMPI2opP_op_mask
);
2898 int src
= ((iw0
>> COMPI2opP_src_bits
) & COMPI2opP_src_mask
);
2899 int dst
= ((iw0
>> COMPI2opP_dst_bits
) & COMPI2opP_dst_mask
);
2900 int imm
= imm7 (src
);
2901 const char *dst_name
= get_preg_name (dst
);
2903 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_COMPI2opP
);
2904 TRACE_EXTRACT (cpu
, "%s: op:%i src:%i dst:%i", __func__
, op
, src
, dst
);
2905 TRACE_DECODE (cpu
, "%s: imm:%#x", __func__
, imm
);
2907 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2908 illegal_instruction_combination (cpu
);
2912 TRACE_INSN (cpu
, "%s = %s;", dst_name
, imm7_str (imm
));
2913 SET_PREG (dst
, imm
);
2917 TRACE_INSN (cpu
, "%s += %s;", dst_name
, imm7_str (imm
));
2918 SET_PREG (dst
, PREG (dst
) + imm
);
2923 decode_LDSTpmod_0 (SIM_CPU
*cpu
, bu16 iw0
)
2926 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2927 | 1 | 0 | 0 | 0 |.W.|.aop...|.reg.......|.idx.......|.ptr.......|
2928 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2929 int W
= ((iw0
>> LDSTpmod_W_bits
) & LDSTpmod_W_mask
);
2930 int aop
= ((iw0
>> LDSTpmod_aop_bits
) & LDSTpmod_aop_mask
);
2931 int idx
= ((iw0
>> LDSTpmod_idx_bits
) & LDSTpmod_idx_mask
);
2932 int ptr
= ((iw0
>> LDSTpmod_ptr_bits
) & LDSTpmod_ptr_mask
);
2933 int reg
= ((iw0
>> LDSTpmod_reg_bits
) & LDSTpmod_reg_mask
);
2934 const char *ptr_name
= get_preg_name (ptr
);
2935 const char *idx_name
= get_preg_name (idx
);
2938 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTpmod
);
2939 TRACE_EXTRACT (cpu
, "%s: W:%i aop:%i reg:%i idx:%i ptr:%i",
2940 __func__
, W
, aop
, reg
, idx
, ptr
);
2942 if (PARALLEL_GROUP
== BFIN_PARALLEL_GROUP2
)
2943 illegal_instruction_combination (cpu
);
2945 if (aop
== 1 && W
== 0 && idx
== ptr
)
2947 TRACE_INSN (cpu
, "R%i.L = W[%s];", reg
, ptr_name
);
2949 val
= GET_WORD (addr
);
2950 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | val
);
2952 else if (aop
== 2 && W
== 0 && idx
== ptr
)
2954 TRACE_INSN (cpu
, "R%i.H = W[%s];", reg
, ptr_name
);
2956 val
= GET_WORD (addr
);
2957 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (val
<< 16));
2959 else if (aop
== 1 && W
== 1 && idx
== ptr
)
2961 TRACE_INSN (cpu
, "W[%s] = R%i.L;", ptr_name
, reg
);
2963 PUT_WORD (addr
, DREG (reg
));
2965 else if (aop
== 2 && W
== 1 && idx
== ptr
)
2967 TRACE_INSN (cpu
, "W[%s] = R%i.H;", ptr_name
, reg
);
2969 PUT_WORD (addr
, DREG (reg
) >> 16);
2971 else if (aop
== 0 && W
== 0)
2973 TRACE_INSN (cpu
, "R%i = [%s ++ %s];", reg
, ptr_name
, idx_name
);
2975 val
= GET_LONG (addr
);
2976 STORE (DREG (reg
), val
);
2978 STORE (PREG (ptr
), addr
+ PREG (idx
));
2980 else if (aop
== 1 && W
== 0)
2982 TRACE_INSN (cpu
, "R%i.L = W[%s ++ %s];", reg
, ptr_name
, idx_name
);
2984 val
= GET_WORD (addr
);
2985 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | val
);
2987 STORE (PREG (ptr
), addr
+ PREG (idx
));
2989 else if (aop
== 2 && W
== 0)
2991 TRACE_INSN (cpu
, "R%i.H = W[%s ++ %s];", reg
, ptr_name
, idx_name
);
2993 val
= GET_WORD (addr
);
2994 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (val
<< 16));
2996 STORE (PREG (ptr
), addr
+ PREG (idx
));
2998 else if (aop
== 3 && W
== 0)
3000 TRACE_INSN (cpu
, "R%i = W[%s ++ %s] (Z);", reg
, ptr_name
, idx_name
);
3002 val
= GET_WORD (addr
);
3003 STORE (DREG (reg
), val
);
3005 STORE (PREG (ptr
), addr
+ PREG (idx
));
3007 else if (aop
== 3 && W
== 1)
3009 TRACE_INSN (cpu
, "R%i = W[%s ++ %s] (X);", reg
, ptr_name
, idx_name
);
3011 val
= GET_WORD (addr
);
3012 STORE (DREG (reg
), (bs32
) (bs16
) val
);
3014 STORE (PREG (ptr
), addr
+ PREG (idx
));
3016 else if (aop
== 0 && W
== 1)
3018 TRACE_INSN (cpu
, "[%s ++ %s] = R%i;", ptr_name
, idx_name
, reg
);
3020 PUT_LONG (addr
, DREG (reg
));
3022 STORE (PREG (ptr
), addr
+ PREG (idx
));
3024 else if (aop
== 1 && W
== 1)
3026 TRACE_INSN (cpu
, "W[%s ++ %s] = R%i.L;", ptr_name
, idx_name
, reg
);
3028 PUT_WORD (addr
, DREG (reg
));
3030 STORE (PREG (ptr
), addr
+ PREG (idx
));
3032 else if (aop
== 2 && W
== 1)
3034 TRACE_INSN (cpu
, "W[%s ++ %s] = R%i.H;", ptr_name
, idx_name
, reg
);
3036 PUT_WORD (addr
, DREG (reg
) >> 16);
3038 STORE (PREG (ptr
), addr
+ PREG (idx
));
3041 illegal_instruction_or_combination (cpu
);
3045 decode_dagMODim_0 (SIM_CPU
*cpu
, bu16 iw0
)
3048 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3049 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 0 |.br| 1 | 1 |.op|.m.....|.i.....|
3050 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3051 int i
= ((iw0
>> DagMODim_i_bits
) & DagMODim_i_mask
);
3052 int m
= ((iw0
>> DagMODim_m_bits
) & DagMODim_m_mask
);
3053 int br
= ((iw0
>> DagMODim_br_bits
) & DagMODim_br_mask
);
3054 int op
= ((iw0
>> DagMODim_op_bits
) & DagMODim_op_mask
);
3056 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dagMODim
);
3057 TRACE_EXTRACT (cpu
, "%s: br:%i op:%i m:%i i:%i", __func__
, br
, op
, m
, i
);
3059 if (PARALLEL_GROUP
== BFIN_PARALLEL_GROUP2
)
3060 illegal_instruction_combination (cpu
);
3062 if (op
== 0 && br
== 1)
3064 TRACE_INSN (cpu
, "I%i += M%i (BREV);", i
, m
);
3065 SET_IREG (i
, add_brev (IREG (i
), MREG (m
)));
3069 TRACE_INSN (cpu
, "I%i += M%i;", i
, m
);
3070 dagadd (cpu
, i
, MREG (m
));
3072 else if (op
== 1 && br
== 0)
3074 TRACE_INSN (cpu
, "I%i -= M%i;", i
, m
);
3075 dagsub (cpu
, i
, MREG (m
));
3078 illegal_instruction_or_combination (cpu
);
3082 decode_dagMODik_0 (SIM_CPU
*cpu
, bu16 iw0
)
3085 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3086 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 0 |.op....|.i.....|
3087 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3088 int i
= ((iw0
>> DagMODik_i_bits
) & DagMODik_i_mask
);
3089 int op
= ((iw0
>> DagMODik_op_bits
) & DagMODik_op_mask
);
3091 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dagMODik
);
3092 TRACE_EXTRACT (cpu
, "%s: op:%i i:%i", __func__
, op
, i
);
3094 if (PARALLEL_GROUP
== BFIN_PARALLEL_GROUP2
)
3095 illegal_instruction_combination (cpu
);
3099 TRACE_INSN (cpu
, "I%i += 2;", i
);
3104 TRACE_INSN (cpu
, "I%i -= 2;", i
);
3109 TRACE_INSN (cpu
, "I%i += 4;", i
);
3114 TRACE_INSN (cpu
, "I%i -= 4;", i
);
3118 illegal_instruction_or_combination (cpu
);
3122 decode_dspLDST_0 (SIM_CPU
*cpu
, bu16 iw0
)
3125 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3126 | 1 | 0 | 0 | 1 | 1 | 1 |.W.|.aop...|.m.....|.i.....|.reg.......|
3127 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3128 int i
= ((iw0
>> DspLDST_i_bits
) & DspLDST_i_mask
);
3129 int m
= ((iw0
>> DspLDST_m_bits
) & DspLDST_m_mask
);
3130 int W
= ((iw0
>> DspLDST_W_bits
) & DspLDST_W_mask
);
3131 int aop
= ((iw0
>> DspLDST_aop_bits
) & DspLDST_aop_mask
);
3132 int reg
= ((iw0
>> DspLDST_reg_bits
) & DspLDST_reg_mask
);
3135 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dspLDST
);
3136 TRACE_EXTRACT (cpu
, "%s: aop:%i m:%i i:%i reg:%i", __func__
, aop
, m
, i
, reg
);
3138 if (aop
== 0 && W
== 0 && m
== 0)
3140 TRACE_INSN (cpu
, "R%i = [I%i++];", reg
, i
);
3142 if (DIS_ALGN_EXPT
& 0x1)
3145 STORE (DREG (reg
), GET_LONG (addr
));
3147 else if (aop
== 0 && W
== 0 && m
== 1)
3149 TRACE_INSN (cpu
, "R%i.L = W[I%i++];", reg
, i
);
3152 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | GET_WORD (addr
));
3154 else if (aop
== 0 && W
== 0 && m
== 2)
3156 TRACE_INSN (cpu
, "R%i.H = W[I%i++];", reg
, i
);
3159 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (GET_WORD (addr
) << 16));
3161 else if (aop
== 1 && W
== 0 && m
== 0)
3163 TRACE_INSN (cpu
, "R%i = [I%i--];", reg
, i
);
3165 if (DIS_ALGN_EXPT
& 0x1)
3168 STORE (DREG (reg
), GET_LONG (addr
));
3170 else if (aop
== 1 && W
== 0 && m
== 1)
3172 TRACE_INSN (cpu
, "R%i.L = W[I%i--];", reg
, i
);
3175 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | GET_WORD (addr
));
3177 else if (aop
== 1 && W
== 0 && m
== 2)
3179 TRACE_INSN (cpu
, "R%i.H = W[I%i--];", reg
, i
);
3182 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (GET_WORD (addr
) << 16));
3184 else if (aop
== 2 && W
== 0 && m
== 0)
3186 TRACE_INSN (cpu
, "R%i = [I%i];", reg
, i
);
3188 if (DIS_ALGN_EXPT
& 0x1)
3190 STORE (DREG (reg
), GET_LONG (addr
));
3192 else if (aop
== 2 && W
== 0 && m
== 1)
3194 TRACE_INSN (cpu
, "R%i.L = W[I%i];", reg
, i
);
3196 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | GET_WORD (addr
));
3198 else if (aop
== 2 && W
== 0 && m
== 2)
3200 TRACE_INSN (cpu
, "R%i.H = W[I%i];", reg
, i
);
3202 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (GET_WORD (addr
) << 16));
3204 else if (aop
== 0 && W
== 1 && m
== 0)
3206 TRACE_INSN (cpu
, "[I%i++] = R%i;", i
, reg
);
3209 PUT_LONG (addr
, DREG (reg
));
3211 else if (aop
== 0 && W
== 1 && m
== 1)
3213 TRACE_INSN (cpu
, "W[I%i++] = R%i.L;", i
, reg
);
3216 PUT_WORD (addr
, DREG (reg
));
3218 else if (aop
== 0 && W
== 1 && m
== 2)
3220 TRACE_INSN (cpu
, "W[I%i++] = R%i.H;", i
, reg
);
3223 PUT_WORD (addr
, DREG (reg
) >> 16);
3225 else if (aop
== 1 && W
== 1 && m
== 0)
3227 TRACE_INSN (cpu
, "[I%i--] = R%i;", i
, reg
);
3230 PUT_LONG (addr
, DREG (reg
));
3232 else if (aop
== 1 && W
== 1 && m
== 1)
3234 TRACE_INSN (cpu
, "W[I%i--] = R%i.L;", i
, reg
);
3237 PUT_WORD (addr
, DREG (reg
));
3239 else if (aop
== 1 && W
== 1 && m
== 2)
3241 TRACE_INSN (cpu
, "W[I%i--] = R%i.H;", i
, reg
);
3244 PUT_WORD (addr
, DREG (reg
) >> 16);
3246 else if (aop
== 2 && W
== 1 && m
== 0)
3248 TRACE_INSN (cpu
, "[I%i] = R%i;", i
, reg
);
3250 PUT_LONG (addr
, DREG (reg
));
3252 else if (aop
== 2 && W
== 1 && m
== 1)
3254 TRACE_INSN (cpu
, "W[I%i] = R%i.L;", i
, reg
);
3256 PUT_WORD (addr
, DREG (reg
));
3258 else if (aop
== 2 && W
== 1 && m
== 2)
3260 TRACE_INSN (cpu
, "W[I%i] = R%i.H;", i
, reg
);
3262 PUT_WORD (addr
, DREG (reg
) >> 16);
3264 else if (aop
== 3 && W
== 0)
3266 TRACE_INSN (cpu
, "R%i = [I%i ++ M%i];", reg
, i
, m
);
3268 if (DIS_ALGN_EXPT
& 0x1)
3270 dagadd (cpu
, i
, MREG (m
));
3271 STORE (DREG (reg
), GET_LONG (addr
));
3273 else if (aop
== 3 && W
== 1)
3275 TRACE_INSN (cpu
, "[I%i ++ M%i] = R%i;", i
, m
, reg
);
3277 dagadd (cpu
, i
, MREG (m
));
3278 PUT_LONG (addr
, DREG (reg
));
3281 illegal_instruction_or_combination (cpu
);
3285 decode_LDST_0 (SIM_CPU
*cpu
, bu16 iw0
)
3288 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3289 | 1 | 0 | 0 | 1 |.sz....|.W.|.aop...|.Z.|.ptr.......|.reg.......|
3290 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3291 int Z
= ((iw0
>> LDST_Z_bits
) & LDST_Z_mask
);
3292 int W
= ((iw0
>> LDST_W_bits
) & LDST_W_mask
);
3293 int sz
= ((iw0
>> LDST_sz_bits
) & LDST_sz_mask
);
3294 int aop
= ((iw0
>> LDST_aop_bits
) & LDST_aop_mask
);
3295 int reg
= ((iw0
>> LDST_reg_bits
) & LDST_reg_mask
);
3296 int ptr
= ((iw0
>> LDST_ptr_bits
) & LDST_ptr_mask
);
3297 const char * const posts
[] = { "++", "--", "", "<INV>" };
3298 const char *post
= posts
[aop
];
3299 const char *ptr_name
= get_preg_name (ptr
);
3301 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDST
);
3302 TRACE_EXTRACT (cpu
, "%s: sz:%i W:%i aop:%i Z:%i ptr:%i reg:%i",
3303 __func__
, sz
, W
, aop
, Z
, ptr
, reg
);
3305 if (aop
== 3 || PARALLEL_GROUP
== BFIN_PARALLEL_GROUP2
)
3306 illegal_instruction_or_combination (cpu
);
3310 if (sz
== 0 && Z
== 0)
3312 TRACE_INSN (cpu
, "R%i = [%s%s];", reg
, ptr_name
, post
);
3313 SET_DREG (reg
, GET_LONG (PREG (ptr
)));
3315 else if (sz
== 0 && Z
== 1)
3317 TRACE_INSN (cpu
, "%s = [%s%s];", get_preg_name (reg
), ptr_name
, post
);
3318 if (aop
< 2 && ptr
== reg
)
3319 illegal_instruction_combination (cpu
);
3320 SET_PREG (reg
, GET_LONG (PREG (ptr
)));
3322 else if (sz
== 1 && Z
== 0)
3324 TRACE_INSN (cpu
, "R%i = W[%s%s] (Z);", reg
, ptr_name
, post
);
3325 SET_DREG (reg
, GET_WORD (PREG (ptr
)));
3327 else if (sz
== 1 && Z
== 1)
3329 TRACE_INSN (cpu
, "R%i = W[%s%s] (X);", reg
, ptr_name
, post
);
3330 SET_DREG (reg
, (bs32
) (bs16
) GET_WORD (PREG (ptr
)));
3332 else if (sz
== 2 && Z
== 0)
3334 TRACE_INSN (cpu
, "R%i = B[%s%s] (Z);", reg
, ptr_name
, post
);
3335 SET_DREG (reg
, GET_BYTE (PREG (ptr
)));
3337 else if (sz
== 2 && Z
== 1)
3339 TRACE_INSN (cpu
, "R%i = B[%s%s] (X);", reg
, ptr_name
, post
);
3340 SET_DREG (reg
, (bs32
) (bs8
) GET_BYTE (PREG (ptr
)));
3343 illegal_instruction_or_combination (cpu
);
3347 if (sz
== 0 && Z
== 0)
3349 TRACE_INSN (cpu
, "[%s%s] = R%i;", ptr_name
, post
, reg
);
3350 PUT_LONG (PREG (ptr
), DREG (reg
));
3352 else if (sz
== 0 && Z
== 1)
3354 TRACE_INSN (cpu
, "[%s%s] = %s;", ptr_name
, post
, get_preg_name (reg
));
3355 PUT_LONG (PREG (ptr
), PREG (reg
));
3357 else if (sz
== 1 && Z
== 0)
3359 TRACE_INSN (cpu
, "W[%s%s] = R%i;", ptr_name
, post
, reg
);
3360 PUT_WORD (PREG (ptr
), DREG (reg
));
3362 else if (sz
== 2 && Z
== 0)
3364 TRACE_INSN (cpu
, "B[%s%s] = R%i;", ptr_name
, post
, reg
);
3365 PUT_BYTE (PREG (ptr
), DREG (reg
));
3368 illegal_instruction_or_combination (cpu
);
3372 SET_PREG (ptr
, PREG (ptr
) + (1 << (2 - sz
)));
3374 SET_PREG (ptr
, PREG (ptr
) - (1 << (2 - sz
)));
3378 decode_LDSTiiFP_0 (SIM_CPU
*cpu
, bu16 iw0
)
3381 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3382 | 1 | 0 | 1 | 1 | 1 | 0 |.W.|.offset............|.reg...........|
3383 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3384 /* This isn't exactly a grp:reg as this insn only supports Dregs & Pregs,
3385 but for our usage, its functionality the same thing. */
3386 int grp
= ((iw0
>> 3) & 0x1);
3387 int reg
= ((iw0
>> LDSTiiFP_reg_bits
) & 0x7 /*LDSTiiFP_reg_mask*/);
3388 int offset
= ((iw0
>> LDSTiiFP_offset_bits
) & LDSTiiFP_offset_mask
);
3389 int W
= ((iw0
>> LDSTiiFP_W_bits
) & LDSTiiFP_W_mask
);
3390 bu32 imm
= negimm5s4 (offset
);
3391 bu32 ea
= FPREG
+ imm
;
3392 const char *imm_str
= negimm5s4_str (offset
);
3393 const char *reg_name
= get_allreg_name (grp
, reg
);
3395 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTiiFP
);
3396 TRACE_EXTRACT (cpu
, "%s: W:%i offset:%#x grp:%i reg:%i", __func__
,
3397 W
, offset
, grp
, reg
);
3398 TRACE_DECODE (cpu
, "%s: negimm5s4:%#x", __func__
, imm
);
3400 if (PARALLEL_GROUP
== BFIN_PARALLEL_GROUP2
)
3401 illegal_instruction_or_combination (cpu
);
3405 TRACE_INSN (cpu
, "%s = [FP + %s];", reg_name
, imm_str
);
3406 reg_write (cpu
, grp
, reg
, GET_LONG (ea
));
3410 TRACE_INSN (cpu
, "[FP + %s] = %s;", imm_str
, reg_name
);
3411 PUT_LONG (ea
, reg_read (cpu
, grp
, reg
));
3416 decode_LDSTii_0 (SIM_CPU
*cpu
, bu16 iw0
)
3419 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3420 | 1 | 0 | 1 |.W.|.op....|.offset........|.ptr.......|.reg.......|
3421 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3422 int reg
= ((iw0
>> LDSTii_reg_bit
) & LDSTii_reg_mask
);
3423 int ptr
= ((iw0
>> LDSTii_ptr_bit
) & LDSTii_ptr_mask
);
3424 int offset
= ((iw0
>> LDSTii_offset_bit
) & LDSTii_offset_mask
);
3425 int op
= ((iw0
>> LDSTii_op_bit
) & LDSTii_op_mask
);
3426 int W
= ((iw0
>> LDSTii_W_bit
) & LDSTii_W_mask
);
3428 const char *imm_str
;
3429 const char *ptr_name
= get_preg_name (ptr
);
3431 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTii
);
3432 TRACE_EXTRACT (cpu
, "%s: W:%i op:%i offset:%#x ptr:%i reg:%i",
3433 __func__
, W
, op
, offset
, ptr
, reg
);
3435 if (op
== 0 || op
== 3)
3436 imm
= uimm4s4 (offset
), imm_str
= uimm4s4_str (offset
);
3438 imm
= uimm4s2 (offset
), imm_str
= uimm4s2_str (offset
);
3439 ea
= PREG (ptr
) + imm
;
3441 TRACE_DECODE (cpu
, "%s: uimm4s4/uimm4s2:%#x", __func__
, imm
);
3443 if (PARALLEL_GROUP
== BFIN_PARALLEL_GROUP2
)
3444 illegal_instruction_combination (cpu
);
3446 if (W
== 1 && op
== 2)
3447 illegal_instruction (cpu
);
3453 TRACE_INSN (cpu
, "R%i = [%s + %s];", reg
, ptr_name
, imm_str
);
3454 SET_DREG (reg
, GET_LONG (ea
));
3458 TRACE_INSN (cpu
, "R%i = W[%s + %s] (Z);", reg
, ptr_name
, imm_str
);
3459 SET_DREG (reg
, GET_WORD (ea
));
3463 TRACE_INSN (cpu
, "R%i = W[%s + %s] (X);", reg
, ptr_name
, imm_str
);
3464 SET_DREG (reg
, (bs32
) (bs16
) GET_WORD (ea
));
3468 TRACE_INSN (cpu
, "%s = [%s + %s];",
3469 get_preg_name (reg
), ptr_name
, imm_str
);
3470 SET_PREG (reg
, GET_LONG (ea
));
3477 TRACE_INSN (cpu
, "[%s + %s] = R%i;", ptr_name
, imm_str
, reg
);
3478 PUT_LONG (ea
, DREG (reg
));
3482 TRACE_INSN (cpu
, "W[%s + %s] = R%i;", ptr_name
, imm_str
, reg
);
3483 PUT_WORD (ea
, DREG (reg
));
3487 TRACE_INSN (cpu
, "[%s + %s] = %s;",
3488 ptr_name
, imm_str
, get_preg_name (reg
));
3489 PUT_LONG (ea
, PREG (reg
));
3495 decode_LoopSetup_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
, bu32 pc
)
3498 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3499 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |.rop...|.c.|.soffset.......|
3500 |.reg...........| - | - |.eoffset...............................|
3501 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3502 int c
= ((iw0
>> (LoopSetup_c_bits
- 16)) & LoopSetup_c_mask
);
3503 int reg
= ((iw1
>> LoopSetup_reg_bits
) & LoopSetup_reg_mask
);
3504 int rop
= ((iw0
>> (LoopSetup_rop_bits
- 16)) & LoopSetup_rop_mask
);
3505 int soffset
= ((iw0
>> (LoopSetup_soffset_bits
- 16)) & LoopSetup_soffset_mask
);
3506 int eoffset
= ((iw1
>> LoopSetup_eoffset_bits
) & LoopSetup_eoffset_mask
);
3507 int spcrel
= pcrel4 (soffset
);
3508 int epcrel
= lppcrel10 (eoffset
);
3510 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LoopSetup
);
3511 TRACE_EXTRACT (cpu
, "%s: rop:%i c:%i soffset:%i reg:%i eoffset:%i",
3512 __func__
, rop
, c
, soffset
, reg
, eoffset
);
3513 TRACE_DECODE (cpu
, "%s: s_pcrel4:%#x e_lppcrel10:%#x",
3514 __func__
, spcrel
, epcrel
);
3517 illegal_instruction (cpu
);
3519 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
3520 illegal_instruction_combination (cpu
);
3524 TRACE_INSN (cpu
, "LSETUP (%#x, %#x) LC%i;", spcrel
, epcrel
, c
);
3526 else if (rop
== 1 && reg
<= 7)
3528 TRACE_INSN (cpu
, "LSETUP (%#x, %#x) LC%i = %s;",
3529 spcrel
, epcrel
, c
, get_preg_name (reg
));
3530 SET_LCREG (c
, PREG (reg
));
3532 else if (rop
== 3 && reg
<= 7)
3534 TRACE_INSN (cpu
, "LSETUP (%#x, %#x) LC%i = %s >> 1;",
3535 spcrel
, epcrel
, c
, get_preg_name (reg
));
3536 SET_LCREG (c
, PREG (reg
) >> 1);
3539 illegal_instruction (cpu
);
3541 SET_LTREG (c
, pc
+ spcrel
);
3542 SET_LBREG (c
, pc
+ epcrel
);
3546 decode_LDIMMhalf_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3549 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3550 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 |.Z.|.H.|.S.|.grp...|.reg.......|
3551 |.hword.........................................................|
3552 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3553 int H
= ((iw0
>> (LDIMMhalf_H_bits
- 16)) & LDIMMhalf_H_mask
);
3554 int Z
= ((iw0
>> (LDIMMhalf_Z_bits
- 16)) & LDIMMhalf_Z_mask
);
3555 int S
= ((iw0
>> (LDIMMhalf_S_bits
- 16)) & LDIMMhalf_S_mask
);
3556 int reg
= ((iw0
>> (LDIMMhalf_reg_bits
- 16)) & LDIMMhalf_reg_mask
);
3557 int grp
= ((iw0
>> (LDIMMhalf_grp_bits
- 16)) & LDIMMhalf_grp_mask
);
3558 int hword
= ((iw1
>> LDIMMhalf_hword_bits
) & LDIMMhalf_hword_mask
);
3560 const char *val_str
;
3561 const char *reg_name
= get_allreg_name (grp
, reg
);
3563 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDIMMhalf
);
3564 TRACE_EXTRACT (cpu
, "%s: Z:%i H:%i S:%i grp:%i reg:%i hword:%#x",
3565 __func__
, Z
, H
, S
, grp
, reg
, hword
);
3567 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
3568 illegal_instruction_combination (cpu
);
3571 val
= imm16 (hword
), val_str
= imm16_str (hword
);
3573 val
= luimm16 (hword
), val_str
= luimm16_str (hword
);
3575 if (H
== 0 && S
== 1 && Z
== 0)
3577 TRACE_INSN (cpu
, "%s = %s (X);", reg_name
, val_str
);
3579 else if (H
== 0 && S
== 0 && Z
== 1)
3581 TRACE_INSN (cpu
, "%s = %s (Z);", reg_name
, val_str
);
3583 else if (H
== 0 && S
== 0 && Z
== 0)
3585 TRACE_INSN (cpu
, "%s.L = %s;", reg_name
, val_str
);
3586 val
= REG_H_L (reg_read (cpu
, grp
, reg
), val
);
3588 else if (H
== 1 && S
== 0 && Z
== 0)
3590 TRACE_INSN (cpu
, "%s.H = %s;", reg_name
, val_str
);
3591 val
= REG_H_L (val
<< 16, reg_read (cpu
, grp
, reg
));
3594 illegal_instruction (cpu
);
3596 reg_write (cpu
, grp
, reg
, val
);
3600 decode_CALLa_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
, bu32 pc
)
3603 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3604 | 1 | 1 | 1 | 0 | 0 | 0 | 1 |.S.|.msw...........................|
3605 |.lsw...........................................................|
3606 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3607 int S
= ((iw0
>> (CALLa_S_bits
- 16)) & CALLa_S_mask
);
3608 int lsw
= ((iw1
>> 0) & 0xffff);
3609 int msw
= ((iw0
>> 0) & 0xff);
3610 int pcrel
= pcrel24 ((msw
<< 16) | lsw
);
3611 bu32 newpc
= pc
+ pcrel
;
3613 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CALLa
);
3614 TRACE_EXTRACT (cpu
, "%s: S:%i msw:%#x lsw:%#x", __func__
, S
, msw
, lsw
);
3615 TRACE_DECODE (cpu
, "%s: pcrel24:%#x", __func__
, pcrel
);
3617 TRACE_INSN (cpu
, "%s %#x;", S
? "CALL" : "JUMP.L", pcrel
);
3619 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
3620 illegal_instruction_combination (cpu
);
3624 BFIN_TRACE_BRANCH (cpu
, pc
, newpc
, -1, "CALL");
3625 SET_RETSREG (hwloop_get_next_pc (cpu
, pc
, 4));
3628 BFIN_TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP.L");
3631 BFIN_CPU_STATE
.did_jump
= true;
3632 PROFILE_BRANCH_TAKEN (cpu
);
3637 decode_LDSTidxI_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3640 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3641 | 1 | 1 | 1 | 0 | 0 | 1 |.W.|.Z.|.sz....|.ptr.......|.reg.......|
3642 |.offset........................................................|
3643 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3644 int Z
= ((iw0
>> (LDSTidxI_Z_bits
- 16)) & LDSTidxI_Z_mask
);
3645 int W
= ((iw0
>> (LDSTidxI_W_bits
- 16)) & LDSTidxI_W_mask
);
3646 int sz
= ((iw0
>> (LDSTidxI_sz_bits
- 16)) & LDSTidxI_sz_mask
);
3647 int reg
= ((iw0
>> (LDSTidxI_reg_bits
- 16)) & LDSTidxI_reg_mask
);
3648 int ptr
= ((iw0
>> (LDSTidxI_ptr_bits
- 16)) & LDSTidxI_ptr_mask
);
3649 int offset
= ((iw1
>> LDSTidxI_offset_bits
) & LDSTidxI_offset_mask
);
3650 const char *ptr_name
= get_preg_name (ptr
);
3651 bu32 imm_16s4
= imm16s4 (offset
);
3652 bu32 imm_16s2
= imm16s2 (offset
);
3653 bu32 imm_16
= imm16 (offset
);
3655 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTidxI
);
3656 TRACE_EXTRACT (cpu
, "%s: W:%i Z:%i sz:%i ptr:%i reg:%i offset:%#x",
3657 __func__
, W
, Z
, sz
, ptr
, reg
, offset
);
3660 illegal_instruction (cpu
);
3664 if (sz
== 0 && Z
== 0)
3666 TRACE_INSN (cpu
, "R%i = [%s + %s];",
3667 reg
, ptr_name
, imm16s4_str (offset
));
3668 SET_DREG (reg
, GET_LONG (PREG (ptr
) + imm_16s4
));
3670 else if (sz
== 0 && Z
== 1)
3672 TRACE_INSN (cpu
, "%s = [%s + %s];",
3673 get_preg_name (reg
), ptr_name
, imm16s4_str (offset
));
3674 SET_PREG (reg
, GET_LONG (PREG (ptr
) + imm_16s4
));
3676 else if (sz
== 1 && Z
== 0)
3678 TRACE_INSN (cpu
, "R%i = W[%s + %s] (Z);",
3679 reg
, ptr_name
, imm16s2_str (offset
));
3680 SET_DREG (reg
, GET_WORD (PREG (ptr
) + imm_16s2
));
3682 else if (sz
== 1 && Z
== 1)
3684 TRACE_INSN (cpu
, "R%i = W[%s + %s] (X);",
3685 reg
, ptr_name
, imm16s2_str (offset
));
3686 SET_DREG (reg
, (bs32
) (bs16
) GET_WORD (PREG (ptr
) + imm_16s2
));
3688 else if (sz
== 2 && Z
== 0)
3690 TRACE_INSN (cpu
, "R%i = B[%s + %s] (Z);",
3691 reg
, ptr_name
, imm16_str (offset
));
3692 SET_DREG (reg
, GET_BYTE (PREG (ptr
) + imm_16
));
3694 else if (sz
== 2 && Z
== 1)
3696 TRACE_INSN (cpu
, "R%i = B[%s + %s] (X);",
3697 reg
, ptr_name
, imm16_str (offset
));
3698 SET_DREG (reg
, (bs32
) (bs8
) GET_BYTE (PREG (ptr
) + imm_16
));
3703 if (sz
!= 0 && Z
!= 0)
3704 illegal_instruction (cpu
);
3706 if (sz
== 0 && Z
== 0)
3708 TRACE_INSN (cpu
, "[%s + %s] = R%i;", ptr_name
,
3709 imm16s4_str (offset
), reg
);
3710 PUT_LONG (PREG (ptr
) + imm_16s4
, DREG (reg
));
3712 else if (sz
== 0 && Z
== 1)
3714 TRACE_INSN (cpu
, "[%s + %s] = %s;",
3715 ptr_name
, imm16s4_str (offset
), get_preg_name (reg
));
3716 PUT_LONG (PREG (ptr
) + imm_16s4
, PREG (reg
));
3718 else if (sz
== 1 && Z
== 0)
3720 TRACE_INSN (cpu
, "W[%s + %s] = R%i;",
3721 ptr_name
, imm16s2_str (offset
), reg
);
3722 PUT_WORD (PREG (ptr
) + imm_16s2
, DREG (reg
));
3724 else if (sz
== 2 && Z
== 0)
3726 TRACE_INSN (cpu
, "B[%s + %s] = R%i;",
3727 ptr_name
, imm16_str (offset
), reg
);
3728 PUT_BYTE (PREG (ptr
) + imm_16
, DREG (reg
));
3734 decode_linkage_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3737 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3738 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |.R.|
3739 |.framesize.....................................................|
3740 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3741 int R
= ((iw0
>> (Linkage_R_bits
- 16)) & Linkage_R_mask
);
3742 int framesize
= ((iw1
>> Linkage_framesize_bits
) & Linkage_framesize_mask
);
3745 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_linkage
);
3746 TRACE_EXTRACT (cpu
, "%s: R:%i framesize:%#x", __func__
, R
, framesize
);
3750 int size
= uimm16s4 (framesize
);
3752 TRACE_INSN (cpu
, "LINK %s;", uimm16s4_str (framesize
));
3753 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
3754 illegal_instruction_combination (cpu
);
3756 PUT_LONG (sp
, RETSREG
);
3758 PUT_LONG (sp
, FPREG
);
3765 /* Restore SP from FP. */
3767 TRACE_INSN (cpu
, "UNLINK;");
3768 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
3769 illegal_instruction_combination (cpu
);
3770 SET_FPREG (GET_LONG (sp
));
3772 SET_RETSREG (GET_LONG (sp
));
3781 decode_dsp32mac_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3784 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3785 | 1 | 1 | 0 | 0 |.M.| 0 | 0 |.mmod..........|.MM|.P.|.w1|.op1...|
3786 |.h01|.h11|.w0|.op0...|.h00|.h10|.dst.......|.src0......|.src1..|
3787 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3788 int op1
= ((iw0
>> (DSP32Mac_op1_bits
- 16)) & DSP32Mac_op1_mask
);
3789 int w1
= ((iw0
>> (DSP32Mac_w1_bits
- 16)) & DSP32Mac_w1_mask
);
3790 int P
= ((iw0
>> (DSP32Mac_p_bits
- 16)) & DSP32Mac_p_mask
);
3791 int MM
= ((iw0
>> (DSP32Mac_MM_bits
- 16)) & DSP32Mac_MM_mask
);
3792 int mmod
= ((iw0
>> (DSP32Mac_mmod_bits
- 16)) & DSP32Mac_mmod_mask
);
3793 int M
= ((iw0
>> (DSP32Mac_M_bits
- 16)) & DSP32Mac_M_mask
);
3794 int w0
= ((iw1
>> DSP32Mac_w0_bits
) & DSP32Mac_w0_mask
);
3795 int src0
= ((iw1
>> DSP32Mac_src0_bits
) & DSP32Mac_src0_mask
);
3796 int src1
= ((iw1
>> DSP32Mac_src1_bits
) & DSP32Mac_src1_mask
);
3797 int dst
= ((iw1
>> DSP32Mac_dst_bits
) & DSP32Mac_dst_mask
);
3798 int h10
= ((iw1
>> DSP32Mac_h10_bits
) & DSP32Mac_h10_mask
);
3799 int h00
= ((iw1
>> DSP32Mac_h00_bits
) & DSP32Mac_h00_mask
);
3800 int op0
= ((iw1
>> DSP32Mac_op0_bits
) & DSP32Mac_op0_mask
);
3801 int h11
= ((iw1
>> DSP32Mac_h11_bits
) & DSP32Mac_h11_mask
);
3802 int h01
= ((iw1
>> DSP32Mac_h01_bits
) & DSP32Mac_h01_mask
);
3804 bu32 res
= DREG (dst
);
3805 bu32 v_0
= 0, v_1
= 0, zero
= 0, n_1
= 0, n_0
= 0;
3807 static const char * const ops
[] = { "=", "+=", "-=" };
3808 char _buf
[128], *buf
= _buf
;
3811 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32mac
);
3812 TRACE_EXTRACT (cpu
, "%s: M:%i mmod:%i MM:%i P:%i w1:%i op1:%i h01:%i h11:%i "
3813 "w0:%i op0:%i h00:%i h10:%i dst:%i src0:%i src1:%i",
3814 __func__
, M
, mmod
, MM
, P
, w1
, op1
, h01
, h11
, w0
, op0
, h00
, h10
,
3817 if (w0
== 0 && w1
== 0 && op1
== 3 && op0
== 3)
3818 illegal_instruction (cpu
);
3820 if ((w1
|| w0
) && mmod
== M_W32
)
3821 illegal_instruction (cpu
);
3823 if (((1 << mmod
) & (P
? 0x131b : 0x1b5f)) == 0)
3824 illegal_instruction (cpu
);
3826 /* First handle MAC1 side. */
3827 if (w1
== 1 || op1
!= 3)
3829 bu32 res1
= decode_macfunc (cpu
, 1, op1
, h01
, h11
, src0
,
3830 src1
, mmod
, MM
, P
, &v_1
, &n_1
);
3833 buf
+= sprintf (buf
, P
? "R%i" : "R%i.H", dst
+ P
);
3837 buf
+= sprintf (buf
, " = A1");
3838 zero
= !!(res1
== 0);
3843 buf
+= sprintf (buf
, " = (");
3844 buf
+= sprintf (buf
, "A1 %s R%i.%c * R%i.%c", ops
[op1
],
3845 src0
, h01
? 'H' : 'L',
3846 src1
, h11
? 'H' : 'L');
3848 buf
+= sprintf (buf
, ")");
3854 STORE (DREG (dst
+ 1), res1
);
3857 if (res1
& 0xffff0000)
3858 illegal_instruction (cpu
);
3859 res
= REG_H_L (res1
<< 16, res
);
3865 if (w0
== 1 || op0
!= 3)
3868 buf
+= sprintf (buf
, " (M)");
3870 buf
+= sprintf (buf
, ", ");
3874 /* Then handle MAC0 side. */
3875 if (w0
== 1 || op0
!= 3)
3877 bu32 res0
= decode_macfunc (cpu
, 0, op0
, h00
, h10
, src0
,
3878 src1
, mmod
, 0, P
, &v_0
, &n_0
);
3881 buf
+= sprintf (buf
, P
? "R%i" : "R%i.L", dst
);
3885 buf
+= sprintf (buf
, " = A0");
3886 zero
|= !!(res0
== 0);
3891 buf
+= sprintf (buf
, " = (");
3892 buf
+= sprintf (buf
, "A0 %s R%i.%c * R%i.%c", ops
[op0
],
3893 src0
, h00
? 'H' : 'L',
3894 src1
, h10
? 'H' : 'L');
3896 buf
+= sprintf (buf
, ")");
3902 STORE (DREG (dst
), res0
);
3905 if (res0
& 0xffff0000)
3906 illegal_instruction (cpu
);
3907 res
= REG_H_L (res
, res0
);
3914 TRACE_INSN (cpu
, "%s%s;", _buf
, mac_optmode (mmod
, _MM
));
3916 if (!P
&& (w0
|| w1
))
3918 STORE (DREG (dst
), res
);
3919 SET_ASTATREG (v
, v_0
| v_1
);
3921 SET_ASTATREG (vs
, 1);
3925 SET_ASTATREG (v
, v_0
| v_1
);
3927 SET_ASTATREG (vs
, 1);
3930 if ((w0
== 1 && op0
== 3) || (w1
== 1 && op1
== 3))
3932 SET_ASTATREG (az
, zero
);
3933 if (!(w0
== 1 && op0
== 3))
3935 if (!(w1
== 1 && op1
== 3))
3937 SET_ASTATREG (an
, n_1
| n_0
);
3942 decode_dsp32mult_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3945 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3946 | 1 | 1 | 0 | 0 |.M.| 0 | 1 |.mmod..........|.MM|.P.|.w1|.op1...|
3947 |.h01|.h11|.w0|.op0...|.h00|.h10|.dst.......|.src0......|.src1..|
3948 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3949 int op1
= ((iw0
>> (DSP32Mac_op1_bits
- 16)) & DSP32Mac_op1_mask
);
3950 int w1
= ((iw0
>> (DSP32Mac_w1_bits
- 16)) & DSP32Mac_w1_mask
);
3951 int P
= ((iw0
>> (DSP32Mac_p_bits
- 16)) & DSP32Mac_p_mask
);
3952 int MM
= ((iw0
>> (DSP32Mac_MM_bits
- 16)) & DSP32Mac_MM_mask
);
3953 int mmod
= ((iw0
>> (DSP32Mac_mmod_bits
- 16)) & DSP32Mac_mmod_mask
);
3954 int M
= ((iw0
>> (DSP32Mac_M_bits
- 16)) & DSP32Mac_M_mask
);
3955 int w0
= ((iw1
>> DSP32Mac_w0_bits
) & DSP32Mac_w0_mask
);
3956 int src0
= ((iw1
>> DSP32Mac_src0_bits
) & DSP32Mac_src0_mask
);
3957 int src1
= ((iw1
>> DSP32Mac_src1_bits
) & DSP32Mac_src1_mask
);
3958 int dst
= ((iw1
>> DSP32Mac_dst_bits
) & DSP32Mac_dst_mask
);
3959 int h10
= ((iw1
>> DSP32Mac_h10_bits
) & DSP32Mac_h10_mask
);
3960 int h00
= ((iw1
>> DSP32Mac_h00_bits
) & DSP32Mac_h00_mask
);
3961 int op0
= ((iw1
>> DSP32Mac_op0_bits
) & DSP32Mac_op0_mask
);
3962 int h11
= ((iw1
>> DSP32Mac_h11_bits
) & DSP32Mac_h11_mask
);
3963 int h01
= ((iw1
>> DSP32Mac_h01_bits
) & DSP32Mac_h01_mask
);
3965 bu32 res
= DREG (dst
);
3966 bu32 sat0
= 0, sat1
= 0, v_i0
= 0, v_i1
= 0;
3967 char _buf
[128], *buf
= _buf
;
3970 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32mult
);
3971 TRACE_EXTRACT (cpu
, "%s: M:%i mmod:%i MM:%i P:%i w1:%i op1:%i h01:%i h11:%i "
3972 "w0:%i op0:%i h00:%i h10:%i dst:%i src0:%i src1:%i",
3973 __func__
, M
, mmod
, MM
, P
, w1
, op1
, h01
, h11
, w0
, op0
, h00
, h10
,
3976 if (w1
== 0 && w0
== 0)
3977 illegal_instruction (cpu
);
3978 if (((1 << mmod
) & (P
? 0x313 : 0x1b57)) == 0)
3979 illegal_instruction (cpu
);
3980 if (P
&& ((dst
& 1) || (op1
!= 0) || (op0
!= 0) || !is_macmod_pmove (mmod
)))
3981 illegal_instruction (cpu
);
3982 if (!P
&& ((op1
!= 0) || (op0
!= 0) || !is_macmod_hmove (mmod
)))
3983 illegal_instruction (cpu
);
3985 /* First handle MAC1 side. */
3988 bu64 r
= decode_multfunc (cpu
, h01
, h11
, src0
, src1
, mmod
, MM
, &sat1
);
3989 bu32 res1
= extract_mult (cpu
, r
, mmod
, MM
, P
, &v_i1
);
3991 buf
+= sprintf (buf
, P
? "R%i" : "R%i.H", dst
+ P
);
3992 buf
+= sprintf (buf
, " = R%i.%c * R%i.%c",
3993 src0
, h01
? 'H' : 'L',
3994 src1
, h11
? 'H' : 'L');
3998 buf
+= sprintf (buf
, " (M)");
4000 buf
+= sprintf (buf
, ", ");
4004 STORE (DREG (dst
+ 1), res1
);
4007 if (res1
& 0xFFFF0000)
4008 illegal_instruction (cpu
);
4009 res
= REG_H_L (res1
<< 16, res
);
4013 /* First handle MAC0 side. */
4016 bu64 r
= decode_multfunc (cpu
, h00
, h10
, src0
, src1
, mmod
, 0, &sat0
);
4017 bu32 res0
= extract_mult (cpu
, r
, mmod
, 0, P
, &v_i0
);
4019 buf
+= sprintf (buf
, P
? "R%i" : "R%i.L", dst
);
4020 buf
+= sprintf (buf
, " = R%i.%c * R%i.%c",
4021 src0
, h01
? 'H' : 'L',
4022 src1
, h11
? 'H' : 'L');
4025 STORE (DREG (dst
), res0
);
4028 if (res0
& 0xFFFF0000)
4029 illegal_instruction (cpu
);
4030 res
= REG_H_L (res
, res0
);
4034 TRACE_INSN (cpu
, "%s%s;", _buf
, mac_optmode (mmod
, _MM
));
4036 if (!P
&& (w0
|| w1
))
4037 STORE (DREG (dst
), res
);
4041 bu32 v
= sat0
| sat1
| v_i0
| v_i1
;
4043 STORE (ASTATREG (v
), v
);
4044 STORE (ASTATREG (v_copy
), v
);
4046 STORE (ASTATREG (vs
), v
);
4051 decode_dsp32alu_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
4054 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
4055 | 1 | 1 | 0 | 0 |.M.| 1 | 0 | - | - | - |.HL|.aopcde............|
4056 |.aop...|.s.|.x.|.dst0......|.dst1......|.src0......|.src1......|
4057 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
4058 int s
= ((iw1
>> DSP32Alu_s_bits
) & DSP32Alu_s_mask
);
4059 int x
= ((iw1
>> DSP32Alu_x_bits
) & DSP32Alu_x_mask
);
4060 int aop
= ((iw1
>> DSP32Alu_aop_bits
) & DSP32Alu_aop_mask
);
4061 int src0
= ((iw1
>> DSP32Alu_src0_bits
) & DSP32Alu_src0_mask
);
4062 int src1
= ((iw1
>> DSP32Alu_src1_bits
) & DSP32Alu_src1_mask
);
4063 int dst0
= ((iw1
>> DSP32Alu_dst0_bits
) & DSP32Alu_dst0_mask
);
4064 int dst1
= ((iw1
>> DSP32Alu_dst1_bits
) & DSP32Alu_dst1_mask
);
4065 int M
= ((iw0
>> (DSP32Alu_M_bits
- 16)) & DSP32Alu_M_mask
);
4066 int HL
= ((iw0
>> (DSP32Alu_HL_bits
- 16)) & DSP32Alu_HL_mask
);
4067 int aopcde
= ((iw0
>> (DSP32Alu_aopcde_bits
- 16)) & DSP32Alu_aopcde_mask
);
4069 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32alu
);
4070 TRACE_EXTRACT (cpu
, "%s: M:%i HL:%i aopcde:%i aop:%i s:%i x:%i dst0:%i "
4071 "dst1:%i src0:%i src1:%i",
4072 __func__
, M
, HL
, aopcde
, aop
, s
, x
, dst0
, dst1
, src0
, src1
);
4074 if ((aop
== 0 || aop
== 2) && aopcde
== 9 && x
== 0 && s
== 0 && HL
== 0)
4077 TRACE_INSN (cpu
, "A%i.L = R%i.L;", a
, src0
);
4078 SET_AWREG (a
, REG_H_L (AWREG (a
), DREG (src0
)));
4080 else if ((aop
== 0 || aop
== 2) && aopcde
== 9 && x
== 0 && s
== 0 && HL
== 1)
4083 TRACE_INSN (cpu
, "A%i.H = R%i.H;", a
, src0
);
4084 SET_AWREG (a
, REG_H_L (DREG (src0
), AWREG (a
)));
4086 else if ((aop
== 1 || aop
== 0) && aopcde
== 5 && x
== 0 && s
== 0)
4088 bs32 val0
= DREG (src0
);
4089 bs32 val1
= DREG (src1
);
4092 bs32 ovX
, sBit1
, sBit2
, sBitRes1
, sBitRes2
;
4094 TRACE_INSN (cpu
, "R%i.%s = R%i %s R%i (RND12)", dst0
, HL
? "L" : "H",
4095 src0
, aop
& 0x1 ? "-" : "+", src1
);
4097 /* If subtract, just invert and add one. */
4100 if (val1
== 0x80000000)
4106 /* Get the sign bits, since we need them later. */
4107 sBit1
= !!(val0
& 0x80000000);
4108 sBit2
= !!(val1
& 0x80000000);
4112 sBitRes1
= !!(res
& 0x80000000);
4113 /* Round to the 12th bit. */
4115 sBitRes2
= !!(res
& 0x80000000);
4123 positive_res + positive_round = neg
4124 Shift and upper 4 bits where not the same. */
4125 if ((!(sBit1
^ sBit2
) && (sBit1
^ sBitRes1
))
4126 || (!sBit1
&& !sBit2
&& sBitRes2
)
4127 || ((signRes
!= 0) && (signRes
!= -1)))
4129 /* Both X1 and X2 Neg res is neg overflow. */
4132 /* Both X1 and X2 Pos res is pos overflow. */
4133 else if (!sBit1
&& !sBit2
)
4135 /* Pos+Neg or Neg+Pos take the sign of the result. */
4145 /* Shift up now after overflow detection. */
4153 STORE (DREG (dst0
), REG_H_L (res
<< 16, DREG (dst0
)));
4155 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), res
));
4157 SET_ASTATREG (az
, res
== 0);
4158 SET_ASTATREG (an
, res
& 0x8000);
4159 SET_ASTATREG (v
, ovX
);
4161 SET_ASTATREG (vs
, ovX
);
4163 else if ((aop
== 2 || aop
== 3) && aopcde
== 5 && x
== 1 && s
== 0)
4165 bs32 val0
= DREG (src0
);
4166 bs32 val1
= DREG (src1
);
4169 TRACE_INSN (cpu
, "R%i.%s = R%i %s R%i (RND20)", dst0
, HL
? "L" : "H",
4170 src0
, aop
& 0x1 ? "-" : "+", src1
);
4172 /* If subtract, just invert and add one. */
4176 res
= (val0
>> 4) + (val1
>> 4) + (((val0
& 0xf) + (val1
& 0xf)) >> 4);
4178 /* Don't sign extend during the shift. */
4179 res
= ((bu32
)res
>> 16);
4181 /* Don't worry about overflows, since we are shifting right. */
4184 STORE (DREG (dst0
), REG_H_L (res
<< 16, DREG (dst0
)));
4186 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), res
));
4188 SET_ASTATREG (az
, res
== 0);
4189 SET_ASTATREG (an
, res
& 0x8000);
4190 SET_ASTATREG (v
, 0);
4192 else if ((aopcde
== 2 || aopcde
== 3) && x
== 0)
4194 bu32 s1
, s2
, val
, ac0_i
= 0, v_i
= 0;
4196 TRACE_INSN (cpu
, "R%i.%c = R%i.%c %c R%i.%c%s;",
4197 dst0
, HL
? 'H' : 'L',
4198 src0
, aop
& 2 ? 'H' : 'L',
4199 aopcde
== 2 ? '+' : '-',
4200 src1
, aop
& 1 ? 'H' : 'L',
4211 val
= add16 (cpu
, s1
, s2
, &ac0_i
, &v_i
, 0, 0, s
, 0);
4213 val
= sub16 (cpu
, s1
, s2
, &ac0_i
, &v_i
, 0, 0, s
, 0);
4215 SET_ASTATREG (ac0
, ac0_i
);
4216 SET_ASTATREG (v
, v_i
);
4218 SET_ASTATREG (vs
, v_i
);
4221 SET_DREG_H (dst0
, val
<< 16);
4223 SET_DREG_L (dst0
, val
);
4225 SET_ASTATREG (an
, val
& 0x8000);
4226 SET_ASTATREG (az
, val
== 0);
4228 else if ((aop
== 0 || aop
== 2) && aopcde
== 9 && x
== 0 && s
== 1 && HL
== 0)
4231 TRACE_INSN (cpu
, "A%i = R%i;", a
, src0
);
4232 SET_AREG32 (a
, DREG (src0
));
4234 else if ((aop
== 1 || aop
== 3) && aopcde
== 9 && x
== 0 && s
== 0 && HL
== 0)
4237 TRACE_INSN (cpu
, "A%i.X = R%i.L;", a
, src0
);
4238 SET_AXREG (a
, (bs8
)DREG (src0
));
4240 else if (aop
== 3 && aopcde
== 11 && x
== 0 && HL
== 0)
4242 bu64 acc0
= get_extended_acc (cpu
, 0);
4243 bu64 acc1
= get_extended_acc (cpu
, 1);
4244 bu32 carry
= (bu40
)acc1
< (bu40
)acc0
;
4247 TRACE_INSN (cpu
, "A0 -= A1%s;", s
? " (W32)" : "");
4250 if ((bs64
)acc0
< -0x8000000000ll
)
4251 acc0
= -0x8000000000ull
, sat
= 1;
4252 else if ((bs64
)acc0
>= 0x7fffffffffll
)
4253 acc0
= 0x7fffffffffull
, sat
= 1;
4257 /* A0 -= A1 (W32) */
4258 if (acc0
& (bu64
)0x8000000000ll
)
4259 acc0
&= 0x80ffffffffll
, sat
= 1;
4261 acc0
&= 0xffffffffll
;
4263 STORE (AXREG (0), (acc0
>> 32) & 0xff);
4264 STORE (AWREG (0), acc0
& 0xffffffff);
4265 STORE (ASTATREG (az
), acc0
== 0);
4266 STORE (ASTATREG (an
), !!(acc0
& (bu64
)0x8000000000ll
));
4267 STORE (ASTATREG (ac0
), carry
);
4268 STORE (ASTATREG (ac0_copy
), carry
);
4269 STORE (ASTATREG (av0
), sat
);
4271 STORE (ASTATREG (av0s
), sat
);
4273 else if ((aop
== 0 || aop
== 1) && aopcde
== 22 && x
== 0)
4275 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4277 const char * const opts
[] = { "rndl", "rndh", "tl", "th" };
4279 TRACE_INSN (cpu
, "R%i = BYTEOP2P (R%i:%i, R%i:%i) (%s%s);", dst0
,
4280 src0
+ 1, src0
, src1
+ 1, src1
, opts
[HL
+ (aop
<< 1)],
4283 if ((src1
!= 0 && src1
!= 2) || (src0
!= 0 && src0
!= 2))
4284 illegal_instruction (cpu
);
4287 s0H
= DREG (src0
+ 1);
4289 s1H
= DREG (src1
+ 1);
4292 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4293 s1
= algn (s1H
, s1L
, IREG (0) & 3);
4297 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4298 s1
= algn (s1L
, s1H
, IREG (0) & 3);
4302 tmp0
= ((((s1
>> 8) & 0xff) + ((s1
>> 0) & 0xff) +
4303 ((s0
>> 8) & 0xff) + ((s0
>> 0) & 0xff) + i
) >> 2) & 0xff;
4304 tmp1
= ((((s1
>> 24) & 0xff) + ((s1
>> 16) & 0xff) +
4305 ((s0
>> 24) & 0xff) + ((s0
>> 16) & 0xff) + i
) >> 2) & 0xff;
4306 STORE (DREG (dst0
), (tmp1
<< (16 + (HL
* 8))) | (tmp0
<< (HL
* 8)));
4308 /* Implicit DISALGNEXCPT in parallel. */
4311 else if ((aop
== 0 || aop
== 1) && aopcde
== 8 && x
== 0 && s
== 0 && HL
== 0)
4313 TRACE_INSN (cpu
, "A%i = 0;", aop
);
4316 else if (aop
== 2 && aopcde
== 8 && x
== 0 && s
== 0 && HL
== 0)
4318 TRACE_INSN (cpu
, "A1 = A0 = 0;");
4322 else if ((aop
== 0 || aop
== 1 || aop
== 2) && s
== 1 && aopcde
== 8
4323 && x
== 0 && HL
== 0)
4325 bs40 acc0
= get_extended_acc (cpu
, 0);
4326 bs40 acc1
= get_extended_acc (cpu
, 1);
4329 if (aop
== 0 || aop
== 1)
4330 TRACE_INSN (cpu
, "A%i = A%i (S);", aop
, aop
);
4332 TRACE_INSN (cpu
, "A1 = A1 (S), A0 = A0 (S);");
4334 if (aop
== 0 || aop
== 2)
4337 acc0
= saturate_s32 (acc0
, &sat
);
4338 acc0
|= -(acc0
& 0x80000000ull
);
4339 SET_AXREG (0, (acc0
>> 31) & 0xFF);
4340 SET_AWREG (0, acc0
& 0xFFFFFFFF);
4341 SET_ASTATREG (av0
, sat
);
4343 SET_ASTATREG (av0s
, sat
);
4348 if (aop
== 1 || aop
== 2)
4351 acc1
= saturate_s32 (acc1
, &sat
);
4352 acc1
|= -(acc1
& 0x80000000ull
);
4353 SET_AXREG (1, (acc1
>> 31) & 0xFF);
4354 SET_AWREG (1, acc1
& 0xFFFFFFFF);
4355 SET_ASTATREG (av1
, sat
);
4357 SET_ASTATREG (av1s
, sat
);
4362 SET_ASTATREG (az
, (acc0
== 0) || (acc1
== 0));
4363 SET_ASTATREG (an
, ((acc0
>> 31) & 1) || ((acc1
>> 31) & 1));
4365 else if (aop
== 3 && aopcde
== 8 && x
== 0 && HL
== 0)
4367 TRACE_INSN (cpu
, "A%i = A%i;", s
, !s
);
4368 SET_AXREG (s
, AXREG (!s
));
4369 SET_AWREG (s
, AWREG (!s
));
4371 else if (aop
== 3 && HL
== 0 && aopcde
== 16 && x
== 0 && s
== 0)
4376 TRACE_INSN (cpu
, "A1 = ABS A1 , A0 = ABS A0;");
4379 for (i
= 0; i
< 2; ++i
)
4382 bs40 acc
= get_extended_acc (cpu
, i
);
4386 av
= acc
== ((bs40
)1 << 39);
4388 acc
= ((bs40
)1 << 39) - 1;
4391 SET_ASTATREG (av
[i
], av
);
4393 SET_ASTATREG (avs
[i
], av
);
4396 SET_ASTATREG (az
, az
);
4397 SET_ASTATREG (an
, 0);
4399 else if (aop
== 0 && aopcde
== 23 && x
== 0)
4401 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4404 TRACE_INSN (cpu
, "R%i = BYTEOP3P (R%i:%i, R%i:%i) (%s%s);", dst0
,
4405 src0
+ 1, src0
, src1
+ 1, src1
, HL
? "HI" : "LO",
4408 if ((src1
!= 0 && src1
!= 2) || (src0
!= 0 && src0
!= 2))
4409 illegal_instruction (cpu
);
4412 s0H
= DREG (src0
+ 1);
4414 s1H
= DREG (src1
+ 1);
4417 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4418 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4422 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4423 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4426 tmp0
= (bs32
)(bs16
)(s0
>> 0) + ((s1
>> ( 0 + (8 * !HL
))) & 0xff);
4427 tmp1
= (bs32
)(bs16
)(s0
>> 16) + ((s1
>> (16 + (8 * !HL
))) & 0xff);
4428 STORE (DREG (dst0
), (CLAMP (tmp0
, 0, 255) << ( 0 + (8 * HL
))) |
4429 (CLAMP (tmp1
, 0, 255) << (16 + (8 * HL
))));
4431 /* Implicit DISALGNEXCPT in parallel. */
4434 else if ((aop
== 0 || aop
== 1) && aopcde
== 16 && x
== 0 && s
== 0)
4439 TRACE_INSN (cpu
, "A%i = ABS A%i;", HL
, aop
);
4441 acc
= get_extended_acc (cpu
, aop
);
4444 av
= acc
== ((bs40
)1 << 39);
4446 acc
= ((bs40
)1 << 39) - 1;
4449 SET_ASTATREG (av
[HL
], av
);
4451 SET_ASTATREG (avs
[HL
], av
);
4452 SET_ASTATREG (az
, acc
== 0);
4453 SET_ASTATREG (an
, 0);
4455 else if (aop
== 3 && aopcde
== 12 && x
== 0 && s
== 0)
4457 bs32 res
= DREG (src0
);
4459 bool sBit_a
, sBit_b
;
4461 TRACE_INSN (cpu
, "R%i.%s = R%i (RND);", dst0
, HL
== 0 ? "L" : "H", src0
);
4462 TRACE_DECODE (cpu
, "R%i.%s = R%i:%#x (RND);", dst0
,
4463 HL
== 0 ? "L" : "H", src0
, res
);
4465 sBit_b
= !!(res
& 0x80000000);
4468 sBit_a
= !!(res
& 0x80000000);
4470 /* Overflow if the sign bit changed when we rounded. */
4471 if ((res
>> 16) && (sBit_b
!= sBit_a
))
4486 SET_DREG (dst0
, REG_H_L (DREG (dst0
), res
));
4488 SET_DREG (dst0
, REG_H_L (res
<< 16, DREG (dst0
)));
4490 SET_ASTATREG (az
, res
== 0);
4491 SET_ASTATREG (an
, res
< 0);
4492 SET_ASTATREG (v
, ovX
);
4494 SET_ASTATREG (vs
, ovX
);
4496 else if (aop
== 3 && HL
== 0 && aopcde
== 15 && x
== 0 && s
== 0)
4498 bu32 hi
= (-(bs16
)(DREG (src0
) >> 16)) << 16;
4499 bu32 lo
= (-(bs16
)(DREG (src0
) & 0xFFFF)) & 0xFFFF;
4502 TRACE_INSN (cpu
, "R%i = -R%i (V);", dst0
, src0
);
4506 if (hi
== 0x80000000)
4522 SET_DREG (dst0
, hi
| lo
);
4524 SET_ASTATREG (v
, v
);
4526 SET_ASTATREG (vs
, 1);
4527 SET_ASTATREG (ac0
, ac0
);
4528 SET_ASTATREG (ac1
, ac1
);
4529 setflags_nz_2x16 (cpu
, DREG (dst0
));
4531 else if (aop
== 3 && HL
== 0 && aopcde
== 14 && x
== 0 && s
== 0)
4533 TRACE_INSN (cpu
, "A1 = - A1 , A0 = - A0;");
4535 SET_AREG (0, saturate_s40 (-get_extended_acc (cpu
, 0)));
4536 SET_AREG (1, saturate_s40 (-get_extended_acc (cpu
, 1)));
4537 /* XXX: what ASTAT flags need updating ? */
4539 else if ((aop
== 0 || aop
== 1) && aopcde
== 14 && x
== 0 && s
== 0)
4541 bs40 src_acc
= get_extended_acc (cpu
, aop
);
4544 TRACE_INSN (cpu
, "A%i = - A%i;", HL
, aop
);
4546 SET_AREG (HL
, saturate_s40_astat (-src_acc
, &v
));
4548 SET_ASTATREG (az
, AWREG (HL
) == 0 && AXREG (HL
) == 0);
4549 SET_ASTATREG (an
, AXREG (HL
) >> 7);
4552 SET_ASTATREG (ac0
, !src_acc
);
4553 SET_ASTATREG (av0
, v
);
4555 SET_ASTATREG (av0s
, 1);
4559 SET_ASTATREG (ac1
, !src_acc
);
4560 SET_ASTATREG (av1
, v
);
4562 SET_ASTATREG (av1s
, 1);
4565 else if (aop
== 0 && aopcde
== 12 && x
== 0 && s
== 0 && HL
== 0)
4567 bs16 tmp0_hi
= DREG (src0
) >> 16;
4568 bs16 tmp0_lo
= DREG (src0
);
4569 bs16 tmp1_hi
= DREG (src1
) >> 16;
4570 bs16 tmp1_lo
= DREG (src1
);
4572 TRACE_INSN (cpu
, "R%i.L = R%i.H = SIGN(R%i.H) * R%i.H + SIGN(R%i.L) * R%i.L;",
4573 dst0
, dst0
, src0
, src1
, src0
, src1
);
4575 if ((tmp0_hi
>> 15) & 1)
4576 tmp1_hi
= ~tmp1_hi
+ 1;
4578 if ((tmp0_lo
>> 15) & 1)
4579 tmp1_lo
= ~tmp1_lo
+ 1;
4581 tmp1_hi
= tmp1_hi
+ tmp1_lo
;
4583 STORE (DREG (dst0
), REG_H_L (tmp1_hi
<< 16, tmp1_hi
));
4585 else if (aopcde
== 0 && HL
== 0)
4587 bu32 s0
= DREG (src0
);
4588 bu32 s1
= DREG (src1
);
4589 bu32 s0h
= s0
>> 16;
4590 bu32 s0l
= s0
& 0xFFFF;
4591 bu32 s1h
= s1
>> 16;
4592 bu32 s1l
= s1
& 0xFFFF;
4594 bu32 ac1_i
= 0, ac0_i
= 0, v_i
= 0, z_i
= 0, n_i
= 0;
4596 TRACE_INSN (cpu
, "R%i = R%i %c|%c R%i%s;", dst0
, src0
,
4597 (aop
& 2) ? '-' : '+', (aop
& 1) ? '-' : '+', src1
,
4600 t0
= sub16 (cpu
, s0h
, s1h
, &ac1_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4602 t0
= add16 (cpu
, s0h
, s1h
, &ac1_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4605 t1
= sub16 (cpu
, s0l
, s1l
, &ac0_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4607 t1
= add16 (cpu
, s0l
, s1l
, &ac0_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4609 SET_ASTATREG (ac1
, ac1_i
);
4610 SET_ASTATREG (ac0
, ac0_i
);
4611 SET_ASTATREG (az
, z_i
);
4612 SET_ASTATREG (an
, n_i
);
4613 SET_ASTATREG (v
, v_i
);
4615 SET_ASTATREG (vs
, v_i
);
4620 SET_DREG (dst0
, (t1
<< 16) | t0
);
4622 SET_DREG (dst0
, (t0
<< 16) | t1
);
4624 else if (aop
== 1 && aopcde
== 12 && x
== 0 && s
== 0 && HL
== 0)
4626 bs32 val0
= (bs16
)(AWREG (0) >> 16) + (bs16
)AWREG (0);
4627 bs32 val1
= (bs16
)(AWREG (1) >> 16) + (bs16
)AWREG (1);
4629 TRACE_INSN (cpu
, "R%i = A1.L + A1.H, R%i = A0.L + A0.H;", dst1
, dst0
);
4632 illegal_instruction_combination (cpu
);
4634 SET_DREG (dst0
, val0
);
4635 SET_DREG (dst1
, val1
);
4637 else if ((aop
== 0 || aop
== 2 || aop
== 3) && aopcde
== 1)
4641 bu16 s0L
= DREG (src0
);
4642 bu16 s0H
= DREG (src0
) >> 16;
4643 bu16 s1L
= DREG (src1
);
4644 bu16 s1H
= DREG (src1
) >> 16;
4645 bu32 v_i
= 0, n_i
= 0, z_i
= 0;
4647 TRACE_INSN (cpu
, "R%i = R%i %s R%i, R%i = R%i %s R%i%s;",
4648 dst1
, src0
, HL
? "+|-" : "+|+", src1
,
4649 dst0
, src0
, HL
? "-|+" : "-|-", src1
,
4650 amod0amod2 (s
, x
, aop
));
4653 illegal_instruction_combination (cpu
);
4657 x0
= add16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4658 x1
= add16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4659 d1
= (x0
<< 16) | x1
;
4661 x0
= sub16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4662 x1
= sub16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4664 d0
= (x0
<< 16) | x1
;
4666 d0
= (x1
<< 16) | x0
;
4670 x0
= add16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4671 x1
= sub16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4672 d1
= (x0
<< 16) | x1
;
4674 x0
= sub16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4675 x1
= add16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4677 d0
= (x0
<< 16) | x1
;
4679 d0
= (x1
<< 16) | x0
;
4681 SET_ASTATREG (az
, z_i
);
4682 SET_ASTATREG (an
, n_i
);
4683 SET_ASTATREG (v
, v_i
);
4685 SET_ASTATREG (vs
, v_i
);
4687 STORE (DREG (dst0
), d0
);
4688 STORE (DREG (dst1
), d1
);
4690 else if ((aop
== 0 || aop
== 1 || aop
== 2) && aopcde
== 11 && x
== 0)
4692 bs40 acc0
= get_extended_acc (cpu
, 0);
4693 bs40 acc1
= get_extended_acc (cpu
, 1);
4694 bu32 v
, dreg
, sat
= 0;
4695 bu32 carry
= !!((bu40
)~acc1
< (bu40
)acc0
);
4699 if (s
!= 0 || HL
!= 0)
4700 illegal_instruction (cpu
);
4701 TRACE_INSN (cpu
, "R%i = (A0 += A1);", dst0
);
4706 illegal_instruction (cpu
);
4707 TRACE_INSN (cpu
, "R%i.%c = (A0 += A1);", dst0
, HL
? 'H' : 'L');
4712 illegal_instruction (cpu
);
4713 TRACE_INSN (cpu
, "A0 += A1%s;", s
? " (W32)" : "");
4717 acc0
= saturate_s40_astat (acc0
, &v
);
4719 if (aop
== 2 && s
== 1) /* A0 += A1 (W32) */
4721 if (acc0
& (bs40
)0x8000000000ll
)
4722 acc0
&= 0x80ffffffffll
;
4724 acc0
&= 0xffffffffll
;
4727 STORE (AXREG (0), acc0
>> 32);
4728 STORE (AWREG (0), acc0
);
4729 SET_ASTATREG (av0
, v
&& acc1
);
4731 SET_ASTATREG (av0s
, v
);
4733 if (aop
== 0 || aop
== 1)
4735 if (aop
) /* Dregs_lo = A0 += A1 */
4737 dreg
= saturate_s32 (rnd16 (acc0
) << 16, &sat
);
4739 STORE (DREG (dst0
), REG_H_L (dreg
, DREG (dst0
)));
4741 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), dreg
>> 16));
4743 else /* Dregs = A0 += A1 */
4745 dreg
= saturate_s32 (acc0
, &sat
);
4746 STORE (DREG (dst0
), dreg
);
4749 STORE (ASTATREG (az
), dreg
== 0);
4750 STORE (ASTATREG (an
), !!(dreg
& 0x80000000));
4751 STORE (ASTATREG (ac0
), carry
);
4752 STORE (ASTATREG (ac0_copy
), carry
);
4753 STORE (ASTATREG (v
), sat
);
4754 STORE (ASTATREG (v_copy
), sat
);
4756 STORE (ASTATREG (vs
), sat
);
4760 STORE (ASTATREG (az
), acc0
== 0);
4761 STORE (ASTATREG (an
), !!(acc0
& 0x8000000000ull
));
4762 STORE (ASTATREG (ac0
), carry
);
4763 STORE (ASTATREG (ac0_copy
), carry
);
4766 else if ((aop
== 0 || aop
== 1) && aopcde
== 10 && x
== 0 && s
== 0 && HL
== 0)
4768 TRACE_INSN (cpu
, "R%i.L = A%i.X;", dst0
, aop
);
4769 SET_DREG_L (dst0
, (bs8
)AXREG (aop
));
4771 else if (aop
== 0 && aopcde
== 4 && x
== 0 && HL
== 0)
4773 TRACE_INSN (cpu
, "R%i = R%i + R%i%s;", dst0
, src0
, src1
, amod1 (s
, x
));
4774 SET_DREG (dst0
, add32 (cpu
, DREG (src0
), DREG (src1
), 1, s
));
4776 else if (aop
== 1 && aopcde
== 4 && x
== 0 && HL
== 0)
4778 TRACE_INSN (cpu
, "R%i = R%i - R%i%s;", dst0
, src0
, src1
, amod1 (s
, x
));
4779 SET_DREG (dst0
, sub32 (cpu
, DREG (src0
), DREG (src1
), 1, s
, 0));
4781 else if (aop
== 2 && aopcde
== 4 && x
== 0 && HL
== 0)
4783 TRACE_INSN (cpu
, "R%i = R%i + R%i, R%i = R%i - R%i%s;",
4784 dst1
, src0
, src1
, dst0
, src0
, src1
, amod1 (s
, x
));
4787 illegal_instruction_combination (cpu
);
4789 STORE (DREG (dst1
), add32 (cpu
, DREG (src0
), DREG (src1
), 1, s
));
4790 STORE (DREG (dst0
), sub32 (cpu
, DREG (src0
), DREG (src1
), 1, s
, 1));
4792 else if ((aop
== 0 || aop
== 1) && aopcde
== 17 && x
== 0 && HL
== 0)
4794 bs40 acc0
= get_extended_acc (cpu
, 0);
4795 bs40 acc1
= get_extended_acc (cpu
, 1);
4796 bs40 val0
, val1
, sval0
, sval1
;
4799 TRACE_INSN (cpu
, "R%i = A%i + A%i, R%i = A%i - A%i%s",
4800 dst1
, !aop
, aop
, dst0
, !aop
, aop
, amod1 (s
, x
));
4801 TRACE_DECODE (cpu
, "R%i = A%i:%#"PRIx64
" + A%i:%#"PRIx64
", "
4802 "R%i = A%i:%#"PRIx64
" - A%i:%#"PRIx64
"%s",
4803 dst1
, !aop
, aop
? acc0
: acc1
, aop
, aop
? acc1
: acc0
,
4804 dst0
, !aop
, aop
? acc0
: acc1
, aop
, aop
? acc1
: acc0
,
4808 illegal_instruction_combination (cpu
);
4816 sval0
= saturate_s32 (val0
, &sat
);
4818 sval1
= saturate_s32 (val1
, &sat
);
4826 STORE (DREG (dst0
), val0
);
4827 STORE (DREG (dst1
), val1
);
4828 SET_ASTATREG (v
, sat_i
);
4830 SET_ASTATREG (vs
, sat_i
);
4831 SET_ASTATREG (an
, val0
& 0x80000000 || val1
& 0x80000000);
4832 SET_ASTATREG (az
, val0
== 0 || val1
== 0);
4833 SET_ASTATREG (ac1
, (bu40
)~acc0
< (bu40
)acc1
);
4835 SET_ASTATREG (ac0
, !!((bu40
)acc1
<= (bu40
)acc0
));
4837 SET_ASTATREG (ac0
, !!((bu40
)acc0
<= (bu40
)acc1
));
4839 else if (aop
== 0 && aopcde
== 18 && x
== 0 && HL
== 0)
4841 bu40 acc0
= get_extended_acc (cpu
, 0);
4842 bu40 acc1
= get_extended_acc (cpu
, 1);
4843 bu32 s0L
= DREG (src0
);
4844 bu32 s0H
= DREG (src0
+ 1);
4845 bu32 s1L
= DREG (src1
);
4846 bu32 s1H
= DREG (src1
+ 1);
4848 bs16 tmp0
, tmp1
, tmp2
, tmp3
;
4850 /* This instruction is only defined for register pairs R1:0 and R3:2. */
4851 if (!((src0
== 0 || src0
== 2) && (src1
== 0 || src1
== 2)))
4852 illegal_instruction (cpu
);
4854 TRACE_INSN (cpu
, "SAA (R%i:%i, R%i:%i)%s", src0
+ 1, src0
,
4855 src1
+ 1, src1
, s
? " (R)" :"");
4857 /* Bit s determines the order of the two registers from a pair:
4858 if s=0 the low-order bytes come from the low reg in the pair,
4859 and if s=1 the low-order bytes come from the high reg. */
4863 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4864 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4868 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4869 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4872 /* Find the absolute difference between pairs, make it
4873 absolute, then add it to the existing accumulator half. */
4875 tmp0
= ((s0
<< 24) >> 24) - ((s1
<< 24) >> 24);
4876 tmp1
= ((s0
<< 16) >> 24) - ((s1
<< 16) >> 24);
4877 tmp2
= ((s0
<< 8) >> 24) - ((s1
<< 8) >> 24);
4878 tmp3
= ((s0
<< 0) >> 24) - ((s1
<< 0) >> 24);
4880 tmp0
= (tmp0
< 0) ? -tmp0
: tmp0
;
4881 tmp1
= (tmp1
< 0) ? -tmp1
: tmp1
;
4882 tmp2
= (tmp2
< 0) ? -tmp2
: tmp2
;
4883 tmp3
= (tmp3
< 0) ? -tmp3
: tmp3
;
4885 s0L
= saturate_u16 ((bu32
)tmp0
+ ((acc0
>> 0) & 0xffff), 0);
4886 s0H
= saturate_u16 ((bu32
)tmp1
+ ((acc0
>> 16) & 0xffff), 0);
4887 s1L
= saturate_u16 ((bu32
)tmp2
+ ((acc1
>> 0) & 0xffff), 0);
4888 s1H
= saturate_u16 ((bu32
)tmp3
+ ((acc1
>> 16) & 0xffff), 0);
4890 STORE (AWREG (0), (s0H
<< 16) | (s0L
& 0xFFFF));
4891 STORE (AXREG (0), 0);
4892 STORE (AWREG (1), (s1H
<< 16) | (s1L
& 0xFFFF));
4893 STORE (AXREG (1), 0);
4895 /* Implicit DISALGNEXCPT in parallel. */
4898 else if (aop
== 3 && aopcde
== 18 && x
== 0 && s
== 0 && HL
== 0)
4900 TRACE_INSN (cpu
, "DISALGNEXCPT");
4903 else if ((aop
== 0 || aop
== 1) && aopcde
== 20 && x
== 0 && HL
== 0)
4905 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4906 const char * const opts
[] = { "", " (R)", " (T)", " (T, R)" };
4908 TRACE_INSN (cpu
, "R%i = BYTEOP1P (R%i:%i, R%i:%i)%s;", dst0
,
4909 src0
+ 1, src0
, src1
+ 1, src1
, opts
[s
+ (aop
<< 1)]);
4911 if ((src1
!= 0 && src1
!= 2) || (src0
!= 0 && src0
!= 2))
4912 illegal_instruction (cpu
);
4915 s0H
= DREG (src0
+ 1);
4917 s1H
= DREG (src1
+ 1);
4920 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4921 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4925 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4926 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4930 (((((s0
>> 0) & 0xff) + ((s1
>> 0) & 0xff) + !aop
) >> 1) << 0) |
4931 (((((s0
>> 8) & 0xff) + ((s1
>> 8) & 0xff) + !aop
) >> 1) << 8) |
4932 (((((s0
>> 16) & 0xff) + ((s1
>> 16) & 0xff) + !aop
) >> 1) << 16) |
4933 (((((s0
>> 24) & 0xff) + ((s1
>> 24) & 0xff) + !aop
) >> 1) << 24));
4935 /* Implicit DISALGNEXCPT in parallel. */
4938 else if (aop
== 0 && aopcde
== 21 && x
== 0 && HL
== 0)
4940 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4942 TRACE_INSN (cpu
, "(R%i, R%i) = BYTEOP16P (R%i:%i, R%i:%i)%s;", dst1
, dst0
,
4943 src0
+ 1, src0
, src1
+ 1, src1
, s
? " (R)" : "");
4945 if ((src1
!= 0 && src1
!= 2) || (src0
!= 0 && src0
!= 2))
4946 illegal_instruction (cpu
);
4949 illegal_instruction_combination (cpu
);
4952 s0H
= DREG (src0
+ 1);
4954 s1H
= DREG (src1
+ 1);
4957 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4958 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4962 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4963 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4967 ((((s0
>> 0) & 0xff) + ((s1
>> 0) & 0xff)) << 0) |
4968 ((((s0
>> 8) & 0xff) + ((s1
>> 8) & 0xff)) << 16));
4970 ((((s0
>> 16) & 0xff) + ((s1
>> 16) & 0xff)) << 0) |
4971 ((((s0
>> 24) & 0xff) + ((s1
>> 24) & 0xff)) << 16));
4973 /* Implicit DISALGNEXCPT in parallel. */
4976 else if (aop
== 1 && aopcde
== 21 && x
== 0 && HL
== 0)
4978 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4980 TRACE_INSN (cpu
, "(R%i, R%i) = BYTEOP16M (R%i:%i, R%i:%i)%s;", dst1
, dst0
,
4981 src0
+ 1, src0
, src1
+ 1, src1
, s
? " (R)" : "");
4983 if ((src1
!= 0 && src1
!= 2) || (src0
!= 0 && src0
!= 2))
4984 illegal_instruction (cpu
);
4987 illegal_instruction_combination (cpu
);
4990 s0H
= DREG (src0
+ 1);
4992 s1H
= DREG (src1
+ 1);
4995 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4996 s1
= algn (s1H
, s1L
, IREG (1) & 3);
5000 s0
= algn (s0L
, s0H
, IREG (0) & 3);
5001 s1
= algn (s1L
, s1H
, IREG (1) & 3);
5005 (((((s0
>> 0) & 0xff) - ((s1
>> 0) & 0xff)) << 0) & 0xffff) |
5006 (((((s0
>> 8) & 0xff) - ((s1
>> 8) & 0xff)) << 16)));
5008 (((((s0
>> 16) & 0xff) - ((s1
>> 16) & 0xff)) << 0) & 0xffff) |
5009 (((((s0
>> 24) & 0xff) - ((s1
>> 24) & 0xff)) << 16)));
5011 /* Implicit DISALGNEXCPT in parallel. */
5014 else if (aop
== 1 && aopcde
== 7 && x
== 0 && s
== 0 && HL
== 0)
5016 TRACE_INSN (cpu
, "R%i = MIN (R%i, R%i);", dst0
, src0
, src1
);
5017 SET_DREG (dst0
, min32 (cpu
, DREG (src0
), DREG (src1
)));
5019 else if (aop
== 0 && aopcde
== 7 && x
== 0 && s
== 0 && HL
== 0)
5021 TRACE_INSN (cpu
, "R%i = MAX (R%i, R%i);", dst0
, src0
, src1
);
5022 SET_DREG (dst0
, max32 (cpu
, DREG (src0
), DREG (src1
)));
5024 else if (aop
== 2 && aopcde
== 7 && x
== 0 && s
== 0 && HL
== 0)
5026 bu32 val
= DREG (src0
);
5029 TRACE_INSN (cpu
, "R%i = ABS R%i;", dst0
, src0
);
5033 v
= (val
== 0x80000000);
5036 SET_DREG (dst0
, val
);
5038 SET_ASTATREG (v
, v
);
5040 SET_ASTATREG (vs
, 1);
5041 setflags_nz (cpu
, val
);
5043 else if (aop
== 3 && aopcde
== 7 && x
== 0 && HL
== 0)
5045 bu32 val
= DREG (src0
);
5047 TRACE_INSN (cpu
, "R%i = - R%i%s;", dst0
, src0
, amod1 (s
, 0));
5049 if (s
&& val
== 0x80000000)
5052 SET_ASTATREG (v
, 1);
5053 SET_ASTATREG (vs
, 1);
5055 else if (val
== 0x80000000)
5059 SET_DREG (dst0
, val
);
5061 SET_ASTATREG (az
, val
== 0);
5062 SET_ASTATREG (an
, val
& 0x80000000);
5064 else if (aop
== 2 && aopcde
== 6 && x
== 0 && s
== 0 && HL
== 0)
5066 bu32 in
= DREG (src0
);
5067 bu32 hi
= (in
& 0x80000000 ? (bu32
)-(bs16
)(in
>> 16) : in
>> 16) << 16;
5068 bu32 lo
= (in
& 0x8000 ? (bu32
)-(bs16
)(in
& 0xFFFF) : in
) & 0xFFFF;
5071 TRACE_INSN (cpu
, "R%i = ABS R%i (V);", dst0
, src0
);
5074 if (hi
== 0x80000000)
5084 SET_DREG (dst0
, hi
| lo
);
5086 SET_ASTATREG (v
, v
);
5088 SET_ASTATREG (vs
, 1);
5089 setflags_nz_2x16 (cpu
, DREG (dst0
));
5091 else if (aop
== 1 && aopcde
== 6 && x
== 0 && s
== 0 && HL
== 0)
5093 TRACE_INSN (cpu
, "R%i = MIN (R%i, R%i) (V);", dst0
, src0
, src1
);
5094 SET_DREG (dst0
, min2x16 (cpu
, DREG (src0
), DREG (src1
)));
5096 else if (aop
== 0 && aopcde
== 6 && x
== 0 && s
== 0 && HL
== 0)
5098 TRACE_INSN (cpu
, "R%i = MAX (R%i, R%i) (V);", dst0
, src0
, src1
);
5099 SET_DREG (dst0
, max2x16 (cpu
, DREG (src0
), DREG (src1
)));
5101 else if (aop
== 0 && aopcde
== 24 && x
== 0 && s
== 0 && HL
== 0)
5103 TRACE_INSN (cpu
, "R%i = BYTEPACK (R%i, R%i);", dst0
, src0
, src1
);
5105 (((DREG (src0
) >> 0) & 0xff) << 0) |
5106 (((DREG (src0
) >> 16) & 0xff) << 8) |
5107 (((DREG (src1
) >> 0) & 0xff) << 16) |
5108 (((DREG (src1
) >> 16) & 0xff) << 24));
5110 /* Implicit DISALGNEXCPT in parallel. */
5113 else if (aop
== 1 && aopcde
== 24 && x
== 0 && HL
== 0)
5117 bu8 bytea
, byteb
, bytec
, byted
;
5119 TRACE_INSN (cpu
, "(R%i, R%i) = BYTEUNPACK R%i:%i%s;",
5120 dst1
, dst0
, src0
+ 1, src0
, s
? " (R)" : "");
5122 if ((src1
!= 0 && src1
!= 2) || (src0
!= 0 && src0
!= 2))
5123 illegal_instruction (cpu
);
5126 illegal_instruction_combination (cpu
);
5128 order
= IREG (0) & 0x3;
5130 hi
= src0
, lo
= src0
+ 1;
5132 hi
= src0
+ 1, lo
= src0
;
5133 comb_src
= (((bu64
)DREG (hi
)) << 32) | DREG (lo
);
5134 bytea
= (comb_src
>> (0 + 8 * order
));
5135 byteb
= (comb_src
>> (8 + 8 * order
));
5136 bytec
= (comb_src
>> (16 + 8 * order
));
5137 byted
= (comb_src
>> (24 + 8 * order
));
5138 STORE (DREG (dst0
), bytea
| ((bu32
)byteb
<< 16));
5139 STORE (DREG (dst1
), bytec
| ((bu32
)byted
<< 16));
5141 /* Implicit DISALGNEXCPT in parallel. */
5144 else if (aopcde
== 13 && HL
== 0 && x
== 0 && s
== 0)
5146 const char *searchmodes
[] = { "GT", "GE", "LT", "LE" };
5148 bs16 a0_lo
, a1_lo
, src_hi
, src_lo
;
5150 TRACE_INSN (cpu
, "(R%i, R%i) = SEARCH R%i (%s);",
5151 dst1
, dst0
, src0
, searchmodes
[aop
]);
5153 /* XXX: The parallel version is a bit weird in its limits:
5155 This instruction can be issued in parallel with the combination of one
5156 16-bit length load instruction to the P0 register and one 16-bit NOP.
5157 No other instructions can be issued in parallel with the Vector Search
5158 instruction. Note the following legal and illegal forms.
5159 (r1, r0) = search r2 (LT) || r2 = [p0++p3]; // ILLEGAL
5160 (r1, r0) = search r2 (LT) || r2 = [p0++]; // LEGAL
5161 (r1, r0) = search r2 (LT) || r2 = [p0++]; // LEGAL
5163 Unfortunately, our parallel insn state doesn't (currently) track enough
5164 details to be able to check this. */
5167 illegal_instruction_combination (cpu
);
5169 up_hi
= up_lo
= false;
5172 src_lo
= DREG (src0
);
5173 src_hi
= DREG (src0
) >> 16;
5178 up_hi
= (src_hi
> a1_lo
);
5179 up_lo
= (src_lo
> a0_lo
);
5182 up_hi
= (src_hi
>= a1_lo
);
5183 up_lo
= (src_lo
>= a0_lo
);
5186 up_hi
= (src_hi
< a1_lo
);
5187 up_lo
= (src_lo
< a0_lo
);
5190 up_hi
= (src_hi
<= a1_lo
);
5191 up_lo
= (src_lo
<= a0_lo
);
5197 SET_AREG (1, src_hi
);
5198 SET_DREG (dst1
, PREG (0));
5201 SET_AREG (1, a1_lo
);
5205 SET_AREG (0, src_lo
);
5206 SET_DREG (dst0
, PREG (0));
5209 SET_AREG (0, a0_lo
);
5212 illegal_instruction (cpu
);
5216 decode_dsp32shift_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
5219 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5220 | 1 | 1 | 0 | 0 |.M.| 1 | 1 | 0 | 0 | - | - |.sopcde............|
5221 |.sop...|.HLs...|.dst0......| - | - | - |.src0......|.src1......|
5222 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5223 int HLs
= ((iw1
>> DSP32Shift_HLs_bits
) & DSP32Shift_HLs_mask
);
5224 int sop
= ((iw1
>> DSP32Shift_sop_bits
) & DSP32Shift_sop_mask
);
5225 int src0
= ((iw1
>> DSP32Shift_src0_bits
) & DSP32Shift_src0_mask
);
5226 int src1
= ((iw1
>> DSP32Shift_src1_bits
) & DSP32Shift_src1_mask
);
5227 int dst0
= ((iw1
>> DSP32Shift_dst0_bits
) & DSP32Shift_dst0_mask
);
5228 int sopcde
= ((iw0
>> (DSP32Shift_sopcde_bits
- 16)) & DSP32Shift_sopcde_mask
);
5229 int M
= ((iw0
>> (DSP32Shift_M_bits
- 16)) & DSP32Shift_M_mask
);
5231 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32shift
);
5232 TRACE_EXTRACT (cpu
, "%s: M:%i sopcde:%i sop:%i HLs:%i dst0:%i src0:%i src1:%i",
5233 __func__
, M
, sopcde
, sop
, HLs
, dst0
, src0
, src1
);
5235 if ((sop
== 0 || sop
== 1) && sopcde
== 0)
5238 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5240 TRACE_INSN (cpu
, "R%i.%c = ASHIFT R%i.%c BY R%i.L%s;",
5241 dst0
, HLs
< 2 ? 'L' : 'H',
5242 src1
, HLs
& 1 ? 'H' : 'L',
5243 src0
, sop
== 1 ? " (S)" : "");
5246 val
= (bu16
)(DREG (src1
) & 0xFFFF);
5248 val
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5250 /* Positive shift magnitudes produce Logical Left shifts.
5251 Negative shift magnitudes produce Arithmetic Right shifts. */
5253 val
= ashiftrt (cpu
, val
, -shft
, 16);
5256 int sgn
= (val
>> 15) & 0x1;
5258 val
= lshift (cpu
, val
, shft
, 16, sop
== 1, 1);
5259 if (((val
>> 15) & 0x1) != sgn
)
5261 SET_ASTATREG (v
, 1);
5262 SET_ASTATREG (vs
, 1);
5267 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), val
));
5269 STORE (DREG (dst0
), REG_H_L (val
<< 16, DREG (dst0
)));
5271 else if (sop
== 2 && sopcde
== 0)
5273 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5276 TRACE_INSN (cpu
, "R%i.%c = LSHIFT R%i.%c BY R%i.L;",
5277 dst0
, HLs
< 2 ? 'L' : 'H',
5278 src1
, HLs
& 1 ? 'H' : 'L', src0
);
5281 val
= (bu16
)(DREG (src1
) & 0xFFFF);
5283 val
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5286 val
= val
>> (-1 * shft
);
5291 SET_DREG (dst0
, REG_H_L (DREG (dst0
), val
));
5293 SET_DREG (dst0
, REG_H_L (val
<< 16, DREG (dst0
)));
5295 SET_ASTATREG (az
, !((val
& 0xFFFF0000) == 0) || ((val
& 0xFFFF) == 0));
5296 SET_ASTATREG (an
, (!!(val
& 0x80000000)) ^ (!!(val
& 0x8000)));
5297 SET_ASTATREG (v
, 0);
5299 else if (sop
== 2 && sopcde
== 3 && (HLs
== 1 || HLs
== 0))
5301 int shift
= imm6 (DREG (src0
) & 0xFFFF);
5303 bu40 acc
= get_unextended_acc (cpu
, HLs
);
5305 TRACE_INSN (cpu
, "A%i = ROT A%i BY R%i.L;", HLs
, HLs
, src0
);
5306 TRACE_DECODE (cpu
, "A%i:%#"PRIx64
" shift:%i CC:%i", HLs
, acc
, shift
, cc
);
5308 acc
= rot40 (acc
, shift
, &cc
);
5309 SET_AREG (HLs
, acc
);
5313 else if (sop
== 0 && sopcde
== 3 && (HLs
== 0 || HLs
== 1))
5315 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5316 bu64 acc
= get_extended_acc (cpu
, HLs
);
5320 TRACE_INSN (cpu
, "A%i = ASHIFT A%i BY R%i.L;", HLs
, HLs
, src0
);
5321 TRACE_DECODE (cpu
, "A%i:%#"PRIx64
" shift:%i", HLs
, acc
, shft
);
5324 val
= ashiftrt (cpu
, acc
, -shft
, 40);
5326 val
= lshift (cpu
, acc
, shft
, 40, 0, 0);
5328 STORE (AXREG (HLs
), (val
>> 32) & 0xff);
5329 STORE (AWREG (HLs
), (val
& 0xffffffff));
5330 STORE (ASTATREG (av
[HLs
]), 0);
5332 else if (sop
== 1 && sopcde
== 3 && (HLs
== 0 || HLs
== 1))
5334 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5335 bu64 acc
= get_unextended_acc (cpu
, HLs
);
5339 TRACE_INSN (cpu
, "A%i = LSHIFT A%i BY R%i.L;", HLs
, HLs
, src0
);
5340 TRACE_DECODE (cpu
, "A%i:%#"PRIx64
" shift:%i", HLs
, acc
, shft
);
5343 val
= lshiftrt (cpu
, acc
, -shft
, 40);
5345 val
= lshift (cpu
, acc
, shft
, 40, 0, 0);
5347 STORE (AXREG (HLs
), (val
>> 32) & 0xff);
5348 STORE (AWREG (HLs
), (val
& 0xffffffff));
5349 STORE (ASTATREG (av
[HLs
]), 0);
5352 /* All the insns after this point don't use HLs. */
5353 illegal_instruction (cpu
);
5354 else if ((sop
== 0 || sop
== 1) && sopcde
== 1 && HLs
== 0)
5356 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5360 TRACE_INSN (cpu
, "R%i = ASHIFT R%i BY R%i.L (V%s);",
5361 dst0
, src1
, src0
, sop
== 1 ? ",S" : "");
5363 val0
= (bu16
)DREG (src1
) & 0xFFFF;
5364 val1
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5368 val0
= ashiftrt (cpu
, val0
, -shft
, 16);
5370 val1
= ashiftrt (cpu
, val1
, -shft
, 16);
5374 int sgn0
= (val0
>> 15) & 0x1;
5375 int sgn1
= (val1
>> 15) & 0x1;
5377 val0
= lshift (cpu
, val0
, shft
, 16, sop
== 1, 1);
5379 val1
= lshift (cpu
, val1
, shft
, 16, sop
== 1, 1);
5381 if ((sgn0
!= ((val0
>> 15) & 0x1)) || (sgn1
!= ((val1
>> 15) & 0x1)))
5383 SET_ASTATREG (v
, 1);
5384 SET_ASTATREG (vs
, 1);
5387 SET_ASTAT (ASTAT
| astat
);
5388 STORE (DREG (dst0
), (val1
<< 16) | val0
);
5390 else if ((sop
== 0 || sop
== 1 || sop
== 2) && sopcde
== 2)
5392 /* dregs = [LA]SHIFT dregs BY dregs_lo (opt_S) */
5393 /* sop == 1 : opt_S */
5394 bu32 v
= DREG (src1
);
5395 /* LSHIFT uses sign extended low 6 bits of dregs_lo. */
5396 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5398 TRACE_INSN (cpu
, "R%i = %cSHIFT R%i BY R%i.L%s;", dst0
,
5399 shft
&& sop
!= 2 ? 'A' : 'L', src1
, src0
,
5400 sop
== 1 ? " (S)" : "");
5405 STORE (DREG (dst0
), lshiftrt (cpu
, v
, -shft
, 32));
5407 STORE (DREG (dst0
), ashiftrt (cpu
, v
, -shft
, 32));
5411 bu32 val
= lshift (cpu
, v
, shft
, 32, sop
== 1, 1);
5413 STORE (DREG (dst0
), val
);
5414 if (((v
>> 31) & 0x1) != ((val
>> 31) & 0x1))
5416 SET_ASTATREG (v
, 1);
5417 SET_ASTATREG (vs
, 1);
5421 else if (sop
== 3 && sopcde
== 2)
5423 int shift
= imm6 (DREG (src0
) & 0xFFFF);
5424 bu32 src
= DREG (src1
);
5425 bu32 ret
, cc
= CCREG
;
5427 TRACE_INSN (cpu
, "R%i = ROT R%i BY R%i.L;", dst0
, src1
, src0
);
5428 TRACE_DECODE (cpu
, "R%i:%#x R%i:%#x shift:%i CC:%i",
5429 dst0
, DREG (dst0
), src1
, src
, shift
, cc
);
5431 ret
= rot32 (src
, shift
, &cc
);
5432 STORE (DREG (dst0
), ret
);
5436 else if (sop
== 2 && sopcde
== 1 && HLs
== 0)
5438 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5442 TRACE_INSN (cpu
, "R%i = LSHIFT R%i BY R%i.L (V);", dst0
, src1
, src0
);
5444 val0
= (bu16
)DREG (src1
) & 0xFFFF;
5445 val1
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5449 val0
= lshiftrt (cpu
, val0
, -shft
, 16);
5451 val1
= lshiftrt (cpu
, val1
, -shft
, 16);
5455 val0
= lshift (cpu
, val0
, shft
, 16, 0, 0);
5457 val1
= lshift (cpu
, val1
, shft
, 16, 0, 0);
5459 SET_ASTAT (ASTAT
| astat
);
5460 STORE (DREG (dst0
), (val1
<< 16) | val0
);
5462 else if (sopcde
== 4)
5464 bu32 sv0
= DREG (src0
);
5465 bu32 sv1
= DREG (src1
);
5466 TRACE_INSN (cpu
, "R%i = PACK (R%i.%c, R%i.%c);", dst0
,
5467 src1
, sop
& 2 ? 'H' : 'L',
5468 src0
, sop
& 1 ? 'H' : 'L');
5473 STORE (DREG (dst0
), (sv1
<< 16) | (sv0
& 0xFFFF));
5475 else if (sop
== 0 && sopcde
== 5)
5477 bu32 sv1
= DREG (src1
);
5478 TRACE_INSN (cpu
, "R%i.L = SIGNBITS R%i;", dst0
, src1
);
5479 SET_DREG_L (dst0
, signbits (sv1
, 32));
5481 else if (sop
== 1 && sopcde
== 5)
5483 bu32 sv1
= DREG (src1
);
5484 TRACE_INSN (cpu
, "R%i.L = SIGNBITS R%i.L;", dst0
, src1
);
5485 SET_DREG_L (dst0
, signbits (sv1
, 16));
5487 else if (sop
== 2 && sopcde
== 5)
5489 bu32 sv1
= DREG (src1
);
5490 TRACE_INSN (cpu
, "R%i.L = SIGNBITS R%i.H;", dst0
, src1
);
5491 SET_DREG_L (dst0
, signbits (sv1
>> 16, 16));
5493 else if ((sop
== 0 || sop
== 1) && sopcde
== 6)
5495 bu64 acc
= AXREG (sop
);
5496 TRACE_INSN (cpu
, "R%i.L = SIGNBITS A%i;", dst0
, sop
);
5499 SET_DREG_L (dst0
, signbits (acc
, 40) & 0xFFFF);
5501 else if (sop
== 3 && sopcde
== 6)
5503 bu32 v
= ones (DREG (src1
));
5504 TRACE_INSN (cpu
, "R%i.L = ONES R%i;", dst0
, src1
);
5505 SET_DREG_L (dst0
, v
);
5507 else if (sop
== 0 && sopcde
== 7)
5509 bu16 sv1
= (bu16
)signbits (DREG (src1
), 32);
5510 bu16 sv0
= (bu16
)DREG (src0
);
5513 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i, R%i.L);", dst0
, src1
, src0
);
5515 if ((sv1
& 0x1f) < (sv0
& 0x1f))
5519 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), dst_lo
));
5521 else if (sop
== 1 && sopcde
== 7)
5523 /* Exponent adjust on two 16-bit inputs. Select
5524 smallest norm among 3 inputs. */
5525 bs16 src1_hi
= (DREG (src1
) & 0xFFFF0000) >> 16;
5526 bs16 src1_lo
= (DREG (src1
) & 0xFFFF);
5527 bu16 src0_lo
= (DREG (src0
) & 0xFFFF);
5528 bu16 tmp_hi
, tmp_lo
, tmp
;
5530 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i, R%i.L) (V);", dst0
, src1
, src0
);
5532 tmp_hi
= signbits (src1_hi
, 16);
5533 tmp_lo
= signbits (src1_lo
, 16);
5535 if ((tmp_hi
& 0xf) < (tmp_lo
& 0xf))
5536 if ((tmp_hi
& 0xf) < (src0_lo
& 0xf))
5541 if ((tmp_lo
& 0xf) < (src0_lo
& 0xf))
5545 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), tmp
));
5547 else if (sop
== 2 && sopcde
== 7)
5549 /* Exponent adjust on single 16-bit register. */
5551 bu16 src0_lo
= (bu16
)(DREG (src0
) & 0xFFFF);
5553 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i.L, R%i.L);", dst0
, src1
, src0
);
5555 tmp
= signbits (DREG (src1
) & 0xFFFF, 16);
5557 if ((tmp
& 0xf) < (src0_lo
& 0xf))
5558 SET_DREG_L (dst0
, tmp
);
5560 SET_DREG_L (dst0
, src0_lo
);
5562 else if (sop
== 3 && sopcde
== 7)
5565 bu16 src0_lo
= (bu16
)(DREG (src0
) & 0xFFFF);
5567 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i.H, R%i.L);", dst0
, src1
, src0
);
5569 tmp
= signbits ((DREG (src1
) & 0xFFFF0000) >> 16, 16);
5571 if ((tmp
& 0xf) < (src0_lo
& 0xf))
5572 SET_DREG_L (dst0
, tmp
);
5574 SET_DREG_L (dst0
, src0_lo
);
5576 else if (sop
== 0 && sopcde
== 8)
5578 bu64 acc
= get_unextended_acc (cpu
, 0);
5581 TRACE_INSN (cpu
, "BITMUX (R%i, R%i, A0) (ASR);", src0
, src1
);
5584 illegal_instruction_combination (cpu
);
5589 (((bu64
)s0
& 1) << 38) |
5590 (((bu64
)s1
& 1) << 39);
5591 STORE (DREG (src0
), s0
>> 1);
5592 STORE (DREG (src1
), s1
>> 1);
5596 else if (sop
== 1 && sopcde
== 8)
5598 bu64 acc
= get_unextended_acc (cpu
, 0);
5601 TRACE_INSN (cpu
, "BITMUX (R%i, R%i, A0) (ASL);", src0
, src1
);
5604 illegal_instruction_combination (cpu
);
5611 STORE (DREG (src0
), s0
<< 1);
5612 STORE (DREG (src1
), s1
<< 1);
5616 else if ((sop
== 0 || sop
== 1) && sopcde
== 9)
5618 bs40 acc0
= get_unextended_acc (cpu
, 0);
5621 TRACE_INSN (cpu
, "R%i.L = VIT_MAX (R%i) (AS%c);",
5622 dst0
, src1
, sop
& 1 ? 'R' : 'L');
5625 sH
= DREG (src1
) >> 16;
5628 acc0
= (acc0
& 0xfeffffffffull
) >> 1;
5632 if (((sH
- sL
) & 0x8000) == 0)
5635 acc0
|= (sop
& 1) ? 0x80000000 : 1;
5641 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), out
));
5643 else if ((sop
== 2 || sop
== 3) && sopcde
== 9)
5645 bs40 acc0
= get_extended_acc (cpu
, 0);
5646 bs16 s0L
, s0H
, s1L
, s1H
, out0
, out1
;
5648 TRACE_INSN (cpu
, "R%i = VIT_MAX (R%i, R%i) (AS%c);",
5649 dst0
, src1
, src0
, sop
& 1 ? 'R' : 'L');
5652 s0H
= DREG (src0
) >> 16;
5654 s1H
= DREG (src1
) >> 16;
5661 if (((s0H
- s0L
) & 0x8000) == 0)
5664 acc0
|= (sop
& 1) ? 0x40000000 : 2;
5669 if (((s1H
- s1L
) & 0x8000) == 0)
5672 acc0
|= (sop
& 1) ? 0x80000000 : 1;
5678 STORE (DREG (dst0
), REG_H_L (out1
<< 16, out0
));
5680 else if (sop
== 0 && sopcde
== 10)
5682 bu32 v
= DREG (src0
);
5683 bu32 x
= DREG (src1
);
5684 bu32 mask
= (1 << (v
& 0x1f)) - 1;
5686 TRACE_INSN (cpu
, "R%i = EXTRACT (R%i, R%i.L) (Z);", dst0
, src1
, src0
);
5688 x
>>= ((v
>> 8) & 0x1f);
5690 STORE (DREG (dst0
), x
);
5691 setflags_logical (cpu
, x
);
5693 else if (sop
== 1 && sopcde
== 10)
5695 bu32 v
= DREG (src0
);
5696 bu32 x
= DREG (src1
);
5697 bu32 sgn
= (1 << (v
& 0x1f)) >> 1;
5698 bu32 mask
= (1 << (v
& 0x1f)) - 1;
5700 TRACE_INSN (cpu
, "R%i = EXTRACT (R%i, R%i.L) (X);", dst0
, src1
, src0
);
5702 x
>>= ((v
>> 8) & 0x1f);
5706 STORE (DREG (dst0
), x
);
5707 setflags_logical (cpu
, x
);
5709 else if ((sop
== 2 || sop
== 3) && sopcde
== 10)
5711 /* The first dregs is the "background" while the second dregs is the
5712 "foreground". The fg reg is used to overlay the bg reg and is:
5713 | nnnn nnnn | nnnn nnnn | xxxp pppp | xxxL LLLL |
5714 n = the fg bit field
5715 p = bit position in bg reg to start LSB of fg field
5716 L = number of fg bits to extract
5717 Using (X) sign-extends the fg bit field. */
5718 bu32 fg
= DREG (src0
);
5719 bu32 bg
= DREG (src1
);
5720 bu32 len
= fg
& 0x1f;
5721 bu32 mask
= (1 << min (16, len
)) - 1;
5722 bu32 fgnd
= (fg
>> 16) & mask
;
5723 int shft
= ((fg
>> 8) & 0x1f);
5725 TRACE_INSN (cpu
, "R%i = DEPOSIT (R%i, R%i)%s;", dst0
, src1
, src0
,
5726 sop
== 3 ? " (X)" : "");
5730 /* Sign extend the fg bit field. */
5732 fgnd
= ((bs32
)(bs16
)(fgnd
<< (16 - len
))) >> (16 - len
);
5739 STORE (DREG (dst0
), bg
);
5740 setflags_logical (cpu
, bg
);
5742 else if (sop
== 0 && sopcde
== 11)
5744 bu64 acc0
= get_unextended_acc (cpu
, 0);
5746 TRACE_INSN (cpu
, "R%i.L = CC = BXORSHIFT (A0, R%i);", dst0
, src0
);
5749 SET_CCREG (xor_reduce (acc0
, DREG (src0
)));
5750 SET_DREG (dst0
, REG_H_L (DREG (dst0
), CCREG
));
5753 else if (sop
== 1 && sopcde
== 11)
5755 bu64 acc0
= get_unextended_acc (cpu
, 0);
5757 TRACE_INSN (cpu
, "R%i.L = CC = BXOR (A0, R%i);", dst0
, src0
);
5759 SET_CCREG (xor_reduce (acc0
, DREG (src0
)));
5760 SET_DREG (dst0
, REG_H_L (DREG (dst0
), CCREG
));
5762 else if (sop
== 0 && sopcde
== 12)
5764 bu64 acc0
= get_unextended_acc (cpu
, 0);
5765 bu64 acc1
= get_unextended_acc (cpu
, 1);
5767 TRACE_INSN (cpu
, "A0 = BXORSHIFT (A0, A1, CC);");
5769 acc0
= (acc0
<< 1) | (CCREG
^ xor_reduce (acc0
, acc1
));
5772 else if (sop
== 1 && sopcde
== 12)
5774 bu64 acc0
= get_unextended_acc (cpu
, 0);
5775 bu64 acc1
= get_unextended_acc (cpu
, 1);
5777 TRACE_INSN (cpu
, "R%i.L = CC = BXOR (A0, A1, CC);", dst0
);
5779 SET_CCREG (CCREG
^ xor_reduce (acc0
, acc1
));
5780 acc0
= (acc0
<< 1) | CCREG
;
5781 SET_DREG (dst0
, REG_H_L (DREG (dst0
), CCREG
));
5783 else if ((sop
== 0 || sop
== 1 || sop
== 2) && sopcde
== 13)
5785 int shift
= (sop
+ 1) * 8;
5786 TRACE_INSN (cpu
, "R%i = ALIGN%i (R%i, R%i);", dst0
, shift
, src1
, src0
);
5787 STORE (DREG (dst0
), (DREG (src1
) << (32 - shift
)) | (DREG (src0
) >> shift
));
5790 illegal_instruction (cpu
);
5794 sgn_extend (bu40 org
, bu40 val
, int size
)
5798 if (org
& (1ULL << (size
- 1)))
5800 /* We need to shift in to the MSB which is set. */
5803 for (n
= 40; n
>= 0; n
--)
5804 if (ret
& (1ULL << n
))
5806 ret
|= (-1ULL << n
);
5809 ret
&= ~(-1ULL << 39);
5814 decode_dsp32shiftimm_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
5817 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5818 | 1 | 1 | 0 | 0 |.M.| 1 | 1 | 0 | 1 | - | - |.sopcde............|
5819 |.sop...|.HLs...|.dst0......|.immag.................|.src1......|
5820 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5821 int src1
= ((iw1
>> DSP32ShiftImm_src1_bits
) & DSP32ShiftImm_src1_mask
);
5822 int sop
= ((iw1
>> DSP32ShiftImm_sop_bits
) & DSP32ShiftImm_sop_mask
);
5823 int bit8
= ((iw1
>> 8) & 0x1);
5824 int immag
= ((iw1
>> DSP32ShiftImm_immag_bits
) & DSP32ShiftImm_immag_mask
);
5825 int newimmag
= (-(iw1
>> DSP32ShiftImm_immag_bits
) & DSP32ShiftImm_immag_mask
);
5826 int dst0
= ((iw1
>> DSP32ShiftImm_dst0_bits
) & DSP32ShiftImm_dst0_mask
);
5827 int M
= ((iw0
>> (DSP32ShiftImm_M_bits
- 16)) & DSP32ShiftImm_M_mask
);
5828 int sopcde
= ((iw0
>> (DSP32ShiftImm_sopcde_bits
- 16)) & DSP32ShiftImm_sopcde_mask
);
5829 int HLs
= ((iw1
>> DSP32ShiftImm_HLs_bits
) & DSP32ShiftImm_HLs_mask
);
5831 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32shiftimm
);
5832 TRACE_EXTRACT (cpu
, "%s: M:%i sopcde:%i sop:%i HLs:%i dst0:%i immag:%#x src1:%i",
5833 __func__
, M
, sopcde
, sop
, HLs
, dst0
, immag
, src1
);
5837 bu16 in
= DREG (src1
) >> ((HLs
& 1) ? 16 : 0);
5843 TRACE_INSN (cpu
, "R%i.%c = R%i.%c >>> %i;",
5844 dst0
, (HLs
& 2) ? 'H' : 'L',
5845 src1
, (HLs
& 1) ? 'H' : 'L', newimmag
);
5848 result
= lshift (cpu
, in
, 16 - (newimmag
& 0xF), 16, 0, 1);
5849 if (((result
>> 15) & 0x1) != ((in
>> 15) & 0x1))
5851 SET_ASTATREG (v
, 1);
5852 SET_ASTATREG (vs
, 1);
5856 result
= ashiftrt (cpu
, in
, newimmag
, 16);
5858 else if (sop
== 1 && bit8
== 0)
5860 TRACE_INSN (cpu
, "R%i.%c = R%i.%c << %i (S);",
5861 dst0
, (HLs
& 2) ? 'H' : 'L',
5862 src1
, (HLs
& 1) ? 'H' : 'L', immag
);
5863 result
= lshift (cpu
, in
, immag
, 16, 1, 1);
5865 else if (sop
== 1 && bit8
)
5867 TRACE_INSN (cpu
, "R%i.%c = R%i.%c >>> %i (S);",
5868 dst0
, (HLs
& 2) ? 'H' : 'L',
5869 src1
, (HLs
& 1) ? 'H' : 'L', newimmag
);
5872 int shift
= 32 - newimmag
;
5873 bu16 inshift
= in
<< shift
;
5875 if (((inshift
& ~0xFFFF)
5876 && ((inshift
& ~0xFFFF) >> 16) != ~(~0 << shift
))
5877 || (inshift
& 0x8000) != (in
& 0x8000))
5883 SET_ASTATREG (v
, 1);
5884 SET_ASTATREG (vs
, 1);
5889 SET_ASTATREG (v
, 0);
5892 SET_ASTATREG (az
, !result
);
5893 SET_ASTATREG (an
, !!(result
& 0x8000));
5897 result
= ashiftrt (cpu
, in
, newimmag
, 16);
5898 result
= sgn_extend (in
, result
, 16);
5901 else if (sop
== 2 && bit8
)
5903 TRACE_INSN (cpu
, "R%i.%c = R%i.%c >> %i;",
5904 dst0
, (HLs
& 2) ? 'H' : 'L',
5905 src1
, (HLs
& 1) ? 'H' : 'L', newimmag
);
5906 result
= lshiftrt (cpu
, in
, newimmag
, 16);
5908 else if (sop
== 2 && bit8
== 0)
5910 TRACE_INSN (cpu
, "R%i.%c = R%i.%c << %i;",
5911 dst0
, (HLs
& 2) ? 'H' : 'L',
5912 src1
, (HLs
& 1) ? 'H' : 'L', immag
);
5913 result
= lshift (cpu
, in
, immag
, 16, 0, 1);
5916 illegal_instruction (cpu
);
5920 STORE (DREG (dst0
), (v
& 0xFFFF) | (result
<< 16));
5922 STORE (DREG (dst0
), (v
& 0xFFFF0000) | result
);
5924 else if (sop
== 2 && sopcde
== 3 && (HLs
== 1 || HLs
== 0))
5926 int shift
= imm6 (immag
);
5928 bu40 acc
= get_unextended_acc (cpu
, HLs
);
5930 TRACE_INSN (cpu
, "A%i = ROT A%i BY %i;", HLs
, HLs
, shift
);
5931 TRACE_DECODE (cpu
, "A%i:%#"PRIx64
" shift:%i CC:%i", HLs
, acc
, shift
, cc
);
5933 acc
= rot40 (acc
, shift
, &cc
);
5934 SET_AREG (HLs
, acc
);
5938 else if (sop
== 0 && sopcde
== 3 && bit8
== 1 && HLs
< 2)
5940 /* Arithmetic shift, so shift in sign bit copies. */
5942 int shift
= uimm5 (newimmag
);
5944 TRACE_INSN (cpu
, "A%i = A%i >>> %i;", HLs
, HLs
, shift
);
5946 acc
= get_extended_acc (cpu
, HLs
);
5949 /* Sign extend again. */
5950 val
= sgn_extend (acc
, val
, 40);
5952 STORE (AXREG (HLs
), (val
>> 32) & 0xFF);
5953 STORE (AWREG (HLs
), val
& 0xFFFFFFFF);
5954 STORE (ASTATREG (an
), !!(val
& (1ULL << 39)));
5955 STORE (ASTATREG (az
), !val
);
5956 STORE (ASTATREG (av
[HLs
]), 0);
5958 else if (((sop
== 0 && sopcde
== 3 && bit8
== 0)
5959 || (sop
== 1 && sopcde
== 3)) && HLs
< 2)
5962 int shiftup
= uimm5 (immag
);
5963 int shiftdn
= uimm5 (newimmag
);
5965 TRACE_INSN (cpu
, "A%i = A%i %s %i;", HLs
, HLs
,
5966 sop
== 0 ? "<<" : ">>",
5967 sop
== 0 ? shiftup
: shiftdn
);
5970 /* Logical shift, so shift in zeroes. */
5982 acc
<<= 32 - (shiftdn
& 0x1f);
5985 SET_AREG (HLs
, acc
);
5986 SET_ASTATREG (av
[HLs
], 0);
5987 SET_ASTATREG (an
, !!(acc
& 0x8000000000ull
));
5988 SET_ASTATREG (az
, (acc
& 0xFFFFFFFFFF) == 0);
5991 /* All the insns after this point don't use HLs. */
5992 illegal_instruction (cpu
);
5993 else if (sop
== 1 && sopcde
== 1 && bit8
== 0)
5995 int count
= imm5 (immag
);
5996 bu16 val0
= DREG (src1
) >> 16;
5997 bu16 val1
= DREG (src1
) & 0xFFFF;
6000 TRACE_INSN (cpu
, "R%i = R%i << %i (V,S);", dst0
, src1
, count
);
6003 val0
= lshift (cpu
, val0
, count
, 16, 1, 1);
6005 val1
= lshift (cpu
, val1
, count
, 16, 1, 1);
6009 val0
= ashiftrt (cpu
, val0
, -count
, 16);
6011 val1
= ashiftrt (cpu
, val1
, -count
, 16);
6013 SET_ASTAT (ASTAT
| astat
);
6015 STORE (DREG (dst0
), (val0
<< 16) | val1
);
6017 else if (sop
== 2 && sopcde
== 1 && bit8
== 1)
6019 int count
= imm5 (newimmag
);
6020 bu16 val0
= DREG (src1
) & 0xFFFF;
6021 bu16 val1
= DREG (src1
) >> 16;
6024 TRACE_INSN (cpu
, "R%i = R%i >> %i (V);", dst0
, src1
, count
);
6025 val0
= lshiftrt (cpu
, val0
, count
, 16);
6027 val1
= lshiftrt (cpu
, val1
, count
, 16);
6028 SET_ASTAT (ASTAT
| astat
);
6030 STORE (DREG (dst0
), val0
| (val1
<< 16));
6032 else if (sop
== 2 && sopcde
== 1 && bit8
== 0)
6034 int count
= imm5 (immag
);
6035 bu16 val0
= DREG (src1
) & 0xFFFF;
6036 bu16 val1
= DREG (src1
) >> 16;
6039 TRACE_INSN (cpu
, "R%i = R%i << %i (V);", dst0
, src1
, count
);
6040 val0
= lshift (cpu
, val0
, count
, 16, 0, 1);
6042 val1
= lshift (cpu
, val1
, count
, 16, 0, 1);
6043 SET_ASTAT (ASTAT
| astat
);
6045 STORE (DREG (dst0
), val0
| (val1
<< 16));
6047 else if (sopcde
== 1 && (sop
== 0 || (sop
== 1 && bit8
== 1)))
6049 int count
= uimm5 (newimmag
);
6050 bu16 val0
= DREG (src1
) & 0xFFFF;
6051 bu16 val1
= DREG (src1
) >> 16;
6054 TRACE_INSN (cpu
, "R%i = R%i >>> %i %s;", dst0
, src1
, count
,
6055 sop
== 0 ? "(V)" : "(V,S)");
6059 int sgn0
= (val0
>> 15) & 0x1;
6060 int sgn1
= (val1
>> 15) & 0x1;
6062 val0
= lshift (cpu
, val0
, 16 - (count
& 0xF), 16, 0, 1);
6064 val1
= lshift (cpu
, val1
, 16 - (count
& 0xF), 16, 0, 1);
6066 if ((sgn0
!= ((val0
>> 15) & 0x1)) || (sgn1
!= ((val1
>> 15) & 0x1)))
6068 SET_ASTATREG (v
, 1);
6069 SET_ASTATREG (vs
, 1);
6074 val0
= ashiftrt (cpu
, val0
, count
, 16);
6076 val1
= ashiftrt (cpu
, val1
, count
, 16);
6079 SET_ASTAT (ASTAT
| astat
);
6081 STORE (DREG (dst0
), REG_H_L (val1
<< 16, val0
));
6083 else if (sop
== 1 && sopcde
== 2)
6085 int count
= imm6 (immag
);
6087 TRACE_INSN (cpu
, "R%i = R%i << %i (S);", dst0
, src1
, count
);
6090 STORE (DREG (dst0
), ashiftrt (cpu
, DREG (src1
), -count
, 32));
6092 STORE (DREG (dst0
), lshift (cpu
, DREG (src1
), count
, 32, 1, 1));
6094 else if (sop
== 2 && sopcde
== 2)
6096 int count
= imm6 (newimmag
);
6098 TRACE_INSN (cpu
, "R%i = R%i >> %i;", dst0
, src1
, count
);
6101 STORE (DREG (dst0
), lshift (cpu
, DREG (src1
), -count
, 32, 0, 1));
6103 STORE (DREG (dst0
), lshiftrt (cpu
, DREG (src1
), count
, 32));
6105 else if (sop
== 3 && sopcde
== 2)
6107 int shift
= imm6 (immag
);
6108 bu32 src
= DREG (src1
);
6109 bu32 ret
, cc
= CCREG
;
6111 TRACE_INSN (cpu
, "R%i = ROT R%i BY %i;", dst0
, src1
, shift
);
6112 TRACE_DECODE (cpu
, "R%i:%#x R%i:%#x shift:%i CC:%i",
6113 dst0
, DREG (dst0
), src1
, src
, shift
, cc
);
6115 ret
= rot32 (src
, shift
, &cc
);
6116 STORE (DREG (dst0
), ret
);
6120 else if (sop
== 0 && sopcde
== 2)
6122 int count
= imm6 (newimmag
);
6124 TRACE_INSN (cpu
, "R%i = R%i >>> %i;", dst0
, src1
, count
);
6127 STORE (DREG (dst0
), lshift (cpu
, DREG (src1
), -count
, 32, 0, 1));
6129 STORE (DREG (dst0
), ashiftrt (cpu
, DREG (src1
), count
, 32));
6132 illegal_instruction (cpu
);
6136 outc (SIM_CPU
*cpu
, char ch
)
6138 SIM_DESC sd
= CPU_STATE (cpu
);
6139 sim_io_printf (sd
, "%c", ch
);
6141 sim_io_flush_stdout (sd
);
6145 decode_psedoDEBUG_0 (SIM_CPU
*cpu
, bu16 iw0
)
6148 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
6149 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 |.fn....|.grp.......|.reg.......|
6150 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
6151 SIM_DESC sd
= CPU_STATE (cpu
);
6152 int fn
= ((iw0
>> PseudoDbg_fn_bits
) & PseudoDbg_fn_mask
);
6153 int grp
= ((iw0
>> PseudoDbg_grp_bits
) & PseudoDbg_grp_mask
);
6154 int reg
= ((iw0
>> PseudoDbg_reg_bits
) & PseudoDbg_reg_mask
);
6156 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_psedoDEBUG
);
6157 TRACE_EXTRACT (cpu
, "%s: fn:%i grp:%i reg:%i", __func__
, fn
, grp
, reg
);
6159 if ((reg
== 0 || reg
== 1) && fn
== 3)
6161 TRACE_INSN (cpu
, "DBG A%i;", reg
);
6162 sim_io_printf (sd
, "DBG : A%i = %#"PRIx64
"\n", reg
,
6163 get_unextended_acc (cpu
, reg
));
6165 else if (reg
== 3 && fn
== 3)
6167 TRACE_INSN (cpu
, "ABORT;");
6168 cec_exception (cpu
, VEC_SIM_ABORT
);
6171 else if (reg
== 4 && fn
== 3)
6173 TRACE_INSN (cpu
, "HLT;");
6174 cec_exception (cpu
, VEC_SIM_HLT
);
6177 else if (reg
== 5 && fn
== 3)
6178 unhandled_instruction (cpu
, "DBGHALT");
6179 else if (reg
== 6 && fn
== 3)
6180 unhandled_instruction (cpu
, "DBGCMPLX (dregs)");
6181 else if (reg
== 7 && fn
== 3)
6182 unhandled_instruction (cpu
, "DBG");
6183 else if (grp
== 0 && fn
== 2)
6185 TRACE_INSN (cpu
, "OUTC R%i;", reg
);
6186 outc (cpu
, DREG (reg
));
6190 const char *reg_name
= get_allreg_name (grp
, reg
);
6191 TRACE_INSN (cpu
, "DBG %s;", reg_name
);
6192 sim_io_printf (sd
, "DBG : %s = 0x%08x\n", reg_name
,
6193 reg_read (cpu
, grp
, reg
));
6196 unhandled_instruction (cpu
, "PRNT allregs");
6198 illegal_instruction (cpu
);
6202 decode_psedoOChar_0 (SIM_CPU
*cpu
, bu16 iw0
)
6205 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
6206 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |.ch............................|
6207 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
6208 int ch
= ((iw0
>> PseudoChr_ch_bits
) & PseudoChr_ch_mask
);
6210 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_psedoOChar
);
6211 TRACE_EXTRACT (cpu
, "%s: ch:%#x", __func__
, ch
);
6212 TRACE_INSN (cpu
, "OUTC %#x;", ch
);
6218 decode_psedodbg_assert_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
, bu32 pc
)
6221 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
6222 | 1 | 1 | 1 | 1 | 0 | - | - | - | dbgop |.grp.......|.regtest...|
6223 |.expected......................................................|
6224 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
6225 SIM_DESC sd
= CPU_STATE (cpu
);
6226 int expected
= ((iw1
>> PseudoDbg_Assert_expected_bits
) & PseudoDbg_Assert_expected_mask
);
6227 int dbgop
= ((iw0
>> (PseudoDbg_Assert_dbgop_bits
- 16)) & PseudoDbg_Assert_dbgop_mask
);
6228 int grp
= ((iw0
>> (PseudoDbg_Assert_grp_bits
- 16)) & PseudoDbg_Assert_grp_mask
);
6229 int regtest
= ((iw0
>> (PseudoDbg_Assert_regtest_bits
- 16)) & PseudoDbg_Assert_regtest_mask
);
6232 bu32 val
= reg_read (cpu
, grp
, regtest
);
6233 const char *reg_name
= get_allreg_name (grp
, regtest
);
6234 const char *dbg_name
, *dbg_appd
;
6236 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_psedodbg_assert
);
6237 TRACE_EXTRACT (cpu
, "%s: dbgop:%i grp:%i regtest:%i expected:%#x",
6238 __func__
, dbgop
, grp
, regtest
, expected
);
6240 if (dbgop
== 0 || dbgop
== 2)
6242 dbg_name
= dbgop
== 0 ? "DBGA" : "DBGAL";
6243 dbg_appd
= dbgop
== 0 ? ".L" : "";
6246 else if (dbgop
== 1 || dbgop
== 3)
6248 dbg_name
= dbgop
== 1 ? "DBGA" : "DBGAH";
6249 dbg_appd
= dbgop
== 1 ? ".H" : "";
6253 illegal_instruction (cpu
);
6255 actual
= val
>> offset
;
6257 TRACE_INSN (cpu
, "%s (%s%s, 0x%x);", dbg_name
, reg_name
, dbg_appd
, expected
);
6258 if (actual
!= expected
)
6260 sim_io_printf (sd
, "FAIL at %#x: %s (%s%s, 0x%04x); actual value %#x\n",
6261 pc
, dbg_name
, reg_name
, dbg_appd
, expected
, actual
);
6263 /* Decode the actual ASTAT bits that are different. */
6264 if (grp
== 4 && regtest
== 6)
6268 sim_io_printf (sd
, "Expected ASTAT:\n");
6269 for (i
= 0; i
< 16; ++i
)
6270 sim_io_printf (sd
, " %8s%c%i%s",
6271 astat_names
[i
+ offset
],
6272 (((expected
>> i
) & 1) != ((actual
>> i
) & 1))
6274 (expected
>> i
) & 1,
6275 i
== 7 ? "\n" : "");
6276 sim_io_printf (sd
, "\n");
6278 sim_io_printf (sd
, "Actual ASTAT:\n");
6279 for (i
= 0; i
< 16; ++i
)
6280 sim_io_printf (sd
, " %8s%c%i%s",
6281 astat_names
[i
+ offset
],
6282 (((expected
>> i
) & 1) != ((actual
>> i
) & 1))
6285 i
== 7 ? "\n" : "");
6286 sim_io_printf (sd
, "\n");
6289 cec_exception (cpu
, VEC_SIM_DBGA
);
6295 _interp_insn_bfin (SIM_CPU
*cpu
, bu32 pc
)
6300 BFIN_CPU_STATE
.multi_pc
= pc
;
6302 if ((iw0
& 0xc000) != 0xc000)
6304 /* 16-bit opcode. */
6307 INSN_LEN
= insn_len
;
6309 TRACE_EXTRACT (cpu
, "%s: iw0:%#x", __func__
, iw0
);
6310 if ((iw0
& 0xFF00) == 0x0000)
6311 decode_ProgCtrl_0 (cpu
, iw0
, pc
);
6312 else if ((iw0
& 0xFFC0) == 0x0240)
6313 decode_CaCTRL_0 (cpu
, iw0
);
6314 else if ((iw0
& 0xFF80) == 0x0100)
6315 decode_PushPopReg_0 (cpu
, iw0
);
6316 else if ((iw0
& 0xFE00) == 0x0400)
6317 decode_PushPopMultiple_0 (cpu
, iw0
);
6318 else if ((iw0
& 0xFE00) == 0x0600)
6319 decode_ccMV_0 (cpu
, iw0
);
6320 else if ((iw0
& 0xF800) == 0x0800)
6321 decode_CCflag_0 (cpu
, iw0
);
6322 else if ((iw0
& 0xFFE0) == 0x0200)
6323 decode_CC2dreg_0 (cpu
, iw0
);
6324 else if ((iw0
& 0xFF00) == 0x0300)
6325 decode_CC2stat_0 (cpu
, iw0
);
6326 else if ((iw0
& 0xF000) == 0x1000)
6327 decode_BRCC_0 (cpu
, iw0
, pc
);
6328 else if ((iw0
& 0xF000) == 0x2000)
6329 decode_UJUMP_0 (cpu
, iw0
, pc
);
6330 else if ((iw0
& 0xF000) == 0x3000)
6331 decode_REGMV_0 (cpu
, iw0
);
6332 else if ((iw0
& 0xFC00) == 0x4000)
6333 decode_ALU2op_0 (cpu
, iw0
);
6334 else if ((iw0
& 0xFE00) == 0x4400)
6335 decode_PTR2op_0 (cpu
, iw0
);
6336 else if ((iw0
& 0xF800) == 0x4800)
6337 decode_LOGI2op_0 (cpu
, iw0
);
6338 else if ((iw0
& 0xF000) == 0x5000)
6339 decode_COMP3op_0 (cpu
, iw0
);
6340 else if ((iw0
& 0xF800) == 0x6000)
6341 decode_COMPI2opD_0 (cpu
, iw0
);
6342 else if ((iw0
& 0xF800) == 0x6800)
6343 decode_COMPI2opP_0 (cpu
, iw0
);
6344 else if ((iw0
& 0xF000) == 0x8000)
6345 decode_LDSTpmod_0 (cpu
, iw0
);
6346 else if ((iw0
& 0xFF60) == 0x9E60)
6347 decode_dagMODim_0 (cpu
, iw0
);
6348 else if ((iw0
& 0xFFF0) == 0x9F60)
6349 decode_dagMODik_0 (cpu
, iw0
);
6350 else if ((iw0
& 0xFC00) == 0x9C00)
6351 decode_dspLDST_0 (cpu
, iw0
);
6352 else if ((iw0
& 0xF000) == 0x9000)
6353 decode_LDST_0 (cpu
, iw0
);
6354 else if ((iw0
& 0xFC00) == 0xB800)
6355 decode_LDSTiiFP_0 (cpu
, iw0
);
6356 else if ((iw0
& 0xE000) == 0xA000)
6357 decode_LDSTii_0 (cpu
, iw0
);
6360 TRACE_EXTRACT (cpu
, "%s: no matching 16-bit pattern", __func__
);
6361 illegal_instruction_or_combination (cpu
);
6366 /* Grab the next 16 bits to determine if it's a 32-bit or 64-bit opcode. */
6367 iw1
= IFETCH (pc
+ 2);
6368 if ((iw0
& BIT_MULTI_INS
) && (iw0
& 0xe800) != 0xe800 /* not linkage */)
6370 SIM_DESC sd
= CPU_STATE (cpu
);
6371 trace_prefix (sd
, cpu
, NULL_CIA
, pc
, TRACE_LINENUM_P (cpu
),
6372 NULL
, 0, "|| %#"PRIx64
, sim_events_time (sd
));
6374 PARALLEL_GROUP
= BFIN_PARALLEL_GROUP0
;
6379 TRACE_EXTRACT (cpu
, "%s: iw0:%#x iw1:%#x insn_len:%i", __func__
,
6380 iw0
, iw1
, insn_len
);
6382 /* Only cache on first run through (in case of parallel insns). */
6384 INSN_LEN
= insn_len
;
6386 /* Once you're past the first slot, only 16bit insns are valid. */
6387 illegal_instruction_combination (cpu
);
6389 if ((iw0
& 0xf7ff) == 0xc003 && (iw1
& 0xfe00) == 0x1800)
6391 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32mac
);
6392 TRACE_INSN (cpu
, "MNOP;");
6394 else if (((iw0
& 0xFF80) == 0xE080) && ((iw1
& 0x0C00) == 0x0000))
6395 decode_LoopSetup_0 (cpu
, iw0
, iw1
, pc
);
6396 else if (((iw0
& 0xFF00) == 0xE100) && ((iw1
& 0x0000) == 0x0000))
6397 decode_LDIMMhalf_0 (cpu
, iw0
, iw1
);
6398 else if (((iw0
& 0xFE00) == 0xE200) && ((iw1
& 0x0000) == 0x0000))
6399 decode_CALLa_0 (cpu
, iw0
, iw1
, pc
);
6400 else if (((iw0
& 0xFC00) == 0xE400) && ((iw1
& 0x0000) == 0x0000))
6401 decode_LDSTidxI_0 (cpu
, iw0
, iw1
);
6402 else if (((iw0
& 0xFFFE) == 0xE800) && ((iw1
& 0x0000) == 0x0000))
6403 decode_linkage_0 (cpu
, iw0
, iw1
);
6404 else if (((iw0
& 0xF600) == 0xC000) && ((iw1
& 0x0000) == 0x0000))
6405 decode_dsp32mac_0 (cpu
, iw0
, iw1
);
6406 else if (((iw0
& 0xF600) == 0xC200) && ((iw1
& 0x0000) == 0x0000))
6407 decode_dsp32mult_0 (cpu
, iw0
, iw1
);
6408 else if (((iw0
& 0xF7C0) == 0xC400) && ((iw1
& 0x0000) == 0x0000))
6409 decode_dsp32alu_0 (cpu
, iw0
, iw1
);
6410 else if (((iw0
& 0xF7E0) == 0xC600) && ((iw1
& 0x01C0) == 0x0000))
6411 decode_dsp32shift_0 (cpu
, iw0
, iw1
);
6412 else if (((iw0
& 0xF7E0) == 0xC680) && ((iw1
& 0x0000) == 0x0000))
6413 decode_dsp32shiftimm_0 (cpu
, iw0
, iw1
);
6414 else if ((iw0
& 0xFF00) == 0xF800)
6415 decode_psedoDEBUG_0 (cpu
, iw0
), insn_len
= 2;
6416 else if ((iw0
& 0xFF00) == 0xF900)
6417 decode_psedoOChar_0 (cpu
, iw0
), insn_len
= 2;
6418 else if (((iw0
& 0xFF00) == 0xF000) && ((iw1
& 0x0000) == 0x0000))
6419 decode_psedodbg_assert_0 (cpu
, iw0
, iw1
, pc
);
6422 TRACE_EXTRACT (cpu
, "%s: no matching 32-bit pattern", __func__
);
6423 illegal_instruction (cpu
);
6430 interp_insn_bfin (SIM_CPU
*cpu
, bu32 pc
)
6435 BFIN_CPU_STATE
.n_stores
= 0;
6436 PARALLEL_GROUP
= BFIN_PARALLEL_NONE
;
6437 DIS_ALGN_EXPT
&= ~1;
6441 insn_len
= _interp_insn_bfin (cpu
, pc
);
6443 /* Proper display of multiple issue instructions. */
6446 PARALLEL_GROUP
= BFIN_PARALLEL_GROUP1
;
6447 _interp_insn_bfin (cpu
, pc
+ 4);
6448 PARALLEL_GROUP
= BFIN_PARALLEL_GROUP2
;
6449 _interp_insn_bfin (cpu
, pc
+ 6);
6451 for (i
= 0; i
< BFIN_CPU_STATE
.n_stores
; i
++)
6453 bu32
*addr
= BFIN_CPU_STATE
.stores
[i
].addr
;
6454 *addr
= BFIN_CPU_STATE
.stores
[i
].val
;
6455 TRACE_REGISTER (cpu
, "dequeuing write %s = %#x",
6456 get_store_name (cpu
, addr
), *addr
);
6459 cycles_inc (cpu
, CYCLE_DELAY
);
6461 /* Set back to zero in case a pending CEC event occurs
6462 after this this insn. */