1 /* Simulator for Analog Devices Blackfin processors.
3 Copyright (C) 2005-2011 Free Software Foundation, Inc.
4 Contributed by Analog Devices, Inc.
6 This file is part of simulators.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
28 #include "opcode/bfin.h"
30 #include "dv-bfin_cec.h"
31 #include "dv-bfin_mmu.h"
33 #define HOST_LONG_WORD_SIZE (sizeof (long) * 8)
35 #define SIGNEXTEND(v, n) \
36 (((bs32)(v) << (HOST_LONG_WORD_SIZE - (n))) >> (HOST_LONG_WORD_SIZE - (n)))
38 static __attribute__ ((noreturn
)) void
39 illegal_instruction (SIM_CPU
*cpu
)
41 TRACE_INSN (cpu
, "ILLEGAL INSTRUCTION");
43 cec_exception (cpu
, VEC_UNDEF_I
);
46 static __attribute__ ((noreturn
)) void
47 illegal_instruction_combination (SIM_CPU
*cpu
)
49 TRACE_INSN (cpu
, "ILLEGAL INSTRUCTION COMBINATION");
51 cec_exception (cpu
, VEC_ILGAL_I
);
54 static __attribute__ ((noreturn
)) void
55 unhandled_instruction (SIM_CPU
*cpu
, const char *insn
)
57 SIM_DESC sd
= CPU_STATE (cpu
);
61 TRACE_EVENTS (cpu
, "unhandled instruction");
64 iw1
= IFETCH (PCREG
+ 2);
65 iw2
= ((bu32
)iw0
<< 16) | iw1
;
67 sim_io_eprintf (sd
, "Unhandled instruction at 0x%08x (%s opcode 0x", PCREG
, insn
);
68 if ((iw0
& 0xc000) == 0xc000)
69 sim_io_eprintf (sd
, "%08x", iw2
);
71 sim_io_eprintf (sd
, "%04x", iw0
);
73 sim_io_eprintf (sd
, ") ... aborting\n");
75 illegal_instruction (cpu
);
80 c_0
, c_1
, c_4
, c_2
, c_uimm2
, c_uimm3
, c_imm3
, c_pcrel4
,
81 c_imm4
, c_uimm4s4
, c_uimm4s4d
, c_uimm4
, c_uimm4s2
, c_negimm5s4
, c_imm5
,
82 c_imm5d
, c_uimm5
, c_imm6
, c_imm7
, c_imm7d
, c_imm8
, c_uimm8
, c_pcrel8
,
83 c_uimm8s4
, c_pcrel8s4
, c_lppcrel10
, c_pcrel10
, c_pcrel12
, c_imm16s4
,
84 c_luimm16
, c_imm16
, c_imm16d
, c_huimm16
, c_rimm16
, c_imm16s2
, c_uimm16s4
,
85 c_uimm16s4d
, c_uimm16
, c_pcrel24
, c_uimm32
, c_imm32
, c_huimm32
, c_huimm32e
,
102 } constant_formats
[] =
104 { "0", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
105 { "1", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
106 { "4", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
107 { "2", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
108 { "uimm2", 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
109 { "uimm3", 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
110 { "imm3", 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
111 { "pcrel4", 4, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0},
112 { "imm4", 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
113 { "uimm4s4", 4, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0},
114 { "uimm4s4d", 4, 0, 0, 0, 2, 0, 0, 1, 1, 0, 0},
115 { "uimm4", 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
116 { "uimm4s2", 4, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0},
117 { "negimm5s4", 5, 0, 1, 0, 2, 0, 1, 0, 0, 0, 0},
118 { "imm5", 5, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
119 { "imm5d", 5, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0},
120 { "uimm5", 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
121 { "imm6", 6, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
122 { "imm7", 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
123 { "imm7d", 7, 0, 1, 0, 0, 0, 0, 0, 1, 3, 0},
124 { "imm8", 8, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
125 { "uimm8", 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
126 { "pcrel8", 8, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0},
127 { "uimm8s4", 8, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0},
128 { "pcrel8s4", 8, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0},
129 { "lppcrel10", 10, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0},
130 { "pcrel10", 10, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
131 { "pcrel12", 12, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
132 { "imm16s4", 16, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0},
133 { "luimm16", 16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
134 { "imm16", 16, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
135 { "imm16d", 16, 0, 1, 0, 0, 0, 0, 0, 1, 3, 0},
136 { "huimm16", 16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
137 { "rimm16", 16, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0},
138 { "imm16s2", 16, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0},
139 { "uimm16s4", 16, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0},
140 { "uimm16s4d", 16, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0},
141 { "uimm16", 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
142 { "pcrel24", 24, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
143 { "uimm32", 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
144 { "imm32", 32, 0, 1, 0, 0, 0, 0, 0, 1, 3, 0},
145 { "huimm32", 32, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
146 { "huimm32e", 32, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
150 fmtconst_str (const_forms_t cf
, bs32 x
, bu32 pc
)
154 if (constant_formats
[cf
].reloc
)
156 bu32 ea
= (((constant_formats
[cf
].pcrel
? SIGNEXTEND (x
, constant_formats
[cf
].nbits
)
157 : x
) + constant_formats
[cf
].offset
) << constant_formats
[cf
].scale
);
158 if (constant_formats
[cf
].pcrel
)
160 /*if (outf->symbol_at_address_func (ea, outf) || !constant_formats[cf].exact)
162 outf->print_address_func (ea, outf);
167 sprintf (buf
, "%#x", x
);
172 /* Negative constants have an implied sign bit. */
173 if (constant_formats
[cf
].negative
)
175 int nb
= constant_formats
[cf
].nbits
+ 1;
177 x
= x
| (1 << constant_formats
[cf
].nbits
);
178 x
= SIGNEXTEND (x
, nb
);
181 x
= constant_formats
[cf
].issigned
? SIGNEXTEND (x
, constant_formats
[cf
].nbits
) : x
;
183 if (constant_formats
[cf
].offset
)
184 x
+= constant_formats
[cf
].offset
;
186 if (constant_formats
[cf
].scale
)
187 x
<<= constant_formats
[cf
].scale
;
189 if (constant_formats
[cf
].decimal
)
191 if (constant_formats
[cf
].leading
)
194 sprintf (ps
, "%%%ii", constant_formats
[cf
].leading
);
195 sprintf (buf
, ps
, x
);
198 sprintf (buf
, "%i", x
);
202 if (constant_formats
[cf
].issigned
&& x
< 0)
203 sprintf (buf
, "-0x%x", abs (x
));
205 sprintf (buf
, "0x%x", x
);
212 fmtconst_val (const_forms_t cf
, bu32 x
, bu32 pc
)
214 if (0 && constant_formats
[cf
].reloc
)
216 bu32 ea
= (((constant_formats
[cf
].pcrel
217 ? (bu32
)SIGNEXTEND (x
, constant_formats
[cf
].nbits
)
218 : x
) + constant_formats
[cf
].offset
)
219 << constant_formats
[cf
].scale
);
220 if (constant_formats
[cf
].pcrel
)
226 /* Negative constants have an implied sign bit. */
227 if (constant_formats
[cf
].negative
)
229 int nb
= constant_formats
[cf
].nbits
+ 1;
230 x
= x
| (1 << constant_formats
[cf
].nbits
);
231 x
= SIGNEXTEND (x
, nb
);
233 else if (constant_formats
[cf
].issigned
)
234 x
= SIGNEXTEND (x
, constant_formats
[cf
].nbits
);
236 x
+= constant_formats
[cf
].offset
;
237 x
<<= constant_formats
[cf
].scale
;
242 #define uimm16s4(x) fmtconst_val (c_uimm16s4, x, 0)
243 #define uimm16s4_str(x) fmtconst_str (c_uimm16s4, x, 0)
244 #define uimm16s4d(x) fmtconst_val (c_uimm16s4d, x, 0)
245 #define pcrel4(x) fmtconst_val (c_pcrel4, x, pc)
246 #define pcrel8(x) fmtconst_val (c_pcrel8, x, pc)
247 #define pcrel8s4(x) fmtconst_val (c_pcrel8s4, x, pc)
248 #define pcrel10(x) fmtconst_val (c_pcrel10, x, pc)
249 #define pcrel12(x) fmtconst_val (c_pcrel12, x, pc)
250 #define negimm5s4(x) fmtconst_val (c_negimm5s4, x, 0)
251 #define negimm5s4_str(x) fmtconst_str (c_negimm5s4, x, 0)
252 #define rimm16(x) fmtconst_val (c_rimm16, x, 0)
253 #define huimm16(x) fmtconst_val (c_huimm16, x, 0)
254 #define imm16(x) fmtconst_val (c_imm16, x, 0)
255 #define imm16_str(x) fmtconst_str (c_imm16, x, 0)
256 #define imm16d(x) fmtconst_val (c_imm16d, x, 0)
257 #define uimm2(x) fmtconst_val (c_uimm2, x, 0)
258 #define uimm3(x) fmtconst_val (c_uimm3, x, 0)
259 #define uimm3_str(x) fmtconst_str (c_uimm3, x, 0)
260 #define luimm16(x) fmtconst_val (c_luimm16, x, 0)
261 #define luimm16_str(x) fmtconst_str (c_luimm16, x, 0)
262 #define uimm4(x) fmtconst_val (c_uimm4, x, 0)
263 #define uimm4_str(x) fmtconst_str (c_uimm4, x, 0)
264 #define uimm5(x) fmtconst_val (c_uimm5, x, 0)
265 #define uimm5_str(x) fmtconst_str (c_uimm5, x, 0)
266 #define imm16s2(x) fmtconst_val (c_imm16s2, x, 0)
267 #define imm16s2_str(x) fmtconst_str (c_imm16s2, x, 0)
268 #define uimm8(x) fmtconst_val (c_uimm8, x, 0)
269 #define imm16s4(x) fmtconst_val (c_imm16s4, x, 0)
270 #define imm16s4_str(x) fmtconst_str (c_imm16s4, x, 0)
271 #define uimm4s2(x) fmtconst_val (c_uimm4s2, x, 0)
272 #define uimm4s2_str(x) fmtconst_str (c_uimm4s2, x, 0)
273 #define uimm4s4(x) fmtconst_val (c_uimm4s4, x, 0)
274 #define uimm4s4_str(x) fmtconst_str (c_uimm4s4, x, 0)
275 #define uimm4s4d(x) fmtconst_val (c_uimm4s4d, x, 0)
276 #define lppcrel10(x) fmtconst_val (c_lppcrel10, x, pc)
277 #define imm3(x) fmtconst_val (c_imm3, x, 0)
278 #define imm3_str(x) fmtconst_str (c_imm3, x, 0)
279 #define imm4(x) fmtconst_val (c_imm4, x, 0)
280 #define uimm8s4(x) fmtconst_val (c_uimm8s4, x, 0)
281 #define imm5(x) fmtconst_val (c_imm5, x, 0)
282 #define imm5d(x) fmtconst_val (c_imm5d, x, 0)
283 #define imm6(x) fmtconst_val (c_imm6, x, 0)
284 #define imm7(x) fmtconst_val (c_imm7, x, 0)
285 #define imm7_str(x) fmtconst_str (c_imm7, x, 0)
286 #define imm7d(x) fmtconst_val (c_imm7d, x, 0)
287 #define imm8(x) fmtconst_val (c_imm8, x, 0)
288 #define pcrel24(x) fmtconst_val (c_pcrel24, x, pc)
289 #define pcrel24_str(x) fmtconst_str (c_pcrel24, x, pc)
290 #define uimm16(x) fmtconst_val (c_uimm16, x, 0)
291 #define uimm32(x) fmtconst_val (c_uimm32, x, 0)
292 #define imm32(x) fmtconst_val (c_imm32, x, 0)
293 #define huimm32(x) fmtconst_val (c_huimm32, x, 0)
294 #define huimm32e(x) fmtconst_val (c_huimm32e, x, 0)
296 /* Table C-4. Core Register Encoding Map. */
297 const char * const greg_names
[] =
299 "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7",
300 "P0", "P1", "P2", "P3", "P4", "P5", "SP", "FP",
301 "I0", "I1", "I2", "I3", "M0", "M1", "M2", "M3",
302 "B0", "B1", "B2", "B3", "L0", "L1", "L2", "L3",
303 "A0.X", "A0.W", "A1.X", "A1.W", "<res>", "<res>", "ASTAT", "RETS",
304 "<res>", "<res>", "<res>", "<res>", "<res>", "<res>", "<res>", "<res>",
305 "LC0", "LT0", "LB0", "LC1", "LT1", "LB1", "CYCLES", "CYCLES2",
306 "USP", "SEQSTAT", "SYSCFG", "RETI", "RETX", "RETN", "RETE", "EMUDAT",
309 get_allreg_name (int grp
, int reg
)
311 return greg_names
[(grp
<< 3) | reg
];
314 get_preg_name (int reg
)
316 return get_allreg_name (1, reg
);
320 reg_is_reserved (int grp
, int reg
)
322 return (grp
== 4 && (reg
== 4 || reg
== 5)) || (grp
== 5);
326 get_allreg (SIM_CPU
*cpu
, int grp
, int reg
)
328 int fullreg
= (grp
<< 3) | reg
;
329 /* REG_R0, REG_R1, REG_R2, REG_R3, REG_R4, REG_R5, REG_R6, REG_R7,
330 REG_P0, REG_P1, REG_P2, REG_P3, REG_P4, REG_P5, REG_SP, REG_FP,
331 REG_I0, REG_I1, REG_I2, REG_I3, REG_M0, REG_M1, REG_M2, REG_M3,
332 REG_B0, REG_B1, REG_B2, REG_B3, REG_L0, REG_L1, REG_L2, REG_L3,
333 REG_A0x, REG_A0w, REG_A1x, REG_A1w, , , REG_ASTAT, REG_RETS,
335 REG_LC0, REG_LT0, REG_LB0, REG_LC1, REG_LT1, REG_LB1, REG_CYCLES,
337 REG_USP, REG_SEQSTAT, REG_SYSCFG, REG_RETI, REG_RETX, REG_RETN, REG_RETE,
339 switch (fullreg
>> 2)
341 case 0: case 1: return &DREG (reg
);
342 case 2: case 3: return &PREG (reg
);
343 case 4: return &IREG (reg
& 3);
344 case 5: return &MREG (reg
& 3);
345 case 6: return &BREG (reg
& 3);
346 case 7: return &LREG (reg
& 3);
350 case 32: return &AXREG (0);
351 case 33: return &AWREG (0);
352 case 34: return &AXREG (1);
353 case 35: return &AWREG (1);
354 case 39: return &RETSREG
;
355 case 48: return &LCREG (0);
356 case 49: return <REG (0);
357 case 50: return &LBREG (0);
358 case 51: return &LCREG (1);
359 case 52: return <REG (1);
360 case 53: return &LBREG (1);
361 case 54: return &CYCLESREG
;
362 case 55: return &CYCLES2REG
;
363 case 56: return &USPREG
;
364 case 57: return &SEQSTATREG
;
365 case 58: return &SYSCFGREG
;
366 case 59: return &RETIREG
;
367 case 60: return &RETXREG
;
368 case 61: return &RETNREG
;
369 case 62: return &RETEREG
;
370 case 63: return &EMUDAT_INREG
;
372 illegal_instruction (cpu
);
377 amod0 (int s0
, int x0
)
379 static const char * const mod0
[] = {
380 "", " (S)", " (CO)", " (SCO)",
382 int i
= s0
+ (x0
<< 1);
384 if (i
< ARRAY_SIZE (mod0
))
391 amod0amod2 (int s0
, int x0
, int aop0
)
393 static const char * const mod02
[] = {
394 "", " (S)", " (CO)", " (SCO)",
396 " (ASR)", " (S, ASR)", " (CO, ASR)", " (SCO, ASR)",
397 " (ASL)", " (S, ASL)", " (CO, ASL)", " (SCO, ASL)",
399 int i
= s0
+ (x0
<< 1) + (aop0
<< 2);
401 if (i
< ARRAY_SIZE (mod02
))
408 amod1 (int s0
, int x0
)
410 static const char * const mod1
[] = {
413 int i
= s0
+ (x0
<< 1);
415 if (i
< ARRAY_SIZE (mod1
))
422 mac_optmode (int mmod
, int MM
)
424 static const char * const omode
[] = {
425 [(M_S2RND
<< 1) + 0] = " (S2RND)",
426 [(M_T
<< 1) + 0] = " (T)",
427 [(M_W32
<< 1) + 0] = " (W32)",
428 [(M_FU
<< 1) + 0] = " (FU)",
429 [(M_TFU
<< 1) + 0] = " (TFU)",
430 [(M_IS
<< 1) + 0] = " (IS)",
431 [(M_ISS2
<< 1) + 0] = " (ISS2)",
432 [(M_IH
<< 1) + 0] = " (IH)",
433 [(M_IU
<< 1) + 0] = " (IU)",
434 [(M_S2RND
<< 1) + 1] = " (M, S2RND)",
435 [(M_T
<< 1) + 1] = " (M, T)",
436 [(M_W32
<< 1) + 1] = " (M, W32)",
437 [(M_FU
<< 1) + 1] = " (M, FU)",
438 [(M_TFU
<< 1) + 1] = " (M, TFU)",
439 [(M_IS
<< 1) + 1] = " (M, IS)",
440 [(M_ISS2
<< 1) + 1] = " (M, ISS2)",
441 [(M_IH
<< 1) + 1] = " (M, IH)",
442 [(M_IU
<< 1) + 1] = " (M, IU)",
444 int i
= MM
+ (mmod
<< 1);
446 if (i
< ARRAY_SIZE (omode
) && omode
[i
])
453 get_store_name (SIM_CPU
*cpu
, bu32
*p
)
455 if (p
>= &DREG (0) && p
<= &CYCLESREG
)
456 return greg_names
[p
- &DREG (0)];
457 else if (p
== &AXREG (0))
458 return greg_names
[4 * 8 + 0];
459 else if (p
== &AWREG (0))
460 return greg_names
[4 * 8 + 1];
461 else if (p
== &AXREG (1))
462 return greg_names
[4 * 8 + 2];
463 else if (p
== &AWREG (1))
464 return greg_names
[4 * 8 + 3];
465 else if (p
== &ASTATREG (av0
))
467 else if (p
== &ASTATREG (av0s
))
468 return "ASTAT[av0s]";
469 else if (p
== &ASTATREG (av1
))
471 else if (p
== &ASTATREG (av1s
))
472 return "ASTAT[av1s]";
473 else if (p
== &ASTATREG (v
))
475 else if (p
== &ASTATREG (vs
))
477 else if (p
== &ASTATREG (v_copy
))
478 return "ASTAT[v_copy]";
479 else if (p
== &ASTATREG (az
))
481 else if (p
== &ASTATREG (an
))
483 else if (p
== &ASTATREG (az
))
485 else if (p
== &ASTATREG (ac0
))
487 else if (p
== &ASTATREG (ac0_copy
))
488 return "ASTAT[ac0_copy]";
491 /* Worry about this when we start to STORE() it. */
492 sim_io_eprintf (CPU_STATE (cpu
), "STORE(): unknown register\n");
498 queue_store (SIM_CPU
*cpu
, bu32
*addr
, bu32 val
)
500 struct store
*s
= &BFIN_CPU_STATE
.stores
[BFIN_CPU_STATE
.n_stores
];
503 TRACE_REGISTER (cpu
, "queuing write %s = %#x",
504 get_store_name (cpu
, addr
), val
);
505 ++BFIN_CPU_STATE
.n_stores
;
507 #define STORE(X, Y) \
509 if (BFIN_CPU_STATE.n_stores == 20) abort (); \
510 queue_store (cpu, &(X), (Y)); \
514 setflags_nz (SIM_CPU
*cpu
, bu32 val
)
516 SET_ASTATREG (az
, val
== 0);
517 SET_ASTATREG (an
, val
>> 31);
521 setflags_nz_2x16 (SIM_CPU
*cpu
, bu32 val
)
523 SET_ASTATREG (an
, (bs16
)val
< 0 || (bs16
)(val
>> 16) < 0);
524 SET_ASTATREG (az
, (bs16
)val
== 0 || (bs16
)(val
>> 16) == 0);
528 setflags_logical (SIM_CPU
*cpu
, bu32 val
)
530 setflags_nz (cpu
, val
);
531 SET_ASTATREG (ac0
, 0);
536 add_brev (bu32 addend1
, bu32 addend2
)
545 for (i
= 31; i
>= 0; --i
)
547 b
= ((addend1
& mask
) >> i
) + ((addend2
& mask
) >> i
);
558 /* This is a bit crazy, but we want to simulate the hardware behavior exactly
559 rather than worry about the circular buffers being used correctly. Which
560 isn't to say there isn't room for improvement here, just that we want to
561 be conservative. See also dagsub(). */
563 dagadd (SIM_CPU
*cpu
, int dagno
, bs32 M
)
565 bu64 i
= IREG (dagno
);
566 bu64 l
= LREG (dagno
);
567 bu64 b
= BREG (dagno
);
571 bu32 im32
, iml32
, lb32
, res
;
574 /* A naïve implementation that mostly works:
576 if (l && res >= b + l)
578 STORE (IREG (dagno), res);
593 if ((i
& msb
) || (IM
& car
))
594 res
= (im32
< b
) ? iml32
: im32
;
596 res
= (im32
< b
) ? im32
: iml32
;
602 if ((IM
& car
) == (LB
& car
))
603 res
= (im32
< lb32
) ? im32
: iml32
;
605 res
= (im32
< lb32
) ? iml32
: im32
;
608 STORE (IREG (dagno
), res
);
612 /* See dagadd() notes above. */
614 dagsub (SIM_CPU
*cpu
, int dagno
, bs32 M
)
616 bu64 i
= IREG (dagno
);
617 bu64 l
= LREG (dagno
);
618 bu64 b
= BREG (dagno
);
621 bu64 mbar
= (bu32
)(~m
+ 1);
623 bu32 b32
, im32
, iml32
, lb32
, res
;
626 /* A naïve implementation that mostly works:
630 STORE (IREG (dagno), newi);
645 if (!!((i
& msb
) && (IM
& car
)) == !!(LB
& car
))
646 res
= (im32
< lb32
) ? im32
: iml32
;
648 res
= (im32
< lb32
) ? iml32
: im32
;
655 if (M
== 0 || IM
& car
)
656 res
= (im32
< b32
) ? iml32
: im32
;
658 res
= (im32
< b32
) ? im32
: iml32
;
661 STORE (IREG (dagno
), res
);
666 ashiftrt (SIM_CPU
*cpu
, bu40 val
, int cnt
, int size
)
668 int real_cnt
= cnt
> size
? size
: cnt
;
669 bu40 sgn
= ~(((val
& 0xFFFFFFFFFFull
) >> (size
- 1)) - 1);
670 int sgncnt
= size
- real_cnt
;
672 sgn
<<= 16, sgncnt
-= 16;
675 val
>>= 16, real_cnt
-= 16;
678 SET_ASTATREG (an
, val
>> (size
- 1));
679 SET_ASTATREG (az
, val
== 0);
680 /* XXX: Need to check ASTAT[v] behavior here. */
686 lshiftrt (SIM_CPU
*cpu
, bu64 val
, int cnt
, int size
)
688 int real_cnt
= cnt
> size
? size
: cnt
;
690 val
>>= 16, real_cnt
-= 16;
701 val
&= 0xFFFFFFFFFFull
;
704 illegal_instruction (cpu
);
707 SET_ASTATREG (an
, val
>> (size
- 1));
708 SET_ASTATREG (az
, val
== 0);
714 lshift (SIM_CPU
*cpu
, bu64 val
, int cnt
, int size
, bool saturate
)
716 int i
, j
, real_cnt
= cnt
> size
? size
: cnt
;
717 bu64 sgn
= ~((val
>> (size
- 1)) - 1);
718 int mask_cnt
= size
- 1;
719 bu64 masked
, new_val
= val
, tmp
;
727 new_val
<<= 16, real_cnt
-= 16;
729 new_val
<<= real_cnt
;
731 masked
= new_val
& mask
;
733 /* If an operation would otherwise cause a positive value to overflow
734 and become negative, instead, saturation limits the result to the
735 maximum positive value for the size register being used.
737 Conversely, if an operation would otherwise cause a negative value
738 to overflow and become positive, saturation limits the result to the
739 maximum negative value for the register size.
741 However, it's a little more complex than looking at sign bits, we need
742 to see if we are shifting the sign information away... */
743 tmp
= val
& ((~mask
<< 1) | 1);
746 for (i
= 1; i
<= real_cnt
&& saturate
; i
++)
748 if ((tmp
& ((bu64
)1 << (size
- 1))) !=
749 (((val
>> mask_cnt
) & 0x1) << mask_cnt
))
753 saturate
&= (!sgn
&& (new_val
& (1 << mask_cnt
)))
754 || (sgn
&& !(new_val
& (1 << mask_cnt
)));
759 if (j
|| (saturate
&& (new_val
& mask
)))
760 new_val
= sgn
== 0 ? 0x7fff : 0x8000, saturate
= 1;
764 new_val
&= 0xFFFFFFFF;
765 masked
&= 0xFFFFFFFF;
766 if (j
|| (saturate
&& ((sgn
!= masked
) || (!sgn
&& new_val
== 0))))
767 new_val
= sgn
== 0 ? 0x7fffffff : 0x80000000, saturate
= 1;
770 new_val
&= 0xFFFFFFFFFFull
;
771 masked
&= 0xFFFFFFFFFFull
;
774 illegal_instruction (cpu
);
778 SET_ASTATREG (an
, new_val
>> (size
- 1));
779 SET_ASTATREG (az
, new_val
== 0);
780 SET_ASTATREG (v
, !!(saturate
|| j
));
782 SET_ASTATREG (vs
, 1);
787 algn (bu32 l
, bu32 h
, bu32 aln
)
792 return (l
>> (8 * aln
)) | (h
<< (32 - 8 * aln
));
796 saturate_s16 (bu64 val
, bu32
*overflow
)
798 if ((bs64
)val
< -0x8000ll
)
804 if ((bs64
)val
> 0x7fff)
814 rot40 (bu40 val
, int shift
, bu32
*cc
)
816 const int nbits
= 40;
819 shift
= CLAMP (shift
, -nbits
, nbits
);
823 /* Reduce everything to rotate left. */
827 ret
= shift
== nbits
? 0 : val
<< shift
;
828 ret
|= shift
== 1 ? 0 : val
>> ((nbits
+ 1) - shift
);
829 ret
|= (bu40
)*cc
<< (shift
- 1);
830 *cc
= (val
>> (nbits
- shift
)) & 1;
836 rot32 (bu32 val
, int shift
, bu32
*cc
)
838 const int nbits
= 32;
841 shift
= CLAMP (shift
, -nbits
, nbits
);
845 /* Reduce everything to rotate left. */
849 ret
= shift
== nbits
? 0 : val
<< shift
;
850 ret
|= shift
== 1 ? 0 : val
>> ((nbits
+ 1) - shift
);
851 ret
|= (bu32
)*cc
<< (shift
- 1);
852 *cc
= (val
>> (nbits
- shift
)) & 1;
858 add32 (SIM_CPU
*cpu
, bu32 a
, bu32 b
, int carry
, int sat
)
860 int flgs
= (a
>> 31) & 1;
861 int flgo
= (b
>> 31) & 1;
863 int flgn
= (v
>> 31) & 1;
864 int overflow
= (flgs
^ flgn
) & (flgo
^ flgn
);
871 flgn
= (v
>> 31) & 1;
874 SET_ASTATREG (an
, flgn
);
876 SET_ASTATREG (vs
, 1);
877 SET_ASTATREG (v
, overflow
);
878 ASTATREG (v_internal
) |= overflow
;
879 SET_ASTATREG (az
, v
== 0);
881 SET_ASTATREG (ac0
, ~a
< b
);
887 sub32 (SIM_CPU
*cpu
, bu32 a
, bu32 b
, int carry
, int sat
, int parallel
)
889 int flgs
= (a
>> 31) & 1;
890 int flgo
= (b
>> 31) & 1;
892 int flgn
= (v
>> 31) & 1;
893 int overflow
= (flgs
^ flgo
) & (flgn
^ flgs
);
900 flgn
= (v
>> 31) & 1;
903 if (!parallel
|| flgn
)
904 SET_ASTATREG (an
, flgn
);
906 SET_ASTATREG (vs
, 1);
907 if (!parallel
|| overflow
)
908 SET_ASTATREG (v
, overflow
);
909 if (!parallel
|| overflow
)
910 ASTATREG (v_internal
) |= overflow
;
911 if (!parallel
|| v
== 0)
912 SET_ASTATREG (az
, v
== 0);
913 if (carry
&& (!parallel
|| b
<= a
))
914 SET_ASTATREG (ac0
, b
<= a
);
920 add16 (SIM_CPU
*cpu
, bu16 a
, bu16 b
, bu32
*carry
, bu32
*overfl
,
921 bu32
*zero
, bu32
*neg
, int sat
, int scale
)
923 int flgs
= (a
>> 15) & 1;
924 int flgo
= (b
>> 15) & 1;
925 bs64 v
= (bs16
)a
+ (bs16
)b
;
926 int flgn
= (v
>> 15) & 1;
927 int overflow
= (flgs
^ flgn
) & (flgo
^ flgn
);
935 v
= (a
>> 1) + (a
& 0x8000) + (b
>> 1) + (b
& 0x8000)
936 + (((a
& 1) + (b
& 1)) >> 1);
944 illegal_instruction (cpu
);
947 flgn
= (v
>> 15) & 1;
948 overflow
= (flgs
^ flgn
) & (flgo
^ flgn
);
950 if (v
> (bs64
)0xffff)
954 v
= saturate_s16 (v
, 0);
957 *neg
|= (v
>> 15) & 1;
961 *zero
|= (v
& 0xFFFF) == 0;
963 *carry
|= ((bu16
)~a
< (bu16
)b
);
969 sub16 (SIM_CPU
*cpu
, bu16 a
, bu16 b
, bu32
*carry
, bu32
*overfl
,
970 bu32
*zero
, bu32
*neg
, int sat
, int scale
)
972 int flgs
= (a
>> 15) & 1;
973 int flgo
= (b
>> 15) & 1;
974 bs64 v
= (bs16
)a
- (bs16
)b
;
975 int flgn
= (v
>> 15) & 1;
976 int overflow
= (flgs
^ flgo
) & (flgn
^ flgs
);
985 v
= ((a
>> 1) + (a
& 0x8000)) - ( (b
>> 1) + (b
& 0x8000))
986 + (((a
& 1)-(b
& 1)));
989 v
= ((v
& 0xFFFF) >> 1);
990 if ((!flgs
& !flgo
& flgn
)
991 || (flgs
& !flgo
& !flgn
)
992 || (flgs
& flgo
& flgn
)
993 || (flgs
& !flgo
& flgn
))
997 flgn
= (v
>> 15) & 1;
998 overflow
= (flgs
^ flgo
) & (flgn
^ flgs
);
1003 if (v
> (bs64
)0x7fff || v
< (bs64
)-0xffff)
1007 illegal_instruction (cpu
);
1012 v
= saturate_s16 (v
, 0);
1015 *neg
|= (v
>> 15) & 1;
1017 *zero
|= (v
& 0xFFFF) == 0;
1019 *overfl
|= overflow
;
1021 *carry
|= (bu16
)b
<= (bu16
)a
;
1026 min32 (SIM_CPU
*cpu
, bu32 a
, bu32 b
)
1029 if ((bs32
)a
> (bs32
)b
)
1031 setflags_nz (cpu
, val
);
1032 SET_ASTATREG (v
, 0);
1037 max32 (SIM_CPU
*cpu
, bu32 a
, bu32 b
)
1040 if ((bs32
)a
< (bs32
)b
)
1042 setflags_nz (cpu
, val
);
1043 SET_ASTATREG (v
, 0);
1048 min2x16 (SIM_CPU
*cpu
, bu32 a
, bu32 b
)
1051 if ((bs16
)a
> (bs16
)b
)
1052 val
= (val
& 0xFFFF0000) | (b
& 0xFFFF);
1053 if ((bs16
)(a
>> 16) > (bs16
)(b
>> 16))
1054 val
= (val
& 0xFFFF) | (b
& 0xFFFF0000);
1055 setflags_nz_2x16 (cpu
, val
);
1056 SET_ASTATREG (v
, 0);
1061 max2x16 (SIM_CPU
*cpu
, bu32 a
, bu32 b
)
1064 if ((bs16
)a
< (bs16
)b
)
1065 val
= (val
& 0xFFFF0000) | (b
& 0xFFFF);
1066 if ((bs16
)(a
>> 16) < (bs16
)(b
>> 16))
1067 val
= (val
& 0xFFFF) | (b
& 0xFFFF0000);
1068 setflags_nz_2x16 (cpu
, val
);
1069 SET_ASTATREG (v
, 0);
1074 add_and_shift (SIM_CPU
*cpu
, bu32 a
, bu32 b
, int shift
)
1077 ASTATREG (v_internal
) = 0;
1078 v
= add32 (cpu
, a
, b
, 0, 0);
1081 int x
= (v
>> 30) & 0x3;
1082 if (x
== 1 || x
== 2)
1083 ASTATREG (v_internal
) = 1;
1086 SET_ASTATREG (az
, v
== 0);
1087 SET_ASTATREG (an
, v
& 0x80000000);
1088 SET_ASTATREG (v
, ASTATREG (v_internal
));
1090 SET_ASTATREG (vs
, 1);
1095 xor_reduce (bu64 acc0
, bu64 acc1
)
1099 for (i
= 0; i
< 40; ++i
)
1101 v
^= (acc0
& acc1
& 1);
1108 /* DIVS ( Dreg, Dreg ) ;
1109 Initialize for DIVQ. Set the AQ status bit based on the signs of
1110 the 32-bit dividend and the 16-bit divisor. Left shift the dividend
1111 one bit. Copy AQ into the dividend LSB. */
1113 divs (SIM_CPU
*cpu
, bu32 pquo
, bu16 divisor
)
1115 bu16 r
= pquo
>> 16;
1118 aq
= (r
^ divisor
) >> 15; /* Extract msb's and compute quotient bit. */
1119 SET_ASTATREG (aq
, aq
); /* Update global quotient state. */
1123 pquo
= (pquo
& 0x1FFFF) | (r
<< 17);
1127 /* DIVQ ( Dreg, Dreg ) ;
1128 Based on AQ status bit, either add or subtract the divisor from
1129 the dividend. Then set the AQ status bit based on the MSBs of the
1130 32-bit dividend and the 16-bit divisor. Left shift the dividend one
1131 bit. Copy the logical inverse of AQ into the dividend LSB. */
1133 divq (SIM_CPU
*cpu
, bu32 pquo
, bu16 divisor
)
1135 unsigned short af
= pquo
>> 16;
1144 aq
= (r
^ divisor
) >> 15; /* Extract msb's and compute quotient bit. */
1145 SET_ASTATREG (aq
, aq
); /* Update global quotient state. */
1149 pquo
= (pquo
& 0x1FFFF) | (r
<< 17);
1154 Count the number of bits set to 1 in the 32bit value. */
1162 for (i
= 0; i
< 32; ++i
)
1163 ret
+= !!(val
& (1 << i
));
1169 reg_check_sup (SIM_CPU
*cpu
, int grp
, int reg
)
1172 cec_require_supervisor (cpu
);
1176 reg_write (SIM_CPU
*cpu
, int grp
, int reg
, bu32 value
)
1180 /* ASTAT is special! */
1181 if (grp
== 4 && reg
== 6)
1187 /* Check supervisor after get_allreg() so exception order is correct. */
1188 whichreg
= get_allreg (cpu
, grp
, reg
);
1189 reg_check_sup (cpu
, grp
, reg
);
1191 if (whichreg
== &CYCLES2REG
)
1192 /* Writes to CYCLES2 goes to the shadow. */
1193 whichreg
= &CYCLES2SHDREG
;
1194 else if (whichreg
== &SEQSTATREG
)
1195 /* Register is read only -- discard writes. */
1197 else if (whichreg
== &EMUDAT_INREG
)
1198 /* Writes to EMUDAT goes to the output. */
1199 whichreg
= &EMUDAT_OUTREG
;
1200 else if (whichreg
== <REG (0) || whichreg
== <REG (1))
1201 /* Writes to LT clears LSB automatically. */
1203 else if (whichreg
== &AXREG (0) || whichreg
== &AXREG (1))
1206 TRACE_REGISTER (cpu
, "wrote %s = %#x", get_allreg_name (grp
, reg
), value
);
1212 reg_read (SIM_CPU
*cpu
, int grp
, int reg
)
1217 /* ASTAT is special! */
1218 if (grp
== 4 && reg
== 6)
1221 /* Check supervisor after get_allreg() so exception order is correct. */
1222 whichreg
= get_allreg (cpu
, grp
, reg
);
1223 reg_check_sup (cpu
, grp
, reg
);
1227 if (whichreg
== &CYCLESREG
)
1228 /* Reads of CYCLES reloads CYCLES2 from the shadow. */
1229 SET_CYCLES2REG (CYCLES2SHDREG
);
1230 else if ((whichreg
== &AXREG (1) || whichreg
== &AXREG (0)) && (value
& 0x80))
1231 /* Sign extend if necessary. */
1232 value
|= 0xFFFFFF00;
1238 get_extended_cycles (SIM_CPU
*cpu
)
1240 return ((bu64
)CYCLES2SHDREG
<< 32) | CYCLESREG
;
1243 /* We can't re-use sim_events_time() because the CYCLES registers may be
1244 written/cleared/reset/stopped/started at any time by software. */
1246 cycles_inc (SIM_CPU
*cpu
, bu32 inc
)
1251 if (!(SYSCFGREG
& SYSCFG_CCEN
))
1254 cycles
= get_extended_cycles (cpu
) + inc
;
1255 SET_CYCLESREG (cycles
);
1256 cycles2
= cycles
>> 32;
1257 if (CYCLES2SHDREG
!= cycles2
)
1258 SET_CYCLES2SHDREG (cycles2
);
1262 get_unextended_acc (SIM_CPU
*cpu
, int which
)
1264 return ((bu64
)(AXREG (which
) & 0xff) << 32) | AWREG (which
);
1268 get_extended_acc (SIM_CPU
*cpu
, int which
)
1270 bu64 acc
= AXREG (which
);
1271 /* Sign extend accumulator values before adding. */
1277 acc
|= AWREG (which
);
1281 /* Perform a multiplication of D registers SRC0 and SRC1, sign- or
1282 zero-extending the result to 64 bit. H0 and H1 determine whether the
1283 high part or the low part of the source registers is used. Store 1 in
1284 *PSAT if saturation occurs, 0 otherwise. */
1286 decode_multfunc (SIM_CPU
*cpu
, int h0
, int h1
, int src0
, int src1
, int mmod
,
1289 bu32 s0
= DREG (src0
), s1
= DREG (src1
);
1303 sgn0
= -(s0
& 0x8000);
1304 sgn1
= -(s1
& 0x8000);
1326 illegal_instruction (cpu
);
1330 /* Perform shift correction if appropriate for the mode. */
1332 if (!MM
&& (mmod
== 0 || mmod
== M_T
|| mmod
== M_S2RND
|| mmod
== M_W32
))
1334 if (val
== 0x40000000)
1347 if (mmod
== 0 || mmod
== M_IS
|| mmod
== M_T
|| mmod
== M_S2RND
1348 || mmod
== M_ISS2
|| mmod
== M_IH
|| (MM
&& mmod
== M_FU
))
1349 val1
|= -(val1
& 0x80000000);
1352 val1
&= 0xFFFFFFFFull
;
1358 saturate_s40_astat (bu64 val
, bu32
*v
)
1360 if ((bs64
)val
< -((bs64
)1 << 39))
1363 return -((bs64
)1 << 39);
1365 else if ((bs64
)val
>= ((bs64
)1 << 39) - 1)
1368 return ((bu64
)1 << 39) - 1;
1370 *v
= 0; /* No overflow. */
1375 saturate_s40 (bu64 val
)
1378 return saturate_s40_astat (val
, &v
);
1382 saturate_s32 (bu64 val
, bu32
*overflow
)
1384 if ((bs64
)val
< -0x80000000ll
)
1390 if ((bs64
)val
> 0x7fffffff)
1400 saturate_u32 (bu64 val
, bu32
*overflow
)
1402 if (val
> 0xffffffff)
1412 saturate_u16 (bu64 val
, bu32
*overflow
)
1428 /* FIXME: Should honour rounding mode. */
1429 if ((val
& 0xffff) > 0x8000
1430 || ((val
& 0xffff) == 0x8000 && (val
& 0x10000)))
1433 sgnbits
= val
& 0xffff000000000000ull
;
1435 return val
| sgnbits
;
1441 bu64 sgnbits
= val
& 0xffff000000000000ull
;
1443 return val
| sgnbits
;
1447 signbits (bu64 val
, int size
)
1449 bu64 mask
= (bu64
)1 << (size
- 1);
1450 bu64 bit
= val
& mask
;
1458 if ((val
& mask
) != bit
)
1468 /* Extract a 16 or 32 bit value from a 64 bit multiplication result.
1469 These 64 bits must be sign- or zero-extended properly from the source
1470 we want to extract, either a 32 bit multiply or a 40 bit accumulator. */
1473 extract_mult (SIM_CPU
*cpu
, bu64 res
, int mmod
, int MM
,
1474 int fullword
, bu32
*overflow
)
1481 return saturate_s32 (res
, overflow
);
1483 return saturate_u32 (res
, overflow
);
1486 return saturate_s32 (res
, overflow
);
1487 return saturate_u32 (res
, overflow
);
1490 return saturate_s32 (res
<< 1, overflow
);
1492 illegal_instruction (cpu
);
1499 return saturate_s16 (rnd16 (res
), overflow
);
1501 return saturate_s32 (rnd16 (res
), overflow
) & 0xFFFF;
1503 return saturate_s16 (res
, overflow
);
1506 return saturate_s16 (rnd16 (res
), overflow
);
1507 return saturate_u16 (rnd16 (res
), overflow
);
1510 return saturate_s16 (res
, overflow
);
1511 return saturate_u16 (res
, overflow
);
1514 return saturate_s16 (trunc16 (res
), overflow
);
1516 return saturate_u16 (trunc16 (res
), overflow
);
1519 return saturate_s16 (rnd16 (res
<< 1), overflow
);
1521 return saturate_s16 (res
<< 1, overflow
);
1523 illegal_instruction (cpu
);
1528 decode_macfunc (SIM_CPU
*cpu
, int which
, int op
, int h0
, int h1
, int src0
,
1529 int src1
, int mmod
, int MM
, int fullword
, bu32
*overflow
)
1534 /* Sign extend accumulator if necessary, otherwise unsigned. */
1535 if (mmod
== 0 || mmod
== M_T
|| mmod
== M_IS
|| mmod
== M_ISS2
1536 || mmod
== M_S2RND
|| mmod
== M_IH
|| mmod
== M_W32
)
1537 acc
= get_extended_acc (cpu
, which
);
1539 acc
= get_unextended_acc (cpu
, which
);
1541 if (MM
&& (mmod
== M_T
|| mmod
== M_IS
|| mmod
== M_ISS2
1542 || mmod
== M_S2RND
|| mmod
== M_IH
|| mmod
== M_W32
))
1543 acc
|= -(acc
& 0x80000000);
1547 bu8 sgn0
= (acc
>> 31) & 1;
1548 /* This can't saturate, so we don't keep track of the sat flag. */
1549 bu64 res
= decode_multfunc (cpu
, h0
, h1
, src0
, src1
, mmod
,
1552 /* Perform accumulation. */
1557 sgn0
= (acc
>> 31) & 1;
1575 if ((bs64
)acc
< -((bs64
)1 << 39))
1576 acc
= -((bu64
)1 << 39), sat
= 1;
1577 else if ((bs64
)acc
> 0x7fffffffffll
)
1578 acc
= 0x7fffffffffull
, sat
= 1;
1581 if (!MM
&& acc
> 0xFFFFFFFFFFull
)
1583 if (MM
&& acc
> 0xFFFFFFFF)
1587 if (acc
& 0x8000000000000000ull
)
1589 if (acc
> 0xFFFFFFFFFFull
)
1590 acc
&= 0xFFFFFFFFFFull
, sat
= 1;
1591 if (MM
&& acc
> 0xFFFFFFFF)
1593 if (acc
& 0x80000000)
1594 acc
|= 0xffffffff00000000ull
;
1597 if (!MM
&& (bs64
)acc
< 0)
1599 if (MM
&& (bs64
)acc
< -((bs64
)1 << 39))
1600 acc
= -((bu64
)1 << 39), sat
= 1;
1601 if (!MM
&& (bs64
)acc
> (bs64
)0xFFFFFFFFFFll
)
1602 acc
= 0xFFFFFFFFFFull
, sat
= 1;
1603 if (MM
&& acc
> 0xFFFFFFFFFFull
)
1604 acc
&= 0xFFFFFFFFFFull
;
1605 if (MM
&& acc
& 0x80000000)
1606 acc
|= 0xffffffff00000000ull
;
1609 if ((bs64
)acc
< -0x80000000ll
)
1610 acc
= -0x80000000ull
, sat
= 1;
1611 else if ((bs64
)acc
>= 0x7fffffffll
)
1612 acc
= 0x7fffffffull
, sat
= 1;
1615 if (sgn0
&& (sgn0
!= ((acc
>> 31) & 1))
1616 && (((acc
>> 32) & 0xFF) == 0xff))
1619 if (acc
& 0x80000000)
1620 acc
|= 0xffffffff00000000ull
;
1623 illegal_instruction (cpu
);
1627 STORE (AXREG (which
), (acc
>> 32) & 0xff);
1628 STORE (AWREG (which
), acc
& 0xffffffff);
1629 STORE (ASTATREG (av
[which
]), sat
);
1631 STORE (ASTATREG (avs
[which
]), sat
);
1633 return extract_mult (cpu
, acc
, mmod
, MM
, fullword
, overflow
);
1637 hwloop_get_next_pc (SIM_CPU
*cpu
, bu32 pc
, bu32 insn_len
)
1644 /* If our PC has reached the bottom of a hardware loop,
1645 move back up to the top of the hardware loop. */
1646 for (i
= 1; i
>= 0; --i
)
1647 if (LCREG (i
) > 1 && pc
== LBREG (i
))
1649 TRACE_BRANCH (cpu
, pc
, LTREG (i
), i
, "Hardware loop %i", i
);
1653 return pc
+ insn_len
;
1657 decode_ProgCtrl_0 (SIM_CPU
*cpu
, bu16 iw0
, bu32 pc
)
1660 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
1661 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |.prgfunc.......|.poprnd........|
1662 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
1663 int poprnd
= ((iw0
>> ProgCtrl_poprnd_bits
) & ProgCtrl_poprnd_mask
);
1664 int prgfunc
= ((iw0
>> ProgCtrl_prgfunc_bits
) & ProgCtrl_prgfunc_mask
);
1666 TRACE_EXTRACT (cpu
, "%s: poprnd:%i prgfunc:%i", __func__
, poprnd
, prgfunc
);
1668 if (prgfunc
== 0 && poprnd
== 0)
1670 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_nop
);
1671 TRACE_INSN (cpu
, "NOP;");
1673 else if (prgfunc
== 1 && poprnd
== 0)
1675 bu32 newpc
= RETSREG
;
1676 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1677 TRACE_INSN (cpu
, "RTS;");
1678 IFETCH_CHECK (newpc
);
1680 illegal_instruction_combination (cpu
);
1681 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "RTS");
1683 BFIN_CPU_STATE
.did_jump
= true;
1686 else if (prgfunc
== 1 && poprnd
== 1)
1688 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1689 TRACE_INSN (cpu
, "RTI;");
1690 /* Do not do IFETCH_CHECK here -- LSB has special meaning. */
1692 illegal_instruction_combination (cpu
);
1693 cec_return (cpu
, -1);
1696 else if (prgfunc
== 1 && poprnd
== 2)
1698 bu32 newpc
= RETXREG
;
1699 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1700 TRACE_INSN (cpu
, "RTX;");
1701 /* XXX: Not sure if this is what the hardware does. */
1702 IFETCH_CHECK (newpc
);
1704 illegal_instruction_combination (cpu
);
1705 cec_return (cpu
, IVG_EVX
);
1708 else if (prgfunc
== 1 && poprnd
== 3)
1710 bu32 newpc
= RETNREG
;
1711 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1712 TRACE_INSN (cpu
, "RTN;");
1713 /* XXX: Not sure if this is what the hardware does. */
1714 IFETCH_CHECK (newpc
);
1716 illegal_instruction_combination (cpu
);
1717 cec_return (cpu
, IVG_NMI
);
1720 else if (prgfunc
== 1 && poprnd
== 4)
1722 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1723 TRACE_INSN (cpu
, "RTE;");
1725 illegal_instruction_combination (cpu
);
1726 cec_return (cpu
, IVG_EMU
);
1729 else if (prgfunc
== 2 && poprnd
== 0)
1731 SIM_DESC sd
= CPU_STATE (cpu
);
1732 sim_events
*events
= STATE_EVENTS (sd
);
1734 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_sync
);
1735 /* XXX: in supervisor mode, utilizes wake up sources
1736 in user mode, it's a NOP ... */
1737 TRACE_INSN (cpu
, "IDLE;");
1740 illegal_instruction_combination (cpu
);
1744 CYCLE_DELAY
= events
->time_from_event
;
1746 abort (); /* XXX: Should this ever happen ? */
1748 else if (prgfunc
== 2 && poprnd
== 3)
1750 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_sync
);
1752 TRACE_INSN (cpu
, "CSYNC;");
1754 illegal_instruction_combination (cpu
);
1757 else if (prgfunc
== 2 && poprnd
== 4)
1759 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_sync
);
1761 TRACE_INSN (cpu
, "SSYNC;");
1763 illegal_instruction_combination (cpu
);
1765 /* Really 10+, but no model info for this. */
1768 else if (prgfunc
== 2 && poprnd
== 5)
1770 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1771 TRACE_INSN (cpu
, "EMUEXCPT;");
1773 illegal_instruction_combination (cpu
);
1774 cec_exception (cpu
, VEC_SIM_TRAP
);
1776 else if (prgfunc
== 3 && poprnd
< 8)
1778 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1779 TRACE_INSN (cpu
, "CLI R%i;", poprnd
);
1781 illegal_instruction_combination (cpu
);
1782 SET_DREG (poprnd
, cec_cli (cpu
));
1784 else if (prgfunc
== 4 && poprnd
< 8)
1786 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1787 TRACE_INSN (cpu
, "STI R%i;", poprnd
);
1789 illegal_instruction_combination (cpu
);
1790 cec_sti (cpu
, DREG (poprnd
));
1793 else if (prgfunc
== 5 && poprnd
< 8)
1795 bu32 newpc
= PREG (poprnd
);
1796 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1797 TRACE_INSN (cpu
, "JUMP (%s);", get_preg_name (poprnd
));
1798 IFETCH_CHECK (newpc
);
1800 illegal_instruction_combination (cpu
);
1801 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP (Preg)");
1803 BFIN_CPU_STATE
.did_jump
= true;
1804 PROFILE_BRANCH_TAKEN (cpu
);
1807 else if (prgfunc
== 6 && poprnd
< 8)
1809 bu32 newpc
= PREG (poprnd
);
1810 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1811 TRACE_INSN (cpu
, "CALL (%s);", get_preg_name (poprnd
));
1812 IFETCH_CHECK (newpc
);
1814 illegal_instruction_combination (cpu
);
1815 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "CALL (Preg)");
1816 /* If we're at the end of a hardware loop, RETS is going to be
1817 the top of the loop rather than the next instruction. */
1818 SET_RETSREG (hwloop_get_next_pc (cpu
, pc
, 2));
1820 BFIN_CPU_STATE
.did_jump
= true;
1821 PROFILE_BRANCH_TAKEN (cpu
);
1824 else if (prgfunc
== 7 && poprnd
< 8)
1826 bu32 newpc
= pc
+ PREG (poprnd
);
1827 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1828 TRACE_INSN (cpu
, "CALL (PC + %s);", get_preg_name (poprnd
));
1829 IFETCH_CHECK (newpc
);
1831 illegal_instruction_combination (cpu
);
1832 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "CALL (PC + Preg)");
1833 SET_RETSREG (hwloop_get_next_pc (cpu
, pc
, 2));
1835 BFIN_CPU_STATE
.did_jump
= true;
1836 PROFILE_BRANCH_TAKEN (cpu
);
1839 else if (prgfunc
== 8 && poprnd
< 8)
1841 bu32 newpc
= pc
+ PREG (poprnd
);
1842 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1843 TRACE_INSN (cpu
, "JUMP (PC + %s);", get_preg_name (poprnd
));
1844 IFETCH_CHECK (newpc
);
1846 illegal_instruction_combination (cpu
);
1847 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP (PC + Preg)");
1849 BFIN_CPU_STATE
.did_jump
= true;
1850 PROFILE_BRANCH_TAKEN (cpu
);
1853 else if (prgfunc
== 9)
1855 int raise
= uimm4 (poprnd
);
1856 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1857 TRACE_INSN (cpu
, "RAISE %s;", uimm4_str (raise
));
1859 illegal_instruction_combination (cpu
);
1860 cec_require_supervisor (cpu
);
1861 if (raise
== IVG_IVHW
)
1862 cec_hwerr (cpu
, HWERR_RAISE_5
);
1864 cec_latch (cpu
, raise
);
1865 CYCLE_DELAY
= 3; /* XXX: Only if IVG is unmasked. */
1867 else if (prgfunc
== 10)
1869 int excpt
= uimm4 (poprnd
);
1870 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1871 TRACE_INSN (cpu
, "EXCPT %s;", uimm4_str (excpt
));
1873 illegal_instruction_combination (cpu
);
1874 cec_exception (cpu
, excpt
);
1877 else if (prgfunc
== 11 && poprnd
< 6)
1879 bu32 addr
= PREG (poprnd
);
1881 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_atomic
);
1882 TRACE_INSN (cpu
, "TESTSET (%s);", get_preg_name (poprnd
));
1884 illegal_instruction_combination (cpu
);
1885 byte
= GET_WORD (addr
);
1886 SET_CCREG (byte
== 0);
1887 PUT_BYTE (addr
, byte
| 0x80);
1888 /* Also includes memory stalls, but we don't model that. */
1892 illegal_instruction (cpu
);
1896 decode_CaCTRL_0 (SIM_CPU
*cpu
, bu16 iw0
)
1899 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
1900 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 |.a.|.op....|.reg.......|
1901 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
1902 int a
= ((iw0
>> CaCTRL_a_bits
) & CaCTRL_a_mask
);
1903 int op
= ((iw0
>> CaCTRL_op_bits
) & CaCTRL_op_mask
);
1904 int reg
= ((iw0
>> CaCTRL_reg_bits
) & CaCTRL_reg_mask
);
1905 bu32 preg
= PREG (reg
);
1906 const char * const sinsn
[] = { "PREFETCH", "FLUSHINV", "FLUSH", "IFLUSH", };
1908 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CaCTRL
);
1909 TRACE_EXTRACT (cpu
, "%s: a:%i op:%i reg:%i", __func__
, a
, op
, reg
);
1910 TRACE_INSN (cpu
, "%s [%s%s];", sinsn
[op
], get_preg_name (reg
), a
? "++" : "");
1913 /* None of these can be part of a parallel instruction. */
1914 illegal_instruction_combination (cpu
);
1916 /* No cache simulation, so these are (mostly) all NOPs.
1917 XXX: The hardware takes care of masking to cache lines, but need
1918 to check behavior of the post increment. Should we be aligning
1919 the value to the cache line before adding the cache line size, or
1920 do we just add the cache line size ? */
1923 mmu_check_cache_addr (cpu
, preg
, false, false);
1927 mmu_check_cache_addr (cpu
, preg
, true, false);
1931 mmu_check_cache_addr (cpu
, preg
, true, false);
1935 mmu_check_cache_addr (cpu
, preg
, false, true);
1939 SET_PREG (reg
, preg
+ BFIN_L1_CACHE_BYTES
);
1943 decode_PushPopReg_0 (SIM_CPU
*cpu
, bu16 iw0
)
1946 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
1947 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |.W.|.grp.......|.reg.......|
1948 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
1949 int W
= ((iw0
>> PushPopReg_W_bits
) & PushPopReg_W_mask
);
1950 int grp
= ((iw0
>> PushPopReg_grp_bits
) & PushPopReg_grp_mask
);
1951 int reg
= ((iw0
>> PushPopReg_reg_bits
) & PushPopReg_reg_mask
);
1952 const char *reg_name
= get_allreg_name (grp
, reg
);
1956 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_PushPopReg
);
1957 TRACE_EXTRACT (cpu
, "%s: W:%i grp:%i reg:%i", __func__
, W
, grp
, reg
);
1958 TRACE_DECODE (cpu
, "%s: reg:%s", __func__
, reg_name
);
1960 /* Can't push/pop reserved registers */
1961 if (reg_is_reserved (grp
, reg
))
1962 illegal_instruction (cpu
);
1966 /* Dreg and Preg are not supported by this instruction. */
1967 if (grp
== 0 || grp
== 1)
1968 illegal_instruction (cpu
);
1969 TRACE_INSN (cpu
, "%s = [SP++];", reg_name
);
1970 /* Can't pop USP while in userspace. */
1971 if (INSN_LEN
== 8 || (grp
== 7 && reg
== 0 && cec_is_user_mode(cpu
)))
1972 illegal_instruction_combination (cpu
);
1973 /* XXX: The valid register check is in reg_write(), so we might
1974 incorrectly do a GET_LONG() here ... */
1975 value
= GET_LONG (sp
);
1976 reg_write (cpu
, grp
, reg
, value
);
1977 if (grp
== 7 && reg
== 3)
1984 TRACE_INSN (cpu
, "[--SP] = %s;", reg_name
);
1985 /* Can't push SP. */
1986 if (INSN_LEN
== 8 || (grp
== 1 && reg
== 6))
1987 illegal_instruction_combination (cpu
);
1990 value
= reg_read (cpu
, grp
, reg
);
1991 if (grp
== 7 && reg
== 3)
1992 cec_push_reti (cpu
);
1994 PUT_LONG (sp
, value
);
1997 /* Note: SP update must be delayed until after all reads/writes; see
1998 comments in decode_PushPopMultiple_0() for more info. */
2003 decode_PushPopMultiple_0 (SIM_CPU
*cpu
, bu16 iw0
)
2006 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2007 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |.d.|.p.|.W.|.dr........|.pr........|
2008 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2009 int p
= ((iw0
>> PushPopMultiple_p_bits
) & PushPopMultiple_p_mask
);
2010 int d
= ((iw0
>> PushPopMultiple_d_bits
) & PushPopMultiple_d_mask
);
2011 int W
= ((iw0
>> PushPopMultiple_W_bits
) & PushPopMultiple_W_mask
);
2012 int dr
= ((iw0
>> PushPopMultiple_dr_bits
) & PushPopMultiple_dr_mask
);
2013 int pr
= ((iw0
>> PushPopMultiple_pr_bits
) & PushPopMultiple_pr_mask
);
2017 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_PushPopMultiple
);
2018 TRACE_EXTRACT (cpu
, "%s: d:%i p:%i W:%i dr:%i pr:%i",
2019 __func__
, d
, p
, W
, dr
, pr
);
2021 if ((d
== 0 && p
== 0) || (p
&& imm5 (pr
) > 5)
2022 || (d
&& !p
&& pr
) || (p
&& !d
&& dr
))
2023 illegal_instruction (cpu
);
2028 TRACE_INSN (cpu
, "[--SP] = (R7:%i, P5:%i);", dr
, pr
);
2030 TRACE_INSN (cpu
, "[--SP] = (R7:%i);", dr
);
2032 TRACE_INSN (cpu
, "[--SP] = (P5:%i);", pr
);
2035 for (i
= dr
; i
< 8; i
++)
2038 PUT_LONG (sp
, DREG (i
));
2041 for (i
= pr
; i
< 6; i
++)
2044 PUT_LONG (sp
, PREG (i
));
2052 TRACE_INSN (cpu
, "(R7:%i, P5:%i) = [SP++];", dr
, pr
);
2054 TRACE_INSN (cpu
, "(R7:%i) = [SP++];", dr
);
2056 TRACE_INSN (cpu
, "(P5:%i) = [SP++];", pr
);
2059 for (i
= 5; i
>= pr
; i
--)
2061 SET_PREG (i
, GET_LONG (sp
));
2065 for (i
= 7; i
>= dr
; i
--)
2067 SET_DREG (i
, GET_LONG (sp
));
2074 /* Note: SP update must be delayed until after all reads/writes so that
2075 if an exception does occur, the insn may be re-executed as the
2076 SP has not yet changed. */
2081 decode_ccMV_0 (SIM_CPU
*cpu
, bu16 iw0
)
2084 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2085 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |.T.|.d.|.s.|.dst.......|.src.......|
2086 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2087 int s
= ((iw0
>> CCmv_s_bits
) & CCmv_s_mask
);
2088 int d
= ((iw0
>> CCmv_d_bits
) & CCmv_d_mask
);
2089 int T
= ((iw0
>> CCmv_T_bits
) & CCmv_T_mask
);
2090 int src
= ((iw0
>> CCmv_src_bits
) & CCmv_src_mask
);
2091 int dst
= ((iw0
>> CCmv_dst_bits
) & CCmv_dst_mask
);
2092 int cond
= T
? CCREG
: ! CCREG
;
2094 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ccMV
);
2095 TRACE_EXTRACT (cpu
, "%s: T:%i d:%i s:%i dst:%i src:%i",
2096 __func__
, T
, d
, s
, dst
, src
);
2098 TRACE_INSN (cpu
, "IF %sCC %s = %s;", T
? "" : "! ",
2099 get_allreg_name (d
, dst
),
2100 get_allreg_name (s
, src
));
2102 illegal_instruction_combination (cpu
);
2105 reg_write (cpu
, d
, dst
, reg_read (cpu
, s
, src
));
2109 decode_CCflag_0 (SIM_CPU
*cpu
, bu16 iw0
)
2112 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2113 | 0 | 0 | 0 | 0 | 1 |.I.|.opc.......|.G.|.y.........|.x.........|
2114 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2115 int x
= ((iw0
>> CCflag_x_bits
) & CCflag_x_mask
);
2116 int y
= ((iw0
>> CCflag_y_bits
) & CCflag_y_mask
);
2117 int I
= ((iw0
>> CCflag_I_bits
) & CCflag_I_mask
);
2118 int G
= ((iw0
>> CCflag_G_bits
) & CCflag_G_mask
);
2119 int opc
= ((iw0
>> CCflag_opc_bits
) & CCflag_opc_mask
);
2121 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CCflag
);
2122 TRACE_EXTRACT (cpu
, "%s: I:%i opc:%i G:%i y:%i x:%i",
2123 __func__
, I
, opc
, G
, y
, x
);
2127 bs64 acc0
= get_extended_acc (cpu
, 0);
2128 bs64 acc1
= get_extended_acc (cpu
, 1);
2129 bs64 diff
= acc0
- acc1
;
2131 if (x
!= 0 || y
!= 0)
2132 illegal_instruction (cpu
);
2134 if (opc
== 5 && I
== 0 && G
== 0)
2136 TRACE_INSN (cpu
, "CC = A0 == A1;");
2138 illegal_instruction_combination (cpu
);
2139 SET_CCREG (acc0
== acc1
);
2141 else if (opc
== 6 && I
== 0 && G
== 0)
2143 TRACE_INSN (cpu
, "CC = A0 < A1");
2145 illegal_instruction_combination (cpu
);
2146 SET_CCREG (acc0
< acc1
);
2148 else if (opc
== 7 && I
== 0 && G
== 0)
2150 TRACE_INSN (cpu
, "CC = A0 <= A1");
2152 illegal_instruction_combination (cpu
);
2153 SET_CCREG (acc0
<= acc1
);
2156 illegal_instruction (cpu
);
2158 SET_ASTATREG (az
, diff
== 0);
2159 SET_ASTATREG (an
, diff
< 0);
2160 SET_ASTATREG (ac0
, (bu40
)acc1
<= (bu40
)acc0
);
2164 int issigned
= opc
< 3;
2165 const char *sign
= issigned
? "" : " (IU)";
2166 bu32 srcop
= G
? PREG (x
) : DREG (x
);
2167 char s
= G
? 'P' : 'R';
2168 bu32 dstop
= I
? (issigned
? imm3 (y
) : uimm3 (y
)) : G
? PREG (y
) : DREG (y
);
2170 char d
= G
? 'P' : 'R';
2171 int flgs
= srcop
>> 31;
2172 int flgo
= dstop
>> 31;
2174 bu32 result
= srcop
- dstop
;
2176 int flgn
= result
>> 31;
2177 int overflow
= (flgs
^ flgo
) & (flgn
^ flgs
);
2178 int az
= result
== 0;
2179 int ac0
= dstop
<= srcop
;
2182 an
= (flgn
&& !overflow
) || (!flgn
&& overflow
);
2188 default: /* Shutup useless gcc warnings. */
2189 case 0: /* signed */
2193 case 1: /* signed */
2197 case 2: /* signed */
2201 case 3: /* unsigned */
2205 case 4: /* unsigned */
2212 TRACE_INSN (cpu
, "CC = %c%i %s %s%s;", s
, x
, op
,
2213 issigned
? imm3_str (y
) : uimm3_str (y
), sign
);
2216 TRACE_DECODE (cpu
, "%s %c%i:%x %c%i:%x", __func__
,
2217 s
, x
, srcop
, d
, y
, dstop
);
2218 TRACE_INSN (cpu
, "CC = %c%i %s %c%i%s;", s
, x
, op
, d
, y
, sign
);
2222 /* Pointer compares only touch CC. */
2225 SET_ASTATREG (az
, az
);
2226 SET_ASTATREG (an
, an
);
2227 SET_ASTATREG (ac0
, ac0
);
2233 decode_CC2dreg_0 (SIM_CPU
*cpu
, bu16 iw0
)
2236 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2237 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |.op....|.reg.......|
2238 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2239 int op
= ((iw0
>> CC2dreg_op_bits
) & CC2dreg_op_mask
);
2240 int reg
= ((iw0
>> CC2dreg_reg_bits
) & CC2dreg_reg_mask
);
2242 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CC2dreg
);
2243 TRACE_EXTRACT (cpu
, "%s: op:%i reg:%i", __func__
, op
, reg
);
2247 TRACE_INSN (cpu
, "R%i = CC;", reg
);
2249 illegal_instruction_combination (cpu
);
2250 SET_DREG (reg
, CCREG
);
2254 TRACE_INSN (cpu
, "CC = R%i;", reg
);
2256 illegal_instruction_combination (cpu
);
2257 SET_CCREG (DREG (reg
) != 0);
2259 else if (op
== 3 && reg
== 0)
2261 TRACE_INSN (cpu
, "CC = !CC;");
2263 illegal_instruction_combination (cpu
);
2267 illegal_instruction (cpu
);
2271 decode_CC2stat_0 (SIM_CPU
*cpu
, bu16 iw0
)
2274 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2275 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |.D.|.op....|.cbit..............|
2276 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2277 int D
= ((iw0
>> CC2stat_D_bits
) & CC2stat_D_mask
);
2278 int op
= ((iw0
>> CC2stat_op_bits
) & CC2stat_op_mask
);
2279 int cbit
= ((iw0
>> CC2stat_cbit_bits
) & CC2stat_cbit_mask
);
2282 const char * const op_names
[] = { "", "|", "&", "^" } ;
2283 const char *astat_name
;
2284 const char * const astat_names
[32] = {
2301 astat_name
= astat_names
[cbit
];
2304 static char astat_bit
[12];
2305 sprintf (astat_bit
, "ASTAT[%i]", cbit
);
2306 astat_name
= astat_bit
;
2309 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CC2stat
);
2310 TRACE_EXTRACT (cpu
, "%s: D:%i op:%i cbit:%i", __func__
, D
, op
, cbit
);
2312 TRACE_INSN (cpu
, "%s %s= %s;", D
? astat_name
: "CC",
2313 op_names
[op
], D
? "CC" : astat_name
);
2315 /* CC = CC; is invalid. */
2317 illegal_instruction (cpu
);
2320 illegal_instruction_combination (cpu
);
2322 pval
= !!(ASTAT
& (1 << cbit
));
2326 case 0: SET_CCREG (pval
); break;
2327 case 1: SET_CCREG (CCREG
| pval
); break;
2328 case 2: SET_CCREG (CCREG
& pval
); break;
2329 case 3: SET_CCREG (CCREG
^ pval
); break;
2335 case 0: pval
= CCREG
; break;
2336 case 1: pval
|= CCREG
; break;
2337 case 2: pval
&= CCREG
; break;
2338 case 3: pval
^= CCREG
; break;
2340 if (astat_names
[cbit
])
2341 TRACE_REGISTER (cpu
, "wrote ASTAT[%s] = %i", astat_name
, pval
);
2343 TRACE_REGISTER (cpu
, "wrote %s = %i", astat_name
, pval
);
2344 SET_ASTAT ((ASTAT
& ~(1 << cbit
)) | (pval
<< cbit
));
2349 decode_BRCC_0 (SIM_CPU
*cpu
, bu16 iw0
, bu32 pc
)
2352 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2353 | 0 | 0 | 0 | 1 |.T.|.B.|.offset................................|
2354 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2355 int B
= ((iw0
>> BRCC_B_bits
) & BRCC_B_mask
);
2356 int T
= ((iw0
>> BRCC_T_bits
) & BRCC_T_mask
);
2357 int offset
= ((iw0
>> BRCC_offset_bits
) & BRCC_offset_mask
);
2358 int cond
= T
? CCREG
: ! CCREG
;
2359 int pcrel
= pcrel10 (offset
);
2361 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_BRCC
);
2362 TRACE_EXTRACT (cpu
, "%s: T:%i B:%i offset:%#x", __func__
, T
, B
, offset
);
2363 TRACE_DECODE (cpu
, "%s: pcrel10:%#x", __func__
, pcrel
);
2365 TRACE_INSN (cpu
, "IF %sCC JUMP %#x%s;", T
? "" : "! ",
2366 pcrel
, B
? " (bp)" : "");
2369 illegal_instruction_combination (cpu
);
2373 bu32 newpc
= pc
+ pcrel
;
2374 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "Conditional JUMP");
2376 BFIN_CPU_STATE
.did_jump
= true;
2377 PROFILE_BRANCH_TAKEN (cpu
);
2378 CYCLE_DELAY
= B
? 5 : 9;
2382 PROFILE_BRANCH_UNTAKEN (cpu
);
2383 CYCLE_DELAY
= B
? 9 : 1;
2388 decode_UJUMP_0 (SIM_CPU
*cpu
, bu16 iw0
, bu32 pc
)
2391 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2392 | 0 | 0 | 1 | 0 |.offset........................................|
2393 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2394 int offset
= ((iw0
>> UJump_offset_bits
) & UJump_offset_mask
);
2395 int pcrel
= pcrel12 (offset
);
2396 bu32 newpc
= pc
+ pcrel
;
2398 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_UJUMP
);
2399 TRACE_EXTRACT (cpu
, "%s: offset:%#x", __func__
, offset
);
2400 TRACE_DECODE (cpu
, "%s: pcrel12:%#x", __func__
, pcrel
);
2402 TRACE_INSN (cpu
, "JUMP.S %#x;", pcrel
);
2405 illegal_instruction_combination (cpu
);
2407 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP.S");
2410 BFIN_CPU_STATE
.did_jump
= true;
2411 PROFILE_BRANCH_TAKEN (cpu
);
2416 decode_REGMV_0 (SIM_CPU
*cpu
, bu16 iw0
)
2419 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2420 | 0 | 0 | 1 | 1 |.gd........|.gs........|.dst.......|.src.......|
2421 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2422 int gs
= ((iw0
>> RegMv_gs_bits
) & RegMv_gs_mask
);
2423 int gd
= ((iw0
>> RegMv_gd_bits
) & RegMv_gd_mask
);
2424 int src
= ((iw0
>> RegMv_src_bits
) & RegMv_src_mask
);
2425 int dst
= ((iw0
>> RegMv_dst_bits
) & RegMv_dst_mask
);
2426 const char *srcreg_name
= get_allreg_name (gs
, src
);
2427 const char *dstreg_name
= get_allreg_name (gd
, dst
);
2429 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_REGMV
);
2430 TRACE_EXTRACT (cpu
, "%s: gd:%i gs:%i dst:%i src:%i",
2431 __func__
, gd
, gs
, dst
, src
);
2432 TRACE_DECODE (cpu
, "%s: dst:%s src:%s", __func__
, dstreg_name
, srcreg_name
);
2434 TRACE_INSN (cpu
, "%s = %s;", dstreg_name
, srcreg_name
);
2436 /* Reserved slots cannot be a src/dst. */
2437 if (reg_is_reserved (gs
, src
) || reg_is_reserved (gd
, dst
))
2440 /* Standard register moves. */
2441 if ((gs
< 2) /* Dregs/Pregs src */
2442 || (gd
< 2) /* Dregs/Pregs dst */
2443 || (gs
== 4 && src
< 4) /* Accumulators src */
2444 || (gd
== 4 && dst
< 4 && (gs
< 4)) /* Accumulators dst */
2445 || (gs
== 7 && src
== 7 && !(gd
== 4 && dst
< 4)) /* EMUDAT src */
2446 || (gd
== 7 && dst
== 7)) /* EMUDAT dst */
2449 /* dareg = dareg (IMBL) */
2450 if (gs
< 4 && gd
< 4)
2453 /* USP can be src to sysregs, but not dagregs. */
2454 if ((gs
== 7 && src
== 0) && (gd
>= 4))
2457 /* USP can move between genregs (only check Accumulators). */
2458 if (((gs
== 7 && src
== 0) && (gd
== 4 && dst
< 4))
2459 || ((gd
== 7 && dst
== 0) && (gs
== 4 && src
< 4)))
2462 /* Still here ? Invalid reg pair. */
2464 illegal_instruction (cpu
);
2467 reg_write (cpu
, gd
, dst
, reg_read (cpu
, gs
, src
));
2471 decode_ALU2op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2474 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2475 | 0 | 1 | 0 | 0 | 0 | 0 |.opc...........|.src.......|.dst.......|
2476 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2477 int src
= ((iw0
>> ALU2op_src_bits
) & ALU2op_src_mask
);
2478 int opc
= ((iw0
>> ALU2op_opc_bits
) & ALU2op_opc_mask
);
2479 int dst
= ((iw0
>> ALU2op_dst_bits
) & ALU2op_dst_mask
);
2481 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ALU2op
);
2482 TRACE_EXTRACT (cpu
, "%s: opc:%i src:%i dst:%i", __func__
, opc
, src
, dst
);
2486 TRACE_INSN (cpu
, "R%i >>>= R%i;", dst
, src
);
2487 SET_DREG (dst
, ashiftrt (cpu
, DREG (dst
), DREG (src
), 32));
2492 TRACE_INSN (cpu
, "R%i >>= R%i;", dst
, src
);
2493 if (DREG (src
) <= 0x1F)
2494 val
= lshiftrt (cpu
, DREG (dst
), DREG (src
), 32);
2497 SET_DREG (dst
, val
);
2501 TRACE_INSN (cpu
, "R%i <<= R%i;", dst
, src
);
2502 SET_DREG (dst
, lshift (cpu
, DREG (dst
), DREG (src
), 32, 0));
2506 TRACE_INSN (cpu
, "R%i *= R%i;", dst
, src
);
2507 SET_DREG (dst
, DREG (dst
) * DREG (src
));
2512 TRACE_INSN (cpu
, "R%i = (R%i + R%i) << 1;", dst
, dst
, src
);
2513 SET_DREG (dst
, add_and_shift (cpu
, DREG (dst
), DREG (src
), 1));
2517 TRACE_INSN (cpu
, "R%i = (R%i + R%i) << 2;", dst
, dst
, src
);
2518 SET_DREG (dst
, add_and_shift (cpu
, DREG (dst
), DREG (src
), 2));
2522 TRACE_INSN (cpu
, "DIVQ ( R%i, R%i );", dst
, src
);
2523 SET_DREG (dst
, divq (cpu
, DREG (dst
), (bu16
)DREG (src
)));
2527 TRACE_INSN (cpu
, "DIVS ( R%i, R%i );", dst
, src
);
2528 SET_DREG (dst
, divs (cpu
, DREG (dst
), (bu16
)DREG (src
)));
2532 TRACE_INSN (cpu
, "R%i = R%i.L (X);", dst
, src
);
2533 SET_DREG (dst
, (bs32
) (bs16
) DREG (src
));
2534 setflags_logical (cpu
, DREG (dst
));
2538 TRACE_INSN (cpu
, "R%i = R%i.L (Z);", dst
, src
);
2539 SET_DREG (dst
, (bu32
) (bu16
) DREG (src
));
2540 setflags_logical (cpu
, DREG (dst
));
2544 TRACE_INSN (cpu
, "R%i = R%i.B (X);", dst
, src
);
2545 SET_DREG (dst
, (bs32
) (bs8
) DREG (src
));
2546 setflags_logical (cpu
, DREG (dst
));
2550 TRACE_INSN (cpu
, "R%i = R%i.B (Z);", dst
, src
);
2551 SET_DREG (dst
, (bu32
) (bu8
) DREG (src
));
2552 setflags_logical (cpu
, DREG (dst
));
2556 bu32 val
= DREG (src
);
2557 TRACE_INSN (cpu
, "R%i = - R%i;", dst
, src
);
2558 SET_DREG (dst
, -val
);
2559 setflags_nz (cpu
, DREG (dst
));
2560 SET_ASTATREG (v
, val
== 0x80000000);
2562 SET_ASTATREG (vs
, 1);
2563 SET_ASTATREG (ac0
, val
== 0x0);
2564 /* XXX: Documentation isn't entirely clear about av0 and av1. */
2568 TRACE_INSN (cpu
, "R%i = ~ R%i;", dst
, src
);
2569 SET_DREG (dst
, ~DREG (src
));
2570 setflags_logical (cpu
, DREG (dst
));
2573 illegal_instruction (cpu
);
2577 decode_PTR2op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2580 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2581 | 0 | 1 | 0 | 0 | 0 | 1 | 0 |.opc.......|.src.......|.dst.......|
2582 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2583 int src
= ((iw0
>> PTR2op_src_bits
) & PTR2op_dst_mask
);
2584 int opc
= ((iw0
>> PTR2op_opc_bits
) & PTR2op_opc_mask
);
2585 int dst
= ((iw0
>> PTR2op_dst_bits
) & PTR2op_dst_mask
);
2586 const char *src_name
= get_preg_name (src
);
2587 const char *dst_name
= get_preg_name (dst
);
2589 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_PTR2op
);
2590 TRACE_EXTRACT (cpu
, "%s: opc:%i src:%i dst:%i", __func__
, opc
, src
, dst
);
2594 TRACE_INSN (cpu
, "%s -= %s", dst_name
, src_name
);
2595 SET_PREG (dst
, PREG (dst
) - PREG (src
));
2599 TRACE_INSN (cpu
, "%s = %s << 2", dst_name
, src_name
);
2600 SET_PREG (dst
, PREG (src
) << 2);
2604 TRACE_INSN (cpu
, "%s = %s >> 2", dst_name
, src_name
);
2605 SET_PREG (dst
, PREG (src
) >> 2);
2609 TRACE_INSN (cpu
, "%s = %s >> 1", dst_name
, src_name
);
2610 SET_PREG (dst
, PREG (src
) >> 1);
2614 TRACE_INSN (cpu
, "%s += %s (BREV)", dst_name
, src_name
);
2615 SET_PREG (dst
, add_brev (PREG (dst
), PREG (src
)));
2619 TRACE_INSN (cpu
, "%s = (%s + %s) << 1", dst_name
, dst_name
, src_name
);
2620 SET_PREG (dst
, (PREG (dst
) + PREG (src
)) << 1);
2624 TRACE_INSN (cpu
, "%s = (%s + %s) << 2", dst_name
, dst_name
, src_name
);
2625 SET_PREG (dst
, (PREG (dst
) + PREG (src
)) << 2);
2628 illegal_instruction (cpu
);
2632 decode_LOGI2op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2635 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2636 | 0 | 1 | 0 | 0 | 1 |.opc.......|.src...............|.dst.......|
2637 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2638 int src
= ((iw0
>> LOGI2op_src_bits
) & LOGI2op_src_mask
);
2639 int opc
= ((iw0
>> LOGI2op_opc_bits
) & LOGI2op_opc_mask
);
2640 int dst
= ((iw0
>> LOGI2op_dst_bits
) & LOGI2op_dst_mask
);
2641 int uimm
= uimm5 (src
);
2642 const char *uimm_str
= uimm5_str (uimm
);
2644 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LOGI2op
);
2645 TRACE_EXTRACT (cpu
, "%s: opc:%i src:%i dst:%i", __func__
, opc
, src
, dst
);
2646 TRACE_DECODE (cpu
, "%s: uimm5:%#x", __func__
, uimm
);
2650 TRACE_INSN (cpu
, "CC = ! BITTST (R%i, %s);", dst
, uimm_str
);
2652 illegal_instruction_combination (cpu
);
2653 SET_CCREG ((~DREG (dst
) >> uimm
) & 1);
2657 TRACE_INSN (cpu
, "CC = BITTST (R%i, %s);", dst
, uimm_str
);
2659 illegal_instruction_combination (cpu
);
2660 SET_CCREG ((DREG (dst
) >> uimm
) & 1);
2664 TRACE_INSN (cpu
, "BITSET (R%i, %s);", dst
, uimm_str
);
2666 illegal_instruction_combination (cpu
);
2667 SET_DREG (dst
, DREG (dst
) | (1 << uimm
));
2668 setflags_logical (cpu
, DREG (dst
));
2672 TRACE_INSN (cpu
, "BITTGL (R%i, %s);", dst
, uimm_str
);
2674 illegal_instruction_combination (cpu
);
2675 SET_DREG (dst
, DREG (dst
) ^ (1 << uimm
));
2676 setflags_logical (cpu
, DREG (dst
));
2680 TRACE_INSN (cpu
, "BITCLR (R%i, %s);", dst
, uimm_str
);
2682 illegal_instruction_combination (cpu
);
2683 SET_DREG (dst
, DREG (dst
) & ~(1 << uimm
));
2684 setflags_logical (cpu
, DREG (dst
));
2688 TRACE_INSN (cpu
, "R%i >>>= %s;", dst
, uimm_str
);
2690 illegal_instruction_combination (cpu
);
2691 SET_DREG (dst
, ashiftrt (cpu
, DREG (dst
), uimm
, 32));
2695 TRACE_INSN (cpu
, "R%i >>= %s;", dst
, uimm_str
);
2697 illegal_instruction_combination (cpu
);
2698 SET_DREG (dst
, lshiftrt (cpu
, DREG (dst
), uimm
, 32));
2702 TRACE_INSN (cpu
, "R%i <<= %s;", dst
, uimm_str
);
2704 illegal_instruction_combination (cpu
);
2705 SET_DREG (dst
, lshift (cpu
, DREG (dst
), uimm
, 32, 0));
2710 decode_COMP3op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2713 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2714 | 0 | 1 | 0 | 1 |.opc.......|.dst.......|.src1......|.src0......|
2715 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2716 int opc
= ((iw0
>> COMP3op_opc_bits
) & COMP3op_opc_mask
);
2717 int dst
= ((iw0
>> COMP3op_dst_bits
) & COMP3op_dst_mask
);
2718 int src0
= ((iw0
>> COMP3op_src0_bits
) & COMP3op_src0_mask
);
2719 int src1
= ((iw0
>> COMP3op_src1_bits
) & COMP3op_src1_mask
);
2721 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_COMP3op
);
2722 TRACE_EXTRACT (cpu
, "%s: opc:%i dst:%i src1:%i src0:%i",
2723 __func__
, opc
, dst
, src1
, src0
);
2727 TRACE_INSN (cpu
, "R%i = R%i + R%i;", dst
, src0
, src1
);
2728 SET_DREG (dst
, add32 (cpu
, DREG (src0
), DREG (src1
), 1, 0));
2732 TRACE_INSN (cpu
, "R%i = R%i - R%i;", dst
, src0
, src1
);
2733 SET_DREG (dst
, sub32 (cpu
, DREG (src0
), DREG (src1
), 1, 0, 0));
2737 TRACE_INSN (cpu
, "R%i = R%i & R%i;", dst
, src0
, src1
);
2738 SET_DREG (dst
, DREG (src0
) & DREG (src1
));
2739 setflags_logical (cpu
, DREG (dst
));
2743 TRACE_INSN (cpu
, "R%i = R%i | R%i;", dst
, src0
, src1
);
2744 SET_DREG (dst
, DREG (src0
) | DREG (src1
));
2745 setflags_logical (cpu
, DREG (dst
));
2749 TRACE_INSN (cpu
, "R%i = R%i ^ R%i;", dst
, src0
, src1
);
2750 SET_DREG (dst
, DREG (src0
) ^ DREG (src1
));
2751 setflags_logical (cpu
, DREG (dst
));
2755 int shift
= opc
- 5;
2756 const char *dst_name
= get_preg_name (dst
);
2757 const char *src0_name
= get_preg_name (src0
);
2758 const char *src1_name
= get_preg_name (src1
);
2760 /* If src0 == src1 this is disassembled as a shift by 1, but this
2761 distinction doesn't matter for our purposes. */
2763 TRACE_INSN (cpu
, "%s = (%s + %s) << %#x;",
2764 dst_name
, src0_name
, src1_name
, shift
);
2766 TRACE_INSN (cpu
, "%s = %s + %s",
2767 dst_name
, src0_name
, src1_name
);
2768 SET_PREG (dst
, PREG (src0
) + (PREG (src1
) << shift
));
2773 decode_COMPI2opD_0 (SIM_CPU
*cpu
, bu16 iw0
)
2776 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2777 | 0 | 1 | 1 | 0 | 0 |.op|..src......................|.dst.......|
2778 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2779 int op
= ((iw0
>> COMPI2opD_op_bits
) & COMPI2opD_op_mask
);
2780 int dst
= ((iw0
>> COMPI2opD_dst_bits
) & COMPI2opD_dst_mask
);
2781 int src
= ((iw0
>> COMPI2opD_src_bits
) & COMPI2opD_src_mask
);
2782 int imm
= imm7 (src
);
2784 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_COMPI2opD
);
2785 TRACE_EXTRACT (cpu
, "%s: op:%i src:%i dst:%i", __func__
, op
, src
, dst
);
2786 TRACE_DECODE (cpu
, "%s: imm7:%#x", __func__
, imm
);
2790 TRACE_INSN (cpu
, "R%i = %s (X);", dst
, imm7_str (imm
));
2791 SET_DREG (dst
, imm
);
2795 TRACE_INSN (cpu
, "R%i += %s;", dst
, imm7_str (imm
));
2796 SET_DREG (dst
, add32 (cpu
, DREG (dst
), imm
, 1, 0));
2801 decode_COMPI2opP_0 (SIM_CPU
*cpu
, bu16 iw0
)
2804 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2805 | 0 | 1 | 1 | 0 | 1 |.op|.src.......................|.dst.......|
2806 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2807 int op
= ((iw0
>> COMPI2opP_op_bits
) & COMPI2opP_op_mask
);
2808 int src
= ((iw0
>> COMPI2opP_src_bits
) & COMPI2opP_src_mask
);
2809 int dst
= ((iw0
>> COMPI2opP_dst_bits
) & COMPI2opP_dst_mask
);
2810 int imm
= imm7 (src
);
2811 const char *dst_name
= get_preg_name (dst
);
2813 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_COMPI2opP
);
2814 TRACE_EXTRACT (cpu
, "%s: op:%i src:%i dst:%i", __func__
, op
, src
, dst
);
2815 TRACE_DECODE (cpu
, "%s: imm:%#x", __func__
, imm
);
2819 TRACE_INSN (cpu
, "%s = %s;", dst_name
, imm7_str (imm
));
2820 SET_PREG (dst
, imm
);
2824 TRACE_INSN (cpu
, "%s += %s;", dst_name
, imm7_str (imm
));
2825 SET_PREG (dst
, PREG (dst
) + imm
);
2830 decode_LDSTpmod_0 (SIM_CPU
*cpu
, bu16 iw0
)
2833 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2834 | 1 | 0 | 0 | 0 |.W.|.aop...|.reg.......|.idx.......|.ptr.......|
2835 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2836 int W
= ((iw0
>> LDSTpmod_W_bits
) & LDSTpmod_W_mask
);
2837 int aop
= ((iw0
>> LDSTpmod_aop_bits
) & LDSTpmod_aop_mask
);
2838 int idx
= ((iw0
>> LDSTpmod_idx_bits
) & LDSTpmod_idx_mask
);
2839 int ptr
= ((iw0
>> LDSTpmod_ptr_bits
) & LDSTpmod_ptr_mask
);
2840 int reg
= ((iw0
>> LDSTpmod_reg_bits
) & LDSTpmod_reg_mask
);
2841 const char *ptr_name
= get_preg_name (ptr
);
2842 const char *idx_name
= get_preg_name (idx
);
2845 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTpmod
);
2846 TRACE_EXTRACT (cpu
, "%s: W:%i aop:%i reg:%i idx:%i ptr:%i",
2847 __func__
, W
, aop
, reg
, idx
, ptr
);
2849 if (aop
== 1 && W
== 0 && idx
== ptr
)
2851 TRACE_INSN (cpu
, "R%i.L = W[%s];", reg
, ptr_name
);
2853 val
= GET_WORD (addr
);
2854 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | val
);
2856 else if (aop
== 2 && W
== 0 && idx
== ptr
)
2858 TRACE_INSN (cpu
, "R%i.H = W[%s];", reg
, ptr_name
);
2860 val
= GET_WORD (addr
);
2861 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (val
<< 16));
2863 else if (aop
== 1 && W
== 1 && idx
== ptr
)
2865 TRACE_INSN (cpu
, "W[%s] = R%i.L;", ptr_name
, reg
);
2867 PUT_WORD (addr
, DREG (reg
));
2869 else if (aop
== 2 && W
== 1 && idx
== ptr
)
2871 TRACE_INSN (cpu
, "W[%s] = R%i.H;", ptr_name
, reg
);
2873 PUT_WORD (addr
, DREG (reg
) >> 16);
2875 else if (aop
== 0 && W
== 0)
2877 TRACE_INSN (cpu
, "R%i = [%s ++ %s];", reg
, ptr_name
, idx_name
);
2879 val
= GET_LONG (addr
);
2880 STORE (DREG (reg
), val
);
2882 STORE (PREG (ptr
), addr
+ PREG (idx
));
2884 else if (aop
== 1 && W
== 0)
2886 TRACE_INSN (cpu
, "R%i.L = W[%s ++ %s];", reg
, ptr_name
, idx_name
);
2888 val
= GET_WORD (addr
);
2889 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | val
);
2891 STORE (PREG (ptr
), addr
+ PREG (idx
));
2893 else if (aop
== 2 && W
== 0)
2895 TRACE_INSN (cpu
, "R%i.H = W[%s ++ %s];", reg
, ptr_name
, idx_name
);
2897 val
= GET_WORD (addr
);
2898 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (val
<< 16));
2900 STORE (PREG (ptr
), addr
+ PREG (idx
));
2902 else if (aop
== 3 && W
== 0)
2904 TRACE_INSN (cpu
, "R%i = W[%s ++ %s] (Z);", reg
, ptr_name
, idx_name
);
2906 val
= GET_WORD (addr
);
2907 STORE (DREG (reg
), val
);
2909 STORE (PREG (ptr
), addr
+ PREG (idx
));
2911 else if (aop
== 3 && W
== 1)
2913 TRACE_INSN (cpu
, "R%i = W[%s ++ %s] (X);", reg
, ptr_name
, idx_name
);
2915 val
= GET_WORD (addr
);
2916 STORE (DREG (reg
), (bs32
) (bs16
) val
);
2918 STORE (PREG (ptr
), addr
+ PREG (idx
));
2920 else if (aop
== 0 && W
== 1)
2922 TRACE_INSN (cpu
, "[%s ++ %s] = R%i;", ptr_name
, idx_name
, reg
);
2924 PUT_LONG (addr
, DREG (reg
));
2926 STORE (PREG (ptr
), addr
+ PREG (idx
));
2928 else if (aop
== 1 && W
== 1)
2930 TRACE_INSN (cpu
, "W[%s ++ %s] = R%i.L;", ptr_name
, idx_name
, reg
);
2932 PUT_WORD (addr
, DREG (reg
));
2934 STORE (PREG (ptr
), addr
+ PREG (idx
));
2936 else if (aop
== 2 && W
== 1)
2938 TRACE_INSN (cpu
, "W[%s ++ %s] = R%i.H;", ptr_name
, idx_name
, reg
);
2940 PUT_WORD (addr
, DREG (reg
) >> 16);
2942 STORE (PREG (ptr
), addr
+ PREG (idx
));
2945 illegal_instruction (cpu
);
2949 decode_dagMODim_0 (SIM_CPU
*cpu
, bu16 iw0
)
2952 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2953 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 0 |.br| 1 | 1 |.op|.m.....|.i.....|
2954 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2955 int i
= ((iw0
>> DagMODim_i_bits
) & DagMODim_i_mask
);
2956 int m
= ((iw0
>> DagMODim_m_bits
) & DagMODim_m_mask
);
2957 int br
= ((iw0
>> DagMODim_br_bits
) & DagMODim_br_mask
);
2958 int op
= ((iw0
>> DagMODim_op_bits
) & DagMODim_op_mask
);
2960 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dagMODim
);
2961 TRACE_EXTRACT (cpu
, "%s: br:%i op:%i m:%i i:%i", __func__
, br
, op
, m
, i
);
2963 if (op
== 0 && br
== 1)
2965 TRACE_INSN (cpu
, "I%i += M%i (BREV);", i
, m
);
2966 SET_IREG (i
, add_brev (IREG (i
), MREG (m
)));
2970 TRACE_INSN (cpu
, "I%i += M%i;", i
, m
);
2971 dagadd (cpu
, i
, MREG (m
));
2973 else if (op
== 1 && br
== 0)
2975 TRACE_INSN (cpu
, "I%i -= M%i;", i
, m
);
2976 dagsub (cpu
, i
, MREG (m
));
2979 illegal_instruction (cpu
);
2983 decode_dagMODik_0 (SIM_CPU
*cpu
, bu16 iw0
)
2986 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2987 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 0 |.op....|.i.....|
2988 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2989 int i
= ((iw0
>> DagMODik_i_bits
) & DagMODik_i_mask
);
2990 int op
= ((iw0
>> DagMODik_op_bits
) & DagMODik_op_mask
);
2992 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dagMODik
);
2993 TRACE_EXTRACT (cpu
, "%s: op:%i i:%i", __func__
, op
, i
);
2997 TRACE_INSN (cpu
, "I%i += 2;", i
);
3002 TRACE_INSN (cpu
, "I%i -= 2;", i
);
3007 TRACE_INSN (cpu
, "I%i += 4;", i
);
3012 TRACE_INSN (cpu
, "I%i -= 4;", i
);
3016 illegal_instruction (cpu
);
3020 decode_dspLDST_0 (SIM_CPU
*cpu
, bu16 iw0
)
3023 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3024 | 1 | 0 | 0 | 1 | 1 | 1 |.W.|.aop...|.m.....|.i.....|.reg.......|
3025 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3026 int i
= ((iw0
>> DspLDST_i_bits
) & DspLDST_i_mask
);
3027 int m
= ((iw0
>> DspLDST_m_bits
) & DspLDST_m_mask
);
3028 int W
= ((iw0
>> DspLDST_W_bits
) & DspLDST_W_mask
);
3029 int aop
= ((iw0
>> DspLDST_aop_bits
) & DspLDST_aop_mask
);
3030 int reg
= ((iw0
>> DspLDST_reg_bits
) & DspLDST_reg_mask
);
3033 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dspLDST
);
3034 TRACE_EXTRACT (cpu
, "%s: aop:%i m:%i i:%i reg:%i", __func__
, aop
, m
, i
, reg
);
3036 if (aop
== 0 && W
== 0 && m
== 0)
3038 TRACE_INSN (cpu
, "R%i = [I%i++];", reg
, i
);
3040 if (DIS_ALGN_EXPT
& 0x1)
3043 STORE (DREG (reg
), GET_LONG (addr
));
3045 else if (aop
== 0 && W
== 0 && m
== 1)
3047 TRACE_INSN (cpu
, "R%i.L = W[I%i++];", reg
, i
);
3050 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | GET_WORD (addr
));
3052 else if (aop
== 0 && W
== 0 && m
== 2)
3054 TRACE_INSN (cpu
, "R%i.H = W[I%i++];", reg
, i
);
3057 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (GET_WORD (addr
) << 16));
3059 else if (aop
== 1 && W
== 0 && m
== 0)
3061 TRACE_INSN (cpu
, "R%i = [I%i--];", reg
, i
);
3063 if (DIS_ALGN_EXPT
& 0x1)
3066 STORE (DREG (reg
), GET_LONG (addr
));
3068 else if (aop
== 1 && W
== 0 && m
== 1)
3070 TRACE_INSN (cpu
, "R%i.L = W[I%i--];", reg
, i
);
3073 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | GET_WORD (addr
));
3075 else if (aop
== 1 && W
== 0 && m
== 2)
3077 TRACE_INSN (cpu
, "R%i.H = W[I%i--];", reg
, i
);
3080 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (GET_WORD (addr
) << 16));
3082 else if (aop
== 2 && W
== 0 && m
== 0)
3084 TRACE_INSN (cpu
, "R%i = [I%i];", reg
, i
);
3086 if (DIS_ALGN_EXPT
& 0x1)
3088 STORE (DREG (reg
), GET_LONG (addr
));
3090 else if (aop
== 2 && W
== 0 && m
== 1)
3092 TRACE_INSN (cpu
, "R%i.L = W[I%i];", reg
, i
);
3094 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | GET_WORD (addr
));
3096 else if (aop
== 2 && W
== 0 && m
== 2)
3098 TRACE_INSN (cpu
, "R%i.H = W[I%i];", reg
, i
);
3100 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (GET_WORD (addr
) << 16));
3102 else if (aop
== 0 && W
== 1 && m
== 0)
3104 TRACE_INSN (cpu
, "[I%i++] = R%i;", i
, reg
);
3107 PUT_LONG (addr
, DREG (reg
));
3109 else if (aop
== 0 && W
== 1 && m
== 1)
3111 TRACE_INSN (cpu
, "W[I%i++] = R%i.L;", i
, reg
);
3114 PUT_WORD (addr
, DREG (reg
));
3116 else if (aop
== 0 && W
== 1 && m
== 2)
3118 TRACE_INSN (cpu
, "W[I%i++] = R%i.H;", i
, reg
);
3121 PUT_WORD (addr
, DREG (reg
) >> 16);
3123 else if (aop
== 1 && W
== 1 && m
== 0)
3125 TRACE_INSN (cpu
, "[I%i--] = R%i;", i
, reg
);
3128 PUT_LONG (addr
, DREG (reg
));
3130 else if (aop
== 1 && W
== 1 && m
== 1)
3132 TRACE_INSN (cpu
, "W[I%i--] = R%i.L;", i
, reg
);
3135 PUT_WORD (addr
, DREG (reg
));
3137 else if (aop
== 1 && W
== 1 && m
== 2)
3139 TRACE_INSN (cpu
, "W[I%i--] = R%i.H;", i
, reg
);
3142 PUT_WORD (addr
, DREG (reg
) >> 16);
3144 else if (aop
== 2 && W
== 1 && m
== 0)
3146 TRACE_INSN (cpu
, "[I%i] = R%i;", i
, reg
);
3148 PUT_LONG (addr
, DREG (reg
));
3150 else if (aop
== 2 && W
== 1 && m
== 1)
3152 TRACE_INSN (cpu
, "W[I%i] = R%i.L;", i
, reg
);
3154 PUT_WORD (addr
, DREG (reg
));
3156 else if (aop
== 2 && W
== 1 && m
== 2)
3158 TRACE_INSN (cpu
, "W[I%i] = R%i.H;", i
, reg
);
3160 PUT_WORD (addr
, DREG (reg
) >> 16);
3162 else if (aop
== 3 && W
== 0)
3164 TRACE_INSN (cpu
, "R%i = [I%i ++ M%i];", reg
, i
, m
);
3166 if (DIS_ALGN_EXPT
& 0x1)
3168 dagadd (cpu
, i
, MREG (m
));
3169 STORE (DREG (reg
), GET_LONG (addr
));
3171 else if (aop
== 3 && W
== 1)
3173 TRACE_INSN (cpu
, "[I%i ++ M%i] = R%i;", i
, m
, reg
);
3175 dagadd (cpu
, i
, MREG (m
));
3176 PUT_LONG (addr
, DREG (reg
));
3179 illegal_instruction (cpu
);
3183 decode_LDST_0 (SIM_CPU
*cpu
, bu16 iw0
)
3186 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3187 | 1 | 0 | 0 | 1 |.sz....|.W.|.aop...|.Z.|.ptr.......|.reg.......|
3188 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3189 int Z
= ((iw0
>> LDST_Z_bits
) & LDST_Z_mask
);
3190 int W
= ((iw0
>> LDST_W_bits
) & LDST_W_mask
);
3191 int sz
= ((iw0
>> LDST_sz_bits
) & LDST_sz_mask
);
3192 int aop
= ((iw0
>> LDST_aop_bits
) & LDST_aop_mask
);
3193 int reg
= ((iw0
>> LDST_reg_bits
) & LDST_reg_mask
);
3194 int ptr
= ((iw0
>> LDST_ptr_bits
) & LDST_ptr_mask
);
3195 const char * const posts
[] = { "++", "--", "" };
3196 const char *post
= posts
[aop
];
3197 const char *ptr_name
= get_preg_name (ptr
);
3199 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDST
);
3200 TRACE_EXTRACT (cpu
, "%s: sz:%i W:%i aop:%i Z:%i ptr:%i reg:%i",
3201 __func__
, sz
, W
, aop
, Z
, ptr
, reg
);
3204 illegal_instruction (cpu
);
3208 if (sz
== 0 && Z
== 0)
3210 TRACE_INSN (cpu
, "R%i = [%s%s];", reg
, ptr_name
, post
);
3211 SET_DREG (reg
, GET_LONG (PREG (ptr
)));
3213 else if (sz
== 0 && Z
== 1)
3215 TRACE_INSN (cpu
, "%s = [%s%s];", get_preg_name (reg
), ptr_name
, post
);
3216 if (aop
< 2 && ptr
== reg
)
3217 illegal_instruction_combination (cpu
);
3218 SET_PREG (reg
, GET_LONG (PREG (ptr
)));
3220 else if (sz
== 1 && Z
== 0)
3222 TRACE_INSN (cpu
, "R%i = W[%s%s] (Z);", reg
, ptr_name
, post
);
3223 SET_DREG (reg
, GET_WORD (PREG (ptr
)));
3225 else if (sz
== 1 && Z
== 1)
3227 TRACE_INSN (cpu
, "R%i = W[%s%s] (X);", reg
, ptr_name
, post
);
3228 SET_DREG (reg
, (bs32
) (bs16
) GET_WORD (PREG (ptr
)));
3230 else if (sz
== 2 && Z
== 0)
3232 TRACE_INSN (cpu
, "R%i = B[%s%s] (Z);", reg
, ptr_name
, post
);
3233 SET_DREG (reg
, GET_BYTE (PREG (ptr
)));
3235 else if (sz
== 2 && Z
== 1)
3237 TRACE_INSN (cpu
, "R%i = B[%s%s] (X);", reg
, ptr_name
, post
);
3238 SET_DREG (reg
, (bs32
) (bs8
) GET_BYTE (PREG (ptr
)));
3241 illegal_instruction (cpu
);
3245 if (sz
== 0 && Z
== 0)
3247 TRACE_INSN (cpu
, "[%s%s] = R%i;", ptr_name
, post
, reg
);
3248 PUT_LONG (PREG (ptr
), DREG (reg
));
3250 else if (sz
== 0 && Z
== 1)
3252 TRACE_INSN (cpu
, "[%s%s] = %s;", ptr_name
, post
, get_preg_name (reg
));
3253 PUT_LONG (PREG (ptr
), PREG (reg
));
3255 else if (sz
== 1 && Z
== 0)
3257 TRACE_INSN (cpu
, "W[%s%s] = R%i;", ptr_name
, post
, reg
);
3258 PUT_WORD (PREG (ptr
), DREG (reg
));
3260 else if (sz
== 2 && Z
== 0)
3262 TRACE_INSN (cpu
, "B[%s%s] = R%i;", ptr_name
, post
, reg
);
3263 PUT_BYTE (PREG (ptr
), DREG (reg
));
3266 illegal_instruction (cpu
);
3270 SET_PREG (ptr
, PREG (ptr
) + (1 << (2 - sz
)));
3272 SET_PREG (ptr
, PREG (ptr
) - (1 << (2 - sz
)));
3276 decode_LDSTiiFP_0 (SIM_CPU
*cpu
, bu16 iw0
)
3279 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3280 | 1 | 0 | 1 | 1 | 1 | 0 |.W.|.offset............|.reg...........|
3281 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3282 /* This isn't exactly a grp:reg as this insn only supports Dregs & Pregs,
3283 but for our usage, its functionality the same thing. */
3284 int grp
= ((iw0
>> 3) & 0x1);
3285 int reg
= ((iw0
>> LDSTiiFP_reg_bits
) & 0x7 /*LDSTiiFP_reg_mask*/);
3286 int offset
= ((iw0
>> LDSTiiFP_offset_bits
) & LDSTiiFP_offset_mask
);
3287 int W
= ((iw0
>> LDSTiiFP_W_bits
) & LDSTiiFP_W_mask
);
3288 bu32 imm
= negimm5s4 (offset
);
3289 bu32 ea
= FPREG
+ imm
;
3290 const char *imm_str
= negimm5s4_str (offset
);
3291 const char *reg_name
= get_allreg_name (grp
, reg
);
3293 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTiiFP
);
3294 TRACE_EXTRACT (cpu
, "%s: W:%i offset:%#x grp:%i reg:%i", __func__
,
3295 W
, offset
, grp
, reg
);
3296 TRACE_DECODE (cpu
, "%s: negimm5s4:%#x", __func__
, imm
);
3300 TRACE_INSN (cpu
, "%s = [FP + %s];", reg_name
, imm_str
);
3301 reg_write (cpu
, grp
, reg
, GET_LONG (ea
));
3305 TRACE_INSN (cpu
, "[FP + %s] = %s;", imm_str
, reg_name
);
3306 PUT_LONG (ea
, reg_read (cpu
, grp
, reg
));
3311 decode_LDSTii_0 (SIM_CPU
*cpu
, bu16 iw0
)
3314 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3315 | 1 | 0 | 1 |.W.|.op....|.offset........|.ptr.......|.reg.......|
3316 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3317 int reg
= ((iw0
>> LDSTii_reg_bit
) & LDSTii_reg_mask
);
3318 int ptr
= ((iw0
>> LDSTii_ptr_bit
) & LDSTii_ptr_mask
);
3319 int offset
= ((iw0
>> LDSTii_offset_bit
) & LDSTii_offset_mask
);
3320 int op
= ((iw0
>> LDSTii_op_bit
) & LDSTii_op_mask
);
3321 int W
= ((iw0
>> LDSTii_W_bit
) & LDSTii_W_mask
);
3323 const char *imm_str
;
3324 const char *ptr_name
= get_preg_name (ptr
);
3326 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTii
);
3327 TRACE_EXTRACT (cpu
, "%s: W:%i op:%i offset:%#x ptr:%i reg:%i",
3328 __func__
, W
, op
, offset
, ptr
, reg
);
3330 if (op
== 0 || op
== 3)
3331 imm
= uimm4s4 (offset
), imm_str
= uimm4s4_str (offset
);
3333 imm
= uimm4s2 (offset
), imm_str
= uimm4s2_str (offset
);
3334 ea
= PREG (ptr
) + imm
;
3336 TRACE_DECODE (cpu
, "%s: uimm4s4/uimm4s2:%#x", __func__
, imm
);
3338 if (W
== 1 && op
== 2)
3339 illegal_instruction (cpu
);
3345 TRACE_INSN (cpu
, "R%i = [%s + %s];", reg
, ptr_name
, imm_str
);
3346 SET_DREG (reg
, GET_LONG (ea
));
3350 TRACE_INSN (cpu
, "R%i = W[%s + %s] (Z);", reg
, ptr_name
, imm_str
);
3351 SET_DREG (reg
, GET_WORD (ea
));
3355 TRACE_INSN (cpu
, "R%i = W[%s + %s] (X);", reg
, ptr_name
, imm_str
);
3356 SET_DREG (reg
, (bs32
) (bs16
) GET_WORD (ea
));
3360 TRACE_INSN (cpu
, "%s = [%s + %s];",
3361 get_preg_name (reg
), ptr_name
, imm_str
);
3362 SET_PREG (reg
, GET_LONG (ea
));
3369 TRACE_INSN (cpu
, "[%s + %s] = R%i;", ptr_name
, imm_str
, reg
);
3370 PUT_LONG (ea
, DREG (reg
));
3374 TRACE_INSN (cpu
, "W[%s + %s] = R%i;", ptr_name
, imm_str
, reg
);
3375 PUT_WORD (ea
, DREG (reg
));
3379 TRACE_INSN (cpu
, "[%s + %s] = %s;",
3380 ptr_name
, imm_str
, get_preg_name (reg
));
3381 PUT_LONG (ea
, PREG (reg
));
3387 decode_LoopSetup_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
, bu32 pc
)
3390 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3391 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |.rop...|.c.|.soffset.......|
3392 |.reg...........| - | - |.eoffset...............................|
3393 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3394 int c
= ((iw0
>> (LoopSetup_c_bits
- 16)) & LoopSetup_c_mask
);
3395 int reg
= ((iw1
>> LoopSetup_reg_bits
) & LoopSetup_reg_mask
);
3396 int rop
= ((iw0
>> (LoopSetup_rop_bits
- 16)) & LoopSetup_rop_mask
);
3397 int soffset
= ((iw0
>> (LoopSetup_soffset_bits
- 16)) & LoopSetup_soffset_mask
);
3398 int eoffset
= ((iw1
>> LoopSetup_eoffset_bits
) & LoopSetup_eoffset_mask
);
3399 int spcrel
= pcrel4 (soffset
);
3400 int epcrel
= lppcrel10 (eoffset
);
3402 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LoopSetup
);
3403 TRACE_EXTRACT (cpu
, "%s: rop:%i c:%i soffset:%i reg:%i eoffset:%i",
3404 __func__
, rop
, c
, soffset
, reg
, eoffset
);
3405 TRACE_DECODE (cpu
, "%s: s_pcrel4:%#x e_lppcrel10:%#x",
3406 __func__
, spcrel
, epcrel
);
3409 illegal_instruction (cpu
);
3412 illegal_instruction_combination (cpu
);
3416 TRACE_INSN (cpu
, "LSETUP (%#x, %#x) LC%i;", spcrel
, epcrel
, c
);
3418 else if (rop
== 1 && reg
<= 7)
3420 TRACE_INSN (cpu
, "LSETUP (%#x, %#x) LC%i = %s;",
3421 spcrel
, epcrel
, c
, get_preg_name (reg
));
3422 SET_LCREG (c
, PREG (reg
));
3424 else if (rop
== 3 && reg
<= 7)
3426 TRACE_INSN (cpu
, "LSETUP (%#x, %#x) LC%i = %s >> 1;",
3427 spcrel
, epcrel
, c
, get_preg_name (reg
));
3428 SET_LCREG (c
, PREG (reg
) >> 1);
3431 illegal_instruction (cpu
);
3433 SET_LTREG (c
, pc
+ spcrel
);
3434 SET_LBREG (c
, pc
+ epcrel
);
3438 decode_LDIMMhalf_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3441 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3442 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 |.Z.|.H.|.S.|.grp...|.reg.......|
3443 |.hword.........................................................|
3444 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3445 int H
= ((iw0
>> (LDIMMhalf_H_bits
- 16)) & LDIMMhalf_H_mask
);
3446 int Z
= ((iw0
>> (LDIMMhalf_Z_bits
- 16)) & LDIMMhalf_Z_mask
);
3447 int S
= ((iw0
>> (LDIMMhalf_S_bits
- 16)) & LDIMMhalf_S_mask
);
3448 int reg
= ((iw0
>> (LDIMMhalf_reg_bits
- 16)) & LDIMMhalf_reg_mask
);
3449 int grp
= ((iw0
>> (LDIMMhalf_grp_bits
- 16)) & LDIMMhalf_grp_mask
);
3450 int hword
= ((iw1
>> LDIMMhalf_hword_bits
) & LDIMMhalf_hword_mask
);
3452 const char *val_str
;
3453 const char *reg_name
= get_allreg_name (grp
, reg
);
3455 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDIMMhalf
);
3456 TRACE_EXTRACT (cpu
, "%s: Z:%i H:%i S:%i grp:%i reg:%i hword:%#x",
3457 __func__
, Z
, H
, S
, grp
, reg
, hword
);
3460 illegal_instruction_combination (cpu
);
3463 val
= imm16 (hword
), val_str
= imm16_str (hword
);
3465 val
= luimm16 (hword
), val_str
= luimm16_str (hword
);
3467 if (H
== 0 && S
== 1 && Z
== 0)
3469 TRACE_INSN (cpu
, "%s = %s (X);", reg_name
, val_str
);
3471 else if (H
== 0 && S
== 0 && Z
== 1)
3473 TRACE_INSN (cpu
, "%s = %s (Z);", reg_name
, val_str
);
3475 else if (H
== 0 && S
== 0 && Z
== 0)
3477 TRACE_INSN (cpu
, "%s.L = %s;", reg_name
, val_str
);
3478 val
= REG_H_L (reg_read (cpu
, grp
, reg
), val
);
3480 else if (H
== 1 && S
== 0 && Z
== 0)
3482 TRACE_INSN (cpu
, "%s.H = %s;", reg_name
, val_str
);
3483 val
= REG_H_L (val
<< 16, reg_read (cpu
, grp
, reg
));
3486 illegal_instruction (cpu
);
3488 reg_write (cpu
, grp
, reg
, val
);
3492 decode_CALLa_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
, bu32 pc
)
3495 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3496 | 1 | 1 | 1 | 0 | 0 | 0 | 1 |.S.|.msw...........................|
3497 |.lsw...........................................................|
3498 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3499 int S
= ((iw0
>> (CALLa_S_bits
- 16)) & CALLa_S_mask
);
3500 int lsw
= ((iw1
>> 0) & 0xffff);
3501 int msw
= ((iw0
>> 0) & 0xff);
3502 int pcrel
= pcrel24 ((msw
<< 16) | lsw
);
3503 bu32 newpc
= pc
+ pcrel
;
3505 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CALLa
);
3506 TRACE_EXTRACT (cpu
, "%s: S:%i msw:%#x lsw:%#x", __func__
, S
, msw
, lsw
);
3507 TRACE_DECODE (cpu
, "%s: pcrel24:%#x", __func__
, pcrel
);
3509 TRACE_INSN (cpu
, "%s %#x;", S
? "CALL" : "JUMP.L", pcrel
);
3512 illegal_instruction_combination (cpu
);
3516 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "CALL");
3517 SET_RETSREG (hwloop_get_next_pc (cpu
, pc
, 4));
3520 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP.L");
3523 BFIN_CPU_STATE
.did_jump
= true;
3524 PROFILE_BRANCH_TAKEN (cpu
);
3529 decode_LDSTidxI_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3532 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3533 | 1 | 1 | 1 | 0 | 0 | 1 |.W.|.Z.|.sz....|.ptr.......|.reg.......|
3534 |.offset........................................................|
3535 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3536 int Z
= ((iw0
>> (LDSTidxI_Z_bits
- 16)) & LDSTidxI_Z_mask
);
3537 int W
= ((iw0
>> (LDSTidxI_W_bits
- 16)) & LDSTidxI_W_mask
);
3538 int sz
= ((iw0
>> (LDSTidxI_sz_bits
- 16)) & LDSTidxI_sz_mask
);
3539 int reg
= ((iw0
>> (LDSTidxI_reg_bits
- 16)) & LDSTidxI_reg_mask
);
3540 int ptr
= ((iw0
>> (LDSTidxI_ptr_bits
- 16)) & LDSTidxI_ptr_mask
);
3541 int offset
= ((iw1
>> LDSTidxI_offset_bits
) & LDSTidxI_offset_mask
);
3542 const char *ptr_name
= get_preg_name (ptr
);
3543 bu32 imm_16s4
= imm16s4 (offset
);
3544 bu32 imm_16s2
= imm16s2 (offset
);
3545 bu32 imm_16
= imm16 (offset
);
3547 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTidxI
);
3548 TRACE_EXTRACT (cpu
, "%s: W:%i Z:%i sz:%i ptr:%i reg:%i offset:%#x",
3549 __func__
, W
, Z
, sz
, ptr
, reg
, offset
);
3552 illegal_instruction (cpu
);
3556 if (sz
== 0 && Z
== 0)
3558 TRACE_INSN (cpu
, "R%i = [%s + %s];",
3559 reg
, ptr_name
, imm16s4_str (offset
));
3560 SET_DREG (reg
, GET_LONG (PREG (ptr
) + imm_16s4
));
3562 else if (sz
== 0 && Z
== 1)
3564 TRACE_INSN (cpu
, "%s = [%s + %s];",
3565 get_preg_name (reg
), ptr_name
, imm16s4_str (offset
));
3566 SET_PREG (reg
, GET_LONG (PREG (ptr
) + imm_16s4
));
3568 else if (sz
== 1 && Z
== 0)
3570 TRACE_INSN (cpu
, "R%i = W[%s + %s] (Z);",
3571 reg
, ptr_name
, imm16s2_str (offset
));
3572 SET_DREG (reg
, GET_WORD (PREG (ptr
) + imm_16s2
));
3574 else if (sz
== 1 && Z
== 1)
3576 TRACE_INSN (cpu
, "R%i = W[%s + %s] (X);",
3577 reg
, ptr_name
, imm16s2_str (offset
));
3578 SET_DREG (reg
, (bs32
) (bs16
) GET_WORD (PREG (ptr
) + imm_16s2
));
3580 else if (sz
== 2 && Z
== 0)
3582 TRACE_INSN (cpu
, "R%i = B[%s + %s] (Z);",
3583 reg
, ptr_name
, imm16_str (offset
));
3584 SET_DREG (reg
, GET_BYTE (PREG (ptr
) + imm_16
));
3586 else if (sz
== 2 && Z
== 1)
3588 TRACE_INSN (cpu
, "R%i = B[%s + %s] (X);",
3589 reg
, ptr_name
, imm16_str (offset
));
3590 SET_DREG (reg
, (bs32
) (bs8
) GET_BYTE (PREG (ptr
) + imm_16
));
3595 if (sz
!= 0 && Z
!= 0)
3596 illegal_instruction (cpu
);
3598 if (sz
== 0 && Z
== 0)
3600 TRACE_INSN (cpu
, "[%s + %s] = R%i;", ptr_name
,
3601 imm16s4_str (offset
), reg
);
3602 PUT_LONG (PREG (ptr
) + imm_16s4
, DREG (reg
));
3604 else if (sz
== 0 && Z
== 1)
3606 TRACE_INSN (cpu
, "[%s + %s] = %s;",
3607 ptr_name
, imm16s4_str (offset
), get_preg_name (reg
));
3608 PUT_LONG (PREG (ptr
) + imm_16s4
, PREG (reg
));
3610 else if (sz
== 1 && Z
== 0)
3612 TRACE_INSN (cpu
, "W[%s + %s] = R%i;",
3613 ptr_name
, imm16s2_str (offset
), reg
);
3614 PUT_WORD (PREG (ptr
) + imm_16s2
, DREG (reg
));
3616 else if (sz
== 2 && Z
== 0)
3618 TRACE_INSN (cpu
, "B[%s + %s] = R%i;",
3619 ptr_name
, imm16_str (offset
), reg
);
3620 PUT_BYTE (PREG (ptr
) + imm_16
, DREG (reg
));
3626 decode_linkage_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3629 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3630 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |.R.|
3631 |.framesize.....................................................|
3632 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3633 int R
= ((iw0
>> (Linkage_R_bits
- 16)) & Linkage_R_mask
);
3634 int framesize
= ((iw1
>> Linkage_framesize_bits
) & Linkage_framesize_mask
);
3637 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_linkage
);
3638 TRACE_EXTRACT (cpu
, "%s: R:%i framesize:%#x", __func__
, R
, framesize
);
3642 int size
= uimm16s4 (framesize
);
3644 TRACE_INSN (cpu
, "LINK %s;", uimm16s4_str (framesize
));
3646 illegal_instruction_combination (cpu
);
3648 PUT_LONG (sp
, RETSREG
);
3650 PUT_LONG (sp
, FPREG
);
3657 /* Restore SP from FP. */
3659 TRACE_INSN (cpu
, "UNLINK;");
3661 illegal_instruction_combination (cpu
);
3662 SET_FPREG (GET_LONG (sp
));
3664 SET_RETSREG (GET_LONG (sp
));
3673 decode_dsp32mac_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3676 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3677 | 1 | 1 | 0 | 0 |.M.| 0 | 0 |.mmod..........|.MM|.P.|.w1|.op1...|
3678 |.h01|.h11|.w0|.op0...|.h00|.h10|.dst.......|.src0......|.src1..|
3679 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3680 int op1
= ((iw0
>> (DSP32Mac_op1_bits
- 16)) & DSP32Mac_op1_mask
);
3681 int w1
= ((iw0
>> (DSP32Mac_w1_bits
- 16)) & DSP32Mac_w1_mask
);
3682 int P
= ((iw0
>> (DSP32Mac_p_bits
- 16)) & DSP32Mac_p_mask
);
3683 int MM
= ((iw0
>> (DSP32Mac_MM_bits
- 16)) & DSP32Mac_MM_mask
);
3684 int mmod
= ((iw0
>> (DSP32Mac_mmod_bits
- 16)) & DSP32Mac_mmod_mask
);
3685 int M
= ((iw0
>> (DSP32Mac_M_bits
- 16)) & DSP32Mac_M_mask
);
3686 int w0
= ((iw1
>> DSP32Mac_w0_bits
) & DSP32Mac_w0_mask
);
3687 int src0
= ((iw1
>> DSP32Mac_src0_bits
) & DSP32Mac_src0_mask
);
3688 int src1
= ((iw1
>> DSP32Mac_src1_bits
) & DSP32Mac_src1_mask
);
3689 int dst
= ((iw1
>> DSP32Mac_dst_bits
) & DSP32Mac_dst_mask
);
3690 int h10
= ((iw1
>> DSP32Mac_h10_bits
) & DSP32Mac_h10_mask
);
3691 int h00
= ((iw1
>> DSP32Mac_h00_bits
) & DSP32Mac_h00_mask
);
3692 int op0
= ((iw1
>> DSP32Mac_op0_bits
) & DSP32Mac_op0_mask
);
3693 int h11
= ((iw1
>> DSP32Mac_h11_bits
) & DSP32Mac_h11_mask
);
3694 int h01
= ((iw1
>> DSP32Mac_h01_bits
) & DSP32Mac_h01_mask
);
3696 bu32 res
= DREG (dst
);
3697 bu32 v_i
= 0, zero
= 0;
3699 static const char * const ops
[] = { "=", "+=", "-=" };
3700 char _buf
[128], *buf
= _buf
;
3703 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32mac
);
3704 TRACE_EXTRACT (cpu
, "%s: M:%i mmod:%i MM:%i P:%i w1:%i op1:%i h01:%i h11:%i "
3705 "w0:%i op0:%i h00:%i h10:%i dst:%i src0:%i src1:%i",
3706 __func__
, M
, mmod
, MM
, P
, w1
, op1
, h01
, h11
, w0
, op0
, h00
, h10
,
3709 if (w0
== 0 && w1
== 0 && op1
== 3 && op0
== 3)
3710 illegal_instruction (cpu
);
3712 if ((w1
|| w0
) && mmod
== M_W32
)
3713 illegal_instruction (cpu
);
3715 if (((1 << mmod
) & (P
? 0x131b : 0x1b5f)) == 0)
3716 illegal_instruction (cpu
);
3718 /* First handle MAC1 side. */
3719 if (w1
== 1 || op1
!= 3)
3721 bu32 res1
= decode_macfunc (cpu
, 1, op1
, h01
, h11
, src0
,
3722 src1
, mmod
, MM
, P
, &v_i
);
3725 buf
+= sprintf (buf
, P
? "R%i" : "R%i.H", dst
+ P
);
3729 buf
+= sprintf (buf
, " = A1");
3730 zero
= !!(res1
== 0);
3735 buf
+= sprintf (buf
, " = (");
3736 buf
+= sprintf (buf
, "A1 %s R%i.%c * R%i.%c", ops
[op1
],
3737 src0
, h01
? 'H' : 'L',
3738 src1
, h11
? 'H' : 'L');
3740 buf
+= sprintf (buf
, ")");
3746 STORE (DREG (dst
+ 1), res1
);
3749 if (res1
& 0xffff0000)
3750 illegal_instruction (cpu
);
3751 res
= REG_H_L (res1
<< 16, res
);
3755 if (w0
== 1 || op0
!= 3)
3758 buf
+= sprintf (buf
, " (M)");
3760 buf
+= sprintf (buf
, ", ");
3764 /* Then handle MAC0 side. */
3765 if (w0
== 1 || op0
!= 3)
3767 bu32 res0
= decode_macfunc (cpu
, 0, op0
, h00
, h10
, src0
,
3768 src1
, mmod
, 0, P
, &v_i
);
3771 buf
+= sprintf (buf
, P
? "R%i" : "R%i.L", dst
);
3775 buf
+= sprintf (buf
, " = A0");
3776 zero
|= !!(res0
== 0);
3781 buf
+= sprintf (buf
, " = (");
3782 buf
+= sprintf (buf
, "A0 %s R%i.%c * R%i.%c", ops
[op0
],
3783 src0
, h00
? 'H' : 'L',
3784 src1
, h10
? 'H' : 'L');
3786 buf
+= sprintf (buf
, ")");
3792 STORE (DREG (dst
), res0
);
3795 if (res0
& 0xffff0000)
3796 illegal_instruction (cpu
);
3797 res
= REG_H_L (res
, res0
);
3802 TRACE_INSN (cpu
, "%s%s;", _buf
, mac_optmode (mmod
, _MM
));
3804 if (!P
&& (w0
|| w1
))
3806 STORE (DREG (dst
), res
);
3807 SET_ASTATREG (v
, v_i
);
3809 SET_ASTATREG (vs
, v_i
);
3813 SET_ASTATREG (v
, v_i
);
3815 SET_ASTATREG (vs
, v_i
);
3817 if (op0
== 3 || op1
== 3)
3818 SET_ASTATREG (az
, zero
);
3822 decode_dsp32mult_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3825 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3826 | 1 | 1 | 0 | 0 |.M.| 0 | 1 |.mmod..........|.MM|.P.|.w1|.op1...|
3827 |.h01|.h11|.w0|.op0...|.h00|.h10|.dst.......|.src0......|.src1..|
3828 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3829 int op1
= ((iw0
>> (DSP32Mac_op1_bits
- 16)) & DSP32Mac_op1_mask
);
3830 int w1
= ((iw0
>> (DSP32Mac_w1_bits
- 16)) & DSP32Mac_w1_mask
);
3831 int P
= ((iw0
>> (DSP32Mac_p_bits
- 16)) & DSP32Mac_p_mask
);
3832 int MM
= ((iw0
>> (DSP32Mac_MM_bits
- 16)) & DSP32Mac_MM_mask
);
3833 int mmod
= ((iw0
>> (DSP32Mac_mmod_bits
- 16)) & DSP32Mac_mmod_mask
);
3834 int M
= ((iw0
>> (DSP32Mac_M_bits
- 16)) & DSP32Mac_M_mask
);
3835 int w0
= ((iw1
>> DSP32Mac_w0_bits
) & DSP32Mac_w0_mask
);
3836 int src0
= ((iw1
>> DSP32Mac_src0_bits
) & DSP32Mac_src0_mask
);
3837 int src1
= ((iw1
>> DSP32Mac_src1_bits
) & DSP32Mac_src1_mask
);
3838 int dst
= ((iw1
>> DSP32Mac_dst_bits
) & DSP32Mac_dst_mask
);
3839 int h10
= ((iw1
>> DSP32Mac_h10_bits
) & DSP32Mac_h10_mask
);
3840 int h00
= ((iw1
>> DSP32Mac_h00_bits
) & DSP32Mac_h00_mask
);
3841 int op0
= ((iw1
>> DSP32Mac_op0_bits
) & DSP32Mac_op0_mask
);
3842 int h11
= ((iw1
>> DSP32Mac_h11_bits
) & DSP32Mac_h11_mask
);
3843 int h01
= ((iw1
>> DSP32Mac_h01_bits
) & DSP32Mac_h01_mask
);
3845 bu32 res
= DREG (dst
);
3846 bu32 sat0
= 0, sat1
= 0;
3847 char _buf
[128], *buf
= _buf
;
3850 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32mult
);
3851 TRACE_EXTRACT (cpu
, "%s: M:%i mmod:%i MM:%i P:%i w1:%i op1:%i h01:%i h11:%i "
3852 "w0:%i op0:%i h00:%i h10:%i dst:%i src0:%i src1:%i",
3853 __func__
, M
, mmod
, MM
, P
, w1
, op1
, h01
, h11
, w0
, op0
, h00
, h10
,
3856 if (w1
== 0 && w0
== 0)
3857 illegal_instruction (cpu
);
3858 if (((1 << mmod
) & (P
? 0x313 : 0x1b57)) == 0)
3859 illegal_instruction (cpu
);
3860 if (P
&& ((dst
& 1) || (op1
!= 0) || (op0
!= 0) || !is_macmod_pmove (mmod
)))
3861 illegal_instruction (cpu
);
3862 if (!P
&& ((op1
!= 0) || (op0
!= 0) || !is_macmod_hmove (mmod
)))
3863 illegal_instruction (cpu
);
3865 /* First handle MAC1 side. */
3868 bu64 r
= decode_multfunc (cpu
, h01
, h11
, src0
, src1
, mmod
, MM
, &sat1
);
3869 bu32 res1
= extract_mult (cpu
, r
, mmod
, MM
, P
, NULL
);
3871 buf
+= sprintf (buf
, P
? "R%i" : "R%i.H", dst
+ P
);
3872 buf
+= sprintf (buf
, " = R%i.%c * R%i.%c",
3873 src0
, h01
? 'H' : 'L',
3874 src1
, h11
? 'H' : 'L');
3878 buf
+= sprintf (buf
, " (M)");
3880 buf
+= sprintf (buf
, ", ");
3884 STORE (DREG (dst
+ 1), res1
);
3887 if (res1
& 0xFFFF0000)
3888 illegal_instruction (cpu
);
3889 res
= REG_H_L (res1
<< 16, res
);
3893 /* First handle MAC0 side. */
3896 bu64 r
= decode_multfunc (cpu
, h00
, h10
, src0
, src1
, mmod
, 0, &sat0
);
3897 bu32 res0
= extract_mult (cpu
, r
, mmod
, 0, P
, NULL
);
3899 buf
+= sprintf (buf
, P
? "R%i" : "R%i.L", dst
);
3900 buf
+= sprintf (buf
, " = R%i.%c * R%i.%c",
3901 src0
, h01
? 'H' : 'L',
3902 src1
, h11
? 'H' : 'L');
3905 STORE (DREG (dst
), res0
);
3908 if (res0
& 0xFFFF0000)
3909 illegal_instruction (cpu
);
3910 res
= REG_H_L (res
, res0
);
3914 TRACE_INSN (cpu
, "%s%s;", _buf
, mac_optmode (mmod
, _MM
));
3916 if (!P
&& (w0
|| w1
))
3917 STORE (DREG (dst
), res
);
3921 STORE (ASTATREG (v
), sat0
| sat1
);
3922 STORE (ASTATREG (v_copy
), sat0
| sat1
);
3924 STORE (ASTATREG (vs
), 1);
3929 decode_dsp32alu_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3932 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3933 | 1 | 1 | 0 | 0 |.M.| 1 | 0 | - | - | - |.HL|.aopcde............|
3934 |.aop...|.s.|.x.|.dst0......|.dst1......|.src0......|.src1......|
3935 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3936 int s
= ((iw1
>> DSP32Alu_s_bits
) & DSP32Alu_s_mask
);
3937 int x
= ((iw1
>> DSP32Alu_x_bits
) & DSP32Alu_x_mask
);
3938 int aop
= ((iw1
>> DSP32Alu_aop_bits
) & DSP32Alu_aop_mask
);
3939 int src0
= ((iw1
>> DSP32Alu_src0_bits
) & DSP32Alu_src0_mask
);
3940 int src1
= ((iw1
>> DSP32Alu_src1_bits
) & DSP32Alu_src1_mask
);
3941 int dst0
= ((iw1
>> DSP32Alu_dst0_bits
) & DSP32Alu_dst0_mask
);
3942 int dst1
= ((iw1
>> DSP32Alu_dst1_bits
) & DSP32Alu_dst1_mask
);
3943 int M
= ((iw0
>> (DSP32Alu_M_bits
- 16)) & DSP32Alu_M_mask
);
3944 int HL
= ((iw0
>> (DSP32Alu_HL_bits
- 16)) & DSP32Alu_HL_mask
);
3945 int aopcde
= ((iw0
>> (DSP32Alu_aopcde_bits
- 16)) & DSP32Alu_aopcde_mask
);
3947 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32alu
);
3948 TRACE_EXTRACT (cpu
, "%s: M:%i HL:%i aopcde:%i aop:%i s:%i x:%i dst0:%i "
3949 "dst1:%i src0:%i src1:%i",
3950 __func__
, M
, HL
, aopcde
, aop
, s
, x
, dst0
, dst1
, src0
, src1
);
3952 if ((aop
== 0 || aop
== 2) && aopcde
== 9 && HL
== 0 && s
== 0)
3955 TRACE_INSN (cpu
, "A%i.L = R%i.L;", a
, src0
);
3956 SET_AWREG (a
, REG_H_L (AWREG (a
), DREG (src0
)));
3958 else if ((aop
== 0 || aop
== 2) && aopcde
== 9 && HL
== 1 && s
== 0)
3961 TRACE_INSN (cpu
, "A%i.H = R%i.H;", a
, src0
);
3962 SET_AWREG (a
, REG_H_L (DREG (src0
), AWREG (a
)));
3964 else if ((aop
== 1 || aop
== 0) && aopcde
== 5)
3966 bs32 val0
= DREG (src0
);
3967 bs32 val1
= DREG (src1
);
3970 bs32 ovX
, sBit1
, sBit2
, sBitRes1
, sBitRes2
;
3972 TRACE_INSN (cpu
, "R%i.%s = R%i %s R%i (RND12)", dst0
, HL
? "L" : "H",
3973 src0
, aop
& 0x1 ? "-" : "+", src1
);
3975 /* If subtract, just invert and add one. */
3979 /* Get the sign bits, since we need them later. */
3980 sBit1
= !!(val0
& 0x80000000);
3981 sBit2
= !!(val1
& 0x80000000);
3985 sBitRes1
= !!(res
& 0x80000000);
3986 /* Round to the 12th bit. */
3988 sBitRes2
= !!(res
& 0x80000000);
3996 positive_res + positive_round = neg
3997 Shift and upper 4 bits where not the same. */
3998 if ((!(sBit1
^ sBit2
) && (sBit1
^ sBitRes1
))
3999 || (!sBit1
&& !sBit2
&& sBitRes2
)
4000 || ((signRes
!= 0) && (signRes
!= -1)))
4002 /* Both X1 and X2 Neg res is neg overflow. */
4005 /* Both X1 and X2 Pos res is pos overflow. */
4006 else if (!sBit1
&& !sBit2
)
4008 /* Pos+Neg or Neg+Pos take the sign of the result. */
4018 /* Shift up now after overflow detection. */
4026 STORE (DREG (dst0
), REG_H_L (res
<< 16, DREG (dst0
)));
4028 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), res
));
4030 SET_ASTATREG (az
, res
== 0);
4031 SET_ASTATREG (an
, res
& 0x8000);
4032 SET_ASTATREG (v
, ovX
);
4034 SET_ASTATREG (vs
, ovX
);
4036 else if ((aop
== 2 || aop
== 3) && aopcde
== 5)
4038 bs32 val0
= DREG (src0
);
4039 bs32 val1
= DREG (src1
);
4042 TRACE_INSN (cpu
, "R%i.%s = R%i %s R%i (RND20)", dst0
, HL
? "L" : "H",
4043 src0
, aop
& 0x1 ? "-" : "+", src1
);
4045 /* If subtract, just invert and add one. */
4049 res
= (val0
>> 4) + (val1
>> 4) + (((val0
& 0xf) + (val1
& 0xf)) >> 4);
4051 /* Don't sign extend during the shift. */
4052 res
= ((bu32
)res
>> 16);
4054 /* Don't worry about overflows, since we are shifting right. */
4057 STORE (DREG (dst0
), REG_H_L (res
<< 16, DREG (dst0
)));
4059 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), res
));
4061 SET_ASTATREG (az
, res
== 0);
4062 SET_ASTATREG (an
, res
& 0x8000);
4063 SET_ASTATREG (v
, 0);
4065 else if (aopcde
== 2 || aopcde
== 3)
4067 bu32 s1
, s2
, val
, ac0_i
= 0, v_i
= 0;
4069 TRACE_INSN (cpu
, "R%i.%c = R%i.%c %c R%i.%c%s;",
4070 dst0
, HL
? 'H' : 'L',
4071 src0
, aop
& 2 ? 'H' : 'L',
4072 aopcde
== 2 ? '+' : '-',
4073 src1
, aop
& 1 ? 'H' : 'L',
4084 val
= add16 (cpu
, s1
, s2
, &ac0_i
, &v_i
, 0, 0, s
, 0);
4086 val
= sub16 (cpu
, s1
, s2
, &ac0_i
, &v_i
, 0, 0, s
, 0);
4088 SET_ASTATREG (ac0
, ac0_i
);
4089 SET_ASTATREG (v
, v_i
);
4091 SET_DREG_H (dst0
, val
<< 16);
4093 SET_DREG_L (dst0
, val
);
4095 SET_ASTATREG (an
, val
& 0x8000);
4098 else if ((aop
== 0 || aop
== 2) && aopcde
== 9 && s
== 1)
4101 TRACE_INSN (cpu
, "A%i = R%i;", a
, src0
);
4102 SET_AREG32 (a
, DREG (src0
));
4104 else if ((aop
== 1 || aop
== 3) && aopcde
== 9 && s
== 0)
4107 TRACE_INSN (cpu
, "A%i.X = R%i.L;", a
, src0
);
4108 SET_AXREG (a
, (bs8
)DREG (src0
));
4110 else if (aop
== 3 && aopcde
== 11 && (s
== 0 || s
== 1))
4112 bu64 acc0
= get_extended_acc (cpu
, 0);
4113 bu64 acc1
= get_extended_acc (cpu
, 1);
4114 bu32 carry
= (bu40
)acc1
< (bu40
)acc0
;
4117 TRACE_INSN (cpu
, "A0 -= A1%s;", s
? " (W32)" : "");
4120 if ((bs64
)acc0
< -0x8000000000ll
)
4121 acc0
= -0x8000000000ull
, sat
= 1;
4122 else if ((bs64
)acc0
>= 0x7fffffffffll
)
4123 acc0
= 0x7fffffffffull
, sat
= 1;
4127 /* A0 -= A1 (W32) */
4128 if (acc0
& (bu64
)0x8000000000ll
)
4129 acc0
&= 0x80ffffffffll
, sat
= 1;
4131 acc0
&= 0xffffffffll
;
4133 STORE (AXREG (0), (acc0
>> 32) & 0xff);
4134 STORE (AWREG (0), acc0
& 0xffffffff);
4135 STORE (ASTATREG (az
), acc0
== 0);
4136 STORE (ASTATREG (an
), !!(acc0
& (bu64
)0x8000000000ll
));
4137 STORE (ASTATREG (ac0
), carry
);
4138 STORE (ASTATREG (ac0_copy
), carry
);
4139 STORE (ASTATREG (av0
), sat
);
4141 STORE (ASTATREG (av0s
), sat
);
4143 else if ((aop
== 0 || aop
== 1) && aopcde
== 22)
4145 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4147 const char * const opts
[] = { "rndl", "rndh", "tl", "th" };
4149 TRACE_INSN (cpu
, "R%i = BYTEOP2P (R%i:%i, R%i:%i) (%s%s);", dst0
,
4150 src0
+ 1, src0
, src1
+ 1, src1
, opts
[HL
+ (aop
<< 1)],
4154 illegal_instruction_combination (cpu
);
4157 s0H
= DREG (src0
+ 1);
4159 s1H
= DREG (src1
+ 1);
4162 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4163 s1
= algn (s1H
, s1L
, IREG (0) & 3);
4167 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4168 s1
= algn (s1L
, s1H
, IREG (0) & 3);
4172 tmp0
= ((((s1
>> 8) & 0xff) + ((s1
>> 0) & 0xff) +
4173 ((s0
>> 8) & 0xff) + ((s0
>> 0) & 0xff) + i
) >> 2) & 0xff;
4174 tmp1
= ((((s1
>> 24) & 0xff) + ((s1
>> 16) & 0xff) +
4175 ((s0
>> 24) & 0xff) + ((s0
>> 16) & 0xff) + i
) >> 2) & 0xff;
4176 SET_DREG (dst0
, (tmp1
<< (16 + (HL
* 8))) | (tmp0
<< (HL
* 8)));
4178 else if ((aop
== 0 || aop
== 1) && s
== 0 && aopcde
== 8)
4180 TRACE_INSN (cpu
, "A%i = 0;", aop
);
4183 else if (aop
== 2 && s
== 0 && aopcde
== 8)
4185 TRACE_INSN (cpu
, "A1 = A0 = 0;");
4189 else if ((aop
== 0 || aop
== 1 || aop
== 2) && s
== 1 && aopcde
== 8)
4191 bs40 acc0
= get_extended_acc (cpu
, 0);
4192 bs40 acc1
= get_extended_acc (cpu
, 1);
4195 if (aop
== 0 || aop
== 1)
4196 TRACE_INSN (cpu
, "A%i = A%i (S);", aop
, aop
);
4198 TRACE_INSN (cpu
, "A1 = A1 (S), A0 = A0 (S);");
4200 if (aop
== 0 || aop
== 2)
4203 acc0
= saturate_s32 (acc0
, &sat
);
4204 acc0
|= -(acc0
& 0x80000000ull
);
4205 SET_AXREG (0, (acc0
>> 31) & 0xFF);
4206 SET_AWREG (0, acc0
& 0xFFFFFFFF);
4207 SET_ASTATREG (av0
, sat
);
4209 SET_ASTATREG (av0s
, sat
);
4214 if (aop
== 1 || aop
== 2)
4217 acc1
= saturate_s32 (acc1
, &sat
);
4218 acc1
|= -(acc1
& 0x80000000ull
);
4219 SET_AXREG (1, (acc1
>> 31) & 0xFF);
4220 SET_AWREG (1, acc1
& 0xFFFFFFFF);
4221 SET_ASTATREG (av1
, sat
);
4223 SET_ASTATREG (av1s
, sat
);
4228 SET_ASTATREG (az
, (acc0
== 0) || (acc1
== 0));
4229 SET_ASTATREG (an
, ((acc0
>> 31) & 1) || ((acc1
>> 31) & 1));
4231 else if (aop
== 3 && (s
== 0 || s
== 1) && aopcde
== 8)
4233 TRACE_INSN (cpu
, "A%i = A%i;", s
, !s
);
4234 SET_AXREG (s
, AXREG (!s
));
4235 SET_AWREG (s
, AWREG (!s
));
4237 else if (aop
== 3 && HL
== 0 && aopcde
== 16)
4242 TRACE_INSN (cpu
, "A1 = ABS A1 , A0 = ABS A0;");
4245 for (i
= 0; i
< 2; ++i
)
4248 bs40 acc
= get_extended_acc (cpu
, i
);
4252 av
= acc
== ((bs40
)1 << 39);
4254 acc
= ((bs40
)1 << 39) - 1;
4257 SET_ASTATREG (av
[i
], av
);
4259 SET_ASTATREG (avs
[i
], av
);
4262 SET_ASTATREG (az
, az
);
4263 SET_ASTATREG (an
, 0);
4265 else if (aop
== 0 && aopcde
== 23)
4267 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4270 TRACE_INSN (cpu
, "R%i = BYTEOP3P (R%i:%i, R%i:%i) (%s%s);", dst0
,
4271 src0
+ 1, src0
, src1
+ 1, src1
, HL
? "HI" : "LO",
4275 illegal_instruction_combination (cpu
);
4278 s0H
= DREG (src0
+ 1);
4280 s1H
= DREG (src1
+ 1);
4283 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4284 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4288 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4289 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4292 tmp0
= (bs32
)(bs16
)(s0
>> 0) + ((s1
>> ( 0 + (8 * !HL
))) & 0xff);
4293 tmp1
= (bs32
)(bs16
)(s0
>> 16) + ((s1
>> (16 + (8 * !HL
))) & 0xff);
4294 SET_DREG (dst0
, (CLAMP (tmp0
, 0, 255) << ( 0 + (8 * HL
))) |
4295 (CLAMP (tmp1
, 0, 255) << (16 + (8 * HL
))));
4297 else if ((aop
== 0 || aop
== 1) && aopcde
== 16)
4302 TRACE_INSN (cpu
, "A%i = ABS A%i;", HL
, aop
);
4304 acc
= get_extended_acc (cpu
, aop
);
4307 av
= acc
== ((bs40
)1 << 39);
4309 acc
= ((bs40
)1 << 39) - 1;
4312 SET_ASTATREG (av
[HL
], av
);
4314 SET_ASTATREG (avs
[HL
], av
);
4315 SET_ASTATREG (az
, acc
== 0);
4316 SET_ASTATREG (an
, 0);
4318 else if (aop
== 3 && aopcde
== 12)
4320 bs32 res
= DREG (src0
);
4322 bool sBit_a
, sBit_b
;
4324 TRACE_INSN (cpu
, "R%i.%s = R%i (RND);", dst0
, HL
== 0 ? "L" : "H", src0
);
4325 TRACE_DECODE (cpu
, "R%i.%s = R%i:%#x (RND);", dst0
,
4326 HL
== 0 ? "L" : "H", src0
, res
);
4328 sBit_b
= !!(res
& 0x80000000);
4331 sBit_a
= !!(res
& 0x80000000);
4333 /* Overflow if the sign bit changed when we rounded. */
4334 if ((res
>> 16) && (sBit_b
!= sBit_a
))
4349 SET_DREG (dst0
, REG_H_L (DREG (dst0
), res
));
4351 SET_DREG (dst0
, REG_H_L (res
<< 16, DREG (dst0
)));
4353 SET_ASTATREG (az
, res
== 0);
4354 SET_ASTATREG (an
, res
< 0);
4355 SET_ASTATREG (v
, ovX
);
4357 SET_ASTATREG (vs
, ovX
);
4359 else if (aop
== 3 && HL
== 0 && aopcde
== 15)
4361 bu32 hi
= (-(bs16
)(DREG (src0
) >> 16)) << 16;
4362 bu32 lo
= (-(bs16
)(DREG (src0
) & 0xFFFF)) & 0xFFFF;
4365 TRACE_INSN (cpu
, "R%i = -R%i (V);", dst0
, src0
);
4369 if (hi
== 0x80000000)
4385 SET_DREG (dst0
, hi
| lo
);
4387 SET_ASTATREG (v
, v
);
4389 SET_ASTATREG (vs
, 1);
4390 SET_ASTATREG (ac0
, ac0
);
4391 SET_ASTATREG (ac1
, ac1
);
4392 setflags_nz_2x16 (cpu
, DREG (dst0
));
4394 else if (aop
== 3 && HL
== 0 && aopcde
== 14)
4396 TRACE_INSN (cpu
, "A1 = - A1 , A0 = - A0;");
4398 SET_AREG (0, saturate_s40 (-get_extended_acc (cpu
, 0)));
4399 SET_AREG (1, saturate_s40 (-get_extended_acc (cpu
, 1)));
4400 /* XXX: what ASTAT flags need updating ? */
4402 else if ((aop
== 0 || aop
== 1) && (HL
== 0 || HL
== 1) && aopcde
== 14)
4404 bs40 src_acc
= get_extended_acc (cpu
, aop
);
4406 TRACE_INSN (cpu
, "A%i = - A%i;", HL
, aop
);
4408 SET_AREG (HL
, saturate_s40 (-src_acc
));
4410 SET_ASTATREG (az
, AWREG (HL
) == 0 && AXREG (HL
) == 0);
4411 SET_ASTATREG (an
, AXREG (HL
) >> 7);
4412 SET_ASTATREG (ac0
, src_acc
== 0);
4415 SET_ASTATREG (av0
, src_acc
< 0);
4417 SET_ASTATREG (av0s
, 1);
4421 SET_ASTATREG (av1
, src_acc
< 0);
4423 SET_ASTATREG (av1s
, 1);
4426 else if (aop
== 0 && aopcde
== 12)
4428 bs16 tmp0_hi
= DREG (src0
) >> 16;
4429 bs16 tmp0_lo
= DREG (src0
);
4430 bs16 tmp1_hi
= DREG (src1
) >> 16;
4431 bs16 tmp1_lo
= DREG (src1
);
4433 TRACE_INSN (cpu
, "R%i.L = R%i.H = SIGN(R%i.H) * R%i.H + SIGN(R%i.L) * R%i.L;",
4434 dst0
, dst0
, src0
, src1
, src0
, src1
);
4436 if ((tmp0_hi
>> 15) & 1)
4437 tmp1_hi
= ~tmp1_hi
+ 1;
4439 if ((tmp0_lo
>> 15) & 1)
4440 tmp1_lo
= ~tmp1_lo
+ 1;
4442 tmp1_hi
= tmp1_hi
+ tmp1_lo
;
4444 STORE (DREG (dst0
), REG_H_L (tmp1_hi
<< 16, tmp1_hi
));
4446 else if (aopcde
== 0)
4448 bu32 s0
= DREG (src0
);
4449 bu32 s1
= DREG (src1
);
4450 bu32 s0h
= s0
>> 16;
4451 bu32 s0l
= s0
& 0xFFFF;
4452 bu32 s1h
= s1
>> 16;
4453 bu32 s1l
= s1
& 0xFFFF;
4455 bu32 ac1_i
= 0, ac0_i
= 0, v_i
= 0, z_i
= 0, n_i
= 0;
4457 TRACE_INSN (cpu
, "R%i = R%i %c|%c R%i%s;", dst0
, src0
,
4458 (aop
& 2) ? '-' : '+', (aop
& 1) ? '-' : '+', src1
,
4461 t0
= sub16 (cpu
, s0h
, s1h
, &ac1_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4463 t0
= add16 (cpu
, s0h
, s1h
, &ac1_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4466 t1
= sub16 (cpu
, s0l
, s1l
, &ac0_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4468 t1
= add16 (cpu
, s0l
, s1l
, &ac0_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4470 SET_ASTATREG (ac1
, ac1_i
);
4471 SET_ASTATREG (ac0
, ac0_i
);
4472 SET_ASTATREG (az
, z_i
);
4473 SET_ASTATREG (an
, n_i
);
4474 SET_ASTATREG (v
, v_i
);
4476 SET_ASTATREG (vs
, v_i
);
4481 SET_DREG (dst0
, (t1
<< 16) | t0
);
4483 SET_DREG (dst0
, (t0
<< 16) | t1
);
4485 else if (aop
== 1 && aopcde
== 12)
4487 bu32 val0
= ((AWREG (0) >> 16) + (AWREG (0) & 0xFFFF)) & 0xFFFF;
4488 bu32 val1
= ((AWREG (1) >> 16) + (AWREG (1) & 0xFFFF)) & 0xFFFF;
4490 TRACE_INSN (cpu
, "R%i = A1.L + A1.H, R%i = A0.L + A0.H;", dst1
, dst0
);
4493 illegal_instruction_combination (cpu
);
4501 SET_DREG (dst0
, val0
);
4502 SET_DREG (dst1
, val1
);
4505 else if (aopcde
== 1)
4509 bu16 s0L
= DREG (src0
);
4510 bu16 s0H
= DREG (src0
) >> 16;
4511 bu16 s1L
= DREG (src1
);
4512 bu16 s1H
= DREG (src1
) >> 16;
4513 bu32 v_i
= 0, n_i
= 0, z_i
= 0;
4515 TRACE_INSN (cpu
, "R%i = R%i %s R%i, R%i = R%i %s R%i%s;",
4516 dst1
, src0
, HL
? "+|-" : "+|+", src1
,
4517 dst0
, src0
, HL
? "-|+" : "-|-", src1
,
4518 amod0amod2 (s
, x
, aop
));
4521 illegal_instruction_combination (cpu
);
4525 x0
= add16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4526 x1
= add16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4527 d1
= (x0
<< 16) | x1
;
4529 x0
= sub16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4530 x1
= sub16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4532 d0
= (x0
<< 16) | x1
;
4534 d0
= (x1
<< 16) | x0
;
4538 x0
= add16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4539 x1
= sub16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4540 d1
= (x0
<< 16) | x1
;
4542 x0
= sub16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4543 x1
= add16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4545 d0
= (x0
<< 16) | x1
;
4547 d0
= (x1
<< 16) | x0
;
4549 SET_ASTATREG (az
, z_i
);
4550 SET_ASTATREG (an
, n_i
);
4551 SET_ASTATREG (v
, v_i
);
4553 SET_ASTATREG (vs
, v_i
);
4555 STORE (DREG (dst0
), d0
);
4556 STORE (DREG (dst1
), d1
);
4558 else if ((aop
== 0 || aop
== 1 || aop
== 2) && aopcde
== 11)
4560 bs40 acc0
= get_extended_acc (cpu
, 0);
4561 bs40 acc1
= get_extended_acc (cpu
, 1);
4562 bu32 v
, dreg
, sat
= 0;
4563 bu32 carry
= !!((bu40
)~acc1
< (bu40
)acc0
);
4566 TRACE_INSN (cpu
, "R%i = (A0 += A1);", dst0
);
4568 TRACE_INSN (cpu
, "R%i.%c = (A0 += A1);", dst0
, HL
? 'H' : 'L');
4570 TRACE_INSN (cpu
, "A0 += A1%s;", s
? " (W32)" : "");
4573 acc0
= saturate_s40_astat (acc0
, &v
);
4575 if (aop
== 2 && s
== 1) /* A0 += A1 (W32) */
4577 if (acc0
& (bs40
)0x8000000000ll
)
4578 acc0
&= 0x80ffffffffll
;
4580 acc0
&= 0xffffffffll
;
4583 STORE (AXREG (0), acc0
>> 32);
4584 STORE (AWREG (0), acc0
);
4585 SET_ASTATREG (av0
, v
&& acc1
);
4587 SET_ASTATREG (av0s
, v
);
4589 if (aop
== 0 || aop
== 1)
4591 if (aop
) /* Dregs_lo = A0 += A1 */
4593 dreg
= saturate_s32 (rnd16 (acc0
) << 16, &sat
);
4595 STORE (DREG (dst0
), REG_H_L (dreg
, DREG (dst0
)));
4597 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), dreg
>> 16));
4599 else /* Dregs = A0 += A1 */
4601 dreg
= saturate_s32 (acc0
, &sat
);
4602 STORE (DREG (dst0
), dreg
);
4605 STORE (ASTATREG (az
), dreg
== 0);
4606 STORE (ASTATREG (an
), !!(dreg
& 0x80000000));
4607 STORE (ASTATREG (ac0
), carry
);
4608 STORE (ASTATREG (ac0_copy
), carry
);
4609 STORE (ASTATREG (v
), sat
);
4610 STORE (ASTATREG (v_copy
), sat
);
4612 STORE (ASTATREG (vs
), sat
);
4616 STORE (ASTATREG (az
), acc0
== 0);
4617 STORE (ASTATREG (an
), !!(acc0
& 0x8000000000ull
));
4618 STORE (ASTATREG (ac0
), carry
);
4619 STORE (ASTATREG (ac0_copy
), carry
);
4622 else if ((aop
== 0 || aop
== 1) && aopcde
== 10)
4624 TRACE_INSN (cpu
, "R%i.L = A%i.X;", dst0
, aop
);
4625 SET_DREG_L (dst0
, (bs8
)AXREG (aop
));
4627 else if (aop
== 0 && aopcde
== 4)
4629 TRACE_INSN (cpu
, "R%i = R%i + R%i%s;", dst0
, src0
, src1
, amod1 (s
, x
));
4630 SET_DREG (dst0
, add32 (cpu
, DREG (src0
), DREG (src1
), 1, s
));
4632 else if (aop
== 1 && aopcde
== 4)
4634 TRACE_INSN (cpu
, "R%i = R%i - R%i%s;", dst0
, src0
, src1
, amod1 (s
, x
));
4635 SET_DREG (dst0
, sub32 (cpu
, DREG (src0
), DREG (src1
), 1, s
, 0));
4637 else if (aop
== 2 && aopcde
== 4)
4639 TRACE_INSN (cpu
, "R%i = R%i + R%i, R%i = R%i - R%i%s;",
4640 dst1
, src0
, src1
, dst0
, src0
, src1
, amod1 (s
, x
));
4643 illegal_instruction_combination (cpu
);
4645 STORE (DREG (dst1
), add32 (cpu
, DREG (src0
), DREG (src1
), 1, s
));
4646 STORE (DREG (dst0
), sub32 (cpu
, DREG (src0
), DREG (src1
), 1, s
, 1));
4648 else if ((aop
== 0 || aop
== 1) && aopcde
== 17)
4650 bs40 acc0
= get_extended_acc (cpu
, 0);
4651 bs40 acc1
= get_extended_acc (cpu
, 1);
4652 bs40 val0
, val1
, sval0
, sval1
;
4655 TRACE_INSN (cpu
, "R%i = A%i + A%i, R%i = A%i - A%i%s",
4656 dst1
, !aop
, aop
, dst0
, !aop
, aop
, amod1 (s
, x
));
4657 TRACE_DECODE (cpu
, "R%i = A%i:%#"PRIx64
" + A%i:%#"PRIx64
", "
4658 "R%i = A%i:%#"PRIx64
" - A%i:%#"PRIx64
"%s",
4659 dst1
, !aop
, aop
? acc0
: acc1
, aop
, aop
? acc1
: acc0
,
4660 dst0
, !aop
, aop
? acc0
: acc1
, aop
, aop
? acc1
: acc0
,
4664 illegal_instruction_combination (cpu
);
4672 sval0
= saturate_s32 (val0
, &sat
);
4674 sval1
= saturate_s32 (val1
, &sat
);
4682 STORE (DREG (dst0
), val0
);
4683 STORE (DREG (dst1
), val1
);
4684 SET_ASTATREG (v
, sat_i
);
4686 SET_ASTATREG (vs
, sat_i
);
4687 SET_ASTATREG (an
, val0
& 0x80000000 || val1
& 0x80000000);
4688 SET_ASTATREG (az
, val0
== 0 || val1
== 0);
4689 SET_ASTATREG (ac1
, (bu40
)~acc0
< (bu40
)acc1
);
4691 SET_ASTATREG (ac0
, !!((bu40
)acc1
<= (bu40
)acc0
));
4693 SET_ASTATREG (ac0
, !!((bu40
)acc0
<= (bu40
)acc1
));
4695 else if (aop
== 0 && aopcde
== 18)
4697 bu40 acc0
= get_extended_acc (cpu
, 0);
4698 bu40 acc1
= get_extended_acc (cpu
, 1);
4699 bu32 s0L
= DREG (src0
);
4700 bu32 s0H
= DREG (src0
+ 1);
4701 bu32 s1L
= DREG (src1
);
4702 bu32 s1H
= DREG (src1
+ 1);
4704 bs16 tmp0
, tmp1
, tmp2
, tmp3
;
4706 /* This instruction is only defined for register pairs R1:0 and R3:2. */
4707 if (!((src0
== 0 || src0
== 2) && (src1
== 0 || src1
== 2)))
4708 illegal_instruction (cpu
);
4710 TRACE_INSN (cpu
, "SAA (R%i:%i, R%i:%i)%s", src0
+ 1, src0
,
4711 src1
+ 1, src1
, s
? " (R)" :"");
4713 /* Bit s determines the order of the two registers from a pair:
4714 if s=0 the low-order bytes come from the low reg in the pair,
4715 and if s=1 the low-order bytes come from the high reg. */
4719 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4720 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4724 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4725 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4728 /* Find the absolute difference between pairs, make it
4729 absolute, then add it to the existing accumulator half. */
4731 tmp0
= ((s0
<< 24) >> 24) - ((s1
<< 24) >> 24);
4732 tmp1
= ((s0
<< 16) >> 24) - ((s1
<< 16) >> 24);
4733 tmp2
= ((s0
<< 8) >> 24) - ((s1
<< 8) >> 24);
4734 tmp3
= ((s0
<< 0) >> 24) - ((s1
<< 0) >> 24);
4736 tmp0
= (tmp0
< 0) ? -tmp0
: tmp0
;
4737 tmp1
= (tmp1
< 0) ? -tmp1
: tmp1
;
4738 tmp2
= (tmp2
< 0) ? -tmp2
: tmp2
;
4739 tmp3
= (tmp3
< 0) ? -tmp3
: tmp3
;
4741 s0L
= saturate_u16 ((bu32
)tmp0
+ ((acc0
>> 0) & 0xffff), 0);
4742 s0H
= saturate_u16 ((bu32
)tmp1
+ ((acc0
>> 16) & 0xffff), 0);
4743 s1L
= saturate_u16 ((bu32
)tmp2
+ ((acc1
>> 0) & 0xffff), 0);
4744 s1H
= saturate_u16 ((bu32
)tmp3
+ ((acc1
>> 16) & 0xffff), 0);
4746 STORE (AWREG (0), (s0H
<< 16) | (s0L
& 0xFFFF));
4747 STORE (AXREG (0), 0);
4748 STORE (AWREG (1), (s1H
<< 16) | (s1L
& 0xFFFF));
4749 STORE (AXREG (1), 0);
4751 else if (aop
== 3 && aopcde
== 18)
4753 TRACE_INSN (cpu
, "DISALGNEXCPT");
4756 else if ((aop
== 0 || aop
== 1) && aopcde
== 20)
4758 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4759 const char * const opts
[] = { "", " (R)", " (T)", " (T, R)" };
4761 TRACE_INSN (cpu
, "R%i = BYTEOP1P (R%i:%i, R%i:%i)%s;", dst0
,
4762 src0
+ 1, src0
, src1
+ 1, src1
, opts
[s
+ (aop
<< 1)]);
4765 illegal_instruction_combination (cpu
);
4768 s0H
= DREG (src0
+ 1);
4770 s1H
= DREG (src1
+ 1);
4773 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4774 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4778 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4779 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4783 (((((s0
>> 0) & 0xff) + ((s1
>> 0) & 0xff) + !aop
) >> 1) << 0) |
4784 (((((s0
>> 8) & 0xff) + ((s1
>> 8) & 0xff) + !aop
) >> 1) << 8) |
4785 (((((s0
>> 16) & 0xff) + ((s1
>> 16) & 0xff) + !aop
) >> 1) << 16) |
4786 (((((s0
>> 24) & 0xff) + ((s1
>> 24) & 0xff) + !aop
) >> 1) << 24));
4788 else if (aop
== 0 && aopcde
== 21)
4790 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4792 TRACE_INSN (cpu
, "(R%i, R%i) = BYTEOP16P (R%i:%i, R%i:%i)%s;", dst1
, dst0
,
4793 src0
+ 1, src0
, src1
+ 1, src1
, s
? " (R)" : "");
4796 illegal_instruction_combination (cpu
);
4799 s0H
= DREG (src0
+ 1);
4801 s1H
= DREG (src1
+ 1);
4804 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4805 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4809 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4810 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4814 ((((s0
>> 0) & 0xff) + ((s1
>> 0) & 0xff)) << 0) |
4815 ((((s0
>> 8) & 0xff) + ((s1
>> 8) & 0xff)) << 16));
4817 ((((s0
>> 16) & 0xff) + ((s1
>> 16) & 0xff)) << 0) |
4818 ((((s0
>> 24) & 0xff) + ((s1
>> 24) & 0xff)) << 16));
4820 else if (aop
== 1 && aopcde
== 21)
4822 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4824 TRACE_INSN (cpu
, "(R%i, R%i) = BYTEOP16M (R%i:%i, R%i:%i)%s;", dst1
, dst0
,
4825 src0
+ 1, src0
, src1
+ 1, src1
, s
? " (R)" : "");
4828 illegal_instruction_combination (cpu
);
4831 s0H
= DREG (src0
+ 1);
4833 s1H
= DREG (src1
+ 1);
4836 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4837 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4841 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4842 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4846 (((((s0
>> 0) & 0xff) - ((s1
>> 0) & 0xff)) << 0) & 0xffff) |
4847 (((((s0
>> 8) & 0xff) - ((s1
>> 8) & 0xff)) << 16)));
4849 (((((s0
>> 16) & 0xff) - ((s1
>> 16) & 0xff)) << 0) & 0xffff) |
4850 (((((s0
>> 24) & 0xff) - ((s1
>> 24) & 0xff)) << 16)));
4852 else if (aop
== 1 && aopcde
== 7)
4854 TRACE_INSN (cpu
, "R%i = MIN (R%i, R%i);", dst0
, src0
, src1
);
4855 SET_DREG (dst0
, min32 (cpu
, DREG (src0
), DREG (src1
)));
4857 else if (aop
== 0 && aopcde
== 7)
4859 TRACE_INSN (cpu
, "R%i = MAX (R%i, R%i);", dst0
, src0
, src1
);
4860 SET_DREG (dst0
, max32 (cpu
, DREG (src0
), DREG (src1
)));
4862 else if (aop
== 2 && aopcde
== 7)
4864 bu32 val
= DREG (src0
);
4867 TRACE_INSN (cpu
, "R%i = ABS R%i;", dst0
, src0
);
4871 v
= (val
== 0x80000000);
4874 SET_DREG (dst0
, val
);
4876 SET_ASTATREG (v
, v
);
4878 SET_ASTATREG (vs
, 1);
4879 setflags_nz (cpu
, val
);
4881 else if (aop
== 3 && aopcde
== 7)
4883 bu32 val
= DREG (src0
);
4885 TRACE_INSN (cpu
, "R%i = - R%i %s;", dst0
, src0
, amod1 (s
, 0));
4887 if (s
&& val
== 0x80000000)
4890 SET_ASTATREG (v
, 1);
4891 SET_ASTATREG (vs
, 1);
4893 else if (val
== 0x80000000)
4897 SET_DREG (dst0
, val
);
4899 SET_ASTATREG (az
, val
== 0);
4900 SET_ASTATREG (an
, val
& 0x80000000);
4902 else if (aop
== 2 && aopcde
== 6)
4904 bu32 in
= DREG (src0
);
4905 bu32 hi
= (in
& 0x80000000 ? (bu32
)-(bs16
)(in
>> 16) : in
>> 16) << 16;
4906 bu32 lo
= (in
& 0x8000 ? (bu32
)-(bs16
)(in
& 0xFFFF) : in
) & 0xFFFF;
4909 TRACE_INSN (cpu
, "R%i = ABS R%i (V);", dst0
, src0
);
4912 if (hi
== 0x80000000)
4922 SET_DREG (dst0
, hi
| lo
);
4924 SET_ASTATREG (v
, v
);
4926 SET_ASTATREG (vs
, 1);
4927 setflags_nz_2x16 (cpu
, DREG (dst0
));
4929 else if (aop
== 1 && aopcde
== 6)
4931 TRACE_INSN (cpu
, "R%i = MIN (R%i, R%i) (V);", dst0
, src0
, src1
);
4932 SET_DREG (dst0
, min2x16 (cpu
, DREG (src0
), DREG (src1
)));
4934 else if (aop
== 0 && aopcde
== 6)
4936 TRACE_INSN (cpu
, "R%i = MAX (R%i, R%i) (V);", dst0
, src0
, src1
);
4937 SET_DREG (dst0
, max2x16 (cpu
, DREG (src0
), DREG (src1
)));
4939 else if (aop
== 0 && aopcde
== 24)
4941 TRACE_INSN (cpu
, "R%i = BYTEPACK (R%i, R%i);", dst0
, src0
, src1
);
4943 (((DREG (src0
) >> 0) & 0xff) << 0) |
4944 (((DREG (src0
) >> 16) & 0xff) << 8) |
4945 (((DREG (src1
) >> 0) & 0xff) << 16) |
4946 (((DREG (src1
) >> 16) & 0xff) << 24));
4948 else if (aop
== 1 && aopcde
== 24)
4952 bu8 bytea
, byteb
, bytec
, byted
;
4954 TRACE_INSN (cpu
, "(R%i, R%i) = BYTEUNPACK R%i:%i%s;",
4955 dst1
, dst0
, src0
+ 1, src0
, s
? " (R)" : "");
4958 illegal_instruction_combination (cpu
);
4960 order
= IREG (0) & 0x3;
4962 hi
= src0
, lo
= src0
+ 1;
4964 hi
= src0
+ 1, lo
= src0
;
4965 comb_src
= (((bu64
)DREG (hi
)) << 32) | DREG (lo
);
4966 bytea
= (comb_src
>> (0 + 8 * order
));
4967 byteb
= (comb_src
>> (8 + 8 * order
));
4968 bytec
= (comb_src
>> (16 + 8 * order
));
4969 byted
= (comb_src
>> (24 + 8 * order
));
4970 SET_DREG (dst0
, bytea
| ((bu32
)byteb
<< 16));
4971 SET_DREG (dst1
, bytec
| ((bu32
)byted
<< 16));
4973 else if (aopcde
== 13)
4975 const char *searchmodes
[] = { "GT", "GE", "LT", "LE" };
4977 bs16 a0_lo
, a1_lo
, src_hi
, src_lo
;
4979 TRACE_INSN (cpu
, "(R%i, R%i) = SEARCH R%i (%s);",
4980 dst1
, dst0
, src0
, searchmodes
[aop
]);
4983 illegal_instruction_combination (cpu
);
4985 up_hi
= up_lo
= false;
4988 src_lo
= DREG (src0
);
4989 src_hi
= DREG (src0
) >> 16;
4994 up_hi
= (src_hi
> a1_lo
);
4995 up_lo
= (src_lo
> a0_lo
);
4998 up_hi
= (src_hi
>= a1_lo
);
4999 up_lo
= (src_lo
>= a0_lo
);
5002 up_hi
= (src_hi
< a1_lo
);
5003 up_lo
= (src_lo
< a0_lo
);
5006 up_hi
= (src_hi
<= a1_lo
);
5007 up_lo
= (src_lo
<= a0_lo
);
5013 SET_AREG (1, src_hi
);
5014 SET_DREG (dst1
, PREG (0));
5018 SET_AREG (0, src_lo
);
5019 SET_DREG (dst0
, PREG (0));
5023 illegal_instruction (cpu
);
5027 decode_dsp32shift_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
5030 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5031 | 1 | 1 | 0 | 0 |.M.| 1 | 1 | 0 | 0 | - | - |.sopcde............|
5032 |.sop...|.HLs...|.dst0......| - | - | - |.src0......|.src1......|
5033 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5034 int HLs
= ((iw1
>> DSP32Shift_HLs_bits
) & DSP32Shift_HLs_mask
);
5035 int sop
= ((iw1
>> DSP32Shift_sop_bits
) & DSP32Shift_sop_mask
);
5036 int src0
= ((iw1
>> DSP32Shift_src0_bits
) & DSP32Shift_src0_mask
);
5037 int src1
= ((iw1
>> DSP32Shift_src1_bits
) & DSP32Shift_src1_mask
);
5038 int dst0
= ((iw1
>> DSP32Shift_dst0_bits
) & DSP32Shift_dst0_mask
);
5039 int sopcde
= ((iw0
>> (DSP32Shift_sopcde_bits
- 16)) & DSP32Shift_sopcde_mask
);
5040 int M
= ((iw0
>> (DSP32Shift_M_bits
- 16)) & DSP32Shift_M_mask
);
5042 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32shift
);
5043 TRACE_EXTRACT (cpu
, "%s: M:%i sopcde:%i sop:%i HLs:%i dst0:%i src0:%i src1:%i",
5044 __func__
, M
, sopcde
, sop
, HLs
, dst0
, src0
, src1
);
5046 if ((sop
== 0 || sop
== 1) && sopcde
== 0)
5049 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5051 TRACE_INSN (cpu
, "R%i.%c = ASHIFT R%i.%c BY R%i.L%s;",
5052 dst0
, HLs
< 2 ? 'L' : 'H',
5053 src1
, HLs
& 1 ? 'H' : 'L',
5054 src0
, sop
== 1 ? " (S)" : "");
5057 val
= (bu16
)(DREG (src1
) & 0xFFFF);
5059 val
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5061 /* Positive shift magnitudes produce Logical Left shifts.
5062 Negative shift magnitudes produce Arithmetic Right shifts. */
5064 val
= ashiftrt (cpu
, val
, -shft
, 16);
5066 val
= lshift (cpu
, val
, shft
, 16, sop
== 1);
5069 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), val
));
5071 STORE (DREG (dst0
), REG_H_L (val
<< 16, DREG (dst0
)));
5073 else if (sop
== 2 && sopcde
== 0)
5075 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5078 TRACE_INSN (cpu
, "R%i.%c = LSHIFT R%i.%c BY R%i.L;",
5079 dst0
, HLs
< 2 ? 'L' : 'H',
5080 src1
, HLs
& 1 ? 'H' : 'L', src0
);
5083 val
= (bu16
)(DREG (src1
) & 0xFFFF);
5085 val
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5088 val
= val
>> (-1 * shft
);
5093 SET_DREG (dst0
, REG_H_L (DREG (dst0
), val
));
5095 SET_DREG (dst0
, REG_H_L (val
<< 16, DREG (dst0
)));
5097 SET_ASTATREG (az
, !((val
& 0xFFFF0000) == 0) || ((val
& 0xFFFF) == 0));
5098 SET_ASTATREG (an
, (!!(val
& 0x80000000)) ^ (!!(val
& 0x8000)));
5099 SET_ASTATREG (v
, 0);
5101 else if (sop
== 2 && sopcde
== 3 && (HLs
== 1 || HLs
== 0))
5103 int shift
= imm6 (DREG (src0
) & 0xFFFF);
5105 bu40 acc
= get_unextended_acc (cpu
, HLs
);
5107 TRACE_INSN (cpu
, "A%i = ROT A%i BY R%i.L;", HLs
, HLs
, src0
);
5108 TRACE_DECODE (cpu
, "A%i:%#"PRIx64
" shift:%i CC:%i", HLs
, acc
, shift
, cc
);
5110 acc
= rot40 (acc
, shift
, &cc
);
5111 SET_AREG (HLs
, acc
);
5115 else if (sop
== 0 && sopcde
== 3 && (HLs
== 0 || HLs
== 1))
5117 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5118 bu64 val
= get_extended_acc (cpu
, HLs
);
5121 TRACE_INSN (cpu
, "A%i = ASHIFT A%i BY R%i.L;", HLs
, HLs
, src0
);
5122 TRACE_DECODE (cpu
, "A%i:%#"PRIx64
" shift:%i", HLs
, val
, shft
);
5125 val
= ashiftrt (cpu
, val
, -shft
, 40);
5127 val
= lshift (cpu
, val
, shft
, 40, 0);
5129 STORE (AXREG (HLs
), (val
>> 32) & 0xff);
5130 STORE (AWREG (HLs
), (val
& 0xffffffff));
5132 else if (sop
== 1 && sopcde
== 3 && (HLs
== 0 || HLs
== 1))
5134 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5138 TRACE_INSN (cpu
, "A%i = LSHIFT A%i BY R%i.L;", HLs
, HLs
, src0
);
5139 val
= get_extended_acc (cpu
, HLs
);
5142 val
= lshiftrt (cpu
, val
, -shft
, 40);
5144 val
= lshift (cpu
, val
, shft
, 40, 0);
5146 STORE (AXREG (HLs
), (val
>> 32) & 0xff);
5147 STORE (AWREG (HLs
), (val
& 0xffffffff));
5149 else if ((sop
== 0 || sop
== 1) && sopcde
== 1)
5151 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5155 TRACE_INSN (cpu
, "R%i = ASHIFT R%i BY R%i.L (V%s);",
5156 dst0
, src1
, src0
, sop
== 1 ? ",S" : "");
5158 val0
= (bu16
)DREG (src1
) & 0xFFFF;
5159 val1
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5163 val0
= ashiftrt (cpu
, val0
, -shft
, 16);
5165 val1
= ashiftrt (cpu
, val1
, -shft
, 16);
5169 val0
= lshift (cpu
, val0
, shft
, 16, sop
== 1);
5171 val1
= lshift (cpu
, val1
, shft
, 16, sop
== 1);
5173 SET_ASTAT (ASTAT
| astat
);
5174 STORE (DREG (dst0
), (val1
<< 16) | val0
);
5176 else if ((sop
== 0 || sop
== 1 || sop
== 2) && sopcde
== 2)
5178 /* dregs = [LA]SHIFT dregs BY dregs_lo (opt_S) */
5179 /* sop == 1 : opt_S */
5180 bu32 v
= DREG (src1
);
5181 /* LSHIFT uses sign extended low 6 bits of dregs_lo. */
5182 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5184 TRACE_INSN (cpu
, "R%i = %cSHIFT R%i BY R%i.L%s;", dst0
,
5185 shft
&& sop
!= 2 ? 'A' : 'L', src1
, src0
,
5186 sop
== 1 ? " (S)" : "");
5191 STORE (DREG (dst0
), lshiftrt (cpu
, v
, -shft
, 32));
5193 STORE (DREG (dst0
), ashiftrt (cpu
, v
, -shft
, 32));
5196 STORE (DREG (dst0
), lshift (cpu
, v
, shft
, 32, sop
== 1));
5198 else if (sop
== 3 && sopcde
== 2)
5200 int shift
= imm6 (DREG (src0
) & 0xFFFF);
5201 bu32 src
= DREG (src1
);
5202 bu32 ret
, cc
= CCREG
;
5204 TRACE_INSN (cpu
, "R%i = ROT R%i BY R%i.L;", dst0
, src1
, src0
);
5205 TRACE_DECODE (cpu
, "R%i:%#x R%i:%#x shift:%i CC:%i",
5206 dst0
, DREG (dst0
), src1
, src
, shift
, cc
);
5208 ret
= rot32 (src
, shift
, &cc
);
5209 STORE (DREG (dst0
), ret
);
5213 else if (sop
== 2 && sopcde
== 1)
5215 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5219 TRACE_INSN (cpu
, "R%i = LSHIFT R%i BY R%i.L (V);", dst0
, src1
, src0
);
5221 val0
= (bu16
)DREG (src1
) & 0xFFFF;
5222 val1
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5226 val0
= lshiftrt (cpu
, val0
, -shft
, 16);
5228 val1
= lshiftrt (cpu
, val1
, -shft
, 16);
5232 val0
= lshift (cpu
, val0
, shft
, 16, 0);
5234 val1
= lshift (cpu
, val1
, shft
, 16, 0);
5236 SET_ASTAT (ASTAT
| astat
);
5237 STORE (DREG (dst0
), (val1
<< 16) | val0
);
5239 else if (sopcde
== 4)
5241 bu32 sv0
= DREG (src0
);
5242 bu32 sv1
= DREG (src1
);
5243 TRACE_INSN (cpu
, "R%i = PACK (R%i.%c, R%i.%c);", dst0
,
5244 src1
, sop
& 2 ? 'H' : 'L',
5245 src0
, sop
& 1 ? 'H' : 'L');
5250 SET_DREG (dst0
, (sv1
<< 16) | (sv0
& 0xFFFF));
5252 else if (sop
== 0 && sopcde
== 5)
5254 bu32 sv1
= DREG (src1
);
5255 TRACE_INSN (cpu
, "R%i.L = SIGNBITS R%i;", dst0
, src1
);
5256 SET_DREG_L (dst0
, signbits (sv1
, 32));
5258 else if (sop
== 1 && sopcde
== 5)
5260 bu32 sv1
= DREG (src1
);
5261 TRACE_INSN (cpu
, "R%i.L = SIGNBITS R%i.L;", dst0
, src1
);
5262 SET_DREG_L (dst0
, signbits (sv1
, 16));
5264 else if (sop
== 2 && sopcde
== 5)
5266 bu32 sv1
= DREG (src1
);
5267 TRACE_INSN (cpu
, "R%i.L = SIGNBITS R%i.H;", dst0
, src1
);
5268 SET_DREG_L (dst0
, signbits (sv1
>> 16, 16));
5270 else if ((sop
== 0 || sop
== 1) && sopcde
== 6)
5272 bu64 acc
= AXREG (sop
);
5273 TRACE_INSN (cpu
, "R%i.L = SIGNBITS A%i;", dst0
, sop
);
5276 SET_DREG_L (dst0
, signbits (acc
, 40) & 0xFFFF);
5278 else if (sop
== 3 && sopcde
== 6)
5280 bu32 v
= ones (DREG (src1
));
5281 TRACE_INSN (cpu
, "R%i.L = ONES R%i;", dst0
, src1
);
5282 SET_DREG_L (dst0
, v
);
5284 else if (sop
== 0 && sopcde
== 7)
5286 bu16 sv1
= (bu16
)signbits (DREG (src1
), 32);
5287 bu16 sv0
= (bu16
)DREG (src0
);
5290 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i, R%i.L);", dst0
, src1
, src0
);
5292 if ((sv1
& 0x1f) < (sv0
& 0x1f))
5296 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), dst_lo
));
5298 else if (sop
== 1 && sopcde
== 7)
5300 /* Exponent adjust on two 16-bit inputs. Select
5301 smallest norm among 3 inputs. */
5302 bs16 src1_hi
= (DREG (src1
) & 0xFFFF0000) >> 16;
5303 bs16 src1_lo
= (DREG (src1
) & 0xFFFF);
5304 bu16 src0_lo
= (DREG (src0
) & 0xFFFF);
5305 bu16 tmp_hi
, tmp_lo
, tmp
;
5307 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i, R%i.L) (V);", dst0
, src1
, src0
);
5309 tmp_hi
= signbits (src1_hi
, 16);
5310 tmp_lo
= signbits (src1_lo
, 16);
5312 if ((tmp_hi
& 0xf) < (tmp_lo
& 0xf))
5313 if ((tmp_hi
& 0xf) < (src0_lo
& 0xf))
5318 if ((tmp_lo
& 0xf) < (src0_lo
& 0xf))
5322 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), tmp
));
5324 else if (sop
== 2 && sopcde
== 7)
5326 /* Exponent adjust on single 16-bit register. */
5328 bu16 src0_lo
= (bu16
)(DREG (src0
) & 0xFFFF);
5330 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i.L, R%i.L);", dst0
, src1
, src0
);
5332 tmp
= signbits (DREG (src1
) & 0xFFFF, 16);
5334 if ((tmp
& 0xf) < (src0_lo
& 0xf))
5335 SET_DREG_L (dst0
, tmp
);
5337 SET_DREG_L (dst0
, src0_lo
);
5339 else if (sop
== 3 && sopcde
== 7)
5342 bu16 src0_lo
= (bu16
)(DREG (src0
) & 0xFFFF);
5344 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i.H, R%i.L);", dst0
, src1
, src0
);
5346 tmp
= signbits ((DREG (src1
) & 0xFFFF0000) >> 16, 16);
5348 if ((tmp
& 0xf) < (src0_lo
& 0xf))
5349 SET_DREG_L (dst0
, tmp
);
5351 SET_DREG_L (dst0
, src0_lo
);
5353 else if (sop
== 0 && sopcde
== 8)
5355 bu64 acc
= get_unextended_acc (cpu
, 0);
5358 TRACE_INSN (cpu
, "BITMUX (R%i, R%i, A0) (ASR);", src0
, src1
);
5361 illegal_instruction_combination (cpu
);
5366 (((bu64
)s0
& 1) << 38) |
5367 (((bu64
)s1
& 1) << 39);
5368 SET_DREG (src0
, s0
>> 1);
5369 SET_DREG (src1
, s1
>> 1);
5373 else if (sop
== 1 && sopcde
== 8)
5375 bu64 acc
= get_unextended_acc (cpu
, 0);
5378 TRACE_INSN (cpu
, "BITMUX (R%i, R%i, A0) (ASL);", src0
, src1
);
5381 illegal_instruction_combination (cpu
);
5388 SET_DREG (src0
, s0
<< 1);
5389 SET_DREG (src1
, s1
<< 1);
5393 else if ((sop
== 0 || sop
== 1) && sopcde
== 9)
5395 bs40 acc0
= get_extended_acc (cpu
, 0);
5398 TRACE_INSN (cpu
, "R%i.L = VIT_MAX (R%i) (AS%c);",
5399 dst0
, src1
, sop
& 1 ? 'R' : 'L');
5402 sH
= DREG (src1
) >> 16;
5409 if (((sH
- sL
) & 0x8000) == 0)
5412 acc0
|= (sop
& 1) ? 0x80000000 : 1;
5418 SET_DREG (dst0
, REG_H_L (DREG (dst0
), out
));
5420 else if ((sop
== 2 || sop
== 3) && sopcde
== 9)
5422 bs40 acc0
= get_extended_acc (cpu
, 0);
5423 bs16 s0L
, s0H
, s1L
, s1H
, out0
, out1
;
5425 TRACE_INSN (cpu
, "R%i = VIT_MAX (R%i, R%i) (AS%c);",
5426 dst0
, src1
, src0
, sop
& 1 ? 'R' : 'L');
5429 s0H
= DREG (src0
) >> 16;
5431 s1H
= DREG (src1
) >> 16;
5438 if (((s0H
- s0L
) & 0x8000) == 0)
5441 acc0
|= (sop
& 1) ? 0x40000000 : 2;
5446 if (((s1H
- s1L
) & 0x8000) == 0)
5449 acc0
|= (sop
& 1) ? 0x80000000 : 1;
5455 SET_DREG (dst0
, REG_H_L (out1
<< 16, out0
));
5457 else if (sop
== 0 && sopcde
== 10)
5459 bu32 v
= DREG (src0
);
5460 bu32 x
= DREG (src1
);
5461 bu32 mask
= (1 << (v
& 0x1f)) - 1;
5462 TRACE_INSN (cpu
, "R%i = EXTRACT (R%i, R%i.L) (Z);", dst0
, src1
, src0
);
5463 x
>>= ((v
>> 8) & 0x1f);
5464 SET_DREG (dst0
, x
& mask
);
5465 setflags_logical (cpu
, DREG (dst0
));
5467 else if (sop
== 1 && sopcde
== 10)
5469 bu32 v
= DREG (src0
);
5470 bu32 x
= DREG (src1
);
5471 bu32 sgn
= (1 << (v
& 0x1f)) >> 1;
5472 bu32 mask
= (1 << (v
& 0x1f)) - 1;
5473 TRACE_INSN (cpu
, "R%i = EXTRACT (R%i, R%i.L) (X);", dst0
, src1
, src0
);
5474 x
>>= ((v
>> 8) & 0x1f);
5479 setflags_logical (cpu
, DREG (dst0
));
5481 else if ((sop
== 2 || sop
== 3) && sopcde
== 10)
5483 /* The first dregs is the "background" while the second dregs is the
5484 "foreground". The fg reg is used to overlay the bg reg and is:
5485 | nnnn nnnn | nnnn nnnn | xxxp pppp | xxxL LLLL |
5486 n = the fg bit field
5487 p = bit position in bg reg to start LSB of fg field
5488 L = number of fg bits to extract
5489 Using (X) sign-extends the fg bit field. */
5490 bu32 fg
= DREG (src0
);
5491 bu32 bg
= DREG (src1
);
5492 bu32 len
= fg
& 0x1f;
5493 bu32 mask
= (1 << MIN (16, len
)) - 1;
5494 bu32 fgnd
= (fg
>> 16) & mask
;
5495 int shft
= ((fg
>> 8) & 0x1f);
5497 TRACE_INSN (cpu
, "R%i = DEPOSIT (R%i, R%i)%s;", dst0
, src1
, src0
,
5498 sop
== 3 ? " (X)" : "");
5502 /* Sign extend the fg bit field. */
5504 fgnd
= ((bs32
)(bs16
)(fgnd
<< (16 - len
))) >> (16 - len
);
5510 SET_DREG (dst0
, bg
| fgnd
);
5511 setflags_logical (cpu
, DREG (dst0
));
5513 else if (sop
== 0 && sopcde
== 11)
5515 bu64 acc0
= get_unextended_acc (cpu
, 0);
5517 TRACE_INSN (cpu
, "R%i.L = CC = BXORSHIFT (A0, R%i);", dst0
, src0
);
5520 SET_CCREG (xor_reduce (acc0
, DREG (src0
)));
5521 SET_DREG (dst0
, REG_H_L (DREG (dst0
), CCREG
));
5524 else if (sop
== 1 && sopcde
== 11)
5526 bu64 acc0
= get_unextended_acc (cpu
, 0);
5528 TRACE_INSN (cpu
, "R%i.L = CC = BXOR (A0, R%i);", dst0
, src0
);
5530 SET_CCREG (xor_reduce (acc0
, DREG (src0
)));
5531 SET_DREG (dst0
, REG_H_L (DREG (dst0
), CCREG
));
5533 else if (sop
== 0 && sopcde
== 12)
5535 bu64 acc0
= get_unextended_acc (cpu
, 0);
5536 bu64 acc1
= get_unextended_acc (cpu
, 1);
5538 TRACE_INSN (cpu
, "A0 = BXORSHIFT (A0, A1, CC);");
5540 acc0
= (acc0
<< 1) | (CCREG
^ xor_reduce (acc0
, acc1
));
5543 else if (sop
== 1 && sopcde
== 12)
5545 bu64 acc0
= get_unextended_acc (cpu
, 0);
5546 bu64 acc1
= get_unextended_acc (cpu
, 1);
5548 TRACE_INSN (cpu
, "R%i.L = CC = BXOR (A0, A1, CC);", dst0
);
5550 SET_CCREG (CCREG
^ xor_reduce (acc0
, acc1
));
5551 acc0
= (acc0
<< 1) | CCREG
;
5552 SET_DREG (dst0
, REG_H_L (DREG (dst0
), CCREG
));
5554 else if ((sop
== 0 || sop
== 1 || sop
== 2) && sopcde
== 13)
5556 int shift
= (sop
+ 1) * 8;
5557 TRACE_INSN (cpu
, "R%i = ALIGN%i (R%i, R%i);", dst0
, shift
, src1
, src0
);
5558 SET_DREG (dst0
, (DREG (src1
) << (32 - shift
)) | (DREG (src0
) >> shift
));
5561 illegal_instruction (cpu
);
5565 decode_dsp32shiftimm_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
5568 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5569 | 1 | 1 | 0 | 0 |.M.| 1 | 1 | 0 | 1 | - | - |.sopcde............|
5570 |.sop...|.HLs...|.dst0......|.immag.................|.src1......|
5571 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5572 int src1
= ((iw1
>> DSP32ShiftImm_src1_bits
) & DSP32ShiftImm_src1_mask
);
5573 int sop
= ((iw1
>> DSP32ShiftImm_sop_bits
) & DSP32ShiftImm_sop_mask
);
5574 int bit8
= ((iw1
>> 8) & 0x1);
5575 int immag
= ((iw1
>> DSP32ShiftImm_immag_bits
) & DSP32ShiftImm_immag_mask
);
5576 int newimmag
= (-(iw1
>> DSP32ShiftImm_immag_bits
) & DSP32ShiftImm_immag_mask
);
5577 int dst0
= ((iw1
>> DSP32ShiftImm_dst0_bits
) & DSP32ShiftImm_dst0_mask
);
5578 int M
= ((iw0
>> (DSP32ShiftImm_M_bits
- 16)) & DSP32ShiftImm_M_mask
);
5579 int sopcde
= ((iw0
>> (DSP32ShiftImm_sopcde_bits
- 16)) & DSP32ShiftImm_sopcde_mask
);
5580 int HLs
= ((iw1
>> DSP32ShiftImm_HLs_bits
) & DSP32ShiftImm_HLs_mask
);
5582 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32shiftimm
);
5583 TRACE_EXTRACT (cpu
, "%s: M:%i sopcde:%i sop:%i HLs:%i dst0:%i immag:%#x src1:%i",
5584 __func__
, M
, sopcde
, sop
, HLs
, dst0
, immag
, src1
);
5588 bu16 in
= DREG (src1
) >> ((HLs
& 1) ? 16 : 0);
5594 TRACE_INSN (cpu
, "R%i.%c = R%i.%c >>> %i;",
5595 dst0
, (HLs
& 2) ? 'H' : 'L',
5596 src1
, (HLs
& 1) ? 'H' : 'L', newimmag
);
5597 result
= ashiftrt (cpu
, in
, newimmag
, 16);
5599 else if (sop
== 1 && bit8
== 0)
5601 TRACE_INSN (cpu
, "R%i.%c = R%i.%c << %i (S);",
5602 dst0
, (HLs
& 2) ? 'H' : 'L',
5603 src1
, (HLs
& 1) ? 'H' : 'L', immag
);
5604 result
= lshift (cpu
, in
, immag
, 16, 1);
5606 else if (sop
== 1 && bit8
)
5608 TRACE_INSN (cpu
, "R%i.%c = R%i.%c >>> %i (S);",
5609 dst0
, (HLs
& 2) ? 'H' : 'L',
5610 src1
, (HLs
& 1) ? 'H' : 'L', immag
);
5611 result
= lshift (cpu
, in
, immag
, 16, 1);
5613 else if (sop
== 2 && bit8
)
5615 TRACE_INSN (cpu
, "R%i.%c = R%i.%c >> %i;",
5616 dst0
, (HLs
& 2) ? 'H' : 'L',
5617 src1
, (HLs
& 1) ? 'H' : 'L', newimmag
);
5618 result
= lshiftrt (cpu
, in
, newimmag
, 16);
5620 else if (sop
== 2 && bit8
== 0)
5622 TRACE_INSN (cpu
, "R%i.%c = R%i.%c << %i;",
5623 dst0
, (HLs
& 2) ? 'H' : 'L',
5624 src1
, (HLs
& 1) ? 'H' : 'L', immag
);
5625 result
= lshift (cpu
, in
, immag
, 16, 0);
5628 illegal_instruction (cpu
);
5632 STORE (DREG (dst0
), (v
& 0xFFFF) | (result
<< 16));
5634 STORE (DREG (dst0
), (v
& 0xFFFF0000) | result
);
5636 else if (sop
== 2 && sopcde
== 3 && (HLs
== 1 || HLs
== 0))
5638 int shift
= imm6 (immag
);
5640 bu40 acc
= get_unextended_acc (cpu
, HLs
);
5642 TRACE_INSN (cpu
, "A%i = ROT A%i BY %i;", HLs
, HLs
, shift
);
5643 TRACE_DECODE (cpu
, "A%i:%#"PRIx64
" shift:%i CC:%i", HLs
, acc
, shift
, cc
);
5645 acc
= rot40 (acc
, shift
, &cc
);
5646 SET_AREG (HLs
, acc
);
5650 else if (sop
== 0 && sopcde
== 3 && bit8
== 1)
5652 /* Arithmetic shift, so shift in sign bit copies. */
5654 int shift
= uimm5 (newimmag
);
5657 TRACE_INSN (cpu
, "A%i = A%i >>> %i;", HLs
, HLs
, shift
);
5659 acc
= get_extended_acc (cpu
, HLs
);
5661 /* Sign extend again. */
5662 if (acc
& (1ULL << 39))
5663 acc
|= -(1ULL << 39);
5665 acc
&= ~(-(1ULL << 39));
5667 STORE (AXREG (HLs
), (acc
>> 32) & 0xFF);
5668 STORE (AWREG (HLs
), acc
& 0xFFFFFFFF);
5670 else if ((sop
== 0 && sopcde
== 3 && bit8
== 0)
5671 || (sop
== 1 && sopcde
== 3))
5674 int shiftup
= uimm5 (immag
);
5675 int shiftdn
= uimm5 (newimmag
);
5678 TRACE_INSN (cpu
, "A%i = A%i %s %i;", HLs
, HLs
,
5679 sop
== 0 ? "<<" : ">>",
5680 sop
== 0 ? shiftup
: shiftdn
);
5683 /* Logical shift, so shift in zeroes. */
5693 SET_AREG (HLs
, acc
);
5694 SET_ASTATREG (an
, !!(acc
& 0x8000000000ull
));
5695 SET_ASTATREG (az
, acc
== 0);
5697 else if (sop
== 1 && sopcde
== 1 && bit8
== 0)
5699 int count
= imm5 (immag
);
5700 bu16 val0
= DREG (src1
) >> 16;
5701 bu16 val1
= DREG (src1
) & 0xFFFF;
5704 TRACE_INSN (cpu
, "R%i = R%i << %i (V,S);", dst0
, src1
, count
);
5705 val0
= lshift (cpu
, val0
, count
, 16, 1);
5707 val1
= lshift (cpu
, val1
, count
, 16, 1);
5708 SET_ASTAT (ASTAT
| astat
);
5710 STORE (DREG (dst0
), (val0
<< 16) | val1
);
5712 else if (sop
== 2 && sopcde
== 1 && bit8
== 1)
5714 int count
= imm5 (newimmag
);
5715 bu16 val0
= DREG (src1
) & 0xFFFF;
5716 bu16 val1
= DREG (src1
) >> 16;
5719 TRACE_INSN (cpu
, "R%i = R%i >> %i (V);", dst0
, src1
, count
);
5720 val0
= lshiftrt (cpu
, val0
, count
, 16);
5722 val1
= lshiftrt (cpu
, val1
, count
, 16);
5723 SET_ASTAT (ASTAT
| astat
);
5725 STORE (DREG (dst0
), val0
| (val1
<< 16));
5727 else if (sop
== 2 && sopcde
== 1 && bit8
== 0)
5729 int count
= imm5 (immag
);
5730 bu16 val0
= DREG (src1
) & 0xFFFF;
5731 bu16 val1
= DREG (src1
) >> 16;
5734 TRACE_INSN (cpu
, "R%i = R%i << %i (V);", dst0
, src1
, count
);
5735 val0
= lshift (cpu
, val0
, count
, 16, 0);
5737 val1
= lshift (cpu
, val1
, count
, 16, 0);
5738 SET_ASTAT (ASTAT
| astat
);
5740 STORE (DREG (dst0
), val0
| (val1
<< 16));
5742 else if (sopcde
== 1 && (sop
== 0 || (sop
== 1 && bit8
== 1)))
5744 int count
= uimm5 (newimmag
);
5745 bu16 val0
= DREG (src1
) & 0xFFFF;
5746 bu16 val1
= DREG (src1
) >> 16;
5749 TRACE_INSN (cpu
, "R%i = R%i >>> %i %s;", dst0
, src1
, count
,
5750 sop
== 0 ? "(V)" : "(V,S)");
5752 val0
= ashiftrt (cpu
, val0
, count
, 16);
5754 val1
= ashiftrt (cpu
, val1
, count
, 16);
5755 SET_ASTAT (ASTAT
| astat
);
5757 STORE (DREG (dst0
), REG_H_L (val1
<< 16, val0
));
5759 else if (sop
== 1 && sopcde
== 2)
5761 int count
= imm6 (immag
);
5763 TRACE_INSN (cpu
, "R%i = R%i << %i (S);", dst0
, src1
, count
);
5764 STORE (DREG (dst0
), lshift (cpu
, DREG (src1
), count
, 32, 1));
5766 else if (sop
== 2 && sopcde
== 2)
5768 int count
= imm6 (newimmag
);
5770 TRACE_INSN (cpu
, "R%i = R%i >> %i;", dst0
, src1
, count
);
5773 STORE (DREG (dst0
), lshift (cpu
, DREG (src1
), -count
, 32, 0));
5775 STORE (DREG (dst0
), lshiftrt (cpu
, DREG (src1
), count
, 32));
5777 else if (sop
== 3 && sopcde
== 2)
5779 int shift
= imm6 (immag
);
5780 bu32 src
= DREG (src1
);
5781 bu32 ret
, cc
= CCREG
;
5783 TRACE_INSN (cpu
, "R%i = ROT R%i BY %i;", dst0
, src1
, shift
);
5784 TRACE_DECODE (cpu
, "R%i:%#x R%i:%#x shift:%i CC:%i",
5785 dst0
, DREG (dst0
), src1
, src
, shift
, cc
);
5787 ret
= rot32 (src
, shift
, &cc
);
5788 STORE (DREG (dst0
), ret
);
5792 else if (sop
== 0 && sopcde
== 2)
5794 int count
= imm6 (newimmag
);
5796 TRACE_INSN (cpu
, "R%i = R%i >>> %i;", dst0
, src1
, count
);
5799 STORE (DREG (dst0
), lshift (cpu
, DREG (src1
), -count
, 32, 0));
5801 STORE (DREG (dst0
), ashiftrt (cpu
, DREG (src1
), count
, 32));
5804 illegal_instruction (cpu
);
5808 outc (SIM_CPU
*cpu
, char ch
)
5810 SIM_DESC sd
= CPU_STATE (cpu
);
5811 sim_io_printf (sd
, "%c", ch
);
5813 sim_io_flush_stdout (sd
);
5817 decode_psedoDEBUG_0 (SIM_CPU
*cpu
, bu16 iw0
)
5820 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5821 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 |.fn....|.grp.......|.reg.......|
5822 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5823 SIM_DESC sd
= CPU_STATE (cpu
);
5824 int fn
= ((iw0
>> PseudoDbg_fn_bits
) & PseudoDbg_fn_mask
);
5825 int grp
= ((iw0
>> PseudoDbg_grp_bits
) & PseudoDbg_grp_mask
);
5826 int reg
= ((iw0
>> PseudoDbg_reg_bits
) & PseudoDbg_reg_mask
);
5828 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_psedoDEBUG
);
5829 TRACE_EXTRACT (cpu
, "%s: fn:%i grp:%i reg:%i", __func__
, fn
, grp
, reg
);
5831 if ((reg
== 0 || reg
== 1) && fn
== 3)
5833 TRACE_INSN (cpu
, "DBG A%i;", reg
);
5834 sim_io_printf (sd
, "DBG : A%i = %#"PRIx64
"\n", reg
,
5835 get_unextended_acc (cpu
, reg
));
5837 else if (reg
== 3 && fn
== 3)
5839 TRACE_INSN (cpu
, "ABORT;");
5840 cec_exception (cpu
, VEC_SIM_ABORT
);
5843 else if (reg
== 4 && fn
== 3)
5845 TRACE_INSN (cpu
, "HLT;");
5846 cec_exception (cpu
, VEC_SIM_HLT
);
5849 else if (reg
== 5 && fn
== 3)
5850 unhandled_instruction (cpu
, "DBGHALT");
5851 else if (reg
== 6 && fn
== 3)
5852 unhandled_instruction (cpu
, "DBGCMPLX (dregs)");
5853 else if (reg
== 7 && fn
== 3)
5854 unhandled_instruction (cpu
, "DBG");
5855 else if (grp
== 0 && fn
== 2)
5857 TRACE_INSN (cpu
, "OUTC R%i;", reg
);
5858 outc (cpu
, DREG (reg
));
5862 const char *reg_name
= get_allreg_name (grp
, reg
);
5863 TRACE_INSN (cpu
, "DBG %s;", reg_name
);
5864 sim_io_printf (sd
, "DBG : %s = 0x%08x\n", reg_name
,
5865 reg_read (cpu
, grp
, reg
));
5868 unhandled_instruction (cpu
, "PRNT allregs");
5870 illegal_instruction (cpu
);
5874 decode_psedoOChar_0 (SIM_CPU
*cpu
, bu16 iw0
)
5877 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5878 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |.ch............................|
5879 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5880 int ch
= ((iw0
>> PseudoChr_ch_bits
) & PseudoChr_ch_mask
);
5882 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_psedoOChar
);
5883 TRACE_EXTRACT (cpu
, "%s: ch:%#x", __func__
, ch
);
5884 TRACE_INSN (cpu
, "OUTC %#x;", ch
);
5890 decode_psedodbg_assert_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
, bu32 pc
)
5893 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5894 | 1 | 1 | 1 | 1 | 0 | - | - | - | dbgop |.grp.......|.regtest...|
5895 |.expected......................................................|
5896 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5897 SIM_DESC sd
= CPU_STATE (cpu
);
5898 int expected
= ((iw1
>> PseudoDbg_Assert_expected_bits
) & PseudoDbg_Assert_expected_mask
);
5899 int dbgop
= ((iw0
>> (PseudoDbg_Assert_dbgop_bits
- 16)) & PseudoDbg_Assert_dbgop_mask
);
5900 int grp
= ((iw0
>> (PseudoDbg_Assert_grp_bits
- 16)) & PseudoDbg_Assert_grp_mask
);
5901 int regtest
= ((iw0
>> (PseudoDbg_Assert_regtest_bits
- 16)) & PseudoDbg_Assert_regtest_mask
);
5903 bu32 val
= reg_read (cpu
, grp
, regtest
);
5904 const char *reg_name
= get_allreg_name (grp
, regtest
);
5905 const char *dbg_name
, *dbg_appd
;
5907 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_psedodbg_assert
);
5908 TRACE_EXTRACT (cpu
, "%s: dbgop:%i grp:%i regtest:%i expected:%#x",
5909 __func__
, dbgop
, grp
, regtest
, expected
);
5911 if (dbgop
== 0 || dbgop
== 2)
5913 dbg_name
= dbgop
== 0 ? "DBGA" : "DBGAL";
5914 dbg_appd
= dbgop
== 0 ? ".L" : "";
5917 else if (dbgop
== 1 || dbgop
== 3)
5919 dbg_name
= dbgop
== 1 ? "DBGA" : "DBGAH";
5920 dbg_appd
= dbgop
== 1 ? ".H" : "";
5924 illegal_instruction (cpu
);
5926 TRACE_INSN (cpu
, "%s (%s%s, 0x%x);", dbg_name
, reg_name
, dbg_appd
, expected
);
5927 if (actual
!= expected
)
5929 sim_io_printf (sd
, "FAIL at %#x: %s (%s%s, 0x%04x), actual value %#x\n",
5930 pc
, dbg_name
, reg_name
, dbg_appd
, expected
, actual
);
5931 cec_exception (cpu
, VEC_SIM_DBGA
);
5937 _interp_insn_bfin (SIM_CPU
*cpu
, bu32 pc
)
5942 BFIN_CPU_STATE
.multi_pc
= pc
;
5944 if ((iw0
& 0xc000) != 0xc000)
5946 /* 16-bit opcode. */
5949 INSN_LEN
= insn_len
;
5951 TRACE_EXTRACT (cpu
, "%s: iw0:%#x", __func__
, iw0
);
5952 if ((iw0
& 0xFF00) == 0x0000)
5953 decode_ProgCtrl_0 (cpu
, iw0
, pc
);
5954 else if ((iw0
& 0xFFC0) == 0x0240)
5955 decode_CaCTRL_0 (cpu
, iw0
);
5956 else if ((iw0
& 0xFF80) == 0x0100)
5957 decode_PushPopReg_0 (cpu
, iw0
);
5958 else if ((iw0
& 0xFE00) == 0x0400)
5959 decode_PushPopMultiple_0 (cpu
, iw0
);
5960 else if ((iw0
& 0xFE00) == 0x0600)
5961 decode_ccMV_0 (cpu
, iw0
);
5962 else if ((iw0
& 0xF800) == 0x0800)
5963 decode_CCflag_0 (cpu
, iw0
);
5964 else if ((iw0
& 0xFFE0) == 0x0200)
5965 decode_CC2dreg_0 (cpu
, iw0
);
5966 else if ((iw0
& 0xFF00) == 0x0300)
5967 decode_CC2stat_0 (cpu
, iw0
);
5968 else if ((iw0
& 0xF000) == 0x1000)
5969 decode_BRCC_0 (cpu
, iw0
, pc
);
5970 else if ((iw0
& 0xF000) == 0x2000)
5971 decode_UJUMP_0 (cpu
, iw0
, pc
);
5972 else if ((iw0
& 0xF000) == 0x3000)
5973 decode_REGMV_0 (cpu
, iw0
);
5974 else if ((iw0
& 0xFC00) == 0x4000)
5975 decode_ALU2op_0 (cpu
, iw0
);
5976 else if ((iw0
& 0xFE00) == 0x4400)
5977 decode_PTR2op_0 (cpu
, iw0
);
5978 else if ((iw0
& 0xF800) == 0x4800)
5979 decode_LOGI2op_0 (cpu
, iw0
);
5980 else if ((iw0
& 0xF000) == 0x5000)
5981 decode_COMP3op_0 (cpu
, iw0
);
5982 else if ((iw0
& 0xF800) == 0x6000)
5983 decode_COMPI2opD_0 (cpu
, iw0
);
5984 else if ((iw0
& 0xF800) == 0x6800)
5985 decode_COMPI2opP_0 (cpu
, iw0
);
5986 else if ((iw0
& 0xF000) == 0x8000)
5987 decode_LDSTpmod_0 (cpu
, iw0
);
5988 else if ((iw0
& 0xFF60) == 0x9E60)
5989 decode_dagMODim_0 (cpu
, iw0
);
5990 else if ((iw0
& 0xFFF0) == 0x9F60)
5991 decode_dagMODik_0 (cpu
, iw0
);
5992 else if ((iw0
& 0xFC00) == 0x9C00)
5993 decode_dspLDST_0 (cpu
, iw0
);
5994 else if ((iw0
& 0xF000) == 0x9000)
5995 decode_LDST_0 (cpu
, iw0
);
5996 else if ((iw0
& 0xFC00) == 0xB800)
5997 decode_LDSTiiFP_0 (cpu
, iw0
);
5998 else if ((iw0
& 0xE000) == 0xA000)
5999 decode_LDSTii_0 (cpu
, iw0
);
6002 TRACE_EXTRACT (cpu
, "%s: no matching 16-bit pattern", __func__
);
6003 illegal_instruction (cpu
);
6008 /* Grab the next 16 bits to determine if it's a 32-bit or 64-bit opcode. */
6009 iw1
= IFETCH (pc
+ 2);
6010 if ((iw0
& BIT_MULTI_INS
) && (iw0
& 0xe800) != 0xe800 /* not linkage */)
6012 SIM_DESC sd
= CPU_STATE (cpu
);
6013 trace_prefix (sd
, cpu
, NULL_CIA
, pc
, TRACE_LINENUM_P (cpu
),
6014 NULL
, 0, "|| %#"PRIx64
, sim_events_time (sd
));
6020 TRACE_EXTRACT (cpu
, "%s: iw0:%#x iw1:%#x insn_len:%i", __func__
,
6021 iw0
, iw1
, insn_len
);
6023 /* Only cache on first run through (in case of parallel insns). */
6025 INSN_LEN
= insn_len
;
6027 if ((iw0
& 0xf7ff) == 0xc003 && (iw1
& 0xfe00) == 0x1800)
6029 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32mac
);
6030 TRACE_INSN (cpu
, "MNOP;");
6032 else if (((iw0
& 0xFF80) == 0xE080) && ((iw1
& 0x0C00) == 0x0000))
6033 decode_LoopSetup_0 (cpu
, iw0
, iw1
, pc
);
6034 else if (((iw0
& 0xFF00) == 0xE100) && ((iw1
& 0x0000) == 0x0000))
6035 decode_LDIMMhalf_0 (cpu
, iw0
, iw1
);
6036 else if (((iw0
& 0xFE00) == 0xE200) && ((iw1
& 0x0000) == 0x0000))
6037 decode_CALLa_0 (cpu
, iw0
, iw1
, pc
);
6038 else if (((iw0
& 0xFC00) == 0xE400) && ((iw1
& 0x0000) == 0x0000))
6039 decode_LDSTidxI_0 (cpu
, iw0
, iw1
);
6040 else if (((iw0
& 0xFFFE) == 0xE800) && ((iw1
& 0x0000) == 0x0000))
6041 decode_linkage_0 (cpu
, iw0
, iw1
);
6042 else if (((iw0
& 0xF600) == 0xC000) && ((iw1
& 0x0000) == 0x0000))
6043 decode_dsp32mac_0 (cpu
, iw0
, iw1
);
6044 else if (((iw0
& 0xF600) == 0xC200) && ((iw1
& 0x0000) == 0x0000))
6045 decode_dsp32mult_0 (cpu
, iw0
, iw1
);
6046 else if (((iw0
& 0xF7C0) == 0xC400) && ((iw1
& 0x0000) == 0x0000))
6047 decode_dsp32alu_0 (cpu
, iw0
, iw1
);
6048 else if (((iw0
& 0xF7E0) == 0xC600) && ((iw1
& 0x01C0) == 0x0000))
6049 decode_dsp32shift_0 (cpu
, iw0
, iw1
);
6050 else if (((iw0
& 0xF7E0) == 0xC680) && ((iw1
& 0x0000) == 0x0000))
6051 decode_dsp32shiftimm_0 (cpu
, iw0
, iw1
);
6052 else if ((iw0
& 0xFF00) == 0xF800)
6053 decode_psedoDEBUG_0 (cpu
, iw0
), insn_len
= 2;
6054 else if ((iw0
& 0xFF00) == 0xF900)
6055 decode_psedoOChar_0 (cpu
, iw0
), insn_len
= 2;
6056 else if (((iw0
& 0xFF00) == 0xF000) && ((iw1
& 0x0000) == 0x0000))
6057 decode_psedodbg_assert_0 (cpu
, iw0
, iw1
, pc
);
6060 TRACE_EXTRACT (cpu
, "%s: no matching 32-bit pattern", __func__
);
6061 illegal_instruction (cpu
);
6068 interp_insn_bfin (SIM_CPU
*cpu
, bu32 pc
)
6073 BFIN_CPU_STATE
.n_stores
= 0;
6074 DIS_ALGN_EXPT
&= ~1;
6078 insn_len
= _interp_insn_bfin (cpu
, pc
);
6080 /* Proper display of multiple issue instructions. */
6083 _interp_insn_bfin (cpu
, pc
+ 4);
6084 _interp_insn_bfin (cpu
, pc
+ 6);
6086 for (i
= 0; i
< BFIN_CPU_STATE
.n_stores
; i
++)
6088 bu32
*addr
= BFIN_CPU_STATE
.stores
[i
].addr
;
6089 *addr
= BFIN_CPU_STATE
.stores
[i
].val
;
6090 TRACE_REGISTER (cpu
, "dequeuing write %s = %#x",
6091 get_store_name (cpu
, addr
), *addr
);
6094 cycles_inc (cpu
, CYCLE_DELAY
);
6096 /* Set back to zero in case a pending CEC event occurs
6097 after this this insn. */