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 /* In signed modes, sign extend. */
1384 if (is_macmod_signed (mmod
) || MM
)
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
);
1520 return saturate_s32 (res
, overflow
);
1521 return saturate_u32 (res
, overflow
);
1524 return saturate_s32 (res
, overflow
);
1525 return saturate_u32 (res
, overflow
);
1528 return saturate_s32 (res
<< 1, overflow
);
1530 illegal_instruction (cpu
);
1538 return saturate_s16 (rnd16 (res
), overflow
);
1540 return saturate_s16 (res
, overflow
);
1543 return saturate_s16 (rnd16 (res
), overflow
);
1544 return saturate_u16 (rnd16 (res
), overflow
);
1547 return saturate_s16 (res
, overflow
);
1548 return saturate_u16 (res
, overflow
);
1551 return saturate_s16 (trunc16 (res
), overflow
);
1554 return saturate_s16 (trunc16 (res
), overflow
);
1555 return saturate_u16 (trunc16 (res
), overflow
);
1558 return saturate_s16 (rnd16 (res
<< 1), overflow
);
1560 return saturate_s16 (res
<< 1, overflow
);
1562 illegal_instruction (cpu
);
1567 decode_macfunc (SIM_CPU
*cpu
, int which
, int op
, int h0
, int h1
, int src0
,
1568 int src1
, int mmod
, int MM
, int fullword
, bu32
*overflow
,
1572 bu32 sat
= 0, tsat
, ret
;
1574 /* Sign extend accumulator if necessary, otherwise unsigned. */
1575 if (is_macmod_signed (mmod
) || MM
)
1576 acc
= get_extended_acc (cpu
, which
);
1578 acc
= get_unextended_acc (cpu
, which
);
1582 bu8 sgn0
= (acc
>> 31) & 1;
1583 bu8 sgn40
= (acc
>> 39) & 1;
1586 /* This can't saturate, so we don't keep track of the sat flag. */
1587 bu64 res
= decode_multfunc (cpu
, h0
, h1
, src0
, src1
, mmod
,
1590 /* Perform accumulation. */
1595 sgn0
= (acc
>> 31) & 1;
1614 if ((bs64
)acc
< -((bs64
)1 << 39))
1615 acc
= -((bu64
)1 << 39), sat
= 1;
1616 else if ((bs64
)acc
> 0x7fffffffffll
)
1617 acc
= 0x7fffffffffull
, sat
= 1;
1620 if (!MM
&& (bs64
)acc
< 0)
1622 if (!MM
&& (bs64
)acc
> 0xFFFFFFFFFFull
)
1623 acc
= 0xFFFFFFFFFFull
, sat
= 1;
1626 if (!MM
&& acc
& 0x8000000000000000ull
)
1628 if (!MM
&& acc
> 0xFFFFFFFFFFull
)
1629 acc
= 0xFFFFFFFFFFull
, sat
= 1;
1630 if (MM
&& acc
> 0xFFFFFFFFFFull
)
1631 acc
&= 0xFFFFFFFFFFull
;
1632 if (acc
& 0x8000000000ull
)
1633 acc
|= 0xffffff0000000000ull
;
1636 if (!MM
&& (bs64
)acc
< 0)
1638 if (MM
&& (bs64
)acc
< -((bs64
)1 << 39))
1639 acc
= -((bu64
)1 << 39), sat
= 1;
1640 if (!MM
&& (bs64
)acc
> (bs64
)0xFFFFFFFFFFll
)
1641 acc
= 0xFFFFFFFFFFull
, sat
= 1;
1642 if (MM
&& acc
> 0xFFFFFFFFFFull
)
1643 acc
&= 0xFFFFFFFFFFull
;
1644 if (MM
&& acc
& 0x8000000000ull
)
1645 acc
|= 0xffffff0000000000ull
;
1648 if ((bs64
)acc
< -0x80000000ll
)
1649 acc
= -0x80000000ull
, sat
= 1;
1650 else if ((bs64
)acc
> 0x7fffffffll
)
1651 acc
= 0x7fffffffull
, sat
= 1;
1654 /* check max negative value */
1655 if (sgn40
&& ((acc
>> 31) != 0x1ffffffff)
1656 && ((acc
>> 31) != 0x0))
1657 acc
= 0x80000000, sat
= 1;
1658 if (!sat
&& !sgn40
&& ((acc
>> 31) != 0x0)
1659 && ((acc
>> 31) != 0x1ffffffff))
1660 acc
= 0x7FFFFFFF, sat
= 1;
1662 if (acc
& 0x80000000)
1663 acc
|= 0xffffffff00000000ull
;
1668 illegal_instruction (cpu
);
1671 if (acc
& 0x8000000000ull
)
1674 STORE (AXREG (which
), (acc
>> 32) & 0xff);
1675 STORE (AWREG (which
), acc
& 0xffffffff);
1676 STORE (ASTATREG (av
[which
]), sat
);
1678 STORE (ASTATREG (avs
[which
]), sat
);
1680 /* Figure out the overflow bit. */
1686 ret
= extract_mult (cpu
, nosat_acc
, mmod
, MM
, fullword
, overflow
);
1690 ret
= extract_mult (cpu
, acc
, mmod
, MM
, fullword
, overflow
);
1699 if (ret
& 0x80000000)
1707 hwloop_get_next_pc (SIM_CPU
*cpu
, bu32 pc
, bu32 insn_len
)
1714 /* If our PC has reached the bottom of a hardware loop,
1715 move back up to the top of the hardware loop. */
1716 for (i
= 1; i
>= 0; --i
)
1717 if (LCREG (i
) > 1 && pc
== LBREG (i
))
1719 TRACE_BRANCH (cpu
, pc
, LTREG (i
), i
, "Hardware loop %i", i
);
1723 return pc
+ insn_len
;
1727 decode_ProgCtrl_0 (SIM_CPU
*cpu
, bu16 iw0
, bu32 pc
)
1730 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
1731 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |.prgfunc.......|.poprnd........|
1732 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
1733 int poprnd
= ((iw0
>> ProgCtrl_poprnd_bits
) & ProgCtrl_poprnd_mask
);
1734 int prgfunc
= ((iw0
>> ProgCtrl_prgfunc_bits
) & ProgCtrl_prgfunc_mask
);
1736 TRACE_EXTRACT (cpu
, "%s: poprnd:%i prgfunc:%i", __func__
, poprnd
, prgfunc
);
1738 if (prgfunc
== 0 && poprnd
== 0)
1740 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_nop
);
1741 TRACE_INSN (cpu
, "NOP;");
1743 else if (prgfunc
== 1 && poprnd
== 0)
1745 bu32 newpc
= RETSREG
;
1746 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1747 TRACE_INSN (cpu
, "RTS;");
1748 IFETCH_CHECK (newpc
);
1750 illegal_instruction_combination (cpu
);
1751 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "RTS");
1753 BFIN_CPU_STATE
.did_jump
= true;
1756 else if (prgfunc
== 1 && poprnd
== 1)
1758 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1759 TRACE_INSN (cpu
, "RTI;");
1760 /* Do not do IFETCH_CHECK here -- LSB has special meaning. */
1762 illegal_instruction_combination (cpu
);
1763 cec_return (cpu
, -1);
1766 else if (prgfunc
== 1 && poprnd
== 2)
1768 bu32 newpc
= RETXREG
;
1769 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1770 TRACE_INSN (cpu
, "RTX;");
1771 /* XXX: Not sure if this is what the hardware does. */
1772 IFETCH_CHECK (newpc
);
1774 illegal_instruction_combination (cpu
);
1775 cec_return (cpu
, IVG_EVX
);
1778 else if (prgfunc
== 1 && poprnd
== 3)
1780 bu32 newpc
= RETNREG
;
1781 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1782 TRACE_INSN (cpu
, "RTN;");
1783 /* XXX: Not sure if this is what the hardware does. */
1784 IFETCH_CHECK (newpc
);
1786 illegal_instruction_combination (cpu
);
1787 cec_return (cpu
, IVG_NMI
);
1790 else if (prgfunc
== 1 && poprnd
== 4)
1792 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1793 TRACE_INSN (cpu
, "RTE;");
1795 illegal_instruction_combination (cpu
);
1796 cec_return (cpu
, IVG_EMU
);
1799 else if (prgfunc
== 2 && poprnd
== 0)
1801 SIM_DESC sd
= CPU_STATE (cpu
);
1802 sim_events
*events
= STATE_EVENTS (sd
);
1804 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_sync
);
1805 /* XXX: in supervisor mode, utilizes wake up sources
1806 in user mode, it's a NOP ... */
1807 TRACE_INSN (cpu
, "IDLE;");
1810 illegal_instruction_combination (cpu
);
1814 CYCLE_DELAY
= events
->time_from_event
;
1816 abort (); /* XXX: Should this ever happen ? */
1818 else if (prgfunc
== 2 && poprnd
== 3)
1820 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_sync
);
1822 TRACE_INSN (cpu
, "CSYNC;");
1824 illegal_instruction_combination (cpu
);
1827 else if (prgfunc
== 2 && poprnd
== 4)
1829 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_sync
);
1831 TRACE_INSN (cpu
, "SSYNC;");
1833 illegal_instruction_combination (cpu
);
1835 /* Really 10+, but no model info for this. */
1838 else if (prgfunc
== 2 && poprnd
== 5)
1840 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1841 TRACE_INSN (cpu
, "EMUEXCPT;");
1843 illegal_instruction_combination (cpu
);
1844 cec_exception (cpu
, VEC_SIM_TRAP
);
1846 else if (prgfunc
== 3 && poprnd
< 8)
1848 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1849 TRACE_INSN (cpu
, "CLI R%i;", poprnd
);
1851 illegal_instruction_combination (cpu
);
1852 SET_DREG (poprnd
, cec_cli (cpu
));
1854 else if (prgfunc
== 4 && poprnd
< 8)
1856 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1857 TRACE_INSN (cpu
, "STI R%i;", poprnd
);
1859 illegal_instruction_combination (cpu
);
1860 cec_sti (cpu
, DREG (poprnd
));
1863 else if (prgfunc
== 5 && poprnd
< 8)
1865 bu32 newpc
= PREG (poprnd
);
1866 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1867 TRACE_INSN (cpu
, "JUMP (%s);", get_preg_name (poprnd
));
1868 IFETCH_CHECK (newpc
);
1870 illegal_instruction_combination (cpu
);
1871 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP (Preg)");
1873 BFIN_CPU_STATE
.did_jump
= true;
1874 PROFILE_BRANCH_TAKEN (cpu
);
1877 else if (prgfunc
== 6 && poprnd
< 8)
1879 bu32 newpc
= PREG (poprnd
);
1880 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1881 TRACE_INSN (cpu
, "CALL (%s);", get_preg_name (poprnd
));
1882 IFETCH_CHECK (newpc
);
1884 illegal_instruction_combination (cpu
);
1885 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "CALL (Preg)");
1886 /* If we're at the end of a hardware loop, RETS is going to be
1887 the top of the loop rather than the next instruction. */
1888 SET_RETSREG (hwloop_get_next_pc (cpu
, pc
, 2));
1890 BFIN_CPU_STATE
.did_jump
= true;
1891 PROFILE_BRANCH_TAKEN (cpu
);
1894 else if (prgfunc
== 7 && poprnd
< 8)
1896 bu32 newpc
= pc
+ PREG (poprnd
);
1897 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1898 TRACE_INSN (cpu
, "CALL (PC + %s);", get_preg_name (poprnd
));
1899 IFETCH_CHECK (newpc
);
1901 illegal_instruction_combination (cpu
);
1902 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "CALL (PC + Preg)");
1903 SET_RETSREG (hwloop_get_next_pc (cpu
, pc
, 2));
1905 BFIN_CPU_STATE
.did_jump
= true;
1906 PROFILE_BRANCH_TAKEN (cpu
);
1909 else if (prgfunc
== 8 && poprnd
< 8)
1911 bu32 newpc
= pc
+ PREG (poprnd
);
1912 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1913 TRACE_INSN (cpu
, "JUMP (PC + %s);", get_preg_name (poprnd
));
1914 IFETCH_CHECK (newpc
);
1916 illegal_instruction_combination (cpu
);
1917 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP (PC + Preg)");
1919 BFIN_CPU_STATE
.did_jump
= true;
1920 PROFILE_BRANCH_TAKEN (cpu
);
1923 else if (prgfunc
== 9)
1925 int raise
= uimm4 (poprnd
);
1926 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1927 TRACE_INSN (cpu
, "RAISE %s;", uimm4_str (raise
));
1929 illegal_instruction_combination (cpu
);
1930 cec_require_supervisor (cpu
);
1931 if (raise
== IVG_IVHW
)
1932 cec_hwerr (cpu
, HWERR_RAISE_5
);
1934 cec_latch (cpu
, raise
);
1935 CYCLE_DELAY
= 3; /* XXX: Only if IVG is unmasked. */
1937 else if (prgfunc
== 10)
1939 int excpt
= uimm4 (poprnd
);
1940 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1941 TRACE_INSN (cpu
, "EXCPT %s;", uimm4_str (excpt
));
1943 illegal_instruction_combination (cpu
);
1944 cec_exception (cpu
, excpt
);
1947 else if (prgfunc
== 11 && poprnd
< 6)
1949 bu32 addr
= PREG (poprnd
);
1951 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_atomic
);
1952 TRACE_INSN (cpu
, "TESTSET (%s);", get_preg_name (poprnd
));
1954 illegal_instruction_combination (cpu
);
1955 byte
= GET_WORD (addr
);
1956 SET_CCREG (byte
== 0);
1957 PUT_BYTE (addr
, byte
| 0x80);
1958 /* Also includes memory stalls, but we don't model that. */
1962 illegal_instruction (cpu
);
1966 decode_CaCTRL_0 (SIM_CPU
*cpu
, bu16 iw0
)
1969 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
1970 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 |.a.|.op....|.reg.......|
1971 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
1972 int a
= ((iw0
>> CaCTRL_a_bits
) & CaCTRL_a_mask
);
1973 int op
= ((iw0
>> CaCTRL_op_bits
) & CaCTRL_op_mask
);
1974 int reg
= ((iw0
>> CaCTRL_reg_bits
) & CaCTRL_reg_mask
);
1975 bu32 preg
= PREG (reg
);
1976 const char * const sinsn
[] = { "PREFETCH", "FLUSHINV", "FLUSH", "IFLUSH", };
1978 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CaCTRL
);
1979 TRACE_EXTRACT (cpu
, "%s: a:%i op:%i reg:%i", __func__
, a
, op
, reg
);
1980 TRACE_INSN (cpu
, "%s [%s%s];", sinsn
[op
], get_preg_name (reg
), a
? "++" : "");
1983 /* None of these can be part of a parallel instruction. */
1984 illegal_instruction_combination (cpu
);
1986 /* No cache simulation, so these are (mostly) all NOPs.
1987 XXX: The hardware takes care of masking to cache lines, but need
1988 to check behavior of the post increment. Should we be aligning
1989 the value to the cache line before adding the cache line size, or
1990 do we just add the cache line size ? */
1993 mmu_check_cache_addr (cpu
, preg
, false, false);
1997 mmu_check_cache_addr (cpu
, preg
, true, false);
2001 mmu_check_cache_addr (cpu
, preg
, true, false);
2005 mmu_check_cache_addr (cpu
, preg
, false, true);
2009 SET_PREG (reg
, preg
+ BFIN_L1_CACHE_BYTES
);
2013 decode_PushPopReg_0 (SIM_CPU
*cpu
, bu16 iw0
)
2016 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2017 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |.W.|.grp.......|.reg.......|
2018 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2019 int W
= ((iw0
>> PushPopReg_W_bits
) & PushPopReg_W_mask
);
2020 int grp
= ((iw0
>> PushPopReg_grp_bits
) & PushPopReg_grp_mask
);
2021 int reg
= ((iw0
>> PushPopReg_reg_bits
) & PushPopReg_reg_mask
);
2022 const char *reg_name
= get_allreg_name (grp
, reg
);
2026 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_PushPopReg
);
2027 TRACE_EXTRACT (cpu
, "%s: W:%i grp:%i reg:%i", __func__
, W
, grp
, reg
);
2028 TRACE_DECODE (cpu
, "%s: reg:%s", __func__
, reg_name
);
2030 /* Can't push/pop reserved registers */
2031 if (reg_is_reserved (grp
, reg
))
2032 illegal_instruction (cpu
);
2036 /* Dreg and Preg are not supported by this instruction. */
2037 if (grp
== 0 || grp
== 1)
2038 illegal_instruction (cpu
);
2039 TRACE_INSN (cpu
, "%s = [SP++];", reg_name
);
2040 /* Can't pop USP while in userspace. */
2041 if (INSN_LEN
== 8 || (grp
== 7 && reg
== 0 && cec_is_user_mode(cpu
)))
2042 illegal_instruction_combination (cpu
);
2043 /* XXX: The valid register check is in reg_write(), so we might
2044 incorrectly do a GET_LONG() here ... */
2045 value
= GET_LONG (sp
);
2046 reg_write (cpu
, grp
, reg
, value
);
2047 if (grp
== 7 && reg
== 3)
2054 TRACE_INSN (cpu
, "[--SP] = %s;", reg_name
);
2056 illegal_instruction_combination (cpu
);
2059 value
= reg_read (cpu
, grp
, reg
);
2060 if (grp
== 7 && reg
== 3)
2061 cec_push_reti (cpu
);
2063 PUT_LONG (sp
, value
);
2066 /* Note: SP update must be delayed until after all reads/writes; see
2067 comments in decode_PushPopMultiple_0() for more info. */
2072 decode_PushPopMultiple_0 (SIM_CPU
*cpu
, bu16 iw0
)
2075 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2076 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |.d.|.p.|.W.|.dr........|.pr........|
2077 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2078 int p
= ((iw0
>> PushPopMultiple_p_bits
) & PushPopMultiple_p_mask
);
2079 int d
= ((iw0
>> PushPopMultiple_d_bits
) & PushPopMultiple_d_mask
);
2080 int W
= ((iw0
>> PushPopMultiple_W_bits
) & PushPopMultiple_W_mask
);
2081 int dr
= ((iw0
>> PushPopMultiple_dr_bits
) & PushPopMultiple_dr_mask
);
2082 int pr
= ((iw0
>> PushPopMultiple_pr_bits
) & PushPopMultiple_pr_mask
);
2086 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_PushPopMultiple
);
2087 TRACE_EXTRACT (cpu
, "%s: d:%i p:%i W:%i dr:%i pr:%i",
2088 __func__
, d
, p
, W
, dr
, pr
);
2090 if ((d
== 0 && p
== 0) || (p
&& imm5 (pr
) > 5)
2091 || (d
&& !p
&& pr
) || (p
&& !d
&& dr
))
2092 illegal_instruction (cpu
);
2097 TRACE_INSN (cpu
, "[--SP] = (R7:%i, P5:%i);", dr
, pr
);
2099 TRACE_INSN (cpu
, "[--SP] = (R7:%i);", dr
);
2101 TRACE_INSN (cpu
, "[--SP] = (P5:%i);", pr
);
2104 for (i
= dr
; i
< 8; i
++)
2107 PUT_LONG (sp
, DREG (i
));
2110 for (i
= pr
; i
< 6; i
++)
2113 PUT_LONG (sp
, PREG (i
));
2121 TRACE_INSN (cpu
, "(R7:%i, P5:%i) = [SP++];", dr
, pr
);
2123 TRACE_INSN (cpu
, "(R7:%i) = [SP++];", dr
);
2125 TRACE_INSN (cpu
, "(P5:%i) = [SP++];", pr
);
2128 for (i
= 5; i
>= pr
; i
--)
2130 SET_PREG (i
, GET_LONG (sp
));
2134 for (i
= 7; i
>= dr
; i
--)
2136 SET_DREG (i
, GET_LONG (sp
));
2143 /* Note: SP update must be delayed until after all reads/writes so that
2144 if an exception does occur, the insn may be re-executed as the
2145 SP has not yet changed. */
2150 decode_ccMV_0 (SIM_CPU
*cpu
, bu16 iw0
)
2153 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2154 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |.T.|.d.|.s.|.dst.......|.src.......|
2155 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2156 int s
= ((iw0
>> CCmv_s_bits
) & CCmv_s_mask
);
2157 int d
= ((iw0
>> CCmv_d_bits
) & CCmv_d_mask
);
2158 int T
= ((iw0
>> CCmv_T_bits
) & CCmv_T_mask
);
2159 int src
= ((iw0
>> CCmv_src_bits
) & CCmv_src_mask
);
2160 int dst
= ((iw0
>> CCmv_dst_bits
) & CCmv_dst_mask
);
2161 int cond
= T
? CCREG
: ! CCREG
;
2163 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ccMV
);
2164 TRACE_EXTRACT (cpu
, "%s: T:%i d:%i s:%i dst:%i src:%i",
2165 __func__
, T
, d
, s
, dst
, src
);
2167 TRACE_INSN (cpu
, "IF %sCC %s = %s;", T
? "" : "! ",
2168 get_allreg_name (d
, dst
),
2169 get_allreg_name (s
, src
));
2171 illegal_instruction_combination (cpu
);
2174 reg_write (cpu
, d
, dst
, reg_read (cpu
, s
, src
));
2178 decode_CCflag_0 (SIM_CPU
*cpu
, bu16 iw0
)
2181 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2182 | 0 | 0 | 0 | 0 | 1 |.I.|.opc.......|.G.|.y.........|.x.........|
2183 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2184 int x
= ((iw0
>> CCflag_x_bits
) & CCflag_x_mask
);
2185 int y
= ((iw0
>> CCflag_y_bits
) & CCflag_y_mask
);
2186 int I
= ((iw0
>> CCflag_I_bits
) & CCflag_I_mask
);
2187 int G
= ((iw0
>> CCflag_G_bits
) & CCflag_G_mask
);
2188 int opc
= ((iw0
>> CCflag_opc_bits
) & CCflag_opc_mask
);
2190 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CCflag
);
2191 TRACE_EXTRACT (cpu
, "%s: I:%i opc:%i G:%i y:%i x:%i",
2192 __func__
, I
, opc
, G
, y
, x
);
2196 bs64 acc0
= get_extended_acc (cpu
, 0);
2197 bs64 acc1
= get_extended_acc (cpu
, 1);
2198 bs64 diff
= acc0
- acc1
;
2200 if (x
!= 0 || y
!= 0)
2201 illegal_instruction (cpu
);
2203 if (opc
== 5 && I
== 0 && G
== 0)
2205 TRACE_INSN (cpu
, "CC = A0 == A1;");
2207 illegal_instruction_combination (cpu
);
2208 SET_CCREG (acc0
== acc1
);
2210 else if (opc
== 6 && I
== 0 && G
== 0)
2212 TRACE_INSN (cpu
, "CC = A0 < A1");
2214 illegal_instruction_combination (cpu
);
2215 SET_CCREG (acc0
< acc1
);
2217 else if (opc
== 7 && I
== 0 && G
== 0)
2219 TRACE_INSN (cpu
, "CC = A0 <= A1");
2221 illegal_instruction_combination (cpu
);
2222 SET_CCREG (acc0
<= acc1
);
2225 illegal_instruction (cpu
);
2227 SET_ASTATREG (az
, diff
== 0);
2228 SET_ASTATREG (an
, diff
< 0);
2229 SET_ASTATREG (ac0
, (bu40
)acc1
<= (bu40
)acc0
);
2233 int issigned
= opc
< 3;
2234 const char *sign
= issigned
? "" : " (IU)";
2235 bu32 srcop
= G
? PREG (x
) : DREG (x
);
2236 char s
= G
? 'P' : 'R';
2237 bu32 dstop
= I
? (issigned
? imm3 (y
) : uimm3 (y
)) : G
? PREG (y
) : DREG (y
);
2239 char d
= G
? 'P' : 'R';
2240 int flgs
= srcop
>> 31;
2241 int flgo
= dstop
>> 31;
2243 bu32 result
= srcop
- dstop
;
2245 int flgn
= result
>> 31;
2246 int overflow
= (flgs
^ flgo
) & (flgn
^ flgs
);
2247 int az
= result
== 0;
2248 int ac0
= dstop
<= srcop
;
2251 an
= (flgn
&& !overflow
) || (!flgn
&& overflow
);
2257 default: /* Shutup useless gcc warnings. */
2258 case 0: /* signed */
2262 case 1: /* signed */
2266 case 2: /* signed */
2270 case 3: /* unsigned */
2274 case 4: /* unsigned */
2281 TRACE_INSN (cpu
, "CC = %c%i %s %s%s;", s
, x
, op
,
2282 issigned
? imm3_str (y
) : uimm3_str (y
), sign
);
2285 TRACE_DECODE (cpu
, "%s %c%i:%x %c%i:%x", __func__
,
2286 s
, x
, srcop
, d
, y
, dstop
);
2287 TRACE_INSN (cpu
, "CC = %c%i %s %c%i%s;", s
, x
, op
, d
, y
, sign
);
2291 /* Pointer compares only touch CC. */
2294 SET_ASTATREG (az
, az
);
2295 SET_ASTATREG (an
, an
);
2296 SET_ASTATREG (ac0
, ac0
);
2302 decode_CC2dreg_0 (SIM_CPU
*cpu
, bu16 iw0
)
2305 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2306 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |.op....|.reg.......|
2307 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2308 int op
= ((iw0
>> CC2dreg_op_bits
) & CC2dreg_op_mask
);
2309 int reg
= ((iw0
>> CC2dreg_reg_bits
) & CC2dreg_reg_mask
);
2311 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CC2dreg
);
2312 TRACE_EXTRACT (cpu
, "%s: op:%i reg:%i", __func__
, op
, reg
);
2316 TRACE_INSN (cpu
, "R%i = CC;", reg
);
2318 illegal_instruction_combination (cpu
);
2319 SET_DREG (reg
, CCREG
);
2323 TRACE_INSN (cpu
, "CC = R%i;", reg
);
2325 illegal_instruction_combination (cpu
);
2326 SET_CCREG (DREG (reg
) != 0);
2328 else if (op
== 3 && reg
== 0)
2330 TRACE_INSN (cpu
, "CC = !CC;");
2332 illegal_instruction_combination (cpu
);
2336 illegal_instruction (cpu
);
2340 decode_CC2stat_0 (SIM_CPU
*cpu
, bu16 iw0
)
2343 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2344 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |.D.|.op....|.cbit..............|
2345 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2346 int D
= ((iw0
>> CC2stat_D_bits
) & CC2stat_D_mask
);
2347 int op
= ((iw0
>> CC2stat_op_bits
) & CC2stat_op_mask
);
2348 int cbit
= ((iw0
>> CC2stat_cbit_bits
) & CC2stat_cbit_mask
);
2351 const char * const op_names
[] = { "", "|", "&", "^" } ;
2353 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CC2stat
);
2354 TRACE_EXTRACT (cpu
, "%s: D:%i op:%i cbit:%i", __func__
, D
, op
, cbit
);
2356 TRACE_INSN (cpu
, "%s %s= %s;", D
? astat_names
[cbit
] : "CC",
2357 op_names
[op
], D
? "CC" : astat_names
[cbit
]);
2359 /* CC = CC; is invalid. */
2361 illegal_instruction (cpu
);
2364 illegal_instruction_combination (cpu
);
2366 pval
= !!(ASTAT
& (1 << cbit
));
2370 case 0: SET_CCREG (pval
); break;
2371 case 1: SET_CCREG (CCREG
| pval
); break;
2372 case 2: SET_CCREG (CCREG
& pval
); break;
2373 case 3: SET_CCREG (CCREG
^ pval
); break;
2379 case 0: pval
= CCREG
; break;
2380 case 1: pval
|= CCREG
; break;
2381 case 2: pval
&= CCREG
; break;
2382 case 3: pval
^= CCREG
; break;
2384 TRACE_REGISTER (cpu
, "wrote ASTAT[%s] = %i", astat_names
[cbit
], pval
);
2385 SET_ASTAT ((ASTAT
& ~(1 << cbit
)) | (pval
<< cbit
));
2390 decode_BRCC_0 (SIM_CPU
*cpu
, bu16 iw0
, bu32 pc
)
2393 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2394 | 0 | 0 | 0 | 1 |.T.|.B.|.offset................................|
2395 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2396 int B
= ((iw0
>> BRCC_B_bits
) & BRCC_B_mask
);
2397 int T
= ((iw0
>> BRCC_T_bits
) & BRCC_T_mask
);
2398 int offset
= ((iw0
>> BRCC_offset_bits
) & BRCC_offset_mask
);
2399 int cond
= T
? CCREG
: ! CCREG
;
2400 int pcrel
= pcrel10 (offset
);
2402 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_BRCC
);
2403 TRACE_EXTRACT (cpu
, "%s: T:%i B:%i offset:%#x", __func__
, T
, B
, offset
);
2404 TRACE_DECODE (cpu
, "%s: pcrel10:%#x", __func__
, pcrel
);
2406 TRACE_INSN (cpu
, "IF %sCC JUMP %#x%s;", T
? "" : "! ",
2407 pcrel
, B
? " (bp)" : "");
2410 illegal_instruction_combination (cpu
);
2414 bu32 newpc
= pc
+ pcrel
;
2415 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "Conditional JUMP");
2417 BFIN_CPU_STATE
.did_jump
= true;
2418 PROFILE_BRANCH_TAKEN (cpu
);
2419 CYCLE_DELAY
= B
? 5 : 9;
2423 PROFILE_BRANCH_UNTAKEN (cpu
);
2424 CYCLE_DELAY
= B
? 9 : 1;
2429 decode_UJUMP_0 (SIM_CPU
*cpu
, bu16 iw0
, bu32 pc
)
2432 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2433 | 0 | 0 | 1 | 0 |.offset........................................|
2434 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2435 int offset
= ((iw0
>> UJump_offset_bits
) & UJump_offset_mask
);
2436 int pcrel
= pcrel12 (offset
);
2437 bu32 newpc
= pc
+ pcrel
;
2439 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_UJUMP
);
2440 TRACE_EXTRACT (cpu
, "%s: offset:%#x", __func__
, offset
);
2441 TRACE_DECODE (cpu
, "%s: pcrel12:%#x", __func__
, pcrel
);
2443 TRACE_INSN (cpu
, "JUMP.S %#x;", pcrel
);
2446 illegal_instruction_combination (cpu
);
2448 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP.S");
2451 BFIN_CPU_STATE
.did_jump
= true;
2452 PROFILE_BRANCH_TAKEN (cpu
);
2457 decode_REGMV_0 (SIM_CPU
*cpu
, bu16 iw0
)
2460 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2461 | 0 | 0 | 1 | 1 |.gd........|.gs........|.dst.......|.src.......|
2462 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2463 int gs
= ((iw0
>> RegMv_gs_bits
) & RegMv_gs_mask
);
2464 int gd
= ((iw0
>> RegMv_gd_bits
) & RegMv_gd_mask
);
2465 int src
= ((iw0
>> RegMv_src_bits
) & RegMv_src_mask
);
2466 int dst
= ((iw0
>> RegMv_dst_bits
) & RegMv_dst_mask
);
2467 const char *srcreg_name
= get_allreg_name (gs
, src
);
2468 const char *dstreg_name
= get_allreg_name (gd
, dst
);
2470 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_REGMV
);
2471 TRACE_EXTRACT (cpu
, "%s: gd:%i gs:%i dst:%i src:%i",
2472 __func__
, gd
, gs
, dst
, src
);
2473 TRACE_DECODE (cpu
, "%s: dst:%s src:%s", __func__
, dstreg_name
, srcreg_name
);
2475 TRACE_INSN (cpu
, "%s = %s;", dstreg_name
, srcreg_name
);
2477 /* Reserved slots cannot be a src/dst. */
2478 if (reg_is_reserved (gs
, src
) || reg_is_reserved (gd
, dst
))
2481 /* Standard register moves. */
2482 if ((gs
< 2) /* Dregs/Pregs src */
2483 || (gd
< 2) /* Dregs/Pregs dst */
2484 || (gs
== 4 && src
< 4) /* Accumulators src */
2485 || (gd
== 4 && dst
< 4 && (gs
< 4)) /* Accumulators dst */
2486 || (gs
== 7 && src
== 7 && !(gd
== 4 && dst
< 4)) /* EMUDAT src */
2487 || (gd
== 7 && dst
== 7)) /* EMUDAT dst */
2490 /* dareg = dareg (IMBL) */
2491 if (gs
< 4 && gd
< 4)
2494 /* USP can be src to sysregs, but not dagregs. */
2495 if ((gs
== 7 && src
== 0) && (gd
>= 4))
2498 /* USP can move between genregs (only check Accumulators). */
2499 if (((gs
== 7 && src
== 0) && (gd
== 4 && dst
< 4))
2500 || ((gd
== 7 && dst
== 0) && (gs
== 4 && src
< 4)))
2503 /* Still here ? Invalid reg pair. */
2505 illegal_instruction (cpu
);
2508 reg_write (cpu
, gd
, dst
, reg_read (cpu
, gs
, src
));
2512 decode_ALU2op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2515 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2516 | 0 | 1 | 0 | 0 | 0 | 0 |.opc...........|.src.......|.dst.......|
2517 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2518 int src
= ((iw0
>> ALU2op_src_bits
) & ALU2op_src_mask
);
2519 int opc
= ((iw0
>> ALU2op_opc_bits
) & ALU2op_opc_mask
);
2520 int dst
= ((iw0
>> ALU2op_dst_bits
) & ALU2op_dst_mask
);
2522 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ALU2op
);
2523 TRACE_EXTRACT (cpu
, "%s: opc:%i src:%i dst:%i", __func__
, opc
, src
, dst
);
2527 TRACE_INSN (cpu
, "R%i >>>= R%i;", dst
, src
);
2528 SET_DREG (dst
, ashiftrt (cpu
, DREG (dst
), DREG (src
), 32));
2533 TRACE_INSN (cpu
, "R%i >>= R%i;", dst
, src
);
2534 if (DREG (src
) <= 0x1F)
2535 val
= lshiftrt (cpu
, DREG (dst
), DREG (src
), 32);
2538 SET_DREG (dst
, val
);
2542 TRACE_INSN (cpu
, "R%i <<= R%i;", dst
, src
);
2543 SET_DREG (dst
, lshift (cpu
, DREG (dst
), DREG (src
), 32, 0));
2547 TRACE_INSN (cpu
, "R%i *= R%i;", dst
, src
);
2548 SET_DREG (dst
, DREG (dst
) * DREG (src
));
2553 TRACE_INSN (cpu
, "R%i = (R%i + R%i) << 1;", dst
, dst
, src
);
2554 SET_DREG (dst
, add_and_shift (cpu
, DREG (dst
), DREG (src
), 1));
2558 TRACE_INSN (cpu
, "R%i = (R%i + R%i) << 2;", dst
, dst
, src
);
2559 SET_DREG (dst
, add_and_shift (cpu
, DREG (dst
), DREG (src
), 2));
2563 TRACE_INSN (cpu
, "DIVQ ( R%i, R%i );", dst
, src
);
2564 SET_DREG (dst
, divq (cpu
, DREG (dst
), (bu16
)DREG (src
)));
2568 TRACE_INSN (cpu
, "DIVS ( R%i, R%i );", dst
, src
);
2569 SET_DREG (dst
, divs (cpu
, DREG (dst
), (bu16
)DREG (src
)));
2573 TRACE_INSN (cpu
, "R%i = R%i.L (X);", dst
, src
);
2574 SET_DREG (dst
, (bs32
) (bs16
) DREG (src
));
2575 setflags_logical (cpu
, DREG (dst
));
2579 TRACE_INSN (cpu
, "R%i = R%i.L (Z);", dst
, src
);
2580 SET_DREG (dst
, (bu32
) (bu16
) DREG (src
));
2581 setflags_logical (cpu
, DREG (dst
));
2585 TRACE_INSN (cpu
, "R%i = R%i.B (X);", dst
, src
);
2586 SET_DREG (dst
, (bs32
) (bs8
) DREG (src
));
2587 setflags_logical (cpu
, DREG (dst
));
2591 TRACE_INSN (cpu
, "R%i = R%i.B (Z);", dst
, src
);
2592 SET_DREG (dst
, (bu32
) (bu8
) DREG (src
));
2593 setflags_logical (cpu
, DREG (dst
));
2597 bu32 val
= DREG (src
);
2598 TRACE_INSN (cpu
, "R%i = - R%i;", dst
, src
);
2599 SET_DREG (dst
, -val
);
2600 setflags_nz (cpu
, DREG (dst
));
2601 SET_ASTATREG (v
, val
== 0x80000000);
2603 SET_ASTATREG (vs
, 1);
2604 SET_ASTATREG (ac0
, val
== 0x0);
2605 /* XXX: Documentation isn't entirely clear about av0 and av1. */
2609 TRACE_INSN (cpu
, "R%i = ~ R%i;", dst
, src
);
2610 SET_DREG (dst
, ~DREG (src
));
2611 setflags_logical (cpu
, DREG (dst
));
2614 illegal_instruction (cpu
);
2618 decode_PTR2op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2621 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2622 | 0 | 1 | 0 | 0 | 0 | 1 | 0 |.opc.......|.src.......|.dst.......|
2623 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2624 int src
= ((iw0
>> PTR2op_src_bits
) & PTR2op_dst_mask
);
2625 int opc
= ((iw0
>> PTR2op_opc_bits
) & PTR2op_opc_mask
);
2626 int dst
= ((iw0
>> PTR2op_dst_bits
) & PTR2op_dst_mask
);
2627 const char *src_name
= get_preg_name (src
);
2628 const char *dst_name
= get_preg_name (dst
);
2630 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_PTR2op
);
2631 TRACE_EXTRACT (cpu
, "%s: opc:%i src:%i dst:%i", __func__
, opc
, src
, dst
);
2635 TRACE_INSN (cpu
, "%s -= %s", dst_name
, src_name
);
2636 SET_PREG (dst
, PREG (dst
) - PREG (src
));
2640 TRACE_INSN (cpu
, "%s = %s << 2", dst_name
, src_name
);
2641 SET_PREG (dst
, PREG (src
) << 2);
2645 TRACE_INSN (cpu
, "%s = %s >> 2", dst_name
, src_name
);
2646 SET_PREG (dst
, PREG (src
) >> 2);
2650 TRACE_INSN (cpu
, "%s = %s >> 1", dst_name
, src_name
);
2651 SET_PREG (dst
, PREG (src
) >> 1);
2655 TRACE_INSN (cpu
, "%s += %s (BREV)", dst_name
, src_name
);
2656 SET_PREG (dst
, add_brev (PREG (dst
), PREG (src
)));
2660 TRACE_INSN (cpu
, "%s = (%s + %s) << 1", dst_name
, dst_name
, src_name
);
2661 SET_PREG (dst
, (PREG (dst
) + PREG (src
)) << 1);
2665 TRACE_INSN (cpu
, "%s = (%s + %s) << 2", dst_name
, dst_name
, src_name
);
2666 SET_PREG (dst
, (PREG (dst
) + PREG (src
)) << 2);
2669 illegal_instruction (cpu
);
2673 decode_LOGI2op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2676 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2677 | 0 | 1 | 0 | 0 | 1 |.opc.......|.src...............|.dst.......|
2678 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2679 int src
= ((iw0
>> LOGI2op_src_bits
) & LOGI2op_src_mask
);
2680 int opc
= ((iw0
>> LOGI2op_opc_bits
) & LOGI2op_opc_mask
);
2681 int dst
= ((iw0
>> LOGI2op_dst_bits
) & LOGI2op_dst_mask
);
2682 int uimm
= uimm5 (src
);
2683 const char *uimm_str
= uimm5_str (uimm
);
2685 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LOGI2op
);
2686 TRACE_EXTRACT (cpu
, "%s: opc:%i src:%i dst:%i", __func__
, opc
, src
, dst
);
2687 TRACE_DECODE (cpu
, "%s: uimm5:%#x", __func__
, uimm
);
2691 TRACE_INSN (cpu
, "CC = ! BITTST (R%i, %s);", dst
, uimm_str
);
2693 illegal_instruction_combination (cpu
);
2694 SET_CCREG ((~DREG (dst
) >> uimm
) & 1);
2698 TRACE_INSN (cpu
, "CC = BITTST (R%i, %s);", dst
, uimm_str
);
2700 illegal_instruction_combination (cpu
);
2701 SET_CCREG ((DREG (dst
) >> uimm
) & 1);
2705 TRACE_INSN (cpu
, "BITSET (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
, "BITTGL (R%i, %s);", dst
, uimm_str
);
2715 illegal_instruction_combination (cpu
);
2716 SET_DREG (dst
, DREG (dst
) ^ (1 << uimm
));
2717 setflags_logical (cpu
, DREG (dst
));
2721 TRACE_INSN (cpu
, "BITCLR (R%i, %s);", dst
, uimm_str
);
2723 illegal_instruction_combination (cpu
);
2724 SET_DREG (dst
, DREG (dst
) & ~(1 << uimm
));
2725 setflags_logical (cpu
, DREG (dst
));
2729 TRACE_INSN (cpu
, "R%i >>>= %s;", dst
, uimm_str
);
2731 illegal_instruction_combination (cpu
);
2732 SET_DREG (dst
, ashiftrt (cpu
, DREG (dst
), uimm
, 32));
2736 TRACE_INSN (cpu
, "R%i >>= %s;", dst
, uimm_str
);
2738 illegal_instruction_combination (cpu
);
2739 SET_DREG (dst
, lshiftrt (cpu
, DREG (dst
), uimm
, 32));
2743 TRACE_INSN (cpu
, "R%i <<= %s;", dst
, uimm_str
);
2745 illegal_instruction_combination (cpu
);
2746 SET_DREG (dst
, lshift (cpu
, DREG (dst
), uimm
, 32, 0));
2751 decode_COMP3op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2754 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2755 | 0 | 1 | 0 | 1 |.opc.......|.dst.......|.src1......|.src0......|
2756 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2757 int opc
= ((iw0
>> COMP3op_opc_bits
) & COMP3op_opc_mask
);
2758 int dst
= ((iw0
>> COMP3op_dst_bits
) & COMP3op_dst_mask
);
2759 int src0
= ((iw0
>> COMP3op_src0_bits
) & COMP3op_src0_mask
);
2760 int src1
= ((iw0
>> COMP3op_src1_bits
) & COMP3op_src1_mask
);
2762 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_COMP3op
);
2763 TRACE_EXTRACT (cpu
, "%s: opc:%i dst:%i src1:%i src0:%i",
2764 __func__
, opc
, dst
, src1
, src0
);
2768 TRACE_INSN (cpu
, "R%i = R%i + R%i;", dst
, src0
, src1
);
2769 SET_DREG (dst
, add32 (cpu
, DREG (src0
), DREG (src1
), 1, 0));
2773 TRACE_INSN (cpu
, "R%i = R%i - R%i;", dst
, src0
, src1
);
2774 SET_DREG (dst
, sub32 (cpu
, DREG (src0
), DREG (src1
), 1, 0, 0));
2778 TRACE_INSN (cpu
, "R%i = R%i & R%i;", dst
, src0
, src1
);
2779 SET_DREG (dst
, DREG (src0
) & DREG (src1
));
2780 setflags_logical (cpu
, DREG (dst
));
2784 TRACE_INSN (cpu
, "R%i = R%i | R%i;", dst
, src0
, src1
);
2785 SET_DREG (dst
, DREG (src0
) | DREG (src1
));
2786 setflags_logical (cpu
, DREG (dst
));
2790 TRACE_INSN (cpu
, "R%i = R%i ^ R%i;", dst
, src0
, src1
);
2791 SET_DREG (dst
, DREG (src0
) ^ DREG (src1
));
2792 setflags_logical (cpu
, DREG (dst
));
2796 int shift
= opc
- 5;
2797 const char *dst_name
= get_preg_name (dst
);
2798 const char *src0_name
= get_preg_name (src0
);
2799 const char *src1_name
= get_preg_name (src1
);
2801 /* If src0 == src1 this is disassembled as a shift by 1, but this
2802 distinction doesn't matter for our purposes. */
2804 TRACE_INSN (cpu
, "%s = (%s + %s) << %#x;",
2805 dst_name
, src0_name
, src1_name
, shift
);
2807 TRACE_INSN (cpu
, "%s = %s + %s",
2808 dst_name
, src0_name
, src1_name
);
2809 SET_PREG (dst
, PREG (src0
) + (PREG (src1
) << shift
));
2814 decode_COMPI2opD_0 (SIM_CPU
*cpu
, bu16 iw0
)
2817 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2818 | 0 | 1 | 1 | 0 | 0 |.op|..src......................|.dst.......|
2819 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2820 int op
= ((iw0
>> COMPI2opD_op_bits
) & COMPI2opD_op_mask
);
2821 int dst
= ((iw0
>> COMPI2opD_dst_bits
) & COMPI2opD_dst_mask
);
2822 int src
= ((iw0
>> COMPI2opD_src_bits
) & COMPI2opD_src_mask
);
2823 int imm
= imm7 (src
);
2825 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_COMPI2opD
);
2826 TRACE_EXTRACT (cpu
, "%s: op:%i src:%i dst:%i", __func__
, op
, src
, dst
);
2827 TRACE_DECODE (cpu
, "%s: imm7:%#x", __func__
, imm
);
2831 TRACE_INSN (cpu
, "R%i = %s (X);", dst
, imm7_str (imm
));
2832 SET_DREG (dst
, imm
);
2836 TRACE_INSN (cpu
, "R%i += %s;", dst
, imm7_str (imm
));
2837 SET_DREG (dst
, add32 (cpu
, DREG (dst
), imm
, 1, 0));
2842 decode_COMPI2opP_0 (SIM_CPU
*cpu
, bu16 iw0
)
2845 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2846 | 0 | 1 | 1 | 0 | 1 |.op|.src.......................|.dst.......|
2847 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2848 int op
= ((iw0
>> COMPI2opP_op_bits
) & COMPI2opP_op_mask
);
2849 int src
= ((iw0
>> COMPI2opP_src_bits
) & COMPI2opP_src_mask
);
2850 int dst
= ((iw0
>> COMPI2opP_dst_bits
) & COMPI2opP_dst_mask
);
2851 int imm
= imm7 (src
);
2852 const char *dst_name
= get_preg_name (dst
);
2854 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_COMPI2opP
);
2855 TRACE_EXTRACT (cpu
, "%s: op:%i src:%i dst:%i", __func__
, op
, src
, dst
);
2856 TRACE_DECODE (cpu
, "%s: imm:%#x", __func__
, imm
);
2860 TRACE_INSN (cpu
, "%s = %s;", dst_name
, imm7_str (imm
));
2861 SET_PREG (dst
, imm
);
2865 TRACE_INSN (cpu
, "%s += %s;", dst_name
, imm7_str (imm
));
2866 SET_PREG (dst
, PREG (dst
) + imm
);
2871 decode_LDSTpmod_0 (SIM_CPU
*cpu
, bu16 iw0
)
2874 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2875 | 1 | 0 | 0 | 0 |.W.|.aop...|.reg.......|.idx.......|.ptr.......|
2876 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2877 int W
= ((iw0
>> LDSTpmod_W_bits
) & LDSTpmod_W_mask
);
2878 int aop
= ((iw0
>> LDSTpmod_aop_bits
) & LDSTpmod_aop_mask
);
2879 int idx
= ((iw0
>> LDSTpmod_idx_bits
) & LDSTpmod_idx_mask
);
2880 int ptr
= ((iw0
>> LDSTpmod_ptr_bits
) & LDSTpmod_ptr_mask
);
2881 int reg
= ((iw0
>> LDSTpmod_reg_bits
) & LDSTpmod_reg_mask
);
2882 const char *ptr_name
= get_preg_name (ptr
);
2883 const char *idx_name
= get_preg_name (idx
);
2886 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTpmod
);
2887 TRACE_EXTRACT (cpu
, "%s: W:%i aop:%i reg:%i idx:%i ptr:%i",
2888 __func__
, W
, aop
, reg
, idx
, ptr
);
2890 if (aop
== 1 && W
== 0 && idx
== ptr
)
2892 TRACE_INSN (cpu
, "R%i.L = W[%s];", reg
, ptr_name
);
2894 val
= GET_WORD (addr
);
2895 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | val
);
2897 else if (aop
== 2 && W
== 0 && idx
== ptr
)
2899 TRACE_INSN (cpu
, "R%i.H = W[%s];", reg
, ptr_name
);
2901 val
= GET_WORD (addr
);
2902 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (val
<< 16));
2904 else if (aop
== 1 && W
== 1 && idx
== ptr
)
2906 TRACE_INSN (cpu
, "W[%s] = R%i.L;", ptr_name
, reg
);
2908 PUT_WORD (addr
, DREG (reg
));
2910 else if (aop
== 2 && W
== 1 && idx
== ptr
)
2912 TRACE_INSN (cpu
, "W[%s] = R%i.H;", ptr_name
, reg
);
2914 PUT_WORD (addr
, DREG (reg
) >> 16);
2916 else if (aop
== 0 && W
== 0)
2918 TRACE_INSN (cpu
, "R%i = [%s ++ %s];", reg
, ptr_name
, idx_name
);
2920 val
= GET_LONG (addr
);
2921 STORE (DREG (reg
), val
);
2923 STORE (PREG (ptr
), addr
+ PREG (idx
));
2925 else if (aop
== 1 && W
== 0)
2927 TRACE_INSN (cpu
, "R%i.L = W[%s ++ %s];", reg
, ptr_name
, idx_name
);
2929 val
= GET_WORD (addr
);
2930 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | val
);
2932 STORE (PREG (ptr
), addr
+ PREG (idx
));
2934 else if (aop
== 2 && W
== 0)
2936 TRACE_INSN (cpu
, "R%i.H = W[%s ++ %s];", reg
, ptr_name
, idx_name
);
2938 val
= GET_WORD (addr
);
2939 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (val
<< 16));
2941 STORE (PREG (ptr
), addr
+ PREG (idx
));
2943 else if (aop
== 3 && W
== 0)
2945 TRACE_INSN (cpu
, "R%i = W[%s ++ %s] (Z);", reg
, ptr_name
, idx_name
);
2947 val
= GET_WORD (addr
);
2948 STORE (DREG (reg
), val
);
2950 STORE (PREG (ptr
), addr
+ PREG (idx
));
2952 else if (aop
== 3 && W
== 1)
2954 TRACE_INSN (cpu
, "R%i = W[%s ++ %s] (X);", reg
, ptr_name
, idx_name
);
2956 val
= GET_WORD (addr
);
2957 STORE (DREG (reg
), (bs32
) (bs16
) val
);
2959 STORE (PREG (ptr
), addr
+ PREG (idx
));
2961 else if (aop
== 0 && W
== 1)
2963 TRACE_INSN (cpu
, "[%s ++ %s] = R%i;", ptr_name
, idx_name
, reg
);
2965 PUT_LONG (addr
, DREG (reg
));
2967 STORE (PREG (ptr
), addr
+ PREG (idx
));
2969 else if (aop
== 1 && W
== 1)
2971 TRACE_INSN (cpu
, "W[%s ++ %s] = R%i.L;", ptr_name
, idx_name
, reg
);
2973 PUT_WORD (addr
, DREG (reg
));
2975 STORE (PREG (ptr
), addr
+ PREG (idx
));
2977 else if (aop
== 2 && W
== 1)
2979 TRACE_INSN (cpu
, "W[%s ++ %s] = R%i.H;", ptr_name
, idx_name
, reg
);
2981 PUT_WORD (addr
, DREG (reg
) >> 16);
2983 STORE (PREG (ptr
), addr
+ PREG (idx
));
2986 illegal_instruction (cpu
);
2990 decode_dagMODim_0 (SIM_CPU
*cpu
, bu16 iw0
)
2993 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2994 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 0 |.br| 1 | 1 |.op|.m.....|.i.....|
2995 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2996 int i
= ((iw0
>> DagMODim_i_bits
) & DagMODim_i_mask
);
2997 int m
= ((iw0
>> DagMODim_m_bits
) & DagMODim_m_mask
);
2998 int br
= ((iw0
>> DagMODim_br_bits
) & DagMODim_br_mask
);
2999 int op
= ((iw0
>> DagMODim_op_bits
) & DagMODim_op_mask
);
3001 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dagMODim
);
3002 TRACE_EXTRACT (cpu
, "%s: br:%i op:%i m:%i i:%i", __func__
, br
, op
, m
, i
);
3004 if (op
== 0 && br
== 1)
3006 TRACE_INSN (cpu
, "I%i += M%i (BREV);", i
, m
);
3007 SET_IREG (i
, add_brev (IREG (i
), MREG (m
)));
3011 TRACE_INSN (cpu
, "I%i += M%i;", i
, m
);
3012 dagadd (cpu
, i
, MREG (m
));
3014 else if (op
== 1 && br
== 0)
3016 TRACE_INSN (cpu
, "I%i -= M%i;", i
, m
);
3017 dagsub (cpu
, i
, MREG (m
));
3020 illegal_instruction (cpu
);
3024 decode_dagMODik_0 (SIM_CPU
*cpu
, bu16 iw0
)
3027 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3028 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 0 |.op....|.i.....|
3029 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3030 int i
= ((iw0
>> DagMODik_i_bits
) & DagMODik_i_mask
);
3031 int op
= ((iw0
>> DagMODik_op_bits
) & DagMODik_op_mask
);
3033 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dagMODik
);
3034 TRACE_EXTRACT (cpu
, "%s: op:%i i:%i", __func__
, op
, i
);
3038 TRACE_INSN (cpu
, "I%i += 2;", i
);
3043 TRACE_INSN (cpu
, "I%i -= 2;", i
);
3048 TRACE_INSN (cpu
, "I%i += 4;", i
);
3053 TRACE_INSN (cpu
, "I%i -= 4;", i
);
3057 illegal_instruction (cpu
);
3061 decode_dspLDST_0 (SIM_CPU
*cpu
, bu16 iw0
)
3064 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3065 | 1 | 0 | 0 | 1 | 1 | 1 |.W.|.aop...|.m.....|.i.....|.reg.......|
3066 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3067 int i
= ((iw0
>> DspLDST_i_bits
) & DspLDST_i_mask
);
3068 int m
= ((iw0
>> DspLDST_m_bits
) & DspLDST_m_mask
);
3069 int W
= ((iw0
>> DspLDST_W_bits
) & DspLDST_W_mask
);
3070 int aop
= ((iw0
>> DspLDST_aop_bits
) & DspLDST_aop_mask
);
3071 int reg
= ((iw0
>> DspLDST_reg_bits
) & DspLDST_reg_mask
);
3074 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dspLDST
);
3075 TRACE_EXTRACT (cpu
, "%s: aop:%i m:%i i:%i reg:%i", __func__
, aop
, m
, i
, reg
);
3077 if (aop
== 0 && W
== 0 && m
== 0)
3079 TRACE_INSN (cpu
, "R%i = [I%i++];", reg
, i
);
3081 if (DIS_ALGN_EXPT
& 0x1)
3084 STORE (DREG (reg
), GET_LONG (addr
));
3086 else if (aop
== 0 && W
== 0 && m
== 1)
3088 TRACE_INSN (cpu
, "R%i.L = W[I%i++];", reg
, i
);
3091 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | GET_WORD (addr
));
3093 else if (aop
== 0 && W
== 0 && m
== 2)
3095 TRACE_INSN (cpu
, "R%i.H = W[I%i++];", reg
, i
);
3098 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (GET_WORD (addr
) << 16));
3100 else if (aop
== 1 && W
== 0 && m
== 0)
3102 TRACE_INSN (cpu
, "R%i = [I%i--];", reg
, i
);
3104 if (DIS_ALGN_EXPT
& 0x1)
3107 STORE (DREG (reg
), GET_LONG (addr
));
3109 else if (aop
== 1 && W
== 0 && m
== 1)
3111 TRACE_INSN (cpu
, "R%i.L = W[I%i--];", reg
, i
);
3114 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | GET_WORD (addr
));
3116 else if (aop
== 1 && W
== 0 && m
== 2)
3118 TRACE_INSN (cpu
, "R%i.H = W[I%i--];", reg
, i
);
3121 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (GET_WORD (addr
) << 16));
3123 else if (aop
== 2 && W
== 0 && m
== 0)
3125 TRACE_INSN (cpu
, "R%i = [I%i];", reg
, i
);
3127 if (DIS_ALGN_EXPT
& 0x1)
3129 STORE (DREG (reg
), GET_LONG (addr
));
3131 else if (aop
== 2 && W
== 0 && m
== 1)
3133 TRACE_INSN (cpu
, "R%i.L = W[I%i];", reg
, i
);
3135 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | GET_WORD (addr
));
3137 else if (aop
== 2 && W
== 0 && m
== 2)
3139 TRACE_INSN (cpu
, "R%i.H = W[I%i];", reg
, i
);
3141 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (GET_WORD (addr
) << 16));
3143 else if (aop
== 0 && W
== 1 && m
== 0)
3145 TRACE_INSN (cpu
, "[I%i++] = R%i;", i
, reg
);
3148 PUT_LONG (addr
, DREG (reg
));
3150 else if (aop
== 0 && W
== 1 && m
== 1)
3152 TRACE_INSN (cpu
, "W[I%i++] = R%i.L;", i
, reg
);
3155 PUT_WORD (addr
, DREG (reg
));
3157 else if (aop
== 0 && W
== 1 && m
== 2)
3159 TRACE_INSN (cpu
, "W[I%i++] = R%i.H;", i
, reg
);
3162 PUT_WORD (addr
, DREG (reg
) >> 16);
3164 else if (aop
== 1 && W
== 1 && m
== 0)
3166 TRACE_INSN (cpu
, "[I%i--] = R%i;", i
, reg
);
3169 PUT_LONG (addr
, DREG (reg
));
3171 else if (aop
== 1 && W
== 1 && m
== 1)
3173 TRACE_INSN (cpu
, "W[I%i--] = R%i.L;", i
, reg
);
3176 PUT_WORD (addr
, DREG (reg
));
3178 else if (aop
== 1 && W
== 1 && m
== 2)
3180 TRACE_INSN (cpu
, "W[I%i--] = R%i.H;", i
, reg
);
3183 PUT_WORD (addr
, DREG (reg
) >> 16);
3185 else if (aop
== 2 && W
== 1 && m
== 0)
3187 TRACE_INSN (cpu
, "[I%i] = R%i;", i
, reg
);
3189 PUT_LONG (addr
, DREG (reg
));
3191 else if (aop
== 2 && W
== 1 && m
== 1)
3193 TRACE_INSN (cpu
, "W[I%i] = R%i.L;", i
, reg
);
3195 PUT_WORD (addr
, DREG (reg
));
3197 else if (aop
== 2 && W
== 1 && m
== 2)
3199 TRACE_INSN (cpu
, "W[I%i] = R%i.H;", i
, reg
);
3201 PUT_WORD (addr
, DREG (reg
) >> 16);
3203 else if (aop
== 3 && W
== 0)
3205 TRACE_INSN (cpu
, "R%i = [I%i ++ M%i];", reg
, i
, m
);
3207 if (DIS_ALGN_EXPT
& 0x1)
3209 dagadd (cpu
, i
, MREG (m
));
3210 STORE (DREG (reg
), GET_LONG (addr
));
3212 else if (aop
== 3 && W
== 1)
3214 TRACE_INSN (cpu
, "[I%i ++ M%i] = R%i;", i
, m
, reg
);
3216 dagadd (cpu
, i
, MREG (m
));
3217 PUT_LONG (addr
, DREG (reg
));
3220 illegal_instruction (cpu
);
3224 decode_LDST_0 (SIM_CPU
*cpu
, bu16 iw0
)
3227 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3228 | 1 | 0 | 0 | 1 |.sz....|.W.|.aop...|.Z.|.ptr.......|.reg.......|
3229 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3230 int Z
= ((iw0
>> LDST_Z_bits
) & LDST_Z_mask
);
3231 int W
= ((iw0
>> LDST_W_bits
) & LDST_W_mask
);
3232 int sz
= ((iw0
>> LDST_sz_bits
) & LDST_sz_mask
);
3233 int aop
= ((iw0
>> LDST_aop_bits
) & LDST_aop_mask
);
3234 int reg
= ((iw0
>> LDST_reg_bits
) & LDST_reg_mask
);
3235 int ptr
= ((iw0
>> LDST_ptr_bits
) & LDST_ptr_mask
);
3236 const char * const posts
[] = { "++", "--", "" };
3237 const char *post
= posts
[aop
];
3238 const char *ptr_name
= get_preg_name (ptr
);
3240 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDST
);
3241 TRACE_EXTRACT (cpu
, "%s: sz:%i W:%i aop:%i Z:%i ptr:%i reg:%i",
3242 __func__
, sz
, W
, aop
, Z
, ptr
, reg
);
3245 illegal_instruction (cpu
);
3249 if (sz
== 0 && Z
== 0)
3251 TRACE_INSN (cpu
, "R%i = [%s%s];", reg
, ptr_name
, post
);
3252 SET_DREG (reg
, GET_LONG (PREG (ptr
)));
3254 else if (sz
== 0 && Z
== 1)
3256 TRACE_INSN (cpu
, "%s = [%s%s];", get_preg_name (reg
), ptr_name
, post
);
3257 if (aop
< 2 && ptr
== reg
)
3258 illegal_instruction_combination (cpu
);
3259 SET_PREG (reg
, GET_LONG (PREG (ptr
)));
3261 else if (sz
== 1 && Z
== 0)
3263 TRACE_INSN (cpu
, "R%i = W[%s%s] (Z);", reg
, ptr_name
, post
);
3264 SET_DREG (reg
, GET_WORD (PREG (ptr
)));
3266 else if (sz
== 1 && Z
== 1)
3268 TRACE_INSN (cpu
, "R%i = W[%s%s] (X);", reg
, ptr_name
, post
);
3269 SET_DREG (reg
, (bs32
) (bs16
) GET_WORD (PREG (ptr
)));
3271 else if (sz
== 2 && Z
== 0)
3273 TRACE_INSN (cpu
, "R%i = B[%s%s] (Z);", reg
, ptr_name
, post
);
3274 SET_DREG (reg
, GET_BYTE (PREG (ptr
)));
3276 else if (sz
== 2 && Z
== 1)
3278 TRACE_INSN (cpu
, "R%i = B[%s%s] (X);", reg
, ptr_name
, post
);
3279 SET_DREG (reg
, (bs32
) (bs8
) GET_BYTE (PREG (ptr
)));
3282 illegal_instruction (cpu
);
3286 if (sz
== 0 && Z
== 0)
3288 TRACE_INSN (cpu
, "[%s%s] = R%i;", ptr_name
, post
, reg
);
3289 PUT_LONG (PREG (ptr
), DREG (reg
));
3291 else if (sz
== 0 && Z
== 1)
3293 TRACE_INSN (cpu
, "[%s%s] = %s;", ptr_name
, post
, get_preg_name (reg
));
3294 PUT_LONG (PREG (ptr
), PREG (reg
));
3296 else if (sz
== 1 && Z
== 0)
3298 TRACE_INSN (cpu
, "W[%s%s] = R%i;", ptr_name
, post
, reg
);
3299 PUT_WORD (PREG (ptr
), DREG (reg
));
3301 else if (sz
== 2 && Z
== 0)
3303 TRACE_INSN (cpu
, "B[%s%s] = R%i;", ptr_name
, post
, reg
);
3304 PUT_BYTE (PREG (ptr
), DREG (reg
));
3307 illegal_instruction (cpu
);
3311 SET_PREG (ptr
, PREG (ptr
) + (1 << (2 - sz
)));
3313 SET_PREG (ptr
, PREG (ptr
) - (1 << (2 - sz
)));
3317 decode_LDSTiiFP_0 (SIM_CPU
*cpu
, bu16 iw0
)
3320 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3321 | 1 | 0 | 1 | 1 | 1 | 0 |.W.|.offset............|.reg...........|
3322 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3323 /* This isn't exactly a grp:reg as this insn only supports Dregs & Pregs,
3324 but for our usage, its functionality the same thing. */
3325 int grp
= ((iw0
>> 3) & 0x1);
3326 int reg
= ((iw0
>> LDSTiiFP_reg_bits
) & 0x7 /*LDSTiiFP_reg_mask*/);
3327 int offset
= ((iw0
>> LDSTiiFP_offset_bits
) & LDSTiiFP_offset_mask
);
3328 int W
= ((iw0
>> LDSTiiFP_W_bits
) & LDSTiiFP_W_mask
);
3329 bu32 imm
= negimm5s4 (offset
);
3330 bu32 ea
= FPREG
+ imm
;
3331 const char *imm_str
= negimm5s4_str (offset
);
3332 const char *reg_name
= get_allreg_name (grp
, reg
);
3334 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTiiFP
);
3335 TRACE_EXTRACT (cpu
, "%s: W:%i offset:%#x grp:%i reg:%i", __func__
,
3336 W
, offset
, grp
, reg
);
3337 TRACE_DECODE (cpu
, "%s: negimm5s4:%#x", __func__
, imm
);
3341 TRACE_INSN (cpu
, "%s = [FP + %s];", reg_name
, imm_str
);
3342 reg_write (cpu
, grp
, reg
, GET_LONG (ea
));
3346 TRACE_INSN (cpu
, "[FP + %s] = %s;", imm_str
, reg_name
);
3347 PUT_LONG (ea
, reg_read (cpu
, grp
, reg
));
3352 decode_LDSTii_0 (SIM_CPU
*cpu
, bu16 iw0
)
3355 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3356 | 1 | 0 | 1 |.W.|.op....|.offset........|.ptr.......|.reg.......|
3357 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3358 int reg
= ((iw0
>> LDSTii_reg_bit
) & LDSTii_reg_mask
);
3359 int ptr
= ((iw0
>> LDSTii_ptr_bit
) & LDSTii_ptr_mask
);
3360 int offset
= ((iw0
>> LDSTii_offset_bit
) & LDSTii_offset_mask
);
3361 int op
= ((iw0
>> LDSTii_op_bit
) & LDSTii_op_mask
);
3362 int W
= ((iw0
>> LDSTii_W_bit
) & LDSTii_W_mask
);
3364 const char *imm_str
;
3365 const char *ptr_name
= get_preg_name (ptr
);
3367 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTii
);
3368 TRACE_EXTRACT (cpu
, "%s: W:%i op:%i offset:%#x ptr:%i reg:%i",
3369 __func__
, W
, op
, offset
, ptr
, reg
);
3371 if (op
== 0 || op
== 3)
3372 imm
= uimm4s4 (offset
), imm_str
= uimm4s4_str (offset
);
3374 imm
= uimm4s2 (offset
), imm_str
= uimm4s2_str (offset
);
3375 ea
= PREG (ptr
) + imm
;
3377 TRACE_DECODE (cpu
, "%s: uimm4s4/uimm4s2:%#x", __func__
, imm
);
3379 if (W
== 1 && op
== 2)
3380 illegal_instruction (cpu
);
3386 TRACE_INSN (cpu
, "R%i = [%s + %s];", reg
, ptr_name
, imm_str
);
3387 SET_DREG (reg
, GET_LONG (ea
));
3391 TRACE_INSN (cpu
, "R%i = W[%s + %s] (Z);", reg
, ptr_name
, imm_str
);
3392 SET_DREG (reg
, GET_WORD (ea
));
3396 TRACE_INSN (cpu
, "R%i = W[%s + %s] (X);", reg
, ptr_name
, imm_str
);
3397 SET_DREG (reg
, (bs32
) (bs16
) GET_WORD (ea
));
3401 TRACE_INSN (cpu
, "%s = [%s + %s];",
3402 get_preg_name (reg
), ptr_name
, imm_str
);
3403 SET_PREG (reg
, GET_LONG (ea
));
3410 TRACE_INSN (cpu
, "[%s + %s] = R%i;", ptr_name
, imm_str
, reg
);
3411 PUT_LONG (ea
, DREG (reg
));
3415 TRACE_INSN (cpu
, "W[%s + %s] = R%i;", ptr_name
, imm_str
, reg
);
3416 PUT_WORD (ea
, DREG (reg
));
3420 TRACE_INSN (cpu
, "[%s + %s] = %s;",
3421 ptr_name
, imm_str
, get_preg_name (reg
));
3422 PUT_LONG (ea
, PREG (reg
));
3428 decode_LoopSetup_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
, bu32 pc
)
3431 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3432 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |.rop...|.c.|.soffset.......|
3433 |.reg...........| - | - |.eoffset...............................|
3434 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3435 int c
= ((iw0
>> (LoopSetup_c_bits
- 16)) & LoopSetup_c_mask
);
3436 int reg
= ((iw1
>> LoopSetup_reg_bits
) & LoopSetup_reg_mask
);
3437 int rop
= ((iw0
>> (LoopSetup_rop_bits
- 16)) & LoopSetup_rop_mask
);
3438 int soffset
= ((iw0
>> (LoopSetup_soffset_bits
- 16)) & LoopSetup_soffset_mask
);
3439 int eoffset
= ((iw1
>> LoopSetup_eoffset_bits
) & LoopSetup_eoffset_mask
);
3440 int spcrel
= pcrel4 (soffset
);
3441 int epcrel
= lppcrel10 (eoffset
);
3443 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LoopSetup
);
3444 TRACE_EXTRACT (cpu
, "%s: rop:%i c:%i soffset:%i reg:%i eoffset:%i",
3445 __func__
, rop
, c
, soffset
, reg
, eoffset
);
3446 TRACE_DECODE (cpu
, "%s: s_pcrel4:%#x e_lppcrel10:%#x",
3447 __func__
, spcrel
, epcrel
);
3450 illegal_instruction (cpu
);
3453 illegal_instruction_combination (cpu
);
3457 TRACE_INSN (cpu
, "LSETUP (%#x, %#x) LC%i;", spcrel
, epcrel
, c
);
3459 else if (rop
== 1 && reg
<= 7)
3461 TRACE_INSN (cpu
, "LSETUP (%#x, %#x) LC%i = %s;",
3462 spcrel
, epcrel
, c
, get_preg_name (reg
));
3463 SET_LCREG (c
, PREG (reg
));
3465 else if (rop
== 3 && reg
<= 7)
3467 TRACE_INSN (cpu
, "LSETUP (%#x, %#x) LC%i = %s >> 1;",
3468 spcrel
, epcrel
, c
, get_preg_name (reg
));
3469 SET_LCREG (c
, PREG (reg
) >> 1);
3472 illegal_instruction (cpu
);
3474 SET_LTREG (c
, pc
+ spcrel
);
3475 SET_LBREG (c
, pc
+ epcrel
);
3479 decode_LDIMMhalf_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3482 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3483 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 |.Z.|.H.|.S.|.grp...|.reg.......|
3484 |.hword.........................................................|
3485 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3486 int H
= ((iw0
>> (LDIMMhalf_H_bits
- 16)) & LDIMMhalf_H_mask
);
3487 int Z
= ((iw0
>> (LDIMMhalf_Z_bits
- 16)) & LDIMMhalf_Z_mask
);
3488 int S
= ((iw0
>> (LDIMMhalf_S_bits
- 16)) & LDIMMhalf_S_mask
);
3489 int reg
= ((iw0
>> (LDIMMhalf_reg_bits
- 16)) & LDIMMhalf_reg_mask
);
3490 int grp
= ((iw0
>> (LDIMMhalf_grp_bits
- 16)) & LDIMMhalf_grp_mask
);
3491 int hword
= ((iw1
>> LDIMMhalf_hword_bits
) & LDIMMhalf_hword_mask
);
3493 const char *val_str
;
3494 const char *reg_name
= get_allreg_name (grp
, reg
);
3496 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDIMMhalf
);
3497 TRACE_EXTRACT (cpu
, "%s: Z:%i H:%i S:%i grp:%i reg:%i hword:%#x",
3498 __func__
, Z
, H
, S
, grp
, reg
, hword
);
3501 illegal_instruction_combination (cpu
);
3504 val
= imm16 (hword
), val_str
= imm16_str (hword
);
3506 val
= luimm16 (hword
), val_str
= luimm16_str (hword
);
3508 if (H
== 0 && S
== 1 && Z
== 0)
3510 TRACE_INSN (cpu
, "%s = %s (X);", reg_name
, val_str
);
3512 else if (H
== 0 && S
== 0 && Z
== 1)
3514 TRACE_INSN (cpu
, "%s = %s (Z);", reg_name
, val_str
);
3516 else if (H
== 0 && S
== 0 && Z
== 0)
3518 TRACE_INSN (cpu
, "%s.L = %s;", reg_name
, val_str
);
3519 val
= REG_H_L (reg_read (cpu
, grp
, reg
), val
);
3521 else if (H
== 1 && S
== 0 && Z
== 0)
3523 TRACE_INSN (cpu
, "%s.H = %s;", reg_name
, val_str
);
3524 val
= REG_H_L (val
<< 16, reg_read (cpu
, grp
, reg
));
3527 illegal_instruction (cpu
);
3529 reg_write (cpu
, grp
, reg
, val
);
3533 decode_CALLa_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
, bu32 pc
)
3536 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3537 | 1 | 1 | 1 | 0 | 0 | 0 | 1 |.S.|.msw...........................|
3538 |.lsw...........................................................|
3539 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3540 int S
= ((iw0
>> (CALLa_S_bits
- 16)) & CALLa_S_mask
);
3541 int lsw
= ((iw1
>> 0) & 0xffff);
3542 int msw
= ((iw0
>> 0) & 0xff);
3543 int pcrel
= pcrel24 ((msw
<< 16) | lsw
);
3544 bu32 newpc
= pc
+ pcrel
;
3546 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CALLa
);
3547 TRACE_EXTRACT (cpu
, "%s: S:%i msw:%#x lsw:%#x", __func__
, S
, msw
, lsw
);
3548 TRACE_DECODE (cpu
, "%s: pcrel24:%#x", __func__
, pcrel
);
3550 TRACE_INSN (cpu
, "%s %#x;", S
? "CALL" : "JUMP.L", pcrel
);
3553 illegal_instruction_combination (cpu
);
3557 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "CALL");
3558 SET_RETSREG (hwloop_get_next_pc (cpu
, pc
, 4));
3561 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP.L");
3564 BFIN_CPU_STATE
.did_jump
= true;
3565 PROFILE_BRANCH_TAKEN (cpu
);
3570 decode_LDSTidxI_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3573 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3574 | 1 | 1 | 1 | 0 | 0 | 1 |.W.|.Z.|.sz....|.ptr.......|.reg.......|
3575 |.offset........................................................|
3576 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3577 int Z
= ((iw0
>> (LDSTidxI_Z_bits
- 16)) & LDSTidxI_Z_mask
);
3578 int W
= ((iw0
>> (LDSTidxI_W_bits
- 16)) & LDSTidxI_W_mask
);
3579 int sz
= ((iw0
>> (LDSTidxI_sz_bits
- 16)) & LDSTidxI_sz_mask
);
3580 int reg
= ((iw0
>> (LDSTidxI_reg_bits
- 16)) & LDSTidxI_reg_mask
);
3581 int ptr
= ((iw0
>> (LDSTidxI_ptr_bits
- 16)) & LDSTidxI_ptr_mask
);
3582 int offset
= ((iw1
>> LDSTidxI_offset_bits
) & LDSTidxI_offset_mask
);
3583 const char *ptr_name
= get_preg_name (ptr
);
3584 bu32 imm_16s4
= imm16s4 (offset
);
3585 bu32 imm_16s2
= imm16s2 (offset
);
3586 bu32 imm_16
= imm16 (offset
);
3588 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTidxI
);
3589 TRACE_EXTRACT (cpu
, "%s: W:%i Z:%i sz:%i ptr:%i reg:%i offset:%#x",
3590 __func__
, W
, Z
, sz
, ptr
, reg
, offset
);
3593 illegal_instruction (cpu
);
3597 if (sz
== 0 && Z
== 0)
3599 TRACE_INSN (cpu
, "R%i = [%s + %s];",
3600 reg
, ptr_name
, imm16s4_str (offset
));
3601 SET_DREG (reg
, GET_LONG (PREG (ptr
) + imm_16s4
));
3603 else if (sz
== 0 && Z
== 1)
3605 TRACE_INSN (cpu
, "%s = [%s + %s];",
3606 get_preg_name (reg
), ptr_name
, imm16s4_str (offset
));
3607 SET_PREG (reg
, GET_LONG (PREG (ptr
) + imm_16s4
));
3609 else if (sz
== 1 && Z
== 0)
3611 TRACE_INSN (cpu
, "R%i = W[%s + %s] (Z);",
3612 reg
, ptr_name
, imm16s2_str (offset
));
3613 SET_DREG (reg
, GET_WORD (PREG (ptr
) + imm_16s2
));
3615 else if (sz
== 1 && Z
== 1)
3617 TRACE_INSN (cpu
, "R%i = W[%s + %s] (X);",
3618 reg
, ptr_name
, imm16s2_str (offset
));
3619 SET_DREG (reg
, (bs32
) (bs16
) GET_WORD (PREG (ptr
) + imm_16s2
));
3621 else if (sz
== 2 && Z
== 0)
3623 TRACE_INSN (cpu
, "R%i = B[%s + %s] (Z);",
3624 reg
, ptr_name
, imm16_str (offset
));
3625 SET_DREG (reg
, GET_BYTE (PREG (ptr
) + imm_16
));
3627 else if (sz
== 2 && Z
== 1)
3629 TRACE_INSN (cpu
, "R%i = B[%s + %s] (X);",
3630 reg
, ptr_name
, imm16_str (offset
));
3631 SET_DREG (reg
, (bs32
) (bs8
) GET_BYTE (PREG (ptr
) + imm_16
));
3636 if (sz
!= 0 && Z
!= 0)
3637 illegal_instruction (cpu
);
3639 if (sz
== 0 && Z
== 0)
3641 TRACE_INSN (cpu
, "[%s + %s] = R%i;", ptr_name
,
3642 imm16s4_str (offset
), reg
);
3643 PUT_LONG (PREG (ptr
) + imm_16s4
, DREG (reg
));
3645 else if (sz
== 0 && Z
== 1)
3647 TRACE_INSN (cpu
, "[%s + %s] = %s;",
3648 ptr_name
, imm16s4_str (offset
), get_preg_name (reg
));
3649 PUT_LONG (PREG (ptr
) + imm_16s4
, PREG (reg
));
3651 else if (sz
== 1 && Z
== 0)
3653 TRACE_INSN (cpu
, "W[%s + %s] = R%i;",
3654 ptr_name
, imm16s2_str (offset
), reg
);
3655 PUT_WORD (PREG (ptr
) + imm_16s2
, DREG (reg
));
3657 else if (sz
== 2 && Z
== 0)
3659 TRACE_INSN (cpu
, "B[%s + %s] = R%i;",
3660 ptr_name
, imm16_str (offset
), reg
);
3661 PUT_BYTE (PREG (ptr
) + imm_16
, DREG (reg
));
3667 decode_linkage_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3670 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3671 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |.R.|
3672 |.framesize.....................................................|
3673 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3674 int R
= ((iw0
>> (Linkage_R_bits
- 16)) & Linkage_R_mask
);
3675 int framesize
= ((iw1
>> Linkage_framesize_bits
) & Linkage_framesize_mask
);
3678 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_linkage
);
3679 TRACE_EXTRACT (cpu
, "%s: R:%i framesize:%#x", __func__
, R
, framesize
);
3683 int size
= uimm16s4 (framesize
);
3685 TRACE_INSN (cpu
, "LINK %s;", uimm16s4_str (framesize
));
3687 illegal_instruction_combination (cpu
);
3689 PUT_LONG (sp
, RETSREG
);
3691 PUT_LONG (sp
, FPREG
);
3698 /* Restore SP from FP. */
3700 TRACE_INSN (cpu
, "UNLINK;");
3702 illegal_instruction_combination (cpu
);
3703 SET_FPREG (GET_LONG (sp
));
3705 SET_RETSREG (GET_LONG (sp
));
3714 decode_dsp32mac_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3717 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3718 | 1 | 1 | 0 | 0 |.M.| 0 | 0 |.mmod..........|.MM|.P.|.w1|.op1...|
3719 |.h01|.h11|.w0|.op0...|.h00|.h10|.dst.......|.src0......|.src1..|
3720 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3721 int op1
= ((iw0
>> (DSP32Mac_op1_bits
- 16)) & DSP32Mac_op1_mask
);
3722 int w1
= ((iw0
>> (DSP32Mac_w1_bits
- 16)) & DSP32Mac_w1_mask
);
3723 int P
= ((iw0
>> (DSP32Mac_p_bits
- 16)) & DSP32Mac_p_mask
);
3724 int MM
= ((iw0
>> (DSP32Mac_MM_bits
- 16)) & DSP32Mac_MM_mask
);
3725 int mmod
= ((iw0
>> (DSP32Mac_mmod_bits
- 16)) & DSP32Mac_mmod_mask
);
3726 int M
= ((iw0
>> (DSP32Mac_M_bits
- 16)) & DSP32Mac_M_mask
);
3727 int w0
= ((iw1
>> DSP32Mac_w0_bits
) & DSP32Mac_w0_mask
);
3728 int src0
= ((iw1
>> DSP32Mac_src0_bits
) & DSP32Mac_src0_mask
);
3729 int src1
= ((iw1
>> DSP32Mac_src1_bits
) & DSP32Mac_src1_mask
);
3730 int dst
= ((iw1
>> DSP32Mac_dst_bits
) & DSP32Mac_dst_mask
);
3731 int h10
= ((iw1
>> DSP32Mac_h10_bits
) & DSP32Mac_h10_mask
);
3732 int h00
= ((iw1
>> DSP32Mac_h00_bits
) & DSP32Mac_h00_mask
);
3733 int op0
= ((iw1
>> DSP32Mac_op0_bits
) & DSP32Mac_op0_mask
);
3734 int h11
= ((iw1
>> DSP32Mac_h11_bits
) & DSP32Mac_h11_mask
);
3735 int h01
= ((iw1
>> DSP32Mac_h01_bits
) & DSP32Mac_h01_mask
);
3737 bu32 res
= DREG (dst
);
3738 bu32 v_0
= 0, v_1
= 0, zero
= 0, n_1
= 0, n_0
= 0;
3740 static const char * const ops
[] = { "=", "+=", "-=" };
3741 char _buf
[128], *buf
= _buf
;
3744 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32mac
);
3745 TRACE_EXTRACT (cpu
, "%s: M:%i mmod:%i MM:%i P:%i w1:%i op1:%i h01:%i h11:%i "
3746 "w0:%i op0:%i h00:%i h10:%i dst:%i src0:%i src1:%i",
3747 __func__
, M
, mmod
, MM
, P
, w1
, op1
, h01
, h11
, w0
, op0
, h00
, h10
,
3750 if (w0
== 0 && w1
== 0 && op1
== 3 && op0
== 3)
3751 illegal_instruction (cpu
);
3753 if ((w1
|| w0
) && mmod
== M_W32
)
3754 illegal_instruction (cpu
);
3756 if (((1 << mmod
) & (P
? 0x131b : 0x1b5f)) == 0)
3757 illegal_instruction (cpu
);
3759 /* First handle MAC1 side. */
3760 if (w1
== 1 || op1
!= 3)
3762 bu32 res1
= decode_macfunc (cpu
, 1, op1
, h01
, h11
, src0
,
3763 src1
, mmod
, MM
, P
, &v_1
, &n_1
);
3766 buf
+= sprintf (buf
, P
? "R%i" : "R%i.H", dst
+ P
);
3770 buf
+= sprintf (buf
, " = A1");
3771 zero
= !!(res1
== 0);
3776 buf
+= sprintf (buf
, " = (");
3777 buf
+= sprintf (buf
, "A1 %s R%i.%c * R%i.%c", ops
[op1
],
3778 src0
, h01
? 'H' : 'L',
3779 src1
, h11
? 'H' : 'L');
3781 buf
+= sprintf (buf
, ")");
3787 STORE (DREG (dst
+ 1), res1
);
3790 if (res1
& 0xffff0000)
3791 illegal_instruction (cpu
);
3792 res
= REG_H_L (res1
<< 16, res
);
3798 if (w0
== 1 || op0
!= 3)
3801 buf
+= sprintf (buf
, " (M)");
3803 buf
+= sprintf (buf
, ", ");
3807 /* Then handle MAC0 side. */
3808 if (w0
== 1 || op0
!= 3)
3810 bu32 res0
= decode_macfunc (cpu
, 0, op0
, h00
, h10
, src0
,
3811 src1
, mmod
, 0, P
, &v_0
, &n_0
);
3814 buf
+= sprintf (buf
, P
? "R%i" : "R%i.L", dst
);
3818 buf
+= sprintf (buf
, " = A0");
3819 zero
|= !!(res0
== 0);
3824 buf
+= sprintf (buf
, " = (");
3825 buf
+= sprintf (buf
, "A0 %s R%i.%c * R%i.%c", ops
[op0
],
3826 src0
, h00
? 'H' : 'L',
3827 src1
, h10
? 'H' : 'L');
3829 buf
+= sprintf (buf
, ")");
3835 STORE (DREG (dst
), res0
);
3838 if (res0
& 0xffff0000)
3839 illegal_instruction (cpu
);
3840 res
= REG_H_L (res
, res0
);
3847 TRACE_INSN (cpu
, "%s%s;", _buf
, mac_optmode (mmod
, _MM
));
3849 if (!P
&& (w0
|| w1
))
3851 STORE (DREG (dst
), res
);
3852 SET_ASTATREG (v
, v_0
| v_1
);
3854 SET_ASTATREG (vs
, 1);
3858 SET_ASTATREG (v
, v_0
| v_1
);
3860 SET_ASTATREG (vs
, 1);
3863 if ((w0
== 1 && op0
== 3) || (w1
== 1 && op1
== 3))
3865 SET_ASTATREG (az
, zero
);
3866 if (!(w0
== 1 && op0
== 3))
3868 if (!(w1
== 1 && op1
== 3))
3870 SET_ASTATREG (an
, n_1
| n_0
);
3875 decode_dsp32mult_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3878 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3879 | 1 | 1 | 0 | 0 |.M.| 0 | 1 |.mmod..........|.MM|.P.|.w1|.op1...|
3880 |.h01|.h11|.w0|.op0...|.h00|.h10|.dst.......|.src0......|.src1..|
3881 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3882 int op1
= ((iw0
>> (DSP32Mac_op1_bits
- 16)) & DSP32Mac_op1_mask
);
3883 int w1
= ((iw0
>> (DSP32Mac_w1_bits
- 16)) & DSP32Mac_w1_mask
);
3884 int P
= ((iw0
>> (DSP32Mac_p_bits
- 16)) & DSP32Mac_p_mask
);
3885 int MM
= ((iw0
>> (DSP32Mac_MM_bits
- 16)) & DSP32Mac_MM_mask
);
3886 int mmod
= ((iw0
>> (DSP32Mac_mmod_bits
- 16)) & DSP32Mac_mmod_mask
);
3887 int M
= ((iw0
>> (DSP32Mac_M_bits
- 16)) & DSP32Mac_M_mask
);
3888 int w0
= ((iw1
>> DSP32Mac_w0_bits
) & DSP32Mac_w0_mask
);
3889 int src0
= ((iw1
>> DSP32Mac_src0_bits
) & DSP32Mac_src0_mask
);
3890 int src1
= ((iw1
>> DSP32Mac_src1_bits
) & DSP32Mac_src1_mask
);
3891 int dst
= ((iw1
>> DSP32Mac_dst_bits
) & DSP32Mac_dst_mask
);
3892 int h10
= ((iw1
>> DSP32Mac_h10_bits
) & DSP32Mac_h10_mask
);
3893 int h00
= ((iw1
>> DSP32Mac_h00_bits
) & DSP32Mac_h00_mask
);
3894 int op0
= ((iw1
>> DSP32Mac_op0_bits
) & DSP32Mac_op0_mask
);
3895 int h11
= ((iw1
>> DSP32Mac_h11_bits
) & DSP32Mac_h11_mask
);
3896 int h01
= ((iw1
>> DSP32Mac_h01_bits
) & DSP32Mac_h01_mask
);
3898 bu32 res
= DREG (dst
);
3899 bu32 sat0
= 0, sat1
= 0, v_i0
= 0, v_i1
= 0;
3900 char _buf
[128], *buf
= _buf
;
3903 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32mult
);
3904 TRACE_EXTRACT (cpu
, "%s: M:%i mmod:%i MM:%i P:%i w1:%i op1:%i h01:%i h11:%i "
3905 "w0:%i op0:%i h00:%i h10:%i dst:%i src0:%i src1:%i",
3906 __func__
, M
, mmod
, MM
, P
, w1
, op1
, h01
, h11
, w0
, op0
, h00
, h10
,
3909 if (w1
== 0 && w0
== 0)
3910 illegal_instruction (cpu
);
3911 if (((1 << mmod
) & (P
? 0x313 : 0x1b57)) == 0)
3912 illegal_instruction (cpu
);
3913 if (P
&& ((dst
& 1) || (op1
!= 0) || (op0
!= 0) || !is_macmod_pmove (mmod
)))
3914 illegal_instruction (cpu
);
3915 if (!P
&& ((op1
!= 0) || (op0
!= 0) || !is_macmod_hmove (mmod
)))
3916 illegal_instruction (cpu
);
3918 /* First handle MAC1 side. */
3921 bu64 r
= decode_multfunc (cpu
, h01
, h11
, src0
, src1
, mmod
, MM
, &sat1
);
3922 bu32 res1
= extract_mult (cpu
, r
, mmod
, MM
, P
, &v_i1
);
3924 buf
+= sprintf (buf
, P
? "R%i" : "R%i.H", dst
+ P
);
3925 buf
+= sprintf (buf
, " = R%i.%c * R%i.%c",
3926 src0
, h01
? 'H' : 'L',
3927 src1
, h11
? 'H' : 'L');
3931 buf
+= sprintf (buf
, " (M)");
3933 buf
+= sprintf (buf
, ", ");
3937 STORE (DREG (dst
+ 1), res1
);
3940 if (res1
& 0xFFFF0000)
3941 illegal_instruction (cpu
);
3942 res
= REG_H_L (res1
<< 16, res
);
3946 /* First handle MAC0 side. */
3949 bu64 r
= decode_multfunc (cpu
, h00
, h10
, src0
, src1
, mmod
, 0, &sat0
);
3950 bu32 res0
= extract_mult (cpu
, r
, mmod
, 0, P
, &v_i0
);
3952 buf
+= sprintf (buf
, P
? "R%i" : "R%i.L", dst
);
3953 buf
+= sprintf (buf
, " = R%i.%c * R%i.%c",
3954 src0
, h01
? 'H' : 'L',
3955 src1
, h11
? 'H' : 'L');
3958 STORE (DREG (dst
), res0
);
3961 if (res0
& 0xFFFF0000)
3962 illegal_instruction (cpu
);
3963 res
= REG_H_L (res
, res0
);
3967 TRACE_INSN (cpu
, "%s%s;", _buf
, mac_optmode (mmod
, _MM
));
3969 if (!P
&& (w0
|| w1
))
3970 STORE (DREG (dst
), res
);
3974 bu32 v
= sat0
| sat1
| v_i0
| v_i1
;
3976 STORE (ASTATREG (v
), v
);
3977 STORE (ASTATREG (v_copy
), v
);
3979 STORE (ASTATREG (vs
), v
);
3984 decode_dsp32alu_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3987 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3988 | 1 | 1 | 0 | 0 |.M.| 1 | 0 | - | - | - |.HL|.aopcde............|
3989 |.aop...|.s.|.x.|.dst0......|.dst1......|.src0......|.src1......|
3990 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3991 int s
= ((iw1
>> DSP32Alu_s_bits
) & DSP32Alu_s_mask
);
3992 int x
= ((iw1
>> DSP32Alu_x_bits
) & DSP32Alu_x_mask
);
3993 int aop
= ((iw1
>> DSP32Alu_aop_bits
) & DSP32Alu_aop_mask
);
3994 int src0
= ((iw1
>> DSP32Alu_src0_bits
) & DSP32Alu_src0_mask
);
3995 int src1
= ((iw1
>> DSP32Alu_src1_bits
) & DSP32Alu_src1_mask
);
3996 int dst0
= ((iw1
>> DSP32Alu_dst0_bits
) & DSP32Alu_dst0_mask
);
3997 int dst1
= ((iw1
>> DSP32Alu_dst1_bits
) & DSP32Alu_dst1_mask
);
3998 int M
= ((iw0
>> (DSP32Alu_M_bits
- 16)) & DSP32Alu_M_mask
);
3999 int HL
= ((iw0
>> (DSP32Alu_HL_bits
- 16)) & DSP32Alu_HL_mask
);
4000 int aopcde
= ((iw0
>> (DSP32Alu_aopcde_bits
- 16)) & DSP32Alu_aopcde_mask
);
4002 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32alu
);
4003 TRACE_EXTRACT (cpu
, "%s: M:%i HL:%i aopcde:%i aop:%i s:%i x:%i dst0:%i "
4004 "dst1:%i src0:%i src1:%i",
4005 __func__
, M
, HL
, aopcde
, aop
, s
, x
, dst0
, dst1
, src0
, src1
);
4007 if ((aop
== 0 || aop
== 2) && aopcde
== 9 && HL
== 0 && s
== 0)
4010 TRACE_INSN (cpu
, "A%i.L = R%i.L;", a
, src0
);
4011 SET_AWREG (a
, REG_H_L (AWREG (a
), DREG (src0
)));
4013 else if ((aop
== 0 || aop
== 2) && aopcde
== 9 && HL
== 1 && s
== 0)
4016 TRACE_INSN (cpu
, "A%i.H = R%i.H;", a
, src0
);
4017 SET_AWREG (a
, REG_H_L (DREG (src0
), AWREG (a
)));
4019 else if ((aop
== 1 || aop
== 0) && aopcde
== 5)
4021 bs32 val0
= DREG (src0
);
4022 bs32 val1
= DREG (src1
);
4025 bs32 ovX
, sBit1
, sBit2
, sBitRes1
, sBitRes2
;
4027 TRACE_INSN (cpu
, "R%i.%s = R%i %s R%i (RND12)", dst0
, HL
? "L" : "H",
4028 src0
, aop
& 0x1 ? "-" : "+", src1
);
4030 /* If subtract, just invert and add one. */
4033 if (val1
== 0x80000000)
4039 /* Get the sign bits, since we need them later. */
4040 sBit1
= !!(val0
& 0x80000000);
4041 sBit2
= !!(val1
& 0x80000000);
4045 sBitRes1
= !!(res
& 0x80000000);
4046 /* Round to the 12th bit. */
4048 sBitRes2
= !!(res
& 0x80000000);
4056 positive_res + positive_round = neg
4057 Shift and upper 4 bits where not the same. */
4058 if ((!(sBit1
^ sBit2
) && (sBit1
^ sBitRes1
))
4059 || (!sBit1
&& !sBit2
&& sBitRes2
)
4060 || ((signRes
!= 0) && (signRes
!= -1)))
4062 /* Both X1 and X2 Neg res is neg overflow. */
4065 /* Both X1 and X2 Pos res is pos overflow. */
4066 else if (!sBit1
&& !sBit2
)
4068 /* Pos+Neg or Neg+Pos take the sign of the result. */
4078 /* Shift up now after overflow detection. */
4086 STORE (DREG (dst0
), REG_H_L (res
<< 16, DREG (dst0
)));
4088 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), res
));
4090 SET_ASTATREG (az
, res
== 0);
4091 SET_ASTATREG (an
, res
& 0x8000);
4092 SET_ASTATREG (v
, ovX
);
4094 SET_ASTATREG (vs
, ovX
);
4096 else if ((aop
== 2 || aop
== 3) && aopcde
== 5)
4098 bs32 val0
= DREG (src0
);
4099 bs32 val1
= DREG (src1
);
4102 TRACE_INSN (cpu
, "R%i.%s = R%i %s R%i (RND20)", dst0
, HL
? "L" : "H",
4103 src0
, aop
& 0x1 ? "-" : "+", src1
);
4105 /* If subtract, just invert and add one. */
4109 res
= (val0
>> 4) + (val1
>> 4) + (((val0
& 0xf) + (val1
& 0xf)) >> 4);
4111 /* Don't sign extend during the shift. */
4112 res
= ((bu32
)res
>> 16);
4114 /* Don't worry about overflows, since we are shifting right. */
4117 STORE (DREG (dst0
), REG_H_L (res
<< 16, DREG (dst0
)));
4119 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), res
));
4121 SET_ASTATREG (az
, res
== 0);
4122 SET_ASTATREG (an
, res
& 0x8000);
4123 SET_ASTATREG (v
, 0);
4125 else if (aopcde
== 2 || aopcde
== 3)
4127 bu32 s1
, s2
, val
, ac0_i
= 0, v_i
= 0;
4129 TRACE_INSN (cpu
, "R%i.%c = R%i.%c %c R%i.%c%s;",
4130 dst0
, HL
? 'H' : 'L',
4131 src0
, aop
& 2 ? 'H' : 'L',
4132 aopcde
== 2 ? '+' : '-',
4133 src1
, aop
& 1 ? 'H' : 'L',
4144 val
= add16 (cpu
, s1
, s2
, &ac0_i
, &v_i
, 0, 0, s
, 0);
4146 val
= sub16 (cpu
, s1
, s2
, &ac0_i
, &v_i
, 0, 0, s
, 0);
4148 SET_ASTATREG (ac0
, ac0_i
);
4149 SET_ASTATREG (v
, v_i
);
4151 SET_ASTATREG (vs
, v_i
);
4154 SET_DREG_H (dst0
, val
<< 16);
4156 SET_DREG_L (dst0
, val
);
4158 SET_ASTATREG (an
, val
& 0x8000);
4159 SET_ASTATREG (az
, val
== 0);
4161 else if ((aop
== 0 || aop
== 2) && aopcde
== 9 && s
== 1)
4164 TRACE_INSN (cpu
, "A%i = R%i;", a
, src0
);
4165 SET_AREG32 (a
, DREG (src0
));
4167 else if ((aop
== 1 || aop
== 3) && aopcde
== 9 && s
== 0)
4170 TRACE_INSN (cpu
, "A%i.X = R%i.L;", a
, src0
);
4171 SET_AXREG (a
, (bs8
)DREG (src0
));
4173 else if (aop
== 3 && aopcde
== 11 && (s
== 0 || s
== 1))
4175 bu64 acc0
= get_extended_acc (cpu
, 0);
4176 bu64 acc1
= get_extended_acc (cpu
, 1);
4177 bu32 carry
= (bu40
)acc1
< (bu40
)acc0
;
4180 TRACE_INSN (cpu
, "A0 -= A1%s;", s
? " (W32)" : "");
4183 if ((bs64
)acc0
< -0x8000000000ll
)
4184 acc0
= -0x8000000000ull
, sat
= 1;
4185 else if ((bs64
)acc0
>= 0x7fffffffffll
)
4186 acc0
= 0x7fffffffffull
, sat
= 1;
4190 /* A0 -= A1 (W32) */
4191 if (acc0
& (bu64
)0x8000000000ll
)
4192 acc0
&= 0x80ffffffffll
, sat
= 1;
4194 acc0
&= 0xffffffffll
;
4196 STORE (AXREG (0), (acc0
>> 32) & 0xff);
4197 STORE (AWREG (0), acc0
& 0xffffffff);
4198 STORE (ASTATREG (az
), acc0
== 0);
4199 STORE (ASTATREG (an
), !!(acc0
& (bu64
)0x8000000000ll
));
4200 STORE (ASTATREG (ac0
), carry
);
4201 STORE (ASTATREG (ac0_copy
), carry
);
4202 STORE (ASTATREG (av0
), sat
);
4204 STORE (ASTATREG (av0s
), sat
);
4206 else if ((aop
== 0 || aop
== 1) && aopcde
== 22)
4208 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4210 const char * const opts
[] = { "rndl", "rndh", "tl", "th" };
4212 TRACE_INSN (cpu
, "R%i = BYTEOP2P (R%i:%i, R%i:%i) (%s%s);", dst0
,
4213 src0
+ 1, src0
, src1
+ 1, src1
, opts
[HL
+ (aop
<< 1)],
4217 s0H
= DREG (src0
+ 1);
4219 s1H
= DREG (src1
+ 1);
4222 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4223 s1
= algn (s1H
, s1L
, IREG (0) & 3);
4227 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4228 s1
= algn (s1L
, s1H
, IREG (0) & 3);
4232 tmp0
= ((((s1
>> 8) & 0xff) + ((s1
>> 0) & 0xff) +
4233 ((s0
>> 8) & 0xff) + ((s0
>> 0) & 0xff) + i
) >> 2) & 0xff;
4234 tmp1
= ((((s1
>> 24) & 0xff) + ((s1
>> 16) & 0xff) +
4235 ((s0
>> 24) & 0xff) + ((s0
>> 16) & 0xff) + i
) >> 2) & 0xff;
4236 STORE (DREG (dst0
), (tmp1
<< (16 + (HL
* 8))) | (tmp0
<< (HL
* 8)));
4238 /* Implicit DISALGNEXCPT in parallel. */
4241 else if ((aop
== 0 || aop
== 1) && s
== 0 && aopcde
== 8)
4243 TRACE_INSN (cpu
, "A%i = 0;", aop
);
4246 else if (aop
== 2 && s
== 0 && aopcde
== 8)
4248 TRACE_INSN (cpu
, "A1 = A0 = 0;");
4252 else if ((aop
== 0 || aop
== 1 || aop
== 2) && s
== 1 && aopcde
== 8)
4254 bs40 acc0
= get_extended_acc (cpu
, 0);
4255 bs40 acc1
= get_extended_acc (cpu
, 1);
4258 if (aop
== 0 || aop
== 1)
4259 TRACE_INSN (cpu
, "A%i = A%i (S);", aop
, aop
);
4261 TRACE_INSN (cpu
, "A1 = A1 (S), A0 = A0 (S);");
4263 if (aop
== 0 || aop
== 2)
4266 acc0
= saturate_s32 (acc0
, &sat
);
4267 acc0
|= -(acc0
& 0x80000000ull
);
4268 SET_AXREG (0, (acc0
>> 31) & 0xFF);
4269 SET_AWREG (0, acc0
& 0xFFFFFFFF);
4270 SET_ASTATREG (av0
, sat
);
4272 SET_ASTATREG (av0s
, sat
);
4277 if (aop
== 1 || aop
== 2)
4280 acc1
= saturate_s32 (acc1
, &sat
);
4281 acc1
|= -(acc1
& 0x80000000ull
);
4282 SET_AXREG (1, (acc1
>> 31) & 0xFF);
4283 SET_AWREG (1, acc1
& 0xFFFFFFFF);
4284 SET_ASTATREG (av1
, sat
);
4286 SET_ASTATREG (av1s
, sat
);
4291 SET_ASTATREG (az
, (acc0
== 0) || (acc1
== 0));
4292 SET_ASTATREG (an
, ((acc0
>> 31) & 1) || ((acc1
>> 31) & 1));
4294 else if (aop
== 3 && (s
== 0 || s
== 1) && aopcde
== 8)
4296 TRACE_INSN (cpu
, "A%i = A%i;", s
, !s
);
4297 SET_AXREG (s
, AXREG (!s
));
4298 SET_AWREG (s
, AWREG (!s
));
4300 else if (aop
== 3 && HL
== 0 && aopcde
== 16)
4305 TRACE_INSN (cpu
, "A1 = ABS A1 , A0 = ABS A0;");
4308 for (i
= 0; i
< 2; ++i
)
4311 bs40 acc
= get_extended_acc (cpu
, i
);
4315 av
= acc
== ((bs40
)1 << 39);
4317 acc
= ((bs40
)1 << 39) - 1;
4320 SET_ASTATREG (av
[i
], av
);
4322 SET_ASTATREG (avs
[i
], av
);
4325 SET_ASTATREG (az
, az
);
4326 SET_ASTATREG (an
, 0);
4328 else if (aop
== 0 && aopcde
== 23)
4330 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4333 TRACE_INSN (cpu
, "R%i = BYTEOP3P (R%i:%i, R%i:%i) (%s%s);", dst0
,
4334 src0
+ 1, src0
, src1
+ 1, src1
, HL
? "HI" : "LO",
4338 s0H
= DREG (src0
+ 1);
4340 s1H
= DREG (src1
+ 1);
4343 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4344 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4348 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4349 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4352 tmp0
= (bs32
)(bs16
)(s0
>> 0) + ((s1
>> ( 0 + (8 * !HL
))) & 0xff);
4353 tmp1
= (bs32
)(bs16
)(s0
>> 16) + ((s1
>> (16 + (8 * !HL
))) & 0xff);
4354 STORE (DREG (dst0
), (CLAMP (tmp0
, 0, 255) << ( 0 + (8 * HL
))) |
4355 (CLAMP (tmp1
, 0, 255) << (16 + (8 * HL
))));
4357 /* Implicit DISALGNEXCPT in parallel. */
4360 else if ((aop
== 0 || aop
== 1) && aopcde
== 16)
4365 TRACE_INSN (cpu
, "A%i = ABS A%i;", HL
, aop
);
4367 acc
= get_extended_acc (cpu
, aop
);
4370 av
= acc
== ((bs40
)1 << 39);
4372 acc
= ((bs40
)1 << 39) - 1;
4375 SET_ASTATREG (av
[HL
], av
);
4377 SET_ASTATREG (avs
[HL
], av
);
4378 SET_ASTATREG (az
, acc
== 0);
4379 SET_ASTATREG (an
, 0);
4381 else if (aop
== 3 && aopcde
== 12)
4383 bs32 res
= DREG (src0
);
4385 bool sBit_a
, sBit_b
;
4387 TRACE_INSN (cpu
, "R%i.%s = R%i (RND);", dst0
, HL
== 0 ? "L" : "H", src0
);
4388 TRACE_DECODE (cpu
, "R%i.%s = R%i:%#x (RND);", dst0
,
4389 HL
== 0 ? "L" : "H", src0
, res
);
4391 sBit_b
= !!(res
& 0x80000000);
4394 sBit_a
= !!(res
& 0x80000000);
4396 /* Overflow if the sign bit changed when we rounded. */
4397 if ((res
>> 16) && (sBit_b
!= sBit_a
))
4412 SET_DREG (dst0
, REG_H_L (DREG (dst0
), res
));
4414 SET_DREG (dst0
, REG_H_L (res
<< 16, DREG (dst0
)));
4416 SET_ASTATREG (az
, res
== 0);
4417 SET_ASTATREG (an
, res
< 0);
4418 SET_ASTATREG (v
, ovX
);
4420 SET_ASTATREG (vs
, ovX
);
4422 else if (aop
== 3 && HL
== 0 && aopcde
== 15)
4424 bu32 hi
= (-(bs16
)(DREG (src0
) >> 16)) << 16;
4425 bu32 lo
= (-(bs16
)(DREG (src0
) & 0xFFFF)) & 0xFFFF;
4428 TRACE_INSN (cpu
, "R%i = -R%i (V);", dst0
, src0
);
4432 if (hi
== 0x80000000)
4448 SET_DREG (dst0
, hi
| lo
);
4450 SET_ASTATREG (v
, v
);
4452 SET_ASTATREG (vs
, 1);
4453 SET_ASTATREG (ac0
, ac0
);
4454 SET_ASTATREG (ac1
, ac1
);
4455 setflags_nz_2x16 (cpu
, DREG (dst0
));
4457 else if (aop
== 3 && HL
== 0 && aopcde
== 14)
4459 TRACE_INSN (cpu
, "A1 = - A1 , A0 = - A0;");
4461 SET_AREG (0, saturate_s40 (-get_extended_acc (cpu
, 0)));
4462 SET_AREG (1, saturate_s40 (-get_extended_acc (cpu
, 1)));
4463 /* XXX: what ASTAT flags need updating ? */
4465 else if ((aop
== 0 || aop
== 1) && (HL
== 0 || HL
== 1) && aopcde
== 14)
4467 bs40 src_acc
= get_extended_acc (cpu
, aop
);
4470 TRACE_INSN (cpu
, "A%i = - A%i;", HL
, aop
);
4472 SET_AREG (HL
, saturate_s40_astat (-src_acc
, &v
));
4474 SET_ASTATREG (az
, AWREG (HL
) == 0 && AXREG (HL
) == 0);
4475 SET_ASTATREG (an
, AXREG (HL
) >> 7);
4478 SET_ASTATREG (ac0
, !src_acc
);
4479 SET_ASTATREG (av0
, v
);
4481 SET_ASTATREG (av0s
, 1);
4485 SET_ASTATREG (ac1
, !src_acc
);
4486 SET_ASTATREG (av1
, v
);
4488 SET_ASTATREG (av1s
, 1);
4491 else if (aop
== 0 && aopcde
== 12)
4493 bs16 tmp0_hi
= DREG (src0
) >> 16;
4494 bs16 tmp0_lo
= DREG (src0
);
4495 bs16 tmp1_hi
= DREG (src1
) >> 16;
4496 bs16 tmp1_lo
= DREG (src1
);
4498 TRACE_INSN (cpu
, "R%i.L = R%i.H = SIGN(R%i.H) * R%i.H + SIGN(R%i.L) * R%i.L;",
4499 dst0
, dst0
, src0
, src1
, src0
, src1
);
4501 if ((tmp0_hi
>> 15) & 1)
4502 tmp1_hi
= ~tmp1_hi
+ 1;
4504 if ((tmp0_lo
>> 15) & 1)
4505 tmp1_lo
= ~tmp1_lo
+ 1;
4507 tmp1_hi
= tmp1_hi
+ tmp1_lo
;
4509 STORE (DREG (dst0
), REG_H_L (tmp1_hi
<< 16, tmp1_hi
));
4511 else if (aopcde
== 0)
4513 bu32 s0
= DREG (src0
);
4514 bu32 s1
= DREG (src1
);
4515 bu32 s0h
= s0
>> 16;
4516 bu32 s0l
= s0
& 0xFFFF;
4517 bu32 s1h
= s1
>> 16;
4518 bu32 s1l
= s1
& 0xFFFF;
4520 bu32 ac1_i
= 0, ac0_i
= 0, v_i
= 0, z_i
= 0, n_i
= 0;
4522 TRACE_INSN (cpu
, "R%i = R%i %c|%c R%i%s;", dst0
, src0
,
4523 (aop
& 2) ? '-' : '+', (aop
& 1) ? '-' : '+', src1
,
4526 t0
= sub16 (cpu
, s0h
, s1h
, &ac1_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4528 t0
= add16 (cpu
, s0h
, s1h
, &ac1_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4531 t1
= sub16 (cpu
, s0l
, s1l
, &ac0_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4533 t1
= add16 (cpu
, s0l
, s1l
, &ac0_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4535 SET_ASTATREG (ac1
, ac1_i
);
4536 SET_ASTATREG (ac0
, ac0_i
);
4537 SET_ASTATREG (az
, z_i
);
4538 SET_ASTATREG (an
, n_i
);
4539 SET_ASTATREG (v
, v_i
);
4541 SET_ASTATREG (vs
, v_i
);
4546 SET_DREG (dst0
, (t1
<< 16) | t0
);
4548 SET_DREG (dst0
, (t0
<< 16) | t1
);
4550 else if (aop
== 1 && aopcde
== 12)
4552 bs32 val0
= (bs16
)(AWREG (0) >> 16) + (bs16
)AWREG (0);
4553 bs32 val1
= (bs16
)(AWREG (1) >> 16) + (bs16
)AWREG (1);
4555 TRACE_INSN (cpu
, "R%i = A1.L + A1.H, R%i = A0.L + A0.H;", dst1
, dst0
);
4558 illegal_instruction_combination (cpu
);
4560 SET_DREG (dst0
, val0
);
4561 SET_DREG (dst1
, val1
);
4563 else if (aopcde
== 1)
4567 bu16 s0L
= DREG (src0
);
4568 bu16 s0H
= DREG (src0
) >> 16;
4569 bu16 s1L
= DREG (src1
);
4570 bu16 s1H
= DREG (src1
) >> 16;
4571 bu32 v_i
= 0, n_i
= 0, z_i
= 0;
4573 TRACE_INSN (cpu
, "R%i = R%i %s R%i, R%i = R%i %s R%i%s;",
4574 dst1
, src0
, HL
? "+|-" : "+|+", src1
,
4575 dst0
, src0
, HL
? "-|+" : "-|-", src1
,
4576 amod0amod2 (s
, x
, aop
));
4579 illegal_instruction_combination (cpu
);
4583 x0
= add16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4584 x1
= add16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4585 d1
= (x0
<< 16) | x1
;
4587 x0
= sub16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4588 x1
= sub16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4590 d0
= (x0
<< 16) | x1
;
4592 d0
= (x1
<< 16) | x0
;
4596 x0
= add16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4597 x1
= sub16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4598 d1
= (x0
<< 16) | x1
;
4600 x0
= sub16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4601 x1
= add16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4603 d0
= (x0
<< 16) | x1
;
4605 d0
= (x1
<< 16) | x0
;
4607 SET_ASTATREG (az
, z_i
);
4608 SET_ASTATREG (an
, n_i
);
4609 SET_ASTATREG (v
, v_i
);
4611 SET_ASTATREG (vs
, v_i
);
4613 STORE (DREG (dst0
), d0
);
4614 STORE (DREG (dst1
), d1
);
4616 else if ((aop
== 0 || aop
== 1 || aop
== 2) && aopcde
== 11)
4618 bs40 acc0
= get_extended_acc (cpu
, 0);
4619 bs40 acc1
= get_extended_acc (cpu
, 1);
4620 bu32 v
, dreg
, sat
= 0;
4621 bu32 carry
= !!((bu40
)~acc1
< (bu40
)acc0
);
4624 TRACE_INSN (cpu
, "R%i = (A0 += A1);", dst0
);
4626 TRACE_INSN (cpu
, "R%i.%c = (A0 += A1);", dst0
, HL
? 'H' : 'L');
4628 TRACE_INSN (cpu
, "A0 += A1%s;", s
? " (W32)" : "");
4631 acc0
= saturate_s40_astat (acc0
, &v
);
4633 if (aop
== 2 && s
== 1) /* A0 += A1 (W32) */
4635 if (acc0
& (bs40
)0x8000000000ll
)
4636 acc0
&= 0x80ffffffffll
;
4638 acc0
&= 0xffffffffll
;
4641 STORE (AXREG (0), acc0
>> 32);
4642 STORE (AWREG (0), acc0
);
4643 SET_ASTATREG (av0
, v
&& acc1
);
4645 SET_ASTATREG (av0s
, v
);
4647 if (aop
== 0 || aop
== 1)
4649 if (aop
) /* Dregs_lo = A0 += A1 */
4651 dreg
= saturate_s32 (rnd16 (acc0
) << 16, &sat
);
4653 STORE (DREG (dst0
), REG_H_L (dreg
, DREG (dst0
)));
4655 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), dreg
>> 16));
4657 else /* Dregs = A0 += A1 */
4659 dreg
= saturate_s32 (acc0
, &sat
);
4660 STORE (DREG (dst0
), dreg
);
4663 STORE (ASTATREG (az
), dreg
== 0);
4664 STORE (ASTATREG (an
), !!(dreg
& 0x80000000));
4665 STORE (ASTATREG (ac0
), carry
);
4666 STORE (ASTATREG (ac0_copy
), carry
);
4667 STORE (ASTATREG (v
), sat
);
4668 STORE (ASTATREG (v_copy
), sat
);
4670 STORE (ASTATREG (vs
), sat
);
4674 STORE (ASTATREG (az
), acc0
== 0);
4675 STORE (ASTATREG (an
), !!(acc0
& 0x8000000000ull
));
4676 STORE (ASTATREG (ac0
), carry
);
4677 STORE (ASTATREG (ac0_copy
), carry
);
4680 else if ((aop
== 0 || aop
== 1) && aopcde
== 10)
4682 TRACE_INSN (cpu
, "R%i.L = A%i.X;", dst0
, aop
);
4683 SET_DREG_L (dst0
, (bs8
)AXREG (aop
));
4685 else if (aop
== 0 && aopcde
== 4)
4687 TRACE_INSN (cpu
, "R%i = R%i + R%i%s;", dst0
, src0
, src1
, amod1 (s
, x
));
4688 SET_DREG (dst0
, add32 (cpu
, DREG (src0
), DREG (src1
), 1, s
));
4690 else if (aop
== 1 && aopcde
== 4)
4692 TRACE_INSN (cpu
, "R%i = R%i - R%i%s;", dst0
, src0
, src1
, amod1 (s
, x
));
4693 SET_DREG (dst0
, sub32 (cpu
, DREG (src0
), DREG (src1
), 1, s
, 0));
4695 else if (aop
== 2 && aopcde
== 4)
4697 TRACE_INSN (cpu
, "R%i = R%i + R%i, R%i = R%i - R%i%s;",
4698 dst1
, src0
, src1
, dst0
, src0
, src1
, amod1 (s
, x
));
4701 illegal_instruction_combination (cpu
);
4703 STORE (DREG (dst1
), add32 (cpu
, DREG (src0
), DREG (src1
), 1, s
));
4704 STORE (DREG (dst0
), sub32 (cpu
, DREG (src0
), DREG (src1
), 1, s
, 1));
4706 else if ((aop
== 0 || aop
== 1) && aopcde
== 17)
4708 bs40 acc0
= get_extended_acc (cpu
, 0);
4709 bs40 acc1
= get_extended_acc (cpu
, 1);
4710 bs40 val0
, val1
, sval0
, sval1
;
4713 TRACE_INSN (cpu
, "R%i = A%i + A%i, R%i = A%i - A%i%s",
4714 dst1
, !aop
, aop
, dst0
, !aop
, aop
, amod1 (s
, x
));
4715 TRACE_DECODE (cpu
, "R%i = A%i:%#"PRIx64
" + A%i:%#"PRIx64
", "
4716 "R%i = A%i:%#"PRIx64
" - A%i:%#"PRIx64
"%s",
4717 dst1
, !aop
, aop
? acc0
: acc1
, aop
, aop
? acc1
: acc0
,
4718 dst0
, !aop
, aop
? acc0
: acc1
, aop
, aop
? acc1
: acc0
,
4722 illegal_instruction_combination (cpu
);
4730 sval0
= saturate_s32 (val0
, &sat
);
4732 sval1
= saturate_s32 (val1
, &sat
);
4740 STORE (DREG (dst0
), val0
);
4741 STORE (DREG (dst1
), val1
);
4742 SET_ASTATREG (v
, sat_i
);
4744 SET_ASTATREG (vs
, sat_i
);
4745 SET_ASTATREG (an
, val0
& 0x80000000 || val1
& 0x80000000);
4746 SET_ASTATREG (az
, val0
== 0 || val1
== 0);
4747 SET_ASTATREG (ac1
, (bu40
)~acc0
< (bu40
)acc1
);
4749 SET_ASTATREG (ac0
, !!((bu40
)acc1
<= (bu40
)acc0
));
4751 SET_ASTATREG (ac0
, !!((bu40
)acc0
<= (bu40
)acc1
));
4753 else if (aop
== 0 && aopcde
== 18)
4755 bu40 acc0
= get_extended_acc (cpu
, 0);
4756 bu40 acc1
= get_extended_acc (cpu
, 1);
4757 bu32 s0L
= DREG (src0
);
4758 bu32 s0H
= DREG (src0
+ 1);
4759 bu32 s1L
= DREG (src1
);
4760 bu32 s1H
= DREG (src1
+ 1);
4762 bs16 tmp0
, tmp1
, tmp2
, tmp3
;
4764 /* This instruction is only defined for register pairs R1:0 and R3:2. */
4765 if (!((src0
== 0 || src0
== 2) && (src1
== 0 || src1
== 2)))
4766 illegal_instruction (cpu
);
4768 TRACE_INSN (cpu
, "SAA (R%i:%i, R%i:%i)%s", src0
+ 1, src0
,
4769 src1
+ 1, src1
, s
? " (R)" :"");
4771 /* Bit s determines the order of the two registers from a pair:
4772 if s=0 the low-order bytes come from the low reg in the pair,
4773 and if s=1 the low-order bytes come from the high reg. */
4777 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4778 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4782 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4783 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4786 /* Find the absolute difference between pairs, make it
4787 absolute, then add it to the existing accumulator half. */
4789 tmp0
= ((s0
<< 24) >> 24) - ((s1
<< 24) >> 24);
4790 tmp1
= ((s0
<< 16) >> 24) - ((s1
<< 16) >> 24);
4791 tmp2
= ((s0
<< 8) >> 24) - ((s1
<< 8) >> 24);
4792 tmp3
= ((s0
<< 0) >> 24) - ((s1
<< 0) >> 24);
4794 tmp0
= (tmp0
< 0) ? -tmp0
: tmp0
;
4795 tmp1
= (tmp1
< 0) ? -tmp1
: tmp1
;
4796 tmp2
= (tmp2
< 0) ? -tmp2
: tmp2
;
4797 tmp3
= (tmp3
< 0) ? -tmp3
: tmp3
;
4799 s0L
= saturate_u16 ((bu32
)tmp0
+ ((acc0
>> 0) & 0xffff), 0);
4800 s0H
= saturate_u16 ((bu32
)tmp1
+ ((acc0
>> 16) & 0xffff), 0);
4801 s1L
= saturate_u16 ((bu32
)tmp2
+ ((acc1
>> 0) & 0xffff), 0);
4802 s1H
= saturate_u16 ((bu32
)tmp3
+ ((acc1
>> 16) & 0xffff), 0);
4804 STORE (AWREG (0), (s0H
<< 16) | (s0L
& 0xFFFF));
4805 STORE (AXREG (0), 0);
4806 STORE (AWREG (1), (s1H
<< 16) | (s1L
& 0xFFFF));
4807 STORE (AXREG (1), 0);
4809 /* Implicit DISALGNEXCPT in parallel. */
4812 else if (aop
== 3 && aopcde
== 18)
4814 TRACE_INSN (cpu
, "DISALGNEXCPT");
4817 else if ((aop
== 0 || aop
== 1) && aopcde
== 20)
4819 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4820 const char * const opts
[] = { "", " (R)", " (T)", " (T, R)" };
4822 TRACE_INSN (cpu
, "R%i = BYTEOP1P (R%i:%i, R%i:%i)%s;", dst0
,
4823 src0
+ 1, src0
, src1
+ 1, src1
, opts
[s
+ (aop
<< 1)]);
4826 s0H
= DREG (src0
+ 1);
4828 s1H
= DREG (src1
+ 1);
4831 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4832 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4836 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4837 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4841 (((((s0
>> 0) & 0xff) + ((s1
>> 0) & 0xff) + !aop
) >> 1) << 0) |
4842 (((((s0
>> 8) & 0xff) + ((s1
>> 8) & 0xff) + !aop
) >> 1) << 8) |
4843 (((((s0
>> 16) & 0xff) + ((s1
>> 16) & 0xff) + !aop
) >> 1) << 16) |
4844 (((((s0
>> 24) & 0xff) + ((s1
>> 24) & 0xff) + !aop
) >> 1) << 24));
4846 /* Implicit DISALGNEXCPT in parallel. */
4849 else if (aop
== 0 && aopcde
== 21)
4851 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4853 TRACE_INSN (cpu
, "(R%i, R%i) = BYTEOP16P (R%i:%i, R%i:%i)%s;", dst1
, dst0
,
4854 src0
+ 1, src0
, src1
+ 1, src1
, s
? " (R)" : "");
4857 illegal_instruction_combination (cpu
);
4860 s0H
= DREG (src0
+ 1);
4862 s1H
= DREG (src1
+ 1);
4865 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4866 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4870 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4871 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4875 ((((s0
>> 0) & 0xff) + ((s1
>> 0) & 0xff)) << 0) |
4876 ((((s0
>> 8) & 0xff) + ((s1
>> 8) & 0xff)) << 16));
4878 ((((s0
>> 16) & 0xff) + ((s1
>> 16) & 0xff)) << 0) |
4879 ((((s0
>> 24) & 0xff) + ((s1
>> 24) & 0xff)) << 16));
4881 /* Implicit DISALGNEXCPT in parallel. */
4884 else if (aop
== 1 && aopcde
== 21)
4886 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4888 TRACE_INSN (cpu
, "(R%i, R%i) = BYTEOP16M (R%i:%i, R%i:%i)%s;", dst1
, dst0
,
4889 src0
+ 1, src0
, src1
+ 1, src1
, s
? " (R)" : "");
4892 illegal_instruction_combination (cpu
);
4895 s0H
= DREG (src0
+ 1);
4897 s1H
= DREG (src1
+ 1);
4900 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4901 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4905 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4906 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4910 (((((s0
>> 0) & 0xff) - ((s1
>> 0) & 0xff)) << 0) & 0xffff) |
4911 (((((s0
>> 8) & 0xff) - ((s1
>> 8) & 0xff)) << 16)));
4913 (((((s0
>> 16) & 0xff) - ((s1
>> 16) & 0xff)) << 0) & 0xffff) |
4914 (((((s0
>> 24) & 0xff) - ((s1
>> 24) & 0xff)) << 16)));
4916 /* Implicit DISALGNEXCPT in parallel. */
4919 else if (aop
== 1 && aopcde
== 7)
4921 TRACE_INSN (cpu
, "R%i = MIN (R%i, R%i);", dst0
, src0
, src1
);
4922 SET_DREG (dst0
, min32 (cpu
, DREG (src0
), DREG (src1
)));
4924 else if (aop
== 0 && aopcde
== 7)
4926 TRACE_INSN (cpu
, "R%i = MAX (R%i, R%i);", dst0
, src0
, src1
);
4927 SET_DREG (dst0
, max32 (cpu
, DREG (src0
), DREG (src1
)));
4929 else if (aop
== 2 && aopcde
== 7)
4931 bu32 val
= DREG (src0
);
4934 TRACE_INSN (cpu
, "R%i = ABS R%i;", dst0
, src0
);
4938 v
= (val
== 0x80000000);
4941 SET_DREG (dst0
, val
);
4943 SET_ASTATREG (v
, v
);
4945 SET_ASTATREG (vs
, 1);
4946 setflags_nz (cpu
, val
);
4948 else if (aop
== 3 && aopcde
== 7)
4950 bu32 val
= DREG (src0
);
4952 TRACE_INSN (cpu
, "R%i = - R%i %s;", dst0
, src0
, amod1 (s
, 0));
4954 if (s
&& val
== 0x80000000)
4957 SET_ASTATREG (v
, 1);
4958 SET_ASTATREG (vs
, 1);
4960 else if (val
== 0x80000000)
4964 SET_DREG (dst0
, val
);
4966 SET_ASTATREG (az
, val
== 0);
4967 SET_ASTATREG (an
, val
& 0x80000000);
4969 else if (aop
== 2 && aopcde
== 6)
4971 bu32 in
= DREG (src0
);
4972 bu32 hi
= (in
& 0x80000000 ? (bu32
)-(bs16
)(in
>> 16) : in
>> 16) << 16;
4973 bu32 lo
= (in
& 0x8000 ? (bu32
)-(bs16
)(in
& 0xFFFF) : in
) & 0xFFFF;
4976 TRACE_INSN (cpu
, "R%i = ABS R%i (V);", dst0
, src0
);
4979 if (hi
== 0x80000000)
4989 SET_DREG (dst0
, hi
| lo
);
4991 SET_ASTATREG (v
, v
);
4993 SET_ASTATREG (vs
, 1);
4994 setflags_nz_2x16 (cpu
, DREG (dst0
));
4996 else if (aop
== 1 && aopcde
== 6)
4998 TRACE_INSN (cpu
, "R%i = MIN (R%i, R%i) (V);", dst0
, src0
, src1
);
4999 SET_DREG (dst0
, min2x16 (cpu
, DREG (src0
), DREG (src1
)));
5001 else if (aop
== 0 && aopcde
== 6)
5003 TRACE_INSN (cpu
, "R%i = MAX (R%i, R%i) (V);", dst0
, src0
, src1
);
5004 SET_DREG (dst0
, max2x16 (cpu
, DREG (src0
), DREG (src1
)));
5006 else if (aop
== 0 && aopcde
== 24)
5008 TRACE_INSN (cpu
, "R%i = BYTEPACK (R%i, R%i);", dst0
, src0
, src1
);
5010 (((DREG (src0
) >> 0) & 0xff) << 0) |
5011 (((DREG (src0
) >> 16) & 0xff) << 8) |
5012 (((DREG (src1
) >> 0) & 0xff) << 16) |
5013 (((DREG (src1
) >> 16) & 0xff) << 24));
5015 /* Implicit DISALGNEXCPT in parallel. */
5018 else if (aop
== 1 && aopcde
== 24)
5022 bu8 bytea
, byteb
, bytec
, byted
;
5024 TRACE_INSN (cpu
, "(R%i, R%i) = BYTEUNPACK R%i:%i%s;",
5025 dst1
, dst0
, src0
+ 1, src0
, s
? " (R)" : "");
5028 illegal_instruction_combination (cpu
);
5030 order
= IREG (0) & 0x3;
5032 hi
= src0
, lo
= src0
+ 1;
5034 hi
= src0
+ 1, lo
= src0
;
5035 comb_src
= (((bu64
)DREG (hi
)) << 32) | DREG (lo
);
5036 bytea
= (comb_src
>> (0 + 8 * order
));
5037 byteb
= (comb_src
>> (8 + 8 * order
));
5038 bytec
= (comb_src
>> (16 + 8 * order
));
5039 byted
= (comb_src
>> (24 + 8 * order
));
5040 STORE (DREG (dst0
), bytea
| ((bu32
)byteb
<< 16));
5041 STORE (DREG (dst1
), bytec
| ((bu32
)byted
<< 16));
5043 /* Implicit DISALGNEXCPT in parallel. */
5046 else if (aopcde
== 13)
5048 const char *searchmodes
[] = { "GT", "GE", "LT", "LE" };
5050 bs16 a0_lo
, a1_lo
, src_hi
, src_lo
;
5052 TRACE_INSN (cpu
, "(R%i, R%i) = SEARCH R%i (%s);",
5053 dst1
, dst0
, src0
, searchmodes
[aop
]);
5056 illegal_instruction_combination (cpu
);
5058 up_hi
= up_lo
= false;
5061 src_lo
= DREG (src0
);
5062 src_hi
= DREG (src0
) >> 16;
5067 up_hi
= (src_hi
> a1_lo
);
5068 up_lo
= (src_lo
> a0_lo
);
5071 up_hi
= (src_hi
>= a1_lo
);
5072 up_lo
= (src_lo
>= a0_lo
);
5075 up_hi
= (src_hi
< a1_lo
);
5076 up_lo
= (src_lo
< a0_lo
);
5079 up_hi
= (src_hi
<= a1_lo
);
5080 up_lo
= (src_lo
<= a0_lo
);
5086 SET_AREG (1, src_hi
);
5087 SET_DREG (dst1
, PREG (0));
5090 SET_AREG (1, a1_lo
);
5094 SET_AREG (0, src_lo
);
5095 SET_DREG (dst0
, PREG (0));
5098 SET_AREG (0, a0_lo
);
5101 illegal_instruction (cpu
);
5105 decode_dsp32shift_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
5108 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5109 | 1 | 1 | 0 | 0 |.M.| 1 | 1 | 0 | 0 | - | - |.sopcde............|
5110 |.sop...|.HLs...|.dst0......| - | - | - |.src0......|.src1......|
5111 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5112 int HLs
= ((iw1
>> DSP32Shift_HLs_bits
) & DSP32Shift_HLs_mask
);
5113 int sop
= ((iw1
>> DSP32Shift_sop_bits
) & DSP32Shift_sop_mask
);
5114 int src0
= ((iw1
>> DSP32Shift_src0_bits
) & DSP32Shift_src0_mask
);
5115 int src1
= ((iw1
>> DSP32Shift_src1_bits
) & DSP32Shift_src1_mask
);
5116 int dst0
= ((iw1
>> DSP32Shift_dst0_bits
) & DSP32Shift_dst0_mask
);
5117 int sopcde
= ((iw0
>> (DSP32Shift_sopcde_bits
- 16)) & DSP32Shift_sopcde_mask
);
5118 int M
= ((iw0
>> (DSP32Shift_M_bits
- 16)) & DSP32Shift_M_mask
);
5120 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32shift
);
5121 TRACE_EXTRACT (cpu
, "%s: M:%i sopcde:%i sop:%i HLs:%i dst0:%i src0:%i src1:%i",
5122 __func__
, M
, sopcde
, sop
, HLs
, dst0
, src0
, src1
);
5124 if ((sop
== 0 || sop
== 1) && sopcde
== 0)
5127 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5129 TRACE_INSN (cpu
, "R%i.%c = ASHIFT R%i.%c BY R%i.L%s;",
5130 dst0
, HLs
< 2 ? 'L' : 'H',
5131 src1
, HLs
& 1 ? 'H' : 'L',
5132 src0
, sop
== 1 ? " (S)" : "");
5135 val
= (bu16
)(DREG (src1
) & 0xFFFF);
5137 val
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5139 /* Positive shift magnitudes produce Logical Left shifts.
5140 Negative shift magnitudes produce Arithmetic Right shifts. */
5142 val
= ashiftrt (cpu
, val
, -shft
, 16);
5144 val
= lshift (cpu
, val
, shft
, 16, sop
== 1);
5147 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), val
));
5149 STORE (DREG (dst0
), REG_H_L (val
<< 16, DREG (dst0
)));
5151 else if (sop
== 2 && sopcde
== 0)
5153 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5156 TRACE_INSN (cpu
, "R%i.%c = LSHIFT R%i.%c BY R%i.L;",
5157 dst0
, HLs
< 2 ? 'L' : 'H',
5158 src1
, HLs
& 1 ? 'H' : 'L', src0
);
5161 val
= (bu16
)(DREG (src1
) & 0xFFFF);
5163 val
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5166 val
= val
>> (-1 * shft
);
5171 SET_DREG (dst0
, REG_H_L (DREG (dst0
), val
));
5173 SET_DREG (dst0
, REG_H_L (val
<< 16, DREG (dst0
)));
5175 SET_ASTATREG (az
, !((val
& 0xFFFF0000) == 0) || ((val
& 0xFFFF) == 0));
5176 SET_ASTATREG (an
, (!!(val
& 0x80000000)) ^ (!!(val
& 0x8000)));
5177 SET_ASTATREG (v
, 0);
5179 else if (sop
== 2 && sopcde
== 3 && (HLs
== 1 || HLs
== 0))
5181 int shift
= imm6 (DREG (src0
) & 0xFFFF);
5183 bu40 acc
= get_unextended_acc (cpu
, HLs
);
5185 TRACE_INSN (cpu
, "A%i = ROT A%i BY R%i.L;", HLs
, HLs
, src0
);
5186 TRACE_DECODE (cpu
, "A%i:%#"PRIx64
" shift:%i CC:%i", HLs
, acc
, shift
, cc
);
5188 acc
= rot40 (acc
, shift
, &cc
);
5189 SET_AREG (HLs
, acc
);
5193 else if (sop
== 0 && sopcde
== 3 && (HLs
== 0 || HLs
== 1))
5195 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5196 bu64 val
= get_extended_acc (cpu
, HLs
);
5199 TRACE_INSN (cpu
, "A%i = ASHIFT A%i BY R%i.L;", HLs
, HLs
, src0
);
5200 TRACE_DECODE (cpu
, "A%i:%#"PRIx64
" shift:%i", HLs
, val
, shft
);
5203 val
= ashiftrt (cpu
, val
, -shft
, 40);
5205 val
= lshift (cpu
, val
, shft
, 40, 0);
5207 STORE (AXREG (HLs
), (val
>> 32) & 0xff);
5208 STORE (AWREG (HLs
), (val
& 0xffffffff));
5210 else if (sop
== 1 && sopcde
== 3 && (HLs
== 0 || HLs
== 1))
5212 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5216 TRACE_INSN (cpu
, "A%i = LSHIFT A%i BY R%i.L;", HLs
, HLs
, src0
);
5217 val
= get_extended_acc (cpu
, HLs
);
5220 val
= lshiftrt (cpu
, val
, -shft
, 40);
5222 val
= lshift (cpu
, val
, shft
, 40, 0);
5224 STORE (AXREG (HLs
), (val
>> 32) & 0xff);
5225 STORE (AWREG (HLs
), (val
& 0xffffffff));
5227 else if ((sop
== 0 || sop
== 1) && sopcde
== 1)
5229 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5233 TRACE_INSN (cpu
, "R%i = ASHIFT R%i BY R%i.L (V%s);",
5234 dst0
, src1
, src0
, sop
== 1 ? ",S" : "");
5236 val0
= (bu16
)DREG (src1
) & 0xFFFF;
5237 val1
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5241 val0
= ashiftrt (cpu
, val0
, -shft
, 16);
5243 val1
= ashiftrt (cpu
, val1
, -shft
, 16);
5247 val0
= lshift (cpu
, val0
, shft
, 16, sop
== 1);
5249 val1
= lshift (cpu
, val1
, shft
, 16, sop
== 1);
5251 SET_ASTAT (ASTAT
| astat
);
5252 STORE (DREG (dst0
), (val1
<< 16) | val0
);
5254 else if ((sop
== 0 || sop
== 1 || sop
== 2) && sopcde
== 2)
5256 /* dregs = [LA]SHIFT dregs BY dregs_lo (opt_S) */
5257 /* sop == 1 : opt_S */
5258 bu32 v
= DREG (src1
);
5259 /* LSHIFT uses sign extended low 6 bits of dregs_lo. */
5260 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5262 TRACE_INSN (cpu
, "R%i = %cSHIFT R%i BY R%i.L%s;", dst0
,
5263 shft
&& sop
!= 2 ? 'A' : 'L', src1
, src0
,
5264 sop
== 1 ? " (S)" : "");
5269 STORE (DREG (dst0
), lshiftrt (cpu
, v
, -shft
, 32));
5271 STORE (DREG (dst0
), ashiftrt (cpu
, v
, -shft
, 32));
5274 STORE (DREG (dst0
), lshift (cpu
, v
, shft
, 32, sop
== 1));
5276 else if (sop
== 3 && sopcde
== 2)
5278 int shift
= imm6 (DREG (src0
) & 0xFFFF);
5279 bu32 src
= DREG (src1
);
5280 bu32 ret
, cc
= CCREG
;
5282 TRACE_INSN (cpu
, "R%i = ROT R%i BY R%i.L;", dst0
, src1
, src0
);
5283 TRACE_DECODE (cpu
, "R%i:%#x R%i:%#x shift:%i CC:%i",
5284 dst0
, DREG (dst0
), src1
, src
, shift
, cc
);
5286 ret
= rot32 (src
, shift
, &cc
);
5287 STORE (DREG (dst0
), ret
);
5291 else if (sop
== 2 && sopcde
== 1)
5293 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5297 TRACE_INSN (cpu
, "R%i = LSHIFT R%i BY R%i.L (V);", dst0
, src1
, src0
);
5299 val0
= (bu16
)DREG (src1
) & 0xFFFF;
5300 val1
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5304 val0
= lshiftrt (cpu
, val0
, -shft
, 16);
5306 val1
= lshiftrt (cpu
, val1
, -shft
, 16);
5310 val0
= lshift (cpu
, val0
, shft
, 16, 0);
5312 val1
= lshift (cpu
, val1
, shft
, 16, 0);
5314 SET_ASTAT (ASTAT
| astat
);
5315 STORE (DREG (dst0
), (val1
<< 16) | val0
);
5317 else if (sopcde
== 4)
5319 bu32 sv0
= DREG (src0
);
5320 bu32 sv1
= DREG (src1
);
5321 TRACE_INSN (cpu
, "R%i = PACK (R%i.%c, R%i.%c);", dst0
,
5322 src1
, sop
& 2 ? 'H' : 'L',
5323 src0
, sop
& 1 ? 'H' : 'L');
5328 STORE (DREG (dst0
), (sv1
<< 16) | (sv0
& 0xFFFF));
5330 else if (sop
== 0 && sopcde
== 5)
5332 bu32 sv1
= DREG (src1
);
5333 TRACE_INSN (cpu
, "R%i.L = SIGNBITS R%i;", dst0
, src1
);
5334 SET_DREG_L (dst0
, signbits (sv1
, 32));
5336 else if (sop
== 1 && sopcde
== 5)
5338 bu32 sv1
= DREG (src1
);
5339 TRACE_INSN (cpu
, "R%i.L = SIGNBITS R%i.L;", dst0
, src1
);
5340 SET_DREG_L (dst0
, signbits (sv1
, 16));
5342 else if (sop
== 2 && sopcde
== 5)
5344 bu32 sv1
= DREG (src1
);
5345 TRACE_INSN (cpu
, "R%i.L = SIGNBITS R%i.H;", dst0
, src1
);
5346 SET_DREG_L (dst0
, signbits (sv1
>> 16, 16));
5348 else if ((sop
== 0 || sop
== 1) && sopcde
== 6)
5350 bu64 acc
= AXREG (sop
);
5351 TRACE_INSN (cpu
, "R%i.L = SIGNBITS A%i;", dst0
, sop
);
5354 SET_DREG_L (dst0
, signbits (acc
, 40) & 0xFFFF);
5356 else if (sop
== 3 && sopcde
== 6)
5358 bu32 v
= ones (DREG (src1
));
5359 TRACE_INSN (cpu
, "R%i.L = ONES R%i;", dst0
, src1
);
5360 SET_DREG_L (dst0
, v
);
5362 else if (sop
== 0 && sopcde
== 7)
5364 bu16 sv1
= (bu16
)signbits (DREG (src1
), 32);
5365 bu16 sv0
= (bu16
)DREG (src0
);
5368 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i, R%i.L);", dst0
, src1
, src0
);
5370 if ((sv1
& 0x1f) < (sv0
& 0x1f))
5374 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), dst_lo
));
5376 else if (sop
== 1 && sopcde
== 7)
5378 /* Exponent adjust on two 16-bit inputs. Select
5379 smallest norm among 3 inputs. */
5380 bs16 src1_hi
= (DREG (src1
) & 0xFFFF0000) >> 16;
5381 bs16 src1_lo
= (DREG (src1
) & 0xFFFF);
5382 bu16 src0_lo
= (DREG (src0
) & 0xFFFF);
5383 bu16 tmp_hi
, tmp_lo
, tmp
;
5385 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i, R%i.L) (V);", dst0
, src1
, src0
);
5387 tmp_hi
= signbits (src1_hi
, 16);
5388 tmp_lo
= signbits (src1_lo
, 16);
5390 if ((tmp_hi
& 0xf) < (tmp_lo
& 0xf))
5391 if ((tmp_hi
& 0xf) < (src0_lo
& 0xf))
5396 if ((tmp_lo
& 0xf) < (src0_lo
& 0xf))
5400 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), tmp
));
5402 else if (sop
== 2 && sopcde
== 7)
5404 /* Exponent adjust on single 16-bit register. */
5406 bu16 src0_lo
= (bu16
)(DREG (src0
) & 0xFFFF);
5408 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i.L, R%i.L);", dst0
, src1
, src0
);
5410 tmp
= signbits (DREG (src1
) & 0xFFFF, 16);
5412 if ((tmp
& 0xf) < (src0_lo
& 0xf))
5413 SET_DREG_L (dst0
, tmp
);
5415 SET_DREG_L (dst0
, src0_lo
);
5417 else if (sop
== 3 && sopcde
== 7)
5420 bu16 src0_lo
= (bu16
)(DREG (src0
) & 0xFFFF);
5422 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i.H, R%i.L);", dst0
, src1
, src0
);
5424 tmp
= signbits ((DREG (src1
) & 0xFFFF0000) >> 16, 16);
5426 if ((tmp
& 0xf) < (src0_lo
& 0xf))
5427 SET_DREG_L (dst0
, tmp
);
5429 SET_DREG_L (dst0
, src0_lo
);
5431 else if (sop
== 0 && sopcde
== 8)
5433 bu64 acc
= get_unextended_acc (cpu
, 0);
5436 TRACE_INSN (cpu
, "BITMUX (R%i, R%i, A0) (ASR);", src0
, src1
);
5439 illegal_instruction_combination (cpu
);
5444 (((bu64
)s0
& 1) << 38) |
5445 (((bu64
)s1
& 1) << 39);
5446 STORE (DREG (src0
), s0
>> 1);
5447 STORE (DREG (src1
), s1
>> 1);
5451 else if (sop
== 1 && sopcde
== 8)
5453 bu64 acc
= get_unextended_acc (cpu
, 0);
5456 TRACE_INSN (cpu
, "BITMUX (R%i, R%i, A0) (ASL);", src0
, src1
);
5459 illegal_instruction_combination (cpu
);
5466 STORE (DREG (src0
), s0
<< 1);
5467 STORE (DREG (src1
), s1
<< 1);
5471 else if ((sop
== 0 || sop
== 1) && sopcde
== 9)
5473 bs40 acc0
= get_unextended_acc (cpu
, 0);
5476 TRACE_INSN (cpu
, "R%i.L = VIT_MAX (R%i) (AS%c);",
5477 dst0
, src1
, sop
& 1 ? 'R' : 'L');
5480 sH
= DREG (src1
) >> 16;
5483 acc0
= (acc0
& 0xfeffffffffull
) >> 1;
5487 if (((sH
- sL
) & 0x8000) == 0)
5490 acc0
|= (sop
& 1) ? 0x80000000 : 1;
5496 SET_DREG (dst0
, REG_H_L (DREG (dst0
), out
));
5498 else if ((sop
== 2 || sop
== 3) && sopcde
== 9)
5500 bs40 acc0
= get_extended_acc (cpu
, 0);
5501 bs16 s0L
, s0H
, s1L
, s1H
, out0
, out1
;
5503 TRACE_INSN (cpu
, "R%i = VIT_MAX (R%i, R%i) (AS%c);",
5504 dst0
, src1
, src0
, sop
& 1 ? 'R' : 'L');
5507 s0H
= DREG (src0
) >> 16;
5509 s1H
= DREG (src1
) >> 16;
5516 if (((s0H
- s0L
) & 0x8000) == 0)
5519 acc0
|= (sop
& 1) ? 0x40000000 : 2;
5524 if (((s1H
- s1L
) & 0x8000) == 0)
5527 acc0
|= (sop
& 1) ? 0x80000000 : 1;
5533 SET_DREG (dst0
, REG_H_L (out1
<< 16, out0
));
5535 else if (sop
== 0 && sopcde
== 10)
5537 bu32 v
= DREG (src0
);
5538 bu32 x
= DREG (src1
);
5539 bu32 mask
= (1 << (v
& 0x1f)) - 1;
5541 TRACE_INSN (cpu
, "R%i = EXTRACT (R%i, R%i.L) (Z);", dst0
, src1
, src0
);
5543 x
>>= ((v
>> 8) & 0x1f);
5545 STORE (DREG (dst0
), x
);
5546 setflags_logical (cpu
, x
);
5548 else if (sop
== 1 && sopcde
== 10)
5550 bu32 v
= DREG (src0
);
5551 bu32 x
= DREG (src1
);
5552 bu32 sgn
= (1 << (v
& 0x1f)) >> 1;
5553 bu32 mask
= (1 << (v
& 0x1f)) - 1;
5555 TRACE_INSN (cpu
, "R%i = EXTRACT (R%i, R%i.L) (X);", dst0
, src1
, src0
);
5557 x
>>= ((v
>> 8) & 0x1f);
5561 STORE (DREG (dst0
), x
);
5562 setflags_logical (cpu
, x
);
5564 else if ((sop
== 2 || sop
== 3) && sopcde
== 10)
5566 /* The first dregs is the "background" while the second dregs is the
5567 "foreground". The fg reg is used to overlay the bg reg and is:
5568 | nnnn nnnn | nnnn nnnn | xxxp pppp | xxxL LLLL |
5569 n = the fg bit field
5570 p = bit position in bg reg to start LSB of fg field
5571 L = number of fg bits to extract
5572 Using (X) sign-extends the fg bit field. */
5573 bu32 fg
= DREG (src0
);
5574 bu32 bg
= DREG (src1
);
5575 bu32 len
= fg
& 0x1f;
5576 bu32 mask
= (1 << MIN (16, len
)) - 1;
5577 bu32 fgnd
= (fg
>> 16) & mask
;
5578 int shft
= ((fg
>> 8) & 0x1f);
5580 TRACE_INSN (cpu
, "R%i = DEPOSIT (R%i, R%i)%s;", dst0
, src1
, src0
,
5581 sop
== 3 ? " (X)" : "");
5585 /* Sign extend the fg bit field. */
5587 fgnd
= ((bs32
)(bs16
)(fgnd
<< (16 - len
))) >> (16 - len
);
5594 STORE (DREG (dst0
), bg
);
5595 setflags_logical (cpu
, bg
);
5597 else if (sop
== 0 && sopcde
== 11)
5599 bu64 acc0
= get_unextended_acc (cpu
, 0);
5601 TRACE_INSN (cpu
, "R%i.L = CC = BXORSHIFT (A0, R%i);", dst0
, src0
);
5604 SET_CCREG (xor_reduce (acc0
, DREG (src0
)));
5605 SET_DREG (dst0
, REG_H_L (DREG (dst0
), CCREG
));
5608 else if (sop
== 1 && sopcde
== 11)
5610 bu64 acc0
= get_unextended_acc (cpu
, 0);
5612 TRACE_INSN (cpu
, "R%i.L = CC = BXOR (A0, R%i);", dst0
, src0
);
5614 SET_CCREG (xor_reduce (acc0
, DREG (src0
)));
5615 SET_DREG (dst0
, REG_H_L (DREG (dst0
), CCREG
));
5617 else if (sop
== 0 && sopcde
== 12)
5619 bu64 acc0
= get_unextended_acc (cpu
, 0);
5620 bu64 acc1
= get_unextended_acc (cpu
, 1);
5622 TRACE_INSN (cpu
, "A0 = BXORSHIFT (A0, A1, CC);");
5624 acc0
= (acc0
<< 1) | (CCREG
^ xor_reduce (acc0
, acc1
));
5627 else if (sop
== 1 && sopcde
== 12)
5629 bu64 acc0
= get_unextended_acc (cpu
, 0);
5630 bu64 acc1
= get_unextended_acc (cpu
, 1);
5632 TRACE_INSN (cpu
, "R%i.L = CC = BXOR (A0, A1, CC);", dst0
);
5634 SET_CCREG (CCREG
^ xor_reduce (acc0
, acc1
));
5635 acc0
= (acc0
<< 1) | CCREG
;
5636 SET_DREG (dst0
, REG_H_L (DREG (dst0
), CCREG
));
5638 else if ((sop
== 0 || sop
== 1 || sop
== 2) && sopcde
== 13)
5640 int shift
= (sop
+ 1) * 8;
5641 TRACE_INSN (cpu
, "R%i = ALIGN%i (R%i, R%i);", dst0
, shift
, src1
, src0
);
5642 STORE (DREG (dst0
), (DREG (src1
) << (32 - shift
)) | (DREG (src0
) >> shift
));
5645 illegal_instruction (cpu
);
5649 decode_dsp32shiftimm_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
5652 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5653 | 1 | 1 | 0 | 0 |.M.| 1 | 1 | 0 | 1 | - | - |.sopcde............|
5654 |.sop...|.HLs...|.dst0......|.immag.................|.src1......|
5655 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5656 int src1
= ((iw1
>> DSP32ShiftImm_src1_bits
) & DSP32ShiftImm_src1_mask
);
5657 int sop
= ((iw1
>> DSP32ShiftImm_sop_bits
) & DSP32ShiftImm_sop_mask
);
5658 int bit8
= ((iw1
>> 8) & 0x1);
5659 int immag
= ((iw1
>> DSP32ShiftImm_immag_bits
) & DSP32ShiftImm_immag_mask
);
5660 int newimmag
= (-(iw1
>> DSP32ShiftImm_immag_bits
) & DSP32ShiftImm_immag_mask
);
5661 int dst0
= ((iw1
>> DSP32ShiftImm_dst0_bits
) & DSP32ShiftImm_dst0_mask
);
5662 int M
= ((iw0
>> (DSP32ShiftImm_M_bits
- 16)) & DSP32ShiftImm_M_mask
);
5663 int sopcde
= ((iw0
>> (DSP32ShiftImm_sopcde_bits
- 16)) & DSP32ShiftImm_sopcde_mask
);
5664 int HLs
= ((iw1
>> DSP32ShiftImm_HLs_bits
) & DSP32ShiftImm_HLs_mask
);
5666 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32shiftimm
);
5667 TRACE_EXTRACT (cpu
, "%s: M:%i sopcde:%i sop:%i HLs:%i dst0:%i immag:%#x src1:%i",
5668 __func__
, M
, sopcde
, sop
, HLs
, dst0
, immag
, src1
);
5672 bu16 in
= DREG (src1
) >> ((HLs
& 1) ? 16 : 0);
5678 TRACE_INSN (cpu
, "R%i.%c = R%i.%c >>> %i;",
5679 dst0
, (HLs
& 2) ? 'H' : 'L',
5680 src1
, (HLs
& 1) ? 'H' : 'L', newimmag
);
5681 result
= ashiftrt (cpu
, in
, newimmag
, 16);
5683 else if (sop
== 1 && bit8
== 0)
5685 TRACE_INSN (cpu
, "R%i.%c = R%i.%c << %i (S);",
5686 dst0
, (HLs
& 2) ? 'H' : 'L',
5687 src1
, (HLs
& 1) ? 'H' : 'L', immag
);
5688 result
= lshift (cpu
, in
, immag
, 16, 1);
5690 else if (sop
== 1 && bit8
)
5692 TRACE_INSN (cpu
, "R%i.%c = R%i.%c >>> %i (S);",
5693 dst0
, (HLs
& 2) ? 'H' : 'L',
5694 src1
, (HLs
& 1) ? 'H' : 'L', immag
);
5695 result
= lshift (cpu
, in
, immag
, 16, 1);
5697 else if (sop
== 2 && bit8
)
5699 TRACE_INSN (cpu
, "R%i.%c = R%i.%c >> %i;",
5700 dst0
, (HLs
& 2) ? 'H' : 'L',
5701 src1
, (HLs
& 1) ? 'H' : 'L', newimmag
);
5702 result
= lshiftrt (cpu
, in
, newimmag
, 16);
5704 else if (sop
== 2 && bit8
== 0)
5706 TRACE_INSN (cpu
, "R%i.%c = R%i.%c << %i;",
5707 dst0
, (HLs
& 2) ? 'H' : 'L',
5708 src1
, (HLs
& 1) ? 'H' : 'L', immag
);
5709 result
= lshift (cpu
, in
, immag
, 16, 0);
5712 illegal_instruction (cpu
);
5716 STORE (DREG (dst0
), (v
& 0xFFFF) | (result
<< 16));
5718 STORE (DREG (dst0
), (v
& 0xFFFF0000) | result
);
5720 else if (sop
== 2 && sopcde
== 3 && (HLs
== 1 || HLs
== 0))
5722 int shift
= imm6 (immag
);
5724 bu40 acc
= get_unextended_acc (cpu
, HLs
);
5726 TRACE_INSN (cpu
, "A%i = ROT A%i BY %i;", HLs
, HLs
, shift
);
5727 TRACE_DECODE (cpu
, "A%i:%#"PRIx64
" shift:%i CC:%i", HLs
, acc
, shift
, cc
);
5729 acc
= rot40 (acc
, shift
, &cc
);
5730 SET_AREG (HLs
, acc
);
5734 else if (sop
== 0 && sopcde
== 3 && bit8
== 1)
5736 /* Arithmetic shift, so shift in sign bit copies. */
5738 int shift
= uimm5 (newimmag
);
5741 TRACE_INSN (cpu
, "A%i = A%i >>> %i;", HLs
, HLs
, shift
);
5743 acc
= get_extended_acc (cpu
, HLs
);
5745 /* Sign extend again. */
5746 if (acc
& (1ULL << 39))
5747 acc
|= -(1ULL << 39);
5749 acc
&= ~(-(1ULL << 39));
5751 STORE (AXREG (HLs
), (acc
>> 32) & 0xFF);
5752 STORE (AWREG (HLs
), acc
& 0xFFFFFFFF);
5754 else if ((sop
== 0 && sopcde
== 3 && bit8
== 0)
5755 || (sop
== 1 && sopcde
== 3))
5758 int shiftup
= uimm5 (immag
);
5759 int shiftdn
= uimm5 (newimmag
);
5762 TRACE_INSN (cpu
, "A%i = A%i %s %i;", HLs
, HLs
,
5763 sop
== 0 ? "<<" : ">>",
5764 sop
== 0 ? shiftup
: shiftdn
);
5767 /* Logical shift, so shift in zeroes. */
5777 SET_AREG (HLs
, acc
);
5778 SET_ASTATREG (an
, !!(acc
& 0x8000000000ull
));
5779 SET_ASTATREG (az
, acc
== 0);
5781 else if (sop
== 1 && sopcde
== 1 && bit8
== 0)
5783 int count
= imm5 (immag
);
5784 bu16 val0
= DREG (src1
) >> 16;
5785 bu16 val1
= DREG (src1
) & 0xFFFF;
5788 TRACE_INSN (cpu
, "R%i = R%i << %i (V,S);", dst0
, src1
, count
);
5789 val0
= lshift (cpu
, val0
, count
, 16, 1);
5791 val1
= lshift (cpu
, val1
, count
, 16, 1);
5792 SET_ASTAT (ASTAT
| astat
);
5794 STORE (DREG (dst0
), (val0
<< 16) | val1
);
5796 else if (sop
== 2 && sopcde
== 1 && bit8
== 1)
5798 int count
= imm5 (newimmag
);
5799 bu16 val0
= DREG (src1
) & 0xFFFF;
5800 bu16 val1
= DREG (src1
) >> 16;
5803 TRACE_INSN (cpu
, "R%i = R%i >> %i (V);", dst0
, src1
, count
);
5804 val0
= lshiftrt (cpu
, val0
, count
, 16);
5806 val1
= lshiftrt (cpu
, val1
, count
, 16);
5807 SET_ASTAT (ASTAT
| astat
);
5809 STORE (DREG (dst0
), val0
| (val1
<< 16));
5811 else if (sop
== 2 && sopcde
== 1 && bit8
== 0)
5813 int count
= imm5 (immag
);
5814 bu16 val0
= DREG (src1
) & 0xFFFF;
5815 bu16 val1
= DREG (src1
) >> 16;
5818 TRACE_INSN (cpu
, "R%i = R%i << %i (V);", dst0
, src1
, count
);
5819 val0
= lshift (cpu
, val0
, count
, 16, 0);
5821 val1
= lshift (cpu
, val1
, count
, 16, 0);
5822 SET_ASTAT (ASTAT
| astat
);
5824 STORE (DREG (dst0
), val0
| (val1
<< 16));
5826 else if (sopcde
== 1 && (sop
== 0 || (sop
== 1 && bit8
== 1)))
5828 int count
= uimm5 (newimmag
);
5829 bu16 val0
= DREG (src1
) & 0xFFFF;
5830 bu16 val1
= DREG (src1
) >> 16;
5833 TRACE_INSN (cpu
, "R%i = R%i >>> %i %s;", dst0
, src1
, count
,
5834 sop
== 0 ? "(V)" : "(V,S)");
5836 val0
= ashiftrt (cpu
, val0
, count
, 16);
5838 val1
= ashiftrt (cpu
, val1
, count
, 16);
5839 SET_ASTAT (ASTAT
| astat
);
5841 STORE (DREG (dst0
), REG_H_L (val1
<< 16, val0
));
5843 else if (sop
== 1 && sopcde
== 2)
5845 int count
= imm6 (immag
);
5847 TRACE_INSN (cpu
, "R%i = R%i << %i (S);", dst0
, src1
, count
);
5848 STORE (DREG (dst0
), lshift (cpu
, DREG (src1
), count
, 32, 1));
5850 else if (sop
== 2 && sopcde
== 2)
5852 int count
= imm6 (newimmag
);
5854 TRACE_INSN (cpu
, "R%i = R%i >> %i;", dst0
, src1
, count
);
5857 STORE (DREG (dst0
), lshift (cpu
, DREG (src1
), -count
, 32, 0));
5859 STORE (DREG (dst0
), lshiftrt (cpu
, DREG (src1
), count
, 32));
5861 else if (sop
== 3 && sopcde
== 2)
5863 int shift
= imm6 (immag
);
5864 bu32 src
= DREG (src1
);
5865 bu32 ret
, cc
= CCREG
;
5867 TRACE_INSN (cpu
, "R%i = ROT R%i BY %i;", dst0
, src1
, shift
);
5868 TRACE_DECODE (cpu
, "R%i:%#x R%i:%#x shift:%i CC:%i",
5869 dst0
, DREG (dst0
), src1
, src
, shift
, cc
);
5871 ret
= rot32 (src
, shift
, &cc
);
5872 STORE (DREG (dst0
), ret
);
5876 else if (sop
== 0 && sopcde
== 2)
5878 int count
= imm6 (newimmag
);
5880 TRACE_INSN (cpu
, "R%i = R%i >>> %i;", dst0
, src1
, count
);
5883 STORE (DREG (dst0
), lshift (cpu
, DREG (src1
), -count
, 32, 0));
5885 STORE (DREG (dst0
), ashiftrt (cpu
, DREG (src1
), count
, 32));
5888 illegal_instruction (cpu
);
5892 outc (SIM_CPU
*cpu
, char ch
)
5894 SIM_DESC sd
= CPU_STATE (cpu
);
5895 sim_io_printf (sd
, "%c", ch
);
5897 sim_io_flush_stdout (sd
);
5901 decode_psedoDEBUG_0 (SIM_CPU
*cpu
, bu16 iw0
)
5904 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5905 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 |.fn....|.grp.......|.reg.......|
5906 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5907 SIM_DESC sd
= CPU_STATE (cpu
);
5908 int fn
= ((iw0
>> PseudoDbg_fn_bits
) & PseudoDbg_fn_mask
);
5909 int grp
= ((iw0
>> PseudoDbg_grp_bits
) & PseudoDbg_grp_mask
);
5910 int reg
= ((iw0
>> PseudoDbg_reg_bits
) & PseudoDbg_reg_mask
);
5912 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_psedoDEBUG
);
5913 TRACE_EXTRACT (cpu
, "%s: fn:%i grp:%i reg:%i", __func__
, fn
, grp
, reg
);
5915 if ((reg
== 0 || reg
== 1) && fn
== 3)
5917 TRACE_INSN (cpu
, "DBG A%i;", reg
);
5918 sim_io_printf (sd
, "DBG : A%i = %#"PRIx64
"\n", reg
,
5919 get_unextended_acc (cpu
, reg
));
5921 else if (reg
== 3 && fn
== 3)
5923 TRACE_INSN (cpu
, "ABORT;");
5924 cec_exception (cpu
, VEC_SIM_ABORT
);
5927 else if (reg
== 4 && fn
== 3)
5929 TRACE_INSN (cpu
, "HLT;");
5930 cec_exception (cpu
, VEC_SIM_HLT
);
5933 else if (reg
== 5 && fn
== 3)
5934 unhandled_instruction (cpu
, "DBGHALT");
5935 else if (reg
== 6 && fn
== 3)
5936 unhandled_instruction (cpu
, "DBGCMPLX (dregs)");
5937 else if (reg
== 7 && fn
== 3)
5938 unhandled_instruction (cpu
, "DBG");
5939 else if (grp
== 0 && fn
== 2)
5941 TRACE_INSN (cpu
, "OUTC R%i;", reg
);
5942 outc (cpu
, DREG (reg
));
5946 const char *reg_name
= get_allreg_name (grp
, reg
);
5947 TRACE_INSN (cpu
, "DBG %s;", reg_name
);
5948 sim_io_printf (sd
, "DBG : %s = 0x%08x\n", reg_name
,
5949 reg_read (cpu
, grp
, reg
));
5952 unhandled_instruction (cpu
, "PRNT allregs");
5954 illegal_instruction (cpu
);
5958 decode_psedoOChar_0 (SIM_CPU
*cpu
, bu16 iw0
)
5961 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5962 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |.ch............................|
5963 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5964 int ch
= ((iw0
>> PseudoChr_ch_bits
) & PseudoChr_ch_mask
);
5966 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_psedoOChar
);
5967 TRACE_EXTRACT (cpu
, "%s: ch:%#x", __func__
, ch
);
5968 TRACE_INSN (cpu
, "OUTC %#x;", ch
);
5974 decode_psedodbg_assert_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
, bu32 pc
)
5977 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5978 | 1 | 1 | 1 | 1 | 0 | - | - | - | dbgop |.grp.......|.regtest...|
5979 |.expected......................................................|
5980 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5981 SIM_DESC sd
= CPU_STATE (cpu
);
5982 int expected
= ((iw1
>> PseudoDbg_Assert_expected_bits
) & PseudoDbg_Assert_expected_mask
);
5983 int dbgop
= ((iw0
>> (PseudoDbg_Assert_dbgop_bits
- 16)) & PseudoDbg_Assert_dbgop_mask
);
5984 int grp
= ((iw0
>> (PseudoDbg_Assert_grp_bits
- 16)) & PseudoDbg_Assert_grp_mask
);
5985 int regtest
= ((iw0
>> (PseudoDbg_Assert_regtest_bits
- 16)) & PseudoDbg_Assert_regtest_mask
);
5988 bu32 val
= reg_read (cpu
, grp
, regtest
);
5989 const char *reg_name
= get_allreg_name (grp
, regtest
);
5990 const char *dbg_name
, *dbg_appd
;
5992 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_psedodbg_assert
);
5993 TRACE_EXTRACT (cpu
, "%s: dbgop:%i grp:%i regtest:%i expected:%#x",
5994 __func__
, dbgop
, grp
, regtest
, expected
);
5996 if (dbgop
== 0 || dbgop
== 2)
5998 dbg_name
= dbgop
== 0 ? "DBGA" : "DBGAL";
5999 dbg_appd
= dbgop
== 0 ? ".L" : "";
6002 else if (dbgop
== 1 || dbgop
== 3)
6004 dbg_name
= dbgop
== 1 ? "DBGA" : "DBGAH";
6005 dbg_appd
= dbgop
== 1 ? ".H" : "";
6009 illegal_instruction (cpu
);
6011 actual
= val
>> offset
;
6013 TRACE_INSN (cpu
, "%s (%s%s, 0x%x);", dbg_name
, reg_name
, dbg_appd
, expected
);
6014 if (actual
!= expected
)
6016 sim_io_printf (sd
, "FAIL at %#x: %s (%s%s, 0x%04x); actual value %#x\n",
6017 pc
, dbg_name
, reg_name
, dbg_appd
, expected
, actual
);
6019 /* Decode the actual ASTAT bits that are different. */
6020 if (grp
== 4 && regtest
== 6)
6024 sim_io_printf (sd
, "Expected ASTAT:\n");
6025 for (i
= 0; i
< 16; ++i
)
6026 sim_io_printf (sd
, " %8s%c%i%s",
6027 astat_names
[i
+ offset
],
6028 (((expected
>> i
) & 1) != ((actual
>> i
) & 1))
6030 (expected
>> i
) & 1,
6031 i
== 7 ? "\n" : "");
6032 sim_io_printf (sd
, "\n");
6034 sim_io_printf (sd
, "Actual ASTAT:\n");
6035 for (i
= 0; i
< 16; ++i
)
6036 sim_io_printf (sd
, " %8s%c%i%s",
6037 astat_names
[i
+ offset
],
6038 (((expected
>> i
) & 1) != ((actual
>> i
) & 1))
6041 i
== 7 ? "\n" : "");
6042 sim_io_printf (sd
, "\n");
6045 cec_exception (cpu
, VEC_SIM_DBGA
);
6051 _interp_insn_bfin (SIM_CPU
*cpu
, bu32 pc
)
6056 BFIN_CPU_STATE
.multi_pc
= pc
;
6058 if ((iw0
& 0xc000) != 0xc000)
6060 /* 16-bit opcode. */
6063 INSN_LEN
= insn_len
;
6065 TRACE_EXTRACT (cpu
, "%s: iw0:%#x", __func__
, iw0
);
6066 if ((iw0
& 0xFF00) == 0x0000)
6067 decode_ProgCtrl_0 (cpu
, iw0
, pc
);
6068 else if ((iw0
& 0xFFC0) == 0x0240)
6069 decode_CaCTRL_0 (cpu
, iw0
);
6070 else if ((iw0
& 0xFF80) == 0x0100)
6071 decode_PushPopReg_0 (cpu
, iw0
);
6072 else if ((iw0
& 0xFE00) == 0x0400)
6073 decode_PushPopMultiple_0 (cpu
, iw0
);
6074 else if ((iw0
& 0xFE00) == 0x0600)
6075 decode_ccMV_0 (cpu
, iw0
);
6076 else if ((iw0
& 0xF800) == 0x0800)
6077 decode_CCflag_0 (cpu
, iw0
);
6078 else if ((iw0
& 0xFFE0) == 0x0200)
6079 decode_CC2dreg_0 (cpu
, iw0
);
6080 else if ((iw0
& 0xFF00) == 0x0300)
6081 decode_CC2stat_0 (cpu
, iw0
);
6082 else if ((iw0
& 0xF000) == 0x1000)
6083 decode_BRCC_0 (cpu
, iw0
, pc
);
6084 else if ((iw0
& 0xF000) == 0x2000)
6085 decode_UJUMP_0 (cpu
, iw0
, pc
);
6086 else if ((iw0
& 0xF000) == 0x3000)
6087 decode_REGMV_0 (cpu
, iw0
);
6088 else if ((iw0
& 0xFC00) == 0x4000)
6089 decode_ALU2op_0 (cpu
, iw0
);
6090 else if ((iw0
& 0xFE00) == 0x4400)
6091 decode_PTR2op_0 (cpu
, iw0
);
6092 else if ((iw0
& 0xF800) == 0x4800)
6093 decode_LOGI2op_0 (cpu
, iw0
);
6094 else if ((iw0
& 0xF000) == 0x5000)
6095 decode_COMP3op_0 (cpu
, iw0
);
6096 else if ((iw0
& 0xF800) == 0x6000)
6097 decode_COMPI2opD_0 (cpu
, iw0
);
6098 else if ((iw0
& 0xF800) == 0x6800)
6099 decode_COMPI2opP_0 (cpu
, iw0
);
6100 else if ((iw0
& 0xF000) == 0x8000)
6101 decode_LDSTpmod_0 (cpu
, iw0
);
6102 else if ((iw0
& 0xFF60) == 0x9E60)
6103 decode_dagMODim_0 (cpu
, iw0
);
6104 else if ((iw0
& 0xFFF0) == 0x9F60)
6105 decode_dagMODik_0 (cpu
, iw0
);
6106 else if ((iw0
& 0xFC00) == 0x9C00)
6107 decode_dspLDST_0 (cpu
, iw0
);
6108 else if ((iw0
& 0xF000) == 0x9000)
6109 decode_LDST_0 (cpu
, iw0
);
6110 else if ((iw0
& 0xFC00) == 0xB800)
6111 decode_LDSTiiFP_0 (cpu
, iw0
);
6112 else if ((iw0
& 0xE000) == 0xA000)
6113 decode_LDSTii_0 (cpu
, iw0
);
6116 TRACE_EXTRACT (cpu
, "%s: no matching 16-bit pattern", __func__
);
6117 illegal_instruction (cpu
);
6122 /* Grab the next 16 bits to determine if it's a 32-bit or 64-bit opcode. */
6123 iw1
= IFETCH (pc
+ 2);
6124 if ((iw0
& BIT_MULTI_INS
) && (iw0
& 0xe800) != 0xe800 /* not linkage */)
6126 SIM_DESC sd
= CPU_STATE (cpu
);
6127 trace_prefix (sd
, cpu
, NULL_CIA
, pc
, TRACE_LINENUM_P (cpu
),
6128 NULL
, 0, "|| %#"PRIx64
, sim_events_time (sd
));
6134 TRACE_EXTRACT (cpu
, "%s: iw0:%#x iw1:%#x insn_len:%i", __func__
,
6135 iw0
, iw1
, insn_len
);
6137 /* Only cache on first run through (in case of parallel insns). */
6139 INSN_LEN
= insn_len
;
6141 if ((iw0
& 0xf7ff) == 0xc003 && (iw1
& 0xfe00) == 0x1800)
6143 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32mac
);
6144 TRACE_INSN (cpu
, "MNOP;");
6146 else if (((iw0
& 0xFF80) == 0xE080) && ((iw1
& 0x0C00) == 0x0000))
6147 decode_LoopSetup_0 (cpu
, iw0
, iw1
, pc
);
6148 else if (((iw0
& 0xFF00) == 0xE100) && ((iw1
& 0x0000) == 0x0000))
6149 decode_LDIMMhalf_0 (cpu
, iw0
, iw1
);
6150 else if (((iw0
& 0xFE00) == 0xE200) && ((iw1
& 0x0000) == 0x0000))
6151 decode_CALLa_0 (cpu
, iw0
, iw1
, pc
);
6152 else if (((iw0
& 0xFC00) == 0xE400) && ((iw1
& 0x0000) == 0x0000))
6153 decode_LDSTidxI_0 (cpu
, iw0
, iw1
);
6154 else if (((iw0
& 0xFFFE) == 0xE800) && ((iw1
& 0x0000) == 0x0000))
6155 decode_linkage_0 (cpu
, iw0
, iw1
);
6156 else if (((iw0
& 0xF600) == 0xC000) && ((iw1
& 0x0000) == 0x0000))
6157 decode_dsp32mac_0 (cpu
, iw0
, iw1
);
6158 else if (((iw0
& 0xF600) == 0xC200) && ((iw1
& 0x0000) == 0x0000))
6159 decode_dsp32mult_0 (cpu
, iw0
, iw1
);
6160 else if (((iw0
& 0xF7C0) == 0xC400) && ((iw1
& 0x0000) == 0x0000))
6161 decode_dsp32alu_0 (cpu
, iw0
, iw1
);
6162 else if (((iw0
& 0xF7E0) == 0xC600) && ((iw1
& 0x01C0) == 0x0000))
6163 decode_dsp32shift_0 (cpu
, iw0
, iw1
);
6164 else if (((iw0
& 0xF7E0) == 0xC680) && ((iw1
& 0x0000) == 0x0000))
6165 decode_dsp32shiftimm_0 (cpu
, iw0
, iw1
);
6166 else if ((iw0
& 0xFF00) == 0xF800)
6167 decode_psedoDEBUG_0 (cpu
, iw0
), insn_len
= 2;
6168 else if ((iw0
& 0xFF00) == 0xF900)
6169 decode_psedoOChar_0 (cpu
, iw0
), insn_len
= 2;
6170 else if (((iw0
& 0xFF00) == 0xF000) && ((iw1
& 0x0000) == 0x0000))
6171 decode_psedodbg_assert_0 (cpu
, iw0
, iw1
, pc
);
6174 TRACE_EXTRACT (cpu
, "%s: no matching 32-bit pattern", __func__
);
6175 illegal_instruction (cpu
);
6182 interp_insn_bfin (SIM_CPU
*cpu
, bu32 pc
)
6187 BFIN_CPU_STATE
.n_stores
= 0;
6188 DIS_ALGN_EXPT
&= ~1;
6192 insn_len
= _interp_insn_bfin (cpu
, pc
);
6194 /* Proper display of multiple issue instructions. */
6197 _interp_insn_bfin (cpu
, pc
+ 4);
6198 _interp_insn_bfin (cpu
, pc
+ 6);
6200 for (i
= 0; i
< BFIN_CPU_STATE
.n_stores
; i
++)
6202 bu32
*addr
= BFIN_CPU_STATE
.stores
[i
].addr
;
6203 *addr
= BFIN_CPU_STATE
.stores
[i
].val
;
6204 TRACE_REGISTER (cpu
, "dequeuing write %s = %#x",
6205 get_store_name (cpu
, addr
), *addr
);
6208 cycles_inc (cpu
, CYCLE_DELAY
);
6210 /* Set back to zero in case a pending CEC event occurs
6211 after this this insn. */