1 /* Simulator for Analog Devices Blackfin processors.
3 Copyright (C) 2005-2013 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/>. */
28 #include "opcode/bfin.h"
30 #include "dv-bfin_cec.h"
31 #include "dv-bfin_mmu.h"
33 #define HOST_LONG_WORD_SIZE (sizeof (long) * 8)
35 #define SIGNEXTEND(v, n) \
36 (((bs32)(v) << (HOST_LONG_WORD_SIZE - (n))) >> (HOST_LONG_WORD_SIZE - (n)))
38 static __attribute__ ((noreturn
)) void
39 illegal_instruction (SIM_CPU
*cpu
)
41 TRACE_INSN (cpu
, "ILLEGAL INSTRUCTION");
43 cec_exception (cpu
, VEC_UNDEF_I
);
46 static __attribute__ ((noreturn
)) void
47 illegal_instruction_combination (SIM_CPU
*cpu
)
49 TRACE_INSN (cpu
, "ILLEGAL INSTRUCTION COMBINATION");
51 cec_exception (cpu
, VEC_ILGAL_I
);
54 static __attribute__ ((noreturn
)) void
55 illegal_instruction_or_combination (SIM_CPU
*cpu
)
57 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
58 illegal_instruction_combination (cpu
);
60 illegal_instruction (cpu
);
63 static __attribute__ ((noreturn
)) void
64 unhandled_instruction (SIM_CPU
*cpu
, const char *insn
)
66 SIM_DESC sd
= CPU_STATE (cpu
);
70 TRACE_EVENTS (cpu
, "unhandled instruction");
73 iw1
= IFETCH (PCREG
+ 2);
74 iw2
= ((bu32
)iw0
<< 16) | iw1
;
76 sim_io_eprintf (sd
, "Unhandled instruction at 0x%08x (%s opcode 0x", PCREG
, insn
);
77 if ((iw0
& 0xc000) == 0xc000)
78 sim_io_eprintf (sd
, "%08x", iw2
);
80 sim_io_eprintf (sd
, "%04x", iw0
);
82 sim_io_eprintf (sd
, ") ... aborting\n");
84 illegal_instruction (cpu
);
87 static const char * const astat_names
[] =
125 c_0
, c_1
, c_4
, c_2
, c_uimm2
, c_uimm3
, c_imm3
, c_pcrel4
,
126 c_imm4
, c_uimm4s4
, c_uimm4s4d
, c_uimm4
, c_uimm4s2
, c_negimm5s4
, c_imm5
,
127 c_imm5d
, c_uimm5
, c_imm6
, c_imm7
, c_imm7d
, c_imm8
, c_uimm8
, c_pcrel8
,
128 c_uimm8s4
, c_pcrel8s4
, c_lppcrel10
, c_pcrel10
, c_pcrel12
, c_imm16s4
,
129 c_luimm16
, c_imm16
, c_imm16d
, c_huimm16
, c_rimm16
, c_imm16s2
, c_uimm16s4
,
130 c_uimm16s4d
, c_uimm16
, c_pcrel24
, c_uimm32
, c_imm32
, c_huimm32
, c_huimm32e
,
147 } constant_formats
[] =
149 { "0", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
150 { "1", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
151 { "4", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
152 { "2", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
153 { "uimm2", 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
154 { "uimm3", 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
155 { "imm3", 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
156 { "pcrel4", 4, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0},
157 { "imm4", 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
158 { "uimm4s4", 4, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0},
159 { "uimm4s4d", 4, 0, 0, 0, 2, 0, 0, 1, 1, 0, 0},
160 { "uimm4", 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
161 { "uimm4s2", 4, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0},
162 { "negimm5s4", 5, 0, 1, 0, 2, 0, 1, 0, 0, 0, 0},
163 { "imm5", 5, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
164 { "imm5d", 5, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0},
165 { "uimm5", 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
166 { "imm6", 6, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
167 { "imm7", 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
168 { "imm7d", 7, 0, 1, 0, 0, 0, 0, 0, 1, 3, 0},
169 { "imm8", 8, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
170 { "uimm8", 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
171 { "pcrel8", 8, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0},
172 { "uimm8s4", 8, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0},
173 { "pcrel8s4", 8, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0},
174 { "lppcrel10", 10, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0},
175 { "pcrel10", 10, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
176 { "pcrel12", 12, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
177 { "imm16s4", 16, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0},
178 { "luimm16", 16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
179 { "imm16", 16, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
180 { "imm16d", 16, 0, 1, 0, 0, 0, 0, 0, 1, 3, 0},
181 { "huimm16", 16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
182 { "rimm16", 16, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0},
183 { "imm16s2", 16, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0},
184 { "uimm16s4", 16, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0},
185 { "uimm16s4d", 16, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0},
186 { "uimm16", 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
187 { "pcrel24", 24, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
188 { "uimm32", 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
189 { "imm32", 32, 0, 1, 0, 0, 0, 0, 0, 1, 3, 0},
190 { "huimm32", 32, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
191 { "huimm32e", 32, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
195 fmtconst_str (const_forms_t cf
, bs32 x
, bu32 pc
)
199 if (constant_formats
[cf
].reloc
)
201 bu32 ea
= (((constant_formats
[cf
].pcrel
? SIGNEXTEND (x
, constant_formats
[cf
].nbits
)
202 : x
) + constant_formats
[cf
].offset
) << constant_formats
[cf
].scale
);
203 if (constant_formats
[cf
].pcrel
)
205 /*if (outf->symbol_at_address_func (ea, outf) || !constant_formats[cf].exact)
207 outf->print_address_func (ea, outf);
212 sprintf (buf
, "%#x", x
);
217 /* Negative constants have an implied sign bit. */
218 if (constant_formats
[cf
].negative
)
220 int nb
= constant_formats
[cf
].nbits
+ 1;
222 x
= x
| (1 << constant_formats
[cf
].nbits
);
223 x
= SIGNEXTEND (x
, nb
);
226 x
= constant_formats
[cf
].issigned
? SIGNEXTEND (x
, constant_formats
[cf
].nbits
) : x
;
228 if (constant_formats
[cf
].offset
)
229 x
+= constant_formats
[cf
].offset
;
231 if (constant_formats
[cf
].scale
)
232 x
<<= constant_formats
[cf
].scale
;
234 if (constant_formats
[cf
].decimal
)
235 sprintf (buf
, "%*i", constant_formats
[cf
].leading
, x
);
238 if (constant_formats
[cf
].issigned
&& x
< 0)
239 sprintf (buf
, "-0x%x", abs (x
));
241 sprintf (buf
, "0x%x", x
);
248 fmtconst_val (const_forms_t cf
, bu32 x
, bu32 pc
)
250 if (0 && constant_formats
[cf
].reloc
)
252 bu32 ea
= (((constant_formats
[cf
].pcrel
253 ? (bu32
)SIGNEXTEND (x
, constant_formats
[cf
].nbits
)
254 : x
) + constant_formats
[cf
].offset
)
255 << constant_formats
[cf
].scale
);
256 if (constant_formats
[cf
].pcrel
)
262 /* Negative constants have an implied sign bit. */
263 if (constant_formats
[cf
].negative
)
265 int nb
= constant_formats
[cf
].nbits
+ 1;
266 x
= x
| (1 << constant_formats
[cf
].nbits
);
267 x
= SIGNEXTEND (x
, nb
);
269 else if (constant_formats
[cf
].issigned
)
270 x
= SIGNEXTEND (x
, constant_formats
[cf
].nbits
);
272 x
+= constant_formats
[cf
].offset
;
273 x
<<= constant_formats
[cf
].scale
;
278 #define uimm16s4(x) fmtconst_val (c_uimm16s4, x, 0)
279 #define uimm16s4_str(x) fmtconst_str (c_uimm16s4, x, 0)
280 #define uimm16s4d(x) fmtconst_val (c_uimm16s4d, x, 0)
281 #define pcrel4(x) fmtconst_val (c_pcrel4, x, pc)
282 #define pcrel8(x) fmtconst_val (c_pcrel8, x, pc)
283 #define pcrel8s4(x) fmtconst_val (c_pcrel8s4, x, pc)
284 #define pcrel10(x) fmtconst_val (c_pcrel10, x, pc)
285 #define pcrel12(x) fmtconst_val (c_pcrel12, x, pc)
286 #define negimm5s4(x) fmtconst_val (c_negimm5s4, x, 0)
287 #define negimm5s4_str(x) fmtconst_str (c_negimm5s4, x, 0)
288 #define rimm16(x) fmtconst_val (c_rimm16, x, 0)
289 #define huimm16(x) fmtconst_val (c_huimm16, x, 0)
290 #define imm16(x) fmtconst_val (c_imm16, x, 0)
291 #define imm16_str(x) fmtconst_str (c_imm16, x, 0)
292 #define imm16d(x) fmtconst_val (c_imm16d, x, 0)
293 #define uimm2(x) fmtconst_val (c_uimm2, x, 0)
294 #define uimm3(x) fmtconst_val (c_uimm3, x, 0)
295 #define uimm3_str(x) fmtconst_str (c_uimm3, x, 0)
296 #define luimm16(x) fmtconst_val (c_luimm16, x, 0)
297 #define luimm16_str(x) fmtconst_str (c_luimm16, x, 0)
298 #define uimm4(x) fmtconst_val (c_uimm4, x, 0)
299 #define uimm4_str(x) fmtconst_str (c_uimm4, x, 0)
300 #define uimm5(x) fmtconst_val (c_uimm5, x, 0)
301 #define uimm5_str(x) fmtconst_str (c_uimm5, x, 0)
302 #define imm16s2(x) fmtconst_val (c_imm16s2, x, 0)
303 #define imm16s2_str(x) fmtconst_str (c_imm16s2, x, 0)
304 #define uimm8(x) fmtconst_val (c_uimm8, x, 0)
305 #define imm16s4(x) fmtconst_val (c_imm16s4, x, 0)
306 #define imm16s4_str(x) fmtconst_str (c_imm16s4, x, 0)
307 #define uimm4s2(x) fmtconst_val (c_uimm4s2, x, 0)
308 #define uimm4s2_str(x) fmtconst_str (c_uimm4s2, x, 0)
309 #define uimm4s4(x) fmtconst_val (c_uimm4s4, x, 0)
310 #define uimm4s4_str(x) fmtconst_str (c_uimm4s4, x, 0)
311 #define uimm4s4d(x) fmtconst_val (c_uimm4s4d, x, 0)
312 #define lppcrel10(x) fmtconst_val (c_lppcrel10, x, pc)
313 #define imm3(x) fmtconst_val (c_imm3, x, 0)
314 #define imm3_str(x) fmtconst_str (c_imm3, x, 0)
315 #define imm4(x) fmtconst_val (c_imm4, x, 0)
316 #define uimm8s4(x) fmtconst_val (c_uimm8s4, x, 0)
317 #define imm5(x) fmtconst_val (c_imm5, x, 0)
318 #define imm5d(x) fmtconst_val (c_imm5d, x, 0)
319 #define imm6(x) fmtconst_val (c_imm6, x, 0)
320 #define imm7(x) fmtconst_val (c_imm7, x, 0)
321 #define imm7_str(x) fmtconst_str (c_imm7, x, 0)
322 #define imm7d(x) fmtconst_val (c_imm7d, x, 0)
323 #define imm8(x) fmtconst_val (c_imm8, x, 0)
324 #define pcrel24(x) fmtconst_val (c_pcrel24, x, pc)
325 #define pcrel24_str(x) fmtconst_str (c_pcrel24, x, pc)
326 #define uimm16(x) fmtconst_val (c_uimm16, x, 0)
327 #define uimm32(x) fmtconst_val (c_uimm32, x, 0)
328 #define imm32(x) fmtconst_val (c_imm32, x, 0)
329 #define huimm32(x) fmtconst_val (c_huimm32, x, 0)
330 #define huimm32e(x) fmtconst_val (c_huimm32e, x, 0)
332 /* Table C-4. Core Register Encoding Map. */
333 const char * const greg_names
[] =
335 "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7",
336 "P0", "P1", "P2", "P3", "P4", "P5", "SP", "FP",
337 "I0", "I1", "I2", "I3", "M0", "M1", "M2", "M3",
338 "B0", "B1", "B2", "B3", "L0", "L1", "L2", "L3",
339 "A0.X", "A0.W", "A1.X", "A1.W", "<res>", "<res>", "ASTAT", "RETS",
340 "<res>", "<res>", "<res>", "<res>", "<res>", "<res>", "<res>", "<res>",
341 "LC0", "LT0", "LB0", "LC1", "LT1", "LB1", "CYCLES", "CYCLES2",
342 "USP", "SEQSTAT", "SYSCFG", "RETI", "RETX", "RETN", "RETE", "EMUDAT",
345 get_allreg_name (int grp
, int reg
)
347 return greg_names
[(grp
<< 3) | reg
];
350 get_preg_name (int reg
)
352 return get_allreg_name (1, reg
);
356 reg_is_reserved (int grp
, int reg
)
358 return (grp
== 4 && (reg
== 4 || reg
== 5)) || (grp
== 5);
362 get_allreg (SIM_CPU
*cpu
, int grp
, int reg
)
364 int fullreg
= (grp
<< 3) | reg
;
365 /* REG_R0, REG_R1, REG_R2, REG_R3, REG_R4, REG_R5, REG_R6, REG_R7,
366 REG_P0, REG_P1, REG_P2, REG_P3, REG_P4, REG_P5, REG_SP, REG_FP,
367 REG_I0, REG_I1, REG_I2, REG_I3, REG_M0, REG_M1, REG_M2, REG_M3,
368 REG_B0, REG_B1, REG_B2, REG_B3, REG_L0, REG_L1, REG_L2, REG_L3,
369 REG_A0x, REG_A0w, REG_A1x, REG_A1w, , , REG_ASTAT, REG_RETS,
371 REG_LC0, REG_LT0, REG_LB0, REG_LC1, REG_LT1, REG_LB1, REG_CYCLES,
373 REG_USP, REG_SEQSTAT, REG_SYSCFG, REG_RETI, REG_RETX, REG_RETN, REG_RETE,
375 switch (fullreg
>> 2)
377 case 0: case 1: return &DREG (reg
);
378 case 2: case 3: return &PREG (reg
);
379 case 4: return &IREG (reg
& 3);
380 case 5: return &MREG (reg
& 3);
381 case 6: return &BREG (reg
& 3);
382 case 7: return &LREG (reg
& 3);
386 case 32: return &AXREG (0);
387 case 33: return &AWREG (0);
388 case 34: return &AXREG (1);
389 case 35: return &AWREG (1);
390 case 39: return &RETSREG
;
391 case 48: return &LCREG (0);
392 case 49: return <REG (0);
393 case 50: return &LBREG (0);
394 case 51: return &LCREG (1);
395 case 52: return <REG (1);
396 case 53: return &LBREG (1);
397 case 54: return &CYCLESREG
;
398 case 55: return &CYCLES2REG
;
399 case 56: return &USPREG
;
400 case 57: return &SEQSTATREG
;
401 case 58: return &SYSCFGREG
;
402 case 59: return &RETIREG
;
403 case 60: return &RETXREG
;
404 case 61: return &RETNREG
;
405 case 62: return &RETEREG
;
406 case 63: return &EMUDAT_INREG
;
408 illegal_instruction (cpu
);
413 amod0 (int s0
, int x0
)
415 static const char * const mod0
[] = {
416 "", " (S)", " (CO)", " (SCO)",
418 int i
= s0
+ (x0
<< 1);
420 if (i
< ARRAY_SIZE (mod0
))
427 amod0amod2 (int s0
, int x0
, int aop0
)
429 static const char * const mod02
[] = {
430 "", " (S)", " (CO)", " (SCO)",
432 " (ASR)", " (S, ASR)", " (CO, ASR)", " (SCO, ASR)",
433 " (ASL)", " (S, ASL)", " (CO, ASL)", " (SCO, ASL)",
435 int i
= s0
+ (x0
<< 1) + (aop0
<< 2);
437 if (i
< ARRAY_SIZE (mod02
))
444 amod1 (int s0
, int x0
)
446 static const char * const mod1
[] = {
449 int i
= s0
+ (x0
<< 1);
451 if (i
< ARRAY_SIZE (mod1
))
458 mac_optmode (int mmod
, int MM
)
460 static const char * const omode
[] = {
461 [(M_S2RND
<< 1) + 0] = " (S2RND)",
462 [(M_T
<< 1) + 0] = " (T)",
463 [(M_W32
<< 1) + 0] = " (W32)",
464 [(M_FU
<< 1) + 0] = " (FU)",
465 [(M_TFU
<< 1) + 0] = " (TFU)",
466 [(M_IS
<< 1) + 0] = " (IS)",
467 [(M_ISS2
<< 1) + 0] = " (ISS2)",
468 [(M_IH
<< 1) + 0] = " (IH)",
469 [(M_IU
<< 1) + 0] = " (IU)",
470 [(M_S2RND
<< 1) + 1] = " (M, S2RND)",
471 [(M_T
<< 1) + 1] = " (M, T)",
472 [(M_W32
<< 1) + 1] = " (M, W32)",
473 [(M_FU
<< 1) + 1] = " (M, FU)",
474 [(M_TFU
<< 1) + 1] = " (M, TFU)",
475 [(M_IS
<< 1) + 1] = " (M, IS)",
476 [(M_ISS2
<< 1) + 1] = " (M, ISS2)",
477 [(M_IH
<< 1) + 1] = " (M, IH)",
478 [(M_IU
<< 1) + 1] = " (M, IU)",
480 int i
= MM
+ (mmod
<< 1);
482 if (i
< ARRAY_SIZE (omode
) && omode
[i
])
489 get_store_name (SIM_CPU
*cpu
, bu32
*p
)
491 if (p
>= &DREG (0) && p
<= &CYCLESREG
)
492 return greg_names
[p
- &DREG (0)];
493 else if (p
== &AXREG (0))
494 return greg_names
[4 * 8 + 0];
495 else if (p
== &AWREG (0))
496 return greg_names
[4 * 8 + 1];
497 else if (p
== &AXREG (1))
498 return greg_names
[4 * 8 + 2];
499 else if (p
== &AWREG (1))
500 return greg_names
[4 * 8 + 3];
501 else if (p
== &ASTATREG (av0
))
503 else if (p
== &ASTATREG (av0s
))
504 return "ASTAT[av0s]";
505 else if (p
== &ASTATREG (av1
))
507 else if (p
== &ASTATREG (av1s
))
508 return "ASTAT[av1s]";
509 else if (p
== &ASTATREG (v
))
511 else if (p
== &ASTATREG (vs
))
513 else if (p
== &ASTATREG (v_copy
))
514 return "ASTAT[v_copy]";
515 else if (p
== &ASTATREG (az
))
517 else if (p
== &ASTATREG (an
))
519 else if (p
== &ASTATREG (az
))
521 else if (p
== &ASTATREG (ac0
))
523 else if (p
== &ASTATREG (ac0_copy
))
524 return "ASTAT[ac0_copy]";
527 /* Worry about this when we start to STORE() it. */
528 sim_io_eprintf (CPU_STATE (cpu
), "STORE(): unknown register\n");
534 queue_store (SIM_CPU
*cpu
, bu32
*addr
, bu32 val
)
536 struct store
*s
= &BFIN_CPU_STATE
.stores
[BFIN_CPU_STATE
.n_stores
];
539 TRACE_REGISTER (cpu
, "queuing write %s = %#x",
540 get_store_name (cpu
, addr
), val
);
541 ++BFIN_CPU_STATE
.n_stores
;
543 #define STORE(X, Y) \
545 if (BFIN_CPU_STATE.n_stores == 20) abort (); \
546 queue_store (cpu, &(X), (Y)); \
550 setflags_nz (SIM_CPU
*cpu
, bu32 val
)
552 SET_ASTATREG (az
, val
== 0);
553 SET_ASTATREG (an
, val
>> 31);
557 setflags_nz_2x16 (SIM_CPU
*cpu
, bu32 val
)
559 SET_ASTATREG (an
, (bs16
)val
< 0 || (bs16
)(val
>> 16) < 0);
560 SET_ASTATREG (az
, (bs16
)val
== 0 || (bs16
)(val
>> 16) == 0);
564 setflags_logical (SIM_CPU
*cpu
, bu32 val
)
566 setflags_nz (cpu
, val
);
567 SET_ASTATREG (ac0
, 0);
572 add_brev (bu32 addend1
, bu32 addend2
)
581 for (i
= 31; i
>= 0; --i
)
583 b
= ((addend1
& mask
) >> i
) + ((addend2
& mask
) >> i
);
594 /* This is a bit crazy, but we want to simulate the hardware behavior exactly
595 rather than worry about the circular buffers being used correctly. Which
596 isn't to say there isn't room for improvement here, just that we want to
597 be conservative. See also dagsub(). */
599 dagadd (SIM_CPU
*cpu
, int dagno
, bs32 M
)
601 bu64 i
= IREG (dagno
);
602 bu64 l
= LREG (dagno
);
603 bu64 b
= BREG (dagno
);
607 bu32 im32
, iml32
, lb32
, res
;
610 /* A naïve implementation that mostly works:
612 if (l && res >= b + l)
614 STORE (IREG (dagno), res);
629 if ((i
& msb
) || (IM
& car
))
630 res
= (im32
< b
) ? iml32
: im32
;
632 res
= (im32
< b
) ? im32
: iml32
;
638 if ((IM
& car
) == (LB
& car
))
639 res
= (im32
< lb32
) ? im32
: iml32
;
641 res
= (im32
< lb32
) ? iml32
: im32
;
644 STORE (IREG (dagno
), res
);
648 /* See dagadd() notes above. */
650 dagsub (SIM_CPU
*cpu
, int dagno
, bs32 M
)
652 bu64 i
= IREG (dagno
);
653 bu64 l
= LREG (dagno
);
654 bu64 b
= BREG (dagno
);
657 bu64 mbar
= (bu32
)(~m
+ 1);
659 bu32 b32
, im32
, iml32
, lb32
, res
;
662 /* A naïve implementation that mostly works:
666 STORE (IREG (dagno), newi);
681 if (!!((i
& msb
) && (IM
& car
)) == !!(LB
& car
))
682 res
= (im32
< lb32
) ? im32
: iml32
;
684 res
= (im32
< lb32
) ? iml32
: im32
;
691 if (M
== 0 || IM
& car
)
692 res
= (im32
< b32
) ? iml32
: im32
;
694 res
= (im32
< b32
) ? im32
: iml32
;
697 STORE (IREG (dagno
), res
);
702 ashiftrt (SIM_CPU
*cpu
, bu40 val
, int cnt
, int size
)
704 int real_cnt
= cnt
> size
? size
: cnt
;
705 bu40 sgn
= ~(((val
& 0xFFFFFFFFFFull
) >> (size
- 1)) - 1);
706 int sgncnt
= size
- real_cnt
;
708 sgn
<<= 16, sgncnt
-= 16;
711 val
>>= 16, real_cnt
-= 16;
714 SET_ASTATREG (an
, val
>> (size
- 1));
715 SET_ASTATREG (az
, val
== 0);
722 lshiftrt (SIM_CPU
*cpu
, bu64 val
, int cnt
, int size
)
724 int real_cnt
= cnt
> size
? size
: cnt
;
726 val
>>= 16, real_cnt
-= 16;
737 val
&= 0xFFFFFFFFFFull
;
740 illegal_instruction (cpu
);
743 SET_ASTATREG (an
, val
>> (size
- 1));
744 SET_ASTATREG (az
, val
== 0);
751 lshift (SIM_CPU
*cpu
, bu64 val
, int cnt
, int size
, bool saturate
, bool overflow
)
753 int v_i
, real_cnt
= cnt
> size
? size
: cnt
;
754 bu64 sgn
= ~((val
>> (size
- 1)) - 1);
755 int mask_cnt
= size
- 1;
756 bu64 masked
, new_val
= val
;
764 new_val
<<= 16, real_cnt
-= 16;
766 new_val
<<= real_cnt
;
768 masked
= new_val
& mask
;
770 /* If an operation would otherwise cause a positive value to overflow
771 and become negative, instead, saturation limits the result to the
772 maximum positive value for the size register being used.
774 Conversely, if an operation would otherwise cause a negative value
775 to overflow and become positive, saturation limits the result to the
776 maximum negative value for the register size.
778 However, it's a little more complex than looking at sign bits, we need
779 to see if we are shifting the sign information away... */
780 if (((val
<< cnt
) >> size
) == 0
781 || (((val
<< cnt
) >> size
) == ~(~0 << cnt
)
782 && ((new_val
>> (size
- 1)) & 0x1)))
791 if (saturate
&& (v_i
|| ((val
>> (size
- 1)) != (new_val
>> (size
- 1)))))
793 new_val
= (val
>> (size
- 1)) == 0 ? 0x7fff : 0x8000;
798 new_val
&= 0xFFFFFFFF;
799 masked
&= 0xFFFFFFFF;
804 || (!sgn
&& new_val
== 0 && val
!= 0)))
806 new_val
= sgn
== 0 ? 0x7fffffff : 0x80000000;
811 new_val
&= 0xFFFFFFFFFFull
;
812 masked
&= 0xFFFFFFFFFFull
;
815 illegal_instruction (cpu
);
819 SET_ASTATREG (an
, new_val
>> (size
- 1));
820 SET_ASTATREG (az
, new_val
== 0);
823 SET_ASTATREG (v
, overflow
&& v_i
);
825 SET_ASTATREG (vs
, 1);
832 algn (bu32 l
, bu32 h
, bu32 aln
)
837 return (l
>> (8 * aln
)) | (h
<< (32 - 8 * aln
));
841 saturate_s16 (bu64 val
, bu32
*overflow
)
843 if ((bs64
)val
< -0x8000ll
)
849 if ((bs64
)val
> 0x7fff)
859 rot40 (bu40 val
, int shift
, bu32
*cc
)
861 const int nbits
= 40;
864 shift
= CLAMP (shift
, -nbits
, nbits
);
868 /* Reduce everything to rotate left. */
872 ret
= shift
== nbits
? 0 : val
<< shift
;
873 ret
|= shift
== 1 ? 0 : val
>> ((nbits
+ 1) - shift
);
874 ret
|= (bu40
)*cc
<< (shift
- 1);
875 *cc
= (val
>> (nbits
- shift
)) & 1;
881 rot32 (bu32 val
, int shift
, bu32
*cc
)
883 const int nbits
= 32;
886 shift
= CLAMP (shift
, -nbits
, nbits
);
890 /* Reduce everything to rotate left. */
894 ret
= shift
== nbits
? 0 : val
<< shift
;
895 ret
|= shift
== 1 ? 0 : val
>> ((nbits
+ 1) - shift
);
896 ret
|= (bu32
)*cc
<< (shift
- 1);
897 *cc
= (val
>> (nbits
- shift
)) & 1;
903 add32 (SIM_CPU
*cpu
, bu32 a
, bu32 b
, int carry
, int sat
)
905 int flgs
= (a
>> 31) & 1;
906 int flgo
= (b
>> 31) & 1;
908 int flgn
= (v
>> 31) & 1;
909 int overflow
= (flgs
^ flgn
) & (flgo
^ flgn
);
916 flgn
= (v
>> 31) & 1;
919 SET_ASTATREG (an
, flgn
);
921 SET_ASTATREG (vs
, 1);
922 SET_ASTATREG (v
, overflow
);
923 ASTATREG (v_internal
) |= overflow
;
924 SET_ASTATREG (az
, v
== 0);
926 SET_ASTATREG (ac0
, ~a
< b
);
932 sub32 (SIM_CPU
*cpu
, bu32 a
, bu32 b
, int carry
, int sat
, int parallel
)
934 int flgs
= (a
>> 31) & 1;
935 int flgo
= (b
>> 31) & 1;
937 int flgn
= (v
>> 31) & 1;
938 int overflow
= (flgs
^ flgo
) & (flgn
^ flgs
);
945 flgn
= (v
>> 31) & 1;
948 if (!parallel
|| flgn
)
949 SET_ASTATREG (an
, flgn
);
951 SET_ASTATREG (vs
, 1);
952 if (!parallel
|| overflow
)
953 SET_ASTATREG (v
, overflow
);
954 if (!parallel
|| overflow
)
955 ASTATREG (v_internal
) |= overflow
;
956 if (!parallel
|| v
== 0)
957 SET_ASTATREG (az
, v
== 0);
958 if (carry
&& (!parallel
|| b
<= a
))
959 SET_ASTATREG (ac0
, b
<= a
);
965 add16 (SIM_CPU
*cpu
, bu16 a
, bu16 b
, bu32
*carry
, bu32
*overfl
,
966 bu32
*zero
, bu32
*neg
, int sat
, int scale
)
968 int flgs
= (a
>> 15) & 1;
969 int flgo
= (b
>> 15) & 1;
970 bs64 v
= (bs16
)a
+ (bs16
)b
;
971 int flgn
= (v
>> 15) & 1;
972 int overflow
= (flgs
^ flgn
) & (flgo
^ flgn
);
980 v
= (a
>> 1) + (a
& 0x8000) + (b
>> 1) + (b
& 0x8000)
981 + (((a
& 1) + (b
& 1)) >> 1);
989 illegal_instruction (cpu
);
992 flgn
= (v
>> 15) & 1;
993 overflow
= (flgs
^ flgn
) & (flgo
^ flgn
);
995 if (v
> (bs64
)0xffff)
999 v
= saturate_s16 (v
, 0);
1002 *neg
|= (v
>> 15) & 1;
1004 *overfl
|= overflow
;
1006 *zero
|= (v
& 0xFFFF) == 0;
1008 *carry
|= ((bu16
)~a
< (bu16
)b
);
1014 sub16 (SIM_CPU
*cpu
, bu16 a
, bu16 b
, bu32
*carry
, bu32
*overfl
,
1015 bu32
*zero
, bu32
*neg
, int sat
, int scale
)
1017 int flgs
= (a
>> 15) & 1;
1018 int flgo
= (b
>> 15) & 1;
1019 bs64 v
= (bs16
)a
- (bs16
)b
;
1020 int flgn
= (v
>> 15) & 1;
1021 int overflow
= (flgs
^ flgo
) & (flgn
^ flgs
);
1030 v
= ((a
>> 1) + (a
& 0x8000)) - ( (b
>> 1) + (b
& 0x8000))
1031 + (((a
& 1)-(b
& 1)));
1034 v
= ((v
& 0xFFFF) >> 1);
1035 if ((!flgs
& !flgo
& flgn
)
1036 || (flgs
& !flgo
& !flgn
)
1037 || (flgs
& flgo
& flgn
)
1038 || (flgs
& !flgo
& flgn
))
1042 flgn
= (v
>> 15) & 1;
1043 overflow
= (flgs
^ flgo
) & (flgn
^ flgs
);
1048 if (v
> (bs64
)0x7fff || v
< (bs64
)-0xffff)
1052 illegal_instruction (cpu
);
1057 v
= saturate_s16 (v
, 0);
1060 *neg
|= (v
>> 15) & 1;
1062 *zero
|= (v
& 0xFFFF) == 0;
1064 *overfl
|= overflow
;
1066 *carry
|= (bu16
)b
<= (bu16
)a
;
1071 min32 (SIM_CPU
*cpu
, bu32 a
, bu32 b
)
1074 if ((bs32
)a
> (bs32
)b
)
1076 setflags_nz (cpu
, val
);
1077 SET_ASTATREG (v
, 0);
1082 max32 (SIM_CPU
*cpu
, bu32 a
, bu32 b
)
1085 if ((bs32
)a
< (bs32
)b
)
1087 setflags_nz (cpu
, val
);
1088 SET_ASTATREG (v
, 0);
1093 min2x16 (SIM_CPU
*cpu
, bu32 a
, bu32 b
)
1096 if ((bs16
)a
> (bs16
)b
)
1097 val
= (val
& 0xFFFF0000) | (b
& 0xFFFF);
1098 if ((bs16
)(a
>> 16) > (bs16
)(b
>> 16))
1099 val
= (val
& 0xFFFF) | (b
& 0xFFFF0000);
1100 setflags_nz_2x16 (cpu
, val
);
1101 SET_ASTATREG (v
, 0);
1106 max2x16 (SIM_CPU
*cpu
, bu32 a
, bu32 b
)
1109 if ((bs16
)a
< (bs16
)b
)
1110 val
= (val
& 0xFFFF0000) | (b
& 0xFFFF);
1111 if ((bs16
)(a
>> 16) < (bs16
)(b
>> 16))
1112 val
= (val
& 0xFFFF) | (b
& 0xFFFF0000);
1113 setflags_nz_2x16 (cpu
, val
);
1114 SET_ASTATREG (v
, 0);
1119 add_and_shift (SIM_CPU
*cpu
, bu32 a
, bu32 b
, int shift
)
1122 ASTATREG (v_internal
) = 0;
1123 v
= add32 (cpu
, a
, b
, 0, 0);
1126 int x
= (v
>> 30) & 0x3;
1127 if (x
== 1 || x
== 2)
1128 ASTATREG (v_internal
) = 1;
1131 SET_ASTATREG (az
, v
== 0);
1132 SET_ASTATREG (an
, v
& 0x80000000);
1133 SET_ASTATREG (v
, ASTATREG (v_internal
));
1135 SET_ASTATREG (vs
, 1);
1140 xor_reduce (bu64 acc0
, bu64 acc1
)
1144 for (i
= 0; i
< 40; ++i
)
1146 v
^= (acc0
& acc1
& 1);
1153 /* DIVS ( Dreg, Dreg ) ;
1154 Initialize for DIVQ. Set the AQ status bit based on the signs of
1155 the 32-bit dividend and the 16-bit divisor. Left shift the dividend
1156 one bit. Copy AQ into the dividend LSB. */
1158 divs (SIM_CPU
*cpu
, bu32 pquo
, bu16 divisor
)
1160 bu16 r
= pquo
>> 16;
1163 aq
= (r
^ divisor
) >> 15; /* Extract msb's and compute quotient bit. */
1164 SET_ASTATREG (aq
, aq
); /* Update global quotient state. */
1168 pquo
= (pquo
& 0x1FFFF) | (r
<< 17);
1172 /* DIVQ ( Dreg, Dreg ) ;
1173 Based on AQ status bit, either add or subtract the divisor from
1174 the dividend. Then set the AQ status bit based on the MSBs of the
1175 32-bit dividend and the 16-bit divisor. Left shift the dividend one
1176 bit. Copy the logical inverse of AQ into the dividend LSB. */
1178 divq (SIM_CPU
*cpu
, bu32 pquo
, bu16 divisor
)
1180 unsigned short af
= pquo
>> 16;
1189 aq
= (r
^ divisor
) >> 15; /* Extract msb's and compute quotient bit. */
1190 SET_ASTATREG (aq
, aq
); /* Update global quotient state. */
1194 pquo
= (pquo
& 0x1FFFF) | (r
<< 17);
1199 Count the number of bits set to 1 in the 32bit value. */
1207 for (i
= 0; i
< 32; ++i
)
1208 ret
+= !!(val
& (1 << i
));
1214 reg_check_sup (SIM_CPU
*cpu
, int grp
, int reg
)
1217 cec_require_supervisor (cpu
);
1221 reg_write (SIM_CPU
*cpu
, int grp
, int reg
, bu32 value
)
1225 /* ASTAT is special! */
1226 if (grp
== 4 && reg
== 6)
1232 /* Check supervisor after get_allreg() so exception order is correct. */
1233 whichreg
= get_allreg (cpu
, grp
, reg
);
1234 reg_check_sup (cpu
, grp
, reg
);
1236 if (whichreg
== &CYCLES2REG
)
1237 /* Writes to CYCLES2 goes to the shadow. */
1238 whichreg
= &CYCLES2SHDREG
;
1239 else if (whichreg
== &SEQSTATREG
)
1240 /* Register is read only -- discard writes. */
1242 else if (whichreg
== &EMUDAT_INREG
)
1243 /* Writes to EMUDAT goes to the output. */
1244 whichreg
= &EMUDAT_OUTREG
;
1245 else if (whichreg
== <REG (0) || whichreg
== <REG (1))
1246 /* Writes to LT clears LSB automatically. */
1248 else if (whichreg
== &AXREG (0) || whichreg
== &AXREG (1))
1251 TRACE_REGISTER (cpu
, "wrote %s = %#x", get_allreg_name (grp
, reg
), value
);
1257 reg_read (SIM_CPU
*cpu
, int grp
, int reg
)
1262 /* ASTAT is special! */
1263 if (grp
== 4 && reg
== 6)
1266 /* Check supervisor after get_allreg() so exception order is correct. */
1267 whichreg
= get_allreg (cpu
, grp
, reg
);
1268 reg_check_sup (cpu
, grp
, reg
);
1272 if (whichreg
== &CYCLESREG
)
1273 /* Reads of CYCLES reloads CYCLES2 from the shadow. */
1274 SET_CYCLES2REG (CYCLES2SHDREG
);
1275 else if ((whichreg
== &AXREG (1) || whichreg
== &AXREG (0)) && (value
& 0x80))
1276 /* Sign extend if necessary. */
1277 value
|= 0xFFFFFF00;
1283 get_extended_cycles (SIM_CPU
*cpu
)
1285 return ((bu64
)CYCLES2SHDREG
<< 32) | CYCLESREG
;
1288 /* We can't re-use sim_events_time() because the CYCLES registers may be
1289 written/cleared/reset/stopped/started at any time by software. */
1291 cycles_inc (SIM_CPU
*cpu
, bu32 inc
)
1296 if (!(SYSCFGREG
& SYSCFG_CCEN
))
1299 cycles
= get_extended_cycles (cpu
) + inc
;
1300 SET_CYCLESREG (cycles
);
1301 cycles2
= cycles
>> 32;
1302 if (CYCLES2SHDREG
!= cycles2
)
1303 SET_CYCLES2SHDREG (cycles2
);
1307 get_unextended_acc (SIM_CPU
*cpu
, int which
)
1309 return ((bu64
)(AXREG (which
) & 0xff) << 32) | AWREG (which
);
1313 get_extended_acc (SIM_CPU
*cpu
, int which
)
1315 bu64 acc
= AXREG (which
);
1316 /* Sign extend accumulator values before adding. */
1322 acc
|= AWREG (which
);
1326 /* Perform a multiplication of D registers SRC0 and SRC1, sign- or
1327 zero-extending the result to 64 bit. H0 and H1 determine whether the
1328 high part or the low part of the source registers is used. Store 1 in
1329 *PSAT if saturation occurs, 0 otherwise. */
1331 decode_multfunc (SIM_CPU
*cpu
, int h0
, int h1
, int src0
, int src1
, int mmod
,
1334 bu32 s0
= DREG (src0
), s1
= DREG (src1
);
1348 sgn0
= -(s0
& 0x8000);
1349 sgn1
= -(s1
& 0x8000);
1371 illegal_instruction (cpu
);
1375 /* Perform shift correction if appropriate for the mode. */
1377 if (!MM
&& (mmod
== 0 || mmod
== M_T
|| mmod
== M_S2RND
|| mmod
== M_W32
))
1379 if (val
== 0x40000000)
1392 /* In signed modes, sign extend. */
1393 if (is_macmod_signed (mmod
) || MM
)
1394 val1
|= -(val1
& 0x80000000);
1397 val1
&= 0xFFFFFFFFull
;
1403 saturate_s40_astat (bu64 val
, bu32
*v
)
1405 if ((bs64
)val
< -((bs64
)1 << 39))
1408 return -((bs64
)1 << 39);
1410 else if ((bs64
)val
> ((bs64
)1 << 39) - 1)
1413 return ((bu64
)1 << 39) - 1;
1415 *v
= 0; /* No overflow. */
1420 saturate_s40 (bu64 val
)
1423 return saturate_s40_astat (val
, &v
);
1427 saturate_s32 (bu64 val
, bu32
*overflow
)
1429 if ((bs64
)val
< -0x80000000ll
)
1435 if ((bs64
)val
> 0x7fffffff)
1445 saturate_u32 (bu64 val
, bu32
*overflow
)
1447 if (val
> 0xffffffff)
1457 saturate_u16 (bu64 val
, bu32
*overflow
)
1473 /* FIXME: Should honour rounding mode. */
1474 if ((val
& 0xffff) > 0x8000
1475 || ((val
& 0xffff) == 0x8000 && (val
& 0x10000)))
1478 sgnbits
= val
& 0xffff000000000000ull
;
1480 return val
| sgnbits
;
1486 bu64 sgnbits
= val
& 0xffff000000000000ull
;
1488 return val
| sgnbits
;
1492 signbits (bu64 val
, int size
)
1494 bu64 mask
= (bu64
)1 << (size
- 1);
1495 bu64 bit
= val
& mask
;
1503 if ((val
& mask
) != bit
)
1513 /* Extract a 16 or 32 bit value from a 64 bit multiplication result.
1514 These 64 bits must be sign- or zero-extended properly from the source
1515 we want to extract, either a 32 bit multiply or a 40 bit accumulator. */
1518 extract_mult (SIM_CPU
*cpu
, bu64 res
, int mmod
, int MM
,
1519 int fullword
, bu32
*overflow
)
1526 return saturate_s32 (res
, overflow
);
1529 return saturate_s32 (res
, overflow
);
1530 return saturate_u32 (res
, overflow
);
1533 return saturate_s32 (res
, overflow
);
1534 return saturate_u32 (res
, overflow
);
1537 return saturate_s32 (res
<< 1, overflow
);
1539 illegal_instruction (cpu
);
1547 return saturate_s16 (rnd16 (res
), overflow
);
1549 return saturate_s16 (res
, overflow
);
1552 return saturate_s16 (rnd16 (res
), overflow
);
1553 return saturate_u16 (rnd16 (res
), overflow
);
1556 return saturate_s16 (res
, overflow
);
1557 return saturate_u16 (res
, overflow
);
1560 return saturate_s16 (trunc16 (res
), overflow
);
1563 return saturate_s16 (trunc16 (res
), overflow
);
1564 return saturate_u16 (trunc16 (res
), overflow
);
1567 return saturate_s16 (rnd16 (res
<< 1), overflow
);
1569 return saturate_s16 (res
<< 1, overflow
);
1571 illegal_instruction (cpu
);
1576 decode_macfunc (SIM_CPU
*cpu
, int which
, int op
, int h0
, int h1
, int src0
,
1577 int src1
, int mmod
, int MM
, int fullword
, bu32
*overflow
,
1581 bu32 sat
= 0, tsat
, ret
;
1583 /* Sign extend accumulator if necessary, otherwise unsigned. */
1584 if (is_macmod_signed (mmod
) || MM
)
1585 acc
= get_extended_acc (cpu
, which
);
1587 acc
= get_unextended_acc (cpu
, which
);
1591 bu8 sgn0
= (acc
>> 31) & 1;
1592 bu8 sgn40
= (acc
>> 39) & 1;
1595 /* This can't saturate, so we don't keep track of the sat flag. */
1596 bu64 res
= decode_multfunc (cpu
, h0
, h1
, src0
, src1
, mmod
,
1599 /* Perform accumulation. */
1604 sgn0
= (acc
>> 31) & 1;
1623 if ((bs64
)acc
< -((bs64
)1 << 39))
1624 acc
= -((bu64
)1 << 39), sat
= 1;
1625 else if ((bs64
)acc
> 0x7fffffffffll
)
1626 acc
= 0x7fffffffffull
, sat
= 1;
1631 if ((bs64
)acc
< -((bs64
)1 << 39))
1632 acc
= -((bu64
)1 << 39), sat
= 1;
1633 if ((bs64
)acc
> 0x7FFFFFFFFFll
)
1634 acc
= 0x7FFFFFFFFFull
, sat
= 1;
1640 if ((bs64
)acc
> 0xFFFFFFFFFFull
)
1641 acc
= 0xFFFFFFFFFFull
, sat
= 1;
1645 if (!MM
&& acc
& 0x8000000000000000ull
)
1647 if (!MM
&& acc
> 0xFFFFFFFFFFull
)
1648 acc
= 0xFFFFFFFFFFull
, sat
= 1;
1649 if (MM
&& acc
> 0xFFFFFFFFFFull
)
1650 acc
&= 0xFFFFFFFFFFull
;
1651 if (acc
& 0x8000000000ull
)
1652 acc
|= 0xffffff0000000000ull
;
1657 if ((bs64
)acc
< -((bs64
)1 << 39))
1658 acc
= -((bu64
)1 << 39), sat
= 1;
1659 if ((bs64
)acc
> 0x7FFFFFFFFFll
)
1660 acc
= 0x7FFFFFFFFFull
, sat
= 1;
1661 else if (acc
& 0x8000000000ull
)
1662 acc
|= 0xffffff0000000000ull
;
1668 else if ((bs64
)acc
> (bs64
)0xFFFFFFFFFFll
)
1669 acc
= 0xFFFFFFFFFFull
, sat
= 1;
1673 if ((bs64
)acc
< -0x80000000ll
)
1674 acc
= -0x80000000ull
, sat
= 1;
1675 else if ((bs64
)acc
> 0x7fffffffll
)
1676 acc
= 0x7fffffffull
, sat
= 1;
1679 /* check max negative value */
1680 if (sgn40
&& ((acc
>> 31) != 0x1ffffffff)
1681 && ((acc
>> 31) != 0x0))
1682 acc
= 0x80000000, sat
= 1;
1683 if (!sat
&& !sgn40
&& ((acc
>> 31) != 0x0)
1684 && ((acc
>> 31) != 0x1ffffffff))
1685 acc
= 0x7FFFFFFF, sat
= 1;
1687 if (acc
& 0x80000000)
1688 acc
|= 0xffffffff00000000ull
;
1693 illegal_instruction (cpu
);
1696 if (acc
& 0x8000000000ull
)
1699 STORE (AXREG (which
), (acc
>> 32) & 0xff);
1700 STORE (AWREG (which
), acc
& 0xffffffff);
1701 STORE (ASTATREG (av
[which
]), sat
);
1703 STORE (ASTATREG (avs
[which
]), sat
);
1705 /* Figure out the overflow bit. */
1711 ret
= extract_mult (cpu
, nosat_acc
, mmod
, MM
, fullword
, overflow
);
1715 ret
= extract_mult (cpu
, acc
, mmod
, MM
, fullword
, overflow
);
1724 if (ret
& 0x80000000)
1732 hwloop_get_next_pc (SIM_CPU
*cpu
, bu32 pc
, bu32 insn_len
)
1739 /* If our PC has reached the bottom of a hardware loop,
1740 move back up to the top of the hardware loop. */
1741 for (i
= 1; i
>= 0; --i
)
1742 if (LCREG (i
) > 1 && pc
== LBREG (i
))
1744 TRACE_BRANCH (cpu
, pc
, LTREG (i
), i
, "Hardware loop %i", i
);
1748 return pc
+ insn_len
;
1752 decode_ProgCtrl_0 (SIM_CPU
*cpu
, bu16 iw0
, bu32 pc
)
1755 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
1756 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |.prgfunc.......|.poprnd........|
1757 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
1758 int poprnd
= ((iw0
>> ProgCtrl_poprnd_bits
) & ProgCtrl_poprnd_mask
);
1759 int prgfunc
= ((iw0
>> ProgCtrl_prgfunc_bits
) & ProgCtrl_prgfunc_mask
);
1761 TRACE_EXTRACT (cpu
, "%s: poprnd:%i prgfunc:%i", __func__
, poprnd
, prgfunc
);
1763 if (prgfunc
== 0 && poprnd
== 0)
1765 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_nop
);
1766 TRACE_INSN (cpu
, "NOP;");
1768 else if (prgfunc
== 1 && poprnd
== 0)
1770 bu32 newpc
= RETSREG
;
1771 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1772 TRACE_INSN (cpu
, "RTS;");
1773 IFETCH_CHECK (newpc
);
1774 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1775 illegal_instruction_combination (cpu
);
1776 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "RTS");
1778 BFIN_CPU_STATE
.did_jump
= true;
1781 else if (prgfunc
== 1 && poprnd
== 1)
1783 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1784 TRACE_INSN (cpu
, "RTI;");
1785 /* Do not do IFETCH_CHECK here -- LSB has special meaning. */
1786 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1787 illegal_instruction_combination (cpu
);
1788 cec_return (cpu
, -1);
1791 else if (prgfunc
== 1 && poprnd
== 2)
1793 bu32 newpc
= RETXREG
;
1794 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1795 TRACE_INSN (cpu
, "RTX;");
1796 /* XXX: Not sure if this is what the hardware does. */
1797 IFETCH_CHECK (newpc
);
1798 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1799 illegal_instruction_combination (cpu
);
1800 cec_return (cpu
, IVG_EVX
);
1803 else if (prgfunc
== 1 && poprnd
== 3)
1805 bu32 newpc
= RETNREG
;
1806 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1807 TRACE_INSN (cpu
, "RTN;");
1808 /* XXX: Not sure if this is what the hardware does. */
1809 IFETCH_CHECK (newpc
);
1810 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1811 illegal_instruction_combination (cpu
);
1812 cec_return (cpu
, IVG_NMI
);
1815 else if (prgfunc
== 1 && poprnd
== 4)
1817 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1818 TRACE_INSN (cpu
, "RTE;");
1819 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1820 illegal_instruction_combination (cpu
);
1821 cec_return (cpu
, IVG_EMU
);
1824 else if (prgfunc
== 2 && poprnd
== 0)
1826 SIM_DESC sd
= CPU_STATE (cpu
);
1827 sim_events
*events
= STATE_EVENTS (sd
);
1829 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_sync
);
1830 /* XXX: in supervisor mode, utilizes wake up sources
1831 in user mode, it's a NOP ... */
1832 TRACE_INSN (cpu
, "IDLE;");
1834 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1835 illegal_instruction_combination (cpu
);
1839 CYCLE_DELAY
= events
->time_from_event
;
1841 abort (); /* XXX: Should this ever happen ? */
1843 else if (prgfunc
== 2 && poprnd
== 3)
1845 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_sync
);
1847 TRACE_INSN (cpu
, "CSYNC;");
1848 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1849 illegal_instruction_combination (cpu
);
1852 else if (prgfunc
== 2 && poprnd
== 4)
1854 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_sync
);
1856 TRACE_INSN (cpu
, "SSYNC;");
1857 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1858 illegal_instruction_combination (cpu
);
1860 /* Really 10+, but no model info for this. */
1863 else if (prgfunc
== 2 && poprnd
== 5)
1865 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1866 TRACE_INSN (cpu
, "EMUEXCPT;");
1867 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1868 illegal_instruction_combination (cpu
);
1869 cec_exception (cpu
, VEC_SIM_TRAP
);
1871 else if (prgfunc
== 3 && poprnd
< 8)
1873 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1874 TRACE_INSN (cpu
, "CLI R%i;", poprnd
);
1875 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1876 illegal_instruction_combination (cpu
);
1877 SET_DREG (poprnd
, cec_cli (cpu
));
1879 else if (prgfunc
== 4 && poprnd
< 8)
1881 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1882 TRACE_INSN (cpu
, "STI R%i;", poprnd
);
1883 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1884 illegal_instruction_combination (cpu
);
1885 cec_sti (cpu
, DREG (poprnd
));
1888 else if (prgfunc
== 5 && poprnd
< 8)
1890 bu32 newpc
= PREG (poprnd
);
1891 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1892 TRACE_INSN (cpu
, "JUMP (%s);", get_preg_name (poprnd
));
1893 IFETCH_CHECK (newpc
);
1894 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1895 illegal_instruction_combination (cpu
);
1896 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP (Preg)");
1898 BFIN_CPU_STATE
.did_jump
= true;
1899 PROFILE_BRANCH_TAKEN (cpu
);
1902 else if (prgfunc
== 6 && poprnd
< 8)
1904 bu32 newpc
= PREG (poprnd
);
1905 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1906 TRACE_INSN (cpu
, "CALL (%s);", get_preg_name (poprnd
));
1907 IFETCH_CHECK (newpc
);
1908 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1909 illegal_instruction_combination (cpu
);
1910 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "CALL (Preg)");
1911 /* If we're at the end of a hardware loop, RETS is going to be
1912 the top of the loop rather than the next instruction. */
1913 SET_RETSREG (hwloop_get_next_pc (cpu
, pc
, 2));
1915 BFIN_CPU_STATE
.did_jump
= true;
1916 PROFILE_BRANCH_TAKEN (cpu
);
1919 else if (prgfunc
== 7 && poprnd
< 8)
1921 bu32 newpc
= pc
+ PREG (poprnd
);
1922 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1923 TRACE_INSN (cpu
, "CALL (PC + %s);", get_preg_name (poprnd
));
1924 IFETCH_CHECK (newpc
);
1925 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1926 illegal_instruction_combination (cpu
);
1927 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "CALL (PC + Preg)");
1928 SET_RETSREG (hwloop_get_next_pc (cpu
, pc
, 2));
1930 BFIN_CPU_STATE
.did_jump
= true;
1931 PROFILE_BRANCH_TAKEN (cpu
);
1934 else if (prgfunc
== 8 && poprnd
< 8)
1936 bu32 newpc
= pc
+ PREG (poprnd
);
1937 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1938 TRACE_INSN (cpu
, "JUMP (PC + %s);", get_preg_name (poprnd
));
1939 IFETCH_CHECK (newpc
);
1940 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1941 illegal_instruction_combination (cpu
);
1942 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP (PC + Preg)");
1944 BFIN_CPU_STATE
.did_jump
= true;
1945 PROFILE_BRANCH_TAKEN (cpu
);
1948 else if (prgfunc
== 9)
1950 int raise
= uimm4 (poprnd
);
1951 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1952 TRACE_INSN (cpu
, "RAISE %s;", uimm4_str (raise
));
1953 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1954 illegal_instruction_combination (cpu
);
1955 cec_require_supervisor (cpu
);
1956 if (raise
== IVG_IVHW
)
1957 cec_hwerr (cpu
, HWERR_RAISE_5
);
1959 cec_latch (cpu
, raise
);
1960 CYCLE_DELAY
= 3; /* XXX: Only if IVG is unmasked. */
1962 else if (prgfunc
== 10)
1964 int excpt
= uimm4 (poprnd
);
1965 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1966 TRACE_INSN (cpu
, "EXCPT %s;", uimm4_str (excpt
));
1967 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1968 illegal_instruction_combination (cpu
);
1969 cec_exception (cpu
, excpt
);
1972 else if (prgfunc
== 11 && poprnd
< 6)
1974 bu32 addr
= PREG (poprnd
);
1976 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_atomic
);
1977 TRACE_INSN (cpu
, "TESTSET (%s);", get_preg_name (poprnd
));
1978 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
1979 illegal_instruction_combination (cpu
);
1980 byte
= GET_WORD (addr
);
1981 SET_CCREG (byte
== 0);
1982 PUT_BYTE (addr
, byte
| 0x80);
1983 /* Also includes memory stalls, but we don't model that. */
1987 illegal_instruction_or_combination (cpu
);
1991 decode_CaCTRL_0 (SIM_CPU
*cpu
, bu16 iw0
)
1994 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
1995 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 |.a.|.op....|.reg.......|
1996 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
1997 int a
= ((iw0
>> CaCTRL_a_bits
) & CaCTRL_a_mask
);
1998 int op
= ((iw0
>> CaCTRL_op_bits
) & CaCTRL_op_mask
);
1999 int reg
= ((iw0
>> CaCTRL_reg_bits
) & CaCTRL_reg_mask
);
2000 bu32 preg
= PREG (reg
);
2001 const char * const sinsn
[] = { "PREFETCH", "FLUSHINV", "FLUSH", "IFLUSH", };
2003 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CaCTRL
);
2004 TRACE_EXTRACT (cpu
, "%s: a:%i op:%i reg:%i", __func__
, a
, op
, reg
);
2005 TRACE_INSN (cpu
, "%s [%s%s];", sinsn
[op
], get_preg_name (reg
), a
? "++" : "");
2007 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2008 /* None of these can be part of a parallel instruction. */
2009 illegal_instruction_combination (cpu
);
2011 /* No cache simulation, so these are (mostly) all NOPs.
2012 XXX: The hardware takes care of masking to cache lines, but need
2013 to check behavior of the post increment. Should we be aligning
2014 the value to the cache line before adding the cache line size, or
2015 do we just add the cache line size ? */
2018 mmu_check_cache_addr (cpu
, preg
, false, false);
2022 mmu_check_cache_addr (cpu
, preg
, true, false);
2026 mmu_check_cache_addr (cpu
, preg
, true, false);
2030 mmu_check_cache_addr (cpu
, preg
, false, true);
2034 SET_PREG (reg
, preg
+ BFIN_L1_CACHE_BYTES
);
2038 decode_PushPopReg_0 (SIM_CPU
*cpu
, bu16 iw0
)
2041 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2042 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |.W.|.grp.......|.reg.......|
2043 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2044 int W
= ((iw0
>> PushPopReg_W_bits
) & PushPopReg_W_mask
);
2045 int grp
= ((iw0
>> PushPopReg_grp_bits
) & PushPopReg_grp_mask
);
2046 int reg
= ((iw0
>> PushPopReg_reg_bits
) & PushPopReg_reg_mask
);
2047 const char *reg_name
= get_allreg_name (grp
, reg
);
2051 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_PushPopReg
);
2052 TRACE_EXTRACT (cpu
, "%s: W:%i grp:%i reg:%i", __func__
, W
, grp
, reg
);
2053 TRACE_DECODE (cpu
, "%s: reg:%s", __func__
, reg_name
);
2055 /* Can't push/pop reserved registers */
2056 if (reg_is_reserved (grp
, reg
))
2057 illegal_instruction_or_combination (cpu
);
2061 /* Dreg and Preg are not supported by this instruction. */
2062 if (grp
== 0 || grp
== 1)
2063 illegal_instruction_or_combination (cpu
);
2064 TRACE_INSN (cpu
, "%s = [SP++];", reg_name
);
2065 /* Can't pop USP while in userspace. */
2066 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
2067 || (grp
== 7 && reg
== 0 && cec_is_user_mode(cpu
)))
2068 illegal_instruction_combination (cpu
);
2069 /* XXX: The valid register check is in reg_write(), so we might
2070 incorrectly do a GET_LONG() here ... */
2071 value
= GET_LONG (sp
);
2072 reg_write (cpu
, grp
, reg
, value
);
2073 if (grp
== 7 && reg
== 3)
2080 TRACE_INSN (cpu
, "[--SP] = %s;", reg_name
);
2081 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2082 illegal_instruction_combination (cpu
);
2085 value
= reg_read (cpu
, grp
, reg
);
2086 if (grp
== 7 && reg
== 3)
2087 cec_push_reti (cpu
);
2089 PUT_LONG (sp
, value
);
2092 /* Note: SP update must be delayed until after all reads/writes; see
2093 comments in decode_PushPopMultiple_0() for more info. */
2098 decode_PushPopMultiple_0 (SIM_CPU
*cpu
, bu16 iw0
)
2101 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2102 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |.d.|.p.|.W.|.dr........|.pr........|
2103 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2104 int p
= ((iw0
>> PushPopMultiple_p_bits
) & PushPopMultiple_p_mask
);
2105 int d
= ((iw0
>> PushPopMultiple_d_bits
) & PushPopMultiple_d_mask
);
2106 int W
= ((iw0
>> PushPopMultiple_W_bits
) & PushPopMultiple_W_mask
);
2107 int dr
= ((iw0
>> PushPopMultiple_dr_bits
) & PushPopMultiple_dr_mask
);
2108 int pr
= ((iw0
>> PushPopMultiple_pr_bits
) & PushPopMultiple_pr_mask
);
2112 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_PushPopMultiple
);
2113 TRACE_EXTRACT (cpu
, "%s: d:%i p:%i W:%i dr:%i pr:%i",
2114 __func__
, d
, p
, W
, dr
, pr
);
2116 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2117 illegal_instruction_combination (cpu
);
2119 if ((d
== 0 && p
== 0) || (p
&& imm5 (pr
) > 5)
2120 || (d
&& !p
&& pr
) || (p
&& !d
&& dr
))
2121 illegal_instruction (cpu
);
2126 TRACE_INSN (cpu
, "[--SP] = (R7:%i, P5:%i);", dr
, pr
);
2128 TRACE_INSN (cpu
, "[--SP] = (R7:%i);", dr
);
2130 TRACE_INSN (cpu
, "[--SP] = (P5:%i);", pr
);
2133 for (i
= dr
; i
< 8; i
++)
2136 PUT_LONG (sp
, DREG (i
));
2139 for (i
= pr
; i
< 6; i
++)
2142 PUT_LONG (sp
, PREG (i
));
2150 TRACE_INSN (cpu
, "(R7:%i, P5:%i) = [SP++];", dr
, pr
);
2152 TRACE_INSN (cpu
, "(R7:%i) = [SP++];", dr
);
2154 TRACE_INSN (cpu
, "(P5:%i) = [SP++];", pr
);
2157 for (i
= 5; i
>= pr
; i
--)
2159 SET_PREG (i
, GET_LONG (sp
));
2163 for (i
= 7; i
>= dr
; i
--)
2165 SET_DREG (i
, GET_LONG (sp
));
2172 /* Note: SP update must be delayed until after all reads/writes so that
2173 if an exception does occur, the insn may be re-executed as the
2174 SP has not yet changed. */
2179 decode_ccMV_0 (SIM_CPU
*cpu
, bu16 iw0
)
2182 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2183 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |.T.|.d.|.s.|.dst.......|.src.......|
2184 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2185 int s
= ((iw0
>> CCmv_s_bits
) & CCmv_s_mask
);
2186 int d
= ((iw0
>> CCmv_d_bits
) & CCmv_d_mask
);
2187 int T
= ((iw0
>> CCmv_T_bits
) & CCmv_T_mask
);
2188 int src
= ((iw0
>> CCmv_src_bits
) & CCmv_src_mask
);
2189 int dst
= ((iw0
>> CCmv_dst_bits
) & CCmv_dst_mask
);
2190 int cond
= T
? CCREG
: ! CCREG
;
2192 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ccMV
);
2193 TRACE_EXTRACT (cpu
, "%s: T:%i d:%i s:%i dst:%i src:%i",
2194 __func__
, T
, d
, s
, dst
, src
);
2196 TRACE_INSN (cpu
, "IF %sCC %s = %s;", T
? "" : "! ",
2197 get_allreg_name (d
, dst
),
2198 get_allreg_name (s
, src
));
2199 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2200 illegal_instruction_combination (cpu
);
2203 reg_write (cpu
, d
, dst
, reg_read (cpu
, s
, src
));
2207 decode_CCflag_0 (SIM_CPU
*cpu
, bu16 iw0
)
2210 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2211 | 0 | 0 | 0 | 0 | 1 |.I.|.opc.......|.G.|.y.........|.x.........|
2212 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2213 int x
= ((iw0
>> CCflag_x_bits
) & CCflag_x_mask
);
2214 int y
= ((iw0
>> CCflag_y_bits
) & CCflag_y_mask
);
2215 int I
= ((iw0
>> CCflag_I_bits
) & CCflag_I_mask
);
2216 int G
= ((iw0
>> CCflag_G_bits
) & CCflag_G_mask
);
2217 int opc
= ((iw0
>> CCflag_opc_bits
) & CCflag_opc_mask
);
2219 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CCflag
);
2220 TRACE_EXTRACT (cpu
, "%s: I:%i opc:%i G:%i y:%i x:%i",
2221 __func__
, I
, opc
, G
, y
, x
);
2225 bs64 acc0
= get_extended_acc (cpu
, 0);
2226 bs64 acc1
= get_extended_acc (cpu
, 1);
2227 bs64 diff
= acc0
- acc1
;
2229 if (x
!= 0 || y
!= 0)
2230 illegal_instruction_or_combination (cpu
);
2232 if (opc
== 5 && I
== 0 && G
== 0)
2234 TRACE_INSN (cpu
, "CC = A0 == A1;");
2235 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2236 illegal_instruction_combination (cpu
);
2237 SET_CCREG (acc0
== acc1
);
2239 else if (opc
== 6 && I
== 0 && G
== 0)
2241 TRACE_INSN (cpu
, "CC = A0 < A1");
2242 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2243 illegal_instruction_combination (cpu
);
2244 SET_CCREG (acc0
< acc1
);
2246 else if (opc
== 7 && I
== 0 && G
== 0)
2248 TRACE_INSN (cpu
, "CC = A0 <= A1");
2249 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2250 illegal_instruction_combination (cpu
);
2251 SET_CCREG (acc0
<= acc1
);
2254 illegal_instruction_or_combination (cpu
);
2256 SET_ASTATREG (az
, diff
== 0);
2257 SET_ASTATREG (an
, diff
< 0);
2258 SET_ASTATREG (ac0
, (bu40
)acc1
<= (bu40
)acc0
);
2262 int issigned
= opc
< 3;
2263 const char *sign
= issigned
? "" : " (IU)";
2264 bu32 srcop
= G
? PREG (x
) : DREG (x
);
2265 char s
= G
? 'P' : 'R';
2266 bu32 dstop
= I
? (issigned
? imm3 (y
) : uimm3 (y
)) : G
? PREG (y
) : DREG (y
);
2268 char d
= G
? 'P' : 'R';
2269 int flgs
= srcop
>> 31;
2270 int flgo
= dstop
>> 31;
2272 bu32 result
= srcop
- dstop
;
2274 int flgn
= result
>> 31;
2275 int overflow
= (flgs
^ flgo
) & (flgn
^ flgs
);
2276 int az
= result
== 0;
2277 int ac0
= dstop
<= srcop
;
2280 an
= (flgn
&& !overflow
) || (!flgn
&& overflow
);
2286 default: /* Shutup useless gcc warnings. */
2287 case 0: /* signed */
2291 case 1: /* signed */
2295 case 2: /* signed */
2299 case 3: /* unsigned */
2303 case 4: /* unsigned */
2310 TRACE_INSN (cpu
, "CC = %c%i %s %s%s;", s
, x
, op
,
2311 issigned
? imm3_str (y
) : uimm3_str (y
), sign
);
2314 TRACE_DECODE (cpu
, "%s %c%i:%x %c%i:%x", __func__
,
2315 s
, x
, srcop
, d
, y
, dstop
);
2316 TRACE_INSN (cpu
, "CC = %c%i %s %c%i%s;", s
, x
, op
, d
, y
, sign
);
2319 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2320 illegal_instruction_combination (cpu
);
2323 /* Pointer compares only touch CC. */
2326 SET_ASTATREG (az
, az
);
2327 SET_ASTATREG (an
, an
);
2328 SET_ASTATREG (ac0
, ac0
);
2334 decode_CC2dreg_0 (SIM_CPU
*cpu
, bu16 iw0
)
2337 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2338 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |.op....|.reg.......|
2339 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2340 int op
= ((iw0
>> CC2dreg_op_bits
) & CC2dreg_op_mask
);
2341 int reg
= ((iw0
>> CC2dreg_reg_bits
) & CC2dreg_reg_mask
);
2343 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CC2dreg
);
2344 TRACE_EXTRACT (cpu
, "%s: op:%i reg:%i", __func__
, op
, reg
);
2348 TRACE_INSN (cpu
, "R%i = CC;", reg
);
2349 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2350 illegal_instruction_combination (cpu
);
2351 SET_DREG (reg
, CCREG
);
2355 TRACE_INSN (cpu
, "CC = R%i;", reg
);
2356 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2357 illegal_instruction_combination (cpu
);
2358 SET_CCREG (DREG (reg
) != 0);
2360 else if (op
== 3 && reg
== 0)
2362 TRACE_INSN (cpu
, "CC = !CC;");
2363 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2364 illegal_instruction_combination (cpu
);
2368 illegal_instruction_or_combination (cpu
);
2372 decode_CC2stat_0 (SIM_CPU
*cpu
, bu16 iw0
)
2375 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2376 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |.D.|.op....|.cbit..............|
2377 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2378 int D
= ((iw0
>> CC2stat_D_bits
) & CC2stat_D_mask
);
2379 int op
= ((iw0
>> CC2stat_op_bits
) & CC2stat_op_mask
);
2380 int cbit
= ((iw0
>> CC2stat_cbit_bits
) & CC2stat_cbit_mask
);
2383 const char * const op_names
[] = { "", "|", "&", "^" } ;
2385 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CC2stat
);
2386 TRACE_EXTRACT (cpu
, "%s: D:%i op:%i cbit:%i", __func__
, D
, op
, cbit
);
2388 TRACE_INSN (cpu
, "%s %s= %s;", D
? astat_names
[cbit
] : "CC",
2389 op_names
[op
], D
? "CC" : astat_names
[cbit
]);
2391 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2392 illegal_instruction_combination (cpu
);
2394 /* CC = CC; is invalid. */
2396 illegal_instruction (cpu
);
2398 pval
= !!(ASTAT
& (1 << cbit
));
2402 case 0: SET_CCREG (pval
); break;
2403 case 1: SET_CCREG (CCREG
| pval
); break;
2404 case 2: SET_CCREG (CCREG
& pval
); break;
2405 case 3: SET_CCREG (CCREG
^ pval
); break;
2411 case 0: pval
= CCREG
; break;
2412 case 1: pval
|= CCREG
; break;
2413 case 2: pval
&= CCREG
; break;
2414 case 3: pval
^= CCREG
; break;
2416 TRACE_REGISTER (cpu
, "wrote ASTAT[%s] = %i", astat_names
[cbit
], pval
);
2417 SET_ASTAT ((ASTAT
& ~(1 << cbit
)) | (pval
<< cbit
));
2422 decode_BRCC_0 (SIM_CPU
*cpu
, bu16 iw0
, bu32 pc
)
2425 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2426 | 0 | 0 | 0 | 1 |.T.|.B.|.offset................................|
2427 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2428 int B
= ((iw0
>> BRCC_B_bits
) & BRCC_B_mask
);
2429 int T
= ((iw0
>> BRCC_T_bits
) & BRCC_T_mask
);
2430 int offset
= ((iw0
>> BRCC_offset_bits
) & BRCC_offset_mask
);
2431 int cond
= T
? CCREG
: ! CCREG
;
2432 int pcrel
= pcrel10 (offset
);
2434 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_BRCC
);
2435 TRACE_EXTRACT (cpu
, "%s: T:%i B:%i offset:%#x", __func__
, T
, B
, offset
);
2436 TRACE_DECODE (cpu
, "%s: pcrel10:%#x", __func__
, pcrel
);
2438 TRACE_INSN (cpu
, "IF %sCC JUMP %#x%s;", T
? "" : "! ",
2439 pcrel
, B
? " (bp)" : "");
2441 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2442 illegal_instruction_combination (cpu
);
2446 bu32 newpc
= pc
+ pcrel
;
2447 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "Conditional JUMP");
2449 BFIN_CPU_STATE
.did_jump
= true;
2450 PROFILE_BRANCH_TAKEN (cpu
);
2451 CYCLE_DELAY
= B
? 5 : 9;
2455 PROFILE_BRANCH_UNTAKEN (cpu
);
2456 CYCLE_DELAY
= B
? 9 : 1;
2461 decode_UJUMP_0 (SIM_CPU
*cpu
, bu16 iw0
, bu32 pc
)
2464 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2465 | 0 | 0 | 1 | 0 |.offset........................................|
2466 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2467 int offset
= ((iw0
>> UJump_offset_bits
) & UJump_offset_mask
);
2468 int pcrel
= pcrel12 (offset
);
2469 bu32 newpc
= pc
+ pcrel
;
2471 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_UJUMP
);
2472 TRACE_EXTRACT (cpu
, "%s: offset:%#x", __func__
, offset
);
2473 TRACE_DECODE (cpu
, "%s: pcrel12:%#x", __func__
, pcrel
);
2475 TRACE_INSN (cpu
, "JUMP.S %#x;", pcrel
);
2477 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2478 illegal_instruction_combination (cpu
);
2480 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP.S");
2483 BFIN_CPU_STATE
.did_jump
= true;
2484 PROFILE_BRANCH_TAKEN (cpu
);
2489 decode_REGMV_0 (SIM_CPU
*cpu
, bu16 iw0
)
2492 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2493 | 0 | 0 | 1 | 1 |.gd........|.gs........|.dst.......|.src.......|
2494 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2495 int gs
= ((iw0
>> RegMv_gs_bits
) & RegMv_gs_mask
);
2496 int gd
= ((iw0
>> RegMv_gd_bits
) & RegMv_gd_mask
);
2497 int src
= ((iw0
>> RegMv_src_bits
) & RegMv_src_mask
);
2498 int dst
= ((iw0
>> RegMv_dst_bits
) & RegMv_dst_mask
);
2499 const char *srcreg_name
= get_allreg_name (gs
, src
);
2500 const char *dstreg_name
= get_allreg_name (gd
, dst
);
2502 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_REGMV
);
2503 TRACE_EXTRACT (cpu
, "%s: gd:%i gs:%i dst:%i src:%i",
2504 __func__
, gd
, gs
, dst
, src
);
2505 TRACE_DECODE (cpu
, "%s: dst:%s src:%s", __func__
, dstreg_name
, srcreg_name
);
2507 TRACE_INSN (cpu
, "%s = %s;", dstreg_name
, srcreg_name
);
2509 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2510 illegal_instruction_combination (cpu
);
2512 /* Reserved slots cannot be a src/dst. */
2513 if (reg_is_reserved (gs
, src
) || reg_is_reserved (gd
, dst
))
2516 /* Standard register moves. */
2517 if ((gs
< 2) /* Dregs/Pregs src */
2518 || (gd
< 2) /* Dregs/Pregs dst */
2519 || (gs
== 4 && src
< 4) /* Accumulators src */
2520 || (gd
== 4 && dst
< 4 && (gs
< 4)) /* Accumulators dst */
2521 || (gs
== 7 && src
== 7 && !(gd
== 4 && dst
< 4)) /* EMUDAT src */
2522 || (gd
== 7 && dst
== 7)) /* EMUDAT dst */
2525 /* dareg = dareg (IMBL) */
2526 if (gs
< 4 && gd
< 4)
2529 /* USP can be src to sysregs, but not dagregs. */
2530 if ((gs
== 7 && src
== 0) && (gd
>= 4))
2533 /* USP can move between genregs (only check Accumulators). */
2534 if (((gs
== 7 && src
== 0) && (gd
== 4 && dst
< 4))
2535 || ((gd
== 7 && dst
== 0) && (gs
== 4 && src
< 4)))
2538 /* Still here ? Invalid reg pair. */
2540 illegal_instruction (cpu
);
2543 reg_write (cpu
, gd
, dst
, reg_read (cpu
, gs
, src
));
2547 decode_ALU2op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2550 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2551 | 0 | 1 | 0 | 0 | 0 | 0 |.opc...........|.src.......|.dst.......|
2552 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2553 int src
= ((iw0
>> ALU2op_src_bits
) & ALU2op_src_mask
);
2554 int opc
= ((iw0
>> ALU2op_opc_bits
) & ALU2op_opc_mask
);
2555 int dst
= ((iw0
>> ALU2op_dst_bits
) & ALU2op_dst_mask
);
2557 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ALU2op
);
2558 TRACE_EXTRACT (cpu
, "%s: opc:%i src:%i dst:%i", __func__
, opc
, src
, dst
);
2560 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2561 illegal_instruction_combination (cpu
);
2565 TRACE_INSN (cpu
, "R%i >>>= R%i;", dst
, src
);
2566 SET_DREG (dst
, ashiftrt (cpu
, DREG (dst
), DREG (src
), 32));
2571 TRACE_INSN (cpu
, "R%i >>= R%i;", dst
, src
);
2572 if (DREG (src
) <= 0x1F)
2573 val
= lshiftrt (cpu
, DREG (dst
), DREG (src
), 32);
2576 SET_DREG (dst
, val
);
2580 TRACE_INSN (cpu
, "R%i <<= R%i;", dst
, src
);
2581 SET_DREG (dst
, lshift (cpu
, DREG (dst
), DREG (src
), 32, 0, 0));
2585 TRACE_INSN (cpu
, "R%i *= R%i;", dst
, src
);
2586 SET_DREG (dst
, DREG (dst
) * DREG (src
));
2591 TRACE_INSN (cpu
, "R%i = (R%i + R%i) << 1;", dst
, dst
, src
);
2592 SET_DREG (dst
, add_and_shift (cpu
, DREG (dst
), DREG (src
), 1));
2596 TRACE_INSN (cpu
, "R%i = (R%i + R%i) << 2;", dst
, dst
, src
);
2597 SET_DREG (dst
, add_and_shift (cpu
, DREG (dst
), DREG (src
), 2));
2601 TRACE_INSN (cpu
, "DIVQ ( R%i, R%i );", dst
, src
);
2602 SET_DREG (dst
, divq (cpu
, DREG (dst
), (bu16
)DREG (src
)));
2606 TRACE_INSN (cpu
, "DIVS ( R%i, R%i );", dst
, src
);
2607 SET_DREG (dst
, divs (cpu
, DREG (dst
), (bu16
)DREG (src
)));
2611 TRACE_INSN (cpu
, "R%i = R%i.L (X);", dst
, src
);
2612 SET_DREG (dst
, (bs32
) (bs16
) DREG (src
));
2613 setflags_logical (cpu
, DREG (dst
));
2617 TRACE_INSN (cpu
, "R%i = R%i.L (Z);", dst
, src
);
2618 SET_DREG (dst
, (bu32
) (bu16
) DREG (src
));
2619 setflags_logical (cpu
, DREG (dst
));
2623 TRACE_INSN (cpu
, "R%i = R%i.B (X);", dst
, src
);
2624 SET_DREG (dst
, (bs32
) (bs8
) DREG (src
));
2625 setflags_logical (cpu
, DREG (dst
));
2629 TRACE_INSN (cpu
, "R%i = R%i.B (Z);", dst
, src
);
2630 SET_DREG (dst
, (bu32
) (bu8
) DREG (src
));
2631 setflags_logical (cpu
, DREG (dst
));
2635 bu32 val
= DREG (src
);
2636 TRACE_INSN (cpu
, "R%i = - R%i;", dst
, src
);
2637 SET_DREG (dst
, -val
);
2638 setflags_nz (cpu
, DREG (dst
));
2639 SET_ASTATREG (v
, val
== 0x80000000);
2641 SET_ASTATREG (vs
, 1);
2642 SET_ASTATREG (ac0
, val
== 0x0);
2643 /* XXX: Documentation isn't entirely clear about av0 and av1. */
2647 TRACE_INSN (cpu
, "R%i = ~ R%i;", dst
, src
);
2648 SET_DREG (dst
, ~DREG (src
));
2649 setflags_logical (cpu
, DREG (dst
));
2652 illegal_instruction (cpu
);
2656 decode_PTR2op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2659 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2660 | 0 | 1 | 0 | 0 | 0 | 1 | 0 |.opc.......|.src.......|.dst.......|
2661 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2662 int src
= ((iw0
>> PTR2op_src_bits
) & PTR2op_dst_mask
);
2663 int opc
= ((iw0
>> PTR2op_opc_bits
) & PTR2op_opc_mask
);
2664 int dst
= ((iw0
>> PTR2op_dst_bits
) & PTR2op_dst_mask
);
2665 const char *src_name
= get_preg_name (src
);
2666 const char *dst_name
= get_preg_name (dst
);
2668 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_PTR2op
);
2669 TRACE_EXTRACT (cpu
, "%s: opc:%i src:%i dst:%i", __func__
, opc
, src
, dst
);
2671 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2672 illegal_instruction_combination (cpu
);
2676 TRACE_INSN (cpu
, "%s -= %s", dst_name
, src_name
);
2677 SET_PREG (dst
, PREG (dst
) - PREG (src
));
2681 TRACE_INSN (cpu
, "%s = %s << 2", dst_name
, src_name
);
2682 SET_PREG (dst
, PREG (src
) << 2);
2686 TRACE_INSN (cpu
, "%s = %s >> 2", dst_name
, src_name
);
2687 SET_PREG (dst
, PREG (src
) >> 2);
2691 TRACE_INSN (cpu
, "%s = %s >> 1", dst_name
, src_name
);
2692 SET_PREG (dst
, PREG (src
) >> 1);
2696 TRACE_INSN (cpu
, "%s += %s (BREV)", dst_name
, src_name
);
2697 SET_PREG (dst
, add_brev (PREG (dst
), PREG (src
)));
2701 TRACE_INSN (cpu
, "%s = (%s + %s) << 1", dst_name
, dst_name
, src_name
);
2702 SET_PREG (dst
, (PREG (dst
) + PREG (src
)) << 1);
2706 TRACE_INSN (cpu
, "%s = (%s + %s) << 2", dst_name
, dst_name
, src_name
);
2707 SET_PREG (dst
, (PREG (dst
) + PREG (src
)) << 2);
2710 illegal_instruction (cpu
);
2714 decode_LOGI2op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2717 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2718 | 0 | 1 | 0 | 0 | 1 |.opc.......|.src...............|.dst.......|
2719 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2720 int src
= ((iw0
>> LOGI2op_src_bits
) & LOGI2op_src_mask
);
2721 int opc
= ((iw0
>> LOGI2op_opc_bits
) & LOGI2op_opc_mask
);
2722 int dst
= ((iw0
>> LOGI2op_dst_bits
) & LOGI2op_dst_mask
);
2723 int uimm
= uimm5 (src
);
2724 const char *uimm_str
= uimm5_str (uimm
);
2726 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LOGI2op
);
2727 TRACE_EXTRACT (cpu
, "%s: opc:%i src:%i dst:%i", __func__
, opc
, src
, dst
);
2728 TRACE_DECODE (cpu
, "%s: uimm5:%#x", __func__
, uimm
);
2732 TRACE_INSN (cpu
, "CC = ! BITTST (R%i, %s);", dst
, uimm_str
);
2733 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2734 illegal_instruction_combination (cpu
);
2735 SET_CCREG ((~DREG (dst
) >> uimm
) & 1);
2739 TRACE_INSN (cpu
, "CC = BITTST (R%i, %s);", dst
, uimm_str
);
2740 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2741 illegal_instruction_combination (cpu
);
2742 SET_CCREG ((DREG (dst
) >> uimm
) & 1);
2746 TRACE_INSN (cpu
, "BITSET (R%i, %s);", dst
, uimm_str
);
2747 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2748 illegal_instruction_combination (cpu
);
2749 SET_DREG (dst
, DREG (dst
) | (1 << uimm
));
2750 setflags_logical (cpu
, DREG (dst
));
2754 TRACE_INSN (cpu
, "BITTGL (R%i, %s);", dst
, uimm_str
);
2755 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2756 illegal_instruction_combination (cpu
);
2757 SET_DREG (dst
, DREG (dst
) ^ (1 << uimm
));
2758 setflags_logical (cpu
, DREG (dst
));
2762 TRACE_INSN (cpu
, "BITCLR (R%i, %s);", dst
, uimm_str
);
2763 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2764 illegal_instruction_combination (cpu
);
2765 SET_DREG (dst
, DREG (dst
) & ~(1 << uimm
));
2766 setflags_logical (cpu
, DREG (dst
));
2770 TRACE_INSN (cpu
, "R%i >>>= %s;", dst
, uimm_str
);
2771 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2772 illegal_instruction_combination (cpu
);
2773 SET_DREG (dst
, ashiftrt (cpu
, DREG (dst
), uimm
, 32));
2777 TRACE_INSN (cpu
, "R%i >>= %s;", dst
, uimm_str
);
2778 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2779 illegal_instruction_combination (cpu
);
2780 SET_DREG (dst
, lshiftrt (cpu
, DREG (dst
), uimm
, 32));
2784 TRACE_INSN (cpu
, "R%i <<= %s;", dst
, uimm_str
);
2785 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2786 illegal_instruction_combination (cpu
);
2787 SET_DREG (dst
, lshift (cpu
, DREG (dst
), uimm
, 32, 0, 0));
2792 decode_COMP3op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2795 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2796 | 0 | 1 | 0 | 1 |.opc.......|.dst.......|.src1......|.src0......|
2797 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2798 int opc
= ((iw0
>> COMP3op_opc_bits
) & COMP3op_opc_mask
);
2799 int dst
= ((iw0
>> COMP3op_dst_bits
) & COMP3op_dst_mask
);
2800 int src0
= ((iw0
>> COMP3op_src0_bits
) & COMP3op_src0_mask
);
2801 int src1
= ((iw0
>> COMP3op_src1_bits
) & COMP3op_src1_mask
);
2803 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_COMP3op
);
2804 TRACE_EXTRACT (cpu
, "%s: opc:%i dst:%i src1:%i src0:%i",
2805 __func__
, opc
, dst
, src1
, src0
);
2807 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2808 illegal_instruction_combination (cpu
);
2812 TRACE_INSN (cpu
, "R%i = R%i + R%i;", dst
, src0
, src1
);
2813 SET_DREG (dst
, add32 (cpu
, DREG (src0
), DREG (src1
), 1, 0));
2817 TRACE_INSN (cpu
, "R%i = R%i - R%i;", dst
, src0
, src1
);
2818 SET_DREG (dst
, sub32 (cpu
, DREG (src0
), DREG (src1
), 1, 0, 0));
2822 TRACE_INSN (cpu
, "R%i = R%i & R%i;", dst
, src0
, src1
);
2823 SET_DREG (dst
, DREG (src0
) & DREG (src1
));
2824 setflags_logical (cpu
, DREG (dst
));
2828 TRACE_INSN (cpu
, "R%i = R%i | R%i;", dst
, src0
, src1
);
2829 SET_DREG (dst
, DREG (src0
) | DREG (src1
));
2830 setflags_logical (cpu
, DREG (dst
));
2834 TRACE_INSN (cpu
, "R%i = R%i ^ R%i;", dst
, src0
, src1
);
2835 SET_DREG (dst
, DREG (src0
) ^ DREG (src1
));
2836 setflags_logical (cpu
, DREG (dst
));
2840 int shift
= opc
- 5;
2841 const char *dst_name
= get_preg_name (dst
);
2842 const char *src0_name
= get_preg_name (src0
);
2843 const char *src1_name
= get_preg_name (src1
);
2845 /* If src0 == src1 this is disassembled as a shift by 1, but this
2846 distinction doesn't matter for our purposes. */
2848 TRACE_INSN (cpu
, "%s = (%s + %s) << %#x;",
2849 dst_name
, src0_name
, src1_name
, shift
);
2851 TRACE_INSN (cpu
, "%s = %s + %s",
2852 dst_name
, src0_name
, src1_name
);
2853 SET_PREG (dst
, PREG (src0
) + (PREG (src1
) << shift
));
2858 decode_COMPI2opD_0 (SIM_CPU
*cpu
, bu16 iw0
)
2861 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2862 | 0 | 1 | 1 | 0 | 0 |.op|..src......................|.dst.......|
2863 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2864 int op
= ((iw0
>> COMPI2opD_op_bits
) & COMPI2opD_op_mask
);
2865 int dst
= ((iw0
>> COMPI2opD_dst_bits
) & COMPI2opD_dst_mask
);
2866 int src
= ((iw0
>> COMPI2opD_src_bits
) & COMPI2opD_src_mask
);
2867 int imm
= imm7 (src
);
2869 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_COMPI2opD
);
2870 TRACE_EXTRACT (cpu
, "%s: op:%i src:%i dst:%i", __func__
, op
, src
, dst
);
2871 TRACE_DECODE (cpu
, "%s: imm7:%#x", __func__
, imm
);
2873 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2874 illegal_instruction_combination (cpu
);
2878 TRACE_INSN (cpu
, "R%i = %s (X);", dst
, imm7_str (imm
));
2879 SET_DREG (dst
, imm
);
2883 TRACE_INSN (cpu
, "R%i += %s;", dst
, imm7_str (imm
));
2884 SET_DREG (dst
, add32 (cpu
, DREG (dst
), imm
, 1, 0));
2889 decode_COMPI2opP_0 (SIM_CPU
*cpu
, bu16 iw0
)
2892 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2893 | 0 | 1 | 1 | 0 | 1 |.op|.src.......................|.dst.......|
2894 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2895 int op
= ((iw0
>> COMPI2opP_op_bits
) & COMPI2opP_op_mask
);
2896 int src
= ((iw0
>> COMPI2opP_src_bits
) & COMPI2opP_src_mask
);
2897 int dst
= ((iw0
>> COMPI2opP_dst_bits
) & COMPI2opP_dst_mask
);
2898 int imm
= imm7 (src
);
2899 const char *dst_name
= get_preg_name (dst
);
2901 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_COMPI2opP
);
2902 TRACE_EXTRACT (cpu
, "%s: op:%i src:%i dst:%i", __func__
, op
, src
, dst
);
2903 TRACE_DECODE (cpu
, "%s: imm:%#x", __func__
, imm
);
2905 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
2906 illegal_instruction_combination (cpu
);
2910 TRACE_INSN (cpu
, "%s = %s;", dst_name
, imm7_str (imm
));
2911 SET_PREG (dst
, imm
);
2915 TRACE_INSN (cpu
, "%s += %s;", dst_name
, imm7_str (imm
));
2916 SET_PREG (dst
, PREG (dst
) + imm
);
2921 decode_LDSTpmod_0 (SIM_CPU
*cpu
, bu16 iw0
)
2924 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2925 | 1 | 0 | 0 | 0 |.W.|.aop...|.reg.......|.idx.......|.ptr.......|
2926 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2927 int W
= ((iw0
>> LDSTpmod_W_bits
) & LDSTpmod_W_mask
);
2928 int aop
= ((iw0
>> LDSTpmod_aop_bits
) & LDSTpmod_aop_mask
);
2929 int idx
= ((iw0
>> LDSTpmod_idx_bits
) & LDSTpmod_idx_mask
);
2930 int ptr
= ((iw0
>> LDSTpmod_ptr_bits
) & LDSTpmod_ptr_mask
);
2931 int reg
= ((iw0
>> LDSTpmod_reg_bits
) & LDSTpmod_reg_mask
);
2932 const char *ptr_name
= get_preg_name (ptr
);
2933 const char *idx_name
= get_preg_name (idx
);
2936 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTpmod
);
2937 TRACE_EXTRACT (cpu
, "%s: W:%i aop:%i reg:%i idx:%i ptr:%i",
2938 __func__
, W
, aop
, reg
, idx
, ptr
);
2940 if (PARALLEL_GROUP
== BFIN_PARALLEL_GROUP2
)
2941 illegal_instruction_combination (cpu
);
2943 if (aop
== 1 && W
== 0 && idx
== ptr
)
2945 TRACE_INSN (cpu
, "R%i.L = W[%s];", reg
, ptr_name
);
2947 val
= GET_WORD (addr
);
2948 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | val
);
2950 else if (aop
== 2 && W
== 0 && idx
== ptr
)
2952 TRACE_INSN (cpu
, "R%i.H = W[%s];", reg
, ptr_name
);
2954 val
= GET_WORD (addr
);
2955 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (val
<< 16));
2957 else if (aop
== 1 && W
== 1 && idx
== ptr
)
2959 TRACE_INSN (cpu
, "W[%s] = R%i.L;", ptr_name
, reg
);
2961 PUT_WORD (addr
, DREG (reg
));
2963 else if (aop
== 2 && W
== 1 && idx
== ptr
)
2965 TRACE_INSN (cpu
, "W[%s] = R%i.H;", ptr_name
, reg
);
2967 PUT_WORD (addr
, DREG (reg
) >> 16);
2969 else if (aop
== 0 && W
== 0)
2971 TRACE_INSN (cpu
, "R%i = [%s ++ %s];", reg
, ptr_name
, idx_name
);
2973 val
= GET_LONG (addr
);
2974 STORE (DREG (reg
), val
);
2976 STORE (PREG (ptr
), addr
+ PREG (idx
));
2978 else if (aop
== 1 && W
== 0)
2980 TRACE_INSN (cpu
, "R%i.L = W[%s ++ %s];", reg
, ptr_name
, idx_name
);
2982 val
= GET_WORD (addr
);
2983 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | val
);
2985 STORE (PREG (ptr
), addr
+ PREG (idx
));
2987 else if (aop
== 2 && W
== 0)
2989 TRACE_INSN (cpu
, "R%i.H = W[%s ++ %s];", reg
, ptr_name
, idx_name
);
2991 val
= GET_WORD (addr
);
2992 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (val
<< 16));
2994 STORE (PREG (ptr
), addr
+ PREG (idx
));
2996 else if (aop
== 3 && W
== 0)
2998 TRACE_INSN (cpu
, "R%i = W[%s ++ %s] (Z);", reg
, ptr_name
, idx_name
);
3000 val
= GET_WORD (addr
);
3001 STORE (DREG (reg
), val
);
3003 STORE (PREG (ptr
), addr
+ PREG (idx
));
3005 else if (aop
== 3 && W
== 1)
3007 TRACE_INSN (cpu
, "R%i = W[%s ++ %s] (X);", reg
, ptr_name
, idx_name
);
3009 val
= GET_WORD (addr
);
3010 STORE (DREG (reg
), (bs32
) (bs16
) val
);
3012 STORE (PREG (ptr
), addr
+ PREG (idx
));
3014 else if (aop
== 0 && W
== 1)
3016 TRACE_INSN (cpu
, "[%s ++ %s] = R%i;", ptr_name
, idx_name
, reg
);
3018 PUT_LONG (addr
, DREG (reg
));
3020 STORE (PREG (ptr
), addr
+ PREG (idx
));
3022 else if (aop
== 1 && W
== 1)
3024 TRACE_INSN (cpu
, "W[%s ++ %s] = R%i.L;", ptr_name
, idx_name
, reg
);
3026 PUT_WORD (addr
, DREG (reg
));
3028 STORE (PREG (ptr
), addr
+ PREG (idx
));
3030 else if (aop
== 2 && W
== 1)
3032 TRACE_INSN (cpu
, "W[%s ++ %s] = R%i.H;", ptr_name
, idx_name
, reg
);
3034 PUT_WORD (addr
, DREG (reg
) >> 16);
3036 STORE (PREG (ptr
), addr
+ PREG (idx
));
3039 illegal_instruction_or_combination (cpu
);
3043 decode_dagMODim_0 (SIM_CPU
*cpu
, bu16 iw0
)
3046 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3047 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 0 |.br| 1 | 1 |.op|.m.....|.i.....|
3048 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3049 int i
= ((iw0
>> DagMODim_i_bits
) & DagMODim_i_mask
);
3050 int m
= ((iw0
>> DagMODim_m_bits
) & DagMODim_m_mask
);
3051 int br
= ((iw0
>> DagMODim_br_bits
) & DagMODim_br_mask
);
3052 int op
= ((iw0
>> DagMODim_op_bits
) & DagMODim_op_mask
);
3054 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dagMODim
);
3055 TRACE_EXTRACT (cpu
, "%s: br:%i op:%i m:%i i:%i", __func__
, br
, op
, m
, i
);
3057 if (PARALLEL_GROUP
== BFIN_PARALLEL_GROUP2
)
3058 illegal_instruction_combination (cpu
);
3060 if (op
== 0 && br
== 1)
3062 TRACE_INSN (cpu
, "I%i += M%i (BREV);", i
, m
);
3063 SET_IREG (i
, add_brev (IREG (i
), MREG (m
)));
3067 TRACE_INSN (cpu
, "I%i += M%i;", i
, m
);
3068 dagadd (cpu
, i
, MREG (m
));
3070 else if (op
== 1 && br
== 0)
3072 TRACE_INSN (cpu
, "I%i -= M%i;", i
, m
);
3073 dagsub (cpu
, i
, MREG (m
));
3076 illegal_instruction_or_combination (cpu
);
3080 decode_dagMODik_0 (SIM_CPU
*cpu
, bu16 iw0
)
3083 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3084 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 0 |.op....|.i.....|
3085 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3086 int i
= ((iw0
>> DagMODik_i_bits
) & DagMODik_i_mask
);
3087 int op
= ((iw0
>> DagMODik_op_bits
) & DagMODik_op_mask
);
3089 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dagMODik
);
3090 TRACE_EXTRACT (cpu
, "%s: op:%i i:%i", __func__
, op
, i
);
3092 if (PARALLEL_GROUP
== BFIN_PARALLEL_GROUP2
)
3093 illegal_instruction_combination (cpu
);
3097 TRACE_INSN (cpu
, "I%i += 2;", i
);
3102 TRACE_INSN (cpu
, "I%i -= 2;", i
);
3107 TRACE_INSN (cpu
, "I%i += 4;", i
);
3112 TRACE_INSN (cpu
, "I%i -= 4;", i
);
3116 illegal_instruction_or_combination (cpu
);
3120 decode_dspLDST_0 (SIM_CPU
*cpu
, bu16 iw0
)
3123 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3124 | 1 | 0 | 0 | 1 | 1 | 1 |.W.|.aop...|.m.....|.i.....|.reg.......|
3125 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3126 int i
= ((iw0
>> DspLDST_i_bits
) & DspLDST_i_mask
);
3127 int m
= ((iw0
>> DspLDST_m_bits
) & DspLDST_m_mask
);
3128 int W
= ((iw0
>> DspLDST_W_bits
) & DspLDST_W_mask
);
3129 int aop
= ((iw0
>> DspLDST_aop_bits
) & DspLDST_aop_mask
);
3130 int reg
= ((iw0
>> DspLDST_reg_bits
) & DspLDST_reg_mask
);
3133 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dspLDST
);
3134 TRACE_EXTRACT (cpu
, "%s: aop:%i m:%i i:%i reg:%i", __func__
, aop
, m
, i
, reg
);
3136 if (aop
== 0 && W
== 0 && m
== 0)
3138 TRACE_INSN (cpu
, "R%i = [I%i++];", reg
, i
);
3140 if (DIS_ALGN_EXPT
& 0x1)
3143 STORE (DREG (reg
), GET_LONG (addr
));
3145 else if (aop
== 0 && W
== 0 && m
== 1)
3147 TRACE_INSN (cpu
, "R%i.L = W[I%i++];", reg
, i
);
3150 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | GET_WORD (addr
));
3152 else if (aop
== 0 && W
== 0 && m
== 2)
3154 TRACE_INSN (cpu
, "R%i.H = W[I%i++];", reg
, i
);
3157 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (GET_WORD (addr
) << 16));
3159 else if (aop
== 1 && W
== 0 && m
== 0)
3161 TRACE_INSN (cpu
, "R%i = [I%i--];", reg
, i
);
3163 if (DIS_ALGN_EXPT
& 0x1)
3166 STORE (DREG (reg
), GET_LONG (addr
));
3168 else if (aop
== 1 && W
== 0 && m
== 1)
3170 TRACE_INSN (cpu
, "R%i.L = W[I%i--];", reg
, i
);
3173 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | GET_WORD (addr
));
3175 else if (aop
== 1 && W
== 0 && m
== 2)
3177 TRACE_INSN (cpu
, "R%i.H = W[I%i--];", reg
, i
);
3180 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (GET_WORD (addr
) << 16));
3182 else if (aop
== 2 && W
== 0 && m
== 0)
3184 TRACE_INSN (cpu
, "R%i = [I%i];", reg
, i
);
3186 if (DIS_ALGN_EXPT
& 0x1)
3188 STORE (DREG (reg
), GET_LONG (addr
));
3190 else if (aop
== 2 && W
== 0 && m
== 1)
3192 TRACE_INSN (cpu
, "R%i.L = W[I%i];", reg
, i
);
3194 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | GET_WORD (addr
));
3196 else if (aop
== 2 && W
== 0 && m
== 2)
3198 TRACE_INSN (cpu
, "R%i.H = W[I%i];", reg
, i
);
3200 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (GET_WORD (addr
) << 16));
3202 else if (aop
== 0 && W
== 1 && m
== 0)
3204 TRACE_INSN (cpu
, "[I%i++] = R%i;", i
, reg
);
3207 PUT_LONG (addr
, DREG (reg
));
3209 else if (aop
== 0 && W
== 1 && m
== 1)
3211 TRACE_INSN (cpu
, "W[I%i++] = R%i.L;", i
, reg
);
3214 PUT_WORD (addr
, DREG (reg
));
3216 else if (aop
== 0 && W
== 1 && m
== 2)
3218 TRACE_INSN (cpu
, "W[I%i++] = R%i.H;", i
, reg
);
3221 PUT_WORD (addr
, DREG (reg
) >> 16);
3223 else if (aop
== 1 && W
== 1 && m
== 0)
3225 TRACE_INSN (cpu
, "[I%i--] = R%i;", i
, reg
);
3228 PUT_LONG (addr
, DREG (reg
));
3230 else if (aop
== 1 && W
== 1 && m
== 1)
3232 TRACE_INSN (cpu
, "W[I%i--] = R%i.L;", i
, reg
);
3235 PUT_WORD (addr
, DREG (reg
));
3237 else if (aop
== 1 && W
== 1 && m
== 2)
3239 TRACE_INSN (cpu
, "W[I%i--] = R%i.H;", i
, reg
);
3242 PUT_WORD (addr
, DREG (reg
) >> 16);
3244 else if (aop
== 2 && W
== 1 && m
== 0)
3246 TRACE_INSN (cpu
, "[I%i] = R%i;", i
, reg
);
3248 PUT_LONG (addr
, DREG (reg
));
3250 else if (aop
== 2 && W
== 1 && m
== 1)
3252 TRACE_INSN (cpu
, "W[I%i] = R%i.L;", i
, reg
);
3254 PUT_WORD (addr
, DREG (reg
));
3256 else if (aop
== 2 && W
== 1 && m
== 2)
3258 TRACE_INSN (cpu
, "W[I%i] = R%i.H;", i
, reg
);
3260 PUT_WORD (addr
, DREG (reg
) >> 16);
3262 else if (aop
== 3 && W
== 0)
3264 TRACE_INSN (cpu
, "R%i = [I%i ++ M%i];", reg
, i
, m
);
3266 if (DIS_ALGN_EXPT
& 0x1)
3268 dagadd (cpu
, i
, MREG (m
));
3269 STORE (DREG (reg
), GET_LONG (addr
));
3271 else if (aop
== 3 && W
== 1)
3273 TRACE_INSN (cpu
, "[I%i ++ M%i] = R%i;", i
, m
, reg
);
3275 dagadd (cpu
, i
, MREG (m
));
3276 PUT_LONG (addr
, DREG (reg
));
3279 illegal_instruction_or_combination (cpu
);
3283 decode_LDST_0 (SIM_CPU
*cpu
, bu16 iw0
)
3286 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3287 | 1 | 0 | 0 | 1 |.sz....|.W.|.aop...|.Z.|.ptr.......|.reg.......|
3288 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3289 int Z
= ((iw0
>> LDST_Z_bits
) & LDST_Z_mask
);
3290 int W
= ((iw0
>> LDST_W_bits
) & LDST_W_mask
);
3291 int sz
= ((iw0
>> LDST_sz_bits
) & LDST_sz_mask
);
3292 int aop
= ((iw0
>> LDST_aop_bits
) & LDST_aop_mask
);
3293 int reg
= ((iw0
>> LDST_reg_bits
) & LDST_reg_mask
);
3294 int ptr
= ((iw0
>> LDST_ptr_bits
) & LDST_ptr_mask
);
3295 const char * const posts
[] = { "++", "--", "" };
3296 const char *post
= posts
[aop
];
3297 const char *ptr_name
= get_preg_name (ptr
);
3299 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDST
);
3300 TRACE_EXTRACT (cpu
, "%s: sz:%i W:%i aop:%i Z:%i ptr:%i reg:%i",
3301 __func__
, sz
, W
, aop
, Z
, ptr
, reg
);
3303 if (aop
== 3 || PARALLEL_GROUP
== BFIN_PARALLEL_GROUP2
)
3304 illegal_instruction_or_combination (cpu
);
3308 if (sz
== 0 && Z
== 0)
3310 TRACE_INSN (cpu
, "R%i = [%s%s];", reg
, ptr_name
, post
);
3311 SET_DREG (reg
, GET_LONG (PREG (ptr
)));
3313 else if (sz
== 0 && Z
== 1)
3315 TRACE_INSN (cpu
, "%s = [%s%s];", get_preg_name (reg
), ptr_name
, post
);
3316 if (aop
< 2 && ptr
== reg
)
3317 illegal_instruction_combination (cpu
);
3318 SET_PREG (reg
, GET_LONG (PREG (ptr
)));
3320 else if (sz
== 1 && Z
== 0)
3322 TRACE_INSN (cpu
, "R%i = W[%s%s] (Z);", reg
, ptr_name
, post
);
3323 SET_DREG (reg
, GET_WORD (PREG (ptr
)));
3325 else if (sz
== 1 && Z
== 1)
3327 TRACE_INSN (cpu
, "R%i = W[%s%s] (X);", reg
, ptr_name
, post
);
3328 SET_DREG (reg
, (bs32
) (bs16
) GET_WORD (PREG (ptr
)));
3330 else if (sz
== 2 && Z
== 0)
3332 TRACE_INSN (cpu
, "R%i = B[%s%s] (Z);", reg
, ptr_name
, post
);
3333 SET_DREG (reg
, GET_BYTE (PREG (ptr
)));
3335 else if (sz
== 2 && Z
== 1)
3337 TRACE_INSN (cpu
, "R%i = B[%s%s] (X);", reg
, ptr_name
, post
);
3338 SET_DREG (reg
, (bs32
) (bs8
) GET_BYTE (PREG (ptr
)));
3341 illegal_instruction_or_combination (cpu
);
3345 if (sz
== 0 && Z
== 0)
3347 TRACE_INSN (cpu
, "[%s%s] = R%i;", ptr_name
, post
, reg
);
3348 PUT_LONG (PREG (ptr
), DREG (reg
));
3350 else if (sz
== 0 && Z
== 1)
3352 TRACE_INSN (cpu
, "[%s%s] = %s;", ptr_name
, post
, get_preg_name (reg
));
3353 PUT_LONG (PREG (ptr
), PREG (reg
));
3355 else if (sz
== 1 && Z
== 0)
3357 TRACE_INSN (cpu
, "W[%s%s] = R%i;", ptr_name
, post
, reg
);
3358 PUT_WORD (PREG (ptr
), DREG (reg
));
3360 else if (sz
== 2 && Z
== 0)
3362 TRACE_INSN (cpu
, "B[%s%s] = R%i;", ptr_name
, post
, reg
);
3363 PUT_BYTE (PREG (ptr
), DREG (reg
));
3366 illegal_instruction_or_combination (cpu
);
3370 SET_PREG (ptr
, PREG (ptr
) + (1 << (2 - sz
)));
3372 SET_PREG (ptr
, PREG (ptr
) - (1 << (2 - sz
)));
3376 decode_LDSTiiFP_0 (SIM_CPU
*cpu
, bu16 iw0
)
3379 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3380 | 1 | 0 | 1 | 1 | 1 | 0 |.W.|.offset............|.reg...........|
3381 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3382 /* This isn't exactly a grp:reg as this insn only supports Dregs & Pregs,
3383 but for our usage, its functionality the same thing. */
3384 int grp
= ((iw0
>> 3) & 0x1);
3385 int reg
= ((iw0
>> LDSTiiFP_reg_bits
) & 0x7 /*LDSTiiFP_reg_mask*/);
3386 int offset
= ((iw0
>> LDSTiiFP_offset_bits
) & LDSTiiFP_offset_mask
);
3387 int W
= ((iw0
>> LDSTiiFP_W_bits
) & LDSTiiFP_W_mask
);
3388 bu32 imm
= negimm5s4 (offset
);
3389 bu32 ea
= FPREG
+ imm
;
3390 const char *imm_str
= negimm5s4_str (offset
);
3391 const char *reg_name
= get_allreg_name (grp
, reg
);
3393 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTiiFP
);
3394 TRACE_EXTRACT (cpu
, "%s: W:%i offset:%#x grp:%i reg:%i", __func__
,
3395 W
, offset
, grp
, reg
);
3396 TRACE_DECODE (cpu
, "%s: negimm5s4:%#x", __func__
, imm
);
3398 if (PARALLEL_GROUP
== BFIN_PARALLEL_GROUP2
)
3399 illegal_instruction_or_combination (cpu
);
3403 TRACE_INSN (cpu
, "%s = [FP + %s];", reg_name
, imm_str
);
3404 reg_write (cpu
, grp
, reg
, GET_LONG (ea
));
3408 TRACE_INSN (cpu
, "[FP + %s] = %s;", imm_str
, reg_name
);
3409 PUT_LONG (ea
, reg_read (cpu
, grp
, reg
));
3414 decode_LDSTii_0 (SIM_CPU
*cpu
, bu16 iw0
)
3417 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3418 | 1 | 0 | 1 |.W.|.op....|.offset........|.ptr.......|.reg.......|
3419 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3420 int reg
= ((iw0
>> LDSTii_reg_bit
) & LDSTii_reg_mask
);
3421 int ptr
= ((iw0
>> LDSTii_ptr_bit
) & LDSTii_ptr_mask
);
3422 int offset
= ((iw0
>> LDSTii_offset_bit
) & LDSTii_offset_mask
);
3423 int op
= ((iw0
>> LDSTii_op_bit
) & LDSTii_op_mask
);
3424 int W
= ((iw0
>> LDSTii_W_bit
) & LDSTii_W_mask
);
3426 const char *imm_str
;
3427 const char *ptr_name
= get_preg_name (ptr
);
3429 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTii
);
3430 TRACE_EXTRACT (cpu
, "%s: W:%i op:%i offset:%#x ptr:%i reg:%i",
3431 __func__
, W
, op
, offset
, ptr
, reg
);
3433 if (op
== 0 || op
== 3)
3434 imm
= uimm4s4 (offset
), imm_str
= uimm4s4_str (offset
);
3436 imm
= uimm4s2 (offset
), imm_str
= uimm4s2_str (offset
);
3437 ea
= PREG (ptr
) + imm
;
3439 TRACE_DECODE (cpu
, "%s: uimm4s4/uimm4s2:%#x", __func__
, imm
);
3441 if (PARALLEL_GROUP
== BFIN_PARALLEL_GROUP2
)
3442 illegal_instruction_combination (cpu
);
3444 if (W
== 1 && op
== 2)
3445 illegal_instruction (cpu
);
3451 TRACE_INSN (cpu
, "R%i = [%s + %s];", reg
, ptr_name
, imm_str
);
3452 SET_DREG (reg
, GET_LONG (ea
));
3456 TRACE_INSN (cpu
, "R%i = W[%s + %s] (Z);", reg
, ptr_name
, imm_str
);
3457 SET_DREG (reg
, GET_WORD (ea
));
3461 TRACE_INSN (cpu
, "R%i = W[%s + %s] (X);", reg
, ptr_name
, imm_str
);
3462 SET_DREG (reg
, (bs32
) (bs16
) GET_WORD (ea
));
3466 TRACE_INSN (cpu
, "%s = [%s + %s];",
3467 get_preg_name (reg
), ptr_name
, imm_str
);
3468 SET_PREG (reg
, GET_LONG (ea
));
3475 TRACE_INSN (cpu
, "[%s + %s] = R%i;", ptr_name
, imm_str
, reg
);
3476 PUT_LONG (ea
, DREG (reg
));
3480 TRACE_INSN (cpu
, "W[%s + %s] = R%i;", ptr_name
, imm_str
, reg
);
3481 PUT_WORD (ea
, DREG (reg
));
3485 TRACE_INSN (cpu
, "[%s + %s] = %s;",
3486 ptr_name
, imm_str
, get_preg_name (reg
));
3487 PUT_LONG (ea
, PREG (reg
));
3493 decode_LoopSetup_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
, bu32 pc
)
3496 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3497 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |.rop...|.c.|.soffset.......|
3498 |.reg...........| - | - |.eoffset...............................|
3499 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3500 int c
= ((iw0
>> (LoopSetup_c_bits
- 16)) & LoopSetup_c_mask
);
3501 int reg
= ((iw1
>> LoopSetup_reg_bits
) & LoopSetup_reg_mask
);
3502 int rop
= ((iw0
>> (LoopSetup_rop_bits
- 16)) & LoopSetup_rop_mask
);
3503 int soffset
= ((iw0
>> (LoopSetup_soffset_bits
- 16)) & LoopSetup_soffset_mask
);
3504 int eoffset
= ((iw1
>> LoopSetup_eoffset_bits
) & LoopSetup_eoffset_mask
);
3505 int spcrel
= pcrel4 (soffset
);
3506 int epcrel
= lppcrel10 (eoffset
);
3508 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LoopSetup
);
3509 TRACE_EXTRACT (cpu
, "%s: rop:%i c:%i soffset:%i reg:%i eoffset:%i",
3510 __func__
, rop
, c
, soffset
, reg
, eoffset
);
3511 TRACE_DECODE (cpu
, "%s: s_pcrel4:%#x e_lppcrel10:%#x",
3512 __func__
, spcrel
, epcrel
);
3515 illegal_instruction (cpu
);
3517 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
3518 illegal_instruction_combination (cpu
);
3522 TRACE_INSN (cpu
, "LSETUP (%#x, %#x) LC%i;", spcrel
, epcrel
, c
);
3524 else if (rop
== 1 && reg
<= 7)
3526 TRACE_INSN (cpu
, "LSETUP (%#x, %#x) LC%i = %s;",
3527 spcrel
, epcrel
, c
, get_preg_name (reg
));
3528 SET_LCREG (c
, PREG (reg
));
3530 else if (rop
== 3 && reg
<= 7)
3532 TRACE_INSN (cpu
, "LSETUP (%#x, %#x) LC%i = %s >> 1;",
3533 spcrel
, epcrel
, c
, get_preg_name (reg
));
3534 SET_LCREG (c
, PREG (reg
) >> 1);
3537 illegal_instruction (cpu
);
3539 SET_LTREG (c
, pc
+ spcrel
);
3540 SET_LBREG (c
, pc
+ epcrel
);
3544 decode_LDIMMhalf_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3547 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3548 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 |.Z.|.H.|.S.|.grp...|.reg.......|
3549 |.hword.........................................................|
3550 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3551 int H
= ((iw0
>> (LDIMMhalf_H_bits
- 16)) & LDIMMhalf_H_mask
);
3552 int Z
= ((iw0
>> (LDIMMhalf_Z_bits
- 16)) & LDIMMhalf_Z_mask
);
3553 int S
= ((iw0
>> (LDIMMhalf_S_bits
- 16)) & LDIMMhalf_S_mask
);
3554 int reg
= ((iw0
>> (LDIMMhalf_reg_bits
- 16)) & LDIMMhalf_reg_mask
);
3555 int grp
= ((iw0
>> (LDIMMhalf_grp_bits
- 16)) & LDIMMhalf_grp_mask
);
3556 int hword
= ((iw1
>> LDIMMhalf_hword_bits
) & LDIMMhalf_hword_mask
);
3558 const char *val_str
;
3559 const char *reg_name
= get_allreg_name (grp
, reg
);
3561 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDIMMhalf
);
3562 TRACE_EXTRACT (cpu
, "%s: Z:%i H:%i S:%i grp:%i reg:%i hword:%#x",
3563 __func__
, Z
, H
, S
, grp
, reg
, hword
);
3565 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
3566 illegal_instruction_combination (cpu
);
3569 val
= imm16 (hword
), val_str
= imm16_str (hword
);
3571 val
= luimm16 (hword
), val_str
= luimm16_str (hword
);
3573 if (H
== 0 && S
== 1 && Z
== 0)
3575 TRACE_INSN (cpu
, "%s = %s (X);", reg_name
, val_str
);
3577 else if (H
== 0 && S
== 0 && Z
== 1)
3579 TRACE_INSN (cpu
, "%s = %s (Z);", reg_name
, val_str
);
3581 else if (H
== 0 && S
== 0 && Z
== 0)
3583 TRACE_INSN (cpu
, "%s.L = %s;", reg_name
, val_str
);
3584 val
= REG_H_L (reg_read (cpu
, grp
, reg
), val
);
3586 else if (H
== 1 && S
== 0 && Z
== 0)
3588 TRACE_INSN (cpu
, "%s.H = %s;", reg_name
, val_str
);
3589 val
= REG_H_L (val
<< 16, reg_read (cpu
, grp
, reg
));
3592 illegal_instruction (cpu
);
3594 reg_write (cpu
, grp
, reg
, val
);
3598 decode_CALLa_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
, bu32 pc
)
3601 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3602 | 1 | 1 | 1 | 0 | 0 | 0 | 1 |.S.|.msw...........................|
3603 |.lsw...........................................................|
3604 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3605 int S
= ((iw0
>> (CALLa_S_bits
- 16)) & CALLa_S_mask
);
3606 int lsw
= ((iw1
>> 0) & 0xffff);
3607 int msw
= ((iw0
>> 0) & 0xff);
3608 int pcrel
= pcrel24 ((msw
<< 16) | lsw
);
3609 bu32 newpc
= pc
+ pcrel
;
3611 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CALLa
);
3612 TRACE_EXTRACT (cpu
, "%s: S:%i msw:%#x lsw:%#x", __func__
, S
, msw
, lsw
);
3613 TRACE_DECODE (cpu
, "%s: pcrel24:%#x", __func__
, pcrel
);
3615 TRACE_INSN (cpu
, "%s %#x;", S
? "CALL" : "JUMP.L", pcrel
);
3617 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
3618 illegal_instruction_combination (cpu
);
3622 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "CALL");
3623 SET_RETSREG (hwloop_get_next_pc (cpu
, pc
, 4));
3626 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP.L");
3629 BFIN_CPU_STATE
.did_jump
= true;
3630 PROFILE_BRANCH_TAKEN (cpu
);
3635 decode_LDSTidxI_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3638 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3639 | 1 | 1 | 1 | 0 | 0 | 1 |.W.|.Z.|.sz....|.ptr.......|.reg.......|
3640 |.offset........................................................|
3641 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3642 int Z
= ((iw0
>> (LDSTidxI_Z_bits
- 16)) & LDSTidxI_Z_mask
);
3643 int W
= ((iw0
>> (LDSTidxI_W_bits
- 16)) & LDSTidxI_W_mask
);
3644 int sz
= ((iw0
>> (LDSTidxI_sz_bits
- 16)) & LDSTidxI_sz_mask
);
3645 int reg
= ((iw0
>> (LDSTidxI_reg_bits
- 16)) & LDSTidxI_reg_mask
);
3646 int ptr
= ((iw0
>> (LDSTidxI_ptr_bits
- 16)) & LDSTidxI_ptr_mask
);
3647 int offset
= ((iw1
>> LDSTidxI_offset_bits
) & LDSTidxI_offset_mask
);
3648 const char *ptr_name
= get_preg_name (ptr
);
3649 bu32 imm_16s4
= imm16s4 (offset
);
3650 bu32 imm_16s2
= imm16s2 (offset
);
3651 bu32 imm_16
= imm16 (offset
);
3653 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTidxI
);
3654 TRACE_EXTRACT (cpu
, "%s: W:%i Z:%i sz:%i ptr:%i reg:%i offset:%#x",
3655 __func__
, W
, Z
, sz
, ptr
, reg
, offset
);
3658 illegal_instruction (cpu
);
3662 if (sz
== 0 && Z
== 0)
3664 TRACE_INSN (cpu
, "R%i = [%s + %s];",
3665 reg
, ptr_name
, imm16s4_str (offset
));
3666 SET_DREG (reg
, GET_LONG (PREG (ptr
) + imm_16s4
));
3668 else if (sz
== 0 && Z
== 1)
3670 TRACE_INSN (cpu
, "%s = [%s + %s];",
3671 get_preg_name (reg
), ptr_name
, imm16s4_str (offset
));
3672 SET_PREG (reg
, GET_LONG (PREG (ptr
) + imm_16s4
));
3674 else if (sz
== 1 && Z
== 0)
3676 TRACE_INSN (cpu
, "R%i = W[%s + %s] (Z);",
3677 reg
, ptr_name
, imm16s2_str (offset
));
3678 SET_DREG (reg
, GET_WORD (PREG (ptr
) + imm_16s2
));
3680 else if (sz
== 1 && Z
== 1)
3682 TRACE_INSN (cpu
, "R%i = W[%s + %s] (X);",
3683 reg
, ptr_name
, imm16s2_str (offset
));
3684 SET_DREG (reg
, (bs32
) (bs16
) GET_WORD (PREG (ptr
) + imm_16s2
));
3686 else if (sz
== 2 && Z
== 0)
3688 TRACE_INSN (cpu
, "R%i = B[%s + %s] (Z);",
3689 reg
, ptr_name
, imm16_str (offset
));
3690 SET_DREG (reg
, GET_BYTE (PREG (ptr
) + imm_16
));
3692 else if (sz
== 2 && Z
== 1)
3694 TRACE_INSN (cpu
, "R%i = B[%s + %s] (X);",
3695 reg
, ptr_name
, imm16_str (offset
));
3696 SET_DREG (reg
, (bs32
) (bs8
) GET_BYTE (PREG (ptr
) + imm_16
));
3701 if (sz
!= 0 && Z
!= 0)
3702 illegal_instruction (cpu
);
3704 if (sz
== 0 && Z
== 0)
3706 TRACE_INSN (cpu
, "[%s + %s] = R%i;", ptr_name
,
3707 imm16s4_str (offset
), reg
);
3708 PUT_LONG (PREG (ptr
) + imm_16s4
, DREG (reg
));
3710 else if (sz
== 0 && Z
== 1)
3712 TRACE_INSN (cpu
, "[%s + %s] = %s;",
3713 ptr_name
, imm16s4_str (offset
), get_preg_name (reg
));
3714 PUT_LONG (PREG (ptr
) + imm_16s4
, PREG (reg
));
3716 else if (sz
== 1 && Z
== 0)
3718 TRACE_INSN (cpu
, "W[%s + %s] = R%i;",
3719 ptr_name
, imm16s2_str (offset
), reg
);
3720 PUT_WORD (PREG (ptr
) + imm_16s2
, DREG (reg
));
3722 else if (sz
== 2 && Z
== 0)
3724 TRACE_INSN (cpu
, "B[%s + %s] = R%i;",
3725 ptr_name
, imm16_str (offset
), reg
);
3726 PUT_BYTE (PREG (ptr
) + imm_16
, DREG (reg
));
3732 decode_linkage_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3735 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3736 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |.R.|
3737 |.framesize.....................................................|
3738 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3739 int R
= ((iw0
>> (Linkage_R_bits
- 16)) & Linkage_R_mask
);
3740 int framesize
= ((iw1
>> Linkage_framesize_bits
) & Linkage_framesize_mask
);
3743 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_linkage
);
3744 TRACE_EXTRACT (cpu
, "%s: R:%i framesize:%#x", __func__
, R
, framesize
);
3748 int size
= uimm16s4 (framesize
);
3750 TRACE_INSN (cpu
, "LINK %s;", uimm16s4_str (framesize
));
3751 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
3752 illegal_instruction_combination (cpu
);
3754 PUT_LONG (sp
, RETSREG
);
3756 PUT_LONG (sp
, FPREG
);
3763 /* Restore SP from FP. */
3765 TRACE_INSN (cpu
, "UNLINK;");
3766 if (PARALLEL_GROUP
!= BFIN_PARALLEL_NONE
)
3767 illegal_instruction_combination (cpu
);
3768 SET_FPREG (GET_LONG (sp
));
3770 SET_RETSREG (GET_LONG (sp
));
3779 decode_dsp32mac_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3782 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3783 | 1 | 1 | 0 | 0 |.M.| 0 | 0 |.mmod..........|.MM|.P.|.w1|.op1...|
3784 |.h01|.h11|.w0|.op0...|.h00|.h10|.dst.......|.src0......|.src1..|
3785 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3786 int op1
= ((iw0
>> (DSP32Mac_op1_bits
- 16)) & DSP32Mac_op1_mask
);
3787 int w1
= ((iw0
>> (DSP32Mac_w1_bits
- 16)) & DSP32Mac_w1_mask
);
3788 int P
= ((iw0
>> (DSP32Mac_p_bits
- 16)) & DSP32Mac_p_mask
);
3789 int MM
= ((iw0
>> (DSP32Mac_MM_bits
- 16)) & DSP32Mac_MM_mask
);
3790 int mmod
= ((iw0
>> (DSP32Mac_mmod_bits
- 16)) & DSP32Mac_mmod_mask
);
3791 int M
= ((iw0
>> (DSP32Mac_M_bits
- 16)) & DSP32Mac_M_mask
);
3792 int w0
= ((iw1
>> DSP32Mac_w0_bits
) & DSP32Mac_w0_mask
);
3793 int src0
= ((iw1
>> DSP32Mac_src0_bits
) & DSP32Mac_src0_mask
);
3794 int src1
= ((iw1
>> DSP32Mac_src1_bits
) & DSP32Mac_src1_mask
);
3795 int dst
= ((iw1
>> DSP32Mac_dst_bits
) & DSP32Mac_dst_mask
);
3796 int h10
= ((iw1
>> DSP32Mac_h10_bits
) & DSP32Mac_h10_mask
);
3797 int h00
= ((iw1
>> DSP32Mac_h00_bits
) & DSP32Mac_h00_mask
);
3798 int op0
= ((iw1
>> DSP32Mac_op0_bits
) & DSP32Mac_op0_mask
);
3799 int h11
= ((iw1
>> DSP32Mac_h11_bits
) & DSP32Mac_h11_mask
);
3800 int h01
= ((iw1
>> DSP32Mac_h01_bits
) & DSP32Mac_h01_mask
);
3802 bu32 res
= DREG (dst
);
3803 bu32 v_0
= 0, v_1
= 0, zero
= 0, n_1
= 0, n_0
= 0;
3805 static const char * const ops
[] = { "=", "+=", "-=" };
3806 char _buf
[128], *buf
= _buf
;
3809 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32mac
);
3810 TRACE_EXTRACT (cpu
, "%s: M:%i mmod:%i MM:%i P:%i w1:%i op1:%i h01:%i h11:%i "
3811 "w0:%i op0:%i h00:%i h10:%i dst:%i src0:%i src1:%i",
3812 __func__
, M
, mmod
, MM
, P
, w1
, op1
, h01
, h11
, w0
, op0
, h00
, h10
,
3815 if (w0
== 0 && w1
== 0 && op1
== 3 && op0
== 3)
3816 illegal_instruction (cpu
);
3818 if ((w1
|| w0
) && mmod
== M_W32
)
3819 illegal_instruction (cpu
);
3821 if (((1 << mmod
) & (P
? 0x131b : 0x1b5f)) == 0)
3822 illegal_instruction (cpu
);
3824 /* First handle MAC1 side. */
3825 if (w1
== 1 || op1
!= 3)
3827 bu32 res1
= decode_macfunc (cpu
, 1, op1
, h01
, h11
, src0
,
3828 src1
, mmod
, MM
, P
, &v_1
, &n_1
);
3831 buf
+= sprintf (buf
, P
? "R%i" : "R%i.H", dst
+ P
);
3835 buf
+= sprintf (buf
, " = A1");
3836 zero
= !!(res1
== 0);
3841 buf
+= sprintf (buf
, " = (");
3842 buf
+= sprintf (buf
, "A1 %s R%i.%c * R%i.%c", ops
[op1
],
3843 src0
, h01
? 'H' : 'L',
3844 src1
, h11
? 'H' : 'L');
3846 buf
+= sprintf (buf
, ")");
3852 STORE (DREG (dst
+ 1), res1
);
3855 if (res1
& 0xffff0000)
3856 illegal_instruction (cpu
);
3857 res
= REG_H_L (res1
<< 16, res
);
3863 if (w0
== 1 || op0
!= 3)
3866 buf
+= sprintf (buf
, " (M)");
3868 buf
+= sprintf (buf
, ", ");
3872 /* Then handle MAC0 side. */
3873 if (w0
== 1 || op0
!= 3)
3875 bu32 res0
= decode_macfunc (cpu
, 0, op0
, h00
, h10
, src0
,
3876 src1
, mmod
, 0, P
, &v_0
, &n_0
);
3879 buf
+= sprintf (buf
, P
? "R%i" : "R%i.L", dst
);
3883 buf
+= sprintf (buf
, " = A0");
3884 zero
|= !!(res0
== 0);
3889 buf
+= sprintf (buf
, " = (");
3890 buf
+= sprintf (buf
, "A0 %s R%i.%c * R%i.%c", ops
[op0
],
3891 src0
, h00
? 'H' : 'L',
3892 src1
, h10
? 'H' : 'L');
3894 buf
+= sprintf (buf
, ")");
3900 STORE (DREG (dst
), res0
);
3903 if (res0
& 0xffff0000)
3904 illegal_instruction (cpu
);
3905 res
= REG_H_L (res
, res0
);
3912 TRACE_INSN (cpu
, "%s%s;", _buf
, mac_optmode (mmod
, _MM
));
3914 if (!P
&& (w0
|| w1
))
3916 STORE (DREG (dst
), res
);
3917 SET_ASTATREG (v
, v_0
| v_1
);
3919 SET_ASTATREG (vs
, 1);
3923 SET_ASTATREG (v
, v_0
| v_1
);
3925 SET_ASTATREG (vs
, 1);
3928 if ((w0
== 1 && op0
== 3) || (w1
== 1 && op1
== 3))
3930 SET_ASTATREG (az
, zero
);
3931 if (!(w0
== 1 && op0
== 3))
3933 if (!(w1
== 1 && op1
== 3))
3935 SET_ASTATREG (an
, n_1
| n_0
);
3940 decode_dsp32mult_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3943 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3944 | 1 | 1 | 0 | 0 |.M.| 0 | 1 |.mmod..........|.MM|.P.|.w1|.op1...|
3945 |.h01|.h11|.w0|.op0...|.h00|.h10|.dst.......|.src0......|.src1..|
3946 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3947 int op1
= ((iw0
>> (DSP32Mac_op1_bits
- 16)) & DSP32Mac_op1_mask
);
3948 int w1
= ((iw0
>> (DSP32Mac_w1_bits
- 16)) & DSP32Mac_w1_mask
);
3949 int P
= ((iw0
>> (DSP32Mac_p_bits
- 16)) & DSP32Mac_p_mask
);
3950 int MM
= ((iw0
>> (DSP32Mac_MM_bits
- 16)) & DSP32Mac_MM_mask
);
3951 int mmod
= ((iw0
>> (DSP32Mac_mmod_bits
- 16)) & DSP32Mac_mmod_mask
);
3952 int M
= ((iw0
>> (DSP32Mac_M_bits
- 16)) & DSP32Mac_M_mask
);
3953 int w0
= ((iw1
>> DSP32Mac_w0_bits
) & DSP32Mac_w0_mask
);
3954 int src0
= ((iw1
>> DSP32Mac_src0_bits
) & DSP32Mac_src0_mask
);
3955 int src1
= ((iw1
>> DSP32Mac_src1_bits
) & DSP32Mac_src1_mask
);
3956 int dst
= ((iw1
>> DSP32Mac_dst_bits
) & DSP32Mac_dst_mask
);
3957 int h10
= ((iw1
>> DSP32Mac_h10_bits
) & DSP32Mac_h10_mask
);
3958 int h00
= ((iw1
>> DSP32Mac_h00_bits
) & DSP32Mac_h00_mask
);
3959 int op0
= ((iw1
>> DSP32Mac_op0_bits
) & DSP32Mac_op0_mask
);
3960 int h11
= ((iw1
>> DSP32Mac_h11_bits
) & DSP32Mac_h11_mask
);
3961 int h01
= ((iw1
>> DSP32Mac_h01_bits
) & DSP32Mac_h01_mask
);
3963 bu32 res
= DREG (dst
);
3964 bu32 sat0
= 0, sat1
= 0, v_i0
= 0, v_i1
= 0;
3965 char _buf
[128], *buf
= _buf
;
3968 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32mult
);
3969 TRACE_EXTRACT (cpu
, "%s: M:%i mmod:%i MM:%i P:%i w1:%i op1:%i h01:%i h11:%i "
3970 "w0:%i op0:%i h00:%i h10:%i dst:%i src0:%i src1:%i",
3971 __func__
, M
, mmod
, MM
, P
, w1
, op1
, h01
, h11
, w0
, op0
, h00
, h10
,
3974 if (w1
== 0 && w0
== 0)
3975 illegal_instruction (cpu
);
3976 if (((1 << mmod
) & (P
? 0x313 : 0x1b57)) == 0)
3977 illegal_instruction (cpu
);
3978 if (P
&& ((dst
& 1) || (op1
!= 0) || (op0
!= 0) || !is_macmod_pmove (mmod
)))
3979 illegal_instruction (cpu
);
3980 if (!P
&& ((op1
!= 0) || (op0
!= 0) || !is_macmod_hmove (mmod
)))
3981 illegal_instruction (cpu
);
3983 /* First handle MAC1 side. */
3986 bu64 r
= decode_multfunc (cpu
, h01
, h11
, src0
, src1
, mmod
, MM
, &sat1
);
3987 bu32 res1
= extract_mult (cpu
, r
, mmod
, MM
, P
, &v_i1
);
3989 buf
+= sprintf (buf
, P
? "R%i" : "R%i.H", dst
+ P
);
3990 buf
+= sprintf (buf
, " = R%i.%c * R%i.%c",
3991 src0
, h01
? 'H' : 'L',
3992 src1
, h11
? 'H' : 'L');
3996 buf
+= sprintf (buf
, " (M)");
3998 buf
+= sprintf (buf
, ", ");
4002 STORE (DREG (dst
+ 1), res1
);
4005 if (res1
& 0xFFFF0000)
4006 illegal_instruction (cpu
);
4007 res
= REG_H_L (res1
<< 16, res
);
4011 /* First handle MAC0 side. */
4014 bu64 r
= decode_multfunc (cpu
, h00
, h10
, src0
, src1
, mmod
, 0, &sat0
);
4015 bu32 res0
= extract_mult (cpu
, r
, mmod
, 0, P
, &v_i0
);
4017 buf
+= sprintf (buf
, P
? "R%i" : "R%i.L", dst
);
4018 buf
+= sprintf (buf
, " = R%i.%c * R%i.%c",
4019 src0
, h01
? 'H' : 'L',
4020 src1
, h11
? 'H' : 'L');
4023 STORE (DREG (dst
), res0
);
4026 if (res0
& 0xFFFF0000)
4027 illegal_instruction (cpu
);
4028 res
= REG_H_L (res
, res0
);
4032 TRACE_INSN (cpu
, "%s%s;", _buf
, mac_optmode (mmod
, _MM
));
4034 if (!P
&& (w0
|| w1
))
4035 STORE (DREG (dst
), res
);
4039 bu32 v
= sat0
| sat1
| v_i0
| v_i1
;
4041 STORE (ASTATREG (v
), v
);
4042 STORE (ASTATREG (v_copy
), v
);
4044 STORE (ASTATREG (vs
), v
);
4049 decode_dsp32alu_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
4052 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
4053 | 1 | 1 | 0 | 0 |.M.| 1 | 0 | - | - | - |.HL|.aopcde............|
4054 |.aop...|.s.|.x.|.dst0......|.dst1......|.src0......|.src1......|
4055 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
4056 int s
= ((iw1
>> DSP32Alu_s_bits
) & DSP32Alu_s_mask
);
4057 int x
= ((iw1
>> DSP32Alu_x_bits
) & DSP32Alu_x_mask
);
4058 int aop
= ((iw1
>> DSP32Alu_aop_bits
) & DSP32Alu_aop_mask
);
4059 int src0
= ((iw1
>> DSP32Alu_src0_bits
) & DSP32Alu_src0_mask
);
4060 int src1
= ((iw1
>> DSP32Alu_src1_bits
) & DSP32Alu_src1_mask
);
4061 int dst0
= ((iw1
>> DSP32Alu_dst0_bits
) & DSP32Alu_dst0_mask
);
4062 int dst1
= ((iw1
>> DSP32Alu_dst1_bits
) & DSP32Alu_dst1_mask
);
4063 int M
= ((iw0
>> (DSP32Alu_M_bits
- 16)) & DSP32Alu_M_mask
);
4064 int HL
= ((iw0
>> (DSP32Alu_HL_bits
- 16)) & DSP32Alu_HL_mask
);
4065 int aopcde
= ((iw0
>> (DSP32Alu_aopcde_bits
- 16)) & DSP32Alu_aopcde_mask
);
4067 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32alu
);
4068 TRACE_EXTRACT (cpu
, "%s: M:%i HL:%i aopcde:%i aop:%i s:%i x:%i dst0:%i "
4069 "dst1:%i src0:%i src1:%i",
4070 __func__
, M
, HL
, aopcde
, aop
, s
, x
, dst0
, dst1
, src0
, src1
);
4072 if ((aop
== 0 || aop
== 2) && aopcde
== 9 && x
== 0 && s
== 0 && HL
== 0)
4075 TRACE_INSN (cpu
, "A%i.L = R%i.L;", a
, src0
);
4076 SET_AWREG (a
, REG_H_L (AWREG (a
), DREG (src0
)));
4078 else if ((aop
== 0 || aop
== 2) && aopcde
== 9 && x
== 0 && s
== 0 && HL
== 1)
4081 TRACE_INSN (cpu
, "A%i.H = R%i.H;", a
, src0
);
4082 SET_AWREG (a
, REG_H_L (DREG (src0
), AWREG (a
)));
4084 else if ((aop
== 1 || aop
== 0) && aopcde
== 5 && x
== 0 && s
== 0)
4086 bs32 val0
= DREG (src0
);
4087 bs32 val1
= DREG (src1
);
4090 bs32 ovX
, sBit1
, sBit2
, sBitRes1
, sBitRes2
;
4092 TRACE_INSN (cpu
, "R%i.%s = R%i %s R%i (RND12)", dst0
, HL
? "L" : "H",
4093 src0
, aop
& 0x1 ? "-" : "+", src1
);
4095 /* If subtract, just invert and add one. */
4098 if (val1
== 0x80000000)
4104 /* Get the sign bits, since we need them later. */
4105 sBit1
= !!(val0
& 0x80000000);
4106 sBit2
= !!(val1
& 0x80000000);
4110 sBitRes1
= !!(res
& 0x80000000);
4111 /* Round to the 12th bit. */
4113 sBitRes2
= !!(res
& 0x80000000);
4121 positive_res + positive_round = neg
4122 Shift and upper 4 bits where not the same. */
4123 if ((!(sBit1
^ sBit2
) && (sBit1
^ sBitRes1
))
4124 || (!sBit1
&& !sBit2
&& sBitRes2
)
4125 || ((signRes
!= 0) && (signRes
!= -1)))
4127 /* Both X1 and X2 Neg res is neg overflow. */
4130 /* Both X1 and X2 Pos res is pos overflow. */
4131 else if (!sBit1
&& !sBit2
)
4133 /* Pos+Neg or Neg+Pos take the sign of the result. */
4143 /* Shift up now after overflow detection. */
4151 STORE (DREG (dst0
), REG_H_L (res
<< 16, DREG (dst0
)));
4153 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), res
));
4155 SET_ASTATREG (az
, res
== 0);
4156 SET_ASTATREG (an
, res
& 0x8000);
4157 SET_ASTATREG (v
, ovX
);
4159 SET_ASTATREG (vs
, ovX
);
4161 else if ((aop
== 2 || aop
== 3) && aopcde
== 5 && x
== 1 && s
== 0)
4163 bs32 val0
= DREG (src0
);
4164 bs32 val1
= DREG (src1
);
4167 TRACE_INSN (cpu
, "R%i.%s = R%i %s R%i (RND20)", dst0
, HL
? "L" : "H",
4168 src0
, aop
& 0x1 ? "-" : "+", src1
);
4170 /* If subtract, just invert and add one. */
4174 res
= (val0
>> 4) + (val1
>> 4) + (((val0
& 0xf) + (val1
& 0xf)) >> 4);
4176 /* Don't sign extend during the shift. */
4177 res
= ((bu32
)res
>> 16);
4179 /* Don't worry about overflows, since we are shifting right. */
4182 STORE (DREG (dst0
), REG_H_L (res
<< 16, DREG (dst0
)));
4184 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), res
));
4186 SET_ASTATREG (az
, res
== 0);
4187 SET_ASTATREG (an
, res
& 0x8000);
4188 SET_ASTATREG (v
, 0);
4190 else if ((aopcde
== 2 || aopcde
== 3) && x
== 0)
4192 bu32 s1
, s2
, val
, ac0_i
= 0, v_i
= 0;
4194 TRACE_INSN (cpu
, "R%i.%c = R%i.%c %c R%i.%c%s;",
4195 dst0
, HL
? 'H' : 'L',
4196 src0
, aop
& 2 ? 'H' : 'L',
4197 aopcde
== 2 ? '+' : '-',
4198 src1
, aop
& 1 ? 'H' : 'L',
4209 val
= add16 (cpu
, s1
, s2
, &ac0_i
, &v_i
, 0, 0, s
, 0);
4211 val
= sub16 (cpu
, s1
, s2
, &ac0_i
, &v_i
, 0, 0, s
, 0);
4213 SET_ASTATREG (ac0
, ac0_i
);
4214 SET_ASTATREG (v
, v_i
);
4216 SET_ASTATREG (vs
, v_i
);
4219 SET_DREG_H (dst0
, val
<< 16);
4221 SET_DREG_L (dst0
, val
);
4223 SET_ASTATREG (an
, val
& 0x8000);
4224 SET_ASTATREG (az
, val
== 0);
4226 else if ((aop
== 0 || aop
== 2) && aopcde
== 9 && x
== 0 && s
== 1 && HL
== 0)
4229 TRACE_INSN (cpu
, "A%i = R%i;", a
, src0
);
4230 SET_AREG32 (a
, DREG (src0
));
4232 else if ((aop
== 1 || aop
== 3) && aopcde
== 9 && x
== 0 && s
== 0 && HL
== 0)
4235 TRACE_INSN (cpu
, "A%i.X = R%i.L;", a
, src0
);
4236 SET_AXREG (a
, (bs8
)DREG (src0
));
4238 else if (aop
== 3 && aopcde
== 11 && x
== 0 && HL
== 0)
4240 bu64 acc0
= get_extended_acc (cpu
, 0);
4241 bu64 acc1
= get_extended_acc (cpu
, 1);
4242 bu32 carry
= (bu40
)acc1
< (bu40
)acc0
;
4245 TRACE_INSN (cpu
, "A0 -= A1%s;", s
? " (W32)" : "");
4248 if ((bs64
)acc0
< -0x8000000000ll
)
4249 acc0
= -0x8000000000ull
, sat
= 1;
4250 else if ((bs64
)acc0
>= 0x7fffffffffll
)
4251 acc0
= 0x7fffffffffull
, sat
= 1;
4255 /* A0 -= A1 (W32) */
4256 if (acc0
& (bu64
)0x8000000000ll
)
4257 acc0
&= 0x80ffffffffll
, sat
= 1;
4259 acc0
&= 0xffffffffll
;
4261 STORE (AXREG (0), (acc0
>> 32) & 0xff);
4262 STORE (AWREG (0), acc0
& 0xffffffff);
4263 STORE (ASTATREG (az
), acc0
== 0);
4264 STORE (ASTATREG (an
), !!(acc0
& (bu64
)0x8000000000ll
));
4265 STORE (ASTATREG (ac0
), carry
);
4266 STORE (ASTATREG (ac0_copy
), carry
);
4267 STORE (ASTATREG (av0
), sat
);
4269 STORE (ASTATREG (av0s
), sat
);
4271 else if ((aop
== 0 || aop
== 1) && aopcde
== 22 && x
== 0)
4273 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4275 const char * const opts
[] = { "rndl", "rndh", "tl", "th" };
4277 TRACE_INSN (cpu
, "R%i = BYTEOP2P (R%i:%i, R%i:%i) (%s%s);", dst0
,
4278 src0
+ 1, src0
, src1
+ 1, src1
, opts
[HL
+ (aop
<< 1)],
4281 if ((src1
!= 0 && src1
!= 2) || (src0
!= 0 && src0
!= 2))
4282 illegal_instruction (cpu
);
4285 s0H
= DREG (src0
+ 1);
4287 s1H
= DREG (src1
+ 1);
4290 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4291 s1
= algn (s1H
, s1L
, IREG (0) & 3);
4295 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4296 s1
= algn (s1L
, s1H
, IREG (0) & 3);
4300 tmp0
= ((((s1
>> 8) & 0xff) + ((s1
>> 0) & 0xff) +
4301 ((s0
>> 8) & 0xff) + ((s0
>> 0) & 0xff) + i
) >> 2) & 0xff;
4302 tmp1
= ((((s1
>> 24) & 0xff) + ((s1
>> 16) & 0xff) +
4303 ((s0
>> 24) & 0xff) + ((s0
>> 16) & 0xff) + i
) >> 2) & 0xff;
4304 STORE (DREG (dst0
), (tmp1
<< (16 + (HL
* 8))) | (tmp0
<< (HL
* 8)));
4306 /* Implicit DISALGNEXCPT in parallel. */
4309 else if ((aop
== 0 || aop
== 1) && aopcde
== 8 && x
== 0 && s
== 0 && HL
== 0)
4311 TRACE_INSN (cpu
, "A%i = 0;", aop
);
4314 else if (aop
== 2 && aopcde
== 8 && x
== 0 && s
== 0 && HL
== 0)
4316 TRACE_INSN (cpu
, "A1 = A0 = 0;");
4320 else if ((aop
== 0 || aop
== 1 || aop
== 2) && s
== 1 && aopcde
== 8
4321 && x
== 0 && s
== 1 && HL
== 0)
4323 bs40 acc0
= get_extended_acc (cpu
, 0);
4324 bs40 acc1
= get_extended_acc (cpu
, 1);
4327 if (aop
== 0 || aop
== 1)
4328 TRACE_INSN (cpu
, "A%i = A%i (S);", aop
, aop
);
4330 TRACE_INSN (cpu
, "A1 = A1 (S), A0 = A0 (S);");
4332 if (aop
== 0 || aop
== 2)
4335 acc0
= saturate_s32 (acc0
, &sat
);
4336 acc0
|= -(acc0
& 0x80000000ull
);
4337 SET_AXREG (0, (acc0
>> 31) & 0xFF);
4338 SET_AWREG (0, acc0
& 0xFFFFFFFF);
4339 SET_ASTATREG (av0
, sat
);
4341 SET_ASTATREG (av0s
, sat
);
4346 if (aop
== 1 || aop
== 2)
4349 acc1
= saturate_s32 (acc1
, &sat
);
4350 acc1
|= -(acc1
& 0x80000000ull
);
4351 SET_AXREG (1, (acc1
>> 31) & 0xFF);
4352 SET_AWREG (1, acc1
& 0xFFFFFFFF);
4353 SET_ASTATREG (av1
, sat
);
4355 SET_ASTATREG (av1s
, sat
);
4360 SET_ASTATREG (az
, (acc0
== 0) || (acc1
== 0));
4361 SET_ASTATREG (an
, ((acc0
>> 31) & 1) || ((acc1
>> 31) & 1));
4363 else if (aop
== 3 && aopcde
== 8 && x
== 0 && HL
== 0)
4365 TRACE_INSN (cpu
, "A%i = A%i;", s
, !s
);
4366 SET_AXREG (s
, AXREG (!s
));
4367 SET_AWREG (s
, AWREG (!s
));
4369 else if (aop
== 3 && HL
== 0 && aopcde
== 16 && x
== 0 && s
== 0)
4374 TRACE_INSN (cpu
, "A1 = ABS A1 , A0 = ABS A0;");
4377 for (i
= 0; i
< 2; ++i
)
4380 bs40 acc
= get_extended_acc (cpu
, i
);
4384 av
= acc
== ((bs40
)1 << 39);
4386 acc
= ((bs40
)1 << 39) - 1;
4389 SET_ASTATREG (av
[i
], av
);
4391 SET_ASTATREG (avs
[i
], av
);
4394 SET_ASTATREG (az
, az
);
4395 SET_ASTATREG (an
, 0);
4397 else if (aop
== 0 && aopcde
== 23 && x
== 0)
4399 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4402 TRACE_INSN (cpu
, "R%i = BYTEOP3P (R%i:%i, R%i:%i) (%s%s);", dst0
,
4403 src0
+ 1, src0
, src1
+ 1, src1
, HL
? "HI" : "LO",
4406 if ((src1
!= 0 && src1
!= 2) || (src0
!= 0 && src0
!= 2))
4407 illegal_instruction (cpu
);
4410 s0H
= DREG (src0
+ 1);
4412 s1H
= DREG (src1
+ 1);
4415 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4416 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4420 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4421 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4424 tmp0
= (bs32
)(bs16
)(s0
>> 0) + ((s1
>> ( 0 + (8 * !HL
))) & 0xff);
4425 tmp1
= (bs32
)(bs16
)(s0
>> 16) + ((s1
>> (16 + (8 * !HL
))) & 0xff);
4426 STORE (DREG (dst0
), (CLAMP (tmp0
, 0, 255) << ( 0 + (8 * HL
))) |
4427 (CLAMP (tmp1
, 0, 255) << (16 + (8 * HL
))));
4429 /* Implicit DISALGNEXCPT in parallel. */
4432 else if ((aop
== 0 || aop
== 1) && aopcde
== 16 && x
== 0 && s
== 0)
4437 TRACE_INSN (cpu
, "A%i = ABS A%i;", HL
, aop
);
4439 acc
= get_extended_acc (cpu
, aop
);
4442 av
= acc
== ((bs40
)1 << 39);
4444 acc
= ((bs40
)1 << 39) - 1;
4447 SET_ASTATREG (av
[HL
], av
);
4449 SET_ASTATREG (avs
[HL
], av
);
4450 SET_ASTATREG (az
, acc
== 0);
4451 SET_ASTATREG (an
, 0);
4453 else if (aop
== 3 && aopcde
== 12 && x
== 0 && s
== 0)
4455 bs32 res
= DREG (src0
);
4457 bool sBit_a
, sBit_b
;
4459 TRACE_INSN (cpu
, "R%i.%s = R%i (RND);", dst0
, HL
== 0 ? "L" : "H", src0
);
4460 TRACE_DECODE (cpu
, "R%i.%s = R%i:%#x (RND);", dst0
,
4461 HL
== 0 ? "L" : "H", src0
, res
);
4463 sBit_b
= !!(res
& 0x80000000);
4466 sBit_a
= !!(res
& 0x80000000);
4468 /* Overflow if the sign bit changed when we rounded. */
4469 if ((res
>> 16) && (sBit_b
!= sBit_a
))
4484 SET_DREG (dst0
, REG_H_L (DREG (dst0
), res
));
4486 SET_DREG (dst0
, REG_H_L (res
<< 16, DREG (dst0
)));
4488 SET_ASTATREG (az
, res
== 0);
4489 SET_ASTATREG (an
, res
< 0);
4490 SET_ASTATREG (v
, ovX
);
4492 SET_ASTATREG (vs
, ovX
);
4494 else if (aop
== 3 && HL
== 0 && aopcde
== 15 && x
== 0 && s
== 0)
4496 bu32 hi
= (-(bs16
)(DREG (src0
) >> 16)) << 16;
4497 bu32 lo
= (-(bs16
)(DREG (src0
) & 0xFFFF)) & 0xFFFF;
4500 TRACE_INSN (cpu
, "R%i = -R%i (V);", dst0
, src0
);
4504 if (hi
== 0x80000000)
4520 SET_DREG (dst0
, hi
| lo
);
4522 SET_ASTATREG (v
, v
);
4524 SET_ASTATREG (vs
, 1);
4525 SET_ASTATREG (ac0
, ac0
);
4526 SET_ASTATREG (ac1
, ac1
);
4527 setflags_nz_2x16 (cpu
, DREG (dst0
));
4529 else if (aop
== 3 && HL
== 0 && aopcde
== 14 && x
== 0 && s
== 0)
4531 TRACE_INSN (cpu
, "A1 = - A1 , A0 = - A0;");
4533 SET_AREG (0, saturate_s40 (-get_extended_acc (cpu
, 0)));
4534 SET_AREG (1, saturate_s40 (-get_extended_acc (cpu
, 1)));
4535 /* XXX: what ASTAT flags need updating ? */
4537 else if ((aop
== 0 || aop
== 1) && aopcde
== 14 && x
== 0 && s
== 0)
4539 bs40 src_acc
= get_extended_acc (cpu
, aop
);
4542 TRACE_INSN (cpu
, "A%i = - A%i;", HL
, aop
);
4544 SET_AREG (HL
, saturate_s40_astat (-src_acc
, &v
));
4546 SET_ASTATREG (az
, AWREG (HL
) == 0 && AXREG (HL
) == 0);
4547 SET_ASTATREG (an
, AXREG (HL
) >> 7);
4550 SET_ASTATREG (ac0
, !src_acc
);
4551 SET_ASTATREG (av0
, v
);
4553 SET_ASTATREG (av0s
, 1);
4557 SET_ASTATREG (ac1
, !src_acc
);
4558 SET_ASTATREG (av1
, v
);
4560 SET_ASTATREG (av1s
, 1);
4563 else if (aop
== 0 && aopcde
== 12 && x
== 0 && s
== 0 && HL
== 0)
4565 bs16 tmp0_hi
= DREG (src0
) >> 16;
4566 bs16 tmp0_lo
= DREG (src0
);
4567 bs16 tmp1_hi
= DREG (src1
) >> 16;
4568 bs16 tmp1_lo
= DREG (src1
);
4570 TRACE_INSN (cpu
, "R%i.L = R%i.H = SIGN(R%i.H) * R%i.H + SIGN(R%i.L) * R%i.L;",
4571 dst0
, dst0
, src0
, src1
, src0
, src1
);
4573 if ((tmp0_hi
>> 15) & 1)
4574 tmp1_hi
= ~tmp1_hi
+ 1;
4576 if ((tmp0_lo
>> 15) & 1)
4577 tmp1_lo
= ~tmp1_lo
+ 1;
4579 tmp1_hi
= tmp1_hi
+ tmp1_lo
;
4581 STORE (DREG (dst0
), REG_H_L (tmp1_hi
<< 16, tmp1_hi
));
4583 else if (aopcde
== 0 && HL
== 0)
4585 bu32 s0
= DREG (src0
);
4586 bu32 s1
= DREG (src1
);
4587 bu32 s0h
= s0
>> 16;
4588 bu32 s0l
= s0
& 0xFFFF;
4589 bu32 s1h
= s1
>> 16;
4590 bu32 s1l
= s1
& 0xFFFF;
4592 bu32 ac1_i
= 0, ac0_i
= 0, v_i
= 0, z_i
= 0, n_i
= 0;
4594 TRACE_INSN (cpu
, "R%i = R%i %c|%c R%i%s;", dst0
, src0
,
4595 (aop
& 2) ? '-' : '+', (aop
& 1) ? '-' : '+', src1
,
4598 t0
= sub16 (cpu
, s0h
, s1h
, &ac1_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4600 t0
= add16 (cpu
, s0h
, s1h
, &ac1_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4603 t1
= sub16 (cpu
, s0l
, s1l
, &ac0_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4605 t1
= add16 (cpu
, s0l
, s1l
, &ac0_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4607 SET_ASTATREG (ac1
, ac1_i
);
4608 SET_ASTATREG (ac0
, ac0_i
);
4609 SET_ASTATREG (az
, z_i
);
4610 SET_ASTATREG (an
, n_i
);
4611 SET_ASTATREG (v
, v_i
);
4613 SET_ASTATREG (vs
, v_i
);
4618 SET_DREG (dst0
, (t1
<< 16) | t0
);
4620 SET_DREG (dst0
, (t0
<< 16) | t1
);
4622 else if (aop
== 1 && aopcde
== 12 && x
== 0 && s
== 0 && HL
== 0)
4624 bs32 val0
= (bs16
)(AWREG (0) >> 16) + (bs16
)AWREG (0);
4625 bs32 val1
= (bs16
)(AWREG (1) >> 16) + (bs16
)AWREG (1);
4627 TRACE_INSN (cpu
, "R%i = A1.L + A1.H, R%i = A0.L + A0.H;", dst1
, dst0
);
4630 illegal_instruction_combination (cpu
);
4632 SET_DREG (dst0
, val0
);
4633 SET_DREG (dst1
, val1
);
4635 else if ((aop
== 0 || aop
== 2 || aop
== 3) && aopcde
== 1)
4639 bu16 s0L
= DREG (src0
);
4640 bu16 s0H
= DREG (src0
) >> 16;
4641 bu16 s1L
= DREG (src1
);
4642 bu16 s1H
= DREG (src1
) >> 16;
4643 bu32 v_i
= 0, n_i
= 0, z_i
= 0;
4645 TRACE_INSN (cpu
, "R%i = R%i %s R%i, R%i = R%i %s R%i%s;",
4646 dst1
, src0
, HL
? "+|-" : "+|+", src1
,
4647 dst0
, src0
, HL
? "-|+" : "-|-", src1
,
4648 amod0amod2 (s
, x
, aop
));
4651 illegal_instruction_combination (cpu
);
4655 x0
= add16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4656 x1
= add16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4657 d1
= (x0
<< 16) | x1
;
4659 x0
= sub16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4660 x1
= sub16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4662 d0
= (x0
<< 16) | x1
;
4664 d0
= (x1
<< 16) | x0
;
4668 x0
= add16 (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;
4670 d1
= (x0
<< 16) | x1
;
4672 x0
= sub16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4673 x1
= add16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4675 d0
= (x0
<< 16) | x1
;
4677 d0
= (x1
<< 16) | x0
;
4679 SET_ASTATREG (az
, z_i
);
4680 SET_ASTATREG (an
, n_i
);
4681 SET_ASTATREG (v
, v_i
);
4683 SET_ASTATREG (vs
, v_i
);
4685 STORE (DREG (dst0
), d0
);
4686 STORE (DREG (dst1
), d1
);
4688 else if ((aop
== 0 || aop
== 1 || aop
== 2) && aopcde
== 11 && x
== 0)
4690 bs40 acc0
= get_extended_acc (cpu
, 0);
4691 bs40 acc1
= get_extended_acc (cpu
, 1);
4692 bu32 v
, dreg
, sat
= 0;
4693 bu32 carry
= !!((bu40
)~acc1
< (bu40
)acc0
);
4697 if (s
!= 0 || HL
!= 0)
4698 illegal_instruction (cpu
);
4699 TRACE_INSN (cpu
, "R%i = (A0 += A1);", dst0
);
4704 illegal_instruction (cpu
);
4705 TRACE_INSN (cpu
, "R%i.%c = (A0 += A1);", dst0
, HL
? 'H' : 'L');
4710 illegal_instruction (cpu
);
4711 TRACE_INSN (cpu
, "A0 += A1%s;", s
? " (W32)" : "");
4715 acc0
= saturate_s40_astat (acc0
, &v
);
4717 if (aop
== 2 && s
== 1) /* A0 += A1 (W32) */
4719 if (acc0
& (bs40
)0x8000000000ll
)
4720 acc0
&= 0x80ffffffffll
;
4722 acc0
&= 0xffffffffll
;
4725 STORE (AXREG (0), acc0
>> 32);
4726 STORE (AWREG (0), acc0
);
4727 SET_ASTATREG (av0
, v
&& acc1
);
4729 SET_ASTATREG (av0s
, v
);
4731 if (aop
== 0 || aop
== 1)
4733 if (aop
) /* Dregs_lo = A0 += A1 */
4735 dreg
= saturate_s32 (rnd16 (acc0
) << 16, &sat
);
4737 STORE (DREG (dst0
), REG_H_L (dreg
, DREG (dst0
)));
4739 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), dreg
>> 16));
4741 else /* Dregs = A0 += A1 */
4743 dreg
= saturate_s32 (acc0
, &sat
);
4744 STORE (DREG (dst0
), dreg
);
4747 STORE (ASTATREG (az
), dreg
== 0);
4748 STORE (ASTATREG (an
), !!(dreg
& 0x80000000));
4749 STORE (ASTATREG (ac0
), carry
);
4750 STORE (ASTATREG (ac0_copy
), carry
);
4751 STORE (ASTATREG (v
), sat
);
4752 STORE (ASTATREG (v_copy
), sat
);
4754 STORE (ASTATREG (vs
), sat
);
4758 STORE (ASTATREG (az
), acc0
== 0);
4759 STORE (ASTATREG (an
), !!(acc0
& 0x8000000000ull
));
4760 STORE (ASTATREG (ac0
), carry
);
4761 STORE (ASTATREG (ac0_copy
), carry
);
4764 else if ((aop
== 0 || aop
== 1) && aopcde
== 10 && x
== 0 && s
== 0 && HL
== 0)
4766 TRACE_INSN (cpu
, "R%i.L = A%i.X;", dst0
, aop
);
4767 SET_DREG_L (dst0
, (bs8
)AXREG (aop
));
4769 else if (aop
== 0 && aopcde
== 4 && x
== 0 && HL
== 0)
4771 TRACE_INSN (cpu
, "R%i = R%i + R%i%s;", dst0
, src0
, src1
, amod1 (s
, x
));
4772 SET_DREG (dst0
, add32 (cpu
, DREG (src0
), DREG (src1
), 1, s
));
4774 else if (aop
== 1 && aopcde
== 4 && x
== 0 && HL
== 0)
4776 TRACE_INSN (cpu
, "R%i = R%i - R%i%s;", dst0
, src0
, src1
, amod1 (s
, x
));
4777 SET_DREG (dst0
, sub32 (cpu
, DREG (src0
), DREG (src1
), 1, s
, 0));
4779 else if (aop
== 2 && aopcde
== 4 && x
== 0 && HL
== 0)
4781 TRACE_INSN (cpu
, "R%i = R%i + R%i, R%i = R%i - R%i%s;",
4782 dst1
, src0
, src1
, dst0
, src0
, src1
, amod1 (s
, x
));
4785 illegal_instruction_combination (cpu
);
4787 STORE (DREG (dst1
), add32 (cpu
, DREG (src0
), DREG (src1
), 1, s
));
4788 STORE (DREG (dst0
), sub32 (cpu
, DREG (src0
), DREG (src1
), 1, s
, 1));
4790 else if ((aop
== 0 || aop
== 1) && aopcde
== 17 && x
== 0 && HL
== 0)
4792 bs40 acc0
= get_extended_acc (cpu
, 0);
4793 bs40 acc1
= get_extended_acc (cpu
, 1);
4794 bs40 val0
, val1
, sval0
, sval1
;
4797 TRACE_INSN (cpu
, "R%i = A%i + A%i, R%i = A%i - A%i%s",
4798 dst1
, !aop
, aop
, dst0
, !aop
, aop
, amod1 (s
, x
));
4799 TRACE_DECODE (cpu
, "R%i = A%i:%#"PRIx64
" + A%i:%#"PRIx64
", "
4800 "R%i = A%i:%#"PRIx64
" - A%i:%#"PRIx64
"%s",
4801 dst1
, !aop
, aop
? acc0
: acc1
, aop
, aop
? acc1
: acc0
,
4802 dst0
, !aop
, aop
? acc0
: acc1
, aop
, aop
? acc1
: acc0
,
4806 illegal_instruction_combination (cpu
);
4814 sval0
= saturate_s32 (val0
, &sat
);
4816 sval1
= saturate_s32 (val1
, &sat
);
4824 STORE (DREG (dst0
), val0
);
4825 STORE (DREG (dst1
), val1
);
4826 SET_ASTATREG (v
, sat_i
);
4828 SET_ASTATREG (vs
, sat_i
);
4829 SET_ASTATREG (an
, val0
& 0x80000000 || val1
& 0x80000000);
4830 SET_ASTATREG (az
, val0
== 0 || val1
== 0);
4831 SET_ASTATREG (ac1
, (bu40
)~acc0
< (bu40
)acc1
);
4833 SET_ASTATREG (ac0
, !!((bu40
)acc1
<= (bu40
)acc0
));
4835 SET_ASTATREG (ac0
, !!((bu40
)acc0
<= (bu40
)acc1
));
4837 else if (aop
== 0 && aopcde
== 18 && x
== 0 && HL
== 0)
4839 bu40 acc0
= get_extended_acc (cpu
, 0);
4840 bu40 acc1
= get_extended_acc (cpu
, 1);
4841 bu32 s0L
= DREG (src0
);
4842 bu32 s0H
= DREG (src0
+ 1);
4843 bu32 s1L
= DREG (src1
);
4844 bu32 s1H
= DREG (src1
+ 1);
4846 bs16 tmp0
, tmp1
, tmp2
, tmp3
;
4848 /* This instruction is only defined for register pairs R1:0 and R3:2. */
4849 if (!((src0
== 0 || src0
== 2) && (src1
== 0 || src1
== 2)))
4850 illegal_instruction (cpu
);
4852 TRACE_INSN (cpu
, "SAA (R%i:%i, R%i:%i)%s", src0
+ 1, src0
,
4853 src1
+ 1, src1
, s
? " (R)" :"");
4855 /* Bit s determines the order of the two registers from a pair:
4856 if s=0 the low-order bytes come from the low reg in the pair,
4857 and if s=1 the low-order bytes come from the high reg. */
4861 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4862 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4866 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4867 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4870 /* Find the absolute difference between pairs, make it
4871 absolute, then add it to the existing accumulator half. */
4873 tmp0
= ((s0
<< 24) >> 24) - ((s1
<< 24) >> 24);
4874 tmp1
= ((s0
<< 16) >> 24) - ((s1
<< 16) >> 24);
4875 tmp2
= ((s0
<< 8) >> 24) - ((s1
<< 8) >> 24);
4876 tmp3
= ((s0
<< 0) >> 24) - ((s1
<< 0) >> 24);
4878 tmp0
= (tmp0
< 0) ? -tmp0
: tmp0
;
4879 tmp1
= (tmp1
< 0) ? -tmp1
: tmp1
;
4880 tmp2
= (tmp2
< 0) ? -tmp2
: tmp2
;
4881 tmp3
= (tmp3
< 0) ? -tmp3
: tmp3
;
4883 s0L
= saturate_u16 ((bu32
)tmp0
+ ((acc0
>> 0) & 0xffff), 0);
4884 s0H
= saturate_u16 ((bu32
)tmp1
+ ((acc0
>> 16) & 0xffff), 0);
4885 s1L
= saturate_u16 ((bu32
)tmp2
+ ((acc1
>> 0) & 0xffff), 0);
4886 s1H
= saturate_u16 ((bu32
)tmp3
+ ((acc1
>> 16) & 0xffff), 0);
4888 STORE (AWREG (0), (s0H
<< 16) | (s0L
& 0xFFFF));
4889 STORE (AXREG (0), 0);
4890 STORE (AWREG (1), (s1H
<< 16) | (s1L
& 0xFFFF));
4891 STORE (AXREG (1), 0);
4893 /* Implicit DISALGNEXCPT in parallel. */
4896 else if (aop
== 3 && aopcde
== 18 && x
== 0 && s
== 0 && HL
== 0)
4898 TRACE_INSN (cpu
, "DISALGNEXCPT");
4901 else if ((aop
== 0 || aop
== 1) && aopcde
== 20 && x
== 0 && HL
== 0)
4903 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4904 const char * const opts
[] = { "", " (R)", " (T)", " (T, R)" };
4906 TRACE_INSN (cpu
, "R%i = BYTEOP1P (R%i:%i, R%i:%i)%s;", dst0
,
4907 src0
+ 1, src0
, src1
+ 1, src1
, opts
[s
+ (aop
<< 1)]);
4909 if ((src1
!= 0 && src1
!= 2) || (src0
!= 0 && src0
!= 2))
4910 illegal_instruction (cpu
);
4913 s0H
= DREG (src0
+ 1);
4915 s1H
= DREG (src1
+ 1);
4918 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4919 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4923 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4924 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4928 (((((s0
>> 0) & 0xff) + ((s1
>> 0) & 0xff) + !aop
) >> 1) << 0) |
4929 (((((s0
>> 8) & 0xff) + ((s1
>> 8) & 0xff) + !aop
) >> 1) << 8) |
4930 (((((s0
>> 16) & 0xff) + ((s1
>> 16) & 0xff) + !aop
) >> 1) << 16) |
4931 (((((s0
>> 24) & 0xff) + ((s1
>> 24) & 0xff) + !aop
) >> 1) << 24));
4933 /* Implicit DISALGNEXCPT in parallel. */
4936 else if (aop
== 0 && aopcde
== 21 && x
== 0 && HL
== 0)
4938 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4940 TRACE_INSN (cpu
, "(R%i, R%i) = BYTEOP16P (R%i:%i, R%i:%i)%s;", dst1
, dst0
,
4941 src0
+ 1, src0
, src1
+ 1, src1
, s
? " (R)" : "");
4943 if ((src1
!= 0 && src1
!= 2) || (src0
!= 0 && src0
!= 2))
4944 illegal_instruction (cpu
);
4947 illegal_instruction_combination (cpu
);
4950 s0H
= DREG (src0
+ 1);
4952 s1H
= DREG (src1
+ 1);
4955 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4956 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4960 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4961 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4965 ((((s0
>> 0) & 0xff) + ((s1
>> 0) & 0xff)) << 0) |
4966 ((((s0
>> 8) & 0xff) + ((s1
>> 8) & 0xff)) << 16));
4968 ((((s0
>> 16) & 0xff) + ((s1
>> 16) & 0xff)) << 0) |
4969 ((((s0
>> 24) & 0xff) + ((s1
>> 24) & 0xff)) << 16));
4971 /* Implicit DISALGNEXCPT in parallel. */
4974 else if (aop
== 1 && aopcde
== 21 && x
== 0 && HL
== 0)
4976 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4978 TRACE_INSN (cpu
, "(R%i, R%i) = BYTEOP16M (R%i:%i, R%i:%i)%s;", dst1
, dst0
,
4979 src0
+ 1, src0
, src1
+ 1, src1
, s
? " (R)" : "");
4981 if ((src1
!= 0 && src1
!= 2) || (src0
!= 0 && src0
!= 2))
4982 illegal_instruction (cpu
);
4985 illegal_instruction_combination (cpu
);
4988 s0H
= DREG (src0
+ 1);
4990 s1H
= DREG (src1
+ 1);
4993 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4994 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4998 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4999 s1
= algn (s1L
, s1H
, IREG (1) & 3);
5003 (((((s0
>> 0) & 0xff) - ((s1
>> 0) & 0xff)) << 0) & 0xffff) |
5004 (((((s0
>> 8) & 0xff) - ((s1
>> 8) & 0xff)) << 16)));
5006 (((((s0
>> 16) & 0xff) - ((s1
>> 16) & 0xff)) << 0) & 0xffff) |
5007 (((((s0
>> 24) & 0xff) - ((s1
>> 24) & 0xff)) << 16)));
5009 /* Implicit DISALGNEXCPT in parallel. */
5012 else if (aop
== 1 && aopcde
== 7 && x
== 0 && s
== 0 && HL
== 0)
5014 TRACE_INSN (cpu
, "R%i = MIN (R%i, R%i);", dst0
, src0
, src1
);
5015 SET_DREG (dst0
, min32 (cpu
, DREG (src0
), DREG (src1
)));
5017 else if (aop
== 0 && aopcde
== 7 && x
== 0 && s
== 0 && HL
== 0)
5019 TRACE_INSN (cpu
, "R%i = MAX (R%i, R%i);", dst0
, src0
, src1
);
5020 SET_DREG (dst0
, max32 (cpu
, DREG (src0
), DREG (src1
)));
5022 else if (aop
== 2 && aopcde
== 7 && x
== 0 && s
== 0 && HL
== 0)
5024 bu32 val
= DREG (src0
);
5027 TRACE_INSN (cpu
, "R%i = ABS R%i;", dst0
, src0
);
5031 v
= (val
== 0x80000000);
5034 SET_DREG (dst0
, val
);
5036 SET_ASTATREG (v
, v
);
5038 SET_ASTATREG (vs
, 1);
5039 setflags_nz (cpu
, val
);
5041 else if (aop
== 3 && aopcde
== 7 && x
== 0 && HL
== 0)
5043 bu32 val
= DREG (src0
);
5045 TRACE_INSN (cpu
, "R%i = - R%i%s;", dst0
, src0
, amod1 (s
, 0));
5047 if (s
&& val
== 0x80000000)
5050 SET_ASTATREG (v
, 1);
5051 SET_ASTATREG (vs
, 1);
5053 else if (val
== 0x80000000)
5057 SET_DREG (dst0
, val
);
5059 SET_ASTATREG (az
, val
== 0);
5060 SET_ASTATREG (an
, val
& 0x80000000);
5062 else if (aop
== 2 && aopcde
== 6 && x
== 0 && s
== 0 && HL
== 0)
5064 bu32 in
= DREG (src0
);
5065 bu32 hi
= (in
& 0x80000000 ? (bu32
)-(bs16
)(in
>> 16) : in
>> 16) << 16;
5066 bu32 lo
= (in
& 0x8000 ? (bu32
)-(bs16
)(in
& 0xFFFF) : in
) & 0xFFFF;
5069 TRACE_INSN (cpu
, "R%i = ABS R%i (V);", dst0
, src0
);
5072 if (hi
== 0x80000000)
5082 SET_DREG (dst0
, hi
| lo
);
5084 SET_ASTATREG (v
, v
);
5086 SET_ASTATREG (vs
, 1);
5087 setflags_nz_2x16 (cpu
, DREG (dst0
));
5089 else if (aop
== 1 && aopcde
== 6 && x
== 0 && s
== 0 && HL
== 0)
5091 TRACE_INSN (cpu
, "R%i = MIN (R%i, R%i) (V);", dst0
, src0
, src1
);
5092 SET_DREG (dst0
, min2x16 (cpu
, DREG (src0
), DREG (src1
)));
5094 else if (aop
== 0 && aopcde
== 6 && x
== 0 && s
== 0 && HL
== 0)
5096 TRACE_INSN (cpu
, "R%i = MAX (R%i, R%i) (V);", dst0
, src0
, src1
);
5097 SET_DREG (dst0
, max2x16 (cpu
, DREG (src0
), DREG (src1
)));
5099 else if (aop
== 0 && aopcde
== 24 && x
== 0 && s
== 0 && HL
== 0)
5101 TRACE_INSN (cpu
, "R%i = BYTEPACK (R%i, R%i);", dst0
, src0
, src1
);
5103 (((DREG (src0
) >> 0) & 0xff) << 0) |
5104 (((DREG (src0
) >> 16) & 0xff) << 8) |
5105 (((DREG (src1
) >> 0) & 0xff) << 16) |
5106 (((DREG (src1
) >> 16) & 0xff) << 24));
5108 /* Implicit DISALGNEXCPT in parallel. */
5111 else if (aop
== 1 && aopcde
== 24 && x
== 0 && HL
== 0)
5115 bu8 bytea
, byteb
, bytec
, byted
;
5117 TRACE_INSN (cpu
, "(R%i, R%i) = BYTEUNPACK R%i:%i%s;",
5118 dst1
, dst0
, src0
+ 1, src0
, s
? " (R)" : "");
5120 if ((src1
!= 0 && src1
!= 2) || (src0
!= 0 && src0
!= 2))
5121 illegal_instruction (cpu
);
5124 illegal_instruction_combination (cpu
);
5126 order
= IREG (0) & 0x3;
5128 hi
= src0
, lo
= src0
+ 1;
5130 hi
= src0
+ 1, lo
= src0
;
5131 comb_src
= (((bu64
)DREG (hi
)) << 32) | DREG (lo
);
5132 bytea
= (comb_src
>> (0 + 8 * order
));
5133 byteb
= (comb_src
>> (8 + 8 * order
));
5134 bytec
= (comb_src
>> (16 + 8 * order
));
5135 byted
= (comb_src
>> (24 + 8 * order
));
5136 STORE (DREG (dst0
), bytea
| ((bu32
)byteb
<< 16));
5137 STORE (DREG (dst1
), bytec
| ((bu32
)byted
<< 16));
5139 /* Implicit DISALGNEXCPT in parallel. */
5142 else if (aopcde
== 13 && HL
== 0 && x
== 0 && s
== 0)
5144 const char *searchmodes
[] = { "GT", "GE", "LT", "LE" };
5146 bs16 a0_lo
, a1_lo
, src_hi
, src_lo
;
5148 TRACE_INSN (cpu
, "(R%i, R%i) = SEARCH R%i (%s);",
5149 dst1
, dst0
, src0
, searchmodes
[aop
]);
5152 illegal_instruction_combination (cpu
);
5154 up_hi
= up_lo
= false;
5157 src_lo
= DREG (src0
);
5158 src_hi
= DREG (src0
) >> 16;
5163 up_hi
= (src_hi
> a1_lo
);
5164 up_lo
= (src_lo
> a0_lo
);
5167 up_hi
= (src_hi
>= a1_lo
);
5168 up_lo
= (src_lo
>= a0_lo
);
5171 up_hi
= (src_hi
< a1_lo
);
5172 up_lo
= (src_lo
< a0_lo
);
5175 up_hi
= (src_hi
<= a1_lo
);
5176 up_lo
= (src_lo
<= a0_lo
);
5182 SET_AREG (1, src_hi
);
5183 SET_DREG (dst1
, PREG (0));
5186 SET_AREG (1, a1_lo
);
5190 SET_AREG (0, src_lo
);
5191 SET_DREG (dst0
, PREG (0));
5194 SET_AREG (0, a0_lo
);
5197 illegal_instruction (cpu
);
5201 decode_dsp32shift_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
5204 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5205 | 1 | 1 | 0 | 0 |.M.| 1 | 1 | 0 | 0 | - | - |.sopcde............|
5206 |.sop...|.HLs...|.dst0......| - | - | - |.src0......|.src1......|
5207 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5208 int HLs
= ((iw1
>> DSP32Shift_HLs_bits
) & DSP32Shift_HLs_mask
);
5209 int sop
= ((iw1
>> DSP32Shift_sop_bits
) & DSP32Shift_sop_mask
);
5210 int src0
= ((iw1
>> DSP32Shift_src0_bits
) & DSP32Shift_src0_mask
);
5211 int src1
= ((iw1
>> DSP32Shift_src1_bits
) & DSP32Shift_src1_mask
);
5212 int dst0
= ((iw1
>> DSP32Shift_dst0_bits
) & DSP32Shift_dst0_mask
);
5213 int sopcde
= ((iw0
>> (DSP32Shift_sopcde_bits
- 16)) & DSP32Shift_sopcde_mask
);
5214 int M
= ((iw0
>> (DSP32Shift_M_bits
- 16)) & DSP32Shift_M_mask
);
5216 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32shift
);
5217 TRACE_EXTRACT (cpu
, "%s: M:%i sopcde:%i sop:%i HLs:%i dst0:%i src0:%i src1:%i",
5218 __func__
, M
, sopcde
, sop
, HLs
, dst0
, src0
, src1
);
5220 if ((sop
== 0 || sop
== 1) && sopcde
== 0)
5223 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5225 TRACE_INSN (cpu
, "R%i.%c = ASHIFT R%i.%c BY R%i.L%s;",
5226 dst0
, HLs
< 2 ? 'L' : 'H',
5227 src1
, HLs
& 1 ? 'H' : 'L',
5228 src0
, sop
== 1 ? " (S)" : "");
5231 val
= (bu16
)(DREG (src1
) & 0xFFFF);
5233 val
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5235 /* Positive shift magnitudes produce Logical Left shifts.
5236 Negative shift magnitudes produce Arithmetic Right shifts. */
5238 val
= ashiftrt (cpu
, val
, -shft
, 16);
5241 int sgn
= (val
>> 15) & 0x1;
5243 val
= lshift (cpu
, val
, shft
, 16, sop
== 1, 1);
5244 if (((val
>> 15) & 0x1) != sgn
)
5246 SET_ASTATREG (v
, 1);
5247 SET_ASTATREG (vs
, 1);
5252 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), val
));
5254 STORE (DREG (dst0
), REG_H_L (val
<< 16, DREG (dst0
)));
5256 else if (sop
== 2 && sopcde
== 0)
5258 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5261 TRACE_INSN (cpu
, "R%i.%c = LSHIFT R%i.%c BY R%i.L;",
5262 dst0
, HLs
< 2 ? 'L' : 'H',
5263 src1
, HLs
& 1 ? 'H' : 'L', src0
);
5266 val
= (bu16
)(DREG (src1
) & 0xFFFF);
5268 val
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5271 val
= val
>> (-1 * shft
);
5276 SET_DREG (dst0
, REG_H_L (DREG (dst0
), val
));
5278 SET_DREG (dst0
, REG_H_L (val
<< 16, DREG (dst0
)));
5280 SET_ASTATREG (az
, !((val
& 0xFFFF0000) == 0) || ((val
& 0xFFFF) == 0));
5281 SET_ASTATREG (an
, (!!(val
& 0x80000000)) ^ (!!(val
& 0x8000)));
5282 SET_ASTATREG (v
, 0);
5284 else if (sop
== 2 && sopcde
== 3 && (HLs
== 1 || HLs
== 0))
5286 int shift
= imm6 (DREG (src0
) & 0xFFFF);
5288 bu40 acc
= get_unextended_acc (cpu
, HLs
);
5290 TRACE_INSN (cpu
, "A%i = ROT A%i BY R%i.L;", HLs
, HLs
, src0
);
5291 TRACE_DECODE (cpu
, "A%i:%#"PRIx64
" shift:%i CC:%i", HLs
, acc
, shift
, cc
);
5293 acc
= rot40 (acc
, shift
, &cc
);
5294 SET_AREG (HLs
, acc
);
5298 else if (sop
== 0 && sopcde
== 3 && (HLs
== 0 || HLs
== 1))
5300 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5301 bu64 acc
= get_extended_acc (cpu
, HLs
);
5305 TRACE_INSN (cpu
, "A%i = ASHIFT A%i BY R%i.L;", HLs
, HLs
, src0
);
5306 TRACE_DECODE (cpu
, "A%i:%#"PRIx64
" shift:%i", HLs
, acc
, shft
);
5309 val
= ashiftrt (cpu
, acc
, -shft
, 40);
5311 val
= lshift (cpu
, acc
, shft
, 40, 0, 0);
5313 STORE (AXREG (HLs
), (val
>> 32) & 0xff);
5314 STORE (AWREG (HLs
), (val
& 0xffffffff));
5315 STORE (ASTATREG (av
[HLs
]), 0);
5317 else if (sop
== 1 && sopcde
== 3 && (HLs
== 0 || HLs
== 1))
5319 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5320 bu64 acc
= get_unextended_acc (cpu
, HLs
);
5324 TRACE_INSN (cpu
, "A%i = LSHIFT A%i BY R%i.L;", HLs
, HLs
, src0
);
5325 TRACE_DECODE (cpu
, "A%i:%#"PRIx64
" shift:%i", HLs
, acc
, shft
);
5328 val
= lshiftrt (cpu
, acc
, -shft
, 40);
5330 val
= lshift (cpu
, acc
, shft
, 40, 0, 0);
5332 STORE (AXREG (HLs
), (val
>> 32) & 0xff);
5333 STORE (AWREG (HLs
), (val
& 0xffffffff));
5334 STORE (ASTATREG (av
[HLs
]), 0);
5337 /* All the insns after this point don't use HLs. */
5338 illegal_instruction (cpu
);
5339 else if ((sop
== 0 || sop
== 1) && sopcde
== 1 && HLs
== 0)
5341 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5345 TRACE_INSN (cpu
, "R%i = ASHIFT R%i BY R%i.L (V%s);",
5346 dst0
, src1
, src0
, sop
== 1 ? ",S" : "");
5348 val0
= (bu16
)DREG (src1
) & 0xFFFF;
5349 val1
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5353 val0
= ashiftrt (cpu
, val0
, -shft
, 16);
5355 val1
= ashiftrt (cpu
, val1
, -shft
, 16);
5359 int sgn0
= (val0
>> 15) & 0x1;
5360 int sgn1
= (val1
>> 15) & 0x1;
5362 val0
= lshift (cpu
, val0
, shft
, 16, sop
== 1, 1);
5364 val1
= lshift (cpu
, val1
, shft
, 16, sop
== 1, 1);
5366 if ((sgn0
!= ((val0
>> 15) & 0x1)) || (sgn1
!= ((val1
>> 15) & 0x1)))
5368 SET_ASTATREG (v
, 1);
5369 SET_ASTATREG (vs
, 1);
5372 SET_ASTAT (ASTAT
| astat
);
5373 STORE (DREG (dst0
), (val1
<< 16) | val0
);
5375 else if ((sop
== 0 || sop
== 1 || sop
== 2) && sopcde
== 2)
5377 /* dregs = [LA]SHIFT dregs BY dregs_lo (opt_S) */
5378 /* sop == 1 : opt_S */
5379 bu32 v
= DREG (src1
);
5380 /* LSHIFT uses sign extended low 6 bits of dregs_lo. */
5381 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5383 TRACE_INSN (cpu
, "R%i = %cSHIFT R%i BY R%i.L%s;", dst0
,
5384 shft
&& sop
!= 2 ? 'A' : 'L', src1
, src0
,
5385 sop
== 1 ? " (S)" : "");
5390 STORE (DREG (dst0
), lshiftrt (cpu
, v
, -shft
, 32));
5392 STORE (DREG (dst0
), ashiftrt (cpu
, v
, -shft
, 32));
5396 bu32 val
= lshift (cpu
, v
, shft
, 32, sop
== 1, 1);
5398 STORE (DREG (dst0
), val
);
5399 if (((v
>> 31) & 0x1) != ((val
>> 31) & 0x1))
5401 SET_ASTATREG (v
, 1);
5402 SET_ASTATREG (vs
, 1);
5406 else if (sop
== 3 && sopcde
== 2)
5408 int shift
= imm6 (DREG (src0
) & 0xFFFF);
5409 bu32 src
= DREG (src1
);
5410 bu32 ret
, cc
= CCREG
;
5412 TRACE_INSN (cpu
, "R%i = ROT R%i BY R%i.L;", dst0
, src1
, src0
);
5413 TRACE_DECODE (cpu
, "R%i:%#x R%i:%#x shift:%i CC:%i",
5414 dst0
, DREG (dst0
), src1
, src
, shift
, cc
);
5416 ret
= rot32 (src
, shift
, &cc
);
5417 STORE (DREG (dst0
), ret
);
5421 else if (sop
== 2 && sopcde
== 1 && HLs
== 0)
5423 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5427 TRACE_INSN (cpu
, "R%i = LSHIFT R%i BY R%i.L (V);", dst0
, src1
, src0
);
5429 val0
= (bu16
)DREG (src1
) & 0xFFFF;
5430 val1
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5434 val0
= lshiftrt (cpu
, val0
, -shft
, 16);
5436 val1
= lshiftrt (cpu
, val1
, -shft
, 16);
5440 val0
= lshift (cpu
, val0
, shft
, 16, 0, 0);
5442 val1
= lshift (cpu
, val1
, shft
, 16, 0, 0);
5444 SET_ASTAT (ASTAT
| astat
);
5445 STORE (DREG (dst0
), (val1
<< 16) | val0
);
5447 else if (sopcde
== 4)
5449 bu32 sv0
= DREG (src0
);
5450 bu32 sv1
= DREG (src1
);
5451 TRACE_INSN (cpu
, "R%i = PACK (R%i.%c, R%i.%c);", dst0
,
5452 src1
, sop
& 2 ? 'H' : 'L',
5453 src0
, sop
& 1 ? 'H' : 'L');
5458 STORE (DREG (dst0
), (sv1
<< 16) | (sv0
& 0xFFFF));
5460 else if (sop
== 0 && sopcde
== 5)
5462 bu32 sv1
= DREG (src1
);
5463 TRACE_INSN (cpu
, "R%i.L = SIGNBITS R%i;", dst0
, src1
);
5464 SET_DREG_L (dst0
, signbits (sv1
, 32));
5466 else if (sop
== 1 && sopcde
== 5)
5468 bu32 sv1
= DREG (src1
);
5469 TRACE_INSN (cpu
, "R%i.L = SIGNBITS R%i.L;", dst0
, src1
);
5470 SET_DREG_L (dst0
, signbits (sv1
, 16));
5472 else if (sop
== 2 && sopcde
== 5)
5474 bu32 sv1
= DREG (src1
);
5475 TRACE_INSN (cpu
, "R%i.L = SIGNBITS R%i.H;", dst0
, src1
);
5476 SET_DREG_L (dst0
, signbits (sv1
>> 16, 16));
5478 else if ((sop
== 0 || sop
== 1) && sopcde
== 6)
5480 bu64 acc
= AXREG (sop
);
5481 TRACE_INSN (cpu
, "R%i.L = SIGNBITS A%i;", dst0
, sop
);
5484 SET_DREG_L (dst0
, signbits (acc
, 40) & 0xFFFF);
5486 else if (sop
== 3 && sopcde
== 6)
5488 bu32 v
= ones (DREG (src1
));
5489 TRACE_INSN (cpu
, "R%i.L = ONES R%i;", dst0
, src1
);
5490 SET_DREG_L (dst0
, v
);
5492 else if (sop
== 0 && sopcde
== 7)
5494 bu16 sv1
= (bu16
)signbits (DREG (src1
), 32);
5495 bu16 sv0
= (bu16
)DREG (src0
);
5498 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i, R%i.L);", dst0
, src1
, src0
);
5500 if ((sv1
& 0x1f) < (sv0
& 0x1f))
5504 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), dst_lo
));
5506 else if (sop
== 1 && sopcde
== 7)
5508 /* Exponent adjust on two 16-bit inputs. Select
5509 smallest norm among 3 inputs. */
5510 bs16 src1_hi
= (DREG (src1
) & 0xFFFF0000) >> 16;
5511 bs16 src1_lo
= (DREG (src1
) & 0xFFFF);
5512 bu16 src0_lo
= (DREG (src0
) & 0xFFFF);
5513 bu16 tmp_hi
, tmp_lo
, tmp
;
5515 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i, R%i.L) (V);", dst0
, src1
, src0
);
5517 tmp_hi
= signbits (src1_hi
, 16);
5518 tmp_lo
= signbits (src1_lo
, 16);
5520 if ((tmp_hi
& 0xf) < (tmp_lo
& 0xf))
5521 if ((tmp_hi
& 0xf) < (src0_lo
& 0xf))
5526 if ((tmp_lo
& 0xf) < (src0_lo
& 0xf))
5530 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), tmp
));
5532 else if (sop
== 2 && sopcde
== 7)
5534 /* Exponent adjust on single 16-bit register. */
5536 bu16 src0_lo
= (bu16
)(DREG (src0
) & 0xFFFF);
5538 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i.L, R%i.L);", dst0
, src1
, src0
);
5540 tmp
= signbits (DREG (src1
) & 0xFFFF, 16);
5542 if ((tmp
& 0xf) < (src0_lo
& 0xf))
5543 SET_DREG_L (dst0
, tmp
);
5545 SET_DREG_L (dst0
, src0_lo
);
5547 else if (sop
== 3 && sopcde
== 7)
5550 bu16 src0_lo
= (bu16
)(DREG (src0
) & 0xFFFF);
5552 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i.H, R%i.L);", dst0
, src1
, src0
);
5554 tmp
= signbits ((DREG (src1
) & 0xFFFF0000) >> 16, 16);
5556 if ((tmp
& 0xf) < (src0_lo
& 0xf))
5557 SET_DREG_L (dst0
, tmp
);
5559 SET_DREG_L (dst0
, src0_lo
);
5561 else if (sop
== 0 && sopcde
== 8)
5563 bu64 acc
= get_unextended_acc (cpu
, 0);
5566 TRACE_INSN (cpu
, "BITMUX (R%i, R%i, A0) (ASR);", src0
, src1
);
5569 illegal_instruction_combination (cpu
);
5574 (((bu64
)s0
& 1) << 38) |
5575 (((bu64
)s1
& 1) << 39);
5576 STORE (DREG (src0
), s0
>> 1);
5577 STORE (DREG (src1
), s1
>> 1);
5581 else if (sop
== 1 && sopcde
== 8)
5583 bu64 acc
= get_unextended_acc (cpu
, 0);
5586 TRACE_INSN (cpu
, "BITMUX (R%i, R%i, A0) (ASL);", src0
, src1
);
5589 illegal_instruction_combination (cpu
);
5596 STORE (DREG (src0
), s0
<< 1);
5597 STORE (DREG (src1
), s1
<< 1);
5601 else if ((sop
== 0 || sop
== 1) && sopcde
== 9)
5603 bs40 acc0
= get_unextended_acc (cpu
, 0);
5606 TRACE_INSN (cpu
, "R%i.L = VIT_MAX (R%i) (AS%c);",
5607 dst0
, src1
, sop
& 1 ? 'R' : 'L');
5610 sH
= DREG (src1
) >> 16;
5613 acc0
= (acc0
& 0xfeffffffffull
) >> 1;
5617 if (((sH
- sL
) & 0x8000) == 0)
5620 acc0
|= (sop
& 1) ? 0x80000000 : 1;
5626 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), out
));
5628 else if ((sop
== 2 || sop
== 3) && sopcde
== 9)
5630 bs40 acc0
= get_extended_acc (cpu
, 0);
5631 bs16 s0L
, s0H
, s1L
, s1H
, out0
, out1
;
5633 TRACE_INSN (cpu
, "R%i = VIT_MAX (R%i, R%i) (AS%c);",
5634 dst0
, src1
, src0
, sop
& 1 ? 'R' : 'L');
5637 s0H
= DREG (src0
) >> 16;
5639 s1H
= DREG (src1
) >> 16;
5646 if (((s0H
- s0L
) & 0x8000) == 0)
5649 acc0
|= (sop
& 1) ? 0x40000000 : 2;
5654 if (((s1H
- s1L
) & 0x8000) == 0)
5657 acc0
|= (sop
& 1) ? 0x80000000 : 1;
5663 STORE (DREG (dst0
), REG_H_L (out1
<< 16, out0
));
5665 else if (sop
== 0 && sopcde
== 10)
5667 bu32 v
= DREG (src0
);
5668 bu32 x
= DREG (src1
);
5669 bu32 mask
= (1 << (v
& 0x1f)) - 1;
5671 TRACE_INSN (cpu
, "R%i = EXTRACT (R%i, R%i.L) (Z);", dst0
, src1
, src0
);
5673 x
>>= ((v
>> 8) & 0x1f);
5675 STORE (DREG (dst0
), x
);
5676 setflags_logical (cpu
, x
);
5678 else if (sop
== 1 && sopcde
== 10)
5680 bu32 v
= DREG (src0
);
5681 bu32 x
= DREG (src1
);
5682 bu32 sgn
= (1 << (v
& 0x1f)) >> 1;
5683 bu32 mask
= (1 << (v
& 0x1f)) - 1;
5685 TRACE_INSN (cpu
, "R%i = EXTRACT (R%i, R%i.L) (X);", dst0
, src1
, src0
);
5687 x
>>= ((v
>> 8) & 0x1f);
5691 STORE (DREG (dst0
), x
);
5692 setflags_logical (cpu
, x
);
5694 else if ((sop
== 2 || sop
== 3) && sopcde
== 10)
5696 /* The first dregs is the "background" while the second dregs is the
5697 "foreground". The fg reg is used to overlay the bg reg and is:
5698 | nnnn nnnn | nnnn nnnn | xxxp pppp | xxxL LLLL |
5699 n = the fg bit field
5700 p = bit position in bg reg to start LSB of fg field
5701 L = number of fg bits to extract
5702 Using (X) sign-extends the fg bit field. */
5703 bu32 fg
= DREG (src0
);
5704 bu32 bg
= DREG (src1
);
5705 bu32 len
= fg
& 0x1f;
5706 bu32 mask
= (1 << MIN (16, len
)) - 1;
5707 bu32 fgnd
= (fg
>> 16) & mask
;
5708 int shft
= ((fg
>> 8) & 0x1f);
5710 TRACE_INSN (cpu
, "R%i = DEPOSIT (R%i, R%i)%s;", dst0
, src1
, src0
,
5711 sop
== 3 ? " (X)" : "");
5715 /* Sign extend the fg bit field. */
5717 fgnd
= ((bs32
)(bs16
)(fgnd
<< (16 - len
))) >> (16 - len
);
5724 STORE (DREG (dst0
), bg
);
5725 setflags_logical (cpu
, bg
);
5727 else if (sop
== 0 && sopcde
== 11)
5729 bu64 acc0
= get_unextended_acc (cpu
, 0);
5731 TRACE_INSN (cpu
, "R%i.L = CC = BXORSHIFT (A0, R%i);", dst0
, src0
);
5734 SET_CCREG (xor_reduce (acc0
, DREG (src0
)));
5735 SET_DREG (dst0
, REG_H_L (DREG (dst0
), CCREG
));
5738 else if (sop
== 1 && sopcde
== 11)
5740 bu64 acc0
= get_unextended_acc (cpu
, 0);
5742 TRACE_INSN (cpu
, "R%i.L = CC = BXOR (A0, R%i);", dst0
, src0
);
5744 SET_CCREG (xor_reduce (acc0
, DREG (src0
)));
5745 SET_DREG (dst0
, REG_H_L (DREG (dst0
), CCREG
));
5747 else if (sop
== 0 && sopcde
== 12)
5749 bu64 acc0
= get_unextended_acc (cpu
, 0);
5750 bu64 acc1
= get_unextended_acc (cpu
, 1);
5752 TRACE_INSN (cpu
, "A0 = BXORSHIFT (A0, A1, CC);");
5754 acc0
= (acc0
<< 1) | (CCREG
^ xor_reduce (acc0
, acc1
));
5757 else if (sop
== 1 && sopcde
== 12)
5759 bu64 acc0
= get_unextended_acc (cpu
, 0);
5760 bu64 acc1
= get_unextended_acc (cpu
, 1);
5762 TRACE_INSN (cpu
, "R%i.L = CC = BXOR (A0, A1, CC);", dst0
);
5764 SET_CCREG (CCREG
^ xor_reduce (acc0
, acc1
));
5765 acc0
= (acc0
<< 1) | CCREG
;
5766 SET_DREG (dst0
, REG_H_L (DREG (dst0
), CCREG
));
5768 else if ((sop
== 0 || sop
== 1 || sop
== 2) && sopcde
== 13)
5770 int shift
= (sop
+ 1) * 8;
5771 TRACE_INSN (cpu
, "R%i = ALIGN%i (R%i, R%i);", dst0
, shift
, src1
, src0
);
5772 STORE (DREG (dst0
), (DREG (src1
) << (32 - shift
)) | (DREG (src0
) >> shift
));
5775 illegal_instruction (cpu
);
5779 sgn_extend (bu40 org
, bu40 val
, int size
)
5783 if (org
& (1ULL << (size
- 1)))
5785 /* We need to shift in to the MSB which is set. */
5788 for (n
= 40; n
>= 0; n
--)
5789 if (ret
& (1ULL << n
))
5791 ret
|= (-1ULL << n
);
5794 ret
&= ~(-1ULL << 39);
5799 decode_dsp32shiftimm_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
5802 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5803 | 1 | 1 | 0 | 0 |.M.| 1 | 1 | 0 | 1 | - | - |.sopcde............|
5804 |.sop...|.HLs...|.dst0......|.immag.................|.src1......|
5805 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5806 int src1
= ((iw1
>> DSP32ShiftImm_src1_bits
) & DSP32ShiftImm_src1_mask
);
5807 int sop
= ((iw1
>> DSP32ShiftImm_sop_bits
) & DSP32ShiftImm_sop_mask
);
5808 int bit8
= ((iw1
>> 8) & 0x1);
5809 int immag
= ((iw1
>> DSP32ShiftImm_immag_bits
) & DSP32ShiftImm_immag_mask
);
5810 int newimmag
= (-(iw1
>> DSP32ShiftImm_immag_bits
) & DSP32ShiftImm_immag_mask
);
5811 int dst0
= ((iw1
>> DSP32ShiftImm_dst0_bits
) & DSP32ShiftImm_dst0_mask
);
5812 int M
= ((iw0
>> (DSP32ShiftImm_M_bits
- 16)) & DSP32ShiftImm_M_mask
);
5813 int sopcde
= ((iw0
>> (DSP32ShiftImm_sopcde_bits
- 16)) & DSP32ShiftImm_sopcde_mask
);
5814 int HLs
= ((iw1
>> DSP32ShiftImm_HLs_bits
) & DSP32ShiftImm_HLs_mask
);
5816 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32shiftimm
);
5817 TRACE_EXTRACT (cpu
, "%s: M:%i sopcde:%i sop:%i HLs:%i dst0:%i immag:%#x src1:%i",
5818 __func__
, M
, sopcde
, sop
, HLs
, dst0
, immag
, src1
);
5822 bu16 in
= DREG (src1
) >> ((HLs
& 1) ? 16 : 0);
5828 TRACE_INSN (cpu
, "R%i.%c = R%i.%c >>> %i;",
5829 dst0
, (HLs
& 2) ? 'H' : 'L',
5830 src1
, (HLs
& 1) ? 'H' : 'L', newimmag
);
5833 result
= lshift (cpu
, in
, 16 - (newimmag
& 0xF), 16, 0, 1);
5834 if (((result
>> 15) & 0x1) != ((in
>> 15) & 0x1))
5836 SET_ASTATREG (v
, 1);
5837 SET_ASTATREG (vs
, 1);
5841 result
= ashiftrt (cpu
, in
, newimmag
, 16);
5843 else if (sop
== 1 && bit8
== 0)
5845 TRACE_INSN (cpu
, "R%i.%c = R%i.%c << %i (S);",
5846 dst0
, (HLs
& 2) ? 'H' : 'L',
5847 src1
, (HLs
& 1) ? 'H' : 'L', immag
);
5848 result
= lshift (cpu
, in
, immag
, 16, 1, 1);
5850 else if (sop
== 1 && bit8
)
5852 TRACE_INSN (cpu
, "R%i.%c = R%i.%c >>> %i (S);",
5853 dst0
, (HLs
& 2) ? 'H' : 'L',
5854 src1
, (HLs
& 1) ? 'H' : 'L', newimmag
);
5857 int shift
= 32 - newimmag
;
5858 bu16 inshift
= in
<< shift
;
5860 if (((inshift
& ~0xFFFF)
5861 && ((inshift
& ~0xFFFF) >> 16) != ~(~0 << shift
))
5862 || (inshift
& 0x8000) != (in
& 0x8000))
5868 SET_ASTATREG (v
, 1);
5869 SET_ASTATREG (vs
, 1);
5874 SET_ASTATREG (v
, 0);
5877 SET_ASTATREG (az
, !result
);
5878 SET_ASTATREG (an
, !!(result
& 0x8000));
5882 result
= ashiftrt (cpu
, in
, newimmag
, 16);
5883 result
= sgn_extend (in
, result
, 16);
5886 else if (sop
== 2 && bit8
)
5888 TRACE_INSN (cpu
, "R%i.%c = R%i.%c >> %i;",
5889 dst0
, (HLs
& 2) ? 'H' : 'L',
5890 src1
, (HLs
& 1) ? 'H' : 'L', newimmag
);
5891 result
= lshiftrt (cpu
, in
, newimmag
, 16);
5893 else if (sop
== 2 && bit8
== 0)
5895 TRACE_INSN (cpu
, "R%i.%c = R%i.%c << %i;",
5896 dst0
, (HLs
& 2) ? 'H' : 'L',
5897 src1
, (HLs
& 1) ? 'H' : 'L', immag
);
5898 result
= lshift (cpu
, in
, immag
, 16, 0, 1);
5901 illegal_instruction (cpu
);
5905 STORE (DREG (dst0
), (v
& 0xFFFF) | (result
<< 16));
5907 STORE (DREG (dst0
), (v
& 0xFFFF0000) | result
);
5909 else if (sop
== 2 && sopcde
== 3 && (HLs
== 1 || HLs
== 0))
5911 int shift
= imm6 (immag
);
5913 bu40 acc
= get_unextended_acc (cpu
, HLs
);
5915 TRACE_INSN (cpu
, "A%i = ROT A%i BY %i;", HLs
, HLs
, shift
);
5916 TRACE_DECODE (cpu
, "A%i:%#"PRIx64
" shift:%i CC:%i", HLs
, acc
, shift
, cc
);
5918 acc
= rot40 (acc
, shift
, &cc
);
5919 SET_AREG (HLs
, acc
);
5923 else if (sop
== 0 && sopcde
== 3 && bit8
== 1 && HLs
< 2)
5925 /* Arithmetic shift, so shift in sign bit copies. */
5927 int shift
= uimm5 (newimmag
);
5929 TRACE_INSN (cpu
, "A%i = A%i >>> %i;", HLs
, HLs
, shift
);
5931 acc
= get_extended_acc (cpu
, HLs
);
5934 /* Sign extend again. */
5935 val
= sgn_extend (acc
, val
, 40);
5937 STORE (AXREG (HLs
), (val
>> 32) & 0xFF);
5938 STORE (AWREG (HLs
), val
& 0xFFFFFFFF);
5939 STORE (ASTATREG (an
), !!(val
& (1ULL << 39)));
5940 STORE (ASTATREG (az
), !val
);
5941 STORE (ASTATREG (av
[HLs
]), 0);
5943 else if (((sop
== 0 && sopcde
== 3 && bit8
== 0)
5944 || (sop
== 1 && sopcde
== 3)) && HLs
< 2)
5947 int shiftup
= uimm5 (immag
);
5948 int shiftdn
= uimm5 (newimmag
);
5950 TRACE_INSN (cpu
, "A%i = A%i %s %i;", HLs
, HLs
,
5951 sop
== 0 ? "<<" : ">>",
5952 sop
== 0 ? shiftup
: shiftdn
);
5955 /* Logical shift, so shift in zeroes. */
5967 acc
<<= 32 - (shiftdn
& 0x1f);
5970 SET_AREG (HLs
, acc
);
5971 SET_ASTATREG (av
[HLs
], 0);
5972 SET_ASTATREG (an
, !!(acc
& 0x8000000000ull
));
5973 SET_ASTATREG (az
, (acc
& 0xFFFFFFFFFF) == 0);
5976 /* All the insns after this point don't use HLs. */
5977 illegal_instruction (cpu
);
5978 else if (sop
== 1 && sopcde
== 1 && bit8
== 0)
5980 int count
= imm5 (immag
);
5981 bu16 val0
= DREG (src1
) >> 16;
5982 bu16 val1
= DREG (src1
) & 0xFFFF;
5985 TRACE_INSN (cpu
, "R%i = R%i << %i (V,S);", dst0
, src1
, count
);
5988 val0
= lshift (cpu
, val0
, count
, 16, 1, 1);
5990 val1
= lshift (cpu
, val1
, count
, 16, 1, 1);
5994 val0
= ashiftrt (cpu
, val0
, -count
, 16);
5996 val1
= ashiftrt (cpu
, val1
, -count
, 16);
5998 SET_ASTAT (ASTAT
| astat
);
6000 STORE (DREG (dst0
), (val0
<< 16) | val1
);
6002 else if (sop
== 2 && sopcde
== 1 && bit8
== 1)
6004 int count
= imm5 (newimmag
);
6005 bu16 val0
= DREG (src1
) & 0xFFFF;
6006 bu16 val1
= DREG (src1
) >> 16;
6009 TRACE_INSN (cpu
, "R%i = R%i >> %i (V);", dst0
, src1
, count
);
6010 val0
= lshiftrt (cpu
, val0
, count
, 16);
6012 val1
= lshiftrt (cpu
, val1
, count
, 16);
6013 SET_ASTAT (ASTAT
| astat
);
6015 STORE (DREG (dst0
), val0
| (val1
<< 16));
6017 else if (sop
== 2 && sopcde
== 1 && bit8
== 0)
6019 int count
= imm5 (immag
);
6020 bu16 val0
= DREG (src1
) & 0xFFFF;
6021 bu16 val1
= DREG (src1
) >> 16;
6024 TRACE_INSN (cpu
, "R%i = R%i << %i (V);", dst0
, src1
, count
);
6025 val0
= lshift (cpu
, val0
, count
, 16, 0, 1);
6027 val1
= lshift (cpu
, val1
, count
, 16, 0, 1);
6028 SET_ASTAT (ASTAT
| astat
);
6030 STORE (DREG (dst0
), val0
| (val1
<< 16));
6032 else if (sopcde
== 1 && (sop
== 0 || (sop
== 1 && bit8
== 1)))
6034 int count
= uimm5 (newimmag
);
6035 bu16 val0
= DREG (src1
) & 0xFFFF;
6036 bu16 val1
= DREG (src1
) >> 16;
6039 TRACE_INSN (cpu
, "R%i = R%i >>> %i %s;", dst0
, src1
, count
,
6040 sop
== 0 ? "(V)" : "(V,S)");
6044 int sgn0
= (val0
>> 15) & 0x1;
6045 int sgn1
= (val1
>> 15) & 0x1;
6047 val0
= lshift (cpu
, val0
, 16 - (count
& 0xF), 16, 0, 1);
6049 val1
= lshift (cpu
, val1
, 16 - (count
& 0xF), 16, 0, 1);
6051 if ((sgn0
!= ((val0
>> 15) & 0x1)) || (sgn1
!= ((val1
>> 15) & 0x1)))
6053 SET_ASTATREG (v
, 1);
6054 SET_ASTATREG (vs
, 1);
6059 val0
= ashiftrt (cpu
, val0
, count
, 16);
6061 val1
= ashiftrt (cpu
, val1
, count
, 16);
6064 SET_ASTAT (ASTAT
| astat
);
6066 STORE (DREG (dst0
), REG_H_L (val1
<< 16, val0
));
6068 else if (sop
== 1 && sopcde
== 2)
6070 int count
= imm6 (immag
);
6072 TRACE_INSN (cpu
, "R%i = R%i << %i (S);", dst0
, src1
, count
);
6073 STORE (DREG (dst0
), lshift (cpu
, DREG (src1
), count
, 32, 1, 1));
6075 else if (sop
== 2 && sopcde
== 2)
6077 int count
= imm6 (newimmag
);
6079 TRACE_INSN (cpu
, "R%i = R%i >> %i;", dst0
, src1
, count
);
6082 STORE (DREG (dst0
), lshift (cpu
, DREG (src1
), -count
, 32, 0, 1));
6084 STORE (DREG (dst0
), lshiftrt (cpu
, DREG (src1
), count
, 32));
6086 else if (sop
== 3 && sopcde
== 2)
6088 int shift
= imm6 (immag
);
6089 bu32 src
= DREG (src1
);
6090 bu32 ret
, cc
= CCREG
;
6092 TRACE_INSN (cpu
, "R%i = ROT R%i BY %i;", dst0
, src1
, shift
);
6093 TRACE_DECODE (cpu
, "R%i:%#x R%i:%#x shift:%i CC:%i",
6094 dst0
, DREG (dst0
), src1
, src
, shift
, cc
);
6096 ret
= rot32 (src
, shift
, &cc
);
6097 STORE (DREG (dst0
), ret
);
6101 else if (sop
== 0 && 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
), ashiftrt (cpu
, DREG (src1
), count
, 32));
6113 illegal_instruction (cpu
);
6117 outc (SIM_CPU
*cpu
, char ch
)
6119 SIM_DESC sd
= CPU_STATE (cpu
);
6120 sim_io_printf (sd
, "%c", ch
);
6122 sim_io_flush_stdout (sd
);
6126 decode_psedoDEBUG_0 (SIM_CPU
*cpu
, bu16 iw0
)
6129 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
6130 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 |.fn....|.grp.......|.reg.......|
6131 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
6132 SIM_DESC sd
= CPU_STATE (cpu
);
6133 int fn
= ((iw0
>> PseudoDbg_fn_bits
) & PseudoDbg_fn_mask
);
6134 int grp
= ((iw0
>> PseudoDbg_grp_bits
) & PseudoDbg_grp_mask
);
6135 int reg
= ((iw0
>> PseudoDbg_reg_bits
) & PseudoDbg_reg_mask
);
6137 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_psedoDEBUG
);
6138 TRACE_EXTRACT (cpu
, "%s: fn:%i grp:%i reg:%i", __func__
, fn
, grp
, reg
);
6140 if ((reg
== 0 || reg
== 1) && fn
== 3)
6142 TRACE_INSN (cpu
, "DBG A%i;", reg
);
6143 sim_io_printf (sd
, "DBG : A%i = %#"PRIx64
"\n", reg
,
6144 get_unextended_acc (cpu
, reg
));
6146 else if (reg
== 3 && fn
== 3)
6148 TRACE_INSN (cpu
, "ABORT;");
6149 cec_exception (cpu
, VEC_SIM_ABORT
);
6152 else if (reg
== 4 && fn
== 3)
6154 TRACE_INSN (cpu
, "HLT;");
6155 cec_exception (cpu
, VEC_SIM_HLT
);
6158 else if (reg
== 5 && fn
== 3)
6159 unhandled_instruction (cpu
, "DBGHALT");
6160 else if (reg
== 6 && fn
== 3)
6161 unhandled_instruction (cpu
, "DBGCMPLX (dregs)");
6162 else if (reg
== 7 && fn
== 3)
6163 unhandled_instruction (cpu
, "DBG");
6164 else if (grp
== 0 && fn
== 2)
6166 TRACE_INSN (cpu
, "OUTC R%i;", reg
);
6167 outc (cpu
, DREG (reg
));
6171 const char *reg_name
= get_allreg_name (grp
, reg
);
6172 TRACE_INSN (cpu
, "DBG %s;", reg_name
);
6173 sim_io_printf (sd
, "DBG : %s = 0x%08x\n", reg_name
,
6174 reg_read (cpu
, grp
, reg
));
6177 unhandled_instruction (cpu
, "PRNT allregs");
6179 illegal_instruction (cpu
);
6183 decode_psedoOChar_0 (SIM_CPU
*cpu
, bu16 iw0
)
6186 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
6187 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |.ch............................|
6188 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
6189 int ch
= ((iw0
>> PseudoChr_ch_bits
) & PseudoChr_ch_mask
);
6191 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_psedoOChar
);
6192 TRACE_EXTRACT (cpu
, "%s: ch:%#x", __func__
, ch
);
6193 TRACE_INSN (cpu
, "OUTC %#x;", ch
);
6199 decode_psedodbg_assert_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
, bu32 pc
)
6202 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
6203 | 1 | 1 | 1 | 1 | 0 | - | - | - | dbgop |.grp.......|.regtest...|
6204 |.expected......................................................|
6205 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
6206 SIM_DESC sd
= CPU_STATE (cpu
);
6207 int expected
= ((iw1
>> PseudoDbg_Assert_expected_bits
) & PseudoDbg_Assert_expected_mask
);
6208 int dbgop
= ((iw0
>> (PseudoDbg_Assert_dbgop_bits
- 16)) & PseudoDbg_Assert_dbgop_mask
);
6209 int grp
= ((iw0
>> (PseudoDbg_Assert_grp_bits
- 16)) & PseudoDbg_Assert_grp_mask
);
6210 int regtest
= ((iw0
>> (PseudoDbg_Assert_regtest_bits
- 16)) & PseudoDbg_Assert_regtest_mask
);
6213 bu32 val
= reg_read (cpu
, grp
, regtest
);
6214 const char *reg_name
= get_allreg_name (grp
, regtest
);
6215 const char *dbg_name
, *dbg_appd
;
6217 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_psedodbg_assert
);
6218 TRACE_EXTRACT (cpu
, "%s: dbgop:%i grp:%i regtest:%i expected:%#x",
6219 __func__
, dbgop
, grp
, regtest
, expected
);
6221 if (dbgop
== 0 || dbgop
== 2)
6223 dbg_name
= dbgop
== 0 ? "DBGA" : "DBGAL";
6224 dbg_appd
= dbgop
== 0 ? ".L" : "";
6227 else if (dbgop
== 1 || dbgop
== 3)
6229 dbg_name
= dbgop
== 1 ? "DBGA" : "DBGAH";
6230 dbg_appd
= dbgop
== 1 ? ".H" : "";
6234 illegal_instruction (cpu
);
6236 actual
= val
>> offset
;
6238 TRACE_INSN (cpu
, "%s (%s%s, 0x%x);", dbg_name
, reg_name
, dbg_appd
, expected
);
6239 if (actual
!= expected
)
6241 sim_io_printf (sd
, "FAIL at %#x: %s (%s%s, 0x%04x); actual value %#x\n",
6242 pc
, dbg_name
, reg_name
, dbg_appd
, expected
, actual
);
6244 /* Decode the actual ASTAT bits that are different. */
6245 if (grp
== 4 && regtest
== 6)
6249 sim_io_printf (sd
, "Expected ASTAT:\n");
6250 for (i
= 0; i
< 16; ++i
)
6251 sim_io_printf (sd
, " %8s%c%i%s",
6252 astat_names
[i
+ offset
],
6253 (((expected
>> i
) & 1) != ((actual
>> i
) & 1))
6255 (expected
>> i
) & 1,
6256 i
== 7 ? "\n" : "");
6257 sim_io_printf (sd
, "\n");
6259 sim_io_printf (sd
, "Actual ASTAT:\n");
6260 for (i
= 0; i
< 16; ++i
)
6261 sim_io_printf (sd
, " %8s%c%i%s",
6262 astat_names
[i
+ offset
],
6263 (((expected
>> i
) & 1) != ((actual
>> i
) & 1))
6266 i
== 7 ? "\n" : "");
6267 sim_io_printf (sd
, "\n");
6270 cec_exception (cpu
, VEC_SIM_DBGA
);
6276 _interp_insn_bfin (SIM_CPU
*cpu
, bu32 pc
)
6281 BFIN_CPU_STATE
.multi_pc
= pc
;
6283 if ((iw0
& 0xc000) != 0xc000)
6285 /* 16-bit opcode. */
6288 INSN_LEN
= insn_len
;
6290 TRACE_EXTRACT (cpu
, "%s: iw0:%#x", __func__
, iw0
);
6291 if ((iw0
& 0xFF00) == 0x0000)
6292 decode_ProgCtrl_0 (cpu
, iw0
, pc
);
6293 else if ((iw0
& 0xFFC0) == 0x0240)
6294 decode_CaCTRL_0 (cpu
, iw0
);
6295 else if ((iw0
& 0xFF80) == 0x0100)
6296 decode_PushPopReg_0 (cpu
, iw0
);
6297 else if ((iw0
& 0xFE00) == 0x0400)
6298 decode_PushPopMultiple_0 (cpu
, iw0
);
6299 else if ((iw0
& 0xFE00) == 0x0600)
6300 decode_ccMV_0 (cpu
, iw0
);
6301 else if ((iw0
& 0xF800) == 0x0800)
6302 decode_CCflag_0 (cpu
, iw0
);
6303 else if ((iw0
& 0xFFE0) == 0x0200)
6304 decode_CC2dreg_0 (cpu
, iw0
);
6305 else if ((iw0
& 0xFF00) == 0x0300)
6306 decode_CC2stat_0 (cpu
, iw0
);
6307 else if ((iw0
& 0xF000) == 0x1000)
6308 decode_BRCC_0 (cpu
, iw0
, pc
);
6309 else if ((iw0
& 0xF000) == 0x2000)
6310 decode_UJUMP_0 (cpu
, iw0
, pc
);
6311 else if ((iw0
& 0xF000) == 0x3000)
6312 decode_REGMV_0 (cpu
, iw0
);
6313 else if ((iw0
& 0xFC00) == 0x4000)
6314 decode_ALU2op_0 (cpu
, iw0
);
6315 else if ((iw0
& 0xFE00) == 0x4400)
6316 decode_PTR2op_0 (cpu
, iw0
);
6317 else if ((iw0
& 0xF800) == 0x4800)
6318 decode_LOGI2op_0 (cpu
, iw0
);
6319 else if ((iw0
& 0xF000) == 0x5000)
6320 decode_COMP3op_0 (cpu
, iw0
);
6321 else if ((iw0
& 0xF800) == 0x6000)
6322 decode_COMPI2opD_0 (cpu
, iw0
);
6323 else if ((iw0
& 0xF800) == 0x6800)
6324 decode_COMPI2opP_0 (cpu
, iw0
);
6325 else if ((iw0
& 0xF000) == 0x8000)
6326 decode_LDSTpmod_0 (cpu
, iw0
);
6327 else if ((iw0
& 0xFF60) == 0x9E60)
6328 decode_dagMODim_0 (cpu
, iw0
);
6329 else if ((iw0
& 0xFFF0) == 0x9F60)
6330 decode_dagMODik_0 (cpu
, iw0
);
6331 else if ((iw0
& 0xFC00) == 0x9C00)
6332 decode_dspLDST_0 (cpu
, iw0
);
6333 else if ((iw0
& 0xF000) == 0x9000)
6334 decode_LDST_0 (cpu
, iw0
);
6335 else if ((iw0
& 0xFC00) == 0xB800)
6336 decode_LDSTiiFP_0 (cpu
, iw0
);
6337 else if ((iw0
& 0xE000) == 0xA000)
6338 decode_LDSTii_0 (cpu
, iw0
);
6341 TRACE_EXTRACT (cpu
, "%s: no matching 16-bit pattern", __func__
);
6342 illegal_instruction_or_combination (cpu
);
6347 /* Grab the next 16 bits to determine if it's a 32-bit or 64-bit opcode. */
6348 iw1
= IFETCH (pc
+ 2);
6349 if ((iw0
& BIT_MULTI_INS
) && (iw0
& 0xe800) != 0xe800 /* not linkage */)
6351 SIM_DESC sd
= CPU_STATE (cpu
);
6352 trace_prefix (sd
, cpu
, NULL_CIA
, pc
, TRACE_LINENUM_P (cpu
),
6353 NULL
, 0, "|| %#"PRIx64
, sim_events_time (sd
));
6355 PARALLEL_GROUP
= BFIN_PARALLEL_GROUP0
;
6360 TRACE_EXTRACT (cpu
, "%s: iw0:%#x iw1:%#x insn_len:%i", __func__
,
6361 iw0
, iw1
, insn_len
);
6363 /* Only cache on first run through (in case of parallel insns). */
6365 INSN_LEN
= insn_len
;
6367 /* Once you're past the first slot, only 16bit insns are valid. */
6368 illegal_instruction_combination (cpu
);
6370 if ((iw0
& 0xf7ff) == 0xc003 && (iw1
& 0xfe00) == 0x1800)
6372 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32mac
);
6373 TRACE_INSN (cpu
, "MNOP;");
6375 else if (((iw0
& 0xFF80) == 0xE080) && ((iw1
& 0x0C00) == 0x0000))
6376 decode_LoopSetup_0 (cpu
, iw0
, iw1
, pc
);
6377 else if (((iw0
& 0xFF00) == 0xE100) && ((iw1
& 0x0000) == 0x0000))
6378 decode_LDIMMhalf_0 (cpu
, iw0
, iw1
);
6379 else if (((iw0
& 0xFE00) == 0xE200) && ((iw1
& 0x0000) == 0x0000))
6380 decode_CALLa_0 (cpu
, iw0
, iw1
, pc
);
6381 else if (((iw0
& 0xFC00) == 0xE400) && ((iw1
& 0x0000) == 0x0000))
6382 decode_LDSTidxI_0 (cpu
, iw0
, iw1
);
6383 else if (((iw0
& 0xFFFE) == 0xE800) && ((iw1
& 0x0000) == 0x0000))
6384 decode_linkage_0 (cpu
, iw0
, iw1
);
6385 else if (((iw0
& 0xF600) == 0xC000) && ((iw1
& 0x0000) == 0x0000))
6386 decode_dsp32mac_0 (cpu
, iw0
, iw1
);
6387 else if (((iw0
& 0xF600) == 0xC200) && ((iw1
& 0x0000) == 0x0000))
6388 decode_dsp32mult_0 (cpu
, iw0
, iw1
);
6389 else if (((iw0
& 0xF7C0) == 0xC400) && ((iw1
& 0x0000) == 0x0000))
6390 decode_dsp32alu_0 (cpu
, iw0
, iw1
);
6391 else if (((iw0
& 0xF7E0) == 0xC600) && ((iw1
& 0x01C0) == 0x0000))
6392 decode_dsp32shift_0 (cpu
, iw0
, iw1
);
6393 else if (((iw0
& 0xF7E0) == 0xC680) && ((iw1
& 0x0000) == 0x0000))
6394 decode_dsp32shiftimm_0 (cpu
, iw0
, iw1
);
6395 else if ((iw0
& 0xFF00) == 0xF800)
6396 decode_psedoDEBUG_0 (cpu
, iw0
), insn_len
= 2;
6397 else if ((iw0
& 0xFF00) == 0xF900)
6398 decode_psedoOChar_0 (cpu
, iw0
), insn_len
= 2;
6399 else if (((iw0
& 0xFF00) == 0xF000) && ((iw1
& 0x0000) == 0x0000))
6400 decode_psedodbg_assert_0 (cpu
, iw0
, iw1
, pc
);
6403 TRACE_EXTRACT (cpu
, "%s: no matching 32-bit pattern", __func__
);
6404 illegal_instruction (cpu
);
6411 interp_insn_bfin (SIM_CPU
*cpu
, bu32 pc
)
6416 BFIN_CPU_STATE
.n_stores
= 0;
6417 PARALLEL_GROUP
= BFIN_PARALLEL_NONE
;
6418 DIS_ALGN_EXPT
&= ~1;
6422 insn_len
= _interp_insn_bfin (cpu
, pc
);
6424 /* Proper display of multiple issue instructions. */
6427 PARALLEL_GROUP
= BFIN_PARALLEL_GROUP1
;
6428 _interp_insn_bfin (cpu
, pc
+ 4);
6429 PARALLEL_GROUP
= BFIN_PARALLEL_GROUP2
;
6430 _interp_insn_bfin (cpu
, pc
+ 6);
6432 for (i
= 0; i
< BFIN_CPU_STATE
.n_stores
; i
++)
6434 bu32
*addr
= BFIN_CPU_STATE
.stores
[i
].addr
;
6435 *addr
= BFIN_CPU_STATE
.stores
[i
].val
;
6436 TRACE_REGISTER (cpu
, "dequeuing write %s = %#x",
6437 get_store_name (cpu
, addr
), *addr
);
6440 cycles_inc (cpu
, CYCLE_DELAY
);
6442 /* Set back to zero in case a pending CEC event occurs
6443 after this this insn. */