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, v_i0
= 0, v_i1
= 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
, &v_i1
);
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
, &v_i0
);
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 bu32 v
= sat0
| sat1
| v_i0
| v_i1
;
3931 STORE (ASTATREG (v
), v
);
3932 STORE (ASTATREG (v_copy
), v
);
3934 STORE (ASTATREG (vs
), v
);
3939 decode_dsp32alu_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3942 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3943 | 1 | 1 | 0 | 0 |.M.| 1 | 0 | - | - | - |.HL|.aopcde............|
3944 |.aop...|.s.|.x.|.dst0......|.dst1......|.src0......|.src1......|
3945 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3946 int s
= ((iw1
>> DSP32Alu_s_bits
) & DSP32Alu_s_mask
);
3947 int x
= ((iw1
>> DSP32Alu_x_bits
) & DSP32Alu_x_mask
);
3948 int aop
= ((iw1
>> DSP32Alu_aop_bits
) & DSP32Alu_aop_mask
);
3949 int src0
= ((iw1
>> DSP32Alu_src0_bits
) & DSP32Alu_src0_mask
);
3950 int src1
= ((iw1
>> DSP32Alu_src1_bits
) & DSP32Alu_src1_mask
);
3951 int dst0
= ((iw1
>> DSP32Alu_dst0_bits
) & DSP32Alu_dst0_mask
);
3952 int dst1
= ((iw1
>> DSP32Alu_dst1_bits
) & DSP32Alu_dst1_mask
);
3953 int M
= ((iw0
>> (DSP32Alu_M_bits
- 16)) & DSP32Alu_M_mask
);
3954 int HL
= ((iw0
>> (DSP32Alu_HL_bits
- 16)) & DSP32Alu_HL_mask
);
3955 int aopcde
= ((iw0
>> (DSP32Alu_aopcde_bits
- 16)) & DSP32Alu_aopcde_mask
);
3957 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32alu
);
3958 TRACE_EXTRACT (cpu
, "%s: M:%i HL:%i aopcde:%i aop:%i s:%i x:%i dst0:%i "
3959 "dst1:%i src0:%i src1:%i",
3960 __func__
, M
, HL
, aopcde
, aop
, s
, x
, dst0
, dst1
, src0
, src1
);
3962 if ((aop
== 0 || aop
== 2) && aopcde
== 9 && HL
== 0 && s
== 0)
3965 TRACE_INSN (cpu
, "A%i.L = R%i.L;", a
, src0
);
3966 SET_AWREG (a
, REG_H_L (AWREG (a
), DREG (src0
)));
3968 else if ((aop
== 0 || aop
== 2) && aopcde
== 9 && HL
== 1 && s
== 0)
3971 TRACE_INSN (cpu
, "A%i.H = R%i.H;", a
, src0
);
3972 SET_AWREG (a
, REG_H_L (DREG (src0
), AWREG (a
)));
3974 else if ((aop
== 1 || aop
== 0) && aopcde
== 5)
3976 bs32 val0
= DREG (src0
);
3977 bs32 val1
= DREG (src1
);
3980 bs32 ovX
, sBit1
, sBit2
, sBitRes1
, sBitRes2
;
3982 TRACE_INSN (cpu
, "R%i.%s = R%i %s R%i (RND12)", dst0
, HL
? "L" : "H",
3983 src0
, aop
& 0x1 ? "-" : "+", src1
);
3985 /* If subtract, just invert and add one. */
3989 /* Get the sign bits, since we need them later. */
3990 sBit1
= !!(val0
& 0x80000000);
3991 sBit2
= !!(val1
& 0x80000000);
3995 sBitRes1
= !!(res
& 0x80000000);
3996 /* Round to the 12th bit. */
3998 sBitRes2
= !!(res
& 0x80000000);
4006 positive_res + positive_round = neg
4007 Shift and upper 4 bits where not the same. */
4008 if ((!(sBit1
^ sBit2
) && (sBit1
^ sBitRes1
))
4009 || (!sBit1
&& !sBit2
&& sBitRes2
)
4010 || ((signRes
!= 0) && (signRes
!= -1)))
4012 /* Both X1 and X2 Neg res is neg overflow. */
4015 /* Both X1 and X2 Pos res is pos overflow. */
4016 else if (!sBit1
&& !sBit2
)
4018 /* Pos+Neg or Neg+Pos take the sign of the result. */
4028 /* Shift up now after overflow detection. */
4036 STORE (DREG (dst0
), REG_H_L (res
<< 16, DREG (dst0
)));
4038 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), res
));
4040 SET_ASTATREG (az
, res
== 0);
4041 SET_ASTATREG (an
, res
& 0x8000);
4042 SET_ASTATREG (v
, ovX
);
4044 SET_ASTATREG (vs
, ovX
);
4046 else if ((aop
== 2 || aop
== 3) && aopcde
== 5)
4048 bs32 val0
= DREG (src0
);
4049 bs32 val1
= DREG (src1
);
4052 TRACE_INSN (cpu
, "R%i.%s = R%i %s R%i (RND20)", dst0
, HL
? "L" : "H",
4053 src0
, aop
& 0x1 ? "-" : "+", src1
);
4055 /* If subtract, just invert and add one. */
4059 res
= (val0
>> 4) + (val1
>> 4) + (((val0
& 0xf) + (val1
& 0xf)) >> 4);
4061 /* Don't sign extend during the shift. */
4062 res
= ((bu32
)res
>> 16);
4064 /* Don't worry about overflows, since we are shifting right. */
4067 STORE (DREG (dst0
), REG_H_L (res
<< 16, DREG (dst0
)));
4069 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), res
));
4071 SET_ASTATREG (az
, res
== 0);
4072 SET_ASTATREG (an
, res
& 0x8000);
4073 SET_ASTATREG (v
, 0);
4075 else if (aopcde
== 2 || aopcde
== 3)
4077 bu32 s1
, s2
, val
, ac0_i
= 0, v_i
= 0;
4079 TRACE_INSN (cpu
, "R%i.%c = R%i.%c %c R%i.%c%s;",
4080 dst0
, HL
? 'H' : 'L',
4081 src0
, aop
& 2 ? 'H' : 'L',
4082 aopcde
== 2 ? '+' : '-',
4083 src1
, aop
& 1 ? 'H' : 'L',
4094 val
= add16 (cpu
, s1
, s2
, &ac0_i
, &v_i
, 0, 0, s
, 0);
4096 val
= sub16 (cpu
, s1
, s2
, &ac0_i
, &v_i
, 0, 0, s
, 0);
4098 SET_ASTATREG (ac0
, ac0_i
);
4099 SET_ASTATREG (v
, v_i
);
4101 SET_DREG_H (dst0
, val
<< 16);
4103 SET_DREG_L (dst0
, val
);
4105 SET_ASTATREG (an
, val
& 0x8000);
4108 else if ((aop
== 0 || aop
== 2) && aopcde
== 9 && s
== 1)
4111 TRACE_INSN (cpu
, "A%i = R%i;", a
, src0
);
4112 SET_AREG32 (a
, DREG (src0
));
4114 else if ((aop
== 1 || aop
== 3) && aopcde
== 9 && s
== 0)
4117 TRACE_INSN (cpu
, "A%i.X = R%i.L;", a
, src0
);
4118 SET_AXREG (a
, (bs8
)DREG (src0
));
4120 else if (aop
== 3 && aopcde
== 11 && (s
== 0 || s
== 1))
4122 bu64 acc0
= get_extended_acc (cpu
, 0);
4123 bu64 acc1
= get_extended_acc (cpu
, 1);
4124 bu32 carry
= (bu40
)acc1
< (bu40
)acc0
;
4127 TRACE_INSN (cpu
, "A0 -= A1%s;", s
? " (W32)" : "");
4130 if ((bs64
)acc0
< -0x8000000000ll
)
4131 acc0
= -0x8000000000ull
, sat
= 1;
4132 else if ((bs64
)acc0
>= 0x7fffffffffll
)
4133 acc0
= 0x7fffffffffull
, sat
= 1;
4137 /* A0 -= A1 (W32) */
4138 if (acc0
& (bu64
)0x8000000000ll
)
4139 acc0
&= 0x80ffffffffll
, sat
= 1;
4141 acc0
&= 0xffffffffll
;
4143 STORE (AXREG (0), (acc0
>> 32) & 0xff);
4144 STORE (AWREG (0), acc0
& 0xffffffff);
4145 STORE (ASTATREG (az
), acc0
== 0);
4146 STORE (ASTATREG (an
), !!(acc0
& (bu64
)0x8000000000ll
));
4147 STORE (ASTATREG (ac0
), carry
);
4148 STORE (ASTATREG (ac0_copy
), carry
);
4149 STORE (ASTATREG (av0
), sat
);
4151 STORE (ASTATREG (av0s
), sat
);
4153 else if ((aop
== 0 || aop
== 1) && aopcde
== 22)
4155 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4157 const char * const opts
[] = { "rndl", "rndh", "tl", "th" };
4159 TRACE_INSN (cpu
, "R%i = BYTEOP2P (R%i:%i, R%i:%i) (%s%s);", dst0
,
4160 src0
+ 1, src0
, src1
+ 1, src1
, opts
[HL
+ (aop
<< 1)],
4164 illegal_instruction_combination (cpu
);
4167 s0H
= DREG (src0
+ 1);
4169 s1H
= DREG (src1
+ 1);
4172 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4173 s1
= algn (s1H
, s1L
, IREG (0) & 3);
4177 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4178 s1
= algn (s1L
, s1H
, IREG (0) & 3);
4182 tmp0
= ((((s1
>> 8) & 0xff) + ((s1
>> 0) & 0xff) +
4183 ((s0
>> 8) & 0xff) + ((s0
>> 0) & 0xff) + i
) >> 2) & 0xff;
4184 tmp1
= ((((s1
>> 24) & 0xff) + ((s1
>> 16) & 0xff) +
4185 ((s0
>> 24) & 0xff) + ((s0
>> 16) & 0xff) + i
) >> 2) & 0xff;
4186 SET_DREG (dst0
, (tmp1
<< (16 + (HL
* 8))) | (tmp0
<< (HL
* 8)));
4188 else if ((aop
== 0 || aop
== 1) && s
== 0 && aopcde
== 8)
4190 TRACE_INSN (cpu
, "A%i = 0;", aop
);
4193 else if (aop
== 2 && s
== 0 && aopcde
== 8)
4195 TRACE_INSN (cpu
, "A1 = A0 = 0;");
4199 else if ((aop
== 0 || aop
== 1 || aop
== 2) && s
== 1 && aopcde
== 8)
4201 bs40 acc0
= get_extended_acc (cpu
, 0);
4202 bs40 acc1
= get_extended_acc (cpu
, 1);
4205 if (aop
== 0 || aop
== 1)
4206 TRACE_INSN (cpu
, "A%i = A%i (S);", aop
, aop
);
4208 TRACE_INSN (cpu
, "A1 = A1 (S), A0 = A0 (S);");
4210 if (aop
== 0 || aop
== 2)
4213 acc0
= saturate_s32 (acc0
, &sat
);
4214 acc0
|= -(acc0
& 0x80000000ull
);
4215 SET_AXREG (0, (acc0
>> 31) & 0xFF);
4216 SET_AWREG (0, acc0
& 0xFFFFFFFF);
4217 SET_ASTATREG (av0
, sat
);
4219 SET_ASTATREG (av0s
, sat
);
4224 if (aop
== 1 || aop
== 2)
4227 acc1
= saturate_s32 (acc1
, &sat
);
4228 acc1
|= -(acc1
& 0x80000000ull
);
4229 SET_AXREG (1, (acc1
>> 31) & 0xFF);
4230 SET_AWREG (1, acc1
& 0xFFFFFFFF);
4231 SET_ASTATREG (av1
, sat
);
4233 SET_ASTATREG (av1s
, sat
);
4238 SET_ASTATREG (az
, (acc0
== 0) || (acc1
== 0));
4239 SET_ASTATREG (an
, ((acc0
>> 31) & 1) || ((acc1
>> 31) & 1));
4241 else if (aop
== 3 && (s
== 0 || s
== 1) && aopcde
== 8)
4243 TRACE_INSN (cpu
, "A%i = A%i;", s
, !s
);
4244 SET_AXREG (s
, AXREG (!s
));
4245 SET_AWREG (s
, AWREG (!s
));
4247 else if (aop
== 3 && HL
== 0 && aopcde
== 16)
4252 TRACE_INSN (cpu
, "A1 = ABS A1 , A0 = ABS A0;");
4255 for (i
= 0; i
< 2; ++i
)
4258 bs40 acc
= get_extended_acc (cpu
, i
);
4262 av
= acc
== ((bs40
)1 << 39);
4264 acc
= ((bs40
)1 << 39) - 1;
4267 SET_ASTATREG (av
[i
], av
);
4269 SET_ASTATREG (avs
[i
], av
);
4272 SET_ASTATREG (az
, az
);
4273 SET_ASTATREG (an
, 0);
4275 else if (aop
== 0 && aopcde
== 23)
4277 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4280 TRACE_INSN (cpu
, "R%i = BYTEOP3P (R%i:%i, R%i:%i) (%s%s);", dst0
,
4281 src0
+ 1, src0
, src1
+ 1, src1
, HL
? "HI" : "LO",
4285 illegal_instruction_combination (cpu
);
4288 s0H
= DREG (src0
+ 1);
4290 s1H
= DREG (src1
+ 1);
4293 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4294 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4298 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4299 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4302 tmp0
= (bs32
)(bs16
)(s0
>> 0) + ((s1
>> ( 0 + (8 * !HL
))) & 0xff);
4303 tmp1
= (bs32
)(bs16
)(s0
>> 16) + ((s1
>> (16 + (8 * !HL
))) & 0xff);
4304 SET_DREG (dst0
, (CLAMP (tmp0
, 0, 255) << ( 0 + (8 * HL
))) |
4305 (CLAMP (tmp1
, 0, 255) << (16 + (8 * HL
))));
4307 else if ((aop
== 0 || aop
== 1) && aopcde
== 16)
4312 TRACE_INSN (cpu
, "A%i = ABS A%i;", HL
, aop
);
4314 acc
= get_extended_acc (cpu
, aop
);
4317 av
= acc
== ((bs40
)1 << 39);
4319 acc
= ((bs40
)1 << 39) - 1;
4322 SET_ASTATREG (av
[HL
], av
);
4324 SET_ASTATREG (avs
[HL
], av
);
4325 SET_ASTATREG (az
, acc
== 0);
4326 SET_ASTATREG (an
, 0);
4328 else if (aop
== 3 && aopcde
== 12)
4330 bs32 res
= DREG (src0
);
4332 bool sBit_a
, sBit_b
;
4334 TRACE_INSN (cpu
, "R%i.%s = R%i (RND);", dst0
, HL
== 0 ? "L" : "H", src0
);
4335 TRACE_DECODE (cpu
, "R%i.%s = R%i:%#x (RND);", dst0
,
4336 HL
== 0 ? "L" : "H", src0
, res
);
4338 sBit_b
= !!(res
& 0x80000000);
4341 sBit_a
= !!(res
& 0x80000000);
4343 /* Overflow if the sign bit changed when we rounded. */
4344 if ((res
>> 16) && (sBit_b
!= sBit_a
))
4359 SET_DREG (dst0
, REG_H_L (DREG (dst0
), res
));
4361 SET_DREG (dst0
, REG_H_L (res
<< 16, DREG (dst0
)));
4363 SET_ASTATREG (az
, res
== 0);
4364 SET_ASTATREG (an
, res
< 0);
4365 SET_ASTATREG (v
, ovX
);
4367 SET_ASTATREG (vs
, ovX
);
4369 else if (aop
== 3 && HL
== 0 && aopcde
== 15)
4371 bu32 hi
= (-(bs16
)(DREG (src0
) >> 16)) << 16;
4372 bu32 lo
= (-(bs16
)(DREG (src0
) & 0xFFFF)) & 0xFFFF;
4375 TRACE_INSN (cpu
, "R%i = -R%i (V);", dst0
, src0
);
4379 if (hi
== 0x80000000)
4395 SET_DREG (dst0
, hi
| lo
);
4397 SET_ASTATREG (v
, v
);
4399 SET_ASTATREG (vs
, 1);
4400 SET_ASTATREG (ac0
, ac0
);
4401 SET_ASTATREG (ac1
, ac1
);
4402 setflags_nz_2x16 (cpu
, DREG (dst0
));
4404 else if (aop
== 3 && HL
== 0 && aopcde
== 14)
4406 TRACE_INSN (cpu
, "A1 = - A1 , A0 = - A0;");
4408 SET_AREG (0, saturate_s40 (-get_extended_acc (cpu
, 0)));
4409 SET_AREG (1, saturate_s40 (-get_extended_acc (cpu
, 1)));
4410 /* XXX: what ASTAT flags need updating ? */
4412 else if ((aop
== 0 || aop
== 1) && (HL
== 0 || HL
== 1) && aopcde
== 14)
4414 bs40 src_acc
= get_extended_acc (cpu
, aop
);
4416 TRACE_INSN (cpu
, "A%i = - A%i;", HL
, aop
);
4418 SET_AREG (HL
, saturate_s40 (-src_acc
));
4420 SET_ASTATREG (az
, AWREG (HL
) == 0 && AXREG (HL
) == 0);
4421 SET_ASTATREG (an
, AXREG (HL
) >> 7);
4422 SET_ASTATREG (ac0
, src_acc
== 0);
4425 SET_ASTATREG (av0
, src_acc
< 0);
4427 SET_ASTATREG (av0s
, 1);
4431 SET_ASTATREG (av1
, src_acc
< 0);
4433 SET_ASTATREG (av1s
, 1);
4436 else if (aop
== 0 && aopcde
== 12)
4438 bs16 tmp0_hi
= DREG (src0
) >> 16;
4439 bs16 tmp0_lo
= DREG (src0
);
4440 bs16 tmp1_hi
= DREG (src1
) >> 16;
4441 bs16 tmp1_lo
= DREG (src1
);
4443 TRACE_INSN (cpu
, "R%i.L = R%i.H = SIGN(R%i.H) * R%i.H + SIGN(R%i.L) * R%i.L;",
4444 dst0
, dst0
, src0
, src1
, src0
, src1
);
4446 if ((tmp0_hi
>> 15) & 1)
4447 tmp1_hi
= ~tmp1_hi
+ 1;
4449 if ((tmp0_lo
>> 15) & 1)
4450 tmp1_lo
= ~tmp1_lo
+ 1;
4452 tmp1_hi
= tmp1_hi
+ tmp1_lo
;
4454 STORE (DREG (dst0
), REG_H_L (tmp1_hi
<< 16, tmp1_hi
));
4456 else if (aopcde
== 0)
4458 bu32 s0
= DREG (src0
);
4459 bu32 s1
= DREG (src1
);
4460 bu32 s0h
= s0
>> 16;
4461 bu32 s0l
= s0
& 0xFFFF;
4462 bu32 s1h
= s1
>> 16;
4463 bu32 s1l
= s1
& 0xFFFF;
4465 bu32 ac1_i
= 0, ac0_i
= 0, v_i
= 0, z_i
= 0, n_i
= 0;
4467 TRACE_INSN (cpu
, "R%i = R%i %c|%c R%i%s;", dst0
, src0
,
4468 (aop
& 2) ? '-' : '+', (aop
& 1) ? '-' : '+', src1
,
4471 t0
= sub16 (cpu
, s0h
, s1h
, &ac1_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4473 t0
= add16 (cpu
, s0h
, s1h
, &ac1_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4476 t1
= sub16 (cpu
, s0l
, s1l
, &ac0_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4478 t1
= add16 (cpu
, s0l
, s1l
, &ac0_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4480 SET_ASTATREG (ac1
, ac1_i
);
4481 SET_ASTATREG (ac0
, ac0_i
);
4482 SET_ASTATREG (az
, z_i
);
4483 SET_ASTATREG (an
, n_i
);
4484 SET_ASTATREG (v
, v_i
);
4486 SET_ASTATREG (vs
, v_i
);
4491 SET_DREG (dst0
, (t1
<< 16) | t0
);
4493 SET_DREG (dst0
, (t0
<< 16) | t1
);
4495 else if (aop
== 1 && aopcde
== 12)
4497 bu32 val0
= ((AWREG (0) >> 16) + (AWREG (0) & 0xFFFF)) & 0xFFFF;
4498 bu32 val1
= ((AWREG (1) >> 16) + (AWREG (1) & 0xFFFF)) & 0xFFFF;
4500 TRACE_INSN (cpu
, "R%i = A1.L + A1.H, R%i = A0.L + A0.H;", dst1
, dst0
);
4503 illegal_instruction_combination (cpu
);
4511 SET_DREG (dst0
, val0
);
4512 SET_DREG (dst1
, val1
);
4515 else if (aopcde
== 1)
4519 bu16 s0L
= DREG (src0
);
4520 bu16 s0H
= DREG (src0
) >> 16;
4521 bu16 s1L
= DREG (src1
);
4522 bu16 s1H
= DREG (src1
) >> 16;
4523 bu32 v_i
= 0, n_i
= 0, z_i
= 0;
4525 TRACE_INSN (cpu
, "R%i = R%i %s R%i, R%i = R%i %s R%i%s;",
4526 dst1
, src0
, HL
? "+|-" : "+|+", src1
,
4527 dst0
, src0
, HL
? "-|+" : "-|-", src1
,
4528 amod0amod2 (s
, x
, aop
));
4531 illegal_instruction_combination (cpu
);
4535 x0
= add16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4536 x1
= add16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4537 d1
= (x0
<< 16) | x1
;
4539 x0
= sub16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4540 x1
= sub16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4542 d0
= (x0
<< 16) | x1
;
4544 d0
= (x1
<< 16) | x0
;
4548 x0
= add16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4549 x1
= sub16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4550 d1
= (x0
<< 16) | x1
;
4552 x0
= sub16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4553 x1
= add16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4555 d0
= (x0
<< 16) | x1
;
4557 d0
= (x1
<< 16) | x0
;
4559 SET_ASTATREG (az
, z_i
);
4560 SET_ASTATREG (an
, n_i
);
4561 SET_ASTATREG (v
, v_i
);
4563 SET_ASTATREG (vs
, v_i
);
4565 STORE (DREG (dst0
), d0
);
4566 STORE (DREG (dst1
), d1
);
4568 else if ((aop
== 0 || aop
== 1 || aop
== 2) && aopcde
== 11)
4570 bs40 acc0
= get_extended_acc (cpu
, 0);
4571 bs40 acc1
= get_extended_acc (cpu
, 1);
4572 bu32 v
, dreg
, sat
= 0;
4573 bu32 carry
= !!((bu40
)~acc1
< (bu40
)acc0
);
4576 TRACE_INSN (cpu
, "R%i = (A0 += A1);", dst0
);
4578 TRACE_INSN (cpu
, "R%i.%c = (A0 += A1);", dst0
, HL
? 'H' : 'L');
4580 TRACE_INSN (cpu
, "A0 += A1%s;", s
? " (W32)" : "");
4583 acc0
= saturate_s40_astat (acc0
, &v
);
4585 if (aop
== 2 && s
== 1) /* A0 += A1 (W32) */
4587 if (acc0
& (bs40
)0x8000000000ll
)
4588 acc0
&= 0x80ffffffffll
;
4590 acc0
&= 0xffffffffll
;
4593 STORE (AXREG (0), acc0
>> 32);
4594 STORE (AWREG (0), acc0
);
4595 SET_ASTATREG (av0
, v
&& acc1
);
4597 SET_ASTATREG (av0s
, v
);
4599 if (aop
== 0 || aop
== 1)
4601 if (aop
) /* Dregs_lo = A0 += A1 */
4603 dreg
= saturate_s32 (rnd16 (acc0
) << 16, &sat
);
4605 STORE (DREG (dst0
), REG_H_L (dreg
, DREG (dst0
)));
4607 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), dreg
>> 16));
4609 else /* Dregs = A0 += A1 */
4611 dreg
= saturate_s32 (acc0
, &sat
);
4612 STORE (DREG (dst0
), dreg
);
4615 STORE (ASTATREG (az
), dreg
== 0);
4616 STORE (ASTATREG (an
), !!(dreg
& 0x80000000));
4617 STORE (ASTATREG (ac0
), carry
);
4618 STORE (ASTATREG (ac0_copy
), carry
);
4619 STORE (ASTATREG (v
), sat
);
4620 STORE (ASTATREG (v_copy
), sat
);
4622 STORE (ASTATREG (vs
), sat
);
4626 STORE (ASTATREG (az
), acc0
== 0);
4627 STORE (ASTATREG (an
), !!(acc0
& 0x8000000000ull
));
4628 STORE (ASTATREG (ac0
), carry
);
4629 STORE (ASTATREG (ac0_copy
), carry
);
4632 else if ((aop
== 0 || aop
== 1) && aopcde
== 10)
4634 TRACE_INSN (cpu
, "R%i.L = A%i.X;", dst0
, aop
);
4635 SET_DREG_L (dst0
, (bs8
)AXREG (aop
));
4637 else if (aop
== 0 && aopcde
== 4)
4639 TRACE_INSN (cpu
, "R%i = R%i + R%i%s;", dst0
, src0
, src1
, amod1 (s
, x
));
4640 SET_DREG (dst0
, add32 (cpu
, DREG (src0
), DREG (src1
), 1, s
));
4642 else if (aop
== 1 && aopcde
== 4)
4644 TRACE_INSN (cpu
, "R%i = R%i - R%i%s;", dst0
, src0
, src1
, amod1 (s
, x
));
4645 SET_DREG (dst0
, sub32 (cpu
, DREG (src0
), DREG (src1
), 1, s
, 0));
4647 else if (aop
== 2 && aopcde
== 4)
4649 TRACE_INSN (cpu
, "R%i = R%i + R%i, R%i = R%i - R%i%s;",
4650 dst1
, src0
, src1
, dst0
, src0
, src1
, amod1 (s
, x
));
4653 illegal_instruction_combination (cpu
);
4655 STORE (DREG (dst1
), add32 (cpu
, DREG (src0
), DREG (src1
), 1, s
));
4656 STORE (DREG (dst0
), sub32 (cpu
, DREG (src0
), DREG (src1
), 1, s
, 1));
4658 else if ((aop
== 0 || aop
== 1) && aopcde
== 17)
4660 bs40 acc0
= get_extended_acc (cpu
, 0);
4661 bs40 acc1
= get_extended_acc (cpu
, 1);
4662 bs40 val0
, val1
, sval0
, sval1
;
4665 TRACE_INSN (cpu
, "R%i = A%i + A%i, R%i = A%i - A%i%s",
4666 dst1
, !aop
, aop
, dst0
, !aop
, aop
, amod1 (s
, x
));
4667 TRACE_DECODE (cpu
, "R%i = A%i:%#"PRIx64
" + A%i:%#"PRIx64
", "
4668 "R%i = A%i:%#"PRIx64
" - A%i:%#"PRIx64
"%s",
4669 dst1
, !aop
, aop
? acc0
: acc1
, aop
, aop
? acc1
: acc0
,
4670 dst0
, !aop
, aop
? acc0
: acc1
, aop
, aop
? acc1
: acc0
,
4674 illegal_instruction_combination (cpu
);
4682 sval0
= saturate_s32 (val0
, &sat
);
4684 sval1
= saturate_s32 (val1
, &sat
);
4692 STORE (DREG (dst0
), val0
);
4693 STORE (DREG (dst1
), val1
);
4694 SET_ASTATREG (v
, sat_i
);
4696 SET_ASTATREG (vs
, sat_i
);
4697 SET_ASTATREG (an
, val0
& 0x80000000 || val1
& 0x80000000);
4698 SET_ASTATREG (az
, val0
== 0 || val1
== 0);
4699 SET_ASTATREG (ac1
, (bu40
)~acc0
< (bu40
)acc1
);
4701 SET_ASTATREG (ac0
, !!((bu40
)acc1
<= (bu40
)acc0
));
4703 SET_ASTATREG (ac0
, !!((bu40
)acc0
<= (bu40
)acc1
));
4705 else if (aop
== 0 && aopcde
== 18)
4707 bu40 acc0
= get_extended_acc (cpu
, 0);
4708 bu40 acc1
= get_extended_acc (cpu
, 1);
4709 bu32 s0L
= DREG (src0
);
4710 bu32 s0H
= DREG (src0
+ 1);
4711 bu32 s1L
= DREG (src1
);
4712 bu32 s1H
= DREG (src1
+ 1);
4714 bs16 tmp0
, tmp1
, tmp2
, tmp3
;
4716 /* This instruction is only defined for register pairs R1:0 and R3:2. */
4717 if (!((src0
== 0 || src0
== 2) && (src1
== 0 || src1
== 2)))
4718 illegal_instruction (cpu
);
4720 TRACE_INSN (cpu
, "SAA (R%i:%i, R%i:%i)%s", src0
+ 1, src0
,
4721 src1
+ 1, src1
, s
? " (R)" :"");
4723 /* Bit s determines the order of the two registers from a pair:
4724 if s=0 the low-order bytes come from the low reg in the pair,
4725 and if s=1 the low-order bytes come from the high reg. */
4729 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4730 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4734 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4735 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4738 /* Find the absolute difference between pairs, make it
4739 absolute, then add it to the existing accumulator half. */
4741 tmp0
= ((s0
<< 24) >> 24) - ((s1
<< 24) >> 24);
4742 tmp1
= ((s0
<< 16) >> 24) - ((s1
<< 16) >> 24);
4743 tmp2
= ((s0
<< 8) >> 24) - ((s1
<< 8) >> 24);
4744 tmp3
= ((s0
<< 0) >> 24) - ((s1
<< 0) >> 24);
4746 tmp0
= (tmp0
< 0) ? -tmp0
: tmp0
;
4747 tmp1
= (tmp1
< 0) ? -tmp1
: tmp1
;
4748 tmp2
= (tmp2
< 0) ? -tmp2
: tmp2
;
4749 tmp3
= (tmp3
< 0) ? -tmp3
: tmp3
;
4751 s0L
= saturate_u16 ((bu32
)tmp0
+ ((acc0
>> 0) & 0xffff), 0);
4752 s0H
= saturate_u16 ((bu32
)tmp1
+ ((acc0
>> 16) & 0xffff), 0);
4753 s1L
= saturate_u16 ((bu32
)tmp2
+ ((acc1
>> 0) & 0xffff), 0);
4754 s1H
= saturate_u16 ((bu32
)tmp3
+ ((acc1
>> 16) & 0xffff), 0);
4756 STORE (AWREG (0), (s0H
<< 16) | (s0L
& 0xFFFF));
4757 STORE (AXREG (0), 0);
4758 STORE (AWREG (1), (s1H
<< 16) | (s1L
& 0xFFFF));
4759 STORE (AXREG (1), 0);
4761 else if (aop
== 3 && aopcde
== 18)
4763 TRACE_INSN (cpu
, "DISALGNEXCPT");
4766 else if ((aop
== 0 || aop
== 1) && aopcde
== 20)
4768 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4769 const char * const opts
[] = { "", " (R)", " (T)", " (T, R)" };
4771 TRACE_INSN (cpu
, "R%i = BYTEOP1P (R%i:%i, R%i:%i)%s;", dst0
,
4772 src0
+ 1, src0
, src1
+ 1, src1
, opts
[s
+ (aop
<< 1)]);
4775 illegal_instruction_combination (cpu
);
4778 s0H
= DREG (src0
+ 1);
4780 s1H
= DREG (src1
+ 1);
4783 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4784 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4788 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4789 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4793 (((((s0
>> 0) & 0xff) + ((s1
>> 0) & 0xff) + !aop
) >> 1) << 0) |
4794 (((((s0
>> 8) & 0xff) + ((s1
>> 8) & 0xff) + !aop
) >> 1) << 8) |
4795 (((((s0
>> 16) & 0xff) + ((s1
>> 16) & 0xff) + !aop
) >> 1) << 16) |
4796 (((((s0
>> 24) & 0xff) + ((s1
>> 24) & 0xff) + !aop
) >> 1) << 24));
4798 else if (aop
== 0 && aopcde
== 21)
4800 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4802 TRACE_INSN (cpu
, "(R%i, R%i) = BYTEOP16P (R%i:%i, R%i:%i)%s;", dst1
, dst0
,
4803 src0
+ 1, src0
, src1
+ 1, src1
, s
? " (R)" : "");
4806 illegal_instruction_combination (cpu
);
4809 s0H
= DREG (src0
+ 1);
4811 s1H
= DREG (src1
+ 1);
4814 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4815 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4819 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4820 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4824 ((((s0
>> 0) & 0xff) + ((s1
>> 0) & 0xff)) << 0) |
4825 ((((s0
>> 8) & 0xff) + ((s1
>> 8) & 0xff)) << 16));
4827 ((((s0
>> 16) & 0xff) + ((s1
>> 16) & 0xff)) << 0) |
4828 ((((s0
>> 24) & 0xff) + ((s1
>> 24) & 0xff)) << 16));
4830 else if (aop
== 1 && aopcde
== 21)
4832 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4834 TRACE_INSN (cpu
, "(R%i, R%i) = BYTEOP16M (R%i:%i, R%i:%i)%s;", dst1
, dst0
,
4835 src0
+ 1, src0
, src1
+ 1, src1
, s
? " (R)" : "");
4838 illegal_instruction_combination (cpu
);
4841 s0H
= DREG (src0
+ 1);
4843 s1H
= DREG (src1
+ 1);
4846 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4847 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4851 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4852 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4856 (((((s0
>> 0) & 0xff) - ((s1
>> 0) & 0xff)) << 0) & 0xffff) |
4857 (((((s0
>> 8) & 0xff) - ((s1
>> 8) & 0xff)) << 16)));
4859 (((((s0
>> 16) & 0xff) - ((s1
>> 16) & 0xff)) << 0) & 0xffff) |
4860 (((((s0
>> 24) & 0xff) - ((s1
>> 24) & 0xff)) << 16)));
4862 else if (aop
== 1 && aopcde
== 7)
4864 TRACE_INSN (cpu
, "R%i = MIN (R%i, R%i);", dst0
, src0
, src1
);
4865 SET_DREG (dst0
, min32 (cpu
, DREG (src0
), DREG (src1
)));
4867 else if (aop
== 0 && aopcde
== 7)
4869 TRACE_INSN (cpu
, "R%i = MAX (R%i, R%i);", dst0
, src0
, src1
);
4870 SET_DREG (dst0
, max32 (cpu
, DREG (src0
), DREG (src1
)));
4872 else if (aop
== 2 && aopcde
== 7)
4874 bu32 val
= DREG (src0
);
4877 TRACE_INSN (cpu
, "R%i = ABS R%i;", dst0
, src0
);
4881 v
= (val
== 0x80000000);
4884 SET_DREG (dst0
, val
);
4886 SET_ASTATREG (v
, v
);
4888 SET_ASTATREG (vs
, 1);
4889 setflags_nz (cpu
, val
);
4891 else if (aop
== 3 && aopcde
== 7)
4893 bu32 val
= DREG (src0
);
4895 TRACE_INSN (cpu
, "R%i = - R%i %s;", dst0
, src0
, amod1 (s
, 0));
4897 if (s
&& val
== 0x80000000)
4900 SET_ASTATREG (v
, 1);
4901 SET_ASTATREG (vs
, 1);
4903 else if (val
== 0x80000000)
4907 SET_DREG (dst0
, val
);
4909 SET_ASTATREG (az
, val
== 0);
4910 SET_ASTATREG (an
, val
& 0x80000000);
4912 else if (aop
== 2 && aopcde
== 6)
4914 bu32 in
= DREG (src0
);
4915 bu32 hi
= (in
& 0x80000000 ? (bu32
)-(bs16
)(in
>> 16) : in
>> 16) << 16;
4916 bu32 lo
= (in
& 0x8000 ? (bu32
)-(bs16
)(in
& 0xFFFF) : in
) & 0xFFFF;
4919 TRACE_INSN (cpu
, "R%i = ABS R%i (V);", dst0
, src0
);
4922 if (hi
== 0x80000000)
4932 SET_DREG (dst0
, hi
| lo
);
4934 SET_ASTATREG (v
, v
);
4936 SET_ASTATREG (vs
, 1);
4937 setflags_nz_2x16 (cpu
, DREG (dst0
));
4939 else if (aop
== 1 && aopcde
== 6)
4941 TRACE_INSN (cpu
, "R%i = MIN (R%i, R%i) (V);", dst0
, src0
, src1
);
4942 SET_DREG (dst0
, min2x16 (cpu
, DREG (src0
), DREG (src1
)));
4944 else if (aop
== 0 && aopcde
== 6)
4946 TRACE_INSN (cpu
, "R%i = MAX (R%i, R%i) (V);", dst0
, src0
, src1
);
4947 SET_DREG (dst0
, max2x16 (cpu
, DREG (src0
), DREG (src1
)));
4949 else if (aop
== 0 && aopcde
== 24)
4951 TRACE_INSN (cpu
, "R%i = BYTEPACK (R%i, R%i);", dst0
, src0
, src1
);
4953 (((DREG (src0
) >> 0) & 0xff) << 0) |
4954 (((DREG (src0
) >> 16) & 0xff) << 8) |
4955 (((DREG (src1
) >> 0) & 0xff) << 16) |
4956 (((DREG (src1
) >> 16) & 0xff) << 24));
4958 else if (aop
== 1 && aopcde
== 24)
4962 bu8 bytea
, byteb
, bytec
, byted
;
4964 TRACE_INSN (cpu
, "(R%i, R%i) = BYTEUNPACK R%i:%i%s;",
4965 dst1
, dst0
, src0
+ 1, src0
, s
? " (R)" : "");
4968 illegal_instruction_combination (cpu
);
4970 order
= IREG (0) & 0x3;
4972 hi
= src0
, lo
= src0
+ 1;
4974 hi
= src0
+ 1, lo
= src0
;
4975 comb_src
= (((bu64
)DREG (hi
)) << 32) | DREG (lo
);
4976 bytea
= (comb_src
>> (0 + 8 * order
));
4977 byteb
= (comb_src
>> (8 + 8 * order
));
4978 bytec
= (comb_src
>> (16 + 8 * order
));
4979 byted
= (comb_src
>> (24 + 8 * order
));
4980 SET_DREG (dst0
, bytea
| ((bu32
)byteb
<< 16));
4981 SET_DREG (dst1
, bytec
| ((bu32
)byted
<< 16));
4983 else if (aopcde
== 13)
4985 const char *searchmodes
[] = { "GT", "GE", "LT", "LE" };
4987 bs16 a0_lo
, a1_lo
, src_hi
, src_lo
;
4989 TRACE_INSN (cpu
, "(R%i, R%i) = SEARCH R%i (%s);",
4990 dst1
, dst0
, src0
, searchmodes
[aop
]);
4993 illegal_instruction_combination (cpu
);
4995 up_hi
= up_lo
= false;
4998 src_lo
= DREG (src0
);
4999 src_hi
= DREG (src0
) >> 16;
5004 up_hi
= (src_hi
> a1_lo
);
5005 up_lo
= (src_lo
> a0_lo
);
5008 up_hi
= (src_hi
>= a1_lo
);
5009 up_lo
= (src_lo
>= a0_lo
);
5012 up_hi
= (src_hi
< a1_lo
);
5013 up_lo
= (src_lo
< a0_lo
);
5016 up_hi
= (src_hi
<= a1_lo
);
5017 up_lo
= (src_lo
<= a0_lo
);
5023 SET_AREG (1, src_hi
);
5024 SET_DREG (dst1
, PREG (0));
5028 SET_AREG (0, src_lo
);
5029 SET_DREG (dst0
, PREG (0));
5033 illegal_instruction (cpu
);
5037 decode_dsp32shift_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
5040 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5041 | 1 | 1 | 0 | 0 |.M.| 1 | 1 | 0 | 0 | - | - |.sopcde............|
5042 |.sop...|.HLs...|.dst0......| - | - | - |.src0......|.src1......|
5043 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5044 int HLs
= ((iw1
>> DSP32Shift_HLs_bits
) & DSP32Shift_HLs_mask
);
5045 int sop
= ((iw1
>> DSP32Shift_sop_bits
) & DSP32Shift_sop_mask
);
5046 int src0
= ((iw1
>> DSP32Shift_src0_bits
) & DSP32Shift_src0_mask
);
5047 int src1
= ((iw1
>> DSP32Shift_src1_bits
) & DSP32Shift_src1_mask
);
5048 int dst0
= ((iw1
>> DSP32Shift_dst0_bits
) & DSP32Shift_dst0_mask
);
5049 int sopcde
= ((iw0
>> (DSP32Shift_sopcde_bits
- 16)) & DSP32Shift_sopcde_mask
);
5050 int M
= ((iw0
>> (DSP32Shift_M_bits
- 16)) & DSP32Shift_M_mask
);
5052 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32shift
);
5053 TRACE_EXTRACT (cpu
, "%s: M:%i sopcde:%i sop:%i HLs:%i dst0:%i src0:%i src1:%i",
5054 __func__
, M
, sopcde
, sop
, HLs
, dst0
, src0
, src1
);
5056 if ((sop
== 0 || sop
== 1) && sopcde
== 0)
5059 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5061 TRACE_INSN (cpu
, "R%i.%c = ASHIFT R%i.%c BY R%i.L%s;",
5062 dst0
, HLs
< 2 ? 'L' : 'H',
5063 src1
, HLs
& 1 ? 'H' : 'L',
5064 src0
, sop
== 1 ? " (S)" : "");
5067 val
= (bu16
)(DREG (src1
) & 0xFFFF);
5069 val
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5071 /* Positive shift magnitudes produce Logical Left shifts.
5072 Negative shift magnitudes produce Arithmetic Right shifts. */
5074 val
= ashiftrt (cpu
, val
, -shft
, 16);
5076 val
= lshift (cpu
, val
, shft
, 16, sop
== 1);
5079 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), val
));
5081 STORE (DREG (dst0
), REG_H_L (val
<< 16, DREG (dst0
)));
5083 else if (sop
== 2 && sopcde
== 0)
5085 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5088 TRACE_INSN (cpu
, "R%i.%c = LSHIFT R%i.%c BY R%i.L;",
5089 dst0
, HLs
< 2 ? 'L' : 'H',
5090 src1
, HLs
& 1 ? 'H' : 'L', src0
);
5093 val
= (bu16
)(DREG (src1
) & 0xFFFF);
5095 val
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5098 val
= val
>> (-1 * shft
);
5103 SET_DREG (dst0
, REG_H_L (DREG (dst0
), val
));
5105 SET_DREG (dst0
, REG_H_L (val
<< 16, DREG (dst0
)));
5107 SET_ASTATREG (az
, !((val
& 0xFFFF0000) == 0) || ((val
& 0xFFFF) == 0));
5108 SET_ASTATREG (an
, (!!(val
& 0x80000000)) ^ (!!(val
& 0x8000)));
5109 SET_ASTATREG (v
, 0);
5111 else if (sop
== 2 && sopcde
== 3 && (HLs
== 1 || HLs
== 0))
5113 int shift
= imm6 (DREG (src0
) & 0xFFFF);
5115 bu40 acc
= get_unextended_acc (cpu
, HLs
);
5117 TRACE_INSN (cpu
, "A%i = ROT A%i BY R%i.L;", HLs
, HLs
, src0
);
5118 TRACE_DECODE (cpu
, "A%i:%#"PRIx64
" shift:%i CC:%i", HLs
, acc
, shift
, cc
);
5120 acc
= rot40 (acc
, shift
, &cc
);
5121 SET_AREG (HLs
, acc
);
5125 else if (sop
== 0 && sopcde
== 3 && (HLs
== 0 || HLs
== 1))
5127 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5128 bu64 val
= get_extended_acc (cpu
, HLs
);
5131 TRACE_INSN (cpu
, "A%i = ASHIFT A%i BY R%i.L;", HLs
, HLs
, src0
);
5132 TRACE_DECODE (cpu
, "A%i:%#"PRIx64
" shift:%i", HLs
, val
, shft
);
5135 val
= ashiftrt (cpu
, val
, -shft
, 40);
5137 val
= lshift (cpu
, val
, shft
, 40, 0);
5139 STORE (AXREG (HLs
), (val
>> 32) & 0xff);
5140 STORE (AWREG (HLs
), (val
& 0xffffffff));
5142 else if (sop
== 1 && sopcde
== 3 && (HLs
== 0 || HLs
== 1))
5144 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5148 TRACE_INSN (cpu
, "A%i = LSHIFT A%i BY R%i.L;", HLs
, HLs
, src0
);
5149 val
= get_extended_acc (cpu
, HLs
);
5152 val
= lshiftrt (cpu
, val
, -shft
, 40);
5154 val
= lshift (cpu
, val
, shft
, 40, 0);
5156 STORE (AXREG (HLs
), (val
>> 32) & 0xff);
5157 STORE (AWREG (HLs
), (val
& 0xffffffff));
5159 else if ((sop
== 0 || sop
== 1) && sopcde
== 1)
5161 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5165 TRACE_INSN (cpu
, "R%i = ASHIFT R%i BY R%i.L (V%s);",
5166 dst0
, src1
, src0
, sop
== 1 ? ",S" : "");
5168 val0
= (bu16
)DREG (src1
) & 0xFFFF;
5169 val1
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5173 val0
= ashiftrt (cpu
, val0
, -shft
, 16);
5175 val1
= ashiftrt (cpu
, val1
, -shft
, 16);
5179 val0
= lshift (cpu
, val0
, shft
, 16, sop
== 1);
5181 val1
= lshift (cpu
, val1
, shft
, 16, sop
== 1);
5183 SET_ASTAT (ASTAT
| astat
);
5184 STORE (DREG (dst0
), (val1
<< 16) | val0
);
5186 else if ((sop
== 0 || sop
== 1 || sop
== 2) && sopcde
== 2)
5188 /* dregs = [LA]SHIFT dregs BY dregs_lo (opt_S) */
5189 /* sop == 1 : opt_S */
5190 bu32 v
= DREG (src1
);
5191 /* LSHIFT uses sign extended low 6 bits of dregs_lo. */
5192 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5194 TRACE_INSN (cpu
, "R%i = %cSHIFT R%i BY R%i.L%s;", dst0
,
5195 shft
&& sop
!= 2 ? 'A' : 'L', src1
, src0
,
5196 sop
== 1 ? " (S)" : "");
5201 STORE (DREG (dst0
), lshiftrt (cpu
, v
, -shft
, 32));
5203 STORE (DREG (dst0
), ashiftrt (cpu
, v
, -shft
, 32));
5206 STORE (DREG (dst0
), lshift (cpu
, v
, shft
, 32, sop
== 1));
5208 else if (sop
== 3 && sopcde
== 2)
5210 int shift
= imm6 (DREG (src0
) & 0xFFFF);
5211 bu32 src
= DREG (src1
);
5212 bu32 ret
, cc
= CCREG
;
5214 TRACE_INSN (cpu
, "R%i = ROT R%i BY R%i.L;", dst0
, src1
, src0
);
5215 TRACE_DECODE (cpu
, "R%i:%#x R%i:%#x shift:%i CC:%i",
5216 dst0
, DREG (dst0
), src1
, src
, shift
, cc
);
5218 ret
= rot32 (src
, shift
, &cc
);
5219 STORE (DREG (dst0
), ret
);
5223 else if (sop
== 2 && sopcde
== 1)
5225 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5229 TRACE_INSN (cpu
, "R%i = LSHIFT R%i BY R%i.L (V);", dst0
, src1
, src0
);
5231 val0
= (bu16
)DREG (src1
) & 0xFFFF;
5232 val1
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5236 val0
= lshiftrt (cpu
, val0
, -shft
, 16);
5238 val1
= lshiftrt (cpu
, val1
, -shft
, 16);
5242 val0
= lshift (cpu
, val0
, shft
, 16, 0);
5244 val1
= lshift (cpu
, val1
, shft
, 16, 0);
5246 SET_ASTAT (ASTAT
| astat
);
5247 STORE (DREG (dst0
), (val1
<< 16) | val0
);
5249 else if (sopcde
== 4)
5251 bu32 sv0
= DREG (src0
);
5252 bu32 sv1
= DREG (src1
);
5253 TRACE_INSN (cpu
, "R%i = PACK (R%i.%c, R%i.%c);", dst0
,
5254 src1
, sop
& 2 ? 'H' : 'L',
5255 src0
, sop
& 1 ? 'H' : 'L');
5260 SET_DREG (dst0
, (sv1
<< 16) | (sv0
& 0xFFFF));
5262 else if (sop
== 0 && sopcde
== 5)
5264 bu32 sv1
= DREG (src1
);
5265 TRACE_INSN (cpu
, "R%i.L = SIGNBITS R%i;", dst0
, src1
);
5266 SET_DREG_L (dst0
, signbits (sv1
, 32));
5268 else if (sop
== 1 && sopcde
== 5)
5270 bu32 sv1
= DREG (src1
);
5271 TRACE_INSN (cpu
, "R%i.L = SIGNBITS R%i.L;", dst0
, src1
);
5272 SET_DREG_L (dst0
, signbits (sv1
, 16));
5274 else if (sop
== 2 && sopcde
== 5)
5276 bu32 sv1
= DREG (src1
);
5277 TRACE_INSN (cpu
, "R%i.L = SIGNBITS R%i.H;", dst0
, src1
);
5278 SET_DREG_L (dst0
, signbits (sv1
>> 16, 16));
5280 else if ((sop
== 0 || sop
== 1) && sopcde
== 6)
5282 bu64 acc
= AXREG (sop
);
5283 TRACE_INSN (cpu
, "R%i.L = SIGNBITS A%i;", dst0
, sop
);
5286 SET_DREG_L (dst0
, signbits (acc
, 40) & 0xFFFF);
5288 else if (sop
== 3 && sopcde
== 6)
5290 bu32 v
= ones (DREG (src1
));
5291 TRACE_INSN (cpu
, "R%i.L = ONES R%i;", dst0
, src1
);
5292 SET_DREG_L (dst0
, v
);
5294 else if (sop
== 0 && sopcde
== 7)
5296 bu16 sv1
= (bu16
)signbits (DREG (src1
), 32);
5297 bu16 sv0
= (bu16
)DREG (src0
);
5300 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i, R%i.L);", dst0
, src1
, src0
);
5302 if ((sv1
& 0x1f) < (sv0
& 0x1f))
5306 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), dst_lo
));
5308 else if (sop
== 1 && sopcde
== 7)
5310 /* Exponent adjust on two 16-bit inputs. Select
5311 smallest norm among 3 inputs. */
5312 bs16 src1_hi
= (DREG (src1
) & 0xFFFF0000) >> 16;
5313 bs16 src1_lo
= (DREG (src1
) & 0xFFFF);
5314 bu16 src0_lo
= (DREG (src0
) & 0xFFFF);
5315 bu16 tmp_hi
, tmp_lo
, tmp
;
5317 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i, R%i.L) (V);", dst0
, src1
, src0
);
5319 tmp_hi
= signbits (src1_hi
, 16);
5320 tmp_lo
= signbits (src1_lo
, 16);
5322 if ((tmp_hi
& 0xf) < (tmp_lo
& 0xf))
5323 if ((tmp_hi
& 0xf) < (src0_lo
& 0xf))
5328 if ((tmp_lo
& 0xf) < (src0_lo
& 0xf))
5332 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), tmp
));
5334 else if (sop
== 2 && sopcde
== 7)
5336 /* Exponent adjust on single 16-bit register. */
5338 bu16 src0_lo
= (bu16
)(DREG (src0
) & 0xFFFF);
5340 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i.L, R%i.L);", dst0
, src1
, src0
);
5342 tmp
= signbits (DREG (src1
) & 0xFFFF, 16);
5344 if ((tmp
& 0xf) < (src0_lo
& 0xf))
5345 SET_DREG_L (dst0
, tmp
);
5347 SET_DREG_L (dst0
, src0_lo
);
5349 else if (sop
== 3 && sopcde
== 7)
5352 bu16 src0_lo
= (bu16
)(DREG (src0
) & 0xFFFF);
5354 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i.H, R%i.L);", dst0
, src1
, src0
);
5356 tmp
= signbits ((DREG (src1
) & 0xFFFF0000) >> 16, 16);
5358 if ((tmp
& 0xf) < (src0_lo
& 0xf))
5359 SET_DREG_L (dst0
, tmp
);
5361 SET_DREG_L (dst0
, src0_lo
);
5363 else if (sop
== 0 && sopcde
== 8)
5365 bu64 acc
= get_unextended_acc (cpu
, 0);
5368 TRACE_INSN (cpu
, "BITMUX (R%i, R%i, A0) (ASR);", src0
, src1
);
5371 illegal_instruction_combination (cpu
);
5376 (((bu64
)s0
& 1) << 38) |
5377 (((bu64
)s1
& 1) << 39);
5378 SET_DREG (src0
, s0
>> 1);
5379 SET_DREG (src1
, s1
>> 1);
5383 else if (sop
== 1 && sopcde
== 8)
5385 bu64 acc
= get_unextended_acc (cpu
, 0);
5388 TRACE_INSN (cpu
, "BITMUX (R%i, R%i, A0) (ASL);", src0
, src1
);
5391 illegal_instruction_combination (cpu
);
5398 SET_DREG (src0
, s0
<< 1);
5399 SET_DREG (src1
, s1
<< 1);
5403 else if ((sop
== 0 || sop
== 1) && sopcde
== 9)
5405 bs40 acc0
= get_extended_acc (cpu
, 0);
5408 TRACE_INSN (cpu
, "R%i.L = VIT_MAX (R%i) (AS%c);",
5409 dst0
, src1
, sop
& 1 ? 'R' : 'L');
5412 sH
= DREG (src1
) >> 16;
5419 if (((sH
- sL
) & 0x8000) == 0)
5422 acc0
|= (sop
& 1) ? 0x80000000 : 1;
5428 SET_DREG (dst0
, REG_H_L (DREG (dst0
), out
));
5430 else if ((sop
== 2 || sop
== 3) && sopcde
== 9)
5432 bs40 acc0
= get_extended_acc (cpu
, 0);
5433 bs16 s0L
, s0H
, s1L
, s1H
, out0
, out1
;
5435 TRACE_INSN (cpu
, "R%i = VIT_MAX (R%i, R%i) (AS%c);",
5436 dst0
, src1
, src0
, sop
& 1 ? 'R' : 'L');
5439 s0H
= DREG (src0
) >> 16;
5441 s1H
= DREG (src1
) >> 16;
5448 if (((s0H
- s0L
) & 0x8000) == 0)
5451 acc0
|= (sop
& 1) ? 0x40000000 : 2;
5456 if (((s1H
- s1L
) & 0x8000) == 0)
5459 acc0
|= (sop
& 1) ? 0x80000000 : 1;
5465 SET_DREG (dst0
, REG_H_L (out1
<< 16, out0
));
5467 else if (sop
== 0 && sopcde
== 10)
5469 bu32 v
= DREG (src0
);
5470 bu32 x
= DREG (src1
);
5471 bu32 mask
= (1 << (v
& 0x1f)) - 1;
5472 TRACE_INSN (cpu
, "R%i = EXTRACT (R%i, R%i.L) (Z);", dst0
, src1
, src0
);
5473 x
>>= ((v
>> 8) & 0x1f);
5474 SET_DREG (dst0
, x
& mask
);
5475 setflags_logical (cpu
, DREG (dst0
));
5477 else if (sop
== 1 && sopcde
== 10)
5479 bu32 v
= DREG (src0
);
5480 bu32 x
= DREG (src1
);
5481 bu32 sgn
= (1 << (v
& 0x1f)) >> 1;
5482 bu32 mask
= (1 << (v
& 0x1f)) - 1;
5483 TRACE_INSN (cpu
, "R%i = EXTRACT (R%i, R%i.L) (X);", dst0
, src1
, src0
);
5484 x
>>= ((v
>> 8) & 0x1f);
5489 setflags_logical (cpu
, DREG (dst0
));
5491 else if ((sop
== 2 || sop
== 3) && sopcde
== 10)
5493 /* The first dregs is the "background" while the second dregs is the
5494 "foreground". The fg reg is used to overlay the bg reg and is:
5495 | nnnn nnnn | nnnn nnnn | xxxp pppp | xxxL LLLL |
5496 n = the fg bit field
5497 p = bit position in bg reg to start LSB of fg field
5498 L = number of fg bits to extract
5499 Using (X) sign-extends the fg bit field. */
5500 bu32 fg
= DREG (src0
);
5501 bu32 bg
= DREG (src1
);
5502 bu32 len
= fg
& 0x1f;
5503 bu32 mask
= (1 << MIN (16, len
)) - 1;
5504 bu32 fgnd
= (fg
>> 16) & mask
;
5505 int shft
= ((fg
>> 8) & 0x1f);
5507 TRACE_INSN (cpu
, "R%i = DEPOSIT (R%i, R%i)%s;", dst0
, src1
, src0
,
5508 sop
== 3 ? " (X)" : "");
5512 /* Sign extend the fg bit field. */
5514 fgnd
= ((bs32
)(bs16
)(fgnd
<< (16 - len
))) >> (16 - len
);
5520 SET_DREG (dst0
, bg
| fgnd
);
5521 setflags_logical (cpu
, DREG (dst0
));
5523 else if (sop
== 0 && sopcde
== 11)
5525 bu64 acc0
= get_unextended_acc (cpu
, 0);
5527 TRACE_INSN (cpu
, "R%i.L = CC = BXORSHIFT (A0, R%i);", dst0
, src0
);
5530 SET_CCREG (xor_reduce (acc0
, DREG (src0
)));
5531 SET_DREG (dst0
, REG_H_L (DREG (dst0
), CCREG
));
5534 else if (sop
== 1 && sopcde
== 11)
5536 bu64 acc0
= get_unextended_acc (cpu
, 0);
5538 TRACE_INSN (cpu
, "R%i.L = CC = BXOR (A0, R%i);", dst0
, src0
);
5540 SET_CCREG (xor_reduce (acc0
, DREG (src0
)));
5541 SET_DREG (dst0
, REG_H_L (DREG (dst0
), CCREG
));
5543 else if (sop
== 0 && sopcde
== 12)
5545 bu64 acc0
= get_unextended_acc (cpu
, 0);
5546 bu64 acc1
= get_unextended_acc (cpu
, 1);
5548 TRACE_INSN (cpu
, "A0 = BXORSHIFT (A0, A1, CC);");
5550 acc0
= (acc0
<< 1) | (CCREG
^ xor_reduce (acc0
, acc1
));
5553 else if (sop
== 1 && sopcde
== 12)
5555 bu64 acc0
= get_unextended_acc (cpu
, 0);
5556 bu64 acc1
= get_unextended_acc (cpu
, 1);
5558 TRACE_INSN (cpu
, "R%i.L = CC = BXOR (A0, A1, CC);", dst0
);
5560 SET_CCREG (CCREG
^ xor_reduce (acc0
, acc1
));
5561 acc0
= (acc0
<< 1) | CCREG
;
5562 SET_DREG (dst0
, REG_H_L (DREG (dst0
), CCREG
));
5564 else if ((sop
== 0 || sop
== 1 || sop
== 2) && sopcde
== 13)
5566 int shift
= (sop
+ 1) * 8;
5567 TRACE_INSN (cpu
, "R%i = ALIGN%i (R%i, R%i);", dst0
, shift
, src1
, src0
);
5568 SET_DREG (dst0
, (DREG (src1
) << (32 - shift
)) | (DREG (src0
) >> shift
));
5571 illegal_instruction (cpu
);
5575 decode_dsp32shiftimm_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
5578 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5579 | 1 | 1 | 0 | 0 |.M.| 1 | 1 | 0 | 1 | - | - |.sopcde............|
5580 |.sop...|.HLs...|.dst0......|.immag.................|.src1......|
5581 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5582 int src1
= ((iw1
>> DSP32ShiftImm_src1_bits
) & DSP32ShiftImm_src1_mask
);
5583 int sop
= ((iw1
>> DSP32ShiftImm_sop_bits
) & DSP32ShiftImm_sop_mask
);
5584 int bit8
= ((iw1
>> 8) & 0x1);
5585 int immag
= ((iw1
>> DSP32ShiftImm_immag_bits
) & DSP32ShiftImm_immag_mask
);
5586 int newimmag
= (-(iw1
>> DSP32ShiftImm_immag_bits
) & DSP32ShiftImm_immag_mask
);
5587 int dst0
= ((iw1
>> DSP32ShiftImm_dst0_bits
) & DSP32ShiftImm_dst0_mask
);
5588 int M
= ((iw0
>> (DSP32ShiftImm_M_bits
- 16)) & DSP32ShiftImm_M_mask
);
5589 int sopcde
= ((iw0
>> (DSP32ShiftImm_sopcde_bits
- 16)) & DSP32ShiftImm_sopcde_mask
);
5590 int HLs
= ((iw1
>> DSP32ShiftImm_HLs_bits
) & DSP32ShiftImm_HLs_mask
);
5592 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32shiftimm
);
5593 TRACE_EXTRACT (cpu
, "%s: M:%i sopcde:%i sop:%i HLs:%i dst0:%i immag:%#x src1:%i",
5594 __func__
, M
, sopcde
, sop
, HLs
, dst0
, immag
, src1
);
5598 bu16 in
= DREG (src1
) >> ((HLs
& 1) ? 16 : 0);
5604 TRACE_INSN (cpu
, "R%i.%c = R%i.%c >>> %i;",
5605 dst0
, (HLs
& 2) ? 'H' : 'L',
5606 src1
, (HLs
& 1) ? 'H' : 'L', newimmag
);
5607 result
= ashiftrt (cpu
, in
, newimmag
, 16);
5609 else if (sop
== 1 && bit8
== 0)
5611 TRACE_INSN (cpu
, "R%i.%c = R%i.%c << %i (S);",
5612 dst0
, (HLs
& 2) ? 'H' : 'L',
5613 src1
, (HLs
& 1) ? 'H' : 'L', immag
);
5614 result
= lshift (cpu
, in
, immag
, 16, 1);
5616 else if (sop
== 1 && bit8
)
5618 TRACE_INSN (cpu
, "R%i.%c = R%i.%c >>> %i (S);",
5619 dst0
, (HLs
& 2) ? 'H' : 'L',
5620 src1
, (HLs
& 1) ? 'H' : 'L', immag
);
5621 result
= lshift (cpu
, in
, immag
, 16, 1);
5623 else if (sop
== 2 && bit8
)
5625 TRACE_INSN (cpu
, "R%i.%c = R%i.%c >> %i;",
5626 dst0
, (HLs
& 2) ? 'H' : 'L',
5627 src1
, (HLs
& 1) ? 'H' : 'L', newimmag
);
5628 result
= lshiftrt (cpu
, in
, newimmag
, 16);
5630 else if (sop
== 2 && bit8
== 0)
5632 TRACE_INSN (cpu
, "R%i.%c = R%i.%c << %i;",
5633 dst0
, (HLs
& 2) ? 'H' : 'L',
5634 src1
, (HLs
& 1) ? 'H' : 'L', immag
);
5635 result
= lshift (cpu
, in
, immag
, 16, 0);
5638 illegal_instruction (cpu
);
5642 STORE (DREG (dst0
), (v
& 0xFFFF) | (result
<< 16));
5644 STORE (DREG (dst0
), (v
& 0xFFFF0000) | result
);
5646 else if (sop
== 2 && sopcde
== 3 && (HLs
== 1 || HLs
== 0))
5648 int shift
= imm6 (immag
);
5650 bu40 acc
= get_unextended_acc (cpu
, HLs
);
5652 TRACE_INSN (cpu
, "A%i = ROT A%i BY %i;", HLs
, HLs
, shift
);
5653 TRACE_DECODE (cpu
, "A%i:%#"PRIx64
" shift:%i CC:%i", HLs
, acc
, shift
, cc
);
5655 acc
= rot40 (acc
, shift
, &cc
);
5656 SET_AREG (HLs
, acc
);
5660 else if (sop
== 0 && sopcde
== 3 && bit8
== 1)
5662 /* Arithmetic shift, so shift in sign bit copies. */
5664 int shift
= uimm5 (newimmag
);
5667 TRACE_INSN (cpu
, "A%i = A%i >>> %i;", HLs
, HLs
, shift
);
5669 acc
= get_extended_acc (cpu
, HLs
);
5671 /* Sign extend again. */
5672 if (acc
& (1ULL << 39))
5673 acc
|= -(1ULL << 39);
5675 acc
&= ~(-(1ULL << 39));
5677 STORE (AXREG (HLs
), (acc
>> 32) & 0xFF);
5678 STORE (AWREG (HLs
), acc
& 0xFFFFFFFF);
5680 else if ((sop
== 0 && sopcde
== 3 && bit8
== 0)
5681 || (sop
== 1 && sopcde
== 3))
5684 int shiftup
= uimm5 (immag
);
5685 int shiftdn
= uimm5 (newimmag
);
5688 TRACE_INSN (cpu
, "A%i = A%i %s %i;", HLs
, HLs
,
5689 sop
== 0 ? "<<" : ">>",
5690 sop
== 0 ? shiftup
: shiftdn
);
5693 /* Logical shift, so shift in zeroes. */
5703 SET_AREG (HLs
, acc
);
5704 SET_ASTATREG (an
, !!(acc
& 0x8000000000ull
));
5705 SET_ASTATREG (az
, acc
== 0);
5707 else if (sop
== 1 && sopcde
== 1 && bit8
== 0)
5709 int count
= imm5 (immag
);
5710 bu16 val0
= DREG (src1
) >> 16;
5711 bu16 val1
= DREG (src1
) & 0xFFFF;
5714 TRACE_INSN (cpu
, "R%i = R%i << %i (V,S);", dst0
, src1
, count
);
5715 val0
= lshift (cpu
, val0
, count
, 16, 1);
5717 val1
= lshift (cpu
, val1
, count
, 16, 1);
5718 SET_ASTAT (ASTAT
| astat
);
5720 STORE (DREG (dst0
), (val0
<< 16) | val1
);
5722 else if (sop
== 2 && sopcde
== 1 && bit8
== 1)
5724 int count
= imm5 (newimmag
);
5725 bu16 val0
= DREG (src1
) & 0xFFFF;
5726 bu16 val1
= DREG (src1
) >> 16;
5729 TRACE_INSN (cpu
, "R%i = R%i >> %i (V);", dst0
, src1
, count
);
5730 val0
= lshiftrt (cpu
, val0
, count
, 16);
5732 val1
= lshiftrt (cpu
, val1
, count
, 16);
5733 SET_ASTAT (ASTAT
| astat
);
5735 STORE (DREG (dst0
), val0
| (val1
<< 16));
5737 else if (sop
== 2 && sopcde
== 1 && bit8
== 0)
5739 int count
= imm5 (immag
);
5740 bu16 val0
= DREG (src1
) & 0xFFFF;
5741 bu16 val1
= DREG (src1
) >> 16;
5744 TRACE_INSN (cpu
, "R%i = R%i << %i (V);", dst0
, src1
, count
);
5745 val0
= lshift (cpu
, val0
, count
, 16, 0);
5747 val1
= lshift (cpu
, val1
, count
, 16, 0);
5748 SET_ASTAT (ASTAT
| astat
);
5750 STORE (DREG (dst0
), val0
| (val1
<< 16));
5752 else if (sopcde
== 1 && (sop
== 0 || (sop
== 1 && bit8
== 1)))
5754 int count
= uimm5 (newimmag
);
5755 bu16 val0
= DREG (src1
) & 0xFFFF;
5756 bu16 val1
= DREG (src1
) >> 16;
5759 TRACE_INSN (cpu
, "R%i = R%i >>> %i %s;", dst0
, src1
, count
,
5760 sop
== 0 ? "(V)" : "(V,S)");
5762 val0
= ashiftrt (cpu
, val0
, count
, 16);
5764 val1
= ashiftrt (cpu
, val1
, count
, 16);
5765 SET_ASTAT (ASTAT
| astat
);
5767 STORE (DREG (dst0
), REG_H_L (val1
<< 16, val0
));
5769 else if (sop
== 1 && sopcde
== 2)
5771 int count
= imm6 (immag
);
5773 TRACE_INSN (cpu
, "R%i = R%i << %i (S);", dst0
, src1
, count
);
5774 STORE (DREG (dst0
), lshift (cpu
, DREG (src1
), count
, 32, 1));
5776 else if (sop
== 2 && sopcde
== 2)
5778 int count
= imm6 (newimmag
);
5780 TRACE_INSN (cpu
, "R%i = R%i >> %i;", dst0
, src1
, count
);
5783 STORE (DREG (dst0
), lshift (cpu
, DREG (src1
), -count
, 32, 0));
5785 STORE (DREG (dst0
), lshiftrt (cpu
, DREG (src1
), count
, 32));
5787 else if (sop
== 3 && sopcde
== 2)
5789 int shift
= imm6 (immag
);
5790 bu32 src
= DREG (src1
);
5791 bu32 ret
, cc
= CCREG
;
5793 TRACE_INSN (cpu
, "R%i = ROT R%i BY %i;", dst0
, src1
, shift
);
5794 TRACE_DECODE (cpu
, "R%i:%#x R%i:%#x shift:%i CC:%i",
5795 dst0
, DREG (dst0
), src1
, src
, shift
, cc
);
5797 ret
= rot32 (src
, shift
, &cc
);
5798 STORE (DREG (dst0
), ret
);
5802 else if (sop
== 0 && sopcde
== 2)
5804 int count
= imm6 (newimmag
);
5806 TRACE_INSN (cpu
, "R%i = R%i >>> %i;", dst0
, src1
, count
);
5809 STORE (DREG (dst0
), lshift (cpu
, DREG (src1
), -count
, 32, 0));
5811 STORE (DREG (dst0
), ashiftrt (cpu
, DREG (src1
), count
, 32));
5814 illegal_instruction (cpu
);
5818 outc (SIM_CPU
*cpu
, char ch
)
5820 SIM_DESC sd
= CPU_STATE (cpu
);
5821 sim_io_printf (sd
, "%c", ch
);
5823 sim_io_flush_stdout (sd
);
5827 decode_psedoDEBUG_0 (SIM_CPU
*cpu
, bu16 iw0
)
5830 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5831 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 |.fn....|.grp.......|.reg.......|
5832 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5833 SIM_DESC sd
= CPU_STATE (cpu
);
5834 int fn
= ((iw0
>> PseudoDbg_fn_bits
) & PseudoDbg_fn_mask
);
5835 int grp
= ((iw0
>> PseudoDbg_grp_bits
) & PseudoDbg_grp_mask
);
5836 int reg
= ((iw0
>> PseudoDbg_reg_bits
) & PseudoDbg_reg_mask
);
5838 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_psedoDEBUG
);
5839 TRACE_EXTRACT (cpu
, "%s: fn:%i grp:%i reg:%i", __func__
, fn
, grp
, reg
);
5841 if ((reg
== 0 || reg
== 1) && fn
== 3)
5843 TRACE_INSN (cpu
, "DBG A%i;", reg
);
5844 sim_io_printf (sd
, "DBG : A%i = %#"PRIx64
"\n", reg
,
5845 get_unextended_acc (cpu
, reg
));
5847 else if (reg
== 3 && fn
== 3)
5849 TRACE_INSN (cpu
, "ABORT;");
5850 cec_exception (cpu
, VEC_SIM_ABORT
);
5853 else if (reg
== 4 && fn
== 3)
5855 TRACE_INSN (cpu
, "HLT;");
5856 cec_exception (cpu
, VEC_SIM_HLT
);
5859 else if (reg
== 5 && fn
== 3)
5860 unhandled_instruction (cpu
, "DBGHALT");
5861 else if (reg
== 6 && fn
== 3)
5862 unhandled_instruction (cpu
, "DBGCMPLX (dregs)");
5863 else if (reg
== 7 && fn
== 3)
5864 unhandled_instruction (cpu
, "DBG");
5865 else if (grp
== 0 && fn
== 2)
5867 TRACE_INSN (cpu
, "OUTC R%i;", reg
);
5868 outc (cpu
, DREG (reg
));
5872 const char *reg_name
= get_allreg_name (grp
, reg
);
5873 TRACE_INSN (cpu
, "DBG %s;", reg_name
);
5874 sim_io_printf (sd
, "DBG : %s = 0x%08x\n", reg_name
,
5875 reg_read (cpu
, grp
, reg
));
5878 unhandled_instruction (cpu
, "PRNT allregs");
5880 illegal_instruction (cpu
);
5884 decode_psedoOChar_0 (SIM_CPU
*cpu
, bu16 iw0
)
5887 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5888 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |.ch............................|
5889 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5890 int ch
= ((iw0
>> PseudoChr_ch_bits
) & PseudoChr_ch_mask
);
5892 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_psedoOChar
);
5893 TRACE_EXTRACT (cpu
, "%s: ch:%#x", __func__
, ch
);
5894 TRACE_INSN (cpu
, "OUTC %#x;", ch
);
5900 decode_psedodbg_assert_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
, bu32 pc
)
5903 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5904 | 1 | 1 | 1 | 1 | 0 | - | - | - | dbgop |.grp.......|.regtest...|
5905 |.expected......................................................|
5906 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5907 SIM_DESC sd
= CPU_STATE (cpu
);
5908 int expected
= ((iw1
>> PseudoDbg_Assert_expected_bits
) & PseudoDbg_Assert_expected_mask
);
5909 int dbgop
= ((iw0
>> (PseudoDbg_Assert_dbgop_bits
- 16)) & PseudoDbg_Assert_dbgop_mask
);
5910 int grp
= ((iw0
>> (PseudoDbg_Assert_grp_bits
- 16)) & PseudoDbg_Assert_grp_mask
);
5911 int regtest
= ((iw0
>> (PseudoDbg_Assert_regtest_bits
- 16)) & PseudoDbg_Assert_regtest_mask
);
5914 bu32 val
= reg_read (cpu
, grp
, regtest
);
5915 const char *reg_name
= get_allreg_name (grp
, regtest
);
5916 const char *dbg_name
, *dbg_appd
;
5918 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_psedodbg_assert
);
5919 TRACE_EXTRACT (cpu
, "%s: dbgop:%i grp:%i regtest:%i expected:%#x",
5920 __func__
, dbgop
, grp
, regtest
, expected
);
5922 if (dbgop
== 0 || dbgop
== 2)
5924 dbg_name
= dbgop
== 0 ? "DBGA" : "DBGAL";
5925 dbg_appd
= dbgop
== 0 ? ".L" : "";
5928 else if (dbgop
== 1 || dbgop
== 3)
5930 dbg_name
= dbgop
== 1 ? "DBGA" : "DBGAH";
5931 dbg_appd
= dbgop
== 1 ? ".H" : "";
5935 illegal_instruction (cpu
);
5937 actual
= val
>> offset
;
5939 TRACE_INSN (cpu
, "%s (%s%s, 0x%x);", dbg_name
, reg_name
, dbg_appd
, expected
);
5940 if (actual
!= expected
)
5942 sim_io_printf (sd
, "FAIL at %#x: %s (%s%s, 0x%04x); actual value %#x\n",
5943 pc
, dbg_name
, reg_name
, dbg_appd
, expected
, actual
);
5945 /* Decode the actual ASTAT bits that are different. */
5946 if (grp
== 4 && regtest
== 6)
5950 sim_io_printf (sd
, "Expected ASTAT:\n");
5951 for (i
= 0; i
< 16; ++i
)
5952 sim_io_printf (sd
, " %8s%c%i%s",
5953 astat_names
[i
+ offset
],
5954 (((expected
>> i
) & 1) != ((actual
>> i
) & 1))
5956 (expected
>> i
) & 1,
5957 i
== 7 ? "\n" : "");
5958 sim_io_printf (sd
, "\n");
5960 sim_io_printf (sd
, "Actual ASTAT:\n");
5961 for (i
= 0; i
< 16; ++i
)
5962 sim_io_printf (sd
, " %8s%c%i%s",
5963 astat_names
[i
+ offset
],
5964 (((expected
>> i
) & 1) != ((actual
>> i
) & 1))
5967 i
== 7 ? "\n" : "");
5968 sim_io_printf (sd
, "\n");
5971 cec_exception (cpu
, VEC_SIM_DBGA
);
5977 _interp_insn_bfin (SIM_CPU
*cpu
, bu32 pc
)
5982 BFIN_CPU_STATE
.multi_pc
= pc
;
5984 if ((iw0
& 0xc000) != 0xc000)
5986 /* 16-bit opcode. */
5989 INSN_LEN
= insn_len
;
5991 TRACE_EXTRACT (cpu
, "%s: iw0:%#x", __func__
, iw0
);
5992 if ((iw0
& 0xFF00) == 0x0000)
5993 decode_ProgCtrl_0 (cpu
, iw0
, pc
);
5994 else if ((iw0
& 0xFFC0) == 0x0240)
5995 decode_CaCTRL_0 (cpu
, iw0
);
5996 else if ((iw0
& 0xFF80) == 0x0100)
5997 decode_PushPopReg_0 (cpu
, iw0
);
5998 else if ((iw0
& 0xFE00) == 0x0400)
5999 decode_PushPopMultiple_0 (cpu
, iw0
);
6000 else if ((iw0
& 0xFE00) == 0x0600)
6001 decode_ccMV_0 (cpu
, iw0
);
6002 else if ((iw0
& 0xF800) == 0x0800)
6003 decode_CCflag_0 (cpu
, iw0
);
6004 else if ((iw0
& 0xFFE0) == 0x0200)
6005 decode_CC2dreg_0 (cpu
, iw0
);
6006 else if ((iw0
& 0xFF00) == 0x0300)
6007 decode_CC2stat_0 (cpu
, iw0
);
6008 else if ((iw0
& 0xF000) == 0x1000)
6009 decode_BRCC_0 (cpu
, iw0
, pc
);
6010 else if ((iw0
& 0xF000) == 0x2000)
6011 decode_UJUMP_0 (cpu
, iw0
, pc
);
6012 else if ((iw0
& 0xF000) == 0x3000)
6013 decode_REGMV_0 (cpu
, iw0
);
6014 else if ((iw0
& 0xFC00) == 0x4000)
6015 decode_ALU2op_0 (cpu
, iw0
);
6016 else if ((iw0
& 0xFE00) == 0x4400)
6017 decode_PTR2op_0 (cpu
, iw0
);
6018 else if ((iw0
& 0xF800) == 0x4800)
6019 decode_LOGI2op_0 (cpu
, iw0
);
6020 else if ((iw0
& 0xF000) == 0x5000)
6021 decode_COMP3op_0 (cpu
, iw0
);
6022 else if ((iw0
& 0xF800) == 0x6000)
6023 decode_COMPI2opD_0 (cpu
, iw0
);
6024 else if ((iw0
& 0xF800) == 0x6800)
6025 decode_COMPI2opP_0 (cpu
, iw0
);
6026 else if ((iw0
& 0xF000) == 0x8000)
6027 decode_LDSTpmod_0 (cpu
, iw0
);
6028 else if ((iw0
& 0xFF60) == 0x9E60)
6029 decode_dagMODim_0 (cpu
, iw0
);
6030 else if ((iw0
& 0xFFF0) == 0x9F60)
6031 decode_dagMODik_0 (cpu
, iw0
);
6032 else if ((iw0
& 0xFC00) == 0x9C00)
6033 decode_dspLDST_0 (cpu
, iw0
);
6034 else if ((iw0
& 0xF000) == 0x9000)
6035 decode_LDST_0 (cpu
, iw0
);
6036 else if ((iw0
& 0xFC00) == 0xB800)
6037 decode_LDSTiiFP_0 (cpu
, iw0
);
6038 else if ((iw0
& 0xE000) == 0xA000)
6039 decode_LDSTii_0 (cpu
, iw0
);
6042 TRACE_EXTRACT (cpu
, "%s: no matching 16-bit pattern", __func__
);
6043 illegal_instruction (cpu
);
6048 /* Grab the next 16 bits to determine if it's a 32-bit or 64-bit opcode. */
6049 iw1
= IFETCH (pc
+ 2);
6050 if ((iw0
& BIT_MULTI_INS
) && (iw0
& 0xe800) != 0xe800 /* not linkage */)
6052 SIM_DESC sd
= CPU_STATE (cpu
);
6053 trace_prefix (sd
, cpu
, NULL_CIA
, pc
, TRACE_LINENUM_P (cpu
),
6054 NULL
, 0, "|| %#"PRIx64
, sim_events_time (sd
));
6060 TRACE_EXTRACT (cpu
, "%s: iw0:%#x iw1:%#x insn_len:%i", __func__
,
6061 iw0
, iw1
, insn_len
);
6063 /* Only cache on first run through (in case of parallel insns). */
6065 INSN_LEN
= insn_len
;
6067 if ((iw0
& 0xf7ff) == 0xc003 && (iw1
& 0xfe00) == 0x1800)
6069 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32mac
);
6070 TRACE_INSN (cpu
, "MNOP;");
6072 else if (((iw0
& 0xFF80) == 0xE080) && ((iw1
& 0x0C00) == 0x0000))
6073 decode_LoopSetup_0 (cpu
, iw0
, iw1
, pc
);
6074 else if (((iw0
& 0xFF00) == 0xE100) && ((iw1
& 0x0000) == 0x0000))
6075 decode_LDIMMhalf_0 (cpu
, iw0
, iw1
);
6076 else if (((iw0
& 0xFE00) == 0xE200) && ((iw1
& 0x0000) == 0x0000))
6077 decode_CALLa_0 (cpu
, iw0
, iw1
, pc
);
6078 else if (((iw0
& 0xFC00) == 0xE400) && ((iw1
& 0x0000) == 0x0000))
6079 decode_LDSTidxI_0 (cpu
, iw0
, iw1
);
6080 else if (((iw0
& 0xFFFE) == 0xE800) && ((iw1
& 0x0000) == 0x0000))
6081 decode_linkage_0 (cpu
, iw0
, iw1
);
6082 else if (((iw0
& 0xF600) == 0xC000) && ((iw1
& 0x0000) == 0x0000))
6083 decode_dsp32mac_0 (cpu
, iw0
, iw1
);
6084 else if (((iw0
& 0xF600) == 0xC200) && ((iw1
& 0x0000) == 0x0000))
6085 decode_dsp32mult_0 (cpu
, iw0
, iw1
);
6086 else if (((iw0
& 0xF7C0) == 0xC400) && ((iw1
& 0x0000) == 0x0000))
6087 decode_dsp32alu_0 (cpu
, iw0
, iw1
);
6088 else if (((iw0
& 0xF7E0) == 0xC600) && ((iw1
& 0x01C0) == 0x0000))
6089 decode_dsp32shift_0 (cpu
, iw0
, iw1
);
6090 else if (((iw0
& 0xF7E0) == 0xC680) && ((iw1
& 0x0000) == 0x0000))
6091 decode_dsp32shiftimm_0 (cpu
, iw0
, iw1
);
6092 else if ((iw0
& 0xFF00) == 0xF800)
6093 decode_psedoDEBUG_0 (cpu
, iw0
), insn_len
= 2;
6094 else if ((iw0
& 0xFF00) == 0xF900)
6095 decode_psedoOChar_0 (cpu
, iw0
), insn_len
= 2;
6096 else if (((iw0
& 0xFF00) == 0xF000) && ((iw1
& 0x0000) == 0x0000))
6097 decode_psedodbg_assert_0 (cpu
, iw0
, iw1
, pc
);
6100 TRACE_EXTRACT (cpu
, "%s: no matching 32-bit pattern", __func__
);
6101 illegal_instruction (cpu
);
6108 interp_insn_bfin (SIM_CPU
*cpu
, bu32 pc
)
6113 BFIN_CPU_STATE
.n_stores
= 0;
6114 DIS_ALGN_EXPT
&= ~1;
6118 insn_len
= _interp_insn_bfin (cpu
, pc
);
6120 /* Proper display of multiple issue instructions. */
6123 _interp_insn_bfin (cpu
, pc
+ 4);
6124 _interp_insn_bfin (cpu
, pc
+ 6);
6126 for (i
= 0; i
< BFIN_CPU_STATE
.n_stores
; i
++)
6128 bu32
*addr
= BFIN_CPU_STATE
.stores
[i
].addr
;
6129 *addr
= BFIN_CPU_STATE
.stores
[i
].val
;
6130 TRACE_REGISTER (cpu
, "dequeuing write %s = %#x",
6131 get_store_name (cpu
, addr
), *addr
);
6134 cycles_inc (cpu
, CYCLE_DELAY
);
6136 /* Set back to zero in case a pending CEC event occurs
6137 after this this insn. */