1 /* Simulator for Analog Devices Blackfin processors.
3 Copyright (C) 2005-2012 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
)
226 sprintf (buf
, "%*i", constant_formats
[cf
].leading
, x
);
229 if (constant_formats
[cf
].issigned
&& x
< 0)
230 sprintf (buf
, "-0x%x", abs (x
));
232 sprintf (buf
, "0x%x", x
);
239 fmtconst_val (const_forms_t cf
, bu32 x
, bu32 pc
)
241 if (0 && constant_formats
[cf
].reloc
)
243 bu32 ea
= (((constant_formats
[cf
].pcrel
244 ? (bu32
)SIGNEXTEND (x
, constant_formats
[cf
].nbits
)
245 : x
) + constant_formats
[cf
].offset
)
246 << constant_formats
[cf
].scale
);
247 if (constant_formats
[cf
].pcrel
)
253 /* Negative constants have an implied sign bit. */
254 if (constant_formats
[cf
].negative
)
256 int nb
= constant_formats
[cf
].nbits
+ 1;
257 x
= x
| (1 << constant_formats
[cf
].nbits
);
258 x
= SIGNEXTEND (x
, nb
);
260 else if (constant_formats
[cf
].issigned
)
261 x
= SIGNEXTEND (x
, constant_formats
[cf
].nbits
);
263 x
+= constant_formats
[cf
].offset
;
264 x
<<= constant_formats
[cf
].scale
;
269 #define uimm16s4(x) fmtconst_val (c_uimm16s4, x, 0)
270 #define uimm16s4_str(x) fmtconst_str (c_uimm16s4, x, 0)
271 #define uimm16s4d(x) fmtconst_val (c_uimm16s4d, x, 0)
272 #define pcrel4(x) fmtconst_val (c_pcrel4, x, pc)
273 #define pcrel8(x) fmtconst_val (c_pcrel8, x, pc)
274 #define pcrel8s4(x) fmtconst_val (c_pcrel8s4, x, pc)
275 #define pcrel10(x) fmtconst_val (c_pcrel10, x, pc)
276 #define pcrel12(x) fmtconst_val (c_pcrel12, x, pc)
277 #define negimm5s4(x) fmtconst_val (c_negimm5s4, x, 0)
278 #define negimm5s4_str(x) fmtconst_str (c_negimm5s4, x, 0)
279 #define rimm16(x) fmtconst_val (c_rimm16, x, 0)
280 #define huimm16(x) fmtconst_val (c_huimm16, x, 0)
281 #define imm16(x) fmtconst_val (c_imm16, x, 0)
282 #define imm16_str(x) fmtconst_str (c_imm16, x, 0)
283 #define imm16d(x) fmtconst_val (c_imm16d, x, 0)
284 #define uimm2(x) fmtconst_val (c_uimm2, x, 0)
285 #define uimm3(x) fmtconst_val (c_uimm3, x, 0)
286 #define uimm3_str(x) fmtconst_str (c_uimm3, x, 0)
287 #define luimm16(x) fmtconst_val (c_luimm16, x, 0)
288 #define luimm16_str(x) fmtconst_str (c_luimm16, x, 0)
289 #define uimm4(x) fmtconst_val (c_uimm4, x, 0)
290 #define uimm4_str(x) fmtconst_str (c_uimm4, x, 0)
291 #define uimm5(x) fmtconst_val (c_uimm5, x, 0)
292 #define uimm5_str(x) fmtconst_str (c_uimm5, x, 0)
293 #define imm16s2(x) fmtconst_val (c_imm16s2, x, 0)
294 #define imm16s2_str(x) fmtconst_str (c_imm16s2, x, 0)
295 #define uimm8(x) fmtconst_val (c_uimm8, x, 0)
296 #define imm16s4(x) fmtconst_val (c_imm16s4, x, 0)
297 #define imm16s4_str(x) fmtconst_str (c_imm16s4, x, 0)
298 #define uimm4s2(x) fmtconst_val (c_uimm4s2, x, 0)
299 #define uimm4s2_str(x) fmtconst_str (c_uimm4s2, x, 0)
300 #define uimm4s4(x) fmtconst_val (c_uimm4s4, x, 0)
301 #define uimm4s4_str(x) fmtconst_str (c_uimm4s4, x, 0)
302 #define uimm4s4d(x) fmtconst_val (c_uimm4s4d, x, 0)
303 #define lppcrel10(x) fmtconst_val (c_lppcrel10, x, pc)
304 #define imm3(x) fmtconst_val (c_imm3, x, 0)
305 #define imm3_str(x) fmtconst_str (c_imm3, x, 0)
306 #define imm4(x) fmtconst_val (c_imm4, x, 0)
307 #define uimm8s4(x) fmtconst_val (c_uimm8s4, x, 0)
308 #define imm5(x) fmtconst_val (c_imm5, x, 0)
309 #define imm5d(x) fmtconst_val (c_imm5d, x, 0)
310 #define imm6(x) fmtconst_val (c_imm6, x, 0)
311 #define imm7(x) fmtconst_val (c_imm7, x, 0)
312 #define imm7_str(x) fmtconst_str (c_imm7, x, 0)
313 #define imm7d(x) fmtconst_val (c_imm7d, x, 0)
314 #define imm8(x) fmtconst_val (c_imm8, x, 0)
315 #define pcrel24(x) fmtconst_val (c_pcrel24, x, pc)
316 #define pcrel24_str(x) fmtconst_str (c_pcrel24, x, pc)
317 #define uimm16(x) fmtconst_val (c_uimm16, x, 0)
318 #define uimm32(x) fmtconst_val (c_uimm32, x, 0)
319 #define imm32(x) fmtconst_val (c_imm32, x, 0)
320 #define huimm32(x) fmtconst_val (c_huimm32, x, 0)
321 #define huimm32e(x) fmtconst_val (c_huimm32e, x, 0)
323 /* Table C-4. Core Register Encoding Map. */
324 const char * const greg_names
[] =
326 "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7",
327 "P0", "P1", "P2", "P3", "P4", "P5", "SP", "FP",
328 "I0", "I1", "I2", "I3", "M0", "M1", "M2", "M3",
329 "B0", "B1", "B2", "B3", "L0", "L1", "L2", "L3",
330 "A0.X", "A0.W", "A1.X", "A1.W", "<res>", "<res>", "ASTAT", "RETS",
331 "<res>", "<res>", "<res>", "<res>", "<res>", "<res>", "<res>", "<res>",
332 "LC0", "LT0", "LB0", "LC1", "LT1", "LB1", "CYCLES", "CYCLES2",
333 "USP", "SEQSTAT", "SYSCFG", "RETI", "RETX", "RETN", "RETE", "EMUDAT",
336 get_allreg_name (int grp
, int reg
)
338 return greg_names
[(grp
<< 3) | reg
];
341 get_preg_name (int reg
)
343 return get_allreg_name (1, reg
);
347 reg_is_reserved (int grp
, int reg
)
349 return (grp
== 4 && (reg
== 4 || reg
== 5)) || (grp
== 5);
353 get_allreg (SIM_CPU
*cpu
, int grp
, int reg
)
355 int fullreg
= (grp
<< 3) | reg
;
356 /* REG_R0, REG_R1, REG_R2, REG_R3, REG_R4, REG_R5, REG_R6, REG_R7,
357 REG_P0, REG_P1, REG_P2, REG_P3, REG_P4, REG_P5, REG_SP, REG_FP,
358 REG_I0, REG_I1, REG_I2, REG_I3, REG_M0, REG_M1, REG_M2, REG_M3,
359 REG_B0, REG_B1, REG_B2, REG_B3, REG_L0, REG_L1, REG_L2, REG_L3,
360 REG_A0x, REG_A0w, REG_A1x, REG_A1w, , , REG_ASTAT, REG_RETS,
362 REG_LC0, REG_LT0, REG_LB0, REG_LC1, REG_LT1, REG_LB1, REG_CYCLES,
364 REG_USP, REG_SEQSTAT, REG_SYSCFG, REG_RETI, REG_RETX, REG_RETN, REG_RETE,
366 switch (fullreg
>> 2)
368 case 0: case 1: return &DREG (reg
);
369 case 2: case 3: return &PREG (reg
);
370 case 4: return &IREG (reg
& 3);
371 case 5: return &MREG (reg
& 3);
372 case 6: return &BREG (reg
& 3);
373 case 7: return &LREG (reg
& 3);
377 case 32: return &AXREG (0);
378 case 33: return &AWREG (0);
379 case 34: return &AXREG (1);
380 case 35: return &AWREG (1);
381 case 39: return &RETSREG
;
382 case 48: return &LCREG (0);
383 case 49: return <REG (0);
384 case 50: return &LBREG (0);
385 case 51: return &LCREG (1);
386 case 52: return <REG (1);
387 case 53: return &LBREG (1);
388 case 54: return &CYCLESREG
;
389 case 55: return &CYCLES2REG
;
390 case 56: return &USPREG
;
391 case 57: return &SEQSTATREG
;
392 case 58: return &SYSCFGREG
;
393 case 59: return &RETIREG
;
394 case 60: return &RETXREG
;
395 case 61: return &RETNREG
;
396 case 62: return &RETEREG
;
397 case 63: return &EMUDAT_INREG
;
399 illegal_instruction (cpu
);
404 amod0 (int s0
, int x0
)
406 static const char * const mod0
[] = {
407 "", " (S)", " (CO)", " (SCO)",
409 int i
= s0
+ (x0
<< 1);
411 if (i
< ARRAY_SIZE (mod0
))
418 amod0amod2 (int s0
, int x0
, int aop0
)
420 static const char * const mod02
[] = {
421 "", " (S)", " (CO)", " (SCO)",
423 " (ASR)", " (S, ASR)", " (CO, ASR)", " (SCO, ASR)",
424 " (ASL)", " (S, ASL)", " (CO, ASL)", " (SCO, ASL)",
426 int i
= s0
+ (x0
<< 1) + (aop0
<< 2);
428 if (i
< ARRAY_SIZE (mod02
))
435 amod1 (int s0
, int x0
)
437 static const char * const mod1
[] = {
440 int i
= s0
+ (x0
<< 1);
442 if (i
< ARRAY_SIZE (mod1
))
449 mac_optmode (int mmod
, int MM
)
451 static const char * const omode
[] = {
452 [(M_S2RND
<< 1) + 0] = " (S2RND)",
453 [(M_T
<< 1) + 0] = " (T)",
454 [(M_W32
<< 1) + 0] = " (W32)",
455 [(M_FU
<< 1) + 0] = " (FU)",
456 [(M_TFU
<< 1) + 0] = " (TFU)",
457 [(M_IS
<< 1) + 0] = " (IS)",
458 [(M_ISS2
<< 1) + 0] = " (ISS2)",
459 [(M_IH
<< 1) + 0] = " (IH)",
460 [(M_IU
<< 1) + 0] = " (IU)",
461 [(M_S2RND
<< 1) + 1] = " (M, S2RND)",
462 [(M_T
<< 1) + 1] = " (M, T)",
463 [(M_W32
<< 1) + 1] = " (M, W32)",
464 [(M_FU
<< 1) + 1] = " (M, FU)",
465 [(M_TFU
<< 1) + 1] = " (M, TFU)",
466 [(M_IS
<< 1) + 1] = " (M, IS)",
467 [(M_ISS2
<< 1) + 1] = " (M, ISS2)",
468 [(M_IH
<< 1) + 1] = " (M, IH)",
469 [(M_IU
<< 1) + 1] = " (M, IU)",
471 int i
= MM
+ (mmod
<< 1);
473 if (i
< ARRAY_SIZE (omode
) && omode
[i
])
480 get_store_name (SIM_CPU
*cpu
, bu32
*p
)
482 if (p
>= &DREG (0) && p
<= &CYCLESREG
)
483 return greg_names
[p
- &DREG (0)];
484 else if (p
== &AXREG (0))
485 return greg_names
[4 * 8 + 0];
486 else if (p
== &AWREG (0))
487 return greg_names
[4 * 8 + 1];
488 else if (p
== &AXREG (1))
489 return greg_names
[4 * 8 + 2];
490 else if (p
== &AWREG (1))
491 return greg_names
[4 * 8 + 3];
492 else if (p
== &ASTATREG (av0
))
494 else if (p
== &ASTATREG (av0s
))
495 return "ASTAT[av0s]";
496 else if (p
== &ASTATREG (av1
))
498 else if (p
== &ASTATREG (av1s
))
499 return "ASTAT[av1s]";
500 else if (p
== &ASTATREG (v
))
502 else if (p
== &ASTATREG (vs
))
504 else if (p
== &ASTATREG (v_copy
))
505 return "ASTAT[v_copy]";
506 else if (p
== &ASTATREG (az
))
508 else if (p
== &ASTATREG (an
))
510 else if (p
== &ASTATREG (az
))
512 else if (p
== &ASTATREG (ac0
))
514 else if (p
== &ASTATREG (ac0_copy
))
515 return "ASTAT[ac0_copy]";
518 /* Worry about this when we start to STORE() it. */
519 sim_io_eprintf (CPU_STATE (cpu
), "STORE(): unknown register\n");
525 queue_store (SIM_CPU
*cpu
, bu32
*addr
, bu32 val
)
527 struct store
*s
= &BFIN_CPU_STATE
.stores
[BFIN_CPU_STATE
.n_stores
];
530 TRACE_REGISTER (cpu
, "queuing write %s = %#x",
531 get_store_name (cpu
, addr
), val
);
532 ++BFIN_CPU_STATE
.n_stores
;
534 #define STORE(X, Y) \
536 if (BFIN_CPU_STATE.n_stores == 20) abort (); \
537 queue_store (cpu, &(X), (Y)); \
541 setflags_nz (SIM_CPU
*cpu
, bu32 val
)
543 SET_ASTATREG (az
, val
== 0);
544 SET_ASTATREG (an
, val
>> 31);
548 setflags_nz_2x16 (SIM_CPU
*cpu
, bu32 val
)
550 SET_ASTATREG (an
, (bs16
)val
< 0 || (bs16
)(val
>> 16) < 0);
551 SET_ASTATREG (az
, (bs16
)val
== 0 || (bs16
)(val
>> 16) == 0);
555 setflags_logical (SIM_CPU
*cpu
, bu32 val
)
557 setflags_nz (cpu
, val
);
558 SET_ASTATREG (ac0
, 0);
563 add_brev (bu32 addend1
, bu32 addend2
)
572 for (i
= 31; i
>= 0; --i
)
574 b
= ((addend1
& mask
) >> i
) + ((addend2
& mask
) >> i
);
585 /* This is a bit crazy, but we want to simulate the hardware behavior exactly
586 rather than worry about the circular buffers being used correctly. Which
587 isn't to say there isn't room for improvement here, just that we want to
588 be conservative. See also dagsub(). */
590 dagadd (SIM_CPU
*cpu
, int dagno
, bs32 M
)
592 bu64 i
= IREG (dagno
);
593 bu64 l
= LREG (dagno
);
594 bu64 b
= BREG (dagno
);
598 bu32 im32
, iml32
, lb32
, res
;
601 /* A naïve implementation that mostly works:
603 if (l && res >= b + l)
605 STORE (IREG (dagno), res);
620 if ((i
& msb
) || (IM
& car
))
621 res
= (im32
< b
) ? iml32
: im32
;
623 res
= (im32
< b
) ? im32
: iml32
;
629 if ((IM
& car
) == (LB
& car
))
630 res
= (im32
< lb32
) ? im32
: iml32
;
632 res
= (im32
< lb32
) ? iml32
: im32
;
635 STORE (IREG (dagno
), res
);
639 /* See dagadd() notes above. */
641 dagsub (SIM_CPU
*cpu
, int dagno
, bs32 M
)
643 bu64 i
= IREG (dagno
);
644 bu64 l
= LREG (dagno
);
645 bu64 b
= BREG (dagno
);
648 bu64 mbar
= (bu32
)(~m
+ 1);
650 bu32 b32
, im32
, iml32
, lb32
, res
;
653 /* A naïve implementation that mostly works:
657 STORE (IREG (dagno), newi);
672 if (!!((i
& msb
) && (IM
& car
)) == !!(LB
& car
))
673 res
= (im32
< lb32
) ? im32
: iml32
;
675 res
= (im32
< lb32
) ? iml32
: im32
;
682 if (M
== 0 || IM
& car
)
683 res
= (im32
< b32
) ? iml32
: im32
;
685 res
= (im32
< b32
) ? im32
: iml32
;
688 STORE (IREG (dagno
), res
);
693 ashiftrt (SIM_CPU
*cpu
, bu40 val
, int cnt
, int size
)
695 int real_cnt
= cnt
> size
? size
: cnt
;
696 bu40 sgn
= ~(((val
& 0xFFFFFFFFFFull
) >> (size
- 1)) - 1);
697 int sgncnt
= size
- real_cnt
;
699 sgn
<<= 16, sgncnt
-= 16;
702 val
>>= 16, real_cnt
-= 16;
705 SET_ASTATREG (an
, val
>> (size
- 1));
706 SET_ASTATREG (az
, val
== 0);
713 lshiftrt (SIM_CPU
*cpu
, bu64 val
, int cnt
, int size
)
715 int real_cnt
= cnt
> size
? size
: cnt
;
717 val
>>= 16, real_cnt
-= 16;
728 val
&= 0xFFFFFFFFFFull
;
731 illegal_instruction (cpu
);
734 SET_ASTATREG (an
, val
>> (size
- 1));
735 SET_ASTATREG (az
, val
== 0);
742 lshift (SIM_CPU
*cpu
, bu64 val
, int cnt
, int size
, bool saturate
, bool overflow
)
744 int v_i
, real_cnt
= cnt
> size
? size
: cnt
;
745 bu64 sgn
= ~((val
>> (size
- 1)) - 1);
746 int mask_cnt
= size
- 1;
747 bu64 masked
, new_val
= val
;
755 new_val
<<= 16, real_cnt
-= 16;
757 new_val
<<= real_cnt
;
759 masked
= new_val
& mask
;
761 /* If an operation would otherwise cause a positive value to overflow
762 and become negative, instead, saturation limits the result to the
763 maximum positive value for the size register being used.
765 Conversely, if an operation would otherwise cause a negative value
766 to overflow and become positive, saturation limits the result to the
767 maximum negative value for the register size.
769 However, it's a little more complex than looking at sign bits, we need
770 to see if we are shifting the sign information away... */
771 if (((val
<< cnt
) >> size
) == 0
772 || (((val
<< cnt
) >> size
) == ~(~0 << cnt
)
773 && ((new_val
>> (size
- 1)) & 0x1)))
782 if (saturate
&& (v_i
|| ((val
>> (size
- 1)) != (new_val
>> (size
- 1)))))
784 new_val
= (val
>> (size
- 1)) == 0 ? 0x7fff : 0x8000;
789 new_val
&= 0xFFFFFFFF;
790 masked
&= 0xFFFFFFFF;
795 || (!sgn
&& new_val
== 0 && val
!= 0)))
797 new_val
= sgn
== 0 ? 0x7fffffff : 0x80000000;
802 new_val
&= 0xFFFFFFFFFFull
;
803 masked
&= 0xFFFFFFFFFFull
;
806 illegal_instruction (cpu
);
810 SET_ASTATREG (an
, new_val
>> (size
- 1));
811 SET_ASTATREG (az
, new_val
== 0);
814 SET_ASTATREG (v
, overflow
&& v_i
);
816 SET_ASTATREG (vs
, 1);
823 algn (bu32 l
, bu32 h
, bu32 aln
)
828 return (l
>> (8 * aln
)) | (h
<< (32 - 8 * aln
));
832 saturate_s16 (bu64 val
, bu32
*overflow
)
834 if ((bs64
)val
< -0x8000ll
)
840 if ((bs64
)val
> 0x7fff)
850 rot40 (bu40 val
, int shift
, bu32
*cc
)
852 const int nbits
= 40;
855 shift
= CLAMP (shift
, -nbits
, nbits
);
859 /* Reduce everything to rotate left. */
863 ret
= shift
== nbits
? 0 : val
<< shift
;
864 ret
|= shift
== 1 ? 0 : val
>> ((nbits
+ 1) - shift
);
865 ret
|= (bu40
)*cc
<< (shift
- 1);
866 *cc
= (val
>> (nbits
- shift
)) & 1;
872 rot32 (bu32 val
, int shift
, bu32
*cc
)
874 const int nbits
= 32;
877 shift
= CLAMP (shift
, -nbits
, nbits
);
881 /* Reduce everything to rotate left. */
885 ret
= shift
== nbits
? 0 : val
<< shift
;
886 ret
|= shift
== 1 ? 0 : val
>> ((nbits
+ 1) - shift
);
887 ret
|= (bu32
)*cc
<< (shift
- 1);
888 *cc
= (val
>> (nbits
- shift
)) & 1;
894 add32 (SIM_CPU
*cpu
, bu32 a
, bu32 b
, int carry
, int sat
)
896 int flgs
= (a
>> 31) & 1;
897 int flgo
= (b
>> 31) & 1;
899 int flgn
= (v
>> 31) & 1;
900 int overflow
= (flgs
^ flgn
) & (flgo
^ flgn
);
907 flgn
= (v
>> 31) & 1;
910 SET_ASTATREG (an
, flgn
);
912 SET_ASTATREG (vs
, 1);
913 SET_ASTATREG (v
, overflow
);
914 ASTATREG (v_internal
) |= overflow
;
915 SET_ASTATREG (az
, v
== 0);
917 SET_ASTATREG (ac0
, ~a
< b
);
923 sub32 (SIM_CPU
*cpu
, bu32 a
, bu32 b
, int carry
, int sat
, int parallel
)
925 int flgs
= (a
>> 31) & 1;
926 int flgo
= (b
>> 31) & 1;
928 int flgn
= (v
>> 31) & 1;
929 int overflow
= (flgs
^ flgo
) & (flgn
^ flgs
);
936 flgn
= (v
>> 31) & 1;
939 if (!parallel
|| flgn
)
940 SET_ASTATREG (an
, flgn
);
942 SET_ASTATREG (vs
, 1);
943 if (!parallel
|| overflow
)
944 SET_ASTATREG (v
, overflow
);
945 if (!parallel
|| overflow
)
946 ASTATREG (v_internal
) |= overflow
;
947 if (!parallel
|| v
== 0)
948 SET_ASTATREG (az
, v
== 0);
949 if (carry
&& (!parallel
|| b
<= a
))
950 SET_ASTATREG (ac0
, b
<= a
);
956 add16 (SIM_CPU
*cpu
, bu16 a
, bu16 b
, bu32
*carry
, bu32
*overfl
,
957 bu32
*zero
, bu32
*neg
, int sat
, int scale
)
959 int flgs
= (a
>> 15) & 1;
960 int flgo
= (b
>> 15) & 1;
961 bs64 v
= (bs16
)a
+ (bs16
)b
;
962 int flgn
= (v
>> 15) & 1;
963 int overflow
= (flgs
^ flgn
) & (flgo
^ flgn
);
971 v
= (a
>> 1) + (a
& 0x8000) + (b
>> 1) + (b
& 0x8000)
972 + (((a
& 1) + (b
& 1)) >> 1);
980 illegal_instruction (cpu
);
983 flgn
= (v
>> 15) & 1;
984 overflow
= (flgs
^ flgn
) & (flgo
^ flgn
);
986 if (v
> (bs64
)0xffff)
990 v
= saturate_s16 (v
, 0);
993 *neg
|= (v
>> 15) & 1;
997 *zero
|= (v
& 0xFFFF) == 0;
999 *carry
|= ((bu16
)~a
< (bu16
)b
);
1005 sub16 (SIM_CPU
*cpu
, bu16 a
, bu16 b
, bu32
*carry
, bu32
*overfl
,
1006 bu32
*zero
, bu32
*neg
, int sat
, int scale
)
1008 int flgs
= (a
>> 15) & 1;
1009 int flgo
= (b
>> 15) & 1;
1010 bs64 v
= (bs16
)a
- (bs16
)b
;
1011 int flgn
= (v
>> 15) & 1;
1012 int overflow
= (flgs
^ flgo
) & (flgn
^ flgs
);
1021 v
= ((a
>> 1) + (a
& 0x8000)) - ( (b
>> 1) + (b
& 0x8000))
1022 + (((a
& 1)-(b
& 1)));
1025 v
= ((v
& 0xFFFF) >> 1);
1026 if ((!flgs
& !flgo
& flgn
)
1027 || (flgs
& !flgo
& !flgn
)
1028 || (flgs
& flgo
& flgn
)
1029 || (flgs
& !flgo
& flgn
))
1033 flgn
= (v
>> 15) & 1;
1034 overflow
= (flgs
^ flgo
) & (flgn
^ flgs
);
1039 if (v
> (bs64
)0x7fff || v
< (bs64
)-0xffff)
1043 illegal_instruction (cpu
);
1048 v
= saturate_s16 (v
, 0);
1051 *neg
|= (v
>> 15) & 1;
1053 *zero
|= (v
& 0xFFFF) == 0;
1055 *overfl
|= overflow
;
1057 *carry
|= (bu16
)b
<= (bu16
)a
;
1062 min32 (SIM_CPU
*cpu
, bu32 a
, bu32 b
)
1065 if ((bs32
)a
> (bs32
)b
)
1067 setflags_nz (cpu
, val
);
1068 SET_ASTATREG (v
, 0);
1073 max32 (SIM_CPU
*cpu
, bu32 a
, bu32 b
)
1076 if ((bs32
)a
< (bs32
)b
)
1078 setflags_nz (cpu
, val
);
1079 SET_ASTATREG (v
, 0);
1084 min2x16 (SIM_CPU
*cpu
, bu32 a
, bu32 b
)
1087 if ((bs16
)a
> (bs16
)b
)
1088 val
= (val
& 0xFFFF0000) | (b
& 0xFFFF);
1089 if ((bs16
)(a
>> 16) > (bs16
)(b
>> 16))
1090 val
= (val
& 0xFFFF) | (b
& 0xFFFF0000);
1091 setflags_nz_2x16 (cpu
, val
);
1092 SET_ASTATREG (v
, 0);
1097 max2x16 (SIM_CPU
*cpu
, bu32 a
, bu32 b
)
1100 if ((bs16
)a
< (bs16
)b
)
1101 val
= (val
& 0xFFFF0000) | (b
& 0xFFFF);
1102 if ((bs16
)(a
>> 16) < (bs16
)(b
>> 16))
1103 val
= (val
& 0xFFFF) | (b
& 0xFFFF0000);
1104 setflags_nz_2x16 (cpu
, val
);
1105 SET_ASTATREG (v
, 0);
1110 add_and_shift (SIM_CPU
*cpu
, bu32 a
, bu32 b
, int shift
)
1113 ASTATREG (v_internal
) = 0;
1114 v
= add32 (cpu
, a
, b
, 0, 0);
1117 int x
= (v
>> 30) & 0x3;
1118 if (x
== 1 || x
== 2)
1119 ASTATREG (v_internal
) = 1;
1122 SET_ASTATREG (az
, v
== 0);
1123 SET_ASTATREG (an
, v
& 0x80000000);
1124 SET_ASTATREG (v
, ASTATREG (v_internal
));
1126 SET_ASTATREG (vs
, 1);
1131 xor_reduce (bu64 acc0
, bu64 acc1
)
1135 for (i
= 0; i
< 40; ++i
)
1137 v
^= (acc0
& acc1
& 1);
1144 /* DIVS ( Dreg, Dreg ) ;
1145 Initialize for DIVQ. Set the AQ status bit based on the signs of
1146 the 32-bit dividend and the 16-bit divisor. Left shift the dividend
1147 one bit. Copy AQ into the dividend LSB. */
1149 divs (SIM_CPU
*cpu
, bu32 pquo
, bu16 divisor
)
1151 bu16 r
= pquo
>> 16;
1154 aq
= (r
^ divisor
) >> 15; /* Extract msb's and compute quotient bit. */
1155 SET_ASTATREG (aq
, aq
); /* Update global quotient state. */
1159 pquo
= (pquo
& 0x1FFFF) | (r
<< 17);
1163 /* DIVQ ( Dreg, Dreg ) ;
1164 Based on AQ status bit, either add or subtract the divisor from
1165 the dividend. Then set the AQ status bit based on the MSBs of the
1166 32-bit dividend and the 16-bit divisor. Left shift the dividend one
1167 bit. Copy the logical inverse of AQ into the dividend LSB. */
1169 divq (SIM_CPU
*cpu
, bu32 pquo
, bu16 divisor
)
1171 unsigned short af
= pquo
>> 16;
1180 aq
= (r
^ divisor
) >> 15; /* Extract msb's and compute quotient bit. */
1181 SET_ASTATREG (aq
, aq
); /* Update global quotient state. */
1185 pquo
= (pquo
& 0x1FFFF) | (r
<< 17);
1190 Count the number of bits set to 1 in the 32bit value. */
1198 for (i
= 0; i
< 32; ++i
)
1199 ret
+= !!(val
& (1 << i
));
1205 reg_check_sup (SIM_CPU
*cpu
, int grp
, int reg
)
1208 cec_require_supervisor (cpu
);
1212 reg_write (SIM_CPU
*cpu
, int grp
, int reg
, bu32 value
)
1216 /* ASTAT is special! */
1217 if (grp
== 4 && reg
== 6)
1223 /* Check supervisor after get_allreg() so exception order is correct. */
1224 whichreg
= get_allreg (cpu
, grp
, reg
);
1225 reg_check_sup (cpu
, grp
, reg
);
1227 if (whichreg
== &CYCLES2REG
)
1228 /* Writes to CYCLES2 goes to the shadow. */
1229 whichreg
= &CYCLES2SHDREG
;
1230 else if (whichreg
== &SEQSTATREG
)
1231 /* Register is read only -- discard writes. */
1233 else if (whichreg
== &EMUDAT_INREG
)
1234 /* Writes to EMUDAT goes to the output. */
1235 whichreg
= &EMUDAT_OUTREG
;
1236 else if (whichreg
== <REG (0) || whichreg
== <REG (1))
1237 /* Writes to LT clears LSB automatically. */
1239 else if (whichreg
== &AXREG (0) || whichreg
== &AXREG (1))
1242 TRACE_REGISTER (cpu
, "wrote %s = %#x", get_allreg_name (grp
, reg
), value
);
1248 reg_read (SIM_CPU
*cpu
, int grp
, int reg
)
1253 /* ASTAT is special! */
1254 if (grp
== 4 && reg
== 6)
1257 /* Check supervisor after get_allreg() so exception order is correct. */
1258 whichreg
= get_allreg (cpu
, grp
, reg
);
1259 reg_check_sup (cpu
, grp
, reg
);
1263 if (whichreg
== &CYCLESREG
)
1264 /* Reads of CYCLES reloads CYCLES2 from the shadow. */
1265 SET_CYCLES2REG (CYCLES2SHDREG
);
1266 else if ((whichreg
== &AXREG (1) || whichreg
== &AXREG (0)) && (value
& 0x80))
1267 /* Sign extend if necessary. */
1268 value
|= 0xFFFFFF00;
1274 get_extended_cycles (SIM_CPU
*cpu
)
1276 return ((bu64
)CYCLES2SHDREG
<< 32) | CYCLESREG
;
1279 /* We can't re-use sim_events_time() because the CYCLES registers may be
1280 written/cleared/reset/stopped/started at any time by software. */
1282 cycles_inc (SIM_CPU
*cpu
, bu32 inc
)
1287 if (!(SYSCFGREG
& SYSCFG_CCEN
))
1290 cycles
= get_extended_cycles (cpu
) + inc
;
1291 SET_CYCLESREG (cycles
);
1292 cycles2
= cycles
>> 32;
1293 if (CYCLES2SHDREG
!= cycles2
)
1294 SET_CYCLES2SHDREG (cycles2
);
1298 get_unextended_acc (SIM_CPU
*cpu
, int which
)
1300 return ((bu64
)(AXREG (which
) & 0xff) << 32) | AWREG (which
);
1304 get_extended_acc (SIM_CPU
*cpu
, int which
)
1306 bu64 acc
= AXREG (which
);
1307 /* Sign extend accumulator values before adding. */
1313 acc
|= AWREG (which
);
1317 /* Perform a multiplication of D registers SRC0 and SRC1, sign- or
1318 zero-extending the result to 64 bit. H0 and H1 determine whether the
1319 high part or the low part of the source registers is used. Store 1 in
1320 *PSAT if saturation occurs, 0 otherwise. */
1322 decode_multfunc (SIM_CPU
*cpu
, int h0
, int h1
, int src0
, int src1
, int mmod
,
1325 bu32 s0
= DREG (src0
), s1
= DREG (src1
);
1339 sgn0
= -(s0
& 0x8000);
1340 sgn1
= -(s1
& 0x8000);
1362 illegal_instruction (cpu
);
1366 /* Perform shift correction if appropriate for the mode. */
1368 if (!MM
&& (mmod
== 0 || mmod
== M_T
|| mmod
== M_S2RND
|| mmod
== M_W32
))
1370 if (val
== 0x40000000)
1383 /* In signed modes, sign extend. */
1384 if (is_macmod_signed (mmod
) || MM
)
1385 val1
|= -(val1
& 0x80000000);
1388 val1
&= 0xFFFFFFFFull
;
1394 saturate_s40_astat (bu64 val
, bu32
*v
)
1396 if ((bs64
)val
< -((bs64
)1 << 39))
1399 return -((bs64
)1 << 39);
1401 else if ((bs64
)val
> ((bs64
)1 << 39) - 1)
1404 return ((bu64
)1 << 39) - 1;
1406 *v
= 0; /* No overflow. */
1411 saturate_s40 (bu64 val
)
1414 return saturate_s40_astat (val
, &v
);
1418 saturate_s32 (bu64 val
, bu32
*overflow
)
1420 if ((bs64
)val
< -0x80000000ll
)
1426 if ((bs64
)val
> 0x7fffffff)
1436 saturate_u32 (bu64 val
, bu32
*overflow
)
1438 if (val
> 0xffffffff)
1448 saturate_u16 (bu64 val
, bu32
*overflow
)
1464 /* FIXME: Should honour rounding mode. */
1465 if ((val
& 0xffff) > 0x8000
1466 || ((val
& 0xffff) == 0x8000 && (val
& 0x10000)))
1469 sgnbits
= val
& 0xffff000000000000ull
;
1471 return val
| sgnbits
;
1477 bu64 sgnbits
= val
& 0xffff000000000000ull
;
1479 return val
| sgnbits
;
1483 signbits (bu64 val
, int size
)
1485 bu64 mask
= (bu64
)1 << (size
- 1);
1486 bu64 bit
= val
& mask
;
1494 if ((val
& mask
) != bit
)
1504 /* Extract a 16 or 32 bit value from a 64 bit multiplication result.
1505 These 64 bits must be sign- or zero-extended properly from the source
1506 we want to extract, either a 32 bit multiply or a 40 bit accumulator. */
1509 extract_mult (SIM_CPU
*cpu
, bu64 res
, int mmod
, int MM
,
1510 int fullword
, bu32
*overflow
)
1517 return saturate_s32 (res
, overflow
);
1520 return saturate_s32 (res
, overflow
);
1521 return saturate_u32 (res
, overflow
);
1524 return saturate_s32 (res
, overflow
);
1525 return saturate_u32 (res
, overflow
);
1528 return saturate_s32 (res
<< 1, overflow
);
1530 illegal_instruction (cpu
);
1538 return saturate_s16 (rnd16 (res
), overflow
);
1540 return saturate_s16 (res
, overflow
);
1543 return saturate_s16 (rnd16 (res
), overflow
);
1544 return saturate_u16 (rnd16 (res
), overflow
);
1547 return saturate_s16 (res
, overflow
);
1548 return saturate_u16 (res
, overflow
);
1551 return saturate_s16 (trunc16 (res
), overflow
);
1554 return saturate_s16 (trunc16 (res
), overflow
);
1555 return saturate_u16 (trunc16 (res
), overflow
);
1558 return saturate_s16 (rnd16 (res
<< 1), overflow
);
1560 return saturate_s16 (res
<< 1, overflow
);
1562 illegal_instruction (cpu
);
1567 decode_macfunc (SIM_CPU
*cpu
, int which
, int op
, int h0
, int h1
, int src0
,
1568 int src1
, int mmod
, int MM
, int fullword
, bu32
*overflow
,
1572 bu32 sat
= 0, tsat
, ret
;
1574 /* Sign extend accumulator if necessary, otherwise unsigned. */
1575 if (is_macmod_signed (mmod
) || MM
)
1576 acc
= get_extended_acc (cpu
, which
);
1578 acc
= get_unextended_acc (cpu
, which
);
1582 bu8 sgn0
= (acc
>> 31) & 1;
1583 bu8 sgn40
= (acc
>> 39) & 1;
1586 /* This can't saturate, so we don't keep track of the sat flag. */
1587 bu64 res
= decode_multfunc (cpu
, h0
, h1
, src0
, src1
, mmod
,
1590 /* Perform accumulation. */
1595 sgn0
= (acc
>> 31) & 1;
1614 if ((bs64
)acc
< -((bs64
)1 << 39))
1615 acc
= -((bu64
)1 << 39), sat
= 1;
1616 else if ((bs64
)acc
> 0x7fffffffffll
)
1617 acc
= 0x7fffffffffull
, sat
= 1;
1622 if ((bs64
)acc
< -((bs64
)1 << 39))
1623 acc
= -((bu64
)1 << 39), sat
= 1;
1624 if ((bs64
)acc
> 0x7FFFFFFFFFll
)
1625 acc
= 0x7FFFFFFFFFull
, sat
= 1;
1631 if ((bs64
)acc
> 0xFFFFFFFFFFull
)
1632 acc
= 0xFFFFFFFFFFull
, sat
= 1;
1636 if (!MM
&& acc
& 0x8000000000000000ull
)
1638 if (!MM
&& acc
> 0xFFFFFFFFFFull
)
1639 acc
= 0xFFFFFFFFFFull
, sat
= 1;
1640 if (MM
&& acc
> 0xFFFFFFFFFFull
)
1641 acc
&= 0xFFFFFFFFFFull
;
1642 if (acc
& 0x8000000000ull
)
1643 acc
|= 0xffffff0000000000ull
;
1648 if ((bs64
)acc
< -((bs64
)1 << 39))
1649 acc
= -((bu64
)1 << 39), sat
= 1;
1650 if ((bs64
)acc
> 0x7FFFFFFFFFll
)
1651 acc
= 0x7FFFFFFFFFull
, sat
= 1;
1652 else if (acc
& 0x8000000000ull
)
1653 acc
|= 0xffffff0000000000ull
;
1659 else if ((bs64
)acc
> (bs64
)0xFFFFFFFFFFll
)
1660 acc
= 0xFFFFFFFFFFull
, sat
= 1;
1664 if ((bs64
)acc
< -0x80000000ll
)
1665 acc
= -0x80000000ull
, sat
= 1;
1666 else if ((bs64
)acc
> 0x7fffffffll
)
1667 acc
= 0x7fffffffull
, sat
= 1;
1670 /* check max negative value */
1671 if (sgn40
&& ((acc
>> 31) != 0x1ffffffff)
1672 && ((acc
>> 31) != 0x0))
1673 acc
= 0x80000000, sat
= 1;
1674 if (!sat
&& !sgn40
&& ((acc
>> 31) != 0x0)
1675 && ((acc
>> 31) != 0x1ffffffff))
1676 acc
= 0x7FFFFFFF, sat
= 1;
1678 if (acc
& 0x80000000)
1679 acc
|= 0xffffffff00000000ull
;
1684 illegal_instruction (cpu
);
1687 if (acc
& 0x8000000000ull
)
1690 STORE (AXREG (which
), (acc
>> 32) & 0xff);
1691 STORE (AWREG (which
), acc
& 0xffffffff);
1692 STORE (ASTATREG (av
[which
]), sat
);
1694 STORE (ASTATREG (avs
[which
]), sat
);
1696 /* Figure out the overflow bit. */
1702 ret
= extract_mult (cpu
, nosat_acc
, mmod
, MM
, fullword
, overflow
);
1706 ret
= extract_mult (cpu
, acc
, mmod
, MM
, fullword
, overflow
);
1715 if (ret
& 0x80000000)
1723 hwloop_get_next_pc (SIM_CPU
*cpu
, bu32 pc
, bu32 insn_len
)
1730 /* If our PC has reached the bottom of a hardware loop,
1731 move back up to the top of the hardware loop. */
1732 for (i
= 1; i
>= 0; --i
)
1733 if (LCREG (i
) > 1 && pc
== LBREG (i
))
1735 TRACE_BRANCH (cpu
, pc
, LTREG (i
), i
, "Hardware loop %i", i
);
1739 return pc
+ insn_len
;
1743 decode_ProgCtrl_0 (SIM_CPU
*cpu
, bu16 iw0
, bu32 pc
)
1746 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
1747 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |.prgfunc.......|.poprnd........|
1748 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
1749 int poprnd
= ((iw0
>> ProgCtrl_poprnd_bits
) & ProgCtrl_poprnd_mask
);
1750 int prgfunc
= ((iw0
>> ProgCtrl_prgfunc_bits
) & ProgCtrl_prgfunc_mask
);
1752 TRACE_EXTRACT (cpu
, "%s: poprnd:%i prgfunc:%i", __func__
, poprnd
, prgfunc
);
1754 if (prgfunc
== 0 && poprnd
== 0)
1756 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_nop
);
1757 TRACE_INSN (cpu
, "NOP;");
1759 else if (prgfunc
== 1 && poprnd
== 0)
1761 bu32 newpc
= RETSREG
;
1762 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1763 TRACE_INSN (cpu
, "RTS;");
1764 IFETCH_CHECK (newpc
);
1766 illegal_instruction_combination (cpu
);
1767 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "RTS");
1769 BFIN_CPU_STATE
.did_jump
= true;
1772 else if (prgfunc
== 1 && poprnd
== 1)
1774 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1775 TRACE_INSN (cpu
, "RTI;");
1776 /* Do not do IFETCH_CHECK here -- LSB has special meaning. */
1778 illegal_instruction_combination (cpu
);
1779 cec_return (cpu
, -1);
1782 else if (prgfunc
== 1 && poprnd
== 2)
1784 bu32 newpc
= RETXREG
;
1785 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1786 TRACE_INSN (cpu
, "RTX;");
1787 /* XXX: Not sure if this is what the hardware does. */
1788 IFETCH_CHECK (newpc
);
1790 illegal_instruction_combination (cpu
);
1791 cec_return (cpu
, IVG_EVX
);
1794 else if (prgfunc
== 1 && poprnd
== 3)
1796 bu32 newpc
= RETNREG
;
1797 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1798 TRACE_INSN (cpu
, "RTN;");
1799 /* XXX: Not sure if this is what the hardware does. */
1800 IFETCH_CHECK (newpc
);
1802 illegal_instruction_combination (cpu
);
1803 cec_return (cpu
, IVG_NMI
);
1806 else if (prgfunc
== 1 && poprnd
== 4)
1808 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1809 TRACE_INSN (cpu
, "RTE;");
1811 illegal_instruction_combination (cpu
);
1812 cec_return (cpu
, IVG_EMU
);
1815 else if (prgfunc
== 2 && poprnd
== 0)
1817 SIM_DESC sd
= CPU_STATE (cpu
);
1818 sim_events
*events
= STATE_EVENTS (sd
);
1820 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_sync
);
1821 /* XXX: in supervisor mode, utilizes wake up sources
1822 in user mode, it's a NOP ... */
1823 TRACE_INSN (cpu
, "IDLE;");
1826 illegal_instruction_combination (cpu
);
1830 CYCLE_DELAY
= events
->time_from_event
;
1832 abort (); /* XXX: Should this ever happen ? */
1834 else if (prgfunc
== 2 && poprnd
== 3)
1836 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_sync
);
1838 TRACE_INSN (cpu
, "CSYNC;");
1840 illegal_instruction_combination (cpu
);
1843 else if (prgfunc
== 2 && poprnd
== 4)
1845 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_sync
);
1847 TRACE_INSN (cpu
, "SSYNC;");
1849 illegal_instruction_combination (cpu
);
1851 /* Really 10+, but no model info for this. */
1854 else if (prgfunc
== 2 && poprnd
== 5)
1856 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1857 TRACE_INSN (cpu
, "EMUEXCPT;");
1859 illegal_instruction_combination (cpu
);
1860 cec_exception (cpu
, VEC_SIM_TRAP
);
1862 else if (prgfunc
== 3 && poprnd
< 8)
1864 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1865 TRACE_INSN (cpu
, "CLI R%i;", poprnd
);
1867 illegal_instruction_combination (cpu
);
1868 SET_DREG (poprnd
, cec_cli (cpu
));
1870 else if (prgfunc
== 4 && poprnd
< 8)
1872 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1873 TRACE_INSN (cpu
, "STI R%i;", poprnd
);
1875 illegal_instruction_combination (cpu
);
1876 cec_sti (cpu
, DREG (poprnd
));
1879 else if (prgfunc
== 5 && poprnd
< 8)
1881 bu32 newpc
= PREG (poprnd
);
1882 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1883 TRACE_INSN (cpu
, "JUMP (%s);", get_preg_name (poprnd
));
1884 IFETCH_CHECK (newpc
);
1886 illegal_instruction_combination (cpu
);
1887 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP (Preg)");
1889 BFIN_CPU_STATE
.did_jump
= true;
1890 PROFILE_BRANCH_TAKEN (cpu
);
1893 else if (prgfunc
== 6 && poprnd
< 8)
1895 bu32 newpc
= PREG (poprnd
);
1896 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1897 TRACE_INSN (cpu
, "CALL (%s);", get_preg_name (poprnd
));
1898 IFETCH_CHECK (newpc
);
1900 illegal_instruction_combination (cpu
);
1901 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "CALL (Preg)");
1902 /* If we're at the end of a hardware loop, RETS is going to be
1903 the top of the loop rather than the next instruction. */
1904 SET_RETSREG (hwloop_get_next_pc (cpu
, pc
, 2));
1906 BFIN_CPU_STATE
.did_jump
= true;
1907 PROFILE_BRANCH_TAKEN (cpu
);
1910 else if (prgfunc
== 7 && poprnd
< 8)
1912 bu32 newpc
= pc
+ PREG (poprnd
);
1913 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1914 TRACE_INSN (cpu
, "CALL (PC + %s);", get_preg_name (poprnd
));
1915 IFETCH_CHECK (newpc
);
1917 illegal_instruction_combination (cpu
);
1918 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "CALL (PC + Preg)");
1919 SET_RETSREG (hwloop_get_next_pc (cpu
, pc
, 2));
1921 BFIN_CPU_STATE
.did_jump
= true;
1922 PROFILE_BRANCH_TAKEN (cpu
);
1925 else if (prgfunc
== 8 && poprnd
< 8)
1927 bu32 newpc
= pc
+ PREG (poprnd
);
1928 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1929 TRACE_INSN (cpu
, "JUMP (PC + %s);", get_preg_name (poprnd
));
1930 IFETCH_CHECK (newpc
);
1932 illegal_instruction_combination (cpu
);
1933 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP (PC + Preg)");
1935 BFIN_CPU_STATE
.did_jump
= true;
1936 PROFILE_BRANCH_TAKEN (cpu
);
1939 else if (prgfunc
== 9)
1941 int raise
= uimm4 (poprnd
);
1942 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1943 TRACE_INSN (cpu
, "RAISE %s;", uimm4_str (raise
));
1945 illegal_instruction_combination (cpu
);
1946 cec_require_supervisor (cpu
);
1947 if (raise
== IVG_IVHW
)
1948 cec_hwerr (cpu
, HWERR_RAISE_5
);
1950 cec_latch (cpu
, raise
);
1951 CYCLE_DELAY
= 3; /* XXX: Only if IVG is unmasked. */
1953 else if (prgfunc
== 10)
1955 int excpt
= uimm4 (poprnd
);
1956 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1957 TRACE_INSN (cpu
, "EXCPT %s;", uimm4_str (excpt
));
1959 illegal_instruction_combination (cpu
);
1960 cec_exception (cpu
, excpt
);
1963 else if (prgfunc
== 11 && poprnd
< 6)
1965 bu32 addr
= PREG (poprnd
);
1967 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_atomic
);
1968 TRACE_INSN (cpu
, "TESTSET (%s);", get_preg_name (poprnd
));
1970 illegal_instruction_combination (cpu
);
1971 byte
= GET_WORD (addr
);
1972 SET_CCREG (byte
== 0);
1973 PUT_BYTE (addr
, byte
| 0x80);
1974 /* Also includes memory stalls, but we don't model that. */
1978 illegal_instruction (cpu
);
1982 decode_CaCTRL_0 (SIM_CPU
*cpu
, bu16 iw0
)
1985 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
1986 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 |.a.|.op....|.reg.......|
1987 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
1988 int a
= ((iw0
>> CaCTRL_a_bits
) & CaCTRL_a_mask
);
1989 int op
= ((iw0
>> CaCTRL_op_bits
) & CaCTRL_op_mask
);
1990 int reg
= ((iw0
>> CaCTRL_reg_bits
) & CaCTRL_reg_mask
);
1991 bu32 preg
= PREG (reg
);
1992 const char * const sinsn
[] = { "PREFETCH", "FLUSHINV", "FLUSH", "IFLUSH", };
1994 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CaCTRL
);
1995 TRACE_EXTRACT (cpu
, "%s: a:%i op:%i reg:%i", __func__
, a
, op
, reg
);
1996 TRACE_INSN (cpu
, "%s [%s%s];", sinsn
[op
], get_preg_name (reg
), a
? "++" : "");
1999 /* None of these can be part of a parallel instruction. */
2000 illegal_instruction_combination (cpu
);
2002 /* No cache simulation, so these are (mostly) all NOPs.
2003 XXX: The hardware takes care of masking to cache lines, but need
2004 to check behavior of the post increment. Should we be aligning
2005 the value to the cache line before adding the cache line size, or
2006 do we just add the cache line size ? */
2009 mmu_check_cache_addr (cpu
, preg
, false, false);
2013 mmu_check_cache_addr (cpu
, preg
, true, false);
2017 mmu_check_cache_addr (cpu
, preg
, true, false);
2021 mmu_check_cache_addr (cpu
, preg
, false, true);
2025 SET_PREG (reg
, preg
+ BFIN_L1_CACHE_BYTES
);
2029 decode_PushPopReg_0 (SIM_CPU
*cpu
, bu16 iw0
)
2032 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2033 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |.W.|.grp.......|.reg.......|
2034 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2035 int W
= ((iw0
>> PushPopReg_W_bits
) & PushPopReg_W_mask
);
2036 int grp
= ((iw0
>> PushPopReg_grp_bits
) & PushPopReg_grp_mask
);
2037 int reg
= ((iw0
>> PushPopReg_reg_bits
) & PushPopReg_reg_mask
);
2038 const char *reg_name
= get_allreg_name (grp
, reg
);
2042 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_PushPopReg
);
2043 TRACE_EXTRACT (cpu
, "%s: W:%i grp:%i reg:%i", __func__
, W
, grp
, reg
);
2044 TRACE_DECODE (cpu
, "%s: reg:%s", __func__
, reg_name
);
2046 /* Can't push/pop reserved registers */
2047 if (reg_is_reserved (grp
, reg
))
2048 illegal_instruction (cpu
);
2052 /* Dreg and Preg are not supported by this instruction. */
2053 if (grp
== 0 || grp
== 1)
2054 illegal_instruction (cpu
);
2055 TRACE_INSN (cpu
, "%s = [SP++];", reg_name
);
2056 /* Can't pop USP while in userspace. */
2057 if (INSN_LEN
== 8 || (grp
== 7 && reg
== 0 && cec_is_user_mode(cpu
)))
2058 illegal_instruction_combination (cpu
);
2059 /* XXX: The valid register check is in reg_write(), so we might
2060 incorrectly do a GET_LONG() here ... */
2061 value
= GET_LONG (sp
);
2062 reg_write (cpu
, grp
, reg
, value
);
2063 if (grp
== 7 && reg
== 3)
2070 TRACE_INSN (cpu
, "[--SP] = %s;", reg_name
);
2072 illegal_instruction_combination (cpu
);
2075 value
= reg_read (cpu
, grp
, reg
);
2076 if (grp
== 7 && reg
== 3)
2077 cec_push_reti (cpu
);
2079 PUT_LONG (sp
, value
);
2082 /* Note: SP update must be delayed until after all reads/writes; see
2083 comments in decode_PushPopMultiple_0() for more info. */
2088 decode_PushPopMultiple_0 (SIM_CPU
*cpu
, bu16 iw0
)
2091 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2092 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |.d.|.p.|.W.|.dr........|.pr........|
2093 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2094 int p
= ((iw0
>> PushPopMultiple_p_bits
) & PushPopMultiple_p_mask
);
2095 int d
= ((iw0
>> PushPopMultiple_d_bits
) & PushPopMultiple_d_mask
);
2096 int W
= ((iw0
>> PushPopMultiple_W_bits
) & PushPopMultiple_W_mask
);
2097 int dr
= ((iw0
>> PushPopMultiple_dr_bits
) & PushPopMultiple_dr_mask
);
2098 int pr
= ((iw0
>> PushPopMultiple_pr_bits
) & PushPopMultiple_pr_mask
);
2102 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_PushPopMultiple
);
2103 TRACE_EXTRACT (cpu
, "%s: d:%i p:%i W:%i dr:%i pr:%i",
2104 __func__
, d
, p
, W
, dr
, pr
);
2106 if ((d
== 0 && p
== 0) || (p
&& imm5 (pr
) > 5)
2107 || (d
&& !p
&& pr
) || (p
&& !d
&& dr
))
2108 illegal_instruction (cpu
);
2113 TRACE_INSN (cpu
, "[--SP] = (R7:%i, P5:%i);", dr
, pr
);
2115 TRACE_INSN (cpu
, "[--SP] = (R7:%i);", dr
);
2117 TRACE_INSN (cpu
, "[--SP] = (P5:%i);", pr
);
2120 for (i
= dr
; i
< 8; i
++)
2123 PUT_LONG (sp
, DREG (i
));
2126 for (i
= pr
; i
< 6; i
++)
2129 PUT_LONG (sp
, PREG (i
));
2137 TRACE_INSN (cpu
, "(R7:%i, P5:%i) = [SP++];", dr
, pr
);
2139 TRACE_INSN (cpu
, "(R7:%i) = [SP++];", dr
);
2141 TRACE_INSN (cpu
, "(P5:%i) = [SP++];", pr
);
2144 for (i
= 5; i
>= pr
; i
--)
2146 SET_PREG (i
, GET_LONG (sp
));
2150 for (i
= 7; i
>= dr
; i
--)
2152 SET_DREG (i
, GET_LONG (sp
));
2159 /* Note: SP update must be delayed until after all reads/writes so that
2160 if an exception does occur, the insn may be re-executed as the
2161 SP has not yet changed. */
2166 decode_ccMV_0 (SIM_CPU
*cpu
, bu16 iw0
)
2169 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2170 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |.T.|.d.|.s.|.dst.......|.src.......|
2171 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2172 int s
= ((iw0
>> CCmv_s_bits
) & CCmv_s_mask
);
2173 int d
= ((iw0
>> CCmv_d_bits
) & CCmv_d_mask
);
2174 int T
= ((iw0
>> CCmv_T_bits
) & CCmv_T_mask
);
2175 int src
= ((iw0
>> CCmv_src_bits
) & CCmv_src_mask
);
2176 int dst
= ((iw0
>> CCmv_dst_bits
) & CCmv_dst_mask
);
2177 int cond
= T
? CCREG
: ! CCREG
;
2179 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ccMV
);
2180 TRACE_EXTRACT (cpu
, "%s: T:%i d:%i s:%i dst:%i src:%i",
2181 __func__
, T
, d
, s
, dst
, src
);
2183 TRACE_INSN (cpu
, "IF %sCC %s = %s;", T
? "" : "! ",
2184 get_allreg_name (d
, dst
),
2185 get_allreg_name (s
, src
));
2187 illegal_instruction_combination (cpu
);
2190 reg_write (cpu
, d
, dst
, reg_read (cpu
, s
, src
));
2194 decode_CCflag_0 (SIM_CPU
*cpu
, bu16 iw0
)
2197 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2198 | 0 | 0 | 0 | 0 | 1 |.I.|.opc.......|.G.|.y.........|.x.........|
2199 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2200 int x
= ((iw0
>> CCflag_x_bits
) & CCflag_x_mask
);
2201 int y
= ((iw0
>> CCflag_y_bits
) & CCflag_y_mask
);
2202 int I
= ((iw0
>> CCflag_I_bits
) & CCflag_I_mask
);
2203 int G
= ((iw0
>> CCflag_G_bits
) & CCflag_G_mask
);
2204 int opc
= ((iw0
>> CCflag_opc_bits
) & CCflag_opc_mask
);
2206 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CCflag
);
2207 TRACE_EXTRACT (cpu
, "%s: I:%i opc:%i G:%i y:%i x:%i",
2208 __func__
, I
, opc
, G
, y
, x
);
2212 bs64 acc0
= get_extended_acc (cpu
, 0);
2213 bs64 acc1
= get_extended_acc (cpu
, 1);
2214 bs64 diff
= acc0
- acc1
;
2216 if (x
!= 0 || y
!= 0)
2217 illegal_instruction (cpu
);
2219 if (opc
== 5 && I
== 0 && G
== 0)
2221 TRACE_INSN (cpu
, "CC = A0 == A1;");
2223 illegal_instruction_combination (cpu
);
2224 SET_CCREG (acc0
== acc1
);
2226 else if (opc
== 6 && I
== 0 && G
== 0)
2228 TRACE_INSN (cpu
, "CC = A0 < A1");
2230 illegal_instruction_combination (cpu
);
2231 SET_CCREG (acc0
< acc1
);
2233 else if (opc
== 7 && I
== 0 && G
== 0)
2235 TRACE_INSN (cpu
, "CC = A0 <= A1");
2237 illegal_instruction_combination (cpu
);
2238 SET_CCREG (acc0
<= acc1
);
2241 illegal_instruction (cpu
);
2243 SET_ASTATREG (az
, diff
== 0);
2244 SET_ASTATREG (an
, diff
< 0);
2245 SET_ASTATREG (ac0
, (bu40
)acc1
<= (bu40
)acc0
);
2249 int issigned
= opc
< 3;
2250 const char *sign
= issigned
? "" : " (IU)";
2251 bu32 srcop
= G
? PREG (x
) : DREG (x
);
2252 char s
= G
? 'P' : 'R';
2253 bu32 dstop
= I
? (issigned
? imm3 (y
) : uimm3 (y
)) : G
? PREG (y
) : DREG (y
);
2255 char d
= G
? 'P' : 'R';
2256 int flgs
= srcop
>> 31;
2257 int flgo
= dstop
>> 31;
2259 bu32 result
= srcop
- dstop
;
2261 int flgn
= result
>> 31;
2262 int overflow
= (flgs
^ flgo
) & (flgn
^ flgs
);
2263 int az
= result
== 0;
2264 int ac0
= dstop
<= srcop
;
2267 an
= (flgn
&& !overflow
) || (!flgn
&& overflow
);
2273 default: /* Shutup useless gcc warnings. */
2274 case 0: /* signed */
2278 case 1: /* signed */
2282 case 2: /* signed */
2286 case 3: /* unsigned */
2290 case 4: /* unsigned */
2297 TRACE_INSN (cpu
, "CC = %c%i %s %s%s;", s
, x
, op
,
2298 issigned
? imm3_str (y
) : uimm3_str (y
), sign
);
2301 TRACE_DECODE (cpu
, "%s %c%i:%x %c%i:%x", __func__
,
2302 s
, x
, srcop
, d
, y
, dstop
);
2303 TRACE_INSN (cpu
, "CC = %c%i %s %c%i%s;", s
, x
, op
, d
, y
, sign
);
2307 /* Pointer compares only touch CC. */
2310 SET_ASTATREG (az
, az
);
2311 SET_ASTATREG (an
, an
);
2312 SET_ASTATREG (ac0
, ac0
);
2318 decode_CC2dreg_0 (SIM_CPU
*cpu
, bu16 iw0
)
2321 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2322 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |.op....|.reg.......|
2323 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2324 int op
= ((iw0
>> CC2dreg_op_bits
) & CC2dreg_op_mask
);
2325 int reg
= ((iw0
>> CC2dreg_reg_bits
) & CC2dreg_reg_mask
);
2327 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CC2dreg
);
2328 TRACE_EXTRACT (cpu
, "%s: op:%i reg:%i", __func__
, op
, reg
);
2332 TRACE_INSN (cpu
, "R%i = CC;", reg
);
2334 illegal_instruction_combination (cpu
);
2335 SET_DREG (reg
, CCREG
);
2339 TRACE_INSN (cpu
, "CC = R%i;", reg
);
2341 illegal_instruction_combination (cpu
);
2342 SET_CCREG (DREG (reg
) != 0);
2344 else if (op
== 3 && reg
== 0)
2346 TRACE_INSN (cpu
, "CC = !CC;");
2348 illegal_instruction_combination (cpu
);
2352 illegal_instruction (cpu
);
2356 decode_CC2stat_0 (SIM_CPU
*cpu
, bu16 iw0
)
2359 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2360 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |.D.|.op....|.cbit..............|
2361 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2362 int D
= ((iw0
>> CC2stat_D_bits
) & CC2stat_D_mask
);
2363 int op
= ((iw0
>> CC2stat_op_bits
) & CC2stat_op_mask
);
2364 int cbit
= ((iw0
>> CC2stat_cbit_bits
) & CC2stat_cbit_mask
);
2367 const char * const op_names
[] = { "", "|", "&", "^" } ;
2369 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CC2stat
);
2370 TRACE_EXTRACT (cpu
, "%s: D:%i op:%i cbit:%i", __func__
, D
, op
, cbit
);
2372 TRACE_INSN (cpu
, "%s %s= %s;", D
? astat_names
[cbit
] : "CC",
2373 op_names
[op
], D
? "CC" : astat_names
[cbit
]);
2375 /* CC = CC; is invalid. */
2377 illegal_instruction (cpu
);
2380 illegal_instruction_combination (cpu
);
2382 pval
= !!(ASTAT
& (1 << cbit
));
2386 case 0: SET_CCREG (pval
); break;
2387 case 1: SET_CCREG (CCREG
| pval
); break;
2388 case 2: SET_CCREG (CCREG
& pval
); break;
2389 case 3: SET_CCREG (CCREG
^ pval
); break;
2395 case 0: pval
= CCREG
; break;
2396 case 1: pval
|= CCREG
; break;
2397 case 2: pval
&= CCREG
; break;
2398 case 3: pval
^= CCREG
; break;
2400 TRACE_REGISTER (cpu
, "wrote ASTAT[%s] = %i", astat_names
[cbit
], pval
);
2401 SET_ASTAT ((ASTAT
& ~(1 << cbit
)) | (pval
<< cbit
));
2406 decode_BRCC_0 (SIM_CPU
*cpu
, bu16 iw0
, bu32 pc
)
2409 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2410 | 0 | 0 | 0 | 1 |.T.|.B.|.offset................................|
2411 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2412 int B
= ((iw0
>> BRCC_B_bits
) & BRCC_B_mask
);
2413 int T
= ((iw0
>> BRCC_T_bits
) & BRCC_T_mask
);
2414 int offset
= ((iw0
>> BRCC_offset_bits
) & BRCC_offset_mask
);
2415 int cond
= T
? CCREG
: ! CCREG
;
2416 int pcrel
= pcrel10 (offset
);
2418 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_BRCC
);
2419 TRACE_EXTRACT (cpu
, "%s: T:%i B:%i offset:%#x", __func__
, T
, B
, offset
);
2420 TRACE_DECODE (cpu
, "%s: pcrel10:%#x", __func__
, pcrel
);
2422 TRACE_INSN (cpu
, "IF %sCC JUMP %#x%s;", T
? "" : "! ",
2423 pcrel
, B
? " (bp)" : "");
2426 illegal_instruction_combination (cpu
);
2430 bu32 newpc
= pc
+ pcrel
;
2431 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "Conditional JUMP");
2433 BFIN_CPU_STATE
.did_jump
= true;
2434 PROFILE_BRANCH_TAKEN (cpu
);
2435 CYCLE_DELAY
= B
? 5 : 9;
2439 PROFILE_BRANCH_UNTAKEN (cpu
);
2440 CYCLE_DELAY
= B
? 9 : 1;
2445 decode_UJUMP_0 (SIM_CPU
*cpu
, bu16 iw0
, bu32 pc
)
2448 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2449 | 0 | 0 | 1 | 0 |.offset........................................|
2450 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2451 int offset
= ((iw0
>> UJump_offset_bits
) & UJump_offset_mask
);
2452 int pcrel
= pcrel12 (offset
);
2453 bu32 newpc
= pc
+ pcrel
;
2455 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_UJUMP
);
2456 TRACE_EXTRACT (cpu
, "%s: offset:%#x", __func__
, offset
);
2457 TRACE_DECODE (cpu
, "%s: pcrel12:%#x", __func__
, pcrel
);
2459 TRACE_INSN (cpu
, "JUMP.S %#x;", pcrel
);
2462 illegal_instruction_combination (cpu
);
2464 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP.S");
2467 BFIN_CPU_STATE
.did_jump
= true;
2468 PROFILE_BRANCH_TAKEN (cpu
);
2473 decode_REGMV_0 (SIM_CPU
*cpu
, bu16 iw0
)
2476 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2477 | 0 | 0 | 1 | 1 |.gd........|.gs........|.dst.......|.src.......|
2478 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2479 int gs
= ((iw0
>> RegMv_gs_bits
) & RegMv_gs_mask
);
2480 int gd
= ((iw0
>> RegMv_gd_bits
) & RegMv_gd_mask
);
2481 int src
= ((iw0
>> RegMv_src_bits
) & RegMv_src_mask
);
2482 int dst
= ((iw0
>> RegMv_dst_bits
) & RegMv_dst_mask
);
2483 const char *srcreg_name
= get_allreg_name (gs
, src
);
2484 const char *dstreg_name
= get_allreg_name (gd
, dst
);
2486 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_REGMV
);
2487 TRACE_EXTRACT (cpu
, "%s: gd:%i gs:%i dst:%i src:%i",
2488 __func__
, gd
, gs
, dst
, src
);
2489 TRACE_DECODE (cpu
, "%s: dst:%s src:%s", __func__
, dstreg_name
, srcreg_name
);
2491 TRACE_INSN (cpu
, "%s = %s;", dstreg_name
, srcreg_name
);
2493 /* Reserved slots cannot be a src/dst. */
2494 if (reg_is_reserved (gs
, src
) || reg_is_reserved (gd
, dst
))
2497 /* Standard register moves. */
2498 if ((gs
< 2) /* Dregs/Pregs src */
2499 || (gd
< 2) /* Dregs/Pregs dst */
2500 || (gs
== 4 && src
< 4) /* Accumulators src */
2501 || (gd
== 4 && dst
< 4 && (gs
< 4)) /* Accumulators dst */
2502 || (gs
== 7 && src
== 7 && !(gd
== 4 && dst
< 4)) /* EMUDAT src */
2503 || (gd
== 7 && dst
== 7)) /* EMUDAT dst */
2506 /* dareg = dareg (IMBL) */
2507 if (gs
< 4 && gd
< 4)
2510 /* USP can be src to sysregs, but not dagregs. */
2511 if ((gs
== 7 && src
== 0) && (gd
>= 4))
2514 /* USP can move between genregs (only check Accumulators). */
2515 if (((gs
== 7 && src
== 0) && (gd
== 4 && dst
< 4))
2516 || ((gd
== 7 && dst
== 0) && (gs
== 4 && src
< 4)))
2519 /* Still here ? Invalid reg pair. */
2521 illegal_instruction (cpu
);
2524 reg_write (cpu
, gd
, dst
, reg_read (cpu
, gs
, src
));
2528 decode_ALU2op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2531 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2532 | 0 | 1 | 0 | 0 | 0 | 0 |.opc...........|.src.......|.dst.......|
2533 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2534 int src
= ((iw0
>> ALU2op_src_bits
) & ALU2op_src_mask
);
2535 int opc
= ((iw0
>> ALU2op_opc_bits
) & ALU2op_opc_mask
);
2536 int dst
= ((iw0
>> ALU2op_dst_bits
) & ALU2op_dst_mask
);
2538 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ALU2op
);
2539 TRACE_EXTRACT (cpu
, "%s: opc:%i src:%i dst:%i", __func__
, opc
, src
, dst
);
2543 TRACE_INSN (cpu
, "R%i >>>= R%i;", dst
, src
);
2544 SET_DREG (dst
, ashiftrt (cpu
, DREG (dst
), DREG (src
), 32));
2549 TRACE_INSN (cpu
, "R%i >>= R%i;", dst
, src
);
2550 if (DREG (src
) <= 0x1F)
2551 val
= lshiftrt (cpu
, DREG (dst
), DREG (src
), 32);
2554 SET_DREG (dst
, val
);
2558 TRACE_INSN (cpu
, "R%i <<= R%i;", dst
, src
);
2559 SET_DREG (dst
, lshift (cpu
, DREG (dst
), DREG (src
), 32, 0, 0));
2563 TRACE_INSN (cpu
, "R%i *= R%i;", dst
, src
);
2564 SET_DREG (dst
, DREG (dst
) * DREG (src
));
2569 TRACE_INSN (cpu
, "R%i = (R%i + R%i) << 1;", dst
, dst
, src
);
2570 SET_DREG (dst
, add_and_shift (cpu
, DREG (dst
), DREG (src
), 1));
2574 TRACE_INSN (cpu
, "R%i = (R%i + R%i) << 2;", dst
, dst
, src
);
2575 SET_DREG (dst
, add_and_shift (cpu
, DREG (dst
), DREG (src
), 2));
2579 TRACE_INSN (cpu
, "DIVQ ( R%i, R%i );", dst
, src
);
2580 SET_DREG (dst
, divq (cpu
, DREG (dst
), (bu16
)DREG (src
)));
2584 TRACE_INSN (cpu
, "DIVS ( R%i, R%i );", dst
, src
);
2585 SET_DREG (dst
, divs (cpu
, DREG (dst
), (bu16
)DREG (src
)));
2589 TRACE_INSN (cpu
, "R%i = R%i.L (X);", dst
, src
);
2590 SET_DREG (dst
, (bs32
) (bs16
) DREG (src
));
2591 setflags_logical (cpu
, DREG (dst
));
2595 TRACE_INSN (cpu
, "R%i = R%i.L (Z);", dst
, src
);
2596 SET_DREG (dst
, (bu32
) (bu16
) DREG (src
));
2597 setflags_logical (cpu
, DREG (dst
));
2601 TRACE_INSN (cpu
, "R%i = R%i.B (X);", dst
, src
);
2602 SET_DREG (dst
, (bs32
) (bs8
) DREG (src
));
2603 setflags_logical (cpu
, DREG (dst
));
2607 TRACE_INSN (cpu
, "R%i = R%i.B (Z);", dst
, src
);
2608 SET_DREG (dst
, (bu32
) (bu8
) DREG (src
));
2609 setflags_logical (cpu
, DREG (dst
));
2613 bu32 val
= DREG (src
);
2614 TRACE_INSN (cpu
, "R%i = - R%i;", dst
, src
);
2615 SET_DREG (dst
, -val
);
2616 setflags_nz (cpu
, DREG (dst
));
2617 SET_ASTATREG (v
, val
== 0x80000000);
2619 SET_ASTATREG (vs
, 1);
2620 SET_ASTATREG (ac0
, val
== 0x0);
2621 /* XXX: Documentation isn't entirely clear about av0 and av1. */
2625 TRACE_INSN (cpu
, "R%i = ~ R%i;", dst
, src
);
2626 SET_DREG (dst
, ~DREG (src
));
2627 setflags_logical (cpu
, DREG (dst
));
2630 illegal_instruction (cpu
);
2634 decode_PTR2op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2637 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2638 | 0 | 1 | 0 | 0 | 0 | 1 | 0 |.opc.......|.src.......|.dst.......|
2639 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2640 int src
= ((iw0
>> PTR2op_src_bits
) & PTR2op_dst_mask
);
2641 int opc
= ((iw0
>> PTR2op_opc_bits
) & PTR2op_opc_mask
);
2642 int dst
= ((iw0
>> PTR2op_dst_bits
) & PTR2op_dst_mask
);
2643 const char *src_name
= get_preg_name (src
);
2644 const char *dst_name
= get_preg_name (dst
);
2646 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_PTR2op
);
2647 TRACE_EXTRACT (cpu
, "%s: opc:%i src:%i dst:%i", __func__
, opc
, src
, dst
);
2651 TRACE_INSN (cpu
, "%s -= %s", dst_name
, src_name
);
2652 SET_PREG (dst
, PREG (dst
) - PREG (src
));
2656 TRACE_INSN (cpu
, "%s = %s << 2", dst_name
, src_name
);
2657 SET_PREG (dst
, PREG (src
) << 2);
2661 TRACE_INSN (cpu
, "%s = %s >> 2", dst_name
, src_name
);
2662 SET_PREG (dst
, PREG (src
) >> 2);
2666 TRACE_INSN (cpu
, "%s = %s >> 1", dst_name
, src_name
);
2667 SET_PREG (dst
, PREG (src
) >> 1);
2671 TRACE_INSN (cpu
, "%s += %s (BREV)", dst_name
, src_name
);
2672 SET_PREG (dst
, add_brev (PREG (dst
), PREG (src
)));
2676 TRACE_INSN (cpu
, "%s = (%s + %s) << 1", dst_name
, dst_name
, src_name
);
2677 SET_PREG (dst
, (PREG (dst
) + PREG (src
)) << 1);
2681 TRACE_INSN (cpu
, "%s = (%s + %s) << 2", dst_name
, dst_name
, src_name
);
2682 SET_PREG (dst
, (PREG (dst
) + PREG (src
)) << 2);
2685 illegal_instruction (cpu
);
2689 decode_LOGI2op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2692 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2693 | 0 | 1 | 0 | 0 | 1 |.opc.......|.src...............|.dst.......|
2694 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2695 int src
= ((iw0
>> LOGI2op_src_bits
) & LOGI2op_src_mask
);
2696 int opc
= ((iw0
>> LOGI2op_opc_bits
) & LOGI2op_opc_mask
);
2697 int dst
= ((iw0
>> LOGI2op_dst_bits
) & LOGI2op_dst_mask
);
2698 int uimm
= uimm5 (src
);
2699 const char *uimm_str
= uimm5_str (uimm
);
2701 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LOGI2op
);
2702 TRACE_EXTRACT (cpu
, "%s: opc:%i src:%i dst:%i", __func__
, opc
, src
, dst
);
2703 TRACE_DECODE (cpu
, "%s: uimm5:%#x", __func__
, uimm
);
2707 TRACE_INSN (cpu
, "CC = ! BITTST (R%i, %s);", dst
, uimm_str
);
2709 illegal_instruction_combination (cpu
);
2710 SET_CCREG ((~DREG (dst
) >> uimm
) & 1);
2714 TRACE_INSN (cpu
, "CC = BITTST (R%i, %s);", dst
, uimm_str
);
2716 illegal_instruction_combination (cpu
);
2717 SET_CCREG ((DREG (dst
) >> uimm
) & 1);
2721 TRACE_INSN (cpu
, "BITSET (R%i, %s);", dst
, uimm_str
);
2723 illegal_instruction_combination (cpu
);
2724 SET_DREG (dst
, DREG (dst
) | (1 << uimm
));
2725 setflags_logical (cpu
, DREG (dst
));
2729 TRACE_INSN (cpu
, "BITTGL (R%i, %s);", dst
, uimm_str
);
2731 illegal_instruction_combination (cpu
);
2732 SET_DREG (dst
, DREG (dst
) ^ (1 << uimm
));
2733 setflags_logical (cpu
, DREG (dst
));
2737 TRACE_INSN (cpu
, "BITCLR (R%i, %s);", dst
, uimm_str
);
2739 illegal_instruction_combination (cpu
);
2740 SET_DREG (dst
, DREG (dst
) & ~(1 << uimm
));
2741 setflags_logical (cpu
, DREG (dst
));
2745 TRACE_INSN (cpu
, "R%i >>>= %s;", dst
, uimm_str
);
2747 illegal_instruction_combination (cpu
);
2748 SET_DREG (dst
, ashiftrt (cpu
, DREG (dst
), uimm
, 32));
2752 TRACE_INSN (cpu
, "R%i >>= %s;", dst
, uimm_str
);
2754 illegal_instruction_combination (cpu
);
2755 SET_DREG (dst
, lshiftrt (cpu
, DREG (dst
), uimm
, 32));
2759 TRACE_INSN (cpu
, "R%i <<= %s;", dst
, uimm_str
);
2761 illegal_instruction_combination (cpu
);
2762 SET_DREG (dst
, lshift (cpu
, DREG (dst
), uimm
, 32, 0, 0));
2767 decode_COMP3op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2770 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2771 | 0 | 1 | 0 | 1 |.opc.......|.dst.......|.src1......|.src0......|
2772 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2773 int opc
= ((iw0
>> COMP3op_opc_bits
) & COMP3op_opc_mask
);
2774 int dst
= ((iw0
>> COMP3op_dst_bits
) & COMP3op_dst_mask
);
2775 int src0
= ((iw0
>> COMP3op_src0_bits
) & COMP3op_src0_mask
);
2776 int src1
= ((iw0
>> COMP3op_src1_bits
) & COMP3op_src1_mask
);
2778 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_COMP3op
);
2779 TRACE_EXTRACT (cpu
, "%s: opc:%i dst:%i src1:%i src0:%i",
2780 __func__
, opc
, dst
, src1
, src0
);
2784 TRACE_INSN (cpu
, "R%i = R%i + R%i;", dst
, src0
, src1
);
2785 SET_DREG (dst
, add32 (cpu
, DREG (src0
), DREG (src1
), 1, 0));
2789 TRACE_INSN (cpu
, "R%i = R%i - R%i;", dst
, src0
, src1
);
2790 SET_DREG (dst
, sub32 (cpu
, DREG (src0
), DREG (src1
), 1, 0, 0));
2794 TRACE_INSN (cpu
, "R%i = R%i & R%i;", dst
, src0
, src1
);
2795 SET_DREG (dst
, DREG (src0
) & DREG (src1
));
2796 setflags_logical (cpu
, DREG (dst
));
2800 TRACE_INSN (cpu
, "R%i = R%i | R%i;", dst
, src0
, src1
);
2801 SET_DREG (dst
, DREG (src0
) | DREG (src1
));
2802 setflags_logical (cpu
, DREG (dst
));
2806 TRACE_INSN (cpu
, "R%i = R%i ^ R%i;", dst
, src0
, src1
);
2807 SET_DREG (dst
, DREG (src0
) ^ DREG (src1
));
2808 setflags_logical (cpu
, DREG (dst
));
2812 int shift
= opc
- 5;
2813 const char *dst_name
= get_preg_name (dst
);
2814 const char *src0_name
= get_preg_name (src0
);
2815 const char *src1_name
= get_preg_name (src1
);
2817 /* If src0 == src1 this is disassembled as a shift by 1, but this
2818 distinction doesn't matter for our purposes. */
2820 TRACE_INSN (cpu
, "%s = (%s + %s) << %#x;",
2821 dst_name
, src0_name
, src1_name
, shift
);
2823 TRACE_INSN (cpu
, "%s = %s + %s",
2824 dst_name
, src0_name
, src1_name
);
2825 SET_PREG (dst
, PREG (src0
) + (PREG (src1
) << shift
));
2830 decode_COMPI2opD_0 (SIM_CPU
*cpu
, bu16 iw0
)
2833 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2834 | 0 | 1 | 1 | 0 | 0 |.op|..src......................|.dst.......|
2835 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2836 int op
= ((iw0
>> COMPI2opD_op_bits
) & COMPI2opD_op_mask
);
2837 int dst
= ((iw0
>> COMPI2opD_dst_bits
) & COMPI2opD_dst_mask
);
2838 int src
= ((iw0
>> COMPI2opD_src_bits
) & COMPI2opD_src_mask
);
2839 int imm
= imm7 (src
);
2841 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_COMPI2opD
);
2842 TRACE_EXTRACT (cpu
, "%s: op:%i src:%i dst:%i", __func__
, op
, src
, dst
);
2843 TRACE_DECODE (cpu
, "%s: imm7:%#x", __func__
, imm
);
2847 TRACE_INSN (cpu
, "R%i = %s (X);", dst
, imm7_str (imm
));
2848 SET_DREG (dst
, imm
);
2852 TRACE_INSN (cpu
, "R%i += %s;", dst
, imm7_str (imm
));
2853 SET_DREG (dst
, add32 (cpu
, DREG (dst
), imm
, 1, 0));
2858 decode_COMPI2opP_0 (SIM_CPU
*cpu
, bu16 iw0
)
2861 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2862 | 0 | 1 | 1 | 0 | 1 |.op|.src.......................|.dst.......|
2863 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2864 int op
= ((iw0
>> COMPI2opP_op_bits
) & COMPI2opP_op_mask
);
2865 int src
= ((iw0
>> COMPI2opP_src_bits
) & COMPI2opP_src_mask
);
2866 int dst
= ((iw0
>> COMPI2opP_dst_bits
) & COMPI2opP_dst_mask
);
2867 int imm
= imm7 (src
);
2868 const char *dst_name
= get_preg_name (dst
);
2870 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_COMPI2opP
);
2871 TRACE_EXTRACT (cpu
, "%s: op:%i src:%i dst:%i", __func__
, op
, src
, dst
);
2872 TRACE_DECODE (cpu
, "%s: imm:%#x", __func__
, imm
);
2876 TRACE_INSN (cpu
, "%s = %s;", dst_name
, imm7_str (imm
));
2877 SET_PREG (dst
, imm
);
2881 TRACE_INSN (cpu
, "%s += %s;", dst_name
, imm7_str (imm
));
2882 SET_PREG (dst
, PREG (dst
) + imm
);
2887 decode_LDSTpmod_0 (SIM_CPU
*cpu
, bu16 iw0
)
2890 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2891 | 1 | 0 | 0 | 0 |.W.|.aop...|.reg.......|.idx.......|.ptr.......|
2892 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2893 int W
= ((iw0
>> LDSTpmod_W_bits
) & LDSTpmod_W_mask
);
2894 int aop
= ((iw0
>> LDSTpmod_aop_bits
) & LDSTpmod_aop_mask
);
2895 int idx
= ((iw0
>> LDSTpmod_idx_bits
) & LDSTpmod_idx_mask
);
2896 int ptr
= ((iw0
>> LDSTpmod_ptr_bits
) & LDSTpmod_ptr_mask
);
2897 int reg
= ((iw0
>> LDSTpmod_reg_bits
) & LDSTpmod_reg_mask
);
2898 const char *ptr_name
= get_preg_name (ptr
);
2899 const char *idx_name
= get_preg_name (idx
);
2902 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTpmod
);
2903 TRACE_EXTRACT (cpu
, "%s: W:%i aop:%i reg:%i idx:%i ptr:%i",
2904 __func__
, W
, aop
, reg
, idx
, ptr
);
2906 if (aop
== 1 && W
== 0 && idx
== ptr
)
2908 TRACE_INSN (cpu
, "R%i.L = W[%s];", reg
, ptr_name
);
2910 val
= GET_WORD (addr
);
2911 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | val
);
2913 else if (aop
== 2 && W
== 0 && idx
== ptr
)
2915 TRACE_INSN (cpu
, "R%i.H = W[%s];", reg
, ptr_name
);
2917 val
= GET_WORD (addr
);
2918 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (val
<< 16));
2920 else if (aop
== 1 && W
== 1 && idx
== ptr
)
2922 TRACE_INSN (cpu
, "W[%s] = R%i.L;", ptr_name
, reg
);
2924 PUT_WORD (addr
, DREG (reg
));
2926 else if (aop
== 2 && W
== 1 && idx
== ptr
)
2928 TRACE_INSN (cpu
, "W[%s] = R%i.H;", ptr_name
, reg
);
2930 PUT_WORD (addr
, DREG (reg
) >> 16);
2932 else if (aop
== 0 && W
== 0)
2934 TRACE_INSN (cpu
, "R%i = [%s ++ %s];", reg
, ptr_name
, idx_name
);
2936 val
= GET_LONG (addr
);
2937 STORE (DREG (reg
), val
);
2939 STORE (PREG (ptr
), addr
+ PREG (idx
));
2941 else if (aop
== 1 && W
== 0)
2943 TRACE_INSN (cpu
, "R%i.L = W[%s ++ %s];", reg
, ptr_name
, idx_name
);
2945 val
= GET_WORD (addr
);
2946 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | val
);
2948 STORE (PREG (ptr
), addr
+ PREG (idx
));
2950 else if (aop
== 2 && W
== 0)
2952 TRACE_INSN (cpu
, "R%i.H = W[%s ++ %s];", reg
, ptr_name
, idx_name
);
2954 val
= GET_WORD (addr
);
2955 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (val
<< 16));
2957 STORE (PREG (ptr
), addr
+ PREG (idx
));
2959 else if (aop
== 3 && W
== 0)
2961 TRACE_INSN (cpu
, "R%i = W[%s ++ %s] (Z);", reg
, ptr_name
, idx_name
);
2963 val
= GET_WORD (addr
);
2964 STORE (DREG (reg
), val
);
2966 STORE (PREG (ptr
), addr
+ PREG (idx
));
2968 else if (aop
== 3 && W
== 1)
2970 TRACE_INSN (cpu
, "R%i = W[%s ++ %s] (X);", reg
, ptr_name
, idx_name
);
2972 val
= GET_WORD (addr
);
2973 STORE (DREG (reg
), (bs32
) (bs16
) val
);
2975 STORE (PREG (ptr
), addr
+ PREG (idx
));
2977 else if (aop
== 0 && W
== 1)
2979 TRACE_INSN (cpu
, "[%s ++ %s] = R%i;", ptr_name
, idx_name
, reg
);
2981 PUT_LONG (addr
, DREG (reg
));
2983 STORE (PREG (ptr
), addr
+ PREG (idx
));
2985 else if (aop
== 1 && W
== 1)
2987 TRACE_INSN (cpu
, "W[%s ++ %s] = R%i.L;", ptr_name
, idx_name
, reg
);
2989 PUT_WORD (addr
, DREG (reg
));
2991 STORE (PREG (ptr
), addr
+ PREG (idx
));
2993 else if (aop
== 2 && W
== 1)
2995 TRACE_INSN (cpu
, "W[%s ++ %s] = R%i.H;", ptr_name
, idx_name
, reg
);
2997 PUT_WORD (addr
, DREG (reg
) >> 16);
2999 STORE (PREG (ptr
), addr
+ PREG (idx
));
3002 illegal_instruction (cpu
);
3006 decode_dagMODim_0 (SIM_CPU
*cpu
, bu16 iw0
)
3009 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3010 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 0 |.br| 1 | 1 |.op|.m.....|.i.....|
3011 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3012 int i
= ((iw0
>> DagMODim_i_bits
) & DagMODim_i_mask
);
3013 int m
= ((iw0
>> DagMODim_m_bits
) & DagMODim_m_mask
);
3014 int br
= ((iw0
>> DagMODim_br_bits
) & DagMODim_br_mask
);
3015 int op
= ((iw0
>> DagMODim_op_bits
) & DagMODim_op_mask
);
3017 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dagMODim
);
3018 TRACE_EXTRACT (cpu
, "%s: br:%i op:%i m:%i i:%i", __func__
, br
, op
, m
, i
);
3020 if (op
== 0 && br
== 1)
3022 TRACE_INSN (cpu
, "I%i += M%i (BREV);", i
, m
);
3023 SET_IREG (i
, add_brev (IREG (i
), MREG (m
)));
3027 TRACE_INSN (cpu
, "I%i += M%i;", i
, m
);
3028 dagadd (cpu
, i
, MREG (m
));
3030 else if (op
== 1 && br
== 0)
3032 TRACE_INSN (cpu
, "I%i -= M%i;", i
, m
);
3033 dagsub (cpu
, i
, MREG (m
));
3036 illegal_instruction (cpu
);
3040 decode_dagMODik_0 (SIM_CPU
*cpu
, bu16 iw0
)
3043 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3044 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 0 |.op....|.i.....|
3045 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3046 int i
= ((iw0
>> DagMODik_i_bits
) & DagMODik_i_mask
);
3047 int op
= ((iw0
>> DagMODik_op_bits
) & DagMODik_op_mask
);
3049 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dagMODik
);
3050 TRACE_EXTRACT (cpu
, "%s: op:%i i:%i", __func__
, op
, i
);
3054 TRACE_INSN (cpu
, "I%i += 2;", i
);
3059 TRACE_INSN (cpu
, "I%i -= 2;", i
);
3064 TRACE_INSN (cpu
, "I%i += 4;", i
);
3069 TRACE_INSN (cpu
, "I%i -= 4;", i
);
3073 illegal_instruction (cpu
);
3077 decode_dspLDST_0 (SIM_CPU
*cpu
, bu16 iw0
)
3080 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3081 | 1 | 0 | 0 | 1 | 1 | 1 |.W.|.aop...|.m.....|.i.....|.reg.......|
3082 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3083 int i
= ((iw0
>> DspLDST_i_bits
) & DspLDST_i_mask
);
3084 int m
= ((iw0
>> DspLDST_m_bits
) & DspLDST_m_mask
);
3085 int W
= ((iw0
>> DspLDST_W_bits
) & DspLDST_W_mask
);
3086 int aop
= ((iw0
>> DspLDST_aop_bits
) & DspLDST_aop_mask
);
3087 int reg
= ((iw0
>> DspLDST_reg_bits
) & DspLDST_reg_mask
);
3090 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dspLDST
);
3091 TRACE_EXTRACT (cpu
, "%s: aop:%i m:%i i:%i reg:%i", __func__
, aop
, m
, i
, reg
);
3093 if (aop
== 0 && W
== 0 && m
== 0)
3095 TRACE_INSN (cpu
, "R%i = [I%i++];", reg
, i
);
3097 if (DIS_ALGN_EXPT
& 0x1)
3100 STORE (DREG (reg
), GET_LONG (addr
));
3102 else if (aop
== 0 && W
== 0 && m
== 1)
3104 TRACE_INSN (cpu
, "R%i.L = W[I%i++];", reg
, i
);
3107 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | GET_WORD (addr
));
3109 else if (aop
== 0 && W
== 0 && m
== 2)
3111 TRACE_INSN (cpu
, "R%i.H = W[I%i++];", reg
, i
);
3114 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (GET_WORD (addr
) << 16));
3116 else if (aop
== 1 && W
== 0 && m
== 0)
3118 TRACE_INSN (cpu
, "R%i = [I%i--];", reg
, i
);
3120 if (DIS_ALGN_EXPT
& 0x1)
3123 STORE (DREG (reg
), GET_LONG (addr
));
3125 else if (aop
== 1 && W
== 0 && m
== 1)
3127 TRACE_INSN (cpu
, "R%i.L = W[I%i--];", reg
, i
);
3130 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | GET_WORD (addr
));
3132 else if (aop
== 1 && W
== 0 && m
== 2)
3134 TRACE_INSN (cpu
, "R%i.H = W[I%i--];", reg
, i
);
3137 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (GET_WORD (addr
) << 16));
3139 else if (aop
== 2 && W
== 0 && m
== 0)
3141 TRACE_INSN (cpu
, "R%i = [I%i];", reg
, i
);
3143 if (DIS_ALGN_EXPT
& 0x1)
3145 STORE (DREG (reg
), GET_LONG (addr
));
3147 else if (aop
== 2 && W
== 0 && m
== 1)
3149 TRACE_INSN (cpu
, "R%i.L = W[I%i];", reg
, i
);
3151 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | GET_WORD (addr
));
3153 else if (aop
== 2 && W
== 0 && m
== 2)
3155 TRACE_INSN (cpu
, "R%i.H = W[I%i];", reg
, i
);
3157 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (GET_WORD (addr
) << 16));
3159 else if (aop
== 0 && W
== 1 && m
== 0)
3161 TRACE_INSN (cpu
, "[I%i++] = R%i;", i
, reg
);
3164 PUT_LONG (addr
, DREG (reg
));
3166 else if (aop
== 0 && W
== 1 && m
== 1)
3168 TRACE_INSN (cpu
, "W[I%i++] = R%i.L;", i
, reg
);
3171 PUT_WORD (addr
, DREG (reg
));
3173 else if (aop
== 0 && W
== 1 && m
== 2)
3175 TRACE_INSN (cpu
, "W[I%i++] = R%i.H;", i
, reg
);
3178 PUT_WORD (addr
, DREG (reg
) >> 16);
3180 else if (aop
== 1 && W
== 1 && m
== 0)
3182 TRACE_INSN (cpu
, "[I%i--] = R%i;", i
, reg
);
3185 PUT_LONG (addr
, DREG (reg
));
3187 else if (aop
== 1 && W
== 1 && m
== 1)
3189 TRACE_INSN (cpu
, "W[I%i--] = R%i.L;", i
, reg
);
3192 PUT_WORD (addr
, DREG (reg
));
3194 else if (aop
== 1 && W
== 1 && m
== 2)
3196 TRACE_INSN (cpu
, "W[I%i--] = R%i.H;", i
, reg
);
3199 PUT_WORD (addr
, DREG (reg
) >> 16);
3201 else if (aop
== 2 && W
== 1 && m
== 0)
3203 TRACE_INSN (cpu
, "[I%i] = R%i;", i
, reg
);
3205 PUT_LONG (addr
, DREG (reg
));
3207 else if (aop
== 2 && W
== 1 && m
== 1)
3209 TRACE_INSN (cpu
, "W[I%i] = R%i.L;", i
, reg
);
3211 PUT_WORD (addr
, DREG (reg
));
3213 else if (aop
== 2 && W
== 1 && m
== 2)
3215 TRACE_INSN (cpu
, "W[I%i] = R%i.H;", i
, reg
);
3217 PUT_WORD (addr
, DREG (reg
) >> 16);
3219 else if (aop
== 3 && W
== 0)
3221 TRACE_INSN (cpu
, "R%i = [I%i ++ M%i];", reg
, i
, m
);
3223 if (DIS_ALGN_EXPT
& 0x1)
3225 dagadd (cpu
, i
, MREG (m
));
3226 STORE (DREG (reg
), GET_LONG (addr
));
3228 else if (aop
== 3 && W
== 1)
3230 TRACE_INSN (cpu
, "[I%i ++ M%i] = R%i;", i
, m
, reg
);
3232 dagadd (cpu
, i
, MREG (m
));
3233 PUT_LONG (addr
, DREG (reg
));
3236 illegal_instruction (cpu
);
3240 decode_LDST_0 (SIM_CPU
*cpu
, bu16 iw0
)
3243 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3244 | 1 | 0 | 0 | 1 |.sz....|.W.|.aop...|.Z.|.ptr.......|.reg.......|
3245 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3246 int Z
= ((iw0
>> LDST_Z_bits
) & LDST_Z_mask
);
3247 int W
= ((iw0
>> LDST_W_bits
) & LDST_W_mask
);
3248 int sz
= ((iw0
>> LDST_sz_bits
) & LDST_sz_mask
);
3249 int aop
= ((iw0
>> LDST_aop_bits
) & LDST_aop_mask
);
3250 int reg
= ((iw0
>> LDST_reg_bits
) & LDST_reg_mask
);
3251 int ptr
= ((iw0
>> LDST_ptr_bits
) & LDST_ptr_mask
);
3252 const char * const posts
[] = { "++", "--", "" };
3253 const char *post
= posts
[aop
];
3254 const char *ptr_name
= get_preg_name (ptr
);
3256 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDST
);
3257 TRACE_EXTRACT (cpu
, "%s: sz:%i W:%i aop:%i Z:%i ptr:%i reg:%i",
3258 __func__
, sz
, W
, aop
, Z
, ptr
, reg
);
3261 illegal_instruction (cpu
);
3265 if (sz
== 0 && Z
== 0)
3267 TRACE_INSN (cpu
, "R%i = [%s%s];", reg
, ptr_name
, post
);
3268 SET_DREG (reg
, GET_LONG (PREG (ptr
)));
3270 else if (sz
== 0 && Z
== 1)
3272 TRACE_INSN (cpu
, "%s = [%s%s];", get_preg_name (reg
), ptr_name
, post
);
3273 if (aop
< 2 && ptr
== reg
)
3274 illegal_instruction_combination (cpu
);
3275 SET_PREG (reg
, GET_LONG (PREG (ptr
)));
3277 else if (sz
== 1 && Z
== 0)
3279 TRACE_INSN (cpu
, "R%i = W[%s%s] (Z);", reg
, ptr_name
, post
);
3280 SET_DREG (reg
, GET_WORD (PREG (ptr
)));
3282 else if (sz
== 1 && Z
== 1)
3284 TRACE_INSN (cpu
, "R%i = W[%s%s] (X);", reg
, ptr_name
, post
);
3285 SET_DREG (reg
, (bs32
) (bs16
) GET_WORD (PREG (ptr
)));
3287 else if (sz
== 2 && Z
== 0)
3289 TRACE_INSN (cpu
, "R%i = B[%s%s] (Z);", reg
, ptr_name
, post
);
3290 SET_DREG (reg
, GET_BYTE (PREG (ptr
)));
3292 else if (sz
== 2 && Z
== 1)
3294 TRACE_INSN (cpu
, "R%i = B[%s%s] (X);", reg
, ptr_name
, post
);
3295 SET_DREG (reg
, (bs32
) (bs8
) GET_BYTE (PREG (ptr
)));
3298 illegal_instruction (cpu
);
3302 if (sz
== 0 && Z
== 0)
3304 TRACE_INSN (cpu
, "[%s%s] = R%i;", ptr_name
, post
, reg
);
3305 PUT_LONG (PREG (ptr
), DREG (reg
));
3307 else if (sz
== 0 && Z
== 1)
3309 TRACE_INSN (cpu
, "[%s%s] = %s;", ptr_name
, post
, get_preg_name (reg
));
3310 PUT_LONG (PREG (ptr
), PREG (reg
));
3312 else if (sz
== 1 && Z
== 0)
3314 TRACE_INSN (cpu
, "W[%s%s] = R%i;", ptr_name
, post
, reg
);
3315 PUT_WORD (PREG (ptr
), DREG (reg
));
3317 else if (sz
== 2 && Z
== 0)
3319 TRACE_INSN (cpu
, "B[%s%s] = R%i;", ptr_name
, post
, reg
);
3320 PUT_BYTE (PREG (ptr
), DREG (reg
));
3323 illegal_instruction (cpu
);
3327 SET_PREG (ptr
, PREG (ptr
) + (1 << (2 - sz
)));
3329 SET_PREG (ptr
, PREG (ptr
) - (1 << (2 - sz
)));
3333 decode_LDSTiiFP_0 (SIM_CPU
*cpu
, bu16 iw0
)
3336 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3337 | 1 | 0 | 1 | 1 | 1 | 0 |.W.|.offset............|.reg...........|
3338 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3339 /* This isn't exactly a grp:reg as this insn only supports Dregs & Pregs,
3340 but for our usage, its functionality the same thing. */
3341 int grp
= ((iw0
>> 3) & 0x1);
3342 int reg
= ((iw0
>> LDSTiiFP_reg_bits
) & 0x7 /*LDSTiiFP_reg_mask*/);
3343 int offset
= ((iw0
>> LDSTiiFP_offset_bits
) & LDSTiiFP_offset_mask
);
3344 int W
= ((iw0
>> LDSTiiFP_W_bits
) & LDSTiiFP_W_mask
);
3345 bu32 imm
= negimm5s4 (offset
);
3346 bu32 ea
= FPREG
+ imm
;
3347 const char *imm_str
= negimm5s4_str (offset
);
3348 const char *reg_name
= get_allreg_name (grp
, reg
);
3350 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTiiFP
);
3351 TRACE_EXTRACT (cpu
, "%s: W:%i offset:%#x grp:%i reg:%i", __func__
,
3352 W
, offset
, grp
, reg
);
3353 TRACE_DECODE (cpu
, "%s: negimm5s4:%#x", __func__
, imm
);
3357 TRACE_INSN (cpu
, "%s = [FP + %s];", reg_name
, imm_str
);
3358 reg_write (cpu
, grp
, reg
, GET_LONG (ea
));
3362 TRACE_INSN (cpu
, "[FP + %s] = %s;", imm_str
, reg_name
);
3363 PUT_LONG (ea
, reg_read (cpu
, grp
, reg
));
3368 decode_LDSTii_0 (SIM_CPU
*cpu
, bu16 iw0
)
3371 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3372 | 1 | 0 | 1 |.W.|.op....|.offset........|.ptr.......|.reg.......|
3373 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3374 int reg
= ((iw0
>> LDSTii_reg_bit
) & LDSTii_reg_mask
);
3375 int ptr
= ((iw0
>> LDSTii_ptr_bit
) & LDSTii_ptr_mask
);
3376 int offset
= ((iw0
>> LDSTii_offset_bit
) & LDSTii_offset_mask
);
3377 int op
= ((iw0
>> LDSTii_op_bit
) & LDSTii_op_mask
);
3378 int W
= ((iw0
>> LDSTii_W_bit
) & LDSTii_W_mask
);
3380 const char *imm_str
;
3381 const char *ptr_name
= get_preg_name (ptr
);
3383 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTii
);
3384 TRACE_EXTRACT (cpu
, "%s: W:%i op:%i offset:%#x ptr:%i reg:%i",
3385 __func__
, W
, op
, offset
, ptr
, reg
);
3387 if (op
== 0 || op
== 3)
3388 imm
= uimm4s4 (offset
), imm_str
= uimm4s4_str (offset
);
3390 imm
= uimm4s2 (offset
), imm_str
= uimm4s2_str (offset
);
3391 ea
= PREG (ptr
) + imm
;
3393 TRACE_DECODE (cpu
, "%s: uimm4s4/uimm4s2:%#x", __func__
, imm
);
3395 if (W
== 1 && op
== 2)
3396 illegal_instruction (cpu
);
3402 TRACE_INSN (cpu
, "R%i = [%s + %s];", reg
, ptr_name
, imm_str
);
3403 SET_DREG (reg
, GET_LONG (ea
));
3407 TRACE_INSN (cpu
, "R%i = W[%s + %s] (Z);", reg
, ptr_name
, imm_str
);
3408 SET_DREG (reg
, GET_WORD (ea
));
3412 TRACE_INSN (cpu
, "R%i = W[%s + %s] (X);", reg
, ptr_name
, imm_str
);
3413 SET_DREG (reg
, (bs32
) (bs16
) GET_WORD (ea
));
3417 TRACE_INSN (cpu
, "%s = [%s + %s];",
3418 get_preg_name (reg
), ptr_name
, imm_str
);
3419 SET_PREG (reg
, GET_LONG (ea
));
3426 TRACE_INSN (cpu
, "[%s + %s] = R%i;", ptr_name
, imm_str
, reg
);
3427 PUT_LONG (ea
, DREG (reg
));
3431 TRACE_INSN (cpu
, "W[%s + %s] = R%i;", ptr_name
, imm_str
, reg
);
3432 PUT_WORD (ea
, DREG (reg
));
3436 TRACE_INSN (cpu
, "[%s + %s] = %s;",
3437 ptr_name
, imm_str
, get_preg_name (reg
));
3438 PUT_LONG (ea
, PREG (reg
));
3444 decode_LoopSetup_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
, bu32 pc
)
3447 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3448 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |.rop...|.c.|.soffset.......|
3449 |.reg...........| - | - |.eoffset...............................|
3450 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3451 int c
= ((iw0
>> (LoopSetup_c_bits
- 16)) & LoopSetup_c_mask
);
3452 int reg
= ((iw1
>> LoopSetup_reg_bits
) & LoopSetup_reg_mask
);
3453 int rop
= ((iw0
>> (LoopSetup_rop_bits
- 16)) & LoopSetup_rop_mask
);
3454 int soffset
= ((iw0
>> (LoopSetup_soffset_bits
- 16)) & LoopSetup_soffset_mask
);
3455 int eoffset
= ((iw1
>> LoopSetup_eoffset_bits
) & LoopSetup_eoffset_mask
);
3456 int spcrel
= pcrel4 (soffset
);
3457 int epcrel
= lppcrel10 (eoffset
);
3459 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LoopSetup
);
3460 TRACE_EXTRACT (cpu
, "%s: rop:%i c:%i soffset:%i reg:%i eoffset:%i",
3461 __func__
, rop
, c
, soffset
, reg
, eoffset
);
3462 TRACE_DECODE (cpu
, "%s: s_pcrel4:%#x e_lppcrel10:%#x",
3463 __func__
, spcrel
, epcrel
);
3466 illegal_instruction (cpu
);
3469 illegal_instruction_combination (cpu
);
3473 TRACE_INSN (cpu
, "LSETUP (%#x, %#x) LC%i;", spcrel
, epcrel
, c
);
3475 else if (rop
== 1 && reg
<= 7)
3477 TRACE_INSN (cpu
, "LSETUP (%#x, %#x) LC%i = %s;",
3478 spcrel
, epcrel
, c
, get_preg_name (reg
));
3479 SET_LCREG (c
, PREG (reg
));
3481 else if (rop
== 3 && reg
<= 7)
3483 TRACE_INSN (cpu
, "LSETUP (%#x, %#x) LC%i = %s >> 1;",
3484 spcrel
, epcrel
, c
, get_preg_name (reg
));
3485 SET_LCREG (c
, PREG (reg
) >> 1);
3488 illegal_instruction (cpu
);
3490 SET_LTREG (c
, pc
+ spcrel
);
3491 SET_LBREG (c
, pc
+ epcrel
);
3495 decode_LDIMMhalf_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3498 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3499 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 |.Z.|.H.|.S.|.grp...|.reg.......|
3500 |.hword.........................................................|
3501 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3502 int H
= ((iw0
>> (LDIMMhalf_H_bits
- 16)) & LDIMMhalf_H_mask
);
3503 int Z
= ((iw0
>> (LDIMMhalf_Z_bits
- 16)) & LDIMMhalf_Z_mask
);
3504 int S
= ((iw0
>> (LDIMMhalf_S_bits
- 16)) & LDIMMhalf_S_mask
);
3505 int reg
= ((iw0
>> (LDIMMhalf_reg_bits
- 16)) & LDIMMhalf_reg_mask
);
3506 int grp
= ((iw0
>> (LDIMMhalf_grp_bits
- 16)) & LDIMMhalf_grp_mask
);
3507 int hword
= ((iw1
>> LDIMMhalf_hword_bits
) & LDIMMhalf_hword_mask
);
3509 const char *val_str
;
3510 const char *reg_name
= get_allreg_name (grp
, reg
);
3512 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDIMMhalf
);
3513 TRACE_EXTRACT (cpu
, "%s: Z:%i H:%i S:%i grp:%i reg:%i hword:%#x",
3514 __func__
, Z
, H
, S
, grp
, reg
, hword
);
3517 illegal_instruction_combination (cpu
);
3520 val
= imm16 (hword
), val_str
= imm16_str (hword
);
3522 val
= luimm16 (hword
), val_str
= luimm16_str (hword
);
3524 if (H
== 0 && S
== 1 && Z
== 0)
3526 TRACE_INSN (cpu
, "%s = %s (X);", reg_name
, val_str
);
3528 else if (H
== 0 && S
== 0 && Z
== 1)
3530 TRACE_INSN (cpu
, "%s = %s (Z);", reg_name
, val_str
);
3532 else if (H
== 0 && S
== 0 && Z
== 0)
3534 TRACE_INSN (cpu
, "%s.L = %s;", reg_name
, val_str
);
3535 val
= REG_H_L (reg_read (cpu
, grp
, reg
), val
);
3537 else if (H
== 1 && S
== 0 && Z
== 0)
3539 TRACE_INSN (cpu
, "%s.H = %s;", reg_name
, val_str
);
3540 val
= REG_H_L (val
<< 16, reg_read (cpu
, grp
, reg
));
3543 illegal_instruction (cpu
);
3545 reg_write (cpu
, grp
, reg
, val
);
3549 decode_CALLa_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
, bu32 pc
)
3552 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3553 | 1 | 1 | 1 | 0 | 0 | 0 | 1 |.S.|.msw...........................|
3554 |.lsw...........................................................|
3555 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3556 int S
= ((iw0
>> (CALLa_S_bits
- 16)) & CALLa_S_mask
);
3557 int lsw
= ((iw1
>> 0) & 0xffff);
3558 int msw
= ((iw0
>> 0) & 0xff);
3559 int pcrel
= pcrel24 ((msw
<< 16) | lsw
);
3560 bu32 newpc
= pc
+ pcrel
;
3562 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CALLa
);
3563 TRACE_EXTRACT (cpu
, "%s: S:%i msw:%#x lsw:%#x", __func__
, S
, msw
, lsw
);
3564 TRACE_DECODE (cpu
, "%s: pcrel24:%#x", __func__
, pcrel
);
3566 TRACE_INSN (cpu
, "%s %#x;", S
? "CALL" : "JUMP.L", pcrel
);
3569 illegal_instruction_combination (cpu
);
3573 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "CALL");
3574 SET_RETSREG (hwloop_get_next_pc (cpu
, pc
, 4));
3577 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP.L");
3580 BFIN_CPU_STATE
.did_jump
= true;
3581 PROFILE_BRANCH_TAKEN (cpu
);
3586 decode_LDSTidxI_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3589 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3590 | 1 | 1 | 1 | 0 | 0 | 1 |.W.|.Z.|.sz....|.ptr.......|.reg.......|
3591 |.offset........................................................|
3592 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3593 int Z
= ((iw0
>> (LDSTidxI_Z_bits
- 16)) & LDSTidxI_Z_mask
);
3594 int W
= ((iw0
>> (LDSTidxI_W_bits
- 16)) & LDSTidxI_W_mask
);
3595 int sz
= ((iw0
>> (LDSTidxI_sz_bits
- 16)) & LDSTidxI_sz_mask
);
3596 int reg
= ((iw0
>> (LDSTidxI_reg_bits
- 16)) & LDSTidxI_reg_mask
);
3597 int ptr
= ((iw0
>> (LDSTidxI_ptr_bits
- 16)) & LDSTidxI_ptr_mask
);
3598 int offset
= ((iw1
>> LDSTidxI_offset_bits
) & LDSTidxI_offset_mask
);
3599 const char *ptr_name
= get_preg_name (ptr
);
3600 bu32 imm_16s4
= imm16s4 (offset
);
3601 bu32 imm_16s2
= imm16s2 (offset
);
3602 bu32 imm_16
= imm16 (offset
);
3604 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTidxI
);
3605 TRACE_EXTRACT (cpu
, "%s: W:%i Z:%i sz:%i ptr:%i reg:%i offset:%#x",
3606 __func__
, W
, Z
, sz
, ptr
, reg
, offset
);
3609 illegal_instruction (cpu
);
3613 if (sz
== 0 && Z
== 0)
3615 TRACE_INSN (cpu
, "R%i = [%s + %s];",
3616 reg
, ptr_name
, imm16s4_str (offset
));
3617 SET_DREG (reg
, GET_LONG (PREG (ptr
) + imm_16s4
));
3619 else if (sz
== 0 && Z
== 1)
3621 TRACE_INSN (cpu
, "%s = [%s + %s];",
3622 get_preg_name (reg
), ptr_name
, imm16s4_str (offset
));
3623 SET_PREG (reg
, GET_LONG (PREG (ptr
) + imm_16s4
));
3625 else if (sz
== 1 && Z
== 0)
3627 TRACE_INSN (cpu
, "R%i = W[%s + %s] (Z);",
3628 reg
, ptr_name
, imm16s2_str (offset
));
3629 SET_DREG (reg
, GET_WORD (PREG (ptr
) + imm_16s2
));
3631 else if (sz
== 1 && Z
== 1)
3633 TRACE_INSN (cpu
, "R%i = W[%s + %s] (X);",
3634 reg
, ptr_name
, imm16s2_str (offset
));
3635 SET_DREG (reg
, (bs32
) (bs16
) GET_WORD (PREG (ptr
) + imm_16s2
));
3637 else if (sz
== 2 && Z
== 0)
3639 TRACE_INSN (cpu
, "R%i = B[%s + %s] (Z);",
3640 reg
, ptr_name
, imm16_str (offset
));
3641 SET_DREG (reg
, GET_BYTE (PREG (ptr
) + imm_16
));
3643 else if (sz
== 2 && Z
== 1)
3645 TRACE_INSN (cpu
, "R%i = B[%s + %s] (X);",
3646 reg
, ptr_name
, imm16_str (offset
));
3647 SET_DREG (reg
, (bs32
) (bs8
) GET_BYTE (PREG (ptr
) + imm_16
));
3652 if (sz
!= 0 && Z
!= 0)
3653 illegal_instruction (cpu
);
3655 if (sz
== 0 && Z
== 0)
3657 TRACE_INSN (cpu
, "[%s + %s] = R%i;", ptr_name
,
3658 imm16s4_str (offset
), reg
);
3659 PUT_LONG (PREG (ptr
) + imm_16s4
, DREG (reg
));
3661 else if (sz
== 0 && Z
== 1)
3663 TRACE_INSN (cpu
, "[%s + %s] = %s;",
3664 ptr_name
, imm16s4_str (offset
), get_preg_name (reg
));
3665 PUT_LONG (PREG (ptr
) + imm_16s4
, PREG (reg
));
3667 else if (sz
== 1 && Z
== 0)
3669 TRACE_INSN (cpu
, "W[%s + %s] = R%i;",
3670 ptr_name
, imm16s2_str (offset
), reg
);
3671 PUT_WORD (PREG (ptr
) + imm_16s2
, DREG (reg
));
3673 else if (sz
== 2 && Z
== 0)
3675 TRACE_INSN (cpu
, "B[%s + %s] = R%i;",
3676 ptr_name
, imm16_str (offset
), reg
);
3677 PUT_BYTE (PREG (ptr
) + imm_16
, DREG (reg
));
3683 decode_linkage_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3686 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3687 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |.R.|
3688 |.framesize.....................................................|
3689 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3690 int R
= ((iw0
>> (Linkage_R_bits
- 16)) & Linkage_R_mask
);
3691 int framesize
= ((iw1
>> Linkage_framesize_bits
) & Linkage_framesize_mask
);
3694 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_linkage
);
3695 TRACE_EXTRACT (cpu
, "%s: R:%i framesize:%#x", __func__
, R
, framesize
);
3699 int size
= uimm16s4 (framesize
);
3701 TRACE_INSN (cpu
, "LINK %s;", uimm16s4_str (framesize
));
3703 illegal_instruction_combination (cpu
);
3705 PUT_LONG (sp
, RETSREG
);
3707 PUT_LONG (sp
, FPREG
);
3714 /* Restore SP from FP. */
3716 TRACE_INSN (cpu
, "UNLINK;");
3718 illegal_instruction_combination (cpu
);
3719 SET_FPREG (GET_LONG (sp
));
3721 SET_RETSREG (GET_LONG (sp
));
3730 decode_dsp32mac_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3733 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3734 | 1 | 1 | 0 | 0 |.M.| 0 | 0 |.mmod..........|.MM|.P.|.w1|.op1...|
3735 |.h01|.h11|.w0|.op0...|.h00|.h10|.dst.......|.src0......|.src1..|
3736 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3737 int op1
= ((iw0
>> (DSP32Mac_op1_bits
- 16)) & DSP32Mac_op1_mask
);
3738 int w1
= ((iw0
>> (DSP32Mac_w1_bits
- 16)) & DSP32Mac_w1_mask
);
3739 int P
= ((iw0
>> (DSP32Mac_p_bits
- 16)) & DSP32Mac_p_mask
);
3740 int MM
= ((iw0
>> (DSP32Mac_MM_bits
- 16)) & DSP32Mac_MM_mask
);
3741 int mmod
= ((iw0
>> (DSP32Mac_mmod_bits
- 16)) & DSP32Mac_mmod_mask
);
3742 int M
= ((iw0
>> (DSP32Mac_M_bits
- 16)) & DSP32Mac_M_mask
);
3743 int w0
= ((iw1
>> DSP32Mac_w0_bits
) & DSP32Mac_w0_mask
);
3744 int src0
= ((iw1
>> DSP32Mac_src0_bits
) & DSP32Mac_src0_mask
);
3745 int src1
= ((iw1
>> DSP32Mac_src1_bits
) & DSP32Mac_src1_mask
);
3746 int dst
= ((iw1
>> DSP32Mac_dst_bits
) & DSP32Mac_dst_mask
);
3747 int h10
= ((iw1
>> DSP32Mac_h10_bits
) & DSP32Mac_h10_mask
);
3748 int h00
= ((iw1
>> DSP32Mac_h00_bits
) & DSP32Mac_h00_mask
);
3749 int op0
= ((iw1
>> DSP32Mac_op0_bits
) & DSP32Mac_op0_mask
);
3750 int h11
= ((iw1
>> DSP32Mac_h11_bits
) & DSP32Mac_h11_mask
);
3751 int h01
= ((iw1
>> DSP32Mac_h01_bits
) & DSP32Mac_h01_mask
);
3753 bu32 res
= DREG (dst
);
3754 bu32 v_0
= 0, v_1
= 0, zero
= 0, n_1
= 0, n_0
= 0;
3756 static const char * const ops
[] = { "=", "+=", "-=" };
3757 char _buf
[128], *buf
= _buf
;
3760 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32mac
);
3761 TRACE_EXTRACT (cpu
, "%s: M:%i mmod:%i MM:%i P:%i w1:%i op1:%i h01:%i h11:%i "
3762 "w0:%i op0:%i h00:%i h10:%i dst:%i src0:%i src1:%i",
3763 __func__
, M
, mmod
, MM
, P
, w1
, op1
, h01
, h11
, w0
, op0
, h00
, h10
,
3766 if (w0
== 0 && w1
== 0 && op1
== 3 && op0
== 3)
3767 illegal_instruction (cpu
);
3769 if ((w1
|| w0
) && mmod
== M_W32
)
3770 illegal_instruction (cpu
);
3772 if (((1 << mmod
) & (P
? 0x131b : 0x1b5f)) == 0)
3773 illegal_instruction (cpu
);
3775 /* First handle MAC1 side. */
3776 if (w1
== 1 || op1
!= 3)
3778 bu32 res1
= decode_macfunc (cpu
, 1, op1
, h01
, h11
, src0
,
3779 src1
, mmod
, MM
, P
, &v_1
, &n_1
);
3782 buf
+= sprintf (buf
, P
? "R%i" : "R%i.H", dst
+ P
);
3786 buf
+= sprintf (buf
, " = A1");
3787 zero
= !!(res1
== 0);
3792 buf
+= sprintf (buf
, " = (");
3793 buf
+= sprintf (buf
, "A1 %s R%i.%c * R%i.%c", ops
[op1
],
3794 src0
, h01
? 'H' : 'L',
3795 src1
, h11
? 'H' : 'L');
3797 buf
+= sprintf (buf
, ")");
3803 STORE (DREG (dst
+ 1), res1
);
3806 if (res1
& 0xffff0000)
3807 illegal_instruction (cpu
);
3808 res
= REG_H_L (res1
<< 16, res
);
3814 if (w0
== 1 || op0
!= 3)
3817 buf
+= sprintf (buf
, " (M)");
3819 buf
+= sprintf (buf
, ", ");
3823 /* Then handle MAC0 side. */
3824 if (w0
== 1 || op0
!= 3)
3826 bu32 res0
= decode_macfunc (cpu
, 0, op0
, h00
, h10
, src0
,
3827 src1
, mmod
, 0, P
, &v_0
, &n_0
);
3830 buf
+= sprintf (buf
, P
? "R%i" : "R%i.L", dst
);
3834 buf
+= sprintf (buf
, " = A0");
3835 zero
|= !!(res0
== 0);
3840 buf
+= sprintf (buf
, " = (");
3841 buf
+= sprintf (buf
, "A0 %s R%i.%c * R%i.%c", ops
[op0
],
3842 src0
, h00
? 'H' : 'L',
3843 src1
, h10
? 'H' : 'L');
3845 buf
+= sprintf (buf
, ")");
3851 STORE (DREG (dst
), res0
);
3854 if (res0
& 0xffff0000)
3855 illegal_instruction (cpu
);
3856 res
= REG_H_L (res
, res0
);
3863 TRACE_INSN (cpu
, "%s%s;", _buf
, mac_optmode (mmod
, _MM
));
3865 if (!P
&& (w0
|| w1
))
3867 STORE (DREG (dst
), res
);
3868 SET_ASTATREG (v
, v_0
| v_1
);
3870 SET_ASTATREG (vs
, 1);
3874 SET_ASTATREG (v
, v_0
| v_1
);
3876 SET_ASTATREG (vs
, 1);
3879 if ((w0
== 1 && op0
== 3) || (w1
== 1 && op1
== 3))
3881 SET_ASTATREG (az
, zero
);
3882 if (!(w0
== 1 && op0
== 3))
3884 if (!(w1
== 1 && op1
== 3))
3886 SET_ASTATREG (an
, n_1
| n_0
);
3891 decode_dsp32mult_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3894 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3895 | 1 | 1 | 0 | 0 |.M.| 0 | 1 |.mmod..........|.MM|.P.|.w1|.op1...|
3896 |.h01|.h11|.w0|.op0...|.h00|.h10|.dst.......|.src0......|.src1..|
3897 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3898 int op1
= ((iw0
>> (DSP32Mac_op1_bits
- 16)) & DSP32Mac_op1_mask
);
3899 int w1
= ((iw0
>> (DSP32Mac_w1_bits
- 16)) & DSP32Mac_w1_mask
);
3900 int P
= ((iw0
>> (DSP32Mac_p_bits
- 16)) & DSP32Mac_p_mask
);
3901 int MM
= ((iw0
>> (DSP32Mac_MM_bits
- 16)) & DSP32Mac_MM_mask
);
3902 int mmod
= ((iw0
>> (DSP32Mac_mmod_bits
- 16)) & DSP32Mac_mmod_mask
);
3903 int M
= ((iw0
>> (DSP32Mac_M_bits
- 16)) & DSP32Mac_M_mask
);
3904 int w0
= ((iw1
>> DSP32Mac_w0_bits
) & DSP32Mac_w0_mask
);
3905 int src0
= ((iw1
>> DSP32Mac_src0_bits
) & DSP32Mac_src0_mask
);
3906 int src1
= ((iw1
>> DSP32Mac_src1_bits
) & DSP32Mac_src1_mask
);
3907 int dst
= ((iw1
>> DSP32Mac_dst_bits
) & DSP32Mac_dst_mask
);
3908 int h10
= ((iw1
>> DSP32Mac_h10_bits
) & DSP32Mac_h10_mask
);
3909 int h00
= ((iw1
>> DSP32Mac_h00_bits
) & DSP32Mac_h00_mask
);
3910 int op0
= ((iw1
>> DSP32Mac_op0_bits
) & DSP32Mac_op0_mask
);
3911 int h11
= ((iw1
>> DSP32Mac_h11_bits
) & DSP32Mac_h11_mask
);
3912 int h01
= ((iw1
>> DSP32Mac_h01_bits
) & DSP32Mac_h01_mask
);
3914 bu32 res
= DREG (dst
);
3915 bu32 sat0
= 0, sat1
= 0, v_i0
= 0, v_i1
= 0;
3916 char _buf
[128], *buf
= _buf
;
3919 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32mult
);
3920 TRACE_EXTRACT (cpu
, "%s: M:%i mmod:%i MM:%i P:%i w1:%i op1:%i h01:%i h11:%i "
3921 "w0:%i op0:%i h00:%i h10:%i dst:%i src0:%i src1:%i",
3922 __func__
, M
, mmod
, MM
, P
, w1
, op1
, h01
, h11
, w0
, op0
, h00
, h10
,
3925 if (w1
== 0 && w0
== 0)
3926 illegal_instruction (cpu
);
3927 if (((1 << mmod
) & (P
? 0x313 : 0x1b57)) == 0)
3928 illegal_instruction (cpu
);
3929 if (P
&& ((dst
& 1) || (op1
!= 0) || (op0
!= 0) || !is_macmod_pmove (mmod
)))
3930 illegal_instruction (cpu
);
3931 if (!P
&& ((op1
!= 0) || (op0
!= 0) || !is_macmod_hmove (mmod
)))
3932 illegal_instruction (cpu
);
3934 /* First handle MAC1 side. */
3937 bu64 r
= decode_multfunc (cpu
, h01
, h11
, src0
, src1
, mmod
, MM
, &sat1
);
3938 bu32 res1
= extract_mult (cpu
, r
, mmod
, MM
, P
, &v_i1
);
3940 buf
+= sprintf (buf
, P
? "R%i" : "R%i.H", dst
+ P
);
3941 buf
+= sprintf (buf
, " = R%i.%c * R%i.%c",
3942 src0
, h01
? 'H' : 'L',
3943 src1
, h11
? 'H' : 'L');
3947 buf
+= sprintf (buf
, " (M)");
3949 buf
+= sprintf (buf
, ", ");
3953 STORE (DREG (dst
+ 1), res1
);
3956 if (res1
& 0xFFFF0000)
3957 illegal_instruction (cpu
);
3958 res
= REG_H_L (res1
<< 16, res
);
3962 /* First handle MAC0 side. */
3965 bu64 r
= decode_multfunc (cpu
, h00
, h10
, src0
, src1
, mmod
, 0, &sat0
);
3966 bu32 res0
= extract_mult (cpu
, r
, mmod
, 0, P
, &v_i0
);
3968 buf
+= sprintf (buf
, P
? "R%i" : "R%i.L", dst
);
3969 buf
+= sprintf (buf
, " = R%i.%c * R%i.%c",
3970 src0
, h01
? 'H' : 'L',
3971 src1
, h11
? 'H' : 'L');
3974 STORE (DREG (dst
), res0
);
3977 if (res0
& 0xFFFF0000)
3978 illegal_instruction (cpu
);
3979 res
= REG_H_L (res
, res0
);
3983 TRACE_INSN (cpu
, "%s%s;", _buf
, mac_optmode (mmod
, _MM
));
3985 if (!P
&& (w0
|| w1
))
3986 STORE (DREG (dst
), res
);
3990 bu32 v
= sat0
| sat1
| v_i0
| v_i1
;
3992 STORE (ASTATREG (v
), v
);
3993 STORE (ASTATREG (v_copy
), v
);
3995 STORE (ASTATREG (vs
), v
);
4000 decode_dsp32alu_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
4003 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
4004 | 1 | 1 | 0 | 0 |.M.| 1 | 0 | - | - | - |.HL|.aopcde............|
4005 |.aop...|.s.|.x.|.dst0......|.dst1......|.src0......|.src1......|
4006 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
4007 int s
= ((iw1
>> DSP32Alu_s_bits
) & DSP32Alu_s_mask
);
4008 int x
= ((iw1
>> DSP32Alu_x_bits
) & DSP32Alu_x_mask
);
4009 int aop
= ((iw1
>> DSP32Alu_aop_bits
) & DSP32Alu_aop_mask
);
4010 int src0
= ((iw1
>> DSP32Alu_src0_bits
) & DSP32Alu_src0_mask
);
4011 int src1
= ((iw1
>> DSP32Alu_src1_bits
) & DSP32Alu_src1_mask
);
4012 int dst0
= ((iw1
>> DSP32Alu_dst0_bits
) & DSP32Alu_dst0_mask
);
4013 int dst1
= ((iw1
>> DSP32Alu_dst1_bits
) & DSP32Alu_dst1_mask
);
4014 int M
= ((iw0
>> (DSP32Alu_M_bits
- 16)) & DSP32Alu_M_mask
);
4015 int HL
= ((iw0
>> (DSP32Alu_HL_bits
- 16)) & DSP32Alu_HL_mask
);
4016 int aopcde
= ((iw0
>> (DSP32Alu_aopcde_bits
- 16)) & DSP32Alu_aopcde_mask
);
4018 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32alu
);
4019 TRACE_EXTRACT (cpu
, "%s: M:%i HL:%i aopcde:%i aop:%i s:%i x:%i dst0:%i "
4020 "dst1:%i src0:%i src1:%i",
4021 __func__
, M
, HL
, aopcde
, aop
, s
, x
, dst0
, dst1
, src0
, src1
);
4023 if ((aop
== 0 || aop
== 2) && aopcde
== 9 && HL
== 0 && s
== 0)
4026 TRACE_INSN (cpu
, "A%i.L = R%i.L;", a
, src0
);
4027 SET_AWREG (a
, REG_H_L (AWREG (a
), DREG (src0
)));
4029 else if ((aop
== 0 || aop
== 2) && aopcde
== 9 && HL
== 1 && s
== 0)
4032 TRACE_INSN (cpu
, "A%i.H = R%i.H;", a
, src0
);
4033 SET_AWREG (a
, REG_H_L (DREG (src0
), AWREG (a
)));
4035 else if ((aop
== 1 || aop
== 0) && aopcde
== 5)
4037 bs32 val0
= DREG (src0
);
4038 bs32 val1
= DREG (src1
);
4041 bs32 ovX
, sBit1
, sBit2
, sBitRes1
, sBitRes2
;
4043 TRACE_INSN (cpu
, "R%i.%s = R%i %s R%i (RND12)", dst0
, HL
? "L" : "H",
4044 src0
, aop
& 0x1 ? "-" : "+", src1
);
4046 /* If subtract, just invert and add one. */
4049 if (val1
== 0x80000000)
4055 /* Get the sign bits, since we need them later. */
4056 sBit1
= !!(val0
& 0x80000000);
4057 sBit2
= !!(val1
& 0x80000000);
4061 sBitRes1
= !!(res
& 0x80000000);
4062 /* Round to the 12th bit. */
4064 sBitRes2
= !!(res
& 0x80000000);
4072 positive_res + positive_round = neg
4073 Shift and upper 4 bits where not the same. */
4074 if ((!(sBit1
^ sBit2
) && (sBit1
^ sBitRes1
))
4075 || (!sBit1
&& !sBit2
&& sBitRes2
)
4076 || ((signRes
!= 0) && (signRes
!= -1)))
4078 /* Both X1 and X2 Neg res is neg overflow. */
4081 /* Both X1 and X2 Pos res is pos overflow. */
4082 else if (!sBit1
&& !sBit2
)
4084 /* Pos+Neg or Neg+Pos take the sign of the result. */
4094 /* Shift up now after overflow detection. */
4102 STORE (DREG (dst0
), REG_H_L (res
<< 16, DREG (dst0
)));
4104 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), res
));
4106 SET_ASTATREG (az
, res
== 0);
4107 SET_ASTATREG (an
, res
& 0x8000);
4108 SET_ASTATREG (v
, ovX
);
4110 SET_ASTATREG (vs
, ovX
);
4112 else if ((aop
== 2 || aop
== 3) && aopcde
== 5)
4114 bs32 val0
= DREG (src0
);
4115 bs32 val1
= DREG (src1
);
4118 TRACE_INSN (cpu
, "R%i.%s = R%i %s R%i (RND20)", dst0
, HL
? "L" : "H",
4119 src0
, aop
& 0x1 ? "-" : "+", src1
);
4121 /* If subtract, just invert and add one. */
4125 res
= (val0
>> 4) + (val1
>> 4) + (((val0
& 0xf) + (val1
& 0xf)) >> 4);
4127 /* Don't sign extend during the shift. */
4128 res
= ((bu32
)res
>> 16);
4130 /* Don't worry about overflows, since we are shifting right. */
4133 STORE (DREG (dst0
), REG_H_L (res
<< 16, DREG (dst0
)));
4135 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), res
));
4137 SET_ASTATREG (az
, res
== 0);
4138 SET_ASTATREG (an
, res
& 0x8000);
4139 SET_ASTATREG (v
, 0);
4141 else if (aopcde
== 2 || aopcde
== 3)
4143 bu32 s1
, s2
, val
, ac0_i
= 0, v_i
= 0;
4145 TRACE_INSN (cpu
, "R%i.%c = R%i.%c %c R%i.%c%s;",
4146 dst0
, HL
? 'H' : 'L',
4147 src0
, aop
& 2 ? 'H' : 'L',
4148 aopcde
== 2 ? '+' : '-',
4149 src1
, aop
& 1 ? 'H' : 'L',
4160 val
= add16 (cpu
, s1
, s2
, &ac0_i
, &v_i
, 0, 0, s
, 0);
4162 val
= sub16 (cpu
, s1
, s2
, &ac0_i
, &v_i
, 0, 0, s
, 0);
4164 SET_ASTATREG (ac0
, ac0_i
);
4165 SET_ASTATREG (v
, v_i
);
4167 SET_ASTATREG (vs
, v_i
);
4170 SET_DREG_H (dst0
, val
<< 16);
4172 SET_DREG_L (dst0
, val
);
4174 SET_ASTATREG (an
, val
& 0x8000);
4175 SET_ASTATREG (az
, val
== 0);
4177 else if ((aop
== 0 || aop
== 2) && aopcde
== 9 && s
== 1)
4180 TRACE_INSN (cpu
, "A%i = R%i;", a
, src0
);
4181 SET_AREG32 (a
, DREG (src0
));
4183 else if ((aop
== 1 || aop
== 3) && aopcde
== 9 && s
== 0)
4186 TRACE_INSN (cpu
, "A%i.X = R%i.L;", a
, src0
);
4187 SET_AXREG (a
, (bs8
)DREG (src0
));
4189 else if (aop
== 3 && aopcde
== 11 && (s
== 0 || s
== 1))
4191 bu64 acc0
= get_extended_acc (cpu
, 0);
4192 bu64 acc1
= get_extended_acc (cpu
, 1);
4193 bu32 carry
= (bu40
)acc1
< (bu40
)acc0
;
4196 TRACE_INSN (cpu
, "A0 -= A1%s;", s
? " (W32)" : "");
4199 if ((bs64
)acc0
< -0x8000000000ll
)
4200 acc0
= -0x8000000000ull
, sat
= 1;
4201 else if ((bs64
)acc0
>= 0x7fffffffffll
)
4202 acc0
= 0x7fffffffffull
, sat
= 1;
4206 /* A0 -= A1 (W32) */
4207 if (acc0
& (bu64
)0x8000000000ll
)
4208 acc0
&= 0x80ffffffffll
, sat
= 1;
4210 acc0
&= 0xffffffffll
;
4212 STORE (AXREG (0), (acc0
>> 32) & 0xff);
4213 STORE (AWREG (0), acc0
& 0xffffffff);
4214 STORE (ASTATREG (az
), acc0
== 0);
4215 STORE (ASTATREG (an
), !!(acc0
& (bu64
)0x8000000000ll
));
4216 STORE (ASTATREG (ac0
), carry
);
4217 STORE (ASTATREG (ac0_copy
), carry
);
4218 STORE (ASTATREG (av0
), sat
);
4220 STORE (ASTATREG (av0s
), sat
);
4222 else if ((aop
== 0 || aop
== 1) && aopcde
== 22)
4224 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4226 const char * const opts
[] = { "rndl", "rndh", "tl", "th" };
4228 TRACE_INSN (cpu
, "R%i = BYTEOP2P (R%i:%i, R%i:%i) (%s%s);", dst0
,
4229 src0
+ 1, src0
, src1
+ 1, src1
, opts
[HL
+ (aop
<< 1)],
4233 s0H
= DREG (src0
+ 1);
4235 s1H
= DREG (src1
+ 1);
4238 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4239 s1
= algn (s1H
, s1L
, IREG (0) & 3);
4243 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4244 s1
= algn (s1L
, s1H
, IREG (0) & 3);
4248 tmp0
= ((((s1
>> 8) & 0xff) + ((s1
>> 0) & 0xff) +
4249 ((s0
>> 8) & 0xff) + ((s0
>> 0) & 0xff) + i
) >> 2) & 0xff;
4250 tmp1
= ((((s1
>> 24) & 0xff) + ((s1
>> 16) & 0xff) +
4251 ((s0
>> 24) & 0xff) + ((s0
>> 16) & 0xff) + i
) >> 2) & 0xff;
4252 STORE (DREG (dst0
), (tmp1
<< (16 + (HL
* 8))) | (tmp0
<< (HL
* 8)));
4254 /* Implicit DISALGNEXCPT in parallel. */
4257 else if ((aop
== 0 || aop
== 1) && s
== 0 && aopcde
== 8)
4259 TRACE_INSN (cpu
, "A%i = 0;", aop
);
4262 else if (aop
== 2 && s
== 0 && aopcde
== 8)
4264 TRACE_INSN (cpu
, "A1 = A0 = 0;");
4268 else if ((aop
== 0 || aop
== 1 || aop
== 2) && s
== 1 && aopcde
== 8)
4270 bs40 acc0
= get_extended_acc (cpu
, 0);
4271 bs40 acc1
= get_extended_acc (cpu
, 1);
4274 if (aop
== 0 || aop
== 1)
4275 TRACE_INSN (cpu
, "A%i = A%i (S);", aop
, aop
);
4277 TRACE_INSN (cpu
, "A1 = A1 (S), A0 = A0 (S);");
4279 if (aop
== 0 || aop
== 2)
4282 acc0
= saturate_s32 (acc0
, &sat
);
4283 acc0
|= -(acc0
& 0x80000000ull
);
4284 SET_AXREG (0, (acc0
>> 31) & 0xFF);
4285 SET_AWREG (0, acc0
& 0xFFFFFFFF);
4286 SET_ASTATREG (av0
, sat
);
4288 SET_ASTATREG (av0s
, sat
);
4293 if (aop
== 1 || aop
== 2)
4296 acc1
= saturate_s32 (acc1
, &sat
);
4297 acc1
|= -(acc1
& 0x80000000ull
);
4298 SET_AXREG (1, (acc1
>> 31) & 0xFF);
4299 SET_AWREG (1, acc1
& 0xFFFFFFFF);
4300 SET_ASTATREG (av1
, sat
);
4302 SET_ASTATREG (av1s
, sat
);
4307 SET_ASTATREG (az
, (acc0
== 0) || (acc1
== 0));
4308 SET_ASTATREG (an
, ((acc0
>> 31) & 1) || ((acc1
>> 31) & 1));
4310 else if (aop
== 3 && (s
== 0 || s
== 1) && aopcde
== 8)
4312 TRACE_INSN (cpu
, "A%i = A%i;", s
, !s
);
4313 SET_AXREG (s
, AXREG (!s
));
4314 SET_AWREG (s
, AWREG (!s
));
4316 else if (aop
== 3 && HL
== 0 && aopcde
== 16)
4321 TRACE_INSN (cpu
, "A1 = ABS A1 , A0 = ABS A0;");
4324 for (i
= 0; i
< 2; ++i
)
4327 bs40 acc
= get_extended_acc (cpu
, i
);
4331 av
= acc
== ((bs40
)1 << 39);
4333 acc
= ((bs40
)1 << 39) - 1;
4336 SET_ASTATREG (av
[i
], av
);
4338 SET_ASTATREG (avs
[i
], av
);
4341 SET_ASTATREG (az
, az
);
4342 SET_ASTATREG (an
, 0);
4344 else if (aop
== 0 && aopcde
== 23)
4346 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4349 TRACE_INSN (cpu
, "R%i = BYTEOP3P (R%i:%i, R%i:%i) (%s%s);", dst0
,
4350 src0
+ 1, src0
, src1
+ 1, src1
, HL
? "HI" : "LO",
4354 s0H
= DREG (src0
+ 1);
4356 s1H
= DREG (src1
+ 1);
4359 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4360 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4364 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4365 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4368 tmp0
= (bs32
)(bs16
)(s0
>> 0) + ((s1
>> ( 0 + (8 * !HL
))) & 0xff);
4369 tmp1
= (bs32
)(bs16
)(s0
>> 16) + ((s1
>> (16 + (8 * !HL
))) & 0xff);
4370 STORE (DREG (dst0
), (CLAMP (tmp0
, 0, 255) << ( 0 + (8 * HL
))) |
4371 (CLAMP (tmp1
, 0, 255) << (16 + (8 * HL
))));
4373 /* Implicit DISALGNEXCPT in parallel. */
4376 else if ((aop
== 0 || aop
== 1) && aopcde
== 16)
4381 TRACE_INSN (cpu
, "A%i = ABS A%i;", HL
, aop
);
4383 acc
= get_extended_acc (cpu
, aop
);
4386 av
= acc
== ((bs40
)1 << 39);
4388 acc
= ((bs40
)1 << 39) - 1;
4391 SET_ASTATREG (av
[HL
], av
);
4393 SET_ASTATREG (avs
[HL
], av
);
4394 SET_ASTATREG (az
, acc
== 0);
4395 SET_ASTATREG (an
, 0);
4397 else if (aop
== 3 && aopcde
== 12)
4399 bs32 res
= DREG (src0
);
4401 bool sBit_a
, sBit_b
;
4403 TRACE_INSN (cpu
, "R%i.%s = R%i (RND);", dst0
, HL
== 0 ? "L" : "H", src0
);
4404 TRACE_DECODE (cpu
, "R%i.%s = R%i:%#x (RND);", dst0
,
4405 HL
== 0 ? "L" : "H", src0
, res
);
4407 sBit_b
= !!(res
& 0x80000000);
4410 sBit_a
= !!(res
& 0x80000000);
4412 /* Overflow if the sign bit changed when we rounded. */
4413 if ((res
>> 16) && (sBit_b
!= sBit_a
))
4428 SET_DREG (dst0
, REG_H_L (DREG (dst0
), res
));
4430 SET_DREG (dst0
, REG_H_L (res
<< 16, DREG (dst0
)));
4432 SET_ASTATREG (az
, res
== 0);
4433 SET_ASTATREG (an
, res
< 0);
4434 SET_ASTATREG (v
, ovX
);
4436 SET_ASTATREG (vs
, ovX
);
4438 else if (aop
== 3 && HL
== 0 && aopcde
== 15)
4440 bu32 hi
= (-(bs16
)(DREG (src0
) >> 16)) << 16;
4441 bu32 lo
= (-(bs16
)(DREG (src0
) & 0xFFFF)) & 0xFFFF;
4444 TRACE_INSN (cpu
, "R%i = -R%i (V);", dst0
, src0
);
4448 if (hi
== 0x80000000)
4464 SET_DREG (dst0
, hi
| lo
);
4466 SET_ASTATREG (v
, v
);
4468 SET_ASTATREG (vs
, 1);
4469 SET_ASTATREG (ac0
, ac0
);
4470 SET_ASTATREG (ac1
, ac1
);
4471 setflags_nz_2x16 (cpu
, DREG (dst0
));
4473 else if (aop
== 3 && HL
== 0 && aopcde
== 14)
4475 TRACE_INSN (cpu
, "A1 = - A1 , A0 = - A0;");
4477 SET_AREG (0, saturate_s40 (-get_extended_acc (cpu
, 0)));
4478 SET_AREG (1, saturate_s40 (-get_extended_acc (cpu
, 1)));
4479 /* XXX: what ASTAT flags need updating ? */
4481 else if ((aop
== 0 || aop
== 1) && (HL
== 0 || HL
== 1) && aopcde
== 14)
4483 bs40 src_acc
= get_extended_acc (cpu
, aop
);
4486 TRACE_INSN (cpu
, "A%i = - A%i;", HL
, aop
);
4488 SET_AREG (HL
, saturate_s40_astat (-src_acc
, &v
));
4490 SET_ASTATREG (az
, AWREG (HL
) == 0 && AXREG (HL
) == 0);
4491 SET_ASTATREG (an
, AXREG (HL
) >> 7);
4494 SET_ASTATREG (ac0
, !src_acc
);
4495 SET_ASTATREG (av0
, v
);
4497 SET_ASTATREG (av0s
, 1);
4501 SET_ASTATREG (ac1
, !src_acc
);
4502 SET_ASTATREG (av1
, v
);
4504 SET_ASTATREG (av1s
, 1);
4507 else if (aop
== 0 && aopcde
== 12)
4509 bs16 tmp0_hi
= DREG (src0
) >> 16;
4510 bs16 tmp0_lo
= DREG (src0
);
4511 bs16 tmp1_hi
= DREG (src1
) >> 16;
4512 bs16 tmp1_lo
= DREG (src1
);
4514 TRACE_INSN (cpu
, "R%i.L = R%i.H = SIGN(R%i.H) * R%i.H + SIGN(R%i.L) * R%i.L;",
4515 dst0
, dst0
, src0
, src1
, src0
, src1
);
4517 if ((tmp0_hi
>> 15) & 1)
4518 tmp1_hi
= ~tmp1_hi
+ 1;
4520 if ((tmp0_lo
>> 15) & 1)
4521 tmp1_lo
= ~tmp1_lo
+ 1;
4523 tmp1_hi
= tmp1_hi
+ tmp1_lo
;
4525 STORE (DREG (dst0
), REG_H_L (tmp1_hi
<< 16, tmp1_hi
));
4527 else if (aopcde
== 0)
4529 bu32 s0
= DREG (src0
);
4530 bu32 s1
= DREG (src1
);
4531 bu32 s0h
= s0
>> 16;
4532 bu32 s0l
= s0
& 0xFFFF;
4533 bu32 s1h
= s1
>> 16;
4534 bu32 s1l
= s1
& 0xFFFF;
4536 bu32 ac1_i
= 0, ac0_i
= 0, v_i
= 0, z_i
= 0, n_i
= 0;
4538 TRACE_INSN (cpu
, "R%i = R%i %c|%c R%i%s;", dst0
, src0
,
4539 (aop
& 2) ? '-' : '+', (aop
& 1) ? '-' : '+', src1
,
4542 t0
= sub16 (cpu
, s0h
, s1h
, &ac1_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4544 t0
= add16 (cpu
, s0h
, s1h
, &ac1_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4547 t1
= sub16 (cpu
, s0l
, s1l
, &ac0_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4549 t1
= add16 (cpu
, s0l
, s1l
, &ac0_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4551 SET_ASTATREG (ac1
, ac1_i
);
4552 SET_ASTATREG (ac0
, ac0_i
);
4553 SET_ASTATREG (az
, z_i
);
4554 SET_ASTATREG (an
, n_i
);
4555 SET_ASTATREG (v
, v_i
);
4557 SET_ASTATREG (vs
, v_i
);
4562 SET_DREG (dst0
, (t1
<< 16) | t0
);
4564 SET_DREG (dst0
, (t0
<< 16) | t1
);
4566 else if (aop
== 1 && aopcde
== 12)
4568 bs32 val0
= (bs16
)(AWREG (0) >> 16) + (bs16
)AWREG (0);
4569 bs32 val1
= (bs16
)(AWREG (1) >> 16) + (bs16
)AWREG (1);
4571 TRACE_INSN (cpu
, "R%i = A1.L + A1.H, R%i = A0.L + A0.H;", dst1
, dst0
);
4574 illegal_instruction_combination (cpu
);
4576 SET_DREG (dst0
, val0
);
4577 SET_DREG (dst1
, val1
);
4579 else if (aopcde
== 1)
4583 bu16 s0L
= DREG (src0
);
4584 bu16 s0H
= DREG (src0
) >> 16;
4585 bu16 s1L
= DREG (src1
);
4586 bu16 s1H
= DREG (src1
) >> 16;
4587 bu32 v_i
= 0, n_i
= 0, z_i
= 0;
4589 TRACE_INSN (cpu
, "R%i = R%i %s R%i, R%i = R%i %s R%i%s;",
4590 dst1
, src0
, HL
? "+|-" : "+|+", src1
,
4591 dst0
, src0
, HL
? "-|+" : "-|-", src1
,
4592 amod0amod2 (s
, x
, aop
));
4595 illegal_instruction_combination (cpu
);
4599 x0
= add16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4600 x1
= add16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4601 d1
= (x0
<< 16) | x1
;
4603 x0
= sub16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4604 x1
= sub16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4606 d0
= (x0
<< 16) | x1
;
4608 d0
= (x1
<< 16) | x0
;
4612 x0
= add16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4613 x1
= sub16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4614 d1
= (x0
<< 16) | x1
;
4616 x0
= sub16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4617 x1
= add16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4619 d0
= (x0
<< 16) | x1
;
4621 d0
= (x1
<< 16) | x0
;
4623 SET_ASTATREG (az
, z_i
);
4624 SET_ASTATREG (an
, n_i
);
4625 SET_ASTATREG (v
, v_i
);
4627 SET_ASTATREG (vs
, v_i
);
4629 STORE (DREG (dst0
), d0
);
4630 STORE (DREG (dst1
), d1
);
4632 else if ((aop
== 0 || aop
== 1 || aop
== 2) && aopcde
== 11)
4634 bs40 acc0
= get_extended_acc (cpu
, 0);
4635 bs40 acc1
= get_extended_acc (cpu
, 1);
4636 bu32 v
, dreg
, sat
= 0;
4637 bu32 carry
= !!((bu40
)~acc1
< (bu40
)acc0
);
4640 TRACE_INSN (cpu
, "R%i = (A0 += A1);", dst0
);
4642 TRACE_INSN (cpu
, "R%i.%c = (A0 += A1);", dst0
, HL
? 'H' : 'L');
4644 TRACE_INSN (cpu
, "A0 += A1%s;", s
? " (W32)" : "");
4647 acc0
= saturate_s40_astat (acc0
, &v
);
4649 if (aop
== 2 && s
== 1) /* A0 += A1 (W32) */
4651 if (acc0
& (bs40
)0x8000000000ll
)
4652 acc0
&= 0x80ffffffffll
;
4654 acc0
&= 0xffffffffll
;
4657 STORE (AXREG (0), acc0
>> 32);
4658 STORE (AWREG (0), acc0
);
4659 SET_ASTATREG (av0
, v
&& acc1
);
4661 SET_ASTATREG (av0s
, v
);
4663 if (aop
== 0 || aop
== 1)
4665 if (aop
) /* Dregs_lo = A0 += A1 */
4667 dreg
= saturate_s32 (rnd16 (acc0
) << 16, &sat
);
4669 STORE (DREG (dst0
), REG_H_L (dreg
, DREG (dst0
)));
4671 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), dreg
>> 16));
4673 else /* Dregs = A0 += A1 */
4675 dreg
= saturate_s32 (acc0
, &sat
);
4676 STORE (DREG (dst0
), dreg
);
4679 STORE (ASTATREG (az
), dreg
== 0);
4680 STORE (ASTATREG (an
), !!(dreg
& 0x80000000));
4681 STORE (ASTATREG (ac0
), carry
);
4682 STORE (ASTATREG (ac0_copy
), carry
);
4683 STORE (ASTATREG (v
), sat
);
4684 STORE (ASTATREG (v_copy
), sat
);
4686 STORE (ASTATREG (vs
), sat
);
4690 STORE (ASTATREG (az
), acc0
== 0);
4691 STORE (ASTATREG (an
), !!(acc0
& 0x8000000000ull
));
4692 STORE (ASTATREG (ac0
), carry
);
4693 STORE (ASTATREG (ac0_copy
), carry
);
4696 else if ((aop
== 0 || aop
== 1) && aopcde
== 10)
4698 TRACE_INSN (cpu
, "R%i.L = A%i.X;", dst0
, aop
);
4699 SET_DREG_L (dst0
, (bs8
)AXREG (aop
));
4701 else if (aop
== 0 && aopcde
== 4)
4703 TRACE_INSN (cpu
, "R%i = R%i + R%i%s;", dst0
, src0
, src1
, amod1 (s
, x
));
4704 SET_DREG (dst0
, add32 (cpu
, DREG (src0
), DREG (src1
), 1, s
));
4706 else if (aop
== 1 && aopcde
== 4)
4708 TRACE_INSN (cpu
, "R%i = R%i - R%i%s;", dst0
, src0
, src1
, amod1 (s
, x
));
4709 SET_DREG (dst0
, sub32 (cpu
, DREG (src0
), DREG (src1
), 1, s
, 0));
4711 else if (aop
== 2 && aopcde
== 4)
4713 TRACE_INSN (cpu
, "R%i = R%i + R%i, R%i = R%i - R%i%s;",
4714 dst1
, src0
, src1
, dst0
, src0
, src1
, amod1 (s
, x
));
4717 illegal_instruction_combination (cpu
);
4719 STORE (DREG (dst1
), add32 (cpu
, DREG (src0
), DREG (src1
), 1, s
));
4720 STORE (DREG (dst0
), sub32 (cpu
, DREG (src0
), DREG (src1
), 1, s
, 1));
4722 else if ((aop
== 0 || aop
== 1) && aopcde
== 17)
4724 bs40 acc0
= get_extended_acc (cpu
, 0);
4725 bs40 acc1
= get_extended_acc (cpu
, 1);
4726 bs40 val0
, val1
, sval0
, sval1
;
4729 TRACE_INSN (cpu
, "R%i = A%i + A%i, R%i = A%i - A%i%s",
4730 dst1
, !aop
, aop
, dst0
, !aop
, aop
, amod1 (s
, x
));
4731 TRACE_DECODE (cpu
, "R%i = A%i:%#"PRIx64
" + A%i:%#"PRIx64
", "
4732 "R%i = A%i:%#"PRIx64
" - A%i:%#"PRIx64
"%s",
4733 dst1
, !aop
, aop
? acc0
: acc1
, aop
, aop
? acc1
: acc0
,
4734 dst0
, !aop
, aop
? acc0
: acc1
, aop
, aop
? acc1
: acc0
,
4738 illegal_instruction_combination (cpu
);
4746 sval0
= saturate_s32 (val0
, &sat
);
4748 sval1
= saturate_s32 (val1
, &sat
);
4756 STORE (DREG (dst0
), val0
);
4757 STORE (DREG (dst1
), val1
);
4758 SET_ASTATREG (v
, sat_i
);
4760 SET_ASTATREG (vs
, sat_i
);
4761 SET_ASTATREG (an
, val0
& 0x80000000 || val1
& 0x80000000);
4762 SET_ASTATREG (az
, val0
== 0 || val1
== 0);
4763 SET_ASTATREG (ac1
, (bu40
)~acc0
< (bu40
)acc1
);
4765 SET_ASTATREG (ac0
, !!((bu40
)acc1
<= (bu40
)acc0
));
4767 SET_ASTATREG (ac0
, !!((bu40
)acc0
<= (bu40
)acc1
));
4769 else if (aop
== 0 && aopcde
== 18)
4771 bu40 acc0
= get_extended_acc (cpu
, 0);
4772 bu40 acc1
= get_extended_acc (cpu
, 1);
4773 bu32 s0L
= DREG (src0
);
4774 bu32 s0H
= DREG (src0
+ 1);
4775 bu32 s1L
= DREG (src1
);
4776 bu32 s1H
= DREG (src1
+ 1);
4778 bs16 tmp0
, tmp1
, tmp2
, tmp3
;
4780 /* This instruction is only defined for register pairs R1:0 and R3:2. */
4781 if (!((src0
== 0 || src0
== 2) && (src1
== 0 || src1
== 2)))
4782 illegal_instruction (cpu
);
4784 TRACE_INSN (cpu
, "SAA (R%i:%i, R%i:%i)%s", src0
+ 1, src0
,
4785 src1
+ 1, src1
, s
? " (R)" :"");
4787 /* Bit s determines the order of the two registers from a pair:
4788 if s=0 the low-order bytes come from the low reg in the pair,
4789 and if s=1 the low-order bytes come from the high reg. */
4793 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4794 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4798 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4799 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4802 /* Find the absolute difference between pairs, make it
4803 absolute, then add it to the existing accumulator half. */
4805 tmp0
= ((s0
<< 24) >> 24) - ((s1
<< 24) >> 24);
4806 tmp1
= ((s0
<< 16) >> 24) - ((s1
<< 16) >> 24);
4807 tmp2
= ((s0
<< 8) >> 24) - ((s1
<< 8) >> 24);
4808 tmp3
= ((s0
<< 0) >> 24) - ((s1
<< 0) >> 24);
4810 tmp0
= (tmp0
< 0) ? -tmp0
: tmp0
;
4811 tmp1
= (tmp1
< 0) ? -tmp1
: tmp1
;
4812 tmp2
= (tmp2
< 0) ? -tmp2
: tmp2
;
4813 tmp3
= (tmp3
< 0) ? -tmp3
: tmp3
;
4815 s0L
= saturate_u16 ((bu32
)tmp0
+ ((acc0
>> 0) & 0xffff), 0);
4816 s0H
= saturate_u16 ((bu32
)tmp1
+ ((acc0
>> 16) & 0xffff), 0);
4817 s1L
= saturate_u16 ((bu32
)tmp2
+ ((acc1
>> 0) & 0xffff), 0);
4818 s1H
= saturate_u16 ((bu32
)tmp3
+ ((acc1
>> 16) & 0xffff), 0);
4820 STORE (AWREG (0), (s0H
<< 16) | (s0L
& 0xFFFF));
4821 STORE (AXREG (0), 0);
4822 STORE (AWREG (1), (s1H
<< 16) | (s1L
& 0xFFFF));
4823 STORE (AXREG (1), 0);
4825 /* Implicit DISALGNEXCPT in parallel. */
4828 else if (aop
== 3 && aopcde
== 18)
4830 TRACE_INSN (cpu
, "DISALGNEXCPT");
4833 else if ((aop
== 0 || aop
== 1) && aopcde
== 20)
4835 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4836 const char * const opts
[] = { "", " (R)", " (T)", " (T, R)" };
4838 TRACE_INSN (cpu
, "R%i = BYTEOP1P (R%i:%i, R%i:%i)%s;", dst0
,
4839 src0
+ 1, src0
, src1
+ 1, src1
, opts
[s
+ (aop
<< 1)]);
4842 s0H
= DREG (src0
+ 1);
4844 s1H
= DREG (src1
+ 1);
4847 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4848 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4852 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4853 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4857 (((((s0
>> 0) & 0xff) + ((s1
>> 0) & 0xff) + !aop
) >> 1) << 0) |
4858 (((((s0
>> 8) & 0xff) + ((s1
>> 8) & 0xff) + !aop
) >> 1) << 8) |
4859 (((((s0
>> 16) & 0xff) + ((s1
>> 16) & 0xff) + !aop
) >> 1) << 16) |
4860 (((((s0
>> 24) & 0xff) + ((s1
>> 24) & 0xff) + !aop
) >> 1) << 24));
4862 /* Implicit DISALGNEXCPT in parallel. */
4865 else if (aop
== 0 && aopcde
== 21)
4867 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4869 TRACE_INSN (cpu
, "(R%i, R%i) = BYTEOP16P (R%i:%i, R%i:%i)%s;", dst1
, dst0
,
4870 src0
+ 1, src0
, src1
+ 1, src1
, s
? " (R)" : "");
4873 illegal_instruction_combination (cpu
);
4876 s0H
= DREG (src0
+ 1);
4878 s1H
= DREG (src1
+ 1);
4881 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4882 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4886 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4887 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4891 ((((s0
>> 0) & 0xff) + ((s1
>> 0) & 0xff)) << 0) |
4892 ((((s0
>> 8) & 0xff) + ((s1
>> 8) & 0xff)) << 16));
4894 ((((s0
>> 16) & 0xff) + ((s1
>> 16) & 0xff)) << 0) |
4895 ((((s0
>> 24) & 0xff) + ((s1
>> 24) & 0xff)) << 16));
4897 /* Implicit DISALGNEXCPT in parallel. */
4900 else if (aop
== 1 && aopcde
== 21)
4902 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4904 TRACE_INSN (cpu
, "(R%i, R%i) = BYTEOP16M (R%i:%i, R%i:%i)%s;", dst1
, dst0
,
4905 src0
+ 1, src0
, src1
+ 1, src1
, s
? " (R)" : "");
4908 illegal_instruction_combination (cpu
);
4911 s0H
= DREG (src0
+ 1);
4913 s1H
= DREG (src1
+ 1);
4916 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4917 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4921 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4922 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4926 (((((s0
>> 0) & 0xff) - ((s1
>> 0) & 0xff)) << 0) & 0xffff) |
4927 (((((s0
>> 8) & 0xff) - ((s1
>> 8) & 0xff)) << 16)));
4929 (((((s0
>> 16) & 0xff) - ((s1
>> 16) & 0xff)) << 0) & 0xffff) |
4930 (((((s0
>> 24) & 0xff) - ((s1
>> 24) & 0xff)) << 16)));
4932 /* Implicit DISALGNEXCPT in parallel. */
4935 else if (aop
== 1 && aopcde
== 7)
4937 TRACE_INSN (cpu
, "R%i = MIN (R%i, R%i);", dst0
, src0
, src1
);
4938 SET_DREG (dst0
, min32 (cpu
, DREG (src0
), DREG (src1
)));
4940 else if (aop
== 0 && aopcde
== 7)
4942 TRACE_INSN (cpu
, "R%i = MAX (R%i, R%i);", dst0
, src0
, src1
);
4943 SET_DREG (dst0
, max32 (cpu
, DREG (src0
), DREG (src1
)));
4945 else if (aop
== 2 && aopcde
== 7)
4947 bu32 val
= DREG (src0
);
4950 TRACE_INSN (cpu
, "R%i = ABS R%i;", dst0
, src0
);
4954 v
= (val
== 0x80000000);
4957 SET_DREG (dst0
, val
);
4959 SET_ASTATREG (v
, v
);
4961 SET_ASTATREG (vs
, 1);
4962 setflags_nz (cpu
, val
);
4964 else if (aop
== 3 && aopcde
== 7)
4966 bu32 val
= DREG (src0
);
4968 TRACE_INSN (cpu
, "R%i = - R%i %s;", dst0
, src0
, amod1 (s
, 0));
4970 if (s
&& val
== 0x80000000)
4973 SET_ASTATREG (v
, 1);
4974 SET_ASTATREG (vs
, 1);
4976 else if (val
== 0x80000000)
4980 SET_DREG (dst0
, val
);
4982 SET_ASTATREG (az
, val
== 0);
4983 SET_ASTATREG (an
, val
& 0x80000000);
4985 else if (aop
== 2 && aopcde
== 6)
4987 bu32 in
= DREG (src0
);
4988 bu32 hi
= (in
& 0x80000000 ? (bu32
)-(bs16
)(in
>> 16) : in
>> 16) << 16;
4989 bu32 lo
= (in
& 0x8000 ? (bu32
)-(bs16
)(in
& 0xFFFF) : in
) & 0xFFFF;
4992 TRACE_INSN (cpu
, "R%i = ABS R%i (V);", dst0
, src0
);
4995 if (hi
== 0x80000000)
5005 SET_DREG (dst0
, hi
| lo
);
5007 SET_ASTATREG (v
, v
);
5009 SET_ASTATREG (vs
, 1);
5010 setflags_nz_2x16 (cpu
, DREG (dst0
));
5012 else if (aop
== 1 && aopcde
== 6)
5014 TRACE_INSN (cpu
, "R%i = MIN (R%i, R%i) (V);", dst0
, src0
, src1
);
5015 SET_DREG (dst0
, min2x16 (cpu
, DREG (src0
), DREG (src1
)));
5017 else if (aop
== 0 && aopcde
== 6)
5019 TRACE_INSN (cpu
, "R%i = MAX (R%i, R%i) (V);", dst0
, src0
, src1
);
5020 SET_DREG (dst0
, max2x16 (cpu
, DREG (src0
), DREG (src1
)));
5022 else if (aop
== 0 && aopcde
== 24)
5024 TRACE_INSN (cpu
, "R%i = BYTEPACK (R%i, R%i);", dst0
, src0
, src1
);
5026 (((DREG (src0
) >> 0) & 0xff) << 0) |
5027 (((DREG (src0
) >> 16) & 0xff) << 8) |
5028 (((DREG (src1
) >> 0) & 0xff) << 16) |
5029 (((DREG (src1
) >> 16) & 0xff) << 24));
5031 /* Implicit DISALGNEXCPT in parallel. */
5034 else if (aop
== 1 && aopcde
== 24)
5038 bu8 bytea
, byteb
, bytec
, byted
;
5040 TRACE_INSN (cpu
, "(R%i, R%i) = BYTEUNPACK R%i:%i%s;",
5041 dst1
, dst0
, src0
+ 1, src0
, s
? " (R)" : "");
5044 illegal_instruction_combination (cpu
);
5046 order
= IREG (0) & 0x3;
5048 hi
= src0
, lo
= src0
+ 1;
5050 hi
= src0
+ 1, lo
= src0
;
5051 comb_src
= (((bu64
)DREG (hi
)) << 32) | DREG (lo
);
5052 bytea
= (comb_src
>> (0 + 8 * order
));
5053 byteb
= (comb_src
>> (8 + 8 * order
));
5054 bytec
= (comb_src
>> (16 + 8 * order
));
5055 byted
= (comb_src
>> (24 + 8 * order
));
5056 STORE (DREG (dst0
), bytea
| ((bu32
)byteb
<< 16));
5057 STORE (DREG (dst1
), bytec
| ((bu32
)byted
<< 16));
5059 /* Implicit DISALGNEXCPT in parallel. */
5062 else if (aopcde
== 13)
5064 const char *searchmodes
[] = { "GT", "GE", "LT", "LE" };
5066 bs16 a0_lo
, a1_lo
, src_hi
, src_lo
;
5068 TRACE_INSN (cpu
, "(R%i, R%i) = SEARCH R%i (%s);",
5069 dst1
, dst0
, src0
, searchmodes
[aop
]);
5072 illegal_instruction_combination (cpu
);
5074 up_hi
= up_lo
= false;
5077 src_lo
= DREG (src0
);
5078 src_hi
= DREG (src0
) >> 16;
5083 up_hi
= (src_hi
> a1_lo
);
5084 up_lo
= (src_lo
> a0_lo
);
5087 up_hi
= (src_hi
>= a1_lo
);
5088 up_lo
= (src_lo
>= a0_lo
);
5091 up_hi
= (src_hi
< a1_lo
);
5092 up_lo
= (src_lo
< a0_lo
);
5095 up_hi
= (src_hi
<= a1_lo
);
5096 up_lo
= (src_lo
<= a0_lo
);
5102 SET_AREG (1, src_hi
);
5103 SET_DREG (dst1
, PREG (0));
5106 SET_AREG (1, a1_lo
);
5110 SET_AREG (0, src_lo
);
5111 SET_DREG (dst0
, PREG (0));
5114 SET_AREG (0, a0_lo
);
5117 illegal_instruction (cpu
);
5121 decode_dsp32shift_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
5124 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5125 | 1 | 1 | 0 | 0 |.M.| 1 | 1 | 0 | 0 | - | - |.sopcde............|
5126 |.sop...|.HLs...|.dst0......| - | - | - |.src0......|.src1......|
5127 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5128 int HLs
= ((iw1
>> DSP32Shift_HLs_bits
) & DSP32Shift_HLs_mask
);
5129 int sop
= ((iw1
>> DSP32Shift_sop_bits
) & DSP32Shift_sop_mask
);
5130 int src0
= ((iw1
>> DSP32Shift_src0_bits
) & DSP32Shift_src0_mask
);
5131 int src1
= ((iw1
>> DSP32Shift_src1_bits
) & DSP32Shift_src1_mask
);
5132 int dst0
= ((iw1
>> DSP32Shift_dst0_bits
) & DSP32Shift_dst0_mask
);
5133 int sopcde
= ((iw0
>> (DSP32Shift_sopcde_bits
- 16)) & DSP32Shift_sopcde_mask
);
5134 int M
= ((iw0
>> (DSP32Shift_M_bits
- 16)) & DSP32Shift_M_mask
);
5136 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32shift
);
5137 TRACE_EXTRACT (cpu
, "%s: M:%i sopcde:%i sop:%i HLs:%i dst0:%i src0:%i src1:%i",
5138 __func__
, M
, sopcde
, sop
, HLs
, dst0
, src0
, src1
);
5140 if ((sop
== 0 || sop
== 1) && sopcde
== 0)
5143 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5145 TRACE_INSN (cpu
, "R%i.%c = ASHIFT R%i.%c BY R%i.L%s;",
5146 dst0
, HLs
< 2 ? 'L' : 'H',
5147 src1
, HLs
& 1 ? 'H' : 'L',
5148 src0
, sop
== 1 ? " (S)" : "");
5151 val
= (bu16
)(DREG (src1
) & 0xFFFF);
5153 val
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5155 /* Positive shift magnitudes produce Logical Left shifts.
5156 Negative shift magnitudes produce Arithmetic Right shifts. */
5158 val
= ashiftrt (cpu
, val
, -shft
, 16);
5160 val
= lshift (cpu
, val
, shft
, 16, sop
== 1, 1);
5163 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), val
));
5165 STORE (DREG (dst0
), REG_H_L (val
<< 16, DREG (dst0
)));
5167 else if (sop
== 2 && sopcde
== 0)
5169 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5172 TRACE_INSN (cpu
, "R%i.%c = LSHIFT R%i.%c BY R%i.L;",
5173 dst0
, HLs
< 2 ? 'L' : 'H',
5174 src1
, HLs
& 1 ? 'H' : 'L', src0
);
5177 val
= (bu16
)(DREG (src1
) & 0xFFFF);
5179 val
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5182 val
= val
>> (-1 * shft
);
5187 SET_DREG (dst0
, REG_H_L (DREG (dst0
), val
));
5189 SET_DREG (dst0
, REG_H_L (val
<< 16, DREG (dst0
)));
5191 SET_ASTATREG (az
, !((val
& 0xFFFF0000) == 0) || ((val
& 0xFFFF) == 0));
5192 SET_ASTATREG (an
, (!!(val
& 0x80000000)) ^ (!!(val
& 0x8000)));
5193 SET_ASTATREG (v
, 0);
5195 else if (sop
== 2 && sopcde
== 3 && (HLs
== 1 || HLs
== 0))
5197 int shift
= imm6 (DREG (src0
) & 0xFFFF);
5199 bu40 acc
= get_unextended_acc (cpu
, HLs
);
5201 TRACE_INSN (cpu
, "A%i = ROT A%i BY R%i.L;", HLs
, HLs
, src0
);
5202 TRACE_DECODE (cpu
, "A%i:%#"PRIx64
" shift:%i CC:%i", HLs
, acc
, shift
, cc
);
5204 acc
= rot40 (acc
, shift
, &cc
);
5205 SET_AREG (HLs
, acc
);
5209 else if (sop
== 0 && sopcde
== 3 && (HLs
== 0 || HLs
== 1))
5211 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5212 bu64 val
= get_extended_acc (cpu
, HLs
);
5215 TRACE_INSN (cpu
, "A%i = ASHIFT A%i BY R%i.L;", HLs
, HLs
, src0
);
5216 TRACE_DECODE (cpu
, "A%i:%#"PRIx64
" shift:%i", HLs
, val
, shft
);
5219 val
= ashiftrt (cpu
, val
, -shft
, 40);
5221 val
= lshift (cpu
, val
, shft
, 40, 0, 0);
5223 STORE (AXREG (HLs
), (val
>> 32) & 0xff);
5224 STORE (AWREG (HLs
), (val
& 0xffffffff));
5225 STORE (ASTATREG (av
[HLs
]), val
== 0);
5227 STORE (ASTATREG (avs
[HLs
]), 1);
5229 else if (sop
== 1 && sopcde
== 3 && (HLs
== 0 || HLs
== 1))
5231 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5235 TRACE_INSN (cpu
, "A%i = LSHIFT A%i BY R%i.L;", HLs
, HLs
, src0
);
5236 val
= get_unextended_acc (cpu
, HLs
);
5239 val
= lshiftrt (cpu
, val
, -shft
, 40);
5241 val
= lshift (cpu
, val
, shft
, 40, 0, 0);
5243 STORE (AXREG (HLs
), (val
>> 32) & 0xff);
5244 STORE (AWREG (HLs
), (val
& 0xffffffff));
5245 STORE (ASTATREG (av
[HLs
]), val
== 0);
5247 STORE (ASTATREG (avs
[HLs
]), 1);
5249 else if ((sop
== 0 || sop
== 1) && sopcde
== 1)
5251 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5255 TRACE_INSN (cpu
, "R%i = ASHIFT R%i BY R%i.L (V%s);",
5256 dst0
, src1
, src0
, sop
== 1 ? ",S" : "");
5258 val0
= (bu16
)DREG (src1
) & 0xFFFF;
5259 val1
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5263 val0
= ashiftrt (cpu
, val0
, -shft
, 16);
5265 val1
= ashiftrt (cpu
, val1
, -shft
, 16);
5269 val0
= lshift (cpu
, val0
, shft
, 16, sop
== 1, 1);
5271 val1
= lshift (cpu
, val1
, shft
, 16, sop
== 1, 1);
5273 SET_ASTAT (ASTAT
| astat
);
5274 STORE (DREG (dst0
), (val1
<< 16) | val0
);
5276 else if ((sop
== 0 || sop
== 1 || sop
== 2) && sopcde
== 2)
5278 /* dregs = [LA]SHIFT dregs BY dregs_lo (opt_S) */
5279 /* sop == 1 : opt_S */
5280 bu32 v
= DREG (src1
);
5281 /* LSHIFT uses sign extended low 6 bits of dregs_lo. */
5282 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5284 TRACE_INSN (cpu
, "R%i = %cSHIFT R%i BY R%i.L%s;", dst0
,
5285 shft
&& sop
!= 2 ? 'A' : 'L', src1
, src0
,
5286 sop
== 1 ? " (S)" : "");
5291 STORE (DREG (dst0
), lshiftrt (cpu
, v
, -shft
, 32));
5293 STORE (DREG (dst0
), ashiftrt (cpu
, v
, -shft
, 32));
5296 STORE (DREG (dst0
), lshift (cpu
, v
, shft
, 32, sop
== 1, 1));
5298 else if (sop
== 3 && sopcde
== 2)
5300 int shift
= imm6 (DREG (src0
) & 0xFFFF);
5301 bu32 src
= DREG (src1
);
5302 bu32 ret
, cc
= CCREG
;
5304 TRACE_INSN (cpu
, "R%i = ROT R%i BY R%i.L;", dst0
, src1
, src0
);
5305 TRACE_DECODE (cpu
, "R%i:%#x R%i:%#x shift:%i CC:%i",
5306 dst0
, DREG (dst0
), src1
, src
, shift
, cc
);
5308 ret
= rot32 (src
, shift
, &cc
);
5309 STORE (DREG (dst0
), ret
);
5313 else if (sop
== 2 && sopcde
== 1)
5315 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5319 TRACE_INSN (cpu
, "R%i = LSHIFT R%i BY R%i.L (V);", dst0
, src1
, src0
);
5321 val0
= (bu16
)DREG (src1
) & 0xFFFF;
5322 val1
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5326 val0
= lshiftrt (cpu
, val0
, -shft
, 16);
5328 val1
= lshiftrt (cpu
, val1
, -shft
, 16);
5332 val0
= lshift (cpu
, val0
, shft
, 16, 0, 0);
5334 val1
= lshift (cpu
, val1
, shft
, 16, 0, 0);
5336 SET_ASTAT (ASTAT
| astat
);
5337 STORE (DREG (dst0
), (val1
<< 16) | val0
);
5339 else if (sopcde
== 4)
5341 bu32 sv0
= DREG (src0
);
5342 bu32 sv1
= DREG (src1
);
5343 TRACE_INSN (cpu
, "R%i = PACK (R%i.%c, R%i.%c);", dst0
,
5344 src1
, sop
& 2 ? 'H' : 'L',
5345 src0
, sop
& 1 ? 'H' : 'L');
5350 STORE (DREG (dst0
), (sv1
<< 16) | (sv0
& 0xFFFF));
5352 else if (sop
== 0 && sopcde
== 5)
5354 bu32 sv1
= DREG (src1
);
5355 TRACE_INSN (cpu
, "R%i.L = SIGNBITS R%i;", dst0
, src1
);
5356 SET_DREG_L (dst0
, signbits (sv1
, 32));
5358 else if (sop
== 1 && sopcde
== 5)
5360 bu32 sv1
= DREG (src1
);
5361 TRACE_INSN (cpu
, "R%i.L = SIGNBITS R%i.L;", dst0
, src1
);
5362 SET_DREG_L (dst0
, signbits (sv1
, 16));
5364 else if (sop
== 2 && sopcde
== 5)
5366 bu32 sv1
= DREG (src1
);
5367 TRACE_INSN (cpu
, "R%i.L = SIGNBITS R%i.H;", dst0
, src1
);
5368 SET_DREG_L (dst0
, signbits (sv1
>> 16, 16));
5370 else if ((sop
== 0 || sop
== 1) && sopcde
== 6)
5372 bu64 acc
= AXREG (sop
);
5373 TRACE_INSN (cpu
, "R%i.L = SIGNBITS A%i;", dst0
, sop
);
5376 SET_DREG_L (dst0
, signbits (acc
, 40) & 0xFFFF);
5378 else if (sop
== 3 && sopcde
== 6)
5380 bu32 v
= ones (DREG (src1
));
5381 TRACE_INSN (cpu
, "R%i.L = ONES R%i;", dst0
, src1
);
5382 SET_DREG_L (dst0
, v
);
5384 else if (sop
== 0 && sopcde
== 7)
5386 bu16 sv1
= (bu16
)signbits (DREG (src1
), 32);
5387 bu16 sv0
= (bu16
)DREG (src0
);
5390 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i, R%i.L);", dst0
, src1
, src0
);
5392 if ((sv1
& 0x1f) < (sv0
& 0x1f))
5396 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), dst_lo
));
5398 else if (sop
== 1 && sopcde
== 7)
5400 /* Exponent adjust on two 16-bit inputs. Select
5401 smallest norm among 3 inputs. */
5402 bs16 src1_hi
= (DREG (src1
) & 0xFFFF0000) >> 16;
5403 bs16 src1_lo
= (DREG (src1
) & 0xFFFF);
5404 bu16 src0_lo
= (DREG (src0
) & 0xFFFF);
5405 bu16 tmp_hi
, tmp_lo
, tmp
;
5407 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i, R%i.L) (V);", dst0
, src1
, src0
);
5409 tmp_hi
= signbits (src1_hi
, 16);
5410 tmp_lo
= signbits (src1_lo
, 16);
5412 if ((tmp_hi
& 0xf) < (tmp_lo
& 0xf))
5413 if ((tmp_hi
& 0xf) < (src0_lo
& 0xf))
5418 if ((tmp_lo
& 0xf) < (src0_lo
& 0xf))
5422 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), tmp
));
5424 else if (sop
== 2 && sopcde
== 7)
5426 /* Exponent adjust on single 16-bit register. */
5428 bu16 src0_lo
= (bu16
)(DREG (src0
) & 0xFFFF);
5430 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i.L, R%i.L);", dst0
, src1
, src0
);
5432 tmp
= signbits (DREG (src1
) & 0xFFFF, 16);
5434 if ((tmp
& 0xf) < (src0_lo
& 0xf))
5435 SET_DREG_L (dst0
, tmp
);
5437 SET_DREG_L (dst0
, src0_lo
);
5439 else if (sop
== 3 && sopcde
== 7)
5442 bu16 src0_lo
= (bu16
)(DREG (src0
) & 0xFFFF);
5444 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i.H, R%i.L);", dst0
, src1
, src0
);
5446 tmp
= signbits ((DREG (src1
) & 0xFFFF0000) >> 16, 16);
5448 if ((tmp
& 0xf) < (src0_lo
& 0xf))
5449 SET_DREG_L (dst0
, tmp
);
5451 SET_DREG_L (dst0
, src0_lo
);
5453 else if (sop
== 0 && sopcde
== 8)
5455 bu64 acc
= get_unextended_acc (cpu
, 0);
5458 TRACE_INSN (cpu
, "BITMUX (R%i, R%i, A0) (ASR);", src0
, src1
);
5461 illegal_instruction_combination (cpu
);
5466 (((bu64
)s0
& 1) << 38) |
5467 (((bu64
)s1
& 1) << 39);
5468 STORE (DREG (src0
), s0
>> 1);
5469 STORE (DREG (src1
), s1
>> 1);
5473 else if (sop
== 1 && sopcde
== 8)
5475 bu64 acc
= get_unextended_acc (cpu
, 0);
5478 TRACE_INSN (cpu
, "BITMUX (R%i, R%i, A0) (ASL);", src0
, src1
);
5481 illegal_instruction_combination (cpu
);
5488 STORE (DREG (src0
), s0
<< 1);
5489 STORE (DREG (src1
), s1
<< 1);
5493 else if ((sop
== 0 || sop
== 1) && sopcde
== 9)
5495 bs40 acc0
= get_unextended_acc (cpu
, 0);
5498 TRACE_INSN (cpu
, "R%i.L = VIT_MAX (R%i) (AS%c);",
5499 dst0
, src1
, sop
& 1 ? 'R' : 'L');
5502 sH
= DREG (src1
) >> 16;
5505 acc0
= (acc0
& 0xfeffffffffull
) >> 1;
5509 if (((sH
- sL
) & 0x8000) == 0)
5512 acc0
|= (sop
& 1) ? 0x80000000 : 1;
5518 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), out
));
5520 else if ((sop
== 2 || sop
== 3) && sopcde
== 9)
5522 bs40 acc0
= get_extended_acc (cpu
, 0);
5523 bs16 s0L
, s0H
, s1L
, s1H
, out0
, out1
;
5525 TRACE_INSN (cpu
, "R%i = VIT_MAX (R%i, R%i) (AS%c);",
5526 dst0
, src1
, src0
, sop
& 1 ? 'R' : 'L');
5529 s0H
= DREG (src0
) >> 16;
5531 s1H
= DREG (src1
) >> 16;
5538 if (((s0H
- s0L
) & 0x8000) == 0)
5541 acc0
|= (sop
& 1) ? 0x40000000 : 2;
5546 if (((s1H
- s1L
) & 0x8000) == 0)
5549 acc0
|= (sop
& 1) ? 0x80000000 : 1;
5555 STORE (DREG (dst0
), REG_H_L (out1
<< 16, out0
));
5557 else if (sop
== 0 && sopcde
== 10)
5559 bu32 v
= DREG (src0
);
5560 bu32 x
= DREG (src1
);
5561 bu32 mask
= (1 << (v
& 0x1f)) - 1;
5563 TRACE_INSN (cpu
, "R%i = EXTRACT (R%i, R%i.L) (Z);", dst0
, src1
, src0
);
5565 x
>>= ((v
>> 8) & 0x1f);
5567 STORE (DREG (dst0
), x
);
5568 setflags_logical (cpu
, x
);
5570 else if (sop
== 1 && sopcde
== 10)
5572 bu32 v
= DREG (src0
);
5573 bu32 x
= DREG (src1
);
5574 bu32 sgn
= (1 << (v
& 0x1f)) >> 1;
5575 bu32 mask
= (1 << (v
& 0x1f)) - 1;
5577 TRACE_INSN (cpu
, "R%i = EXTRACT (R%i, R%i.L) (X);", dst0
, src1
, src0
);
5579 x
>>= ((v
>> 8) & 0x1f);
5583 STORE (DREG (dst0
), x
);
5584 setflags_logical (cpu
, x
);
5586 else if ((sop
== 2 || sop
== 3) && sopcde
== 10)
5588 /* The first dregs is the "background" while the second dregs is the
5589 "foreground". The fg reg is used to overlay the bg reg and is:
5590 | nnnn nnnn | nnnn nnnn | xxxp pppp | xxxL LLLL |
5591 n = the fg bit field
5592 p = bit position in bg reg to start LSB of fg field
5593 L = number of fg bits to extract
5594 Using (X) sign-extends the fg bit field. */
5595 bu32 fg
= DREG (src0
);
5596 bu32 bg
= DREG (src1
);
5597 bu32 len
= fg
& 0x1f;
5598 bu32 mask
= (1 << MIN (16, len
)) - 1;
5599 bu32 fgnd
= (fg
>> 16) & mask
;
5600 int shft
= ((fg
>> 8) & 0x1f);
5602 TRACE_INSN (cpu
, "R%i = DEPOSIT (R%i, R%i)%s;", dst0
, src1
, src0
,
5603 sop
== 3 ? " (X)" : "");
5607 /* Sign extend the fg bit field. */
5609 fgnd
= ((bs32
)(bs16
)(fgnd
<< (16 - len
))) >> (16 - len
);
5616 STORE (DREG (dst0
), bg
);
5617 setflags_logical (cpu
, bg
);
5619 else if (sop
== 0 && sopcde
== 11)
5621 bu64 acc0
= get_unextended_acc (cpu
, 0);
5623 TRACE_INSN (cpu
, "R%i.L = CC = BXORSHIFT (A0, R%i);", dst0
, src0
);
5626 SET_CCREG (xor_reduce (acc0
, DREG (src0
)));
5627 SET_DREG (dst0
, REG_H_L (DREG (dst0
), CCREG
));
5630 else if (sop
== 1 && sopcde
== 11)
5632 bu64 acc0
= get_unextended_acc (cpu
, 0);
5634 TRACE_INSN (cpu
, "R%i.L = CC = BXOR (A0, R%i);", dst0
, src0
);
5636 SET_CCREG (xor_reduce (acc0
, DREG (src0
)));
5637 SET_DREG (dst0
, REG_H_L (DREG (dst0
), CCREG
));
5639 else if (sop
== 0 && sopcde
== 12)
5641 bu64 acc0
= get_unextended_acc (cpu
, 0);
5642 bu64 acc1
= get_unextended_acc (cpu
, 1);
5644 TRACE_INSN (cpu
, "A0 = BXORSHIFT (A0, A1, CC);");
5646 acc0
= (acc0
<< 1) | (CCREG
^ xor_reduce (acc0
, acc1
));
5649 else if (sop
== 1 && sopcde
== 12)
5651 bu64 acc0
= get_unextended_acc (cpu
, 0);
5652 bu64 acc1
= get_unextended_acc (cpu
, 1);
5654 TRACE_INSN (cpu
, "R%i.L = CC = BXOR (A0, A1, CC);", dst0
);
5656 SET_CCREG (CCREG
^ xor_reduce (acc0
, acc1
));
5657 acc0
= (acc0
<< 1) | CCREG
;
5658 SET_DREG (dst0
, REG_H_L (DREG (dst0
), CCREG
));
5660 else if ((sop
== 0 || sop
== 1 || sop
== 2) && sopcde
== 13)
5662 int shift
= (sop
+ 1) * 8;
5663 TRACE_INSN (cpu
, "R%i = ALIGN%i (R%i, R%i);", dst0
, shift
, src1
, src0
);
5664 STORE (DREG (dst0
), (DREG (src1
) << (32 - shift
)) | (DREG (src0
) >> shift
));
5667 illegal_instruction (cpu
);
5671 decode_dsp32shiftimm_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
5674 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5675 | 1 | 1 | 0 | 0 |.M.| 1 | 1 | 0 | 1 | - | - |.sopcde............|
5676 |.sop...|.HLs...|.dst0......|.immag.................|.src1......|
5677 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5678 int src1
= ((iw1
>> DSP32ShiftImm_src1_bits
) & DSP32ShiftImm_src1_mask
);
5679 int sop
= ((iw1
>> DSP32ShiftImm_sop_bits
) & DSP32ShiftImm_sop_mask
);
5680 int bit8
= ((iw1
>> 8) & 0x1);
5681 int immag
= ((iw1
>> DSP32ShiftImm_immag_bits
) & DSP32ShiftImm_immag_mask
);
5682 int newimmag
= (-(iw1
>> DSP32ShiftImm_immag_bits
) & DSP32ShiftImm_immag_mask
);
5683 int dst0
= ((iw1
>> DSP32ShiftImm_dst0_bits
) & DSP32ShiftImm_dst0_mask
);
5684 int M
= ((iw0
>> (DSP32ShiftImm_M_bits
- 16)) & DSP32ShiftImm_M_mask
);
5685 int sopcde
= ((iw0
>> (DSP32ShiftImm_sopcde_bits
- 16)) & DSP32ShiftImm_sopcde_mask
);
5686 int HLs
= ((iw1
>> DSP32ShiftImm_HLs_bits
) & DSP32ShiftImm_HLs_mask
);
5688 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32shiftimm
);
5689 TRACE_EXTRACT (cpu
, "%s: M:%i sopcde:%i sop:%i HLs:%i dst0:%i immag:%#x src1:%i",
5690 __func__
, M
, sopcde
, sop
, HLs
, dst0
, immag
, src1
);
5694 bu16 in
= DREG (src1
) >> ((HLs
& 1) ? 16 : 0);
5700 TRACE_INSN (cpu
, "R%i.%c = R%i.%c >>> %i;",
5701 dst0
, (HLs
& 2) ? 'H' : 'L',
5702 src1
, (HLs
& 1) ? 'H' : 'L', newimmag
);
5704 result
= lshift (cpu
, in
, 16 - (newimmag
& 0xF), 16, 0, 1);
5706 result
= ashiftrt (cpu
, in
, newimmag
, 16);
5708 else if (sop
== 1 && bit8
== 0)
5710 TRACE_INSN (cpu
, "R%i.%c = R%i.%c << %i (S);",
5711 dst0
, (HLs
& 2) ? 'H' : 'L',
5712 src1
, (HLs
& 1) ? 'H' : 'L', immag
);
5713 result
= lshift (cpu
, in
, immag
, 16, 1, 1);
5715 else if (sop
== 1 && bit8
)
5717 TRACE_INSN (cpu
, "R%i.%c = R%i.%c >>> %i (S);",
5718 dst0
, (HLs
& 2) ? 'H' : 'L',
5719 src1
, (HLs
& 1) ? 'H' : 'L', immag
);
5720 result
= lshift (cpu
, in
, immag
, 16, 1, 1);
5722 else if (sop
== 2 && bit8
)
5724 TRACE_INSN (cpu
, "R%i.%c = R%i.%c >> %i;",
5725 dst0
, (HLs
& 2) ? 'H' : 'L',
5726 src1
, (HLs
& 1) ? 'H' : 'L', newimmag
);
5727 result
= lshiftrt (cpu
, in
, newimmag
, 16);
5729 else if (sop
== 2 && bit8
== 0)
5731 TRACE_INSN (cpu
, "R%i.%c = R%i.%c << %i;",
5732 dst0
, (HLs
& 2) ? 'H' : 'L',
5733 src1
, (HLs
& 1) ? 'H' : 'L', immag
);
5734 result
= lshift (cpu
, in
, immag
, 16, 0, 1);
5737 illegal_instruction (cpu
);
5741 STORE (DREG (dst0
), (v
& 0xFFFF) | (result
<< 16));
5743 STORE (DREG (dst0
), (v
& 0xFFFF0000) | result
);
5745 else if (sop
== 2 && sopcde
== 3 && (HLs
== 1 || HLs
== 0))
5747 int shift
= imm6 (immag
);
5749 bu40 acc
= get_unextended_acc (cpu
, HLs
);
5751 TRACE_INSN (cpu
, "A%i = ROT A%i BY %i;", HLs
, HLs
, shift
);
5752 TRACE_DECODE (cpu
, "A%i:%#"PRIx64
" shift:%i CC:%i", HLs
, acc
, shift
, cc
);
5754 acc
= rot40 (acc
, shift
, &cc
);
5755 SET_AREG (HLs
, acc
);
5759 else if (sop
== 0 && sopcde
== 3 && bit8
== 1)
5761 /* Arithmetic shift, so shift in sign bit copies. */
5763 int shift
= uimm5 (newimmag
);
5766 TRACE_INSN (cpu
, "A%i = A%i >>> %i;", HLs
, HLs
, shift
);
5768 acc
= get_extended_acc (cpu
, HLs
);
5770 /* Sign extend again. */
5771 if (acc
& (1ULL << 39))
5772 acc
|= -(1ULL << 39);
5774 acc
&= ~(-(1ULL << 39));
5776 STORE (AXREG (HLs
), (acc
>> 32) & 0xFF);
5777 STORE (AWREG (HLs
), acc
& 0xFFFFFFFF);
5779 else if ((sop
== 0 && sopcde
== 3 && bit8
== 0)
5780 || (sop
== 1 && sopcde
== 3))
5783 int shiftup
= uimm5 (immag
);
5784 int shiftdn
= uimm5 (newimmag
);
5787 TRACE_INSN (cpu
, "A%i = A%i %s %i;", HLs
, HLs
,
5788 sop
== 0 ? "<<" : ">>",
5789 sop
== 0 ? shiftup
: shiftdn
);
5792 /* Logical shift, so shift in zeroes. */
5804 acc
<<= 32 - (shiftdn
& 0x1f);
5807 SET_AREG (HLs
, acc
);
5808 SET_ASTATREG (av
[HLs
], 0);
5809 SET_ASTATREG (an
, !!(acc
& 0x8000000000ull
));
5810 SET_ASTATREG (az
, (acc
& 0xFFFFFFFFFF) == 0);
5812 else if (sop
== 1 && sopcde
== 1 && bit8
== 0)
5814 int count
= imm5 (immag
);
5815 bu16 val0
= DREG (src1
) >> 16;
5816 bu16 val1
= DREG (src1
) & 0xFFFF;
5819 TRACE_INSN (cpu
, "R%i = R%i << %i (V,S);", dst0
, src1
, count
);
5822 val0
= lshift (cpu
, val0
, count
, 16, 1, 1);
5824 val1
= lshift (cpu
, val1
, count
, 16, 1, 1);
5828 val0
= ashiftrt (cpu
, val0
, -count
, 16);
5830 val1
= ashiftrt (cpu
, val1
, -count
, 16);
5832 SET_ASTAT (ASTAT
| astat
);
5834 STORE (DREG (dst0
), (val0
<< 16) | val1
);
5836 else if (sop
== 2 && sopcde
== 1 && bit8
== 1)
5838 int count
= imm5 (newimmag
);
5839 bu16 val0
= DREG (src1
) & 0xFFFF;
5840 bu16 val1
= DREG (src1
) >> 16;
5843 TRACE_INSN (cpu
, "R%i = R%i >> %i (V);", dst0
, src1
, count
);
5844 val0
= lshiftrt (cpu
, val0
, count
, 16);
5846 val1
= lshiftrt (cpu
, val1
, count
, 16);
5847 SET_ASTAT (ASTAT
| astat
);
5849 STORE (DREG (dst0
), val0
| (val1
<< 16));
5851 else if (sop
== 2 && sopcde
== 1 && bit8
== 0)
5853 int count
= imm5 (immag
);
5854 bu16 val0
= DREG (src1
) & 0xFFFF;
5855 bu16 val1
= DREG (src1
) >> 16;
5858 TRACE_INSN (cpu
, "R%i = R%i << %i (V);", dst0
, src1
, count
);
5859 val0
= lshift (cpu
, val0
, count
, 16, 0, 1);
5861 val1
= lshift (cpu
, val1
, count
, 16, 0, 1);
5862 SET_ASTAT (ASTAT
| astat
);
5864 STORE (DREG (dst0
), val0
| (val1
<< 16));
5866 else if (sopcde
== 1 && (sop
== 0 || (sop
== 1 && bit8
== 1)))
5868 int count
= uimm5 (newimmag
);
5869 bu16 val0
= DREG (src1
) & 0xFFFF;
5870 bu16 val1
= DREG (src1
) >> 16;
5873 TRACE_INSN (cpu
, "R%i = R%i >>> %i %s;", dst0
, src1
, count
,
5874 sop
== 0 ? "(V)" : "(V,S)");
5878 val0
= lshift (cpu
, val0
, 16 - (count
& 0xF), 16, 0, 1);
5880 val1
= lshift (cpu
, val1
, 16 - (count
& 0xF), 16, 0, 1);
5884 val0
= ashiftrt (cpu
, val0
, count
, 16);
5886 val1
= ashiftrt (cpu
, val1
, count
, 16);
5889 SET_ASTAT (ASTAT
| astat
);
5891 STORE (DREG (dst0
), REG_H_L (val1
<< 16, val0
));
5893 else if (sop
== 1 && sopcde
== 2)
5895 int count
= imm6 (immag
);
5897 TRACE_INSN (cpu
, "R%i = R%i << %i (S);", dst0
, src1
, count
);
5898 STORE (DREG (dst0
), lshift (cpu
, DREG (src1
), count
, 32, 1, 1));
5900 else if (sop
== 2 && sopcde
== 2)
5902 int count
= imm6 (newimmag
);
5904 TRACE_INSN (cpu
, "R%i = R%i >> %i;", dst0
, src1
, count
);
5907 STORE (DREG (dst0
), lshift (cpu
, DREG (src1
), -count
, 32, 0, 1));
5909 STORE (DREG (dst0
), lshiftrt (cpu
, DREG (src1
), count
, 32));
5911 else if (sop
== 3 && sopcde
== 2)
5913 int shift
= imm6 (immag
);
5914 bu32 src
= DREG (src1
);
5915 bu32 ret
, cc
= CCREG
;
5917 TRACE_INSN (cpu
, "R%i = ROT R%i BY %i;", dst0
, src1
, shift
);
5918 TRACE_DECODE (cpu
, "R%i:%#x R%i:%#x shift:%i CC:%i",
5919 dst0
, DREG (dst0
), src1
, src
, shift
, cc
);
5921 ret
= rot32 (src
, shift
, &cc
);
5922 STORE (DREG (dst0
), ret
);
5926 else if (sop
== 0 && sopcde
== 2)
5928 int count
= imm6 (newimmag
);
5930 TRACE_INSN (cpu
, "R%i = R%i >>> %i;", dst0
, src1
, count
);
5933 STORE (DREG (dst0
), lshift (cpu
, DREG (src1
), -count
, 32, 0, 1));
5935 STORE (DREG (dst0
), ashiftrt (cpu
, DREG (src1
), count
, 32));
5938 illegal_instruction (cpu
);
5942 outc (SIM_CPU
*cpu
, char ch
)
5944 SIM_DESC sd
= CPU_STATE (cpu
);
5945 sim_io_printf (sd
, "%c", ch
);
5947 sim_io_flush_stdout (sd
);
5951 decode_psedoDEBUG_0 (SIM_CPU
*cpu
, bu16 iw0
)
5954 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5955 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 |.fn....|.grp.......|.reg.......|
5956 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5957 SIM_DESC sd
= CPU_STATE (cpu
);
5958 int fn
= ((iw0
>> PseudoDbg_fn_bits
) & PseudoDbg_fn_mask
);
5959 int grp
= ((iw0
>> PseudoDbg_grp_bits
) & PseudoDbg_grp_mask
);
5960 int reg
= ((iw0
>> PseudoDbg_reg_bits
) & PseudoDbg_reg_mask
);
5962 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_psedoDEBUG
);
5963 TRACE_EXTRACT (cpu
, "%s: fn:%i grp:%i reg:%i", __func__
, fn
, grp
, reg
);
5965 if ((reg
== 0 || reg
== 1) && fn
== 3)
5967 TRACE_INSN (cpu
, "DBG A%i;", reg
);
5968 sim_io_printf (sd
, "DBG : A%i = %#"PRIx64
"\n", reg
,
5969 get_unextended_acc (cpu
, reg
));
5971 else if (reg
== 3 && fn
== 3)
5973 TRACE_INSN (cpu
, "ABORT;");
5974 cec_exception (cpu
, VEC_SIM_ABORT
);
5977 else if (reg
== 4 && fn
== 3)
5979 TRACE_INSN (cpu
, "HLT;");
5980 cec_exception (cpu
, VEC_SIM_HLT
);
5983 else if (reg
== 5 && fn
== 3)
5984 unhandled_instruction (cpu
, "DBGHALT");
5985 else if (reg
== 6 && fn
== 3)
5986 unhandled_instruction (cpu
, "DBGCMPLX (dregs)");
5987 else if (reg
== 7 && fn
== 3)
5988 unhandled_instruction (cpu
, "DBG");
5989 else if (grp
== 0 && fn
== 2)
5991 TRACE_INSN (cpu
, "OUTC R%i;", reg
);
5992 outc (cpu
, DREG (reg
));
5996 const char *reg_name
= get_allreg_name (grp
, reg
);
5997 TRACE_INSN (cpu
, "DBG %s;", reg_name
);
5998 sim_io_printf (sd
, "DBG : %s = 0x%08x\n", reg_name
,
5999 reg_read (cpu
, grp
, reg
));
6002 unhandled_instruction (cpu
, "PRNT allregs");
6004 illegal_instruction (cpu
);
6008 decode_psedoOChar_0 (SIM_CPU
*cpu
, bu16 iw0
)
6011 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
6012 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |.ch............................|
6013 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
6014 int ch
= ((iw0
>> PseudoChr_ch_bits
) & PseudoChr_ch_mask
);
6016 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_psedoOChar
);
6017 TRACE_EXTRACT (cpu
, "%s: ch:%#x", __func__
, ch
);
6018 TRACE_INSN (cpu
, "OUTC %#x;", ch
);
6024 decode_psedodbg_assert_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
, bu32 pc
)
6027 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
6028 | 1 | 1 | 1 | 1 | 0 | - | - | - | dbgop |.grp.......|.regtest...|
6029 |.expected......................................................|
6030 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
6031 SIM_DESC sd
= CPU_STATE (cpu
);
6032 int expected
= ((iw1
>> PseudoDbg_Assert_expected_bits
) & PseudoDbg_Assert_expected_mask
);
6033 int dbgop
= ((iw0
>> (PseudoDbg_Assert_dbgop_bits
- 16)) & PseudoDbg_Assert_dbgop_mask
);
6034 int grp
= ((iw0
>> (PseudoDbg_Assert_grp_bits
- 16)) & PseudoDbg_Assert_grp_mask
);
6035 int regtest
= ((iw0
>> (PseudoDbg_Assert_regtest_bits
- 16)) & PseudoDbg_Assert_regtest_mask
);
6038 bu32 val
= reg_read (cpu
, grp
, regtest
);
6039 const char *reg_name
= get_allreg_name (grp
, regtest
);
6040 const char *dbg_name
, *dbg_appd
;
6042 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_psedodbg_assert
);
6043 TRACE_EXTRACT (cpu
, "%s: dbgop:%i grp:%i regtest:%i expected:%#x",
6044 __func__
, dbgop
, grp
, regtest
, expected
);
6046 if (dbgop
== 0 || dbgop
== 2)
6048 dbg_name
= dbgop
== 0 ? "DBGA" : "DBGAL";
6049 dbg_appd
= dbgop
== 0 ? ".L" : "";
6052 else if (dbgop
== 1 || dbgop
== 3)
6054 dbg_name
= dbgop
== 1 ? "DBGA" : "DBGAH";
6055 dbg_appd
= dbgop
== 1 ? ".H" : "";
6059 illegal_instruction (cpu
);
6061 actual
= val
>> offset
;
6063 TRACE_INSN (cpu
, "%s (%s%s, 0x%x);", dbg_name
, reg_name
, dbg_appd
, expected
);
6064 if (actual
!= expected
)
6066 sim_io_printf (sd
, "FAIL at %#x: %s (%s%s, 0x%04x); actual value %#x\n",
6067 pc
, dbg_name
, reg_name
, dbg_appd
, expected
, actual
);
6069 /* Decode the actual ASTAT bits that are different. */
6070 if (grp
== 4 && regtest
== 6)
6074 sim_io_printf (sd
, "Expected ASTAT:\n");
6075 for (i
= 0; i
< 16; ++i
)
6076 sim_io_printf (sd
, " %8s%c%i%s",
6077 astat_names
[i
+ offset
],
6078 (((expected
>> i
) & 1) != ((actual
>> i
) & 1))
6080 (expected
>> i
) & 1,
6081 i
== 7 ? "\n" : "");
6082 sim_io_printf (sd
, "\n");
6084 sim_io_printf (sd
, "Actual ASTAT:\n");
6085 for (i
= 0; i
< 16; ++i
)
6086 sim_io_printf (sd
, " %8s%c%i%s",
6087 astat_names
[i
+ offset
],
6088 (((expected
>> i
) & 1) != ((actual
>> i
) & 1))
6091 i
== 7 ? "\n" : "");
6092 sim_io_printf (sd
, "\n");
6095 cec_exception (cpu
, VEC_SIM_DBGA
);
6101 _interp_insn_bfin (SIM_CPU
*cpu
, bu32 pc
)
6106 BFIN_CPU_STATE
.multi_pc
= pc
;
6108 if ((iw0
& 0xc000) != 0xc000)
6110 /* 16-bit opcode. */
6113 INSN_LEN
= insn_len
;
6115 TRACE_EXTRACT (cpu
, "%s: iw0:%#x", __func__
, iw0
);
6116 if ((iw0
& 0xFF00) == 0x0000)
6117 decode_ProgCtrl_0 (cpu
, iw0
, pc
);
6118 else if ((iw0
& 0xFFC0) == 0x0240)
6119 decode_CaCTRL_0 (cpu
, iw0
);
6120 else if ((iw0
& 0xFF80) == 0x0100)
6121 decode_PushPopReg_0 (cpu
, iw0
);
6122 else if ((iw0
& 0xFE00) == 0x0400)
6123 decode_PushPopMultiple_0 (cpu
, iw0
);
6124 else if ((iw0
& 0xFE00) == 0x0600)
6125 decode_ccMV_0 (cpu
, iw0
);
6126 else if ((iw0
& 0xF800) == 0x0800)
6127 decode_CCflag_0 (cpu
, iw0
);
6128 else if ((iw0
& 0xFFE0) == 0x0200)
6129 decode_CC2dreg_0 (cpu
, iw0
);
6130 else if ((iw0
& 0xFF00) == 0x0300)
6131 decode_CC2stat_0 (cpu
, iw0
);
6132 else if ((iw0
& 0xF000) == 0x1000)
6133 decode_BRCC_0 (cpu
, iw0
, pc
);
6134 else if ((iw0
& 0xF000) == 0x2000)
6135 decode_UJUMP_0 (cpu
, iw0
, pc
);
6136 else if ((iw0
& 0xF000) == 0x3000)
6137 decode_REGMV_0 (cpu
, iw0
);
6138 else if ((iw0
& 0xFC00) == 0x4000)
6139 decode_ALU2op_0 (cpu
, iw0
);
6140 else if ((iw0
& 0xFE00) == 0x4400)
6141 decode_PTR2op_0 (cpu
, iw0
);
6142 else if ((iw0
& 0xF800) == 0x4800)
6143 decode_LOGI2op_0 (cpu
, iw0
);
6144 else if ((iw0
& 0xF000) == 0x5000)
6145 decode_COMP3op_0 (cpu
, iw0
);
6146 else if ((iw0
& 0xF800) == 0x6000)
6147 decode_COMPI2opD_0 (cpu
, iw0
);
6148 else if ((iw0
& 0xF800) == 0x6800)
6149 decode_COMPI2opP_0 (cpu
, iw0
);
6150 else if ((iw0
& 0xF000) == 0x8000)
6151 decode_LDSTpmod_0 (cpu
, iw0
);
6152 else if ((iw0
& 0xFF60) == 0x9E60)
6153 decode_dagMODim_0 (cpu
, iw0
);
6154 else if ((iw0
& 0xFFF0) == 0x9F60)
6155 decode_dagMODik_0 (cpu
, iw0
);
6156 else if ((iw0
& 0xFC00) == 0x9C00)
6157 decode_dspLDST_0 (cpu
, iw0
);
6158 else if ((iw0
& 0xF000) == 0x9000)
6159 decode_LDST_0 (cpu
, iw0
);
6160 else if ((iw0
& 0xFC00) == 0xB800)
6161 decode_LDSTiiFP_0 (cpu
, iw0
);
6162 else if ((iw0
& 0xE000) == 0xA000)
6163 decode_LDSTii_0 (cpu
, iw0
);
6166 TRACE_EXTRACT (cpu
, "%s: no matching 16-bit pattern", __func__
);
6167 illegal_instruction (cpu
);
6172 /* Grab the next 16 bits to determine if it's a 32-bit or 64-bit opcode. */
6173 iw1
= IFETCH (pc
+ 2);
6174 if ((iw0
& BIT_MULTI_INS
) && (iw0
& 0xe800) != 0xe800 /* not linkage */)
6176 SIM_DESC sd
= CPU_STATE (cpu
);
6177 trace_prefix (sd
, cpu
, NULL_CIA
, pc
, TRACE_LINENUM_P (cpu
),
6178 NULL
, 0, "|| %#"PRIx64
, sim_events_time (sd
));
6184 TRACE_EXTRACT (cpu
, "%s: iw0:%#x iw1:%#x insn_len:%i", __func__
,
6185 iw0
, iw1
, insn_len
);
6187 /* Only cache on first run through (in case of parallel insns). */
6189 INSN_LEN
= insn_len
;
6191 /* Once you're past the first slot, only 16bit insns are valid. */
6192 illegal_instruction_combination (cpu
);
6194 if ((iw0
& 0xf7ff) == 0xc003 && (iw1
& 0xfe00) == 0x1800)
6196 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32mac
);
6197 TRACE_INSN (cpu
, "MNOP;");
6199 else if (((iw0
& 0xFF80) == 0xE080) && ((iw1
& 0x0C00) == 0x0000))
6200 decode_LoopSetup_0 (cpu
, iw0
, iw1
, pc
);
6201 else if (((iw0
& 0xFF00) == 0xE100) && ((iw1
& 0x0000) == 0x0000))
6202 decode_LDIMMhalf_0 (cpu
, iw0
, iw1
);
6203 else if (((iw0
& 0xFE00) == 0xE200) && ((iw1
& 0x0000) == 0x0000))
6204 decode_CALLa_0 (cpu
, iw0
, iw1
, pc
);
6205 else if (((iw0
& 0xFC00) == 0xE400) && ((iw1
& 0x0000) == 0x0000))
6206 decode_LDSTidxI_0 (cpu
, iw0
, iw1
);
6207 else if (((iw0
& 0xFFFE) == 0xE800) && ((iw1
& 0x0000) == 0x0000))
6208 decode_linkage_0 (cpu
, iw0
, iw1
);
6209 else if (((iw0
& 0xF600) == 0xC000) && ((iw1
& 0x0000) == 0x0000))
6210 decode_dsp32mac_0 (cpu
, iw0
, iw1
);
6211 else if (((iw0
& 0xF600) == 0xC200) && ((iw1
& 0x0000) == 0x0000))
6212 decode_dsp32mult_0 (cpu
, iw0
, iw1
);
6213 else if (((iw0
& 0xF7C0) == 0xC400) && ((iw1
& 0x0000) == 0x0000))
6214 decode_dsp32alu_0 (cpu
, iw0
, iw1
);
6215 else if (((iw0
& 0xF7E0) == 0xC600) && ((iw1
& 0x01C0) == 0x0000))
6216 decode_dsp32shift_0 (cpu
, iw0
, iw1
);
6217 else if (((iw0
& 0xF7E0) == 0xC680) && ((iw1
& 0x0000) == 0x0000))
6218 decode_dsp32shiftimm_0 (cpu
, iw0
, iw1
);
6219 else if ((iw0
& 0xFF00) == 0xF800)
6220 decode_psedoDEBUG_0 (cpu
, iw0
), insn_len
= 2;
6221 else if ((iw0
& 0xFF00) == 0xF900)
6222 decode_psedoOChar_0 (cpu
, iw0
), insn_len
= 2;
6223 else if (((iw0
& 0xFF00) == 0xF000) && ((iw1
& 0x0000) == 0x0000))
6224 decode_psedodbg_assert_0 (cpu
, iw0
, iw1
, pc
);
6227 TRACE_EXTRACT (cpu
, "%s: no matching 32-bit pattern", __func__
);
6228 illegal_instruction (cpu
);
6235 interp_insn_bfin (SIM_CPU
*cpu
, bu32 pc
)
6240 BFIN_CPU_STATE
.n_stores
= 0;
6241 DIS_ALGN_EXPT
&= ~1;
6245 insn_len
= _interp_insn_bfin (cpu
, pc
);
6247 /* Proper display of multiple issue instructions. */
6250 _interp_insn_bfin (cpu
, pc
+ 4);
6251 _interp_insn_bfin (cpu
, pc
+ 6);
6253 for (i
= 0; i
< BFIN_CPU_STATE
.n_stores
; i
++)
6255 bu32
*addr
= BFIN_CPU_STATE
.stores
[i
].addr
;
6256 *addr
= BFIN_CPU_STATE
.stores
[i
].val
;
6257 TRACE_REGISTER (cpu
, "dequeuing write %s = %#x",
6258 get_store_name (cpu
, addr
), *addr
);
6261 cycles_inc (cpu
, CYCLE_DELAY
);
6263 /* Set back to zero in case a pending CEC event occurs
6264 after this this insn. */