1 /* Simulator for Analog Devices Blackfin processors.
3 Copyright (C) 2005-2011 Free Software Foundation, Inc.
4 Contributed by Analog Devices, Inc.
6 This file is part of simulators.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
28 #include "opcode/bfin.h"
30 #include "dv-bfin_cec.h"
31 #include "dv-bfin_mmu.h"
33 #define HOST_LONG_WORD_SIZE (sizeof (long) * 8)
35 #define SIGNEXTEND(v, n) \
36 (((bs32)(v) << (HOST_LONG_WORD_SIZE - (n))) >> (HOST_LONG_WORD_SIZE - (n)))
38 static __attribute__ ((noreturn
)) void
39 illegal_instruction (SIM_CPU
*cpu
)
41 TRACE_INSN (cpu
, "ILLEGAL INSTRUCTION");
43 cec_exception (cpu
, VEC_UNDEF_I
);
46 static __attribute__ ((noreturn
)) void
47 illegal_instruction_combination (SIM_CPU
*cpu
)
49 TRACE_INSN (cpu
, "ILLEGAL INSTRUCTION COMBINATION");
51 cec_exception (cpu
, VEC_ILGAL_I
);
54 static __attribute__ ((noreturn
)) void
55 unhandled_instruction (SIM_CPU
*cpu
, const char *insn
)
57 SIM_DESC sd
= CPU_STATE (cpu
);
61 TRACE_EVENTS (cpu
, "unhandled instruction");
64 iw1
= IFETCH (PCREG
+ 2);
65 iw2
= ((bu32
)iw0
<< 16) | iw1
;
67 sim_io_eprintf (sd
, "Unhandled instruction at 0x%08x (%s opcode 0x", PCREG
, insn
);
68 if ((iw0
& 0xc000) == 0xc000)
69 sim_io_eprintf (sd
, "%08x", iw2
);
71 sim_io_eprintf (sd
, "%04x", iw0
);
73 sim_io_eprintf (sd
, ") ... aborting\n");
75 illegal_instruction (cpu
);
78 static const char * const astat_names
[] =
116 c_0
, c_1
, c_4
, c_2
, c_uimm2
, c_uimm3
, c_imm3
, c_pcrel4
,
117 c_imm4
, c_uimm4s4
, c_uimm4s4d
, c_uimm4
, c_uimm4s2
, c_negimm5s4
, c_imm5
,
118 c_imm5d
, c_uimm5
, c_imm6
, c_imm7
, c_imm7d
, c_imm8
, c_uimm8
, c_pcrel8
,
119 c_uimm8s4
, c_pcrel8s4
, c_lppcrel10
, c_pcrel10
, c_pcrel12
, c_imm16s4
,
120 c_luimm16
, c_imm16
, c_imm16d
, c_huimm16
, c_rimm16
, c_imm16s2
, c_uimm16s4
,
121 c_uimm16s4d
, c_uimm16
, c_pcrel24
, c_uimm32
, c_imm32
, c_huimm32
, c_huimm32e
,
138 } constant_formats
[] =
140 { "0", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
141 { "1", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
142 { "4", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
143 { "2", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
144 { "uimm2", 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
145 { "uimm3", 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
146 { "imm3", 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
147 { "pcrel4", 4, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0},
148 { "imm4", 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
149 { "uimm4s4", 4, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0},
150 { "uimm4s4d", 4, 0, 0, 0, 2, 0, 0, 1, 1, 0, 0},
151 { "uimm4", 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
152 { "uimm4s2", 4, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0},
153 { "negimm5s4", 5, 0, 1, 0, 2, 0, 1, 0, 0, 0, 0},
154 { "imm5", 5, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
155 { "imm5d", 5, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0},
156 { "uimm5", 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
157 { "imm6", 6, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
158 { "imm7", 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
159 { "imm7d", 7, 0, 1, 0, 0, 0, 0, 0, 1, 3, 0},
160 { "imm8", 8, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
161 { "uimm8", 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
162 { "pcrel8", 8, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0},
163 { "uimm8s4", 8, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0},
164 { "pcrel8s4", 8, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0},
165 { "lppcrel10", 10, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0},
166 { "pcrel10", 10, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
167 { "pcrel12", 12, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
168 { "imm16s4", 16, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0},
169 { "luimm16", 16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
170 { "imm16", 16, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
171 { "imm16d", 16, 0, 1, 0, 0, 0, 0, 0, 1, 3, 0},
172 { "huimm16", 16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
173 { "rimm16", 16, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0},
174 { "imm16s2", 16, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0},
175 { "uimm16s4", 16, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0},
176 { "uimm16s4d", 16, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0},
177 { "uimm16", 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
178 { "pcrel24", 24, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
179 { "uimm32", 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
180 { "imm32", 32, 0, 1, 0, 0, 0, 0, 0, 1, 3, 0},
181 { "huimm32", 32, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
182 { "huimm32e", 32, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
186 fmtconst_str (const_forms_t cf
, bs32 x
, bu32 pc
)
190 if (constant_formats
[cf
].reloc
)
192 bu32 ea
= (((constant_formats
[cf
].pcrel
? SIGNEXTEND (x
, constant_formats
[cf
].nbits
)
193 : x
) + constant_formats
[cf
].offset
) << constant_formats
[cf
].scale
);
194 if (constant_formats
[cf
].pcrel
)
196 /*if (outf->symbol_at_address_func (ea, outf) || !constant_formats[cf].exact)
198 outf->print_address_func (ea, outf);
203 sprintf (buf
, "%#x", x
);
208 /* Negative constants have an implied sign bit. */
209 if (constant_formats
[cf
].negative
)
211 int nb
= constant_formats
[cf
].nbits
+ 1;
213 x
= x
| (1 << constant_formats
[cf
].nbits
);
214 x
= SIGNEXTEND (x
, nb
);
217 x
= constant_formats
[cf
].issigned
? SIGNEXTEND (x
, constant_formats
[cf
].nbits
) : x
;
219 if (constant_formats
[cf
].offset
)
220 x
+= constant_formats
[cf
].offset
;
222 if (constant_formats
[cf
].scale
)
223 x
<<= constant_formats
[cf
].scale
;
225 if (constant_formats
[cf
].decimal
)
227 if (constant_formats
[cf
].leading
)
230 sprintf (ps
, "%%%ii", constant_formats
[cf
].leading
);
231 sprintf (buf
, ps
, x
);
234 sprintf (buf
, "%i", x
);
238 if (constant_formats
[cf
].issigned
&& x
< 0)
239 sprintf (buf
, "-0x%x", abs (x
));
241 sprintf (buf
, "0x%x", x
);
248 fmtconst_val (const_forms_t cf
, bu32 x
, bu32 pc
)
250 if (0 && constant_formats
[cf
].reloc
)
252 bu32 ea
= (((constant_formats
[cf
].pcrel
253 ? (bu32
)SIGNEXTEND (x
, constant_formats
[cf
].nbits
)
254 : x
) + constant_formats
[cf
].offset
)
255 << constant_formats
[cf
].scale
);
256 if (constant_formats
[cf
].pcrel
)
262 /* Negative constants have an implied sign bit. */
263 if (constant_formats
[cf
].negative
)
265 int nb
= constant_formats
[cf
].nbits
+ 1;
266 x
= x
| (1 << constant_formats
[cf
].nbits
);
267 x
= SIGNEXTEND (x
, nb
);
269 else if (constant_formats
[cf
].issigned
)
270 x
= SIGNEXTEND (x
, constant_formats
[cf
].nbits
);
272 x
+= constant_formats
[cf
].offset
;
273 x
<<= constant_formats
[cf
].scale
;
278 #define uimm16s4(x) fmtconst_val (c_uimm16s4, x, 0)
279 #define uimm16s4_str(x) fmtconst_str (c_uimm16s4, x, 0)
280 #define uimm16s4d(x) fmtconst_val (c_uimm16s4d, x, 0)
281 #define pcrel4(x) fmtconst_val (c_pcrel4, x, pc)
282 #define pcrel8(x) fmtconst_val (c_pcrel8, x, pc)
283 #define pcrel8s4(x) fmtconst_val (c_pcrel8s4, x, pc)
284 #define pcrel10(x) fmtconst_val (c_pcrel10, x, pc)
285 #define pcrel12(x) fmtconst_val (c_pcrel12, x, pc)
286 #define negimm5s4(x) fmtconst_val (c_negimm5s4, x, 0)
287 #define negimm5s4_str(x) fmtconst_str (c_negimm5s4, x, 0)
288 #define rimm16(x) fmtconst_val (c_rimm16, x, 0)
289 #define huimm16(x) fmtconst_val (c_huimm16, x, 0)
290 #define imm16(x) fmtconst_val (c_imm16, x, 0)
291 #define imm16_str(x) fmtconst_str (c_imm16, x, 0)
292 #define imm16d(x) fmtconst_val (c_imm16d, x, 0)
293 #define uimm2(x) fmtconst_val (c_uimm2, x, 0)
294 #define uimm3(x) fmtconst_val (c_uimm3, x, 0)
295 #define uimm3_str(x) fmtconst_str (c_uimm3, x, 0)
296 #define luimm16(x) fmtconst_val (c_luimm16, x, 0)
297 #define luimm16_str(x) fmtconst_str (c_luimm16, x, 0)
298 #define uimm4(x) fmtconst_val (c_uimm4, x, 0)
299 #define uimm4_str(x) fmtconst_str (c_uimm4, x, 0)
300 #define uimm5(x) fmtconst_val (c_uimm5, x, 0)
301 #define uimm5_str(x) fmtconst_str (c_uimm5, x, 0)
302 #define imm16s2(x) fmtconst_val (c_imm16s2, x, 0)
303 #define imm16s2_str(x) fmtconst_str (c_imm16s2, x, 0)
304 #define uimm8(x) fmtconst_val (c_uimm8, x, 0)
305 #define imm16s4(x) fmtconst_val (c_imm16s4, x, 0)
306 #define imm16s4_str(x) fmtconst_str (c_imm16s4, x, 0)
307 #define uimm4s2(x) fmtconst_val (c_uimm4s2, x, 0)
308 #define uimm4s2_str(x) fmtconst_str (c_uimm4s2, x, 0)
309 #define uimm4s4(x) fmtconst_val (c_uimm4s4, x, 0)
310 #define uimm4s4_str(x) fmtconst_str (c_uimm4s4, x, 0)
311 #define uimm4s4d(x) fmtconst_val (c_uimm4s4d, x, 0)
312 #define lppcrel10(x) fmtconst_val (c_lppcrel10, x, pc)
313 #define imm3(x) fmtconst_val (c_imm3, x, 0)
314 #define imm3_str(x) fmtconst_str (c_imm3, x, 0)
315 #define imm4(x) fmtconst_val (c_imm4, x, 0)
316 #define uimm8s4(x) fmtconst_val (c_uimm8s4, x, 0)
317 #define imm5(x) fmtconst_val (c_imm5, x, 0)
318 #define imm5d(x) fmtconst_val (c_imm5d, x, 0)
319 #define imm6(x) fmtconst_val (c_imm6, x, 0)
320 #define imm7(x) fmtconst_val (c_imm7, x, 0)
321 #define imm7_str(x) fmtconst_str (c_imm7, x, 0)
322 #define imm7d(x) fmtconst_val (c_imm7d, x, 0)
323 #define imm8(x) fmtconst_val (c_imm8, x, 0)
324 #define pcrel24(x) fmtconst_val (c_pcrel24, x, pc)
325 #define pcrel24_str(x) fmtconst_str (c_pcrel24, x, pc)
326 #define uimm16(x) fmtconst_val (c_uimm16, x, 0)
327 #define uimm32(x) fmtconst_val (c_uimm32, x, 0)
328 #define imm32(x) fmtconst_val (c_imm32, x, 0)
329 #define huimm32(x) fmtconst_val (c_huimm32, x, 0)
330 #define huimm32e(x) fmtconst_val (c_huimm32e, x, 0)
332 /* Table C-4. Core Register Encoding Map. */
333 const char * const greg_names
[] =
335 "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7",
336 "P0", "P1", "P2", "P3", "P4", "P5", "SP", "FP",
337 "I0", "I1", "I2", "I3", "M0", "M1", "M2", "M3",
338 "B0", "B1", "B2", "B3", "L0", "L1", "L2", "L3",
339 "A0.X", "A0.W", "A1.X", "A1.W", "<res>", "<res>", "ASTAT", "RETS",
340 "<res>", "<res>", "<res>", "<res>", "<res>", "<res>", "<res>", "<res>",
341 "LC0", "LT0", "LB0", "LC1", "LT1", "LB1", "CYCLES", "CYCLES2",
342 "USP", "SEQSTAT", "SYSCFG", "RETI", "RETX", "RETN", "RETE", "EMUDAT",
345 get_allreg_name (int grp
, int reg
)
347 return greg_names
[(grp
<< 3) | reg
];
350 get_preg_name (int reg
)
352 return get_allreg_name (1, reg
);
356 reg_is_reserved (int grp
, int reg
)
358 return (grp
== 4 && (reg
== 4 || reg
== 5)) || (grp
== 5);
362 get_allreg (SIM_CPU
*cpu
, int grp
, int reg
)
364 int fullreg
= (grp
<< 3) | reg
;
365 /* REG_R0, REG_R1, REG_R2, REG_R3, REG_R4, REG_R5, REG_R6, REG_R7,
366 REG_P0, REG_P1, REG_P2, REG_P3, REG_P4, REG_P5, REG_SP, REG_FP,
367 REG_I0, REG_I1, REG_I2, REG_I3, REG_M0, REG_M1, REG_M2, REG_M3,
368 REG_B0, REG_B1, REG_B2, REG_B3, REG_L0, REG_L1, REG_L2, REG_L3,
369 REG_A0x, REG_A0w, REG_A1x, REG_A1w, , , REG_ASTAT, REG_RETS,
371 REG_LC0, REG_LT0, REG_LB0, REG_LC1, REG_LT1, REG_LB1, REG_CYCLES,
373 REG_USP, REG_SEQSTAT, REG_SYSCFG, REG_RETI, REG_RETX, REG_RETN, REG_RETE,
375 switch (fullreg
>> 2)
377 case 0: case 1: return &DREG (reg
);
378 case 2: case 3: return &PREG (reg
);
379 case 4: return &IREG (reg
& 3);
380 case 5: return &MREG (reg
& 3);
381 case 6: return &BREG (reg
& 3);
382 case 7: return &LREG (reg
& 3);
386 case 32: return &AXREG (0);
387 case 33: return &AWREG (0);
388 case 34: return &AXREG (1);
389 case 35: return &AWREG (1);
390 case 39: return &RETSREG
;
391 case 48: return &LCREG (0);
392 case 49: return <REG (0);
393 case 50: return &LBREG (0);
394 case 51: return &LCREG (1);
395 case 52: return <REG (1);
396 case 53: return &LBREG (1);
397 case 54: return &CYCLESREG
;
398 case 55: return &CYCLES2REG
;
399 case 56: return &USPREG
;
400 case 57: return &SEQSTATREG
;
401 case 58: return &SYSCFGREG
;
402 case 59: return &RETIREG
;
403 case 60: return &RETXREG
;
404 case 61: return &RETNREG
;
405 case 62: return &RETEREG
;
406 case 63: return &EMUDAT_INREG
;
408 illegal_instruction (cpu
);
413 amod0 (int s0
, int x0
)
415 static const char * const mod0
[] = {
416 "", " (S)", " (CO)", " (SCO)",
418 int i
= s0
+ (x0
<< 1);
420 if (i
< ARRAY_SIZE (mod0
))
427 amod0amod2 (int s0
, int x0
, int aop0
)
429 static const char * const mod02
[] = {
430 "", " (S)", " (CO)", " (SCO)",
432 " (ASR)", " (S, ASR)", " (CO, ASR)", " (SCO, ASR)",
433 " (ASL)", " (S, ASL)", " (CO, ASL)", " (SCO, ASL)",
435 int i
= s0
+ (x0
<< 1) + (aop0
<< 2);
437 if (i
< ARRAY_SIZE (mod02
))
444 amod1 (int s0
, int x0
)
446 static const char * const mod1
[] = {
449 int i
= s0
+ (x0
<< 1);
451 if (i
< ARRAY_SIZE (mod1
))
458 mac_optmode (int mmod
, int MM
)
460 static const char * const omode
[] = {
461 [(M_S2RND
<< 1) + 0] = " (S2RND)",
462 [(M_T
<< 1) + 0] = " (T)",
463 [(M_W32
<< 1) + 0] = " (W32)",
464 [(M_FU
<< 1) + 0] = " (FU)",
465 [(M_TFU
<< 1) + 0] = " (TFU)",
466 [(M_IS
<< 1) + 0] = " (IS)",
467 [(M_ISS2
<< 1) + 0] = " (ISS2)",
468 [(M_IH
<< 1) + 0] = " (IH)",
469 [(M_IU
<< 1) + 0] = " (IU)",
470 [(M_S2RND
<< 1) + 1] = " (M, S2RND)",
471 [(M_T
<< 1) + 1] = " (M, T)",
472 [(M_W32
<< 1) + 1] = " (M, W32)",
473 [(M_FU
<< 1) + 1] = " (M, FU)",
474 [(M_TFU
<< 1) + 1] = " (M, TFU)",
475 [(M_IS
<< 1) + 1] = " (M, IS)",
476 [(M_ISS2
<< 1) + 1] = " (M, ISS2)",
477 [(M_IH
<< 1) + 1] = " (M, IH)",
478 [(M_IU
<< 1) + 1] = " (M, IU)",
480 int i
= MM
+ (mmod
<< 1);
482 if (i
< ARRAY_SIZE (omode
) && omode
[i
])
489 get_store_name (SIM_CPU
*cpu
, bu32
*p
)
491 if (p
>= &DREG (0) && p
<= &CYCLESREG
)
492 return greg_names
[p
- &DREG (0)];
493 else if (p
== &AXREG (0))
494 return greg_names
[4 * 8 + 0];
495 else if (p
== &AWREG (0))
496 return greg_names
[4 * 8 + 1];
497 else if (p
== &AXREG (1))
498 return greg_names
[4 * 8 + 2];
499 else if (p
== &AWREG (1))
500 return greg_names
[4 * 8 + 3];
501 else if (p
== &ASTATREG (av0
))
503 else if (p
== &ASTATREG (av0s
))
504 return "ASTAT[av0s]";
505 else if (p
== &ASTATREG (av1
))
507 else if (p
== &ASTATREG (av1s
))
508 return "ASTAT[av1s]";
509 else if (p
== &ASTATREG (v
))
511 else if (p
== &ASTATREG (vs
))
513 else if (p
== &ASTATREG (v_copy
))
514 return "ASTAT[v_copy]";
515 else if (p
== &ASTATREG (az
))
517 else if (p
== &ASTATREG (an
))
519 else if (p
== &ASTATREG (az
))
521 else if (p
== &ASTATREG (ac0
))
523 else if (p
== &ASTATREG (ac0_copy
))
524 return "ASTAT[ac0_copy]";
527 /* Worry about this when we start to STORE() it. */
528 sim_io_eprintf (CPU_STATE (cpu
), "STORE(): unknown register\n");
534 queue_store (SIM_CPU
*cpu
, bu32
*addr
, bu32 val
)
536 struct store
*s
= &BFIN_CPU_STATE
.stores
[BFIN_CPU_STATE
.n_stores
];
539 TRACE_REGISTER (cpu
, "queuing write %s = %#x",
540 get_store_name (cpu
, addr
), val
);
541 ++BFIN_CPU_STATE
.n_stores
;
543 #define STORE(X, Y) \
545 if (BFIN_CPU_STATE.n_stores == 20) abort (); \
546 queue_store (cpu, &(X), (Y)); \
550 setflags_nz (SIM_CPU
*cpu
, bu32 val
)
552 SET_ASTATREG (az
, val
== 0);
553 SET_ASTATREG (an
, val
>> 31);
557 setflags_nz_2x16 (SIM_CPU
*cpu
, bu32 val
)
559 SET_ASTATREG (an
, (bs16
)val
< 0 || (bs16
)(val
>> 16) < 0);
560 SET_ASTATREG (az
, (bs16
)val
== 0 || (bs16
)(val
>> 16) == 0);
564 setflags_logical (SIM_CPU
*cpu
, bu32 val
)
566 setflags_nz (cpu
, val
);
567 SET_ASTATREG (ac0
, 0);
572 add_brev (bu32 addend1
, bu32 addend2
)
581 for (i
= 31; i
>= 0; --i
)
583 b
= ((addend1
& mask
) >> i
) + ((addend2
& mask
) >> i
);
594 /* This is a bit crazy, but we want to simulate the hardware behavior exactly
595 rather than worry about the circular buffers being used correctly. Which
596 isn't to say there isn't room for improvement here, just that we want to
597 be conservative. See also dagsub(). */
599 dagadd (SIM_CPU
*cpu
, int dagno
, bs32 M
)
601 bu64 i
= IREG (dagno
);
602 bu64 l
= LREG (dagno
);
603 bu64 b
= BREG (dagno
);
607 bu32 im32
, iml32
, lb32
, res
;
610 /* A naïve implementation that mostly works:
612 if (l && res >= b + l)
614 STORE (IREG (dagno), res);
629 if ((i
& msb
) || (IM
& car
))
630 res
= (im32
< b
) ? iml32
: im32
;
632 res
= (im32
< b
) ? im32
: iml32
;
638 if ((IM
& car
) == (LB
& car
))
639 res
= (im32
< lb32
) ? im32
: iml32
;
641 res
= (im32
< lb32
) ? iml32
: im32
;
644 STORE (IREG (dagno
), res
);
648 /* See dagadd() notes above. */
650 dagsub (SIM_CPU
*cpu
, int dagno
, bs32 M
)
652 bu64 i
= IREG (dagno
);
653 bu64 l
= LREG (dagno
);
654 bu64 b
= BREG (dagno
);
657 bu64 mbar
= (bu32
)(~m
+ 1);
659 bu32 b32
, im32
, iml32
, lb32
, res
;
662 /* A naïve implementation that mostly works:
666 STORE (IREG (dagno), newi);
681 if (!!((i
& msb
) && (IM
& car
)) == !!(LB
& car
))
682 res
= (im32
< lb32
) ? im32
: iml32
;
684 res
= (im32
< lb32
) ? iml32
: im32
;
691 if (M
== 0 || IM
& car
)
692 res
= (im32
< b32
) ? iml32
: im32
;
694 res
= (im32
< b32
) ? im32
: iml32
;
697 STORE (IREG (dagno
), res
);
702 ashiftrt (SIM_CPU
*cpu
, bu40 val
, int cnt
, int size
)
704 int real_cnt
= cnt
> size
? size
: cnt
;
705 bu40 sgn
= ~(((val
& 0xFFFFFFFFFFull
) >> (size
- 1)) - 1);
706 int sgncnt
= size
- real_cnt
;
708 sgn
<<= 16, sgncnt
-= 16;
711 val
>>= 16, real_cnt
-= 16;
714 SET_ASTATREG (an
, val
>> (size
- 1));
715 SET_ASTATREG (az
, val
== 0);
716 /* XXX: Need to check ASTAT[v] behavior here. */
722 lshiftrt (SIM_CPU
*cpu
, bu64 val
, int cnt
, int size
)
724 int real_cnt
= cnt
> size
? size
: cnt
;
726 val
>>= 16, real_cnt
-= 16;
737 val
&= 0xFFFFFFFFFFull
;
740 illegal_instruction (cpu
);
743 SET_ASTATREG (an
, val
>> (size
- 1));
744 SET_ASTATREG (az
, val
== 0);
750 lshift (SIM_CPU
*cpu
, bu64 val
, int cnt
, int size
, bool saturate
)
752 int i
, j
, real_cnt
= cnt
> size
? size
: cnt
;
753 bu64 sgn
= ~((val
>> (size
- 1)) - 1);
754 int mask_cnt
= size
- 1;
755 bu64 masked
, new_val
= val
, tmp
;
763 new_val
<<= 16, real_cnt
-= 16;
765 new_val
<<= real_cnt
;
767 masked
= new_val
& mask
;
769 /* If an operation would otherwise cause a positive value to overflow
770 and become negative, instead, saturation limits the result to the
771 maximum positive value for the size register being used.
773 Conversely, if an operation would otherwise cause a negative value
774 to overflow and become positive, saturation limits the result to the
775 maximum negative value for the register size.
777 However, it's a little more complex than looking at sign bits, we need
778 to see if we are shifting the sign information away... */
779 tmp
= val
& ((~mask
<< 1) | 1);
782 for (i
= 1; i
<= real_cnt
&& saturate
; i
++)
784 if ((tmp
& ((bu64
)1 << (size
- 1))) !=
785 (((val
>> mask_cnt
) & 0x1) << mask_cnt
))
789 saturate
&= (!sgn
&& (new_val
& (1 << mask_cnt
)))
790 || (sgn
&& !(new_val
& (1 << mask_cnt
)));
795 if (j
|| (saturate
&& (new_val
& mask
)))
796 new_val
= sgn
== 0 ? 0x7fff : 0x8000, saturate
= 1;
800 new_val
&= 0xFFFFFFFF;
801 masked
&= 0xFFFFFFFF;
802 if (j
|| (saturate
&& ((sgn
!= masked
) || (!sgn
&& new_val
== 0))))
803 new_val
= sgn
== 0 ? 0x7fffffff : 0x80000000, saturate
= 1;
806 new_val
&= 0xFFFFFFFFFFull
;
807 masked
&= 0xFFFFFFFFFFull
;
810 illegal_instruction (cpu
);
814 SET_ASTATREG (an
, new_val
>> (size
- 1));
815 SET_ASTATREG (az
, new_val
== 0);
816 SET_ASTATREG (v
, !!(saturate
|| j
));
818 SET_ASTATREG (vs
, 1);
823 algn (bu32 l
, bu32 h
, bu32 aln
)
828 return (l
>> (8 * aln
)) | (h
<< (32 - 8 * aln
));
832 saturate_s16 (bu64 val
, bu32
*overflow
)
834 if ((bs64
)val
< -0x8000ll
)
840 if ((bs64
)val
> 0x7fff)
850 rot40 (bu40 val
, int shift
, bu32
*cc
)
852 const int nbits
= 40;
855 shift
= CLAMP (shift
, -nbits
, nbits
);
859 /* Reduce everything to rotate left. */
863 ret
= shift
== nbits
? 0 : val
<< shift
;
864 ret
|= shift
== 1 ? 0 : val
>> ((nbits
+ 1) - shift
);
865 ret
|= (bu40
)*cc
<< (shift
- 1);
866 *cc
= (val
>> (nbits
- shift
)) & 1;
872 rot32 (bu32 val
, int shift
, bu32
*cc
)
874 const int nbits
= 32;
877 shift
= CLAMP (shift
, -nbits
, nbits
);
881 /* Reduce everything to rotate left. */
885 ret
= shift
== nbits
? 0 : val
<< shift
;
886 ret
|= shift
== 1 ? 0 : val
>> ((nbits
+ 1) - shift
);
887 ret
|= (bu32
)*cc
<< (shift
- 1);
888 *cc
= (val
>> (nbits
- shift
)) & 1;
894 add32 (SIM_CPU
*cpu
, bu32 a
, bu32 b
, int carry
, int sat
)
896 int flgs
= (a
>> 31) & 1;
897 int flgo
= (b
>> 31) & 1;
899 int flgn
= (v
>> 31) & 1;
900 int overflow
= (flgs
^ flgn
) & (flgo
^ flgn
);
907 flgn
= (v
>> 31) & 1;
910 SET_ASTATREG (an
, flgn
);
912 SET_ASTATREG (vs
, 1);
913 SET_ASTATREG (v
, overflow
);
914 ASTATREG (v_internal
) |= overflow
;
915 SET_ASTATREG (az
, v
== 0);
917 SET_ASTATREG (ac0
, ~a
< b
);
923 sub32 (SIM_CPU
*cpu
, bu32 a
, bu32 b
, int carry
, int sat
, int parallel
)
925 int flgs
= (a
>> 31) & 1;
926 int flgo
= (b
>> 31) & 1;
928 int flgn
= (v
>> 31) & 1;
929 int overflow
= (flgs
^ flgo
) & (flgn
^ flgs
);
936 flgn
= (v
>> 31) & 1;
939 if (!parallel
|| flgn
)
940 SET_ASTATREG (an
, flgn
);
942 SET_ASTATREG (vs
, 1);
943 if (!parallel
|| overflow
)
944 SET_ASTATREG (v
, overflow
);
945 if (!parallel
|| overflow
)
946 ASTATREG (v_internal
) |= overflow
;
947 if (!parallel
|| v
== 0)
948 SET_ASTATREG (az
, v
== 0);
949 if (carry
&& (!parallel
|| b
<= a
))
950 SET_ASTATREG (ac0
, b
<= a
);
956 add16 (SIM_CPU
*cpu
, bu16 a
, bu16 b
, bu32
*carry
, bu32
*overfl
,
957 bu32
*zero
, bu32
*neg
, int sat
, int scale
)
959 int flgs
= (a
>> 15) & 1;
960 int flgo
= (b
>> 15) & 1;
961 bs64 v
= (bs16
)a
+ (bs16
)b
;
962 int flgn
= (v
>> 15) & 1;
963 int overflow
= (flgs
^ flgn
) & (flgo
^ flgn
);
971 v
= (a
>> 1) + (a
& 0x8000) + (b
>> 1) + (b
& 0x8000)
972 + (((a
& 1) + (b
& 1)) >> 1);
980 illegal_instruction (cpu
);
983 flgn
= (v
>> 15) & 1;
984 overflow
= (flgs
^ flgn
) & (flgo
^ flgn
);
986 if (v
> (bs64
)0xffff)
990 v
= saturate_s16 (v
, 0);
993 *neg
|= (v
>> 15) & 1;
997 *zero
|= (v
& 0xFFFF) == 0;
999 *carry
|= ((bu16
)~a
< (bu16
)b
);
1005 sub16 (SIM_CPU
*cpu
, bu16 a
, bu16 b
, bu32
*carry
, bu32
*overfl
,
1006 bu32
*zero
, bu32
*neg
, int sat
, int scale
)
1008 int flgs
= (a
>> 15) & 1;
1009 int flgo
= (b
>> 15) & 1;
1010 bs64 v
= (bs16
)a
- (bs16
)b
;
1011 int flgn
= (v
>> 15) & 1;
1012 int overflow
= (flgs
^ flgo
) & (flgn
^ flgs
);
1021 v
= ((a
>> 1) + (a
& 0x8000)) - ( (b
>> 1) + (b
& 0x8000))
1022 + (((a
& 1)-(b
& 1)));
1025 v
= ((v
& 0xFFFF) >> 1);
1026 if ((!flgs
& !flgo
& flgn
)
1027 || (flgs
& !flgo
& !flgn
)
1028 || (flgs
& flgo
& flgn
)
1029 || (flgs
& !flgo
& flgn
))
1033 flgn
= (v
>> 15) & 1;
1034 overflow
= (flgs
^ flgo
) & (flgn
^ flgs
);
1039 if (v
> (bs64
)0x7fff || v
< (bs64
)-0xffff)
1043 illegal_instruction (cpu
);
1048 v
= saturate_s16 (v
, 0);
1051 *neg
|= (v
>> 15) & 1;
1053 *zero
|= (v
& 0xFFFF) == 0;
1055 *overfl
|= overflow
;
1057 *carry
|= (bu16
)b
<= (bu16
)a
;
1062 min32 (SIM_CPU
*cpu
, bu32 a
, bu32 b
)
1065 if ((bs32
)a
> (bs32
)b
)
1067 setflags_nz (cpu
, val
);
1068 SET_ASTATREG (v
, 0);
1073 max32 (SIM_CPU
*cpu
, bu32 a
, bu32 b
)
1076 if ((bs32
)a
< (bs32
)b
)
1078 setflags_nz (cpu
, val
);
1079 SET_ASTATREG (v
, 0);
1084 min2x16 (SIM_CPU
*cpu
, bu32 a
, bu32 b
)
1087 if ((bs16
)a
> (bs16
)b
)
1088 val
= (val
& 0xFFFF0000) | (b
& 0xFFFF);
1089 if ((bs16
)(a
>> 16) > (bs16
)(b
>> 16))
1090 val
= (val
& 0xFFFF) | (b
& 0xFFFF0000);
1091 setflags_nz_2x16 (cpu
, val
);
1092 SET_ASTATREG (v
, 0);
1097 max2x16 (SIM_CPU
*cpu
, bu32 a
, bu32 b
)
1100 if ((bs16
)a
< (bs16
)b
)
1101 val
= (val
& 0xFFFF0000) | (b
& 0xFFFF);
1102 if ((bs16
)(a
>> 16) < (bs16
)(b
>> 16))
1103 val
= (val
& 0xFFFF) | (b
& 0xFFFF0000);
1104 setflags_nz_2x16 (cpu
, val
);
1105 SET_ASTATREG (v
, 0);
1110 add_and_shift (SIM_CPU
*cpu
, bu32 a
, bu32 b
, int shift
)
1113 ASTATREG (v_internal
) = 0;
1114 v
= add32 (cpu
, a
, b
, 0, 0);
1117 int x
= (v
>> 30) & 0x3;
1118 if (x
== 1 || x
== 2)
1119 ASTATREG (v_internal
) = 1;
1122 SET_ASTATREG (az
, v
== 0);
1123 SET_ASTATREG (an
, v
& 0x80000000);
1124 SET_ASTATREG (v
, ASTATREG (v_internal
));
1126 SET_ASTATREG (vs
, 1);
1131 xor_reduce (bu64 acc0
, bu64 acc1
)
1135 for (i
= 0; i
< 40; ++i
)
1137 v
^= (acc0
& acc1
& 1);
1144 /* DIVS ( Dreg, Dreg ) ;
1145 Initialize for DIVQ. Set the AQ status bit based on the signs of
1146 the 32-bit dividend and the 16-bit divisor. Left shift the dividend
1147 one bit. Copy AQ into the dividend LSB. */
1149 divs (SIM_CPU
*cpu
, bu32 pquo
, bu16 divisor
)
1151 bu16 r
= pquo
>> 16;
1154 aq
= (r
^ divisor
) >> 15; /* Extract msb's and compute quotient bit. */
1155 SET_ASTATREG (aq
, aq
); /* Update global quotient state. */
1159 pquo
= (pquo
& 0x1FFFF) | (r
<< 17);
1163 /* DIVQ ( Dreg, Dreg ) ;
1164 Based on AQ status bit, either add or subtract the divisor from
1165 the dividend. Then set the AQ status bit based on the MSBs of the
1166 32-bit dividend and the 16-bit divisor. Left shift the dividend one
1167 bit. Copy the logical inverse of AQ into the dividend LSB. */
1169 divq (SIM_CPU
*cpu
, bu32 pquo
, bu16 divisor
)
1171 unsigned short af
= pquo
>> 16;
1180 aq
= (r
^ divisor
) >> 15; /* Extract msb's and compute quotient bit. */
1181 SET_ASTATREG (aq
, aq
); /* Update global quotient state. */
1185 pquo
= (pquo
& 0x1FFFF) | (r
<< 17);
1190 Count the number of bits set to 1 in the 32bit value. */
1198 for (i
= 0; i
< 32; ++i
)
1199 ret
+= !!(val
& (1 << i
));
1205 reg_check_sup (SIM_CPU
*cpu
, int grp
, int reg
)
1208 cec_require_supervisor (cpu
);
1212 reg_write (SIM_CPU
*cpu
, int grp
, int reg
, bu32 value
)
1216 /* ASTAT is special! */
1217 if (grp
== 4 && reg
== 6)
1223 /* Check supervisor after get_allreg() so exception order is correct. */
1224 whichreg
= get_allreg (cpu
, grp
, reg
);
1225 reg_check_sup (cpu
, grp
, reg
);
1227 if (whichreg
== &CYCLES2REG
)
1228 /* Writes to CYCLES2 goes to the shadow. */
1229 whichreg
= &CYCLES2SHDREG
;
1230 else if (whichreg
== &SEQSTATREG
)
1231 /* Register is read only -- discard writes. */
1233 else if (whichreg
== &EMUDAT_INREG
)
1234 /* Writes to EMUDAT goes to the output. */
1235 whichreg
= &EMUDAT_OUTREG
;
1236 else if (whichreg
== <REG (0) || whichreg
== <REG (1))
1237 /* Writes to LT clears LSB automatically. */
1239 else if (whichreg
== &AXREG (0) || whichreg
== &AXREG (1))
1242 TRACE_REGISTER (cpu
, "wrote %s = %#x", get_allreg_name (grp
, reg
), value
);
1248 reg_read (SIM_CPU
*cpu
, int grp
, int reg
)
1253 /* ASTAT is special! */
1254 if (grp
== 4 && reg
== 6)
1257 /* Check supervisor after get_allreg() so exception order is correct. */
1258 whichreg
= get_allreg (cpu
, grp
, reg
);
1259 reg_check_sup (cpu
, grp
, reg
);
1263 if (whichreg
== &CYCLESREG
)
1264 /* Reads of CYCLES reloads CYCLES2 from the shadow. */
1265 SET_CYCLES2REG (CYCLES2SHDREG
);
1266 else if ((whichreg
== &AXREG (1) || whichreg
== &AXREG (0)) && (value
& 0x80))
1267 /* Sign extend if necessary. */
1268 value
|= 0xFFFFFF00;
1274 get_extended_cycles (SIM_CPU
*cpu
)
1276 return ((bu64
)CYCLES2SHDREG
<< 32) | CYCLESREG
;
1279 /* We can't re-use sim_events_time() because the CYCLES registers may be
1280 written/cleared/reset/stopped/started at any time by software. */
1282 cycles_inc (SIM_CPU
*cpu
, bu32 inc
)
1287 if (!(SYSCFGREG
& SYSCFG_CCEN
))
1290 cycles
= get_extended_cycles (cpu
) + inc
;
1291 SET_CYCLESREG (cycles
);
1292 cycles2
= cycles
>> 32;
1293 if (CYCLES2SHDREG
!= cycles2
)
1294 SET_CYCLES2SHDREG (cycles2
);
1298 get_unextended_acc (SIM_CPU
*cpu
, int which
)
1300 return ((bu64
)(AXREG (which
) & 0xff) << 32) | AWREG (which
);
1304 get_extended_acc (SIM_CPU
*cpu
, int which
)
1306 bu64 acc
= AXREG (which
);
1307 /* Sign extend accumulator values before adding. */
1313 acc
|= AWREG (which
);
1317 /* Perform a multiplication of D registers SRC0 and SRC1, sign- or
1318 zero-extending the result to 64 bit. H0 and H1 determine whether the
1319 high part or the low part of the source registers is used. Store 1 in
1320 *PSAT if saturation occurs, 0 otherwise. */
1322 decode_multfunc (SIM_CPU
*cpu
, int h0
, int h1
, int src0
, int src1
, int mmod
,
1325 bu32 s0
= DREG (src0
), s1
= DREG (src1
);
1339 sgn0
= -(s0
& 0x8000);
1340 sgn1
= -(s1
& 0x8000);
1362 illegal_instruction (cpu
);
1366 /* Perform shift correction if appropriate for the mode. */
1368 if (!MM
&& (mmod
== 0 || mmod
== M_T
|| mmod
== M_S2RND
|| mmod
== M_W32
))
1370 if (val
== 0x40000000)
1383 if (mmod
== 0 || mmod
== M_IS
|| mmod
== M_T
|| mmod
== M_S2RND
1384 || mmod
== M_ISS2
|| mmod
== M_IH
|| (MM
&& mmod
== M_FU
))
1385 val1
|= -(val1
& 0x80000000);
1388 val1
&= 0xFFFFFFFFull
;
1394 saturate_s40_astat (bu64 val
, bu32
*v
)
1396 if ((bs64
)val
< -((bs64
)1 << 39))
1399 return -((bs64
)1 << 39);
1401 else if ((bs64
)val
>= ((bs64
)1 << 39) - 1)
1404 return ((bu64
)1 << 39) - 1;
1406 *v
= 0; /* No overflow. */
1411 saturate_s40 (bu64 val
)
1414 return saturate_s40_astat (val
, &v
);
1418 saturate_s32 (bu64 val
, bu32
*overflow
)
1420 if ((bs64
)val
< -0x80000000ll
)
1426 if ((bs64
)val
> 0x7fffffff)
1436 saturate_u32 (bu64 val
, bu32
*overflow
)
1438 if (val
> 0xffffffff)
1448 saturate_u16 (bu64 val
, bu32
*overflow
)
1464 /* FIXME: Should honour rounding mode. */
1465 if ((val
& 0xffff) > 0x8000
1466 || ((val
& 0xffff) == 0x8000 && (val
& 0x10000)))
1469 sgnbits
= val
& 0xffff000000000000ull
;
1471 return val
| sgnbits
;
1477 bu64 sgnbits
= val
& 0xffff000000000000ull
;
1479 return val
| sgnbits
;
1483 signbits (bu64 val
, int size
)
1485 bu64 mask
= (bu64
)1 << (size
- 1);
1486 bu64 bit
= val
& mask
;
1494 if ((val
& mask
) != bit
)
1504 /* Extract a 16 or 32 bit value from a 64 bit multiplication result.
1505 These 64 bits must be sign- or zero-extended properly from the source
1506 we want to extract, either a 32 bit multiply or a 40 bit accumulator. */
1509 extract_mult (SIM_CPU
*cpu
, bu64 res
, int mmod
, int MM
,
1510 int fullword
, bu32
*overflow
)
1517 return saturate_s32 (res
, overflow
);
1519 return saturate_u32 (res
, overflow
);
1522 return saturate_s32 (res
, overflow
);
1523 return saturate_u32 (res
, overflow
);
1526 return saturate_s32 (res
<< 1, overflow
);
1528 illegal_instruction (cpu
);
1535 return saturate_s16 (rnd16 (res
), overflow
);
1537 return saturate_s32 (rnd16 (res
), overflow
) & 0xFFFF;
1539 return saturate_s16 (res
, overflow
);
1542 return saturate_s16 (rnd16 (res
), overflow
);
1543 return saturate_u16 (rnd16 (res
), overflow
);
1546 return saturate_s16 (res
, overflow
);
1547 return saturate_u16 (res
, overflow
);
1550 return saturate_s16 (trunc16 (res
), overflow
);
1552 return saturate_u16 (trunc16 (res
), overflow
);
1555 return saturate_s16 (rnd16 (res
<< 1), overflow
);
1557 return saturate_s16 (res
<< 1, overflow
);
1559 illegal_instruction (cpu
);
1564 decode_macfunc (SIM_CPU
*cpu
, int which
, int op
, int h0
, int h1
, int src0
,
1565 int src1
, int mmod
, int MM
, int fullword
, bu32
*overflow
)
1570 /* Sign extend accumulator if necessary, otherwise unsigned. */
1571 if (mmod
== 0 || mmod
== M_T
|| mmod
== M_IS
|| mmod
== M_ISS2
1572 || mmod
== M_S2RND
|| mmod
== M_IH
|| mmod
== M_W32
)
1573 acc
= get_extended_acc (cpu
, which
);
1575 acc
= get_unextended_acc (cpu
, which
);
1577 if (MM
&& (mmod
== M_T
|| mmod
== M_IS
|| mmod
== M_ISS2
1578 || mmod
== M_S2RND
|| mmod
== M_IH
|| mmod
== M_W32
))
1579 acc
|= -(acc
& 0x80000000);
1583 bu8 sgn0
= (acc
>> 31) & 1;
1584 /* This can't saturate, so we don't keep track of the sat flag. */
1585 bu64 res
= decode_multfunc (cpu
, h0
, h1
, src0
, src1
, mmod
,
1588 /* Perform accumulation. */
1593 sgn0
= (acc
>> 31) & 1;
1611 if ((bs64
)acc
< -((bs64
)1 << 39))
1612 acc
= -((bu64
)1 << 39), sat
= 1;
1613 else if ((bs64
)acc
> 0x7fffffffffll
)
1614 acc
= 0x7fffffffffull
, sat
= 1;
1617 if (!MM
&& acc
> 0xFFFFFFFFFFull
)
1619 if (MM
&& acc
> 0xFFFFFFFF)
1623 if (acc
& 0x8000000000000000ull
)
1625 if (acc
> 0xFFFFFFFFFFull
)
1626 acc
&= 0xFFFFFFFFFFull
, sat
= 1;
1627 if (MM
&& acc
> 0xFFFFFFFF)
1629 if (acc
& 0x80000000)
1630 acc
|= 0xffffffff00000000ull
;
1633 if (!MM
&& (bs64
)acc
< 0)
1635 if (MM
&& (bs64
)acc
< -((bs64
)1 << 39))
1636 acc
= -((bu64
)1 << 39), sat
= 1;
1637 if (!MM
&& (bs64
)acc
> (bs64
)0xFFFFFFFFFFll
)
1638 acc
= 0xFFFFFFFFFFull
, sat
= 1;
1639 if (MM
&& acc
> 0xFFFFFFFFFFull
)
1640 acc
&= 0xFFFFFFFFFFull
;
1641 if (MM
&& acc
& 0x80000000)
1642 acc
|= 0xffffffff00000000ull
;
1645 if ((bs64
)acc
< -0x80000000ll
)
1646 acc
= -0x80000000ull
, sat
= 1;
1647 else if ((bs64
)acc
>= 0x7fffffffll
)
1648 acc
= 0x7fffffffull
, sat
= 1;
1651 if (sgn0
&& (sgn0
!= ((acc
>> 31) & 1))
1652 && (((acc
>> 32) & 0xFF) == 0xff))
1655 if (acc
& 0x80000000)
1656 acc
|= 0xffffffff00000000ull
;
1659 illegal_instruction (cpu
);
1663 STORE (AXREG (which
), (acc
>> 32) & 0xff);
1664 STORE (AWREG (which
), acc
& 0xffffffff);
1665 STORE (ASTATREG (av
[which
]), sat
);
1667 STORE (ASTATREG (avs
[which
]), sat
);
1669 return extract_mult (cpu
, acc
, mmod
, MM
, fullword
, overflow
);
1673 hwloop_get_next_pc (SIM_CPU
*cpu
, bu32 pc
, bu32 insn_len
)
1680 /* If our PC has reached the bottom of a hardware loop,
1681 move back up to the top of the hardware loop. */
1682 for (i
= 1; i
>= 0; --i
)
1683 if (LCREG (i
) > 1 && pc
== LBREG (i
))
1685 TRACE_BRANCH (cpu
, pc
, LTREG (i
), i
, "Hardware loop %i", i
);
1689 return pc
+ insn_len
;
1693 decode_ProgCtrl_0 (SIM_CPU
*cpu
, bu16 iw0
, bu32 pc
)
1696 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
1697 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |.prgfunc.......|.poprnd........|
1698 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
1699 int poprnd
= ((iw0
>> ProgCtrl_poprnd_bits
) & ProgCtrl_poprnd_mask
);
1700 int prgfunc
= ((iw0
>> ProgCtrl_prgfunc_bits
) & ProgCtrl_prgfunc_mask
);
1702 TRACE_EXTRACT (cpu
, "%s: poprnd:%i prgfunc:%i", __func__
, poprnd
, prgfunc
);
1704 if (prgfunc
== 0 && poprnd
== 0)
1706 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_nop
);
1707 TRACE_INSN (cpu
, "NOP;");
1709 else if (prgfunc
== 1 && poprnd
== 0)
1711 bu32 newpc
= RETSREG
;
1712 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1713 TRACE_INSN (cpu
, "RTS;");
1714 IFETCH_CHECK (newpc
);
1716 illegal_instruction_combination (cpu
);
1717 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "RTS");
1719 BFIN_CPU_STATE
.did_jump
= true;
1722 else if (prgfunc
== 1 && poprnd
== 1)
1724 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1725 TRACE_INSN (cpu
, "RTI;");
1726 /* Do not do IFETCH_CHECK here -- LSB has special meaning. */
1728 illegal_instruction_combination (cpu
);
1729 cec_return (cpu
, -1);
1732 else if (prgfunc
== 1 && poprnd
== 2)
1734 bu32 newpc
= RETXREG
;
1735 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1736 TRACE_INSN (cpu
, "RTX;");
1737 /* XXX: Not sure if this is what the hardware does. */
1738 IFETCH_CHECK (newpc
);
1740 illegal_instruction_combination (cpu
);
1741 cec_return (cpu
, IVG_EVX
);
1744 else if (prgfunc
== 1 && poprnd
== 3)
1746 bu32 newpc
= RETNREG
;
1747 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1748 TRACE_INSN (cpu
, "RTN;");
1749 /* XXX: Not sure if this is what the hardware does. */
1750 IFETCH_CHECK (newpc
);
1752 illegal_instruction_combination (cpu
);
1753 cec_return (cpu
, IVG_NMI
);
1756 else if (prgfunc
== 1 && poprnd
== 4)
1758 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1759 TRACE_INSN (cpu
, "RTE;");
1761 illegal_instruction_combination (cpu
);
1762 cec_return (cpu
, IVG_EMU
);
1765 else if (prgfunc
== 2 && poprnd
== 0)
1767 SIM_DESC sd
= CPU_STATE (cpu
);
1768 sim_events
*events
= STATE_EVENTS (sd
);
1770 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_sync
);
1771 /* XXX: in supervisor mode, utilizes wake up sources
1772 in user mode, it's a NOP ... */
1773 TRACE_INSN (cpu
, "IDLE;");
1776 illegal_instruction_combination (cpu
);
1780 CYCLE_DELAY
= events
->time_from_event
;
1782 abort (); /* XXX: Should this ever happen ? */
1784 else if (prgfunc
== 2 && poprnd
== 3)
1786 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_sync
);
1788 TRACE_INSN (cpu
, "CSYNC;");
1790 illegal_instruction_combination (cpu
);
1793 else if (prgfunc
== 2 && poprnd
== 4)
1795 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_sync
);
1797 TRACE_INSN (cpu
, "SSYNC;");
1799 illegal_instruction_combination (cpu
);
1801 /* Really 10+, but no model info for this. */
1804 else if (prgfunc
== 2 && poprnd
== 5)
1806 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1807 TRACE_INSN (cpu
, "EMUEXCPT;");
1809 illegal_instruction_combination (cpu
);
1810 cec_exception (cpu
, VEC_SIM_TRAP
);
1812 else if (prgfunc
== 3 && poprnd
< 8)
1814 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1815 TRACE_INSN (cpu
, "CLI R%i;", poprnd
);
1817 illegal_instruction_combination (cpu
);
1818 SET_DREG (poprnd
, cec_cli (cpu
));
1820 else if (prgfunc
== 4 && poprnd
< 8)
1822 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1823 TRACE_INSN (cpu
, "STI R%i;", poprnd
);
1825 illegal_instruction_combination (cpu
);
1826 cec_sti (cpu
, DREG (poprnd
));
1829 else if (prgfunc
== 5 && poprnd
< 8)
1831 bu32 newpc
= PREG (poprnd
);
1832 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1833 TRACE_INSN (cpu
, "JUMP (%s);", get_preg_name (poprnd
));
1834 IFETCH_CHECK (newpc
);
1836 illegal_instruction_combination (cpu
);
1837 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP (Preg)");
1839 BFIN_CPU_STATE
.did_jump
= true;
1840 PROFILE_BRANCH_TAKEN (cpu
);
1843 else if (prgfunc
== 6 && poprnd
< 8)
1845 bu32 newpc
= PREG (poprnd
);
1846 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1847 TRACE_INSN (cpu
, "CALL (%s);", get_preg_name (poprnd
));
1848 IFETCH_CHECK (newpc
);
1850 illegal_instruction_combination (cpu
);
1851 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "CALL (Preg)");
1852 /* If we're at the end of a hardware loop, RETS is going to be
1853 the top of the loop rather than the next instruction. */
1854 SET_RETSREG (hwloop_get_next_pc (cpu
, pc
, 2));
1856 BFIN_CPU_STATE
.did_jump
= true;
1857 PROFILE_BRANCH_TAKEN (cpu
);
1860 else if (prgfunc
== 7 && poprnd
< 8)
1862 bu32 newpc
= pc
+ PREG (poprnd
);
1863 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1864 TRACE_INSN (cpu
, "CALL (PC + %s);", get_preg_name (poprnd
));
1865 IFETCH_CHECK (newpc
);
1867 illegal_instruction_combination (cpu
);
1868 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "CALL (PC + Preg)");
1869 SET_RETSREG (hwloop_get_next_pc (cpu
, pc
, 2));
1871 BFIN_CPU_STATE
.did_jump
= true;
1872 PROFILE_BRANCH_TAKEN (cpu
);
1875 else if (prgfunc
== 8 && poprnd
< 8)
1877 bu32 newpc
= pc
+ PREG (poprnd
);
1878 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1879 TRACE_INSN (cpu
, "JUMP (PC + %s);", get_preg_name (poprnd
));
1880 IFETCH_CHECK (newpc
);
1882 illegal_instruction_combination (cpu
);
1883 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP (PC + Preg)");
1885 BFIN_CPU_STATE
.did_jump
= true;
1886 PROFILE_BRANCH_TAKEN (cpu
);
1889 else if (prgfunc
== 9)
1891 int raise
= uimm4 (poprnd
);
1892 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1893 TRACE_INSN (cpu
, "RAISE %s;", uimm4_str (raise
));
1895 illegal_instruction_combination (cpu
);
1896 cec_require_supervisor (cpu
);
1897 if (raise
== IVG_IVHW
)
1898 cec_hwerr (cpu
, HWERR_RAISE_5
);
1900 cec_latch (cpu
, raise
);
1901 CYCLE_DELAY
= 3; /* XXX: Only if IVG is unmasked. */
1903 else if (prgfunc
== 10)
1905 int excpt
= uimm4 (poprnd
);
1906 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1907 TRACE_INSN (cpu
, "EXCPT %s;", uimm4_str (excpt
));
1909 illegal_instruction_combination (cpu
);
1910 cec_exception (cpu
, excpt
);
1913 else if (prgfunc
== 11 && poprnd
< 6)
1915 bu32 addr
= PREG (poprnd
);
1917 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_atomic
);
1918 TRACE_INSN (cpu
, "TESTSET (%s);", get_preg_name (poprnd
));
1920 illegal_instruction_combination (cpu
);
1921 byte
= GET_WORD (addr
);
1922 SET_CCREG (byte
== 0);
1923 PUT_BYTE (addr
, byte
| 0x80);
1924 /* Also includes memory stalls, but we don't model that. */
1928 illegal_instruction (cpu
);
1932 decode_CaCTRL_0 (SIM_CPU
*cpu
, bu16 iw0
)
1935 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
1936 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 |.a.|.op....|.reg.......|
1937 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
1938 int a
= ((iw0
>> CaCTRL_a_bits
) & CaCTRL_a_mask
);
1939 int op
= ((iw0
>> CaCTRL_op_bits
) & CaCTRL_op_mask
);
1940 int reg
= ((iw0
>> CaCTRL_reg_bits
) & CaCTRL_reg_mask
);
1941 bu32 preg
= PREG (reg
);
1942 const char * const sinsn
[] = { "PREFETCH", "FLUSHINV", "FLUSH", "IFLUSH", };
1944 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CaCTRL
);
1945 TRACE_EXTRACT (cpu
, "%s: a:%i op:%i reg:%i", __func__
, a
, op
, reg
);
1946 TRACE_INSN (cpu
, "%s [%s%s];", sinsn
[op
], get_preg_name (reg
), a
? "++" : "");
1949 /* None of these can be part of a parallel instruction. */
1950 illegal_instruction_combination (cpu
);
1952 /* No cache simulation, so these are (mostly) all NOPs.
1953 XXX: The hardware takes care of masking to cache lines, but need
1954 to check behavior of the post increment. Should we be aligning
1955 the value to the cache line before adding the cache line size, or
1956 do we just add the cache line size ? */
1959 mmu_check_cache_addr (cpu
, preg
, false, false);
1963 mmu_check_cache_addr (cpu
, preg
, true, false);
1967 mmu_check_cache_addr (cpu
, preg
, true, false);
1971 mmu_check_cache_addr (cpu
, preg
, false, true);
1975 SET_PREG (reg
, preg
+ BFIN_L1_CACHE_BYTES
);
1979 decode_PushPopReg_0 (SIM_CPU
*cpu
, bu16 iw0
)
1982 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
1983 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |.W.|.grp.......|.reg.......|
1984 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
1985 int W
= ((iw0
>> PushPopReg_W_bits
) & PushPopReg_W_mask
);
1986 int grp
= ((iw0
>> PushPopReg_grp_bits
) & PushPopReg_grp_mask
);
1987 int reg
= ((iw0
>> PushPopReg_reg_bits
) & PushPopReg_reg_mask
);
1988 const char *reg_name
= get_allreg_name (grp
, reg
);
1992 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_PushPopReg
);
1993 TRACE_EXTRACT (cpu
, "%s: W:%i grp:%i reg:%i", __func__
, W
, grp
, reg
);
1994 TRACE_DECODE (cpu
, "%s: reg:%s", __func__
, reg_name
);
1996 /* Can't push/pop reserved registers */
1997 if (reg_is_reserved (grp
, reg
))
1998 illegal_instruction (cpu
);
2002 /* Dreg and Preg are not supported by this instruction. */
2003 if (grp
== 0 || grp
== 1)
2004 illegal_instruction (cpu
);
2005 TRACE_INSN (cpu
, "%s = [SP++];", reg_name
);
2006 /* Can't pop USP while in userspace. */
2007 if (INSN_LEN
== 8 || (grp
== 7 && reg
== 0 && cec_is_user_mode(cpu
)))
2008 illegal_instruction_combination (cpu
);
2009 /* XXX: The valid register check is in reg_write(), so we might
2010 incorrectly do a GET_LONG() here ... */
2011 value
= GET_LONG (sp
);
2012 reg_write (cpu
, grp
, reg
, value
);
2013 if (grp
== 7 && reg
== 3)
2020 TRACE_INSN (cpu
, "[--SP] = %s;", reg_name
);
2021 /* Can't push SP. */
2022 if (INSN_LEN
== 8 || (grp
== 1 && reg
== 6))
2023 illegal_instruction_combination (cpu
);
2026 value
= reg_read (cpu
, grp
, reg
);
2027 if (grp
== 7 && reg
== 3)
2028 cec_push_reti (cpu
);
2030 PUT_LONG (sp
, value
);
2033 /* Note: SP update must be delayed until after all reads/writes; see
2034 comments in decode_PushPopMultiple_0() for more info. */
2039 decode_PushPopMultiple_0 (SIM_CPU
*cpu
, bu16 iw0
)
2042 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2043 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |.d.|.p.|.W.|.dr........|.pr........|
2044 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2045 int p
= ((iw0
>> PushPopMultiple_p_bits
) & PushPopMultiple_p_mask
);
2046 int d
= ((iw0
>> PushPopMultiple_d_bits
) & PushPopMultiple_d_mask
);
2047 int W
= ((iw0
>> PushPopMultiple_W_bits
) & PushPopMultiple_W_mask
);
2048 int dr
= ((iw0
>> PushPopMultiple_dr_bits
) & PushPopMultiple_dr_mask
);
2049 int pr
= ((iw0
>> PushPopMultiple_pr_bits
) & PushPopMultiple_pr_mask
);
2053 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_PushPopMultiple
);
2054 TRACE_EXTRACT (cpu
, "%s: d:%i p:%i W:%i dr:%i pr:%i",
2055 __func__
, d
, p
, W
, dr
, pr
);
2057 if ((d
== 0 && p
== 0) || (p
&& imm5 (pr
) > 5)
2058 || (d
&& !p
&& pr
) || (p
&& !d
&& dr
))
2059 illegal_instruction (cpu
);
2064 TRACE_INSN (cpu
, "[--SP] = (R7:%i, P5:%i);", dr
, pr
);
2066 TRACE_INSN (cpu
, "[--SP] = (R7:%i);", dr
);
2068 TRACE_INSN (cpu
, "[--SP] = (P5:%i);", pr
);
2071 for (i
= dr
; i
< 8; i
++)
2074 PUT_LONG (sp
, DREG (i
));
2077 for (i
= pr
; i
< 6; i
++)
2080 PUT_LONG (sp
, PREG (i
));
2088 TRACE_INSN (cpu
, "(R7:%i, P5:%i) = [SP++];", dr
, pr
);
2090 TRACE_INSN (cpu
, "(R7:%i) = [SP++];", dr
);
2092 TRACE_INSN (cpu
, "(P5:%i) = [SP++];", pr
);
2095 for (i
= 5; i
>= pr
; i
--)
2097 SET_PREG (i
, GET_LONG (sp
));
2101 for (i
= 7; i
>= dr
; i
--)
2103 SET_DREG (i
, GET_LONG (sp
));
2110 /* Note: SP update must be delayed until after all reads/writes so that
2111 if an exception does occur, the insn may be re-executed as the
2112 SP has not yet changed. */
2117 decode_ccMV_0 (SIM_CPU
*cpu
, bu16 iw0
)
2120 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2121 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |.T.|.d.|.s.|.dst.......|.src.......|
2122 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2123 int s
= ((iw0
>> CCmv_s_bits
) & CCmv_s_mask
);
2124 int d
= ((iw0
>> CCmv_d_bits
) & CCmv_d_mask
);
2125 int T
= ((iw0
>> CCmv_T_bits
) & CCmv_T_mask
);
2126 int src
= ((iw0
>> CCmv_src_bits
) & CCmv_src_mask
);
2127 int dst
= ((iw0
>> CCmv_dst_bits
) & CCmv_dst_mask
);
2128 int cond
= T
? CCREG
: ! CCREG
;
2130 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ccMV
);
2131 TRACE_EXTRACT (cpu
, "%s: T:%i d:%i s:%i dst:%i src:%i",
2132 __func__
, T
, d
, s
, dst
, src
);
2134 TRACE_INSN (cpu
, "IF %sCC %s = %s;", T
? "" : "! ",
2135 get_allreg_name (d
, dst
),
2136 get_allreg_name (s
, src
));
2138 illegal_instruction_combination (cpu
);
2141 reg_write (cpu
, d
, dst
, reg_read (cpu
, s
, src
));
2145 decode_CCflag_0 (SIM_CPU
*cpu
, bu16 iw0
)
2148 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2149 | 0 | 0 | 0 | 0 | 1 |.I.|.opc.......|.G.|.y.........|.x.........|
2150 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2151 int x
= ((iw0
>> CCflag_x_bits
) & CCflag_x_mask
);
2152 int y
= ((iw0
>> CCflag_y_bits
) & CCflag_y_mask
);
2153 int I
= ((iw0
>> CCflag_I_bits
) & CCflag_I_mask
);
2154 int G
= ((iw0
>> CCflag_G_bits
) & CCflag_G_mask
);
2155 int opc
= ((iw0
>> CCflag_opc_bits
) & CCflag_opc_mask
);
2157 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CCflag
);
2158 TRACE_EXTRACT (cpu
, "%s: I:%i opc:%i G:%i y:%i x:%i",
2159 __func__
, I
, opc
, G
, y
, x
);
2163 bs64 acc0
= get_extended_acc (cpu
, 0);
2164 bs64 acc1
= get_extended_acc (cpu
, 1);
2165 bs64 diff
= acc0
- acc1
;
2167 if (x
!= 0 || y
!= 0)
2168 illegal_instruction (cpu
);
2170 if (opc
== 5 && I
== 0 && G
== 0)
2172 TRACE_INSN (cpu
, "CC = A0 == A1;");
2174 illegal_instruction_combination (cpu
);
2175 SET_CCREG (acc0
== acc1
);
2177 else if (opc
== 6 && I
== 0 && G
== 0)
2179 TRACE_INSN (cpu
, "CC = A0 < A1");
2181 illegal_instruction_combination (cpu
);
2182 SET_CCREG (acc0
< acc1
);
2184 else if (opc
== 7 && I
== 0 && G
== 0)
2186 TRACE_INSN (cpu
, "CC = A0 <= A1");
2188 illegal_instruction_combination (cpu
);
2189 SET_CCREG (acc0
<= acc1
);
2192 illegal_instruction (cpu
);
2194 SET_ASTATREG (az
, diff
== 0);
2195 SET_ASTATREG (an
, diff
< 0);
2196 SET_ASTATREG (ac0
, (bu40
)acc1
<= (bu40
)acc0
);
2200 int issigned
= opc
< 3;
2201 const char *sign
= issigned
? "" : " (IU)";
2202 bu32 srcop
= G
? PREG (x
) : DREG (x
);
2203 char s
= G
? 'P' : 'R';
2204 bu32 dstop
= I
? (issigned
? imm3 (y
) : uimm3 (y
)) : G
? PREG (y
) : DREG (y
);
2206 char d
= G
? 'P' : 'R';
2207 int flgs
= srcop
>> 31;
2208 int flgo
= dstop
>> 31;
2210 bu32 result
= srcop
- dstop
;
2212 int flgn
= result
>> 31;
2213 int overflow
= (flgs
^ flgo
) & (flgn
^ flgs
);
2214 int az
= result
== 0;
2215 int ac0
= dstop
<= srcop
;
2218 an
= (flgn
&& !overflow
) || (!flgn
&& overflow
);
2224 default: /* Shutup useless gcc warnings. */
2225 case 0: /* signed */
2229 case 1: /* signed */
2233 case 2: /* signed */
2237 case 3: /* unsigned */
2241 case 4: /* unsigned */
2248 TRACE_INSN (cpu
, "CC = %c%i %s %s%s;", s
, x
, op
,
2249 issigned
? imm3_str (y
) : uimm3_str (y
), sign
);
2252 TRACE_DECODE (cpu
, "%s %c%i:%x %c%i:%x", __func__
,
2253 s
, x
, srcop
, d
, y
, dstop
);
2254 TRACE_INSN (cpu
, "CC = %c%i %s %c%i%s;", s
, x
, op
, d
, y
, sign
);
2258 /* Pointer compares only touch CC. */
2261 SET_ASTATREG (az
, az
);
2262 SET_ASTATREG (an
, an
);
2263 SET_ASTATREG (ac0
, ac0
);
2269 decode_CC2dreg_0 (SIM_CPU
*cpu
, bu16 iw0
)
2272 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2273 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |.op....|.reg.......|
2274 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2275 int op
= ((iw0
>> CC2dreg_op_bits
) & CC2dreg_op_mask
);
2276 int reg
= ((iw0
>> CC2dreg_reg_bits
) & CC2dreg_reg_mask
);
2278 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CC2dreg
);
2279 TRACE_EXTRACT (cpu
, "%s: op:%i reg:%i", __func__
, op
, reg
);
2283 TRACE_INSN (cpu
, "R%i = CC;", reg
);
2285 illegal_instruction_combination (cpu
);
2286 SET_DREG (reg
, CCREG
);
2290 TRACE_INSN (cpu
, "CC = R%i;", reg
);
2292 illegal_instruction_combination (cpu
);
2293 SET_CCREG (DREG (reg
) != 0);
2295 else if (op
== 3 && reg
== 0)
2297 TRACE_INSN (cpu
, "CC = !CC;");
2299 illegal_instruction_combination (cpu
);
2303 illegal_instruction (cpu
);
2307 decode_CC2stat_0 (SIM_CPU
*cpu
, bu16 iw0
)
2310 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2311 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |.D.|.op....|.cbit..............|
2312 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2313 int D
= ((iw0
>> CC2stat_D_bits
) & CC2stat_D_mask
);
2314 int op
= ((iw0
>> CC2stat_op_bits
) & CC2stat_op_mask
);
2315 int cbit
= ((iw0
>> CC2stat_cbit_bits
) & CC2stat_cbit_mask
);
2318 const char * const op_names
[] = { "", "|", "&", "^" } ;
2320 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CC2stat
);
2321 TRACE_EXTRACT (cpu
, "%s: D:%i op:%i cbit:%i", __func__
, D
, op
, cbit
);
2323 TRACE_INSN (cpu
, "%s %s= %s;", D
? astat_names
[cbit
] : "CC",
2324 op_names
[op
], D
? "CC" : astat_names
[cbit
]);
2326 /* CC = CC; is invalid. */
2328 illegal_instruction (cpu
);
2331 illegal_instruction_combination (cpu
);
2333 pval
= !!(ASTAT
& (1 << cbit
));
2337 case 0: SET_CCREG (pval
); break;
2338 case 1: SET_CCREG (CCREG
| pval
); break;
2339 case 2: SET_CCREG (CCREG
& pval
); break;
2340 case 3: SET_CCREG (CCREG
^ pval
); break;
2346 case 0: pval
= CCREG
; break;
2347 case 1: pval
|= CCREG
; break;
2348 case 2: pval
&= CCREG
; break;
2349 case 3: pval
^= CCREG
; break;
2351 TRACE_REGISTER (cpu
, "wrote ASTAT[%s] = %i", astat_names
[cbit
], pval
);
2352 SET_ASTAT ((ASTAT
& ~(1 << cbit
)) | (pval
<< cbit
));
2357 decode_BRCC_0 (SIM_CPU
*cpu
, bu16 iw0
, bu32 pc
)
2360 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2361 | 0 | 0 | 0 | 1 |.T.|.B.|.offset................................|
2362 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2363 int B
= ((iw0
>> BRCC_B_bits
) & BRCC_B_mask
);
2364 int T
= ((iw0
>> BRCC_T_bits
) & BRCC_T_mask
);
2365 int offset
= ((iw0
>> BRCC_offset_bits
) & BRCC_offset_mask
);
2366 int cond
= T
? CCREG
: ! CCREG
;
2367 int pcrel
= pcrel10 (offset
);
2369 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_BRCC
);
2370 TRACE_EXTRACT (cpu
, "%s: T:%i B:%i offset:%#x", __func__
, T
, B
, offset
);
2371 TRACE_DECODE (cpu
, "%s: pcrel10:%#x", __func__
, pcrel
);
2373 TRACE_INSN (cpu
, "IF %sCC JUMP %#x%s;", T
? "" : "! ",
2374 pcrel
, B
? " (bp)" : "");
2377 illegal_instruction_combination (cpu
);
2381 bu32 newpc
= pc
+ pcrel
;
2382 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "Conditional JUMP");
2384 BFIN_CPU_STATE
.did_jump
= true;
2385 PROFILE_BRANCH_TAKEN (cpu
);
2386 CYCLE_DELAY
= B
? 5 : 9;
2390 PROFILE_BRANCH_UNTAKEN (cpu
);
2391 CYCLE_DELAY
= B
? 9 : 1;
2396 decode_UJUMP_0 (SIM_CPU
*cpu
, bu16 iw0
, bu32 pc
)
2399 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2400 | 0 | 0 | 1 | 0 |.offset........................................|
2401 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2402 int offset
= ((iw0
>> UJump_offset_bits
) & UJump_offset_mask
);
2403 int pcrel
= pcrel12 (offset
);
2404 bu32 newpc
= pc
+ pcrel
;
2406 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_UJUMP
);
2407 TRACE_EXTRACT (cpu
, "%s: offset:%#x", __func__
, offset
);
2408 TRACE_DECODE (cpu
, "%s: pcrel12:%#x", __func__
, pcrel
);
2410 TRACE_INSN (cpu
, "JUMP.S %#x;", pcrel
);
2413 illegal_instruction_combination (cpu
);
2415 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP.S");
2418 BFIN_CPU_STATE
.did_jump
= true;
2419 PROFILE_BRANCH_TAKEN (cpu
);
2424 decode_REGMV_0 (SIM_CPU
*cpu
, bu16 iw0
)
2427 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2428 | 0 | 0 | 1 | 1 |.gd........|.gs........|.dst.......|.src.......|
2429 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2430 int gs
= ((iw0
>> RegMv_gs_bits
) & RegMv_gs_mask
);
2431 int gd
= ((iw0
>> RegMv_gd_bits
) & RegMv_gd_mask
);
2432 int src
= ((iw0
>> RegMv_src_bits
) & RegMv_src_mask
);
2433 int dst
= ((iw0
>> RegMv_dst_bits
) & RegMv_dst_mask
);
2434 const char *srcreg_name
= get_allreg_name (gs
, src
);
2435 const char *dstreg_name
= get_allreg_name (gd
, dst
);
2437 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_REGMV
);
2438 TRACE_EXTRACT (cpu
, "%s: gd:%i gs:%i dst:%i src:%i",
2439 __func__
, gd
, gs
, dst
, src
);
2440 TRACE_DECODE (cpu
, "%s: dst:%s src:%s", __func__
, dstreg_name
, srcreg_name
);
2442 TRACE_INSN (cpu
, "%s = %s;", dstreg_name
, srcreg_name
);
2444 /* Reserved slots cannot be a src/dst. */
2445 if (reg_is_reserved (gs
, src
) || reg_is_reserved (gd
, dst
))
2448 /* Standard register moves. */
2449 if ((gs
< 2) /* Dregs/Pregs src */
2450 || (gd
< 2) /* Dregs/Pregs dst */
2451 || (gs
== 4 && src
< 4) /* Accumulators src */
2452 || (gd
== 4 && dst
< 4 && (gs
< 4)) /* Accumulators dst */
2453 || (gs
== 7 && src
== 7 && !(gd
== 4 && dst
< 4)) /* EMUDAT src */
2454 || (gd
== 7 && dst
== 7)) /* EMUDAT dst */
2457 /* dareg = dareg (IMBL) */
2458 if (gs
< 4 && gd
< 4)
2461 /* USP can be src to sysregs, but not dagregs. */
2462 if ((gs
== 7 && src
== 0) && (gd
>= 4))
2465 /* USP can move between genregs (only check Accumulators). */
2466 if (((gs
== 7 && src
== 0) && (gd
== 4 && dst
< 4))
2467 || ((gd
== 7 && dst
== 0) && (gs
== 4 && src
< 4)))
2470 /* Still here ? Invalid reg pair. */
2472 illegal_instruction (cpu
);
2475 reg_write (cpu
, gd
, dst
, reg_read (cpu
, gs
, src
));
2479 decode_ALU2op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2482 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2483 | 0 | 1 | 0 | 0 | 0 | 0 |.opc...........|.src.......|.dst.......|
2484 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2485 int src
= ((iw0
>> ALU2op_src_bits
) & ALU2op_src_mask
);
2486 int opc
= ((iw0
>> ALU2op_opc_bits
) & ALU2op_opc_mask
);
2487 int dst
= ((iw0
>> ALU2op_dst_bits
) & ALU2op_dst_mask
);
2489 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ALU2op
);
2490 TRACE_EXTRACT (cpu
, "%s: opc:%i src:%i dst:%i", __func__
, opc
, src
, dst
);
2494 TRACE_INSN (cpu
, "R%i >>>= R%i;", dst
, src
);
2495 SET_DREG (dst
, ashiftrt (cpu
, DREG (dst
), DREG (src
), 32));
2500 TRACE_INSN (cpu
, "R%i >>= R%i;", dst
, src
);
2501 if (DREG (src
) <= 0x1F)
2502 val
= lshiftrt (cpu
, DREG (dst
), DREG (src
), 32);
2505 SET_DREG (dst
, val
);
2509 TRACE_INSN (cpu
, "R%i <<= R%i;", dst
, src
);
2510 SET_DREG (dst
, lshift (cpu
, DREG (dst
), DREG (src
), 32, 0));
2514 TRACE_INSN (cpu
, "R%i *= R%i;", dst
, src
);
2515 SET_DREG (dst
, DREG (dst
) * DREG (src
));
2520 TRACE_INSN (cpu
, "R%i = (R%i + R%i) << 1;", dst
, dst
, src
);
2521 SET_DREG (dst
, add_and_shift (cpu
, DREG (dst
), DREG (src
), 1));
2525 TRACE_INSN (cpu
, "R%i = (R%i + R%i) << 2;", dst
, dst
, src
);
2526 SET_DREG (dst
, add_and_shift (cpu
, DREG (dst
), DREG (src
), 2));
2530 TRACE_INSN (cpu
, "DIVQ ( R%i, R%i );", dst
, src
);
2531 SET_DREG (dst
, divq (cpu
, DREG (dst
), (bu16
)DREG (src
)));
2535 TRACE_INSN (cpu
, "DIVS ( R%i, R%i );", dst
, src
);
2536 SET_DREG (dst
, divs (cpu
, DREG (dst
), (bu16
)DREG (src
)));
2540 TRACE_INSN (cpu
, "R%i = R%i.L (X);", dst
, src
);
2541 SET_DREG (dst
, (bs32
) (bs16
) DREG (src
));
2542 setflags_logical (cpu
, DREG (dst
));
2546 TRACE_INSN (cpu
, "R%i = R%i.L (Z);", dst
, src
);
2547 SET_DREG (dst
, (bu32
) (bu16
) DREG (src
));
2548 setflags_logical (cpu
, DREG (dst
));
2552 TRACE_INSN (cpu
, "R%i = R%i.B (X);", dst
, src
);
2553 SET_DREG (dst
, (bs32
) (bs8
) DREG (src
));
2554 setflags_logical (cpu
, DREG (dst
));
2558 TRACE_INSN (cpu
, "R%i = R%i.B (Z);", dst
, src
);
2559 SET_DREG (dst
, (bu32
) (bu8
) DREG (src
));
2560 setflags_logical (cpu
, DREG (dst
));
2564 bu32 val
= DREG (src
);
2565 TRACE_INSN (cpu
, "R%i = - R%i;", dst
, src
);
2566 SET_DREG (dst
, -val
);
2567 setflags_nz (cpu
, DREG (dst
));
2568 SET_ASTATREG (v
, val
== 0x80000000);
2570 SET_ASTATREG (vs
, 1);
2571 SET_ASTATREG (ac0
, val
== 0x0);
2572 /* XXX: Documentation isn't entirely clear about av0 and av1. */
2576 TRACE_INSN (cpu
, "R%i = ~ R%i;", dst
, src
);
2577 SET_DREG (dst
, ~DREG (src
));
2578 setflags_logical (cpu
, DREG (dst
));
2581 illegal_instruction (cpu
);
2585 decode_PTR2op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2588 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2589 | 0 | 1 | 0 | 0 | 0 | 1 | 0 |.opc.......|.src.......|.dst.......|
2590 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2591 int src
= ((iw0
>> PTR2op_src_bits
) & PTR2op_dst_mask
);
2592 int opc
= ((iw0
>> PTR2op_opc_bits
) & PTR2op_opc_mask
);
2593 int dst
= ((iw0
>> PTR2op_dst_bits
) & PTR2op_dst_mask
);
2594 const char *src_name
= get_preg_name (src
);
2595 const char *dst_name
= get_preg_name (dst
);
2597 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_PTR2op
);
2598 TRACE_EXTRACT (cpu
, "%s: opc:%i src:%i dst:%i", __func__
, opc
, src
, dst
);
2602 TRACE_INSN (cpu
, "%s -= %s", dst_name
, src_name
);
2603 SET_PREG (dst
, PREG (dst
) - PREG (src
));
2607 TRACE_INSN (cpu
, "%s = %s << 2", dst_name
, src_name
);
2608 SET_PREG (dst
, PREG (src
) << 2);
2612 TRACE_INSN (cpu
, "%s = %s >> 2", dst_name
, src_name
);
2613 SET_PREG (dst
, PREG (src
) >> 2);
2617 TRACE_INSN (cpu
, "%s = %s >> 1", dst_name
, src_name
);
2618 SET_PREG (dst
, PREG (src
) >> 1);
2622 TRACE_INSN (cpu
, "%s += %s (BREV)", dst_name
, src_name
);
2623 SET_PREG (dst
, add_brev (PREG (dst
), PREG (src
)));
2627 TRACE_INSN (cpu
, "%s = (%s + %s) << 1", dst_name
, dst_name
, src_name
);
2628 SET_PREG (dst
, (PREG (dst
) + PREG (src
)) << 1);
2632 TRACE_INSN (cpu
, "%s = (%s + %s) << 2", dst_name
, dst_name
, src_name
);
2633 SET_PREG (dst
, (PREG (dst
) + PREG (src
)) << 2);
2636 illegal_instruction (cpu
);
2640 decode_LOGI2op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2643 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2644 | 0 | 1 | 0 | 0 | 1 |.opc.......|.src...............|.dst.......|
2645 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2646 int src
= ((iw0
>> LOGI2op_src_bits
) & LOGI2op_src_mask
);
2647 int opc
= ((iw0
>> LOGI2op_opc_bits
) & LOGI2op_opc_mask
);
2648 int dst
= ((iw0
>> LOGI2op_dst_bits
) & LOGI2op_dst_mask
);
2649 int uimm
= uimm5 (src
);
2650 const char *uimm_str
= uimm5_str (uimm
);
2652 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LOGI2op
);
2653 TRACE_EXTRACT (cpu
, "%s: opc:%i src:%i dst:%i", __func__
, opc
, src
, dst
);
2654 TRACE_DECODE (cpu
, "%s: uimm5:%#x", __func__
, uimm
);
2658 TRACE_INSN (cpu
, "CC = ! BITTST (R%i, %s);", dst
, uimm_str
);
2660 illegal_instruction_combination (cpu
);
2661 SET_CCREG ((~DREG (dst
) >> uimm
) & 1);
2665 TRACE_INSN (cpu
, "CC = BITTST (R%i, %s);", dst
, uimm_str
);
2667 illegal_instruction_combination (cpu
);
2668 SET_CCREG ((DREG (dst
) >> uimm
) & 1);
2672 TRACE_INSN (cpu
, "BITSET (R%i, %s);", dst
, uimm_str
);
2674 illegal_instruction_combination (cpu
);
2675 SET_DREG (dst
, DREG (dst
) | (1 << uimm
));
2676 setflags_logical (cpu
, DREG (dst
));
2680 TRACE_INSN (cpu
, "BITTGL (R%i, %s);", dst
, uimm_str
);
2682 illegal_instruction_combination (cpu
);
2683 SET_DREG (dst
, DREG (dst
) ^ (1 << uimm
));
2684 setflags_logical (cpu
, DREG (dst
));
2688 TRACE_INSN (cpu
, "BITCLR (R%i, %s);", dst
, uimm_str
);
2690 illegal_instruction_combination (cpu
);
2691 SET_DREG (dst
, DREG (dst
) & ~(1 << uimm
));
2692 setflags_logical (cpu
, DREG (dst
));
2696 TRACE_INSN (cpu
, "R%i >>>= %s;", dst
, uimm_str
);
2698 illegal_instruction_combination (cpu
);
2699 SET_DREG (dst
, ashiftrt (cpu
, DREG (dst
), uimm
, 32));
2703 TRACE_INSN (cpu
, "R%i >>= %s;", dst
, uimm_str
);
2705 illegal_instruction_combination (cpu
);
2706 SET_DREG (dst
, lshiftrt (cpu
, DREG (dst
), uimm
, 32));
2710 TRACE_INSN (cpu
, "R%i <<= %s;", dst
, uimm_str
);
2712 illegal_instruction_combination (cpu
);
2713 SET_DREG (dst
, lshift (cpu
, DREG (dst
), uimm
, 32, 0));
2718 decode_COMP3op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2721 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2722 | 0 | 1 | 0 | 1 |.opc.......|.dst.......|.src1......|.src0......|
2723 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2724 int opc
= ((iw0
>> COMP3op_opc_bits
) & COMP3op_opc_mask
);
2725 int dst
= ((iw0
>> COMP3op_dst_bits
) & COMP3op_dst_mask
);
2726 int src0
= ((iw0
>> COMP3op_src0_bits
) & COMP3op_src0_mask
);
2727 int src1
= ((iw0
>> COMP3op_src1_bits
) & COMP3op_src1_mask
);
2729 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_COMP3op
);
2730 TRACE_EXTRACT (cpu
, "%s: opc:%i dst:%i src1:%i src0:%i",
2731 __func__
, opc
, dst
, src1
, src0
);
2735 TRACE_INSN (cpu
, "R%i = R%i + R%i;", dst
, src0
, src1
);
2736 SET_DREG (dst
, add32 (cpu
, DREG (src0
), DREG (src1
), 1, 0));
2740 TRACE_INSN (cpu
, "R%i = R%i - R%i;", dst
, src0
, src1
);
2741 SET_DREG (dst
, sub32 (cpu
, DREG (src0
), DREG (src1
), 1, 0, 0));
2745 TRACE_INSN (cpu
, "R%i = R%i & R%i;", dst
, src0
, src1
);
2746 SET_DREG (dst
, DREG (src0
) & DREG (src1
));
2747 setflags_logical (cpu
, DREG (dst
));
2751 TRACE_INSN (cpu
, "R%i = R%i | R%i;", dst
, src0
, src1
);
2752 SET_DREG (dst
, DREG (src0
) | DREG (src1
));
2753 setflags_logical (cpu
, DREG (dst
));
2757 TRACE_INSN (cpu
, "R%i = R%i ^ R%i;", dst
, src0
, src1
);
2758 SET_DREG (dst
, DREG (src0
) ^ DREG (src1
));
2759 setflags_logical (cpu
, DREG (dst
));
2763 int shift
= opc
- 5;
2764 const char *dst_name
= get_preg_name (dst
);
2765 const char *src0_name
= get_preg_name (src0
);
2766 const char *src1_name
= get_preg_name (src1
);
2768 /* If src0 == src1 this is disassembled as a shift by 1, but this
2769 distinction doesn't matter for our purposes. */
2771 TRACE_INSN (cpu
, "%s = (%s + %s) << %#x;",
2772 dst_name
, src0_name
, src1_name
, shift
);
2774 TRACE_INSN (cpu
, "%s = %s + %s",
2775 dst_name
, src0_name
, src1_name
);
2776 SET_PREG (dst
, PREG (src0
) + (PREG (src1
) << shift
));
2781 decode_COMPI2opD_0 (SIM_CPU
*cpu
, bu16 iw0
)
2784 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2785 | 0 | 1 | 1 | 0 | 0 |.op|..src......................|.dst.......|
2786 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2787 int op
= ((iw0
>> COMPI2opD_op_bits
) & COMPI2opD_op_mask
);
2788 int dst
= ((iw0
>> COMPI2opD_dst_bits
) & COMPI2opD_dst_mask
);
2789 int src
= ((iw0
>> COMPI2opD_src_bits
) & COMPI2opD_src_mask
);
2790 int imm
= imm7 (src
);
2792 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_COMPI2opD
);
2793 TRACE_EXTRACT (cpu
, "%s: op:%i src:%i dst:%i", __func__
, op
, src
, dst
);
2794 TRACE_DECODE (cpu
, "%s: imm7:%#x", __func__
, imm
);
2798 TRACE_INSN (cpu
, "R%i = %s (X);", dst
, imm7_str (imm
));
2799 SET_DREG (dst
, imm
);
2803 TRACE_INSN (cpu
, "R%i += %s;", dst
, imm7_str (imm
));
2804 SET_DREG (dst
, add32 (cpu
, DREG (dst
), imm
, 1, 0));
2809 decode_COMPI2opP_0 (SIM_CPU
*cpu
, bu16 iw0
)
2812 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2813 | 0 | 1 | 1 | 0 | 1 |.op|.src.......................|.dst.......|
2814 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2815 int op
= ((iw0
>> COMPI2opP_op_bits
) & COMPI2opP_op_mask
);
2816 int src
= ((iw0
>> COMPI2opP_src_bits
) & COMPI2opP_src_mask
);
2817 int dst
= ((iw0
>> COMPI2opP_dst_bits
) & COMPI2opP_dst_mask
);
2818 int imm
= imm7 (src
);
2819 const char *dst_name
= get_preg_name (dst
);
2821 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_COMPI2opP
);
2822 TRACE_EXTRACT (cpu
, "%s: op:%i src:%i dst:%i", __func__
, op
, src
, dst
);
2823 TRACE_DECODE (cpu
, "%s: imm:%#x", __func__
, imm
);
2827 TRACE_INSN (cpu
, "%s = %s;", dst_name
, imm7_str (imm
));
2828 SET_PREG (dst
, imm
);
2832 TRACE_INSN (cpu
, "%s += %s;", dst_name
, imm7_str (imm
));
2833 SET_PREG (dst
, PREG (dst
) + imm
);
2838 decode_LDSTpmod_0 (SIM_CPU
*cpu
, bu16 iw0
)
2841 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2842 | 1 | 0 | 0 | 0 |.W.|.aop...|.reg.......|.idx.......|.ptr.......|
2843 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2844 int W
= ((iw0
>> LDSTpmod_W_bits
) & LDSTpmod_W_mask
);
2845 int aop
= ((iw0
>> LDSTpmod_aop_bits
) & LDSTpmod_aop_mask
);
2846 int idx
= ((iw0
>> LDSTpmod_idx_bits
) & LDSTpmod_idx_mask
);
2847 int ptr
= ((iw0
>> LDSTpmod_ptr_bits
) & LDSTpmod_ptr_mask
);
2848 int reg
= ((iw0
>> LDSTpmod_reg_bits
) & LDSTpmod_reg_mask
);
2849 const char *ptr_name
= get_preg_name (ptr
);
2850 const char *idx_name
= get_preg_name (idx
);
2853 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTpmod
);
2854 TRACE_EXTRACT (cpu
, "%s: W:%i aop:%i reg:%i idx:%i ptr:%i",
2855 __func__
, W
, aop
, reg
, idx
, ptr
);
2857 if (aop
== 1 && W
== 0 && idx
== ptr
)
2859 TRACE_INSN (cpu
, "R%i.L = W[%s];", reg
, ptr_name
);
2861 val
= GET_WORD (addr
);
2862 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | val
);
2864 else if (aop
== 2 && W
== 0 && idx
== ptr
)
2866 TRACE_INSN (cpu
, "R%i.H = W[%s];", reg
, ptr_name
);
2868 val
= GET_WORD (addr
);
2869 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (val
<< 16));
2871 else if (aop
== 1 && W
== 1 && idx
== ptr
)
2873 TRACE_INSN (cpu
, "W[%s] = R%i.L;", ptr_name
, reg
);
2875 PUT_WORD (addr
, DREG (reg
));
2877 else if (aop
== 2 && W
== 1 && idx
== ptr
)
2879 TRACE_INSN (cpu
, "W[%s] = R%i.H;", ptr_name
, reg
);
2881 PUT_WORD (addr
, DREG (reg
) >> 16);
2883 else if (aop
== 0 && W
== 0)
2885 TRACE_INSN (cpu
, "R%i = [%s ++ %s];", reg
, ptr_name
, idx_name
);
2887 val
= GET_LONG (addr
);
2888 STORE (DREG (reg
), val
);
2890 STORE (PREG (ptr
), addr
+ PREG (idx
));
2892 else if (aop
== 1 && W
== 0)
2894 TRACE_INSN (cpu
, "R%i.L = W[%s ++ %s];", reg
, ptr_name
, idx_name
);
2896 val
= GET_WORD (addr
);
2897 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | val
);
2899 STORE (PREG (ptr
), addr
+ PREG (idx
));
2901 else if (aop
== 2 && W
== 0)
2903 TRACE_INSN (cpu
, "R%i.H = W[%s ++ %s];", reg
, ptr_name
, idx_name
);
2905 val
= GET_WORD (addr
);
2906 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (val
<< 16));
2908 STORE (PREG (ptr
), addr
+ PREG (idx
));
2910 else if (aop
== 3 && W
== 0)
2912 TRACE_INSN (cpu
, "R%i = W[%s ++ %s] (Z);", reg
, ptr_name
, idx_name
);
2914 val
= GET_WORD (addr
);
2915 STORE (DREG (reg
), val
);
2917 STORE (PREG (ptr
), addr
+ PREG (idx
));
2919 else if (aop
== 3 && W
== 1)
2921 TRACE_INSN (cpu
, "R%i = W[%s ++ %s] (X);", reg
, ptr_name
, idx_name
);
2923 val
= GET_WORD (addr
);
2924 STORE (DREG (reg
), (bs32
) (bs16
) val
);
2926 STORE (PREG (ptr
), addr
+ PREG (idx
));
2928 else if (aop
== 0 && W
== 1)
2930 TRACE_INSN (cpu
, "[%s ++ %s] = R%i;", ptr_name
, idx_name
, reg
);
2932 PUT_LONG (addr
, DREG (reg
));
2934 STORE (PREG (ptr
), addr
+ PREG (idx
));
2936 else if (aop
== 1 && W
== 1)
2938 TRACE_INSN (cpu
, "W[%s ++ %s] = R%i.L;", ptr_name
, idx_name
, reg
);
2940 PUT_WORD (addr
, DREG (reg
));
2942 STORE (PREG (ptr
), addr
+ PREG (idx
));
2944 else if (aop
== 2 && W
== 1)
2946 TRACE_INSN (cpu
, "W[%s ++ %s] = R%i.H;", ptr_name
, idx_name
, reg
);
2948 PUT_WORD (addr
, DREG (reg
) >> 16);
2950 STORE (PREG (ptr
), addr
+ PREG (idx
));
2953 illegal_instruction (cpu
);
2957 decode_dagMODim_0 (SIM_CPU
*cpu
, bu16 iw0
)
2960 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2961 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 0 |.br| 1 | 1 |.op|.m.....|.i.....|
2962 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2963 int i
= ((iw0
>> DagMODim_i_bits
) & DagMODim_i_mask
);
2964 int m
= ((iw0
>> DagMODim_m_bits
) & DagMODim_m_mask
);
2965 int br
= ((iw0
>> DagMODim_br_bits
) & DagMODim_br_mask
);
2966 int op
= ((iw0
>> DagMODim_op_bits
) & DagMODim_op_mask
);
2968 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dagMODim
);
2969 TRACE_EXTRACT (cpu
, "%s: br:%i op:%i m:%i i:%i", __func__
, br
, op
, m
, i
);
2971 if (op
== 0 && br
== 1)
2973 TRACE_INSN (cpu
, "I%i += M%i (BREV);", i
, m
);
2974 SET_IREG (i
, add_brev (IREG (i
), MREG (m
)));
2978 TRACE_INSN (cpu
, "I%i += M%i;", i
, m
);
2979 dagadd (cpu
, i
, MREG (m
));
2981 else if (op
== 1 && br
== 0)
2983 TRACE_INSN (cpu
, "I%i -= M%i;", i
, m
);
2984 dagsub (cpu
, i
, MREG (m
));
2987 illegal_instruction (cpu
);
2991 decode_dagMODik_0 (SIM_CPU
*cpu
, bu16 iw0
)
2994 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2995 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 0 |.op....|.i.....|
2996 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2997 int i
= ((iw0
>> DagMODik_i_bits
) & DagMODik_i_mask
);
2998 int op
= ((iw0
>> DagMODik_op_bits
) & DagMODik_op_mask
);
3000 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dagMODik
);
3001 TRACE_EXTRACT (cpu
, "%s: op:%i i:%i", __func__
, op
, i
);
3005 TRACE_INSN (cpu
, "I%i += 2;", i
);
3010 TRACE_INSN (cpu
, "I%i -= 2;", i
);
3015 TRACE_INSN (cpu
, "I%i += 4;", i
);
3020 TRACE_INSN (cpu
, "I%i -= 4;", i
);
3024 illegal_instruction (cpu
);
3028 decode_dspLDST_0 (SIM_CPU
*cpu
, bu16 iw0
)
3031 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3032 | 1 | 0 | 0 | 1 | 1 | 1 |.W.|.aop...|.m.....|.i.....|.reg.......|
3033 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3034 int i
= ((iw0
>> DspLDST_i_bits
) & DspLDST_i_mask
);
3035 int m
= ((iw0
>> DspLDST_m_bits
) & DspLDST_m_mask
);
3036 int W
= ((iw0
>> DspLDST_W_bits
) & DspLDST_W_mask
);
3037 int aop
= ((iw0
>> DspLDST_aop_bits
) & DspLDST_aop_mask
);
3038 int reg
= ((iw0
>> DspLDST_reg_bits
) & DspLDST_reg_mask
);
3041 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dspLDST
);
3042 TRACE_EXTRACT (cpu
, "%s: aop:%i m:%i i:%i reg:%i", __func__
, aop
, m
, i
, reg
);
3044 if (aop
== 0 && W
== 0 && m
== 0)
3046 TRACE_INSN (cpu
, "R%i = [I%i++];", reg
, i
);
3048 if (DIS_ALGN_EXPT
& 0x1)
3051 STORE (DREG (reg
), GET_LONG (addr
));
3053 else if (aop
== 0 && W
== 0 && m
== 1)
3055 TRACE_INSN (cpu
, "R%i.L = W[I%i++];", reg
, i
);
3058 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | GET_WORD (addr
));
3060 else if (aop
== 0 && W
== 0 && m
== 2)
3062 TRACE_INSN (cpu
, "R%i.H = W[I%i++];", reg
, i
);
3065 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (GET_WORD (addr
) << 16));
3067 else if (aop
== 1 && W
== 0 && m
== 0)
3069 TRACE_INSN (cpu
, "R%i = [I%i--];", reg
, i
);
3071 if (DIS_ALGN_EXPT
& 0x1)
3074 STORE (DREG (reg
), GET_LONG (addr
));
3076 else if (aop
== 1 && W
== 0 && m
== 1)
3078 TRACE_INSN (cpu
, "R%i.L = W[I%i--];", reg
, i
);
3081 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | GET_WORD (addr
));
3083 else if (aop
== 1 && W
== 0 && m
== 2)
3085 TRACE_INSN (cpu
, "R%i.H = W[I%i--];", reg
, i
);
3088 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (GET_WORD (addr
) << 16));
3090 else if (aop
== 2 && W
== 0 && m
== 0)
3092 TRACE_INSN (cpu
, "R%i = [I%i];", reg
, i
);
3094 if (DIS_ALGN_EXPT
& 0x1)
3096 STORE (DREG (reg
), GET_LONG (addr
));
3098 else if (aop
== 2 && W
== 0 && m
== 1)
3100 TRACE_INSN (cpu
, "R%i.L = W[I%i];", reg
, i
);
3102 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | GET_WORD (addr
));
3104 else if (aop
== 2 && W
== 0 && m
== 2)
3106 TRACE_INSN (cpu
, "R%i.H = W[I%i];", reg
, i
);
3108 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (GET_WORD (addr
) << 16));
3110 else if (aop
== 0 && W
== 1 && m
== 0)
3112 TRACE_INSN (cpu
, "[I%i++] = R%i;", i
, reg
);
3115 PUT_LONG (addr
, DREG (reg
));
3117 else if (aop
== 0 && W
== 1 && m
== 1)
3119 TRACE_INSN (cpu
, "W[I%i++] = R%i.L;", i
, reg
);
3122 PUT_WORD (addr
, DREG (reg
));
3124 else if (aop
== 0 && W
== 1 && m
== 2)
3126 TRACE_INSN (cpu
, "W[I%i++] = R%i.H;", i
, reg
);
3129 PUT_WORD (addr
, DREG (reg
) >> 16);
3131 else if (aop
== 1 && W
== 1 && m
== 0)
3133 TRACE_INSN (cpu
, "[I%i--] = R%i;", i
, reg
);
3136 PUT_LONG (addr
, DREG (reg
));
3138 else if (aop
== 1 && W
== 1 && m
== 1)
3140 TRACE_INSN (cpu
, "W[I%i--] = R%i.L;", i
, reg
);
3143 PUT_WORD (addr
, DREG (reg
));
3145 else if (aop
== 1 && W
== 1 && m
== 2)
3147 TRACE_INSN (cpu
, "W[I%i--] = R%i.H;", i
, reg
);
3150 PUT_WORD (addr
, DREG (reg
) >> 16);
3152 else if (aop
== 2 && W
== 1 && m
== 0)
3154 TRACE_INSN (cpu
, "[I%i] = R%i;", i
, reg
);
3156 PUT_LONG (addr
, DREG (reg
));
3158 else if (aop
== 2 && W
== 1 && m
== 1)
3160 TRACE_INSN (cpu
, "W[I%i] = R%i.L;", i
, reg
);
3162 PUT_WORD (addr
, DREG (reg
));
3164 else if (aop
== 2 && W
== 1 && m
== 2)
3166 TRACE_INSN (cpu
, "W[I%i] = R%i.H;", i
, reg
);
3168 PUT_WORD (addr
, DREG (reg
) >> 16);
3170 else if (aop
== 3 && W
== 0)
3172 TRACE_INSN (cpu
, "R%i = [I%i ++ M%i];", reg
, i
, m
);
3174 if (DIS_ALGN_EXPT
& 0x1)
3176 dagadd (cpu
, i
, MREG (m
));
3177 STORE (DREG (reg
), GET_LONG (addr
));
3179 else if (aop
== 3 && W
== 1)
3181 TRACE_INSN (cpu
, "[I%i ++ M%i] = R%i;", i
, m
, reg
);
3183 dagadd (cpu
, i
, MREG (m
));
3184 PUT_LONG (addr
, DREG (reg
));
3187 illegal_instruction (cpu
);
3191 decode_LDST_0 (SIM_CPU
*cpu
, bu16 iw0
)
3194 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3195 | 1 | 0 | 0 | 1 |.sz....|.W.|.aop...|.Z.|.ptr.......|.reg.......|
3196 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3197 int Z
= ((iw0
>> LDST_Z_bits
) & LDST_Z_mask
);
3198 int W
= ((iw0
>> LDST_W_bits
) & LDST_W_mask
);
3199 int sz
= ((iw0
>> LDST_sz_bits
) & LDST_sz_mask
);
3200 int aop
= ((iw0
>> LDST_aop_bits
) & LDST_aop_mask
);
3201 int reg
= ((iw0
>> LDST_reg_bits
) & LDST_reg_mask
);
3202 int ptr
= ((iw0
>> LDST_ptr_bits
) & LDST_ptr_mask
);
3203 const char * const posts
[] = { "++", "--", "" };
3204 const char *post
= posts
[aop
];
3205 const char *ptr_name
= get_preg_name (ptr
);
3207 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDST
);
3208 TRACE_EXTRACT (cpu
, "%s: sz:%i W:%i aop:%i Z:%i ptr:%i reg:%i",
3209 __func__
, sz
, W
, aop
, Z
, ptr
, reg
);
3212 illegal_instruction (cpu
);
3216 if (sz
== 0 && Z
== 0)
3218 TRACE_INSN (cpu
, "R%i = [%s%s];", reg
, ptr_name
, post
);
3219 SET_DREG (reg
, GET_LONG (PREG (ptr
)));
3221 else if (sz
== 0 && Z
== 1)
3223 TRACE_INSN (cpu
, "%s = [%s%s];", get_preg_name (reg
), ptr_name
, post
);
3224 if (aop
< 2 && ptr
== reg
)
3225 illegal_instruction_combination (cpu
);
3226 SET_PREG (reg
, GET_LONG (PREG (ptr
)));
3228 else if (sz
== 1 && Z
== 0)
3230 TRACE_INSN (cpu
, "R%i = W[%s%s] (Z);", reg
, ptr_name
, post
);
3231 SET_DREG (reg
, GET_WORD (PREG (ptr
)));
3233 else if (sz
== 1 && Z
== 1)
3235 TRACE_INSN (cpu
, "R%i = W[%s%s] (X);", reg
, ptr_name
, post
);
3236 SET_DREG (reg
, (bs32
) (bs16
) GET_WORD (PREG (ptr
)));
3238 else if (sz
== 2 && Z
== 0)
3240 TRACE_INSN (cpu
, "R%i = B[%s%s] (Z);", reg
, ptr_name
, post
);
3241 SET_DREG (reg
, GET_BYTE (PREG (ptr
)));
3243 else if (sz
== 2 && Z
== 1)
3245 TRACE_INSN (cpu
, "R%i = B[%s%s] (X);", reg
, ptr_name
, post
);
3246 SET_DREG (reg
, (bs32
) (bs8
) GET_BYTE (PREG (ptr
)));
3249 illegal_instruction (cpu
);
3253 if (sz
== 0 && Z
== 0)
3255 TRACE_INSN (cpu
, "[%s%s] = R%i;", ptr_name
, post
, reg
);
3256 PUT_LONG (PREG (ptr
), DREG (reg
));
3258 else if (sz
== 0 && Z
== 1)
3260 TRACE_INSN (cpu
, "[%s%s] = %s;", ptr_name
, post
, get_preg_name (reg
));
3261 PUT_LONG (PREG (ptr
), PREG (reg
));
3263 else if (sz
== 1 && Z
== 0)
3265 TRACE_INSN (cpu
, "W[%s%s] = R%i;", ptr_name
, post
, reg
);
3266 PUT_WORD (PREG (ptr
), DREG (reg
));
3268 else if (sz
== 2 && Z
== 0)
3270 TRACE_INSN (cpu
, "B[%s%s] = R%i;", ptr_name
, post
, reg
);
3271 PUT_BYTE (PREG (ptr
), DREG (reg
));
3274 illegal_instruction (cpu
);
3278 SET_PREG (ptr
, PREG (ptr
) + (1 << (2 - sz
)));
3280 SET_PREG (ptr
, PREG (ptr
) - (1 << (2 - sz
)));
3284 decode_LDSTiiFP_0 (SIM_CPU
*cpu
, bu16 iw0
)
3287 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3288 | 1 | 0 | 1 | 1 | 1 | 0 |.W.|.offset............|.reg...........|
3289 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3290 /* This isn't exactly a grp:reg as this insn only supports Dregs & Pregs,
3291 but for our usage, its functionality the same thing. */
3292 int grp
= ((iw0
>> 3) & 0x1);
3293 int reg
= ((iw0
>> LDSTiiFP_reg_bits
) & 0x7 /*LDSTiiFP_reg_mask*/);
3294 int offset
= ((iw0
>> LDSTiiFP_offset_bits
) & LDSTiiFP_offset_mask
);
3295 int W
= ((iw0
>> LDSTiiFP_W_bits
) & LDSTiiFP_W_mask
);
3296 bu32 imm
= negimm5s4 (offset
);
3297 bu32 ea
= FPREG
+ imm
;
3298 const char *imm_str
= negimm5s4_str (offset
);
3299 const char *reg_name
= get_allreg_name (grp
, reg
);
3301 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTiiFP
);
3302 TRACE_EXTRACT (cpu
, "%s: W:%i offset:%#x grp:%i reg:%i", __func__
,
3303 W
, offset
, grp
, reg
);
3304 TRACE_DECODE (cpu
, "%s: negimm5s4:%#x", __func__
, imm
);
3308 TRACE_INSN (cpu
, "%s = [FP + %s];", reg_name
, imm_str
);
3309 reg_write (cpu
, grp
, reg
, GET_LONG (ea
));
3313 TRACE_INSN (cpu
, "[FP + %s] = %s;", imm_str
, reg_name
);
3314 PUT_LONG (ea
, reg_read (cpu
, grp
, reg
));
3319 decode_LDSTii_0 (SIM_CPU
*cpu
, bu16 iw0
)
3322 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3323 | 1 | 0 | 1 |.W.|.op....|.offset........|.ptr.......|.reg.......|
3324 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3325 int reg
= ((iw0
>> LDSTii_reg_bit
) & LDSTii_reg_mask
);
3326 int ptr
= ((iw0
>> LDSTii_ptr_bit
) & LDSTii_ptr_mask
);
3327 int offset
= ((iw0
>> LDSTii_offset_bit
) & LDSTii_offset_mask
);
3328 int op
= ((iw0
>> LDSTii_op_bit
) & LDSTii_op_mask
);
3329 int W
= ((iw0
>> LDSTii_W_bit
) & LDSTii_W_mask
);
3331 const char *imm_str
;
3332 const char *ptr_name
= get_preg_name (ptr
);
3334 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTii
);
3335 TRACE_EXTRACT (cpu
, "%s: W:%i op:%i offset:%#x ptr:%i reg:%i",
3336 __func__
, W
, op
, offset
, ptr
, reg
);
3338 if (op
== 0 || op
== 3)
3339 imm
= uimm4s4 (offset
), imm_str
= uimm4s4_str (offset
);
3341 imm
= uimm4s2 (offset
), imm_str
= uimm4s2_str (offset
);
3342 ea
= PREG (ptr
) + imm
;
3344 TRACE_DECODE (cpu
, "%s: uimm4s4/uimm4s2:%#x", __func__
, imm
);
3346 if (W
== 1 && op
== 2)
3347 illegal_instruction (cpu
);
3353 TRACE_INSN (cpu
, "R%i = [%s + %s];", reg
, ptr_name
, imm_str
);
3354 SET_DREG (reg
, GET_LONG (ea
));
3358 TRACE_INSN (cpu
, "R%i = W[%s + %s] (Z);", reg
, ptr_name
, imm_str
);
3359 SET_DREG (reg
, GET_WORD (ea
));
3363 TRACE_INSN (cpu
, "R%i = W[%s + %s] (X);", reg
, ptr_name
, imm_str
);
3364 SET_DREG (reg
, (bs32
) (bs16
) GET_WORD (ea
));
3368 TRACE_INSN (cpu
, "%s = [%s + %s];",
3369 get_preg_name (reg
), ptr_name
, imm_str
);
3370 SET_PREG (reg
, GET_LONG (ea
));
3377 TRACE_INSN (cpu
, "[%s + %s] = R%i;", ptr_name
, imm_str
, reg
);
3378 PUT_LONG (ea
, DREG (reg
));
3382 TRACE_INSN (cpu
, "W[%s + %s] = R%i;", ptr_name
, imm_str
, reg
);
3383 PUT_WORD (ea
, DREG (reg
));
3387 TRACE_INSN (cpu
, "[%s + %s] = %s;",
3388 ptr_name
, imm_str
, get_preg_name (reg
));
3389 PUT_LONG (ea
, PREG (reg
));
3395 decode_LoopSetup_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
, bu32 pc
)
3398 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3399 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |.rop...|.c.|.soffset.......|
3400 |.reg...........| - | - |.eoffset...............................|
3401 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3402 int c
= ((iw0
>> (LoopSetup_c_bits
- 16)) & LoopSetup_c_mask
);
3403 int reg
= ((iw1
>> LoopSetup_reg_bits
) & LoopSetup_reg_mask
);
3404 int rop
= ((iw0
>> (LoopSetup_rop_bits
- 16)) & LoopSetup_rop_mask
);
3405 int soffset
= ((iw0
>> (LoopSetup_soffset_bits
- 16)) & LoopSetup_soffset_mask
);
3406 int eoffset
= ((iw1
>> LoopSetup_eoffset_bits
) & LoopSetup_eoffset_mask
);
3407 int spcrel
= pcrel4 (soffset
);
3408 int epcrel
= lppcrel10 (eoffset
);
3410 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LoopSetup
);
3411 TRACE_EXTRACT (cpu
, "%s: rop:%i c:%i soffset:%i reg:%i eoffset:%i",
3412 __func__
, rop
, c
, soffset
, reg
, eoffset
);
3413 TRACE_DECODE (cpu
, "%s: s_pcrel4:%#x e_lppcrel10:%#x",
3414 __func__
, spcrel
, epcrel
);
3417 illegal_instruction (cpu
);
3420 illegal_instruction_combination (cpu
);
3424 TRACE_INSN (cpu
, "LSETUP (%#x, %#x) LC%i;", spcrel
, epcrel
, c
);
3426 else if (rop
== 1 && reg
<= 7)
3428 TRACE_INSN (cpu
, "LSETUP (%#x, %#x) LC%i = %s;",
3429 spcrel
, epcrel
, c
, get_preg_name (reg
));
3430 SET_LCREG (c
, PREG (reg
));
3432 else if (rop
== 3 && reg
<= 7)
3434 TRACE_INSN (cpu
, "LSETUP (%#x, %#x) LC%i = %s >> 1;",
3435 spcrel
, epcrel
, c
, get_preg_name (reg
));
3436 SET_LCREG (c
, PREG (reg
) >> 1);
3439 illegal_instruction (cpu
);
3441 SET_LTREG (c
, pc
+ spcrel
);
3442 SET_LBREG (c
, pc
+ epcrel
);
3446 decode_LDIMMhalf_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3449 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3450 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 |.Z.|.H.|.S.|.grp...|.reg.......|
3451 |.hword.........................................................|
3452 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3453 int H
= ((iw0
>> (LDIMMhalf_H_bits
- 16)) & LDIMMhalf_H_mask
);
3454 int Z
= ((iw0
>> (LDIMMhalf_Z_bits
- 16)) & LDIMMhalf_Z_mask
);
3455 int S
= ((iw0
>> (LDIMMhalf_S_bits
- 16)) & LDIMMhalf_S_mask
);
3456 int reg
= ((iw0
>> (LDIMMhalf_reg_bits
- 16)) & LDIMMhalf_reg_mask
);
3457 int grp
= ((iw0
>> (LDIMMhalf_grp_bits
- 16)) & LDIMMhalf_grp_mask
);
3458 int hword
= ((iw1
>> LDIMMhalf_hword_bits
) & LDIMMhalf_hword_mask
);
3460 const char *val_str
;
3461 const char *reg_name
= get_allreg_name (grp
, reg
);
3463 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDIMMhalf
);
3464 TRACE_EXTRACT (cpu
, "%s: Z:%i H:%i S:%i grp:%i reg:%i hword:%#x",
3465 __func__
, Z
, H
, S
, grp
, reg
, hword
);
3468 illegal_instruction_combination (cpu
);
3471 val
= imm16 (hword
), val_str
= imm16_str (hword
);
3473 val
= luimm16 (hword
), val_str
= luimm16_str (hword
);
3475 if (H
== 0 && S
== 1 && Z
== 0)
3477 TRACE_INSN (cpu
, "%s = %s (X);", reg_name
, val_str
);
3479 else if (H
== 0 && S
== 0 && Z
== 1)
3481 TRACE_INSN (cpu
, "%s = %s (Z);", reg_name
, val_str
);
3483 else if (H
== 0 && S
== 0 && Z
== 0)
3485 TRACE_INSN (cpu
, "%s.L = %s;", reg_name
, val_str
);
3486 val
= REG_H_L (reg_read (cpu
, grp
, reg
), val
);
3488 else if (H
== 1 && S
== 0 && Z
== 0)
3490 TRACE_INSN (cpu
, "%s.H = %s;", reg_name
, val_str
);
3491 val
= REG_H_L (val
<< 16, reg_read (cpu
, grp
, reg
));
3494 illegal_instruction (cpu
);
3496 reg_write (cpu
, grp
, reg
, val
);
3500 decode_CALLa_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
, bu32 pc
)
3503 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3504 | 1 | 1 | 1 | 0 | 0 | 0 | 1 |.S.|.msw...........................|
3505 |.lsw...........................................................|
3506 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3507 int S
= ((iw0
>> (CALLa_S_bits
- 16)) & CALLa_S_mask
);
3508 int lsw
= ((iw1
>> 0) & 0xffff);
3509 int msw
= ((iw0
>> 0) & 0xff);
3510 int pcrel
= pcrel24 ((msw
<< 16) | lsw
);
3511 bu32 newpc
= pc
+ pcrel
;
3513 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CALLa
);
3514 TRACE_EXTRACT (cpu
, "%s: S:%i msw:%#x lsw:%#x", __func__
, S
, msw
, lsw
);
3515 TRACE_DECODE (cpu
, "%s: pcrel24:%#x", __func__
, pcrel
);
3517 TRACE_INSN (cpu
, "%s %#x;", S
? "CALL" : "JUMP.L", pcrel
);
3520 illegal_instruction_combination (cpu
);
3524 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "CALL");
3525 SET_RETSREG (hwloop_get_next_pc (cpu
, pc
, 4));
3528 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP.L");
3531 BFIN_CPU_STATE
.did_jump
= true;
3532 PROFILE_BRANCH_TAKEN (cpu
);
3537 decode_LDSTidxI_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3540 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3541 | 1 | 1 | 1 | 0 | 0 | 1 |.W.|.Z.|.sz....|.ptr.......|.reg.......|
3542 |.offset........................................................|
3543 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3544 int Z
= ((iw0
>> (LDSTidxI_Z_bits
- 16)) & LDSTidxI_Z_mask
);
3545 int W
= ((iw0
>> (LDSTidxI_W_bits
- 16)) & LDSTidxI_W_mask
);
3546 int sz
= ((iw0
>> (LDSTidxI_sz_bits
- 16)) & LDSTidxI_sz_mask
);
3547 int reg
= ((iw0
>> (LDSTidxI_reg_bits
- 16)) & LDSTidxI_reg_mask
);
3548 int ptr
= ((iw0
>> (LDSTidxI_ptr_bits
- 16)) & LDSTidxI_ptr_mask
);
3549 int offset
= ((iw1
>> LDSTidxI_offset_bits
) & LDSTidxI_offset_mask
);
3550 const char *ptr_name
= get_preg_name (ptr
);
3551 bu32 imm_16s4
= imm16s4 (offset
);
3552 bu32 imm_16s2
= imm16s2 (offset
);
3553 bu32 imm_16
= imm16 (offset
);
3555 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTidxI
);
3556 TRACE_EXTRACT (cpu
, "%s: W:%i Z:%i sz:%i ptr:%i reg:%i offset:%#x",
3557 __func__
, W
, Z
, sz
, ptr
, reg
, offset
);
3560 illegal_instruction (cpu
);
3564 if (sz
== 0 && Z
== 0)
3566 TRACE_INSN (cpu
, "R%i = [%s + %s];",
3567 reg
, ptr_name
, imm16s4_str (offset
));
3568 SET_DREG (reg
, GET_LONG (PREG (ptr
) + imm_16s4
));
3570 else if (sz
== 0 && Z
== 1)
3572 TRACE_INSN (cpu
, "%s = [%s + %s];",
3573 get_preg_name (reg
), ptr_name
, imm16s4_str (offset
));
3574 SET_PREG (reg
, GET_LONG (PREG (ptr
) + imm_16s4
));
3576 else if (sz
== 1 && Z
== 0)
3578 TRACE_INSN (cpu
, "R%i = W[%s + %s] (Z);",
3579 reg
, ptr_name
, imm16s2_str (offset
));
3580 SET_DREG (reg
, GET_WORD (PREG (ptr
) + imm_16s2
));
3582 else if (sz
== 1 && Z
== 1)
3584 TRACE_INSN (cpu
, "R%i = W[%s + %s] (X);",
3585 reg
, ptr_name
, imm16s2_str (offset
));
3586 SET_DREG (reg
, (bs32
) (bs16
) GET_WORD (PREG (ptr
) + imm_16s2
));
3588 else if (sz
== 2 && Z
== 0)
3590 TRACE_INSN (cpu
, "R%i = B[%s + %s] (Z);",
3591 reg
, ptr_name
, imm16_str (offset
));
3592 SET_DREG (reg
, GET_BYTE (PREG (ptr
) + imm_16
));
3594 else if (sz
== 2 && Z
== 1)
3596 TRACE_INSN (cpu
, "R%i = B[%s + %s] (X);",
3597 reg
, ptr_name
, imm16_str (offset
));
3598 SET_DREG (reg
, (bs32
) (bs8
) GET_BYTE (PREG (ptr
) + imm_16
));
3603 if (sz
!= 0 && Z
!= 0)
3604 illegal_instruction (cpu
);
3606 if (sz
== 0 && Z
== 0)
3608 TRACE_INSN (cpu
, "[%s + %s] = R%i;", ptr_name
,
3609 imm16s4_str (offset
), reg
);
3610 PUT_LONG (PREG (ptr
) + imm_16s4
, DREG (reg
));
3612 else if (sz
== 0 && Z
== 1)
3614 TRACE_INSN (cpu
, "[%s + %s] = %s;",
3615 ptr_name
, imm16s4_str (offset
), get_preg_name (reg
));
3616 PUT_LONG (PREG (ptr
) + imm_16s4
, PREG (reg
));
3618 else if (sz
== 1 && Z
== 0)
3620 TRACE_INSN (cpu
, "W[%s + %s] = R%i;",
3621 ptr_name
, imm16s2_str (offset
), reg
);
3622 PUT_WORD (PREG (ptr
) + imm_16s2
, DREG (reg
));
3624 else if (sz
== 2 && Z
== 0)
3626 TRACE_INSN (cpu
, "B[%s + %s] = R%i;",
3627 ptr_name
, imm16_str (offset
), reg
);
3628 PUT_BYTE (PREG (ptr
) + imm_16
, DREG (reg
));
3634 decode_linkage_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3637 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3638 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |.R.|
3639 |.framesize.....................................................|
3640 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3641 int R
= ((iw0
>> (Linkage_R_bits
- 16)) & Linkage_R_mask
);
3642 int framesize
= ((iw1
>> Linkage_framesize_bits
) & Linkage_framesize_mask
);
3645 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_linkage
);
3646 TRACE_EXTRACT (cpu
, "%s: R:%i framesize:%#x", __func__
, R
, framesize
);
3650 int size
= uimm16s4 (framesize
);
3652 TRACE_INSN (cpu
, "LINK %s;", uimm16s4_str (framesize
));
3654 illegal_instruction_combination (cpu
);
3656 PUT_LONG (sp
, RETSREG
);
3658 PUT_LONG (sp
, FPREG
);
3665 /* Restore SP from FP. */
3667 TRACE_INSN (cpu
, "UNLINK;");
3669 illegal_instruction_combination (cpu
);
3670 SET_FPREG (GET_LONG (sp
));
3672 SET_RETSREG (GET_LONG (sp
));
3681 decode_dsp32mac_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3684 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3685 | 1 | 1 | 0 | 0 |.M.| 0 | 0 |.mmod..........|.MM|.P.|.w1|.op1...|
3686 |.h01|.h11|.w0|.op0...|.h00|.h10|.dst.......|.src0......|.src1..|
3687 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3688 int op1
= ((iw0
>> (DSP32Mac_op1_bits
- 16)) & DSP32Mac_op1_mask
);
3689 int w1
= ((iw0
>> (DSP32Mac_w1_bits
- 16)) & DSP32Mac_w1_mask
);
3690 int P
= ((iw0
>> (DSP32Mac_p_bits
- 16)) & DSP32Mac_p_mask
);
3691 int MM
= ((iw0
>> (DSP32Mac_MM_bits
- 16)) & DSP32Mac_MM_mask
);
3692 int mmod
= ((iw0
>> (DSP32Mac_mmod_bits
- 16)) & DSP32Mac_mmod_mask
);
3693 int M
= ((iw0
>> (DSP32Mac_M_bits
- 16)) & DSP32Mac_M_mask
);
3694 int w0
= ((iw1
>> DSP32Mac_w0_bits
) & DSP32Mac_w0_mask
);
3695 int src0
= ((iw1
>> DSP32Mac_src0_bits
) & DSP32Mac_src0_mask
);
3696 int src1
= ((iw1
>> DSP32Mac_src1_bits
) & DSP32Mac_src1_mask
);
3697 int dst
= ((iw1
>> DSP32Mac_dst_bits
) & DSP32Mac_dst_mask
);
3698 int h10
= ((iw1
>> DSP32Mac_h10_bits
) & DSP32Mac_h10_mask
);
3699 int h00
= ((iw1
>> DSP32Mac_h00_bits
) & DSP32Mac_h00_mask
);
3700 int op0
= ((iw1
>> DSP32Mac_op0_bits
) & DSP32Mac_op0_mask
);
3701 int h11
= ((iw1
>> DSP32Mac_h11_bits
) & DSP32Mac_h11_mask
);
3702 int h01
= ((iw1
>> DSP32Mac_h01_bits
) & DSP32Mac_h01_mask
);
3704 bu32 res
= DREG (dst
);
3705 bu32 v_i
= 0, zero
= 0;
3707 static const char * const ops
[] = { "=", "+=", "-=" };
3708 char _buf
[128], *buf
= _buf
;
3711 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32mac
);
3712 TRACE_EXTRACT (cpu
, "%s: M:%i mmod:%i MM:%i P:%i w1:%i op1:%i h01:%i h11:%i "
3713 "w0:%i op0:%i h00:%i h10:%i dst:%i src0:%i src1:%i",
3714 __func__
, M
, mmod
, MM
, P
, w1
, op1
, h01
, h11
, w0
, op0
, h00
, h10
,
3717 if (w0
== 0 && w1
== 0 && op1
== 3 && op0
== 3)
3718 illegal_instruction (cpu
);
3720 if ((w1
|| w0
) && mmod
== M_W32
)
3721 illegal_instruction (cpu
);
3723 if (((1 << mmod
) & (P
? 0x131b : 0x1b5f)) == 0)
3724 illegal_instruction (cpu
);
3726 /* First handle MAC1 side. */
3727 if (w1
== 1 || op1
!= 3)
3729 bu32 res1
= decode_macfunc (cpu
, 1, op1
, h01
, h11
, src0
,
3730 src1
, mmod
, MM
, P
, &v_i
);
3733 buf
+= sprintf (buf
, P
? "R%i" : "R%i.H", dst
+ P
);
3737 buf
+= sprintf (buf
, " = A1");
3738 zero
= !!(res1
== 0);
3743 buf
+= sprintf (buf
, " = (");
3744 buf
+= sprintf (buf
, "A1 %s R%i.%c * R%i.%c", ops
[op1
],
3745 src0
, h01
? 'H' : 'L',
3746 src1
, h11
? 'H' : 'L');
3748 buf
+= sprintf (buf
, ")");
3754 STORE (DREG (dst
+ 1), res1
);
3757 if (res1
& 0xffff0000)
3758 illegal_instruction (cpu
);
3759 res
= REG_H_L (res1
<< 16, res
);
3763 if (w0
== 1 || op0
!= 3)
3766 buf
+= sprintf (buf
, " (M)");
3768 buf
+= sprintf (buf
, ", ");
3772 /* Then handle MAC0 side. */
3773 if (w0
== 1 || op0
!= 3)
3775 bu32 res0
= decode_macfunc (cpu
, 0, op0
, h00
, h10
, src0
,
3776 src1
, mmod
, 0, P
, &v_i
);
3779 buf
+= sprintf (buf
, P
? "R%i" : "R%i.L", dst
);
3783 buf
+= sprintf (buf
, " = A0");
3784 zero
|= !!(res0
== 0);
3789 buf
+= sprintf (buf
, " = (");
3790 buf
+= sprintf (buf
, "A0 %s R%i.%c * R%i.%c", ops
[op0
],
3791 src0
, h00
? 'H' : 'L',
3792 src1
, h10
? 'H' : 'L');
3794 buf
+= sprintf (buf
, ")");
3800 STORE (DREG (dst
), res0
);
3803 if (res0
& 0xffff0000)
3804 illegal_instruction (cpu
);
3805 res
= REG_H_L (res
, res0
);
3810 TRACE_INSN (cpu
, "%s%s;", _buf
, mac_optmode (mmod
, _MM
));
3812 if (!P
&& (w0
|| w1
))
3814 STORE (DREG (dst
), res
);
3815 SET_ASTATREG (v
, v_i
);
3817 SET_ASTATREG (vs
, v_i
);
3821 SET_ASTATREG (v
, v_i
);
3823 SET_ASTATREG (vs
, v_i
);
3825 if (op0
== 3 || op1
== 3)
3826 SET_ASTATREG (az
, zero
);
3830 decode_dsp32mult_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3833 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3834 | 1 | 1 | 0 | 0 |.M.| 0 | 1 |.mmod..........|.MM|.P.|.w1|.op1...|
3835 |.h01|.h11|.w0|.op0...|.h00|.h10|.dst.......|.src0......|.src1..|
3836 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3837 int op1
= ((iw0
>> (DSP32Mac_op1_bits
- 16)) & DSP32Mac_op1_mask
);
3838 int w1
= ((iw0
>> (DSP32Mac_w1_bits
- 16)) & DSP32Mac_w1_mask
);
3839 int P
= ((iw0
>> (DSP32Mac_p_bits
- 16)) & DSP32Mac_p_mask
);
3840 int MM
= ((iw0
>> (DSP32Mac_MM_bits
- 16)) & DSP32Mac_MM_mask
);
3841 int mmod
= ((iw0
>> (DSP32Mac_mmod_bits
- 16)) & DSP32Mac_mmod_mask
);
3842 int M
= ((iw0
>> (DSP32Mac_M_bits
- 16)) & DSP32Mac_M_mask
);
3843 int w0
= ((iw1
>> DSP32Mac_w0_bits
) & DSP32Mac_w0_mask
);
3844 int src0
= ((iw1
>> DSP32Mac_src0_bits
) & DSP32Mac_src0_mask
);
3845 int src1
= ((iw1
>> DSP32Mac_src1_bits
) & DSP32Mac_src1_mask
);
3846 int dst
= ((iw1
>> DSP32Mac_dst_bits
) & DSP32Mac_dst_mask
);
3847 int h10
= ((iw1
>> DSP32Mac_h10_bits
) & DSP32Mac_h10_mask
);
3848 int h00
= ((iw1
>> DSP32Mac_h00_bits
) & DSP32Mac_h00_mask
);
3849 int op0
= ((iw1
>> DSP32Mac_op0_bits
) & DSP32Mac_op0_mask
);
3850 int h11
= ((iw1
>> DSP32Mac_h11_bits
) & DSP32Mac_h11_mask
);
3851 int h01
= ((iw1
>> DSP32Mac_h01_bits
) & DSP32Mac_h01_mask
);
3853 bu32 res
= DREG (dst
);
3854 bu32 sat0
= 0, sat1
= 0;
3855 char _buf
[128], *buf
= _buf
;
3858 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32mult
);
3859 TRACE_EXTRACT (cpu
, "%s: M:%i mmod:%i MM:%i P:%i w1:%i op1:%i h01:%i h11:%i "
3860 "w0:%i op0:%i h00:%i h10:%i dst:%i src0:%i src1:%i",
3861 __func__
, M
, mmod
, MM
, P
, w1
, op1
, h01
, h11
, w0
, op0
, h00
, h10
,
3864 if (w1
== 0 && w0
== 0)
3865 illegal_instruction (cpu
);
3866 if (((1 << mmod
) & (P
? 0x313 : 0x1b57)) == 0)
3867 illegal_instruction (cpu
);
3868 if (P
&& ((dst
& 1) || (op1
!= 0) || (op0
!= 0) || !is_macmod_pmove (mmod
)))
3869 illegal_instruction (cpu
);
3870 if (!P
&& ((op1
!= 0) || (op0
!= 0) || !is_macmod_hmove (mmod
)))
3871 illegal_instruction (cpu
);
3873 /* First handle MAC1 side. */
3876 bu64 r
= decode_multfunc (cpu
, h01
, h11
, src0
, src1
, mmod
, MM
, &sat1
);
3877 bu32 res1
= extract_mult (cpu
, r
, mmod
, MM
, P
, NULL
);
3879 buf
+= sprintf (buf
, P
? "R%i" : "R%i.H", dst
+ P
);
3880 buf
+= sprintf (buf
, " = R%i.%c * R%i.%c",
3881 src0
, h01
? 'H' : 'L',
3882 src1
, h11
? 'H' : 'L');
3886 buf
+= sprintf (buf
, " (M)");
3888 buf
+= sprintf (buf
, ", ");
3892 STORE (DREG (dst
+ 1), res1
);
3895 if (res1
& 0xFFFF0000)
3896 illegal_instruction (cpu
);
3897 res
= REG_H_L (res1
<< 16, res
);
3901 /* First handle MAC0 side. */
3904 bu64 r
= decode_multfunc (cpu
, h00
, h10
, src0
, src1
, mmod
, 0, &sat0
);
3905 bu32 res0
= extract_mult (cpu
, r
, mmod
, 0, P
, NULL
);
3907 buf
+= sprintf (buf
, P
? "R%i" : "R%i.L", dst
);
3908 buf
+= sprintf (buf
, " = R%i.%c * R%i.%c",
3909 src0
, h01
? 'H' : 'L',
3910 src1
, h11
? 'H' : 'L');
3913 STORE (DREG (dst
), res0
);
3916 if (res0
& 0xFFFF0000)
3917 illegal_instruction (cpu
);
3918 res
= REG_H_L (res
, res0
);
3922 TRACE_INSN (cpu
, "%s%s;", _buf
, mac_optmode (mmod
, _MM
));
3924 if (!P
&& (w0
|| w1
))
3925 STORE (DREG (dst
), res
);
3929 STORE (ASTATREG (v
), sat0
| sat1
);
3930 STORE (ASTATREG (v_copy
), sat0
| sat1
);
3932 STORE (ASTATREG (vs
), 1);
3937 decode_dsp32alu_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3940 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3941 | 1 | 1 | 0 | 0 |.M.| 1 | 0 | - | - | - |.HL|.aopcde............|
3942 |.aop...|.s.|.x.|.dst0......|.dst1......|.src0......|.src1......|
3943 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3944 int s
= ((iw1
>> DSP32Alu_s_bits
) & DSP32Alu_s_mask
);
3945 int x
= ((iw1
>> DSP32Alu_x_bits
) & DSP32Alu_x_mask
);
3946 int aop
= ((iw1
>> DSP32Alu_aop_bits
) & DSP32Alu_aop_mask
);
3947 int src0
= ((iw1
>> DSP32Alu_src0_bits
) & DSP32Alu_src0_mask
);
3948 int src1
= ((iw1
>> DSP32Alu_src1_bits
) & DSP32Alu_src1_mask
);
3949 int dst0
= ((iw1
>> DSP32Alu_dst0_bits
) & DSP32Alu_dst0_mask
);
3950 int dst1
= ((iw1
>> DSP32Alu_dst1_bits
) & DSP32Alu_dst1_mask
);
3951 int M
= ((iw0
>> (DSP32Alu_M_bits
- 16)) & DSP32Alu_M_mask
);
3952 int HL
= ((iw0
>> (DSP32Alu_HL_bits
- 16)) & DSP32Alu_HL_mask
);
3953 int aopcde
= ((iw0
>> (DSP32Alu_aopcde_bits
- 16)) & DSP32Alu_aopcde_mask
);
3955 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32alu
);
3956 TRACE_EXTRACT (cpu
, "%s: M:%i HL:%i aopcde:%i aop:%i s:%i x:%i dst0:%i "
3957 "dst1:%i src0:%i src1:%i",
3958 __func__
, M
, HL
, aopcde
, aop
, s
, x
, dst0
, dst1
, src0
, src1
);
3960 if ((aop
== 0 || aop
== 2) && aopcde
== 9 && HL
== 0 && s
== 0)
3963 TRACE_INSN (cpu
, "A%i.L = R%i.L;", a
, src0
);
3964 SET_AWREG (a
, REG_H_L (AWREG (a
), DREG (src0
)));
3966 else if ((aop
== 0 || aop
== 2) && aopcde
== 9 && HL
== 1 && s
== 0)
3969 TRACE_INSN (cpu
, "A%i.H = R%i.H;", a
, src0
);
3970 SET_AWREG (a
, REG_H_L (DREG (src0
), AWREG (a
)));
3972 else if ((aop
== 1 || aop
== 0) && aopcde
== 5)
3974 bs32 val0
= DREG (src0
);
3975 bs32 val1
= DREG (src1
);
3978 bs32 ovX
, sBit1
, sBit2
, sBitRes1
, sBitRes2
;
3980 TRACE_INSN (cpu
, "R%i.%s = R%i %s R%i (RND12)", dst0
, HL
? "L" : "H",
3981 src0
, aop
& 0x1 ? "-" : "+", src1
);
3983 /* If subtract, just invert and add one. */
3987 /* Get the sign bits, since we need them later. */
3988 sBit1
= !!(val0
& 0x80000000);
3989 sBit2
= !!(val1
& 0x80000000);
3993 sBitRes1
= !!(res
& 0x80000000);
3994 /* Round to the 12th bit. */
3996 sBitRes2
= !!(res
& 0x80000000);
4004 positive_res + positive_round = neg
4005 Shift and upper 4 bits where not the same. */
4006 if ((!(sBit1
^ sBit2
) && (sBit1
^ sBitRes1
))
4007 || (!sBit1
&& !sBit2
&& sBitRes2
)
4008 || ((signRes
!= 0) && (signRes
!= -1)))
4010 /* Both X1 and X2 Neg res is neg overflow. */
4013 /* Both X1 and X2 Pos res is pos overflow. */
4014 else if (!sBit1
&& !sBit2
)
4016 /* Pos+Neg or Neg+Pos take the sign of the result. */
4026 /* Shift up now after overflow detection. */
4034 STORE (DREG (dst0
), REG_H_L (res
<< 16, DREG (dst0
)));
4036 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), res
));
4038 SET_ASTATREG (az
, res
== 0);
4039 SET_ASTATREG (an
, res
& 0x8000);
4040 SET_ASTATREG (v
, ovX
);
4042 SET_ASTATREG (vs
, ovX
);
4044 else if ((aop
== 2 || aop
== 3) && aopcde
== 5)
4046 bs32 val0
= DREG (src0
);
4047 bs32 val1
= DREG (src1
);
4050 TRACE_INSN (cpu
, "R%i.%s = R%i %s R%i (RND20)", dst0
, HL
? "L" : "H",
4051 src0
, aop
& 0x1 ? "-" : "+", src1
);
4053 /* If subtract, just invert and add one. */
4057 res
= (val0
>> 4) + (val1
>> 4) + (((val0
& 0xf) + (val1
& 0xf)) >> 4);
4059 /* Don't sign extend during the shift. */
4060 res
= ((bu32
)res
>> 16);
4062 /* Don't worry about overflows, since we are shifting right. */
4065 STORE (DREG (dst0
), REG_H_L (res
<< 16, DREG (dst0
)));
4067 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), res
));
4069 SET_ASTATREG (az
, res
== 0);
4070 SET_ASTATREG (an
, res
& 0x8000);
4071 SET_ASTATREG (v
, 0);
4073 else if (aopcde
== 2 || aopcde
== 3)
4075 bu32 s1
, s2
, val
, ac0_i
= 0, v_i
= 0;
4077 TRACE_INSN (cpu
, "R%i.%c = R%i.%c %c R%i.%c%s;",
4078 dst0
, HL
? 'H' : 'L',
4079 src0
, aop
& 2 ? 'H' : 'L',
4080 aopcde
== 2 ? '+' : '-',
4081 src1
, aop
& 1 ? 'H' : 'L',
4092 val
= add16 (cpu
, s1
, s2
, &ac0_i
, &v_i
, 0, 0, s
, 0);
4094 val
= sub16 (cpu
, s1
, s2
, &ac0_i
, &v_i
, 0, 0, s
, 0);
4096 SET_ASTATREG (ac0
, ac0_i
);
4097 SET_ASTATREG (v
, v_i
);
4099 SET_DREG_H (dst0
, val
<< 16);
4101 SET_DREG_L (dst0
, val
);
4103 SET_ASTATREG (an
, val
& 0x8000);
4106 else if ((aop
== 0 || aop
== 2) && aopcde
== 9 && s
== 1)
4109 TRACE_INSN (cpu
, "A%i = R%i;", a
, src0
);
4110 SET_AREG32 (a
, DREG (src0
));
4112 else if ((aop
== 1 || aop
== 3) && aopcde
== 9 && s
== 0)
4115 TRACE_INSN (cpu
, "A%i.X = R%i.L;", a
, src0
);
4116 SET_AXREG (a
, (bs8
)DREG (src0
));
4118 else if (aop
== 3 && aopcde
== 11 && (s
== 0 || s
== 1))
4120 bu64 acc0
= get_extended_acc (cpu
, 0);
4121 bu64 acc1
= get_extended_acc (cpu
, 1);
4122 bu32 carry
= (bu40
)acc1
< (bu40
)acc0
;
4125 TRACE_INSN (cpu
, "A0 -= A1%s;", s
? " (W32)" : "");
4128 if ((bs64
)acc0
< -0x8000000000ll
)
4129 acc0
= -0x8000000000ull
, sat
= 1;
4130 else if ((bs64
)acc0
>= 0x7fffffffffll
)
4131 acc0
= 0x7fffffffffull
, sat
= 1;
4135 /* A0 -= A1 (W32) */
4136 if (acc0
& (bu64
)0x8000000000ll
)
4137 acc0
&= 0x80ffffffffll
, sat
= 1;
4139 acc0
&= 0xffffffffll
;
4141 STORE (AXREG (0), (acc0
>> 32) & 0xff);
4142 STORE (AWREG (0), acc0
& 0xffffffff);
4143 STORE (ASTATREG (az
), acc0
== 0);
4144 STORE (ASTATREG (an
), !!(acc0
& (bu64
)0x8000000000ll
));
4145 STORE (ASTATREG (ac0
), carry
);
4146 STORE (ASTATREG (ac0_copy
), carry
);
4147 STORE (ASTATREG (av0
), sat
);
4149 STORE (ASTATREG (av0s
), sat
);
4151 else if ((aop
== 0 || aop
== 1) && aopcde
== 22)
4153 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4155 const char * const opts
[] = { "rndl", "rndh", "tl", "th" };
4157 TRACE_INSN (cpu
, "R%i = BYTEOP2P (R%i:%i, R%i:%i) (%s%s);", dst0
,
4158 src0
+ 1, src0
, src1
+ 1, src1
, opts
[HL
+ (aop
<< 1)],
4162 illegal_instruction_combination (cpu
);
4165 s0H
= DREG (src0
+ 1);
4167 s1H
= DREG (src1
+ 1);
4170 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4171 s1
= algn (s1H
, s1L
, IREG (0) & 3);
4175 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4176 s1
= algn (s1L
, s1H
, IREG (0) & 3);
4180 tmp0
= ((((s1
>> 8) & 0xff) + ((s1
>> 0) & 0xff) +
4181 ((s0
>> 8) & 0xff) + ((s0
>> 0) & 0xff) + i
) >> 2) & 0xff;
4182 tmp1
= ((((s1
>> 24) & 0xff) + ((s1
>> 16) & 0xff) +
4183 ((s0
>> 24) & 0xff) + ((s0
>> 16) & 0xff) + i
) >> 2) & 0xff;
4184 SET_DREG (dst0
, (tmp1
<< (16 + (HL
* 8))) | (tmp0
<< (HL
* 8)));
4186 else if ((aop
== 0 || aop
== 1) && s
== 0 && aopcde
== 8)
4188 TRACE_INSN (cpu
, "A%i = 0;", aop
);
4191 else if (aop
== 2 && s
== 0 && aopcde
== 8)
4193 TRACE_INSN (cpu
, "A1 = A0 = 0;");
4197 else if ((aop
== 0 || aop
== 1 || aop
== 2) && s
== 1 && aopcde
== 8)
4199 bs40 acc0
= get_extended_acc (cpu
, 0);
4200 bs40 acc1
= get_extended_acc (cpu
, 1);
4203 if (aop
== 0 || aop
== 1)
4204 TRACE_INSN (cpu
, "A%i = A%i (S);", aop
, aop
);
4206 TRACE_INSN (cpu
, "A1 = A1 (S), A0 = A0 (S);");
4208 if (aop
== 0 || aop
== 2)
4211 acc0
= saturate_s32 (acc0
, &sat
);
4212 acc0
|= -(acc0
& 0x80000000ull
);
4213 SET_AXREG (0, (acc0
>> 31) & 0xFF);
4214 SET_AWREG (0, acc0
& 0xFFFFFFFF);
4215 SET_ASTATREG (av0
, sat
);
4217 SET_ASTATREG (av0s
, sat
);
4222 if (aop
== 1 || aop
== 2)
4225 acc1
= saturate_s32 (acc1
, &sat
);
4226 acc1
|= -(acc1
& 0x80000000ull
);
4227 SET_AXREG (1, (acc1
>> 31) & 0xFF);
4228 SET_AWREG (1, acc1
& 0xFFFFFFFF);
4229 SET_ASTATREG (av1
, sat
);
4231 SET_ASTATREG (av1s
, sat
);
4236 SET_ASTATREG (az
, (acc0
== 0) || (acc1
== 0));
4237 SET_ASTATREG (an
, ((acc0
>> 31) & 1) || ((acc1
>> 31) & 1));
4239 else if (aop
== 3 && (s
== 0 || s
== 1) && aopcde
== 8)
4241 TRACE_INSN (cpu
, "A%i = A%i;", s
, !s
);
4242 SET_AXREG (s
, AXREG (!s
));
4243 SET_AWREG (s
, AWREG (!s
));
4245 else if (aop
== 3 && HL
== 0 && aopcde
== 16)
4250 TRACE_INSN (cpu
, "A1 = ABS A1 , A0 = ABS A0;");
4253 for (i
= 0; i
< 2; ++i
)
4256 bs40 acc
= get_extended_acc (cpu
, i
);
4260 av
= acc
== ((bs40
)1 << 39);
4262 acc
= ((bs40
)1 << 39) - 1;
4265 SET_ASTATREG (av
[i
], av
);
4267 SET_ASTATREG (avs
[i
], av
);
4270 SET_ASTATREG (az
, az
);
4271 SET_ASTATREG (an
, 0);
4273 else if (aop
== 0 && aopcde
== 23)
4275 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4278 TRACE_INSN (cpu
, "R%i = BYTEOP3P (R%i:%i, R%i:%i) (%s%s);", dst0
,
4279 src0
+ 1, src0
, src1
+ 1, src1
, HL
? "HI" : "LO",
4283 illegal_instruction_combination (cpu
);
4286 s0H
= DREG (src0
+ 1);
4288 s1H
= DREG (src1
+ 1);
4291 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4292 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4296 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4297 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4300 tmp0
= (bs32
)(bs16
)(s0
>> 0) + ((s1
>> ( 0 + (8 * !HL
))) & 0xff);
4301 tmp1
= (bs32
)(bs16
)(s0
>> 16) + ((s1
>> (16 + (8 * !HL
))) & 0xff);
4302 SET_DREG (dst0
, (CLAMP (tmp0
, 0, 255) << ( 0 + (8 * HL
))) |
4303 (CLAMP (tmp1
, 0, 255) << (16 + (8 * HL
))));
4305 else if ((aop
== 0 || aop
== 1) && aopcde
== 16)
4310 TRACE_INSN (cpu
, "A%i = ABS A%i;", HL
, aop
);
4312 acc
= get_extended_acc (cpu
, aop
);
4315 av
= acc
== ((bs40
)1 << 39);
4317 acc
= ((bs40
)1 << 39) - 1;
4320 SET_ASTATREG (av
[HL
], av
);
4322 SET_ASTATREG (avs
[HL
], av
);
4323 SET_ASTATREG (az
, acc
== 0);
4324 SET_ASTATREG (an
, 0);
4326 else if (aop
== 3 && aopcde
== 12)
4328 bs32 res
= DREG (src0
);
4330 bool sBit_a
, sBit_b
;
4332 TRACE_INSN (cpu
, "R%i.%s = R%i (RND);", dst0
, HL
== 0 ? "L" : "H", src0
);
4333 TRACE_DECODE (cpu
, "R%i.%s = R%i:%#x (RND);", dst0
,
4334 HL
== 0 ? "L" : "H", src0
, res
);
4336 sBit_b
= !!(res
& 0x80000000);
4339 sBit_a
= !!(res
& 0x80000000);
4341 /* Overflow if the sign bit changed when we rounded. */
4342 if ((res
>> 16) && (sBit_b
!= sBit_a
))
4357 SET_DREG (dst0
, REG_H_L (DREG (dst0
), res
));
4359 SET_DREG (dst0
, REG_H_L (res
<< 16, DREG (dst0
)));
4361 SET_ASTATREG (az
, res
== 0);
4362 SET_ASTATREG (an
, res
< 0);
4363 SET_ASTATREG (v
, ovX
);
4365 SET_ASTATREG (vs
, ovX
);
4367 else if (aop
== 3 && HL
== 0 && aopcde
== 15)
4369 bu32 hi
= (-(bs16
)(DREG (src0
) >> 16)) << 16;
4370 bu32 lo
= (-(bs16
)(DREG (src0
) & 0xFFFF)) & 0xFFFF;
4373 TRACE_INSN (cpu
, "R%i = -R%i (V);", dst0
, src0
);
4377 if (hi
== 0x80000000)
4393 SET_DREG (dst0
, hi
| lo
);
4395 SET_ASTATREG (v
, v
);
4397 SET_ASTATREG (vs
, 1);
4398 SET_ASTATREG (ac0
, ac0
);
4399 SET_ASTATREG (ac1
, ac1
);
4400 setflags_nz_2x16 (cpu
, DREG (dst0
));
4402 else if (aop
== 3 && HL
== 0 && aopcde
== 14)
4404 TRACE_INSN (cpu
, "A1 = - A1 , A0 = - A0;");
4406 SET_AREG (0, saturate_s40 (-get_extended_acc (cpu
, 0)));
4407 SET_AREG (1, saturate_s40 (-get_extended_acc (cpu
, 1)));
4408 /* XXX: what ASTAT flags need updating ? */
4410 else if ((aop
== 0 || aop
== 1) && (HL
== 0 || HL
== 1) && aopcde
== 14)
4412 bs40 src_acc
= get_extended_acc (cpu
, aop
);
4414 TRACE_INSN (cpu
, "A%i = - A%i;", HL
, aop
);
4416 SET_AREG (HL
, saturate_s40 (-src_acc
));
4418 SET_ASTATREG (az
, AWREG (HL
) == 0 && AXREG (HL
) == 0);
4419 SET_ASTATREG (an
, AXREG (HL
) >> 7);
4420 SET_ASTATREG (ac0
, src_acc
== 0);
4423 SET_ASTATREG (av0
, src_acc
< 0);
4425 SET_ASTATREG (av0s
, 1);
4429 SET_ASTATREG (av1
, src_acc
< 0);
4431 SET_ASTATREG (av1s
, 1);
4434 else if (aop
== 0 && aopcde
== 12)
4436 bs16 tmp0_hi
= DREG (src0
) >> 16;
4437 bs16 tmp0_lo
= DREG (src0
);
4438 bs16 tmp1_hi
= DREG (src1
) >> 16;
4439 bs16 tmp1_lo
= DREG (src1
);
4441 TRACE_INSN (cpu
, "R%i.L = R%i.H = SIGN(R%i.H) * R%i.H + SIGN(R%i.L) * R%i.L;",
4442 dst0
, dst0
, src0
, src1
, src0
, src1
);
4444 if ((tmp0_hi
>> 15) & 1)
4445 tmp1_hi
= ~tmp1_hi
+ 1;
4447 if ((tmp0_lo
>> 15) & 1)
4448 tmp1_lo
= ~tmp1_lo
+ 1;
4450 tmp1_hi
= tmp1_hi
+ tmp1_lo
;
4452 STORE (DREG (dst0
), REG_H_L (tmp1_hi
<< 16, tmp1_hi
));
4454 else if (aopcde
== 0)
4456 bu32 s0
= DREG (src0
);
4457 bu32 s1
= DREG (src1
);
4458 bu32 s0h
= s0
>> 16;
4459 bu32 s0l
= s0
& 0xFFFF;
4460 bu32 s1h
= s1
>> 16;
4461 bu32 s1l
= s1
& 0xFFFF;
4463 bu32 ac1_i
= 0, ac0_i
= 0, v_i
= 0, z_i
= 0, n_i
= 0;
4465 TRACE_INSN (cpu
, "R%i = R%i %c|%c R%i%s;", dst0
, src0
,
4466 (aop
& 2) ? '-' : '+', (aop
& 1) ? '-' : '+', src1
,
4469 t0
= sub16 (cpu
, s0h
, s1h
, &ac1_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4471 t0
= add16 (cpu
, s0h
, s1h
, &ac1_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4474 t1
= sub16 (cpu
, s0l
, s1l
, &ac0_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4476 t1
= add16 (cpu
, s0l
, s1l
, &ac0_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4478 SET_ASTATREG (ac1
, ac1_i
);
4479 SET_ASTATREG (ac0
, ac0_i
);
4480 SET_ASTATREG (az
, z_i
);
4481 SET_ASTATREG (an
, n_i
);
4482 SET_ASTATREG (v
, v_i
);
4484 SET_ASTATREG (vs
, v_i
);
4489 SET_DREG (dst0
, (t1
<< 16) | t0
);
4491 SET_DREG (dst0
, (t0
<< 16) | t1
);
4493 else if (aop
== 1 && aopcde
== 12)
4495 bu32 val0
= ((AWREG (0) >> 16) + (AWREG (0) & 0xFFFF)) & 0xFFFF;
4496 bu32 val1
= ((AWREG (1) >> 16) + (AWREG (1) & 0xFFFF)) & 0xFFFF;
4498 TRACE_INSN (cpu
, "R%i = A1.L + A1.H, R%i = A0.L + A0.H;", dst1
, dst0
);
4501 illegal_instruction_combination (cpu
);
4509 SET_DREG (dst0
, val0
);
4510 SET_DREG (dst1
, val1
);
4513 else if (aopcde
== 1)
4517 bu16 s0L
= DREG (src0
);
4518 bu16 s0H
= DREG (src0
) >> 16;
4519 bu16 s1L
= DREG (src1
);
4520 bu16 s1H
= DREG (src1
) >> 16;
4521 bu32 v_i
= 0, n_i
= 0, z_i
= 0;
4523 TRACE_INSN (cpu
, "R%i = R%i %s R%i, R%i = R%i %s R%i%s;",
4524 dst1
, src0
, HL
? "+|-" : "+|+", src1
,
4525 dst0
, src0
, HL
? "-|+" : "-|-", src1
,
4526 amod0amod2 (s
, x
, aop
));
4529 illegal_instruction_combination (cpu
);
4533 x0
= add16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4534 x1
= add16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4535 d1
= (x0
<< 16) | x1
;
4537 x0
= sub16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4538 x1
= sub16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4540 d0
= (x0
<< 16) | x1
;
4542 d0
= (x1
<< 16) | x0
;
4546 x0
= add16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4547 x1
= sub16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4548 d1
= (x0
<< 16) | x1
;
4550 x0
= sub16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4551 x1
= add16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4553 d0
= (x0
<< 16) | x1
;
4555 d0
= (x1
<< 16) | x0
;
4557 SET_ASTATREG (az
, z_i
);
4558 SET_ASTATREG (an
, n_i
);
4559 SET_ASTATREG (v
, v_i
);
4561 SET_ASTATREG (vs
, v_i
);
4563 STORE (DREG (dst0
), d0
);
4564 STORE (DREG (dst1
), d1
);
4566 else if ((aop
== 0 || aop
== 1 || aop
== 2) && aopcde
== 11)
4568 bs40 acc0
= get_extended_acc (cpu
, 0);
4569 bs40 acc1
= get_extended_acc (cpu
, 1);
4570 bu32 v
, dreg
, sat
= 0;
4571 bu32 carry
= !!((bu40
)~acc1
< (bu40
)acc0
);
4574 TRACE_INSN (cpu
, "R%i = (A0 += A1);", dst0
);
4576 TRACE_INSN (cpu
, "R%i.%c = (A0 += A1);", dst0
, HL
? 'H' : 'L');
4578 TRACE_INSN (cpu
, "A0 += A1%s;", s
? " (W32)" : "");
4581 acc0
= saturate_s40_astat (acc0
, &v
);
4583 if (aop
== 2 && s
== 1) /* A0 += A1 (W32) */
4585 if (acc0
& (bs40
)0x8000000000ll
)
4586 acc0
&= 0x80ffffffffll
;
4588 acc0
&= 0xffffffffll
;
4591 STORE (AXREG (0), acc0
>> 32);
4592 STORE (AWREG (0), acc0
);
4593 SET_ASTATREG (av0
, v
&& acc1
);
4595 SET_ASTATREG (av0s
, v
);
4597 if (aop
== 0 || aop
== 1)
4599 if (aop
) /* Dregs_lo = A0 += A1 */
4601 dreg
= saturate_s32 (rnd16 (acc0
) << 16, &sat
);
4603 STORE (DREG (dst0
), REG_H_L (dreg
, DREG (dst0
)));
4605 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), dreg
>> 16));
4607 else /* Dregs = A0 += A1 */
4609 dreg
= saturate_s32 (acc0
, &sat
);
4610 STORE (DREG (dst0
), dreg
);
4613 STORE (ASTATREG (az
), dreg
== 0);
4614 STORE (ASTATREG (an
), !!(dreg
& 0x80000000));
4615 STORE (ASTATREG (ac0
), carry
);
4616 STORE (ASTATREG (ac0_copy
), carry
);
4617 STORE (ASTATREG (v
), sat
);
4618 STORE (ASTATREG (v_copy
), sat
);
4620 STORE (ASTATREG (vs
), sat
);
4624 STORE (ASTATREG (az
), acc0
== 0);
4625 STORE (ASTATREG (an
), !!(acc0
& 0x8000000000ull
));
4626 STORE (ASTATREG (ac0
), carry
);
4627 STORE (ASTATREG (ac0_copy
), carry
);
4630 else if ((aop
== 0 || aop
== 1) && aopcde
== 10)
4632 TRACE_INSN (cpu
, "R%i.L = A%i.X;", dst0
, aop
);
4633 SET_DREG_L (dst0
, (bs8
)AXREG (aop
));
4635 else if (aop
== 0 && aopcde
== 4)
4637 TRACE_INSN (cpu
, "R%i = R%i + R%i%s;", dst0
, src0
, src1
, amod1 (s
, x
));
4638 SET_DREG (dst0
, add32 (cpu
, DREG (src0
), DREG (src1
), 1, s
));
4640 else if (aop
== 1 && aopcde
== 4)
4642 TRACE_INSN (cpu
, "R%i = R%i - R%i%s;", dst0
, src0
, src1
, amod1 (s
, x
));
4643 SET_DREG (dst0
, sub32 (cpu
, DREG (src0
), DREG (src1
), 1, s
, 0));
4645 else if (aop
== 2 && aopcde
== 4)
4647 TRACE_INSN (cpu
, "R%i = R%i + R%i, R%i = R%i - R%i%s;",
4648 dst1
, src0
, src1
, dst0
, src0
, src1
, amod1 (s
, x
));
4651 illegal_instruction_combination (cpu
);
4653 STORE (DREG (dst1
), add32 (cpu
, DREG (src0
), DREG (src1
), 1, s
));
4654 STORE (DREG (dst0
), sub32 (cpu
, DREG (src0
), DREG (src1
), 1, s
, 1));
4656 else if ((aop
== 0 || aop
== 1) && aopcde
== 17)
4658 bs40 acc0
= get_extended_acc (cpu
, 0);
4659 bs40 acc1
= get_extended_acc (cpu
, 1);
4660 bs40 val0
, val1
, sval0
, sval1
;
4663 TRACE_INSN (cpu
, "R%i = A%i + A%i, R%i = A%i - A%i%s",
4664 dst1
, !aop
, aop
, dst0
, !aop
, aop
, amod1 (s
, x
));
4665 TRACE_DECODE (cpu
, "R%i = A%i:%#"PRIx64
" + A%i:%#"PRIx64
", "
4666 "R%i = A%i:%#"PRIx64
" - A%i:%#"PRIx64
"%s",
4667 dst1
, !aop
, aop
? acc0
: acc1
, aop
, aop
? acc1
: acc0
,
4668 dst0
, !aop
, aop
? acc0
: acc1
, aop
, aop
? acc1
: acc0
,
4672 illegal_instruction_combination (cpu
);
4680 sval0
= saturate_s32 (val0
, &sat
);
4682 sval1
= saturate_s32 (val1
, &sat
);
4690 STORE (DREG (dst0
), val0
);
4691 STORE (DREG (dst1
), val1
);
4692 SET_ASTATREG (v
, sat_i
);
4694 SET_ASTATREG (vs
, sat_i
);
4695 SET_ASTATREG (an
, val0
& 0x80000000 || val1
& 0x80000000);
4696 SET_ASTATREG (az
, val0
== 0 || val1
== 0);
4697 SET_ASTATREG (ac1
, (bu40
)~acc0
< (bu40
)acc1
);
4699 SET_ASTATREG (ac0
, !!((bu40
)acc1
<= (bu40
)acc0
));
4701 SET_ASTATREG (ac0
, !!((bu40
)acc0
<= (bu40
)acc1
));
4703 else if (aop
== 0 && aopcde
== 18)
4705 bu40 acc0
= get_extended_acc (cpu
, 0);
4706 bu40 acc1
= get_extended_acc (cpu
, 1);
4707 bu32 s0L
= DREG (src0
);
4708 bu32 s0H
= DREG (src0
+ 1);
4709 bu32 s1L
= DREG (src1
);
4710 bu32 s1H
= DREG (src1
+ 1);
4712 bs16 tmp0
, tmp1
, tmp2
, tmp3
;
4714 /* This instruction is only defined for register pairs R1:0 and R3:2. */
4715 if (!((src0
== 0 || src0
== 2) && (src1
== 0 || src1
== 2)))
4716 illegal_instruction (cpu
);
4718 TRACE_INSN (cpu
, "SAA (R%i:%i, R%i:%i)%s", src0
+ 1, src0
,
4719 src1
+ 1, src1
, s
? " (R)" :"");
4721 /* Bit s determines the order of the two registers from a pair:
4722 if s=0 the low-order bytes come from the low reg in the pair,
4723 and if s=1 the low-order bytes come from the high reg. */
4727 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4728 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4732 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4733 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4736 /* Find the absolute difference between pairs, make it
4737 absolute, then add it to the existing accumulator half. */
4739 tmp0
= ((s0
<< 24) >> 24) - ((s1
<< 24) >> 24);
4740 tmp1
= ((s0
<< 16) >> 24) - ((s1
<< 16) >> 24);
4741 tmp2
= ((s0
<< 8) >> 24) - ((s1
<< 8) >> 24);
4742 tmp3
= ((s0
<< 0) >> 24) - ((s1
<< 0) >> 24);
4744 tmp0
= (tmp0
< 0) ? -tmp0
: tmp0
;
4745 tmp1
= (tmp1
< 0) ? -tmp1
: tmp1
;
4746 tmp2
= (tmp2
< 0) ? -tmp2
: tmp2
;
4747 tmp3
= (tmp3
< 0) ? -tmp3
: tmp3
;
4749 s0L
= saturate_u16 ((bu32
)tmp0
+ ((acc0
>> 0) & 0xffff), 0);
4750 s0H
= saturate_u16 ((bu32
)tmp1
+ ((acc0
>> 16) & 0xffff), 0);
4751 s1L
= saturate_u16 ((bu32
)tmp2
+ ((acc1
>> 0) & 0xffff), 0);
4752 s1H
= saturate_u16 ((bu32
)tmp3
+ ((acc1
>> 16) & 0xffff), 0);
4754 STORE (AWREG (0), (s0H
<< 16) | (s0L
& 0xFFFF));
4755 STORE (AXREG (0), 0);
4756 STORE (AWREG (1), (s1H
<< 16) | (s1L
& 0xFFFF));
4757 STORE (AXREG (1), 0);
4759 else if (aop
== 3 && aopcde
== 18)
4761 TRACE_INSN (cpu
, "DISALGNEXCPT");
4764 else if ((aop
== 0 || aop
== 1) && aopcde
== 20)
4766 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4767 const char * const opts
[] = { "", " (R)", " (T)", " (T, R)" };
4769 TRACE_INSN (cpu
, "R%i = BYTEOP1P (R%i:%i, R%i:%i)%s;", dst0
,
4770 src0
+ 1, src0
, src1
+ 1, src1
, opts
[s
+ (aop
<< 1)]);
4773 illegal_instruction_combination (cpu
);
4776 s0H
= DREG (src0
+ 1);
4778 s1H
= DREG (src1
+ 1);
4781 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4782 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4786 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4787 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4791 (((((s0
>> 0) & 0xff) + ((s1
>> 0) & 0xff) + !aop
) >> 1) << 0) |
4792 (((((s0
>> 8) & 0xff) + ((s1
>> 8) & 0xff) + !aop
) >> 1) << 8) |
4793 (((((s0
>> 16) & 0xff) + ((s1
>> 16) & 0xff) + !aop
) >> 1) << 16) |
4794 (((((s0
>> 24) & 0xff) + ((s1
>> 24) & 0xff) + !aop
) >> 1) << 24));
4796 else if (aop
== 0 && aopcde
== 21)
4798 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4800 TRACE_INSN (cpu
, "(R%i, R%i) = BYTEOP16P (R%i:%i, R%i:%i)%s;", dst1
, dst0
,
4801 src0
+ 1, src0
, src1
+ 1, src1
, s
? " (R)" : "");
4804 illegal_instruction_combination (cpu
);
4807 s0H
= DREG (src0
+ 1);
4809 s1H
= DREG (src1
+ 1);
4812 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4813 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4817 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4818 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4822 ((((s0
>> 0) & 0xff) + ((s1
>> 0) & 0xff)) << 0) |
4823 ((((s0
>> 8) & 0xff) + ((s1
>> 8) & 0xff)) << 16));
4825 ((((s0
>> 16) & 0xff) + ((s1
>> 16) & 0xff)) << 0) |
4826 ((((s0
>> 24) & 0xff) + ((s1
>> 24) & 0xff)) << 16));
4828 else if (aop
== 1 && aopcde
== 21)
4830 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4832 TRACE_INSN (cpu
, "(R%i, R%i) = BYTEOP16M (R%i:%i, R%i:%i)%s;", dst1
, dst0
,
4833 src0
+ 1, src0
, src1
+ 1, src1
, s
? " (R)" : "");
4836 illegal_instruction_combination (cpu
);
4839 s0H
= DREG (src0
+ 1);
4841 s1H
= DREG (src1
+ 1);
4844 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4845 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4849 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4850 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4854 (((((s0
>> 0) & 0xff) - ((s1
>> 0) & 0xff)) << 0) & 0xffff) |
4855 (((((s0
>> 8) & 0xff) - ((s1
>> 8) & 0xff)) << 16)));
4857 (((((s0
>> 16) & 0xff) - ((s1
>> 16) & 0xff)) << 0) & 0xffff) |
4858 (((((s0
>> 24) & 0xff) - ((s1
>> 24) & 0xff)) << 16)));
4860 else if (aop
== 1 && aopcde
== 7)
4862 TRACE_INSN (cpu
, "R%i = MIN (R%i, R%i);", dst0
, src0
, src1
);
4863 SET_DREG (dst0
, min32 (cpu
, DREG (src0
), DREG (src1
)));
4865 else if (aop
== 0 && aopcde
== 7)
4867 TRACE_INSN (cpu
, "R%i = MAX (R%i, R%i);", dst0
, src0
, src1
);
4868 SET_DREG (dst0
, max32 (cpu
, DREG (src0
), DREG (src1
)));
4870 else if (aop
== 2 && aopcde
== 7)
4872 bu32 val
= DREG (src0
);
4875 TRACE_INSN (cpu
, "R%i = ABS R%i;", dst0
, src0
);
4879 v
= (val
== 0x80000000);
4882 SET_DREG (dst0
, val
);
4884 SET_ASTATREG (v
, v
);
4886 SET_ASTATREG (vs
, 1);
4887 setflags_nz (cpu
, val
);
4889 else if (aop
== 3 && aopcde
== 7)
4891 bu32 val
= DREG (src0
);
4893 TRACE_INSN (cpu
, "R%i = - R%i %s;", dst0
, src0
, amod1 (s
, 0));
4895 if (s
&& val
== 0x80000000)
4898 SET_ASTATREG (v
, 1);
4899 SET_ASTATREG (vs
, 1);
4901 else if (val
== 0x80000000)
4905 SET_DREG (dst0
, val
);
4907 SET_ASTATREG (az
, val
== 0);
4908 SET_ASTATREG (an
, val
& 0x80000000);
4910 else if (aop
== 2 && aopcde
== 6)
4912 bu32 in
= DREG (src0
);
4913 bu32 hi
= (in
& 0x80000000 ? (bu32
)-(bs16
)(in
>> 16) : in
>> 16) << 16;
4914 bu32 lo
= (in
& 0x8000 ? (bu32
)-(bs16
)(in
& 0xFFFF) : in
) & 0xFFFF;
4917 TRACE_INSN (cpu
, "R%i = ABS R%i (V);", dst0
, src0
);
4920 if (hi
== 0x80000000)
4930 SET_DREG (dst0
, hi
| lo
);
4932 SET_ASTATREG (v
, v
);
4934 SET_ASTATREG (vs
, 1);
4935 setflags_nz_2x16 (cpu
, DREG (dst0
));
4937 else if (aop
== 1 && aopcde
== 6)
4939 TRACE_INSN (cpu
, "R%i = MIN (R%i, R%i) (V);", dst0
, src0
, src1
);
4940 SET_DREG (dst0
, min2x16 (cpu
, DREG (src0
), DREG (src1
)));
4942 else if (aop
== 0 && aopcde
== 6)
4944 TRACE_INSN (cpu
, "R%i = MAX (R%i, R%i) (V);", dst0
, src0
, src1
);
4945 SET_DREG (dst0
, max2x16 (cpu
, DREG (src0
), DREG (src1
)));
4947 else if (aop
== 0 && aopcde
== 24)
4949 TRACE_INSN (cpu
, "R%i = BYTEPACK (R%i, R%i);", dst0
, src0
, src1
);
4951 (((DREG (src0
) >> 0) & 0xff) << 0) |
4952 (((DREG (src0
) >> 16) & 0xff) << 8) |
4953 (((DREG (src1
) >> 0) & 0xff) << 16) |
4954 (((DREG (src1
) >> 16) & 0xff) << 24));
4956 else if (aop
== 1 && aopcde
== 24)
4960 bu8 bytea
, byteb
, bytec
, byted
;
4962 TRACE_INSN (cpu
, "(R%i, R%i) = BYTEUNPACK R%i:%i%s;",
4963 dst1
, dst0
, src0
+ 1, src0
, s
? " (R)" : "");
4966 illegal_instruction_combination (cpu
);
4968 order
= IREG (0) & 0x3;
4970 hi
= src0
, lo
= src0
+ 1;
4972 hi
= src0
+ 1, lo
= src0
;
4973 comb_src
= (((bu64
)DREG (hi
)) << 32) | DREG (lo
);
4974 bytea
= (comb_src
>> (0 + 8 * order
));
4975 byteb
= (comb_src
>> (8 + 8 * order
));
4976 bytec
= (comb_src
>> (16 + 8 * order
));
4977 byted
= (comb_src
>> (24 + 8 * order
));
4978 SET_DREG (dst0
, bytea
| ((bu32
)byteb
<< 16));
4979 SET_DREG (dst1
, bytec
| ((bu32
)byted
<< 16));
4981 else if (aopcde
== 13)
4983 const char *searchmodes
[] = { "GT", "GE", "LT", "LE" };
4985 bs16 a0_lo
, a1_lo
, src_hi
, src_lo
;
4987 TRACE_INSN (cpu
, "(R%i, R%i) = SEARCH R%i (%s);",
4988 dst1
, dst0
, src0
, searchmodes
[aop
]);
4991 illegal_instruction_combination (cpu
);
4993 up_hi
= up_lo
= false;
4996 src_lo
= DREG (src0
);
4997 src_hi
= DREG (src0
) >> 16;
5002 up_hi
= (src_hi
> a1_lo
);
5003 up_lo
= (src_lo
> a0_lo
);
5006 up_hi
= (src_hi
>= a1_lo
);
5007 up_lo
= (src_lo
>= a0_lo
);
5010 up_hi
= (src_hi
< a1_lo
);
5011 up_lo
= (src_lo
< a0_lo
);
5014 up_hi
= (src_hi
<= a1_lo
);
5015 up_lo
= (src_lo
<= a0_lo
);
5021 SET_AREG (1, src_hi
);
5022 SET_DREG (dst1
, PREG (0));
5026 SET_AREG (0, src_lo
);
5027 SET_DREG (dst0
, PREG (0));
5031 illegal_instruction (cpu
);
5035 decode_dsp32shift_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
5038 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5039 | 1 | 1 | 0 | 0 |.M.| 1 | 1 | 0 | 0 | - | - |.sopcde............|
5040 |.sop...|.HLs...|.dst0......| - | - | - |.src0......|.src1......|
5041 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5042 int HLs
= ((iw1
>> DSP32Shift_HLs_bits
) & DSP32Shift_HLs_mask
);
5043 int sop
= ((iw1
>> DSP32Shift_sop_bits
) & DSP32Shift_sop_mask
);
5044 int src0
= ((iw1
>> DSP32Shift_src0_bits
) & DSP32Shift_src0_mask
);
5045 int src1
= ((iw1
>> DSP32Shift_src1_bits
) & DSP32Shift_src1_mask
);
5046 int dst0
= ((iw1
>> DSP32Shift_dst0_bits
) & DSP32Shift_dst0_mask
);
5047 int sopcde
= ((iw0
>> (DSP32Shift_sopcde_bits
- 16)) & DSP32Shift_sopcde_mask
);
5048 int M
= ((iw0
>> (DSP32Shift_M_bits
- 16)) & DSP32Shift_M_mask
);
5050 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32shift
);
5051 TRACE_EXTRACT (cpu
, "%s: M:%i sopcde:%i sop:%i HLs:%i dst0:%i src0:%i src1:%i",
5052 __func__
, M
, sopcde
, sop
, HLs
, dst0
, src0
, src1
);
5054 if ((sop
== 0 || sop
== 1) && sopcde
== 0)
5057 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5059 TRACE_INSN (cpu
, "R%i.%c = ASHIFT R%i.%c BY R%i.L%s;",
5060 dst0
, HLs
< 2 ? 'L' : 'H',
5061 src1
, HLs
& 1 ? 'H' : 'L',
5062 src0
, sop
== 1 ? " (S)" : "");
5065 val
= (bu16
)(DREG (src1
) & 0xFFFF);
5067 val
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5069 /* Positive shift magnitudes produce Logical Left shifts.
5070 Negative shift magnitudes produce Arithmetic Right shifts. */
5072 val
= ashiftrt (cpu
, val
, -shft
, 16);
5074 val
= lshift (cpu
, val
, shft
, 16, sop
== 1);
5077 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), val
));
5079 STORE (DREG (dst0
), REG_H_L (val
<< 16, DREG (dst0
)));
5081 else if (sop
== 2 && sopcde
== 0)
5083 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5086 TRACE_INSN (cpu
, "R%i.%c = LSHIFT R%i.%c BY R%i.L;",
5087 dst0
, HLs
< 2 ? 'L' : 'H',
5088 src1
, HLs
& 1 ? 'H' : 'L', src0
);
5091 val
= (bu16
)(DREG (src1
) & 0xFFFF);
5093 val
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5096 val
= val
>> (-1 * shft
);
5101 SET_DREG (dst0
, REG_H_L (DREG (dst0
), val
));
5103 SET_DREG (dst0
, REG_H_L (val
<< 16, DREG (dst0
)));
5105 SET_ASTATREG (az
, !((val
& 0xFFFF0000) == 0) || ((val
& 0xFFFF) == 0));
5106 SET_ASTATREG (an
, (!!(val
& 0x80000000)) ^ (!!(val
& 0x8000)));
5107 SET_ASTATREG (v
, 0);
5109 else if (sop
== 2 && sopcde
== 3 && (HLs
== 1 || HLs
== 0))
5111 int shift
= imm6 (DREG (src0
) & 0xFFFF);
5113 bu40 acc
= get_unextended_acc (cpu
, HLs
);
5115 TRACE_INSN (cpu
, "A%i = ROT A%i BY R%i.L;", HLs
, HLs
, src0
);
5116 TRACE_DECODE (cpu
, "A%i:%#"PRIx64
" shift:%i CC:%i", HLs
, acc
, shift
, cc
);
5118 acc
= rot40 (acc
, shift
, &cc
);
5119 SET_AREG (HLs
, acc
);
5123 else if (sop
== 0 && sopcde
== 3 && (HLs
== 0 || HLs
== 1))
5125 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5126 bu64 val
= get_extended_acc (cpu
, HLs
);
5129 TRACE_INSN (cpu
, "A%i = ASHIFT A%i BY R%i.L;", HLs
, HLs
, src0
);
5130 TRACE_DECODE (cpu
, "A%i:%#"PRIx64
" shift:%i", HLs
, val
, shft
);
5133 val
= ashiftrt (cpu
, val
, -shft
, 40);
5135 val
= lshift (cpu
, val
, shft
, 40, 0);
5137 STORE (AXREG (HLs
), (val
>> 32) & 0xff);
5138 STORE (AWREG (HLs
), (val
& 0xffffffff));
5140 else if (sop
== 1 && sopcde
== 3 && (HLs
== 0 || HLs
== 1))
5142 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5146 TRACE_INSN (cpu
, "A%i = LSHIFT A%i BY R%i.L;", HLs
, HLs
, src0
);
5147 val
= get_extended_acc (cpu
, HLs
);
5150 val
= lshiftrt (cpu
, val
, -shft
, 40);
5152 val
= lshift (cpu
, val
, shft
, 40, 0);
5154 STORE (AXREG (HLs
), (val
>> 32) & 0xff);
5155 STORE (AWREG (HLs
), (val
& 0xffffffff));
5157 else if ((sop
== 0 || sop
== 1) && sopcde
== 1)
5159 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5163 TRACE_INSN (cpu
, "R%i = ASHIFT R%i BY R%i.L (V%s);",
5164 dst0
, src1
, src0
, sop
== 1 ? ",S" : "");
5166 val0
= (bu16
)DREG (src1
) & 0xFFFF;
5167 val1
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5171 val0
= ashiftrt (cpu
, val0
, -shft
, 16);
5173 val1
= ashiftrt (cpu
, val1
, -shft
, 16);
5177 val0
= lshift (cpu
, val0
, shft
, 16, sop
== 1);
5179 val1
= lshift (cpu
, val1
, shft
, 16, sop
== 1);
5181 SET_ASTAT (ASTAT
| astat
);
5182 STORE (DREG (dst0
), (val1
<< 16) | val0
);
5184 else if ((sop
== 0 || sop
== 1 || sop
== 2) && sopcde
== 2)
5186 /* dregs = [LA]SHIFT dregs BY dregs_lo (opt_S) */
5187 /* sop == 1 : opt_S */
5188 bu32 v
= DREG (src1
);
5189 /* LSHIFT uses sign extended low 6 bits of dregs_lo. */
5190 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5192 TRACE_INSN (cpu
, "R%i = %cSHIFT R%i BY R%i.L%s;", dst0
,
5193 shft
&& sop
!= 2 ? 'A' : 'L', src1
, src0
,
5194 sop
== 1 ? " (S)" : "");
5199 STORE (DREG (dst0
), lshiftrt (cpu
, v
, -shft
, 32));
5201 STORE (DREG (dst0
), ashiftrt (cpu
, v
, -shft
, 32));
5204 STORE (DREG (dst0
), lshift (cpu
, v
, shft
, 32, sop
== 1));
5206 else if (sop
== 3 && sopcde
== 2)
5208 int shift
= imm6 (DREG (src0
) & 0xFFFF);
5209 bu32 src
= DREG (src1
);
5210 bu32 ret
, cc
= CCREG
;
5212 TRACE_INSN (cpu
, "R%i = ROT R%i BY R%i.L;", dst0
, src1
, src0
);
5213 TRACE_DECODE (cpu
, "R%i:%#x R%i:%#x shift:%i CC:%i",
5214 dst0
, DREG (dst0
), src1
, src
, shift
, cc
);
5216 ret
= rot32 (src
, shift
, &cc
);
5217 STORE (DREG (dst0
), ret
);
5221 else if (sop
== 2 && sopcde
== 1)
5223 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5227 TRACE_INSN (cpu
, "R%i = LSHIFT R%i BY R%i.L (V);", dst0
, src1
, src0
);
5229 val0
= (bu16
)DREG (src1
) & 0xFFFF;
5230 val1
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5234 val0
= lshiftrt (cpu
, val0
, -shft
, 16);
5236 val1
= lshiftrt (cpu
, val1
, -shft
, 16);
5240 val0
= lshift (cpu
, val0
, shft
, 16, 0);
5242 val1
= lshift (cpu
, val1
, shft
, 16, 0);
5244 SET_ASTAT (ASTAT
| astat
);
5245 STORE (DREG (dst0
), (val1
<< 16) | val0
);
5247 else if (sopcde
== 4)
5249 bu32 sv0
= DREG (src0
);
5250 bu32 sv1
= DREG (src1
);
5251 TRACE_INSN (cpu
, "R%i = PACK (R%i.%c, R%i.%c);", dst0
,
5252 src1
, sop
& 2 ? 'H' : 'L',
5253 src0
, sop
& 1 ? 'H' : 'L');
5258 SET_DREG (dst0
, (sv1
<< 16) | (sv0
& 0xFFFF));
5260 else if (sop
== 0 && sopcde
== 5)
5262 bu32 sv1
= DREG (src1
);
5263 TRACE_INSN (cpu
, "R%i.L = SIGNBITS R%i;", dst0
, src1
);
5264 SET_DREG_L (dst0
, signbits (sv1
, 32));
5266 else if (sop
== 1 && sopcde
== 5)
5268 bu32 sv1
= DREG (src1
);
5269 TRACE_INSN (cpu
, "R%i.L = SIGNBITS R%i.L;", dst0
, src1
);
5270 SET_DREG_L (dst0
, signbits (sv1
, 16));
5272 else if (sop
== 2 && sopcde
== 5)
5274 bu32 sv1
= DREG (src1
);
5275 TRACE_INSN (cpu
, "R%i.L = SIGNBITS R%i.H;", dst0
, src1
);
5276 SET_DREG_L (dst0
, signbits (sv1
>> 16, 16));
5278 else if ((sop
== 0 || sop
== 1) && sopcde
== 6)
5280 bu64 acc
= AXREG (sop
);
5281 TRACE_INSN (cpu
, "R%i.L = SIGNBITS A%i;", dst0
, sop
);
5284 SET_DREG_L (dst0
, signbits (acc
, 40) & 0xFFFF);
5286 else if (sop
== 3 && sopcde
== 6)
5288 bu32 v
= ones (DREG (src1
));
5289 TRACE_INSN (cpu
, "R%i.L = ONES R%i;", dst0
, src1
);
5290 SET_DREG_L (dst0
, v
);
5292 else if (sop
== 0 && sopcde
== 7)
5294 bu16 sv1
= (bu16
)signbits (DREG (src1
), 32);
5295 bu16 sv0
= (bu16
)DREG (src0
);
5298 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i, R%i.L);", dst0
, src1
, src0
);
5300 if ((sv1
& 0x1f) < (sv0
& 0x1f))
5304 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), dst_lo
));
5306 else if (sop
== 1 && sopcde
== 7)
5308 /* Exponent adjust on two 16-bit inputs. Select
5309 smallest norm among 3 inputs. */
5310 bs16 src1_hi
= (DREG (src1
) & 0xFFFF0000) >> 16;
5311 bs16 src1_lo
= (DREG (src1
) & 0xFFFF);
5312 bu16 src0_lo
= (DREG (src0
) & 0xFFFF);
5313 bu16 tmp_hi
, tmp_lo
, tmp
;
5315 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i, R%i.L) (V);", dst0
, src1
, src0
);
5317 tmp_hi
= signbits (src1_hi
, 16);
5318 tmp_lo
= signbits (src1_lo
, 16);
5320 if ((tmp_hi
& 0xf) < (tmp_lo
& 0xf))
5321 if ((tmp_hi
& 0xf) < (src0_lo
& 0xf))
5326 if ((tmp_lo
& 0xf) < (src0_lo
& 0xf))
5330 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), tmp
));
5332 else if (sop
== 2 && sopcde
== 7)
5334 /* Exponent adjust on single 16-bit register. */
5336 bu16 src0_lo
= (bu16
)(DREG (src0
) & 0xFFFF);
5338 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i.L, R%i.L);", dst0
, src1
, src0
);
5340 tmp
= signbits (DREG (src1
) & 0xFFFF, 16);
5342 if ((tmp
& 0xf) < (src0_lo
& 0xf))
5343 SET_DREG_L (dst0
, tmp
);
5345 SET_DREG_L (dst0
, src0_lo
);
5347 else if (sop
== 3 && sopcde
== 7)
5350 bu16 src0_lo
= (bu16
)(DREG (src0
) & 0xFFFF);
5352 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i.H, R%i.L);", dst0
, src1
, src0
);
5354 tmp
= signbits ((DREG (src1
) & 0xFFFF0000) >> 16, 16);
5356 if ((tmp
& 0xf) < (src0_lo
& 0xf))
5357 SET_DREG_L (dst0
, tmp
);
5359 SET_DREG_L (dst0
, src0_lo
);
5361 else if (sop
== 0 && sopcde
== 8)
5363 bu64 acc
= get_unextended_acc (cpu
, 0);
5366 TRACE_INSN (cpu
, "BITMUX (R%i, R%i, A0) (ASR);", src0
, src1
);
5369 illegal_instruction_combination (cpu
);
5374 (((bu64
)s0
& 1) << 38) |
5375 (((bu64
)s1
& 1) << 39);
5376 SET_DREG (src0
, s0
>> 1);
5377 SET_DREG (src1
, s1
>> 1);
5381 else if (sop
== 1 && sopcde
== 8)
5383 bu64 acc
= get_unextended_acc (cpu
, 0);
5386 TRACE_INSN (cpu
, "BITMUX (R%i, R%i, A0) (ASL);", src0
, src1
);
5389 illegal_instruction_combination (cpu
);
5396 SET_DREG (src0
, s0
<< 1);
5397 SET_DREG (src1
, s1
<< 1);
5401 else if ((sop
== 0 || sop
== 1) && sopcde
== 9)
5403 bs40 acc0
= get_extended_acc (cpu
, 0);
5406 TRACE_INSN (cpu
, "R%i.L = VIT_MAX (R%i) (AS%c);",
5407 dst0
, src1
, sop
& 1 ? 'R' : 'L');
5410 sH
= DREG (src1
) >> 16;
5417 if (((sH
- sL
) & 0x8000) == 0)
5420 acc0
|= (sop
& 1) ? 0x80000000 : 1;
5426 SET_DREG (dst0
, REG_H_L (DREG (dst0
), out
));
5428 else if ((sop
== 2 || sop
== 3) && sopcde
== 9)
5430 bs40 acc0
= get_extended_acc (cpu
, 0);
5431 bs16 s0L
, s0H
, s1L
, s1H
, out0
, out1
;
5433 TRACE_INSN (cpu
, "R%i = VIT_MAX (R%i, R%i) (AS%c);",
5434 dst0
, src1
, src0
, sop
& 1 ? 'R' : 'L');
5437 s0H
= DREG (src0
) >> 16;
5439 s1H
= DREG (src1
) >> 16;
5446 if (((s0H
- s0L
) & 0x8000) == 0)
5449 acc0
|= (sop
& 1) ? 0x40000000 : 2;
5454 if (((s1H
- s1L
) & 0x8000) == 0)
5457 acc0
|= (sop
& 1) ? 0x80000000 : 1;
5463 SET_DREG (dst0
, REG_H_L (out1
<< 16, out0
));
5465 else if (sop
== 0 && sopcde
== 10)
5467 bu32 v
= DREG (src0
);
5468 bu32 x
= DREG (src1
);
5469 bu32 mask
= (1 << (v
& 0x1f)) - 1;
5470 TRACE_INSN (cpu
, "R%i = EXTRACT (R%i, R%i.L) (Z);", dst0
, src1
, src0
);
5471 x
>>= ((v
>> 8) & 0x1f);
5472 SET_DREG (dst0
, x
& mask
);
5473 setflags_logical (cpu
, DREG (dst0
));
5475 else if (sop
== 1 && sopcde
== 10)
5477 bu32 v
= DREG (src0
);
5478 bu32 x
= DREG (src1
);
5479 bu32 sgn
= (1 << (v
& 0x1f)) >> 1;
5480 bu32 mask
= (1 << (v
& 0x1f)) - 1;
5481 TRACE_INSN (cpu
, "R%i = EXTRACT (R%i, R%i.L) (X);", dst0
, src1
, src0
);
5482 x
>>= ((v
>> 8) & 0x1f);
5487 setflags_logical (cpu
, DREG (dst0
));
5489 else if ((sop
== 2 || sop
== 3) && sopcde
== 10)
5491 /* The first dregs is the "background" while the second dregs is the
5492 "foreground". The fg reg is used to overlay the bg reg and is:
5493 | nnnn nnnn | nnnn nnnn | xxxp pppp | xxxL LLLL |
5494 n = the fg bit field
5495 p = bit position in bg reg to start LSB of fg field
5496 L = number of fg bits to extract
5497 Using (X) sign-extends the fg bit field. */
5498 bu32 fg
= DREG (src0
);
5499 bu32 bg
= DREG (src1
);
5500 bu32 len
= fg
& 0x1f;
5501 bu32 mask
= (1 << MIN (16, len
)) - 1;
5502 bu32 fgnd
= (fg
>> 16) & mask
;
5503 int shft
= ((fg
>> 8) & 0x1f);
5505 TRACE_INSN (cpu
, "R%i = DEPOSIT (R%i, R%i)%s;", dst0
, src1
, src0
,
5506 sop
== 3 ? " (X)" : "");
5510 /* Sign extend the fg bit field. */
5512 fgnd
= ((bs32
)(bs16
)(fgnd
<< (16 - len
))) >> (16 - len
);
5518 SET_DREG (dst0
, bg
| fgnd
);
5519 setflags_logical (cpu
, DREG (dst0
));
5521 else if (sop
== 0 && sopcde
== 11)
5523 bu64 acc0
= get_unextended_acc (cpu
, 0);
5525 TRACE_INSN (cpu
, "R%i.L = CC = BXORSHIFT (A0, R%i);", dst0
, src0
);
5528 SET_CCREG (xor_reduce (acc0
, DREG (src0
)));
5529 SET_DREG (dst0
, REG_H_L (DREG (dst0
), CCREG
));
5532 else if (sop
== 1 && sopcde
== 11)
5534 bu64 acc0
= get_unextended_acc (cpu
, 0);
5536 TRACE_INSN (cpu
, "R%i.L = CC = BXOR (A0, R%i);", dst0
, src0
);
5538 SET_CCREG (xor_reduce (acc0
, DREG (src0
)));
5539 SET_DREG (dst0
, REG_H_L (DREG (dst0
), CCREG
));
5541 else if (sop
== 0 && sopcde
== 12)
5543 bu64 acc0
= get_unextended_acc (cpu
, 0);
5544 bu64 acc1
= get_unextended_acc (cpu
, 1);
5546 TRACE_INSN (cpu
, "A0 = BXORSHIFT (A0, A1, CC);");
5548 acc0
= (acc0
<< 1) | (CCREG
^ xor_reduce (acc0
, acc1
));
5551 else if (sop
== 1 && sopcde
== 12)
5553 bu64 acc0
= get_unextended_acc (cpu
, 0);
5554 bu64 acc1
= get_unextended_acc (cpu
, 1);
5556 TRACE_INSN (cpu
, "R%i.L = CC = BXOR (A0, A1, CC);", dst0
);
5558 SET_CCREG (CCREG
^ xor_reduce (acc0
, acc1
));
5559 acc0
= (acc0
<< 1) | CCREG
;
5560 SET_DREG (dst0
, REG_H_L (DREG (dst0
), CCREG
));
5562 else if ((sop
== 0 || sop
== 1 || sop
== 2) && sopcde
== 13)
5564 int shift
= (sop
+ 1) * 8;
5565 TRACE_INSN (cpu
, "R%i = ALIGN%i (R%i, R%i);", dst0
, shift
, src1
, src0
);
5566 SET_DREG (dst0
, (DREG (src1
) << (32 - shift
)) | (DREG (src0
) >> shift
));
5569 illegal_instruction (cpu
);
5573 decode_dsp32shiftimm_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
5576 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5577 | 1 | 1 | 0 | 0 |.M.| 1 | 1 | 0 | 1 | - | - |.sopcde............|
5578 |.sop...|.HLs...|.dst0......|.immag.................|.src1......|
5579 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5580 int src1
= ((iw1
>> DSP32ShiftImm_src1_bits
) & DSP32ShiftImm_src1_mask
);
5581 int sop
= ((iw1
>> DSP32ShiftImm_sop_bits
) & DSP32ShiftImm_sop_mask
);
5582 int bit8
= ((iw1
>> 8) & 0x1);
5583 int immag
= ((iw1
>> DSP32ShiftImm_immag_bits
) & DSP32ShiftImm_immag_mask
);
5584 int newimmag
= (-(iw1
>> DSP32ShiftImm_immag_bits
) & DSP32ShiftImm_immag_mask
);
5585 int dst0
= ((iw1
>> DSP32ShiftImm_dst0_bits
) & DSP32ShiftImm_dst0_mask
);
5586 int M
= ((iw0
>> (DSP32ShiftImm_M_bits
- 16)) & DSP32ShiftImm_M_mask
);
5587 int sopcde
= ((iw0
>> (DSP32ShiftImm_sopcde_bits
- 16)) & DSP32ShiftImm_sopcde_mask
);
5588 int HLs
= ((iw1
>> DSP32ShiftImm_HLs_bits
) & DSP32ShiftImm_HLs_mask
);
5590 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32shiftimm
);
5591 TRACE_EXTRACT (cpu
, "%s: M:%i sopcde:%i sop:%i HLs:%i dst0:%i immag:%#x src1:%i",
5592 __func__
, M
, sopcde
, sop
, HLs
, dst0
, immag
, src1
);
5596 bu16 in
= DREG (src1
) >> ((HLs
& 1) ? 16 : 0);
5602 TRACE_INSN (cpu
, "R%i.%c = R%i.%c >>> %i;",
5603 dst0
, (HLs
& 2) ? 'H' : 'L',
5604 src1
, (HLs
& 1) ? 'H' : 'L', newimmag
);
5605 result
= ashiftrt (cpu
, in
, newimmag
, 16);
5607 else if (sop
== 1 && bit8
== 0)
5609 TRACE_INSN (cpu
, "R%i.%c = R%i.%c << %i (S);",
5610 dst0
, (HLs
& 2) ? 'H' : 'L',
5611 src1
, (HLs
& 1) ? 'H' : 'L', immag
);
5612 result
= lshift (cpu
, in
, immag
, 16, 1);
5614 else if (sop
== 1 && bit8
)
5616 TRACE_INSN (cpu
, "R%i.%c = R%i.%c >>> %i (S);",
5617 dst0
, (HLs
& 2) ? 'H' : 'L',
5618 src1
, (HLs
& 1) ? 'H' : 'L', immag
);
5619 result
= lshift (cpu
, in
, immag
, 16, 1);
5621 else if (sop
== 2 && bit8
)
5623 TRACE_INSN (cpu
, "R%i.%c = R%i.%c >> %i;",
5624 dst0
, (HLs
& 2) ? 'H' : 'L',
5625 src1
, (HLs
& 1) ? 'H' : 'L', newimmag
);
5626 result
= lshiftrt (cpu
, in
, newimmag
, 16);
5628 else if (sop
== 2 && bit8
== 0)
5630 TRACE_INSN (cpu
, "R%i.%c = R%i.%c << %i;",
5631 dst0
, (HLs
& 2) ? 'H' : 'L',
5632 src1
, (HLs
& 1) ? 'H' : 'L', immag
);
5633 result
= lshift (cpu
, in
, immag
, 16, 0);
5636 illegal_instruction (cpu
);
5640 STORE (DREG (dst0
), (v
& 0xFFFF) | (result
<< 16));
5642 STORE (DREG (dst0
), (v
& 0xFFFF0000) | result
);
5644 else if (sop
== 2 && sopcde
== 3 && (HLs
== 1 || HLs
== 0))
5646 int shift
= imm6 (immag
);
5648 bu40 acc
= get_unextended_acc (cpu
, HLs
);
5650 TRACE_INSN (cpu
, "A%i = ROT A%i BY %i;", HLs
, HLs
, shift
);
5651 TRACE_DECODE (cpu
, "A%i:%#"PRIx64
" shift:%i CC:%i", HLs
, acc
, shift
, cc
);
5653 acc
= rot40 (acc
, shift
, &cc
);
5654 SET_AREG (HLs
, acc
);
5658 else if (sop
== 0 && sopcde
== 3 && bit8
== 1)
5660 /* Arithmetic shift, so shift in sign bit copies. */
5662 int shift
= uimm5 (newimmag
);
5665 TRACE_INSN (cpu
, "A%i = A%i >>> %i;", HLs
, HLs
, shift
);
5667 acc
= get_extended_acc (cpu
, HLs
);
5669 /* Sign extend again. */
5670 if (acc
& (1ULL << 39))
5671 acc
|= -(1ULL << 39);
5673 acc
&= ~(-(1ULL << 39));
5675 STORE (AXREG (HLs
), (acc
>> 32) & 0xFF);
5676 STORE (AWREG (HLs
), acc
& 0xFFFFFFFF);
5678 else if ((sop
== 0 && sopcde
== 3 && bit8
== 0)
5679 || (sop
== 1 && sopcde
== 3))
5682 int shiftup
= uimm5 (immag
);
5683 int shiftdn
= uimm5 (newimmag
);
5686 TRACE_INSN (cpu
, "A%i = A%i %s %i;", HLs
, HLs
,
5687 sop
== 0 ? "<<" : ">>",
5688 sop
== 0 ? shiftup
: shiftdn
);
5691 /* Logical shift, so shift in zeroes. */
5701 SET_AREG (HLs
, acc
);
5702 SET_ASTATREG (an
, !!(acc
& 0x8000000000ull
));
5703 SET_ASTATREG (az
, acc
== 0);
5705 else if (sop
== 1 && sopcde
== 1 && bit8
== 0)
5707 int count
= imm5 (immag
);
5708 bu16 val0
= DREG (src1
) >> 16;
5709 bu16 val1
= DREG (src1
) & 0xFFFF;
5712 TRACE_INSN (cpu
, "R%i = R%i << %i (V,S);", dst0
, src1
, count
);
5713 val0
= lshift (cpu
, val0
, count
, 16, 1);
5715 val1
= lshift (cpu
, val1
, count
, 16, 1);
5716 SET_ASTAT (ASTAT
| astat
);
5718 STORE (DREG (dst0
), (val0
<< 16) | val1
);
5720 else if (sop
== 2 && sopcde
== 1 && bit8
== 1)
5722 int count
= imm5 (newimmag
);
5723 bu16 val0
= DREG (src1
) & 0xFFFF;
5724 bu16 val1
= DREG (src1
) >> 16;
5727 TRACE_INSN (cpu
, "R%i = R%i >> %i (V);", dst0
, src1
, count
);
5728 val0
= lshiftrt (cpu
, val0
, count
, 16);
5730 val1
= lshiftrt (cpu
, val1
, count
, 16);
5731 SET_ASTAT (ASTAT
| astat
);
5733 STORE (DREG (dst0
), val0
| (val1
<< 16));
5735 else if (sop
== 2 && sopcde
== 1 && bit8
== 0)
5737 int count
= imm5 (immag
);
5738 bu16 val0
= DREG (src1
) & 0xFFFF;
5739 bu16 val1
= DREG (src1
) >> 16;
5742 TRACE_INSN (cpu
, "R%i = R%i << %i (V);", dst0
, src1
, count
);
5743 val0
= lshift (cpu
, val0
, count
, 16, 0);
5745 val1
= lshift (cpu
, val1
, count
, 16, 0);
5746 SET_ASTAT (ASTAT
| astat
);
5748 STORE (DREG (dst0
), val0
| (val1
<< 16));
5750 else if (sopcde
== 1 && (sop
== 0 || (sop
== 1 && bit8
== 1)))
5752 int count
= uimm5 (newimmag
);
5753 bu16 val0
= DREG (src1
) & 0xFFFF;
5754 bu16 val1
= DREG (src1
) >> 16;
5757 TRACE_INSN (cpu
, "R%i = R%i >>> %i %s;", dst0
, src1
, count
,
5758 sop
== 0 ? "(V)" : "(V,S)");
5760 val0
= ashiftrt (cpu
, val0
, count
, 16);
5762 val1
= ashiftrt (cpu
, val1
, count
, 16);
5763 SET_ASTAT (ASTAT
| astat
);
5765 STORE (DREG (dst0
), REG_H_L (val1
<< 16, val0
));
5767 else if (sop
== 1 && sopcde
== 2)
5769 int count
= imm6 (immag
);
5771 TRACE_INSN (cpu
, "R%i = R%i << %i (S);", dst0
, src1
, count
);
5772 STORE (DREG (dst0
), lshift (cpu
, DREG (src1
), count
, 32, 1));
5774 else if (sop
== 2 && sopcde
== 2)
5776 int count
= imm6 (newimmag
);
5778 TRACE_INSN (cpu
, "R%i = R%i >> %i;", dst0
, src1
, count
);
5781 STORE (DREG (dst0
), lshift (cpu
, DREG (src1
), -count
, 32, 0));
5783 STORE (DREG (dst0
), lshiftrt (cpu
, DREG (src1
), count
, 32));
5785 else if (sop
== 3 && sopcde
== 2)
5787 int shift
= imm6 (immag
);
5788 bu32 src
= DREG (src1
);
5789 bu32 ret
, cc
= CCREG
;
5791 TRACE_INSN (cpu
, "R%i = ROT R%i BY %i;", dst0
, src1
, shift
);
5792 TRACE_DECODE (cpu
, "R%i:%#x R%i:%#x shift:%i CC:%i",
5793 dst0
, DREG (dst0
), src1
, src
, shift
, cc
);
5795 ret
= rot32 (src
, shift
, &cc
);
5796 STORE (DREG (dst0
), ret
);
5800 else if (sop
== 0 && sopcde
== 2)
5802 int count
= imm6 (newimmag
);
5804 TRACE_INSN (cpu
, "R%i = R%i >>> %i;", dst0
, src1
, count
);
5807 STORE (DREG (dst0
), lshift (cpu
, DREG (src1
), -count
, 32, 0));
5809 STORE (DREG (dst0
), ashiftrt (cpu
, DREG (src1
), count
, 32));
5812 illegal_instruction (cpu
);
5816 outc (SIM_CPU
*cpu
, char ch
)
5818 SIM_DESC sd
= CPU_STATE (cpu
);
5819 sim_io_printf (sd
, "%c", ch
);
5821 sim_io_flush_stdout (sd
);
5825 decode_psedoDEBUG_0 (SIM_CPU
*cpu
, bu16 iw0
)
5828 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5829 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 |.fn....|.grp.......|.reg.......|
5830 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5831 SIM_DESC sd
= CPU_STATE (cpu
);
5832 int fn
= ((iw0
>> PseudoDbg_fn_bits
) & PseudoDbg_fn_mask
);
5833 int grp
= ((iw0
>> PseudoDbg_grp_bits
) & PseudoDbg_grp_mask
);
5834 int reg
= ((iw0
>> PseudoDbg_reg_bits
) & PseudoDbg_reg_mask
);
5836 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_psedoDEBUG
);
5837 TRACE_EXTRACT (cpu
, "%s: fn:%i grp:%i reg:%i", __func__
, fn
, grp
, reg
);
5839 if ((reg
== 0 || reg
== 1) && fn
== 3)
5841 TRACE_INSN (cpu
, "DBG A%i;", reg
);
5842 sim_io_printf (sd
, "DBG : A%i = %#"PRIx64
"\n", reg
,
5843 get_unextended_acc (cpu
, reg
));
5845 else if (reg
== 3 && fn
== 3)
5847 TRACE_INSN (cpu
, "ABORT;");
5848 cec_exception (cpu
, VEC_SIM_ABORT
);
5851 else if (reg
== 4 && fn
== 3)
5853 TRACE_INSN (cpu
, "HLT;");
5854 cec_exception (cpu
, VEC_SIM_HLT
);
5857 else if (reg
== 5 && fn
== 3)
5858 unhandled_instruction (cpu
, "DBGHALT");
5859 else if (reg
== 6 && fn
== 3)
5860 unhandled_instruction (cpu
, "DBGCMPLX (dregs)");
5861 else if (reg
== 7 && fn
== 3)
5862 unhandled_instruction (cpu
, "DBG");
5863 else if (grp
== 0 && fn
== 2)
5865 TRACE_INSN (cpu
, "OUTC R%i;", reg
);
5866 outc (cpu
, DREG (reg
));
5870 const char *reg_name
= get_allreg_name (grp
, reg
);
5871 TRACE_INSN (cpu
, "DBG %s;", reg_name
);
5872 sim_io_printf (sd
, "DBG : %s = 0x%08x\n", reg_name
,
5873 reg_read (cpu
, grp
, reg
));
5876 unhandled_instruction (cpu
, "PRNT allregs");
5878 illegal_instruction (cpu
);
5882 decode_psedoOChar_0 (SIM_CPU
*cpu
, bu16 iw0
)
5885 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5886 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |.ch............................|
5887 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5888 int ch
= ((iw0
>> PseudoChr_ch_bits
) & PseudoChr_ch_mask
);
5890 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_psedoOChar
);
5891 TRACE_EXTRACT (cpu
, "%s: ch:%#x", __func__
, ch
);
5892 TRACE_INSN (cpu
, "OUTC %#x;", ch
);
5898 decode_psedodbg_assert_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
, bu32 pc
)
5901 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5902 | 1 | 1 | 1 | 1 | 0 | - | - | - | dbgop |.grp.......|.regtest...|
5903 |.expected......................................................|
5904 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5905 SIM_DESC sd
= CPU_STATE (cpu
);
5906 int expected
= ((iw1
>> PseudoDbg_Assert_expected_bits
) & PseudoDbg_Assert_expected_mask
);
5907 int dbgop
= ((iw0
>> (PseudoDbg_Assert_dbgop_bits
- 16)) & PseudoDbg_Assert_dbgop_mask
);
5908 int grp
= ((iw0
>> (PseudoDbg_Assert_grp_bits
- 16)) & PseudoDbg_Assert_grp_mask
);
5909 int regtest
= ((iw0
>> (PseudoDbg_Assert_regtest_bits
- 16)) & PseudoDbg_Assert_regtest_mask
);
5912 bu32 val
= reg_read (cpu
, grp
, regtest
);
5913 const char *reg_name
= get_allreg_name (grp
, regtest
);
5914 const char *dbg_name
, *dbg_appd
;
5916 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_psedodbg_assert
);
5917 TRACE_EXTRACT (cpu
, "%s: dbgop:%i grp:%i regtest:%i expected:%#x",
5918 __func__
, dbgop
, grp
, regtest
, expected
);
5920 if (dbgop
== 0 || dbgop
== 2)
5922 dbg_name
= dbgop
== 0 ? "DBGA" : "DBGAL";
5923 dbg_appd
= dbgop
== 0 ? ".L" : "";
5926 else if (dbgop
== 1 || dbgop
== 3)
5928 dbg_name
= dbgop
== 1 ? "DBGA" : "DBGAH";
5929 dbg_appd
= dbgop
== 1 ? ".H" : "";
5933 illegal_instruction (cpu
);
5935 actual
= val
>> offset
;
5937 TRACE_INSN (cpu
, "%s (%s%s, 0x%x);", dbg_name
, reg_name
, dbg_appd
, expected
);
5938 if (actual
!= expected
)
5940 sim_io_printf (sd
, "FAIL at %#x: %s (%s%s, 0x%04x); actual value %#x\n",
5941 pc
, dbg_name
, reg_name
, dbg_appd
, expected
, actual
);
5943 /* Decode the actual ASTAT bits that are different. */
5944 if (grp
== 4 && regtest
== 6)
5948 sim_io_printf (sd
, "Expected ASTAT:\n");
5949 for (i
= 0; i
< 16; ++i
)
5950 sim_io_printf (sd
, " %8s%c%i%s",
5951 astat_names
[i
+ offset
],
5952 (((expected
>> i
) & 1) != ((actual
>> i
) & 1))
5954 (expected
>> i
) & 1,
5955 i
== 7 ? "\n" : "");
5956 sim_io_printf (sd
, "\n");
5958 sim_io_printf (sd
, "Actual ASTAT:\n");
5959 for (i
= 0; i
< 16; ++i
)
5960 sim_io_printf (sd
, " %8s%c%i%s",
5961 astat_names
[i
+ offset
],
5962 (((expected
>> i
) & 1) != ((actual
>> i
) & 1))
5965 i
== 7 ? "\n" : "");
5966 sim_io_printf (sd
, "\n");
5969 cec_exception (cpu
, VEC_SIM_DBGA
);
5975 _interp_insn_bfin (SIM_CPU
*cpu
, bu32 pc
)
5980 BFIN_CPU_STATE
.multi_pc
= pc
;
5982 if ((iw0
& 0xc000) != 0xc000)
5984 /* 16-bit opcode. */
5987 INSN_LEN
= insn_len
;
5989 TRACE_EXTRACT (cpu
, "%s: iw0:%#x", __func__
, iw0
);
5990 if ((iw0
& 0xFF00) == 0x0000)
5991 decode_ProgCtrl_0 (cpu
, iw0
, pc
);
5992 else if ((iw0
& 0xFFC0) == 0x0240)
5993 decode_CaCTRL_0 (cpu
, iw0
);
5994 else if ((iw0
& 0xFF80) == 0x0100)
5995 decode_PushPopReg_0 (cpu
, iw0
);
5996 else if ((iw0
& 0xFE00) == 0x0400)
5997 decode_PushPopMultiple_0 (cpu
, iw0
);
5998 else if ((iw0
& 0xFE00) == 0x0600)
5999 decode_ccMV_0 (cpu
, iw0
);
6000 else if ((iw0
& 0xF800) == 0x0800)
6001 decode_CCflag_0 (cpu
, iw0
);
6002 else if ((iw0
& 0xFFE0) == 0x0200)
6003 decode_CC2dreg_0 (cpu
, iw0
);
6004 else if ((iw0
& 0xFF00) == 0x0300)
6005 decode_CC2stat_0 (cpu
, iw0
);
6006 else if ((iw0
& 0xF000) == 0x1000)
6007 decode_BRCC_0 (cpu
, iw0
, pc
);
6008 else if ((iw0
& 0xF000) == 0x2000)
6009 decode_UJUMP_0 (cpu
, iw0
, pc
);
6010 else if ((iw0
& 0xF000) == 0x3000)
6011 decode_REGMV_0 (cpu
, iw0
);
6012 else if ((iw0
& 0xFC00) == 0x4000)
6013 decode_ALU2op_0 (cpu
, iw0
);
6014 else if ((iw0
& 0xFE00) == 0x4400)
6015 decode_PTR2op_0 (cpu
, iw0
);
6016 else if ((iw0
& 0xF800) == 0x4800)
6017 decode_LOGI2op_0 (cpu
, iw0
);
6018 else if ((iw0
& 0xF000) == 0x5000)
6019 decode_COMP3op_0 (cpu
, iw0
);
6020 else if ((iw0
& 0xF800) == 0x6000)
6021 decode_COMPI2opD_0 (cpu
, iw0
);
6022 else if ((iw0
& 0xF800) == 0x6800)
6023 decode_COMPI2opP_0 (cpu
, iw0
);
6024 else if ((iw0
& 0xF000) == 0x8000)
6025 decode_LDSTpmod_0 (cpu
, iw0
);
6026 else if ((iw0
& 0xFF60) == 0x9E60)
6027 decode_dagMODim_0 (cpu
, iw0
);
6028 else if ((iw0
& 0xFFF0) == 0x9F60)
6029 decode_dagMODik_0 (cpu
, iw0
);
6030 else if ((iw0
& 0xFC00) == 0x9C00)
6031 decode_dspLDST_0 (cpu
, iw0
);
6032 else if ((iw0
& 0xF000) == 0x9000)
6033 decode_LDST_0 (cpu
, iw0
);
6034 else if ((iw0
& 0xFC00) == 0xB800)
6035 decode_LDSTiiFP_0 (cpu
, iw0
);
6036 else if ((iw0
& 0xE000) == 0xA000)
6037 decode_LDSTii_0 (cpu
, iw0
);
6040 TRACE_EXTRACT (cpu
, "%s: no matching 16-bit pattern", __func__
);
6041 illegal_instruction (cpu
);
6046 /* Grab the next 16 bits to determine if it's a 32-bit or 64-bit opcode. */
6047 iw1
= IFETCH (pc
+ 2);
6048 if ((iw0
& BIT_MULTI_INS
) && (iw0
& 0xe800) != 0xe800 /* not linkage */)
6050 SIM_DESC sd
= CPU_STATE (cpu
);
6051 trace_prefix (sd
, cpu
, NULL_CIA
, pc
, TRACE_LINENUM_P (cpu
),
6052 NULL
, 0, "|| %#"PRIx64
, sim_events_time (sd
));
6058 TRACE_EXTRACT (cpu
, "%s: iw0:%#x iw1:%#x insn_len:%i", __func__
,
6059 iw0
, iw1
, insn_len
);
6061 /* Only cache on first run through (in case of parallel insns). */
6063 INSN_LEN
= insn_len
;
6065 if ((iw0
& 0xf7ff) == 0xc003 && (iw1
& 0xfe00) == 0x1800)
6067 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32mac
);
6068 TRACE_INSN (cpu
, "MNOP;");
6070 else if (((iw0
& 0xFF80) == 0xE080) && ((iw1
& 0x0C00) == 0x0000))
6071 decode_LoopSetup_0 (cpu
, iw0
, iw1
, pc
);
6072 else if (((iw0
& 0xFF00) == 0xE100) && ((iw1
& 0x0000) == 0x0000))
6073 decode_LDIMMhalf_0 (cpu
, iw0
, iw1
);
6074 else if (((iw0
& 0xFE00) == 0xE200) && ((iw1
& 0x0000) == 0x0000))
6075 decode_CALLa_0 (cpu
, iw0
, iw1
, pc
);
6076 else if (((iw0
& 0xFC00) == 0xE400) && ((iw1
& 0x0000) == 0x0000))
6077 decode_LDSTidxI_0 (cpu
, iw0
, iw1
);
6078 else if (((iw0
& 0xFFFE) == 0xE800) && ((iw1
& 0x0000) == 0x0000))
6079 decode_linkage_0 (cpu
, iw0
, iw1
);
6080 else if (((iw0
& 0xF600) == 0xC000) && ((iw1
& 0x0000) == 0x0000))
6081 decode_dsp32mac_0 (cpu
, iw0
, iw1
);
6082 else if (((iw0
& 0xF600) == 0xC200) && ((iw1
& 0x0000) == 0x0000))
6083 decode_dsp32mult_0 (cpu
, iw0
, iw1
);
6084 else if (((iw0
& 0xF7C0) == 0xC400) && ((iw1
& 0x0000) == 0x0000))
6085 decode_dsp32alu_0 (cpu
, iw0
, iw1
);
6086 else if (((iw0
& 0xF7E0) == 0xC600) && ((iw1
& 0x01C0) == 0x0000))
6087 decode_dsp32shift_0 (cpu
, iw0
, iw1
);
6088 else if (((iw0
& 0xF7E0) == 0xC680) && ((iw1
& 0x0000) == 0x0000))
6089 decode_dsp32shiftimm_0 (cpu
, iw0
, iw1
);
6090 else if ((iw0
& 0xFF00) == 0xF800)
6091 decode_psedoDEBUG_0 (cpu
, iw0
), insn_len
= 2;
6092 else if ((iw0
& 0xFF00) == 0xF900)
6093 decode_psedoOChar_0 (cpu
, iw0
), insn_len
= 2;
6094 else if (((iw0
& 0xFF00) == 0xF000) && ((iw1
& 0x0000) == 0x0000))
6095 decode_psedodbg_assert_0 (cpu
, iw0
, iw1
, pc
);
6098 TRACE_EXTRACT (cpu
, "%s: no matching 32-bit pattern", __func__
);
6099 illegal_instruction (cpu
);
6106 interp_insn_bfin (SIM_CPU
*cpu
, bu32 pc
)
6111 BFIN_CPU_STATE
.n_stores
= 0;
6112 DIS_ALGN_EXPT
&= ~1;
6116 insn_len
= _interp_insn_bfin (cpu
, pc
);
6118 /* Proper display of multiple issue instructions. */
6121 _interp_insn_bfin (cpu
, pc
+ 4);
6122 _interp_insn_bfin (cpu
, pc
+ 6);
6124 for (i
= 0; i
< BFIN_CPU_STATE
.n_stores
; i
++)
6126 bu32
*addr
= BFIN_CPU_STATE
.stores
[i
].addr
;
6127 *addr
= BFIN_CPU_STATE
.stores
[i
].val
;
6128 TRACE_REGISTER (cpu
, "dequeuing write %s = %#x",
6129 get_store_name (cpu
, addr
), *addr
);
6132 cycles_inc (cpu
, CYCLE_DELAY
);
6134 /* Set back to zero in case a pending CEC event occurs
6135 after this this insn. */