1 /* Simulator for Analog Devices Blackfin processors.
3 Copyright (C) 2005-2011 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 unhandled_instruction (SIM_CPU
*cpu
, const char *insn
)
57 SIM_DESC sd
= CPU_STATE (cpu
);
61 TRACE_EVENTS (cpu
, "unhandled instruction");
64 iw1
= IFETCH (PCREG
+ 2);
65 iw2
= ((bu32
)iw0
<< 16) | iw1
;
67 sim_io_eprintf (sd
, "Unhandled instruction at 0x%08x (%s opcode 0x", PCREG
, insn
);
68 if ((iw0
& 0xc000) == 0xc000)
69 sim_io_eprintf (sd
, "%08x", iw2
);
71 sim_io_eprintf (sd
, "%04x", iw0
);
73 sim_io_eprintf (sd
, ") ... aborting\n");
75 illegal_instruction (cpu
);
78 static const char * const astat_names
[] =
116 c_0
, c_1
, c_4
, c_2
, c_uimm2
, c_uimm3
, c_imm3
, c_pcrel4
,
117 c_imm4
, c_uimm4s4
, c_uimm4s4d
, c_uimm4
, c_uimm4s2
, c_negimm5s4
, c_imm5
,
118 c_imm5d
, c_uimm5
, c_imm6
, c_imm7
, c_imm7d
, c_imm8
, c_uimm8
, c_pcrel8
,
119 c_uimm8s4
, c_pcrel8s4
, c_lppcrel10
, c_pcrel10
, c_pcrel12
, c_imm16s4
,
120 c_luimm16
, c_imm16
, c_imm16d
, c_huimm16
, c_rimm16
, c_imm16s2
, c_uimm16s4
,
121 c_uimm16s4d
, c_uimm16
, c_pcrel24
, c_uimm32
, c_imm32
, c_huimm32
, c_huimm32e
,
138 } constant_formats
[] =
140 { "0", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
141 { "1", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
142 { "4", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
143 { "2", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
144 { "uimm2", 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
145 { "uimm3", 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
146 { "imm3", 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
147 { "pcrel4", 4, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0},
148 { "imm4", 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
149 { "uimm4s4", 4, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0},
150 { "uimm4s4d", 4, 0, 0, 0, 2, 0, 0, 1, 1, 0, 0},
151 { "uimm4", 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
152 { "uimm4s2", 4, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0},
153 { "negimm5s4", 5, 0, 1, 0, 2, 0, 1, 0, 0, 0, 0},
154 { "imm5", 5, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
155 { "imm5d", 5, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0},
156 { "uimm5", 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
157 { "imm6", 6, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
158 { "imm7", 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
159 { "imm7d", 7, 0, 1, 0, 0, 0, 0, 0, 1, 3, 0},
160 { "imm8", 8, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
161 { "uimm8", 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
162 { "pcrel8", 8, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0},
163 { "uimm8s4", 8, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0},
164 { "pcrel8s4", 8, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0},
165 { "lppcrel10", 10, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0},
166 { "pcrel10", 10, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
167 { "pcrel12", 12, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
168 { "imm16s4", 16, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0},
169 { "luimm16", 16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
170 { "imm16", 16, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
171 { "imm16d", 16, 0, 1, 0, 0, 0, 0, 0, 1, 3, 0},
172 { "huimm16", 16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
173 { "rimm16", 16, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0},
174 { "imm16s2", 16, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0},
175 { "uimm16s4", 16, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0},
176 { "uimm16s4d", 16, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0},
177 { "uimm16", 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
178 { "pcrel24", 24, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
179 { "uimm32", 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
180 { "imm32", 32, 0, 1, 0, 0, 0, 0, 0, 1, 3, 0},
181 { "huimm32", 32, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
182 { "huimm32e", 32, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
186 fmtconst_str (const_forms_t cf
, bs32 x
, bu32 pc
)
190 if (constant_formats
[cf
].reloc
)
192 bu32 ea
= (((constant_formats
[cf
].pcrel
? SIGNEXTEND (x
, constant_formats
[cf
].nbits
)
193 : x
) + constant_formats
[cf
].offset
) << constant_formats
[cf
].scale
);
194 if (constant_formats
[cf
].pcrel
)
196 /*if (outf->symbol_at_address_func (ea, outf) || !constant_formats[cf].exact)
198 outf->print_address_func (ea, outf);
203 sprintf (buf
, "%#x", x
);
208 /* Negative constants have an implied sign bit. */
209 if (constant_formats
[cf
].negative
)
211 int nb
= constant_formats
[cf
].nbits
+ 1;
213 x
= x
| (1 << constant_formats
[cf
].nbits
);
214 x
= SIGNEXTEND (x
, nb
);
217 x
= constant_formats
[cf
].issigned
? SIGNEXTEND (x
, constant_formats
[cf
].nbits
) : x
;
219 if (constant_formats
[cf
].offset
)
220 x
+= constant_formats
[cf
].offset
;
222 if (constant_formats
[cf
].scale
)
223 x
<<= constant_formats
[cf
].scale
;
225 if (constant_formats
[cf
].decimal
)
227 if (constant_formats
[cf
].leading
)
230 sprintf (ps
, "%%%ii", constant_formats
[cf
].leading
);
231 sprintf (buf
, ps
, x
);
234 sprintf (buf
, "%i", 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);
716 /* XXX: Need to check ASTAT[v] behavior here. */
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);
750 lshift (SIM_CPU
*cpu
, bu64 val
, int cnt
, int size
, bool saturate
)
752 int i
, j
, real_cnt
= cnt
> size
? size
: cnt
;
753 bu64 sgn
= ~((val
>> (size
- 1)) - 1);
754 int mask_cnt
= size
- 1;
755 bu64 masked
, new_val
= val
, tmp
;
763 new_val
<<= 16, real_cnt
-= 16;
765 new_val
<<= real_cnt
;
767 masked
= new_val
& mask
;
769 /* If an operation would otherwise cause a positive value to overflow
770 and become negative, instead, saturation limits the result to the
771 maximum positive value for the size register being used.
773 Conversely, if an operation would otherwise cause a negative value
774 to overflow and become positive, saturation limits the result to the
775 maximum negative value for the register size.
777 However, it's a little more complex than looking at sign bits, we need
778 to see if we are shifting the sign information away... */
779 tmp
= val
& ((~mask
<< 1) | 1);
782 for (i
= 1; i
<= real_cnt
&& saturate
; i
++)
784 if ((tmp
& ((bu64
)1 << (size
- 1))) !=
785 (((val
>> mask_cnt
) & 0x1) << mask_cnt
))
789 saturate
&= (!sgn
&& (new_val
& (1 << mask_cnt
)))
790 || (sgn
&& !(new_val
& (1 << mask_cnt
)));
795 if (j
|| (saturate
&& (new_val
& mask
)))
796 new_val
= sgn
== 0 ? 0x7fff : 0x8000, saturate
= 1;
800 new_val
&= 0xFFFFFFFF;
801 masked
&= 0xFFFFFFFF;
802 if (j
|| (saturate
&& ((sgn
!= masked
) || (!sgn
&& new_val
== 0))))
803 new_val
= sgn
== 0 ? 0x7fffffff : 0x80000000, saturate
= 1;
806 new_val
&= 0xFFFFFFFFFFull
;
807 masked
&= 0xFFFFFFFFFFull
;
810 illegal_instruction (cpu
);
814 SET_ASTATREG (an
, new_val
>> (size
- 1));
815 SET_ASTATREG (az
, new_val
== 0);
816 SET_ASTATREG (v
, !!(saturate
|| j
));
818 SET_ASTATREG (vs
, 1);
823 algn (bu32 l
, bu32 h
, bu32 aln
)
828 return (l
>> (8 * aln
)) | (h
<< (32 - 8 * aln
));
832 saturate_s16 (bu64 val
, bu32
*overflow
)
834 if ((bs64
)val
< -0x8000ll
)
840 if ((bs64
)val
> 0x7fff)
850 rot40 (bu40 val
, int shift
, bu32
*cc
)
852 const int nbits
= 40;
855 shift
= CLAMP (shift
, -nbits
, nbits
);
859 /* Reduce everything to rotate left. */
863 ret
= shift
== nbits
? 0 : val
<< shift
;
864 ret
|= shift
== 1 ? 0 : val
>> ((nbits
+ 1) - shift
);
865 ret
|= (bu40
)*cc
<< (shift
- 1);
866 *cc
= (val
>> (nbits
- shift
)) & 1;
872 rot32 (bu32 val
, int shift
, bu32
*cc
)
874 const int nbits
= 32;
877 shift
= CLAMP (shift
, -nbits
, nbits
);
881 /* Reduce everything to rotate left. */
885 ret
= shift
== nbits
? 0 : val
<< shift
;
886 ret
|= shift
== 1 ? 0 : val
>> ((nbits
+ 1) - shift
);
887 ret
|= (bu32
)*cc
<< (shift
- 1);
888 *cc
= (val
>> (nbits
- shift
)) & 1;
894 add32 (SIM_CPU
*cpu
, bu32 a
, bu32 b
, int carry
, int sat
)
896 int flgs
= (a
>> 31) & 1;
897 int flgo
= (b
>> 31) & 1;
899 int flgn
= (v
>> 31) & 1;
900 int overflow
= (flgs
^ flgn
) & (flgo
^ flgn
);
907 flgn
= (v
>> 31) & 1;
910 SET_ASTATREG (an
, flgn
);
912 SET_ASTATREG (vs
, 1);
913 SET_ASTATREG (v
, overflow
);
914 ASTATREG (v_internal
) |= overflow
;
915 SET_ASTATREG (az
, v
== 0);
917 SET_ASTATREG (ac0
, ~a
< b
);
923 sub32 (SIM_CPU
*cpu
, bu32 a
, bu32 b
, int carry
, int sat
, int parallel
)
925 int flgs
= (a
>> 31) & 1;
926 int flgo
= (b
>> 31) & 1;
928 int flgn
= (v
>> 31) & 1;
929 int overflow
= (flgs
^ flgo
) & (flgn
^ flgs
);
936 flgn
= (v
>> 31) & 1;
939 if (!parallel
|| flgn
)
940 SET_ASTATREG (an
, flgn
);
942 SET_ASTATREG (vs
, 1);
943 if (!parallel
|| overflow
)
944 SET_ASTATREG (v
, overflow
);
945 if (!parallel
|| overflow
)
946 ASTATREG (v_internal
) |= overflow
;
947 if (!parallel
|| v
== 0)
948 SET_ASTATREG (az
, v
== 0);
949 if (carry
&& (!parallel
|| b
<= a
))
950 SET_ASTATREG (ac0
, b
<= a
);
956 add16 (SIM_CPU
*cpu
, bu16 a
, bu16 b
, bu32
*carry
, bu32
*overfl
,
957 bu32
*zero
, bu32
*neg
, int sat
, int scale
)
959 int flgs
= (a
>> 15) & 1;
960 int flgo
= (b
>> 15) & 1;
961 bs64 v
= (bs16
)a
+ (bs16
)b
;
962 int flgn
= (v
>> 15) & 1;
963 int overflow
= (flgs
^ flgn
) & (flgo
^ flgn
);
971 v
= (a
>> 1) + (a
& 0x8000) + (b
>> 1) + (b
& 0x8000)
972 + (((a
& 1) + (b
& 1)) >> 1);
980 illegal_instruction (cpu
);
983 flgn
= (v
>> 15) & 1;
984 overflow
= (flgs
^ flgn
) & (flgo
^ flgn
);
986 if (v
> (bs64
)0xffff)
990 v
= saturate_s16 (v
, 0);
993 *neg
|= (v
>> 15) & 1;
997 *zero
|= (v
& 0xFFFF) == 0;
999 *carry
|= ((bu16
)~a
< (bu16
)b
);
1005 sub16 (SIM_CPU
*cpu
, bu16 a
, bu16 b
, bu32
*carry
, bu32
*overfl
,
1006 bu32
*zero
, bu32
*neg
, int sat
, int scale
)
1008 int flgs
= (a
>> 15) & 1;
1009 int flgo
= (b
>> 15) & 1;
1010 bs64 v
= (bs16
)a
- (bs16
)b
;
1011 int flgn
= (v
>> 15) & 1;
1012 int overflow
= (flgs
^ flgo
) & (flgn
^ flgs
);
1021 v
= ((a
>> 1) + (a
& 0x8000)) - ( (b
>> 1) + (b
& 0x8000))
1022 + (((a
& 1)-(b
& 1)));
1025 v
= ((v
& 0xFFFF) >> 1);
1026 if ((!flgs
& !flgo
& flgn
)
1027 || (flgs
& !flgo
& !flgn
)
1028 || (flgs
& flgo
& flgn
)
1029 || (flgs
& !flgo
& flgn
))
1033 flgn
= (v
>> 15) & 1;
1034 overflow
= (flgs
^ flgo
) & (flgn
^ flgs
);
1039 if (v
> (bs64
)0x7fff || v
< (bs64
)-0xffff)
1043 illegal_instruction (cpu
);
1048 v
= saturate_s16 (v
, 0);
1051 *neg
|= (v
>> 15) & 1;
1053 *zero
|= (v
& 0xFFFF) == 0;
1055 *overfl
|= overflow
;
1057 *carry
|= (bu16
)b
<= (bu16
)a
;
1062 min32 (SIM_CPU
*cpu
, bu32 a
, bu32 b
)
1065 if ((bs32
)a
> (bs32
)b
)
1067 setflags_nz (cpu
, val
);
1068 SET_ASTATREG (v
, 0);
1073 max32 (SIM_CPU
*cpu
, bu32 a
, bu32 b
)
1076 if ((bs32
)a
< (bs32
)b
)
1078 setflags_nz (cpu
, val
);
1079 SET_ASTATREG (v
, 0);
1084 min2x16 (SIM_CPU
*cpu
, bu32 a
, bu32 b
)
1087 if ((bs16
)a
> (bs16
)b
)
1088 val
= (val
& 0xFFFF0000) | (b
& 0xFFFF);
1089 if ((bs16
)(a
>> 16) > (bs16
)(b
>> 16))
1090 val
= (val
& 0xFFFF) | (b
& 0xFFFF0000);
1091 setflags_nz_2x16 (cpu
, val
);
1092 SET_ASTATREG (v
, 0);
1097 max2x16 (SIM_CPU
*cpu
, bu32 a
, bu32 b
)
1100 if ((bs16
)a
< (bs16
)b
)
1101 val
= (val
& 0xFFFF0000) | (b
& 0xFFFF);
1102 if ((bs16
)(a
>> 16) < (bs16
)(b
>> 16))
1103 val
= (val
& 0xFFFF) | (b
& 0xFFFF0000);
1104 setflags_nz_2x16 (cpu
, val
);
1105 SET_ASTATREG (v
, 0);
1110 add_and_shift (SIM_CPU
*cpu
, bu32 a
, bu32 b
, int shift
)
1113 ASTATREG (v_internal
) = 0;
1114 v
= add32 (cpu
, a
, b
, 0, 0);
1117 int x
= (v
>> 30) & 0x3;
1118 if (x
== 1 || x
== 2)
1119 ASTATREG (v_internal
) = 1;
1122 SET_ASTATREG (az
, v
== 0);
1123 SET_ASTATREG (an
, v
& 0x80000000);
1124 SET_ASTATREG (v
, ASTATREG (v_internal
));
1126 SET_ASTATREG (vs
, 1);
1131 xor_reduce (bu64 acc0
, bu64 acc1
)
1135 for (i
= 0; i
< 40; ++i
)
1137 v
^= (acc0
& acc1
& 1);
1144 /* DIVS ( Dreg, Dreg ) ;
1145 Initialize for DIVQ. Set the AQ status bit based on the signs of
1146 the 32-bit dividend and the 16-bit divisor. Left shift the dividend
1147 one bit. Copy AQ into the dividend LSB. */
1149 divs (SIM_CPU
*cpu
, bu32 pquo
, bu16 divisor
)
1151 bu16 r
= pquo
>> 16;
1154 aq
= (r
^ divisor
) >> 15; /* Extract msb's and compute quotient bit. */
1155 SET_ASTATREG (aq
, aq
); /* Update global quotient state. */
1159 pquo
= (pquo
& 0x1FFFF) | (r
<< 17);
1163 /* DIVQ ( Dreg, Dreg ) ;
1164 Based on AQ status bit, either add or subtract the divisor from
1165 the dividend. Then set the AQ status bit based on the MSBs of the
1166 32-bit dividend and the 16-bit divisor. Left shift the dividend one
1167 bit. Copy the logical inverse of AQ into the dividend LSB. */
1169 divq (SIM_CPU
*cpu
, bu32 pquo
, bu16 divisor
)
1171 unsigned short af
= pquo
>> 16;
1180 aq
= (r
^ divisor
) >> 15; /* Extract msb's and compute quotient bit. */
1181 SET_ASTATREG (aq
, aq
); /* Update global quotient state. */
1185 pquo
= (pquo
& 0x1FFFF) | (r
<< 17);
1190 Count the number of bits set to 1 in the 32bit value. */
1198 for (i
= 0; i
< 32; ++i
)
1199 ret
+= !!(val
& (1 << i
));
1205 reg_check_sup (SIM_CPU
*cpu
, int grp
, int reg
)
1208 cec_require_supervisor (cpu
);
1212 reg_write (SIM_CPU
*cpu
, int grp
, int reg
, bu32 value
)
1216 /* ASTAT is special! */
1217 if (grp
== 4 && reg
== 6)
1223 /* Check supervisor after get_allreg() so exception order is correct. */
1224 whichreg
= get_allreg (cpu
, grp
, reg
);
1225 reg_check_sup (cpu
, grp
, reg
);
1227 if (whichreg
== &CYCLES2REG
)
1228 /* Writes to CYCLES2 goes to the shadow. */
1229 whichreg
= &CYCLES2SHDREG
;
1230 else if (whichreg
== &SEQSTATREG
)
1231 /* Register is read only -- discard writes. */
1233 else if (whichreg
== &EMUDAT_INREG
)
1234 /* Writes to EMUDAT goes to the output. */
1235 whichreg
= &EMUDAT_OUTREG
;
1236 else if (whichreg
== <REG (0) || whichreg
== <REG (1))
1237 /* Writes to LT clears LSB automatically. */
1239 else if (whichreg
== &AXREG (0) || whichreg
== &AXREG (1))
1242 TRACE_REGISTER (cpu
, "wrote %s = %#x", get_allreg_name (grp
, reg
), value
);
1248 reg_read (SIM_CPU
*cpu
, int grp
, int reg
)
1253 /* ASTAT is special! */
1254 if (grp
== 4 && reg
== 6)
1257 /* Check supervisor after get_allreg() so exception order is correct. */
1258 whichreg
= get_allreg (cpu
, grp
, reg
);
1259 reg_check_sup (cpu
, grp
, reg
);
1263 if (whichreg
== &CYCLESREG
)
1264 /* Reads of CYCLES reloads CYCLES2 from the shadow. */
1265 SET_CYCLES2REG (CYCLES2SHDREG
);
1266 else if ((whichreg
== &AXREG (1) || whichreg
== &AXREG (0)) && (value
& 0x80))
1267 /* Sign extend if necessary. */
1268 value
|= 0xFFFFFF00;
1274 get_extended_cycles (SIM_CPU
*cpu
)
1276 return ((bu64
)CYCLES2SHDREG
<< 32) | CYCLESREG
;
1279 /* We can't re-use sim_events_time() because the CYCLES registers may be
1280 written/cleared/reset/stopped/started at any time by software. */
1282 cycles_inc (SIM_CPU
*cpu
, bu32 inc
)
1287 if (!(SYSCFGREG
& SYSCFG_CCEN
))
1290 cycles
= get_extended_cycles (cpu
) + inc
;
1291 SET_CYCLESREG (cycles
);
1292 cycles2
= cycles
>> 32;
1293 if (CYCLES2SHDREG
!= cycles2
)
1294 SET_CYCLES2SHDREG (cycles2
);
1298 get_unextended_acc (SIM_CPU
*cpu
, int which
)
1300 return ((bu64
)(AXREG (which
) & 0xff) << 32) | AWREG (which
);
1304 get_extended_acc (SIM_CPU
*cpu
, int which
)
1306 bu64 acc
= AXREG (which
);
1307 /* Sign extend accumulator values before adding. */
1313 acc
|= AWREG (which
);
1317 /* Perform a multiplication of D registers SRC0 and SRC1, sign- or
1318 zero-extending the result to 64 bit. H0 and H1 determine whether the
1319 high part or the low part of the source registers is used. Store 1 in
1320 *PSAT if saturation occurs, 0 otherwise. */
1322 decode_multfunc (SIM_CPU
*cpu
, int h0
, int h1
, int src0
, int src1
, int mmod
,
1325 bu32 s0
= DREG (src0
), s1
= DREG (src1
);
1339 sgn0
= -(s0
& 0x8000);
1340 sgn1
= -(s1
& 0x8000);
1362 illegal_instruction (cpu
);
1366 /* Perform shift correction if appropriate for the mode. */
1368 if (!MM
&& (mmod
== 0 || mmod
== M_T
|| mmod
== M_S2RND
|| mmod
== M_W32
))
1370 if (val
== 0x40000000)
1383 if (mmod
== 0 || mmod
== M_IS
|| mmod
== M_T
|| mmod
== M_S2RND
1384 || mmod
== M_ISS2
|| mmod
== M_IH
|| (MM
&& mmod
== M_FU
))
1385 val1
|= -(val1
& 0x80000000);
1388 val1
&= 0xFFFFFFFFull
;
1394 saturate_s40_astat (bu64 val
, bu32
*v
)
1396 if ((bs64
)val
< -((bs64
)1 << 39))
1399 return -((bs64
)1 << 39);
1401 else if ((bs64
)val
>= ((bs64
)1 << 39) - 1)
1404 return ((bu64
)1 << 39) - 1;
1406 *v
= 0; /* No overflow. */
1411 saturate_s40 (bu64 val
)
1414 return saturate_s40_astat (val
, &v
);
1418 saturate_s32 (bu64 val
, bu32
*overflow
)
1420 if ((bs64
)val
< -0x80000000ll
)
1426 if ((bs64
)val
> 0x7fffffff)
1436 saturate_u32 (bu64 val
, bu32
*overflow
)
1438 if (val
> 0xffffffff)
1448 saturate_u16 (bu64 val
, bu32
*overflow
)
1464 /* FIXME: Should honour rounding mode. */
1465 if ((val
& 0xffff) > 0x8000
1466 || ((val
& 0xffff) == 0x8000 && (val
& 0x10000)))
1469 sgnbits
= val
& 0xffff000000000000ull
;
1471 return val
| sgnbits
;
1477 bu64 sgnbits
= val
& 0xffff000000000000ull
;
1479 return val
| sgnbits
;
1483 signbits (bu64 val
, int size
)
1485 bu64 mask
= (bu64
)1 << (size
- 1);
1486 bu64 bit
= val
& mask
;
1494 if ((val
& mask
) != bit
)
1504 /* Extract a 16 or 32 bit value from a 64 bit multiplication result.
1505 These 64 bits must be sign- or zero-extended properly from the source
1506 we want to extract, either a 32 bit multiply or a 40 bit accumulator. */
1509 extract_mult (SIM_CPU
*cpu
, bu64 res
, int mmod
, int MM
,
1510 int fullword
, bu32
*overflow
)
1517 return saturate_s32 (res
, overflow
);
1519 return saturate_u32 (res
, overflow
);
1522 return saturate_s32 (res
, overflow
);
1523 return saturate_u32 (res
, overflow
);
1526 return saturate_s32 (res
<< 1, overflow
);
1528 illegal_instruction (cpu
);
1535 return saturate_s16 (rnd16 (res
), overflow
);
1537 return saturate_s32 (rnd16 (res
), overflow
) & 0xFFFF;
1539 return saturate_s16 (res
, overflow
);
1542 return saturate_s16 (rnd16 (res
), overflow
);
1543 return saturate_u16 (rnd16 (res
), overflow
);
1546 return saturate_s16 (res
, overflow
);
1547 return saturate_u16 (res
, overflow
);
1550 return saturate_s16 (trunc16 (res
), overflow
);
1552 return saturate_u16 (trunc16 (res
), overflow
);
1555 return saturate_s16 (rnd16 (res
<< 1), overflow
);
1557 return saturate_s16 (res
<< 1, overflow
);
1559 illegal_instruction (cpu
);
1564 decode_macfunc (SIM_CPU
*cpu
, int which
, int op
, int h0
, int h1
, int src0
,
1565 int src1
, int mmod
, int MM
, int fullword
, bu32
*overflow
,
1569 bu32 sat
= 0, tsat
, ret
;
1571 /* Sign extend accumulator if necessary, otherwise unsigned. */
1572 if (mmod
== 0 || mmod
== M_T
|| mmod
== M_IS
|| mmod
== M_ISS2
1573 || mmod
== M_S2RND
|| mmod
== M_IH
|| mmod
== M_W32
)
1574 acc
= get_extended_acc (cpu
, which
);
1576 acc
= get_unextended_acc (cpu
, which
);
1578 if (MM
&& (mmod
== M_T
|| mmod
== M_IS
|| mmod
== M_ISS2
1579 || mmod
== M_S2RND
|| mmod
== M_IH
|| mmod
== M_W32
))
1580 acc
|= -(acc
& 0x80000000);
1584 bu8 sgn0
= (acc
>> 31) & 1;
1585 /* This can't saturate, so we don't keep track of the sat flag. */
1586 bu64 res
= decode_multfunc (cpu
, h0
, h1
, src0
, src1
, mmod
,
1589 /* Perform accumulation. */
1594 sgn0
= (acc
>> 31) & 1;
1612 if ((bs64
)acc
< -((bs64
)1 << 39))
1613 acc
= -((bu64
)1 << 39), sat
= 1;
1614 else if ((bs64
)acc
> 0x7fffffffffll
)
1615 acc
= 0x7fffffffffull
, sat
= 1;
1618 if (!MM
&& acc
> 0xFFFFFFFFFFull
)
1620 if (MM
&& acc
> 0xFFFFFFFF)
1624 if (acc
& 0x8000000000000000ull
)
1626 if (acc
> 0xFFFFFFFFFFull
)
1627 acc
&= 0xFFFFFFFFFFull
, sat
= 1;
1628 if (MM
&& acc
> 0xFFFFFFFF)
1630 if (acc
& 0x80000000)
1631 acc
|= 0xffffffff00000000ull
;
1634 if (!MM
&& (bs64
)acc
< 0)
1636 if (MM
&& (bs64
)acc
< -((bs64
)1 << 39))
1637 acc
= -((bu64
)1 << 39), sat
= 1;
1638 if (!MM
&& (bs64
)acc
> (bs64
)0xFFFFFFFFFFll
)
1639 acc
= 0xFFFFFFFFFFull
, sat
= 1;
1640 if (MM
&& acc
> 0xFFFFFFFFFFull
)
1641 acc
&= 0xFFFFFFFFFFull
;
1642 if (MM
&& acc
& 0x80000000)
1643 acc
|= 0xffffffff00000000ull
;
1646 if ((bs64
)acc
< -0x80000000ll
)
1647 acc
= -0x80000000ull
, sat
= 1;
1648 else if ((bs64
)acc
>= 0x7fffffffll
)
1649 acc
= 0x7fffffffull
, sat
= 1;
1652 if (sgn0
&& (sgn0
!= ((acc
>> 31) & 1))
1653 && (((acc
>> 32) & 0xFF) == 0xff))
1656 if (acc
& 0x80000000)
1657 acc
|= 0xffffffff00000000ull
;
1660 illegal_instruction (cpu
);
1663 if (acc
& 0x8000000000ull
)
1666 STORE (AXREG (which
), (acc
>> 32) & 0xff);
1667 STORE (AWREG (which
), acc
& 0xffffffff);
1668 STORE (ASTATREG (av
[which
]), sat
);
1670 STORE (ASTATREG (avs
[which
]), sat
);
1673 ret
= extract_mult (cpu
, acc
, mmod
, MM
, fullword
, overflow
);
1682 if (ret
& 0x80000000)
1690 hwloop_get_next_pc (SIM_CPU
*cpu
, bu32 pc
, bu32 insn_len
)
1697 /* If our PC has reached the bottom of a hardware loop,
1698 move back up to the top of the hardware loop. */
1699 for (i
= 1; i
>= 0; --i
)
1700 if (LCREG (i
) > 1 && pc
== LBREG (i
))
1702 TRACE_BRANCH (cpu
, pc
, LTREG (i
), i
, "Hardware loop %i", i
);
1706 return pc
+ insn_len
;
1710 decode_ProgCtrl_0 (SIM_CPU
*cpu
, bu16 iw0
, bu32 pc
)
1713 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
1714 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |.prgfunc.......|.poprnd........|
1715 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
1716 int poprnd
= ((iw0
>> ProgCtrl_poprnd_bits
) & ProgCtrl_poprnd_mask
);
1717 int prgfunc
= ((iw0
>> ProgCtrl_prgfunc_bits
) & ProgCtrl_prgfunc_mask
);
1719 TRACE_EXTRACT (cpu
, "%s: poprnd:%i prgfunc:%i", __func__
, poprnd
, prgfunc
);
1721 if (prgfunc
== 0 && poprnd
== 0)
1723 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_nop
);
1724 TRACE_INSN (cpu
, "NOP;");
1726 else if (prgfunc
== 1 && poprnd
== 0)
1728 bu32 newpc
= RETSREG
;
1729 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1730 TRACE_INSN (cpu
, "RTS;");
1731 IFETCH_CHECK (newpc
);
1733 illegal_instruction_combination (cpu
);
1734 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "RTS");
1736 BFIN_CPU_STATE
.did_jump
= true;
1739 else if (prgfunc
== 1 && poprnd
== 1)
1741 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1742 TRACE_INSN (cpu
, "RTI;");
1743 /* Do not do IFETCH_CHECK here -- LSB has special meaning. */
1745 illegal_instruction_combination (cpu
);
1746 cec_return (cpu
, -1);
1749 else if (prgfunc
== 1 && poprnd
== 2)
1751 bu32 newpc
= RETXREG
;
1752 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1753 TRACE_INSN (cpu
, "RTX;");
1754 /* XXX: Not sure if this is what the hardware does. */
1755 IFETCH_CHECK (newpc
);
1757 illegal_instruction_combination (cpu
);
1758 cec_return (cpu
, IVG_EVX
);
1761 else if (prgfunc
== 1 && poprnd
== 3)
1763 bu32 newpc
= RETNREG
;
1764 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1765 TRACE_INSN (cpu
, "RTN;");
1766 /* XXX: Not sure if this is what the hardware does. */
1767 IFETCH_CHECK (newpc
);
1769 illegal_instruction_combination (cpu
);
1770 cec_return (cpu
, IVG_NMI
);
1773 else if (prgfunc
== 1 && poprnd
== 4)
1775 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1776 TRACE_INSN (cpu
, "RTE;");
1778 illegal_instruction_combination (cpu
);
1779 cec_return (cpu
, IVG_EMU
);
1782 else if (prgfunc
== 2 && poprnd
== 0)
1784 SIM_DESC sd
= CPU_STATE (cpu
);
1785 sim_events
*events
= STATE_EVENTS (sd
);
1787 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_sync
);
1788 /* XXX: in supervisor mode, utilizes wake up sources
1789 in user mode, it's a NOP ... */
1790 TRACE_INSN (cpu
, "IDLE;");
1793 illegal_instruction_combination (cpu
);
1797 CYCLE_DELAY
= events
->time_from_event
;
1799 abort (); /* XXX: Should this ever happen ? */
1801 else if (prgfunc
== 2 && poprnd
== 3)
1803 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_sync
);
1805 TRACE_INSN (cpu
, "CSYNC;");
1807 illegal_instruction_combination (cpu
);
1810 else if (prgfunc
== 2 && poprnd
== 4)
1812 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_sync
);
1814 TRACE_INSN (cpu
, "SSYNC;");
1816 illegal_instruction_combination (cpu
);
1818 /* Really 10+, but no model info for this. */
1821 else if (prgfunc
== 2 && poprnd
== 5)
1823 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1824 TRACE_INSN (cpu
, "EMUEXCPT;");
1826 illegal_instruction_combination (cpu
);
1827 cec_exception (cpu
, VEC_SIM_TRAP
);
1829 else if (prgfunc
== 3 && poprnd
< 8)
1831 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1832 TRACE_INSN (cpu
, "CLI R%i;", poprnd
);
1834 illegal_instruction_combination (cpu
);
1835 SET_DREG (poprnd
, cec_cli (cpu
));
1837 else if (prgfunc
== 4 && poprnd
< 8)
1839 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1840 TRACE_INSN (cpu
, "STI R%i;", poprnd
);
1842 illegal_instruction_combination (cpu
);
1843 cec_sti (cpu
, DREG (poprnd
));
1846 else if (prgfunc
== 5 && poprnd
< 8)
1848 bu32 newpc
= PREG (poprnd
);
1849 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1850 TRACE_INSN (cpu
, "JUMP (%s);", get_preg_name (poprnd
));
1851 IFETCH_CHECK (newpc
);
1853 illegal_instruction_combination (cpu
);
1854 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP (Preg)");
1856 BFIN_CPU_STATE
.did_jump
= true;
1857 PROFILE_BRANCH_TAKEN (cpu
);
1860 else if (prgfunc
== 6 && poprnd
< 8)
1862 bu32 newpc
= PREG (poprnd
);
1863 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1864 TRACE_INSN (cpu
, "CALL (%s);", get_preg_name (poprnd
));
1865 IFETCH_CHECK (newpc
);
1867 illegal_instruction_combination (cpu
);
1868 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "CALL (Preg)");
1869 /* If we're at the end of a hardware loop, RETS is going to be
1870 the top of the loop rather than the next instruction. */
1871 SET_RETSREG (hwloop_get_next_pc (cpu
, pc
, 2));
1873 BFIN_CPU_STATE
.did_jump
= true;
1874 PROFILE_BRANCH_TAKEN (cpu
);
1877 else if (prgfunc
== 7 && poprnd
< 8)
1879 bu32 newpc
= pc
+ PREG (poprnd
);
1880 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1881 TRACE_INSN (cpu
, "CALL (PC + %s);", get_preg_name (poprnd
));
1882 IFETCH_CHECK (newpc
);
1884 illegal_instruction_combination (cpu
);
1885 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "CALL (PC + Preg)");
1886 SET_RETSREG (hwloop_get_next_pc (cpu
, pc
, 2));
1888 BFIN_CPU_STATE
.did_jump
= true;
1889 PROFILE_BRANCH_TAKEN (cpu
);
1892 else if (prgfunc
== 8 && poprnd
< 8)
1894 bu32 newpc
= pc
+ PREG (poprnd
);
1895 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1896 TRACE_INSN (cpu
, "JUMP (PC + %s);", get_preg_name (poprnd
));
1897 IFETCH_CHECK (newpc
);
1899 illegal_instruction_combination (cpu
);
1900 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP (PC + Preg)");
1902 BFIN_CPU_STATE
.did_jump
= true;
1903 PROFILE_BRANCH_TAKEN (cpu
);
1906 else if (prgfunc
== 9)
1908 int raise
= uimm4 (poprnd
);
1909 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1910 TRACE_INSN (cpu
, "RAISE %s;", uimm4_str (raise
));
1912 illegal_instruction_combination (cpu
);
1913 cec_require_supervisor (cpu
);
1914 if (raise
== IVG_IVHW
)
1915 cec_hwerr (cpu
, HWERR_RAISE_5
);
1917 cec_latch (cpu
, raise
);
1918 CYCLE_DELAY
= 3; /* XXX: Only if IVG is unmasked. */
1920 else if (prgfunc
== 10)
1922 int excpt
= uimm4 (poprnd
);
1923 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1924 TRACE_INSN (cpu
, "EXCPT %s;", uimm4_str (excpt
));
1926 illegal_instruction_combination (cpu
);
1927 cec_exception (cpu
, excpt
);
1930 else if (prgfunc
== 11 && poprnd
< 6)
1932 bu32 addr
= PREG (poprnd
);
1934 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_atomic
);
1935 TRACE_INSN (cpu
, "TESTSET (%s);", get_preg_name (poprnd
));
1937 illegal_instruction_combination (cpu
);
1938 byte
= GET_WORD (addr
);
1939 SET_CCREG (byte
== 0);
1940 PUT_BYTE (addr
, byte
| 0x80);
1941 /* Also includes memory stalls, but we don't model that. */
1945 illegal_instruction (cpu
);
1949 decode_CaCTRL_0 (SIM_CPU
*cpu
, bu16 iw0
)
1952 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
1953 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 |.a.|.op....|.reg.......|
1954 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
1955 int a
= ((iw0
>> CaCTRL_a_bits
) & CaCTRL_a_mask
);
1956 int op
= ((iw0
>> CaCTRL_op_bits
) & CaCTRL_op_mask
);
1957 int reg
= ((iw0
>> CaCTRL_reg_bits
) & CaCTRL_reg_mask
);
1958 bu32 preg
= PREG (reg
);
1959 const char * const sinsn
[] = { "PREFETCH", "FLUSHINV", "FLUSH", "IFLUSH", };
1961 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CaCTRL
);
1962 TRACE_EXTRACT (cpu
, "%s: a:%i op:%i reg:%i", __func__
, a
, op
, reg
);
1963 TRACE_INSN (cpu
, "%s [%s%s];", sinsn
[op
], get_preg_name (reg
), a
? "++" : "");
1966 /* None of these can be part of a parallel instruction. */
1967 illegal_instruction_combination (cpu
);
1969 /* No cache simulation, so these are (mostly) all NOPs.
1970 XXX: The hardware takes care of masking to cache lines, but need
1971 to check behavior of the post increment. Should we be aligning
1972 the value to the cache line before adding the cache line size, or
1973 do we just add the cache line size ? */
1976 mmu_check_cache_addr (cpu
, preg
, false, false);
1980 mmu_check_cache_addr (cpu
, preg
, true, false);
1984 mmu_check_cache_addr (cpu
, preg
, true, false);
1988 mmu_check_cache_addr (cpu
, preg
, false, true);
1992 SET_PREG (reg
, preg
+ BFIN_L1_CACHE_BYTES
);
1996 decode_PushPopReg_0 (SIM_CPU
*cpu
, bu16 iw0
)
1999 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2000 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |.W.|.grp.......|.reg.......|
2001 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2002 int W
= ((iw0
>> PushPopReg_W_bits
) & PushPopReg_W_mask
);
2003 int grp
= ((iw0
>> PushPopReg_grp_bits
) & PushPopReg_grp_mask
);
2004 int reg
= ((iw0
>> PushPopReg_reg_bits
) & PushPopReg_reg_mask
);
2005 const char *reg_name
= get_allreg_name (grp
, reg
);
2009 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_PushPopReg
);
2010 TRACE_EXTRACT (cpu
, "%s: W:%i grp:%i reg:%i", __func__
, W
, grp
, reg
);
2011 TRACE_DECODE (cpu
, "%s: reg:%s", __func__
, reg_name
);
2013 /* Can't push/pop reserved registers */
2014 if (reg_is_reserved (grp
, reg
))
2015 illegal_instruction (cpu
);
2019 /* Dreg and Preg are not supported by this instruction. */
2020 if (grp
== 0 || grp
== 1)
2021 illegal_instruction (cpu
);
2022 TRACE_INSN (cpu
, "%s = [SP++];", reg_name
);
2023 /* Can't pop USP while in userspace. */
2024 if (INSN_LEN
== 8 || (grp
== 7 && reg
== 0 && cec_is_user_mode(cpu
)))
2025 illegal_instruction_combination (cpu
);
2026 /* XXX: The valid register check is in reg_write(), so we might
2027 incorrectly do a GET_LONG() here ... */
2028 value
= GET_LONG (sp
);
2029 reg_write (cpu
, grp
, reg
, value
);
2030 if (grp
== 7 && reg
== 3)
2037 TRACE_INSN (cpu
, "[--SP] = %s;", reg_name
);
2038 /* Can't push SP. */
2039 if (INSN_LEN
== 8 || (grp
== 1 && reg
== 6))
2040 illegal_instruction_combination (cpu
);
2043 value
= reg_read (cpu
, grp
, reg
);
2044 if (grp
== 7 && reg
== 3)
2045 cec_push_reti (cpu
);
2047 PUT_LONG (sp
, value
);
2050 /* Note: SP update must be delayed until after all reads/writes; see
2051 comments in decode_PushPopMultiple_0() for more info. */
2056 decode_PushPopMultiple_0 (SIM_CPU
*cpu
, bu16 iw0
)
2059 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2060 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |.d.|.p.|.W.|.dr........|.pr........|
2061 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2062 int p
= ((iw0
>> PushPopMultiple_p_bits
) & PushPopMultiple_p_mask
);
2063 int d
= ((iw0
>> PushPopMultiple_d_bits
) & PushPopMultiple_d_mask
);
2064 int W
= ((iw0
>> PushPopMultiple_W_bits
) & PushPopMultiple_W_mask
);
2065 int dr
= ((iw0
>> PushPopMultiple_dr_bits
) & PushPopMultiple_dr_mask
);
2066 int pr
= ((iw0
>> PushPopMultiple_pr_bits
) & PushPopMultiple_pr_mask
);
2070 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_PushPopMultiple
);
2071 TRACE_EXTRACT (cpu
, "%s: d:%i p:%i W:%i dr:%i pr:%i",
2072 __func__
, d
, p
, W
, dr
, pr
);
2074 if ((d
== 0 && p
== 0) || (p
&& imm5 (pr
) > 5)
2075 || (d
&& !p
&& pr
) || (p
&& !d
&& dr
))
2076 illegal_instruction (cpu
);
2081 TRACE_INSN (cpu
, "[--SP] = (R7:%i, P5:%i);", dr
, pr
);
2083 TRACE_INSN (cpu
, "[--SP] = (R7:%i);", dr
);
2085 TRACE_INSN (cpu
, "[--SP] = (P5:%i);", pr
);
2088 for (i
= dr
; i
< 8; i
++)
2091 PUT_LONG (sp
, DREG (i
));
2094 for (i
= pr
; i
< 6; i
++)
2097 PUT_LONG (sp
, PREG (i
));
2105 TRACE_INSN (cpu
, "(R7:%i, P5:%i) = [SP++];", dr
, pr
);
2107 TRACE_INSN (cpu
, "(R7:%i) = [SP++];", dr
);
2109 TRACE_INSN (cpu
, "(P5:%i) = [SP++];", pr
);
2112 for (i
= 5; i
>= pr
; i
--)
2114 SET_PREG (i
, GET_LONG (sp
));
2118 for (i
= 7; i
>= dr
; i
--)
2120 SET_DREG (i
, GET_LONG (sp
));
2127 /* Note: SP update must be delayed until after all reads/writes so that
2128 if an exception does occur, the insn may be re-executed as the
2129 SP has not yet changed. */
2134 decode_ccMV_0 (SIM_CPU
*cpu
, bu16 iw0
)
2137 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2138 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |.T.|.d.|.s.|.dst.......|.src.......|
2139 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2140 int s
= ((iw0
>> CCmv_s_bits
) & CCmv_s_mask
);
2141 int d
= ((iw0
>> CCmv_d_bits
) & CCmv_d_mask
);
2142 int T
= ((iw0
>> CCmv_T_bits
) & CCmv_T_mask
);
2143 int src
= ((iw0
>> CCmv_src_bits
) & CCmv_src_mask
);
2144 int dst
= ((iw0
>> CCmv_dst_bits
) & CCmv_dst_mask
);
2145 int cond
= T
? CCREG
: ! CCREG
;
2147 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ccMV
);
2148 TRACE_EXTRACT (cpu
, "%s: T:%i d:%i s:%i dst:%i src:%i",
2149 __func__
, T
, d
, s
, dst
, src
);
2151 TRACE_INSN (cpu
, "IF %sCC %s = %s;", T
? "" : "! ",
2152 get_allreg_name (d
, dst
),
2153 get_allreg_name (s
, src
));
2155 illegal_instruction_combination (cpu
);
2158 reg_write (cpu
, d
, dst
, reg_read (cpu
, s
, src
));
2162 decode_CCflag_0 (SIM_CPU
*cpu
, bu16 iw0
)
2165 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2166 | 0 | 0 | 0 | 0 | 1 |.I.|.opc.......|.G.|.y.........|.x.........|
2167 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2168 int x
= ((iw0
>> CCflag_x_bits
) & CCflag_x_mask
);
2169 int y
= ((iw0
>> CCflag_y_bits
) & CCflag_y_mask
);
2170 int I
= ((iw0
>> CCflag_I_bits
) & CCflag_I_mask
);
2171 int G
= ((iw0
>> CCflag_G_bits
) & CCflag_G_mask
);
2172 int opc
= ((iw0
>> CCflag_opc_bits
) & CCflag_opc_mask
);
2174 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CCflag
);
2175 TRACE_EXTRACT (cpu
, "%s: I:%i opc:%i G:%i y:%i x:%i",
2176 __func__
, I
, opc
, G
, y
, x
);
2180 bs64 acc0
= get_extended_acc (cpu
, 0);
2181 bs64 acc1
= get_extended_acc (cpu
, 1);
2182 bs64 diff
= acc0
- acc1
;
2184 if (x
!= 0 || y
!= 0)
2185 illegal_instruction (cpu
);
2187 if (opc
== 5 && I
== 0 && G
== 0)
2189 TRACE_INSN (cpu
, "CC = A0 == A1;");
2191 illegal_instruction_combination (cpu
);
2192 SET_CCREG (acc0
== acc1
);
2194 else if (opc
== 6 && I
== 0 && G
== 0)
2196 TRACE_INSN (cpu
, "CC = A0 < A1");
2198 illegal_instruction_combination (cpu
);
2199 SET_CCREG (acc0
< acc1
);
2201 else if (opc
== 7 && I
== 0 && G
== 0)
2203 TRACE_INSN (cpu
, "CC = A0 <= A1");
2205 illegal_instruction_combination (cpu
);
2206 SET_CCREG (acc0
<= acc1
);
2209 illegal_instruction (cpu
);
2211 SET_ASTATREG (az
, diff
== 0);
2212 SET_ASTATREG (an
, diff
< 0);
2213 SET_ASTATREG (ac0
, (bu40
)acc1
<= (bu40
)acc0
);
2217 int issigned
= opc
< 3;
2218 const char *sign
= issigned
? "" : " (IU)";
2219 bu32 srcop
= G
? PREG (x
) : DREG (x
);
2220 char s
= G
? 'P' : 'R';
2221 bu32 dstop
= I
? (issigned
? imm3 (y
) : uimm3 (y
)) : G
? PREG (y
) : DREG (y
);
2223 char d
= G
? 'P' : 'R';
2224 int flgs
= srcop
>> 31;
2225 int flgo
= dstop
>> 31;
2227 bu32 result
= srcop
- dstop
;
2229 int flgn
= result
>> 31;
2230 int overflow
= (flgs
^ flgo
) & (flgn
^ flgs
);
2231 int az
= result
== 0;
2232 int ac0
= dstop
<= srcop
;
2235 an
= (flgn
&& !overflow
) || (!flgn
&& overflow
);
2241 default: /* Shutup useless gcc warnings. */
2242 case 0: /* signed */
2246 case 1: /* signed */
2250 case 2: /* signed */
2254 case 3: /* unsigned */
2258 case 4: /* unsigned */
2265 TRACE_INSN (cpu
, "CC = %c%i %s %s%s;", s
, x
, op
,
2266 issigned
? imm3_str (y
) : uimm3_str (y
), sign
);
2269 TRACE_DECODE (cpu
, "%s %c%i:%x %c%i:%x", __func__
,
2270 s
, x
, srcop
, d
, y
, dstop
);
2271 TRACE_INSN (cpu
, "CC = %c%i %s %c%i%s;", s
, x
, op
, d
, y
, sign
);
2275 /* Pointer compares only touch CC. */
2278 SET_ASTATREG (az
, az
);
2279 SET_ASTATREG (an
, an
);
2280 SET_ASTATREG (ac0
, ac0
);
2286 decode_CC2dreg_0 (SIM_CPU
*cpu
, bu16 iw0
)
2289 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2290 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |.op....|.reg.......|
2291 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2292 int op
= ((iw0
>> CC2dreg_op_bits
) & CC2dreg_op_mask
);
2293 int reg
= ((iw0
>> CC2dreg_reg_bits
) & CC2dreg_reg_mask
);
2295 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CC2dreg
);
2296 TRACE_EXTRACT (cpu
, "%s: op:%i reg:%i", __func__
, op
, reg
);
2300 TRACE_INSN (cpu
, "R%i = CC;", reg
);
2302 illegal_instruction_combination (cpu
);
2303 SET_DREG (reg
, CCREG
);
2307 TRACE_INSN (cpu
, "CC = R%i;", reg
);
2309 illegal_instruction_combination (cpu
);
2310 SET_CCREG (DREG (reg
) != 0);
2312 else if (op
== 3 && reg
== 0)
2314 TRACE_INSN (cpu
, "CC = !CC;");
2316 illegal_instruction_combination (cpu
);
2320 illegal_instruction (cpu
);
2324 decode_CC2stat_0 (SIM_CPU
*cpu
, bu16 iw0
)
2327 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2328 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |.D.|.op....|.cbit..............|
2329 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2330 int D
= ((iw0
>> CC2stat_D_bits
) & CC2stat_D_mask
);
2331 int op
= ((iw0
>> CC2stat_op_bits
) & CC2stat_op_mask
);
2332 int cbit
= ((iw0
>> CC2stat_cbit_bits
) & CC2stat_cbit_mask
);
2335 const char * const op_names
[] = { "", "|", "&", "^" } ;
2337 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CC2stat
);
2338 TRACE_EXTRACT (cpu
, "%s: D:%i op:%i cbit:%i", __func__
, D
, op
, cbit
);
2340 TRACE_INSN (cpu
, "%s %s= %s;", D
? astat_names
[cbit
] : "CC",
2341 op_names
[op
], D
? "CC" : astat_names
[cbit
]);
2343 /* CC = CC; is invalid. */
2345 illegal_instruction (cpu
);
2348 illegal_instruction_combination (cpu
);
2350 pval
= !!(ASTAT
& (1 << cbit
));
2354 case 0: SET_CCREG (pval
); break;
2355 case 1: SET_CCREG (CCREG
| pval
); break;
2356 case 2: SET_CCREG (CCREG
& pval
); break;
2357 case 3: SET_CCREG (CCREG
^ pval
); break;
2363 case 0: pval
= CCREG
; break;
2364 case 1: pval
|= CCREG
; break;
2365 case 2: pval
&= CCREG
; break;
2366 case 3: pval
^= CCREG
; break;
2368 TRACE_REGISTER (cpu
, "wrote ASTAT[%s] = %i", astat_names
[cbit
], pval
);
2369 SET_ASTAT ((ASTAT
& ~(1 << cbit
)) | (pval
<< cbit
));
2374 decode_BRCC_0 (SIM_CPU
*cpu
, bu16 iw0
, bu32 pc
)
2377 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2378 | 0 | 0 | 0 | 1 |.T.|.B.|.offset................................|
2379 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2380 int B
= ((iw0
>> BRCC_B_bits
) & BRCC_B_mask
);
2381 int T
= ((iw0
>> BRCC_T_bits
) & BRCC_T_mask
);
2382 int offset
= ((iw0
>> BRCC_offset_bits
) & BRCC_offset_mask
);
2383 int cond
= T
? CCREG
: ! CCREG
;
2384 int pcrel
= pcrel10 (offset
);
2386 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_BRCC
);
2387 TRACE_EXTRACT (cpu
, "%s: T:%i B:%i offset:%#x", __func__
, T
, B
, offset
);
2388 TRACE_DECODE (cpu
, "%s: pcrel10:%#x", __func__
, pcrel
);
2390 TRACE_INSN (cpu
, "IF %sCC JUMP %#x%s;", T
? "" : "! ",
2391 pcrel
, B
? " (bp)" : "");
2394 illegal_instruction_combination (cpu
);
2398 bu32 newpc
= pc
+ pcrel
;
2399 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "Conditional JUMP");
2401 BFIN_CPU_STATE
.did_jump
= true;
2402 PROFILE_BRANCH_TAKEN (cpu
);
2403 CYCLE_DELAY
= B
? 5 : 9;
2407 PROFILE_BRANCH_UNTAKEN (cpu
);
2408 CYCLE_DELAY
= B
? 9 : 1;
2413 decode_UJUMP_0 (SIM_CPU
*cpu
, bu16 iw0
, bu32 pc
)
2416 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2417 | 0 | 0 | 1 | 0 |.offset........................................|
2418 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2419 int offset
= ((iw0
>> UJump_offset_bits
) & UJump_offset_mask
);
2420 int pcrel
= pcrel12 (offset
);
2421 bu32 newpc
= pc
+ pcrel
;
2423 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_UJUMP
);
2424 TRACE_EXTRACT (cpu
, "%s: offset:%#x", __func__
, offset
);
2425 TRACE_DECODE (cpu
, "%s: pcrel12:%#x", __func__
, pcrel
);
2427 TRACE_INSN (cpu
, "JUMP.S %#x;", pcrel
);
2430 illegal_instruction_combination (cpu
);
2432 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP.S");
2435 BFIN_CPU_STATE
.did_jump
= true;
2436 PROFILE_BRANCH_TAKEN (cpu
);
2441 decode_REGMV_0 (SIM_CPU
*cpu
, bu16 iw0
)
2444 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2445 | 0 | 0 | 1 | 1 |.gd........|.gs........|.dst.......|.src.......|
2446 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2447 int gs
= ((iw0
>> RegMv_gs_bits
) & RegMv_gs_mask
);
2448 int gd
= ((iw0
>> RegMv_gd_bits
) & RegMv_gd_mask
);
2449 int src
= ((iw0
>> RegMv_src_bits
) & RegMv_src_mask
);
2450 int dst
= ((iw0
>> RegMv_dst_bits
) & RegMv_dst_mask
);
2451 const char *srcreg_name
= get_allreg_name (gs
, src
);
2452 const char *dstreg_name
= get_allreg_name (gd
, dst
);
2454 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_REGMV
);
2455 TRACE_EXTRACT (cpu
, "%s: gd:%i gs:%i dst:%i src:%i",
2456 __func__
, gd
, gs
, dst
, src
);
2457 TRACE_DECODE (cpu
, "%s: dst:%s src:%s", __func__
, dstreg_name
, srcreg_name
);
2459 TRACE_INSN (cpu
, "%s = %s;", dstreg_name
, srcreg_name
);
2461 /* Reserved slots cannot be a src/dst. */
2462 if (reg_is_reserved (gs
, src
) || reg_is_reserved (gd
, dst
))
2465 /* Standard register moves. */
2466 if ((gs
< 2) /* Dregs/Pregs src */
2467 || (gd
< 2) /* Dregs/Pregs dst */
2468 || (gs
== 4 && src
< 4) /* Accumulators src */
2469 || (gd
== 4 && dst
< 4 && (gs
< 4)) /* Accumulators dst */
2470 || (gs
== 7 && src
== 7 && !(gd
== 4 && dst
< 4)) /* EMUDAT src */
2471 || (gd
== 7 && dst
== 7)) /* EMUDAT dst */
2474 /* dareg = dareg (IMBL) */
2475 if (gs
< 4 && gd
< 4)
2478 /* USP can be src to sysregs, but not dagregs. */
2479 if ((gs
== 7 && src
== 0) && (gd
>= 4))
2482 /* USP can move between genregs (only check Accumulators). */
2483 if (((gs
== 7 && src
== 0) && (gd
== 4 && dst
< 4))
2484 || ((gd
== 7 && dst
== 0) && (gs
== 4 && src
< 4)))
2487 /* Still here ? Invalid reg pair. */
2489 illegal_instruction (cpu
);
2492 reg_write (cpu
, gd
, dst
, reg_read (cpu
, gs
, src
));
2496 decode_ALU2op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2499 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2500 | 0 | 1 | 0 | 0 | 0 | 0 |.opc...........|.src.......|.dst.......|
2501 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2502 int src
= ((iw0
>> ALU2op_src_bits
) & ALU2op_src_mask
);
2503 int opc
= ((iw0
>> ALU2op_opc_bits
) & ALU2op_opc_mask
);
2504 int dst
= ((iw0
>> ALU2op_dst_bits
) & ALU2op_dst_mask
);
2506 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ALU2op
);
2507 TRACE_EXTRACT (cpu
, "%s: opc:%i src:%i dst:%i", __func__
, opc
, src
, dst
);
2511 TRACE_INSN (cpu
, "R%i >>>= R%i;", dst
, src
);
2512 SET_DREG (dst
, ashiftrt (cpu
, DREG (dst
), DREG (src
), 32));
2517 TRACE_INSN (cpu
, "R%i >>= R%i;", dst
, src
);
2518 if (DREG (src
) <= 0x1F)
2519 val
= lshiftrt (cpu
, DREG (dst
), DREG (src
), 32);
2522 SET_DREG (dst
, val
);
2526 TRACE_INSN (cpu
, "R%i <<= R%i;", dst
, src
);
2527 SET_DREG (dst
, lshift (cpu
, DREG (dst
), DREG (src
), 32, 0));
2531 TRACE_INSN (cpu
, "R%i *= R%i;", dst
, src
);
2532 SET_DREG (dst
, DREG (dst
) * DREG (src
));
2537 TRACE_INSN (cpu
, "R%i = (R%i + R%i) << 1;", dst
, dst
, src
);
2538 SET_DREG (dst
, add_and_shift (cpu
, DREG (dst
), DREG (src
), 1));
2542 TRACE_INSN (cpu
, "R%i = (R%i + R%i) << 2;", dst
, dst
, src
);
2543 SET_DREG (dst
, add_and_shift (cpu
, DREG (dst
), DREG (src
), 2));
2547 TRACE_INSN (cpu
, "DIVQ ( R%i, R%i );", dst
, src
);
2548 SET_DREG (dst
, divq (cpu
, DREG (dst
), (bu16
)DREG (src
)));
2552 TRACE_INSN (cpu
, "DIVS ( R%i, R%i );", dst
, src
);
2553 SET_DREG (dst
, divs (cpu
, DREG (dst
), (bu16
)DREG (src
)));
2557 TRACE_INSN (cpu
, "R%i = R%i.L (X);", dst
, src
);
2558 SET_DREG (dst
, (bs32
) (bs16
) DREG (src
));
2559 setflags_logical (cpu
, DREG (dst
));
2563 TRACE_INSN (cpu
, "R%i = R%i.L (Z);", dst
, src
);
2564 SET_DREG (dst
, (bu32
) (bu16
) DREG (src
));
2565 setflags_logical (cpu
, DREG (dst
));
2569 TRACE_INSN (cpu
, "R%i = R%i.B (X);", dst
, src
);
2570 SET_DREG (dst
, (bs32
) (bs8
) DREG (src
));
2571 setflags_logical (cpu
, DREG (dst
));
2575 TRACE_INSN (cpu
, "R%i = R%i.B (Z);", dst
, src
);
2576 SET_DREG (dst
, (bu32
) (bu8
) DREG (src
));
2577 setflags_logical (cpu
, DREG (dst
));
2581 bu32 val
= DREG (src
);
2582 TRACE_INSN (cpu
, "R%i = - R%i;", dst
, src
);
2583 SET_DREG (dst
, -val
);
2584 setflags_nz (cpu
, DREG (dst
));
2585 SET_ASTATREG (v
, val
== 0x80000000);
2587 SET_ASTATREG (vs
, 1);
2588 SET_ASTATREG (ac0
, val
== 0x0);
2589 /* XXX: Documentation isn't entirely clear about av0 and av1. */
2593 TRACE_INSN (cpu
, "R%i = ~ R%i;", dst
, src
);
2594 SET_DREG (dst
, ~DREG (src
));
2595 setflags_logical (cpu
, DREG (dst
));
2598 illegal_instruction (cpu
);
2602 decode_PTR2op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2605 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2606 | 0 | 1 | 0 | 0 | 0 | 1 | 0 |.opc.......|.src.......|.dst.......|
2607 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2608 int src
= ((iw0
>> PTR2op_src_bits
) & PTR2op_dst_mask
);
2609 int opc
= ((iw0
>> PTR2op_opc_bits
) & PTR2op_opc_mask
);
2610 int dst
= ((iw0
>> PTR2op_dst_bits
) & PTR2op_dst_mask
);
2611 const char *src_name
= get_preg_name (src
);
2612 const char *dst_name
= get_preg_name (dst
);
2614 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_PTR2op
);
2615 TRACE_EXTRACT (cpu
, "%s: opc:%i src:%i dst:%i", __func__
, opc
, src
, dst
);
2619 TRACE_INSN (cpu
, "%s -= %s", dst_name
, src_name
);
2620 SET_PREG (dst
, PREG (dst
) - PREG (src
));
2624 TRACE_INSN (cpu
, "%s = %s << 2", dst_name
, src_name
);
2625 SET_PREG (dst
, PREG (src
) << 2);
2629 TRACE_INSN (cpu
, "%s = %s >> 2", dst_name
, src_name
);
2630 SET_PREG (dst
, PREG (src
) >> 2);
2634 TRACE_INSN (cpu
, "%s = %s >> 1", dst_name
, src_name
);
2635 SET_PREG (dst
, PREG (src
) >> 1);
2639 TRACE_INSN (cpu
, "%s += %s (BREV)", dst_name
, src_name
);
2640 SET_PREG (dst
, add_brev (PREG (dst
), PREG (src
)));
2644 TRACE_INSN (cpu
, "%s = (%s + %s) << 1", dst_name
, dst_name
, src_name
);
2645 SET_PREG (dst
, (PREG (dst
) + PREG (src
)) << 1);
2649 TRACE_INSN (cpu
, "%s = (%s + %s) << 2", dst_name
, dst_name
, src_name
);
2650 SET_PREG (dst
, (PREG (dst
) + PREG (src
)) << 2);
2653 illegal_instruction (cpu
);
2657 decode_LOGI2op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2660 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2661 | 0 | 1 | 0 | 0 | 1 |.opc.......|.src...............|.dst.......|
2662 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2663 int src
= ((iw0
>> LOGI2op_src_bits
) & LOGI2op_src_mask
);
2664 int opc
= ((iw0
>> LOGI2op_opc_bits
) & LOGI2op_opc_mask
);
2665 int dst
= ((iw0
>> LOGI2op_dst_bits
) & LOGI2op_dst_mask
);
2666 int uimm
= uimm5 (src
);
2667 const char *uimm_str
= uimm5_str (uimm
);
2669 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LOGI2op
);
2670 TRACE_EXTRACT (cpu
, "%s: opc:%i src:%i dst:%i", __func__
, opc
, src
, dst
);
2671 TRACE_DECODE (cpu
, "%s: uimm5:%#x", __func__
, uimm
);
2675 TRACE_INSN (cpu
, "CC = ! BITTST (R%i, %s);", dst
, uimm_str
);
2677 illegal_instruction_combination (cpu
);
2678 SET_CCREG ((~DREG (dst
) >> uimm
) & 1);
2682 TRACE_INSN (cpu
, "CC = BITTST (R%i, %s);", dst
, uimm_str
);
2684 illegal_instruction_combination (cpu
);
2685 SET_CCREG ((DREG (dst
) >> uimm
) & 1);
2689 TRACE_INSN (cpu
, "BITSET (R%i, %s);", dst
, uimm_str
);
2691 illegal_instruction_combination (cpu
);
2692 SET_DREG (dst
, DREG (dst
) | (1 << uimm
));
2693 setflags_logical (cpu
, DREG (dst
));
2697 TRACE_INSN (cpu
, "BITTGL (R%i, %s);", dst
, uimm_str
);
2699 illegal_instruction_combination (cpu
);
2700 SET_DREG (dst
, DREG (dst
) ^ (1 << uimm
));
2701 setflags_logical (cpu
, DREG (dst
));
2705 TRACE_INSN (cpu
, "BITCLR (R%i, %s);", dst
, uimm_str
);
2707 illegal_instruction_combination (cpu
);
2708 SET_DREG (dst
, DREG (dst
) & ~(1 << uimm
));
2709 setflags_logical (cpu
, DREG (dst
));
2713 TRACE_INSN (cpu
, "R%i >>>= %s;", dst
, uimm_str
);
2715 illegal_instruction_combination (cpu
);
2716 SET_DREG (dst
, ashiftrt (cpu
, DREG (dst
), uimm
, 32));
2720 TRACE_INSN (cpu
, "R%i >>= %s;", dst
, uimm_str
);
2722 illegal_instruction_combination (cpu
);
2723 SET_DREG (dst
, lshiftrt (cpu
, DREG (dst
), uimm
, 32));
2727 TRACE_INSN (cpu
, "R%i <<= %s;", dst
, uimm_str
);
2729 illegal_instruction_combination (cpu
);
2730 SET_DREG (dst
, lshift (cpu
, DREG (dst
), uimm
, 32, 0));
2735 decode_COMP3op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2738 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2739 | 0 | 1 | 0 | 1 |.opc.......|.dst.......|.src1......|.src0......|
2740 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2741 int opc
= ((iw0
>> COMP3op_opc_bits
) & COMP3op_opc_mask
);
2742 int dst
= ((iw0
>> COMP3op_dst_bits
) & COMP3op_dst_mask
);
2743 int src0
= ((iw0
>> COMP3op_src0_bits
) & COMP3op_src0_mask
);
2744 int src1
= ((iw0
>> COMP3op_src1_bits
) & COMP3op_src1_mask
);
2746 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_COMP3op
);
2747 TRACE_EXTRACT (cpu
, "%s: opc:%i dst:%i src1:%i src0:%i",
2748 __func__
, opc
, dst
, src1
, src0
);
2752 TRACE_INSN (cpu
, "R%i = R%i + R%i;", dst
, src0
, src1
);
2753 SET_DREG (dst
, add32 (cpu
, DREG (src0
), DREG (src1
), 1, 0));
2757 TRACE_INSN (cpu
, "R%i = R%i - R%i;", dst
, src0
, src1
);
2758 SET_DREG (dst
, sub32 (cpu
, DREG (src0
), DREG (src1
), 1, 0, 0));
2762 TRACE_INSN (cpu
, "R%i = R%i & R%i;", dst
, src0
, src1
);
2763 SET_DREG (dst
, DREG (src0
) & DREG (src1
));
2764 setflags_logical (cpu
, DREG (dst
));
2768 TRACE_INSN (cpu
, "R%i = R%i | R%i;", dst
, src0
, src1
);
2769 SET_DREG (dst
, DREG (src0
) | DREG (src1
));
2770 setflags_logical (cpu
, DREG (dst
));
2774 TRACE_INSN (cpu
, "R%i = R%i ^ R%i;", dst
, src0
, src1
);
2775 SET_DREG (dst
, DREG (src0
) ^ DREG (src1
));
2776 setflags_logical (cpu
, DREG (dst
));
2780 int shift
= opc
- 5;
2781 const char *dst_name
= get_preg_name (dst
);
2782 const char *src0_name
= get_preg_name (src0
);
2783 const char *src1_name
= get_preg_name (src1
);
2785 /* If src0 == src1 this is disassembled as a shift by 1, but this
2786 distinction doesn't matter for our purposes. */
2788 TRACE_INSN (cpu
, "%s = (%s + %s) << %#x;",
2789 dst_name
, src0_name
, src1_name
, shift
);
2791 TRACE_INSN (cpu
, "%s = %s + %s",
2792 dst_name
, src0_name
, src1_name
);
2793 SET_PREG (dst
, PREG (src0
) + (PREG (src1
) << shift
));
2798 decode_COMPI2opD_0 (SIM_CPU
*cpu
, bu16 iw0
)
2801 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2802 | 0 | 1 | 1 | 0 | 0 |.op|..src......................|.dst.......|
2803 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2804 int op
= ((iw0
>> COMPI2opD_op_bits
) & COMPI2opD_op_mask
);
2805 int dst
= ((iw0
>> COMPI2opD_dst_bits
) & COMPI2opD_dst_mask
);
2806 int src
= ((iw0
>> COMPI2opD_src_bits
) & COMPI2opD_src_mask
);
2807 int imm
= imm7 (src
);
2809 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_COMPI2opD
);
2810 TRACE_EXTRACT (cpu
, "%s: op:%i src:%i dst:%i", __func__
, op
, src
, dst
);
2811 TRACE_DECODE (cpu
, "%s: imm7:%#x", __func__
, imm
);
2815 TRACE_INSN (cpu
, "R%i = %s (X);", dst
, imm7_str (imm
));
2816 SET_DREG (dst
, imm
);
2820 TRACE_INSN (cpu
, "R%i += %s;", dst
, imm7_str (imm
));
2821 SET_DREG (dst
, add32 (cpu
, DREG (dst
), imm
, 1, 0));
2826 decode_COMPI2opP_0 (SIM_CPU
*cpu
, bu16 iw0
)
2829 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2830 | 0 | 1 | 1 | 0 | 1 |.op|.src.......................|.dst.......|
2831 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2832 int op
= ((iw0
>> COMPI2opP_op_bits
) & COMPI2opP_op_mask
);
2833 int src
= ((iw0
>> COMPI2opP_src_bits
) & COMPI2opP_src_mask
);
2834 int dst
= ((iw0
>> COMPI2opP_dst_bits
) & COMPI2opP_dst_mask
);
2835 int imm
= imm7 (src
);
2836 const char *dst_name
= get_preg_name (dst
);
2838 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_COMPI2opP
);
2839 TRACE_EXTRACT (cpu
, "%s: op:%i src:%i dst:%i", __func__
, op
, src
, dst
);
2840 TRACE_DECODE (cpu
, "%s: imm:%#x", __func__
, imm
);
2844 TRACE_INSN (cpu
, "%s = %s;", dst_name
, imm7_str (imm
));
2845 SET_PREG (dst
, imm
);
2849 TRACE_INSN (cpu
, "%s += %s;", dst_name
, imm7_str (imm
));
2850 SET_PREG (dst
, PREG (dst
) + imm
);
2855 decode_LDSTpmod_0 (SIM_CPU
*cpu
, bu16 iw0
)
2858 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2859 | 1 | 0 | 0 | 0 |.W.|.aop...|.reg.......|.idx.......|.ptr.......|
2860 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2861 int W
= ((iw0
>> LDSTpmod_W_bits
) & LDSTpmod_W_mask
);
2862 int aop
= ((iw0
>> LDSTpmod_aop_bits
) & LDSTpmod_aop_mask
);
2863 int idx
= ((iw0
>> LDSTpmod_idx_bits
) & LDSTpmod_idx_mask
);
2864 int ptr
= ((iw0
>> LDSTpmod_ptr_bits
) & LDSTpmod_ptr_mask
);
2865 int reg
= ((iw0
>> LDSTpmod_reg_bits
) & LDSTpmod_reg_mask
);
2866 const char *ptr_name
= get_preg_name (ptr
);
2867 const char *idx_name
= get_preg_name (idx
);
2870 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTpmod
);
2871 TRACE_EXTRACT (cpu
, "%s: W:%i aop:%i reg:%i idx:%i ptr:%i",
2872 __func__
, W
, aop
, reg
, idx
, ptr
);
2874 if (aop
== 1 && W
== 0 && idx
== ptr
)
2876 TRACE_INSN (cpu
, "R%i.L = W[%s];", reg
, ptr_name
);
2878 val
= GET_WORD (addr
);
2879 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | val
);
2881 else if (aop
== 2 && W
== 0 && idx
== ptr
)
2883 TRACE_INSN (cpu
, "R%i.H = W[%s];", reg
, ptr_name
);
2885 val
= GET_WORD (addr
);
2886 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (val
<< 16));
2888 else if (aop
== 1 && W
== 1 && idx
== ptr
)
2890 TRACE_INSN (cpu
, "W[%s] = R%i.L;", ptr_name
, reg
);
2892 PUT_WORD (addr
, DREG (reg
));
2894 else if (aop
== 2 && W
== 1 && idx
== ptr
)
2896 TRACE_INSN (cpu
, "W[%s] = R%i.H;", ptr_name
, reg
);
2898 PUT_WORD (addr
, DREG (reg
) >> 16);
2900 else if (aop
== 0 && W
== 0)
2902 TRACE_INSN (cpu
, "R%i = [%s ++ %s];", reg
, ptr_name
, idx_name
);
2904 val
= GET_LONG (addr
);
2905 STORE (DREG (reg
), val
);
2907 STORE (PREG (ptr
), addr
+ PREG (idx
));
2909 else if (aop
== 1 && W
== 0)
2911 TRACE_INSN (cpu
, "R%i.L = W[%s ++ %s];", reg
, ptr_name
, idx_name
);
2913 val
= GET_WORD (addr
);
2914 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | val
);
2916 STORE (PREG (ptr
), addr
+ PREG (idx
));
2918 else if (aop
== 2 && W
== 0)
2920 TRACE_INSN (cpu
, "R%i.H = W[%s ++ %s];", reg
, ptr_name
, idx_name
);
2922 val
= GET_WORD (addr
);
2923 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (val
<< 16));
2925 STORE (PREG (ptr
), addr
+ PREG (idx
));
2927 else if (aop
== 3 && W
== 0)
2929 TRACE_INSN (cpu
, "R%i = W[%s ++ %s] (Z);", reg
, ptr_name
, idx_name
);
2931 val
= GET_WORD (addr
);
2932 STORE (DREG (reg
), val
);
2934 STORE (PREG (ptr
), addr
+ PREG (idx
));
2936 else if (aop
== 3 && W
== 1)
2938 TRACE_INSN (cpu
, "R%i = W[%s ++ %s] (X);", reg
, ptr_name
, idx_name
);
2940 val
= GET_WORD (addr
);
2941 STORE (DREG (reg
), (bs32
) (bs16
) val
);
2943 STORE (PREG (ptr
), addr
+ PREG (idx
));
2945 else if (aop
== 0 && W
== 1)
2947 TRACE_INSN (cpu
, "[%s ++ %s] = R%i;", ptr_name
, idx_name
, reg
);
2949 PUT_LONG (addr
, DREG (reg
));
2951 STORE (PREG (ptr
), addr
+ PREG (idx
));
2953 else if (aop
== 1 && W
== 1)
2955 TRACE_INSN (cpu
, "W[%s ++ %s] = R%i.L;", ptr_name
, idx_name
, reg
);
2957 PUT_WORD (addr
, DREG (reg
));
2959 STORE (PREG (ptr
), addr
+ PREG (idx
));
2961 else if (aop
== 2 && W
== 1)
2963 TRACE_INSN (cpu
, "W[%s ++ %s] = R%i.H;", ptr_name
, idx_name
, reg
);
2965 PUT_WORD (addr
, DREG (reg
) >> 16);
2967 STORE (PREG (ptr
), addr
+ PREG (idx
));
2970 illegal_instruction (cpu
);
2974 decode_dagMODim_0 (SIM_CPU
*cpu
, bu16 iw0
)
2977 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2978 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 0 |.br| 1 | 1 |.op|.m.....|.i.....|
2979 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2980 int i
= ((iw0
>> DagMODim_i_bits
) & DagMODim_i_mask
);
2981 int m
= ((iw0
>> DagMODim_m_bits
) & DagMODim_m_mask
);
2982 int br
= ((iw0
>> DagMODim_br_bits
) & DagMODim_br_mask
);
2983 int op
= ((iw0
>> DagMODim_op_bits
) & DagMODim_op_mask
);
2985 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dagMODim
);
2986 TRACE_EXTRACT (cpu
, "%s: br:%i op:%i m:%i i:%i", __func__
, br
, op
, m
, i
);
2988 if (op
== 0 && br
== 1)
2990 TRACE_INSN (cpu
, "I%i += M%i (BREV);", i
, m
);
2991 SET_IREG (i
, add_brev (IREG (i
), MREG (m
)));
2995 TRACE_INSN (cpu
, "I%i += M%i;", i
, m
);
2996 dagadd (cpu
, i
, MREG (m
));
2998 else if (op
== 1 && br
== 0)
3000 TRACE_INSN (cpu
, "I%i -= M%i;", i
, m
);
3001 dagsub (cpu
, i
, MREG (m
));
3004 illegal_instruction (cpu
);
3008 decode_dagMODik_0 (SIM_CPU
*cpu
, bu16 iw0
)
3011 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3012 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 0 |.op....|.i.....|
3013 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3014 int i
= ((iw0
>> DagMODik_i_bits
) & DagMODik_i_mask
);
3015 int op
= ((iw0
>> DagMODik_op_bits
) & DagMODik_op_mask
);
3017 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dagMODik
);
3018 TRACE_EXTRACT (cpu
, "%s: op:%i i:%i", __func__
, op
, i
);
3022 TRACE_INSN (cpu
, "I%i += 2;", i
);
3027 TRACE_INSN (cpu
, "I%i -= 2;", i
);
3032 TRACE_INSN (cpu
, "I%i += 4;", i
);
3037 TRACE_INSN (cpu
, "I%i -= 4;", i
);
3041 illegal_instruction (cpu
);
3045 decode_dspLDST_0 (SIM_CPU
*cpu
, bu16 iw0
)
3048 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3049 | 1 | 0 | 0 | 1 | 1 | 1 |.W.|.aop...|.m.....|.i.....|.reg.......|
3050 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3051 int i
= ((iw0
>> DspLDST_i_bits
) & DspLDST_i_mask
);
3052 int m
= ((iw0
>> DspLDST_m_bits
) & DspLDST_m_mask
);
3053 int W
= ((iw0
>> DspLDST_W_bits
) & DspLDST_W_mask
);
3054 int aop
= ((iw0
>> DspLDST_aop_bits
) & DspLDST_aop_mask
);
3055 int reg
= ((iw0
>> DspLDST_reg_bits
) & DspLDST_reg_mask
);
3058 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dspLDST
);
3059 TRACE_EXTRACT (cpu
, "%s: aop:%i m:%i i:%i reg:%i", __func__
, aop
, m
, i
, reg
);
3061 if (aop
== 0 && W
== 0 && m
== 0)
3063 TRACE_INSN (cpu
, "R%i = [I%i++];", reg
, i
);
3065 if (DIS_ALGN_EXPT
& 0x1)
3068 STORE (DREG (reg
), GET_LONG (addr
));
3070 else if (aop
== 0 && W
== 0 && m
== 1)
3072 TRACE_INSN (cpu
, "R%i.L = W[I%i++];", reg
, i
);
3075 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | GET_WORD (addr
));
3077 else if (aop
== 0 && W
== 0 && m
== 2)
3079 TRACE_INSN (cpu
, "R%i.H = W[I%i++];", reg
, i
);
3082 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (GET_WORD (addr
) << 16));
3084 else if (aop
== 1 && W
== 0 && m
== 0)
3086 TRACE_INSN (cpu
, "R%i = [I%i--];", reg
, i
);
3088 if (DIS_ALGN_EXPT
& 0x1)
3091 STORE (DREG (reg
), GET_LONG (addr
));
3093 else if (aop
== 1 && W
== 0 && m
== 1)
3095 TRACE_INSN (cpu
, "R%i.L = W[I%i--];", reg
, i
);
3098 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | GET_WORD (addr
));
3100 else if (aop
== 1 && W
== 0 && m
== 2)
3102 TRACE_INSN (cpu
, "R%i.H = W[I%i--];", reg
, i
);
3105 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (GET_WORD (addr
) << 16));
3107 else if (aop
== 2 && W
== 0 && m
== 0)
3109 TRACE_INSN (cpu
, "R%i = [I%i];", reg
, i
);
3111 if (DIS_ALGN_EXPT
& 0x1)
3113 STORE (DREG (reg
), GET_LONG (addr
));
3115 else if (aop
== 2 && W
== 0 && m
== 1)
3117 TRACE_INSN (cpu
, "R%i.L = W[I%i];", reg
, i
);
3119 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | GET_WORD (addr
));
3121 else if (aop
== 2 && W
== 0 && m
== 2)
3123 TRACE_INSN (cpu
, "R%i.H = W[I%i];", reg
, i
);
3125 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (GET_WORD (addr
) << 16));
3127 else if (aop
== 0 && W
== 1 && m
== 0)
3129 TRACE_INSN (cpu
, "[I%i++] = R%i;", i
, reg
);
3132 PUT_LONG (addr
, DREG (reg
));
3134 else if (aop
== 0 && W
== 1 && m
== 1)
3136 TRACE_INSN (cpu
, "W[I%i++] = R%i.L;", i
, reg
);
3139 PUT_WORD (addr
, DREG (reg
));
3141 else if (aop
== 0 && W
== 1 && m
== 2)
3143 TRACE_INSN (cpu
, "W[I%i++] = R%i.H;", i
, reg
);
3146 PUT_WORD (addr
, DREG (reg
) >> 16);
3148 else if (aop
== 1 && W
== 1 && m
== 0)
3150 TRACE_INSN (cpu
, "[I%i--] = R%i;", i
, reg
);
3153 PUT_LONG (addr
, DREG (reg
));
3155 else if (aop
== 1 && W
== 1 && m
== 1)
3157 TRACE_INSN (cpu
, "W[I%i--] = R%i.L;", i
, reg
);
3160 PUT_WORD (addr
, DREG (reg
));
3162 else if (aop
== 1 && W
== 1 && m
== 2)
3164 TRACE_INSN (cpu
, "W[I%i--] = R%i.H;", i
, reg
);
3167 PUT_WORD (addr
, DREG (reg
) >> 16);
3169 else if (aop
== 2 && W
== 1 && m
== 0)
3171 TRACE_INSN (cpu
, "[I%i] = R%i;", i
, reg
);
3173 PUT_LONG (addr
, DREG (reg
));
3175 else if (aop
== 2 && W
== 1 && m
== 1)
3177 TRACE_INSN (cpu
, "W[I%i] = R%i.L;", i
, reg
);
3179 PUT_WORD (addr
, DREG (reg
));
3181 else if (aop
== 2 && W
== 1 && m
== 2)
3183 TRACE_INSN (cpu
, "W[I%i] = R%i.H;", i
, reg
);
3185 PUT_WORD (addr
, DREG (reg
) >> 16);
3187 else if (aop
== 3 && W
== 0)
3189 TRACE_INSN (cpu
, "R%i = [I%i ++ M%i];", reg
, i
, m
);
3191 if (DIS_ALGN_EXPT
& 0x1)
3193 dagadd (cpu
, i
, MREG (m
));
3194 STORE (DREG (reg
), GET_LONG (addr
));
3196 else if (aop
== 3 && W
== 1)
3198 TRACE_INSN (cpu
, "[I%i ++ M%i] = R%i;", i
, m
, reg
);
3200 dagadd (cpu
, i
, MREG (m
));
3201 PUT_LONG (addr
, DREG (reg
));
3204 illegal_instruction (cpu
);
3208 decode_LDST_0 (SIM_CPU
*cpu
, bu16 iw0
)
3211 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3212 | 1 | 0 | 0 | 1 |.sz....|.W.|.aop...|.Z.|.ptr.......|.reg.......|
3213 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3214 int Z
= ((iw0
>> LDST_Z_bits
) & LDST_Z_mask
);
3215 int W
= ((iw0
>> LDST_W_bits
) & LDST_W_mask
);
3216 int sz
= ((iw0
>> LDST_sz_bits
) & LDST_sz_mask
);
3217 int aop
= ((iw0
>> LDST_aop_bits
) & LDST_aop_mask
);
3218 int reg
= ((iw0
>> LDST_reg_bits
) & LDST_reg_mask
);
3219 int ptr
= ((iw0
>> LDST_ptr_bits
) & LDST_ptr_mask
);
3220 const char * const posts
[] = { "++", "--", "" };
3221 const char *post
= posts
[aop
];
3222 const char *ptr_name
= get_preg_name (ptr
);
3224 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDST
);
3225 TRACE_EXTRACT (cpu
, "%s: sz:%i W:%i aop:%i Z:%i ptr:%i reg:%i",
3226 __func__
, sz
, W
, aop
, Z
, ptr
, reg
);
3229 illegal_instruction (cpu
);
3233 if (sz
== 0 && Z
== 0)
3235 TRACE_INSN (cpu
, "R%i = [%s%s];", reg
, ptr_name
, post
);
3236 SET_DREG (reg
, GET_LONG (PREG (ptr
)));
3238 else if (sz
== 0 && Z
== 1)
3240 TRACE_INSN (cpu
, "%s = [%s%s];", get_preg_name (reg
), ptr_name
, post
);
3241 if (aop
< 2 && ptr
== reg
)
3242 illegal_instruction_combination (cpu
);
3243 SET_PREG (reg
, GET_LONG (PREG (ptr
)));
3245 else if (sz
== 1 && Z
== 0)
3247 TRACE_INSN (cpu
, "R%i = W[%s%s] (Z);", reg
, ptr_name
, post
);
3248 SET_DREG (reg
, GET_WORD (PREG (ptr
)));
3250 else if (sz
== 1 && Z
== 1)
3252 TRACE_INSN (cpu
, "R%i = W[%s%s] (X);", reg
, ptr_name
, post
);
3253 SET_DREG (reg
, (bs32
) (bs16
) GET_WORD (PREG (ptr
)));
3255 else if (sz
== 2 && Z
== 0)
3257 TRACE_INSN (cpu
, "R%i = B[%s%s] (Z);", reg
, ptr_name
, post
);
3258 SET_DREG (reg
, GET_BYTE (PREG (ptr
)));
3260 else if (sz
== 2 && Z
== 1)
3262 TRACE_INSN (cpu
, "R%i = B[%s%s] (X);", reg
, ptr_name
, post
);
3263 SET_DREG (reg
, (bs32
) (bs8
) GET_BYTE (PREG (ptr
)));
3266 illegal_instruction (cpu
);
3270 if (sz
== 0 && Z
== 0)
3272 TRACE_INSN (cpu
, "[%s%s] = R%i;", ptr_name
, post
, reg
);
3273 PUT_LONG (PREG (ptr
), DREG (reg
));
3275 else if (sz
== 0 && Z
== 1)
3277 TRACE_INSN (cpu
, "[%s%s] = %s;", ptr_name
, post
, get_preg_name (reg
));
3278 PUT_LONG (PREG (ptr
), PREG (reg
));
3280 else if (sz
== 1 && Z
== 0)
3282 TRACE_INSN (cpu
, "W[%s%s] = R%i;", ptr_name
, post
, reg
);
3283 PUT_WORD (PREG (ptr
), DREG (reg
));
3285 else if (sz
== 2 && Z
== 0)
3287 TRACE_INSN (cpu
, "B[%s%s] = R%i;", ptr_name
, post
, reg
);
3288 PUT_BYTE (PREG (ptr
), DREG (reg
));
3291 illegal_instruction (cpu
);
3295 SET_PREG (ptr
, PREG (ptr
) + (1 << (2 - sz
)));
3297 SET_PREG (ptr
, PREG (ptr
) - (1 << (2 - sz
)));
3301 decode_LDSTiiFP_0 (SIM_CPU
*cpu
, bu16 iw0
)
3304 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3305 | 1 | 0 | 1 | 1 | 1 | 0 |.W.|.offset............|.reg...........|
3306 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3307 /* This isn't exactly a grp:reg as this insn only supports Dregs & Pregs,
3308 but for our usage, its functionality the same thing. */
3309 int grp
= ((iw0
>> 3) & 0x1);
3310 int reg
= ((iw0
>> LDSTiiFP_reg_bits
) & 0x7 /*LDSTiiFP_reg_mask*/);
3311 int offset
= ((iw0
>> LDSTiiFP_offset_bits
) & LDSTiiFP_offset_mask
);
3312 int W
= ((iw0
>> LDSTiiFP_W_bits
) & LDSTiiFP_W_mask
);
3313 bu32 imm
= negimm5s4 (offset
);
3314 bu32 ea
= FPREG
+ imm
;
3315 const char *imm_str
= negimm5s4_str (offset
);
3316 const char *reg_name
= get_allreg_name (grp
, reg
);
3318 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTiiFP
);
3319 TRACE_EXTRACT (cpu
, "%s: W:%i offset:%#x grp:%i reg:%i", __func__
,
3320 W
, offset
, grp
, reg
);
3321 TRACE_DECODE (cpu
, "%s: negimm5s4:%#x", __func__
, imm
);
3325 TRACE_INSN (cpu
, "%s = [FP + %s];", reg_name
, imm_str
);
3326 reg_write (cpu
, grp
, reg
, GET_LONG (ea
));
3330 TRACE_INSN (cpu
, "[FP + %s] = %s;", imm_str
, reg_name
);
3331 PUT_LONG (ea
, reg_read (cpu
, grp
, reg
));
3336 decode_LDSTii_0 (SIM_CPU
*cpu
, bu16 iw0
)
3339 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3340 | 1 | 0 | 1 |.W.|.op....|.offset........|.ptr.......|.reg.......|
3341 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3342 int reg
= ((iw0
>> LDSTii_reg_bit
) & LDSTii_reg_mask
);
3343 int ptr
= ((iw0
>> LDSTii_ptr_bit
) & LDSTii_ptr_mask
);
3344 int offset
= ((iw0
>> LDSTii_offset_bit
) & LDSTii_offset_mask
);
3345 int op
= ((iw0
>> LDSTii_op_bit
) & LDSTii_op_mask
);
3346 int W
= ((iw0
>> LDSTii_W_bit
) & LDSTii_W_mask
);
3348 const char *imm_str
;
3349 const char *ptr_name
= get_preg_name (ptr
);
3351 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTii
);
3352 TRACE_EXTRACT (cpu
, "%s: W:%i op:%i offset:%#x ptr:%i reg:%i",
3353 __func__
, W
, op
, offset
, ptr
, reg
);
3355 if (op
== 0 || op
== 3)
3356 imm
= uimm4s4 (offset
), imm_str
= uimm4s4_str (offset
);
3358 imm
= uimm4s2 (offset
), imm_str
= uimm4s2_str (offset
);
3359 ea
= PREG (ptr
) + imm
;
3361 TRACE_DECODE (cpu
, "%s: uimm4s4/uimm4s2:%#x", __func__
, imm
);
3363 if (W
== 1 && op
== 2)
3364 illegal_instruction (cpu
);
3370 TRACE_INSN (cpu
, "R%i = [%s + %s];", reg
, ptr_name
, imm_str
);
3371 SET_DREG (reg
, GET_LONG (ea
));
3375 TRACE_INSN (cpu
, "R%i = W[%s + %s] (Z);", reg
, ptr_name
, imm_str
);
3376 SET_DREG (reg
, GET_WORD (ea
));
3380 TRACE_INSN (cpu
, "R%i = W[%s + %s] (X);", reg
, ptr_name
, imm_str
);
3381 SET_DREG (reg
, (bs32
) (bs16
) GET_WORD (ea
));
3385 TRACE_INSN (cpu
, "%s = [%s + %s];",
3386 get_preg_name (reg
), ptr_name
, imm_str
);
3387 SET_PREG (reg
, GET_LONG (ea
));
3394 TRACE_INSN (cpu
, "[%s + %s] = R%i;", ptr_name
, imm_str
, reg
);
3395 PUT_LONG (ea
, DREG (reg
));
3399 TRACE_INSN (cpu
, "W[%s + %s] = R%i;", ptr_name
, imm_str
, reg
);
3400 PUT_WORD (ea
, DREG (reg
));
3404 TRACE_INSN (cpu
, "[%s + %s] = %s;",
3405 ptr_name
, imm_str
, get_preg_name (reg
));
3406 PUT_LONG (ea
, PREG (reg
));
3412 decode_LoopSetup_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
, bu32 pc
)
3415 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3416 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |.rop...|.c.|.soffset.......|
3417 |.reg...........| - | - |.eoffset...............................|
3418 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3419 int c
= ((iw0
>> (LoopSetup_c_bits
- 16)) & LoopSetup_c_mask
);
3420 int reg
= ((iw1
>> LoopSetup_reg_bits
) & LoopSetup_reg_mask
);
3421 int rop
= ((iw0
>> (LoopSetup_rop_bits
- 16)) & LoopSetup_rop_mask
);
3422 int soffset
= ((iw0
>> (LoopSetup_soffset_bits
- 16)) & LoopSetup_soffset_mask
);
3423 int eoffset
= ((iw1
>> LoopSetup_eoffset_bits
) & LoopSetup_eoffset_mask
);
3424 int spcrel
= pcrel4 (soffset
);
3425 int epcrel
= lppcrel10 (eoffset
);
3427 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LoopSetup
);
3428 TRACE_EXTRACT (cpu
, "%s: rop:%i c:%i soffset:%i reg:%i eoffset:%i",
3429 __func__
, rop
, c
, soffset
, reg
, eoffset
);
3430 TRACE_DECODE (cpu
, "%s: s_pcrel4:%#x e_lppcrel10:%#x",
3431 __func__
, spcrel
, epcrel
);
3434 illegal_instruction (cpu
);
3437 illegal_instruction_combination (cpu
);
3441 TRACE_INSN (cpu
, "LSETUP (%#x, %#x) LC%i;", spcrel
, epcrel
, c
);
3443 else if (rop
== 1 && reg
<= 7)
3445 TRACE_INSN (cpu
, "LSETUP (%#x, %#x) LC%i = %s;",
3446 spcrel
, epcrel
, c
, get_preg_name (reg
));
3447 SET_LCREG (c
, PREG (reg
));
3449 else if (rop
== 3 && reg
<= 7)
3451 TRACE_INSN (cpu
, "LSETUP (%#x, %#x) LC%i = %s >> 1;",
3452 spcrel
, epcrel
, c
, get_preg_name (reg
));
3453 SET_LCREG (c
, PREG (reg
) >> 1);
3456 illegal_instruction (cpu
);
3458 SET_LTREG (c
, pc
+ spcrel
);
3459 SET_LBREG (c
, pc
+ epcrel
);
3463 decode_LDIMMhalf_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3466 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3467 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 |.Z.|.H.|.S.|.grp...|.reg.......|
3468 |.hword.........................................................|
3469 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3470 int H
= ((iw0
>> (LDIMMhalf_H_bits
- 16)) & LDIMMhalf_H_mask
);
3471 int Z
= ((iw0
>> (LDIMMhalf_Z_bits
- 16)) & LDIMMhalf_Z_mask
);
3472 int S
= ((iw0
>> (LDIMMhalf_S_bits
- 16)) & LDIMMhalf_S_mask
);
3473 int reg
= ((iw0
>> (LDIMMhalf_reg_bits
- 16)) & LDIMMhalf_reg_mask
);
3474 int grp
= ((iw0
>> (LDIMMhalf_grp_bits
- 16)) & LDIMMhalf_grp_mask
);
3475 int hword
= ((iw1
>> LDIMMhalf_hword_bits
) & LDIMMhalf_hword_mask
);
3477 const char *val_str
;
3478 const char *reg_name
= get_allreg_name (grp
, reg
);
3480 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDIMMhalf
);
3481 TRACE_EXTRACT (cpu
, "%s: Z:%i H:%i S:%i grp:%i reg:%i hword:%#x",
3482 __func__
, Z
, H
, S
, grp
, reg
, hword
);
3485 illegal_instruction_combination (cpu
);
3488 val
= imm16 (hword
), val_str
= imm16_str (hword
);
3490 val
= luimm16 (hword
), val_str
= luimm16_str (hword
);
3492 if (H
== 0 && S
== 1 && Z
== 0)
3494 TRACE_INSN (cpu
, "%s = %s (X);", reg_name
, val_str
);
3496 else if (H
== 0 && S
== 0 && Z
== 1)
3498 TRACE_INSN (cpu
, "%s = %s (Z);", reg_name
, val_str
);
3500 else if (H
== 0 && S
== 0 && Z
== 0)
3502 TRACE_INSN (cpu
, "%s.L = %s;", reg_name
, val_str
);
3503 val
= REG_H_L (reg_read (cpu
, grp
, reg
), val
);
3505 else if (H
== 1 && S
== 0 && Z
== 0)
3507 TRACE_INSN (cpu
, "%s.H = %s;", reg_name
, val_str
);
3508 val
= REG_H_L (val
<< 16, reg_read (cpu
, grp
, reg
));
3511 illegal_instruction (cpu
);
3513 reg_write (cpu
, grp
, reg
, val
);
3517 decode_CALLa_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
, bu32 pc
)
3520 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3521 | 1 | 1 | 1 | 0 | 0 | 0 | 1 |.S.|.msw...........................|
3522 |.lsw...........................................................|
3523 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3524 int S
= ((iw0
>> (CALLa_S_bits
- 16)) & CALLa_S_mask
);
3525 int lsw
= ((iw1
>> 0) & 0xffff);
3526 int msw
= ((iw0
>> 0) & 0xff);
3527 int pcrel
= pcrel24 ((msw
<< 16) | lsw
);
3528 bu32 newpc
= pc
+ pcrel
;
3530 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CALLa
);
3531 TRACE_EXTRACT (cpu
, "%s: S:%i msw:%#x lsw:%#x", __func__
, S
, msw
, lsw
);
3532 TRACE_DECODE (cpu
, "%s: pcrel24:%#x", __func__
, pcrel
);
3534 TRACE_INSN (cpu
, "%s %#x;", S
? "CALL" : "JUMP.L", pcrel
);
3537 illegal_instruction_combination (cpu
);
3541 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "CALL");
3542 SET_RETSREG (hwloop_get_next_pc (cpu
, pc
, 4));
3545 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP.L");
3548 BFIN_CPU_STATE
.did_jump
= true;
3549 PROFILE_BRANCH_TAKEN (cpu
);
3554 decode_LDSTidxI_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3557 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3558 | 1 | 1 | 1 | 0 | 0 | 1 |.W.|.Z.|.sz....|.ptr.......|.reg.......|
3559 |.offset........................................................|
3560 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3561 int Z
= ((iw0
>> (LDSTidxI_Z_bits
- 16)) & LDSTidxI_Z_mask
);
3562 int W
= ((iw0
>> (LDSTidxI_W_bits
- 16)) & LDSTidxI_W_mask
);
3563 int sz
= ((iw0
>> (LDSTidxI_sz_bits
- 16)) & LDSTidxI_sz_mask
);
3564 int reg
= ((iw0
>> (LDSTidxI_reg_bits
- 16)) & LDSTidxI_reg_mask
);
3565 int ptr
= ((iw0
>> (LDSTidxI_ptr_bits
- 16)) & LDSTidxI_ptr_mask
);
3566 int offset
= ((iw1
>> LDSTidxI_offset_bits
) & LDSTidxI_offset_mask
);
3567 const char *ptr_name
= get_preg_name (ptr
);
3568 bu32 imm_16s4
= imm16s4 (offset
);
3569 bu32 imm_16s2
= imm16s2 (offset
);
3570 bu32 imm_16
= imm16 (offset
);
3572 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTidxI
);
3573 TRACE_EXTRACT (cpu
, "%s: W:%i Z:%i sz:%i ptr:%i reg:%i offset:%#x",
3574 __func__
, W
, Z
, sz
, ptr
, reg
, offset
);
3577 illegal_instruction (cpu
);
3581 if (sz
== 0 && Z
== 0)
3583 TRACE_INSN (cpu
, "R%i = [%s + %s];",
3584 reg
, ptr_name
, imm16s4_str (offset
));
3585 SET_DREG (reg
, GET_LONG (PREG (ptr
) + imm_16s4
));
3587 else if (sz
== 0 && Z
== 1)
3589 TRACE_INSN (cpu
, "%s = [%s + %s];",
3590 get_preg_name (reg
), ptr_name
, imm16s4_str (offset
));
3591 SET_PREG (reg
, GET_LONG (PREG (ptr
) + imm_16s4
));
3593 else if (sz
== 1 && Z
== 0)
3595 TRACE_INSN (cpu
, "R%i = W[%s + %s] (Z);",
3596 reg
, ptr_name
, imm16s2_str (offset
));
3597 SET_DREG (reg
, GET_WORD (PREG (ptr
) + imm_16s2
));
3599 else if (sz
== 1 && Z
== 1)
3601 TRACE_INSN (cpu
, "R%i = W[%s + %s] (X);",
3602 reg
, ptr_name
, imm16s2_str (offset
));
3603 SET_DREG (reg
, (bs32
) (bs16
) GET_WORD (PREG (ptr
) + imm_16s2
));
3605 else if (sz
== 2 && Z
== 0)
3607 TRACE_INSN (cpu
, "R%i = B[%s + %s] (Z);",
3608 reg
, ptr_name
, imm16_str (offset
));
3609 SET_DREG (reg
, GET_BYTE (PREG (ptr
) + imm_16
));
3611 else if (sz
== 2 && Z
== 1)
3613 TRACE_INSN (cpu
, "R%i = B[%s + %s] (X);",
3614 reg
, ptr_name
, imm16_str (offset
));
3615 SET_DREG (reg
, (bs32
) (bs8
) GET_BYTE (PREG (ptr
) + imm_16
));
3620 if (sz
!= 0 && Z
!= 0)
3621 illegal_instruction (cpu
);
3623 if (sz
== 0 && Z
== 0)
3625 TRACE_INSN (cpu
, "[%s + %s] = R%i;", ptr_name
,
3626 imm16s4_str (offset
), reg
);
3627 PUT_LONG (PREG (ptr
) + imm_16s4
, DREG (reg
));
3629 else if (sz
== 0 && Z
== 1)
3631 TRACE_INSN (cpu
, "[%s + %s] = %s;",
3632 ptr_name
, imm16s4_str (offset
), get_preg_name (reg
));
3633 PUT_LONG (PREG (ptr
) + imm_16s4
, PREG (reg
));
3635 else if (sz
== 1 && Z
== 0)
3637 TRACE_INSN (cpu
, "W[%s + %s] = R%i;",
3638 ptr_name
, imm16s2_str (offset
), reg
);
3639 PUT_WORD (PREG (ptr
) + imm_16s2
, DREG (reg
));
3641 else if (sz
== 2 && Z
== 0)
3643 TRACE_INSN (cpu
, "B[%s + %s] = R%i;",
3644 ptr_name
, imm16_str (offset
), reg
);
3645 PUT_BYTE (PREG (ptr
) + imm_16
, DREG (reg
));
3651 decode_linkage_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3654 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3655 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |.R.|
3656 |.framesize.....................................................|
3657 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3658 int R
= ((iw0
>> (Linkage_R_bits
- 16)) & Linkage_R_mask
);
3659 int framesize
= ((iw1
>> Linkage_framesize_bits
) & Linkage_framesize_mask
);
3662 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_linkage
);
3663 TRACE_EXTRACT (cpu
, "%s: R:%i framesize:%#x", __func__
, R
, framesize
);
3667 int size
= uimm16s4 (framesize
);
3669 TRACE_INSN (cpu
, "LINK %s;", uimm16s4_str (framesize
));
3671 illegal_instruction_combination (cpu
);
3673 PUT_LONG (sp
, RETSREG
);
3675 PUT_LONG (sp
, FPREG
);
3682 /* Restore SP from FP. */
3684 TRACE_INSN (cpu
, "UNLINK;");
3686 illegal_instruction_combination (cpu
);
3687 SET_FPREG (GET_LONG (sp
));
3689 SET_RETSREG (GET_LONG (sp
));
3698 decode_dsp32mac_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3701 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3702 | 1 | 1 | 0 | 0 |.M.| 0 | 0 |.mmod..........|.MM|.P.|.w1|.op1...|
3703 |.h01|.h11|.w0|.op0...|.h00|.h10|.dst.......|.src0......|.src1..|
3704 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3705 int op1
= ((iw0
>> (DSP32Mac_op1_bits
- 16)) & DSP32Mac_op1_mask
);
3706 int w1
= ((iw0
>> (DSP32Mac_w1_bits
- 16)) & DSP32Mac_w1_mask
);
3707 int P
= ((iw0
>> (DSP32Mac_p_bits
- 16)) & DSP32Mac_p_mask
);
3708 int MM
= ((iw0
>> (DSP32Mac_MM_bits
- 16)) & DSP32Mac_MM_mask
);
3709 int mmod
= ((iw0
>> (DSP32Mac_mmod_bits
- 16)) & DSP32Mac_mmod_mask
);
3710 int M
= ((iw0
>> (DSP32Mac_M_bits
- 16)) & DSP32Mac_M_mask
);
3711 int w0
= ((iw1
>> DSP32Mac_w0_bits
) & DSP32Mac_w0_mask
);
3712 int src0
= ((iw1
>> DSP32Mac_src0_bits
) & DSP32Mac_src0_mask
);
3713 int src1
= ((iw1
>> DSP32Mac_src1_bits
) & DSP32Mac_src1_mask
);
3714 int dst
= ((iw1
>> DSP32Mac_dst_bits
) & DSP32Mac_dst_mask
);
3715 int h10
= ((iw1
>> DSP32Mac_h10_bits
) & DSP32Mac_h10_mask
);
3716 int h00
= ((iw1
>> DSP32Mac_h00_bits
) & DSP32Mac_h00_mask
);
3717 int op0
= ((iw1
>> DSP32Mac_op0_bits
) & DSP32Mac_op0_mask
);
3718 int h11
= ((iw1
>> DSP32Mac_h11_bits
) & DSP32Mac_h11_mask
);
3719 int h01
= ((iw1
>> DSP32Mac_h01_bits
) & DSP32Mac_h01_mask
);
3721 bu32 res
= DREG (dst
);
3722 bu32 v_i
= 0, zero
= 0, n_1
= 0, n_0
= 0;
3724 static const char * const ops
[] = { "=", "+=", "-=" };
3725 char _buf
[128], *buf
= _buf
;
3728 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32mac
);
3729 TRACE_EXTRACT (cpu
, "%s: M:%i mmod:%i MM:%i P:%i w1:%i op1:%i h01:%i h11:%i "
3730 "w0:%i op0:%i h00:%i h10:%i dst:%i src0:%i src1:%i",
3731 __func__
, M
, mmod
, MM
, P
, w1
, op1
, h01
, h11
, w0
, op0
, h00
, h10
,
3734 if (w0
== 0 && w1
== 0 && op1
== 3 && op0
== 3)
3735 illegal_instruction (cpu
);
3737 if ((w1
|| w0
) && mmod
== M_W32
)
3738 illegal_instruction (cpu
);
3740 if (((1 << mmod
) & (P
? 0x131b : 0x1b5f)) == 0)
3741 illegal_instruction (cpu
);
3743 /* First handle MAC1 side. */
3744 if (w1
== 1 || op1
!= 3)
3746 bu32 res1
= decode_macfunc (cpu
, 1, op1
, h01
, h11
, src0
,
3747 src1
, mmod
, MM
, P
, &v_i
, &n_1
);
3750 buf
+= sprintf (buf
, P
? "R%i" : "R%i.H", dst
+ P
);
3754 buf
+= sprintf (buf
, " = A1");
3755 zero
= !!(res1
== 0);
3760 buf
+= sprintf (buf
, " = (");
3761 buf
+= sprintf (buf
, "A1 %s R%i.%c * R%i.%c", ops
[op1
],
3762 src0
, h01
? 'H' : 'L',
3763 src1
, h11
? 'H' : 'L');
3765 buf
+= sprintf (buf
, ")");
3771 STORE (DREG (dst
+ 1), res1
);
3774 if (res1
& 0xffff0000)
3775 illegal_instruction (cpu
);
3776 res
= REG_H_L (res1
<< 16, res
);
3780 if (w0
== 1 || op0
!= 3)
3783 buf
+= sprintf (buf
, " (M)");
3785 buf
+= sprintf (buf
, ", ");
3789 /* Then handle MAC0 side. */
3790 if (w0
== 1 || op0
!= 3)
3792 bu32 res0
= decode_macfunc (cpu
, 0, op0
, h00
, h10
, src0
,
3793 src1
, mmod
, 0, P
, &v_i
, &n_0
);
3796 buf
+= sprintf (buf
, P
? "R%i" : "R%i.L", dst
);
3800 buf
+= sprintf (buf
, " = A0");
3801 zero
|= !!(res0
== 0);
3806 buf
+= sprintf (buf
, " = (");
3807 buf
+= sprintf (buf
, "A0 %s R%i.%c * R%i.%c", ops
[op0
],
3808 src0
, h00
? 'H' : 'L',
3809 src1
, h10
? 'H' : 'L');
3811 buf
+= sprintf (buf
, ")");
3817 STORE (DREG (dst
), res0
);
3820 if (res0
& 0xffff0000)
3821 illegal_instruction (cpu
);
3822 res
= REG_H_L (res
, res0
);
3827 TRACE_INSN (cpu
, "%s%s;", _buf
, mac_optmode (mmod
, _MM
));
3829 if (!P
&& (w0
|| w1
))
3831 STORE (DREG (dst
), res
);
3832 SET_ASTATREG (v
, v_i
);
3834 SET_ASTATREG (vs
, v_i
);
3838 SET_ASTATREG (v
, v_i
);
3840 SET_ASTATREG (vs
, v_i
);
3843 if ((w0
== 1 && op0
== 3) || (w1
== 1 && op1
== 3))
3845 SET_ASTATREG (az
, zero
);
3846 if (!(w0
== 1 && op0
== 3))
3848 if (!(w1
== 1 && op1
== 3))
3850 SET_ASTATREG (an
, n_1
| n_0
);
3855 decode_dsp32mult_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3858 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3859 | 1 | 1 | 0 | 0 |.M.| 0 | 1 |.mmod..........|.MM|.P.|.w1|.op1...|
3860 |.h01|.h11|.w0|.op0...|.h00|.h10|.dst.......|.src0......|.src1..|
3861 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3862 int op1
= ((iw0
>> (DSP32Mac_op1_bits
- 16)) & DSP32Mac_op1_mask
);
3863 int w1
= ((iw0
>> (DSP32Mac_w1_bits
- 16)) & DSP32Mac_w1_mask
);
3864 int P
= ((iw0
>> (DSP32Mac_p_bits
- 16)) & DSP32Mac_p_mask
);
3865 int MM
= ((iw0
>> (DSP32Mac_MM_bits
- 16)) & DSP32Mac_MM_mask
);
3866 int mmod
= ((iw0
>> (DSP32Mac_mmod_bits
- 16)) & DSP32Mac_mmod_mask
);
3867 int M
= ((iw0
>> (DSP32Mac_M_bits
- 16)) & DSP32Mac_M_mask
);
3868 int w0
= ((iw1
>> DSP32Mac_w0_bits
) & DSP32Mac_w0_mask
);
3869 int src0
= ((iw1
>> DSP32Mac_src0_bits
) & DSP32Mac_src0_mask
);
3870 int src1
= ((iw1
>> DSP32Mac_src1_bits
) & DSP32Mac_src1_mask
);
3871 int dst
= ((iw1
>> DSP32Mac_dst_bits
) & DSP32Mac_dst_mask
);
3872 int h10
= ((iw1
>> DSP32Mac_h10_bits
) & DSP32Mac_h10_mask
);
3873 int h00
= ((iw1
>> DSP32Mac_h00_bits
) & DSP32Mac_h00_mask
);
3874 int op0
= ((iw1
>> DSP32Mac_op0_bits
) & DSP32Mac_op0_mask
);
3875 int h11
= ((iw1
>> DSP32Mac_h11_bits
) & DSP32Mac_h11_mask
);
3876 int h01
= ((iw1
>> DSP32Mac_h01_bits
) & DSP32Mac_h01_mask
);
3878 bu32 res
= DREG (dst
);
3879 bu32 sat0
= 0, sat1
= 0, v_i0
= 0, v_i1
= 0;
3880 char _buf
[128], *buf
= _buf
;
3883 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32mult
);
3884 TRACE_EXTRACT (cpu
, "%s: M:%i mmod:%i MM:%i P:%i w1:%i op1:%i h01:%i h11:%i "
3885 "w0:%i op0:%i h00:%i h10:%i dst:%i src0:%i src1:%i",
3886 __func__
, M
, mmod
, MM
, P
, w1
, op1
, h01
, h11
, w0
, op0
, h00
, h10
,
3889 if (w1
== 0 && w0
== 0)
3890 illegal_instruction (cpu
);
3891 if (((1 << mmod
) & (P
? 0x313 : 0x1b57)) == 0)
3892 illegal_instruction (cpu
);
3893 if (P
&& ((dst
& 1) || (op1
!= 0) || (op0
!= 0) || !is_macmod_pmove (mmod
)))
3894 illegal_instruction (cpu
);
3895 if (!P
&& ((op1
!= 0) || (op0
!= 0) || !is_macmod_hmove (mmod
)))
3896 illegal_instruction (cpu
);
3898 /* First handle MAC1 side. */
3901 bu64 r
= decode_multfunc (cpu
, h01
, h11
, src0
, src1
, mmod
, MM
, &sat1
);
3902 bu32 res1
= extract_mult (cpu
, r
, mmod
, MM
, P
, &v_i1
);
3904 buf
+= sprintf (buf
, P
? "R%i" : "R%i.H", dst
+ P
);
3905 buf
+= sprintf (buf
, " = R%i.%c * R%i.%c",
3906 src0
, h01
? 'H' : 'L',
3907 src1
, h11
? 'H' : 'L');
3911 buf
+= sprintf (buf
, " (M)");
3913 buf
+= sprintf (buf
, ", ");
3917 STORE (DREG (dst
+ 1), res1
);
3920 if (res1
& 0xFFFF0000)
3921 illegal_instruction (cpu
);
3922 res
= REG_H_L (res1
<< 16, res
);
3926 /* First handle MAC0 side. */
3929 bu64 r
= decode_multfunc (cpu
, h00
, h10
, src0
, src1
, mmod
, 0, &sat0
);
3930 bu32 res0
= extract_mult (cpu
, r
, mmod
, 0, P
, &v_i0
);
3932 buf
+= sprintf (buf
, P
? "R%i" : "R%i.L", dst
);
3933 buf
+= sprintf (buf
, " = R%i.%c * R%i.%c",
3934 src0
, h01
? 'H' : 'L',
3935 src1
, h11
? 'H' : 'L');
3938 STORE (DREG (dst
), res0
);
3941 if (res0
& 0xFFFF0000)
3942 illegal_instruction (cpu
);
3943 res
= REG_H_L (res
, res0
);
3947 TRACE_INSN (cpu
, "%s%s;", _buf
, mac_optmode (mmod
, _MM
));
3949 if (!P
&& (w0
|| w1
))
3950 STORE (DREG (dst
), res
);
3954 bu32 v
= sat0
| sat1
| v_i0
| v_i1
;
3956 STORE (ASTATREG (v
), v
);
3957 STORE (ASTATREG (v_copy
), v
);
3959 STORE (ASTATREG (vs
), v
);
3964 decode_dsp32alu_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3967 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3968 | 1 | 1 | 0 | 0 |.M.| 1 | 0 | - | - | - |.HL|.aopcde............|
3969 |.aop...|.s.|.x.|.dst0......|.dst1......|.src0......|.src1......|
3970 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3971 int s
= ((iw1
>> DSP32Alu_s_bits
) & DSP32Alu_s_mask
);
3972 int x
= ((iw1
>> DSP32Alu_x_bits
) & DSP32Alu_x_mask
);
3973 int aop
= ((iw1
>> DSP32Alu_aop_bits
) & DSP32Alu_aop_mask
);
3974 int src0
= ((iw1
>> DSP32Alu_src0_bits
) & DSP32Alu_src0_mask
);
3975 int src1
= ((iw1
>> DSP32Alu_src1_bits
) & DSP32Alu_src1_mask
);
3976 int dst0
= ((iw1
>> DSP32Alu_dst0_bits
) & DSP32Alu_dst0_mask
);
3977 int dst1
= ((iw1
>> DSP32Alu_dst1_bits
) & DSP32Alu_dst1_mask
);
3978 int M
= ((iw0
>> (DSP32Alu_M_bits
- 16)) & DSP32Alu_M_mask
);
3979 int HL
= ((iw0
>> (DSP32Alu_HL_bits
- 16)) & DSP32Alu_HL_mask
);
3980 int aopcde
= ((iw0
>> (DSP32Alu_aopcde_bits
- 16)) & DSP32Alu_aopcde_mask
);
3982 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32alu
);
3983 TRACE_EXTRACT (cpu
, "%s: M:%i HL:%i aopcde:%i aop:%i s:%i x:%i dst0:%i "
3984 "dst1:%i src0:%i src1:%i",
3985 __func__
, M
, HL
, aopcde
, aop
, s
, x
, dst0
, dst1
, src0
, src1
);
3987 if ((aop
== 0 || aop
== 2) && aopcde
== 9 && HL
== 0 && s
== 0)
3990 TRACE_INSN (cpu
, "A%i.L = R%i.L;", a
, src0
);
3991 SET_AWREG (a
, REG_H_L (AWREG (a
), DREG (src0
)));
3993 else if ((aop
== 0 || aop
== 2) && aopcde
== 9 && HL
== 1 && s
== 0)
3996 TRACE_INSN (cpu
, "A%i.H = R%i.H;", a
, src0
);
3997 SET_AWREG (a
, REG_H_L (DREG (src0
), AWREG (a
)));
3999 else if ((aop
== 1 || aop
== 0) && aopcde
== 5)
4001 bs32 val0
= DREG (src0
);
4002 bs32 val1
= DREG (src1
);
4005 bs32 ovX
, sBit1
, sBit2
, sBitRes1
, sBitRes2
;
4007 TRACE_INSN (cpu
, "R%i.%s = R%i %s R%i (RND12)", dst0
, HL
? "L" : "H",
4008 src0
, aop
& 0x1 ? "-" : "+", src1
);
4010 /* If subtract, just invert and add one. */
4013 if (val1
== 0x80000000)
4019 /* Get the sign bits, since we need them later. */
4020 sBit1
= !!(val0
& 0x80000000);
4021 sBit2
= !!(val1
& 0x80000000);
4025 sBitRes1
= !!(res
& 0x80000000);
4026 /* Round to the 12th bit. */
4028 sBitRes2
= !!(res
& 0x80000000);
4036 positive_res + positive_round = neg
4037 Shift and upper 4 bits where not the same. */
4038 if ((!(sBit1
^ sBit2
) && (sBit1
^ sBitRes1
))
4039 || (!sBit1
&& !sBit2
&& sBitRes2
)
4040 || ((signRes
!= 0) && (signRes
!= -1)))
4042 /* Both X1 and X2 Neg res is neg overflow. */
4045 /* Both X1 and X2 Pos res is pos overflow. */
4046 else if (!sBit1
&& !sBit2
)
4048 /* Pos+Neg or Neg+Pos take the sign of the result. */
4058 /* Shift up now after overflow detection. */
4066 STORE (DREG (dst0
), REG_H_L (res
<< 16, DREG (dst0
)));
4068 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), res
));
4070 SET_ASTATREG (az
, res
== 0);
4071 SET_ASTATREG (an
, res
& 0x8000);
4072 SET_ASTATREG (v
, ovX
);
4074 SET_ASTATREG (vs
, ovX
);
4076 else if ((aop
== 2 || aop
== 3) && aopcde
== 5)
4078 bs32 val0
= DREG (src0
);
4079 bs32 val1
= DREG (src1
);
4082 TRACE_INSN (cpu
, "R%i.%s = R%i %s R%i (RND20)", dst0
, HL
? "L" : "H",
4083 src0
, aop
& 0x1 ? "-" : "+", src1
);
4085 /* If subtract, just invert and add one. */
4089 res
= (val0
>> 4) + (val1
>> 4) + (((val0
& 0xf) + (val1
& 0xf)) >> 4);
4091 /* Don't sign extend during the shift. */
4092 res
= ((bu32
)res
>> 16);
4094 /* Don't worry about overflows, since we are shifting right. */
4097 STORE (DREG (dst0
), REG_H_L (res
<< 16, DREG (dst0
)));
4099 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), res
));
4101 SET_ASTATREG (az
, res
== 0);
4102 SET_ASTATREG (an
, res
& 0x8000);
4103 SET_ASTATREG (v
, 0);
4105 else if (aopcde
== 2 || aopcde
== 3)
4107 bu32 s1
, s2
, val
, ac0_i
= 0, v_i
= 0;
4109 TRACE_INSN (cpu
, "R%i.%c = R%i.%c %c R%i.%c%s;",
4110 dst0
, HL
? 'H' : 'L',
4111 src0
, aop
& 2 ? 'H' : 'L',
4112 aopcde
== 2 ? '+' : '-',
4113 src1
, aop
& 1 ? 'H' : 'L',
4124 val
= add16 (cpu
, s1
, s2
, &ac0_i
, &v_i
, 0, 0, s
, 0);
4126 val
= sub16 (cpu
, s1
, s2
, &ac0_i
, &v_i
, 0, 0, s
, 0);
4128 SET_ASTATREG (ac0
, ac0_i
);
4129 SET_ASTATREG (v
, v_i
);
4131 SET_ASTATREG (vs
, v_i
);
4134 SET_DREG_H (dst0
, val
<< 16);
4136 SET_DREG_L (dst0
, val
);
4138 SET_ASTATREG (an
, val
& 0x8000);
4139 SET_ASTATREG (az
, val
== 0);
4141 else if ((aop
== 0 || aop
== 2) && aopcde
== 9 && s
== 1)
4144 TRACE_INSN (cpu
, "A%i = R%i;", a
, src0
);
4145 SET_AREG32 (a
, DREG (src0
));
4147 else if ((aop
== 1 || aop
== 3) && aopcde
== 9 && s
== 0)
4150 TRACE_INSN (cpu
, "A%i.X = R%i.L;", a
, src0
);
4151 SET_AXREG (a
, (bs8
)DREG (src0
));
4153 else if (aop
== 3 && aopcde
== 11 && (s
== 0 || s
== 1))
4155 bu64 acc0
= get_extended_acc (cpu
, 0);
4156 bu64 acc1
= get_extended_acc (cpu
, 1);
4157 bu32 carry
= (bu40
)acc1
< (bu40
)acc0
;
4160 TRACE_INSN (cpu
, "A0 -= A1%s;", s
? " (W32)" : "");
4163 if ((bs64
)acc0
< -0x8000000000ll
)
4164 acc0
= -0x8000000000ull
, sat
= 1;
4165 else if ((bs64
)acc0
>= 0x7fffffffffll
)
4166 acc0
= 0x7fffffffffull
, sat
= 1;
4170 /* A0 -= A1 (W32) */
4171 if (acc0
& (bu64
)0x8000000000ll
)
4172 acc0
&= 0x80ffffffffll
, sat
= 1;
4174 acc0
&= 0xffffffffll
;
4176 STORE (AXREG (0), (acc0
>> 32) & 0xff);
4177 STORE (AWREG (0), acc0
& 0xffffffff);
4178 STORE (ASTATREG (az
), acc0
== 0);
4179 STORE (ASTATREG (an
), !!(acc0
& (bu64
)0x8000000000ll
));
4180 STORE (ASTATREG (ac0
), carry
);
4181 STORE (ASTATREG (ac0_copy
), carry
);
4182 STORE (ASTATREG (av0
), sat
);
4184 STORE (ASTATREG (av0s
), sat
);
4186 else if ((aop
== 0 || aop
== 1) && aopcde
== 22)
4188 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4190 const char * const opts
[] = { "rndl", "rndh", "tl", "th" };
4192 TRACE_INSN (cpu
, "R%i = BYTEOP2P (R%i:%i, R%i:%i) (%s%s);", dst0
,
4193 src0
+ 1, src0
, src1
+ 1, src1
, opts
[HL
+ (aop
<< 1)],
4197 s0H
= DREG (src0
+ 1);
4199 s1H
= DREG (src1
+ 1);
4202 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4203 s1
= algn (s1H
, s1L
, IREG (0) & 3);
4207 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4208 s1
= algn (s1L
, s1H
, IREG (0) & 3);
4212 tmp0
= ((((s1
>> 8) & 0xff) + ((s1
>> 0) & 0xff) +
4213 ((s0
>> 8) & 0xff) + ((s0
>> 0) & 0xff) + i
) >> 2) & 0xff;
4214 tmp1
= ((((s1
>> 24) & 0xff) + ((s1
>> 16) & 0xff) +
4215 ((s0
>> 24) & 0xff) + ((s0
>> 16) & 0xff) + i
) >> 2) & 0xff;
4216 STORE (DREG (dst0
), (tmp1
<< (16 + (HL
* 8))) | (tmp0
<< (HL
* 8)));
4218 /* Implicit DISALGNEXCPT in parallel. */
4221 else if ((aop
== 0 || aop
== 1) && s
== 0 && aopcde
== 8)
4223 TRACE_INSN (cpu
, "A%i = 0;", aop
);
4226 else if (aop
== 2 && s
== 0 && aopcde
== 8)
4228 TRACE_INSN (cpu
, "A1 = A0 = 0;");
4232 else if ((aop
== 0 || aop
== 1 || aop
== 2) && s
== 1 && aopcde
== 8)
4234 bs40 acc0
= get_extended_acc (cpu
, 0);
4235 bs40 acc1
= get_extended_acc (cpu
, 1);
4238 if (aop
== 0 || aop
== 1)
4239 TRACE_INSN (cpu
, "A%i = A%i (S);", aop
, aop
);
4241 TRACE_INSN (cpu
, "A1 = A1 (S), A0 = A0 (S);");
4243 if (aop
== 0 || aop
== 2)
4246 acc0
= saturate_s32 (acc0
, &sat
);
4247 acc0
|= -(acc0
& 0x80000000ull
);
4248 SET_AXREG (0, (acc0
>> 31) & 0xFF);
4249 SET_AWREG (0, acc0
& 0xFFFFFFFF);
4250 SET_ASTATREG (av0
, sat
);
4252 SET_ASTATREG (av0s
, sat
);
4257 if (aop
== 1 || aop
== 2)
4260 acc1
= saturate_s32 (acc1
, &sat
);
4261 acc1
|= -(acc1
& 0x80000000ull
);
4262 SET_AXREG (1, (acc1
>> 31) & 0xFF);
4263 SET_AWREG (1, acc1
& 0xFFFFFFFF);
4264 SET_ASTATREG (av1
, sat
);
4266 SET_ASTATREG (av1s
, sat
);
4271 SET_ASTATREG (az
, (acc0
== 0) || (acc1
== 0));
4272 SET_ASTATREG (an
, ((acc0
>> 31) & 1) || ((acc1
>> 31) & 1));
4274 else if (aop
== 3 && (s
== 0 || s
== 1) && aopcde
== 8)
4276 TRACE_INSN (cpu
, "A%i = A%i;", s
, !s
);
4277 SET_AXREG (s
, AXREG (!s
));
4278 SET_AWREG (s
, AWREG (!s
));
4280 else if (aop
== 3 && HL
== 0 && aopcde
== 16)
4285 TRACE_INSN (cpu
, "A1 = ABS A1 , A0 = ABS A0;");
4288 for (i
= 0; i
< 2; ++i
)
4291 bs40 acc
= get_extended_acc (cpu
, i
);
4295 av
= acc
== ((bs40
)1 << 39);
4297 acc
= ((bs40
)1 << 39) - 1;
4300 SET_ASTATREG (av
[i
], av
);
4302 SET_ASTATREG (avs
[i
], av
);
4305 SET_ASTATREG (az
, az
);
4306 SET_ASTATREG (an
, 0);
4308 else if (aop
== 0 && aopcde
== 23)
4310 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4313 TRACE_INSN (cpu
, "R%i = BYTEOP3P (R%i:%i, R%i:%i) (%s%s);", dst0
,
4314 src0
+ 1, src0
, src1
+ 1, src1
, HL
? "HI" : "LO",
4318 s0H
= DREG (src0
+ 1);
4320 s1H
= DREG (src1
+ 1);
4323 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4324 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4328 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4329 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4332 tmp0
= (bs32
)(bs16
)(s0
>> 0) + ((s1
>> ( 0 + (8 * !HL
))) & 0xff);
4333 tmp1
= (bs32
)(bs16
)(s0
>> 16) + ((s1
>> (16 + (8 * !HL
))) & 0xff);
4334 STORE (DREG (dst0
), (CLAMP (tmp0
, 0, 255) << ( 0 + (8 * HL
))) |
4335 (CLAMP (tmp1
, 0, 255) << (16 + (8 * HL
))));
4337 /* Implicit DISALGNEXCPT in parallel. */
4340 else if ((aop
== 0 || aop
== 1) && aopcde
== 16)
4345 TRACE_INSN (cpu
, "A%i = ABS A%i;", HL
, aop
);
4347 acc
= get_extended_acc (cpu
, aop
);
4350 av
= acc
== ((bs40
)1 << 39);
4352 acc
= ((bs40
)1 << 39) - 1;
4355 SET_ASTATREG (av
[HL
], av
);
4357 SET_ASTATREG (avs
[HL
], av
);
4358 SET_ASTATREG (az
, acc
== 0);
4359 SET_ASTATREG (an
, 0);
4361 else if (aop
== 3 && aopcde
== 12)
4363 bs32 res
= DREG (src0
);
4365 bool sBit_a
, sBit_b
;
4367 TRACE_INSN (cpu
, "R%i.%s = R%i (RND);", dst0
, HL
== 0 ? "L" : "H", src0
);
4368 TRACE_DECODE (cpu
, "R%i.%s = R%i:%#x (RND);", dst0
,
4369 HL
== 0 ? "L" : "H", src0
, res
);
4371 sBit_b
= !!(res
& 0x80000000);
4374 sBit_a
= !!(res
& 0x80000000);
4376 /* Overflow if the sign bit changed when we rounded. */
4377 if ((res
>> 16) && (sBit_b
!= sBit_a
))
4392 SET_DREG (dst0
, REG_H_L (DREG (dst0
), res
));
4394 SET_DREG (dst0
, REG_H_L (res
<< 16, DREG (dst0
)));
4396 SET_ASTATREG (az
, res
== 0);
4397 SET_ASTATREG (an
, res
< 0);
4398 SET_ASTATREG (v
, ovX
);
4400 SET_ASTATREG (vs
, ovX
);
4402 else if (aop
== 3 && HL
== 0 && aopcde
== 15)
4404 bu32 hi
= (-(bs16
)(DREG (src0
) >> 16)) << 16;
4405 bu32 lo
= (-(bs16
)(DREG (src0
) & 0xFFFF)) & 0xFFFF;
4408 TRACE_INSN (cpu
, "R%i = -R%i (V);", dst0
, src0
);
4412 if (hi
== 0x80000000)
4428 SET_DREG (dst0
, hi
| lo
);
4430 SET_ASTATREG (v
, v
);
4432 SET_ASTATREG (vs
, 1);
4433 SET_ASTATREG (ac0
, ac0
);
4434 SET_ASTATREG (ac1
, ac1
);
4435 setflags_nz_2x16 (cpu
, DREG (dst0
));
4437 else if (aop
== 3 && HL
== 0 && aopcde
== 14)
4439 TRACE_INSN (cpu
, "A1 = - A1 , A0 = - A0;");
4441 SET_AREG (0, saturate_s40 (-get_extended_acc (cpu
, 0)));
4442 SET_AREG (1, saturate_s40 (-get_extended_acc (cpu
, 1)));
4443 /* XXX: what ASTAT flags need updating ? */
4445 else if ((aop
== 0 || aop
== 1) && (HL
== 0 || HL
== 1) && aopcde
== 14)
4447 bs40 src_acc
= get_extended_acc (cpu
, aop
);
4450 TRACE_INSN (cpu
, "A%i = - A%i;", HL
, aop
);
4452 SET_AREG (HL
, saturate_s40_astat (-src_acc
, &v
));
4454 SET_ASTATREG (az
, AWREG (HL
) == 0 && AXREG (HL
) == 0);
4455 SET_ASTATREG (an
, AXREG (HL
) >> 7);
4458 SET_ASTATREG (ac0
, !src_acc
);
4459 SET_ASTATREG (av0
, v
);
4461 SET_ASTATREG (av0s
, 1);
4465 SET_ASTATREG (ac1
, !src_acc
);
4466 SET_ASTATREG (av1
, v
);
4468 SET_ASTATREG (av1s
, 1);
4471 else if (aop
== 0 && aopcde
== 12)
4473 bs16 tmp0_hi
= DREG (src0
) >> 16;
4474 bs16 tmp0_lo
= DREG (src0
);
4475 bs16 tmp1_hi
= DREG (src1
) >> 16;
4476 bs16 tmp1_lo
= DREG (src1
);
4478 TRACE_INSN (cpu
, "R%i.L = R%i.H = SIGN(R%i.H) * R%i.H + SIGN(R%i.L) * R%i.L;",
4479 dst0
, dst0
, src0
, src1
, src0
, src1
);
4481 if ((tmp0_hi
>> 15) & 1)
4482 tmp1_hi
= ~tmp1_hi
+ 1;
4484 if ((tmp0_lo
>> 15) & 1)
4485 tmp1_lo
= ~tmp1_lo
+ 1;
4487 tmp1_hi
= tmp1_hi
+ tmp1_lo
;
4489 STORE (DREG (dst0
), REG_H_L (tmp1_hi
<< 16, tmp1_hi
));
4491 else if (aopcde
== 0)
4493 bu32 s0
= DREG (src0
);
4494 bu32 s1
= DREG (src1
);
4495 bu32 s0h
= s0
>> 16;
4496 bu32 s0l
= s0
& 0xFFFF;
4497 bu32 s1h
= s1
>> 16;
4498 bu32 s1l
= s1
& 0xFFFF;
4500 bu32 ac1_i
= 0, ac0_i
= 0, v_i
= 0, z_i
= 0, n_i
= 0;
4502 TRACE_INSN (cpu
, "R%i = R%i %c|%c R%i%s;", dst0
, src0
,
4503 (aop
& 2) ? '-' : '+', (aop
& 1) ? '-' : '+', src1
,
4506 t0
= sub16 (cpu
, s0h
, s1h
, &ac1_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4508 t0
= add16 (cpu
, s0h
, s1h
, &ac1_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4511 t1
= sub16 (cpu
, s0l
, s1l
, &ac0_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4513 t1
= add16 (cpu
, s0l
, s1l
, &ac0_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4515 SET_ASTATREG (ac1
, ac1_i
);
4516 SET_ASTATREG (ac0
, ac0_i
);
4517 SET_ASTATREG (az
, z_i
);
4518 SET_ASTATREG (an
, n_i
);
4519 SET_ASTATREG (v
, v_i
);
4521 SET_ASTATREG (vs
, v_i
);
4526 SET_DREG (dst0
, (t1
<< 16) | t0
);
4528 SET_DREG (dst0
, (t0
<< 16) | t1
);
4530 else if (aop
== 1 && aopcde
== 12)
4532 bs32 val0
= (bs16
)(AWREG (0) >> 16) + (bs16
)AWREG (0);
4533 bs32 val1
= (bs16
)(AWREG (1) >> 16) + (bs16
)AWREG (1);
4535 TRACE_INSN (cpu
, "R%i = A1.L + A1.H, R%i = A0.L + A0.H;", dst1
, dst0
);
4538 illegal_instruction_combination (cpu
);
4540 SET_DREG (dst0
, val0
);
4541 SET_DREG (dst1
, val1
);
4543 else if (aopcde
== 1)
4547 bu16 s0L
= DREG (src0
);
4548 bu16 s0H
= DREG (src0
) >> 16;
4549 bu16 s1L
= DREG (src1
);
4550 bu16 s1H
= DREG (src1
) >> 16;
4551 bu32 v_i
= 0, n_i
= 0, z_i
= 0;
4553 TRACE_INSN (cpu
, "R%i = R%i %s R%i, R%i = R%i %s R%i%s;",
4554 dst1
, src0
, HL
? "+|-" : "+|+", src1
,
4555 dst0
, src0
, HL
? "-|+" : "-|-", src1
,
4556 amod0amod2 (s
, x
, aop
));
4559 illegal_instruction_combination (cpu
);
4563 x0
= add16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4564 x1
= add16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4565 d1
= (x0
<< 16) | x1
;
4567 x0
= sub16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4568 x1
= sub16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4570 d0
= (x0
<< 16) | x1
;
4572 d0
= (x1
<< 16) | x0
;
4576 x0
= add16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4577 x1
= sub16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4578 d1
= (x0
<< 16) | x1
;
4580 x0
= sub16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4581 x1
= add16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4583 d0
= (x0
<< 16) | x1
;
4585 d0
= (x1
<< 16) | x0
;
4587 SET_ASTATREG (az
, z_i
);
4588 SET_ASTATREG (an
, n_i
);
4589 SET_ASTATREG (v
, v_i
);
4591 SET_ASTATREG (vs
, v_i
);
4593 STORE (DREG (dst0
), d0
);
4594 STORE (DREG (dst1
), d1
);
4596 else if ((aop
== 0 || aop
== 1 || aop
== 2) && aopcde
== 11)
4598 bs40 acc0
= get_extended_acc (cpu
, 0);
4599 bs40 acc1
= get_extended_acc (cpu
, 1);
4600 bu32 v
, dreg
, sat
= 0;
4601 bu32 carry
= !!((bu40
)~acc1
< (bu40
)acc0
);
4604 TRACE_INSN (cpu
, "R%i = (A0 += A1);", dst0
);
4606 TRACE_INSN (cpu
, "R%i.%c = (A0 += A1);", dst0
, HL
? 'H' : 'L');
4608 TRACE_INSN (cpu
, "A0 += A1%s;", s
? " (W32)" : "");
4611 acc0
= saturate_s40_astat (acc0
, &v
);
4613 if (aop
== 2 && s
== 1) /* A0 += A1 (W32) */
4615 if (acc0
& (bs40
)0x8000000000ll
)
4616 acc0
&= 0x80ffffffffll
;
4618 acc0
&= 0xffffffffll
;
4621 STORE (AXREG (0), acc0
>> 32);
4622 STORE (AWREG (0), acc0
);
4623 SET_ASTATREG (av0
, v
&& acc1
);
4625 SET_ASTATREG (av0s
, v
);
4627 if (aop
== 0 || aop
== 1)
4629 if (aop
) /* Dregs_lo = A0 += A1 */
4631 dreg
= saturate_s32 (rnd16 (acc0
) << 16, &sat
);
4633 STORE (DREG (dst0
), REG_H_L (dreg
, DREG (dst0
)));
4635 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), dreg
>> 16));
4637 else /* Dregs = A0 += A1 */
4639 dreg
= saturate_s32 (acc0
, &sat
);
4640 STORE (DREG (dst0
), dreg
);
4643 STORE (ASTATREG (az
), dreg
== 0);
4644 STORE (ASTATREG (an
), !!(dreg
& 0x80000000));
4645 STORE (ASTATREG (ac0
), carry
);
4646 STORE (ASTATREG (ac0_copy
), carry
);
4647 STORE (ASTATREG (v
), sat
);
4648 STORE (ASTATREG (v_copy
), sat
);
4650 STORE (ASTATREG (vs
), sat
);
4654 STORE (ASTATREG (az
), acc0
== 0);
4655 STORE (ASTATREG (an
), !!(acc0
& 0x8000000000ull
));
4656 STORE (ASTATREG (ac0
), carry
);
4657 STORE (ASTATREG (ac0_copy
), carry
);
4660 else if ((aop
== 0 || aop
== 1) && aopcde
== 10)
4662 TRACE_INSN (cpu
, "R%i.L = A%i.X;", dst0
, aop
);
4663 SET_DREG_L (dst0
, (bs8
)AXREG (aop
));
4665 else if (aop
== 0 && aopcde
== 4)
4667 TRACE_INSN (cpu
, "R%i = R%i + R%i%s;", dst0
, src0
, src1
, amod1 (s
, x
));
4668 SET_DREG (dst0
, add32 (cpu
, DREG (src0
), DREG (src1
), 1, s
));
4670 else if (aop
== 1 && aopcde
== 4)
4672 TRACE_INSN (cpu
, "R%i = R%i - R%i%s;", dst0
, src0
, src1
, amod1 (s
, x
));
4673 SET_DREG (dst0
, sub32 (cpu
, DREG (src0
), DREG (src1
), 1, s
, 0));
4675 else if (aop
== 2 && aopcde
== 4)
4677 TRACE_INSN (cpu
, "R%i = R%i + R%i, R%i = R%i - R%i%s;",
4678 dst1
, src0
, src1
, dst0
, src0
, src1
, amod1 (s
, x
));
4681 illegal_instruction_combination (cpu
);
4683 STORE (DREG (dst1
), add32 (cpu
, DREG (src0
), DREG (src1
), 1, s
));
4684 STORE (DREG (dst0
), sub32 (cpu
, DREG (src0
), DREG (src1
), 1, s
, 1));
4686 else if ((aop
== 0 || aop
== 1) && aopcde
== 17)
4688 bs40 acc0
= get_extended_acc (cpu
, 0);
4689 bs40 acc1
= get_extended_acc (cpu
, 1);
4690 bs40 val0
, val1
, sval0
, sval1
;
4693 TRACE_INSN (cpu
, "R%i = A%i + A%i, R%i = A%i - A%i%s",
4694 dst1
, !aop
, aop
, dst0
, !aop
, aop
, amod1 (s
, x
));
4695 TRACE_DECODE (cpu
, "R%i = A%i:%#"PRIx64
" + A%i:%#"PRIx64
", "
4696 "R%i = A%i:%#"PRIx64
" - A%i:%#"PRIx64
"%s",
4697 dst1
, !aop
, aop
? acc0
: acc1
, aop
, aop
? acc1
: acc0
,
4698 dst0
, !aop
, aop
? acc0
: acc1
, aop
, aop
? acc1
: acc0
,
4702 illegal_instruction_combination (cpu
);
4710 sval0
= saturate_s32 (val0
, &sat
);
4712 sval1
= saturate_s32 (val1
, &sat
);
4720 STORE (DREG (dst0
), val0
);
4721 STORE (DREG (dst1
), val1
);
4722 SET_ASTATREG (v
, sat_i
);
4724 SET_ASTATREG (vs
, sat_i
);
4725 SET_ASTATREG (an
, val0
& 0x80000000 || val1
& 0x80000000);
4726 SET_ASTATREG (az
, val0
== 0 || val1
== 0);
4727 SET_ASTATREG (ac1
, (bu40
)~acc0
< (bu40
)acc1
);
4729 SET_ASTATREG (ac0
, !!((bu40
)acc1
<= (bu40
)acc0
));
4731 SET_ASTATREG (ac0
, !!((bu40
)acc0
<= (bu40
)acc1
));
4733 else if (aop
== 0 && aopcde
== 18)
4735 bu40 acc0
= get_extended_acc (cpu
, 0);
4736 bu40 acc1
= get_extended_acc (cpu
, 1);
4737 bu32 s0L
= DREG (src0
);
4738 bu32 s0H
= DREG (src0
+ 1);
4739 bu32 s1L
= DREG (src1
);
4740 bu32 s1H
= DREG (src1
+ 1);
4742 bs16 tmp0
, tmp1
, tmp2
, tmp3
;
4744 /* This instruction is only defined for register pairs R1:0 and R3:2. */
4745 if (!((src0
== 0 || src0
== 2) && (src1
== 0 || src1
== 2)))
4746 illegal_instruction (cpu
);
4748 TRACE_INSN (cpu
, "SAA (R%i:%i, R%i:%i)%s", src0
+ 1, src0
,
4749 src1
+ 1, src1
, s
? " (R)" :"");
4751 /* Bit s determines the order of the two registers from a pair:
4752 if s=0 the low-order bytes come from the low reg in the pair,
4753 and if s=1 the low-order bytes come from the high reg. */
4757 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4758 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4762 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4763 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4766 /* Find the absolute difference between pairs, make it
4767 absolute, then add it to the existing accumulator half. */
4769 tmp0
= ((s0
<< 24) >> 24) - ((s1
<< 24) >> 24);
4770 tmp1
= ((s0
<< 16) >> 24) - ((s1
<< 16) >> 24);
4771 tmp2
= ((s0
<< 8) >> 24) - ((s1
<< 8) >> 24);
4772 tmp3
= ((s0
<< 0) >> 24) - ((s1
<< 0) >> 24);
4774 tmp0
= (tmp0
< 0) ? -tmp0
: tmp0
;
4775 tmp1
= (tmp1
< 0) ? -tmp1
: tmp1
;
4776 tmp2
= (tmp2
< 0) ? -tmp2
: tmp2
;
4777 tmp3
= (tmp3
< 0) ? -tmp3
: tmp3
;
4779 s0L
= saturate_u16 ((bu32
)tmp0
+ ((acc0
>> 0) & 0xffff), 0);
4780 s0H
= saturate_u16 ((bu32
)tmp1
+ ((acc0
>> 16) & 0xffff), 0);
4781 s1L
= saturate_u16 ((bu32
)tmp2
+ ((acc1
>> 0) & 0xffff), 0);
4782 s1H
= saturate_u16 ((bu32
)tmp3
+ ((acc1
>> 16) & 0xffff), 0);
4784 STORE (AWREG (0), (s0H
<< 16) | (s0L
& 0xFFFF));
4785 STORE (AXREG (0), 0);
4786 STORE (AWREG (1), (s1H
<< 16) | (s1L
& 0xFFFF));
4787 STORE (AXREG (1), 0);
4789 /* Implicit DISALGNEXCPT in parallel. */
4792 else if (aop
== 3 && aopcde
== 18)
4794 TRACE_INSN (cpu
, "DISALGNEXCPT");
4797 else if ((aop
== 0 || aop
== 1) && aopcde
== 20)
4799 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4800 const char * const opts
[] = { "", " (R)", " (T)", " (T, R)" };
4802 TRACE_INSN (cpu
, "R%i = BYTEOP1P (R%i:%i, R%i:%i)%s;", dst0
,
4803 src0
+ 1, src0
, src1
+ 1, src1
, opts
[s
+ (aop
<< 1)]);
4806 s0H
= DREG (src0
+ 1);
4808 s1H
= DREG (src1
+ 1);
4811 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4812 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4816 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4817 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4821 (((((s0
>> 0) & 0xff) + ((s1
>> 0) & 0xff) + !aop
) >> 1) << 0) |
4822 (((((s0
>> 8) & 0xff) + ((s1
>> 8) & 0xff) + !aop
) >> 1) << 8) |
4823 (((((s0
>> 16) & 0xff) + ((s1
>> 16) & 0xff) + !aop
) >> 1) << 16) |
4824 (((((s0
>> 24) & 0xff) + ((s1
>> 24) & 0xff) + !aop
) >> 1) << 24));
4826 /* Implicit DISALGNEXCPT in parallel. */
4829 else if (aop
== 0 && aopcde
== 21)
4831 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4833 TRACE_INSN (cpu
, "(R%i, R%i) = BYTEOP16P (R%i:%i, R%i:%i)%s;", dst1
, dst0
,
4834 src0
+ 1, src0
, src1
+ 1, src1
, s
? " (R)" : "");
4837 illegal_instruction_combination (cpu
);
4840 s0H
= DREG (src0
+ 1);
4842 s1H
= DREG (src1
+ 1);
4845 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4846 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4850 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4851 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4855 ((((s0
>> 0) & 0xff) + ((s1
>> 0) & 0xff)) << 0) |
4856 ((((s0
>> 8) & 0xff) + ((s1
>> 8) & 0xff)) << 16));
4858 ((((s0
>> 16) & 0xff) + ((s1
>> 16) & 0xff)) << 0) |
4859 ((((s0
>> 24) & 0xff) + ((s1
>> 24) & 0xff)) << 16));
4861 /* Implicit DISALGNEXCPT in parallel. */
4864 else if (aop
== 1 && aopcde
== 21)
4866 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4868 TRACE_INSN (cpu
, "(R%i, R%i) = BYTEOP16M (R%i:%i, R%i:%i)%s;", dst1
, dst0
,
4869 src0
+ 1, src0
, src1
+ 1, src1
, s
? " (R)" : "");
4872 illegal_instruction_combination (cpu
);
4875 s0H
= DREG (src0
+ 1);
4877 s1H
= DREG (src1
+ 1);
4880 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4881 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4885 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4886 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4890 (((((s0
>> 0) & 0xff) - ((s1
>> 0) & 0xff)) << 0) & 0xffff) |
4891 (((((s0
>> 8) & 0xff) - ((s1
>> 8) & 0xff)) << 16)));
4893 (((((s0
>> 16) & 0xff) - ((s1
>> 16) & 0xff)) << 0) & 0xffff) |
4894 (((((s0
>> 24) & 0xff) - ((s1
>> 24) & 0xff)) << 16)));
4896 /* Implicit DISALGNEXCPT in parallel. */
4899 else if (aop
== 1 && aopcde
== 7)
4901 TRACE_INSN (cpu
, "R%i = MIN (R%i, R%i);", dst0
, src0
, src1
);
4902 SET_DREG (dst0
, min32 (cpu
, DREG (src0
), DREG (src1
)));
4904 else if (aop
== 0 && aopcde
== 7)
4906 TRACE_INSN (cpu
, "R%i = MAX (R%i, R%i);", dst0
, src0
, src1
);
4907 SET_DREG (dst0
, max32 (cpu
, DREG (src0
), DREG (src1
)));
4909 else if (aop
== 2 && aopcde
== 7)
4911 bu32 val
= DREG (src0
);
4914 TRACE_INSN (cpu
, "R%i = ABS R%i;", dst0
, src0
);
4918 v
= (val
== 0x80000000);
4921 SET_DREG (dst0
, val
);
4923 SET_ASTATREG (v
, v
);
4925 SET_ASTATREG (vs
, 1);
4926 setflags_nz (cpu
, val
);
4928 else if (aop
== 3 && aopcde
== 7)
4930 bu32 val
= DREG (src0
);
4932 TRACE_INSN (cpu
, "R%i = - R%i %s;", dst0
, src0
, amod1 (s
, 0));
4934 if (s
&& val
== 0x80000000)
4937 SET_ASTATREG (v
, 1);
4938 SET_ASTATREG (vs
, 1);
4940 else if (val
== 0x80000000)
4944 SET_DREG (dst0
, val
);
4946 SET_ASTATREG (az
, val
== 0);
4947 SET_ASTATREG (an
, val
& 0x80000000);
4949 else if (aop
== 2 && aopcde
== 6)
4951 bu32 in
= DREG (src0
);
4952 bu32 hi
= (in
& 0x80000000 ? (bu32
)-(bs16
)(in
>> 16) : in
>> 16) << 16;
4953 bu32 lo
= (in
& 0x8000 ? (bu32
)-(bs16
)(in
& 0xFFFF) : in
) & 0xFFFF;
4956 TRACE_INSN (cpu
, "R%i = ABS R%i (V);", dst0
, src0
);
4959 if (hi
== 0x80000000)
4969 SET_DREG (dst0
, hi
| lo
);
4971 SET_ASTATREG (v
, v
);
4973 SET_ASTATREG (vs
, 1);
4974 setflags_nz_2x16 (cpu
, DREG (dst0
));
4976 else if (aop
== 1 && aopcde
== 6)
4978 TRACE_INSN (cpu
, "R%i = MIN (R%i, R%i) (V);", dst0
, src0
, src1
);
4979 SET_DREG (dst0
, min2x16 (cpu
, DREG (src0
), DREG (src1
)));
4981 else if (aop
== 0 && aopcde
== 6)
4983 TRACE_INSN (cpu
, "R%i = MAX (R%i, R%i) (V);", dst0
, src0
, src1
);
4984 SET_DREG (dst0
, max2x16 (cpu
, DREG (src0
), DREG (src1
)));
4986 else if (aop
== 0 && aopcde
== 24)
4988 TRACE_INSN (cpu
, "R%i = BYTEPACK (R%i, R%i);", dst0
, src0
, src1
);
4990 (((DREG (src0
) >> 0) & 0xff) << 0) |
4991 (((DREG (src0
) >> 16) & 0xff) << 8) |
4992 (((DREG (src1
) >> 0) & 0xff) << 16) |
4993 (((DREG (src1
) >> 16) & 0xff) << 24));
4995 /* Implicit DISALGNEXCPT in parallel. */
4998 else if (aop
== 1 && aopcde
== 24)
5002 bu8 bytea
, byteb
, bytec
, byted
;
5004 TRACE_INSN (cpu
, "(R%i, R%i) = BYTEUNPACK R%i:%i%s;",
5005 dst1
, dst0
, src0
+ 1, src0
, s
? " (R)" : "");
5008 illegal_instruction_combination (cpu
);
5010 order
= IREG (0) & 0x3;
5012 hi
= src0
, lo
= src0
+ 1;
5014 hi
= src0
+ 1, lo
= src0
;
5015 comb_src
= (((bu64
)DREG (hi
)) << 32) | DREG (lo
);
5016 bytea
= (comb_src
>> (0 + 8 * order
));
5017 byteb
= (comb_src
>> (8 + 8 * order
));
5018 bytec
= (comb_src
>> (16 + 8 * order
));
5019 byted
= (comb_src
>> (24 + 8 * order
));
5020 STORE (DREG (dst0
), bytea
| ((bu32
)byteb
<< 16));
5021 STORE (DREG (dst1
), bytec
| ((bu32
)byted
<< 16));
5023 /* Implicit DISALGNEXCPT in parallel. */
5026 else if (aopcde
== 13)
5028 const char *searchmodes
[] = { "GT", "GE", "LT", "LE" };
5030 bs16 a0_lo
, a1_lo
, src_hi
, src_lo
;
5032 TRACE_INSN (cpu
, "(R%i, R%i) = SEARCH R%i (%s);",
5033 dst1
, dst0
, src0
, searchmodes
[aop
]);
5036 illegal_instruction_combination (cpu
);
5038 up_hi
= up_lo
= false;
5041 src_lo
= DREG (src0
);
5042 src_hi
= DREG (src0
) >> 16;
5047 up_hi
= (src_hi
> a1_lo
);
5048 up_lo
= (src_lo
> a0_lo
);
5051 up_hi
= (src_hi
>= a1_lo
);
5052 up_lo
= (src_lo
>= a0_lo
);
5055 up_hi
= (src_hi
< a1_lo
);
5056 up_lo
= (src_lo
< a0_lo
);
5059 up_hi
= (src_hi
<= a1_lo
);
5060 up_lo
= (src_lo
<= a0_lo
);
5066 SET_AREG (1, src_hi
);
5067 SET_DREG (dst1
, PREG (0));
5070 SET_AREG (1, a1_lo
);
5074 SET_AREG (0, src_lo
);
5075 SET_DREG (dst0
, PREG (0));
5078 SET_AREG (0, a0_lo
);
5081 illegal_instruction (cpu
);
5085 decode_dsp32shift_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
5088 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5089 | 1 | 1 | 0 | 0 |.M.| 1 | 1 | 0 | 0 | - | - |.sopcde............|
5090 |.sop...|.HLs...|.dst0......| - | - | - |.src0......|.src1......|
5091 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5092 int HLs
= ((iw1
>> DSP32Shift_HLs_bits
) & DSP32Shift_HLs_mask
);
5093 int sop
= ((iw1
>> DSP32Shift_sop_bits
) & DSP32Shift_sop_mask
);
5094 int src0
= ((iw1
>> DSP32Shift_src0_bits
) & DSP32Shift_src0_mask
);
5095 int src1
= ((iw1
>> DSP32Shift_src1_bits
) & DSP32Shift_src1_mask
);
5096 int dst0
= ((iw1
>> DSP32Shift_dst0_bits
) & DSP32Shift_dst0_mask
);
5097 int sopcde
= ((iw0
>> (DSP32Shift_sopcde_bits
- 16)) & DSP32Shift_sopcde_mask
);
5098 int M
= ((iw0
>> (DSP32Shift_M_bits
- 16)) & DSP32Shift_M_mask
);
5100 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32shift
);
5101 TRACE_EXTRACT (cpu
, "%s: M:%i sopcde:%i sop:%i HLs:%i dst0:%i src0:%i src1:%i",
5102 __func__
, M
, sopcde
, sop
, HLs
, dst0
, src0
, src1
);
5104 if ((sop
== 0 || sop
== 1) && sopcde
== 0)
5107 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5109 TRACE_INSN (cpu
, "R%i.%c = ASHIFT R%i.%c BY R%i.L%s;",
5110 dst0
, HLs
< 2 ? 'L' : 'H',
5111 src1
, HLs
& 1 ? 'H' : 'L',
5112 src0
, sop
== 1 ? " (S)" : "");
5115 val
= (bu16
)(DREG (src1
) & 0xFFFF);
5117 val
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5119 /* Positive shift magnitudes produce Logical Left shifts.
5120 Negative shift magnitudes produce Arithmetic Right shifts. */
5122 val
= ashiftrt (cpu
, val
, -shft
, 16);
5124 val
= lshift (cpu
, val
, shft
, 16, sop
== 1);
5127 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), val
));
5129 STORE (DREG (dst0
), REG_H_L (val
<< 16, DREG (dst0
)));
5131 else if (sop
== 2 && sopcde
== 0)
5133 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5136 TRACE_INSN (cpu
, "R%i.%c = LSHIFT R%i.%c BY R%i.L;",
5137 dst0
, HLs
< 2 ? 'L' : 'H',
5138 src1
, HLs
& 1 ? 'H' : 'L', src0
);
5141 val
= (bu16
)(DREG (src1
) & 0xFFFF);
5143 val
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5146 val
= val
>> (-1 * shft
);
5151 SET_DREG (dst0
, REG_H_L (DREG (dst0
), val
));
5153 SET_DREG (dst0
, REG_H_L (val
<< 16, DREG (dst0
)));
5155 SET_ASTATREG (az
, !((val
& 0xFFFF0000) == 0) || ((val
& 0xFFFF) == 0));
5156 SET_ASTATREG (an
, (!!(val
& 0x80000000)) ^ (!!(val
& 0x8000)));
5157 SET_ASTATREG (v
, 0);
5159 else if (sop
== 2 && sopcde
== 3 && (HLs
== 1 || HLs
== 0))
5161 int shift
= imm6 (DREG (src0
) & 0xFFFF);
5163 bu40 acc
= get_unextended_acc (cpu
, HLs
);
5165 TRACE_INSN (cpu
, "A%i = ROT A%i BY R%i.L;", HLs
, HLs
, src0
);
5166 TRACE_DECODE (cpu
, "A%i:%#"PRIx64
" shift:%i CC:%i", HLs
, acc
, shift
, cc
);
5168 acc
= rot40 (acc
, shift
, &cc
);
5169 SET_AREG (HLs
, acc
);
5173 else if (sop
== 0 && sopcde
== 3 && (HLs
== 0 || HLs
== 1))
5175 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5176 bu64 val
= get_extended_acc (cpu
, HLs
);
5179 TRACE_INSN (cpu
, "A%i = ASHIFT A%i BY R%i.L;", HLs
, HLs
, src0
);
5180 TRACE_DECODE (cpu
, "A%i:%#"PRIx64
" shift:%i", HLs
, val
, shft
);
5183 val
= ashiftrt (cpu
, val
, -shft
, 40);
5185 val
= lshift (cpu
, val
, shft
, 40, 0);
5187 STORE (AXREG (HLs
), (val
>> 32) & 0xff);
5188 STORE (AWREG (HLs
), (val
& 0xffffffff));
5190 else if (sop
== 1 && sopcde
== 3 && (HLs
== 0 || HLs
== 1))
5192 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5196 TRACE_INSN (cpu
, "A%i = LSHIFT A%i BY R%i.L;", HLs
, HLs
, src0
);
5197 val
= get_extended_acc (cpu
, HLs
);
5200 val
= lshiftrt (cpu
, val
, -shft
, 40);
5202 val
= lshift (cpu
, val
, shft
, 40, 0);
5204 STORE (AXREG (HLs
), (val
>> 32) & 0xff);
5205 STORE (AWREG (HLs
), (val
& 0xffffffff));
5207 else if ((sop
== 0 || sop
== 1) && sopcde
== 1)
5209 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5213 TRACE_INSN (cpu
, "R%i = ASHIFT R%i BY R%i.L (V%s);",
5214 dst0
, src1
, src0
, sop
== 1 ? ",S" : "");
5216 val0
= (bu16
)DREG (src1
) & 0xFFFF;
5217 val1
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5221 val0
= ashiftrt (cpu
, val0
, -shft
, 16);
5223 val1
= ashiftrt (cpu
, val1
, -shft
, 16);
5227 val0
= lshift (cpu
, val0
, shft
, 16, sop
== 1);
5229 val1
= lshift (cpu
, val1
, shft
, 16, sop
== 1);
5231 SET_ASTAT (ASTAT
| astat
);
5232 STORE (DREG (dst0
), (val1
<< 16) | val0
);
5234 else if ((sop
== 0 || sop
== 1 || sop
== 2) && sopcde
== 2)
5236 /* dregs = [LA]SHIFT dregs BY dregs_lo (opt_S) */
5237 /* sop == 1 : opt_S */
5238 bu32 v
= DREG (src1
);
5239 /* LSHIFT uses sign extended low 6 bits of dregs_lo. */
5240 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5242 TRACE_INSN (cpu
, "R%i = %cSHIFT R%i BY R%i.L%s;", dst0
,
5243 shft
&& sop
!= 2 ? 'A' : 'L', src1
, src0
,
5244 sop
== 1 ? " (S)" : "");
5249 STORE (DREG (dst0
), lshiftrt (cpu
, v
, -shft
, 32));
5251 STORE (DREG (dst0
), ashiftrt (cpu
, v
, -shft
, 32));
5254 STORE (DREG (dst0
), lshift (cpu
, v
, shft
, 32, sop
== 1));
5256 else if (sop
== 3 && sopcde
== 2)
5258 int shift
= imm6 (DREG (src0
) & 0xFFFF);
5259 bu32 src
= DREG (src1
);
5260 bu32 ret
, cc
= CCREG
;
5262 TRACE_INSN (cpu
, "R%i = ROT R%i BY R%i.L;", dst0
, src1
, src0
);
5263 TRACE_DECODE (cpu
, "R%i:%#x R%i:%#x shift:%i CC:%i",
5264 dst0
, DREG (dst0
), src1
, src
, shift
, cc
);
5266 ret
= rot32 (src
, shift
, &cc
);
5267 STORE (DREG (dst0
), ret
);
5271 else if (sop
== 2 && sopcde
== 1)
5273 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5277 TRACE_INSN (cpu
, "R%i = LSHIFT R%i BY R%i.L (V);", dst0
, src1
, src0
);
5279 val0
= (bu16
)DREG (src1
) & 0xFFFF;
5280 val1
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5284 val0
= lshiftrt (cpu
, val0
, -shft
, 16);
5286 val1
= lshiftrt (cpu
, val1
, -shft
, 16);
5290 val0
= lshift (cpu
, val0
, shft
, 16, 0);
5292 val1
= lshift (cpu
, val1
, shft
, 16, 0);
5294 SET_ASTAT (ASTAT
| astat
);
5295 STORE (DREG (dst0
), (val1
<< 16) | val0
);
5297 else if (sopcde
== 4)
5299 bu32 sv0
= DREG (src0
);
5300 bu32 sv1
= DREG (src1
);
5301 TRACE_INSN (cpu
, "R%i = PACK (R%i.%c, R%i.%c);", dst0
,
5302 src1
, sop
& 2 ? 'H' : 'L',
5303 src0
, sop
& 1 ? 'H' : 'L');
5308 STORE (DREG (dst0
), (sv1
<< 16) | (sv0
& 0xFFFF));
5310 else if (sop
== 0 && sopcde
== 5)
5312 bu32 sv1
= DREG (src1
);
5313 TRACE_INSN (cpu
, "R%i.L = SIGNBITS R%i;", dst0
, src1
);
5314 SET_DREG_L (dst0
, signbits (sv1
, 32));
5316 else if (sop
== 1 && sopcde
== 5)
5318 bu32 sv1
= DREG (src1
);
5319 TRACE_INSN (cpu
, "R%i.L = SIGNBITS R%i.L;", dst0
, src1
);
5320 SET_DREG_L (dst0
, signbits (sv1
, 16));
5322 else if (sop
== 2 && sopcde
== 5)
5324 bu32 sv1
= DREG (src1
);
5325 TRACE_INSN (cpu
, "R%i.L = SIGNBITS R%i.H;", dst0
, src1
);
5326 SET_DREG_L (dst0
, signbits (sv1
>> 16, 16));
5328 else if ((sop
== 0 || sop
== 1) && sopcde
== 6)
5330 bu64 acc
= AXREG (sop
);
5331 TRACE_INSN (cpu
, "R%i.L = SIGNBITS A%i;", dst0
, sop
);
5334 SET_DREG_L (dst0
, signbits (acc
, 40) & 0xFFFF);
5336 else if (sop
== 3 && sopcde
== 6)
5338 bu32 v
= ones (DREG (src1
));
5339 TRACE_INSN (cpu
, "R%i.L = ONES R%i;", dst0
, src1
);
5340 SET_DREG_L (dst0
, v
);
5342 else if (sop
== 0 && sopcde
== 7)
5344 bu16 sv1
= (bu16
)signbits (DREG (src1
), 32);
5345 bu16 sv0
= (bu16
)DREG (src0
);
5348 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i, R%i.L);", dst0
, src1
, src0
);
5350 if ((sv1
& 0x1f) < (sv0
& 0x1f))
5354 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), dst_lo
));
5356 else if (sop
== 1 && sopcde
== 7)
5358 /* Exponent adjust on two 16-bit inputs. Select
5359 smallest norm among 3 inputs. */
5360 bs16 src1_hi
= (DREG (src1
) & 0xFFFF0000) >> 16;
5361 bs16 src1_lo
= (DREG (src1
) & 0xFFFF);
5362 bu16 src0_lo
= (DREG (src0
) & 0xFFFF);
5363 bu16 tmp_hi
, tmp_lo
, tmp
;
5365 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i, R%i.L) (V);", dst0
, src1
, src0
);
5367 tmp_hi
= signbits (src1_hi
, 16);
5368 tmp_lo
= signbits (src1_lo
, 16);
5370 if ((tmp_hi
& 0xf) < (tmp_lo
& 0xf))
5371 if ((tmp_hi
& 0xf) < (src0_lo
& 0xf))
5376 if ((tmp_lo
& 0xf) < (src0_lo
& 0xf))
5380 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), tmp
));
5382 else if (sop
== 2 && sopcde
== 7)
5384 /* Exponent adjust on single 16-bit register. */
5386 bu16 src0_lo
= (bu16
)(DREG (src0
) & 0xFFFF);
5388 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i.L, R%i.L);", dst0
, src1
, src0
);
5390 tmp
= signbits (DREG (src1
) & 0xFFFF, 16);
5392 if ((tmp
& 0xf) < (src0_lo
& 0xf))
5393 SET_DREG_L (dst0
, tmp
);
5395 SET_DREG_L (dst0
, src0_lo
);
5397 else if (sop
== 3 && sopcde
== 7)
5400 bu16 src0_lo
= (bu16
)(DREG (src0
) & 0xFFFF);
5402 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i.H, R%i.L);", dst0
, src1
, src0
);
5404 tmp
= signbits ((DREG (src1
) & 0xFFFF0000) >> 16, 16);
5406 if ((tmp
& 0xf) < (src0_lo
& 0xf))
5407 SET_DREG_L (dst0
, tmp
);
5409 SET_DREG_L (dst0
, src0_lo
);
5411 else if (sop
== 0 && sopcde
== 8)
5413 bu64 acc
= get_unextended_acc (cpu
, 0);
5416 TRACE_INSN (cpu
, "BITMUX (R%i, R%i, A0) (ASR);", src0
, src1
);
5419 illegal_instruction_combination (cpu
);
5424 (((bu64
)s0
& 1) << 38) |
5425 (((bu64
)s1
& 1) << 39);
5426 STORE (DREG (src0
), s0
>> 1);
5427 STORE (DREG (src1
), s1
>> 1);
5431 else if (sop
== 1 && sopcde
== 8)
5433 bu64 acc
= get_unextended_acc (cpu
, 0);
5436 TRACE_INSN (cpu
, "BITMUX (R%i, R%i, A0) (ASL);", src0
, src1
);
5439 illegal_instruction_combination (cpu
);
5446 STORE (DREG (src0
), s0
<< 1);
5447 STORE (DREG (src1
), s1
<< 1);
5451 else if ((sop
== 0 || sop
== 1) && sopcde
== 9)
5453 bs40 acc0
= get_unextended_acc (cpu
, 0);
5456 TRACE_INSN (cpu
, "R%i.L = VIT_MAX (R%i) (AS%c);",
5457 dst0
, src1
, sop
& 1 ? 'R' : 'L');
5460 sH
= DREG (src1
) >> 16;
5463 acc0
= (acc0
& 0xfeffffffffull
) >> 1;
5467 if (((sH
- sL
) & 0x8000) == 0)
5470 acc0
|= (sop
& 1) ? 0x80000000 : 1;
5476 SET_DREG (dst0
, REG_H_L (DREG (dst0
), out
));
5478 else if ((sop
== 2 || sop
== 3) && sopcde
== 9)
5480 bs40 acc0
= get_extended_acc (cpu
, 0);
5481 bs16 s0L
, s0H
, s1L
, s1H
, out0
, out1
;
5483 TRACE_INSN (cpu
, "R%i = VIT_MAX (R%i, R%i) (AS%c);",
5484 dst0
, src1
, src0
, sop
& 1 ? 'R' : 'L');
5487 s0H
= DREG (src0
) >> 16;
5489 s1H
= DREG (src1
) >> 16;
5496 if (((s0H
- s0L
) & 0x8000) == 0)
5499 acc0
|= (sop
& 1) ? 0x40000000 : 2;
5504 if (((s1H
- s1L
) & 0x8000) == 0)
5507 acc0
|= (sop
& 1) ? 0x80000000 : 1;
5513 SET_DREG (dst0
, REG_H_L (out1
<< 16, out0
));
5515 else if (sop
== 0 && sopcde
== 10)
5517 bu32 v
= DREG (src0
);
5518 bu32 x
= DREG (src1
);
5519 bu32 mask
= (1 << (v
& 0x1f)) - 1;
5521 TRACE_INSN (cpu
, "R%i = EXTRACT (R%i, R%i.L) (Z);", dst0
, src1
, src0
);
5523 x
>>= ((v
>> 8) & 0x1f);
5525 STORE (DREG (dst0
), x
);
5526 setflags_logical (cpu
, x
);
5528 else if (sop
== 1 && sopcde
== 10)
5530 bu32 v
= DREG (src0
);
5531 bu32 x
= DREG (src1
);
5532 bu32 sgn
= (1 << (v
& 0x1f)) >> 1;
5533 bu32 mask
= (1 << (v
& 0x1f)) - 1;
5535 TRACE_INSN (cpu
, "R%i = EXTRACT (R%i, R%i.L) (X);", dst0
, src1
, src0
);
5537 x
>>= ((v
>> 8) & 0x1f);
5541 STORE (DREG (dst0
), x
);
5542 setflags_logical (cpu
, x
);
5544 else if ((sop
== 2 || sop
== 3) && sopcde
== 10)
5546 /* The first dregs is the "background" while the second dregs is the
5547 "foreground". The fg reg is used to overlay the bg reg and is:
5548 | nnnn nnnn | nnnn nnnn | xxxp pppp | xxxL LLLL |
5549 n = the fg bit field
5550 p = bit position in bg reg to start LSB of fg field
5551 L = number of fg bits to extract
5552 Using (X) sign-extends the fg bit field. */
5553 bu32 fg
= DREG (src0
);
5554 bu32 bg
= DREG (src1
);
5555 bu32 len
= fg
& 0x1f;
5556 bu32 mask
= (1 << MIN (16, len
)) - 1;
5557 bu32 fgnd
= (fg
>> 16) & mask
;
5558 int shft
= ((fg
>> 8) & 0x1f);
5560 TRACE_INSN (cpu
, "R%i = DEPOSIT (R%i, R%i)%s;", dst0
, src1
, src0
,
5561 sop
== 3 ? " (X)" : "");
5565 /* Sign extend the fg bit field. */
5567 fgnd
= ((bs32
)(bs16
)(fgnd
<< (16 - len
))) >> (16 - len
);
5574 STORE (DREG (dst0
), bg
);
5575 setflags_logical (cpu
, bg
);
5577 else if (sop
== 0 && sopcde
== 11)
5579 bu64 acc0
= get_unextended_acc (cpu
, 0);
5581 TRACE_INSN (cpu
, "R%i.L = CC = BXORSHIFT (A0, R%i);", dst0
, src0
);
5584 SET_CCREG (xor_reduce (acc0
, DREG (src0
)));
5585 SET_DREG (dst0
, REG_H_L (DREG (dst0
), CCREG
));
5588 else if (sop
== 1 && sopcde
== 11)
5590 bu64 acc0
= get_unextended_acc (cpu
, 0);
5592 TRACE_INSN (cpu
, "R%i.L = CC = BXOR (A0, R%i);", dst0
, src0
);
5594 SET_CCREG (xor_reduce (acc0
, DREG (src0
)));
5595 SET_DREG (dst0
, REG_H_L (DREG (dst0
), CCREG
));
5597 else if (sop
== 0 && sopcde
== 12)
5599 bu64 acc0
= get_unextended_acc (cpu
, 0);
5600 bu64 acc1
= get_unextended_acc (cpu
, 1);
5602 TRACE_INSN (cpu
, "A0 = BXORSHIFT (A0, A1, CC);");
5604 acc0
= (acc0
<< 1) | (CCREG
^ xor_reduce (acc0
, acc1
));
5607 else if (sop
== 1 && sopcde
== 12)
5609 bu64 acc0
= get_unextended_acc (cpu
, 0);
5610 bu64 acc1
= get_unextended_acc (cpu
, 1);
5612 TRACE_INSN (cpu
, "R%i.L = CC = BXOR (A0, A1, CC);", dst0
);
5614 SET_CCREG (CCREG
^ xor_reduce (acc0
, acc1
));
5615 acc0
= (acc0
<< 1) | CCREG
;
5616 SET_DREG (dst0
, REG_H_L (DREG (dst0
), CCREG
));
5618 else if ((sop
== 0 || sop
== 1 || sop
== 2) && sopcde
== 13)
5620 int shift
= (sop
+ 1) * 8;
5621 TRACE_INSN (cpu
, "R%i = ALIGN%i (R%i, R%i);", dst0
, shift
, src1
, src0
);
5622 STORE (DREG (dst0
), (DREG (src1
) << (32 - shift
)) | (DREG (src0
) >> shift
));
5625 illegal_instruction (cpu
);
5629 decode_dsp32shiftimm_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
5632 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5633 | 1 | 1 | 0 | 0 |.M.| 1 | 1 | 0 | 1 | - | - |.sopcde............|
5634 |.sop...|.HLs...|.dst0......|.immag.................|.src1......|
5635 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5636 int src1
= ((iw1
>> DSP32ShiftImm_src1_bits
) & DSP32ShiftImm_src1_mask
);
5637 int sop
= ((iw1
>> DSP32ShiftImm_sop_bits
) & DSP32ShiftImm_sop_mask
);
5638 int bit8
= ((iw1
>> 8) & 0x1);
5639 int immag
= ((iw1
>> DSP32ShiftImm_immag_bits
) & DSP32ShiftImm_immag_mask
);
5640 int newimmag
= (-(iw1
>> DSP32ShiftImm_immag_bits
) & DSP32ShiftImm_immag_mask
);
5641 int dst0
= ((iw1
>> DSP32ShiftImm_dst0_bits
) & DSP32ShiftImm_dst0_mask
);
5642 int M
= ((iw0
>> (DSP32ShiftImm_M_bits
- 16)) & DSP32ShiftImm_M_mask
);
5643 int sopcde
= ((iw0
>> (DSP32ShiftImm_sopcde_bits
- 16)) & DSP32ShiftImm_sopcde_mask
);
5644 int HLs
= ((iw1
>> DSP32ShiftImm_HLs_bits
) & DSP32ShiftImm_HLs_mask
);
5646 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32shiftimm
);
5647 TRACE_EXTRACT (cpu
, "%s: M:%i sopcde:%i sop:%i HLs:%i dst0:%i immag:%#x src1:%i",
5648 __func__
, M
, sopcde
, sop
, HLs
, dst0
, immag
, src1
);
5652 bu16 in
= DREG (src1
) >> ((HLs
& 1) ? 16 : 0);
5658 TRACE_INSN (cpu
, "R%i.%c = R%i.%c >>> %i;",
5659 dst0
, (HLs
& 2) ? 'H' : 'L',
5660 src1
, (HLs
& 1) ? 'H' : 'L', newimmag
);
5661 result
= ashiftrt (cpu
, in
, newimmag
, 16);
5663 else if (sop
== 1 && bit8
== 0)
5665 TRACE_INSN (cpu
, "R%i.%c = R%i.%c << %i (S);",
5666 dst0
, (HLs
& 2) ? 'H' : 'L',
5667 src1
, (HLs
& 1) ? 'H' : 'L', immag
);
5668 result
= lshift (cpu
, in
, immag
, 16, 1);
5670 else if (sop
== 1 && bit8
)
5672 TRACE_INSN (cpu
, "R%i.%c = R%i.%c >>> %i (S);",
5673 dst0
, (HLs
& 2) ? 'H' : 'L',
5674 src1
, (HLs
& 1) ? 'H' : 'L', immag
);
5675 result
= lshift (cpu
, in
, immag
, 16, 1);
5677 else if (sop
== 2 && bit8
)
5679 TRACE_INSN (cpu
, "R%i.%c = R%i.%c >> %i;",
5680 dst0
, (HLs
& 2) ? 'H' : 'L',
5681 src1
, (HLs
& 1) ? 'H' : 'L', newimmag
);
5682 result
= lshiftrt (cpu
, in
, newimmag
, 16);
5684 else if (sop
== 2 && bit8
== 0)
5686 TRACE_INSN (cpu
, "R%i.%c = R%i.%c << %i;",
5687 dst0
, (HLs
& 2) ? 'H' : 'L',
5688 src1
, (HLs
& 1) ? 'H' : 'L', immag
);
5689 result
= lshift (cpu
, in
, immag
, 16, 0);
5692 illegal_instruction (cpu
);
5696 STORE (DREG (dst0
), (v
& 0xFFFF) | (result
<< 16));
5698 STORE (DREG (dst0
), (v
& 0xFFFF0000) | result
);
5700 else if (sop
== 2 && sopcde
== 3 && (HLs
== 1 || HLs
== 0))
5702 int shift
= imm6 (immag
);
5704 bu40 acc
= get_unextended_acc (cpu
, HLs
);
5706 TRACE_INSN (cpu
, "A%i = ROT A%i BY %i;", HLs
, HLs
, shift
);
5707 TRACE_DECODE (cpu
, "A%i:%#"PRIx64
" shift:%i CC:%i", HLs
, acc
, shift
, cc
);
5709 acc
= rot40 (acc
, shift
, &cc
);
5710 SET_AREG (HLs
, acc
);
5714 else if (sop
== 0 && sopcde
== 3 && bit8
== 1)
5716 /* Arithmetic shift, so shift in sign bit copies. */
5718 int shift
= uimm5 (newimmag
);
5721 TRACE_INSN (cpu
, "A%i = A%i >>> %i;", HLs
, HLs
, shift
);
5723 acc
= get_extended_acc (cpu
, HLs
);
5725 /* Sign extend again. */
5726 if (acc
& (1ULL << 39))
5727 acc
|= -(1ULL << 39);
5729 acc
&= ~(-(1ULL << 39));
5731 STORE (AXREG (HLs
), (acc
>> 32) & 0xFF);
5732 STORE (AWREG (HLs
), acc
& 0xFFFFFFFF);
5734 else if ((sop
== 0 && sopcde
== 3 && bit8
== 0)
5735 || (sop
== 1 && sopcde
== 3))
5738 int shiftup
= uimm5 (immag
);
5739 int shiftdn
= uimm5 (newimmag
);
5742 TRACE_INSN (cpu
, "A%i = A%i %s %i;", HLs
, HLs
,
5743 sop
== 0 ? "<<" : ">>",
5744 sop
== 0 ? shiftup
: shiftdn
);
5747 /* Logical shift, so shift in zeroes. */
5757 SET_AREG (HLs
, acc
);
5758 SET_ASTATREG (an
, !!(acc
& 0x8000000000ull
));
5759 SET_ASTATREG (az
, acc
== 0);
5761 else if (sop
== 1 && sopcde
== 1 && bit8
== 0)
5763 int count
= imm5 (immag
);
5764 bu16 val0
= DREG (src1
) >> 16;
5765 bu16 val1
= DREG (src1
) & 0xFFFF;
5768 TRACE_INSN (cpu
, "R%i = R%i << %i (V,S);", dst0
, src1
, count
);
5769 val0
= lshift (cpu
, val0
, count
, 16, 1);
5771 val1
= lshift (cpu
, val1
, count
, 16, 1);
5772 SET_ASTAT (ASTAT
| astat
);
5774 STORE (DREG (dst0
), (val0
<< 16) | val1
);
5776 else if (sop
== 2 && sopcde
== 1 && bit8
== 1)
5778 int count
= imm5 (newimmag
);
5779 bu16 val0
= DREG (src1
) & 0xFFFF;
5780 bu16 val1
= DREG (src1
) >> 16;
5783 TRACE_INSN (cpu
, "R%i = R%i >> %i (V);", dst0
, src1
, count
);
5784 val0
= lshiftrt (cpu
, val0
, count
, 16);
5786 val1
= lshiftrt (cpu
, val1
, count
, 16);
5787 SET_ASTAT (ASTAT
| astat
);
5789 STORE (DREG (dst0
), val0
| (val1
<< 16));
5791 else if (sop
== 2 && sopcde
== 1 && bit8
== 0)
5793 int count
= imm5 (immag
);
5794 bu16 val0
= DREG (src1
) & 0xFFFF;
5795 bu16 val1
= DREG (src1
) >> 16;
5798 TRACE_INSN (cpu
, "R%i = R%i << %i (V);", dst0
, src1
, count
);
5799 val0
= lshift (cpu
, val0
, count
, 16, 0);
5801 val1
= lshift (cpu
, val1
, count
, 16, 0);
5802 SET_ASTAT (ASTAT
| astat
);
5804 STORE (DREG (dst0
), val0
| (val1
<< 16));
5806 else if (sopcde
== 1 && (sop
== 0 || (sop
== 1 && bit8
== 1)))
5808 int count
= uimm5 (newimmag
);
5809 bu16 val0
= DREG (src1
) & 0xFFFF;
5810 bu16 val1
= DREG (src1
) >> 16;
5813 TRACE_INSN (cpu
, "R%i = R%i >>> %i %s;", dst0
, src1
, count
,
5814 sop
== 0 ? "(V)" : "(V,S)");
5816 val0
= ashiftrt (cpu
, val0
, count
, 16);
5818 val1
= ashiftrt (cpu
, val1
, count
, 16);
5819 SET_ASTAT (ASTAT
| astat
);
5821 STORE (DREG (dst0
), REG_H_L (val1
<< 16, val0
));
5823 else if (sop
== 1 && sopcde
== 2)
5825 int count
= imm6 (immag
);
5827 TRACE_INSN (cpu
, "R%i = R%i << %i (S);", dst0
, src1
, count
);
5828 STORE (DREG (dst0
), lshift (cpu
, DREG (src1
), count
, 32, 1));
5830 else if (sop
== 2 && sopcde
== 2)
5832 int count
= imm6 (newimmag
);
5834 TRACE_INSN (cpu
, "R%i = R%i >> %i;", dst0
, src1
, count
);
5837 STORE (DREG (dst0
), lshift (cpu
, DREG (src1
), -count
, 32, 0));
5839 STORE (DREG (dst0
), lshiftrt (cpu
, DREG (src1
), count
, 32));
5841 else if (sop
== 3 && sopcde
== 2)
5843 int shift
= imm6 (immag
);
5844 bu32 src
= DREG (src1
);
5845 bu32 ret
, cc
= CCREG
;
5847 TRACE_INSN (cpu
, "R%i = ROT R%i BY %i;", dst0
, src1
, shift
);
5848 TRACE_DECODE (cpu
, "R%i:%#x R%i:%#x shift:%i CC:%i",
5849 dst0
, DREG (dst0
), src1
, src
, shift
, cc
);
5851 ret
= rot32 (src
, shift
, &cc
);
5852 STORE (DREG (dst0
), ret
);
5856 else if (sop
== 0 && sopcde
== 2)
5858 int count
= imm6 (newimmag
);
5860 TRACE_INSN (cpu
, "R%i = R%i >>> %i;", dst0
, src1
, count
);
5863 STORE (DREG (dst0
), lshift (cpu
, DREG (src1
), -count
, 32, 0));
5865 STORE (DREG (dst0
), ashiftrt (cpu
, DREG (src1
), count
, 32));
5868 illegal_instruction (cpu
);
5872 outc (SIM_CPU
*cpu
, char ch
)
5874 SIM_DESC sd
= CPU_STATE (cpu
);
5875 sim_io_printf (sd
, "%c", ch
);
5877 sim_io_flush_stdout (sd
);
5881 decode_psedoDEBUG_0 (SIM_CPU
*cpu
, bu16 iw0
)
5884 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5885 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 |.fn....|.grp.......|.reg.......|
5886 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5887 SIM_DESC sd
= CPU_STATE (cpu
);
5888 int fn
= ((iw0
>> PseudoDbg_fn_bits
) & PseudoDbg_fn_mask
);
5889 int grp
= ((iw0
>> PseudoDbg_grp_bits
) & PseudoDbg_grp_mask
);
5890 int reg
= ((iw0
>> PseudoDbg_reg_bits
) & PseudoDbg_reg_mask
);
5892 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_psedoDEBUG
);
5893 TRACE_EXTRACT (cpu
, "%s: fn:%i grp:%i reg:%i", __func__
, fn
, grp
, reg
);
5895 if ((reg
== 0 || reg
== 1) && fn
== 3)
5897 TRACE_INSN (cpu
, "DBG A%i;", reg
);
5898 sim_io_printf (sd
, "DBG : A%i = %#"PRIx64
"\n", reg
,
5899 get_unextended_acc (cpu
, reg
));
5901 else if (reg
== 3 && fn
== 3)
5903 TRACE_INSN (cpu
, "ABORT;");
5904 cec_exception (cpu
, VEC_SIM_ABORT
);
5907 else if (reg
== 4 && fn
== 3)
5909 TRACE_INSN (cpu
, "HLT;");
5910 cec_exception (cpu
, VEC_SIM_HLT
);
5913 else if (reg
== 5 && fn
== 3)
5914 unhandled_instruction (cpu
, "DBGHALT");
5915 else if (reg
== 6 && fn
== 3)
5916 unhandled_instruction (cpu
, "DBGCMPLX (dregs)");
5917 else if (reg
== 7 && fn
== 3)
5918 unhandled_instruction (cpu
, "DBG");
5919 else if (grp
== 0 && fn
== 2)
5921 TRACE_INSN (cpu
, "OUTC R%i;", reg
);
5922 outc (cpu
, DREG (reg
));
5926 const char *reg_name
= get_allreg_name (grp
, reg
);
5927 TRACE_INSN (cpu
, "DBG %s;", reg_name
);
5928 sim_io_printf (sd
, "DBG : %s = 0x%08x\n", reg_name
,
5929 reg_read (cpu
, grp
, reg
));
5932 unhandled_instruction (cpu
, "PRNT allregs");
5934 illegal_instruction (cpu
);
5938 decode_psedoOChar_0 (SIM_CPU
*cpu
, bu16 iw0
)
5941 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5942 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |.ch............................|
5943 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5944 int ch
= ((iw0
>> PseudoChr_ch_bits
) & PseudoChr_ch_mask
);
5946 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_psedoOChar
);
5947 TRACE_EXTRACT (cpu
, "%s: ch:%#x", __func__
, ch
);
5948 TRACE_INSN (cpu
, "OUTC %#x;", ch
);
5954 decode_psedodbg_assert_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
, bu32 pc
)
5957 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5958 | 1 | 1 | 1 | 1 | 0 | - | - | - | dbgop |.grp.......|.regtest...|
5959 |.expected......................................................|
5960 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5961 SIM_DESC sd
= CPU_STATE (cpu
);
5962 int expected
= ((iw1
>> PseudoDbg_Assert_expected_bits
) & PseudoDbg_Assert_expected_mask
);
5963 int dbgop
= ((iw0
>> (PseudoDbg_Assert_dbgop_bits
- 16)) & PseudoDbg_Assert_dbgop_mask
);
5964 int grp
= ((iw0
>> (PseudoDbg_Assert_grp_bits
- 16)) & PseudoDbg_Assert_grp_mask
);
5965 int regtest
= ((iw0
>> (PseudoDbg_Assert_regtest_bits
- 16)) & PseudoDbg_Assert_regtest_mask
);
5968 bu32 val
= reg_read (cpu
, grp
, regtest
);
5969 const char *reg_name
= get_allreg_name (grp
, regtest
);
5970 const char *dbg_name
, *dbg_appd
;
5972 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_psedodbg_assert
);
5973 TRACE_EXTRACT (cpu
, "%s: dbgop:%i grp:%i regtest:%i expected:%#x",
5974 __func__
, dbgop
, grp
, regtest
, expected
);
5976 if (dbgop
== 0 || dbgop
== 2)
5978 dbg_name
= dbgop
== 0 ? "DBGA" : "DBGAL";
5979 dbg_appd
= dbgop
== 0 ? ".L" : "";
5982 else if (dbgop
== 1 || dbgop
== 3)
5984 dbg_name
= dbgop
== 1 ? "DBGA" : "DBGAH";
5985 dbg_appd
= dbgop
== 1 ? ".H" : "";
5989 illegal_instruction (cpu
);
5991 actual
= val
>> offset
;
5993 TRACE_INSN (cpu
, "%s (%s%s, 0x%x);", dbg_name
, reg_name
, dbg_appd
, expected
);
5994 if (actual
!= expected
)
5996 sim_io_printf (sd
, "FAIL at %#x: %s (%s%s, 0x%04x); actual value %#x\n",
5997 pc
, dbg_name
, reg_name
, dbg_appd
, expected
, actual
);
5999 /* Decode the actual ASTAT bits that are different. */
6000 if (grp
== 4 && regtest
== 6)
6004 sim_io_printf (sd
, "Expected ASTAT:\n");
6005 for (i
= 0; i
< 16; ++i
)
6006 sim_io_printf (sd
, " %8s%c%i%s",
6007 astat_names
[i
+ offset
],
6008 (((expected
>> i
) & 1) != ((actual
>> i
) & 1))
6010 (expected
>> i
) & 1,
6011 i
== 7 ? "\n" : "");
6012 sim_io_printf (sd
, "\n");
6014 sim_io_printf (sd
, "Actual ASTAT:\n");
6015 for (i
= 0; i
< 16; ++i
)
6016 sim_io_printf (sd
, " %8s%c%i%s",
6017 astat_names
[i
+ offset
],
6018 (((expected
>> i
) & 1) != ((actual
>> i
) & 1))
6021 i
== 7 ? "\n" : "");
6022 sim_io_printf (sd
, "\n");
6025 cec_exception (cpu
, VEC_SIM_DBGA
);
6031 _interp_insn_bfin (SIM_CPU
*cpu
, bu32 pc
)
6036 BFIN_CPU_STATE
.multi_pc
= pc
;
6038 if ((iw0
& 0xc000) != 0xc000)
6040 /* 16-bit opcode. */
6043 INSN_LEN
= insn_len
;
6045 TRACE_EXTRACT (cpu
, "%s: iw0:%#x", __func__
, iw0
);
6046 if ((iw0
& 0xFF00) == 0x0000)
6047 decode_ProgCtrl_0 (cpu
, iw0
, pc
);
6048 else if ((iw0
& 0xFFC0) == 0x0240)
6049 decode_CaCTRL_0 (cpu
, iw0
);
6050 else if ((iw0
& 0xFF80) == 0x0100)
6051 decode_PushPopReg_0 (cpu
, iw0
);
6052 else if ((iw0
& 0xFE00) == 0x0400)
6053 decode_PushPopMultiple_0 (cpu
, iw0
);
6054 else if ((iw0
& 0xFE00) == 0x0600)
6055 decode_ccMV_0 (cpu
, iw0
);
6056 else if ((iw0
& 0xF800) == 0x0800)
6057 decode_CCflag_0 (cpu
, iw0
);
6058 else if ((iw0
& 0xFFE0) == 0x0200)
6059 decode_CC2dreg_0 (cpu
, iw0
);
6060 else if ((iw0
& 0xFF00) == 0x0300)
6061 decode_CC2stat_0 (cpu
, iw0
);
6062 else if ((iw0
& 0xF000) == 0x1000)
6063 decode_BRCC_0 (cpu
, iw0
, pc
);
6064 else if ((iw0
& 0xF000) == 0x2000)
6065 decode_UJUMP_0 (cpu
, iw0
, pc
);
6066 else if ((iw0
& 0xF000) == 0x3000)
6067 decode_REGMV_0 (cpu
, iw0
);
6068 else if ((iw0
& 0xFC00) == 0x4000)
6069 decode_ALU2op_0 (cpu
, iw0
);
6070 else if ((iw0
& 0xFE00) == 0x4400)
6071 decode_PTR2op_0 (cpu
, iw0
);
6072 else if ((iw0
& 0xF800) == 0x4800)
6073 decode_LOGI2op_0 (cpu
, iw0
);
6074 else if ((iw0
& 0xF000) == 0x5000)
6075 decode_COMP3op_0 (cpu
, iw0
);
6076 else if ((iw0
& 0xF800) == 0x6000)
6077 decode_COMPI2opD_0 (cpu
, iw0
);
6078 else if ((iw0
& 0xF800) == 0x6800)
6079 decode_COMPI2opP_0 (cpu
, iw0
);
6080 else if ((iw0
& 0xF000) == 0x8000)
6081 decode_LDSTpmod_0 (cpu
, iw0
);
6082 else if ((iw0
& 0xFF60) == 0x9E60)
6083 decode_dagMODim_0 (cpu
, iw0
);
6084 else if ((iw0
& 0xFFF0) == 0x9F60)
6085 decode_dagMODik_0 (cpu
, iw0
);
6086 else if ((iw0
& 0xFC00) == 0x9C00)
6087 decode_dspLDST_0 (cpu
, iw0
);
6088 else if ((iw0
& 0xF000) == 0x9000)
6089 decode_LDST_0 (cpu
, iw0
);
6090 else if ((iw0
& 0xFC00) == 0xB800)
6091 decode_LDSTiiFP_0 (cpu
, iw0
);
6092 else if ((iw0
& 0xE000) == 0xA000)
6093 decode_LDSTii_0 (cpu
, iw0
);
6096 TRACE_EXTRACT (cpu
, "%s: no matching 16-bit pattern", __func__
);
6097 illegal_instruction (cpu
);
6102 /* Grab the next 16 bits to determine if it's a 32-bit or 64-bit opcode. */
6103 iw1
= IFETCH (pc
+ 2);
6104 if ((iw0
& BIT_MULTI_INS
) && (iw0
& 0xe800) != 0xe800 /* not linkage */)
6106 SIM_DESC sd
= CPU_STATE (cpu
);
6107 trace_prefix (sd
, cpu
, NULL_CIA
, pc
, TRACE_LINENUM_P (cpu
),
6108 NULL
, 0, "|| %#"PRIx64
, sim_events_time (sd
));
6114 TRACE_EXTRACT (cpu
, "%s: iw0:%#x iw1:%#x insn_len:%i", __func__
,
6115 iw0
, iw1
, insn_len
);
6117 /* Only cache on first run through (in case of parallel insns). */
6119 INSN_LEN
= insn_len
;
6121 if ((iw0
& 0xf7ff) == 0xc003 && (iw1
& 0xfe00) == 0x1800)
6123 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32mac
);
6124 TRACE_INSN (cpu
, "MNOP;");
6126 else if (((iw0
& 0xFF80) == 0xE080) && ((iw1
& 0x0C00) == 0x0000))
6127 decode_LoopSetup_0 (cpu
, iw0
, iw1
, pc
);
6128 else if (((iw0
& 0xFF00) == 0xE100) && ((iw1
& 0x0000) == 0x0000))
6129 decode_LDIMMhalf_0 (cpu
, iw0
, iw1
);
6130 else if (((iw0
& 0xFE00) == 0xE200) && ((iw1
& 0x0000) == 0x0000))
6131 decode_CALLa_0 (cpu
, iw0
, iw1
, pc
);
6132 else if (((iw0
& 0xFC00) == 0xE400) && ((iw1
& 0x0000) == 0x0000))
6133 decode_LDSTidxI_0 (cpu
, iw0
, iw1
);
6134 else if (((iw0
& 0xFFFE) == 0xE800) && ((iw1
& 0x0000) == 0x0000))
6135 decode_linkage_0 (cpu
, iw0
, iw1
);
6136 else if (((iw0
& 0xF600) == 0xC000) && ((iw1
& 0x0000) == 0x0000))
6137 decode_dsp32mac_0 (cpu
, iw0
, iw1
);
6138 else if (((iw0
& 0xF600) == 0xC200) && ((iw1
& 0x0000) == 0x0000))
6139 decode_dsp32mult_0 (cpu
, iw0
, iw1
);
6140 else if (((iw0
& 0xF7C0) == 0xC400) && ((iw1
& 0x0000) == 0x0000))
6141 decode_dsp32alu_0 (cpu
, iw0
, iw1
);
6142 else if (((iw0
& 0xF7E0) == 0xC600) && ((iw1
& 0x01C0) == 0x0000))
6143 decode_dsp32shift_0 (cpu
, iw0
, iw1
);
6144 else if (((iw0
& 0xF7E0) == 0xC680) && ((iw1
& 0x0000) == 0x0000))
6145 decode_dsp32shiftimm_0 (cpu
, iw0
, iw1
);
6146 else if ((iw0
& 0xFF00) == 0xF800)
6147 decode_psedoDEBUG_0 (cpu
, iw0
), insn_len
= 2;
6148 else if ((iw0
& 0xFF00) == 0xF900)
6149 decode_psedoOChar_0 (cpu
, iw0
), insn_len
= 2;
6150 else if (((iw0
& 0xFF00) == 0xF000) && ((iw1
& 0x0000) == 0x0000))
6151 decode_psedodbg_assert_0 (cpu
, iw0
, iw1
, pc
);
6154 TRACE_EXTRACT (cpu
, "%s: no matching 32-bit pattern", __func__
);
6155 illegal_instruction (cpu
);
6162 interp_insn_bfin (SIM_CPU
*cpu
, bu32 pc
)
6167 BFIN_CPU_STATE
.n_stores
= 0;
6168 DIS_ALGN_EXPT
&= ~1;
6172 insn_len
= _interp_insn_bfin (cpu
, pc
);
6174 /* Proper display of multiple issue instructions. */
6177 _interp_insn_bfin (cpu
, pc
+ 4);
6178 _interp_insn_bfin (cpu
, pc
+ 6);
6180 for (i
= 0; i
< BFIN_CPU_STATE
.n_stores
; i
++)
6182 bu32
*addr
= BFIN_CPU_STATE
.stores
[i
].addr
;
6183 *addr
= BFIN_CPU_STATE
.stores
[i
].val
;
6184 TRACE_REGISTER (cpu
, "dequeuing write %s = %#x",
6185 get_store_name (cpu
, addr
), *addr
);
6188 cycles_inc (cpu
, CYCLE_DELAY
);
6190 /* Set back to zero in case a pending CEC event occurs
6191 after this this insn. */