1 /* Simulator for Analog Devices Blackfin processors.
3 Copyright (C) 2005-2024 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"
34 #include "dv-bfin_cec.h"
35 #include "dv-bfin_mmu.h"
37 #define HOST_LONG_WORD_SIZE (sizeof (long) * 8)
39 #define SIGNEXTEND(v, n) \
40 (((bs32)(v) << (HOST_LONG_WORD_SIZE - (n))) >> (HOST_LONG_WORD_SIZE - (n)))
42 static ATTRIBUTE_NORETURN
void
43 illegal_instruction (SIM_CPU
*cpu
)
45 TRACE_INSN (cpu
, "ILLEGAL INSTRUCTION");
47 cec_exception (cpu
, VEC_UNDEF_I
);
50 static ATTRIBUTE_NORETURN
void
51 illegal_instruction_combination (SIM_CPU
*cpu
)
53 TRACE_INSN (cpu
, "ILLEGAL INSTRUCTION COMBINATION");
55 cec_exception (cpu
, VEC_ILGAL_I
);
58 static ATTRIBUTE_NORETURN
void
59 illegal_instruction_or_combination (SIM_CPU
*cpu
)
61 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
62 illegal_instruction_combination (cpu
);
64 illegal_instruction (cpu
);
67 static ATTRIBUTE_NORETURN
void
68 unhandled_instruction (SIM_CPU
*cpu
, const char *insn
)
70 SIM_DESC sd
= CPU_STATE (cpu
);
74 TRACE_EVENTS (cpu
, "unhandled instruction");
77 iw1
= IFETCH (PCREG
+ 2);
78 iw2
= ((bu32
)iw0
<< 16) | iw1
;
80 sim_io_eprintf (sd
, "Unhandled instruction at 0x%08x (%s opcode 0x", PCREG
, insn
);
81 if ((iw0
& 0xc000) == 0xc000)
82 sim_io_eprintf (sd
, "%08x", iw2
);
84 sim_io_eprintf (sd
, "%04x", iw0
);
86 sim_io_eprintf (sd
, ") ... aborting\n");
88 illegal_instruction (cpu
);
91 static const char * const astat_names
[] =
129 c_0
, c_1
, c_4
, c_2
, c_uimm2
, c_uimm3
, c_imm3
, c_pcrel4
,
130 c_imm4
, c_uimm4s4
, c_uimm4s4d
, c_uimm4
, c_uimm4s2
, c_negimm5s4
, c_imm5
,
131 c_imm5d
, c_uimm5
, c_imm6
, c_imm7
, c_imm7d
, c_imm8
, c_uimm8
, c_pcrel8
,
132 c_uimm8s4
, c_pcrel8s4
, c_lppcrel10
, c_pcrel10
, c_pcrel12
, c_imm16s4
,
133 c_luimm16
, c_imm16
, c_imm16d
, c_huimm16
, c_rimm16
, c_imm16s2
, c_uimm16s4
,
134 c_uimm16s4d
, c_uimm16
, c_pcrel24
, c_uimm32
, c_imm32
, c_huimm32
, c_huimm32e
,
151 } constant_formats
[] =
153 { "0", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
154 { "1", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
155 { "4", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
156 { "2", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
157 { "uimm2", 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
158 { "uimm3", 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
159 { "imm3", 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
160 { "pcrel4", 4, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0},
161 { "imm4", 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
162 { "uimm4s4", 4, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0},
163 { "uimm4s4d", 4, 0, 0, 0, 2, 0, 0, 1, 1, 0, 0},
164 { "uimm4", 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
165 { "uimm4s2", 4, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0},
166 { "negimm5s4", 5, 0, 1, 0, 2, 0, 1, 0, 0, 0, 0},
167 { "imm5", 5, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
168 { "imm5d", 5, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0},
169 { "uimm5", 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
170 { "imm6", 6, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
171 { "imm7", 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
172 { "imm7d", 7, 0, 1, 0, 0, 0, 0, 0, 1, 3, 0},
173 { "imm8", 8, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
174 { "uimm8", 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
175 { "pcrel8", 8, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0},
176 { "uimm8s4", 8, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0},
177 { "pcrel8s4", 8, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0},
178 { "lppcrel10", 10, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0},
179 { "pcrel10", 10, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
180 { "pcrel12", 12, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
181 { "imm16s4", 16, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0},
182 { "luimm16", 16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
183 { "imm16", 16, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
184 { "imm16d", 16, 0, 1, 0, 0, 0, 0, 0, 1, 3, 0},
185 { "huimm16", 16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
186 { "rimm16", 16, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0},
187 { "imm16s2", 16, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0},
188 { "uimm16s4", 16, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0},
189 { "uimm16s4d", 16, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0},
190 { "uimm16", 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
191 { "pcrel24", 24, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
192 { "uimm32", 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
193 { "imm32", 32, 0, 1, 0, 0, 0, 0, 0, 1, 3, 0},
194 { "huimm32", 32, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
195 { "huimm32e", 32, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
199 fmtconst_str (const_forms_t cf
, bs32 x
, bu32 pc
)
203 if (constant_formats
[cf
].reloc
)
206 bu32 ea
= (((constant_formats
[cf
].pcrel
? SIGNEXTEND (x
, constant_formats
[cf
].nbits
)
207 : x
) + constant_formats
[cf
].offset
) << constant_formats
[cf
].scale
);
208 if (constant_formats
[cf
].pcrel
)
210 if (outf
->symbol_at_address_func (ea
, outf
) || !constant_formats
[cf
].exact
)
212 outf
->print_address_func (ea
, outf
);
218 sprintf (buf
, "%#x", x
);
223 /* Negative constants have an implied sign bit. */
224 if (constant_formats
[cf
].negative
)
226 int nb
= constant_formats
[cf
].nbits
+ 1;
228 x
= x
| (1 << constant_formats
[cf
].nbits
);
229 x
= SIGNEXTEND (x
, nb
);
232 x
= constant_formats
[cf
].issigned
? SIGNEXTEND (x
, constant_formats
[cf
].nbits
) : x
;
234 if (constant_formats
[cf
].offset
)
235 x
+= constant_formats
[cf
].offset
;
237 if (constant_formats
[cf
].scale
)
238 x
<<= constant_formats
[cf
].scale
;
240 if (constant_formats
[cf
].decimal
)
241 sprintf (buf
, "%*i", constant_formats
[cf
].leading
, x
);
244 if (constant_formats
[cf
].issigned
&& x
< 0)
245 sprintf (buf
, "-0x%x", abs (x
));
247 sprintf (buf
, "0x%x", x
);
254 fmtconst_val (const_forms_t cf
, bu32 x
, bu32 pc
)
256 if (0 && constant_formats
[cf
].reloc
)
258 bu32 ea
= (((constant_formats
[cf
].pcrel
259 ? (bu32
)SIGNEXTEND (x
, constant_formats
[cf
].nbits
)
260 : x
) + constant_formats
[cf
].offset
)
261 << constant_formats
[cf
].scale
);
262 if (constant_formats
[cf
].pcrel
)
268 /* Negative constants have an implied sign bit. */
269 if (constant_formats
[cf
].negative
)
271 int nb
= constant_formats
[cf
].nbits
+ 1;
272 x
= x
| (1 << constant_formats
[cf
].nbits
);
273 x
= SIGNEXTEND (x
, nb
);
275 else if (constant_formats
[cf
].issigned
)
276 x
= SIGNEXTEND (x
, constant_formats
[cf
].nbits
);
278 x
+= constant_formats
[cf
].offset
;
279 x
<<= constant_formats
[cf
].scale
;
284 #define uimm16s4(x) fmtconst_val (c_uimm16s4, x, 0)
285 #define uimm16s4_str(x) fmtconst_str (c_uimm16s4, x, 0)
286 #define uimm16s4d(x) fmtconst_val (c_uimm16s4d, x, 0)
287 #define pcrel4(x) fmtconst_val (c_pcrel4, x, pc)
288 #define pcrel8(x) fmtconst_val (c_pcrel8, x, pc)
289 #define pcrel8s4(x) fmtconst_val (c_pcrel8s4, x, pc)
290 #define pcrel10(x) fmtconst_val (c_pcrel10, x, pc)
291 #define pcrel12(x) fmtconst_val (c_pcrel12, x, pc)
292 #define negimm5s4(x) fmtconst_val (c_negimm5s4, x, 0)
293 #define negimm5s4_str(x) fmtconst_str (c_negimm5s4, x, 0)
294 #define rimm16(x) fmtconst_val (c_rimm16, x, 0)
295 #define huimm16(x) fmtconst_val (c_huimm16, x, 0)
296 #define imm16(x) fmtconst_val (c_imm16, x, 0)
297 #define imm16_str(x) fmtconst_str (c_imm16, x, 0)
298 #define imm16d(x) fmtconst_val (c_imm16d, x, 0)
299 #define uimm2(x) fmtconst_val (c_uimm2, x, 0)
300 #define uimm3(x) fmtconst_val (c_uimm3, x, 0)
301 #define uimm3_str(x) fmtconst_str (c_uimm3, x, 0)
302 #define luimm16(x) fmtconst_val (c_luimm16, x, 0)
303 #define luimm16_str(x) fmtconst_str (c_luimm16, x, 0)
304 #define uimm4(x) fmtconst_val (c_uimm4, x, 0)
305 #define uimm4_str(x) fmtconst_str (c_uimm4, x, 0)
306 #define uimm5(x) fmtconst_val (c_uimm5, x, 0)
307 #define uimm5_str(x) fmtconst_str (c_uimm5, x, 0)
308 #define imm16s2(x) fmtconst_val (c_imm16s2, x, 0)
309 #define imm16s2_str(x) fmtconst_str (c_imm16s2, x, 0)
310 #define uimm8(x) fmtconst_val (c_uimm8, x, 0)
311 #define imm16s4(x) fmtconst_val (c_imm16s4, x, 0)
312 #define imm16s4_str(x) fmtconst_str (c_imm16s4, x, 0)
313 #define uimm4s2(x) fmtconst_val (c_uimm4s2, x, 0)
314 #define uimm4s2_str(x) fmtconst_str (c_uimm4s2, x, 0)
315 #define uimm4s4(x) fmtconst_val (c_uimm4s4, x, 0)
316 #define uimm4s4_str(x) fmtconst_str (c_uimm4s4, x, 0)
317 #define uimm4s4d(x) fmtconst_val (c_uimm4s4d, x, 0)
318 #define lppcrel10(x) fmtconst_val (c_lppcrel10, x, pc)
319 #define imm3(x) fmtconst_val (c_imm3, x, 0)
320 #define imm3_str(x) fmtconst_str (c_imm3, x, 0)
321 #define imm4(x) fmtconst_val (c_imm4, x, 0)
322 #define uimm8s4(x) fmtconst_val (c_uimm8s4, x, 0)
323 #define imm5(x) fmtconst_val (c_imm5, x, 0)
324 #define imm5d(x) fmtconst_val (c_imm5d, x, 0)
325 #define imm6(x) fmtconst_val (c_imm6, x, 0)
326 #define imm7(x) fmtconst_val (c_imm7, x, 0)
327 #define imm7_str(x) fmtconst_str (c_imm7, x, 0)
328 #define imm7d(x) fmtconst_val (c_imm7d, x, 0)
329 #define imm8(x) fmtconst_val (c_imm8, x, 0)
330 #define pcrel24(x) fmtconst_val (c_pcrel24, x, pc)
331 #define pcrel24_str(x) fmtconst_str (c_pcrel24, x, pc)
332 #define uimm16(x) fmtconst_val (c_uimm16, x, 0)
333 #define uimm32(x) fmtconst_val (c_uimm32, x, 0)
334 #define imm32(x) fmtconst_val (c_imm32, x, 0)
335 #define huimm32(x) fmtconst_val (c_huimm32, x, 0)
336 #define huimm32e(x) fmtconst_val (c_huimm32e, x, 0)
338 /* Table C-4. Core Register Encoding Map. */
339 const char * const greg_names
[] =
341 "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7",
342 "P0", "P1", "P2", "P3", "P4", "P5", "SP", "FP",
343 "I0", "I1", "I2", "I3", "M0", "M1", "M2", "M3",
344 "B0", "B1", "B2", "B3", "L0", "L1", "L2", "L3",
345 "A0.X", "A0.W", "A1.X", "A1.W", "<res>", "<res>", "ASTAT", "RETS",
346 "<res>", "<res>", "<res>", "<res>", "<res>", "<res>", "<res>", "<res>",
347 "LC0", "LT0", "LB0", "LC1", "LT1", "LB1", "CYCLES", "CYCLES2",
348 "USP", "SEQSTAT", "SYSCFG", "RETI", "RETX", "RETN", "RETE", "EMUDAT",
351 get_allreg_name (int grp
, int reg
)
353 return greg_names
[(grp
<< 3) | reg
];
356 get_preg_name (int reg
)
358 return get_allreg_name (1, reg
);
362 reg_is_reserved (int grp
, int reg
)
364 return (grp
== 4 && (reg
== 4 || reg
== 5)) || (grp
== 5);
368 get_allreg (SIM_CPU
*cpu
, int grp
, int reg
)
370 int fullreg
= (grp
<< 3) | reg
;
371 /* REG_R0, REG_R1, REG_R2, REG_R3, REG_R4, REG_R5, REG_R6, REG_R7,
372 REG_P0, REG_P1, REG_P2, REG_P3, REG_P4, REG_P5, REG_SP, REG_FP,
373 REG_I0, REG_I1, REG_I2, REG_I3, REG_M0, REG_M1, REG_M2, REG_M3,
374 REG_B0, REG_B1, REG_B2, REG_B3, REG_L0, REG_L1, REG_L2, REG_L3,
375 REG_A0x, REG_A0w, REG_A1x, REG_A1w, , , REG_ASTAT, REG_RETS,
377 REG_LC0, REG_LT0, REG_LB0, REG_LC1, REG_LT1, REG_LB1, REG_CYCLES,
379 REG_USP, REG_SEQSTAT, REG_SYSCFG, REG_RETI, REG_RETX, REG_RETN, REG_RETE,
381 switch (fullreg
>> 2)
383 case 0: case 1: return &DREG (reg
);
384 case 2: case 3: return &PREG (reg
);
385 case 4: return &IREG (reg
& 3);
386 case 5: return &MREG (reg
& 3);
387 case 6: return &BREG (reg
& 3);
388 case 7: return &LREG (reg
& 3);
392 case 32: return &AXREG (0);
393 case 33: return &AWREG (0);
394 case 34: return &AXREG (1);
395 case 35: return &AWREG (1);
396 case 39: return &RETSREG
;
397 case 48: return &LCREG (0);
398 case 49: return <REG (0);
399 case 50: return &LBREG (0);
400 case 51: return &LCREG (1);
401 case 52: return <REG (1);
402 case 53: return &LBREG (1);
403 case 54: return &CYCLESREG
;
404 case 55: return &CYCLES2REG
;
405 case 56: return &USPREG
;
406 case 57: return &SEQSTATREG
;
407 case 58: return &SYSCFGREG
;
408 case 59: return &RETIREG
;
409 case 60: return &RETXREG
;
410 case 61: return &RETNREG
;
411 case 62: return &RETEREG
;
412 case 63: return &EMUDAT_INREG
;
414 illegal_instruction (cpu
);
419 amod0 (int s0
, int x0
)
421 static const char * const mod0
[] = {
422 "", " (S)", " (CO)", " (SCO)",
424 int i
= s0
+ (x0
<< 1);
426 if (i
< ARRAY_SIZE (mod0
))
433 amod0amod2 (int s0
, int x0
, int aop0
)
435 static const char * const mod02
[] = {
436 "", " (S)", " (CO)", " (SCO)",
438 " (ASR)", " (S, ASR)", " (CO, ASR)", " (SCO, ASR)",
439 " (ASL)", " (S, ASL)", " (CO, ASL)", " (SCO, ASL)",
441 int i
= s0
+ (x0
<< 1) + (aop0
<< 2);
443 if (i
< ARRAY_SIZE (mod02
))
450 amod1 (int s0
, int x0
)
452 static const char * const mod1
[] = {
455 int i
= s0
+ (x0
<< 1);
457 if (i
< ARRAY_SIZE (mod1
))
464 mac_optmode (int mmod
, int MM
)
466 static const char * const omode
[] = {
467 [(M_S2RND
<< 1) + 0] = " (S2RND)",
468 [(M_T
<< 1) + 0] = " (T)",
469 [(M_W32
<< 1) + 0] = " (W32)",
470 [(M_FU
<< 1) + 0] = " (FU)",
471 [(M_TFU
<< 1) + 0] = " (TFU)",
472 [(M_IS
<< 1) + 0] = " (IS)",
473 [(M_ISS2
<< 1) + 0] = " (ISS2)",
474 [(M_IH
<< 1) + 0] = " (IH)",
475 [(M_IU
<< 1) + 0] = " (IU)",
476 [(M_S2RND
<< 1) + 1] = " (M, S2RND)",
477 [(M_T
<< 1) + 1] = " (M, T)",
478 [(M_W32
<< 1) + 1] = " (M, W32)",
479 [(M_FU
<< 1) + 1] = " (M, FU)",
480 [(M_TFU
<< 1) + 1] = " (M, TFU)",
481 [(M_IS
<< 1) + 1] = " (M, IS)",
482 [(M_ISS2
<< 1) + 1] = " (M, ISS2)",
483 [(M_IH
<< 1) + 1] = " (M, IH)",
484 [(M_IU
<< 1) + 1] = " (M, IU)",
486 int i
= MM
+ (mmod
<< 1);
488 if (i
< ARRAY_SIZE (omode
) && omode
[i
])
495 get_store_name (SIM_CPU
*cpu
, bu32
*p
)
497 if (p
>= &DREG (0) && p
<= &CYCLESREG
)
498 return greg_names
[p
- &DREG (0)];
499 else if (p
== &AXREG (0))
500 return greg_names
[4 * 8 + 0];
501 else if (p
== &AWREG (0))
502 return greg_names
[4 * 8 + 1];
503 else if (p
== &AXREG (1))
504 return greg_names
[4 * 8 + 2];
505 else if (p
== &AWREG (1))
506 return greg_names
[4 * 8 + 3];
507 else if (p
== &ASTATREG (ac0
))
509 else if (p
== &ASTATREG (ac0_copy
))
510 return "ASTAT[ac0_copy]";
511 else if (p
== &ASTATREG (ac1
))
513 else if (p
== &ASTATREG (an
))
515 else if (p
== &ASTATREG (aq
))
517 else if (p
== &ASTATREG (av0
))
519 else if (p
== &ASTATREG (av0s
))
520 return "ASTAT[av0s]";
521 else if (p
== &ASTATREG (av1
))
523 else if (p
== &ASTATREG (av1s
))
524 return "ASTAT[av1s]";
525 else if (p
== &ASTATREG (az
))
527 else if (p
== &ASTATREG (v
))
529 else if (p
== &ASTATREG (v_copy
))
530 return "ASTAT[v_copy]";
531 else if (p
== &ASTATREG (vs
))
535 /* Worry about this when we start to STORE() it. */
536 sim_io_eprintf (CPU_STATE (cpu
), "STORE(): unknown register\n");
542 queue_store (SIM_CPU
*cpu
, bu32
*addr
, bu32 val
)
544 struct store
*s
= &BFIN_CPU_STATE
.stores
[BFIN_CPU_STATE
.n_stores
];
547 TRACE_REGISTER (cpu
, "queuing write %s = %#x",
548 get_store_name (cpu
, addr
), val
);
549 ++BFIN_CPU_STATE
.n_stores
;
551 #define STORE(X, Y) \
553 if (BFIN_CPU_STATE.n_stores == 20) abort (); \
554 queue_store (cpu, &(X), (Y)); \
558 setflags_nz (SIM_CPU
*cpu
, bu32 val
)
560 SET_ASTATREG (az
, val
== 0);
561 SET_ASTATREG (an
, val
>> 31);
565 setflags_nz_2x16 (SIM_CPU
*cpu
, bu32 val
)
567 SET_ASTATREG (an
, (bs16
)val
< 0 || (bs16
)(val
>> 16) < 0);
568 SET_ASTATREG (az
, (bs16
)val
== 0 || (bs16
)(val
>> 16) == 0);
572 setflags_logical (SIM_CPU
*cpu
, bu32 val
)
574 setflags_nz (cpu
, val
);
575 SET_ASTATREG (ac0
, 0);
580 add_brev (bu32 addend1
, bu32 addend2
)
589 for (i
= 31; i
>= 0; --i
)
591 b
= ((addend1
& mask
) >> i
) + ((addend2
& mask
) >> i
);
602 /* This is a bit crazy, but we want to simulate the hardware behavior exactly
603 rather than worry about the circular buffers being used correctly. Which
604 isn't to say there isn't room for improvement here, just that we want to
605 be conservative. See also dagsub(). */
607 dagadd (SIM_CPU
*cpu
, int dagno
, bs32 M
)
609 bu64 i
= IREG (dagno
);
610 bu64 l
= LREG (dagno
);
611 bu64 b
= BREG (dagno
);
615 bu32 im32
, iml32
, lb32
, res
;
618 /* A naïve implementation that mostly works:
620 if (l && res >= b + l)
622 STORE (IREG (dagno), res);
637 if ((i
& msb
) || (IM
& car
))
638 res
= (im32
< b
) ? iml32
: im32
;
640 res
= (im32
< b
) ? im32
: iml32
;
646 if ((IM
& car
) == (LB
& car
))
647 res
= (im32
< lb32
) ? im32
: iml32
;
649 res
= (im32
< lb32
) ? iml32
: im32
;
652 STORE (IREG (dagno
), res
);
656 /* See dagadd() notes above. */
658 dagsub (SIM_CPU
*cpu
, int dagno
, bs32 M
)
660 bu64 i
= IREG (dagno
);
661 bu64 l
= LREG (dagno
);
662 bu64 b
= BREG (dagno
);
665 bu64 mbar
= (bu32
)(~m
+ 1);
667 bu32 b32
, im32
, iml32
, lb32
, res
;
670 /* A naïve implementation that mostly works:
674 STORE (IREG (dagno), newi);
689 if (!!((i
& msb
) && (IM
& car
)) == !!(LB
& car
))
690 res
= (im32
< lb32
) ? im32
: iml32
;
692 res
= (im32
< lb32
) ? iml32
: im32
;
699 if (M
== 0 || IM
& car
)
700 res
= (im32
< b32
) ? iml32
: im32
;
702 res
= (im32
< b32
) ? im32
: iml32
;
705 STORE (IREG (dagno
), res
);
710 ashiftrt (SIM_CPU
*cpu
, bu40 val
, int cnt
, int size
)
712 int real_cnt
= cnt
> size
? size
: cnt
;
713 bu40 sgn
= ~(((val
& 0xFFFFFFFFFFull
) >> (size
- 1)) - 1);
714 int sgncnt
= size
- real_cnt
;
716 sgn
<<= 16, sgncnt
-= 16;
719 val
>>= 16, real_cnt
-= 16;
722 SET_ASTATREG (an
, val
>> (size
- 1));
723 SET_ASTATREG (az
, val
== 0);
730 lshiftrt (SIM_CPU
*cpu
, bu64 val
, int cnt
, int size
)
732 int real_cnt
= cnt
> size
? size
: cnt
;
734 val
>>= 16, real_cnt
-= 16;
745 val
&= 0xFFFFFFFFFFull
;
748 illegal_instruction (cpu
);
751 SET_ASTATREG (an
, val
>> (size
- 1));
752 SET_ASTATREG (az
, val
== 0);
759 lshift (SIM_CPU
*cpu
, bu64 val
, int cnt
, int size
, bool saturate
, bool overflow
)
761 int v_i
, real_cnt
= cnt
> size
? size
: cnt
;
762 bu64 sgn
= ~((val
>> (size
- 1)) - 1);
763 int mask_cnt
= size
- 1;
764 bu64 masked
, new_val
= val
;
772 new_val
<<= 16, real_cnt
-= 16;
774 new_val
<<= real_cnt
;
776 masked
= new_val
& mask
;
778 /* If an operation would otherwise cause a positive value to overflow
779 and become negative, instead, saturation limits the result to the
780 maximum positive value for the size register being used.
782 Conversely, if an operation would otherwise cause a negative value
783 to overflow and become positive, saturation limits the result to the
784 maximum negative value for the register size.
786 However, it's a little more complex than looking at sign bits, we need
787 to see if we are shifting the sign information away... */
788 if (((val
<< cnt
) >> size
) == 0
789 || (((val
<< cnt
) >> size
) == ~((bu32
)~0 << cnt
)
790 && ((new_val
>> (size
- 1)) & 0x1)))
799 if (saturate
&& (v_i
|| ((val
>> (size
- 1)) != (new_val
>> (size
- 1)))))
801 new_val
= (val
>> (size
- 1)) == 0 ? 0x7fff : 0x8000;
806 new_val
&= 0xFFFFFFFF;
807 masked
&= 0xFFFFFFFF;
812 || (!sgn
&& new_val
== 0 && val
!= 0)))
814 new_val
= sgn
== 0 ? 0x7fffffff : 0x80000000;
819 new_val
&= 0xFFFFFFFFFFull
;
820 masked
&= 0xFFFFFFFFFFull
;
823 illegal_instruction (cpu
);
827 SET_ASTATREG (an
, new_val
>> (size
- 1));
828 SET_ASTATREG (az
, new_val
== 0);
831 SET_ASTATREG (v
, overflow
&& v_i
);
833 SET_ASTATREG (vs
, 1);
840 algn (bu32 l
, bu32 h
, bu32 aln
)
845 return (l
>> (8 * aln
)) | (h
<< (32 - 8 * aln
));
849 saturate_s16 (bu64 val
, bu32
*overflow
)
851 if ((bs64
)val
< -0x8000ll
)
857 if ((bs64
)val
> 0x7fff)
867 rot40 (bu40 val
, int shift
, bu32
*cc
)
869 const int nbits
= 40;
872 shift
= CLAMP (shift
, -nbits
, nbits
);
876 /* Reduce everything to rotate left. */
880 ret
= shift
== nbits
? 0 : val
<< shift
;
881 ret
|= shift
== 1 ? 0 : val
>> ((nbits
+ 1) - shift
);
882 ret
|= (bu40
)*cc
<< (shift
- 1);
883 *cc
= (val
>> (nbits
- shift
)) & 1;
889 rot32 (bu32 val
, int shift
, bu32
*cc
)
891 const int nbits
= 32;
894 shift
= CLAMP (shift
, -nbits
, nbits
);
898 /* Reduce everything to rotate left. */
902 ret
= shift
== nbits
? 0 : val
<< shift
;
903 ret
|= shift
== 1 ? 0 : val
>> ((nbits
+ 1) - shift
);
904 ret
|= (bu32
)*cc
<< (shift
- 1);
905 *cc
= (val
>> (nbits
- shift
)) & 1;
911 add32 (SIM_CPU
*cpu
, bu32 a
, bu32 b
, int carry
, int sat
)
913 int flgs
= (a
>> 31) & 1;
914 int flgo
= (b
>> 31) & 1;
916 int flgn
= (v
>> 31) & 1;
917 int overflow
= (flgs
^ flgn
) & (flgo
^ flgn
);
924 flgn
= (v
>> 31) & 1;
927 SET_ASTATREG (an
, flgn
);
929 SET_ASTATREG (vs
, 1);
930 SET_ASTATREG (v
, overflow
);
931 ASTATREG (v_internal
) |= overflow
;
932 SET_ASTATREG (az
, v
== 0);
934 SET_ASTATREG (ac0
, ~a
< b
);
940 sub32 (SIM_CPU
*cpu
, bu32 a
, bu32 b
, int carry
, int sat
, int parallel
)
942 int flgs
= (a
>> 31) & 1;
943 int flgo
= (b
>> 31) & 1;
945 int flgn
= (v
>> 31) & 1;
946 int overflow
= (flgs
^ flgo
) & (flgn
^ flgs
);
953 flgn
= (v
>> 31) & 1;
956 if (!parallel
|| flgn
)
957 SET_ASTATREG (an
, flgn
);
959 SET_ASTATREG (vs
, 1);
960 if (!parallel
|| overflow
)
961 SET_ASTATREG (v
, overflow
);
962 if (!parallel
|| overflow
)
963 ASTATREG (v_internal
) |= overflow
;
964 if (!parallel
|| v
== 0)
965 SET_ASTATREG (az
, v
== 0);
966 if (carry
&& (!parallel
|| b
<= a
))
967 SET_ASTATREG (ac0
, b
<= a
);
973 add16 (SIM_CPU
*cpu
, bu16 a
, bu16 b
, bu32
*carry
, bu32
*overfl
,
974 bu32
*zero
, bu32
*neg
, int sat
, int scale
)
976 int flgs
= (a
>> 15) & 1;
977 int flgo
= (b
>> 15) & 1;
978 bs64 v
= (bs16
)a
+ (bs16
)b
;
979 int flgn
= (v
>> 15) & 1;
980 int overflow
= (flgs
^ flgn
) & (flgo
^ flgn
);
988 v
= (a
>> 1) + (a
& 0x8000) + (b
>> 1) + (b
& 0x8000)
989 + (((a
& 1) + (b
& 1)) >> 1);
997 illegal_instruction (cpu
);
1000 flgn
= (v
>> 15) & 1;
1001 overflow
= (flgs
^ flgn
) & (flgo
^ flgn
);
1003 if (v
> (bs64
)0xffff)
1007 v
= saturate_s16 (v
, 0);
1010 *neg
|= (v
>> 15) & 1;
1012 *overfl
|= overflow
;
1014 *zero
|= (v
& 0xFFFF) == 0;
1016 *carry
|= ((bu16
)~a
< (bu16
)b
);
1022 sub16 (SIM_CPU
*cpu
, bu16 a
, bu16 b
, bu32
*carry
, bu32
*overfl
,
1023 bu32
*zero
, bu32
*neg
, int sat
, int scale
)
1025 int flgs
= (a
>> 15) & 1;
1026 int flgo
= (b
>> 15) & 1;
1027 bs64 v
= (bs16
)a
- (bs16
)b
;
1028 int flgn
= (v
>> 15) & 1;
1029 int overflow
= (flgs
^ flgo
) & (flgn
^ flgs
);
1038 v
= ((a
>> 1) + (a
& 0x8000)) - ( (b
>> 1) + (b
& 0x8000))
1039 + (((a
& 1)-(b
& 1)));
1042 v
= ((v
& 0xFFFF) >> 1);
1043 if ((!flgs
& !flgo
& flgn
)
1044 || (flgs
& !flgo
& !flgn
)
1045 || (flgs
& flgo
& flgn
)
1046 || (flgs
& !flgo
& flgn
))
1050 flgn
= (v
>> 15) & 1;
1051 overflow
= (flgs
^ flgo
) & (flgn
^ flgs
);
1056 if (v
> (bs64
)0x7fff || v
< (bs64
)-0xffff)
1060 illegal_instruction (cpu
);
1065 v
= saturate_s16 (v
, 0);
1068 *neg
|= (v
>> 15) & 1;
1070 *zero
|= (v
& 0xFFFF) == 0;
1072 *overfl
|= overflow
;
1074 *carry
|= (bu16
)b
<= (bu16
)a
;
1079 min32 (SIM_CPU
*cpu
, bu32 a
, bu32 b
)
1082 if ((bs32
)a
> (bs32
)b
)
1084 setflags_nz (cpu
, val
);
1085 SET_ASTATREG (v
, 0);
1090 max32 (SIM_CPU
*cpu
, bu32 a
, bu32 b
)
1093 if ((bs32
)a
< (bs32
)b
)
1095 setflags_nz (cpu
, val
);
1096 SET_ASTATREG (v
, 0);
1101 min2x16 (SIM_CPU
*cpu
, bu32 a
, bu32 b
)
1104 if ((bs16
)a
> (bs16
)b
)
1105 val
= (val
& 0xFFFF0000) | (b
& 0xFFFF);
1106 if ((bs16
)(a
>> 16) > (bs16
)(b
>> 16))
1107 val
= (val
& 0xFFFF) | (b
& 0xFFFF0000);
1108 setflags_nz_2x16 (cpu
, val
);
1109 SET_ASTATREG (v
, 0);
1114 max2x16 (SIM_CPU
*cpu
, bu32 a
, bu32 b
)
1117 if ((bs16
)a
< (bs16
)b
)
1118 val
= (val
& 0xFFFF0000) | (b
& 0xFFFF);
1119 if ((bs16
)(a
>> 16) < (bs16
)(b
>> 16))
1120 val
= (val
& 0xFFFF) | (b
& 0xFFFF0000);
1121 setflags_nz_2x16 (cpu
, val
);
1122 SET_ASTATREG (v
, 0);
1127 add_and_shift (SIM_CPU
*cpu
, bu32 a
, bu32 b
, int shift
)
1130 ASTATREG (v_internal
) = 0;
1131 v
= add32 (cpu
, a
, b
, 0, 0);
1134 int x
= (v
>> 30) & 0x3;
1135 if (x
== 1 || x
== 2)
1136 ASTATREG (v_internal
) = 1;
1139 SET_ASTATREG (az
, v
== 0);
1140 SET_ASTATREG (an
, v
& 0x80000000);
1141 SET_ASTATREG (v
, ASTATREG (v_internal
));
1143 SET_ASTATREG (vs
, 1);
1148 xor_reduce (bu64 acc0
, bu64 acc1
)
1152 for (i
= 0; i
< 40; ++i
)
1154 v
^= (acc0
& acc1
& 1);
1161 /* DIVS ( Dreg, Dreg ) ;
1162 Initialize for DIVQ. Set the AQ status bit based on the signs of
1163 the 32-bit dividend and the 16-bit divisor. Left shift the dividend
1164 one bit. Copy AQ into the dividend LSB. */
1166 divs (SIM_CPU
*cpu
, bu32 pquo
, bu16 divisor
)
1168 bu16 r
= pquo
>> 16;
1171 aq
= (r
^ divisor
) >> 15; /* Extract msb's and compute quotient bit. */
1172 SET_ASTATREG (aq
, aq
); /* Update global quotient state. */
1176 pquo
= (pquo
& 0x1FFFF) | (r
<< 17);
1180 /* DIVQ ( Dreg, Dreg ) ;
1181 Based on AQ status bit, either add or subtract the divisor from
1182 the dividend. Then set the AQ status bit based on the MSBs of the
1183 32-bit dividend and the 16-bit divisor. Left shift the dividend one
1184 bit. Copy the logical inverse of AQ into the dividend LSB. */
1186 divq (SIM_CPU
*cpu
, bu32 pquo
, bu16 divisor
)
1188 unsigned short af
= pquo
>> 16;
1197 aq
= (r
^ divisor
) >> 15; /* Extract msb's and compute quotient bit. */
1198 SET_ASTATREG (aq
, aq
); /* Update global quotient state. */
1202 pquo
= (pquo
& 0x1FFFF) | (r
<< 17);
1207 Count the number of bits set to 1 in the 32bit value. */
1215 for (i
= 0; i
< 32; ++i
)
1216 ret
+= !!(val
& (1 << i
));
1222 reg_check_sup (SIM_CPU
*cpu
, int grp
, int reg
)
1225 cec_require_supervisor (cpu
);
1229 reg_write (SIM_CPU
*cpu
, int grp
, int reg
, bu32 value
)
1233 /* ASTAT is special! */
1234 if (grp
== 4 && reg
== 6)
1240 /* Check supervisor after get_allreg() so exception order is correct. */
1241 whichreg
= get_allreg (cpu
, grp
, reg
);
1242 reg_check_sup (cpu
, grp
, reg
);
1244 if (whichreg
== &CYCLES2REG
)
1245 /* Writes to CYCLES2 goes to the shadow. */
1246 whichreg
= &CYCLES2SHDREG
;
1247 else if (whichreg
== &SEQSTATREG
)
1248 /* Register is read only -- discard writes. */
1250 else if (whichreg
== &EMUDAT_INREG
)
1251 /* Writes to EMUDAT goes to the output. */
1252 whichreg
= &EMUDAT_OUTREG
;
1253 else if (whichreg
== <REG (0) || whichreg
== <REG (1))
1254 /* Writes to LT clears LSB automatically. */
1256 else if (whichreg
== &AXREG (0) || whichreg
== &AXREG (1))
1259 TRACE_REGISTER (cpu
, "wrote %s = %#x", get_allreg_name (grp
, reg
), value
);
1265 reg_read (SIM_CPU
*cpu
, int grp
, int reg
)
1270 /* ASTAT is special! */
1271 if (grp
== 4 && reg
== 6)
1274 /* Check supervisor after get_allreg() so exception order is correct. */
1275 whichreg
= get_allreg (cpu
, grp
, reg
);
1276 reg_check_sup (cpu
, grp
, reg
);
1280 if (whichreg
== &CYCLESREG
)
1281 /* Reads of CYCLES reloads CYCLES2 from the shadow. */
1282 SET_CYCLES2REG (CYCLES2SHDREG
);
1283 else if ((whichreg
== &AXREG (1) || whichreg
== &AXREG (0)) && (value
& 0x80))
1284 /* Sign extend if necessary. */
1285 value
|= 0xFFFFFF00;
1291 get_extended_cycles (SIM_CPU
*cpu
)
1293 return ((bu64
)CYCLES2SHDREG
<< 32) | CYCLESREG
;
1296 /* We can't re-use sim_events_time() because the CYCLES registers may be
1297 written/cleared/reset/stopped/started at any time by software. */
1299 cycles_inc (SIM_CPU
*cpu
, bu32 inc
)
1304 if (!(SYSCFGREG
& SYSCFG_CCEN
))
1307 cycles
= get_extended_cycles (cpu
) + inc
;
1308 SET_CYCLESREG (cycles
);
1309 cycles2
= cycles
>> 32;
1310 if (CYCLES2SHDREG
!= cycles2
)
1311 SET_CYCLES2SHDREG (cycles2
);
1315 get_unextended_acc (SIM_CPU
*cpu
, int which
)
1317 return ((bu64
)(AXREG (which
) & 0xff) << 32) | AWREG (which
);
1321 get_extended_acc (SIM_CPU
*cpu
, int which
)
1323 bu64 acc
= AXREG (which
);
1324 /* Sign extend accumulator values before adding. */
1330 acc
|= AWREG (which
);
1334 /* Perform a multiplication of D registers SRC0 and SRC1, sign- or
1335 zero-extending the result to 64 bit. H0 and H1 determine whether the
1336 high part or the low part of the source registers is used. Store 1 in
1337 *PSAT if saturation occurs, 0 otherwise. */
1339 decode_multfunc (SIM_CPU
*cpu
, int h0
, int h1
, int src0
, int src1
, int mmod
,
1342 bu32 s0
= DREG (src0
), s1
= DREG (src1
);
1356 sgn0
= -(s0
& 0x8000);
1357 sgn1
= -(s1
& 0x8000);
1379 illegal_instruction (cpu
);
1383 /* Perform shift correction if appropriate for the mode. */
1385 if (!MM
&& (mmod
== 0 || mmod
== M_T
|| mmod
== M_S2RND
|| mmod
== M_W32
))
1387 if (val
== 0x40000000)
1400 /* In signed modes, sign extend. */
1401 if (is_macmod_signed (mmod
) || MM
)
1402 val1
|= -(val1
& 0x80000000);
1405 val1
&= 0xFFFFFFFFull
;
1411 saturate_s40_astat (bu64 val
, bu32
*v
)
1413 if ((bs64
)val
< -((bs64
)1 << 39))
1416 return -((bs64
)1 << 39);
1418 else if ((bs64
)val
> ((bs64
)1 << 39) - 1)
1421 return ((bu64
)1 << 39) - 1;
1423 *v
= 0; /* No overflow. */
1428 saturate_s40 (bu64 val
)
1431 return saturate_s40_astat (val
, &v
);
1435 saturate_s32 (bu64 val
, bu32
*overflow
)
1437 if ((bs64
)val
< -0x80000000ll
)
1443 if ((bs64
)val
> 0x7fffffff)
1453 saturate_u32 (bu64 val
, bu32
*overflow
)
1455 if (val
> 0xffffffff)
1465 saturate_u16 (bu64 val
, bu32
*overflow
)
1481 /* FIXME: Should honour rounding mode. */
1482 if ((val
& 0xffff) > 0x8000
1483 || ((val
& 0xffff) == 0x8000 && (val
& 0x10000)))
1486 sgnbits
= val
& 0xffff000000000000ull
;
1488 return val
| sgnbits
;
1494 bu64 sgnbits
= val
& 0xffff000000000000ull
;
1496 return val
| sgnbits
;
1500 signbits (bu64 val
, int size
)
1502 bu64 mask
= (bu64
)1 << (size
- 1);
1503 bu64 bit
= val
& mask
;
1511 if ((val
& mask
) != bit
)
1521 /* Extract a 16 or 32 bit value from a 64 bit multiplication result.
1522 These 64 bits must be sign- or zero-extended properly from the source
1523 we want to extract, either a 32 bit multiply or a 40 bit accumulator. */
1526 extract_mult (SIM_CPU
*cpu
, bu64 res
, int mmod
, int MM
,
1527 int fullword
, bu32
*overflow
)
1534 return saturate_s32 (res
, overflow
);
1537 return saturate_s32 (res
, overflow
);
1538 return saturate_u32 (res
, overflow
);
1541 return saturate_s32 (res
, overflow
);
1542 return saturate_u32 (res
, overflow
);
1545 return saturate_s32 (res
<< 1, overflow
);
1547 illegal_instruction (cpu
);
1555 return saturate_s16 (rnd16 (res
), overflow
);
1557 return saturate_s16 (res
, overflow
);
1560 return saturate_s16 (rnd16 (res
), overflow
);
1561 return saturate_u16 (rnd16 (res
), overflow
);
1564 return saturate_s16 (res
, overflow
);
1565 return saturate_u16 (res
, overflow
);
1568 return saturate_s16 (trunc16 (res
), overflow
);
1571 return saturate_s16 (trunc16 (res
), overflow
);
1572 return saturate_u16 (trunc16 (res
), overflow
);
1575 return saturate_s16 (rnd16 (res
<< 1), overflow
);
1577 return saturate_s16 (res
<< 1, overflow
);
1579 illegal_instruction (cpu
);
1584 decode_macfunc (SIM_CPU
*cpu
, int which
, int op
, int h0
, int h1
, int src0
,
1585 int src1
, int mmod
, int MM
, int fullword
, bu32
*overflow
,
1589 bu32 sat
= 0, tsat
, ret
;
1591 /* Sign extend accumulator if necessary, otherwise unsigned. */
1592 if (is_macmod_signed (mmod
) || MM
)
1593 acc
= get_extended_acc (cpu
, which
);
1595 acc
= get_unextended_acc (cpu
, which
);
1599 /* TODO: Figure out how the 32-bit sign is used. */
1600 ATTRIBUTE_UNUSED bu8 sgn0
= (acc
>> 31) & 1;
1601 bu8 sgn40
= (acc
>> 39) & 1;
1604 /* This can't saturate, so we don't keep track of the sat flag. */
1605 bu64 res
= decode_multfunc (cpu
, h0
, h1
, src0
, src1
, mmod
,
1608 /* Perform accumulation. */
1613 sgn0
= (acc
>> 31) & 1;
1632 if ((bs64
)acc
< -((bs64
)1 << 39))
1633 acc
= -((bu64
)1 << 39), sat
= 1;
1634 else if ((bs64
)acc
> 0x7fffffffffll
)
1635 acc
= 0x7fffffffffull
, sat
= 1;
1640 if ((bs64
)acc
< -((bs64
)1 << 39))
1641 acc
= -((bu64
)1 << 39), sat
= 1;
1642 if ((bs64
)acc
> 0x7FFFFFFFFFll
)
1643 acc
= 0x7FFFFFFFFFull
, sat
= 1;
1649 if ((bs64
)acc
> 0xFFFFFFFFFFull
)
1650 acc
= 0xFFFFFFFFFFull
, sat
= 1;
1654 if (!MM
&& acc
& 0x8000000000000000ull
)
1656 if (!MM
&& acc
> 0xFFFFFFFFFFull
)
1657 acc
= 0xFFFFFFFFFFull
, sat
= 1;
1658 if (MM
&& acc
> 0xFFFFFFFFFFull
)
1659 acc
&= 0xFFFFFFFFFFull
;
1660 if (acc
& 0x8000000000ull
)
1661 acc
|= 0xffffff0000000000ull
;
1666 if ((bs64
)acc
< -((bs64
)1 << 39))
1667 acc
= -((bu64
)1 << 39), sat
= 1;
1668 if ((bs64
)acc
> 0x7FFFFFFFFFll
)
1669 acc
= 0x7FFFFFFFFFull
, sat
= 1;
1670 else if (acc
& 0x8000000000ull
)
1671 acc
|= 0xffffff0000000000ull
;
1677 else if ((bs64
)acc
> (bs64
)0xFFFFFFFFFFll
)
1678 acc
= 0xFFFFFFFFFFull
, sat
= 1;
1682 if ((bs64
)acc
< -0x80000000ll
)
1683 acc
= -0x80000000ull
, sat
= 1;
1684 else if ((bs64
)acc
> 0x7fffffffll
)
1685 acc
= 0x7fffffffull
, sat
= 1;
1688 /* check max negative value */
1689 if (sgn40
&& ((acc
>> 31) != 0x1ffffffff)
1690 && ((acc
>> 31) != 0x0))
1691 acc
= 0x80000000, sat
= 1;
1692 if (!sat
&& !sgn40
&& ((acc
>> 31) != 0x0)
1693 && ((acc
>> 31) != 0x1ffffffff))
1694 acc
= 0x7FFFFFFF, sat
= 1;
1696 if (acc
& 0x80000000)
1697 acc
|= 0xffffffff00000000ull
;
1702 illegal_instruction (cpu
);
1705 if (acc
& 0x8000000000ull
)
1708 STORE (AXREG (which
), (acc
>> 32) & 0xff);
1709 STORE (AWREG (which
), acc
& 0xffffffff);
1710 STORE (ASTATREG (av
[which
]), sat
);
1712 STORE (ASTATREG (avs
[which
]), sat
);
1714 /* Figure out the overflow bit. */
1720 ret
= extract_mult (cpu
, nosat_acc
, mmod
, MM
, fullword
, overflow
);
1724 ret
= extract_mult (cpu
, acc
, mmod
, MM
, fullword
, overflow
);
1733 if (ret
& 0x80000000)
1741 hwloop_get_next_pc (SIM_CPU
*cpu
, bu32 pc
, bu32 insn_len
)
1748 /* If our PC has reached the bottom of a hardware loop,
1749 move back up to the top of the hardware loop. */
1750 for (i
= 1; i
>= 0; --i
)
1751 if (LCREG (i
) > 1 && pc
== LBREG (i
))
1753 BFIN_TRACE_BRANCH (cpu
, pc
, LTREG (i
), i
, "Hardware loop %i", i
);
1757 return pc
+ insn_len
;
1761 decode_ProgCtrl_0 (SIM_CPU
*cpu
, bu16 iw0
, bu32 pc
)
1764 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
1765 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |.prgfunc.......|.poprnd........|
1766 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
1767 int poprnd
= ((iw0
>> ProgCtrl_poprnd_bits
) & ProgCtrl_poprnd_mask
);
1768 int prgfunc
= ((iw0
>> ProgCtrl_prgfunc_bits
) & ProgCtrl_prgfunc_mask
);
1770 TRACE_EXTRACT (cpu
, "%s: poprnd:%i prgfunc:%i", __func__
, poprnd
, prgfunc
);
1772 if (prgfunc
== 0 && poprnd
== 0)
1774 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_nop
);
1775 TRACE_INSN (cpu
, "NOP;");
1777 else if (prgfunc
== 1 && poprnd
== 0)
1779 bu32 newpc
= RETSREG
;
1780 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1781 TRACE_INSN (cpu
, "RTS;");
1782 IFETCH_CHECK (newpc
);
1783 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1784 illegal_instruction_combination (cpu
);
1785 BFIN_TRACE_BRANCH (cpu
, pc
, newpc
, -1, "RTS");
1787 BFIN_CPU_STATE
.did_jump
= true;
1790 else if (prgfunc
== 1 && poprnd
== 1)
1792 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1793 TRACE_INSN (cpu
, "RTI;");
1794 /* Do not do IFETCH_CHECK here -- LSB has special meaning. */
1795 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1796 illegal_instruction_combination (cpu
);
1797 cec_return (cpu
, -1);
1800 else if (prgfunc
== 1 && poprnd
== 2)
1802 bu32 newpc
= RETXREG
;
1803 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1804 TRACE_INSN (cpu
, "RTX;");
1805 /* XXX: Not sure if this is what the hardware does. */
1806 IFETCH_CHECK (newpc
);
1807 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1808 illegal_instruction_combination (cpu
);
1809 cec_return (cpu
, IVG_EVX
);
1812 else if (prgfunc
== 1 && poprnd
== 3)
1814 bu32 newpc
= RETNREG
;
1815 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1816 TRACE_INSN (cpu
, "RTN;");
1817 /* XXX: Not sure if this is what the hardware does. */
1818 IFETCH_CHECK (newpc
);
1819 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1820 illegal_instruction_combination (cpu
);
1821 cec_return (cpu
, IVG_NMI
);
1824 else if (prgfunc
== 1 && poprnd
== 4)
1826 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1827 TRACE_INSN (cpu
, "RTE;");
1828 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1829 illegal_instruction_combination (cpu
);
1830 cec_return (cpu
, IVG_EMU
);
1833 else if (prgfunc
== 2 && poprnd
== 0)
1835 SIM_DESC sd
= CPU_STATE (cpu
);
1836 sim_events
*events
= STATE_EVENTS (sd
);
1838 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_sync
);
1839 /* XXX: in supervisor mode, utilizes wake up sources
1840 in user mode, it's a NOP ... */
1841 TRACE_INSN (cpu
, "IDLE;");
1843 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1844 illegal_instruction_combination (cpu
);
1848 CYCLE_DELAY
= events
->time_from_event
;
1850 abort (); /* XXX: Should this ever happen ? */
1852 else if (prgfunc
== 2 && poprnd
== 3)
1854 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_sync
);
1856 TRACE_INSN (cpu
, "CSYNC;");
1857 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1858 illegal_instruction_combination (cpu
);
1861 else if (prgfunc
== 2 && poprnd
== 4)
1863 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_sync
);
1865 TRACE_INSN (cpu
, "SSYNC;");
1866 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1867 illegal_instruction_combination (cpu
);
1869 /* Really 10+, but no model info for this. */
1872 else if (prgfunc
== 2 && poprnd
== 5)
1874 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1875 TRACE_INSN (cpu
, "EMUEXCPT;");
1876 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1877 illegal_instruction_combination (cpu
);
1878 cec_exception (cpu
, VEC_SIM_TRAP
);
1880 else if (prgfunc
== 3 && poprnd
< 8)
1882 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1883 TRACE_INSN (cpu
, "CLI R%i;", poprnd
);
1884 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1885 illegal_instruction_combination (cpu
);
1886 SET_DREG (poprnd
, cec_cli (cpu
));
1888 else if (prgfunc
== 4 && poprnd
< 8)
1890 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1891 TRACE_INSN (cpu
, "STI R%i;", poprnd
);
1892 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1893 illegal_instruction_combination (cpu
);
1894 cec_sti (cpu
, DREG (poprnd
));
1897 else if (prgfunc
== 5 && poprnd
< 8)
1899 bu32 newpc
= PREG (poprnd
);
1900 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1901 TRACE_INSN (cpu
, "JUMP (%s);", get_preg_name (poprnd
));
1902 IFETCH_CHECK (newpc
);
1903 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1904 illegal_instruction_combination (cpu
);
1905 BFIN_TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP (Preg)");
1907 BFIN_CPU_STATE
.did_jump
= true;
1908 PROFILE_BRANCH_TAKEN (cpu
);
1911 else if (prgfunc
== 6 && poprnd
< 8)
1913 bu32 newpc
= PREG (poprnd
);
1914 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1915 TRACE_INSN (cpu
, "CALL (%s);", get_preg_name (poprnd
));
1916 IFETCH_CHECK (newpc
);
1917 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1918 illegal_instruction_combination (cpu
);
1919 BFIN_TRACE_BRANCH (cpu
, pc
, newpc
, -1, "CALL (Preg)");
1920 /* If we're at the end of a hardware loop, RETS is going to be
1921 the top of the loop rather than the next instruction. */
1922 SET_RETSREG (hwloop_get_next_pc (cpu
, pc
, 2));
1924 BFIN_CPU_STATE
.did_jump
= true;
1925 PROFILE_BRANCH_TAKEN (cpu
);
1928 else if (prgfunc
== 7 && poprnd
< 8)
1930 bu32 newpc
= pc
+ PREG (poprnd
);
1931 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1932 TRACE_INSN (cpu
, "CALL (PC + %s);", get_preg_name (poprnd
));
1933 IFETCH_CHECK (newpc
);
1934 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1935 illegal_instruction_combination (cpu
);
1936 BFIN_TRACE_BRANCH (cpu
, pc
, newpc
, -1, "CALL (PC + Preg)");
1937 SET_RETSREG (hwloop_get_next_pc (cpu
, pc
, 2));
1939 BFIN_CPU_STATE
.did_jump
= true;
1940 PROFILE_BRANCH_TAKEN (cpu
);
1943 else if (prgfunc
== 8 && poprnd
< 8)
1945 bu32 newpc
= pc
+ PREG (poprnd
);
1946 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1947 TRACE_INSN (cpu
, "JUMP (PC + %s);", get_preg_name (poprnd
));
1948 IFETCH_CHECK (newpc
);
1949 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1950 illegal_instruction_combination (cpu
);
1951 BFIN_TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP (PC + Preg)");
1953 BFIN_CPU_STATE
.did_jump
= true;
1954 PROFILE_BRANCH_TAKEN (cpu
);
1957 else if (prgfunc
== 9)
1959 int raise
= uimm4 (poprnd
);
1960 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1961 TRACE_INSN (cpu
, "RAISE %s;", uimm4_str (raise
));
1962 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1963 illegal_instruction_combination (cpu
);
1964 cec_require_supervisor (cpu
);
1965 if (raise
== IVG_IVHW
)
1966 cec_hwerr (cpu
, HWERR_RAISE_5
);
1968 cec_latch (cpu
, raise
);
1969 CYCLE_DELAY
= 3; /* XXX: Only if IVG is unmasked. */
1971 else if (prgfunc
== 10)
1973 int excpt
= uimm4 (poprnd
);
1974 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1975 TRACE_INSN (cpu
, "EXCPT %s;", uimm4_str (excpt
));
1976 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1977 illegal_instruction_combination (cpu
);
1978 cec_exception (cpu
, excpt
);
1981 else if (prgfunc
== 11 && poprnd
< 6)
1983 bu32 addr
= PREG (poprnd
);
1985 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_atomic
);
1986 TRACE_INSN (cpu
, "TESTSET (%s);", get_preg_name (poprnd
));
1987 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1988 illegal_instruction_combination (cpu
);
1989 byte
= GET_WORD (addr
);
1990 SET_CCREG (byte
== 0);
1991 PUT_BYTE (addr
, byte
| 0x80);
1992 /* Also includes memory stalls, but we don't model that. */
1996 illegal_instruction_or_combination (cpu
);
2000 decode_CaCTRL_0 (SIM_CPU
*cpu
, bu16 iw0
)
2003 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2004 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 |.a.|.op....|.reg.......|
2005 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2006 int a
= ((iw0
>> CaCTRL_a_bits
) & CaCTRL_a_mask
);
2007 int op
= ((iw0
>> CaCTRL_op_bits
) & CaCTRL_op_mask
);
2008 int reg
= ((iw0
>> CaCTRL_reg_bits
) & CaCTRL_reg_mask
);
2009 bu32 preg
= PREG (reg
);
2010 const char * const sinsn
[] = { "PREFETCH", "FLUSHINV", "FLUSH", "IFLUSH", };
2012 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CaCTRL
);
2013 TRACE_EXTRACT (cpu
, "%s: a:%i op:%i reg:%i", __func__
, a
, op
, reg
);
2014 TRACE_INSN (cpu
, "%s [%s%s];", sinsn
[op
], get_preg_name (reg
), a
? "++" : "");
2016 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2017 /* None of these can be part of a parallel instruction. */
2018 illegal_instruction_combination (cpu
);
2020 /* No cache simulation, so these are (mostly) all NOPs.
2021 XXX: The hardware takes care of masking to cache lines, but need
2022 to check behavior of the post increment. Should we be aligning
2023 the value to the cache line before adding the cache line size, or
2024 do we just add the cache line size ? */
2027 mmu_check_cache_addr (cpu
, preg
, false, false);
2031 mmu_check_cache_addr (cpu
, preg
, true, false);
2035 mmu_check_cache_addr (cpu
, preg
, true, false);
2039 mmu_check_cache_addr (cpu
, preg
, false, true);
2043 SET_PREG (reg
, preg
+ BFIN_L1_CACHE_BYTES
);
2047 decode_PushPopReg_0 (SIM_CPU
*cpu
, bu16 iw0
)
2050 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2051 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |.W.|.grp.......|.reg.......|
2052 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2053 int W
= ((iw0
>> PushPopReg_W_bits
) & PushPopReg_W_mask
);
2054 int grp
= ((iw0
>> PushPopReg_grp_bits
) & PushPopReg_grp_mask
);
2055 int reg
= ((iw0
>> PushPopReg_reg_bits
) & PushPopReg_reg_mask
);
2056 const char *reg_name
= get_allreg_name (grp
, reg
);
2060 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_PushPopReg
);
2061 TRACE_EXTRACT (cpu
, "%s: W:%i grp:%i reg:%i", __func__
, W
, grp
, reg
);
2062 TRACE_DECODE (cpu
, "%s: reg:%s", __func__
, reg_name
);
2064 /* Can't push/pop reserved registers */
2065 if (reg_is_reserved (grp
, reg
))
2066 illegal_instruction_or_combination (cpu
);
2070 /* Dreg and Preg are not supported by this instruction. */
2071 if (grp
== 0 || grp
== 1)
2072 illegal_instruction_or_combination (cpu
);
2073 TRACE_INSN (cpu
, "%s = [SP++];", reg_name
);
2074 /* Can't pop USP while in userspace. */
2075 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
2076 || (grp
== 7 && reg
== 0 && cec_is_user_mode(cpu
)))
2077 illegal_instruction_combination (cpu
);
2078 /* XXX: The valid register check is in reg_write(), so we might
2079 incorrectly do a GET_LONG() here ... */
2080 value
= GET_LONG (sp
);
2081 reg_write (cpu
, grp
, reg
, value
);
2082 if (grp
== 7 && reg
== 3)
2089 TRACE_INSN (cpu
, "[--SP] = %s;", reg_name
);
2090 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2091 illegal_instruction_combination (cpu
);
2094 value
= reg_read (cpu
, grp
, reg
);
2095 if (grp
== 7 && reg
== 3)
2096 cec_push_reti (cpu
);
2098 PUT_LONG (sp
, value
);
2101 /* Note: SP update must be delayed until after all reads/writes; see
2102 comments in decode_PushPopMultiple_0() for more info. */
2107 decode_PushPopMultiple_0 (SIM_CPU
*cpu
, bu16 iw0
)
2110 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2111 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |.d.|.p.|.W.|.dr........|.pr........|
2112 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2113 int p
= ((iw0
>> PushPopMultiple_p_bits
) & PushPopMultiple_p_mask
);
2114 int d
= ((iw0
>> PushPopMultiple_d_bits
) & PushPopMultiple_d_mask
);
2115 int W
= ((iw0
>> PushPopMultiple_W_bits
) & PushPopMultiple_W_mask
);
2116 int dr
= ((iw0
>> PushPopMultiple_dr_bits
) & PushPopMultiple_dr_mask
);
2117 int pr
= ((iw0
>> PushPopMultiple_pr_bits
) & PushPopMultiple_pr_mask
);
2121 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_PushPopMultiple
);
2122 TRACE_EXTRACT (cpu
, "%s: d:%i p:%i W:%i dr:%i pr:%i",
2123 __func__
, d
, p
, W
, dr
, pr
);
2125 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2126 illegal_instruction_combination (cpu
);
2128 if ((d
== 0 && p
== 0) || (p
&& imm5 (pr
) > 5)
2129 || (d
&& !p
&& pr
) || (p
&& !d
&& dr
))
2130 illegal_instruction (cpu
);
2135 TRACE_INSN (cpu
, "[--SP] = (R7:%i, P5:%i);", dr
, pr
);
2137 TRACE_INSN (cpu
, "[--SP] = (R7:%i);", dr
);
2139 TRACE_INSN (cpu
, "[--SP] = (P5:%i);", pr
);
2142 for (i
= dr
; i
< 8; i
++)
2145 PUT_LONG (sp
, DREG (i
));
2148 for (i
= pr
; i
< 6; i
++)
2151 PUT_LONG (sp
, PREG (i
));
2159 TRACE_INSN (cpu
, "(R7:%i, P5:%i) = [SP++];", dr
, pr
);
2161 TRACE_INSN (cpu
, "(R7:%i) = [SP++];", dr
);
2163 TRACE_INSN (cpu
, "(P5:%i) = [SP++];", pr
);
2166 for (i
= 5; i
>= pr
; i
--)
2168 SET_PREG (i
, GET_LONG (sp
));
2172 for (i
= 7; i
>= dr
; i
--)
2174 SET_DREG (i
, GET_LONG (sp
));
2181 /* Note: SP update must be delayed until after all reads/writes so that
2182 if an exception does occur, the insn may be re-executed as the
2183 SP has not yet changed. */
2188 decode_ccMV_0 (SIM_CPU
*cpu
, bu16 iw0
)
2191 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2192 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |.T.|.d.|.s.|.dst.......|.src.......|
2193 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2194 int s
= ((iw0
>> CCmv_s_bits
) & CCmv_s_mask
);
2195 int d
= ((iw0
>> CCmv_d_bits
) & CCmv_d_mask
);
2196 int T
= ((iw0
>> CCmv_T_bits
) & CCmv_T_mask
);
2197 int src
= ((iw0
>> CCmv_src_bits
) & CCmv_src_mask
);
2198 int dst
= ((iw0
>> CCmv_dst_bits
) & CCmv_dst_mask
);
2199 int cond
= T
? CCREG
: ! CCREG
;
2201 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ccMV
);
2202 TRACE_EXTRACT (cpu
, "%s: T:%i d:%i s:%i dst:%i src:%i",
2203 __func__
, T
, d
, s
, dst
, src
);
2205 TRACE_INSN (cpu
, "IF %sCC %s = %s;", T
? "" : "! ",
2206 get_allreg_name (d
, dst
),
2207 get_allreg_name (s
, src
));
2208 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2209 illegal_instruction_combination (cpu
);
2212 reg_write (cpu
, d
, dst
, reg_read (cpu
, s
, src
));
2216 decode_CCflag_0 (SIM_CPU
*cpu
, bu16 iw0
)
2219 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2220 | 0 | 0 | 0 | 0 | 1 |.I.|.opc.......|.G.|.y.........|.x.........|
2221 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2222 int x
= ((iw0
>> CCflag_x_bits
) & CCflag_x_mask
);
2223 int y
= ((iw0
>> CCflag_y_bits
) & CCflag_y_mask
);
2224 int I
= ((iw0
>> CCflag_I_bits
) & CCflag_I_mask
);
2225 int G
= ((iw0
>> CCflag_G_bits
) & CCflag_G_mask
);
2226 int opc
= ((iw0
>> CCflag_opc_bits
) & CCflag_opc_mask
);
2228 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CCflag
);
2229 TRACE_EXTRACT (cpu
, "%s: I:%i opc:%i G:%i y:%i x:%i",
2230 __func__
, I
, opc
, G
, y
, x
);
2234 bs64 acc0
= get_extended_acc (cpu
, 0);
2235 bs64 acc1
= get_extended_acc (cpu
, 1);
2236 bs64 diff
= acc0
- acc1
;
2238 if (x
!= 0 || y
!= 0)
2239 illegal_instruction_or_combination (cpu
);
2241 if (opc
== 5 && 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
== 6 && 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
);
2255 else if (opc
== 7 && I
== 0 && G
== 0)
2257 TRACE_INSN (cpu
, "CC = A0 <= A1");
2258 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2259 illegal_instruction_combination (cpu
);
2260 SET_CCREG (acc0
<= acc1
);
2263 illegal_instruction_or_combination (cpu
);
2265 SET_ASTATREG (az
, diff
== 0);
2266 SET_ASTATREG (an
, diff
< 0);
2267 SET_ASTATREG (ac0
, (bu40
)acc1
<= (bu40
)acc0
);
2271 int issigned
= opc
< 3;
2272 const char *sign
= issigned
? "" : " (IU)";
2273 bu32 srcop
= G
? PREG (x
) : DREG (x
);
2274 char s
= G
? 'P' : 'R';
2275 bu32 dstop
= I
? (issigned
? imm3 (y
) : uimm3 (y
)) : G
? PREG (y
) : DREG (y
);
2277 char d
= G
? 'P' : 'R';
2278 int flgs
= srcop
>> 31;
2279 int flgo
= dstop
>> 31;
2281 bu32 result
= srcop
- dstop
;
2283 int flgn
= result
>> 31;
2284 int overflow
= (flgs
^ flgo
) & (flgn
^ flgs
);
2285 int az
= result
== 0;
2286 int ac0
= dstop
<= srcop
;
2289 an
= (flgn
&& !overflow
) || (!flgn
&& overflow
);
2295 default: /* Shutup useless gcc warnings. */
2296 case 0: /* signed */
2300 case 1: /* signed */
2304 case 2: /* signed */
2308 case 3: /* unsigned */
2312 case 4: /* unsigned */
2319 TRACE_INSN (cpu
, "CC = %c%i %s %s%s;", s
, x
, op
,
2320 issigned
? imm3_str (y
) : uimm3_str (y
), sign
);
2323 TRACE_DECODE (cpu
, "%s %c%i:%x %c%i:%x", __func__
,
2324 s
, x
, srcop
, d
, y
, dstop
);
2325 TRACE_INSN (cpu
, "CC = %c%i %s %c%i%s;", s
, x
, op
, d
, y
, sign
);
2328 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2329 illegal_instruction_combination (cpu
);
2332 /* Pointer compares only touch CC. */
2335 SET_ASTATREG (az
, az
);
2336 SET_ASTATREG (an
, an
);
2337 SET_ASTATREG (ac0
, ac0
);
2343 decode_CC2dreg_0 (SIM_CPU
*cpu
, bu16 iw0
)
2346 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2347 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |.op....|.reg.......|
2348 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2349 int op
= ((iw0
>> CC2dreg_op_bits
) & CC2dreg_op_mask
);
2350 int reg
= ((iw0
>> CC2dreg_reg_bits
) & CC2dreg_reg_mask
);
2352 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CC2dreg
);
2353 TRACE_EXTRACT (cpu
, "%s: op:%i reg:%i", __func__
, op
, reg
);
2357 TRACE_INSN (cpu
, "R%i = CC;", reg
);
2358 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2359 illegal_instruction_combination (cpu
);
2360 SET_DREG (reg
, CCREG
);
2364 TRACE_INSN (cpu
, "CC = R%i;", reg
);
2365 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2366 illegal_instruction_combination (cpu
);
2367 SET_CCREG (DREG (reg
) != 0);
2369 else if (op
== 3 && reg
== 0)
2371 TRACE_INSN (cpu
, "CC = !CC;");
2372 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2373 illegal_instruction_combination (cpu
);
2377 illegal_instruction_or_combination (cpu
);
2381 decode_CC2stat_0 (SIM_CPU
*cpu
, bu16 iw0
)
2384 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2385 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |.D.|.op....|.cbit..............|
2386 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2387 int D
= ((iw0
>> CC2stat_D_bits
) & CC2stat_D_mask
);
2388 int op
= ((iw0
>> CC2stat_op_bits
) & CC2stat_op_mask
);
2389 int cbit
= ((iw0
>> CC2stat_cbit_bits
) & CC2stat_cbit_mask
);
2392 const char * const op_names
[] = { "", "|", "&", "^" } ;
2394 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CC2stat
);
2395 TRACE_EXTRACT (cpu
, "%s: D:%i op:%i cbit:%i", __func__
, D
, op
, cbit
);
2397 TRACE_INSN (cpu
, "%s %s= %s;", D
? astat_names
[cbit
] : "CC",
2398 op_names
[op
], D
? "CC" : astat_names
[cbit
]);
2400 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2401 illegal_instruction_combination (cpu
);
2403 /* CC = CC; is invalid. */
2405 illegal_instruction (cpu
);
2407 pval
= !!(ASTAT
& (1 << cbit
));
2411 case 0: SET_CCREG (pval
); break;
2412 case 1: SET_CCREG (CCREG
| pval
); break;
2413 case 2: SET_CCREG (CCREG
& pval
); break;
2414 case 3: SET_CCREG (CCREG
^ pval
); break;
2420 case 0: pval
= CCREG
; break;
2421 case 1: pval
|= CCREG
; break;
2422 case 2: pval
&= CCREG
; break;
2423 case 3: pval
^= CCREG
; break;
2425 TRACE_REGISTER (cpu
, "wrote ASTAT[%s] = %i", astat_names
[cbit
], pval
);
2426 SET_ASTAT ((ASTAT
& ~(1 << cbit
)) | (pval
<< cbit
));
2431 decode_BRCC_0 (SIM_CPU
*cpu
, bu16 iw0
, bu32 pc
)
2434 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2435 | 0 | 0 | 0 | 1 |.T.|.B.|.offset................................|
2436 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2437 int B
= ((iw0
>> BRCC_B_bits
) & BRCC_B_mask
);
2438 int T
= ((iw0
>> BRCC_T_bits
) & BRCC_T_mask
);
2439 int offset
= ((iw0
>> BRCC_offset_bits
) & BRCC_offset_mask
);
2440 int cond
= T
? CCREG
: ! CCREG
;
2441 int pcrel
= pcrel10 (offset
);
2443 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_BRCC
);
2444 TRACE_EXTRACT (cpu
, "%s: T:%i B:%i offset:%#x", __func__
, T
, B
, offset
);
2445 TRACE_DECODE (cpu
, "%s: pcrel10:%#x", __func__
, pcrel
);
2447 TRACE_INSN (cpu
, "IF %sCC JUMP %#x%s;", T
? "" : "! ",
2448 pcrel
, B
? " (bp)" : "");
2450 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2451 illegal_instruction_combination (cpu
);
2455 bu32 newpc
= pc
+ pcrel
;
2456 BFIN_TRACE_BRANCH (cpu
, pc
, newpc
, -1, "Conditional JUMP");
2458 BFIN_CPU_STATE
.did_jump
= true;
2459 PROFILE_BRANCH_TAKEN (cpu
);
2460 CYCLE_DELAY
= B
? 5 : 9;
2464 PROFILE_BRANCH_UNTAKEN (cpu
);
2465 CYCLE_DELAY
= B
? 9 : 1;
2470 decode_UJUMP_0 (SIM_CPU
*cpu
, bu16 iw0
, bu32 pc
)
2473 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2474 | 0 | 0 | 1 | 0 |.offset........................................|
2475 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2476 int offset
= ((iw0
>> UJump_offset_bits
) & UJump_offset_mask
);
2477 int pcrel
= pcrel12 (offset
);
2478 bu32 newpc
= pc
+ pcrel
;
2480 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_UJUMP
);
2481 TRACE_EXTRACT (cpu
, "%s: offset:%#x", __func__
, offset
);
2482 TRACE_DECODE (cpu
, "%s: pcrel12:%#x", __func__
, pcrel
);
2484 TRACE_INSN (cpu
, "JUMP.S %#x;", pcrel
);
2486 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2487 illegal_instruction_combination (cpu
);
2489 BFIN_TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP.S");
2492 BFIN_CPU_STATE
.did_jump
= true;
2493 PROFILE_BRANCH_TAKEN (cpu
);
2498 decode_REGMV_0 (SIM_CPU
*cpu
, bu16 iw0
)
2501 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2502 | 0 | 0 | 1 | 1 |.gd........|.gs........|.dst.......|.src.......|
2503 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2504 int gs
= ((iw0
>> RegMv_gs_bits
) & RegMv_gs_mask
);
2505 int gd
= ((iw0
>> RegMv_gd_bits
) & RegMv_gd_mask
);
2506 int src
= ((iw0
>> RegMv_src_bits
) & RegMv_src_mask
);
2507 int dst
= ((iw0
>> RegMv_dst_bits
) & RegMv_dst_mask
);
2508 const char *srcreg_name
= get_allreg_name (gs
, src
);
2509 const char *dstreg_name
= get_allreg_name (gd
, dst
);
2511 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_REGMV
);
2512 TRACE_EXTRACT (cpu
, "%s: gd:%i gs:%i dst:%i src:%i",
2513 __func__
, gd
, gs
, dst
, src
);
2514 TRACE_DECODE (cpu
, "%s: dst:%s src:%s", __func__
, dstreg_name
, srcreg_name
);
2516 TRACE_INSN (cpu
, "%s = %s;", dstreg_name
, srcreg_name
);
2518 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2519 illegal_instruction_combination (cpu
);
2521 /* Reserved slots cannot be a src/dst. */
2522 if (reg_is_reserved (gs
, src
) || reg_is_reserved (gd
, dst
))
2525 /* Standard register moves. */
2526 if ((gs
< 2) /* Dregs/Pregs src */
2527 || (gd
< 2) /* Dregs/Pregs dst */
2528 || (gs
== 4 && src
< 4) /* Accumulators src */
2529 || (gd
== 4 && dst
< 4 && (gs
< 4)) /* Accumulators dst */
2530 || (gs
== 7 && src
== 7 && !(gd
== 4 && dst
< 4)) /* EMUDAT src */
2531 || (gd
== 7 && dst
== 7)) /* EMUDAT dst */
2534 /* dareg = dareg (IMBL) */
2535 if (gs
< 4 && gd
< 4)
2538 /* USP can be src to sysregs, but not dagregs. */
2539 if ((gs
== 7 && src
== 0) && (gd
>= 4))
2542 /* USP can move between genregs (only check Accumulators). */
2543 if (((gs
== 7 && src
== 0) && (gd
== 4 && dst
< 4))
2544 || ((gd
== 7 && dst
== 0) && (gs
== 4 && src
< 4)))
2547 /* Still here ? Invalid reg pair. */
2549 illegal_instruction (cpu
);
2552 reg_write (cpu
, gd
, dst
, reg_read (cpu
, gs
, src
));
2556 decode_ALU2op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2559 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2560 | 0 | 1 | 0 | 0 | 0 | 0 |.opc...........|.src.......|.dst.......|
2561 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2562 int src
= ((iw0
>> ALU2op_src_bits
) & ALU2op_src_mask
);
2563 int opc
= ((iw0
>> ALU2op_opc_bits
) & ALU2op_opc_mask
);
2564 int dst
= ((iw0
>> ALU2op_dst_bits
) & ALU2op_dst_mask
);
2566 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ALU2op
);
2567 TRACE_EXTRACT (cpu
, "%s: opc:%i src:%i dst:%i", __func__
, opc
, src
, dst
);
2569 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2570 illegal_instruction_combination (cpu
);
2574 TRACE_INSN (cpu
, "R%i >>>= R%i;", dst
, src
);
2575 SET_DREG (dst
, ashiftrt (cpu
, DREG (dst
), DREG (src
), 32));
2580 TRACE_INSN (cpu
, "R%i >>= R%i;", dst
, src
);
2581 if (DREG (src
) <= 0x1F)
2582 val
= lshiftrt (cpu
, DREG (dst
), DREG (src
), 32);
2585 SET_DREG (dst
, val
);
2589 TRACE_INSN (cpu
, "R%i <<= R%i;", dst
, src
);
2590 SET_DREG (dst
, lshift (cpu
, DREG (dst
), DREG (src
), 32, 0, 0));
2594 TRACE_INSN (cpu
, "R%i *= R%i;", dst
, src
);
2595 SET_DREG (dst
, DREG (dst
) * DREG (src
));
2600 TRACE_INSN (cpu
, "R%i = (R%i + R%i) << 1;", dst
, dst
, src
);
2601 SET_DREG (dst
, add_and_shift (cpu
, DREG (dst
), DREG (src
), 1));
2605 TRACE_INSN (cpu
, "R%i = (R%i + R%i) << 2;", dst
, dst
, src
);
2606 SET_DREG (dst
, add_and_shift (cpu
, DREG (dst
), DREG (src
), 2));
2610 TRACE_INSN (cpu
, "DIVQ ( R%i, R%i );", dst
, src
);
2611 SET_DREG (dst
, divq (cpu
, DREG (dst
), (bu16
)DREG (src
)));
2615 TRACE_INSN (cpu
, "DIVS ( R%i, R%i );", dst
, src
);
2616 SET_DREG (dst
, divs (cpu
, DREG (dst
), (bu16
)DREG (src
)));
2620 TRACE_INSN (cpu
, "R%i = R%i.L (X);", dst
, src
);
2621 SET_DREG (dst
, (bs32
) (bs16
) DREG (src
));
2622 setflags_logical (cpu
, DREG (dst
));
2626 TRACE_INSN (cpu
, "R%i = R%i.L (Z);", dst
, src
);
2627 SET_DREG (dst
, (bu32
) (bu16
) DREG (src
));
2628 setflags_logical (cpu
, DREG (dst
));
2632 TRACE_INSN (cpu
, "R%i = R%i.B (X);", dst
, src
);
2633 SET_DREG (dst
, (bs32
) (bs8
) DREG (src
));
2634 setflags_logical (cpu
, DREG (dst
));
2638 TRACE_INSN (cpu
, "R%i = R%i.B (Z);", dst
, src
);
2639 SET_DREG (dst
, (bu32
) (bu8
) DREG (src
));
2640 setflags_logical (cpu
, DREG (dst
));
2644 bu32 val
= DREG (src
);
2645 TRACE_INSN (cpu
, "R%i = - R%i;", dst
, src
);
2646 SET_DREG (dst
, -val
);
2647 setflags_nz (cpu
, DREG (dst
));
2648 SET_ASTATREG (v
, val
== 0x80000000);
2650 SET_ASTATREG (vs
, 1);
2651 SET_ASTATREG (ac0
, val
== 0x0);
2652 /* XXX: Documentation isn't entirely clear about av0 and av1. */
2656 TRACE_INSN (cpu
, "R%i = ~ R%i;", dst
, src
);
2657 SET_DREG (dst
, ~DREG (src
));
2658 setflags_logical (cpu
, DREG (dst
));
2661 illegal_instruction (cpu
);
2665 decode_PTR2op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2668 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2669 | 0 | 1 | 0 | 0 | 0 | 1 | 0 |.opc.......|.src.......|.dst.......|
2670 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2671 int src
= ((iw0
>> PTR2op_src_bits
) & PTR2op_dst_mask
);
2672 int opc
= ((iw0
>> PTR2op_opc_bits
) & PTR2op_opc_mask
);
2673 int dst
= ((iw0
>> PTR2op_dst_bits
) & PTR2op_dst_mask
);
2674 const char *src_name
= get_preg_name (src
);
2675 const char *dst_name
= get_preg_name (dst
);
2677 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_PTR2op
);
2678 TRACE_EXTRACT (cpu
, "%s: opc:%i src:%i dst:%i", __func__
, opc
, src
, dst
);
2680 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2681 illegal_instruction_combination (cpu
);
2685 TRACE_INSN (cpu
, "%s -= %s", dst_name
, src_name
);
2686 SET_PREG (dst
, PREG (dst
) - PREG (src
));
2690 TRACE_INSN (cpu
, "%s = %s << 2", dst_name
, src_name
);
2691 SET_PREG (dst
, PREG (src
) << 2);
2695 TRACE_INSN (cpu
, "%s = %s >> 2", dst_name
, src_name
);
2696 SET_PREG (dst
, PREG (src
) >> 2);
2700 TRACE_INSN (cpu
, "%s = %s >> 1", dst_name
, src_name
);
2701 SET_PREG (dst
, PREG (src
) >> 1);
2705 TRACE_INSN (cpu
, "%s += %s (BREV)", dst_name
, src_name
);
2706 SET_PREG (dst
, add_brev (PREG (dst
), PREG (src
)));
2710 TRACE_INSN (cpu
, "%s = (%s + %s) << 1", dst_name
, dst_name
, src_name
);
2711 SET_PREG (dst
, (PREG (dst
) + PREG (src
)) << 1);
2715 TRACE_INSN (cpu
, "%s = (%s + %s) << 2", dst_name
, dst_name
, src_name
);
2716 SET_PREG (dst
, (PREG (dst
) + PREG (src
)) << 2);
2719 illegal_instruction (cpu
);
2723 decode_LOGI2op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2726 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2727 | 0 | 1 | 0 | 0 | 1 |.opc.......|.src...............|.dst.......|
2728 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2729 int src
= ((iw0
>> LOGI2op_src_bits
) & LOGI2op_src_mask
);
2730 int opc
= ((iw0
>> LOGI2op_opc_bits
) & LOGI2op_opc_mask
);
2731 int dst
= ((iw0
>> LOGI2op_dst_bits
) & LOGI2op_dst_mask
);
2732 int uimm
= uimm5 (src
);
2733 const char *uimm_str
= uimm5_str (uimm
);
2735 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LOGI2op
);
2736 TRACE_EXTRACT (cpu
, "%s: opc:%i src:%i dst:%i", __func__
, opc
, src
, dst
);
2737 TRACE_DECODE (cpu
, "%s: uimm5:%#x", __func__
, uimm
);
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
, "CC = BITTST (R%i, %s);", dst
, uimm_str
);
2749 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2750 illegal_instruction_combination (cpu
);
2751 SET_CCREG ((DREG (dst
) >> uimm
) & 1);
2755 TRACE_INSN (cpu
, "BITSET (R%i, %s);", dst
, uimm_str
);
2756 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2757 illegal_instruction_combination (cpu
);
2758 SET_DREG (dst
, DREG (dst
) | (1 << uimm
));
2759 setflags_logical (cpu
, DREG (dst
));
2763 TRACE_INSN (cpu
, "BITTGL (R%i, %s);", dst
, uimm_str
);
2764 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2765 illegal_instruction_combination (cpu
);
2766 SET_DREG (dst
, DREG (dst
) ^ (1 << uimm
));
2767 setflags_logical (cpu
, DREG (dst
));
2771 TRACE_INSN (cpu
, "BITCLR (R%i, %s);", dst
, uimm_str
);
2772 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2773 illegal_instruction_combination (cpu
);
2774 SET_DREG (dst
, DREG (dst
) & ~(1 << uimm
));
2775 setflags_logical (cpu
, DREG (dst
));
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
, ashiftrt (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
, lshiftrt (cpu
, DREG (dst
), uimm
, 32));
2793 TRACE_INSN (cpu
, "R%i <<= %s;", dst
, uimm_str
);
2794 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2795 illegal_instruction_combination (cpu
);
2796 SET_DREG (dst
, lshift (cpu
, DREG (dst
), uimm
, 32, 0, 0));
2801 decode_COMP3op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2804 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2805 | 0 | 1 | 0 | 1 |.opc.......|.dst.......|.src1......|.src0......|
2806 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2807 int opc
= ((iw0
>> COMP3op_opc_bits
) & COMP3op_opc_mask
);
2808 int dst
= ((iw0
>> COMP3op_dst_bits
) & COMP3op_dst_mask
);
2809 int src0
= ((iw0
>> COMP3op_src0_bits
) & COMP3op_src0_mask
);
2810 int src1
= ((iw0
>> COMP3op_src1_bits
) & COMP3op_src1_mask
);
2812 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_COMP3op
);
2813 TRACE_EXTRACT (cpu
, "%s: opc:%i dst:%i src1:%i src0:%i",
2814 __func__
, opc
, dst
, src1
, src0
);
2816 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2817 illegal_instruction_combination (cpu
);
2821 TRACE_INSN (cpu
, "R%i = R%i + R%i;", dst
, src0
, src1
);
2822 SET_DREG (dst
, add32 (cpu
, DREG (src0
), DREG (src1
), 1, 0));
2826 TRACE_INSN (cpu
, "R%i = R%i - R%i;", dst
, src0
, src1
);
2827 SET_DREG (dst
, sub32 (cpu
, DREG (src0
), DREG (src1
), 1, 0, 0));
2831 TRACE_INSN (cpu
, "R%i = R%i & R%i;", dst
, src0
, src1
);
2832 SET_DREG (dst
, DREG (src0
) & DREG (src1
));
2833 setflags_logical (cpu
, DREG (dst
));
2837 TRACE_INSN (cpu
, "R%i = R%i | R%i;", dst
, src0
, src1
);
2838 SET_DREG (dst
, DREG (src0
) | DREG (src1
));
2839 setflags_logical (cpu
, DREG (dst
));
2843 TRACE_INSN (cpu
, "R%i = R%i ^ R%i;", dst
, src0
, src1
);
2844 SET_DREG (dst
, DREG (src0
) ^ DREG (src1
));
2845 setflags_logical (cpu
, DREG (dst
));
2849 int shift
= opc
- 5;
2850 const char *dst_name
= get_preg_name (dst
);
2851 const char *src0_name
= get_preg_name (src0
);
2852 const char *src1_name
= get_preg_name (src1
);
2854 /* If src0 == src1 this is disassembled as a shift by 1, but this
2855 distinction doesn't matter for our purposes. */
2857 TRACE_INSN (cpu
, "%s = (%s + %s) << %#x;",
2858 dst_name
, src0_name
, src1_name
, shift
);
2860 TRACE_INSN (cpu
, "%s = %s + %s",
2861 dst_name
, src0_name
, src1_name
);
2862 SET_PREG (dst
, PREG (src0
) + (PREG (src1
) << shift
));
2867 decode_COMPI2opD_0 (SIM_CPU
*cpu
, bu16 iw0
)
2870 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2871 | 0 | 1 | 1 | 0 | 0 |.op|..src......................|.dst.......|
2872 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2873 int op
= ((iw0
>> COMPI2opD_op_bits
) & COMPI2opD_op_mask
);
2874 int dst
= ((iw0
>> COMPI2opD_dst_bits
) & COMPI2opD_dst_mask
);
2875 int src
= ((iw0
>> COMPI2opD_src_bits
) & COMPI2opD_src_mask
);
2876 int imm
= imm7 (src
);
2878 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_COMPI2opD
);
2879 TRACE_EXTRACT (cpu
, "%s: op:%i src:%i dst:%i", __func__
, op
, src
, dst
);
2880 TRACE_DECODE (cpu
, "%s: imm7:%#x", __func__
, imm
);
2882 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2883 illegal_instruction_combination (cpu
);
2887 TRACE_INSN (cpu
, "R%i = %s (X);", dst
, imm7_str (imm
));
2888 SET_DREG (dst
, imm
);
2892 TRACE_INSN (cpu
, "R%i += %s;", dst
, imm7_str (imm
));
2893 SET_DREG (dst
, add32 (cpu
, DREG (dst
), imm
, 1, 0));
2898 decode_COMPI2opP_0 (SIM_CPU
*cpu
, bu16 iw0
)
2901 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2902 | 0 | 1 | 1 | 0 | 1 |.op|.src.......................|.dst.......|
2903 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2904 int op
= ((iw0
>> COMPI2opP_op_bits
) & COMPI2opP_op_mask
);
2905 int src
= ((iw0
>> COMPI2opP_src_bits
) & COMPI2opP_src_mask
);
2906 int dst
= ((iw0
>> COMPI2opP_dst_bits
) & COMPI2opP_dst_mask
);
2907 int imm
= imm7 (src
);
2908 const char *dst_name
= get_preg_name (dst
);
2910 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_COMPI2opP
);
2911 TRACE_EXTRACT (cpu
, "%s: op:%i src:%i dst:%i", __func__
, op
, src
, dst
);
2912 TRACE_DECODE (cpu
, "%s: imm:%#x", __func__
, imm
);
2914 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2915 illegal_instruction_combination (cpu
);
2919 TRACE_INSN (cpu
, "%s = %s;", dst_name
, imm7_str (imm
));
2920 SET_PREG (dst
, imm
);
2924 TRACE_INSN (cpu
, "%s += %s;", dst_name
, imm7_str (imm
));
2925 SET_PREG (dst
, PREG (dst
) + imm
);
2930 decode_LDSTpmod_0 (SIM_CPU
*cpu
, bu16 iw0
)
2933 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2934 | 1 | 0 | 0 | 0 |.W.|.aop...|.reg.......|.idx.......|.ptr.......|
2935 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2936 int W
= ((iw0
>> LDSTpmod_W_bits
) & LDSTpmod_W_mask
);
2937 int aop
= ((iw0
>> LDSTpmod_aop_bits
) & LDSTpmod_aop_mask
);
2938 int idx
= ((iw0
>> LDSTpmod_idx_bits
) & LDSTpmod_idx_mask
);
2939 int ptr
= ((iw0
>> LDSTpmod_ptr_bits
) & LDSTpmod_ptr_mask
);
2940 int reg
= ((iw0
>> LDSTpmod_reg_bits
) & LDSTpmod_reg_mask
);
2941 const char *ptr_name
= get_preg_name (ptr
);
2942 const char *idx_name
= get_preg_name (idx
);
2945 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTpmod
);
2946 TRACE_EXTRACT (cpu
, "%s: W:%i aop:%i reg:%i idx:%i ptr:%i",
2947 __func__
, W
, aop
, reg
, idx
, ptr
);
2949 if (PARALLEL_GROUP
== BFIN_PARALLEL_GROUP2
)
2950 illegal_instruction_combination (cpu
);
2952 if (aop
== 1 && W
== 0 && idx
== ptr
)
2954 TRACE_INSN (cpu
, "R%i.L = W[%s];", reg
, ptr_name
);
2956 val
= GET_WORD (addr
);
2957 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | val
);
2959 else if (aop
== 2 && W
== 0 && idx
== ptr
)
2961 TRACE_INSN (cpu
, "R%i.H = W[%s];", reg
, ptr_name
);
2963 val
= GET_WORD (addr
);
2964 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (val
<< 16));
2966 else if (aop
== 1 && W
== 1 && idx
== ptr
)
2968 TRACE_INSN (cpu
, "W[%s] = R%i.L;", ptr_name
, reg
);
2970 PUT_WORD (addr
, DREG (reg
));
2972 else if (aop
== 2 && W
== 1 && idx
== ptr
)
2974 TRACE_INSN (cpu
, "W[%s] = R%i.H;", ptr_name
, reg
);
2976 PUT_WORD (addr
, DREG (reg
) >> 16);
2978 else if (aop
== 0 && W
== 0)
2980 TRACE_INSN (cpu
, "R%i = [%s ++ %s];", reg
, ptr_name
, idx_name
);
2982 val
= GET_LONG (addr
);
2983 STORE (DREG (reg
), val
);
2985 STORE (PREG (ptr
), addr
+ PREG (idx
));
2987 else if (aop
== 1 && W
== 0)
2989 TRACE_INSN (cpu
, "R%i.L = W[%s ++ %s];", reg
, ptr_name
, idx_name
);
2991 val
= GET_WORD (addr
);
2992 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | val
);
2994 STORE (PREG (ptr
), addr
+ PREG (idx
));
2996 else if (aop
== 2 && W
== 0)
2998 TRACE_INSN (cpu
, "R%i.H = W[%s ++ %s];", reg
, ptr_name
, idx_name
);
3000 val
= GET_WORD (addr
);
3001 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (val
<< 16));
3003 STORE (PREG (ptr
), addr
+ PREG (idx
));
3005 else if (aop
== 3 && W
== 0)
3007 TRACE_INSN (cpu
, "R%i = W[%s ++ %s] (Z);", reg
, ptr_name
, idx_name
);
3009 val
= GET_WORD (addr
);
3010 STORE (DREG (reg
), val
);
3012 STORE (PREG (ptr
), addr
+ PREG (idx
));
3014 else if (aop
== 3 && W
== 1)
3016 TRACE_INSN (cpu
, "R%i = W[%s ++ %s] (X);", reg
, ptr_name
, idx_name
);
3018 val
= GET_WORD (addr
);
3019 STORE (DREG (reg
), (bs32
) (bs16
) val
);
3021 STORE (PREG (ptr
), addr
+ PREG (idx
));
3023 else if (aop
== 0 && W
== 1)
3025 TRACE_INSN (cpu
, "[%s ++ %s] = R%i;", ptr_name
, idx_name
, reg
);
3027 PUT_LONG (addr
, DREG (reg
));
3029 STORE (PREG (ptr
), addr
+ PREG (idx
));
3031 else if (aop
== 1 && W
== 1)
3033 TRACE_INSN (cpu
, "W[%s ++ %s] = R%i.L;", ptr_name
, idx_name
, reg
);
3035 PUT_WORD (addr
, DREG (reg
));
3037 STORE (PREG (ptr
), addr
+ PREG (idx
));
3039 else if (aop
== 2 && W
== 1)
3041 TRACE_INSN (cpu
, "W[%s ++ %s] = R%i.H;", ptr_name
, idx_name
, reg
);
3043 PUT_WORD (addr
, DREG (reg
) >> 16);
3045 STORE (PREG (ptr
), addr
+ PREG (idx
));
3048 illegal_instruction_or_combination (cpu
);
3052 decode_dagMODim_0 (SIM_CPU
*cpu
, bu16 iw0
)
3055 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3056 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 0 |.br| 1 | 1 |.op|.m.....|.i.....|
3057 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3058 int i
= ((iw0
>> DagMODim_i_bits
) & DagMODim_i_mask
);
3059 int m
= ((iw0
>> DagMODim_m_bits
) & DagMODim_m_mask
);
3060 int br
= ((iw0
>> DagMODim_br_bits
) & DagMODim_br_mask
);
3061 int op
= ((iw0
>> DagMODim_op_bits
) & DagMODim_op_mask
);
3063 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dagMODim
);
3064 TRACE_EXTRACT (cpu
, "%s: br:%i op:%i m:%i i:%i", __func__
, br
, op
, m
, i
);
3066 if (PARALLEL_GROUP
== BFIN_PARALLEL_GROUP2
)
3067 illegal_instruction_combination (cpu
);
3069 if (op
== 0 && br
== 1)
3071 TRACE_INSN (cpu
, "I%i += M%i (BREV);", i
, m
);
3072 SET_IREG (i
, add_brev (IREG (i
), MREG (m
)));
3076 TRACE_INSN (cpu
, "I%i += M%i;", i
, m
);
3077 dagadd (cpu
, i
, MREG (m
));
3079 else if (op
== 1 && br
== 0)
3081 TRACE_INSN (cpu
, "I%i -= M%i;", i
, m
);
3082 dagsub (cpu
, i
, MREG (m
));
3085 illegal_instruction_or_combination (cpu
);
3089 decode_dagMODik_0 (SIM_CPU
*cpu
, bu16 iw0
)
3092 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3093 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 0 |.op....|.i.....|
3094 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3095 int i
= ((iw0
>> DagMODik_i_bits
) & DagMODik_i_mask
);
3096 int op
= ((iw0
>> DagMODik_op_bits
) & DagMODik_op_mask
);
3098 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dagMODik
);
3099 TRACE_EXTRACT (cpu
, "%s: op:%i i:%i", __func__
, op
, i
);
3101 if (PARALLEL_GROUP
== BFIN_PARALLEL_GROUP2
)
3102 illegal_instruction_combination (cpu
);
3106 TRACE_INSN (cpu
, "I%i += 2;", i
);
3111 TRACE_INSN (cpu
, "I%i -= 2;", i
);
3116 TRACE_INSN (cpu
, "I%i += 4;", i
);
3121 TRACE_INSN (cpu
, "I%i -= 4;", i
);
3125 illegal_instruction_or_combination (cpu
);
3129 decode_dspLDST_0 (SIM_CPU
*cpu
, bu16 iw0
)
3132 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3133 | 1 | 0 | 0 | 1 | 1 | 1 |.W.|.aop...|.m.....|.i.....|.reg.......|
3134 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3135 int i
= ((iw0
>> DspLDST_i_bits
) & DspLDST_i_mask
);
3136 int m
= ((iw0
>> DspLDST_m_bits
) & DspLDST_m_mask
);
3137 int W
= ((iw0
>> DspLDST_W_bits
) & DspLDST_W_mask
);
3138 int aop
= ((iw0
>> DspLDST_aop_bits
) & DspLDST_aop_mask
);
3139 int reg
= ((iw0
>> DspLDST_reg_bits
) & DspLDST_reg_mask
);
3142 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dspLDST
);
3143 TRACE_EXTRACT (cpu
, "%s: aop:%i m:%i i:%i reg:%i", __func__
, aop
, m
, i
, reg
);
3145 if (aop
== 0 && W
== 0 && m
== 0)
3147 TRACE_INSN (cpu
, "R%i = [I%i++];", reg
, i
);
3149 if (DIS_ALGN_EXPT
& 0x1)
3152 STORE (DREG (reg
), GET_LONG (addr
));
3154 else if (aop
== 0 && W
== 0 && m
== 1)
3156 TRACE_INSN (cpu
, "R%i.L = W[I%i++];", reg
, i
);
3159 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | GET_WORD (addr
));
3161 else if (aop
== 0 && W
== 0 && m
== 2)
3163 TRACE_INSN (cpu
, "R%i.H = W[I%i++];", reg
, i
);
3166 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (GET_WORD (addr
) << 16));
3168 else if (aop
== 1 && W
== 0 && m
== 0)
3170 TRACE_INSN (cpu
, "R%i = [I%i--];", reg
, i
);
3172 if (DIS_ALGN_EXPT
& 0x1)
3175 STORE (DREG (reg
), GET_LONG (addr
));
3177 else if (aop
== 1 && W
== 0 && m
== 1)
3179 TRACE_INSN (cpu
, "R%i.L = W[I%i--];", reg
, i
);
3182 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | GET_WORD (addr
));
3184 else if (aop
== 1 && W
== 0 && m
== 2)
3186 TRACE_INSN (cpu
, "R%i.H = W[I%i--];", reg
, i
);
3189 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (GET_WORD (addr
) << 16));
3191 else if (aop
== 2 && W
== 0 && m
== 0)
3193 TRACE_INSN (cpu
, "R%i = [I%i];", reg
, i
);
3195 if (DIS_ALGN_EXPT
& 0x1)
3197 STORE (DREG (reg
), GET_LONG (addr
));
3199 else if (aop
== 2 && W
== 0 && m
== 1)
3201 TRACE_INSN (cpu
, "R%i.L = W[I%i];", reg
, i
);
3203 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | GET_WORD (addr
));
3205 else if (aop
== 2 && W
== 0 && m
== 2)
3207 TRACE_INSN (cpu
, "R%i.H = W[I%i];", reg
, i
);
3209 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (GET_WORD (addr
) << 16));
3211 else if (aop
== 0 && W
== 1 && m
== 0)
3213 TRACE_INSN (cpu
, "[I%i++] = R%i;", i
, reg
);
3216 PUT_LONG (addr
, DREG (reg
));
3218 else if (aop
== 0 && W
== 1 && m
== 1)
3220 TRACE_INSN (cpu
, "W[I%i++] = R%i.L;", i
, reg
);
3223 PUT_WORD (addr
, DREG (reg
));
3225 else if (aop
== 0 && W
== 1 && m
== 2)
3227 TRACE_INSN (cpu
, "W[I%i++] = R%i.H;", i
, reg
);
3230 PUT_WORD (addr
, DREG (reg
) >> 16);
3232 else if (aop
== 1 && W
== 1 && m
== 0)
3234 TRACE_INSN (cpu
, "[I%i--] = R%i;", i
, reg
);
3237 PUT_LONG (addr
, DREG (reg
));
3239 else if (aop
== 1 && W
== 1 && m
== 1)
3241 TRACE_INSN (cpu
, "W[I%i--] = R%i.L;", i
, reg
);
3244 PUT_WORD (addr
, DREG (reg
));
3246 else if (aop
== 1 && W
== 1 && m
== 2)
3248 TRACE_INSN (cpu
, "W[I%i--] = R%i.H;", i
, reg
);
3251 PUT_WORD (addr
, DREG (reg
) >> 16);
3253 else if (aop
== 2 && W
== 1 && m
== 0)
3255 TRACE_INSN (cpu
, "[I%i] = R%i;", i
, reg
);
3257 PUT_LONG (addr
, DREG (reg
));
3259 else if (aop
== 2 && W
== 1 && m
== 1)
3261 TRACE_INSN (cpu
, "W[I%i] = R%i.L;", i
, reg
);
3263 PUT_WORD (addr
, DREG (reg
));
3265 else if (aop
== 2 && W
== 1 && m
== 2)
3267 TRACE_INSN (cpu
, "W[I%i] = R%i.H;", i
, reg
);
3269 PUT_WORD (addr
, DREG (reg
) >> 16);
3271 else if (aop
== 3 && W
== 0)
3273 TRACE_INSN (cpu
, "R%i = [I%i ++ M%i];", reg
, i
, m
);
3275 if (DIS_ALGN_EXPT
& 0x1)
3277 dagadd (cpu
, i
, MREG (m
));
3278 STORE (DREG (reg
), GET_LONG (addr
));
3280 else if (aop
== 3 && W
== 1)
3282 TRACE_INSN (cpu
, "[I%i ++ M%i] = R%i;", i
, m
, reg
);
3284 dagadd (cpu
, i
, MREG (m
));
3285 PUT_LONG (addr
, DREG (reg
));
3288 illegal_instruction_or_combination (cpu
);
3292 decode_LDST_0 (SIM_CPU
*cpu
, bu16 iw0
)
3295 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3296 | 1 | 0 | 0 | 1 |.sz....|.W.|.aop...|.Z.|.ptr.......|.reg.......|
3297 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3298 int Z
= ((iw0
>> LDST_Z_bits
) & LDST_Z_mask
);
3299 int W
= ((iw0
>> LDST_W_bits
) & LDST_W_mask
);
3300 int sz
= ((iw0
>> LDST_sz_bits
) & LDST_sz_mask
);
3301 int aop
= ((iw0
>> LDST_aop_bits
) & LDST_aop_mask
);
3302 int reg
= ((iw0
>> LDST_reg_bits
) & LDST_reg_mask
);
3303 int ptr
= ((iw0
>> LDST_ptr_bits
) & LDST_ptr_mask
);
3304 const char * const posts
[] = { "++", "--", "", "<INV>" };
3305 const char *post
= posts
[aop
];
3306 const char *ptr_name
= get_preg_name (ptr
);
3308 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDST
);
3309 TRACE_EXTRACT (cpu
, "%s: sz:%i W:%i aop:%i Z:%i ptr:%i reg:%i",
3310 __func__
, sz
, W
, aop
, Z
, ptr
, reg
);
3312 if (aop
== 3 || PARALLEL_GROUP
== BFIN_PARALLEL_GROUP2
)
3313 illegal_instruction_or_combination (cpu
);
3317 if (sz
== 0 && Z
== 0)
3319 TRACE_INSN (cpu
, "R%i = [%s%s];", reg
, ptr_name
, post
);
3320 SET_DREG (reg
, GET_LONG (PREG (ptr
)));
3322 else if (sz
== 0 && Z
== 1)
3324 TRACE_INSN (cpu
, "%s = [%s%s];", get_preg_name (reg
), ptr_name
, post
);
3325 if (aop
< 2 && ptr
== reg
)
3326 illegal_instruction_combination (cpu
);
3327 SET_PREG (reg
, GET_LONG (PREG (ptr
)));
3329 else if (sz
== 1 && Z
== 0)
3331 TRACE_INSN (cpu
, "R%i = W[%s%s] (Z);", reg
, ptr_name
, post
);
3332 SET_DREG (reg
, GET_WORD (PREG (ptr
)));
3334 else if (sz
== 1 && Z
== 1)
3336 TRACE_INSN (cpu
, "R%i = W[%s%s] (X);", reg
, ptr_name
, post
);
3337 SET_DREG (reg
, (bs32
) (bs16
) GET_WORD (PREG (ptr
)));
3339 else if (sz
== 2 && Z
== 0)
3341 TRACE_INSN (cpu
, "R%i = B[%s%s] (Z);", reg
, ptr_name
, post
);
3342 SET_DREG (reg
, GET_BYTE (PREG (ptr
)));
3344 else if (sz
== 2 && Z
== 1)
3346 TRACE_INSN (cpu
, "R%i = B[%s%s] (X);", reg
, ptr_name
, post
);
3347 SET_DREG (reg
, (bs32
) (bs8
) GET_BYTE (PREG (ptr
)));
3350 illegal_instruction_or_combination (cpu
);
3354 if (sz
== 0 && Z
== 0)
3356 TRACE_INSN (cpu
, "[%s%s] = R%i;", ptr_name
, post
, reg
);
3357 PUT_LONG (PREG (ptr
), DREG (reg
));
3359 else if (sz
== 0 && Z
== 1)
3361 TRACE_INSN (cpu
, "[%s%s] = %s;", ptr_name
, post
, get_preg_name (reg
));
3362 PUT_LONG (PREG (ptr
), PREG (reg
));
3364 else if (sz
== 1 && Z
== 0)
3366 TRACE_INSN (cpu
, "W[%s%s] = R%i;", ptr_name
, post
, reg
);
3367 PUT_WORD (PREG (ptr
), DREG (reg
));
3369 else if (sz
== 2 && Z
== 0)
3371 TRACE_INSN (cpu
, "B[%s%s] = R%i;", ptr_name
, post
, reg
);
3372 PUT_BYTE (PREG (ptr
), DREG (reg
));
3375 illegal_instruction_or_combination (cpu
);
3379 SET_PREG (ptr
, PREG (ptr
) + (1 << (2 - sz
)));
3381 SET_PREG (ptr
, PREG (ptr
) - (1 << (2 - sz
)));
3385 decode_LDSTiiFP_0 (SIM_CPU
*cpu
, bu16 iw0
)
3388 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3389 | 1 | 0 | 1 | 1 | 1 | 0 |.W.|.offset............|.reg...........|
3390 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3391 /* This isn't exactly a grp:reg as this insn only supports Dregs & Pregs,
3392 but for our usage, its functionality the same thing. */
3393 int grp
= ((iw0
>> 3) & 0x1);
3394 int reg
= ((iw0
>> LDSTiiFP_reg_bits
) & 0x7 /*LDSTiiFP_reg_mask*/);
3395 int offset
= ((iw0
>> LDSTiiFP_offset_bits
) & LDSTiiFP_offset_mask
);
3396 int W
= ((iw0
>> LDSTiiFP_W_bits
) & LDSTiiFP_W_mask
);
3397 bu32 imm
= negimm5s4 (offset
);
3398 bu32 ea
= FPREG
+ imm
;
3399 const char *imm_str
= negimm5s4_str (offset
);
3400 const char *reg_name
= get_allreg_name (grp
, reg
);
3402 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTiiFP
);
3403 TRACE_EXTRACT (cpu
, "%s: W:%i offset:%#x grp:%i reg:%i", __func__
,
3404 W
, offset
, grp
, reg
);
3405 TRACE_DECODE (cpu
, "%s: negimm5s4:%#x", __func__
, imm
);
3407 if (PARALLEL_GROUP
== BFIN_PARALLEL_GROUP2
)
3408 illegal_instruction_or_combination (cpu
);
3412 TRACE_INSN (cpu
, "%s = [FP + %s];", reg_name
, imm_str
);
3413 reg_write (cpu
, grp
, reg
, GET_LONG (ea
));
3417 TRACE_INSN (cpu
, "[FP + %s] = %s;", imm_str
, reg_name
);
3418 PUT_LONG (ea
, reg_read (cpu
, grp
, reg
));
3423 decode_LDSTii_0 (SIM_CPU
*cpu
, bu16 iw0
)
3426 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3427 | 1 | 0 | 1 |.W.|.op....|.offset........|.ptr.......|.reg.......|
3428 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3429 int reg
= ((iw0
>> LDSTii_reg_bit
) & LDSTii_reg_mask
);
3430 int ptr
= ((iw0
>> LDSTii_ptr_bit
) & LDSTii_ptr_mask
);
3431 int offset
= ((iw0
>> LDSTii_offset_bit
) & LDSTii_offset_mask
);
3432 int op
= ((iw0
>> LDSTii_op_bit
) & LDSTii_op_mask
);
3433 int W
= ((iw0
>> LDSTii_W_bit
) & LDSTii_W_mask
);
3435 const char *imm_str
;
3436 const char *ptr_name
= get_preg_name (ptr
);
3438 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTii
);
3439 TRACE_EXTRACT (cpu
, "%s: W:%i op:%i offset:%#x ptr:%i reg:%i",
3440 __func__
, W
, op
, offset
, ptr
, reg
);
3442 if (op
== 0 || op
== 3)
3443 imm
= uimm4s4 (offset
), imm_str
= uimm4s4_str (offset
);
3445 imm
= uimm4s2 (offset
), imm_str
= uimm4s2_str (offset
);
3446 ea
= PREG (ptr
) + imm
;
3448 TRACE_DECODE (cpu
, "%s: uimm4s4/uimm4s2:%#x", __func__
, imm
);
3450 if (PARALLEL_GROUP
== BFIN_PARALLEL_GROUP2
)
3451 illegal_instruction_combination (cpu
);
3453 if (W
== 1 && op
== 2)
3454 illegal_instruction (cpu
);
3460 TRACE_INSN (cpu
, "R%i = [%s + %s];", reg
, ptr_name
, imm_str
);
3461 SET_DREG (reg
, GET_LONG (ea
));
3465 TRACE_INSN (cpu
, "R%i = W[%s + %s] (Z);", reg
, ptr_name
, imm_str
);
3466 SET_DREG (reg
, GET_WORD (ea
));
3470 TRACE_INSN (cpu
, "R%i = W[%s + %s] (X);", reg
, ptr_name
, imm_str
);
3471 SET_DREG (reg
, (bs32
) (bs16
) GET_WORD (ea
));
3475 TRACE_INSN (cpu
, "%s = [%s + %s];",
3476 get_preg_name (reg
), ptr_name
, imm_str
);
3477 SET_PREG (reg
, GET_LONG (ea
));
3484 TRACE_INSN (cpu
, "[%s + %s] = R%i;", ptr_name
, imm_str
, reg
);
3485 PUT_LONG (ea
, DREG (reg
));
3489 TRACE_INSN (cpu
, "W[%s + %s] = R%i;", ptr_name
, imm_str
, reg
);
3490 PUT_WORD (ea
, DREG (reg
));
3494 TRACE_INSN (cpu
, "[%s + %s] = %s;",
3495 ptr_name
, imm_str
, get_preg_name (reg
));
3496 PUT_LONG (ea
, PREG (reg
));
3502 decode_LoopSetup_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
, bu32 pc
)
3505 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3506 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |.rop...|.c.|.soffset.......|
3507 |.reg...........| - | - |.eoffset...............................|
3508 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3509 int c
= ((iw0
>> (LoopSetup_c_bits
- 16)) & LoopSetup_c_mask
);
3510 int reg
= ((iw1
>> LoopSetup_reg_bits
) & LoopSetup_reg_mask
);
3511 int rop
= ((iw0
>> (LoopSetup_rop_bits
- 16)) & LoopSetup_rop_mask
);
3512 int soffset
= ((iw0
>> (LoopSetup_soffset_bits
- 16)) & LoopSetup_soffset_mask
);
3513 int eoffset
= ((iw1
>> LoopSetup_eoffset_bits
) & LoopSetup_eoffset_mask
);
3514 int spcrel
= pcrel4 (soffset
);
3515 int epcrel
= lppcrel10 (eoffset
);
3517 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LoopSetup
);
3518 TRACE_EXTRACT (cpu
, "%s: rop:%i c:%i soffset:%i reg:%i eoffset:%i",
3519 __func__
, rop
, c
, soffset
, reg
, eoffset
);
3520 TRACE_DECODE (cpu
, "%s: s_pcrel4:%#x e_lppcrel10:%#x",
3521 __func__
, spcrel
, epcrel
);
3524 illegal_instruction (cpu
);
3526 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
3527 illegal_instruction_combination (cpu
);
3531 TRACE_INSN (cpu
, "LSETUP (%#x, %#x) LC%i;", spcrel
, epcrel
, c
);
3533 else if (rop
== 1 && reg
<= 7)
3535 TRACE_INSN (cpu
, "LSETUP (%#x, %#x) LC%i = %s;",
3536 spcrel
, epcrel
, c
, get_preg_name (reg
));
3537 SET_LCREG (c
, PREG (reg
));
3539 else if (rop
== 3 && reg
<= 7)
3541 TRACE_INSN (cpu
, "LSETUP (%#x, %#x) LC%i = %s >> 1;",
3542 spcrel
, epcrel
, c
, get_preg_name (reg
));
3543 SET_LCREG (c
, PREG (reg
) >> 1);
3546 illegal_instruction (cpu
);
3548 SET_LTREG (c
, pc
+ spcrel
);
3549 SET_LBREG (c
, pc
+ epcrel
);
3553 decode_LDIMMhalf_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3556 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3557 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 |.Z.|.H.|.S.|.grp...|.reg.......|
3558 |.hword.........................................................|
3559 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3560 int H
= ((iw0
>> (LDIMMhalf_H_bits
- 16)) & LDIMMhalf_H_mask
);
3561 int Z
= ((iw0
>> (LDIMMhalf_Z_bits
- 16)) & LDIMMhalf_Z_mask
);
3562 int S
= ((iw0
>> (LDIMMhalf_S_bits
- 16)) & LDIMMhalf_S_mask
);
3563 int reg
= ((iw0
>> (LDIMMhalf_reg_bits
- 16)) & LDIMMhalf_reg_mask
);
3564 int grp
= ((iw0
>> (LDIMMhalf_grp_bits
- 16)) & LDIMMhalf_grp_mask
);
3565 int hword
= ((iw1
>> LDIMMhalf_hword_bits
) & LDIMMhalf_hword_mask
);
3567 const char *val_str
;
3568 const char *reg_name
= get_allreg_name (grp
, reg
);
3570 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDIMMhalf
);
3571 TRACE_EXTRACT (cpu
, "%s: Z:%i H:%i S:%i grp:%i reg:%i hword:%#x",
3572 __func__
, Z
, H
, S
, grp
, reg
, hword
);
3574 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
3575 illegal_instruction_combination (cpu
);
3578 val
= imm16 (hword
), val_str
= imm16_str (hword
);
3580 val
= luimm16 (hword
), val_str
= luimm16_str (hword
);
3582 if (H
== 0 && S
== 1 && Z
== 0)
3584 TRACE_INSN (cpu
, "%s = %s (X);", reg_name
, val_str
);
3586 else if (H
== 0 && S
== 0 && Z
== 1)
3588 TRACE_INSN (cpu
, "%s = %s (Z);", reg_name
, val_str
);
3590 else if (H
== 0 && S
== 0 && Z
== 0)
3592 TRACE_INSN (cpu
, "%s.L = %s;", reg_name
, val_str
);
3593 val
= REG_H_L (reg_read (cpu
, grp
, reg
), val
);
3595 else if (H
== 1 && S
== 0 && Z
== 0)
3597 TRACE_INSN (cpu
, "%s.H = %s;", reg_name
, val_str
);
3598 val
= REG_H_L (val
<< 16, reg_read (cpu
, grp
, reg
));
3601 illegal_instruction (cpu
);
3603 reg_write (cpu
, grp
, reg
, val
);
3607 decode_CALLa_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
, bu32 pc
)
3610 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3611 | 1 | 1 | 1 | 0 | 0 | 0 | 1 |.S.|.msw...........................|
3612 |.lsw...........................................................|
3613 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3614 int S
= ((iw0
>> (CALLa_S_bits
- 16)) & CALLa_S_mask
);
3615 int lsw
= ((iw1
>> 0) & 0xffff);
3616 int msw
= ((iw0
>> 0) & 0xff);
3617 int pcrel
= pcrel24 ((msw
<< 16) | lsw
);
3618 bu32 newpc
= pc
+ pcrel
;
3620 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CALLa
);
3621 TRACE_EXTRACT (cpu
, "%s: S:%i msw:%#x lsw:%#x", __func__
, S
, msw
, lsw
);
3622 TRACE_DECODE (cpu
, "%s: pcrel24:%#x", __func__
, pcrel
);
3624 TRACE_INSN (cpu
, "%s %#x;", S
? "CALL" : "JUMP.L", pcrel
);
3626 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
3627 illegal_instruction_combination (cpu
);
3631 BFIN_TRACE_BRANCH (cpu
, pc
, newpc
, -1, "CALL");
3632 SET_RETSREG (hwloop_get_next_pc (cpu
, pc
, 4));
3635 BFIN_TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP.L");
3638 BFIN_CPU_STATE
.did_jump
= true;
3639 PROFILE_BRANCH_TAKEN (cpu
);
3644 decode_LDSTidxI_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3647 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3648 | 1 | 1 | 1 | 0 | 0 | 1 |.W.|.Z.|.sz....|.ptr.......|.reg.......|
3649 |.offset........................................................|
3650 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3651 int Z
= ((iw0
>> (LDSTidxI_Z_bits
- 16)) & LDSTidxI_Z_mask
);
3652 int W
= ((iw0
>> (LDSTidxI_W_bits
- 16)) & LDSTidxI_W_mask
);
3653 int sz
= ((iw0
>> (LDSTidxI_sz_bits
- 16)) & LDSTidxI_sz_mask
);
3654 int reg
= ((iw0
>> (LDSTidxI_reg_bits
- 16)) & LDSTidxI_reg_mask
);
3655 int ptr
= ((iw0
>> (LDSTidxI_ptr_bits
- 16)) & LDSTidxI_ptr_mask
);
3656 int offset
= ((iw1
>> LDSTidxI_offset_bits
) & LDSTidxI_offset_mask
);
3657 const char *ptr_name
= get_preg_name (ptr
);
3658 bu32 imm_16s4
= imm16s4 (offset
);
3659 bu32 imm_16s2
= imm16s2 (offset
);
3660 bu32 imm_16
= imm16 (offset
);
3662 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTidxI
);
3663 TRACE_EXTRACT (cpu
, "%s: W:%i Z:%i sz:%i ptr:%i reg:%i offset:%#x",
3664 __func__
, W
, Z
, sz
, ptr
, reg
, offset
);
3667 illegal_instruction (cpu
);
3671 if (sz
== 0 && Z
== 0)
3673 TRACE_INSN (cpu
, "R%i = [%s + %s];",
3674 reg
, ptr_name
, imm16s4_str (offset
));
3675 SET_DREG (reg
, GET_LONG (PREG (ptr
) + imm_16s4
));
3677 else if (sz
== 0 && Z
== 1)
3679 TRACE_INSN (cpu
, "%s = [%s + %s];",
3680 get_preg_name (reg
), ptr_name
, imm16s4_str (offset
));
3681 SET_PREG (reg
, GET_LONG (PREG (ptr
) + imm_16s4
));
3683 else if (sz
== 1 && Z
== 0)
3685 TRACE_INSN (cpu
, "R%i = W[%s + %s] (Z);",
3686 reg
, ptr_name
, imm16s2_str (offset
));
3687 SET_DREG (reg
, GET_WORD (PREG (ptr
) + imm_16s2
));
3689 else if (sz
== 1 && Z
== 1)
3691 TRACE_INSN (cpu
, "R%i = W[%s + %s] (X);",
3692 reg
, ptr_name
, imm16s2_str (offset
));
3693 SET_DREG (reg
, (bs32
) (bs16
) GET_WORD (PREG (ptr
) + imm_16s2
));
3695 else if (sz
== 2 && Z
== 0)
3697 TRACE_INSN (cpu
, "R%i = B[%s + %s] (Z);",
3698 reg
, ptr_name
, imm16_str (offset
));
3699 SET_DREG (reg
, GET_BYTE (PREG (ptr
) + imm_16
));
3701 else if (sz
== 2 && Z
== 1)
3703 TRACE_INSN (cpu
, "R%i = B[%s + %s] (X);",
3704 reg
, ptr_name
, imm16_str (offset
));
3705 SET_DREG (reg
, (bs32
) (bs8
) GET_BYTE (PREG (ptr
) + imm_16
));
3710 if (sz
!= 0 && Z
!= 0)
3711 illegal_instruction (cpu
);
3713 if (sz
== 0 && Z
== 0)
3715 TRACE_INSN (cpu
, "[%s + %s] = R%i;", ptr_name
,
3716 imm16s4_str (offset
), reg
);
3717 PUT_LONG (PREG (ptr
) + imm_16s4
, DREG (reg
));
3719 else if (sz
== 0 && Z
== 1)
3721 TRACE_INSN (cpu
, "[%s + %s] = %s;",
3722 ptr_name
, imm16s4_str (offset
), get_preg_name (reg
));
3723 PUT_LONG (PREG (ptr
) + imm_16s4
, PREG (reg
));
3725 else if (sz
== 1 && Z
== 0)
3727 TRACE_INSN (cpu
, "W[%s + %s] = R%i;",
3728 ptr_name
, imm16s2_str (offset
), reg
);
3729 PUT_WORD (PREG (ptr
) + imm_16s2
, DREG (reg
));
3731 else if (sz
== 2 && Z
== 0)
3733 TRACE_INSN (cpu
, "B[%s + %s] = R%i;",
3734 ptr_name
, imm16_str (offset
), reg
);
3735 PUT_BYTE (PREG (ptr
) + imm_16
, DREG (reg
));
3741 decode_linkage_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3744 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3745 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |.R.|
3746 |.framesize.....................................................|
3747 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3748 int R
= ((iw0
>> (Linkage_R_bits
- 16)) & Linkage_R_mask
);
3749 int framesize
= ((iw1
>> Linkage_framesize_bits
) & Linkage_framesize_mask
);
3752 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_linkage
);
3753 TRACE_EXTRACT (cpu
, "%s: R:%i framesize:%#x", __func__
, R
, framesize
);
3757 int size
= uimm16s4 (framesize
);
3759 TRACE_INSN (cpu
, "LINK %s;", uimm16s4_str (framesize
));
3760 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
3761 illegal_instruction_combination (cpu
);
3763 PUT_LONG (sp
, RETSREG
);
3765 PUT_LONG (sp
, FPREG
);
3772 /* Restore SP from FP. */
3774 TRACE_INSN (cpu
, "UNLINK;");
3775 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
3776 illegal_instruction_combination (cpu
);
3777 SET_FPREG (GET_LONG (sp
));
3779 SET_RETSREG (GET_LONG (sp
));
3788 decode_dsp32mac_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3791 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3792 | 1 | 1 | 0 | 0 |.M.| 0 | 0 |.mmod..........|.MM|.P.|.w1|.op1...|
3793 |.h01|.h11|.w0|.op0...|.h00|.h10|.dst.......|.src0......|.src1..|
3794 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3795 int op1
= ((iw0
>> (DSP32Mac_op1_bits
- 16)) & DSP32Mac_op1_mask
);
3796 int w1
= ((iw0
>> (DSP32Mac_w1_bits
- 16)) & DSP32Mac_w1_mask
);
3797 int P
= ((iw0
>> (DSP32Mac_p_bits
- 16)) & DSP32Mac_p_mask
);
3798 int MM
= ((iw0
>> (DSP32Mac_MM_bits
- 16)) & DSP32Mac_MM_mask
);
3799 int mmod
= ((iw0
>> (DSP32Mac_mmod_bits
- 16)) & DSP32Mac_mmod_mask
);
3800 int M
= ((iw0
>> (DSP32Mac_M_bits
- 16)) & DSP32Mac_M_mask
);
3801 int w0
= ((iw1
>> DSP32Mac_w0_bits
) & DSP32Mac_w0_mask
);
3802 int src0
= ((iw1
>> DSP32Mac_src0_bits
) & DSP32Mac_src0_mask
);
3803 int src1
= ((iw1
>> DSP32Mac_src1_bits
) & DSP32Mac_src1_mask
);
3804 int dst
= ((iw1
>> DSP32Mac_dst_bits
) & DSP32Mac_dst_mask
);
3805 int h10
= ((iw1
>> DSP32Mac_h10_bits
) & DSP32Mac_h10_mask
);
3806 int h00
= ((iw1
>> DSP32Mac_h00_bits
) & DSP32Mac_h00_mask
);
3807 int op0
= ((iw1
>> DSP32Mac_op0_bits
) & DSP32Mac_op0_mask
);
3808 int h11
= ((iw1
>> DSP32Mac_h11_bits
) & DSP32Mac_h11_mask
);
3809 int h01
= ((iw1
>> DSP32Mac_h01_bits
) & DSP32Mac_h01_mask
);
3811 bu32 res
= DREG (dst
);
3812 bu32 v_0
= 0, v_1
= 0, zero
= 0, n_1
= 0, n_0
= 0;
3814 static const char * const ops
[] = { "=", "+=", "-=" };
3815 char _buf
[128], *buf
= _buf
;
3818 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32mac
);
3819 TRACE_EXTRACT (cpu
, "%s: M:%i mmod:%i MM:%i P:%i w1:%i op1:%i h01:%i h11:%i "
3820 "w0:%i op0:%i h00:%i h10:%i dst:%i src0:%i src1:%i",
3821 __func__
, M
, mmod
, MM
, P
, w1
, op1
, h01
, h11
, w0
, op0
, h00
, h10
,
3824 if (w0
== 0 && w1
== 0 && op1
== 3 && op0
== 3)
3825 illegal_instruction (cpu
);
3827 if ((w1
|| w0
) && mmod
== M_W32
)
3828 illegal_instruction (cpu
);
3830 if (((1 << mmod
) & (P
? 0x131b : 0x1b5f)) == 0)
3831 illegal_instruction (cpu
);
3833 /* First handle MAC1 side. */
3834 if (w1
== 1 || op1
!= 3)
3836 bu32 res1
= decode_macfunc (cpu
, 1, op1
, h01
, h11
, src0
,
3837 src1
, mmod
, MM
, P
, &v_1
, &n_1
);
3840 buf
+= sprintf (buf
, P
? "R%i" : "R%i.H", dst
+ P
);
3844 buf
+= sprintf (buf
, " = A1");
3845 zero
= !!(res1
== 0);
3850 buf
+= sprintf (buf
, " = (");
3851 buf
+= sprintf (buf
, "A1 %s R%i.%c * R%i.%c", ops
[op1
],
3852 src0
, h01
? 'H' : 'L',
3853 src1
, h11
? 'H' : 'L');
3855 buf
+= sprintf (buf
, ")");
3861 STORE (DREG (dst
+ 1), res1
);
3864 if (res1
& 0xffff0000)
3865 illegal_instruction (cpu
);
3866 res
= REG_H_L (res1
<< 16, res
);
3872 if (w0
== 1 || op0
!= 3)
3875 buf
+= sprintf (buf
, " (M)");
3877 buf
+= sprintf (buf
, ", ");
3881 /* Then handle MAC0 side. */
3882 if (w0
== 1 || op0
!= 3)
3884 bu32 res0
= decode_macfunc (cpu
, 0, op0
, h00
, h10
, src0
,
3885 src1
, mmod
, 0, P
, &v_0
, &n_0
);
3888 buf
+= sprintf (buf
, P
? "R%i" : "R%i.L", dst
);
3892 buf
+= sprintf (buf
, " = A0");
3893 zero
|= !!(res0
== 0);
3898 buf
+= sprintf (buf
, " = (");
3899 buf
+= sprintf (buf
, "A0 %s R%i.%c * R%i.%c", ops
[op0
],
3900 src0
, h00
? 'H' : 'L',
3901 src1
, h10
? 'H' : 'L');
3903 buf
+= sprintf (buf
, ")");
3909 STORE (DREG (dst
), res0
);
3912 if (res0
& 0xffff0000)
3913 illegal_instruction (cpu
);
3914 res
= REG_H_L (res
, res0
);
3921 TRACE_INSN (cpu
, "%s%s;", _buf
, mac_optmode (mmod
, _MM
));
3923 if (!P
&& (w0
|| w1
))
3925 STORE (DREG (dst
), res
);
3926 SET_ASTATREG (v
, v_0
| v_1
);
3928 SET_ASTATREG (vs
, 1);
3932 SET_ASTATREG (v
, v_0
| v_1
);
3934 SET_ASTATREG (vs
, 1);
3937 if ((w0
== 1 && op0
== 3) || (w1
== 1 && op1
== 3))
3939 SET_ASTATREG (az
, zero
);
3940 if (!(w0
== 1 && op0
== 3))
3942 if (!(w1
== 1 && op1
== 3))
3944 SET_ASTATREG (an
, n_1
| n_0
);
3949 decode_dsp32mult_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3952 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3953 | 1 | 1 | 0 | 0 |.M.| 0 | 1 |.mmod..........|.MM|.P.|.w1|.op1...|
3954 |.h01|.h11|.w0|.op0...|.h00|.h10|.dst.......|.src0......|.src1..|
3955 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3956 int op1
= ((iw0
>> (DSP32Mac_op1_bits
- 16)) & DSP32Mac_op1_mask
);
3957 int w1
= ((iw0
>> (DSP32Mac_w1_bits
- 16)) & DSP32Mac_w1_mask
);
3958 int P
= ((iw0
>> (DSP32Mac_p_bits
- 16)) & DSP32Mac_p_mask
);
3959 int MM
= ((iw0
>> (DSP32Mac_MM_bits
- 16)) & DSP32Mac_MM_mask
);
3960 int mmod
= ((iw0
>> (DSP32Mac_mmod_bits
- 16)) & DSP32Mac_mmod_mask
);
3961 int M
= ((iw0
>> (DSP32Mac_M_bits
- 16)) & DSP32Mac_M_mask
);
3962 int w0
= ((iw1
>> DSP32Mac_w0_bits
) & DSP32Mac_w0_mask
);
3963 int src0
= ((iw1
>> DSP32Mac_src0_bits
) & DSP32Mac_src0_mask
);
3964 int src1
= ((iw1
>> DSP32Mac_src1_bits
) & DSP32Mac_src1_mask
);
3965 int dst
= ((iw1
>> DSP32Mac_dst_bits
) & DSP32Mac_dst_mask
);
3966 int h10
= ((iw1
>> DSP32Mac_h10_bits
) & DSP32Mac_h10_mask
);
3967 int h00
= ((iw1
>> DSP32Mac_h00_bits
) & DSP32Mac_h00_mask
);
3968 int op0
= ((iw1
>> DSP32Mac_op0_bits
) & DSP32Mac_op0_mask
);
3969 int h11
= ((iw1
>> DSP32Mac_h11_bits
) & DSP32Mac_h11_mask
);
3970 int h01
= ((iw1
>> DSP32Mac_h01_bits
) & DSP32Mac_h01_mask
);
3972 bu32 res
= DREG (dst
);
3973 bu32 sat0
= 0, sat1
= 0, v_i0
= 0, v_i1
= 0;
3974 char _buf
[128], *buf
= _buf
;
3977 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32mult
);
3978 TRACE_EXTRACT (cpu
, "%s: M:%i mmod:%i MM:%i P:%i w1:%i op1:%i h01:%i h11:%i "
3979 "w0:%i op0:%i h00:%i h10:%i dst:%i src0:%i src1:%i",
3980 __func__
, M
, mmod
, MM
, P
, w1
, op1
, h01
, h11
, w0
, op0
, h00
, h10
,
3983 if (w1
== 0 && w0
== 0)
3984 illegal_instruction (cpu
);
3985 if (((1 << mmod
) & (P
? 0x313 : 0x1b57)) == 0)
3986 illegal_instruction (cpu
);
3987 if (P
&& ((dst
& 1) || (op1
!= 0) || (op0
!= 0) || !is_macmod_pmove (mmod
)))
3988 illegal_instruction (cpu
);
3989 if (!P
&& ((op1
!= 0) || (op0
!= 0) || !is_macmod_hmove (mmod
)))
3990 illegal_instruction (cpu
);
3992 /* First handle MAC1 side. */
3995 bu64 r
= decode_multfunc (cpu
, h01
, h11
, src0
, src1
, mmod
, MM
, &sat1
);
3996 bu32 res1
= extract_mult (cpu
, r
, mmod
, MM
, P
, &v_i1
);
3998 buf
+= sprintf (buf
, P
? "R%i" : "R%i.H", dst
+ P
);
3999 buf
+= sprintf (buf
, " = R%i.%c * R%i.%c",
4000 src0
, h01
? 'H' : 'L',
4001 src1
, h11
? 'H' : 'L');
4005 buf
+= sprintf (buf
, " (M)");
4007 buf
+= sprintf (buf
, ", ");
4011 STORE (DREG (dst
+ 1), res1
);
4014 if (res1
& 0xFFFF0000)
4015 illegal_instruction (cpu
);
4016 res
= REG_H_L (res1
<< 16, res
);
4020 /* First handle MAC0 side. */
4023 bu64 r
= decode_multfunc (cpu
, h00
, h10
, src0
, src1
, mmod
, 0, &sat0
);
4024 bu32 res0
= extract_mult (cpu
, r
, mmod
, 0, P
, &v_i0
);
4026 buf
+= sprintf (buf
, P
? "R%i" : "R%i.L", dst
);
4027 buf
+= sprintf (buf
, " = R%i.%c * R%i.%c",
4028 src0
, h01
? 'H' : 'L',
4029 src1
, h11
? 'H' : 'L');
4032 STORE (DREG (dst
), res0
);
4035 if (res0
& 0xFFFF0000)
4036 illegal_instruction (cpu
);
4037 res
= REG_H_L (res
, res0
);
4041 TRACE_INSN (cpu
, "%s%s;", _buf
, mac_optmode (mmod
, _MM
));
4043 if (!P
&& (w0
|| w1
))
4044 STORE (DREG (dst
), res
);
4048 bu32 v
= sat0
| sat1
| v_i0
| v_i1
;
4050 STORE (ASTATREG (v
), v
);
4051 STORE (ASTATREG (v_copy
), v
);
4053 STORE (ASTATREG (vs
), v
);
4058 decode_dsp32alu_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
4061 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
4062 | 1 | 1 | 0 | 0 |.M.| 1 | 0 | - | - | - |.HL|.aopcde............|
4063 |.aop...|.s.|.x.|.dst0......|.dst1......|.src0......|.src1......|
4064 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
4065 int s
= ((iw1
>> DSP32Alu_s_bits
) & DSP32Alu_s_mask
);
4066 int x
= ((iw1
>> DSP32Alu_x_bits
) & DSP32Alu_x_mask
);
4067 int aop
= ((iw1
>> DSP32Alu_aop_bits
) & DSP32Alu_aop_mask
);
4068 int src0
= ((iw1
>> DSP32Alu_src0_bits
) & DSP32Alu_src0_mask
);
4069 int src1
= ((iw1
>> DSP32Alu_src1_bits
) & DSP32Alu_src1_mask
);
4070 int dst0
= ((iw1
>> DSP32Alu_dst0_bits
) & DSP32Alu_dst0_mask
);
4071 int dst1
= ((iw1
>> DSP32Alu_dst1_bits
) & DSP32Alu_dst1_mask
);
4072 int M
= ((iw0
>> (DSP32Alu_M_bits
- 16)) & DSP32Alu_M_mask
);
4073 int HL
= ((iw0
>> (DSP32Alu_HL_bits
- 16)) & DSP32Alu_HL_mask
);
4074 int aopcde
= ((iw0
>> (DSP32Alu_aopcde_bits
- 16)) & DSP32Alu_aopcde_mask
);
4076 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32alu
);
4077 TRACE_EXTRACT (cpu
, "%s: M:%i HL:%i aopcde:%i aop:%i s:%i x:%i dst0:%i "
4078 "dst1:%i src0:%i src1:%i",
4079 __func__
, M
, HL
, aopcde
, aop
, s
, x
, dst0
, dst1
, src0
, src1
);
4081 if ((aop
== 0 || aop
== 2) && aopcde
== 9 && x
== 0 && s
== 0 && HL
== 0)
4084 TRACE_INSN (cpu
, "A%i.L = R%i.L;", a
, src0
);
4085 SET_AWREG (a
, REG_H_L (AWREG (a
), DREG (src0
)));
4087 else if ((aop
== 0 || aop
== 2) && aopcde
== 9 && x
== 0 && s
== 0 && HL
== 1)
4090 TRACE_INSN (cpu
, "A%i.H = R%i.H;", a
, src0
);
4091 SET_AWREG (a
, REG_H_L (DREG (src0
), AWREG (a
)));
4093 else if ((aop
== 1 || aop
== 0) && aopcde
== 5 && x
== 0 && s
== 0)
4095 bs32 val0
= DREG (src0
);
4096 bs32 val1
= DREG (src1
);
4099 bs32 ovX
, sBit1
, sBit2
, sBitRes1
, sBitRes2
;
4101 TRACE_INSN (cpu
, "R%i.%s = R%i %s R%i (RND12)", dst0
, HL
? "L" : "H",
4102 src0
, aop
& 0x1 ? "-" : "+", src1
);
4104 /* If subtract, just invert and add one. */
4107 if (val1
== 0x80000000)
4113 /* Get the sign bits, since we need them later. */
4114 sBit1
= !!(val0
& 0x80000000);
4115 sBit2
= !!(val1
& 0x80000000);
4119 sBitRes1
= !!(res
& 0x80000000);
4120 /* Round to the 12th bit. */
4122 sBitRes2
= !!(res
& 0x80000000);
4130 positive_res + positive_round = neg
4131 Shift and upper 4 bits where not the same. */
4132 if ((!(sBit1
^ sBit2
) && (sBit1
^ sBitRes1
))
4133 || (!sBit1
&& !sBit2
&& sBitRes2
)
4134 || ((signRes
!= 0) && (signRes
!= -1)))
4136 /* Both X1 and X2 Neg res is neg overflow. */
4139 /* Both X1 and X2 Pos res is pos overflow. */
4140 else if (!sBit1
&& !sBit2
)
4142 /* Pos+Neg or Neg+Pos take the sign of the result. */
4152 /* Shift up now after overflow detection. */
4160 STORE (DREG (dst0
), REG_H_L (res
<< 16, DREG (dst0
)));
4162 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), res
));
4164 SET_ASTATREG (az
, res
== 0);
4165 SET_ASTATREG (an
, res
& 0x8000);
4166 SET_ASTATREG (v
, ovX
);
4168 SET_ASTATREG (vs
, ovX
);
4170 else if ((aop
== 2 || aop
== 3) && aopcde
== 5 && x
== 1 && s
== 0)
4172 bs32 val0
= DREG (src0
);
4173 bs32 val1
= DREG (src1
);
4176 TRACE_INSN (cpu
, "R%i.%s = R%i %s R%i (RND20)", dst0
, HL
? "L" : "H",
4177 src0
, aop
& 0x1 ? "-" : "+", src1
);
4179 /* If subtract, just invert and add one. */
4183 res
= (val0
>> 4) + (val1
>> 4) + (((val0
& 0xf) + (val1
& 0xf)) >> 4);
4185 /* Don't sign extend during the shift. */
4186 res
= ((bu32
)res
>> 16);
4188 /* Don't worry about overflows, since we are shifting right. */
4191 STORE (DREG (dst0
), REG_H_L (res
<< 16, DREG (dst0
)));
4193 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), res
));
4195 SET_ASTATREG (az
, res
== 0);
4196 SET_ASTATREG (an
, res
& 0x8000);
4197 SET_ASTATREG (v
, 0);
4199 else if ((aopcde
== 2 || aopcde
== 3) && x
== 0)
4201 bu32 s1
, s2
, val
, ac0_i
= 0, v_i
= 0;
4203 TRACE_INSN (cpu
, "R%i.%c = R%i.%c %c R%i.%c%s;",
4204 dst0
, HL
? 'H' : 'L',
4205 src0
, aop
& 2 ? 'H' : 'L',
4206 aopcde
== 2 ? '+' : '-',
4207 src1
, aop
& 1 ? 'H' : 'L',
4218 val
= add16 (cpu
, s1
, s2
, &ac0_i
, &v_i
, 0, 0, s
, 0);
4220 val
= sub16 (cpu
, s1
, s2
, &ac0_i
, &v_i
, 0, 0, s
, 0);
4222 SET_ASTATREG (ac0
, ac0_i
);
4223 SET_ASTATREG (v
, v_i
);
4225 SET_ASTATREG (vs
, v_i
);
4228 SET_DREG_H (dst0
, val
<< 16);
4230 SET_DREG_L (dst0
, val
);
4232 SET_ASTATREG (an
, val
& 0x8000);
4233 SET_ASTATREG (az
, val
== 0);
4235 else if ((aop
== 0 || aop
== 2) && aopcde
== 9 && x
== 0 && s
== 1 && HL
== 0)
4238 TRACE_INSN (cpu
, "A%i = R%i;", a
, src0
);
4239 SET_AREG32 (a
, DREG (src0
));
4241 else if ((aop
== 1 || aop
== 3) && aopcde
== 9 && x
== 0 && s
== 0 && HL
== 0)
4244 TRACE_INSN (cpu
, "A%i.X = R%i.L;", a
, src0
);
4245 SET_AXREG (a
, (bs8
)DREG (src0
));
4247 else if (aop
== 3 && aopcde
== 11 && x
== 0 && HL
== 0)
4249 bu64 acc0
= get_extended_acc (cpu
, 0);
4250 bu64 acc1
= get_extended_acc (cpu
, 1);
4251 bu32 carry
= (bu40
)acc1
< (bu40
)acc0
;
4254 TRACE_INSN (cpu
, "A0 -= A1%s;", s
? " (W32)" : "");
4257 if ((bs64
)acc0
< -0x8000000000ll
)
4258 acc0
= -0x8000000000ull
, sat
= 1;
4259 else if ((bs64
)acc0
>= 0x7fffffffffll
)
4260 acc0
= 0x7fffffffffull
, sat
= 1;
4264 /* A0 -= A1 (W32) */
4265 if (acc0
& (bu64
)0x8000000000ll
)
4266 acc0
&= 0x80ffffffffll
, sat
= 1;
4268 acc0
&= 0xffffffffll
;
4270 STORE (AXREG (0), (acc0
>> 32) & 0xff);
4271 STORE (AWREG (0), acc0
& 0xffffffff);
4272 STORE (ASTATREG (az
), acc0
== 0);
4273 STORE (ASTATREG (an
), !!(acc0
& (bu64
)0x8000000000ll
));
4274 STORE (ASTATREG (ac0
), carry
);
4275 STORE (ASTATREG (ac0_copy
), carry
);
4276 STORE (ASTATREG (av0
), sat
);
4278 STORE (ASTATREG (av0s
), sat
);
4280 else if ((aop
== 0 || aop
== 1) && aopcde
== 22 && x
== 0)
4282 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4284 const char * const opts
[] = { "rndl", "rndh", "tl", "th" };
4286 TRACE_INSN (cpu
, "R%i = BYTEOP2P (R%i:%i, R%i:%i) (%s%s);", dst0
,
4287 src0
+ 1, src0
, src1
+ 1, src1
, opts
[HL
+ (aop
<< 1)],
4290 if ((src1
!= 0 && src1
!= 2) || (src0
!= 0 && src0
!= 2))
4291 illegal_instruction (cpu
);
4294 s0H
= DREG (src0
+ 1);
4296 s1H
= DREG (src1
+ 1);
4299 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4300 s1
= algn (s1H
, s1L
, IREG (0) & 3);
4304 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4305 s1
= algn (s1L
, s1H
, IREG (0) & 3);
4309 tmp0
= ((((s1
>> 8) & 0xff) + ((s1
>> 0) & 0xff) +
4310 ((s0
>> 8) & 0xff) + ((s0
>> 0) & 0xff) + i
) >> 2) & 0xff;
4311 tmp1
= ((((s1
>> 24) & 0xff) + ((s1
>> 16) & 0xff) +
4312 ((s0
>> 24) & 0xff) + ((s0
>> 16) & 0xff) + i
) >> 2) & 0xff;
4313 STORE (DREG (dst0
), (tmp1
<< (16 + (HL
* 8))) | (tmp0
<< (HL
* 8)));
4315 /* Implicit DISALGNEXCPT in parallel. */
4318 else if ((aop
== 0 || aop
== 1) && aopcde
== 8 && x
== 0 && s
== 0 && HL
== 0)
4320 TRACE_INSN (cpu
, "A%i = 0;", aop
);
4323 else if (aop
== 2 && aopcde
== 8 && x
== 0 && s
== 0 && HL
== 0)
4325 TRACE_INSN (cpu
, "A1 = A0 = 0;");
4329 else if ((aop
== 0 || aop
== 1 || aop
== 2) && s
== 1 && aopcde
== 8
4330 && x
== 0 && HL
== 0)
4332 bs40 acc0
= get_extended_acc (cpu
, 0);
4333 bs40 acc1
= get_extended_acc (cpu
, 1);
4336 if (aop
== 0 || aop
== 1)
4337 TRACE_INSN (cpu
, "A%i = A%i (S);", aop
, aop
);
4339 TRACE_INSN (cpu
, "A1 = A1 (S), A0 = A0 (S);");
4341 if (aop
== 0 || aop
== 2)
4344 acc0
= saturate_s32 (acc0
, &sat
);
4345 acc0
|= -(acc0
& 0x80000000ull
);
4346 SET_AXREG (0, (acc0
>> 31) & 0xFF);
4347 SET_AWREG (0, acc0
& 0xFFFFFFFF);
4348 SET_ASTATREG (av0
, sat
);
4350 SET_ASTATREG (av0s
, sat
);
4355 if (aop
== 1 || aop
== 2)
4358 acc1
= saturate_s32 (acc1
, &sat
);
4359 acc1
|= -(acc1
& 0x80000000ull
);
4360 SET_AXREG (1, (acc1
>> 31) & 0xFF);
4361 SET_AWREG (1, acc1
& 0xFFFFFFFF);
4362 SET_ASTATREG (av1
, sat
);
4364 SET_ASTATREG (av1s
, sat
);
4369 SET_ASTATREG (az
, (acc0
== 0) || (acc1
== 0));
4370 SET_ASTATREG (an
, ((acc0
>> 31) & 1) || ((acc1
>> 31) & 1));
4372 else if (aop
== 3 && aopcde
== 8 && x
== 0 && HL
== 0)
4374 TRACE_INSN (cpu
, "A%i = A%i;", s
, !s
);
4375 SET_AXREG (s
, AXREG (!s
));
4376 SET_AWREG (s
, AWREG (!s
));
4378 else if (aop
== 3 && HL
== 0 && aopcde
== 16 && x
== 0 && s
== 0)
4383 TRACE_INSN (cpu
, "A1 = ABS A1 , A0 = ABS A0;");
4386 for (i
= 0; i
< 2; ++i
)
4389 bs40 acc
= get_extended_acc (cpu
, i
);
4393 av
= acc
== ((bs40
)1 << 39);
4395 acc
= ((bs40
)1 << 39) - 1;
4398 SET_ASTATREG (av
[i
], av
);
4400 SET_ASTATREG (avs
[i
], av
);
4403 SET_ASTATREG (az
, az
);
4404 SET_ASTATREG (an
, 0);
4406 else if (aop
== 0 && aopcde
== 23 && x
== 0)
4408 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4411 TRACE_INSN (cpu
, "R%i = BYTEOP3P (R%i:%i, R%i:%i) (%s%s);", dst0
,
4412 src0
+ 1, src0
, src1
+ 1, src1
, HL
? "HI" : "LO",
4415 if ((src1
!= 0 && src1
!= 2) || (src0
!= 0 && src0
!= 2))
4416 illegal_instruction (cpu
);
4419 s0H
= DREG (src0
+ 1);
4421 s1H
= DREG (src1
+ 1);
4424 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4425 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4429 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4430 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4433 tmp0
= (bs32
)(bs16
)(s0
>> 0) + ((s1
>> ( 0 + (8 * !HL
))) & 0xff);
4434 tmp1
= (bs32
)(bs16
)(s0
>> 16) + ((s1
>> (16 + (8 * !HL
))) & 0xff);
4435 STORE (DREG (dst0
), (CLAMP (tmp0
, 0, 255) << ( 0 + (8 * HL
))) |
4436 (CLAMP (tmp1
, 0, 255) << (16 + (8 * HL
))));
4438 /* Implicit DISALGNEXCPT in parallel. */
4441 else if ((aop
== 0 || aop
== 1) && aopcde
== 16 && x
== 0 && s
== 0)
4446 TRACE_INSN (cpu
, "A%i = ABS A%i;", HL
, aop
);
4448 acc
= get_extended_acc (cpu
, aop
);
4451 av
= acc
== ((bs40
)1 << 39);
4453 acc
= ((bs40
)1 << 39) - 1;
4456 SET_ASTATREG (av
[HL
], av
);
4458 SET_ASTATREG (avs
[HL
], av
);
4459 SET_ASTATREG (az
, acc
== 0);
4460 SET_ASTATREG (an
, 0);
4462 else if (aop
== 3 && aopcde
== 12 && x
== 0 && s
== 0)
4464 bs32 res
= DREG (src0
);
4466 bool sBit_a
, sBit_b
;
4468 TRACE_INSN (cpu
, "R%i.%s = R%i (RND);", dst0
, HL
== 0 ? "L" : "H", src0
);
4469 TRACE_DECODE (cpu
, "R%i.%s = R%i:%#x (RND);", dst0
,
4470 HL
== 0 ? "L" : "H", src0
, res
);
4472 sBit_b
= !!(res
& 0x80000000);
4475 sBit_a
= !!(res
& 0x80000000);
4477 /* Overflow if the sign bit changed when we rounded. */
4478 if ((res
>> 16) && (sBit_b
!= sBit_a
))
4493 SET_DREG (dst0
, REG_H_L (DREG (dst0
), res
));
4495 SET_DREG (dst0
, REG_H_L (res
<< 16, DREG (dst0
)));
4497 SET_ASTATREG (az
, res
== 0);
4498 SET_ASTATREG (an
, res
< 0);
4499 SET_ASTATREG (v
, ovX
);
4501 SET_ASTATREG (vs
, ovX
);
4503 else if (aop
== 3 && HL
== 0 && aopcde
== 15 && x
== 0 && s
== 0)
4505 bu32 hi
= (-(bs16
)(DREG (src0
) >> 16)) << 16;
4506 bu32 lo
= (-(bs16
)(DREG (src0
) & 0xFFFF)) & 0xFFFF;
4509 TRACE_INSN (cpu
, "R%i = -R%i (V);", dst0
, src0
);
4513 if (hi
== 0x80000000)
4529 SET_DREG (dst0
, hi
| lo
);
4531 SET_ASTATREG (v
, v
);
4533 SET_ASTATREG (vs
, 1);
4534 SET_ASTATREG (ac0
, ac0
);
4535 SET_ASTATREG (ac1
, ac1
);
4536 setflags_nz_2x16 (cpu
, DREG (dst0
));
4538 else if (aop
== 3 && HL
== 0 && aopcde
== 14 && x
== 0 && s
== 0)
4540 TRACE_INSN (cpu
, "A1 = - A1 , A0 = - A0;");
4542 SET_AREG (0, saturate_s40 (-get_extended_acc (cpu
, 0)));
4543 SET_AREG (1, saturate_s40 (-get_extended_acc (cpu
, 1)));
4544 /* XXX: what ASTAT flags need updating ? */
4546 else if ((aop
== 0 || aop
== 1) && aopcde
== 14 && x
== 0 && s
== 0)
4548 bs40 src_acc
= get_extended_acc (cpu
, aop
);
4551 TRACE_INSN (cpu
, "A%i = - A%i;", HL
, aop
);
4553 SET_AREG (HL
, saturate_s40_astat (-src_acc
, &v
));
4555 SET_ASTATREG (az
, AWREG (HL
) == 0 && AXREG (HL
) == 0);
4556 SET_ASTATREG (an
, AXREG (HL
) >> 7);
4559 SET_ASTATREG (ac0
, !src_acc
);
4560 SET_ASTATREG (av0
, v
);
4562 SET_ASTATREG (av0s
, 1);
4566 SET_ASTATREG (ac1
, !src_acc
);
4567 SET_ASTATREG (av1
, v
);
4569 SET_ASTATREG (av1s
, 1);
4572 else if (aop
== 0 && aopcde
== 12 && x
== 0 && s
== 0 && HL
== 0)
4574 bs16 tmp0_hi
= DREG (src0
) >> 16;
4575 bs16 tmp0_lo
= DREG (src0
);
4576 bs16 tmp1_hi
= DREG (src1
) >> 16;
4577 bs16 tmp1_lo
= DREG (src1
);
4579 TRACE_INSN (cpu
, "R%i.L = R%i.H = SIGN(R%i.H) * R%i.H + SIGN(R%i.L) * R%i.L;",
4580 dst0
, dst0
, src0
, src1
, src0
, src1
);
4582 if ((tmp0_hi
>> 15) & 1)
4583 tmp1_hi
= ~tmp1_hi
+ 1;
4585 if ((tmp0_lo
>> 15) & 1)
4586 tmp1_lo
= ~tmp1_lo
+ 1;
4588 tmp1_hi
= tmp1_hi
+ tmp1_lo
;
4590 STORE (DREG (dst0
), REG_H_L (tmp1_hi
<< 16, tmp1_hi
));
4592 else if (aopcde
== 0 && HL
== 0)
4594 bu32 s0
= DREG (src0
);
4595 bu32 s1
= DREG (src1
);
4596 bu32 s0h
= s0
>> 16;
4597 bu32 s0l
= s0
& 0xFFFF;
4598 bu32 s1h
= s1
>> 16;
4599 bu32 s1l
= s1
& 0xFFFF;
4601 bu32 ac1_i
= 0, ac0_i
= 0, v_i
= 0, z_i
= 0, n_i
= 0;
4603 TRACE_INSN (cpu
, "R%i = R%i %c|%c R%i%s;", dst0
, src0
,
4604 (aop
& 2) ? '-' : '+', (aop
& 1) ? '-' : '+', src1
,
4607 t0
= sub16 (cpu
, s0h
, s1h
, &ac1_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4609 t0
= add16 (cpu
, s0h
, s1h
, &ac1_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4612 t1
= sub16 (cpu
, s0l
, s1l
, &ac0_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4614 t1
= add16 (cpu
, s0l
, s1l
, &ac0_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4616 SET_ASTATREG (ac1
, ac1_i
);
4617 SET_ASTATREG (ac0
, ac0_i
);
4618 SET_ASTATREG (az
, z_i
);
4619 SET_ASTATREG (an
, n_i
);
4620 SET_ASTATREG (v
, v_i
);
4622 SET_ASTATREG (vs
, v_i
);
4627 SET_DREG (dst0
, (t1
<< 16) | t0
);
4629 SET_DREG (dst0
, (t0
<< 16) | t1
);
4631 else if (aop
== 1 && aopcde
== 12 && x
== 0 && s
== 0 && HL
== 0)
4633 bs32 val0
= (bs16
)(AWREG (0) >> 16) + (bs16
)AWREG (0);
4634 bs32 val1
= (bs16
)(AWREG (1) >> 16) + (bs16
)AWREG (1);
4636 TRACE_INSN (cpu
, "R%i = A1.L + A1.H, R%i = A0.L + A0.H;", dst1
, dst0
);
4639 illegal_instruction_combination (cpu
);
4641 SET_DREG (dst0
, val0
);
4642 SET_DREG (dst1
, val1
);
4644 else if ((aop
== 0 || aop
== 2 || aop
== 3) && aopcde
== 1)
4648 bu16 s0L
= DREG (src0
);
4649 bu16 s0H
= DREG (src0
) >> 16;
4650 bu16 s1L
= DREG (src1
);
4651 bu16 s1H
= DREG (src1
) >> 16;
4652 bu32 v_i
= 0, n_i
= 0, z_i
= 0;
4654 TRACE_INSN (cpu
, "R%i = R%i %s R%i, R%i = R%i %s R%i%s;",
4655 dst1
, src0
, HL
? "+|-" : "+|+", src1
,
4656 dst0
, src0
, HL
? "-|+" : "-|-", src1
,
4657 amod0amod2 (s
, x
, aop
));
4660 illegal_instruction_combination (cpu
);
4664 x0
= add16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4665 x1
= add16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4666 d1
= (x0
<< 16) | x1
;
4668 x0
= sub16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4669 x1
= sub16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4671 d0
= (x0
<< 16) | x1
;
4673 d0
= (x1
<< 16) | x0
;
4677 x0
= add16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4678 x1
= sub16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4679 d1
= (x0
<< 16) | x1
;
4681 x0
= sub16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4682 x1
= add16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4684 d0
= (x0
<< 16) | x1
;
4686 d0
= (x1
<< 16) | x0
;
4688 SET_ASTATREG (az
, z_i
);
4689 SET_ASTATREG (an
, n_i
);
4690 SET_ASTATREG (v
, v_i
);
4692 SET_ASTATREG (vs
, v_i
);
4694 STORE (DREG (dst0
), d0
);
4695 STORE (DREG (dst1
), d1
);
4697 else if ((aop
== 0 || aop
== 1 || aop
== 2) && aopcde
== 11 && x
== 0)
4699 bs40 acc0
= get_extended_acc (cpu
, 0);
4700 bs40 acc1
= get_extended_acc (cpu
, 1);
4701 bu32 v
, dreg
, sat
= 0;
4702 bu32 carry
= !!((bu40
)~acc1
< (bu40
)acc0
);
4706 if (s
!= 0 || HL
!= 0)
4707 illegal_instruction (cpu
);
4708 TRACE_INSN (cpu
, "R%i = (A0 += A1);", dst0
);
4713 illegal_instruction (cpu
);
4714 TRACE_INSN (cpu
, "R%i.%c = (A0 += A1);", dst0
, HL
? 'H' : 'L');
4719 illegal_instruction (cpu
);
4720 TRACE_INSN (cpu
, "A0 += A1%s;", s
? " (W32)" : "");
4724 acc0
= saturate_s40_astat (acc0
, &v
);
4726 if (aop
== 2 && s
== 1) /* A0 += A1 (W32) */
4728 if (acc0
& (bs40
)0x8000000000ll
)
4729 acc0
&= 0x80ffffffffll
;
4731 acc0
&= 0xffffffffll
;
4734 STORE (AXREG (0), acc0
>> 32);
4735 STORE (AWREG (0), acc0
);
4736 SET_ASTATREG (av0
, v
&& acc1
);
4738 SET_ASTATREG (av0s
, v
);
4740 if (aop
== 0 || aop
== 1)
4742 if (aop
) /* Dregs_lo = A0 += A1 */
4744 dreg
= saturate_s32 (rnd16 (acc0
) << 16, &sat
);
4746 STORE (DREG (dst0
), REG_H_L (dreg
, DREG (dst0
)));
4748 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), dreg
>> 16));
4750 else /* Dregs = A0 += A1 */
4752 dreg
= saturate_s32 (acc0
, &sat
);
4753 STORE (DREG (dst0
), dreg
);
4756 STORE (ASTATREG (az
), dreg
== 0);
4757 STORE (ASTATREG (an
), !!(dreg
& 0x80000000));
4758 STORE (ASTATREG (ac0
), carry
);
4759 STORE (ASTATREG (ac0_copy
), carry
);
4760 STORE (ASTATREG (v
), sat
);
4761 STORE (ASTATREG (v_copy
), sat
);
4763 STORE (ASTATREG (vs
), sat
);
4767 STORE (ASTATREG (az
), acc0
== 0);
4768 STORE (ASTATREG (an
), !!(acc0
& 0x8000000000ull
));
4769 STORE (ASTATREG (ac0
), carry
);
4770 STORE (ASTATREG (ac0_copy
), carry
);
4773 else if ((aop
== 0 || aop
== 1) && aopcde
== 10 && x
== 0 && s
== 0 && HL
== 0)
4775 TRACE_INSN (cpu
, "R%i.L = A%i.X;", dst0
, aop
);
4776 SET_DREG_L (dst0
, (bs8
)AXREG (aop
));
4778 else if (aop
== 0 && aopcde
== 4 && x
== 0 && HL
== 0)
4780 TRACE_INSN (cpu
, "R%i = R%i + R%i%s;", dst0
, src0
, src1
, amod1 (s
, x
));
4781 SET_DREG (dst0
, add32 (cpu
, DREG (src0
), DREG (src1
), 1, s
));
4783 else if (aop
== 1 && aopcde
== 4 && x
== 0 && HL
== 0)
4785 TRACE_INSN (cpu
, "R%i = R%i - R%i%s;", dst0
, src0
, src1
, amod1 (s
, x
));
4786 SET_DREG (dst0
, sub32 (cpu
, DREG (src0
), DREG (src1
), 1, s
, 0));
4788 else if (aop
== 2 && aopcde
== 4 && x
== 0 && HL
== 0)
4790 TRACE_INSN (cpu
, "R%i = R%i + R%i, R%i = R%i - R%i%s;",
4791 dst1
, src0
, src1
, dst0
, src0
, src1
, amod1 (s
, x
));
4794 illegal_instruction_combination (cpu
);
4796 STORE (DREG (dst1
), add32 (cpu
, DREG (src0
), DREG (src1
), 1, s
));
4797 STORE (DREG (dst0
), sub32 (cpu
, DREG (src0
), DREG (src1
), 1, s
, 1));
4799 else if ((aop
== 0 || aop
== 1) && aopcde
== 17 && x
== 0 && HL
== 0)
4801 bs40 acc0
= get_extended_acc (cpu
, 0);
4802 bs40 acc1
= get_extended_acc (cpu
, 1);
4803 bs40 val0
, val1
, sval0
, sval1
;
4806 TRACE_INSN (cpu
, "R%i = A%i + A%i, R%i = A%i - A%i%s",
4807 dst1
, !aop
, aop
, dst0
, !aop
, aop
, amod1 (s
, x
));
4808 TRACE_DECODE (cpu
, "R%i = A%i:%#"PRIx64
" + A%i:%#"PRIx64
", "
4809 "R%i = A%i:%#"PRIx64
" - A%i:%#"PRIx64
"%s",
4810 dst1
, !aop
, aop
? acc0
: acc1
, aop
, aop
? acc1
: acc0
,
4811 dst0
, !aop
, aop
? acc0
: acc1
, aop
, aop
? acc1
: acc0
,
4815 illegal_instruction_combination (cpu
);
4823 sval0
= saturate_s32 (val0
, &sat
);
4825 sval1
= saturate_s32 (val1
, &sat
);
4833 STORE (DREG (dst0
), val0
);
4834 STORE (DREG (dst1
), val1
);
4835 SET_ASTATREG (v
, sat_i
);
4837 SET_ASTATREG (vs
, sat_i
);
4838 SET_ASTATREG (an
, val0
& 0x80000000 || val1
& 0x80000000);
4839 SET_ASTATREG (az
, val0
== 0 || val1
== 0);
4840 SET_ASTATREG (ac1
, (bu40
)~acc0
< (bu40
)acc1
);
4842 SET_ASTATREG (ac0
, !!((bu40
)acc1
<= (bu40
)acc0
));
4844 SET_ASTATREG (ac0
, !!((bu40
)acc0
<= (bu40
)acc1
));
4846 else if (aop
== 0 && aopcde
== 18 && x
== 0 && HL
== 0)
4848 bu40 acc0
= get_extended_acc (cpu
, 0);
4849 bu40 acc1
= get_extended_acc (cpu
, 1);
4850 bu32 s0L
= DREG (src0
);
4851 bu32 s0H
= DREG (src0
+ 1);
4852 bu32 s1L
= DREG (src1
);
4853 bu32 s1H
= DREG (src1
+ 1);
4855 bs16 tmp0
, tmp1
, tmp2
, tmp3
;
4857 /* This instruction is only defined for register pairs R1:0 and R3:2. */
4858 if (!((src0
== 0 || src0
== 2) && (src1
== 0 || src1
== 2)))
4859 illegal_instruction (cpu
);
4861 TRACE_INSN (cpu
, "SAA (R%i:%i, R%i:%i)%s", src0
+ 1, src0
,
4862 src1
+ 1, src1
, s
? " (R)" :"");
4864 /* Bit s determines the order of the two registers from a pair:
4865 if s=0 the low-order bytes come from the low reg in the pair,
4866 and if s=1 the low-order bytes come from the high reg. */
4870 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4871 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4875 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4876 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4879 /* Find the absolute difference between pairs, make it
4880 absolute, then add it to the existing accumulator half. */
4882 tmp0
= ((s0
<< 24) >> 24) - ((s1
<< 24) >> 24);
4883 tmp1
= ((s0
<< 16) >> 24) - ((s1
<< 16) >> 24);
4884 tmp2
= ((s0
<< 8) >> 24) - ((s1
<< 8) >> 24);
4885 tmp3
= ((s0
<< 0) >> 24) - ((s1
<< 0) >> 24);
4887 tmp0
= (tmp0
< 0) ? -tmp0
: tmp0
;
4888 tmp1
= (tmp1
< 0) ? -tmp1
: tmp1
;
4889 tmp2
= (tmp2
< 0) ? -tmp2
: tmp2
;
4890 tmp3
= (tmp3
< 0) ? -tmp3
: tmp3
;
4892 s0L
= saturate_u16 ((bu32
)tmp0
+ ((acc0
>> 0) & 0xffff), 0);
4893 s0H
= saturate_u16 ((bu32
)tmp1
+ ((acc0
>> 16) & 0xffff), 0);
4894 s1L
= saturate_u16 ((bu32
)tmp2
+ ((acc1
>> 0) & 0xffff), 0);
4895 s1H
= saturate_u16 ((bu32
)tmp3
+ ((acc1
>> 16) & 0xffff), 0);
4897 STORE (AWREG (0), (s0H
<< 16) | (s0L
& 0xFFFF));
4898 STORE (AXREG (0), 0);
4899 STORE (AWREG (1), (s1H
<< 16) | (s1L
& 0xFFFF));
4900 STORE (AXREG (1), 0);
4902 /* Implicit DISALGNEXCPT in parallel. */
4905 else if (aop
== 3 && aopcde
== 18 && x
== 0 && s
== 0 && HL
== 0)
4907 TRACE_INSN (cpu
, "DISALGNEXCPT");
4910 else if ((aop
== 0 || aop
== 1) && aopcde
== 20 && x
== 0 && HL
== 0)
4912 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4913 const char * const opts
[] = { "", " (R)", " (T)", " (T, R)" };
4915 TRACE_INSN (cpu
, "R%i = BYTEOP1P (R%i:%i, R%i:%i)%s;", dst0
,
4916 src0
+ 1, src0
, src1
+ 1, src1
, opts
[s
+ (aop
<< 1)]);
4918 if ((src1
!= 0 && src1
!= 2) || (src0
!= 0 && src0
!= 2))
4919 illegal_instruction (cpu
);
4922 s0H
= DREG (src0
+ 1);
4924 s1H
= DREG (src1
+ 1);
4927 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4928 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4932 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4933 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4937 (((((s0
>> 0) & 0xff) + ((s1
>> 0) & 0xff) + !aop
) >> 1) << 0) |
4938 (((((s0
>> 8) & 0xff) + ((s1
>> 8) & 0xff) + !aop
) >> 1) << 8) |
4939 (((((s0
>> 16) & 0xff) + ((s1
>> 16) & 0xff) + !aop
) >> 1) << 16) |
4940 (((((s0
>> 24) & 0xff) + ((s1
>> 24) & 0xff) + !aop
) >> 1) << 24));
4942 /* Implicit DISALGNEXCPT in parallel. */
4945 else if (aop
== 0 && aopcde
== 21 && x
== 0 && HL
== 0)
4947 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4949 TRACE_INSN (cpu
, "(R%i, R%i) = BYTEOP16P (R%i:%i, R%i:%i)%s;", dst1
, dst0
,
4950 src0
+ 1, src0
, src1
+ 1, src1
, s
? " (R)" : "");
4952 if ((src1
!= 0 && src1
!= 2) || (src0
!= 0 && src0
!= 2))
4953 illegal_instruction (cpu
);
4956 illegal_instruction_combination (cpu
);
4959 s0H
= DREG (src0
+ 1);
4961 s1H
= DREG (src1
+ 1);
4964 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4965 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4969 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4970 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4974 ((((s0
>> 0) & 0xff) + ((s1
>> 0) & 0xff)) << 0) |
4975 ((((s0
>> 8) & 0xff) + ((s1
>> 8) & 0xff)) << 16));
4977 ((((s0
>> 16) & 0xff) + ((s1
>> 16) & 0xff)) << 0) |
4978 ((((s0
>> 24) & 0xff) + ((s1
>> 24) & 0xff)) << 16));
4980 /* Implicit DISALGNEXCPT in parallel. */
4983 else if (aop
== 1 && aopcde
== 21 && x
== 0 && HL
== 0)
4985 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4987 TRACE_INSN (cpu
, "(R%i, R%i) = BYTEOP16M (R%i:%i, R%i:%i)%s;", dst1
, dst0
,
4988 src0
+ 1, src0
, src1
+ 1, src1
, s
? " (R)" : "");
4990 if ((src1
!= 0 && src1
!= 2) || (src0
!= 0 && src0
!= 2))
4991 illegal_instruction (cpu
);
4994 illegal_instruction_combination (cpu
);
4997 s0H
= DREG (src0
+ 1);
4999 s1H
= DREG (src1
+ 1);
5002 s0
= algn (s0H
, s0L
, IREG (0) & 3);
5003 s1
= algn (s1H
, s1L
, IREG (1) & 3);
5007 s0
= algn (s0L
, s0H
, IREG (0) & 3);
5008 s1
= algn (s1L
, s1H
, IREG (1) & 3);
5012 (((((s0
>> 0) & 0xff) - ((s1
>> 0) & 0xff)) << 0) & 0xffff) |
5013 (((((s0
>> 8) & 0xff) - ((s1
>> 8) & 0xff)) << 16)));
5015 (((((s0
>> 16) & 0xff) - ((s1
>> 16) & 0xff)) << 0) & 0xffff) |
5016 (((((s0
>> 24) & 0xff) - ((s1
>> 24) & 0xff)) << 16)));
5018 /* Implicit DISALGNEXCPT in parallel. */
5021 else if (aop
== 1 && aopcde
== 7 && x
== 0 && s
== 0 && HL
== 0)
5023 TRACE_INSN (cpu
, "R%i = MIN (R%i, R%i);", dst0
, src0
, src1
);
5024 SET_DREG (dst0
, min32 (cpu
, DREG (src0
), DREG (src1
)));
5026 else if (aop
== 0 && aopcde
== 7 && x
== 0 && s
== 0 && HL
== 0)
5028 TRACE_INSN (cpu
, "R%i = MAX (R%i, R%i);", dst0
, src0
, src1
);
5029 SET_DREG (dst0
, max32 (cpu
, DREG (src0
), DREG (src1
)));
5031 else if (aop
== 2 && aopcde
== 7 && x
== 0 && s
== 0 && HL
== 0)
5033 bu32 val
= DREG (src0
);
5036 TRACE_INSN (cpu
, "R%i = ABS R%i;", dst0
, src0
);
5040 v
= (val
== 0x80000000);
5043 SET_DREG (dst0
, val
);
5045 SET_ASTATREG (v
, v
);
5047 SET_ASTATREG (vs
, 1);
5048 setflags_nz (cpu
, val
);
5050 else if (aop
== 3 && aopcde
== 7 && x
== 0 && HL
== 0)
5052 bu32 val
= DREG (src0
);
5054 TRACE_INSN (cpu
, "R%i = - R%i%s;", dst0
, src0
, amod1 (s
, 0));
5056 if (s
&& val
== 0x80000000)
5059 SET_ASTATREG (v
, 1);
5060 SET_ASTATREG (vs
, 1);
5062 else if (val
== 0x80000000)
5066 SET_DREG (dst0
, val
);
5068 SET_ASTATREG (az
, val
== 0);
5069 SET_ASTATREG (an
, val
& 0x80000000);
5071 else if (aop
== 2 && aopcde
== 6 && x
== 0 && s
== 0 && HL
== 0)
5073 bu32 in
= DREG (src0
);
5074 bu32 hi
= (in
& 0x80000000 ? (bu32
)-(bs16
)(in
>> 16) : in
>> 16) << 16;
5075 bu32 lo
= (in
& 0x8000 ? (bu32
)-(bs16
)(in
& 0xFFFF) : in
) & 0xFFFF;
5078 TRACE_INSN (cpu
, "R%i = ABS R%i (V);", dst0
, src0
);
5081 if (hi
== 0x80000000)
5091 SET_DREG (dst0
, hi
| lo
);
5093 SET_ASTATREG (v
, v
);
5095 SET_ASTATREG (vs
, 1);
5096 setflags_nz_2x16 (cpu
, DREG (dst0
));
5098 else if (aop
== 1 && aopcde
== 6 && x
== 0 && s
== 0 && HL
== 0)
5100 TRACE_INSN (cpu
, "R%i = MIN (R%i, R%i) (V);", dst0
, src0
, src1
);
5101 SET_DREG (dst0
, min2x16 (cpu
, DREG (src0
), DREG (src1
)));
5103 else if (aop
== 0 && aopcde
== 6 && x
== 0 && s
== 0 && HL
== 0)
5105 TRACE_INSN (cpu
, "R%i = MAX (R%i, R%i) (V);", dst0
, src0
, src1
);
5106 SET_DREG (dst0
, max2x16 (cpu
, DREG (src0
), DREG (src1
)));
5108 else if (aop
== 0 && aopcde
== 24 && x
== 0 && s
== 0 && HL
== 0)
5110 TRACE_INSN (cpu
, "R%i = BYTEPACK (R%i, R%i);", dst0
, src0
, src1
);
5112 (((DREG (src0
) >> 0) & 0xff) << 0) |
5113 (((DREG (src0
) >> 16) & 0xff) << 8) |
5114 (((DREG (src1
) >> 0) & 0xff) << 16) |
5115 (((DREG (src1
) >> 16) & 0xff) << 24));
5117 /* Implicit DISALGNEXCPT in parallel. */
5120 else if (aop
== 1 && aopcde
== 24 && x
== 0 && HL
== 0)
5124 bu8 bytea
, byteb
, bytec
, byted
;
5126 TRACE_INSN (cpu
, "(R%i, R%i) = BYTEUNPACK R%i:%i%s;",
5127 dst1
, dst0
, src0
+ 1, src0
, s
? " (R)" : "");
5129 if ((src1
!= 0 && src1
!= 2) || (src0
!= 0 && src0
!= 2))
5130 illegal_instruction (cpu
);
5133 illegal_instruction_combination (cpu
);
5135 order
= IREG (0) & 0x3;
5137 hi
= src0
, lo
= src0
+ 1;
5139 hi
= src0
+ 1, lo
= src0
;
5140 comb_src
= (((bu64
)DREG (hi
)) << 32) | DREG (lo
);
5141 bytea
= (comb_src
>> (0 + 8 * order
));
5142 byteb
= (comb_src
>> (8 + 8 * order
));
5143 bytec
= (comb_src
>> (16 + 8 * order
));
5144 byted
= (comb_src
>> (24 + 8 * order
));
5145 STORE (DREG (dst0
), bytea
| ((bu32
)byteb
<< 16));
5146 STORE (DREG (dst1
), bytec
| ((bu32
)byted
<< 16));
5148 /* Implicit DISALGNEXCPT in parallel. */
5151 else if (aopcde
== 13 && HL
== 0 && x
== 0 && s
== 0)
5153 const char *searchmodes
[] = { "GT", "GE", "LT", "LE" };
5155 bs16 a0_lo
, a1_lo
, src_hi
, src_lo
;
5157 TRACE_INSN (cpu
, "(R%i, R%i) = SEARCH R%i (%s);",
5158 dst1
, dst0
, src0
, searchmodes
[aop
]);
5160 /* XXX: The parallel version is a bit weird in its limits:
5162 This instruction can be issued in parallel with the combination of one
5163 16-bit length load instruction to the P0 register and one 16-bit NOP.
5164 No other instructions can be issued in parallel with the Vector Search
5165 instruction. Note the following legal and illegal forms.
5166 (r1, r0) = search r2 (LT) || r2 = [p0++p3]; // ILLEGAL
5167 (r1, r0) = search r2 (LT) || r2 = [p0++]; // LEGAL
5168 (r1, r0) = search r2 (LT) || r2 = [p0++]; // LEGAL
5170 Unfortunately, our parallel insn state doesn't (currently) track enough
5171 details to be able to check this. */
5174 illegal_instruction_combination (cpu
);
5176 up_hi
= up_lo
= false;
5179 src_lo
= DREG (src0
);
5180 src_hi
= DREG (src0
) >> 16;
5185 up_hi
= (src_hi
> a1_lo
);
5186 up_lo
= (src_lo
> a0_lo
);
5189 up_hi
= (src_hi
>= a1_lo
);
5190 up_lo
= (src_lo
>= a0_lo
);
5193 up_hi
= (src_hi
< a1_lo
);
5194 up_lo
= (src_lo
< a0_lo
);
5197 up_hi
= (src_hi
<= a1_lo
);
5198 up_lo
= (src_lo
<= a0_lo
);
5204 SET_AREG (1, src_hi
);
5205 SET_DREG (dst1
, PREG (0));
5208 SET_AREG (1, a1_lo
);
5212 SET_AREG (0, src_lo
);
5213 SET_DREG (dst0
, PREG (0));
5216 SET_AREG (0, a0_lo
);
5219 illegal_instruction (cpu
);
5223 decode_dsp32shift_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
5226 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5227 | 1 | 1 | 0 | 0 |.M.| 1 | 1 | 0 | 0 | - | - |.sopcde............|
5228 |.sop...|.HLs...|.dst0......| - | - | - |.src0......|.src1......|
5229 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5230 int HLs
= ((iw1
>> DSP32Shift_HLs_bits
) & DSP32Shift_HLs_mask
);
5231 int sop
= ((iw1
>> DSP32Shift_sop_bits
) & DSP32Shift_sop_mask
);
5232 int src0
= ((iw1
>> DSP32Shift_src0_bits
) & DSP32Shift_src0_mask
);
5233 int src1
= ((iw1
>> DSP32Shift_src1_bits
) & DSP32Shift_src1_mask
);
5234 int dst0
= ((iw1
>> DSP32Shift_dst0_bits
) & DSP32Shift_dst0_mask
);
5235 int sopcde
= ((iw0
>> (DSP32Shift_sopcde_bits
- 16)) & DSP32Shift_sopcde_mask
);
5236 int M
= ((iw0
>> (DSP32Shift_M_bits
- 16)) & DSP32Shift_M_mask
);
5238 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32shift
);
5239 TRACE_EXTRACT (cpu
, "%s: M:%i sopcde:%i sop:%i HLs:%i dst0:%i src0:%i src1:%i",
5240 __func__
, M
, sopcde
, sop
, HLs
, dst0
, src0
, src1
);
5242 if ((sop
== 0 || sop
== 1) && sopcde
== 0)
5245 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5247 TRACE_INSN (cpu
, "R%i.%c = ASHIFT R%i.%c BY R%i.L%s;",
5248 dst0
, HLs
< 2 ? 'L' : 'H',
5249 src1
, HLs
& 1 ? 'H' : 'L',
5250 src0
, sop
== 1 ? " (S)" : "");
5253 val
= (bu16
)(DREG (src1
) & 0xFFFF);
5255 val
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5257 /* Positive shift magnitudes produce Logical Left shifts.
5258 Negative shift magnitudes produce Arithmetic Right shifts. */
5260 val
= ashiftrt (cpu
, val
, -shft
, 16);
5263 int sgn
= (val
>> 15) & 0x1;
5265 val
= lshift (cpu
, val
, shft
, 16, sop
== 1, 1);
5266 if (((val
>> 15) & 0x1) != sgn
)
5268 SET_ASTATREG (v
, 1);
5269 SET_ASTATREG (vs
, 1);
5274 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), val
));
5276 STORE (DREG (dst0
), REG_H_L (val
<< 16, DREG (dst0
)));
5278 else if (sop
== 2 && sopcde
== 0)
5280 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5283 TRACE_INSN (cpu
, "R%i.%c = LSHIFT R%i.%c BY R%i.L;",
5284 dst0
, HLs
< 2 ? 'L' : 'H',
5285 src1
, HLs
& 1 ? 'H' : 'L', src0
);
5288 val
= (bu16
)(DREG (src1
) & 0xFFFF);
5290 val
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5293 val
= val
>> (-1 * shft
);
5298 SET_DREG (dst0
, REG_H_L (DREG (dst0
), val
));
5300 SET_DREG (dst0
, REG_H_L (val
<< 16, DREG (dst0
)));
5302 SET_ASTATREG (az
, !((val
& 0xFFFF0000) == 0) || ((val
& 0xFFFF) == 0));
5303 SET_ASTATREG (an
, (!!(val
& 0x80000000)) ^ (!!(val
& 0x8000)));
5304 SET_ASTATREG (v
, 0);
5306 else if (sop
== 2 && sopcde
== 3 && (HLs
== 1 || HLs
== 0))
5308 int shift
= imm6 (DREG (src0
) & 0xFFFF);
5310 bu40 acc
= get_unextended_acc (cpu
, HLs
);
5312 TRACE_INSN (cpu
, "A%i = ROT A%i BY R%i.L;", HLs
, HLs
, src0
);
5313 TRACE_DECODE (cpu
, "A%i:%#"PRIx64
" shift:%i CC:%i", HLs
, acc
, shift
, cc
);
5315 acc
= rot40 (acc
, shift
, &cc
);
5316 SET_AREG (HLs
, acc
);
5320 else if (sop
== 0 && sopcde
== 3 && (HLs
== 0 || HLs
== 1))
5322 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5323 bu64 acc
= get_extended_acc (cpu
, HLs
);
5327 TRACE_INSN (cpu
, "A%i = ASHIFT A%i BY R%i.L;", HLs
, HLs
, src0
);
5328 TRACE_DECODE (cpu
, "A%i:%#"PRIx64
" shift:%i", HLs
, acc
, shft
);
5331 val
= ashiftrt (cpu
, acc
, -shft
, 40);
5333 val
= lshift (cpu
, acc
, shft
, 40, 0, 0);
5335 STORE (AXREG (HLs
), (val
>> 32) & 0xff);
5336 STORE (AWREG (HLs
), (val
& 0xffffffff));
5337 STORE (ASTATREG (av
[HLs
]), 0);
5339 else if (sop
== 1 && sopcde
== 3 && (HLs
== 0 || HLs
== 1))
5341 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5342 bu64 acc
= get_unextended_acc (cpu
, HLs
);
5346 TRACE_INSN (cpu
, "A%i = LSHIFT A%i BY R%i.L;", HLs
, HLs
, src0
);
5347 TRACE_DECODE (cpu
, "A%i:%#"PRIx64
" shift:%i", HLs
, acc
, shft
);
5350 val
= lshiftrt (cpu
, acc
, -shft
, 40);
5352 val
= lshift (cpu
, acc
, shft
, 40, 0, 0);
5354 STORE (AXREG (HLs
), (val
>> 32) & 0xff);
5355 STORE (AWREG (HLs
), (val
& 0xffffffff));
5356 STORE (ASTATREG (av
[HLs
]), 0);
5359 /* All the insns after this point don't use HLs. */
5360 illegal_instruction (cpu
);
5361 else if ((sop
== 0 || sop
== 1) && sopcde
== 1 && HLs
== 0)
5363 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5367 TRACE_INSN (cpu
, "R%i = ASHIFT R%i BY R%i.L (V%s);",
5368 dst0
, src1
, src0
, sop
== 1 ? ",S" : "");
5370 val0
= (bu16
)DREG (src1
) & 0xFFFF;
5371 val1
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5375 val0
= ashiftrt (cpu
, val0
, -shft
, 16);
5377 val1
= ashiftrt (cpu
, val1
, -shft
, 16);
5381 int sgn0
= (val0
>> 15) & 0x1;
5382 int sgn1
= (val1
>> 15) & 0x1;
5384 val0
= lshift (cpu
, val0
, shft
, 16, sop
== 1, 1);
5386 val1
= lshift (cpu
, val1
, shft
, 16, sop
== 1, 1);
5388 if ((sgn0
!= ((val0
>> 15) & 0x1)) || (sgn1
!= ((val1
>> 15) & 0x1)))
5390 SET_ASTATREG (v
, 1);
5391 SET_ASTATREG (vs
, 1);
5394 SET_ASTAT (ASTAT
| astat
);
5395 STORE (DREG (dst0
), (val1
<< 16) | val0
);
5397 else if ((sop
== 0 || sop
== 1 || sop
== 2) && sopcde
== 2)
5399 /* dregs = [LA]SHIFT dregs BY dregs_lo (opt_S) */
5400 /* sop == 1 : opt_S */
5401 bu32 v
= DREG (src1
);
5402 /* LSHIFT uses sign extended low 6 bits of dregs_lo. */
5403 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5405 TRACE_INSN (cpu
, "R%i = %cSHIFT R%i BY R%i.L%s;", dst0
,
5406 shft
&& sop
!= 2 ? 'A' : 'L', src1
, src0
,
5407 sop
== 1 ? " (S)" : "");
5412 STORE (DREG (dst0
), lshiftrt (cpu
, v
, -shft
, 32));
5414 STORE (DREG (dst0
), ashiftrt (cpu
, v
, -shft
, 32));
5418 bu32 val
= lshift (cpu
, v
, shft
, 32, sop
== 1, 1);
5420 STORE (DREG (dst0
), val
);
5421 if (((v
>> 31) & 0x1) != ((val
>> 31) & 0x1))
5423 SET_ASTATREG (v
, 1);
5424 SET_ASTATREG (vs
, 1);
5428 else if (sop
== 3 && sopcde
== 2)
5430 int shift
= imm6 (DREG (src0
) & 0xFFFF);
5431 bu32 src
= DREG (src1
);
5432 bu32 ret
, cc
= CCREG
;
5434 TRACE_INSN (cpu
, "R%i = ROT R%i BY R%i.L;", dst0
, src1
, src0
);
5435 TRACE_DECODE (cpu
, "R%i:%#x R%i:%#x shift:%i CC:%i",
5436 dst0
, DREG (dst0
), src1
, src
, shift
, cc
);
5438 ret
= rot32 (src
, shift
, &cc
);
5439 STORE (DREG (dst0
), ret
);
5443 else if (sop
== 2 && sopcde
== 1 && HLs
== 0)
5445 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5449 TRACE_INSN (cpu
, "R%i = LSHIFT R%i BY R%i.L (V);", dst0
, src1
, src0
);
5451 val0
= (bu16
)DREG (src1
) & 0xFFFF;
5452 val1
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5456 val0
= lshiftrt (cpu
, val0
, -shft
, 16);
5458 val1
= lshiftrt (cpu
, val1
, -shft
, 16);
5462 val0
= lshift (cpu
, val0
, shft
, 16, 0, 0);
5464 val1
= lshift (cpu
, val1
, shft
, 16, 0, 0);
5466 SET_ASTAT (ASTAT
| astat
);
5467 STORE (DREG (dst0
), (val1
<< 16) | val0
);
5469 else if (sopcde
== 4)
5471 bu32 sv0
= DREG (src0
);
5472 bu32 sv1
= DREG (src1
);
5473 TRACE_INSN (cpu
, "R%i = PACK (R%i.%c, R%i.%c);", dst0
,
5474 src1
, sop
& 2 ? 'H' : 'L',
5475 src0
, sop
& 1 ? 'H' : 'L');
5480 STORE (DREG (dst0
), (sv1
<< 16) | (sv0
& 0xFFFF));
5482 else if (sop
== 0 && sopcde
== 5)
5484 bu32 sv1
= DREG (src1
);
5485 TRACE_INSN (cpu
, "R%i.L = SIGNBITS R%i;", dst0
, src1
);
5486 SET_DREG_L (dst0
, signbits (sv1
, 32));
5488 else if (sop
== 1 && sopcde
== 5)
5490 bu32 sv1
= DREG (src1
);
5491 TRACE_INSN (cpu
, "R%i.L = SIGNBITS R%i.L;", dst0
, src1
);
5492 SET_DREG_L (dst0
, signbits (sv1
, 16));
5494 else if (sop
== 2 && sopcde
== 5)
5496 bu32 sv1
= DREG (src1
);
5497 TRACE_INSN (cpu
, "R%i.L = SIGNBITS R%i.H;", dst0
, src1
);
5498 SET_DREG_L (dst0
, signbits (sv1
>> 16, 16));
5500 else if ((sop
== 0 || sop
== 1) && sopcde
== 6)
5502 bu64 acc
= AXREG (sop
);
5503 TRACE_INSN (cpu
, "R%i.L = SIGNBITS A%i;", dst0
, sop
);
5506 SET_DREG_L (dst0
, signbits (acc
, 40) & 0xFFFF);
5508 else if (sop
== 3 && sopcde
== 6)
5510 bu32 v
= ones (DREG (src1
));
5511 TRACE_INSN (cpu
, "R%i.L = ONES R%i;", dst0
, src1
);
5512 SET_DREG_L (dst0
, v
);
5514 else if (sop
== 0 && sopcde
== 7)
5516 bu16 sv1
= (bu16
)signbits (DREG (src1
), 32);
5517 bu16 sv0
= (bu16
)DREG (src0
);
5520 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i, R%i.L);", dst0
, src1
, src0
);
5522 if ((sv1
& 0x1f) < (sv0
& 0x1f))
5526 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), dst_lo
));
5528 else if (sop
== 1 && sopcde
== 7)
5530 /* Exponent adjust on two 16-bit inputs. Select
5531 smallest norm among 3 inputs. */
5532 bs16 src1_hi
= (DREG (src1
) & 0xFFFF0000) >> 16;
5533 bs16 src1_lo
= (DREG (src1
) & 0xFFFF);
5534 bu16 src0_lo
= (DREG (src0
) & 0xFFFF);
5535 bu16 tmp_hi
, tmp_lo
, tmp
;
5537 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i, R%i.L) (V);", dst0
, src1
, src0
);
5539 tmp_hi
= signbits (src1_hi
, 16);
5540 tmp_lo
= signbits (src1_lo
, 16);
5542 if ((tmp_hi
& 0xf) < (tmp_lo
& 0xf))
5543 if ((tmp_hi
& 0xf) < (src0_lo
& 0xf))
5548 if ((tmp_lo
& 0xf) < (src0_lo
& 0xf))
5552 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), tmp
));
5554 else if (sop
== 2 && sopcde
== 7)
5556 /* Exponent adjust on single 16-bit register. */
5558 bu16 src0_lo
= (bu16
)(DREG (src0
) & 0xFFFF);
5560 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i.L, R%i.L);", dst0
, src1
, src0
);
5562 tmp
= signbits (DREG (src1
) & 0xFFFF, 16);
5564 if ((tmp
& 0xf) < (src0_lo
& 0xf))
5565 SET_DREG_L (dst0
, tmp
);
5567 SET_DREG_L (dst0
, src0_lo
);
5569 else if (sop
== 3 && sopcde
== 7)
5572 bu16 src0_lo
= (bu16
)(DREG (src0
) & 0xFFFF);
5574 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i.H, R%i.L);", dst0
, src1
, src0
);
5576 tmp
= signbits ((DREG (src1
) & 0xFFFF0000) >> 16, 16);
5578 if ((tmp
& 0xf) < (src0_lo
& 0xf))
5579 SET_DREG_L (dst0
, tmp
);
5581 SET_DREG_L (dst0
, src0_lo
);
5583 else if (sop
== 0 && sopcde
== 8)
5585 bu64 acc
= get_unextended_acc (cpu
, 0);
5588 TRACE_INSN (cpu
, "BITMUX (R%i, R%i, A0) (ASR);", src0
, src1
);
5591 illegal_instruction_combination (cpu
);
5596 (((bu64
)s0
& 1) << 38) |
5597 (((bu64
)s1
& 1) << 39);
5598 STORE (DREG (src0
), s0
>> 1);
5599 STORE (DREG (src1
), s1
>> 1);
5603 else if (sop
== 1 && sopcde
== 8)
5605 bu64 acc
= get_unextended_acc (cpu
, 0);
5608 TRACE_INSN (cpu
, "BITMUX (R%i, R%i, A0) (ASL);", src0
, src1
);
5611 illegal_instruction_combination (cpu
);
5618 STORE (DREG (src0
), s0
<< 1);
5619 STORE (DREG (src1
), s1
<< 1);
5623 else if ((sop
== 0 || sop
== 1) && sopcde
== 9)
5625 bs40 acc0
= get_unextended_acc (cpu
, 0);
5628 TRACE_INSN (cpu
, "R%i.L = VIT_MAX (R%i) (AS%c);",
5629 dst0
, src1
, sop
& 1 ? 'R' : 'L');
5632 sH
= DREG (src1
) >> 16;
5635 acc0
= (acc0
& 0xfeffffffffull
) >> 1;
5639 if (((sH
- sL
) & 0x8000) == 0)
5642 acc0
|= (sop
& 1) ? 0x80000000 : 1;
5648 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), out
));
5650 else if ((sop
== 2 || sop
== 3) && sopcde
== 9)
5652 bs40 acc0
= get_extended_acc (cpu
, 0);
5653 bs16 s0L
, s0H
, s1L
, s1H
, out0
, out1
;
5655 TRACE_INSN (cpu
, "R%i = VIT_MAX (R%i, R%i) (AS%c);",
5656 dst0
, src1
, src0
, sop
& 1 ? 'R' : 'L');
5659 s0H
= DREG (src0
) >> 16;
5661 s1H
= DREG (src1
) >> 16;
5668 if (((s0H
- s0L
) & 0x8000) == 0)
5671 acc0
|= (sop
& 1) ? 0x40000000 : 2;
5676 if (((s1H
- s1L
) & 0x8000) == 0)
5679 acc0
|= (sop
& 1) ? 0x80000000 : 1;
5685 STORE (DREG (dst0
), REG_H_L (out1
<< 16, out0
));
5687 else if (sop
== 0 && sopcde
== 10)
5689 bu32 v
= DREG (src0
);
5690 bu32 x
= DREG (src1
);
5691 bu32 mask
= (1 << (v
& 0x1f)) - 1;
5693 TRACE_INSN (cpu
, "R%i = EXTRACT (R%i, R%i.L) (Z);", dst0
, src1
, src0
);
5695 x
>>= ((v
>> 8) & 0x1f);
5697 STORE (DREG (dst0
), x
);
5698 setflags_logical (cpu
, x
);
5700 else if (sop
== 1 && sopcde
== 10)
5702 bu32 v
= DREG (src0
);
5703 bu32 x
= DREG (src1
);
5704 bu32 sgn
= (1 << (v
& 0x1f)) >> 1;
5705 bu32 mask
= (1 << (v
& 0x1f)) - 1;
5707 TRACE_INSN (cpu
, "R%i = EXTRACT (R%i, R%i.L) (X);", dst0
, src1
, src0
);
5709 x
>>= ((v
>> 8) & 0x1f);
5713 STORE (DREG (dst0
), x
);
5714 setflags_logical (cpu
, x
);
5716 else if ((sop
== 2 || sop
== 3) && sopcde
== 10)
5718 /* The first dregs is the "background" while the second dregs is the
5719 "foreground". The fg reg is used to overlay the bg reg and is:
5720 | nnnn nnnn | nnnn nnnn | xxxp pppp | xxxL LLLL |
5721 n = the fg bit field
5722 p = bit position in bg reg to start LSB of fg field
5723 L = number of fg bits to extract
5724 Using (X) sign-extends the fg bit field. */
5725 bu32 fg
= DREG (src0
);
5726 bu32 bg
= DREG (src1
);
5727 bu32 len
= fg
& 0x1f;
5728 bu32 mask
= (1 << min (16, len
)) - 1;
5729 bu32 fgnd
= (fg
>> 16) & mask
;
5730 int shft
= ((fg
>> 8) & 0x1f);
5732 TRACE_INSN (cpu
, "R%i = DEPOSIT (R%i, R%i)%s;", dst0
, src1
, src0
,
5733 sop
== 3 ? " (X)" : "");
5737 /* Sign extend the fg bit field. */
5739 fgnd
= ((bs32
)(bs16
)(fgnd
<< (16 - len
))) >> (16 - len
);
5746 STORE (DREG (dst0
), bg
);
5747 setflags_logical (cpu
, bg
);
5749 else if (sop
== 0 && sopcde
== 11)
5751 bu64 acc0
= get_unextended_acc (cpu
, 0);
5753 TRACE_INSN (cpu
, "R%i.L = CC = BXORSHIFT (A0, R%i);", dst0
, src0
);
5756 SET_CCREG (xor_reduce (acc0
, DREG (src0
)));
5757 SET_DREG (dst0
, REG_H_L (DREG (dst0
), CCREG
));
5760 else if (sop
== 1 && sopcde
== 11)
5762 bu64 acc0
= get_unextended_acc (cpu
, 0);
5764 TRACE_INSN (cpu
, "R%i.L = CC = BXOR (A0, R%i);", dst0
, src0
);
5766 SET_CCREG (xor_reduce (acc0
, DREG (src0
)));
5767 SET_DREG (dst0
, REG_H_L (DREG (dst0
), CCREG
));
5769 else if (sop
== 0 && sopcde
== 12)
5771 bu64 acc0
= get_unextended_acc (cpu
, 0);
5772 bu64 acc1
= get_unextended_acc (cpu
, 1);
5774 TRACE_INSN (cpu
, "A0 = BXORSHIFT (A0, A1, CC);");
5776 acc0
= (acc0
<< 1) | (CCREG
^ xor_reduce (acc0
, acc1
));
5779 else if (sop
== 1 && sopcde
== 12)
5781 bu64 acc0
= get_unextended_acc (cpu
, 0);
5782 bu64 acc1
= get_unextended_acc (cpu
, 1);
5784 TRACE_INSN (cpu
, "R%i.L = CC = BXOR (A0, A1, CC);", dst0
);
5786 SET_CCREG (CCREG
^ xor_reduce (acc0
, acc1
));
5787 acc0
= (acc0
<< 1) | CCREG
;
5788 SET_DREG (dst0
, REG_H_L (DREG (dst0
), CCREG
));
5790 else if ((sop
== 0 || sop
== 1 || sop
== 2) && sopcde
== 13)
5792 int shift
= (sop
+ 1) * 8;
5793 TRACE_INSN (cpu
, "R%i = ALIGN%i (R%i, R%i);", dst0
, shift
, src1
, src0
);
5794 STORE (DREG (dst0
), (DREG (src1
) << (32 - shift
)) | (DREG (src0
) >> shift
));
5797 illegal_instruction (cpu
);
5801 sgn_extend (bu40 org
, bu40 val
, int size
)
5805 if (org
& (1ULL << (size
- 1)))
5807 /* We need to shift in to the MSB which is set. */
5810 for (n
= 40; n
>= 0; n
--)
5811 if (ret
& (1ULL << n
))
5813 ret
|= (-1ULL << n
);
5816 ret
&= ~(-1ULL << 39);
5821 decode_dsp32shiftimm_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
5824 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5825 | 1 | 1 | 0 | 0 |.M.| 1 | 1 | 0 | 1 | - | - |.sopcde............|
5826 |.sop...|.HLs...|.dst0......|.immag.................|.src1......|
5827 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5828 int src1
= ((iw1
>> DSP32ShiftImm_src1_bits
) & DSP32ShiftImm_src1_mask
);
5829 int sop
= ((iw1
>> DSP32ShiftImm_sop_bits
) & DSP32ShiftImm_sop_mask
);
5830 int bit8
= ((iw1
>> 8) & 0x1);
5831 int immag
= ((iw1
>> DSP32ShiftImm_immag_bits
) & DSP32ShiftImm_immag_mask
);
5832 int newimmag
= (-(iw1
>> DSP32ShiftImm_immag_bits
) & DSP32ShiftImm_immag_mask
);
5833 int dst0
= ((iw1
>> DSP32ShiftImm_dst0_bits
) & DSP32ShiftImm_dst0_mask
);
5834 int M
= ((iw0
>> (DSP32ShiftImm_M_bits
- 16)) & DSP32ShiftImm_M_mask
);
5835 int sopcde
= ((iw0
>> (DSP32ShiftImm_sopcde_bits
- 16)) & DSP32ShiftImm_sopcde_mask
);
5836 int HLs
= ((iw1
>> DSP32ShiftImm_HLs_bits
) & DSP32ShiftImm_HLs_mask
);
5838 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32shiftimm
);
5839 TRACE_EXTRACT (cpu
, "%s: M:%i sopcde:%i sop:%i HLs:%i dst0:%i immag:%#x src1:%i",
5840 __func__
, M
, sopcde
, sop
, HLs
, dst0
, immag
, src1
);
5844 bu16 in
= DREG (src1
) >> ((HLs
& 1) ? 16 : 0);
5850 TRACE_INSN (cpu
, "R%i.%c = R%i.%c >>> %i;",
5851 dst0
, (HLs
& 2) ? 'H' : 'L',
5852 src1
, (HLs
& 1) ? 'H' : 'L', newimmag
);
5855 result
= lshift (cpu
, in
, 16 - (newimmag
& 0xF), 16, 0, 1);
5856 if (((result
>> 15) & 0x1) != ((in
>> 15) & 0x1))
5858 SET_ASTATREG (v
, 1);
5859 SET_ASTATREG (vs
, 1);
5863 result
= ashiftrt (cpu
, in
, newimmag
, 16);
5865 else if (sop
== 1 && bit8
== 0)
5867 TRACE_INSN (cpu
, "R%i.%c = R%i.%c << %i (S);",
5868 dst0
, (HLs
& 2) ? 'H' : 'L',
5869 src1
, (HLs
& 1) ? 'H' : 'L', immag
);
5870 result
= lshift (cpu
, in
, immag
, 16, 1, 1);
5872 else if (sop
== 1 && bit8
)
5874 TRACE_INSN (cpu
, "R%i.%c = R%i.%c >>> %i (S);",
5875 dst0
, (HLs
& 2) ? 'H' : 'L',
5876 src1
, (HLs
& 1) ? 'H' : 'L', newimmag
);
5879 int shift
= 32 - newimmag
;
5880 bu16 inshift
= in
<< shift
;
5882 if (((inshift
& ~0xFFFF)
5883 && ((inshift
& ~0xFFFF) >> 16) != ~((bu32
)~0 << shift
))
5884 || (inshift
& 0x8000) != (in
& 0x8000))
5890 SET_ASTATREG (v
, 1);
5891 SET_ASTATREG (vs
, 1);
5896 SET_ASTATREG (v
, 0);
5899 SET_ASTATREG (az
, !result
);
5900 SET_ASTATREG (an
, !!(result
& 0x8000));
5904 result
= ashiftrt (cpu
, in
, newimmag
, 16);
5905 result
= sgn_extend (in
, result
, 16);
5908 else if (sop
== 2 && bit8
)
5910 TRACE_INSN (cpu
, "R%i.%c = R%i.%c >> %i;",
5911 dst0
, (HLs
& 2) ? 'H' : 'L',
5912 src1
, (HLs
& 1) ? 'H' : 'L', newimmag
);
5913 result
= lshiftrt (cpu
, in
, newimmag
, 16);
5915 else if (sop
== 2 && bit8
== 0)
5917 TRACE_INSN (cpu
, "R%i.%c = R%i.%c << %i;",
5918 dst0
, (HLs
& 2) ? 'H' : 'L',
5919 src1
, (HLs
& 1) ? 'H' : 'L', immag
);
5920 result
= lshift (cpu
, in
, immag
, 16, 0, 1);
5923 illegal_instruction (cpu
);
5927 STORE (DREG (dst0
), (v
& 0xFFFF) | (result
<< 16));
5929 STORE (DREG (dst0
), (v
& 0xFFFF0000) | result
);
5931 else if (sop
== 2 && sopcde
== 3 && (HLs
== 1 || HLs
== 0))
5933 int shift
= imm6 (immag
);
5935 bu40 acc
= get_unextended_acc (cpu
, HLs
);
5937 TRACE_INSN (cpu
, "A%i = ROT A%i BY %i;", HLs
, HLs
, shift
);
5938 TRACE_DECODE (cpu
, "A%i:%#"PRIx64
" shift:%i CC:%i", HLs
, acc
, shift
, cc
);
5940 acc
= rot40 (acc
, shift
, &cc
);
5941 SET_AREG (HLs
, acc
);
5945 else if (sop
== 0 && sopcde
== 3 && bit8
== 1 && HLs
< 2)
5947 /* Arithmetic shift, so shift in sign bit copies. */
5949 int shift
= uimm5 (newimmag
);
5951 TRACE_INSN (cpu
, "A%i = A%i >>> %i;", HLs
, HLs
, shift
);
5953 acc
= get_extended_acc (cpu
, HLs
);
5956 /* Sign extend again. */
5957 val
= sgn_extend (acc
, val
, 40);
5959 STORE (AXREG (HLs
), (val
>> 32) & 0xFF);
5960 STORE (AWREG (HLs
), val
& 0xFFFFFFFF);
5961 STORE (ASTATREG (an
), !!(val
& (1ULL << 39)));
5962 STORE (ASTATREG (az
), !val
);
5963 STORE (ASTATREG (av
[HLs
]), 0);
5965 else if (((sop
== 0 && sopcde
== 3 && bit8
== 0)
5966 || (sop
== 1 && sopcde
== 3)) && HLs
< 2)
5969 int shiftup
= uimm5 (immag
);
5970 int shiftdn
= uimm5 (newimmag
);
5972 TRACE_INSN (cpu
, "A%i = A%i %s %i;", HLs
, HLs
,
5973 sop
== 0 ? "<<" : ">>",
5974 sop
== 0 ? shiftup
: shiftdn
);
5977 /* Logical shift, so shift in zeroes. */
5989 acc
<<= 32 - (shiftdn
& 0x1f);
5992 SET_AREG (HLs
, acc
);
5993 SET_ASTATREG (av
[HLs
], 0);
5994 SET_ASTATREG (an
, !!(acc
& 0x8000000000ull
));
5995 SET_ASTATREG (az
, (acc
& 0xFFFFFFFFFF) == 0);
5998 /* All the insns after this point don't use HLs. */
5999 illegal_instruction (cpu
);
6000 else if (sop
== 1 && sopcde
== 1 && bit8
== 0)
6002 int count
= imm5 (immag
);
6003 bu16 val0
= DREG (src1
) >> 16;
6004 bu16 val1
= DREG (src1
) & 0xFFFF;
6007 TRACE_INSN (cpu
, "R%i = R%i << %i (V,S);", dst0
, src1
, count
);
6010 val0
= lshift (cpu
, val0
, count
, 16, 1, 1);
6012 val1
= lshift (cpu
, val1
, count
, 16, 1, 1);
6016 val0
= ashiftrt (cpu
, val0
, -count
, 16);
6018 val1
= ashiftrt (cpu
, val1
, -count
, 16);
6020 SET_ASTAT (ASTAT
| astat
);
6022 STORE (DREG (dst0
), (val0
<< 16) | val1
);
6024 else if (sop
== 2 && sopcde
== 1 && bit8
== 1)
6026 int count
= imm5 (newimmag
);
6027 bu16 val0
= DREG (src1
) & 0xFFFF;
6028 bu16 val1
= DREG (src1
) >> 16;
6031 TRACE_INSN (cpu
, "R%i = R%i >> %i (V);", dst0
, src1
, count
);
6032 val0
= lshiftrt (cpu
, val0
, count
, 16);
6034 val1
= lshiftrt (cpu
, val1
, count
, 16);
6035 SET_ASTAT (ASTAT
| astat
);
6037 STORE (DREG (dst0
), val0
| (val1
<< 16));
6039 else if (sop
== 2 && sopcde
== 1 && bit8
== 0)
6041 int count
= imm5 (immag
);
6042 bu16 val0
= DREG (src1
) & 0xFFFF;
6043 bu16 val1
= DREG (src1
) >> 16;
6046 TRACE_INSN (cpu
, "R%i = R%i << %i (V);", dst0
, src1
, count
);
6047 val0
= lshift (cpu
, val0
, count
, 16, 0, 1);
6049 val1
= lshift (cpu
, val1
, count
, 16, 0, 1);
6050 SET_ASTAT (ASTAT
| astat
);
6052 STORE (DREG (dst0
), val0
| (val1
<< 16));
6054 else if (sopcde
== 1 && (sop
== 0 || (sop
== 1 && bit8
== 1)))
6056 int count
= uimm5 (newimmag
);
6057 bu16 val0
= DREG (src1
) & 0xFFFF;
6058 bu16 val1
= DREG (src1
) >> 16;
6061 TRACE_INSN (cpu
, "R%i = R%i >>> %i %s;", dst0
, src1
, count
,
6062 sop
== 0 ? "(V)" : "(V,S)");
6066 int sgn0
= (val0
>> 15) & 0x1;
6067 int sgn1
= (val1
>> 15) & 0x1;
6069 val0
= lshift (cpu
, val0
, 16 - (count
& 0xF), 16, 0, 1);
6071 val1
= lshift (cpu
, val1
, 16 - (count
& 0xF), 16, 0, 1);
6073 if ((sgn0
!= ((val0
>> 15) & 0x1)) || (sgn1
!= ((val1
>> 15) & 0x1)))
6075 SET_ASTATREG (v
, 1);
6076 SET_ASTATREG (vs
, 1);
6081 val0
= ashiftrt (cpu
, val0
, count
, 16);
6083 val1
= ashiftrt (cpu
, val1
, count
, 16);
6086 SET_ASTAT (ASTAT
| astat
);
6088 STORE (DREG (dst0
), REG_H_L (val1
<< 16, val0
));
6090 else if (sop
== 1 && sopcde
== 2)
6092 int count
= imm6 (immag
);
6094 TRACE_INSN (cpu
, "R%i = R%i << %i (S);", dst0
, src1
, count
);
6097 STORE (DREG (dst0
), ashiftrt (cpu
, DREG (src1
), -count
, 32));
6099 STORE (DREG (dst0
), lshift (cpu
, DREG (src1
), count
, 32, 1, 1));
6101 else if (sop
== 2 && sopcde
== 2)
6103 int count
= imm6 (newimmag
);
6105 TRACE_INSN (cpu
, "R%i = R%i >> %i;", dst0
, src1
, count
);
6108 STORE (DREG (dst0
), lshift (cpu
, DREG (src1
), -count
, 32, 0, 1));
6110 STORE (DREG (dst0
), lshiftrt (cpu
, DREG (src1
), count
, 32));
6112 else if (sop
== 3 && sopcde
== 2)
6114 int shift
= imm6 (immag
);
6115 bu32 src
= DREG (src1
);
6116 bu32 ret
, cc
= CCREG
;
6118 TRACE_INSN (cpu
, "R%i = ROT R%i BY %i;", dst0
, src1
, shift
);
6119 TRACE_DECODE (cpu
, "R%i:%#x R%i:%#x shift:%i CC:%i",
6120 dst0
, DREG (dst0
), src1
, src
, shift
, cc
);
6122 ret
= rot32 (src
, shift
, &cc
);
6123 STORE (DREG (dst0
), ret
);
6127 else if (sop
== 0 && sopcde
== 2)
6129 int count
= imm6 (newimmag
);
6131 TRACE_INSN (cpu
, "R%i = R%i >>> %i;", dst0
, src1
, count
);
6134 STORE (DREG (dst0
), lshift (cpu
, DREG (src1
), -count
, 32, 0, 1));
6136 STORE (DREG (dst0
), ashiftrt (cpu
, DREG (src1
), count
, 32));
6139 illegal_instruction (cpu
);
6143 outc (SIM_CPU
*cpu
, char ch
)
6145 SIM_DESC sd
= CPU_STATE (cpu
);
6146 sim_io_printf (sd
, "%c", ch
);
6148 sim_io_flush_stdout (sd
);
6152 decode_psedoDEBUG_0 (SIM_CPU
*cpu
, bu16 iw0
)
6155 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
6156 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 |.fn....|.grp.......|.reg.......|
6157 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
6158 SIM_DESC sd
= CPU_STATE (cpu
);
6159 int fn
= ((iw0
>> PseudoDbg_fn_bits
) & PseudoDbg_fn_mask
);
6160 int grp
= ((iw0
>> PseudoDbg_grp_bits
) & PseudoDbg_grp_mask
);
6161 int reg
= ((iw0
>> PseudoDbg_reg_bits
) & PseudoDbg_reg_mask
);
6163 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_psedoDEBUG
);
6164 TRACE_EXTRACT (cpu
, "%s: fn:%i grp:%i reg:%i", __func__
, fn
, grp
, reg
);
6166 if ((reg
== 0 || reg
== 1) && fn
== 3)
6168 TRACE_INSN (cpu
, "DBG A%i;", reg
);
6169 sim_io_printf (sd
, "DBG : A%i = %#"PRIx64
"\n", reg
,
6170 get_unextended_acc (cpu
, reg
));
6172 else if (reg
== 3 && fn
== 3)
6174 TRACE_INSN (cpu
, "ABORT;");
6175 cec_exception (cpu
, VEC_SIM_ABORT
);
6178 else if (reg
== 4 && fn
== 3)
6180 TRACE_INSN (cpu
, "HLT;");
6181 cec_exception (cpu
, VEC_SIM_HLT
);
6184 else if (reg
== 5 && fn
== 3)
6185 unhandled_instruction (cpu
, "DBGHALT");
6186 else if (reg
== 6 && fn
== 3)
6187 unhandled_instruction (cpu
, "DBGCMPLX (dregs)");
6188 else if (reg
== 7 && fn
== 3)
6189 unhandled_instruction (cpu
, "DBG");
6190 else if (grp
== 0 && fn
== 2)
6192 TRACE_INSN (cpu
, "OUTC R%i;", reg
);
6193 outc (cpu
, DREG (reg
));
6197 const char *reg_name
= get_allreg_name (grp
, reg
);
6198 TRACE_INSN (cpu
, "DBG %s;", reg_name
);
6199 sim_io_printf (sd
, "DBG : %s = 0x%08x\n", reg_name
,
6200 reg_read (cpu
, grp
, reg
));
6203 unhandled_instruction (cpu
, "PRNT allregs");
6205 illegal_instruction (cpu
);
6209 decode_psedoOChar_0 (SIM_CPU
*cpu
, bu16 iw0
)
6212 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
6213 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |.ch............................|
6214 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
6215 int ch
= ((iw0
>> PseudoChr_ch_bits
) & PseudoChr_ch_mask
);
6217 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_psedoOChar
);
6218 TRACE_EXTRACT (cpu
, "%s: ch:%#x", __func__
, ch
);
6219 TRACE_INSN (cpu
, "OUTC %#x;", ch
);
6225 decode_psedodbg_assert_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
, bu32 pc
)
6228 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
6229 | 1 | 1 | 1 | 1 | 0 | - | - | - | dbgop |.grp.......|.regtest...|
6230 |.expected......................................................|
6231 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
6232 SIM_DESC sd
= CPU_STATE (cpu
);
6233 int expected
= ((iw1
>> PseudoDbg_Assert_expected_bits
) & PseudoDbg_Assert_expected_mask
);
6234 int dbgop
= ((iw0
>> (PseudoDbg_Assert_dbgop_bits
- 16)) & PseudoDbg_Assert_dbgop_mask
);
6235 int grp
= ((iw0
>> (PseudoDbg_Assert_grp_bits
- 16)) & PseudoDbg_Assert_grp_mask
);
6236 int regtest
= ((iw0
>> (PseudoDbg_Assert_regtest_bits
- 16)) & PseudoDbg_Assert_regtest_mask
);
6239 bu32 val
= reg_read (cpu
, grp
, regtest
);
6240 const char *reg_name
= get_allreg_name (grp
, regtest
);
6241 const char *dbg_name
, *dbg_appd
;
6243 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_psedodbg_assert
);
6244 TRACE_EXTRACT (cpu
, "%s: dbgop:%i grp:%i regtest:%i expected:%#x",
6245 __func__
, dbgop
, grp
, regtest
, expected
);
6247 if (dbgop
== 0 || dbgop
== 2)
6249 dbg_name
= dbgop
== 0 ? "DBGA" : "DBGAL";
6250 dbg_appd
= dbgop
== 0 ? ".L" : "";
6253 else if (dbgop
== 1 || dbgop
== 3)
6255 dbg_name
= dbgop
== 1 ? "DBGA" : "DBGAH";
6256 dbg_appd
= dbgop
== 1 ? ".H" : "";
6260 illegal_instruction (cpu
);
6262 actual
= val
>> offset
;
6264 TRACE_INSN (cpu
, "%s (%s%s, 0x%x);", dbg_name
, reg_name
, dbg_appd
, expected
);
6265 if (actual
!= expected
)
6267 sim_io_printf (sd
, "FAIL at %#x: %s (%s%s, 0x%04x); actual value %#x\n",
6268 pc
, dbg_name
, reg_name
, dbg_appd
, expected
, actual
);
6270 /* Decode the actual ASTAT bits that are different. */
6271 if (grp
== 4 && regtest
== 6)
6275 sim_io_printf (sd
, "Expected ASTAT:\n");
6276 for (i
= 0; i
< 16; ++i
)
6277 sim_io_printf (sd
, " %8s%c%i%s",
6278 astat_names
[i
+ offset
],
6279 (((expected
>> i
) & 1) != ((actual
>> i
) & 1))
6281 (expected
>> i
) & 1,
6282 i
== 7 ? "\n" : "");
6283 sim_io_printf (sd
, "\n");
6285 sim_io_printf (sd
, "Actual ASTAT:\n");
6286 for (i
= 0; i
< 16; ++i
)
6287 sim_io_printf (sd
, " %8s%c%i%s",
6288 astat_names
[i
+ offset
],
6289 (((expected
>> i
) & 1) != ((actual
>> i
) & 1))
6292 i
== 7 ? "\n" : "");
6293 sim_io_printf (sd
, "\n");
6296 cec_exception (cpu
, VEC_SIM_DBGA
);
6302 _interp_insn_bfin (SIM_CPU
*cpu
, bu32 pc
)
6307 BFIN_CPU_STATE
.multi_pc
= pc
;
6309 if ((iw0
& 0xc000) != 0xc000)
6311 /* 16-bit opcode. */
6314 INSN_LEN
= insn_len
;
6316 TRACE_EXTRACT (cpu
, "%s: iw0:%#x", __func__
, iw0
);
6317 if ((iw0
& 0xFF00) == 0x0000)
6318 decode_ProgCtrl_0 (cpu
, iw0
, pc
);
6319 else if ((iw0
& 0xFFC0) == 0x0240)
6320 decode_CaCTRL_0 (cpu
, iw0
);
6321 else if ((iw0
& 0xFF80) == 0x0100)
6322 decode_PushPopReg_0 (cpu
, iw0
);
6323 else if ((iw0
& 0xFE00) == 0x0400)
6324 decode_PushPopMultiple_0 (cpu
, iw0
);
6325 else if ((iw0
& 0xFE00) == 0x0600)
6326 decode_ccMV_0 (cpu
, iw0
);
6327 else if ((iw0
& 0xF800) == 0x0800)
6328 decode_CCflag_0 (cpu
, iw0
);
6329 else if ((iw0
& 0xFFE0) == 0x0200)
6330 decode_CC2dreg_0 (cpu
, iw0
);
6331 else if ((iw0
& 0xFF00) == 0x0300)
6332 decode_CC2stat_0 (cpu
, iw0
);
6333 else if ((iw0
& 0xF000) == 0x1000)
6334 decode_BRCC_0 (cpu
, iw0
, pc
);
6335 else if ((iw0
& 0xF000) == 0x2000)
6336 decode_UJUMP_0 (cpu
, iw0
, pc
);
6337 else if ((iw0
& 0xF000) == 0x3000)
6338 decode_REGMV_0 (cpu
, iw0
);
6339 else if ((iw0
& 0xFC00) == 0x4000)
6340 decode_ALU2op_0 (cpu
, iw0
);
6341 else if ((iw0
& 0xFE00) == 0x4400)
6342 decode_PTR2op_0 (cpu
, iw0
);
6343 else if ((iw0
& 0xF800) == 0x4800)
6344 decode_LOGI2op_0 (cpu
, iw0
);
6345 else if ((iw0
& 0xF000) == 0x5000)
6346 decode_COMP3op_0 (cpu
, iw0
);
6347 else if ((iw0
& 0xF800) == 0x6000)
6348 decode_COMPI2opD_0 (cpu
, iw0
);
6349 else if ((iw0
& 0xF800) == 0x6800)
6350 decode_COMPI2opP_0 (cpu
, iw0
);
6351 else if ((iw0
& 0xF000) == 0x8000)
6352 decode_LDSTpmod_0 (cpu
, iw0
);
6353 else if ((iw0
& 0xFF60) == 0x9E60)
6354 decode_dagMODim_0 (cpu
, iw0
);
6355 else if ((iw0
& 0xFFF0) == 0x9F60)
6356 decode_dagMODik_0 (cpu
, iw0
);
6357 else if ((iw0
& 0xFC00) == 0x9C00)
6358 decode_dspLDST_0 (cpu
, iw0
);
6359 else if ((iw0
& 0xF000) == 0x9000)
6360 decode_LDST_0 (cpu
, iw0
);
6361 else if ((iw0
& 0xFC00) == 0xB800)
6362 decode_LDSTiiFP_0 (cpu
, iw0
);
6363 else if ((iw0
& 0xE000) == 0xA000)
6364 decode_LDSTii_0 (cpu
, iw0
);
6367 TRACE_EXTRACT (cpu
, "%s: no matching 16-bit pattern", __func__
);
6368 illegal_instruction_or_combination (cpu
);
6373 /* Grab the next 16 bits to determine if it's a 32-bit or 64-bit opcode. */
6374 iw1
= IFETCH (pc
+ 2);
6375 if ((iw0
& BIT_MULTI_INS
) && (iw0
& 0xe800) != 0xe800 /* not linkage */)
6377 SIM_DESC sd
= CPU_STATE (cpu
);
6378 trace_prefix (sd
, cpu
, NULL_CIA
, pc
, TRACE_LINENUM_P (cpu
),
6379 NULL
, 0, "|| %#"PRIx64
, sim_events_time (sd
));
6381 PARALLEL_GROUP
= BFIN_PARALLEL_GROUP0
;
6386 TRACE_EXTRACT (cpu
, "%s: iw0:%#x iw1:%#x insn_len:%i", __func__
,
6387 iw0
, iw1
, insn_len
);
6389 /* Only cache on first run through (in case of parallel insns). */
6391 INSN_LEN
= insn_len
;
6393 /* Once you're past the first slot, only 16bit insns are valid. */
6394 illegal_instruction_combination (cpu
);
6396 if ((iw0
& 0xf7ff) == 0xc003 && (iw1
& 0xfe00) == 0x1800)
6398 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32mac
);
6399 TRACE_INSN (cpu
, "MNOP;");
6401 else if (((iw0
& 0xFF80) == 0xE080) && ((iw1
& 0x0C00) == 0x0000))
6402 decode_LoopSetup_0 (cpu
, iw0
, iw1
, pc
);
6403 else if (((iw0
& 0xFF00) == 0xE100) && ((iw1
& 0x0000) == 0x0000))
6404 decode_LDIMMhalf_0 (cpu
, iw0
, iw1
);
6405 else if (((iw0
& 0xFE00) == 0xE200) && ((iw1
& 0x0000) == 0x0000))
6406 decode_CALLa_0 (cpu
, iw0
, iw1
, pc
);
6407 else if (((iw0
& 0xFC00) == 0xE400) && ((iw1
& 0x0000) == 0x0000))
6408 decode_LDSTidxI_0 (cpu
, iw0
, iw1
);
6409 else if (((iw0
& 0xFFFE) == 0xE800) && ((iw1
& 0x0000) == 0x0000))
6410 decode_linkage_0 (cpu
, iw0
, iw1
);
6411 else if (((iw0
& 0xF600) == 0xC000) && ((iw1
& 0x0000) == 0x0000))
6412 decode_dsp32mac_0 (cpu
, iw0
, iw1
);
6413 else if (((iw0
& 0xF600) == 0xC200) && ((iw1
& 0x0000) == 0x0000))
6414 decode_dsp32mult_0 (cpu
, iw0
, iw1
);
6415 else if (((iw0
& 0xF7C0) == 0xC400) && ((iw1
& 0x0000) == 0x0000))
6416 decode_dsp32alu_0 (cpu
, iw0
, iw1
);
6417 else if (((iw0
& 0xF7E0) == 0xC600) && ((iw1
& 0x01C0) == 0x0000))
6418 decode_dsp32shift_0 (cpu
, iw0
, iw1
);
6419 else if (((iw0
& 0xF7E0) == 0xC680) && ((iw1
& 0x0000) == 0x0000))
6420 decode_dsp32shiftimm_0 (cpu
, iw0
, iw1
);
6421 else if ((iw0
& 0xFF00) == 0xF800)
6422 decode_psedoDEBUG_0 (cpu
, iw0
), insn_len
= 2;
6423 else if ((iw0
& 0xFF00) == 0xF900)
6424 decode_psedoOChar_0 (cpu
, iw0
), insn_len
= 2;
6425 else if (((iw0
& 0xFF00) == 0xF000) && ((iw1
& 0x0000) == 0x0000))
6426 decode_psedodbg_assert_0 (cpu
, iw0
, iw1
, pc
);
6429 TRACE_EXTRACT (cpu
, "%s: no matching 32-bit pattern", __func__
);
6430 illegal_instruction (cpu
);
6437 interp_insn_bfin (SIM_CPU
*cpu
, bu32 pc
)
6442 BFIN_CPU_STATE
.n_stores
= 0;
6443 PARALLEL_GROUP
= BFIN_PARALLEL_NONE
;
6444 DIS_ALGN_EXPT
&= ~1;
6448 insn_len
= _interp_insn_bfin (cpu
, pc
);
6450 /* Proper display of multiple issue instructions. */
6453 PARALLEL_GROUP
= BFIN_PARALLEL_GROUP1
;
6454 _interp_insn_bfin (cpu
, pc
+ 4);
6455 PARALLEL_GROUP
= BFIN_PARALLEL_GROUP2
;
6456 _interp_insn_bfin (cpu
, pc
+ 6);
6458 for (i
= 0; i
< BFIN_CPU_STATE
.n_stores
; i
++)
6460 bu32
*addr
= BFIN_CPU_STATE
.stores
[i
].addr
;
6461 *addr
= BFIN_CPU_STATE
.stores
[i
].val
;
6462 TRACE_REGISTER (cpu
, "dequeuing write %s = %#x",
6463 get_store_name (cpu
, addr
), *addr
);
6466 cycles_inc (cpu
, CYCLE_DELAY
);
6468 /* Set back to zero in case a pending CEC event occurs
6469 after this this insn. */