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);
722 lshiftrt (SIM_CPU
*cpu
, bu64 val
, int cnt
, int size
)
724 int real_cnt
= cnt
> size
? size
: cnt
;
726 val
>>= 16, real_cnt
-= 16;
737 val
&= 0xFFFFFFFFFFull
;
740 illegal_instruction (cpu
);
743 SET_ASTATREG (an
, val
>> (size
- 1));
744 SET_ASTATREG (az
, val
== 0);
751 lshift (SIM_CPU
*cpu
, bu64 val
, int cnt
, int size
, bool saturate
)
753 int i
, j
, real_cnt
= cnt
> size
? size
: cnt
;
754 bu64 sgn
= ~((val
>> (size
- 1)) - 1);
755 int mask_cnt
= size
- 1;
756 bu64 masked
, new_val
= val
, tmp
;
764 new_val
<<= 16, real_cnt
-= 16;
766 new_val
<<= real_cnt
;
768 masked
= new_val
& mask
;
770 /* If an operation would otherwise cause a positive value to overflow
771 and become negative, instead, saturation limits the result to the
772 maximum positive value for the size register being used.
774 Conversely, if an operation would otherwise cause a negative value
775 to overflow and become positive, saturation limits the result to the
776 maximum negative value for the register size.
778 However, it's a little more complex than looking at sign bits, we need
779 to see if we are shifting the sign information away... */
780 tmp
= val
& ((~mask
<< 1) | 1);
783 for (i
= 1; i
<= real_cnt
&& saturate
; i
++)
785 if ((tmp
& ((bu64
)1 << (size
- 1))) !=
786 (((val
>> mask_cnt
) & 0x1) << mask_cnt
))
790 saturate
&= (!sgn
&& (new_val
& (1 << mask_cnt
)))
791 || (sgn
&& !(new_val
& (1 << mask_cnt
)));
796 if (j
|| (saturate
&& (new_val
& mask
)))
797 new_val
= sgn
== 0 ? 0x7fff : 0x8000, saturate
= 1;
801 new_val
&= 0xFFFFFFFF;
802 masked
&= 0xFFFFFFFF;
803 if (j
|| (saturate
&& ((sgn
!= masked
) || (!sgn
&& new_val
== 0))))
804 new_val
= sgn
== 0 ? 0x7fffffff : 0x80000000, saturate
= 1;
807 new_val
&= 0xFFFFFFFFFFull
;
808 masked
&= 0xFFFFFFFFFFull
;
811 illegal_instruction (cpu
);
815 SET_ASTATREG (an
, new_val
>> (size
- 1));
816 SET_ASTATREG (az
, new_val
== 0);
817 SET_ASTATREG (v
, !!(saturate
|| j
));
819 SET_ASTATREG (vs
, 1);
824 algn (bu32 l
, bu32 h
, bu32 aln
)
829 return (l
>> (8 * aln
)) | (h
<< (32 - 8 * aln
));
833 saturate_s16 (bu64 val
, bu32
*overflow
)
835 if ((bs64
)val
< -0x8000ll
)
841 if ((bs64
)val
> 0x7fff)
851 rot40 (bu40 val
, int shift
, bu32
*cc
)
853 const int nbits
= 40;
856 shift
= CLAMP (shift
, -nbits
, nbits
);
860 /* Reduce everything to rotate left. */
864 ret
= shift
== nbits
? 0 : val
<< shift
;
865 ret
|= shift
== 1 ? 0 : val
>> ((nbits
+ 1) - shift
);
866 ret
|= (bu40
)*cc
<< (shift
- 1);
867 *cc
= (val
>> (nbits
- shift
)) & 1;
873 rot32 (bu32 val
, int shift
, bu32
*cc
)
875 const int nbits
= 32;
878 shift
= CLAMP (shift
, -nbits
, nbits
);
882 /* Reduce everything to rotate left. */
886 ret
= shift
== nbits
? 0 : val
<< shift
;
887 ret
|= shift
== 1 ? 0 : val
>> ((nbits
+ 1) - shift
);
888 ret
|= (bu32
)*cc
<< (shift
- 1);
889 *cc
= (val
>> (nbits
- shift
)) & 1;
895 add32 (SIM_CPU
*cpu
, bu32 a
, bu32 b
, int carry
, int sat
)
897 int flgs
= (a
>> 31) & 1;
898 int flgo
= (b
>> 31) & 1;
900 int flgn
= (v
>> 31) & 1;
901 int overflow
= (flgs
^ flgn
) & (flgo
^ flgn
);
908 flgn
= (v
>> 31) & 1;
911 SET_ASTATREG (an
, flgn
);
913 SET_ASTATREG (vs
, 1);
914 SET_ASTATREG (v
, overflow
);
915 ASTATREG (v_internal
) |= overflow
;
916 SET_ASTATREG (az
, v
== 0);
918 SET_ASTATREG (ac0
, ~a
< b
);
924 sub32 (SIM_CPU
*cpu
, bu32 a
, bu32 b
, int carry
, int sat
, int parallel
)
926 int flgs
= (a
>> 31) & 1;
927 int flgo
= (b
>> 31) & 1;
929 int flgn
= (v
>> 31) & 1;
930 int overflow
= (flgs
^ flgo
) & (flgn
^ flgs
);
937 flgn
= (v
>> 31) & 1;
940 if (!parallel
|| flgn
)
941 SET_ASTATREG (an
, flgn
);
943 SET_ASTATREG (vs
, 1);
944 if (!parallel
|| overflow
)
945 SET_ASTATREG (v
, overflow
);
946 if (!parallel
|| overflow
)
947 ASTATREG (v_internal
) |= overflow
;
948 if (!parallel
|| v
== 0)
949 SET_ASTATREG (az
, v
== 0);
950 if (carry
&& (!parallel
|| b
<= a
))
951 SET_ASTATREG (ac0
, b
<= a
);
957 add16 (SIM_CPU
*cpu
, bu16 a
, bu16 b
, bu32
*carry
, bu32
*overfl
,
958 bu32
*zero
, bu32
*neg
, int sat
, int scale
)
960 int flgs
= (a
>> 15) & 1;
961 int flgo
= (b
>> 15) & 1;
962 bs64 v
= (bs16
)a
+ (bs16
)b
;
963 int flgn
= (v
>> 15) & 1;
964 int overflow
= (flgs
^ flgn
) & (flgo
^ flgn
);
972 v
= (a
>> 1) + (a
& 0x8000) + (b
>> 1) + (b
& 0x8000)
973 + (((a
& 1) + (b
& 1)) >> 1);
981 illegal_instruction (cpu
);
984 flgn
= (v
>> 15) & 1;
985 overflow
= (flgs
^ flgn
) & (flgo
^ flgn
);
987 if (v
> (bs64
)0xffff)
991 v
= saturate_s16 (v
, 0);
994 *neg
|= (v
>> 15) & 1;
998 *zero
|= (v
& 0xFFFF) == 0;
1000 *carry
|= ((bu16
)~a
< (bu16
)b
);
1006 sub16 (SIM_CPU
*cpu
, bu16 a
, bu16 b
, bu32
*carry
, bu32
*overfl
,
1007 bu32
*zero
, bu32
*neg
, int sat
, int scale
)
1009 int flgs
= (a
>> 15) & 1;
1010 int flgo
= (b
>> 15) & 1;
1011 bs64 v
= (bs16
)a
- (bs16
)b
;
1012 int flgn
= (v
>> 15) & 1;
1013 int overflow
= (flgs
^ flgo
) & (flgn
^ flgs
);
1022 v
= ((a
>> 1) + (a
& 0x8000)) - ( (b
>> 1) + (b
& 0x8000))
1023 + (((a
& 1)-(b
& 1)));
1026 v
= ((v
& 0xFFFF) >> 1);
1027 if ((!flgs
& !flgo
& flgn
)
1028 || (flgs
& !flgo
& !flgn
)
1029 || (flgs
& flgo
& flgn
)
1030 || (flgs
& !flgo
& flgn
))
1034 flgn
= (v
>> 15) & 1;
1035 overflow
= (flgs
^ flgo
) & (flgn
^ flgs
);
1040 if (v
> (bs64
)0x7fff || v
< (bs64
)-0xffff)
1044 illegal_instruction (cpu
);
1049 v
= saturate_s16 (v
, 0);
1052 *neg
|= (v
>> 15) & 1;
1054 *zero
|= (v
& 0xFFFF) == 0;
1056 *overfl
|= overflow
;
1058 *carry
|= (bu16
)b
<= (bu16
)a
;
1063 min32 (SIM_CPU
*cpu
, bu32 a
, bu32 b
)
1066 if ((bs32
)a
> (bs32
)b
)
1068 setflags_nz (cpu
, val
);
1069 SET_ASTATREG (v
, 0);
1074 max32 (SIM_CPU
*cpu
, bu32 a
, bu32 b
)
1077 if ((bs32
)a
< (bs32
)b
)
1079 setflags_nz (cpu
, val
);
1080 SET_ASTATREG (v
, 0);
1085 min2x16 (SIM_CPU
*cpu
, bu32 a
, bu32 b
)
1088 if ((bs16
)a
> (bs16
)b
)
1089 val
= (val
& 0xFFFF0000) | (b
& 0xFFFF);
1090 if ((bs16
)(a
>> 16) > (bs16
)(b
>> 16))
1091 val
= (val
& 0xFFFF) | (b
& 0xFFFF0000);
1092 setflags_nz_2x16 (cpu
, val
);
1093 SET_ASTATREG (v
, 0);
1098 max2x16 (SIM_CPU
*cpu
, bu32 a
, bu32 b
)
1101 if ((bs16
)a
< (bs16
)b
)
1102 val
= (val
& 0xFFFF0000) | (b
& 0xFFFF);
1103 if ((bs16
)(a
>> 16) < (bs16
)(b
>> 16))
1104 val
= (val
& 0xFFFF) | (b
& 0xFFFF0000);
1105 setflags_nz_2x16 (cpu
, val
);
1106 SET_ASTATREG (v
, 0);
1111 add_and_shift (SIM_CPU
*cpu
, bu32 a
, bu32 b
, int shift
)
1114 ASTATREG (v_internal
) = 0;
1115 v
= add32 (cpu
, a
, b
, 0, 0);
1118 int x
= (v
>> 30) & 0x3;
1119 if (x
== 1 || x
== 2)
1120 ASTATREG (v_internal
) = 1;
1123 SET_ASTATREG (az
, v
== 0);
1124 SET_ASTATREG (an
, v
& 0x80000000);
1125 SET_ASTATREG (v
, ASTATREG (v_internal
));
1127 SET_ASTATREG (vs
, 1);
1132 xor_reduce (bu64 acc0
, bu64 acc1
)
1136 for (i
= 0; i
< 40; ++i
)
1138 v
^= (acc0
& acc1
& 1);
1145 /* DIVS ( Dreg, Dreg ) ;
1146 Initialize for DIVQ. Set the AQ status bit based on the signs of
1147 the 32-bit dividend and the 16-bit divisor. Left shift the dividend
1148 one bit. Copy AQ into the dividend LSB. */
1150 divs (SIM_CPU
*cpu
, bu32 pquo
, bu16 divisor
)
1152 bu16 r
= pquo
>> 16;
1155 aq
= (r
^ divisor
) >> 15; /* Extract msb's and compute quotient bit. */
1156 SET_ASTATREG (aq
, aq
); /* Update global quotient state. */
1160 pquo
= (pquo
& 0x1FFFF) | (r
<< 17);
1164 /* DIVQ ( Dreg, Dreg ) ;
1165 Based on AQ status bit, either add or subtract the divisor from
1166 the dividend. Then set the AQ status bit based on the MSBs of the
1167 32-bit dividend and the 16-bit divisor. Left shift the dividend one
1168 bit. Copy the logical inverse of AQ into the dividend LSB. */
1170 divq (SIM_CPU
*cpu
, bu32 pquo
, bu16 divisor
)
1172 unsigned short af
= pquo
>> 16;
1181 aq
= (r
^ divisor
) >> 15; /* Extract msb's and compute quotient bit. */
1182 SET_ASTATREG (aq
, aq
); /* Update global quotient state. */
1186 pquo
= (pquo
& 0x1FFFF) | (r
<< 17);
1191 Count the number of bits set to 1 in the 32bit value. */
1199 for (i
= 0; i
< 32; ++i
)
1200 ret
+= !!(val
& (1 << i
));
1206 reg_check_sup (SIM_CPU
*cpu
, int grp
, int reg
)
1209 cec_require_supervisor (cpu
);
1213 reg_write (SIM_CPU
*cpu
, int grp
, int reg
, bu32 value
)
1217 /* ASTAT is special! */
1218 if (grp
== 4 && reg
== 6)
1224 /* Check supervisor after get_allreg() so exception order is correct. */
1225 whichreg
= get_allreg (cpu
, grp
, reg
);
1226 reg_check_sup (cpu
, grp
, reg
);
1228 if (whichreg
== &CYCLES2REG
)
1229 /* Writes to CYCLES2 goes to the shadow. */
1230 whichreg
= &CYCLES2SHDREG
;
1231 else if (whichreg
== &SEQSTATREG
)
1232 /* Register is read only -- discard writes. */
1234 else if (whichreg
== &EMUDAT_INREG
)
1235 /* Writes to EMUDAT goes to the output. */
1236 whichreg
= &EMUDAT_OUTREG
;
1237 else if (whichreg
== <REG (0) || whichreg
== <REG (1))
1238 /* Writes to LT clears LSB automatically. */
1240 else if (whichreg
== &AXREG (0) || whichreg
== &AXREG (1))
1243 TRACE_REGISTER (cpu
, "wrote %s = %#x", get_allreg_name (grp
, reg
), value
);
1249 reg_read (SIM_CPU
*cpu
, int grp
, int reg
)
1254 /* ASTAT is special! */
1255 if (grp
== 4 && reg
== 6)
1258 /* Check supervisor after get_allreg() so exception order is correct. */
1259 whichreg
= get_allreg (cpu
, grp
, reg
);
1260 reg_check_sup (cpu
, grp
, reg
);
1264 if (whichreg
== &CYCLESREG
)
1265 /* Reads of CYCLES reloads CYCLES2 from the shadow. */
1266 SET_CYCLES2REG (CYCLES2SHDREG
);
1267 else if ((whichreg
== &AXREG (1) || whichreg
== &AXREG (0)) && (value
& 0x80))
1268 /* Sign extend if necessary. */
1269 value
|= 0xFFFFFF00;
1275 get_extended_cycles (SIM_CPU
*cpu
)
1277 return ((bu64
)CYCLES2SHDREG
<< 32) | CYCLESREG
;
1280 /* We can't re-use sim_events_time() because the CYCLES registers may be
1281 written/cleared/reset/stopped/started at any time by software. */
1283 cycles_inc (SIM_CPU
*cpu
, bu32 inc
)
1288 if (!(SYSCFGREG
& SYSCFG_CCEN
))
1291 cycles
= get_extended_cycles (cpu
) + inc
;
1292 SET_CYCLESREG (cycles
);
1293 cycles2
= cycles
>> 32;
1294 if (CYCLES2SHDREG
!= cycles2
)
1295 SET_CYCLES2SHDREG (cycles2
);
1299 get_unextended_acc (SIM_CPU
*cpu
, int which
)
1301 return ((bu64
)(AXREG (which
) & 0xff) << 32) | AWREG (which
);
1305 get_extended_acc (SIM_CPU
*cpu
, int which
)
1307 bu64 acc
= AXREG (which
);
1308 /* Sign extend accumulator values before adding. */
1314 acc
|= AWREG (which
);
1318 /* Perform a multiplication of D registers SRC0 and SRC1, sign- or
1319 zero-extending the result to 64 bit. H0 and H1 determine whether the
1320 high part or the low part of the source registers is used. Store 1 in
1321 *PSAT if saturation occurs, 0 otherwise. */
1323 decode_multfunc (SIM_CPU
*cpu
, int h0
, int h1
, int src0
, int src1
, int mmod
,
1326 bu32 s0
= DREG (src0
), s1
= DREG (src1
);
1340 sgn0
= -(s0
& 0x8000);
1341 sgn1
= -(s1
& 0x8000);
1363 illegal_instruction (cpu
);
1367 /* Perform shift correction if appropriate for the mode. */
1369 if (!MM
&& (mmod
== 0 || mmod
== M_T
|| mmod
== M_S2RND
|| mmod
== M_W32
))
1371 if (val
== 0x40000000)
1384 /* In signed modes, sign extend. */
1385 if (is_macmod_signed (mmod
) || MM
)
1386 val1
|= -(val1
& 0x80000000);
1389 val1
&= 0xFFFFFFFFull
;
1395 saturate_s40_astat (bu64 val
, bu32
*v
)
1397 if ((bs64
)val
< -((bs64
)1 << 39))
1400 return -((bs64
)1 << 39);
1402 else if ((bs64
)val
> ((bs64
)1 << 39) - 1)
1405 return ((bu64
)1 << 39) - 1;
1407 *v
= 0; /* No overflow. */
1412 saturate_s40 (bu64 val
)
1415 return saturate_s40_astat (val
, &v
);
1419 saturate_s32 (bu64 val
, bu32
*overflow
)
1421 if ((bs64
)val
< -0x80000000ll
)
1427 if ((bs64
)val
> 0x7fffffff)
1437 saturate_u32 (bu64 val
, bu32
*overflow
)
1439 if (val
> 0xffffffff)
1449 saturate_u16 (bu64 val
, bu32
*overflow
)
1465 /* FIXME: Should honour rounding mode. */
1466 if ((val
& 0xffff) > 0x8000
1467 || ((val
& 0xffff) == 0x8000 && (val
& 0x10000)))
1470 sgnbits
= val
& 0xffff000000000000ull
;
1472 return val
| sgnbits
;
1478 bu64 sgnbits
= val
& 0xffff000000000000ull
;
1480 return val
| sgnbits
;
1484 signbits (bu64 val
, int size
)
1486 bu64 mask
= (bu64
)1 << (size
- 1);
1487 bu64 bit
= val
& mask
;
1495 if ((val
& mask
) != bit
)
1505 /* Extract a 16 or 32 bit value from a 64 bit multiplication result.
1506 These 64 bits must be sign- or zero-extended properly from the source
1507 we want to extract, either a 32 bit multiply or a 40 bit accumulator. */
1510 extract_mult (SIM_CPU
*cpu
, bu64 res
, int mmod
, int MM
,
1511 int fullword
, bu32
*overflow
)
1518 return saturate_s32 (res
, overflow
);
1521 return saturate_s32 (res
, overflow
);
1522 return saturate_u32 (res
, overflow
);
1525 return saturate_s32 (res
, overflow
);
1526 return saturate_u32 (res
, overflow
);
1529 return saturate_s32 (res
<< 1, overflow
);
1531 illegal_instruction (cpu
);
1539 return saturate_s16 (rnd16 (res
), overflow
);
1541 return saturate_s16 (res
, overflow
);
1544 return saturate_s16 (rnd16 (res
), overflow
);
1545 return saturate_u16 (rnd16 (res
), overflow
);
1548 return saturate_s16 (res
, overflow
);
1549 return saturate_u16 (res
, overflow
);
1552 return saturate_s16 (trunc16 (res
), overflow
);
1555 return saturate_s16 (trunc16 (res
), overflow
);
1556 return saturate_u16 (trunc16 (res
), overflow
);
1559 return saturate_s16 (rnd16 (res
<< 1), overflow
);
1561 return saturate_s16 (res
<< 1, overflow
);
1563 illegal_instruction (cpu
);
1568 decode_macfunc (SIM_CPU
*cpu
, int which
, int op
, int h0
, int h1
, int src0
,
1569 int src1
, int mmod
, int MM
, int fullword
, bu32
*overflow
,
1573 bu32 sat
= 0, tsat
, ret
;
1575 /* Sign extend accumulator if necessary, otherwise unsigned. */
1576 if (is_macmod_signed (mmod
) || MM
)
1577 acc
= get_extended_acc (cpu
, which
);
1579 acc
= get_unextended_acc (cpu
, which
);
1583 bu8 sgn0
= (acc
>> 31) & 1;
1584 bu8 sgn40
= (acc
>> 39) & 1;
1587 /* This can't saturate, so we don't keep track of the sat flag. */
1588 bu64 res
= decode_multfunc (cpu
, h0
, h1
, src0
, src1
, mmod
,
1591 /* Perform accumulation. */
1596 sgn0
= (acc
>> 31) & 1;
1615 if ((bs64
)acc
< -((bs64
)1 << 39))
1616 acc
= -((bu64
)1 << 39), sat
= 1;
1617 else if ((bs64
)acc
> 0x7fffffffffll
)
1618 acc
= 0x7fffffffffull
, sat
= 1;
1623 if ((bs64
)acc
< -((bs64
)1 << 39))
1624 acc
= -((bu64
)1 << 39), sat
= 1;
1625 if ((bs64
)acc
> 0x7FFFFFFFFFll
)
1626 acc
= 0x7FFFFFFFFFull
, sat
= 1;
1632 if ((bs64
)acc
> 0xFFFFFFFFFFull
)
1633 acc
= 0xFFFFFFFFFFull
, sat
= 1;
1637 if (!MM
&& acc
& 0x8000000000000000ull
)
1639 if (!MM
&& acc
> 0xFFFFFFFFFFull
)
1640 acc
= 0xFFFFFFFFFFull
, sat
= 1;
1641 if (MM
&& acc
> 0xFFFFFFFFFFull
)
1642 acc
&= 0xFFFFFFFFFFull
;
1643 if (acc
& 0x8000000000ull
)
1644 acc
|= 0xffffff0000000000ull
;
1649 if ((bs64
)acc
< -((bs64
)1 << 39))
1650 acc
= -((bu64
)1 << 39), sat
= 1;
1651 if ((bs64
)acc
> 0x7FFFFFFFFFll
)
1652 acc
= 0x7FFFFFFFFFull
, sat
= 1;
1653 else if (acc
& 0x8000000000ull
)
1654 acc
|= 0xffffff0000000000ull
;
1660 else if ((bs64
)acc
> (bs64
)0xFFFFFFFFFFll
)
1661 acc
= 0xFFFFFFFFFFull
, sat
= 1;
1665 if ((bs64
)acc
< -0x80000000ll
)
1666 acc
= -0x80000000ull
, sat
= 1;
1667 else if ((bs64
)acc
> 0x7fffffffll
)
1668 acc
= 0x7fffffffull
, sat
= 1;
1671 /* check max negative value */
1672 if (sgn40
&& ((acc
>> 31) != 0x1ffffffff)
1673 && ((acc
>> 31) != 0x0))
1674 acc
= 0x80000000, sat
= 1;
1675 if (!sat
&& !sgn40
&& ((acc
>> 31) != 0x0)
1676 && ((acc
>> 31) != 0x1ffffffff))
1677 acc
= 0x7FFFFFFF, sat
= 1;
1679 if (acc
& 0x80000000)
1680 acc
|= 0xffffffff00000000ull
;
1685 illegal_instruction (cpu
);
1688 if (acc
& 0x8000000000ull
)
1691 STORE (AXREG (which
), (acc
>> 32) & 0xff);
1692 STORE (AWREG (which
), acc
& 0xffffffff);
1693 STORE (ASTATREG (av
[which
]), sat
);
1695 STORE (ASTATREG (avs
[which
]), sat
);
1697 /* Figure out the overflow bit. */
1703 ret
= extract_mult (cpu
, nosat_acc
, mmod
, MM
, fullword
, overflow
);
1707 ret
= extract_mult (cpu
, acc
, mmod
, MM
, fullword
, overflow
);
1716 if (ret
& 0x80000000)
1724 hwloop_get_next_pc (SIM_CPU
*cpu
, bu32 pc
, bu32 insn_len
)
1731 /* If our PC has reached the bottom of a hardware loop,
1732 move back up to the top of the hardware loop. */
1733 for (i
= 1; i
>= 0; --i
)
1734 if (LCREG (i
) > 1 && pc
== LBREG (i
))
1736 TRACE_BRANCH (cpu
, pc
, LTREG (i
), i
, "Hardware loop %i", i
);
1740 return pc
+ insn_len
;
1744 decode_ProgCtrl_0 (SIM_CPU
*cpu
, bu16 iw0
, bu32 pc
)
1747 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
1748 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |.prgfunc.......|.poprnd........|
1749 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
1750 int poprnd
= ((iw0
>> ProgCtrl_poprnd_bits
) & ProgCtrl_poprnd_mask
);
1751 int prgfunc
= ((iw0
>> ProgCtrl_prgfunc_bits
) & ProgCtrl_prgfunc_mask
);
1753 TRACE_EXTRACT (cpu
, "%s: poprnd:%i prgfunc:%i", __func__
, poprnd
, prgfunc
);
1755 if (prgfunc
== 0 && poprnd
== 0)
1757 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_nop
);
1758 TRACE_INSN (cpu
, "NOP;");
1760 else if (prgfunc
== 1 && poprnd
== 0)
1762 bu32 newpc
= RETSREG
;
1763 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1764 TRACE_INSN (cpu
, "RTS;");
1765 IFETCH_CHECK (newpc
);
1767 illegal_instruction_combination (cpu
);
1768 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "RTS");
1770 BFIN_CPU_STATE
.did_jump
= true;
1773 else if (prgfunc
== 1 && poprnd
== 1)
1775 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1776 TRACE_INSN (cpu
, "RTI;");
1777 /* Do not do IFETCH_CHECK here -- LSB has special meaning. */
1779 illegal_instruction_combination (cpu
);
1780 cec_return (cpu
, -1);
1783 else if (prgfunc
== 1 && poprnd
== 2)
1785 bu32 newpc
= RETXREG
;
1786 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1787 TRACE_INSN (cpu
, "RTX;");
1788 /* XXX: Not sure if this is what the hardware does. */
1789 IFETCH_CHECK (newpc
);
1791 illegal_instruction_combination (cpu
);
1792 cec_return (cpu
, IVG_EVX
);
1795 else if (prgfunc
== 1 && poprnd
== 3)
1797 bu32 newpc
= RETNREG
;
1798 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1799 TRACE_INSN (cpu
, "RTN;");
1800 /* XXX: Not sure if this is what the hardware does. */
1801 IFETCH_CHECK (newpc
);
1803 illegal_instruction_combination (cpu
);
1804 cec_return (cpu
, IVG_NMI
);
1807 else if (prgfunc
== 1 && poprnd
== 4)
1809 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1810 TRACE_INSN (cpu
, "RTE;");
1812 illegal_instruction_combination (cpu
);
1813 cec_return (cpu
, IVG_EMU
);
1816 else if (prgfunc
== 2 && poprnd
== 0)
1818 SIM_DESC sd
= CPU_STATE (cpu
);
1819 sim_events
*events
= STATE_EVENTS (sd
);
1821 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_sync
);
1822 /* XXX: in supervisor mode, utilizes wake up sources
1823 in user mode, it's a NOP ... */
1824 TRACE_INSN (cpu
, "IDLE;");
1827 illegal_instruction_combination (cpu
);
1831 CYCLE_DELAY
= events
->time_from_event
;
1833 abort (); /* XXX: Should this ever happen ? */
1835 else if (prgfunc
== 2 && poprnd
== 3)
1837 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_sync
);
1839 TRACE_INSN (cpu
, "CSYNC;");
1841 illegal_instruction_combination (cpu
);
1844 else if (prgfunc
== 2 && poprnd
== 4)
1846 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_sync
);
1848 TRACE_INSN (cpu
, "SSYNC;");
1850 illegal_instruction_combination (cpu
);
1852 /* Really 10+, but no model info for this. */
1855 else if (prgfunc
== 2 && poprnd
== 5)
1857 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1858 TRACE_INSN (cpu
, "EMUEXCPT;");
1860 illegal_instruction_combination (cpu
);
1861 cec_exception (cpu
, VEC_SIM_TRAP
);
1863 else if (prgfunc
== 3 && poprnd
< 8)
1865 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1866 TRACE_INSN (cpu
, "CLI R%i;", poprnd
);
1868 illegal_instruction_combination (cpu
);
1869 SET_DREG (poprnd
, cec_cli (cpu
));
1871 else if (prgfunc
== 4 && poprnd
< 8)
1873 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1874 TRACE_INSN (cpu
, "STI R%i;", poprnd
);
1876 illegal_instruction_combination (cpu
);
1877 cec_sti (cpu
, DREG (poprnd
));
1880 else if (prgfunc
== 5 && poprnd
< 8)
1882 bu32 newpc
= PREG (poprnd
);
1883 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1884 TRACE_INSN (cpu
, "JUMP (%s);", get_preg_name (poprnd
));
1885 IFETCH_CHECK (newpc
);
1887 illegal_instruction_combination (cpu
);
1888 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP (Preg)");
1890 BFIN_CPU_STATE
.did_jump
= true;
1891 PROFILE_BRANCH_TAKEN (cpu
);
1894 else if (prgfunc
== 6 && poprnd
< 8)
1896 bu32 newpc
= PREG (poprnd
);
1897 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1898 TRACE_INSN (cpu
, "CALL (%s);", get_preg_name (poprnd
));
1899 IFETCH_CHECK (newpc
);
1901 illegal_instruction_combination (cpu
);
1902 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "CALL (Preg)");
1903 /* If we're at the end of a hardware loop, RETS is going to be
1904 the top of the loop rather than the next instruction. */
1905 SET_RETSREG (hwloop_get_next_pc (cpu
, pc
, 2));
1907 BFIN_CPU_STATE
.did_jump
= true;
1908 PROFILE_BRANCH_TAKEN (cpu
);
1911 else if (prgfunc
== 7 && poprnd
< 8)
1913 bu32 newpc
= pc
+ PREG (poprnd
);
1914 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1915 TRACE_INSN (cpu
, "CALL (PC + %s);", get_preg_name (poprnd
));
1916 IFETCH_CHECK (newpc
);
1918 illegal_instruction_combination (cpu
);
1919 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "CALL (PC + Preg)");
1920 SET_RETSREG (hwloop_get_next_pc (cpu
, pc
, 2));
1922 BFIN_CPU_STATE
.did_jump
= true;
1923 PROFILE_BRANCH_TAKEN (cpu
);
1926 else if (prgfunc
== 8 && poprnd
< 8)
1928 bu32 newpc
= pc
+ PREG (poprnd
);
1929 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1930 TRACE_INSN (cpu
, "JUMP (PC + %s);", get_preg_name (poprnd
));
1931 IFETCH_CHECK (newpc
);
1933 illegal_instruction_combination (cpu
);
1934 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP (PC + Preg)");
1936 BFIN_CPU_STATE
.did_jump
= true;
1937 PROFILE_BRANCH_TAKEN (cpu
);
1940 else if (prgfunc
== 9)
1942 int raise
= uimm4 (poprnd
);
1943 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1944 TRACE_INSN (cpu
, "RAISE %s;", uimm4_str (raise
));
1946 illegal_instruction_combination (cpu
);
1947 cec_require_supervisor (cpu
);
1948 if (raise
== IVG_IVHW
)
1949 cec_hwerr (cpu
, HWERR_RAISE_5
);
1951 cec_latch (cpu
, raise
);
1952 CYCLE_DELAY
= 3; /* XXX: Only if IVG is unmasked. */
1954 else if (prgfunc
== 10)
1956 int excpt
= uimm4 (poprnd
);
1957 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1958 TRACE_INSN (cpu
, "EXCPT %s;", uimm4_str (excpt
));
1960 illegal_instruction_combination (cpu
);
1961 cec_exception (cpu
, excpt
);
1964 else if (prgfunc
== 11 && poprnd
< 6)
1966 bu32 addr
= PREG (poprnd
);
1968 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_atomic
);
1969 TRACE_INSN (cpu
, "TESTSET (%s);", get_preg_name (poprnd
));
1971 illegal_instruction_combination (cpu
);
1972 byte
= GET_WORD (addr
);
1973 SET_CCREG (byte
== 0);
1974 PUT_BYTE (addr
, byte
| 0x80);
1975 /* Also includes memory stalls, but we don't model that. */
1979 illegal_instruction (cpu
);
1983 decode_CaCTRL_0 (SIM_CPU
*cpu
, bu16 iw0
)
1986 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
1987 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 |.a.|.op....|.reg.......|
1988 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
1989 int a
= ((iw0
>> CaCTRL_a_bits
) & CaCTRL_a_mask
);
1990 int op
= ((iw0
>> CaCTRL_op_bits
) & CaCTRL_op_mask
);
1991 int reg
= ((iw0
>> CaCTRL_reg_bits
) & CaCTRL_reg_mask
);
1992 bu32 preg
= PREG (reg
);
1993 const char * const sinsn
[] = { "PREFETCH", "FLUSHINV", "FLUSH", "IFLUSH", };
1995 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CaCTRL
);
1996 TRACE_EXTRACT (cpu
, "%s: a:%i op:%i reg:%i", __func__
, a
, op
, reg
);
1997 TRACE_INSN (cpu
, "%s [%s%s];", sinsn
[op
], get_preg_name (reg
), a
? "++" : "");
2000 /* None of these can be part of a parallel instruction. */
2001 illegal_instruction_combination (cpu
);
2003 /* No cache simulation, so these are (mostly) all NOPs.
2004 XXX: The hardware takes care of masking to cache lines, but need
2005 to check behavior of the post increment. Should we be aligning
2006 the value to the cache line before adding the cache line size, or
2007 do we just add the cache line size ? */
2010 mmu_check_cache_addr (cpu
, preg
, false, false);
2014 mmu_check_cache_addr (cpu
, preg
, true, false);
2018 mmu_check_cache_addr (cpu
, preg
, true, false);
2022 mmu_check_cache_addr (cpu
, preg
, false, true);
2026 SET_PREG (reg
, preg
+ BFIN_L1_CACHE_BYTES
);
2030 decode_PushPopReg_0 (SIM_CPU
*cpu
, bu16 iw0
)
2033 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2034 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |.W.|.grp.......|.reg.......|
2035 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2036 int W
= ((iw0
>> PushPopReg_W_bits
) & PushPopReg_W_mask
);
2037 int grp
= ((iw0
>> PushPopReg_grp_bits
) & PushPopReg_grp_mask
);
2038 int reg
= ((iw0
>> PushPopReg_reg_bits
) & PushPopReg_reg_mask
);
2039 const char *reg_name
= get_allreg_name (grp
, reg
);
2043 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_PushPopReg
);
2044 TRACE_EXTRACT (cpu
, "%s: W:%i grp:%i reg:%i", __func__
, W
, grp
, reg
);
2045 TRACE_DECODE (cpu
, "%s: reg:%s", __func__
, reg_name
);
2047 /* Can't push/pop reserved registers */
2048 if (reg_is_reserved (grp
, reg
))
2049 illegal_instruction (cpu
);
2053 /* Dreg and Preg are not supported by this instruction. */
2054 if (grp
== 0 || grp
== 1)
2055 illegal_instruction (cpu
);
2056 TRACE_INSN (cpu
, "%s = [SP++];", reg_name
);
2057 /* Can't pop USP while in userspace. */
2058 if (INSN_LEN
== 8 || (grp
== 7 && reg
== 0 && cec_is_user_mode(cpu
)))
2059 illegal_instruction_combination (cpu
);
2060 /* XXX: The valid register check is in reg_write(), so we might
2061 incorrectly do a GET_LONG() here ... */
2062 value
= GET_LONG (sp
);
2063 reg_write (cpu
, grp
, reg
, value
);
2064 if (grp
== 7 && reg
== 3)
2071 TRACE_INSN (cpu
, "[--SP] = %s;", reg_name
);
2073 illegal_instruction_combination (cpu
);
2076 value
= reg_read (cpu
, grp
, reg
);
2077 if (grp
== 7 && reg
== 3)
2078 cec_push_reti (cpu
);
2080 PUT_LONG (sp
, value
);
2083 /* Note: SP update must be delayed until after all reads/writes; see
2084 comments in decode_PushPopMultiple_0() for more info. */
2089 decode_PushPopMultiple_0 (SIM_CPU
*cpu
, bu16 iw0
)
2092 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2093 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |.d.|.p.|.W.|.dr........|.pr........|
2094 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2095 int p
= ((iw0
>> PushPopMultiple_p_bits
) & PushPopMultiple_p_mask
);
2096 int d
= ((iw0
>> PushPopMultiple_d_bits
) & PushPopMultiple_d_mask
);
2097 int W
= ((iw0
>> PushPopMultiple_W_bits
) & PushPopMultiple_W_mask
);
2098 int dr
= ((iw0
>> PushPopMultiple_dr_bits
) & PushPopMultiple_dr_mask
);
2099 int pr
= ((iw0
>> PushPopMultiple_pr_bits
) & PushPopMultiple_pr_mask
);
2103 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_PushPopMultiple
);
2104 TRACE_EXTRACT (cpu
, "%s: d:%i p:%i W:%i dr:%i pr:%i",
2105 __func__
, d
, p
, W
, dr
, pr
);
2107 if ((d
== 0 && p
== 0) || (p
&& imm5 (pr
) > 5)
2108 || (d
&& !p
&& pr
) || (p
&& !d
&& dr
))
2109 illegal_instruction (cpu
);
2114 TRACE_INSN (cpu
, "[--SP] = (R7:%i, P5:%i);", dr
, pr
);
2116 TRACE_INSN (cpu
, "[--SP] = (R7:%i);", dr
);
2118 TRACE_INSN (cpu
, "[--SP] = (P5:%i);", pr
);
2121 for (i
= dr
; i
< 8; i
++)
2124 PUT_LONG (sp
, DREG (i
));
2127 for (i
= pr
; i
< 6; i
++)
2130 PUT_LONG (sp
, PREG (i
));
2138 TRACE_INSN (cpu
, "(R7:%i, P5:%i) = [SP++];", dr
, pr
);
2140 TRACE_INSN (cpu
, "(R7:%i) = [SP++];", dr
);
2142 TRACE_INSN (cpu
, "(P5:%i) = [SP++];", pr
);
2145 for (i
= 5; i
>= pr
; i
--)
2147 SET_PREG (i
, GET_LONG (sp
));
2151 for (i
= 7; i
>= dr
; i
--)
2153 SET_DREG (i
, GET_LONG (sp
));
2160 /* Note: SP update must be delayed until after all reads/writes so that
2161 if an exception does occur, the insn may be re-executed as the
2162 SP has not yet changed. */
2167 decode_ccMV_0 (SIM_CPU
*cpu
, bu16 iw0
)
2170 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2171 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |.T.|.d.|.s.|.dst.......|.src.......|
2172 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2173 int s
= ((iw0
>> CCmv_s_bits
) & CCmv_s_mask
);
2174 int d
= ((iw0
>> CCmv_d_bits
) & CCmv_d_mask
);
2175 int T
= ((iw0
>> CCmv_T_bits
) & CCmv_T_mask
);
2176 int src
= ((iw0
>> CCmv_src_bits
) & CCmv_src_mask
);
2177 int dst
= ((iw0
>> CCmv_dst_bits
) & CCmv_dst_mask
);
2178 int cond
= T
? CCREG
: ! CCREG
;
2180 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ccMV
);
2181 TRACE_EXTRACT (cpu
, "%s: T:%i d:%i s:%i dst:%i src:%i",
2182 __func__
, T
, d
, s
, dst
, src
);
2184 TRACE_INSN (cpu
, "IF %sCC %s = %s;", T
? "" : "! ",
2185 get_allreg_name (d
, dst
),
2186 get_allreg_name (s
, src
));
2188 illegal_instruction_combination (cpu
);
2191 reg_write (cpu
, d
, dst
, reg_read (cpu
, s
, src
));
2195 decode_CCflag_0 (SIM_CPU
*cpu
, bu16 iw0
)
2198 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2199 | 0 | 0 | 0 | 0 | 1 |.I.|.opc.......|.G.|.y.........|.x.........|
2200 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2201 int x
= ((iw0
>> CCflag_x_bits
) & CCflag_x_mask
);
2202 int y
= ((iw0
>> CCflag_y_bits
) & CCflag_y_mask
);
2203 int I
= ((iw0
>> CCflag_I_bits
) & CCflag_I_mask
);
2204 int G
= ((iw0
>> CCflag_G_bits
) & CCflag_G_mask
);
2205 int opc
= ((iw0
>> CCflag_opc_bits
) & CCflag_opc_mask
);
2207 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CCflag
);
2208 TRACE_EXTRACT (cpu
, "%s: I:%i opc:%i G:%i y:%i x:%i",
2209 __func__
, I
, opc
, G
, y
, x
);
2213 bs64 acc0
= get_extended_acc (cpu
, 0);
2214 bs64 acc1
= get_extended_acc (cpu
, 1);
2215 bs64 diff
= acc0
- acc1
;
2217 if (x
!= 0 || y
!= 0)
2218 illegal_instruction (cpu
);
2220 if (opc
== 5 && I
== 0 && G
== 0)
2222 TRACE_INSN (cpu
, "CC = A0 == A1;");
2224 illegal_instruction_combination (cpu
);
2225 SET_CCREG (acc0
== acc1
);
2227 else if (opc
== 6 && I
== 0 && G
== 0)
2229 TRACE_INSN (cpu
, "CC = A0 < A1");
2231 illegal_instruction_combination (cpu
);
2232 SET_CCREG (acc0
< acc1
);
2234 else if (opc
== 7 && I
== 0 && G
== 0)
2236 TRACE_INSN (cpu
, "CC = A0 <= A1");
2238 illegal_instruction_combination (cpu
);
2239 SET_CCREG (acc0
<= acc1
);
2242 illegal_instruction (cpu
);
2244 SET_ASTATREG (az
, diff
== 0);
2245 SET_ASTATREG (an
, diff
< 0);
2246 SET_ASTATREG (ac0
, (bu40
)acc1
<= (bu40
)acc0
);
2250 int issigned
= opc
< 3;
2251 const char *sign
= issigned
? "" : " (IU)";
2252 bu32 srcop
= G
? PREG (x
) : DREG (x
);
2253 char s
= G
? 'P' : 'R';
2254 bu32 dstop
= I
? (issigned
? imm3 (y
) : uimm3 (y
)) : G
? PREG (y
) : DREG (y
);
2256 char d
= G
? 'P' : 'R';
2257 int flgs
= srcop
>> 31;
2258 int flgo
= dstop
>> 31;
2260 bu32 result
= srcop
- dstop
;
2262 int flgn
= result
>> 31;
2263 int overflow
= (flgs
^ flgo
) & (flgn
^ flgs
);
2264 int az
= result
== 0;
2265 int ac0
= dstop
<= srcop
;
2268 an
= (flgn
&& !overflow
) || (!flgn
&& overflow
);
2274 default: /* Shutup useless gcc warnings. */
2275 case 0: /* signed */
2279 case 1: /* signed */
2283 case 2: /* signed */
2287 case 3: /* unsigned */
2291 case 4: /* unsigned */
2298 TRACE_INSN (cpu
, "CC = %c%i %s %s%s;", s
, x
, op
,
2299 issigned
? imm3_str (y
) : uimm3_str (y
), sign
);
2302 TRACE_DECODE (cpu
, "%s %c%i:%x %c%i:%x", __func__
,
2303 s
, x
, srcop
, d
, y
, dstop
);
2304 TRACE_INSN (cpu
, "CC = %c%i %s %c%i%s;", s
, x
, op
, d
, y
, sign
);
2308 /* Pointer compares only touch CC. */
2311 SET_ASTATREG (az
, az
);
2312 SET_ASTATREG (an
, an
);
2313 SET_ASTATREG (ac0
, ac0
);
2319 decode_CC2dreg_0 (SIM_CPU
*cpu
, bu16 iw0
)
2322 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2323 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |.op....|.reg.......|
2324 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2325 int op
= ((iw0
>> CC2dreg_op_bits
) & CC2dreg_op_mask
);
2326 int reg
= ((iw0
>> CC2dreg_reg_bits
) & CC2dreg_reg_mask
);
2328 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CC2dreg
);
2329 TRACE_EXTRACT (cpu
, "%s: op:%i reg:%i", __func__
, op
, reg
);
2333 TRACE_INSN (cpu
, "R%i = CC;", reg
);
2335 illegal_instruction_combination (cpu
);
2336 SET_DREG (reg
, CCREG
);
2340 TRACE_INSN (cpu
, "CC = R%i;", reg
);
2342 illegal_instruction_combination (cpu
);
2343 SET_CCREG (DREG (reg
) != 0);
2345 else if (op
== 3 && reg
== 0)
2347 TRACE_INSN (cpu
, "CC = !CC;");
2349 illegal_instruction_combination (cpu
);
2353 illegal_instruction (cpu
);
2357 decode_CC2stat_0 (SIM_CPU
*cpu
, bu16 iw0
)
2360 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2361 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |.D.|.op....|.cbit..............|
2362 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2363 int D
= ((iw0
>> CC2stat_D_bits
) & CC2stat_D_mask
);
2364 int op
= ((iw0
>> CC2stat_op_bits
) & CC2stat_op_mask
);
2365 int cbit
= ((iw0
>> CC2stat_cbit_bits
) & CC2stat_cbit_mask
);
2368 const char * const op_names
[] = { "", "|", "&", "^" } ;
2370 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CC2stat
);
2371 TRACE_EXTRACT (cpu
, "%s: D:%i op:%i cbit:%i", __func__
, D
, op
, cbit
);
2373 TRACE_INSN (cpu
, "%s %s= %s;", D
? astat_names
[cbit
] : "CC",
2374 op_names
[op
], D
? "CC" : astat_names
[cbit
]);
2376 /* CC = CC; is invalid. */
2378 illegal_instruction (cpu
);
2381 illegal_instruction_combination (cpu
);
2383 pval
= !!(ASTAT
& (1 << cbit
));
2387 case 0: SET_CCREG (pval
); break;
2388 case 1: SET_CCREG (CCREG
| pval
); break;
2389 case 2: SET_CCREG (CCREG
& pval
); break;
2390 case 3: SET_CCREG (CCREG
^ pval
); break;
2396 case 0: pval
= CCREG
; break;
2397 case 1: pval
|= CCREG
; break;
2398 case 2: pval
&= CCREG
; break;
2399 case 3: pval
^= CCREG
; break;
2401 TRACE_REGISTER (cpu
, "wrote ASTAT[%s] = %i", astat_names
[cbit
], pval
);
2402 SET_ASTAT ((ASTAT
& ~(1 << cbit
)) | (pval
<< cbit
));
2407 decode_BRCC_0 (SIM_CPU
*cpu
, bu16 iw0
, bu32 pc
)
2410 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2411 | 0 | 0 | 0 | 1 |.T.|.B.|.offset................................|
2412 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2413 int B
= ((iw0
>> BRCC_B_bits
) & BRCC_B_mask
);
2414 int T
= ((iw0
>> BRCC_T_bits
) & BRCC_T_mask
);
2415 int offset
= ((iw0
>> BRCC_offset_bits
) & BRCC_offset_mask
);
2416 int cond
= T
? CCREG
: ! CCREG
;
2417 int pcrel
= pcrel10 (offset
);
2419 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_BRCC
);
2420 TRACE_EXTRACT (cpu
, "%s: T:%i B:%i offset:%#x", __func__
, T
, B
, offset
);
2421 TRACE_DECODE (cpu
, "%s: pcrel10:%#x", __func__
, pcrel
);
2423 TRACE_INSN (cpu
, "IF %sCC JUMP %#x%s;", T
? "" : "! ",
2424 pcrel
, B
? " (bp)" : "");
2427 illegal_instruction_combination (cpu
);
2431 bu32 newpc
= pc
+ pcrel
;
2432 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "Conditional JUMP");
2434 BFIN_CPU_STATE
.did_jump
= true;
2435 PROFILE_BRANCH_TAKEN (cpu
);
2436 CYCLE_DELAY
= B
? 5 : 9;
2440 PROFILE_BRANCH_UNTAKEN (cpu
);
2441 CYCLE_DELAY
= B
? 9 : 1;
2446 decode_UJUMP_0 (SIM_CPU
*cpu
, bu16 iw0
, bu32 pc
)
2449 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2450 | 0 | 0 | 1 | 0 |.offset........................................|
2451 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2452 int offset
= ((iw0
>> UJump_offset_bits
) & UJump_offset_mask
);
2453 int pcrel
= pcrel12 (offset
);
2454 bu32 newpc
= pc
+ pcrel
;
2456 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_UJUMP
);
2457 TRACE_EXTRACT (cpu
, "%s: offset:%#x", __func__
, offset
);
2458 TRACE_DECODE (cpu
, "%s: pcrel12:%#x", __func__
, pcrel
);
2460 TRACE_INSN (cpu
, "JUMP.S %#x;", pcrel
);
2463 illegal_instruction_combination (cpu
);
2465 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP.S");
2468 BFIN_CPU_STATE
.did_jump
= true;
2469 PROFILE_BRANCH_TAKEN (cpu
);
2474 decode_REGMV_0 (SIM_CPU
*cpu
, bu16 iw0
)
2477 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2478 | 0 | 0 | 1 | 1 |.gd........|.gs........|.dst.......|.src.......|
2479 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2480 int gs
= ((iw0
>> RegMv_gs_bits
) & RegMv_gs_mask
);
2481 int gd
= ((iw0
>> RegMv_gd_bits
) & RegMv_gd_mask
);
2482 int src
= ((iw0
>> RegMv_src_bits
) & RegMv_src_mask
);
2483 int dst
= ((iw0
>> RegMv_dst_bits
) & RegMv_dst_mask
);
2484 const char *srcreg_name
= get_allreg_name (gs
, src
);
2485 const char *dstreg_name
= get_allreg_name (gd
, dst
);
2487 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_REGMV
);
2488 TRACE_EXTRACT (cpu
, "%s: gd:%i gs:%i dst:%i src:%i",
2489 __func__
, gd
, gs
, dst
, src
);
2490 TRACE_DECODE (cpu
, "%s: dst:%s src:%s", __func__
, dstreg_name
, srcreg_name
);
2492 TRACE_INSN (cpu
, "%s = %s;", dstreg_name
, srcreg_name
);
2494 /* Reserved slots cannot be a src/dst. */
2495 if (reg_is_reserved (gs
, src
) || reg_is_reserved (gd
, dst
))
2498 /* Standard register moves. */
2499 if ((gs
< 2) /* Dregs/Pregs src */
2500 || (gd
< 2) /* Dregs/Pregs dst */
2501 || (gs
== 4 && src
< 4) /* Accumulators src */
2502 || (gd
== 4 && dst
< 4 && (gs
< 4)) /* Accumulators dst */
2503 || (gs
== 7 && src
== 7 && !(gd
== 4 && dst
< 4)) /* EMUDAT src */
2504 || (gd
== 7 && dst
== 7)) /* EMUDAT dst */
2507 /* dareg = dareg (IMBL) */
2508 if (gs
< 4 && gd
< 4)
2511 /* USP can be src to sysregs, but not dagregs. */
2512 if ((gs
== 7 && src
== 0) && (gd
>= 4))
2515 /* USP can move between genregs (only check Accumulators). */
2516 if (((gs
== 7 && src
== 0) && (gd
== 4 && dst
< 4))
2517 || ((gd
== 7 && dst
== 0) && (gs
== 4 && src
< 4)))
2520 /* Still here ? Invalid reg pair. */
2522 illegal_instruction (cpu
);
2525 reg_write (cpu
, gd
, dst
, reg_read (cpu
, gs
, src
));
2529 decode_ALU2op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2532 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2533 | 0 | 1 | 0 | 0 | 0 | 0 |.opc...........|.src.......|.dst.......|
2534 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2535 int src
= ((iw0
>> ALU2op_src_bits
) & ALU2op_src_mask
);
2536 int opc
= ((iw0
>> ALU2op_opc_bits
) & ALU2op_opc_mask
);
2537 int dst
= ((iw0
>> ALU2op_dst_bits
) & ALU2op_dst_mask
);
2539 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ALU2op
);
2540 TRACE_EXTRACT (cpu
, "%s: opc:%i src:%i dst:%i", __func__
, opc
, src
, dst
);
2544 TRACE_INSN (cpu
, "R%i >>>= R%i;", dst
, src
);
2545 SET_DREG (dst
, ashiftrt (cpu
, DREG (dst
), DREG (src
), 32));
2550 TRACE_INSN (cpu
, "R%i >>= R%i;", dst
, src
);
2551 if (DREG (src
) <= 0x1F)
2552 val
= lshiftrt (cpu
, DREG (dst
), DREG (src
), 32);
2555 SET_DREG (dst
, val
);
2559 TRACE_INSN (cpu
, "R%i <<= R%i;", dst
, src
);
2560 SET_DREG (dst
, lshift (cpu
, DREG (dst
), DREG (src
), 32, 0));
2564 TRACE_INSN (cpu
, "R%i *= R%i;", dst
, src
);
2565 SET_DREG (dst
, DREG (dst
) * DREG (src
));
2570 TRACE_INSN (cpu
, "R%i = (R%i + R%i) << 1;", dst
, dst
, src
);
2571 SET_DREG (dst
, add_and_shift (cpu
, DREG (dst
), DREG (src
), 1));
2575 TRACE_INSN (cpu
, "R%i = (R%i + R%i) << 2;", dst
, dst
, src
);
2576 SET_DREG (dst
, add_and_shift (cpu
, DREG (dst
), DREG (src
), 2));
2580 TRACE_INSN (cpu
, "DIVQ ( R%i, R%i );", dst
, src
);
2581 SET_DREG (dst
, divq (cpu
, DREG (dst
), (bu16
)DREG (src
)));
2585 TRACE_INSN (cpu
, "DIVS ( R%i, R%i );", dst
, src
);
2586 SET_DREG (dst
, divs (cpu
, DREG (dst
), (bu16
)DREG (src
)));
2590 TRACE_INSN (cpu
, "R%i = R%i.L (X);", dst
, src
);
2591 SET_DREG (dst
, (bs32
) (bs16
) DREG (src
));
2592 setflags_logical (cpu
, DREG (dst
));
2596 TRACE_INSN (cpu
, "R%i = R%i.L (Z);", dst
, src
);
2597 SET_DREG (dst
, (bu32
) (bu16
) DREG (src
));
2598 setflags_logical (cpu
, DREG (dst
));
2602 TRACE_INSN (cpu
, "R%i = R%i.B (X);", dst
, src
);
2603 SET_DREG (dst
, (bs32
) (bs8
) DREG (src
));
2604 setflags_logical (cpu
, DREG (dst
));
2608 TRACE_INSN (cpu
, "R%i = R%i.B (Z);", dst
, src
);
2609 SET_DREG (dst
, (bu32
) (bu8
) DREG (src
));
2610 setflags_logical (cpu
, DREG (dst
));
2614 bu32 val
= DREG (src
);
2615 TRACE_INSN (cpu
, "R%i = - R%i;", dst
, src
);
2616 SET_DREG (dst
, -val
);
2617 setflags_nz (cpu
, DREG (dst
));
2618 SET_ASTATREG (v
, val
== 0x80000000);
2620 SET_ASTATREG (vs
, 1);
2621 SET_ASTATREG (ac0
, val
== 0x0);
2622 /* XXX: Documentation isn't entirely clear about av0 and av1. */
2626 TRACE_INSN (cpu
, "R%i = ~ R%i;", dst
, src
);
2627 SET_DREG (dst
, ~DREG (src
));
2628 setflags_logical (cpu
, DREG (dst
));
2631 illegal_instruction (cpu
);
2635 decode_PTR2op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2638 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2639 | 0 | 1 | 0 | 0 | 0 | 1 | 0 |.opc.......|.src.......|.dst.......|
2640 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2641 int src
= ((iw0
>> PTR2op_src_bits
) & PTR2op_dst_mask
);
2642 int opc
= ((iw0
>> PTR2op_opc_bits
) & PTR2op_opc_mask
);
2643 int dst
= ((iw0
>> PTR2op_dst_bits
) & PTR2op_dst_mask
);
2644 const char *src_name
= get_preg_name (src
);
2645 const char *dst_name
= get_preg_name (dst
);
2647 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_PTR2op
);
2648 TRACE_EXTRACT (cpu
, "%s: opc:%i src:%i dst:%i", __func__
, opc
, src
, dst
);
2652 TRACE_INSN (cpu
, "%s -= %s", dst_name
, src_name
);
2653 SET_PREG (dst
, PREG (dst
) - PREG (src
));
2657 TRACE_INSN (cpu
, "%s = %s << 2", dst_name
, src_name
);
2658 SET_PREG (dst
, PREG (src
) << 2);
2662 TRACE_INSN (cpu
, "%s = %s >> 2", dst_name
, src_name
);
2663 SET_PREG (dst
, PREG (src
) >> 2);
2667 TRACE_INSN (cpu
, "%s = %s >> 1", dst_name
, src_name
);
2668 SET_PREG (dst
, PREG (src
) >> 1);
2672 TRACE_INSN (cpu
, "%s += %s (BREV)", dst_name
, src_name
);
2673 SET_PREG (dst
, add_brev (PREG (dst
), PREG (src
)));
2677 TRACE_INSN (cpu
, "%s = (%s + %s) << 1", dst_name
, dst_name
, src_name
);
2678 SET_PREG (dst
, (PREG (dst
) + PREG (src
)) << 1);
2682 TRACE_INSN (cpu
, "%s = (%s + %s) << 2", dst_name
, dst_name
, src_name
);
2683 SET_PREG (dst
, (PREG (dst
) + PREG (src
)) << 2);
2686 illegal_instruction (cpu
);
2690 decode_LOGI2op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2693 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2694 | 0 | 1 | 0 | 0 | 1 |.opc.......|.src...............|.dst.......|
2695 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2696 int src
= ((iw0
>> LOGI2op_src_bits
) & LOGI2op_src_mask
);
2697 int opc
= ((iw0
>> LOGI2op_opc_bits
) & LOGI2op_opc_mask
);
2698 int dst
= ((iw0
>> LOGI2op_dst_bits
) & LOGI2op_dst_mask
);
2699 int uimm
= uimm5 (src
);
2700 const char *uimm_str
= uimm5_str (uimm
);
2702 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LOGI2op
);
2703 TRACE_EXTRACT (cpu
, "%s: opc:%i src:%i dst:%i", __func__
, opc
, src
, dst
);
2704 TRACE_DECODE (cpu
, "%s: uimm5:%#x", __func__
, uimm
);
2708 TRACE_INSN (cpu
, "CC = ! BITTST (R%i, %s);", dst
, uimm_str
);
2710 illegal_instruction_combination (cpu
);
2711 SET_CCREG ((~DREG (dst
) >> uimm
) & 1);
2715 TRACE_INSN (cpu
, "CC = BITTST (R%i, %s);", dst
, uimm_str
);
2717 illegal_instruction_combination (cpu
);
2718 SET_CCREG ((DREG (dst
) >> uimm
) & 1);
2722 TRACE_INSN (cpu
, "BITSET (R%i, %s);", dst
, uimm_str
);
2724 illegal_instruction_combination (cpu
);
2725 SET_DREG (dst
, DREG (dst
) | (1 << uimm
));
2726 setflags_logical (cpu
, DREG (dst
));
2730 TRACE_INSN (cpu
, "BITTGL (R%i, %s);", dst
, uimm_str
);
2732 illegal_instruction_combination (cpu
);
2733 SET_DREG (dst
, DREG (dst
) ^ (1 << uimm
));
2734 setflags_logical (cpu
, DREG (dst
));
2738 TRACE_INSN (cpu
, "BITCLR (R%i, %s);", dst
, uimm_str
);
2740 illegal_instruction_combination (cpu
);
2741 SET_DREG (dst
, DREG (dst
) & ~(1 << uimm
));
2742 setflags_logical (cpu
, DREG (dst
));
2746 TRACE_INSN (cpu
, "R%i >>>= %s;", dst
, uimm_str
);
2748 illegal_instruction_combination (cpu
);
2749 SET_DREG (dst
, ashiftrt (cpu
, DREG (dst
), uimm
, 32));
2753 TRACE_INSN (cpu
, "R%i >>= %s;", dst
, uimm_str
);
2755 illegal_instruction_combination (cpu
);
2756 SET_DREG (dst
, lshiftrt (cpu
, DREG (dst
), uimm
, 32));
2760 TRACE_INSN (cpu
, "R%i <<= %s;", dst
, uimm_str
);
2762 illegal_instruction_combination (cpu
);
2763 SET_DREG (dst
, lshift (cpu
, DREG (dst
), uimm
, 32, 0));
2768 decode_COMP3op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2771 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2772 | 0 | 1 | 0 | 1 |.opc.......|.dst.......|.src1......|.src0......|
2773 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2774 int opc
= ((iw0
>> COMP3op_opc_bits
) & COMP3op_opc_mask
);
2775 int dst
= ((iw0
>> COMP3op_dst_bits
) & COMP3op_dst_mask
);
2776 int src0
= ((iw0
>> COMP3op_src0_bits
) & COMP3op_src0_mask
);
2777 int src1
= ((iw0
>> COMP3op_src1_bits
) & COMP3op_src1_mask
);
2779 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_COMP3op
);
2780 TRACE_EXTRACT (cpu
, "%s: opc:%i dst:%i src1:%i src0:%i",
2781 __func__
, opc
, dst
, src1
, src0
);
2785 TRACE_INSN (cpu
, "R%i = R%i + R%i;", dst
, src0
, src1
);
2786 SET_DREG (dst
, add32 (cpu
, DREG (src0
), DREG (src1
), 1, 0));
2790 TRACE_INSN (cpu
, "R%i = R%i - R%i;", dst
, src0
, src1
);
2791 SET_DREG (dst
, sub32 (cpu
, DREG (src0
), DREG (src1
), 1, 0, 0));
2795 TRACE_INSN (cpu
, "R%i = R%i & R%i;", dst
, src0
, src1
);
2796 SET_DREG (dst
, DREG (src0
) & DREG (src1
));
2797 setflags_logical (cpu
, DREG (dst
));
2801 TRACE_INSN (cpu
, "R%i = R%i | R%i;", dst
, src0
, src1
);
2802 SET_DREG (dst
, DREG (src0
) | DREG (src1
));
2803 setflags_logical (cpu
, DREG (dst
));
2807 TRACE_INSN (cpu
, "R%i = R%i ^ R%i;", dst
, src0
, src1
);
2808 SET_DREG (dst
, DREG (src0
) ^ DREG (src1
));
2809 setflags_logical (cpu
, DREG (dst
));
2813 int shift
= opc
- 5;
2814 const char *dst_name
= get_preg_name (dst
);
2815 const char *src0_name
= get_preg_name (src0
);
2816 const char *src1_name
= get_preg_name (src1
);
2818 /* If src0 == src1 this is disassembled as a shift by 1, but this
2819 distinction doesn't matter for our purposes. */
2821 TRACE_INSN (cpu
, "%s = (%s + %s) << %#x;",
2822 dst_name
, src0_name
, src1_name
, shift
);
2824 TRACE_INSN (cpu
, "%s = %s + %s",
2825 dst_name
, src0_name
, src1_name
);
2826 SET_PREG (dst
, PREG (src0
) + (PREG (src1
) << shift
));
2831 decode_COMPI2opD_0 (SIM_CPU
*cpu
, bu16 iw0
)
2834 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2835 | 0 | 1 | 1 | 0 | 0 |.op|..src......................|.dst.......|
2836 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2837 int op
= ((iw0
>> COMPI2opD_op_bits
) & COMPI2opD_op_mask
);
2838 int dst
= ((iw0
>> COMPI2opD_dst_bits
) & COMPI2opD_dst_mask
);
2839 int src
= ((iw0
>> COMPI2opD_src_bits
) & COMPI2opD_src_mask
);
2840 int imm
= imm7 (src
);
2842 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_COMPI2opD
);
2843 TRACE_EXTRACT (cpu
, "%s: op:%i src:%i dst:%i", __func__
, op
, src
, dst
);
2844 TRACE_DECODE (cpu
, "%s: imm7:%#x", __func__
, imm
);
2848 TRACE_INSN (cpu
, "R%i = %s (X);", dst
, imm7_str (imm
));
2849 SET_DREG (dst
, imm
);
2853 TRACE_INSN (cpu
, "R%i += %s;", dst
, imm7_str (imm
));
2854 SET_DREG (dst
, add32 (cpu
, DREG (dst
), imm
, 1, 0));
2859 decode_COMPI2opP_0 (SIM_CPU
*cpu
, bu16 iw0
)
2862 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2863 | 0 | 1 | 1 | 0 | 1 |.op|.src.......................|.dst.......|
2864 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2865 int op
= ((iw0
>> COMPI2opP_op_bits
) & COMPI2opP_op_mask
);
2866 int src
= ((iw0
>> COMPI2opP_src_bits
) & COMPI2opP_src_mask
);
2867 int dst
= ((iw0
>> COMPI2opP_dst_bits
) & COMPI2opP_dst_mask
);
2868 int imm
= imm7 (src
);
2869 const char *dst_name
= get_preg_name (dst
);
2871 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_COMPI2opP
);
2872 TRACE_EXTRACT (cpu
, "%s: op:%i src:%i dst:%i", __func__
, op
, src
, dst
);
2873 TRACE_DECODE (cpu
, "%s: imm:%#x", __func__
, imm
);
2877 TRACE_INSN (cpu
, "%s = %s;", dst_name
, imm7_str (imm
));
2878 SET_PREG (dst
, imm
);
2882 TRACE_INSN (cpu
, "%s += %s;", dst_name
, imm7_str (imm
));
2883 SET_PREG (dst
, PREG (dst
) + imm
);
2888 decode_LDSTpmod_0 (SIM_CPU
*cpu
, bu16 iw0
)
2891 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2892 | 1 | 0 | 0 | 0 |.W.|.aop...|.reg.......|.idx.......|.ptr.......|
2893 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2894 int W
= ((iw0
>> LDSTpmod_W_bits
) & LDSTpmod_W_mask
);
2895 int aop
= ((iw0
>> LDSTpmod_aop_bits
) & LDSTpmod_aop_mask
);
2896 int idx
= ((iw0
>> LDSTpmod_idx_bits
) & LDSTpmod_idx_mask
);
2897 int ptr
= ((iw0
>> LDSTpmod_ptr_bits
) & LDSTpmod_ptr_mask
);
2898 int reg
= ((iw0
>> LDSTpmod_reg_bits
) & LDSTpmod_reg_mask
);
2899 const char *ptr_name
= get_preg_name (ptr
);
2900 const char *idx_name
= get_preg_name (idx
);
2903 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTpmod
);
2904 TRACE_EXTRACT (cpu
, "%s: W:%i aop:%i reg:%i idx:%i ptr:%i",
2905 __func__
, W
, aop
, reg
, idx
, ptr
);
2907 if (aop
== 1 && W
== 0 && idx
== ptr
)
2909 TRACE_INSN (cpu
, "R%i.L = W[%s];", reg
, ptr_name
);
2911 val
= GET_WORD (addr
);
2912 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | val
);
2914 else if (aop
== 2 && W
== 0 && idx
== ptr
)
2916 TRACE_INSN (cpu
, "R%i.H = W[%s];", reg
, ptr_name
);
2918 val
= GET_WORD (addr
);
2919 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (val
<< 16));
2921 else if (aop
== 1 && W
== 1 && idx
== ptr
)
2923 TRACE_INSN (cpu
, "W[%s] = R%i.L;", ptr_name
, reg
);
2925 PUT_WORD (addr
, DREG (reg
));
2927 else if (aop
== 2 && W
== 1 && idx
== ptr
)
2929 TRACE_INSN (cpu
, "W[%s] = R%i.H;", ptr_name
, reg
);
2931 PUT_WORD (addr
, DREG (reg
) >> 16);
2933 else if (aop
== 0 && W
== 0)
2935 TRACE_INSN (cpu
, "R%i = [%s ++ %s];", reg
, ptr_name
, idx_name
);
2937 val
= GET_LONG (addr
);
2938 STORE (DREG (reg
), val
);
2940 STORE (PREG (ptr
), addr
+ PREG (idx
));
2942 else if (aop
== 1 && W
== 0)
2944 TRACE_INSN (cpu
, "R%i.L = W[%s ++ %s];", reg
, ptr_name
, idx_name
);
2946 val
= GET_WORD (addr
);
2947 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | val
);
2949 STORE (PREG (ptr
), addr
+ PREG (idx
));
2951 else if (aop
== 2 && W
== 0)
2953 TRACE_INSN (cpu
, "R%i.H = W[%s ++ %s];", reg
, ptr_name
, idx_name
);
2955 val
= GET_WORD (addr
);
2956 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (val
<< 16));
2958 STORE (PREG (ptr
), addr
+ PREG (idx
));
2960 else if (aop
== 3 && W
== 0)
2962 TRACE_INSN (cpu
, "R%i = W[%s ++ %s] (Z);", reg
, ptr_name
, idx_name
);
2964 val
= GET_WORD (addr
);
2965 STORE (DREG (reg
), val
);
2967 STORE (PREG (ptr
), addr
+ PREG (idx
));
2969 else if (aop
== 3 && W
== 1)
2971 TRACE_INSN (cpu
, "R%i = W[%s ++ %s] (X);", reg
, ptr_name
, idx_name
);
2973 val
= GET_WORD (addr
);
2974 STORE (DREG (reg
), (bs32
) (bs16
) val
);
2976 STORE (PREG (ptr
), addr
+ PREG (idx
));
2978 else if (aop
== 0 && W
== 1)
2980 TRACE_INSN (cpu
, "[%s ++ %s] = R%i;", ptr_name
, idx_name
, reg
);
2982 PUT_LONG (addr
, DREG (reg
));
2984 STORE (PREG (ptr
), addr
+ PREG (idx
));
2986 else if (aop
== 1 && W
== 1)
2988 TRACE_INSN (cpu
, "W[%s ++ %s] = R%i.L;", ptr_name
, idx_name
, reg
);
2990 PUT_WORD (addr
, DREG (reg
));
2992 STORE (PREG (ptr
), addr
+ PREG (idx
));
2994 else if (aop
== 2 && W
== 1)
2996 TRACE_INSN (cpu
, "W[%s ++ %s] = R%i.H;", ptr_name
, idx_name
, reg
);
2998 PUT_WORD (addr
, DREG (reg
) >> 16);
3000 STORE (PREG (ptr
), addr
+ PREG (idx
));
3003 illegal_instruction (cpu
);
3007 decode_dagMODim_0 (SIM_CPU
*cpu
, bu16 iw0
)
3010 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3011 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 0 |.br| 1 | 1 |.op|.m.....|.i.....|
3012 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3013 int i
= ((iw0
>> DagMODim_i_bits
) & DagMODim_i_mask
);
3014 int m
= ((iw0
>> DagMODim_m_bits
) & DagMODim_m_mask
);
3015 int br
= ((iw0
>> DagMODim_br_bits
) & DagMODim_br_mask
);
3016 int op
= ((iw0
>> DagMODim_op_bits
) & DagMODim_op_mask
);
3018 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dagMODim
);
3019 TRACE_EXTRACT (cpu
, "%s: br:%i op:%i m:%i i:%i", __func__
, br
, op
, m
, i
);
3021 if (op
== 0 && br
== 1)
3023 TRACE_INSN (cpu
, "I%i += M%i (BREV);", i
, m
);
3024 SET_IREG (i
, add_brev (IREG (i
), MREG (m
)));
3028 TRACE_INSN (cpu
, "I%i += M%i;", i
, m
);
3029 dagadd (cpu
, i
, MREG (m
));
3031 else if (op
== 1 && br
== 0)
3033 TRACE_INSN (cpu
, "I%i -= M%i;", i
, m
);
3034 dagsub (cpu
, i
, MREG (m
));
3037 illegal_instruction (cpu
);
3041 decode_dagMODik_0 (SIM_CPU
*cpu
, bu16 iw0
)
3044 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3045 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 0 |.op....|.i.....|
3046 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3047 int i
= ((iw0
>> DagMODik_i_bits
) & DagMODik_i_mask
);
3048 int op
= ((iw0
>> DagMODik_op_bits
) & DagMODik_op_mask
);
3050 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dagMODik
);
3051 TRACE_EXTRACT (cpu
, "%s: op:%i i:%i", __func__
, op
, i
);
3055 TRACE_INSN (cpu
, "I%i += 2;", i
);
3060 TRACE_INSN (cpu
, "I%i -= 2;", i
);
3065 TRACE_INSN (cpu
, "I%i += 4;", i
);
3070 TRACE_INSN (cpu
, "I%i -= 4;", i
);
3074 illegal_instruction (cpu
);
3078 decode_dspLDST_0 (SIM_CPU
*cpu
, bu16 iw0
)
3081 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3082 | 1 | 0 | 0 | 1 | 1 | 1 |.W.|.aop...|.m.....|.i.....|.reg.......|
3083 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3084 int i
= ((iw0
>> DspLDST_i_bits
) & DspLDST_i_mask
);
3085 int m
= ((iw0
>> DspLDST_m_bits
) & DspLDST_m_mask
);
3086 int W
= ((iw0
>> DspLDST_W_bits
) & DspLDST_W_mask
);
3087 int aop
= ((iw0
>> DspLDST_aop_bits
) & DspLDST_aop_mask
);
3088 int reg
= ((iw0
>> DspLDST_reg_bits
) & DspLDST_reg_mask
);
3091 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dspLDST
);
3092 TRACE_EXTRACT (cpu
, "%s: aop:%i m:%i i:%i reg:%i", __func__
, aop
, m
, i
, reg
);
3094 if (aop
== 0 && W
== 0 && m
== 0)
3096 TRACE_INSN (cpu
, "R%i = [I%i++];", reg
, i
);
3098 if (DIS_ALGN_EXPT
& 0x1)
3101 STORE (DREG (reg
), GET_LONG (addr
));
3103 else if (aop
== 0 && W
== 0 && m
== 1)
3105 TRACE_INSN (cpu
, "R%i.L = W[I%i++];", reg
, i
);
3108 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | GET_WORD (addr
));
3110 else if (aop
== 0 && W
== 0 && m
== 2)
3112 TRACE_INSN (cpu
, "R%i.H = W[I%i++];", reg
, i
);
3115 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (GET_WORD (addr
) << 16));
3117 else if (aop
== 1 && W
== 0 && m
== 0)
3119 TRACE_INSN (cpu
, "R%i = [I%i--];", reg
, i
);
3121 if (DIS_ALGN_EXPT
& 0x1)
3124 STORE (DREG (reg
), GET_LONG (addr
));
3126 else if (aop
== 1 && W
== 0 && m
== 1)
3128 TRACE_INSN (cpu
, "R%i.L = W[I%i--];", reg
, i
);
3131 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | GET_WORD (addr
));
3133 else if (aop
== 1 && W
== 0 && m
== 2)
3135 TRACE_INSN (cpu
, "R%i.H = W[I%i--];", reg
, i
);
3138 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (GET_WORD (addr
) << 16));
3140 else if (aop
== 2 && W
== 0 && m
== 0)
3142 TRACE_INSN (cpu
, "R%i = [I%i];", reg
, i
);
3144 if (DIS_ALGN_EXPT
& 0x1)
3146 STORE (DREG (reg
), GET_LONG (addr
));
3148 else if (aop
== 2 && W
== 0 && m
== 1)
3150 TRACE_INSN (cpu
, "R%i.L = W[I%i];", reg
, i
);
3152 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | GET_WORD (addr
));
3154 else if (aop
== 2 && W
== 0 && m
== 2)
3156 TRACE_INSN (cpu
, "R%i.H = W[I%i];", reg
, i
);
3158 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (GET_WORD (addr
) << 16));
3160 else if (aop
== 0 && W
== 1 && m
== 0)
3162 TRACE_INSN (cpu
, "[I%i++] = R%i;", i
, reg
);
3165 PUT_LONG (addr
, DREG (reg
));
3167 else if (aop
== 0 && W
== 1 && m
== 1)
3169 TRACE_INSN (cpu
, "W[I%i++] = R%i.L;", i
, reg
);
3172 PUT_WORD (addr
, DREG (reg
));
3174 else if (aop
== 0 && W
== 1 && m
== 2)
3176 TRACE_INSN (cpu
, "W[I%i++] = R%i.H;", i
, reg
);
3179 PUT_WORD (addr
, DREG (reg
) >> 16);
3181 else if (aop
== 1 && W
== 1 && m
== 0)
3183 TRACE_INSN (cpu
, "[I%i--] = R%i;", i
, reg
);
3186 PUT_LONG (addr
, DREG (reg
));
3188 else if (aop
== 1 && W
== 1 && m
== 1)
3190 TRACE_INSN (cpu
, "W[I%i--] = R%i.L;", i
, reg
);
3193 PUT_WORD (addr
, DREG (reg
));
3195 else if (aop
== 1 && W
== 1 && m
== 2)
3197 TRACE_INSN (cpu
, "W[I%i--] = R%i.H;", i
, reg
);
3200 PUT_WORD (addr
, DREG (reg
) >> 16);
3202 else if (aop
== 2 && W
== 1 && m
== 0)
3204 TRACE_INSN (cpu
, "[I%i] = R%i;", i
, reg
);
3206 PUT_LONG (addr
, DREG (reg
));
3208 else if (aop
== 2 && W
== 1 && m
== 1)
3210 TRACE_INSN (cpu
, "W[I%i] = R%i.L;", i
, reg
);
3212 PUT_WORD (addr
, DREG (reg
));
3214 else if (aop
== 2 && W
== 1 && m
== 2)
3216 TRACE_INSN (cpu
, "W[I%i] = R%i.H;", i
, reg
);
3218 PUT_WORD (addr
, DREG (reg
) >> 16);
3220 else if (aop
== 3 && W
== 0)
3222 TRACE_INSN (cpu
, "R%i = [I%i ++ M%i];", reg
, i
, m
);
3224 if (DIS_ALGN_EXPT
& 0x1)
3226 dagadd (cpu
, i
, MREG (m
));
3227 STORE (DREG (reg
), GET_LONG (addr
));
3229 else if (aop
== 3 && W
== 1)
3231 TRACE_INSN (cpu
, "[I%i ++ M%i] = R%i;", i
, m
, reg
);
3233 dagadd (cpu
, i
, MREG (m
));
3234 PUT_LONG (addr
, DREG (reg
));
3237 illegal_instruction (cpu
);
3241 decode_LDST_0 (SIM_CPU
*cpu
, bu16 iw0
)
3244 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3245 | 1 | 0 | 0 | 1 |.sz....|.W.|.aop...|.Z.|.ptr.......|.reg.......|
3246 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3247 int Z
= ((iw0
>> LDST_Z_bits
) & LDST_Z_mask
);
3248 int W
= ((iw0
>> LDST_W_bits
) & LDST_W_mask
);
3249 int sz
= ((iw0
>> LDST_sz_bits
) & LDST_sz_mask
);
3250 int aop
= ((iw0
>> LDST_aop_bits
) & LDST_aop_mask
);
3251 int reg
= ((iw0
>> LDST_reg_bits
) & LDST_reg_mask
);
3252 int ptr
= ((iw0
>> LDST_ptr_bits
) & LDST_ptr_mask
);
3253 const char * const posts
[] = { "++", "--", "" };
3254 const char *post
= posts
[aop
];
3255 const char *ptr_name
= get_preg_name (ptr
);
3257 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDST
);
3258 TRACE_EXTRACT (cpu
, "%s: sz:%i W:%i aop:%i Z:%i ptr:%i reg:%i",
3259 __func__
, sz
, W
, aop
, Z
, ptr
, reg
);
3262 illegal_instruction (cpu
);
3266 if (sz
== 0 && Z
== 0)
3268 TRACE_INSN (cpu
, "R%i = [%s%s];", reg
, ptr_name
, post
);
3269 SET_DREG (reg
, GET_LONG (PREG (ptr
)));
3271 else if (sz
== 0 && Z
== 1)
3273 TRACE_INSN (cpu
, "%s = [%s%s];", get_preg_name (reg
), ptr_name
, post
);
3274 if (aop
< 2 && ptr
== reg
)
3275 illegal_instruction_combination (cpu
);
3276 SET_PREG (reg
, GET_LONG (PREG (ptr
)));
3278 else if (sz
== 1 && Z
== 0)
3280 TRACE_INSN (cpu
, "R%i = W[%s%s] (Z);", reg
, ptr_name
, post
);
3281 SET_DREG (reg
, GET_WORD (PREG (ptr
)));
3283 else if (sz
== 1 && Z
== 1)
3285 TRACE_INSN (cpu
, "R%i = W[%s%s] (X);", reg
, ptr_name
, post
);
3286 SET_DREG (reg
, (bs32
) (bs16
) GET_WORD (PREG (ptr
)));
3288 else if (sz
== 2 && Z
== 0)
3290 TRACE_INSN (cpu
, "R%i = B[%s%s] (Z);", reg
, ptr_name
, post
);
3291 SET_DREG (reg
, GET_BYTE (PREG (ptr
)));
3293 else if (sz
== 2 && Z
== 1)
3295 TRACE_INSN (cpu
, "R%i = B[%s%s] (X);", reg
, ptr_name
, post
);
3296 SET_DREG (reg
, (bs32
) (bs8
) GET_BYTE (PREG (ptr
)));
3299 illegal_instruction (cpu
);
3303 if (sz
== 0 && Z
== 0)
3305 TRACE_INSN (cpu
, "[%s%s] = R%i;", ptr_name
, post
, reg
);
3306 PUT_LONG (PREG (ptr
), DREG (reg
));
3308 else if (sz
== 0 && Z
== 1)
3310 TRACE_INSN (cpu
, "[%s%s] = %s;", ptr_name
, post
, get_preg_name (reg
));
3311 PUT_LONG (PREG (ptr
), PREG (reg
));
3313 else if (sz
== 1 && Z
== 0)
3315 TRACE_INSN (cpu
, "W[%s%s] = R%i;", ptr_name
, post
, reg
);
3316 PUT_WORD (PREG (ptr
), DREG (reg
));
3318 else if (sz
== 2 && Z
== 0)
3320 TRACE_INSN (cpu
, "B[%s%s] = R%i;", ptr_name
, post
, reg
);
3321 PUT_BYTE (PREG (ptr
), DREG (reg
));
3324 illegal_instruction (cpu
);
3328 SET_PREG (ptr
, PREG (ptr
) + (1 << (2 - sz
)));
3330 SET_PREG (ptr
, PREG (ptr
) - (1 << (2 - sz
)));
3334 decode_LDSTiiFP_0 (SIM_CPU
*cpu
, bu16 iw0
)
3337 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3338 | 1 | 0 | 1 | 1 | 1 | 0 |.W.|.offset............|.reg...........|
3339 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3340 /* This isn't exactly a grp:reg as this insn only supports Dregs & Pregs,
3341 but for our usage, its functionality the same thing. */
3342 int grp
= ((iw0
>> 3) & 0x1);
3343 int reg
= ((iw0
>> LDSTiiFP_reg_bits
) & 0x7 /*LDSTiiFP_reg_mask*/);
3344 int offset
= ((iw0
>> LDSTiiFP_offset_bits
) & LDSTiiFP_offset_mask
);
3345 int W
= ((iw0
>> LDSTiiFP_W_bits
) & LDSTiiFP_W_mask
);
3346 bu32 imm
= negimm5s4 (offset
);
3347 bu32 ea
= FPREG
+ imm
;
3348 const char *imm_str
= negimm5s4_str (offset
);
3349 const char *reg_name
= get_allreg_name (grp
, reg
);
3351 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTiiFP
);
3352 TRACE_EXTRACT (cpu
, "%s: W:%i offset:%#x grp:%i reg:%i", __func__
,
3353 W
, offset
, grp
, reg
);
3354 TRACE_DECODE (cpu
, "%s: negimm5s4:%#x", __func__
, imm
);
3358 TRACE_INSN (cpu
, "%s = [FP + %s];", reg_name
, imm_str
);
3359 reg_write (cpu
, grp
, reg
, GET_LONG (ea
));
3363 TRACE_INSN (cpu
, "[FP + %s] = %s;", imm_str
, reg_name
);
3364 PUT_LONG (ea
, reg_read (cpu
, grp
, reg
));
3369 decode_LDSTii_0 (SIM_CPU
*cpu
, bu16 iw0
)
3372 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3373 | 1 | 0 | 1 |.W.|.op....|.offset........|.ptr.......|.reg.......|
3374 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3375 int reg
= ((iw0
>> LDSTii_reg_bit
) & LDSTii_reg_mask
);
3376 int ptr
= ((iw0
>> LDSTii_ptr_bit
) & LDSTii_ptr_mask
);
3377 int offset
= ((iw0
>> LDSTii_offset_bit
) & LDSTii_offset_mask
);
3378 int op
= ((iw0
>> LDSTii_op_bit
) & LDSTii_op_mask
);
3379 int W
= ((iw0
>> LDSTii_W_bit
) & LDSTii_W_mask
);
3381 const char *imm_str
;
3382 const char *ptr_name
= get_preg_name (ptr
);
3384 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTii
);
3385 TRACE_EXTRACT (cpu
, "%s: W:%i op:%i offset:%#x ptr:%i reg:%i",
3386 __func__
, W
, op
, offset
, ptr
, reg
);
3388 if (op
== 0 || op
== 3)
3389 imm
= uimm4s4 (offset
), imm_str
= uimm4s4_str (offset
);
3391 imm
= uimm4s2 (offset
), imm_str
= uimm4s2_str (offset
);
3392 ea
= PREG (ptr
) + imm
;
3394 TRACE_DECODE (cpu
, "%s: uimm4s4/uimm4s2:%#x", __func__
, imm
);
3396 if (W
== 1 && op
== 2)
3397 illegal_instruction (cpu
);
3403 TRACE_INSN (cpu
, "R%i = [%s + %s];", reg
, ptr_name
, imm_str
);
3404 SET_DREG (reg
, GET_LONG (ea
));
3408 TRACE_INSN (cpu
, "R%i = W[%s + %s] (Z);", reg
, ptr_name
, imm_str
);
3409 SET_DREG (reg
, GET_WORD (ea
));
3413 TRACE_INSN (cpu
, "R%i = W[%s + %s] (X);", reg
, ptr_name
, imm_str
);
3414 SET_DREG (reg
, (bs32
) (bs16
) GET_WORD (ea
));
3418 TRACE_INSN (cpu
, "%s = [%s + %s];",
3419 get_preg_name (reg
), ptr_name
, imm_str
);
3420 SET_PREG (reg
, GET_LONG (ea
));
3427 TRACE_INSN (cpu
, "[%s + %s] = R%i;", ptr_name
, imm_str
, reg
);
3428 PUT_LONG (ea
, DREG (reg
));
3432 TRACE_INSN (cpu
, "W[%s + %s] = R%i;", ptr_name
, imm_str
, reg
);
3433 PUT_WORD (ea
, DREG (reg
));
3437 TRACE_INSN (cpu
, "[%s + %s] = %s;",
3438 ptr_name
, imm_str
, get_preg_name (reg
));
3439 PUT_LONG (ea
, PREG (reg
));
3445 decode_LoopSetup_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
, bu32 pc
)
3448 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3449 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |.rop...|.c.|.soffset.......|
3450 |.reg...........| - | - |.eoffset...............................|
3451 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3452 int c
= ((iw0
>> (LoopSetup_c_bits
- 16)) & LoopSetup_c_mask
);
3453 int reg
= ((iw1
>> LoopSetup_reg_bits
) & LoopSetup_reg_mask
);
3454 int rop
= ((iw0
>> (LoopSetup_rop_bits
- 16)) & LoopSetup_rop_mask
);
3455 int soffset
= ((iw0
>> (LoopSetup_soffset_bits
- 16)) & LoopSetup_soffset_mask
);
3456 int eoffset
= ((iw1
>> LoopSetup_eoffset_bits
) & LoopSetup_eoffset_mask
);
3457 int spcrel
= pcrel4 (soffset
);
3458 int epcrel
= lppcrel10 (eoffset
);
3460 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LoopSetup
);
3461 TRACE_EXTRACT (cpu
, "%s: rop:%i c:%i soffset:%i reg:%i eoffset:%i",
3462 __func__
, rop
, c
, soffset
, reg
, eoffset
);
3463 TRACE_DECODE (cpu
, "%s: s_pcrel4:%#x e_lppcrel10:%#x",
3464 __func__
, spcrel
, epcrel
);
3467 illegal_instruction (cpu
);
3470 illegal_instruction_combination (cpu
);
3474 TRACE_INSN (cpu
, "LSETUP (%#x, %#x) LC%i;", spcrel
, epcrel
, c
);
3476 else if (rop
== 1 && reg
<= 7)
3478 TRACE_INSN (cpu
, "LSETUP (%#x, %#x) LC%i = %s;",
3479 spcrel
, epcrel
, c
, get_preg_name (reg
));
3480 SET_LCREG (c
, PREG (reg
));
3482 else if (rop
== 3 && reg
<= 7)
3484 TRACE_INSN (cpu
, "LSETUP (%#x, %#x) LC%i = %s >> 1;",
3485 spcrel
, epcrel
, c
, get_preg_name (reg
));
3486 SET_LCREG (c
, PREG (reg
) >> 1);
3489 illegal_instruction (cpu
);
3491 SET_LTREG (c
, pc
+ spcrel
);
3492 SET_LBREG (c
, pc
+ epcrel
);
3496 decode_LDIMMhalf_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3499 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3500 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 |.Z.|.H.|.S.|.grp...|.reg.......|
3501 |.hword.........................................................|
3502 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3503 int H
= ((iw0
>> (LDIMMhalf_H_bits
- 16)) & LDIMMhalf_H_mask
);
3504 int Z
= ((iw0
>> (LDIMMhalf_Z_bits
- 16)) & LDIMMhalf_Z_mask
);
3505 int S
= ((iw0
>> (LDIMMhalf_S_bits
- 16)) & LDIMMhalf_S_mask
);
3506 int reg
= ((iw0
>> (LDIMMhalf_reg_bits
- 16)) & LDIMMhalf_reg_mask
);
3507 int grp
= ((iw0
>> (LDIMMhalf_grp_bits
- 16)) & LDIMMhalf_grp_mask
);
3508 int hword
= ((iw1
>> LDIMMhalf_hword_bits
) & LDIMMhalf_hword_mask
);
3510 const char *val_str
;
3511 const char *reg_name
= get_allreg_name (grp
, reg
);
3513 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDIMMhalf
);
3514 TRACE_EXTRACT (cpu
, "%s: Z:%i H:%i S:%i grp:%i reg:%i hword:%#x",
3515 __func__
, Z
, H
, S
, grp
, reg
, hword
);
3518 illegal_instruction_combination (cpu
);
3521 val
= imm16 (hword
), val_str
= imm16_str (hword
);
3523 val
= luimm16 (hword
), val_str
= luimm16_str (hword
);
3525 if (H
== 0 && S
== 1 && Z
== 0)
3527 TRACE_INSN (cpu
, "%s = %s (X);", reg_name
, val_str
);
3529 else if (H
== 0 && S
== 0 && Z
== 1)
3531 TRACE_INSN (cpu
, "%s = %s (Z);", reg_name
, val_str
);
3533 else if (H
== 0 && S
== 0 && Z
== 0)
3535 TRACE_INSN (cpu
, "%s.L = %s;", reg_name
, val_str
);
3536 val
= REG_H_L (reg_read (cpu
, grp
, reg
), val
);
3538 else if (H
== 1 && S
== 0 && Z
== 0)
3540 TRACE_INSN (cpu
, "%s.H = %s;", reg_name
, val_str
);
3541 val
= REG_H_L (val
<< 16, reg_read (cpu
, grp
, reg
));
3544 illegal_instruction (cpu
);
3546 reg_write (cpu
, grp
, reg
, val
);
3550 decode_CALLa_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
, bu32 pc
)
3553 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3554 | 1 | 1 | 1 | 0 | 0 | 0 | 1 |.S.|.msw...........................|
3555 |.lsw...........................................................|
3556 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3557 int S
= ((iw0
>> (CALLa_S_bits
- 16)) & CALLa_S_mask
);
3558 int lsw
= ((iw1
>> 0) & 0xffff);
3559 int msw
= ((iw0
>> 0) & 0xff);
3560 int pcrel
= pcrel24 ((msw
<< 16) | lsw
);
3561 bu32 newpc
= pc
+ pcrel
;
3563 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CALLa
);
3564 TRACE_EXTRACT (cpu
, "%s: S:%i msw:%#x lsw:%#x", __func__
, S
, msw
, lsw
);
3565 TRACE_DECODE (cpu
, "%s: pcrel24:%#x", __func__
, pcrel
);
3567 TRACE_INSN (cpu
, "%s %#x;", S
? "CALL" : "JUMP.L", pcrel
);
3570 illegal_instruction_combination (cpu
);
3574 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "CALL");
3575 SET_RETSREG (hwloop_get_next_pc (cpu
, pc
, 4));
3578 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP.L");
3581 BFIN_CPU_STATE
.did_jump
= true;
3582 PROFILE_BRANCH_TAKEN (cpu
);
3587 decode_LDSTidxI_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3590 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3591 | 1 | 1 | 1 | 0 | 0 | 1 |.W.|.Z.|.sz....|.ptr.......|.reg.......|
3592 |.offset........................................................|
3593 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3594 int Z
= ((iw0
>> (LDSTidxI_Z_bits
- 16)) & LDSTidxI_Z_mask
);
3595 int W
= ((iw0
>> (LDSTidxI_W_bits
- 16)) & LDSTidxI_W_mask
);
3596 int sz
= ((iw0
>> (LDSTidxI_sz_bits
- 16)) & LDSTidxI_sz_mask
);
3597 int reg
= ((iw0
>> (LDSTidxI_reg_bits
- 16)) & LDSTidxI_reg_mask
);
3598 int ptr
= ((iw0
>> (LDSTidxI_ptr_bits
- 16)) & LDSTidxI_ptr_mask
);
3599 int offset
= ((iw1
>> LDSTidxI_offset_bits
) & LDSTidxI_offset_mask
);
3600 const char *ptr_name
= get_preg_name (ptr
);
3601 bu32 imm_16s4
= imm16s4 (offset
);
3602 bu32 imm_16s2
= imm16s2 (offset
);
3603 bu32 imm_16
= imm16 (offset
);
3605 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTidxI
);
3606 TRACE_EXTRACT (cpu
, "%s: W:%i Z:%i sz:%i ptr:%i reg:%i offset:%#x",
3607 __func__
, W
, Z
, sz
, ptr
, reg
, offset
);
3610 illegal_instruction (cpu
);
3614 if (sz
== 0 && Z
== 0)
3616 TRACE_INSN (cpu
, "R%i = [%s + %s];",
3617 reg
, ptr_name
, imm16s4_str (offset
));
3618 SET_DREG (reg
, GET_LONG (PREG (ptr
) + imm_16s4
));
3620 else if (sz
== 0 && Z
== 1)
3622 TRACE_INSN (cpu
, "%s = [%s + %s];",
3623 get_preg_name (reg
), ptr_name
, imm16s4_str (offset
));
3624 SET_PREG (reg
, GET_LONG (PREG (ptr
) + imm_16s4
));
3626 else if (sz
== 1 && Z
== 0)
3628 TRACE_INSN (cpu
, "R%i = W[%s + %s] (Z);",
3629 reg
, ptr_name
, imm16s2_str (offset
));
3630 SET_DREG (reg
, GET_WORD (PREG (ptr
) + imm_16s2
));
3632 else if (sz
== 1 && Z
== 1)
3634 TRACE_INSN (cpu
, "R%i = W[%s + %s] (X);",
3635 reg
, ptr_name
, imm16s2_str (offset
));
3636 SET_DREG (reg
, (bs32
) (bs16
) GET_WORD (PREG (ptr
) + imm_16s2
));
3638 else if (sz
== 2 && Z
== 0)
3640 TRACE_INSN (cpu
, "R%i = B[%s + %s] (Z);",
3641 reg
, ptr_name
, imm16_str (offset
));
3642 SET_DREG (reg
, GET_BYTE (PREG (ptr
) + imm_16
));
3644 else if (sz
== 2 && Z
== 1)
3646 TRACE_INSN (cpu
, "R%i = B[%s + %s] (X);",
3647 reg
, ptr_name
, imm16_str (offset
));
3648 SET_DREG (reg
, (bs32
) (bs8
) GET_BYTE (PREG (ptr
) + imm_16
));
3653 if (sz
!= 0 && Z
!= 0)
3654 illegal_instruction (cpu
);
3656 if (sz
== 0 && Z
== 0)
3658 TRACE_INSN (cpu
, "[%s + %s] = R%i;", ptr_name
,
3659 imm16s4_str (offset
), reg
);
3660 PUT_LONG (PREG (ptr
) + imm_16s4
, DREG (reg
));
3662 else if (sz
== 0 && Z
== 1)
3664 TRACE_INSN (cpu
, "[%s + %s] = %s;",
3665 ptr_name
, imm16s4_str (offset
), get_preg_name (reg
));
3666 PUT_LONG (PREG (ptr
) + imm_16s4
, PREG (reg
));
3668 else if (sz
== 1 && Z
== 0)
3670 TRACE_INSN (cpu
, "W[%s + %s] = R%i;",
3671 ptr_name
, imm16s2_str (offset
), reg
);
3672 PUT_WORD (PREG (ptr
) + imm_16s2
, DREG (reg
));
3674 else if (sz
== 2 && Z
== 0)
3676 TRACE_INSN (cpu
, "B[%s + %s] = R%i;",
3677 ptr_name
, imm16_str (offset
), reg
);
3678 PUT_BYTE (PREG (ptr
) + imm_16
, DREG (reg
));
3684 decode_linkage_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3687 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3688 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |.R.|
3689 |.framesize.....................................................|
3690 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3691 int R
= ((iw0
>> (Linkage_R_bits
- 16)) & Linkage_R_mask
);
3692 int framesize
= ((iw1
>> Linkage_framesize_bits
) & Linkage_framesize_mask
);
3695 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_linkage
);
3696 TRACE_EXTRACT (cpu
, "%s: R:%i framesize:%#x", __func__
, R
, framesize
);
3700 int size
= uimm16s4 (framesize
);
3702 TRACE_INSN (cpu
, "LINK %s;", uimm16s4_str (framesize
));
3704 illegal_instruction_combination (cpu
);
3706 PUT_LONG (sp
, RETSREG
);
3708 PUT_LONG (sp
, FPREG
);
3715 /* Restore SP from FP. */
3717 TRACE_INSN (cpu
, "UNLINK;");
3719 illegal_instruction_combination (cpu
);
3720 SET_FPREG (GET_LONG (sp
));
3722 SET_RETSREG (GET_LONG (sp
));
3731 decode_dsp32mac_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3734 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3735 | 1 | 1 | 0 | 0 |.M.| 0 | 0 |.mmod..........|.MM|.P.|.w1|.op1...|
3736 |.h01|.h11|.w0|.op0...|.h00|.h10|.dst.......|.src0......|.src1..|
3737 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3738 int op1
= ((iw0
>> (DSP32Mac_op1_bits
- 16)) & DSP32Mac_op1_mask
);
3739 int w1
= ((iw0
>> (DSP32Mac_w1_bits
- 16)) & DSP32Mac_w1_mask
);
3740 int P
= ((iw0
>> (DSP32Mac_p_bits
- 16)) & DSP32Mac_p_mask
);
3741 int MM
= ((iw0
>> (DSP32Mac_MM_bits
- 16)) & DSP32Mac_MM_mask
);
3742 int mmod
= ((iw0
>> (DSP32Mac_mmod_bits
- 16)) & DSP32Mac_mmod_mask
);
3743 int M
= ((iw0
>> (DSP32Mac_M_bits
- 16)) & DSP32Mac_M_mask
);
3744 int w0
= ((iw1
>> DSP32Mac_w0_bits
) & DSP32Mac_w0_mask
);
3745 int src0
= ((iw1
>> DSP32Mac_src0_bits
) & DSP32Mac_src0_mask
);
3746 int src1
= ((iw1
>> DSP32Mac_src1_bits
) & DSP32Mac_src1_mask
);
3747 int dst
= ((iw1
>> DSP32Mac_dst_bits
) & DSP32Mac_dst_mask
);
3748 int h10
= ((iw1
>> DSP32Mac_h10_bits
) & DSP32Mac_h10_mask
);
3749 int h00
= ((iw1
>> DSP32Mac_h00_bits
) & DSP32Mac_h00_mask
);
3750 int op0
= ((iw1
>> DSP32Mac_op0_bits
) & DSP32Mac_op0_mask
);
3751 int h11
= ((iw1
>> DSP32Mac_h11_bits
) & DSP32Mac_h11_mask
);
3752 int h01
= ((iw1
>> DSP32Mac_h01_bits
) & DSP32Mac_h01_mask
);
3754 bu32 res
= DREG (dst
);
3755 bu32 v_0
= 0, v_1
= 0, zero
= 0, n_1
= 0, n_0
= 0;
3757 static const char * const ops
[] = { "=", "+=", "-=" };
3758 char _buf
[128], *buf
= _buf
;
3761 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32mac
);
3762 TRACE_EXTRACT (cpu
, "%s: M:%i mmod:%i MM:%i P:%i w1:%i op1:%i h01:%i h11:%i "
3763 "w0:%i op0:%i h00:%i h10:%i dst:%i src0:%i src1:%i",
3764 __func__
, M
, mmod
, MM
, P
, w1
, op1
, h01
, h11
, w0
, op0
, h00
, h10
,
3767 if (w0
== 0 && w1
== 0 && op1
== 3 && op0
== 3)
3768 illegal_instruction (cpu
);
3770 if ((w1
|| w0
) && mmod
== M_W32
)
3771 illegal_instruction (cpu
);
3773 if (((1 << mmod
) & (P
? 0x131b : 0x1b5f)) == 0)
3774 illegal_instruction (cpu
);
3776 /* First handle MAC1 side. */
3777 if (w1
== 1 || op1
!= 3)
3779 bu32 res1
= decode_macfunc (cpu
, 1, op1
, h01
, h11
, src0
,
3780 src1
, mmod
, MM
, P
, &v_1
, &n_1
);
3783 buf
+= sprintf (buf
, P
? "R%i" : "R%i.H", dst
+ P
);
3787 buf
+= sprintf (buf
, " = A1");
3788 zero
= !!(res1
== 0);
3793 buf
+= sprintf (buf
, " = (");
3794 buf
+= sprintf (buf
, "A1 %s R%i.%c * R%i.%c", ops
[op1
],
3795 src0
, h01
? 'H' : 'L',
3796 src1
, h11
? 'H' : 'L');
3798 buf
+= sprintf (buf
, ")");
3804 STORE (DREG (dst
+ 1), res1
);
3807 if (res1
& 0xffff0000)
3808 illegal_instruction (cpu
);
3809 res
= REG_H_L (res1
<< 16, res
);
3815 if (w0
== 1 || op0
!= 3)
3818 buf
+= sprintf (buf
, " (M)");
3820 buf
+= sprintf (buf
, ", ");
3824 /* Then handle MAC0 side. */
3825 if (w0
== 1 || op0
!= 3)
3827 bu32 res0
= decode_macfunc (cpu
, 0, op0
, h00
, h10
, src0
,
3828 src1
, mmod
, 0, P
, &v_0
, &n_0
);
3831 buf
+= sprintf (buf
, P
? "R%i" : "R%i.L", dst
);
3835 buf
+= sprintf (buf
, " = A0");
3836 zero
|= !!(res0
== 0);
3841 buf
+= sprintf (buf
, " = (");
3842 buf
+= sprintf (buf
, "A0 %s R%i.%c * R%i.%c", ops
[op0
],
3843 src0
, h00
? 'H' : 'L',
3844 src1
, h10
? 'H' : 'L');
3846 buf
+= sprintf (buf
, ")");
3852 STORE (DREG (dst
), res0
);
3855 if (res0
& 0xffff0000)
3856 illegal_instruction (cpu
);
3857 res
= REG_H_L (res
, res0
);
3864 TRACE_INSN (cpu
, "%s%s;", _buf
, mac_optmode (mmod
, _MM
));
3866 if (!P
&& (w0
|| w1
))
3868 STORE (DREG (dst
), res
);
3869 SET_ASTATREG (v
, v_0
| v_1
);
3871 SET_ASTATREG (vs
, 1);
3875 SET_ASTATREG (v
, v_0
| v_1
);
3877 SET_ASTATREG (vs
, 1);
3880 if ((w0
== 1 && op0
== 3) || (w1
== 1 && op1
== 3))
3882 SET_ASTATREG (az
, zero
);
3883 if (!(w0
== 1 && op0
== 3))
3885 if (!(w1
== 1 && op1
== 3))
3887 SET_ASTATREG (an
, n_1
| n_0
);
3892 decode_dsp32mult_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3895 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3896 | 1 | 1 | 0 | 0 |.M.| 0 | 1 |.mmod..........|.MM|.P.|.w1|.op1...|
3897 |.h01|.h11|.w0|.op0...|.h00|.h10|.dst.......|.src0......|.src1..|
3898 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3899 int op1
= ((iw0
>> (DSP32Mac_op1_bits
- 16)) & DSP32Mac_op1_mask
);
3900 int w1
= ((iw0
>> (DSP32Mac_w1_bits
- 16)) & DSP32Mac_w1_mask
);
3901 int P
= ((iw0
>> (DSP32Mac_p_bits
- 16)) & DSP32Mac_p_mask
);
3902 int MM
= ((iw0
>> (DSP32Mac_MM_bits
- 16)) & DSP32Mac_MM_mask
);
3903 int mmod
= ((iw0
>> (DSP32Mac_mmod_bits
- 16)) & DSP32Mac_mmod_mask
);
3904 int M
= ((iw0
>> (DSP32Mac_M_bits
- 16)) & DSP32Mac_M_mask
);
3905 int w0
= ((iw1
>> DSP32Mac_w0_bits
) & DSP32Mac_w0_mask
);
3906 int src0
= ((iw1
>> DSP32Mac_src0_bits
) & DSP32Mac_src0_mask
);
3907 int src1
= ((iw1
>> DSP32Mac_src1_bits
) & DSP32Mac_src1_mask
);
3908 int dst
= ((iw1
>> DSP32Mac_dst_bits
) & DSP32Mac_dst_mask
);
3909 int h10
= ((iw1
>> DSP32Mac_h10_bits
) & DSP32Mac_h10_mask
);
3910 int h00
= ((iw1
>> DSP32Mac_h00_bits
) & DSP32Mac_h00_mask
);
3911 int op0
= ((iw1
>> DSP32Mac_op0_bits
) & DSP32Mac_op0_mask
);
3912 int h11
= ((iw1
>> DSP32Mac_h11_bits
) & DSP32Mac_h11_mask
);
3913 int h01
= ((iw1
>> DSP32Mac_h01_bits
) & DSP32Mac_h01_mask
);
3915 bu32 res
= DREG (dst
);
3916 bu32 sat0
= 0, sat1
= 0, v_i0
= 0, v_i1
= 0;
3917 char _buf
[128], *buf
= _buf
;
3920 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32mult
);
3921 TRACE_EXTRACT (cpu
, "%s: M:%i mmod:%i MM:%i P:%i w1:%i op1:%i h01:%i h11:%i "
3922 "w0:%i op0:%i h00:%i h10:%i dst:%i src0:%i src1:%i",
3923 __func__
, M
, mmod
, MM
, P
, w1
, op1
, h01
, h11
, w0
, op0
, h00
, h10
,
3926 if (w1
== 0 && w0
== 0)
3927 illegal_instruction (cpu
);
3928 if (((1 << mmod
) & (P
? 0x313 : 0x1b57)) == 0)
3929 illegal_instruction (cpu
);
3930 if (P
&& ((dst
& 1) || (op1
!= 0) || (op0
!= 0) || !is_macmod_pmove (mmod
)))
3931 illegal_instruction (cpu
);
3932 if (!P
&& ((op1
!= 0) || (op0
!= 0) || !is_macmod_hmove (mmod
)))
3933 illegal_instruction (cpu
);
3935 /* First handle MAC1 side. */
3938 bu64 r
= decode_multfunc (cpu
, h01
, h11
, src0
, src1
, mmod
, MM
, &sat1
);
3939 bu32 res1
= extract_mult (cpu
, r
, mmod
, MM
, P
, &v_i1
);
3941 buf
+= sprintf (buf
, P
? "R%i" : "R%i.H", dst
+ P
);
3942 buf
+= sprintf (buf
, " = R%i.%c * R%i.%c",
3943 src0
, h01
? 'H' : 'L',
3944 src1
, h11
? 'H' : 'L');
3948 buf
+= sprintf (buf
, " (M)");
3950 buf
+= sprintf (buf
, ", ");
3954 STORE (DREG (dst
+ 1), res1
);
3957 if (res1
& 0xFFFF0000)
3958 illegal_instruction (cpu
);
3959 res
= REG_H_L (res1
<< 16, res
);
3963 /* First handle MAC0 side. */
3966 bu64 r
= decode_multfunc (cpu
, h00
, h10
, src0
, src1
, mmod
, 0, &sat0
);
3967 bu32 res0
= extract_mult (cpu
, r
, mmod
, 0, P
, &v_i0
);
3969 buf
+= sprintf (buf
, P
? "R%i" : "R%i.L", dst
);
3970 buf
+= sprintf (buf
, " = R%i.%c * R%i.%c",
3971 src0
, h01
? 'H' : 'L',
3972 src1
, h11
? 'H' : 'L');
3975 STORE (DREG (dst
), res0
);
3978 if (res0
& 0xFFFF0000)
3979 illegal_instruction (cpu
);
3980 res
= REG_H_L (res
, res0
);
3984 TRACE_INSN (cpu
, "%s%s;", _buf
, mac_optmode (mmod
, _MM
));
3986 if (!P
&& (w0
|| w1
))
3987 STORE (DREG (dst
), res
);
3991 bu32 v
= sat0
| sat1
| v_i0
| v_i1
;
3993 STORE (ASTATREG (v
), v
);
3994 STORE (ASTATREG (v_copy
), v
);
3996 STORE (ASTATREG (vs
), v
);
4001 decode_dsp32alu_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
4004 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
4005 | 1 | 1 | 0 | 0 |.M.| 1 | 0 | - | - | - |.HL|.aopcde............|
4006 |.aop...|.s.|.x.|.dst0......|.dst1......|.src0......|.src1......|
4007 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
4008 int s
= ((iw1
>> DSP32Alu_s_bits
) & DSP32Alu_s_mask
);
4009 int x
= ((iw1
>> DSP32Alu_x_bits
) & DSP32Alu_x_mask
);
4010 int aop
= ((iw1
>> DSP32Alu_aop_bits
) & DSP32Alu_aop_mask
);
4011 int src0
= ((iw1
>> DSP32Alu_src0_bits
) & DSP32Alu_src0_mask
);
4012 int src1
= ((iw1
>> DSP32Alu_src1_bits
) & DSP32Alu_src1_mask
);
4013 int dst0
= ((iw1
>> DSP32Alu_dst0_bits
) & DSP32Alu_dst0_mask
);
4014 int dst1
= ((iw1
>> DSP32Alu_dst1_bits
) & DSP32Alu_dst1_mask
);
4015 int M
= ((iw0
>> (DSP32Alu_M_bits
- 16)) & DSP32Alu_M_mask
);
4016 int HL
= ((iw0
>> (DSP32Alu_HL_bits
- 16)) & DSP32Alu_HL_mask
);
4017 int aopcde
= ((iw0
>> (DSP32Alu_aopcde_bits
- 16)) & DSP32Alu_aopcde_mask
);
4019 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32alu
);
4020 TRACE_EXTRACT (cpu
, "%s: M:%i HL:%i aopcde:%i aop:%i s:%i x:%i dst0:%i "
4021 "dst1:%i src0:%i src1:%i",
4022 __func__
, M
, HL
, aopcde
, aop
, s
, x
, dst0
, dst1
, src0
, src1
);
4024 if ((aop
== 0 || aop
== 2) && aopcde
== 9 && HL
== 0 && s
== 0)
4027 TRACE_INSN (cpu
, "A%i.L = R%i.L;", a
, src0
);
4028 SET_AWREG (a
, REG_H_L (AWREG (a
), DREG (src0
)));
4030 else if ((aop
== 0 || aop
== 2) && aopcde
== 9 && HL
== 1 && s
== 0)
4033 TRACE_INSN (cpu
, "A%i.H = R%i.H;", a
, src0
);
4034 SET_AWREG (a
, REG_H_L (DREG (src0
), AWREG (a
)));
4036 else if ((aop
== 1 || aop
== 0) && aopcde
== 5)
4038 bs32 val0
= DREG (src0
);
4039 bs32 val1
= DREG (src1
);
4042 bs32 ovX
, sBit1
, sBit2
, sBitRes1
, sBitRes2
;
4044 TRACE_INSN (cpu
, "R%i.%s = R%i %s R%i (RND12)", dst0
, HL
? "L" : "H",
4045 src0
, aop
& 0x1 ? "-" : "+", src1
);
4047 /* If subtract, just invert and add one. */
4050 if (val1
== 0x80000000)
4056 /* Get the sign bits, since we need them later. */
4057 sBit1
= !!(val0
& 0x80000000);
4058 sBit2
= !!(val1
& 0x80000000);
4062 sBitRes1
= !!(res
& 0x80000000);
4063 /* Round to the 12th bit. */
4065 sBitRes2
= !!(res
& 0x80000000);
4073 positive_res + positive_round = neg
4074 Shift and upper 4 bits where not the same. */
4075 if ((!(sBit1
^ sBit2
) && (sBit1
^ sBitRes1
))
4076 || (!sBit1
&& !sBit2
&& sBitRes2
)
4077 || ((signRes
!= 0) && (signRes
!= -1)))
4079 /* Both X1 and X2 Neg res is neg overflow. */
4082 /* Both X1 and X2 Pos res is pos overflow. */
4083 else if (!sBit1
&& !sBit2
)
4085 /* Pos+Neg or Neg+Pos take the sign of the result. */
4095 /* Shift up now after overflow detection. */
4103 STORE (DREG (dst0
), REG_H_L (res
<< 16, DREG (dst0
)));
4105 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), res
));
4107 SET_ASTATREG (az
, res
== 0);
4108 SET_ASTATREG (an
, res
& 0x8000);
4109 SET_ASTATREG (v
, ovX
);
4111 SET_ASTATREG (vs
, ovX
);
4113 else if ((aop
== 2 || aop
== 3) && aopcde
== 5)
4115 bs32 val0
= DREG (src0
);
4116 bs32 val1
= DREG (src1
);
4119 TRACE_INSN (cpu
, "R%i.%s = R%i %s R%i (RND20)", dst0
, HL
? "L" : "H",
4120 src0
, aop
& 0x1 ? "-" : "+", src1
);
4122 /* If subtract, just invert and add one. */
4126 res
= (val0
>> 4) + (val1
>> 4) + (((val0
& 0xf) + (val1
& 0xf)) >> 4);
4128 /* Don't sign extend during the shift. */
4129 res
= ((bu32
)res
>> 16);
4131 /* Don't worry about overflows, since we are shifting right. */
4134 STORE (DREG (dst0
), REG_H_L (res
<< 16, DREG (dst0
)));
4136 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), res
));
4138 SET_ASTATREG (az
, res
== 0);
4139 SET_ASTATREG (an
, res
& 0x8000);
4140 SET_ASTATREG (v
, 0);
4142 else if (aopcde
== 2 || aopcde
== 3)
4144 bu32 s1
, s2
, val
, ac0_i
= 0, v_i
= 0;
4146 TRACE_INSN (cpu
, "R%i.%c = R%i.%c %c R%i.%c%s;",
4147 dst0
, HL
? 'H' : 'L',
4148 src0
, aop
& 2 ? 'H' : 'L',
4149 aopcde
== 2 ? '+' : '-',
4150 src1
, aop
& 1 ? 'H' : 'L',
4161 val
= add16 (cpu
, s1
, s2
, &ac0_i
, &v_i
, 0, 0, s
, 0);
4163 val
= sub16 (cpu
, s1
, s2
, &ac0_i
, &v_i
, 0, 0, s
, 0);
4165 SET_ASTATREG (ac0
, ac0_i
);
4166 SET_ASTATREG (v
, v_i
);
4168 SET_ASTATREG (vs
, v_i
);
4171 SET_DREG_H (dst0
, val
<< 16);
4173 SET_DREG_L (dst0
, val
);
4175 SET_ASTATREG (an
, val
& 0x8000);
4176 SET_ASTATREG (az
, val
== 0);
4178 else if ((aop
== 0 || aop
== 2) && aopcde
== 9 && s
== 1)
4181 TRACE_INSN (cpu
, "A%i = R%i;", a
, src0
);
4182 SET_AREG32 (a
, DREG (src0
));
4184 else if ((aop
== 1 || aop
== 3) && aopcde
== 9 && s
== 0)
4187 TRACE_INSN (cpu
, "A%i.X = R%i.L;", a
, src0
);
4188 SET_AXREG (a
, (bs8
)DREG (src0
));
4190 else if (aop
== 3 && aopcde
== 11 && (s
== 0 || s
== 1))
4192 bu64 acc0
= get_extended_acc (cpu
, 0);
4193 bu64 acc1
= get_extended_acc (cpu
, 1);
4194 bu32 carry
= (bu40
)acc1
< (bu40
)acc0
;
4197 TRACE_INSN (cpu
, "A0 -= A1%s;", s
? " (W32)" : "");
4200 if ((bs64
)acc0
< -0x8000000000ll
)
4201 acc0
= -0x8000000000ull
, sat
= 1;
4202 else if ((bs64
)acc0
>= 0x7fffffffffll
)
4203 acc0
= 0x7fffffffffull
, sat
= 1;
4207 /* A0 -= A1 (W32) */
4208 if (acc0
& (bu64
)0x8000000000ll
)
4209 acc0
&= 0x80ffffffffll
, sat
= 1;
4211 acc0
&= 0xffffffffll
;
4213 STORE (AXREG (0), (acc0
>> 32) & 0xff);
4214 STORE (AWREG (0), acc0
& 0xffffffff);
4215 STORE (ASTATREG (az
), acc0
== 0);
4216 STORE (ASTATREG (an
), !!(acc0
& (bu64
)0x8000000000ll
));
4217 STORE (ASTATREG (ac0
), carry
);
4218 STORE (ASTATREG (ac0_copy
), carry
);
4219 STORE (ASTATREG (av0
), sat
);
4221 STORE (ASTATREG (av0s
), sat
);
4223 else if ((aop
== 0 || aop
== 1) && aopcde
== 22)
4225 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4227 const char * const opts
[] = { "rndl", "rndh", "tl", "th" };
4229 TRACE_INSN (cpu
, "R%i = BYTEOP2P (R%i:%i, R%i:%i) (%s%s);", dst0
,
4230 src0
+ 1, src0
, src1
+ 1, src1
, opts
[HL
+ (aop
<< 1)],
4234 s0H
= DREG (src0
+ 1);
4236 s1H
= DREG (src1
+ 1);
4239 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4240 s1
= algn (s1H
, s1L
, IREG (0) & 3);
4244 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4245 s1
= algn (s1L
, s1H
, IREG (0) & 3);
4249 tmp0
= ((((s1
>> 8) & 0xff) + ((s1
>> 0) & 0xff) +
4250 ((s0
>> 8) & 0xff) + ((s0
>> 0) & 0xff) + i
) >> 2) & 0xff;
4251 tmp1
= ((((s1
>> 24) & 0xff) + ((s1
>> 16) & 0xff) +
4252 ((s0
>> 24) & 0xff) + ((s0
>> 16) & 0xff) + i
) >> 2) & 0xff;
4253 STORE (DREG (dst0
), (tmp1
<< (16 + (HL
* 8))) | (tmp0
<< (HL
* 8)));
4255 /* Implicit DISALGNEXCPT in parallel. */
4258 else if ((aop
== 0 || aop
== 1) && s
== 0 && aopcde
== 8)
4260 TRACE_INSN (cpu
, "A%i = 0;", aop
);
4263 else if (aop
== 2 && s
== 0 && aopcde
== 8)
4265 TRACE_INSN (cpu
, "A1 = A0 = 0;");
4269 else if ((aop
== 0 || aop
== 1 || aop
== 2) && s
== 1 && aopcde
== 8)
4271 bs40 acc0
= get_extended_acc (cpu
, 0);
4272 bs40 acc1
= get_extended_acc (cpu
, 1);
4275 if (aop
== 0 || aop
== 1)
4276 TRACE_INSN (cpu
, "A%i = A%i (S);", aop
, aop
);
4278 TRACE_INSN (cpu
, "A1 = A1 (S), A0 = A0 (S);");
4280 if (aop
== 0 || aop
== 2)
4283 acc0
= saturate_s32 (acc0
, &sat
);
4284 acc0
|= -(acc0
& 0x80000000ull
);
4285 SET_AXREG (0, (acc0
>> 31) & 0xFF);
4286 SET_AWREG (0, acc0
& 0xFFFFFFFF);
4287 SET_ASTATREG (av0
, sat
);
4289 SET_ASTATREG (av0s
, sat
);
4294 if (aop
== 1 || aop
== 2)
4297 acc1
= saturate_s32 (acc1
, &sat
);
4298 acc1
|= -(acc1
& 0x80000000ull
);
4299 SET_AXREG (1, (acc1
>> 31) & 0xFF);
4300 SET_AWREG (1, acc1
& 0xFFFFFFFF);
4301 SET_ASTATREG (av1
, sat
);
4303 SET_ASTATREG (av1s
, sat
);
4308 SET_ASTATREG (az
, (acc0
== 0) || (acc1
== 0));
4309 SET_ASTATREG (an
, ((acc0
>> 31) & 1) || ((acc1
>> 31) & 1));
4311 else if (aop
== 3 && (s
== 0 || s
== 1) && aopcde
== 8)
4313 TRACE_INSN (cpu
, "A%i = A%i;", s
, !s
);
4314 SET_AXREG (s
, AXREG (!s
));
4315 SET_AWREG (s
, AWREG (!s
));
4317 else if (aop
== 3 && HL
== 0 && aopcde
== 16)
4322 TRACE_INSN (cpu
, "A1 = ABS A1 , A0 = ABS A0;");
4325 for (i
= 0; i
< 2; ++i
)
4328 bs40 acc
= get_extended_acc (cpu
, i
);
4332 av
= acc
== ((bs40
)1 << 39);
4334 acc
= ((bs40
)1 << 39) - 1;
4337 SET_ASTATREG (av
[i
], av
);
4339 SET_ASTATREG (avs
[i
], av
);
4342 SET_ASTATREG (az
, az
);
4343 SET_ASTATREG (an
, 0);
4345 else if (aop
== 0 && aopcde
== 23)
4347 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4350 TRACE_INSN (cpu
, "R%i = BYTEOP3P (R%i:%i, R%i:%i) (%s%s);", dst0
,
4351 src0
+ 1, src0
, src1
+ 1, src1
, HL
? "HI" : "LO",
4355 s0H
= DREG (src0
+ 1);
4357 s1H
= DREG (src1
+ 1);
4360 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4361 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4365 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4366 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4369 tmp0
= (bs32
)(bs16
)(s0
>> 0) + ((s1
>> ( 0 + (8 * !HL
))) & 0xff);
4370 tmp1
= (bs32
)(bs16
)(s0
>> 16) + ((s1
>> (16 + (8 * !HL
))) & 0xff);
4371 STORE (DREG (dst0
), (CLAMP (tmp0
, 0, 255) << ( 0 + (8 * HL
))) |
4372 (CLAMP (tmp1
, 0, 255) << (16 + (8 * HL
))));
4374 /* Implicit DISALGNEXCPT in parallel. */
4377 else if ((aop
== 0 || aop
== 1) && aopcde
== 16)
4382 TRACE_INSN (cpu
, "A%i = ABS A%i;", HL
, aop
);
4384 acc
= get_extended_acc (cpu
, aop
);
4387 av
= acc
== ((bs40
)1 << 39);
4389 acc
= ((bs40
)1 << 39) - 1;
4392 SET_ASTATREG (av
[HL
], av
);
4394 SET_ASTATREG (avs
[HL
], av
);
4395 SET_ASTATREG (az
, acc
== 0);
4396 SET_ASTATREG (an
, 0);
4398 else if (aop
== 3 && aopcde
== 12)
4400 bs32 res
= DREG (src0
);
4402 bool sBit_a
, sBit_b
;
4404 TRACE_INSN (cpu
, "R%i.%s = R%i (RND);", dst0
, HL
== 0 ? "L" : "H", src0
);
4405 TRACE_DECODE (cpu
, "R%i.%s = R%i:%#x (RND);", dst0
,
4406 HL
== 0 ? "L" : "H", src0
, res
);
4408 sBit_b
= !!(res
& 0x80000000);
4411 sBit_a
= !!(res
& 0x80000000);
4413 /* Overflow if the sign bit changed when we rounded. */
4414 if ((res
>> 16) && (sBit_b
!= sBit_a
))
4429 SET_DREG (dst0
, REG_H_L (DREG (dst0
), res
));
4431 SET_DREG (dst0
, REG_H_L (res
<< 16, DREG (dst0
)));
4433 SET_ASTATREG (az
, res
== 0);
4434 SET_ASTATREG (an
, res
< 0);
4435 SET_ASTATREG (v
, ovX
);
4437 SET_ASTATREG (vs
, ovX
);
4439 else if (aop
== 3 && HL
== 0 && aopcde
== 15)
4441 bu32 hi
= (-(bs16
)(DREG (src0
) >> 16)) << 16;
4442 bu32 lo
= (-(bs16
)(DREG (src0
) & 0xFFFF)) & 0xFFFF;
4445 TRACE_INSN (cpu
, "R%i = -R%i (V);", dst0
, src0
);
4449 if (hi
== 0x80000000)
4465 SET_DREG (dst0
, hi
| lo
);
4467 SET_ASTATREG (v
, v
);
4469 SET_ASTATREG (vs
, 1);
4470 SET_ASTATREG (ac0
, ac0
);
4471 SET_ASTATREG (ac1
, ac1
);
4472 setflags_nz_2x16 (cpu
, DREG (dst0
));
4474 else if (aop
== 3 && HL
== 0 && aopcde
== 14)
4476 TRACE_INSN (cpu
, "A1 = - A1 , A0 = - A0;");
4478 SET_AREG (0, saturate_s40 (-get_extended_acc (cpu
, 0)));
4479 SET_AREG (1, saturate_s40 (-get_extended_acc (cpu
, 1)));
4480 /* XXX: what ASTAT flags need updating ? */
4482 else if ((aop
== 0 || aop
== 1) && (HL
== 0 || HL
== 1) && aopcde
== 14)
4484 bs40 src_acc
= get_extended_acc (cpu
, aop
);
4487 TRACE_INSN (cpu
, "A%i = - A%i;", HL
, aop
);
4489 SET_AREG (HL
, saturate_s40_astat (-src_acc
, &v
));
4491 SET_ASTATREG (az
, AWREG (HL
) == 0 && AXREG (HL
) == 0);
4492 SET_ASTATREG (an
, AXREG (HL
) >> 7);
4495 SET_ASTATREG (ac0
, !src_acc
);
4496 SET_ASTATREG (av0
, v
);
4498 SET_ASTATREG (av0s
, 1);
4502 SET_ASTATREG (ac1
, !src_acc
);
4503 SET_ASTATREG (av1
, v
);
4505 SET_ASTATREG (av1s
, 1);
4508 else if (aop
== 0 && aopcde
== 12)
4510 bs16 tmp0_hi
= DREG (src0
) >> 16;
4511 bs16 tmp0_lo
= DREG (src0
);
4512 bs16 tmp1_hi
= DREG (src1
) >> 16;
4513 bs16 tmp1_lo
= DREG (src1
);
4515 TRACE_INSN (cpu
, "R%i.L = R%i.H = SIGN(R%i.H) * R%i.H + SIGN(R%i.L) * R%i.L;",
4516 dst0
, dst0
, src0
, src1
, src0
, src1
);
4518 if ((tmp0_hi
>> 15) & 1)
4519 tmp1_hi
= ~tmp1_hi
+ 1;
4521 if ((tmp0_lo
>> 15) & 1)
4522 tmp1_lo
= ~tmp1_lo
+ 1;
4524 tmp1_hi
= tmp1_hi
+ tmp1_lo
;
4526 STORE (DREG (dst0
), REG_H_L (tmp1_hi
<< 16, tmp1_hi
));
4528 else if (aopcde
== 0)
4530 bu32 s0
= DREG (src0
);
4531 bu32 s1
= DREG (src1
);
4532 bu32 s0h
= s0
>> 16;
4533 bu32 s0l
= s0
& 0xFFFF;
4534 bu32 s1h
= s1
>> 16;
4535 bu32 s1l
= s1
& 0xFFFF;
4537 bu32 ac1_i
= 0, ac0_i
= 0, v_i
= 0, z_i
= 0, n_i
= 0;
4539 TRACE_INSN (cpu
, "R%i = R%i %c|%c R%i%s;", dst0
, src0
,
4540 (aop
& 2) ? '-' : '+', (aop
& 1) ? '-' : '+', src1
,
4543 t0
= sub16 (cpu
, s0h
, s1h
, &ac1_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4545 t0
= add16 (cpu
, s0h
, s1h
, &ac1_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4548 t1
= sub16 (cpu
, s0l
, s1l
, &ac0_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4550 t1
= add16 (cpu
, s0l
, s1l
, &ac0_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4552 SET_ASTATREG (ac1
, ac1_i
);
4553 SET_ASTATREG (ac0
, ac0_i
);
4554 SET_ASTATREG (az
, z_i
);
4555 SET_ASTATREG (an
, n_i
);
4556 SET_ASTATREG (v
, v_i
);
4558 SET_ASTATREG (vs
, v_i
);
4563 SET_DREG (dst0
, (t1
<< 16) | t0
);
4565 SET_DREG (dst0
, (t0
<< 16) | t1
);
4567 else if (aop
== 1 && aopcde
== 12)
4569 bs32 val0
= (bs16
)(AWREG (0) >> 16) + (bs16
)AWREG (0);
4570 bs32 val1
= (bs16
)(AWREG (1) >> 16) + (bs16
)AWREG (1);
4572 TRACE_INSN (cpu
, "R%i = A1.L + A1.H, R%i = A0.L + A0.H;", dst1
, dst0
);
4575 illegal_instruction_combination (cpu
);
4577 SET_DREG (dst0
, val0
);
4578 SET_DREG (dst1
, val1
);
4580 else if (aopcde
== 1)
4584 bu16 s0L
= DREG (src0
);
4585 bu16 s0H
= DREG (src0
) >> 16;
4586 bu16 s1L
= DREG (src1
);
4587 bu16 s1H
= DREG (src1
) >> 16;
4588 bu32 v_i
= 0, n_i
= 0, z_i
= 0;
4590 TRACE_INSN (cpu
, "R%i = R%i %s R%i, R%i = R%i %s R%i%s;",
4591 dst1
, src0
, HL
? "+|-" : "+|+", src1
,
4592 dst0
, src0
, HL
? "-|+" : "-|-", src1
,
4593 amod0amod2 (s
, x
, aop
));
4596 illegal_instruction_combination (cpu
);
4600 x0
= add16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4601 x1
= add16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4602 d1
= (x0
<< 16) | x1
;
4604 x0
= sub16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4605 x1
= sub16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4607 d0
= (x0
<< 16) | x1
;
4609 d0
= (x1
<< 16) | x0
;
4613 x0
= add16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4614 x1
= sub16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4615 d1
= (x0
<< 16) | x1
;
4617 x0
= sub16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4618 x1
= add16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4620 d0
= (x0
<< 16) | x1
;
4622 d0
= (x1
<< 16) | x0
;
4624 SET_ASTATREG (az
, z_i
);
4625 SET_ASTATREG (an
, n_i
);
4626 SET_ASTATREG (v
, v_i
);
4628 SET_ASTATREG (vs
, v_i
);
4630 STORE (DREG (dst0
), d0
);
4631 STORE (DREG (dst1
), d1
);
4633 else if ((aop
== 0 || aop
== 1 || aop
== 2) && aopcde
== 11)
4635 bs40 acc0
= get_extended_acc (cpu
, 0);
4636 bs40 acc1
= get_extended_acc (cpu
, 1);
4637 bu32 v
, dreg
, sat
= 0;
4638 bu32 carry
= !!((bu40
)~acc1
< (bu40
)acc0
);
4641 TRACE_INSN (cpu
, "R%i = (A0 += A1);", dst0
);
4643 TRACE_INSN (cpu
, "R%i.%c = (A0 += A1);", dst0
, HL
? 'H' : 'L');
4645 TRACE_INSN (cpu
, "A0 += A1%s;", s
? " (W32)" : "");
4648 acc0
= saturate_s40_astat (acc0
, &v
);
4650 if (aop
== 2 && s
== 1) /* A0 += A1 (W32) */
4652 if (acc0
& (bs40
)0x8000000000ll
)
4653 acc0
&= 0x80ffffffffll
;
4655 acc0
&= 0xffffffffll
;
4658 STORE (AXREG (0), acc0
>> 32);
4659 STORE (AWREG (0), acc0
);
4660 SET_ASTATREG (av0
, v
&& acc1
);
4662 SET_ASTATREG (av0s
, v
);
4664 if (aop
== 0 || aop
== 1)
4666 if (aop
) /* Dregs_lo = A0 += A1 */
4668 dreg
= saturate_s32 (rnd16 (acc0
) << 16, &sat
);
4670 STORE (DREG (dst0
), REG_H_L (dreg
, DREG (dst0
)));
4672 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), dreg
>> 16));
4674 else /* Dregs = A0 += A1 */
4676 dreg
= saturate_s32 (acc0
, &sat
);
4677 STORE (DREG (dst0
), dreg
);
4680 STORE (ASTATREG (az
), dreg
== 0);
4681 STORE (ASTATREG (an
), !!(dreg
& 0x80000000));
4682 STORE (ASTATREG (ac0
), carry
);
4683 STORE (ASTATREG (ac0_copy
), carry
);
4684 STORE (ASTATREG (v
), sat
);
4685 STORE (ASTATREG (v_copy
), sat
);
4687 STORE (ASTATREG (vs
), sat
);
4691 STORE (ASTATREG (az
), acc0
== 0);
4692 STORE (ASTATREG (an
), !!(acc0
& 0x8000000000ull
));
4693 STORE (ASTATREG (ac0
), carry
);
4694 STORE (ASTATREG (ac0_copy
), carry
);
4697 else if ((aop
== 0 || aop
== 1) && aopcde
== 10)
4699 TRACE_INSN (cpu
, "R%i.L = A%i.X;", dst0
, aop
);
4700 SET_DREG_L (dst0
, (bs8
)AXREG (aop
));
4702 else if (aop
== 0 && aopcde
== 4)
4704 TRACE_INSN (cpu
, "R%i = R%i + R%i%s;", dst0
, src0
, src1
, amod1 (s
, x
));
4705 SET_DREG (dst0
, add32 (cpu
, DREG (src0
), DREG (src1
), 1, s
));
4707 else if (aop
== 1 && aopcde
== 4)
4709 TRACE_INSN (cpu
, "R%i = R%i - R%i%s;", dst0
, src0
, src1
, amod1 (s
, x
));
4710 SET_DREG (dst0
, sub32 (cpu
, DREG (src0
), DREG (src1
), 1, s
, 0));
4712 else if (aop
== 2 && aopcde
== 4)
4714 TRACE_INSN (cpu
, "R%i = R%i + R%i, R%i = R%i - R%i%s;",
4715 dst1
, src0
, src1
, dst0
, src0
, src1
, amod1 (s
, x
));
4718 illegal_instruction_combination (cpu
);
4720 STORE (DREG (dst1
), add32 (cpu
, DREG (src0
), DREG (src1
), 1, s
));
4721 STORE (DREG (dst0
), sub32 (cpu
, DREG (src0
), DREG (src1
), 1, s
, 1));
4723 else if ((aop
== 0 || aop
== 1) && aopcde
== 17)
4725 bs40 acc0
= get_extended_acc (cpu
, 0);
4726 bs40 acc1
= get_extended_acc (cpu
, 1);
4727 bs40 val0
, val1
, sval0
, sval1
;
4730 TRACE_INSN (cpu
, "R%i = A%i + A%i, R%i = A%i - A%i%s",
4731 dst1
, !aop
, aop
, dst0
, !aop
, aop
, amod1 (s
, x
));
4732 TRACE_DECODE (cpu
, "R%i = A%i:%#"PRIx64
" + A%i:%#"PRIx64
", "
4733 "R%i = A%i:%#"PRIx64
" - A%i:%#"PRIx64
"%s",
4734 dst1
, !aop
, aop
? acc0
: acc1
, aop
, aop
? acc1
: acc0
,
4735 dst0
, !aop
, aop
? acc0
: acc1
, aop
, aop
? acc1
: acc0
,
4739 illegal_instruction_combination (cpu
);
4747 sval0
= saturate_s32 (val0
, &sat
);
4749 sval1
= saturate_s32 (val1
, &sat
);
4757 STORE (DREG (dst0
), val0
);
4758 STORE (DREG (dst1
), val1
);
4759 SET_ASTATREG (v
, sat_i
);
4761 SET_ASTATREG (vs
, sat_i
);
4762 SET_ASTATREG (an
, val0
& 0x80000000 || val1
& 0x80000000);
4763 SET_ASTATREG (az
, val0
== 0 || val1
== 0);
4764 SET_ASTATREG (ac1
, (bu40
)~acc0
< (bu40
)acc1
);
4766 SET_ASTATREG (ac0
, !!((bu40
)acc1
<= (bu40
)acc0
));
4768 SET_ASTATREG (ac0
, !!((bu40
)acc0
<= (bu40
)acc1
));
4770 else if (aop
== 0 && aopcde
== 18)
4772 bu40 acc0
= get_extended_acc (cpu
, 0);
4773 bu40 acc1
= get_extended_acc (cpu
, 1);
4774 bu32 s0L
= DREG (src0
);
4775 bu32 s0H
= DREG (src0
+ 1);
4776 bu32 s1L
= DREG (src1
);
4777 bu32 s1H
= DREG (src1
+ 1);
4779 bs16 tmp0
, tmp1
, tmp2
, tmp3
;
4781 /* This instruction is only defined for register pairs R1:0 and R3:2. */
4782 if (!((src0
== 0 || src0
== 2) && (src1
== 0 || src1
== 2)))
4783 illegal_instruction (cpu
);
4785 TRACE_INSN (cpu
, "SAA (R%i:%i, R%i:%i)%s", src0
+ 1, src0
,
4786 src1
+ 1, src1
, s
? " (R)" :"");
4788 /* Bit s determines the order of the two registers from a pair:
4789 if s=0 the low-order bytes come from the low reg in the pair,
4790 and if s=1 the low-order bytes come from the high reg. */
4794 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4795 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4799 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4800 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4803 /* Find the absolute difference between pairs, make it
4804 absolute, then add it to the existing accumulator half. */
4806 tmp0
= ((s0
<< 24) >> 24) - ((s1
<< 24) >> 24);
4807 tmp1
= ((s0
<< 16) >> 24) - ((s1
<< 16) >> 24);
4808 tmp2
= ((s0
<< 8) >> 24) - ((s1
<< 8) >> 24);
4809 tmp3
= ((s0
<< 0) >> 24) - ((s1
<< 0) >> 24);
4811 tmp0
= (tmp0
< 0) ? -tmp0
: tmp0
;
4812 tmp1
= (tmp1
< 0) ? -tmp1
: tmp1
;
4813 tmp2
= (tmp2
< 0) ? -tmp2
: tmp2
;
4814 tmp3
= (tmp3
< 0) ? -tmp3
: tmp3
;
4816 s0L
= saturate_u16 ((bu32
)tmp0
+ ((acc0
>> 0) & 0xffff), 0);
4817 s0H
= saturate_u16 ((bu32
)tmp1
+ ((acc0
>> 16) & 0xffff), 0);
4818 s1L
= saturate_u16 ((bu32
)tmp2
+ ((acc1
>> 0) & 0xffff), 0);
4819 s1H
= saturate_u16 ((bu32
)tmp3
+ ((acc1
>> 16) & 0xffff), 0);
4821 STORE (AWREG (0), (s0H
<< 16) | (s0L
& 0xFFFF));
4822 STORE (AXREG (0), 0);
4823 STORE (AWREG (1), (s1H
<< 16) | (s1L
& 0xFFFF));
4824 STORE (AXREG (1), 0);
4826 /* Implicit DISALGNEXCPT in parallel. */
4829 else if (aop
== 3 && aopcde
== 18)
4831 TRACE_INSN (cpu
, "DISALGNEXCPT");
4834 else if ((aop
== 0 || aop
== 1) && aopcde
== 20)
4836 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4837 const char * const opts
[] = { "", " (R)", " (T)", " (T, R)" };
4839 TRACE_INSN (cpu
, "R%i = BYTEOP1P (R%i:%i, R%i:%i)%s;", dst0
,
4840 src0
+ 1, src0
, src1
+ 1, src1
, opts
[s
+ (aop
<< 1)]);
4843 s0H
= DREG (src0
+ 1);
4845 s1H
= DREG (src1
+ 1);
4848 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4849 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4853 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4854 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4858 (((((s0
>> 0) & 0xff) + ((s1
>> 0) & 0xff) + !aop
) >> 1) << 0) |
4859 (((((s0
>> 8) & 0xff) + ((s1
>> 8) & 0xff) + !aop
) >> 1) << 8) |
4860 (((((s0
>> 16) & 0xff) + ((s1
>> 16) & 0xff) + !aop
) >> 1) << 16) |
4861 (((((s0
>> 24) & 0xff) + ((s1
>> 24) & 0xff) + !aop
) >> 1) << 24));
4863 /* Implicit DISALGNEXCPT in parallel. */
4866 else if (aop
== 0 && aopcde
== 21)
4868 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4870 TRACE_INSN (cpu
, "(R%i, R%i) = BYTEOP16P (R%i:%i, R%i:%i)%s;", dst1
, dst0
,
4871 src0
+ 1, src0
, src1
+ 1, src1
, s
? " (R)" : "");
4874 illegal_instruction_combination (cpu
);
4877 s0H
= DREG (src0
+ 1);
4879 s1H
= DREG (src1
+ 1);
4882 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4883 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4887 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4888 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4892 ((((s0
>> 0) & 0xff) + ((s1
>> 0) & 0xff)) << 0) |
4893 ((((s0
>> 8) & 0xff) + ((s1
>> 8) & 0xff)) << 16));
4895 ((((s0
>> 16) & 0xff) + ((s1
>> 16) & 0xff)) << 0) |
4896 ((((s0
>> 24) & 0xff) + ((s1
>> 24) & 0xff)) << 16));
4898 /* Implicit DISALGNEXCPT in parallel. */
4901 else if (aop
== 1 && aopcde
== 21)
4903 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4905 TRACE_INSN (cpu
, "(R%i, R%i) = BYTEOP16M (R%i:%i, R%i:%i)%s;", dst1
, dst0
,
4906 src0
+ 1, src0
, src1
+ 1, src1
, s
? " (R)" : "");
4909 illegal_instruction_combination (cpu
);
4912 s0H
= DREG (src0
+ 1);
4914 s1H
= DREG (src1
+ 1);
4917 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4918 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4922 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4923 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4927 (((((s0
>> 0) & 0xff) - ((s1
>> 0) & 0xff)) << 0) & 0xffff) |
4928 (((((s0
>> 8) & 0xff) - ((s1
>> 8) & 0xff)) << 16)));
4930 (((((s0
>> 16) & 0xff) - ((s1
>> 16) & 0xff)) << 0) & 0xffff) |
4931 (((((s0
>> 24) & 0xff) - ((s1
>> 24) & 0xff)) << 16)));
4933 /* Implicit DISALGNEXCPT in parallel. */
4936 else if (aop
== 1 && aopcde
== 7)
4938 TRACE_INSN (cpu
, "R%i = MIN (R%i, R%i);", dst0
, src0
, src1
);
4939 SET_DREG (dst0
, min32 (cpu
, DREG (src0
), DREG (src1
)));
4941 else if (aop
== 0 && aopcde
== 7)
4943 TRACE_INSN (cpu
, "R%i = MAX (R%i, R%i);", dst0
, src0
, src1
);
4944 SET_DREG (dst0
, max32 (cpu
, DREG (src0
), DREG (src1
)));
4946 else if (aop
== 2 && aopcde
== 7)
4948 bu32 val
= DREG (src0
);
4951 TRACE_INSN (cpu
, "R%i = ABS R%i;", dst0
, src0
);
4955 v
= (val
== 0x80000000);
4958 SET_DREG (dst0
, val
);
4960 SET_ASTATREG (v
, v
);
4962 SET_ASTATREG (vs
, 1);
4963 setflags_nz (cpu
, val
);
4965 else if (aop
== 3 && aopcde
== 7)
4967 bu32 val
= DREG (src0
);
4969 TRACE_INSN (cpu
, "R%i = - R%i %s;", dst0
, src0
, amod1 (s
, 0));
4971 if (s
&& val
== 0x80000000)
4974 SET_ASTATREG (v
, 1);
4975 SET_ASTATREG (vs
, 1);
4977 else if (val
== 0x80000000)
4981 SET_DREG (dst0
, val
);
4983 SET_ASTATREG (az
, val
== 0);
4984 SET_ASTATREG (an
, val
& 0x80000000);
4986 else if (aop
== 2 && aopcde
== 6)
4988 bu32 in
= DREG (src0
);
4989 bu32 hi
= (in
& 0x80000000 ? (bu32
)-(bs16
)(in
>> 16) : in
>> 16) << 16;
4990 bu32 lo
= (in
& 0x8000 ? (bu32
)-(bs16
)(in
& 0xFFFF) : in
) & 0xFFFF;
4993 TRACE_INSN (cpu
, "R%i = ABS R%i (V);", dst0
, src0
);
4996 if (hi
== 0x80000000)
5006 SET_DREG (dst0
, hi
| lo
);
5008 SET_ASTATREG (v
, v
);
5010 SET_ASTATREG (vs
, 1);
5011 setflags_nz_2x16 (cpu
, DREG (dst0
));
5013 else if (aop
== 1 && aopcde
== 6)
5015 TRACE_INSN (cpu
, "R%i = MIN (R%i, R%i) (V);", dst0
, src0
, src1
);
5016 SET_DREG (dst0
, min2x16 (cpu
, DREG (src0
), DREG (src1
)));
5018 else if (aop
== 0 && aopcde
== 6)
5020 TRACE_INSN (cpu
, "R%i = MAX (R%i, R%i) (V);", dst0
, src0
, src1
);
5021 SET_DREG (dst0
, max2x16 (cpu
, DREG (src0
), DREG (src1
)));
5023 else if (aop
== 0 && aopcde
== 24)
5025 TRACE_INSN (cpu
, "R%i = BYTEPACK (R%i, R%i);", dst0
, src0
, src1
);
5027 (((DREG (src0
) >> 0) & 0xff) << 0) |
5028 (((DREG (src0
) >> 16) & 0xff) << 8) |
5029 (((DREG (src1
) >> 0) & 0xff) << 16) |
5030 (((DREG (src1
) >> 16) & 0xff) << 24));
5032 /* Implicit DISALGNEXCPT in parallel. */
5035 else if (aop
== 1 && aopcde
== 24)
5039 bu8 bytea
, byteb
, bytec
, byted
;
5041 TRACE_INSN (cpu
, "(R%i, R%i) = BYTEUNPACK R%i:%i%s;",
5042 dst1
, dst0
, src0
+ 1, src0
, s
? " (R)" : "");
5045 illegal_instruction_combination (cpu
);
5047 order
= IREG (0) & 0x3;
5049 hi
= src0
, lo
= src0
+ 1;
5051 hi
= src0
+ 1, lo
= src0
;
5052 comb_src
= (((bu64
)DREG (hi
)) << 32) | DREG (lo
);
5053 bytea
= (comb_src
>> (0 + 8 * order
));
5054 byteb
= (comb_src
>> (8 + 8 * order
));
5055 bytec
= (comb_src
>> (16 + 8 * order
));
5056 byted
= (comb_src
>> (24 + 8 * order
));
5057 STORE (DREG (dst0
), bytea
| ((bu32
)byteb
<< 16));
5058 STORE (DREG (dst1
), bytec
| ((bu32
)byted
<< 16));
5060 /* Implicit DISALGNEXCPT in parallel. */
5063 else if (aopcde
== 13)
5065 const char *searchmodes
[] = { "GT", "GE", "LT", "LE" };
5067 bs16 a0_lo
, a1_lo
, src_hi
, src_lo
;
5069 TRACE_INSN (cpu
, "(R%i, R%i) = SEARCH R%i (%s);",
5070 dst1
, dst0
, src0
, searchmodes
[aop
]);
5073 illegal_instruction_combination (cpu
);
5075 up_hi
= up_lo
= false;
5078 src_lo
= DREG (src0
);
5079 src_hi
= DREG (src0
) >> 16;
5084 up_hi
= (src_hi
> a1_lo
);
5085 up_lo
= (src_lo
> a0_lo
);
5088 up_hi
= (src_hi
>= a1_lo
);
5089 up_lo
= (src_lo
>= a0_lo
);
5092 up_hi
= (src_hi
< a1_lo
);
5093 up_lo
= (src_lo
< a0_lo
);
5096 up_hi
= (src_hi
<= a1_lo
);
5097 up_lo
= (src_lo
<= a0_lo
);
5103 SET_AREG (1, src_hi
);
5104 SET_DREG (dst1
, PREG (0));
5107 SET_AREG (1, a1_lo
);
5111 SET_AREG (0, src_lo
);
5112 SET_DREG (dst0
, PREG (0));
5115 SET_AREG (0, a0_lo
);
5118 illegal_instruction (cpu
);
5122 decode_dsp32shift_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
5125 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5126 | 1 | 1 | 0 | 0 |.M.| 1 | 1 | 0 | 0 | - | - |.sopcde............|
5127 |.sop...|.HLs...|.dst0......| - | - | - |.src0......|.src1......|
5128 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5129 int HLs
= ((iw1
>> DSP32Shift_HLs_bits
) & DSP32Shift_HLs_mask
);
5130 int sop
= ((iw1
>> DSP32Shift_sop_bits
) & DSP32Shift_sop_mask
);
5131 int src0
= ((iw1
>> DSP32Shift_src0_bits
) & DSP32Shift_src0_mask
);
5132 int src1
= ((iw1
>> DSP32Shift_src1_bits
) & DSP32Shift_src1_mask
);
5133 int dst0
= ((iw1
>> DSP32Shift_dst0_bits
) & DSP32Shift_dst0_mask
);
5134 int sopcde
= ((iw0
>> (DSP32Shift_sopcde_bits
- 16)) & DSP32Shift_sopcde_mask
);
5135 int M
= ((iw0
>> (DSP32Shift_M_bits
- 16)) & DSP32Shift_M_mask
);
5137 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32shift
);
5138 TRACE_EXTRACT (cpu
, "%s: M:%i sopcde:%i sop:%i HLs:%i dst0:%i src0:%i src1:%i",
5139 __func__
, M
, sopcde
, sop
, HLs
, dst0
, src0
, src1
);
5141 if ((sop
== 0 || sop
== 1) && sopcde
== 0)
5144 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5146 TRACE_INSN (cpu
, "R%i.%c = ASHIFT R%i.%c BY R%i.L%s;",
5147 dst0
, HLs
< 2 ? 'L' : 'H',
5148 src1
, HLs
& 1 ? 'H' : 'L',
5149 src0
, sop
== 1 ? " (S)" : "");
5152 val
= (bu16
)(DREG (src1
) & 0xFFFF);
5154 val
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5156 /* Positive shift magnitudes produce Logical Left shifts.
5157 Negative shift magnitudes produce Arithmetic Right shifts. */
5159 val
= ashiftrt (cpu
, val
, -shft
, 16);
5161 val
= lshift (cpu
, val
, shft
, 16, sop
== 1);
5164 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), val
));
5166 STORE (DREG (dst0
), REG_H_L (val
<< 16, DREG (dst0
)));
5168 else if (sop
== 2 && sopcde
== 0)
5170 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5173 TRACE_INSN (cpu
, "R%i.%c = LSHIFT R%i.%c BY R%i.L;",
5174 dst0
, HLs
< 2 ? 'L' : 'H',
5175 src1
, HLs
& 1 ? 'H' : 'L', src0
);
5178 val
= (bu16
)(DREG (src1
) & 0xFFFF);
5180 val
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5183 val
= val
>> (-1 * shft
);
5188 SET_DREG (dst0
, REG_H_L (DREG (dst0
), val
));
5190 SET_DREG (dst0
, REG_H_L (val
<< 16, DREG (dst0
)));
5192 SET_ASTATREG (az
, !((val
& 0xFFFF0000) == 0) || ((val
& 0xFFFF) == 0));
5193 SET_ASTATREG (an
, (!!(val
& 0x80000000)) ^ (!!(val
& 0x8000)));
5194 SET_ASTATREG (v
, 0);
5196 else if (sop
== 2 && sopcde
== 3 && (HLs
== 1 || HLs
== 0))
5198 int shift
= imm6 (DREG (src0
) & 0xFFFF);
5200 bu40 acc
= get_unextended_acc (cpu
, HLs
);
5202 TRACE_INSN (cpu
, "A%i = ROT A%i BY R%i.L;", HLs
, HLs
, src0
);
5203 TRACE_DECODE (cpu
, "A%i:%#"PRIx64
" shift:%i CC:%i", HLs
, acc
, shift
, cc
);
5205 acc
= rot40 (acc
, shift
, &cc
);
5206 SET_AREG (HLs
, acc
);
5210 else if (sop
== 0 && sopcde
== 3 && (HLs
== 0 || HLs
== 1))
5212 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5213 bu64 val
= get_extended_acc (cpu
, HLs
);
5216 TRACE_INSN (cpu
, "A%i = ASHIFT A%i BY R%i.L;", HLs
, HLs
, src0
);
5217 TRACE_DECODE (cpu
, "A%i:%#"PRIx64
" shift:%i", HLs
, val
, shft
);
5220 val
= ashiftrt (cpu
, val
, -shft
, 40);
5222 val
= lshift (cpu
, val
, shft
, 40, 0);
5224 STORE (AXREG (HLs
), (val
>> 32) & 0xff);
5225 STORE (AWREG (HLs
), (val
& 0xffffffff));
5227 else if (sop
== 1 && sopcde
== 3 && (HLs
== 0 || HLs
== 1))
5229 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5233 TRACE_INSN (cpu
, "A%i = LSHIFT A%i BY R%i.L;", HLs
, HLs
, src0
);
5234 val
= get_unextended_acc (cpu
, HLs
);
5237 val
= lshiftrt (cpu
, val
, -shft
, 40);
5239 val
= lshift (cpu
, val
, shft
, 40, 0);
5241 STORE (AXREG (HLs
), (val
>> 32) & 0xff);
5242 STORE (AWREG (HLs
), (val
& 0xffffffff));
5244 else if ((sop
== 0 || sop
== 1) && sopcde
== 1)
5246 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5250 TRACE_INSN (cpu
, "R%i = ASHIFT R%i BY R%i.L (V%s);",
5251 dst0
, src1
, src0
, sop
== 1 ? ",S" : "");
5253 val0
= (bu16
)DREG (src1
) & 0xFFFF;
5254 val1
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5258 val0
= ashiftrt (cpu
, val0
, -shft
, 16);
5260 val1
= ashiftrt (cpu
, val1
, -shft
, 16);
5264 val0
= lshift (cpu
, val0
, shft
, 16, sop
== 1);
5266 val1
= lshift (cpu
, val1
, shft
, 16, sop
== 1);
5268 SET_ASTAT (ASTAT
| astat
);
5269 STORE (DREG (dst0
), (val1
<< 16) | val0
);
5271 else if ((sop
== 0 || sop
== 1 || sop
== 2) && sopcde
== 2)
5273 /* dregs = [LA]SHIFT dregs BY dregs_lo (opt_S) */
5274 /* sop == 1 : opt_S */
5275 bu32 v
= DREG (src1
);
5276 /* LSHIFT uses sign extended low 6 bits of dregs_lo. */
5277 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5279 TRACE_INSN (cpu
, "R%i = %cSHIFT R%i BY R%i.L%s;", dst0
,
5280 shft
&& sop
!= 2 ? 'A' : 'L', src1
, src0
,
5281 sop
== 1 ? " (S)" : "");
5286 STORE (DREG (dst0
), lshiftrt (cpu
, v
, -shft
, 32));
5288 STORE (DREG (dst0
), ashiftrt (cpu
, v
, -shft
, 32));
5291 STORE (DREG (dst0
), lshift (cpu
, v
, shft
, 32, sop
== 1));
5293 else if (sop
== 3 && sopcde
== 2)
5295 int shift
= imm6 (DREG (src0
) & 0xFFFF);
5296 bu32 src
= DREG (src1
);
5297 bu32 ret
, cc
= CCREG
;
5299 TRACE_INSN (cpu
, "R%i = ROT R%i BY R%i.L;", dst0
, src1
, src0
);
5300 TRACE_DECODE (cpu
, "R%i:%#x R%i:%#x shift:%i CC:%i",
5301 dst0
, DREG (dst0
), src1
, src
, shift
, cc
);
5303 ret
= rot32 (src
, shift
, &cc
);
5304 STORE (DREG (dst0
), ret
);
5308 else if (sop
== 2 && sopcde
== 1)
5310 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5314 TRACE_INSN (cpu
, "R%i = LSHIFT R%i BY R%i.L (V);", dst0
, src1
, src0
);
5316 val0
= (bu16
)DREG (src1
) & 0xFFFF;
5317 val1
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5321 val0
= lshiftrt (cpu
, val0
, -shft
, 16);
5323 val1
= lshiftrt (cpu
, val1
, -shft
, 16);
5327 val0
= lshift (cpu
, val0
, shft
, 16, 0);
5329 val1
= lshift (cpu
, val1
, shft
, 16, 0);
5331 SET_ASTAT (ASTAT
| astat
);
5332 STORE (DREG (dst0
), (val1
<< 16) | val0
);
5334 else if (sopcde
== 4)
5336 bu32 sv0
= DREG (src0
);
5337 bu32 sv1
= DREG (src1
);
5338 TRACE_INSN (cpu
, "R%i = PACK (R%i.%c, R%i.%c);", dst0
,
5339 src1
, sop
& 2 ? 'H' : 'L',
5340 src0
, sop
& 1 ? 'H' : 'L');
5345 STORE (DREG (dst0
), (sv1
<< 16) | (sv0
& 0xFFFF));
5347 else if (sop
== 0 && sopcde
== 5)
5349 bu32 sv1
= DREG (src1
);
5350 TRACE_INSN (cpu
, "R%i.L = SIGNBITS R%i;", dst0
, src1
);
5351 SET_DREG_L (dst0
, signbits (sv1
, 32));
5353 else if (sop
== 1 && sopcde
== 5)
5355 bu32 sv1
= DREG (src1
);
5356 TRACE_INSN (cpu
, "R%i.L = SIGNBITS R%i.L;", dst0
, src1
);
5357 SET_DREG_L (dst0
, signbits (sv1
, 16));
5359 else if (sop
== 2 && sopcde
== 5)
5361 bu32 sv1
= DREG (src1
);
5362 TRACE_INSN (cpu
, "R%i.L = SIGNBITS R%i.H;", dst0
, src1
);
5363 SET_DREG_L (dst0
, signbits (sv1
>> 16, 16));
5365 else if ((sop
== 0 || sop
== 1) && sopcde
== 6)
5367 bu64 acc
= AXREG (sop
);
5368 TRACE_INSN (cpu
, "R%i.L = SIGNBITS A%i;", dst0
, sop
);
5371 SET_DREG_L (dst0
, signbits (acc
, 40) & 0xFFFF);
5373 else if (sop
== 3 && sopcde
== 6)
5375 bu32 v
= ones (DREG (src1
));
5376 TRACE_INSN (cpu
, "R%i.L = ONES R%i;", dst0
, src1
);
5377 SET_DREG_L (dst0
, v
);
5379 else if (sop
== 0 && sopcde
== 7)
5381 bu16 sv1
= (bu16
)signbits (DREG (src1
), 32);
5382 bu16 sv0
= (bu16
)DREG (src0
);
5385 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i, R%i.L);", dst0
, src1
, src0
);
5387 if ((sv1
& 0x1f) < (sv0
& 0x1f))
5391 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), dst_lo
));
5393 else if (sop
== 1 && sopcde
== 7)
5395 /* Exponent adjust on two 16-bit inputs. Select
5396 smallest norm among 3 inputs. */
5397 bs16 src1_hi
= (DREG (src1
) & 0xFFFF0000) >> 16;
5398 bs16 src1_lo
= (DREG (src1
) & 0xFFFF);
5399 bu16 src0_lo
= (DREG (src0
) & 0xFFFF);
5400 bu16 tmp_hi
, tmp_lo
, tmp
;
5402 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i, R%i.L) (V);", dst0
, src1
, src0
);
5404 tmp_hi
= signbits (src1_hi
, 16);
5405 tmp_lo
= signbits (src1_lo
, 16);
5407 if ((tmp_hi
& 0xf) < (tmp_lo
& 0xf))
5408 if ((tmp_hi
& 0xf) < (src0_lo
& 0xf))
5413 if ((tmp_lo
& 0xf) < (src0_lo
& 0xf))
5417 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), tmp
));
5419 else if (sop
== 2 && sopcde
== 7)
5421 /* Exponent adjust on single 16-bit register. */
5423 bu16 src0_lo
= (bu16
)(DREG (src0
) & 0xFFFF);
5425 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i.L, R%i.L);", dst0
, src1
, src0
);
5427 tmp
= signbits (DREG (src1
) & 0xFFFF, 16);
5429 if ((tmp
& 0xf) < (src0_lo
& 0xf))
5430 SET_DREG_L (dst0
, tmp
);
5432 SET_DREG_L (dst0
, src0_lo
);
5434 else if (sop
== 3 && sopcde
== 7)
5437 bu16 src0_lo
= (bu16
)(DREG (src0
) & 0xFFFF);
5439 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i.H, R%i.L);", dst0
, src1
, src0
);
5441 tmp
= signbits ((DREG (src1
) & 0xFFFF0000) >> 16, 16);
5443 if ((tmp
& 0xf) < (src0_lo
& 0xf))
5444 SET_DREG_L (dst0
, tmp
);
5446 SET_DREG_L (dst0
, src0_lo
);
5448 else if (sop
== 0 && sopcde
== 8)
5450 bu64 acc
= get_unextended_acc (cpu
, 0);
5453 TRACE_INSN (cpu
, "BITMUX (R%i, R%i, A0) (ASR);", src0
, src1
);
5456 illegal_instruction_combination (cpu
);
5461 (((bu64
)s0
& 1) << 38) |
5462 (((bu64
)s1
& 1) << 39);
5463 STORE (DREG (src0
), s0
>> 1);
5464 STORE (DREG (src1
), s1
>> 1);
5468 else if (sop
== 1 && sopcde
== 8)
5470 bu64 acc
= get_unextended_acc (cpu
, 0);
5473 TRACE_INSN (cpu
, "BITMUX (R%i, R%i, A0) (ASL);", src0
, src1
);
5476 illegal_instruction_combination (cpu
);
5483 STORE (DREG (src0
), s0
<< 1);
5484 STORE (DREG (src1
), s1
<< 1);
5488 else if ((sop
== 0 || sop
== 1) && sopcde
== 9)
5490 bs40 acc0
= get_unextended_acc (cpu
, 0);
5493 TRACE_INSN (cpu
, "R%i.L = VIT_MAX (R%i) (AS%c);",
5494 dst0
, src1
, sop
& 1 ? 'R' : 'L');
5497 sH
= DREG (src1
) >> 16;
5500 acc0
= (acc0
& 0xfeffffffffull
) >> 1;
5504 if (((sH
- sL
) & 0x8000) == 0)
5507 acc0
|= (sop
& 1) ? 0x80000000 : 1;
5513 SET_DREG (dst0
, REG_H_L (DREG (dst0
), out
));
5515 else if ((sop
== 2 || sop
== 3) && sopcde
== 9)
5517 bs40 acc0
= get_extended_acc (cpu
, 0);
5518 bs16 s0L
, s0H
, s1L
, s1H
, out0
, out1
;
5520 TRACE_INSN (cpu
, "R%i = VIT_MAX (R%i, R%i) (AS%c);",
5521 dst0
, src1
, src0
, sop
& 1 ? 'R' : 'L');
5524 s0H
= DREG (src0
) >> 16;
5526 s1H
= DREG (src1
) >> 16;
5533 if (((s0H
- s0L
) & 0x8000) == 0)
5536 acc0
|= (sop
& 1) ? 0x40000000 : 2;
5541 if (((s1H
- s1L
) & 0x8000) == 0)
5544 acc0
|= (sop
& 1) ? 0x80000000 : 1;
5550 SET_DREG (dst0
, REG_H_L (out1
<< 16, out0
));
5552 else if (sop
== 0 && sopcde
== 10)
5554 bu32 v
= DREG (src0
);
5555 bu32 x
= DREG (src1
);
5556 bu32 mask
= (1 << (v
& 0x1f)) - 1;
5558 TRACE_INSN (cpu
, "R%i = EXTRACT (R%i, R%i.L) (Z);", dst0
, src1
, src0
);
5560 x
>>= ((v
>> 8) & 0x1f);
5562 STORE (DREG (dst0
), x
);
5563 setflags_logical (cpu
, x
);
5565 else if (sop
== 1 && sopcde
== 10)
5567 bu32 v
= DREG (src0
);
5568 bu32 x
= DREG (src1
);
5569 bu32 sgn
= (1 << (v
& 0x1f)) >> 1;
5570 bu32 mask
= (1 << (v
& 0x1f)) - 1;
5572 TRACE_INSN (cpu
, "R%i = EXTRACT (R%i, R%i.L) (X);", dst0
, src1
, src0
);
5574 x
>>= ((v
>> 8) & 0x1f);
5578 STORE (DREG (dst0
), x
);
5579 setflags_logical (cpu
, x
);
5581 else if ((sop
== 2 || sop
== 3) && sopcde
== 10)
5583 /* The first dregs is the "background" while the second dregs is the
5584 "foreground". The fg reg is used to overlay the bg reg and is:
5585 | nnnn nnnn | nnnn nnnn | xxxp pppp | xxxL LLLL |
5586 n = the fg bit field
5587 p = bit position in bg reg to start LSB of fg field
5588 L = number of fg bits to extract
5589 Using (X) sign-extends the fg bit field. */
5590 bu32 fg
= DREG (src0
);
5591 bu32 bg
= DREG (src1
);
5592 bu32 len
= fg
& 0x1f;
5593 bu32 mask
= (1 << MIN (16, len
)) - 1;
5594 bu32 fgnd
= (fg
>> 16) & mask
;
5595 int shft
= ((fg
>> 8) & 0x1f);
5597 TRACE_INSN (cpu
, "R%i = DEPOSIT (R%i, R%i)%s;", dst0
, src1
, src0
,
5598 sop
== 3 ? " (X)" : "");
5602 /* Sign extend the fg bit field. */
5604 fgnd
= ((bs32
)(bs16
)(fgnd
<< (16 - len
))) >> (16 - len
);
5611 STORE (DREG (dst0
), bg
);
5612 setflags_logical (cpu
, bg
);
5614 else if (sop
== 0 && sopcde
== 11)
5616 bu64 acc0
= get_unextended_acc (cpu
, 0);
5618 TRACE_INSN (cpu
, "R%i.L = CC = BXORSHIFT (A0, R%i);", dst0
, src0
);
5621 SET_CCREG (xor_reduce (acc0
, DREG (src0
)));
5622 SET_DREG (dst0
, REG_H_L (DREG (dst0
), CCREG
));
5625 else if (sop
== 1 && sopcde
== 11)
5627 bu64 acc0
= get_unextended_acc (cpu
, 0);
5629 TRACE_INSN (cpu
, "R%i.L = CC = BXOR (A0, R%i);", dst0
, src0
);
5631 SET_CCREG (xor_reduce (acc0
, DREG (src0
)));
5632 SET_DREG (dst0
, REG_H_L (DREG (dst0
), CCREG
));
5634 else if (sop
== 0 && sopcde
== 12)
5636 bu64 acc0
= get_unextended_acc (cpu
, 0);
5637 bu64 acc1
= get_unextended_acc (cpu
, 1);
5639 TRACE_INSN (cpu
, "A0 = BXORSHIFT (A0, A1, CC);");
5641 acc0
= (acc0
<< 1) | (CCREG
^ xor_reduce (acc0
, acc1
));
5644 else if (sop
== 1 && sopcde
== 12)
5646 bu64 acc0
= get_unextended_acc (cpu
, 0);
5647 bu64 acc1
= get_unextended_acc (cpu
, 1);
5649 TRACE_INSN (cpu
, "R%i.L = CC = BXOR (A0, A1, CC);", dst0
);
5651 SET_CCREG (CCREG
^ xor_reduce (acc0
, acc1
));
5652 acc0
= (acc0
<< 1) | CCREG
;
5653 SET_DREG (dst0
, REG_H_L (DREG (dst0
), CCREG
));
5655 else if ((sop
== 0 || sop
== 1 || sop
== 2) && sopcde
== 13)
5657 int shift
= (sop
+ 1) * 8;
5658 TRACE_INSN (cpu
, "R%i = ALIGN%i (R%i, R%i);", dst0
, shift
, src1
, src0
);
5659 STORE (DREG (dst0
), (DREG (src1
) << (32 - shift
)) | (DREG (src0
) >> shift
));
5662 illegal_instruction (cpu
);
5666 decode_dsp32shiftimm_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
5669 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5670 | 1 | 1 | 0 | 0 |.M.| 1 | 1 | 0 | 1 | - | - |.sopcde............|
5671 |.sop...|.HLs...|.dst0......|.immag.................|.src1......|
5672 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5673 int src1
= ((iw1
>> DSP32ShiftImm_src1_bits
) & DSP32ShiftImm_src1_mask
);
5674 int sop
= ((iw1
>> DSP32ShiftImm_sop_bits
) & DSP32ShiftImm_sop_mask
);
5675 int bit8
= ((iw1
>> 8) & 0x1);
5676 int immag
= ((iw1
>> DSP32ShiftImm_immag_bits
) & DSP32ShiftImm_immag_mask
);
5677 int newimmag
= (-(iw1
>> DSP32ShiftImm_immag_bits
) & DSP32ShiftImm_immag_mask
);
5678 int dst0
= ((iw1
>> DSP32ShiftImm_dst0_bits
) & DSP32ShiftImm_dst0_mask
);
5679 int M
= ((iw0
>> (DSP32ShiftImm_M_bits
- 16)) & DSP32ShiftImm_M_mask
);
5680 int sopcde
= ((iw0
>> (DSP32ShiftImm_sopcde_bits
- 16)) & DSP32ShiftImm_sopcde_mask
);
5681 int HLs
= ((iw1
>> DSP32ShiftImm_HLs_bits
) & DSP32ShiftImm_HLs_mask
);
5683 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32shiftimm
);
5684 TRACE_EXTRACT (cpu
, "%s: M:%i sopcde:%i sop:%i HLs:%i dst0:%i immag:%#x src1:%i",
5685 __func__
, M
, sopcde
, sop
, HLs
, dst0
, immag
, src1
);
5689 bu16 in
= DREG (src1
) >> ((HLs
& 1) ? 16 : 0);
5695 TRACE_INSN (cpu
, "R%i.%c = R%i.%c >>> %i;",
5696 dst0
, (HLs
& 2) ? 'H' : 'L',
5697 src1
, (HLs
& 1) ? 'H' : 'L', newimmag
);
5699 result
= lshift (cpu
, in
, 16 - (newimmag
& 0xF), 16, 0);
5701 result
= ashiftrt (cpu
, in
, newimmag
, 16);
5703 else if (sop
== 1 && bit8
== 0)
5705 TRACE_INSN (cpu
, "R%i.%c = R%i.%c << %i (S);",
5706 dst0
, (HLs
& 2) ? 'H' : 'L',
5707 src1
, (HLs
& 1) ? 'H' : 'L', immag
);
5708 result
= lshift (cpu
, in
, immag
, 16, 1);
5710 else if (sop
== 1 && bit8
)
5712 TRACE_INSN (cpu
, "R%i.%c = R%i.%c >>> %i (S);",
5713 dst0
, (HLs
& 2) ? 'H' : 'L',
5714 src1
, (HLs
& 1) ? 'H' : 'L', immag
);
5715 result
= lshift (cpu
, in
, immag
, 16, 1);
5717 else if (sop
== 2 && bit8
)
5719 TRACE_INSN (cpu
, "R%i.%c = R%i.%c >> %i;",
5720 dst0
, (HLs
& 2) ? 'H' : 'L',
5721 src1
, (HLs
& 1) ? 'H' : 'L', newimmag
);
5722 result
= lshiftrt (cpu
, in
, newimmag
, 16);
5724 else if (sop
== 2 && bit8
== 0)
5726 TRACE_INSN (cpu
, "R%i.%c = R%i.%c << %i;",
5727 dst0
, (HLs
& 2) ? 'H' : 'L',
5728 src1
, (HLs
& 1) ? 'H' : 'L', immag
);
5729 result
= lshift (cpu
, in
, immag
, 16, 0);
5732 illegal_instruction (cpu
);
5736 STORE (DREG (dst0
), (v
& 0xFFFF) | (result
<< 16));
5738 STORE (DREG (dst0
), (v
& 0xFFFF0000) | result
);
5740 else if (sop
== 2 && sopcde
== 3 && (HLs
== 1 || HLs
== 0))
5742 int shift
= imm6 (immag
);
5744 bu40 acc
= get_unextended_acc (cpu
, HLs
);
5746 TRACE_INSN (cpu
, "A%i = ROT A%i BY %i;", HLs
, HLs
, shift
);
5747 TRACE_DECODE (cpu
, "A%i:%#"PRIx64
" shift:%i CC:%i", HLs
, acc
, shift
, cc
);
5749 acc
= rot40 (acc
, shift
, &cc
);
5750 SET_AREG (HLs
, acc
);
5754 else if (sop
== 0 && sopcde
== 3 && bit8
== 1)
5756 /* Arithmetic shift, so shift in sign bit copies. */
5758 int shift
= uimm5 (newimmag
);
5761 TRACE_INSN (cpu
, "A%i = A%i >>> %i;", HLs
, HLs
, shift
);
5763 acc
= get_extended_acc (cpu
, HLs
);
5765 /* Sign extend again. */
5766 if (acc
& (1ULL << 39))
5767 acc
|= -(1ULL << 39);
5769 acc
&= ~(-(1ULL << 39));
5771 STORE (AXREG (HLs
), (acc
>> 32) & 0xFF);
5772 STORE (AWREG (HLs
), acc
& 0xFFFFFFFF);
5774 else if ((sop
== 0 && sopcde
== 3 && bit8
== 0)
5775 || (sop
== 1 && sopcde
== 3))
5778 int shiftup
= uimm5 (immag
);
5779 int shiftdn
= uimm5 (newimmag
);
5782 TRACE_INSN (cpu
, "A%i = A%i %s %i;", HLs
, HLs
,
5783 sop
== 0 ? "<<" : ">>",
5784 sop
== 0 ? shiftup
: shiftdn
);
5787 /* Logical shift, so shift in zeroes. */
5799 acc
<<= 32 - (shiftdn
& 0x1f);
5802 SET_AREG (HLs
, acc
);
5803 SET_ASTATREG (av
[HLs
], 0);
5804 SET_ASTATREG (an
, !!(acc
& 0x8000000000ull
));
5805 SET_ASTATREG (az
, (acc
& 0xFFFFFFFFFF) == 0);
5807 else if (sop
== 1 && sopcde
== 1 && bit8
== 0)
5809 int count
= imm5 (immag
);
5810 bu16 val0
= DREG (src1
) >> 16;
5811 bu16 val1
= DREG (src1
) & 0xFFFF;
5814 TRACE_INSN (cpu
, "R%i = R%i << %i (V,S);", dst0
, src1
, count
);
5817 val0
= lshift (cpu
, val0
, count
, 16, 1);
5819 val1
= lshift (cpu
, val1
, count
, 16, 1);
5823 val0
= ashiftrt (cpu
, val0
, -count
, 16);
5825 val1
= ashiftrt (cpu
, val1
, -count
, 16);
5827 SET_ASTAT (ASTAT
| astat
);
5829 STORE (DREG (dst0
), (val0
<< 16) | val1
);
5831 else if (sop
== 2 && sopcde
== 1 && bit8
== 1)
5833 int count
= imm5 (newimmag
);
5834 bu16 val0
= DREG (src1
) & 0xFFFF;
5835 bu16 val1
= DREG (src1
) >> 16;
5838 TRACE_INSN (cpu
, "R%i = R%i >> %i (V);", dst0
, src1
, count
);
5839 val0
= lshiftrt (cpu
, val0
, count
, 16);
5841 val1
= lshiftrt (cpu
, val1
, count
, 16);
5842 SET_ASTAT (ASTAT
| astat
);
5844 STORE (DREG (dst0
), val0
| (val1
<< 16));
5846 else if (sop
== 2 && sopcde
== 1 && bit8
== 0)
5848 int count
= imm5 (immag
);
5849 bu16 val0
= DREG (src1
) & 0xFFFF;
5850 bu16 val1
= DREG (src1
) >> 16;
5853 TRACE_INSN (cpu
, "R%i = R%i << %i (V);", dst0
, src1
, count
);
5854 val0
= lshift (cpu
, val0
, count
, 16, 0);
5856 val1
= lshift (cpu
, val1
, count
, 16, 0);
5857 SET_ASTAT (ASTAT
| astat
);
5859 STORE (DREG (dst0
), val0
| (val1
<< 16));
5861 else if (sopcde
== 1 && (sop
== 0 || (sop
== 1 && bit8
== 1)))
5863 int count
= uimm5 (newimmag
);
5864 bu16 val0
= DREG (src1
) & 0xFFFF;
5865 bu16 val1
= DREG (src1
) >> 16;
5868 TRACE_INSN (cpu
, "R%i = R%i >>> %i %s;", dst0
, src1
, count
,
5869 sop
== 0 ? "(V)" : "(V,S)");
5873 val0
= lshift (cpu
, val0
, 16 - (count
& 0xF), 16, 0);
5875 val1
= lshift (cpu
, val1
, 16 - (count
& 0xF), 16, 0);
5879 val0
= ashiftrt (cpu
, val0
, count
, 16);
5881 val1
= ashiftrt (cpu
, val1
, count
, 16);
5884 SET_ASTAT (ASTAT
| astat
);
5886 STORE (DREG (dst0
), REG_H_L (val1
<< 16, val0
));
5888 else if (sop
== 1 && sopcde
== 2)
5890 int count
= imm6 (immag
);
5892 TRACE_INSN (cpu
, "R%i = R%i << %i (S);", dst0
, src1
, count
);
5893 STORE (DREG (dst0
), lshift (cpu
, DREG (src1
), count
, 32, 1));
5895 else if (sop
== 2 && sopcde
== 2)
5897 int count
= imm6 (newimmag
);
5899 TRACE_INSN (cpu
, "R%i = R%i >> %i;", dst0
, src1
, count
);
5902 STORE (DREG (dst0
), lshift (cpu
, DREG (src1
), -count
, 32, 0));
5904 STORE (DREG (dst0
), lshiftrt (cpu
, DREG (src1
), count
, 32));
5906 else if (sop
== 3 && sopcde
== 2)
5908 int shift
= imm6 (immag
);
5909 bu32 src
= DREG (src1
);
5910 bu32 ret
, cc
= CCREG
;
5912 TRACE_INSN (cpu
, "R%i = ROT R%i BY %i;", dst0
, src1
, shift
);
5913 TRACE_DECODE (cpu
, "R%i:%#x R%i:%#x shift:%i CC:%i",
5914 dst0
, DREG (dst0
), src1
, src
, shift
, cc
);
5916 ret
= rot32 (src
, shift
, &cc
);
5917 STORE (DREG (dst0
), ret
);
5921 else if (sop
== 0 && sopcde
== 2)
5923 int count
= imm6 (newimmag
);
5925 TRACE_INSN (cpu
, "R%i = R%i >>> %i;", dst0
, src1
, count
);
5928 STORE (DREG (dst0
), lshift (cpu
, DREG (src1
), -count
, 32, 0));
5930 STORE (DREG (dst0
), ashiftrt (cpu
, DREG (src1
), count
, 32));
5933 illegal_instruction (cpu
);
5937 outc (SIM_CPU
*cpu
, char ch
)
5939 SIM_DESC sd
= CPU_STATE (cpu
);
5940 sim_io_printf (sd
, "%c", ch
);
5942 sim_io_flush_stdout (sd
);
5946 decode_psedoDEBUG_0 (SIM_CPU
*cpu
, bu16 iw0
)
5949 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5950 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 |.fn....|.grp.......|.reg.......|
5951 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5952 SIM_DESC sd
= CPU_STATE (cpu
);
5953 int fn
= ((iw0
>> PseudoDbg_fn_bits
) & PseudoDbg_fn_mask
);
5954 int grp
= ((iw0
>> PseudoDbg_grp_bits
) & PseudoDbg_grp_mask
);
5955 int reg
= ((iw0
>> PseudoDbg_reg_bits
) & PseudoDbg_reg_mask
);
5957 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_psedoDEBUG
);
5958 TRACE_EXTRACT (cpu
, "%s: fn:%i grp:%i reg:%i", __func__
, fn
, grp
, reg
);
5960 if ((reg
== 0 || reg
== 1) && fn
== 3)
5962 TRACE_INSN (cpu
, "DBG A%i;", reg
);
5963 sim_io_printf (sd
, "DBG : A%i = %#"PRIx64
"\n", reg
,
5964 get_unextended_acc (cpu
, reg
));
5966 else if (reg
== 3 && fn
== 3)
5968 TRACE_INSN (cpu
, "ABORT;");
5969 cec_exception (cpu
, VEC_SIM_ABORT
);
5972 else if (reg
== 4 && fn
== 3)
5974 TRACE_INSN (cpu
, "HLT;");
5975 cec_exception (cpu
, VEC_SIM_HLT
);
5978 else if (reg
== 5 && fn
== 3)
5979 unhandled_instruction (cpu
, "DBGHALT");
5980 else if (reg
== 6 && fn
== 3)
5981 unhandled_instruction (cpu
, "DBGCMPLX (dregs)");
5982 else if (reg
== 7 && fn
== 3)
5983 unhandled_instruction (cpu
, "DBG");
5984 else if (grp
== 0 && fn
== 2)
5986 TRACE_INSN (cpu
, "OUTC R%i;", reg
);
5987 outc (cpu
, DREG (reg
));
5991 const char *reg_name
= get_allreg_name (grp
, reg
);
5992 TRACE_INSN (cpu
, "DBG %s;", reg_name
);
5993 sim_io_printf (sd
, "DBG : %s = 0x%08x\n", reg_name
,
5994 reg_read (cpu
, grp
, reg
));
5997 unhandled_instruction (cpu
, "PRNT allregs");
5999 illegal_instruction (cpu
);
6003 decode_psedoOChar_0 (SIM_CPU
*cpu
, bu16 iw0
)
6006 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
6007 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |.ch............................|
6008 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
6009 int ch
= ((iw0
>> PseudoChr_ch_bits
) & PseudoChr_ch_mask
);
6011 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_psedoOChar
);
6012 TRACE_EXTRACT (cpu
, "%s: ch:%#x", __func__
, ch
);
6013 TRACE_INSN (cpu
, "OUTC %#x;", ch
);
6019 decode_psedodbg_assert_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
, bu32 pc
)
6022 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
6023 | 1 | 1 | 1 | 1 | 0 | - | - | - | dbgop |.grp.......|.regtest...|
6024 |.expected......................................................|
6025 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
6026 SIM_DESC sd
= CPU_STATE (cpu
);
6027 int expected
= ((iw1
>> PseudoDbg_Assert_expected_bits
) & PseudoDbg_Assert_expected_mask
);
6028 int dbgop
= ((iw0
>> (PseudoDbg_Assert_dbgop_bits
- 16)) & PseudoDbg_Assert_dbgop_mask
);
6029 int grp
= ((iw0
>> (PseudoDbg_Assert_grp_bits
- 16)) & PseudoDbg_Assert_grp_mask
);
6030 int regtest
= ((iw0
>> (PseudoDbg_Assert_regtest_bits
- 16)) & PseudoDbg_Assert_regtest_mask
);
6033 bu32 val
= reg_read (cpu
, grp
, regtest
);
6034 const char *reg_name
= get_allreg_name (grp
, regtest
);
6035 const char *dbg_name
, *dbg_appd
;
6037 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_psedodbg_assert
);
6038 TRACE_EXTRACT (cpu
, "%s: dbgop:%i grp:%i regtest:%i expected:%#x",
6039 __func__
, dbgop
, grp
, regtest
, expected
);
6041 if (dbgop
== 0 || dbgop
== 2)
6043 dbg_name
= dbgop
== 0 ? "DBGA" : "DBGAL";
6044 dbg_appd
= dbgop
== 0 ? ".L" : "";
6047 else if (dbgop
== 1 || dbgop
== 3)
6049 dbg_name
= dbgop
== 1 ? "DBGA" : "DBGAH";
6050 dbg_appd
= dbgop
== 1 ? ".H" : "";
6054 illegal_instruction (cpu
);
6056 actual
= val
>> offset
;
6058 TRACE_INSN (cpu
, "%s (%s%s, 0x%x);", dbg_name
, reg_name
, dbg_appd
, expected
);
6059 if (actual
!= expected
)
6061 sim_io_printf (sd
, "FAIL at %#x: %s (%s%s, 0x%04x); actual value %#x\n",
6062 pc
, dbg_name
, reg_name
, dbg_appd
, expected
, actual
);
6064 /* Decode the actual ASTAT bits that are different. */
6065 if (grp
== 4 && regtest
== 6)
6069 sim_io_printf (sd
, "Expected ASTAT:\n");
6070 for (i
= 0; i
< 16; ++i
)
6071 sim_io_printf (sd
, " %8s%c%i%s",
6072 astat_names
[i
+ offset
],
6073 (((expected
>> i
) & 1) != ((actual
>> i
) & 1))
6075 (expected
>> i
) & 1,
6076 i
== 7 ? "\n" : "");
6077 sim_io_printf (sd
, "\n");
6079 sim_io_printf (sd
, "Actual ASTAT:\n");
6080 for (i
= 0; i
< 16; ++i
)
6081 sim_io_printf (sd
, " %8s%c%i%s",
6082 astat_names
[i
+ offset
],
6083 (((expected
>> i
) & 1) != ((actual
>> i
) & 1))
6086 i
== 7 ? "\n" : "");
6087 sim_io_printf (sd
, "\n");
6090 cec_exception (cpu
, VEC_SIM_DBGA
);
6096 _interp_insn_bfin (SIM_CPU
*cpu
, bu32 pc
)
6101 BFIN_CPU_STATE
.multi_pc
= pc
;
6103 if ((iw0
& 0xc000) != 0xc000)
6105 /* 16-bit opcode. */
6108 INSN_LEN
= insn_len
;
6110 TRACE_EXTRACT (cpu
, "%s: iw0:%#x", __func__
, iw0
);
6111 if ((iw0
& 0xFF00) == 0x0000)
6112 decode_ProgCtrl_0 (cpu
, iw0
, pc
);
6113 else if ((iw0
& 0xFFC0) == 0x0240)
6114 decode_CaCTRL_0 (cpu
, iw0
);
6115 else if ((iw0
& 0xFF80) == 0x0100)
6116 decode_PushPopReg_0 (cpu
, iw0
);
6117 else if ((iw0
& 0xFE00) == 0x0400)
6118 decode_PushPopMultiple_0 (cpu
, iw0
);
6119 else if ((iw0
& 0xFE00) == 0x0600)
6120 decode_ccMV_0 (cpu
, iw0
);
6121 else if ((iw0
& 0xF800) == 0x0800)
6122 decode_CCflag_0 (cpu
, iw0
);
6123 else if ((iw0
& 0xFFE0) == 0x0200)
6124 decode_CC2dreg_0 (cpu
, iw0
);
6125 else if ((iw0
& 0xFF00) == 0x0300)
6126 decode_CC2stat_0 (cpu
, iw0
);
6127 else if ((iw0
& 0xF000) == 0x1000)
6128 decode_BRCC_0 (cpu
, iw0
, pc
);
6129 else if ((iw0
& 0xF000) == 0x2000)
6130 decode_UJUMP_0 (cpu
, iw0
, pc
);
6131 else if ((iw0
& 0xF000) == 0x3000)
6132 decode_REGMV_0 (cpu
, iw0
);
6133 else if ((iw0
& 0xFC00) == 0x4000)
6134 decode_ALU2op_0 (cpu
, iw0
);
6135 else if ((iw0
& 0xFE00) == 0x4400)
6136 decode_PTR2op_0 (cpu
, iw0
);
6137 else if ((iw0
& 0xF800) == 0x4800)
6138 decode_LOGI2op_0 (cpu
, iw0
);
6139 else if ((iw0
& 0xF000) == 0x5000)
6140 decode_COMP3op_0 (cpu
, iw0
);
6141 else if ((iw0
& 0xF800) == 0x6000)
6142 decode_COMPI2opD_0 (cpu
, iw0
);
6143 else if ((iw0
& 0xF800) == 0x6800)
6144 decode_COMPI2opP_0 (cpu
, iw0
);
6145 else if ((iw0
& 0xF000) == 0x8000)
6146 decode_LDSTpmod_0 (cpu
, iw0
);
6147 else if ((iw0
& 0xFF60) == 0x9E60)
6148 decode_dagMODim_0 (cpu
, iw0
);
6149 else if ((iw0
& 0xFFF0) == 0x9F60)
6150 decode_dagMODik_0 (cpu
, iw0
);
6151 else if ((iw0
& 0xFC00) == 0x9C00)
6152 decode_dspLDST_0 (cpu
, iw0
);
6153 else if ((iw0
& 0xF000) == 0x9000)
6154 decode_LDST_0 (cpu
, iw0
);
6155 else if ((iw0
& 0xFC00) == 0xB800)
6156 decode_LDSTiiFP_0 (cpu
, iw0
);
6157 else if ((iw0
& 0xE000) == 0xA000)
6158 decode_LDSTii_0 (cpu
, iw0
);
6161 TRACE_EXTRACT (cpu
, "%s: no matching 16-bit pattern", __func__
);
6162 illegal_instruction (cpu
);
6167 /* Grab the next 16 bits to determine if it's a 32-bit or 64-bit opcode. */
6168 iw1
= IFETCH (pc
+ 2);
6169 if ((iw0
& BIT_MULTI_INS
) && (iw0
& 0xe800) != 0xe800 /* not linkage */)
6171 SIM_DESC sd
= CPU_STATE (cpu
);
6172 trace_prefix (sd
, cpu
, NULL_CIA
, pc
, TRACE_LINENUM_P (cpu
),
6173 NULL
, 0, "|| %#"PRIx64
, sim_events_time (sd
));
6179 TRACE_EXTRACT (cpu
, "%s: iw0:%#x iw1:%#x insn_len:%i", __func__
,
6180 iw0
, iw1
, insn_len
);
6182 /* Only cache on first run through (in case of parallel insns). */
6184 INSN_LEN
= insn_len
;
6186 if ((iw0
& 0xf7ff) == 0xc003 && (iw1
& 0xfe00) == 0x1800)
6188 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32mac
);
6189 TRACE_INSN (cpu
, "MNOP;");
6191 else if (((iw0
& 0xFF80) == 0xE080) && ((iw1
& 0x0C00) == 0x0000))
6192 decode_LoopSetup_0 (cpu
, iw0
, iw1
, pc
);
6193 else if (((iw0
& 0xFF00) == 0xE100) && ((iw1
& 0x0000) == 0x0000))
6194 decode_LDIMMhalf_0 (cpu
, iw0
, iw1
);
6195 else if (((iw0
& 0xFE00) == 0xE200) && ((iw1
& 0x0000) == 0x0000))
6196 decode_CALLa_0 (cpu
, iw0
, iw1
, pc
);
6197 else if (((iw0
& 0xFC00) == 0xE400) && ((iw1
& 0x0000) == 0x0000))
6198 decode_LDSTidxI_0 (cpu
, iw0
, iw1
);
6199 else if (((iw0
& 0xFFFE) == 0xE800) && ((iw1
& 0x0000) == 0x0000))
6200 decode_linkage_0 (cpu
, iw0
, iw1
);
6201 else if (((iw0
& 0xF600) == 0xC000) && ((iw1
& 0x0000) == 0x0000))
6202 decode_dsp32mac_0 (cpu
, iw0
, iw1
);
6203 else if (((iw0
& 0xF600) == 0xC200) && ((iw1
& 0x0000) == 0x0000))
6204 decode_dsp32mult_0 (cpu
, iw0
, iw1
);
6205 else if (((iw0
& 0xF7C0) == 0xC400) && ((iw1
& 0x0000) == 0x0000))
6206 decode_dsp32alu_0 (cpu
, iw0
, iw1
);
6207 else if (((iw0
& 0xF7E0) == 0xC600) && ((iw1
& 0x01C0) == 0x0000))
6208 decode_dsp32shift_0 (cpu
, iw0
, iw1
);
6209 else if (((iw0
& 0xF7E0) == 0xC680) && ((iw1
& 0x0000) == 0x0000))
6210 decode_dsp32shiftimm_0 (cpu
, iw0
, iw1
);
6211 else if ((iw0
& 0xFF00) == 0xF800)
6212 decode_psedoDEBUG_0 (cpu
, iw0
), insn_len
= 2;
6213 else if ((iw0
& 0xFF00) == 0xF900)
6214 decode_psedoOChar_0 (cpu
, iw0
), insn_len
= 2;
6215 else if (((iw0
& 0xFF00) == 0xF000) && ((iw1
& 0x0000) == 0x0000))
6216 decode_psedodbg_assert_0 (cpu
, iw0
, iw1
, pc
);
6219 TRACE_EXTRACT (cpu
, "%s: no matching 32-bit pattern", __func__
);
6220 illegal_instruction (cpu
);
6227 interp_insn_bfin (SIM_CPU
*cpu
, bu32 pc
)
6232 BFIN_CPU_STATE
.n_stores
= 0;
6233 DIS_ALGN_EXPT
&= ~1;
6237 insn_len
= _interp_insn_bfin (cpu
, pc
);
6239 /* Proper display of multiple issue instructions. */
6242 _interp_insn_bfin (cpu
, pc
+ 4);
6243 _interp_insn_bfin (cpu
, pc
+ 6);
6245 for (i
= 0; i
< BFIN_CPU_STATE
.n_stores
; i
++)
6247 bu32
*addr
= BFIN_CPU_STATE
.stores
[i
].addr
;
6248 *addr
= BFIN_CPU_STATE
.stores
[i
].val
;
6249 TRACE_REGISTER (cpu
, "dequeuing write %s = %#x",
6250 get_store_name (cpu
, addr
), *addr
);
6253 cycles_inc (cpu
, CYCLE_DELAY
);
6255 /* Set back to zero in case a pending CEC event occurs
6256 after this this insn. */