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
);
1484 return saturate_s32 (res
, overflow
);
1485 return saturate_u32 (res
, overflow
);
1488 return saturate_s32 (res
<< 1, overflow
);
1490 illegal_instruction (cpu
);
1497 return saturate_s16 (rnd16 (res
), overflow
);
1499 return saturate_s32 (rnd16 (res
), overflow
) & 0xFFFF;
1501 return saturate_s16 (res
, overflow
);
1504 return saturate_s16 (rnd16 (res
), overflow
);
1505 return saturate_u16 (rnd16 (res
), overflow
);
1508 return saturate_s16 (res
, overflow
);
1509 return saturate_u16 (res
, overflow
);
1512 return saturate_s16 (trunc16 (res
), overflow
);
1514 return saturate_u16 (trunc16 (res
), overflow
);
1517 return saturate_s16 (rnd16 (res
<< 1), overflow
);
1519 return saturate_s16 (res
<< 1, overflow
);
1521 illegal_instruction (cpu
);
1526 decode_macfunc (SIM_CPU
*cpu
, int which
, int op
, int h0
, int h1
, int src0
,
1527 int src1
, int mmod
, int MM
, int fullword
, bu32
*overflow
)
1532 /* Sign extend accumulator if necessary, otherwise unsigned. */
1533 if (mmod
== 0 || mmod
== M_T
|| mmod
== M_IS
|| mmod
== M_ISS2
1534 || mmod
== M_S2RND
|| mmod
== M_IH
|| mmod
== M_W32
)
1535 acc
= get_extended_acc (cpu
, which
);
1537 acc
= get_unextended_acc (cpu
, which
);
1539 if (MM
&& (mmod
== M_T
|| mmod
== M_IS
|| mmod
== M_ISS2
1540 || mmod
== M_S2RND
|| mmod
== M_IH
|| mmod
== M_W32
))
1541 acc
|= -(acc
& 0x80000000);
1545 bu8 sgn0
= (acc
>> 31) & 1;
1546 /* This can't saturate, so we don't keep track of the sat flag. */
1547 bu64 res
= decode_multfunc (cpu
, h0
, h1
, src0
, src1
, mmod
,
1550 /* Perform accumulation. */
1555 sgn0
= (acc
>> 31) & 1;
1573 if ((bs64
)acc
< -((bs64
)1 << 39))
1574 acc
= -((bu64
)1 << 39), sat
= 1;
1575 else if ((bs64
)acc
> 0x7fffffffffll
)
1576 acc
= 0x7fffffffffull
, sat
= 1;
1579 if (!MM
&& acc
> 0xFFFFFFFFFFull
)
1581 if (MM
&& acc
> 0xFFFFFFFF)
1585 if (acc
& 0x8000000000000000ull
)
1587 if (acc
> 0xFFFFFFFFFFull
)
1588 acc
&= 0xFFFFFFFFFFull
, sat
= 1;
1589 if (MM
&& acc
> 0xFFFFFFFF)
1591 if (acc
& 0x80000000)
1592 acc
|= 0xffffffff00000000ull
;
1595 if (!MM
&& (bs64
)acc
< 0)
1597 if (MM
&& (bs64
)acc
< -((bs64
)1 << 39))
1598 acc
= -((bu64
)1 << 39), sat
= 1;
1599 if (!MM
&& (bs64
)acc
> (bs64
)0xFFFFFFFFFFll
)
1600 acc
= 0xFFFFFFFFFFull
, sat
= 1;
1601 if (MM
&& acc
> 0xFFFFFFFFFFull
)
1602 acc
&= 0xFFFFFFFFFFull
;
1603 if (MM
&& acc
& 0x80000000)
1604 acc
|= 0xffffffff00000000ull
;
1607 if ((bs64
)acc
< -0x80000000ll
)
1608 acc
= -0x80000000ull
, sat
= 1;
1609 else if ((bs64
)acc
>= 0x7fffffffll
)
1610 acc
= 0x7fffffffull
, sat
= 1;
1613 if (sgn0
&& (sgn0
!= ((acc
>> 31) & 1))
1614 && (((acc
>> 32) & 0xFF) == 0xff))
1617 if (acc
& 0x80000000)
1618 acc
|= 0xffffffff00000000ull
;
1621 illegal_instruction (cpu
);
1625 STORE (AXREG (which
), (acc
>> 32) & 0xff);
1626 STORE (AWREG (which
), acc
& 0xffffffff);
1627 STORE (ASTATREG (av
[which
]), sat
);
1629 STORE (ASTATREG (avs
[which
]), sat
);
1631 return extract_mult (cpu
, acc
, mmod
, MM
, fullword
, overflow
);
1635 hwloop_get_next_pc (SIM_CPU
*cpu
, bu32 pc
, bu32 insn_len
)
1642 /* If our PC has reached the bottom of a hardware loop,
1643 move back up to the top of the hardware loop. */
1644 for (i
= 1; i
>= 0; --i
)
1645 if (LCREG (i
) > 1 && pc
== LBREG (i
))
1647 TRACE_BRANCH (cpu
, pc
, LTREG (i
), i
, "Hardware loop %i", i
);
1651 return pc
+ insn_len
;
1655 decode_ProgCtrl_0 (SIM_CPU
*cpu
, bu16 iw0
, bu32 pc
)
1658 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
1659 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |.prgfunc.......|.poprnd........|
1660 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
1661 int poprnd
= ((iw0
>> ProgCtrl_poprnd_bits
) & ProgCtrl_poprnd_mask
);
1662 int prgfunc
= ((iw0
>> ProgCtrl_prgfunc_bits
) & ProgCtrl_prgfunc_mask
);
1664 TRACE_EXTRACT (cpu
, "%s: poprnd:%i prgfunc:%i", __func__
, poprnd
, prgfunc
);
1666 if (prgfunc
== 0 && poprnd
== 0)
1668 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_nop
);
1669 TRACE_INSN (cpu
, "NOP;");
1671 else if (prgfunc
== 1 && poprnd
== 0)
1673 bu32 newpc
= RETSREG
;
1674 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1675 TRACE_INSN (cpu
, "RTS;");
1676 IFETCH_CHECK (newpc
);
1678 illegal_instruction_combination (cpu
);
1679 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "RTS");
1681 BFIN_CPU_STATE
.did_jump
= true;
1684 else if (prgfunc
== 1 && poprnd
== 1)
1686 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1687 TRACE_INSN (cpu
, "RTI;");
1688 /* Do not do IFETCH_CHECK here -- LSB has special meaning. */
1690 illegal_instruction_combination (cpu
);
1691 cec_return (cpu
, -1);
1694 else if (prgfunc
== 1 && poprnd
== 2)
1696 bu32 newpc
= RETXREG
;
1697 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1698 TRACE_INSN (cpu
, "RTX;");
1699 /* XXX: Not sure if this is what the hardware does. */
1700 IFETCH_CHECK (newpc
);
1702 illegal_instruction_combination (cpu
);
1703 cec_return (cpu
, IVG_EVX
);
1706 else if (prgfunc
== 1 && poprnd
== 3)
1708 bu32 newpc
= RETNREG
;
1709 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1710 TRACE_INSN (cpu
, "RTN;");
1711 /* XXX: Not sure if this is what the hardware does. */
1712 IFETCH_CHECK (newpc
);
1714 illegal_instruction_combination (cpu
);
1715 cec_return (cpu
, IVG_NMI
);
1718 else if (prgfunc
== 1 && poprnd
== 4)
1720 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1721 TRACE_INSN (cpu
, "RTE;");
1723 illegal_instruction_combination (cpu
);
1724 cec_return (cpu
, IVG_EMU
);
1727 else if (prgfunc
== 2 && poprnd
== 0)
1729 SIM_DESC sd
= CPU_STATE (cpu
);
1730 sim_events
*events
= STATE_EVENTS (sd
);
1732 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_sync
);
1733 /* XXX: in supervisor mode, utilizes wake up sources
1734 in user mode, it's a NOP ... */
1735 TRACE_INSN (cpu
, "IDLE;");
1738 illegal_instruction_combination (cpu
);
1742 CYCLE_DELAY
= events
->time_from_event
;
1744 abort (); /* XXX: Should this ever happen ? */
1746 else if (prgfunc
== 2 && poprnd
== 3)
1748 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_sync
);
1750 TRACE_INSN (cpu
, "CSYNC;");
1752 illegal_instruction_combination (cpu
);
1755 else if (prgfunc
== 2 && poprnd
== 4)
1757 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_sync
);
1759 TRACE_INSN (cpu
, "SSYNC;");
1761 illegal_instruction_combination (cpu
);
1763 /* Really 10+, but no model info for this. */
1766 else if (prgfunc
== 2 && poprnd
== 5)
1768 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1769 TRACE_INSN (cpu
, "EMUEXCPT;");
1771 illegal_instruction_combination (cpu
);
1772 cec_exception (cpu
, VEC_SIM_TRAP
);
1774 else if (prgfunc
== 3 && poprnd
< 8)
1776 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1777 TRACE_INSN (cpu
, "CLI R%i;", poprnd
);
1779 illegal_instruction_combination (cpu
);
1780 SET_DREG (poprnd
, cec_cli (cpu
));
1782 else if (prgfunc
== 4 && poprnd
< 8)
1784 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1785 TRACE_INSN (cpu
, "STI R%i;", poprnd
);
1787 illegal_instruction_combination (cpu
);
1788 cec_sti (cpu
, DREG (poprnd
));
1791 else if (prgfunc
== 5 && poprnd
< 8)
1793 bu32 newpc
= PREG (poprnd
);
1794 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1795 TRACE_INSN (cpu
, "JUMP (%s);", get_preg_name (poprnd
));
1796 IFETCH_CHECK (newpc
);
1798 illegal_instruction_combination (cpu
);
1799 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP (Preg)");
1801 BFIN_CPU_STATE
.did_jump
= true;
1802 PROFILE_BRANCH_TAKEN (cpu
);
1805 else if (prgfunc
== 6 && poprnd
< 8)
1807 bu32 newpc
= PREG (poprnd
);
1808 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1809 TRACE_INSN (cpu
, "CALL (%s);", get_preg_name (poprnd
));
1810 IFETCH_CHECK (newpc
);
1812 illegal_instruction_combination (cpu
);
1813 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "CALL (Preg)");
1814 /* If we're at the end of a hardware loop, RETS is going to be
1815 the top of the loop rather than the next instruction. */
1816 SET_RETSREG (hwloop_get_next_pc (cpu
, pc
, 2));
1818 BFIN_CPU_STATE
.did_jump
= true;
1819 PROFILE_BRANCH_TAKEN (cpu
);
1822 else if (prgfunc
== 7 && poprnd
< 8)
1824 bu32 newpc
= pc
+ PREG (poprnd
);
1825 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1826 TRACE_INSN (cpu
, "CALL (PC + %s);", get_preg_name (poprnd
));
1827 IFETCH_CHECK (newpc
);
1829 illegal_instruction_combination (cpu
);
1830 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "CALL (PC + Preg)");
1831 SET_RETSREG (hwloop_get_next_pc (cpu
, pc
, 2));
1833 BFIN_CPU_STATE
.did_jump
= true;
1834 PROFILE_BRANCH_TAKEN (cpu
);
1837 else if (prgfunc
== 8 && poprnd
< 8)
1839 bu32 newpc
= pc
+ PREG (poprnd
);
1840 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_branch
);
1841 TRACE_INSN (cpu
, "JUMP (PC + %s);", get_preg_name (poprnd
));
1842 IFETCH_CHECK (newpc
);
1844 illegal_instruction_combination (cpu
);
1845 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP (PC + Preg)");
1847 BFIN_CPU_STATE
.did_jump
= true;
1848 PROFILE_BRANCH_TAKEN (cpu
);
1851 else if (prgfunc
== 9)
1853 int raise
= uimm4 (poprnd
);
1854 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1855 TRACE_INSN (cpu
, "RAISE %s;", uimm4_str (raise
));
1857 illegal_instruction_combination (cpu
);
1858 cec_require_supervisor (cpu
);
1859 if (raise
== IVG_IVHW
)
1860 cec_hwerr (cpu
, HWERR_RAISE_5
);
1862 cec_latch (cpu
, raise
);
1863 CYCLE_DELAY
= 3; /* XXX: Only if IVG is unmasked. */
1865 else if (prgfunc
== 10)
1867 int excpt
= uimm4 (poprnd
);
1868 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_cec
);
1869 TRACE_INSN (cpu
, "EXCPT %s;", uimm4_str (excpt
));
1871 illegal_instruction_combination (cpu
);
1872 cec_exception (cpu
, excpt
);
1875 else if (prgfunc
== 11 && poprnd
< 6)
1877 bu32 addr
= PREG (poprnd
);
1879 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ProgCtrl_atomic
);
1880 TRACE_INSN (cpu
, "TESTSET (%s);", get_preg_name (poprnd
));
1882 illegal_instruction_combination (cpu
);
1883 byte
= GET_WORD (addr
);
1884 SET_CCREG (byte
== 0);
1885 PUT_BYTE (addr
, byte
| 0x80);
1886 /* Also includes memory stalls, but we don't model that. */
1890 illegal_instruction (cpu
);
1894 decode_CaCTRL_0 (SIM_CPU
*cpu
, bu16 iw0
)
1897 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
1898 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 |.a.|.op....|.reg.......|
1899 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
1900 int a
= ((iw0
>> CaCTRL_a_bits
) & CaCTRL_a_mask
);
1901 int op
= ((iw0
>> CaCTRL_op_bits
) & CaCTRL_op_mask
);
1902 int reg
= ((iw0
>> CaCTRL_reg_bits
) & CaCTRL_reg_mask
);
1903 bu32 preg
= PREG (reg
);
1904 const char * const sinsn
[] = { "PREFETCH", "FLUSHINV", "FLUSH", "IFLUSH", };
1906 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CaCTRL
);
1907 TRACE_EXTRACT (cpu
, "%s: a:%i op:%i reg:%i", __func__
, a
, op
, reg
);
1908 TRACE_INSN (cpu
, "%s [%s%s];", sinsn
[op
], get_preg_name (reg
), a
? "++" : "");
1911 /* None of these can be part of a parallel instruction. */
1912 illegal_instruction_combination (cpu
);
1914 /* No cache simulation, so these are (mostly) all NOPs.
1915 XXX: The hardware takes care of masking to cache lines, but need
1916 to check behavior of the post increment. Should we be aligning
1917 the value to the cache line before adding the cache line size, or
1918 do we just add the cache line size ? */
1921 mmu_check_cache_addr (cpu
, preg
, false, false);
1925 mmu_check_cache_addr (cpu
, preg
, true, false);
1929 mmu_check_cache_addr (cpu
, preg
, true, false);
1933 mmu_check_cache_addr (cpu
, preg
, false, true);
1937 SET_PREG (reg
, preg
+ BFIN_L1_CACHE_BYTES
);
1941 decode_PushPopReg_0 (SIM_CPU
*cpu
, bu16 iw0
)
1944 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
1945 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |.W.|.grp.......|.reg.......|
1946 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
1947 int W
= ((iw0
>> PushPopReg_W_bits
) & PushPopReg_W_mask
);
1948 int grp
= ((iw0
>> PushPopReg_grp_bits
) & PushPopReg_grp_mask
);
1949 int reg
= ((iw0
>> PushPopReg_reg_bits
) & PushPopReg_reg_mask
);
1950 const char *reg_name
= get_allreg_name (grp
, reg
);
1954 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_PushPopReg
);
1955 TRACE_EXTRACT (cpu
, "%s: W:%i grp:%i reg:%i", __func__
, W
, grp
, reg
);
1956 TRACE_DECODE (cpu
, "%s: reg:%s", __func__
, reg_name
);
1958 /* Can't push/pop reserved registers */
1959 if (reg_is_reserved (grp
, reg
))
1960 illegal_instruction (cpu
);
1964 /* Dreg and Preg are not supported by this instruction. */
1965 if (grp
== 0 || grp
== 1)
1966 illegal_instruction (cpu
);
1967 TRACE_INSN (cpu
, "%s = [SP++];", reg_name
);
1968 /* Can't pop USP while in userspace. */
1969 if (INSN_LEN
== 8 || (grp
== 7 && reg
== 0 && cec_is_user_mode(cpu
)))
1970 illegal_instruction_combination (cpu
);
1971 /* XXX: The valid register check is in reg_write(), so we might
1972 incorrectly do a GET_LONG() here ... */
1973 value
= GET_LONG (sp
);
1974 reg_write (cpu
, grp
, reg
, value
);
1975 if (grp
== 7 && reg
== 3)
1982 TRACE_INSN (cpu
, "[--SP] = %s;", reg_name
);
1983 /* Can't push SP. */
1984 if (INSN_LEN
== 8 || (grp
== 1 && reg
== 6))
1985 illegal_instruction_combination (cpu
);
1988 value
= reg_read (cpu
, grp
, reg
);
1989 if (grp
== 7 && reg
== 3)
1990 cec_push_reti (cpu
);
1992 PUT_LONG (sp
, value
);
1995 /* Note: SP update must be delayed until after all reads/writes; see
1996 comments in decode_PushPopMultiple_0() for more info. */
2001 decode_PushPopMultiple_0 (SIM_CPU
*cpu
, bu16 iw0
)
2004 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2005 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |.d.|.p.|.W.|.dr........|.pr........|
2006 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2007 int p
= ((iw0
>> PushPopMultiple_p_bits
) & PushPopMultiple_p_mask
);
2008 int d
= ((iw0
>> PushPopMultiple_d_bits
) & PushPopMultiple_d_mask
);
2009 int W
= ((iw0
>> PushPopMultiple_W_bits
) & PushPopMultiple_W_mask
);
2010 int dr
= ((iw0
>> PushPopMultiple_dr_bits
) & PushPopMultiple_dr_mask
);
2011 int pr
= ((iw0
>> PushPopMultiple_pr_bits
) & PushPopMultiple_pr_mask
);
2015 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_PushPopMultiple
);
2016 TRACE_EXTRACT (cpu
, "%s: d:%i p:%i W:%i dr:%i pr:%i",
2017 __func__
, d
, p
, W
, dr
, pr
);
2019 if ((d
== 0 && p
== 0) || (p
&& imm5 (pr
) > 5)
2020 || (d
&& !p
&& pr
) || (p
&& !d
&& dr
))
2021 illegal_instruction (cpu
);
2026 TRACE_INSN (cpu
, "[--SP] = (R7:%i, P5:%i);", dr
, pr
);
2028 TRACE_INSN (cpu
, "[--SP] = (R7:%i);", dr
);
2030 TRACE_INSN (cpu
, "[--SP] = (P5:%i);", pr
);
2033 for (i
= dr
; i
< 8; i
++)
2036 PUT_LONG (sp
, DREG (i
));
2039 for (i
= pr
; i
< 6; i
++)
2042 PUT_LONG (sp
, PREG (i
));
2050 TRACE_INSN (cpu
, "(R7:%i, P5:%i) = [SP++];", dr
, pr
);
2052 TRACE_INSN (cpu
, "(R7:%i) = [SP++];", dr
);
2054 TRACE_INSN (cpu
, "(P5:%i) = [SP++];", pr
);
2057 for (i
= 5; i
>= pr
; i
--)
2059 SET_PREG (i
, GET_LONG (sp
));
2063 for (i
= 7; i
>= dr
; i
--)
2065 SET_DREG (i
, GET_LONG (sp
));
2072 /* Note: SP update must be delayed until after all reads/writes so that
2073 if an exception does occur, the insn may be re-executed as the
2074 SP has not yet changed. */
2079 decode_ccMV_0 (SIM_CPU
*cpu
, bu16 iw0
)
2082 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2083 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |.T.|.d.|.s.|.dst.......|.src.......|
2084 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2085 int s
= ((iw0
>> CCmv_s_bits
) & CCmv_s_mask
);
2086 int d
= ((iw0
>> CCmv_d_bits
) & CCmv_d_mask
);
2087 int T
= ((iw0
>> CCmv_T_bits
) & CCmv_T_mask
);
2088 int src
= ((iw0
>> CCmv_src_bits
) & CCmv_src_mask
);
2089 int dst
= ((iw0
>> CCmv_dst_bits
) & CCmv_dst_mask
);
2090 int cond
= T
? CCREG
: ! CCREG
;
2092 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ccMV
);
2093 TRACE_EXTRACT (cpu
, "%s: T:%i d:%i s:%i dst:%i src:%i",
2094 __func__
, T
, d
, s
, dst
, src
);
2096 TRACE_INSN (cpu
, "IF %sCC %s = %s;", T
? "" : "! ",
2097 get_allreg_name (d
, dst
),
2098 get_allreg_name (s
, src
));
2100 illegal_instruction_combination (cpu
);
2103 reg_write (cpu
, d
, dst
, reg_read (cpu
, s
, src
));
2107 decode_CCflag_0 (SIM_CPU
*cpu
, bu16 iw0
)
2110 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2111 | 0 | 0 | 0 | 0 | 1 |.I.|.opc.......|.G.|.y.........|.x.........|
2112 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2113 int x
= ((iw0
>> CCflag_x_bits
) & CCflag_x_mask
);
2114 int y
= ((iw0
>> CCflag_y_bits
) & CCflag_y_mask
);
2115 int I
= ((iw0
>> CCflag_I_bits
) & CCflag_I_mask
);
2116 int G
= ((iw0
>> CCflag_G_bits
) & CCflag_G_mask
);
2117 int opc
= ((iw0
>> CCflag_opc_bits
) & CCflag_opc_mask
);
2119 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CCflag
);
2120 TRACE_EXTRACT (cpu
, "%s: I:%i opc:%i G:%i y:%i x:%i",
2121 __func__
, I
, opc
, G
, y
, x
);
2125 bs64 acc0
= get_extended_acc (cpu
, 0);
2126 bs64 acc1
= get_extended_acc (cpu
, 1);
2127 bs64 diff
= acc0
- acc1
;
2129 if (x
!= 0 || y
!= 0)
2130 illegal_instruction (cpu
);
2132 if (opc
== 5 && I
== 0 && G
== 0)
2134 TRACE_INSN (cpu
, "CC = A0 == A1;");
2136 illegal_instruction_combination (cpu
);
2137 SET_CCREG (acc0
== acc1
);
2139 else if (opc
== 6 && I
== 0 && G
== 0)
2141 TRACE_INSN (cpu
, "CC = A0 < A1");
2143 illegal_instruction_combination (cpu
);
2144 SET_CCREG (acc0
< acc1
);
2146 else if (opc
== 7 && I
== 0 && G
== 0)
2148 TRACE_INSN (cpu
, "CC = A0 <= A1");
2150 illegal_instruction_combination (cpu
);
2151 SET_CCREG (acc0
<= acc1
);
2154 illegal_instruction (cpu
);
2156 SET_ASTATREG (az
, diff
== 0);
2157 SET_ASTATREG (an
, diff
< 0);
2158 SET_ASTATREG (ac0
, (bu40
)acc1
<= (bu40
)acc0
);
2162 int issigned
= opc
< 3;
2163 const char *sign
= issigned
? "" : " (IU)";
2164 bu32 srcop
= G
? PREG (x
) : DREG (x
);
2165 char s
= G
? 'P' : 'R';
2166 bu32 dstop
= I
? (issigned
? imm3 (y
) : uimm3 (y
)) : G
? PREG (y
) : DREG (y
);
2168 char d
= G
? 'P' : 'R';
2169 int flgs
= srcop
>> 31;
2170 int flgo
= dstop
>> 31;
2172 bu32 result
= srcop
- dstop
;
2174 int flgn
= result
>> 31;
2175 int overflow
= (flgs
^ flgo
) & (flgn
^ flgs
);
2176 int az
= result
== 0;
2177 int ac0
= dstop
<= srcop
;
2180 an
= (flgn
&& !overflow
) || (!flgn
&& overflow
);
2186 default: /* Shutup useless gcc warnings. */
2187 case 0: /* signed */
2191 case 1: /* signed */
2195 case 2: /* signed */
2199 case 3: /* unsigned */
2203 case 4: /* unsigned */
2210 TRACE_INSN (cpu
, "CC = %c%i %s %s%s;", s
, x
, op
,
2211 issigned
? imm3_str (y
) : uimm3_str (y
), sign
);
2214 TRACE_DECODE (cpu
, "%s %c%i:%x %c%i:%x", __func__
,
2215 s
, x
, srcop
, d
, y
, dstop
);
2216 TRACE_INSN (cpu
, "CC = %c%i %s %c%i%s;", s
, x
, op
, d
, y
, sign
);
2220 /* Pointer compares only touch CC. */
2223 SET_ASTATREG (az
, az
);
2224 SET_ASTATREG (an
, an
);
2225 SET_ASTATREG (ac0
, ac0
);
2231 decode_CC2dreg_0 (SIM_CPU
*cpu
, bu16 iw0
)
2234 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2235 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |.op....|.reg.......|
2236 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2237 int op
= ((iw0
>> CC2dreg_op_bits
) & CC2dreg_op_mask
);
2238 int reg
= ((iw0
>> CC2dreg_reg_bits
) & CC2dreg_reg_mask
);
2240 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CC2dreg
);
2241 TRACE_EXTRACT (cpu
, "%s: op:%i reg:%i", __func__
, op
, reg
);
2245 TRACE_INSN (cpu
, "R%i = CC;", reg
);
2247 illegal_instruction_combination (cpu
);
2248 SET_DREG (reg
, CCREG
);
2252 TRACE_INSN (cpu
, "CC = R%i;", reg
);
2254 illegal_instruction_combination (cpu
);
2255 SET_CCREG (DREG (reg
) != 0);
2257 else if (op
== 3 && reg
== 0)
2259 TRACE_INSN (cpu
, "CC = !CC;");
2261 illegal_instruction_combination (cpu
);
2265 illegal_instruction (cpu
);
2269 decode_CC2stat_0 (SIM_CPU
*cpu
, bu16 iw0
)
2272 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2273 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |.D.|.op....|.cbit..............|
2274 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2275 int D
= ((iw0
>> CC2stat_D_bits
) & CC2stat_D_mask
);
2276 int op
= ((iw0
>> CC2stat_op_bits
) & CC2stat_op_mask
);
2277 int cbit
= ((iw0
>> CC2stat_cbit_bits
) & CC2stat_cbit_mask
);
2280 const char * const op_names
[] = { "", "|", "&", "^" } ;
2281 const char *astat_name
;
2282 const char * const astat_names
[32] = {
2299 astat_name
= astat_names
[cbit
];
2302 static char astat_bit
[12];
2303 sprintf (astat_bit
, "ASTAT[%i]", cbit
);
2304 astat_name
= astat_bit
;
2307 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CC2stat
);
2308 TRACE_EXTRACT (cpu
, "%s: D:%i op:%i cbit:%i", __func__
, D
, op
, cbit
);
2310 TRACE_INSN (cpu
, "%s %s= %s;", D
? astat_name
: "CC",
2311 op_names
[op
], D
? "CC" : astat_name
);
2313 /* CC = CC; is invalid. */
2315 illegal_instruction (cpu
);
2318 illegal_instruction_combination (cpu
);
2320 pval
= !!(ASTAT
& (1 << cbit
));
2324 case 0: SET_CCREG (pval
); break;
2325 case 1: SET_CCREG (CCREG
| pval
); break;
2326 case 2: SET_CCREG (CCREG
& pval
); break;
2327 case 3: SET_CCREG (CCREG
^ pval
); break;
2333 case 0: pval
= CCREG
; break;
2334 case 1: pval
|= CCREG
; break;
2335 case 2: pval
&= CCREG
; break;
2336 case 3: pval
^= CCREG
; break;
2338 if (astat_names
[cbit
])
2339 TRACE_REGISTER (cpu
, "wrote ASTAT[%s] = %i", astat_name
, pval
);
2341 TRACE_REGISTER (cpu
, "wrote %s = %i", astat_name
, pval
);
2342 SET_ASTAT ((ASTAT
& ~(1 << cbit
)) | (pval
<< cbit
));
2347 decode_BRCC_0 (SIM_CPU
*cpu
, bu16 iw0
, bu32 pc
)
2350 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2351 | 0 | 0 | 0 | 1 |.T.|.B.|.offset................................|
2352 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2353 int B
= ((iw0
>> BRCC_B_bits
) & BRCC_B_mask
);
2354 int T
= ((iw0
>> BRCC_T_bits
) & BRCC_T_mask
);
2355 int offset
= ((iw0
>> BRCC_offset_bits
) & BRCC_offset_mask
);
2356 int cond
= T
? CCREG
: ! CCREG
;
2357 int pcrel
= pcrel10 (offset
);
2359 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_BRCC
);
2360 TRACE_EXTRACT (cpu
, "%s: T:%i B:%i offset:%#x", __func__
, T
, B
, offset
);
2361 TRACE_DECODE (cpu
, "%s: pcrel10:%#x", __func__
, pcrel
);
2363 TRACE_INSN (cpu
, "IF %sCC JUMP %#x%s;", T
? "" : "! ",
2364 pcrel
, B
? " (bp)" : "");
2367 illegal_instruction_combination (cpu
);
2371 bu32 newpc
= pc
+ pcrel
;
2372 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "Conditional JUMP");
2374 BFIN_CPU_STATE
.did_jump
= true;
2375 PROFILE_BRANCH_TAKEN (cpu
);
2376 CYCLE_DELAY
= B
? 5 : 9;
2380 PROFILE_BRANCH_UNTAKEN (cpu
);
2381 CYCLE_DELAY
= B
? 9 : 1;
2386 decode_UJUMP_0 (SIM_CPU
*cpu
, bu16 iw0
, bu32 pc
)
2389 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2390 | 0 | 0 | 1 | 0 |.offset........................................|
2391 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2392 int offset
= ((iw0
>> UJump_offset_bits
) & UJump_offset_mask
);
2393 int pcrel
= pcrel12 (offset
);
2394 bu32 newpc
= pc
+ pcrel
;
2396 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_UJUMP
);
2397 TRACE_EXTRACT (cpu
, "%s: offset:%#x", __func__
, offset
);
2398 TRACE_DECODE (cpu
, "%s: pcrel12:%#x", __func__
, pcrel
);
2400 TRACE_INSN (cpu
, "JUMP.S %#x;", pcrel
);
2403 illegal_instruction_combination (cpu
);
2405 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP.S");
2408 BFIN_CPU_STATE
.did_jump
= true;
2409 PROFILE_BRANCH_TAKEN (cpu
);
2414 decode_REGMV_0 (SIM_CPU
*cpu
, bu16 iw0
)
2417 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2418 | 0 | 0 | 1 | 1 |.gd........|.gs........|.dst.......|.src.......|
2419 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2420 int gs
= ((iw0
>> RegMv_gs_bits
) & RegMv_gs_mask
);
2421 int gd
= ((iw0
>> RegMv_gd_bits
) & RegMv_gd_mask
);
2422 int src
= ((iw0
>> RegMv_src_bits
) & RegMv_src_mask
);
2423 int dst
= ((iw0
>> RegMv_dst_bits
) & RegMv_dst_mask
);
2424 const char *srcreg_name
= get_allreg_name (gs
, src
);
2425 const char *dstreg_name
= get_allreg_name (gd
, dst
);
2427 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_REGMV
);
2428 TRACE_EXTRACT (cpu
, "%s: gd:%i gs:%i dst:%i src:%i",
2429 __func__
, gd
, gs
, dst
, src
);
2430 TRACE_DECODE (cpu
, "%s: dst:%s src:%s", __func__
, dstreg_name
, srcreg_name
);
2432 TRACE_INSN (cpu
, "%s = %s;", dstreg_name
, srcreg_name
);
2434 /* Reserved slots cannot be a src/dst. */
2435 if (reg_is_reserved (gs
, src
) || reg_is_reserved (gd
, dst
))
2438 /* Standard register moves. */
2439 if ((gs
< 2) /* Dregs/Pregs src */
2440 || (gd
< 2) /* Dregs/Pregs dst */
2441 || (gs
== 4 && src
< 4) /* Accumulators src */
2442 || (gd
== 4 && dst
< 4 && (gs
< 4)) /* Accumulators dst */
2443 || (gs
== 7 && src
== 7 && !(gd
== 4 && dst
< 4)) /* EMUDAT src */
2444 || (gd
== 7 && dst
== 7)) /* EMUDAT dst */
2447 /* dareg = dareg (IMBL) */
2448 if (gs
< 4 && gd
< 4)
2451 /* USP can be src to sysregs, but not dagregs. */
2452 if ((gs
== 7 && src
== 0) && (gd
>= 4))
2455 /* USP can move between genregs (only check Accumulators). */
2456 if (((gs
== 7 && src
== 0) && (gd
== 4 && dst
< 4))
2457 || ((gd
== 7 && dst
== 0) && (gs
== 4 && src
< 4)))
2460 /* Still here ? Invalid reg pair. */
2462 illegal_instruction (cpu
);
2465 reg_write (cpu
, gd
, dst
, reg_read (cpu
, gs
, src
));
2469 decode_ALU2op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2472 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2473 | 0 | 1 | 0 | 0 | 0 | 0 |.opc...........|.src.......|.dst.......|
2474 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2475 int src
= ((iw0
>> ALU2op_src_bits
) & ALU2op_src_mask
);
2476 int opc
= ((iw0
>> ALU2op_opc_bits
) & ALU2op_opc_mask
);
2477 int dst
= ((iw0
>> ALU2op_dst_bits
) & ALU2op_dst_mask
);
2479 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_ALU2op
);
2480 TRACE_EXTRACT (cpu
, "%s: opc:%i src:%i dst:%i", __func__
, opc
, src
, dst
);
2484 TRACE_INSN (cpu
, "R%i >>>= R%i;", dst
, src
);
2485 SET_DREG (dst
, ashiftrt (cpu
, DREG (dst
), DREG (src
), 32));
2490 TRACE_INSN (cpu
, "R%i >>= R%i;", dst
, src
);
2491 if (DREG (src
) <= 0x1F)
2492 val
= lshiftrt (cpu
, DREG (dst
), DREG (src
), 32);
2495 SET_DREG (dst
, val
);
2499 TRACE_INSN (cpu
, "R%i <<= R%i;", dst
, src
);
2500 SET_DREG (dst
, lshift (cpu
, DREG (dst
), DREG (src
), 32, 0));
2504 TRACE_INSN (cpu
, "R%i *= R%i;", dst
, src
);
2505 SET_DREG (dst
, DREG (dst
) * DREG (src
));
2510 TRACE_INSN (cpu
, "R%i = (R%i + R%i) << 1;", dst
, dst
, src
);
2511 SET_DREG (dst
, add_and_shift (cpu
, DREG (dst
), DREG (src
), 1));
2515 TRACE_INSN (cpu
, "R%i = (R%i + R%i) << 2;", dst
, dst
, src
);
2516 SET_DREG (dst
, add_and_shift (cpu
, DREG (dst
), DREG (src
), 2));
2520 TRACE_INSN (cpu
, "DIVQ ( R%i, R%i );", dst
, src
);
2521 SET_DREG (dst
, divq (cpu
, DREG (dst
), (bu16
)DREG (src
)));
2525 TRACE_INSN (cpu
, "DIVS ( R%i, R%i );", dst
, src
);
2526 SET_DREG (dst
, divs (cpu
, DREG (dst
), (bu16
)DREG (src
)));
2530 TRACE_INSN (cpu
, "R%i = R%i.L (X);", dst
, src
);
2531 SET_DREG (dst
, (bs32
) (bs16
) DREG (src
));
2532 setflags_logical (cpu
, DREG (dst
));
2536 TRACE_INSN (cpu
, "R%i = R%i.L (Z);", dst
, src
);
2537 SET_DREG (dst
, (bu32
) (bu16
) DREG (src
));
2538 setflags_logical (cpu
, DREG (dst
));
2542 TRACE_INSN (cpu
, "R%i = R%i.B (X);", dst
, src
);
2543 SET_DREG (dst
, (bs32
) (bs8
) DREG (src
));
2544 setflags_logical (cpu
, DREG (dst
));
2548 TRACE_INSN (cpu
, "R%i = R%i.B (Z);", dst
, src
);
2549 SET_DREG (dst
, (bu32
) (bu8
) DREG (src
));
2550 setflags_logical (cpu
, DREG (dst
));
2554 bu32 val
= DREG (src
);
2555 TRACE_INSN (cpu
, "R%i = - R%i;", dst
, src
);
2556 SET_DREG (dst
, -val
);
2557 setflags_nz (cpu
, DREG (dst
));
2558 SET_ASTATREG (v
, val
== 0x80000000);
2560 SET_ASTATREG (vs
, 1);
2561 SET_ASTATREG (ac0
, val
== 0x0);
2562 /* XXX: Documentation isn't entirely clear about av0 and av1. */
2566 TRACE_INSN (cpu
, "R%i = ~ R%i;", dst
, src
);
2567 SET_DREG (dst
, ~DREG (src
));
2568 setflags_logical (cpu
, DREG (dst
));
2571 illegal_instruction (cpu
);
2575 decode_PTR2op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2578 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2579 | 0 | 1 | 0 | 0 | 0 | 1 | 0 |.opc.......|.src.......|.dst.......|
2580 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2581 int src
= ((iw0
>> PTR2op_src_bits
) & PTR2op_dst_mask
);
2582 int opc
= ((iw0
>> PTR2op_opc_bits
) & PTR2op_opc_mask
);
2583 int dst
= ((iw0
>> PTR2op_dst_bits
) & PTR2op_dst_mask
);
2584 const char *src_name
= get_preg_name (src
);
2585 const char *dst_name
= get_preg_name (dst
);
2587 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_PTR2op
);
2588 TRACE_EXTRACT (cpu
, "%s: opc:%i src:%i dst:%i", __func__
, opc
, src
, dst
);
2592 TRACE_INSN (cpu
, "%s -= %s", dst_name
, src_name
);
2593 SET_PREG (dst
, PREG (dst
) - PREG (src
));
2597 TRACE_INSN (cpu
, "%s = %s << 2", dst_name
, src_name
);
2598 SET_PREG (dst
, PREG (src
) << 2);
2602 TRACE_INSN (cpu
, "%s = %s >> 2", dst_name
, src_name
);
2603 SET_PREG (dst
, PREG (src
) >> 2);
2607 TRACE_INSN (cpu
, "%s = %s >> 1", dst_name
, src_name
);
2608 SET_PREG (dst
, PREG (src
) >> 1);
2612 TRACE_INSN (cpu
, "%s += %s (BREV)", dst_name
, src_name
);
2613 SET_PREG (dst
, add_brev (PREG (dst
), PREG (src
)));
2617 TRACE_INSN (cpu
, "%s = (%s + %s) << 1", dst_name
, dst_name
, src_name
);
2618 SET_PREG (dst
, (PREG (dst
) + PREG (src
)) << 1);
2622 TRACE_INSN (cpu
, "%s = (%s + %s) << 2", dst_name
, dst_name
, src_name
);
2623 SET_PREG (dst
, (PREG (dst
) + PREG (src
)) << 2);
2626 illegal_instruction (cpu
);
2630 decode_LOGI2op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2633 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2634 | 0 | 1 | 0 | 0 | 1 |.opc.......|.src...............|.dst.......|
2635 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2636 int src
= ((iw0
>> LOGI2op_src_bits
) & LOGI2op_src_mask
);
2637 int opc
= ((iw0
>> LOGI2op_opc_bits
) & LOGI2op_opc_mask
);
2638 int dst
= ((iw0
>> LOGI2op_dst_bits
) & LOGI2op_dst_mask
);
2639 int uimm
= uimm5 (src
);
2640 const char *uimm_str
= uimm5_str (uimm
);
2642 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LOGI2op
);
2643 TRACE_EXTRACT (cpu
, "%s: opc:%i src:%i dst:%i", __func__
, opc
, src
, dst
);
2644 TRACE_DECODE (cpu
, "%s: uimm5:%#x", __func__
, uimm
);
2648 TRACE_INSN (cpu
, "CC = ! BITTST (R%i, %s);", dst
, uimm_str
);
2650 illegal_instruction_combination (cpu
);
2651 SET_CCREG ((~DREG (dst
) >> uimm
) & 1);
2655 TRACE_INSN (cpu
, "CC = BITTST (R%i, %s);", dst
, uimm_str
);
2657 illegal_instruction_combination (cpu
);
2658 SET_CCREG ((DREG (dst
) >> uimm
) & 1);
2662 TRACE_INSN (cpu
, "BITSET (R%i, %s);", dst
, uimm_str
);
2664 illegal_instruction_combination (cpu
);
2665 SET_DREG (dst
, DREG (dst
) | (1 << uimm
));
2666 setflags_logical (cpu
, DREG (dst
));
2670 TRACE_INSN (cpu
, "BITTGL (R%i, %s);", dst
, uimm_str
);
2672 illegal_instruction_combination (cpu
);
2673 SET_DREG (dst
, DREG (dst
) ^ (1 << uimm
));
2674 setflags_logical (cpu
, DREG (dst
));
2678 TRACE_INSN (cpu
, "BITCLR (R%i, %s);", dst
, uimm_str
);
2680 illegal_instruction_combination (cpu
);
2681 SET_DREG (dst
, DREG (dst
) & ~(1 << uimm
));
2682 setflags_logical (cpu
, DREG (dst
));
2686 TRACE_INSN (cpu
, "R%i >>>= %s;", dst
, uimm_str
);
2688 illegal_instruction_combination (cpu
);
2689 SET_DREG (dst
, ashiftrt (cpu
, DREG (dst
), uimm
, 32));
2693 TRACE_INSN (cpu
, "R%i >>= %s;", dst
, uimm_str
);
2695 illegal_instruction_combination (cpu
);
2696 SET_DREG (dst
, lshiftrt (cpu
, DREG (dst
), uimm
, 32));
2700 TRACE_INSN (cpu
, "R%i <<= %s;", dst
, uimm_str
);
2702 illegal_instruction_combination (cpu
);
2703 SET_DREG (dst
, lshift (cpu
, DREG (dst
), uimm
, 32, 0));
2708 decode_COMP3op_0 (SIM_CPU
*cpu
, bu16 iw0
)
2711 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2712 | 0 | 1 | 0 | 1 |.opc.......|.dst.......|.src1......|.src0......|
2713 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2714 int opc
= ((iw0
>> COMP3op_opc_bits
) & COMP3op_opc_mask
);
2715 int dst
= ((iw0
>> COMP3op_dst_bits
) & COMP3op_dst_mask
);
2716 int src0
= ((iw0
>> COMP3op_src0_bits
) & COMP3op_src0_mask
);
2717 int src1
= ((iw0
>> COMP3op_src1_bits
) & COMP3op_src1_mask
);
2719 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_COMP3op
);
2720 TRACE_EXTRACT (cpu
, "%s: opc:%i dst:%i src1:%i src0:%i",
2721 __func__
, opc
, dst
, src1
, src0
);
2725 TRACE_INSN (cpu
, "R%i = R%i + R%i;", dst
, src0
, src1
);
2726 SET_DREG (dst
, add32 (cpu
, DREG (src0
), DREG (src1
), 1, 0));
2730 TRACE_INSN (cpu
, "R%i = R%i - R%i;", dst
, src0
, src1
);
2731 SET_DREG (dst
, sub32 (cpu
, DREG (src0
), DREG (src1
), 1, 0, 0));
2735 TRACE_INSN (cpu
, "R%i = R%i & R%i;", dst
, src0
, src1
);
2736 SET_DREG (dst
, DREG (src0
) & DREG (src1
));
2737 setflags_logical (cpu
, DREG (dst
));
2741 TRACE_INSN (cpu
, "R%i = R%i | R%i;", dst
, src0
, src1
);
2742 SET_DREG (dst
, DREG (src0
) | DREG (src1
));
2743 setflags_logical (cpu
, DREG (dst
));
2747 TRACE_INSN (cpu
, "R%i = R%i ^ R%i;", dst
, src0
, src1
);
2748 SET_DREG (dst
, DREG (src0
) ^ DREG (src1
));
2749 setflags_logical (cpu
, DREG (dst
));
2753 int shift
= opc
- 5;
2754 const char *dst_name
= get_preg_name (dst
);
2755 const char *src0_name
= get_preg_name (src0
);
2756 const char *src1_name
= get_preg_name (src1
);
2758 /* If src0 == src1 this is disassembled as a shift by 1, but this
2759 distinction doesn't matter for our purposes. */
2761 TRACE_INSN (cpu
, "%s = (%s + %s) << %#x;",
2762 dst_name
, src0_name
, src1_name
, shift
);
2764 TRACE_INSN (cpu
, "%s = %s + %s",
2765 dst_name
, src0_name
, src1_name
);
2766 SET_PREG (dst
, PREG (src0
) + (PREG (src1
) << shift
));
2771 decode_COMPI2opD_0 (SIM_CPU
*cpu
, bu16 iw0
)
2774 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2775 | 0 | 1 | 1 | 0 | 0 |.op|..src......................|.dst.......|
2776 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2777 int op
= ((iw0
>> COMPI2opD_op_bits
) & COMPI2opD_op_mask
);
2778 int dst
= ((iw0
>> COMPI2opD_dst_bits
) & COMPI2opD_dst_mask
);
2779 int src
= ((iw0
>> COMPI2opD_src_bits
) & COMPI2opD_src_mask
);
2780 int imm
= imm7 (src
);
2782 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_COMPI2opD
);
2783 TRACE_EXTRACT (cpu
, "%s: op:%i src:%i dst:%i", __func__
, op
, src
, dst
);
2784 TRACE_DECODE (cpu
, "%s: imm7:%#x", __func__
, imm
);
2788 TRACE_INSN (cpu
, "R%i = %s (X);", dst
, imm7_str (imm
));
2789 SET_DREG (dst
, imm
);
2793 TRACE_INSN (cpu
, "R%i += %s;", dst
, imm7_str (imm
));
2794 SET_DREG (dst
, add32 (cpu
, DREG (dst
), imm
, 1, 0));
2799 decode_COMPI2opP_0 (SIM_CPU
*cpu
, bu16 iw0
)
2802 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2803 | 0 | 1 | 1 | 0 | 1 |.op|.src.......................|.dst.......|
2804 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2805 int op
= ((iw0
>> COMPI2opP_op_bits
) & COMPI2opP_op_mask
);
2806 int src
= ((iw0
>> COMPI2opP_src_bits
) & COMPI2opP_src_mask
);
2807 int dst
= ((iw0
>> COMPI2opP_dst_bits
) & COMPI2opP_dst_mask
);
2808 int imm
= imm7 (src
);
2809 const char *dst_name
= get_preg_name (dst
);
2811 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_COMPI2opP
);
2812 TRACE_EXTRACT (cpu
, "%s: op:%i src:%i dst:%i", __func__
, op
, src
, dst
);
2813 TRACE_DECODE (cpu
, "%s: imm:%#x", __func__
, imm
);
2817 TRACE_INSN (cpu
, "%s = %s;", dst_name
, imm7_str (imm
));
2818 SET_PREG (dst
, imm
);
2822 TRACE_INSN (cpu
, "%s += %s;", dst_name
, imm7_str (imm
));
2823 SET_PREG (dst
, PREG (dst
) + imm
);
2828 decode_LDSTpmod_0 (SIM_CPU
*cpu
, bu16 iw0
)
2831 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2832 | 1 | 0 | 0 | 0 |.W.|.aop...|.reg.......|.idx.......|.ptr.......|
2833 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2834 int W
= ((iw0
>> LDSTpmod_W_bits
) & LDSTpmod_W_mask
);
2835 int aop
= ((iw0
>> LDSTpmod_aop_bits
) & LDSTpmod_aop_mask
);
2836 int idx
= ((iw0
>> LDSTpmod_idx_bits
) & LDSTpmod_idx_mask
);
2837 int ptr
= ((iw0
>> LDSTpmod_ptr_bits
) & LDSTpmod_ptr_mask
);
2838 int reg
= ((iw0
>> LDSTpmod_reg_bits
) & LDSTpmod_reg_mask
);
2839 const char *ptr_name
= get_preg_name (ptr
);
2840 const char *idx_name
= get_preg_name (idx
);
2843 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTpmod
);
2844 TRACE_EXTRACT (cpu
, "%s: W:%i aop:%i reg:%i idx:%i ptr:%i",
2845 __func__
, W
, aop
, reg
, idx
, ptr
);
2847 if (aop
== 1 && W
== 0 && idx
== ptr
)
2849 TRACE_INSN (cpu
, "R%i.L = W[%s];", reg
, ptr_name
);
2851 val
= GET_WORD (addr
);
2852 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | val
);
2854 else if (aop
== 2 && W
== 0 && idx
== ptr
)
2856 TRACE_INSN (cpu
, "R%i.H = W[%s];", reg
, ptr_name
);
2858 val
= GET_WORD (addr
);
2859 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (val
<< 16));
2861 else if (aop
== 1 && W
== 1 && idx
== ptr
)
2863 TRACE_INSN (cpu
, "W[%s] = R%i.L;", ptr_name
, reg
);
2865 PUT_WORD (addr
, DREG (reg
));
2867 else if (aop
== 2 && W
== 1 && idx
== ptr
)
2869 TRACE_INSN (cpu
, "W[%s] = R%i.H;", ptr_name
, reg
);
2871 PUT_WORD (addr
, DREG (reg
) >> 16);
2873 else if (aop
== 0 && W
== 0)
2875 TRACE_INSN (cpu
, "R%i = [%s ++ %s];", reg
, ptr_name
, idx_name
);
2877 val
= GET_LONG (addr
);
2878 STORE (DREG (reg
), val
);
2880 STORE (PREG (ptr
), addr
+ PREG (idx
));
2882 else if (aop
== 1 && W
== 0)
2884 TRACE_INSN (cpu
, "R%i.L = W[%s ++ %s];", reg
, ptr_name
, idx_name
);
2886 val
= GET_WORD (addr
);
2887 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | val
);
2889 STORE (PREG (ptr
), addr
+ PREG (idx
));
2891 else if (aop
== 2 && W
== 0)
2893 TRACE_INSN (cpu
, "R%i.H = W[%s ++ %s];", reg
, ptr_name
, idx_name
);
2895 val
= GET_WORD (addr
);
2896 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (val
<< 16));
2898 STORE (PREG (ptr
), addr
+ PREG (idx
));
2900 else if (aop
== 3 && W
== 0)
2902 TRACE_INSN (cpu
, "R%i = W[%s ++ %s] (Z);", reg
, ptr_name
, idx_name
);
2904 val
= GET_WORD (addr
);
2905 STORE (DREG (reg
), val
);
2907 STORE (PREG (ptr
), addr
+ PREG (idx
));
2909 else if (aop
== 3 && W
== 1)
2911 TRACE_INSN (cpu
, "R%i = W[%s ++ %s] (X);", reg
, ptr_name
, idx_name
);
2913 val
= GET_WORD (addr
);
2914 STORE (DREG (reg
), (bs32
) (bs16
) val
);
2916 STORE (PREG (ptr
), addr
+ PREG (idx
));
2918 else if (aop
== 0 && W
== 1)
2920 TRACE_INSN (cpu
, "[%s ++ %s] = R%i;", ptr_name
, idx_name
, reg
);
2922 PUT_LONG (addr
, DREG (reg
));
2924 STORE (PREG (ptr
), addr
+ PREG (idx
));
2926 else if (aop
== 1 && W
== 1)
2928 TRACE_INSN (cpu
, "W[%s ++ %s] = R%i.L;", ptr_name
, idx_name
, reg
);
2930 PUT_WORD (addr
, DREG (reg
));
2932 STORE (PREG (ptr
), addr
+ PREG (idx
));
2934 else if (aop
== 2 && W
== 1)
2936 TRACE_INSN (cpu
, "W[%s ++ %s] = R%i.H;", ptr_name
, idx_name
, reg
);
2938 PUT_WORD (addr
, DREG (reg
) >> 16);
2940 STORE (PREG (ptr
), addr
+ PREG (idx
));
2943 illegal_instruction (cpu
);
2947 decode_dagMODim_0 (SIM_CPU
*cpu
, bu16 iw0
)
2950 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2951 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 0 |.br| 1 | 1 |.op|.m.....|.i.....|
2952 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2953 int i
= ((iw0
>> DagMODim_i_bits
) & DagMODim_i_mask
);
2954 int m
= ((iw0
>> DagMODim_m_bits
) & DagMODim_m_mask
);
2955 int br
= ((iw0
>> DagMODim_br_bits
) & DagMODim_br_mask
);
2956 int op
= ((iw0
>> DagMODim_op_bits
) & DagMODim_op_mask
);
2958 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dagMODim
);
2959 TRACE_EXTRACT (cpu
, "%s: br:%i op:%i m:%i i:%i", __func__
, br
, op
, m
, i
);
2961 if (op
== 0 && br
== 1)
2963 TRACE_INSN (cpu
, "I%i += M%i (BREV);", i
, m
);
2964 SET_IREG (i
, add_brev (IREG (i
), MREG (m
)));
2968 TRACE_INSN (cpu
, "I%i += M%i;", i
, m
);
2969 dagadd (cpu
, i
, MREG (m
));
2971 else if (op
== 1 && br
== 0)
2973 TRACE_INSN (cpu
, "I%i -= M%i;", i
, m
);
2974 dagsub (cpu
, i
, MREG (m
));
2977 illegal_instruction (cpu
);
2981 decode_dagMODik_0 (SIM_CPU
*cpu
, bu16 iw0
)
2984 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2985 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 0 |.op....|.i.....|
2986 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2987 int i
= ((iw0
>> DagMODik_i_bits
) & DagMODik_i_mask
);
2988 int op
= ((iw0
>> DagMODik_op_bits
) & DagMODik_op_mask
);
2990 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dagMODik
);
2991 TRACE_EXTRACT (cpu
, "%s: op:%i i:%i", __func__
, op
, i
);
2995 TRACE_INSN (cpu
, "I%i += 2;", i
);
3000 TRACE_INSN (cpu
, "I%i -= 2;", i
);
3005 TRACE_INSN (cpu
, "I%i += 4;", i
);
3010 TRACE_INSN (cpu
, "I%i -= 4;", i
);
3014 illegal_instruction (cpu
);
3018 decode_dspLDST_0 (SIM_CPU
*cpu
, bu16 iw0
)
3021 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3022 | 1 | 0 | 0 | 1 | 1 | 1 |.W.|.aop...|.m.....|.i.....|.reg.......|
3023 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3024 int i
= ((iw0
>> DspLDST_i_bits
) & DspLDST_i_mask
);
3025 int m
= ((iw0
>> DspLDST_m_bits
) & DspLDST_m_mask
);
3026 int W
= ((iw0
>> DspLDST_W_bits
) & DspLDST_W_mask
);
3027 int aop
= ((iw0
>> DspLDST_aop_bits
) & DspLDST_aop_mask
);
3028 int reg
= ((iw0
>> DspLDST_reg_bits
) & DspLDST_reg_mask
);
3031 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dspLDST
);
3032 TRACE_EXTRACT (cpu
, "%s: aop:%i m:%i i:%i reg:%i", __func__
, aop
, m
, i
, reg
);
3034 if (aop
== 0 && W
== 0 && m
== 0)
3036 TRACE_INSN (cpu
, "R%i = [I%i++];", reg
, i
);
3038 if (DIS_ALGN_EXPT
& 0x1)
3041 STORE (DREG (reg
), GET_LONG (addr
));
3043 else if (aop
== 0 && W
== 0 && m
== 1)
3045 TRACE_INSN (cpu
, "R%i.L = W[I%i++];", reg
, i
);
3048 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | GET_WORD (addr
));
3050 else if (aop
== 0 && W
== 0 && m
== 2)
3052 TRACE_INSN (cpu
, "R%i.H = W[I%i++];", reg
, i
);
3055 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (GET_WORD (addr
) << 16));
3057 else if (aop
== 1 && W
== 0 && m
== 0)
3059 TRACE_INSN (cpu
, "R%i = [I%i--];", reg
, i
);
3061 if (DIS_ALGN_EXPT
& 0x1)
3064 STORE (DREG (reg
), GET_LONG (addr
));
3066 else if (aop
== 1 && W
== 0 && m
== 1)
3068 TRACE_INSN (cpu
, "R%i.L = W[I%i--];", reg
, i
);
3071 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | GET_WORD (addr
));
3073 else if (aop
== 1 && W
== 0 && m
== 2)
3075 TRACE_INSN (cpu
, "R%i.H = W[I%i--];", reg
, i
);
3078 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (GET_WORD (addr
) << 16));
3080 else if (aop
== 2 && W
== 0 && m
== 0)
3082 TRACE_INSN (cpu
, "R%i = [I%i];", reg
, i
);
3084 if (DIS_ALGN_EXPT
& 0x1)
3086 STORE (DREG (reg
), GET_LONG (addr
));
3088 else if (aop
== 2 && W
== 0 && m
== 1)
3090 TRACE_INSN (cpu
, "R%i.L = W[I%i];", reg
, i
);
3092 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF0000) | GET_WORD (addr
));
3094 else if (aop
== 2 && W
== 0 && m
== 2)
3096 TRACE_INSN (cpu
, "R%i.H = W[I%i];", reg
, i
);
3098 STORE (DREG (reg
), (DREG (reg
) & 0xFFFF) | (GET_WORD (addr
) << 16));
3100 else if (aop
== 0 && W
== 1 && m
== 0)
3102 TRACE_INSN (cpu
, "[I%i++] = R%i;", i
, reg
);
3105 PUT_LONG (addr
, DREG (reg
));
3107 else if (aop
== 0 && W
== 1 && m
== 1)
3109 TRACE_INSN (cpu
, "W[I%i++] = R%i.L;", i
, reg
);
3112 PUT_WORD (addr
, DREG (reg
));
3114 else if (aop
== 0 && W
== 1 && m
== 2)
3116 TRACE_INSN (cpu
, "W[I%i++] = R%i.H;", i
, reg
);
3119 PUT_WORD (addr
, DREG (reg
) >> 16);
3121 else if (aop
== 1 && W
== 1 && m
== 0)
3123 TRACE_INSN (cpu
, "[I%i--] = R%i;", i
, reg
);
3126 PUT_LONG (addr
, DREG (reg
));
3128 else if (aop
== 1 && W
== 1 && m
== 1)
3130 TRACE_INSN (cpu
, "W[I%i--] = R%i.L;", i
, reg
);
3133 PUT_WORD (addr
, DREG (reg
));
3135 else if (aop
== 1 && W
== 1 && m
== 2)
3137 TRACE_INSN (cpu
, "W[I%i--] = R%i.H;", i
, reg
);
3140 PUT_WORD (addr
, DREG (reg
) >> 16);
3142 else if (aop
== 2 && W
== 1 && m
== 0)
3144 TRACE_INSN (cpu
, "[I%i] = R%i;", i
, reg
);
3146 PUT_LONG (addr
, DREG (reg
));
3148 else if (aop
== 2 && W
== 1 && m
== 1)
3150 TRACE_INSN (cpu
, "W[I%i] = R%i.L;", i
, reg
);
3152 PUT_WORD (addr
, DREG (reg
));
3154 else if (aop
== 2 && W
== 1 && m
== 2)
3156 TRACE_INSN (cpu
, "W[I%i] = R%i.H;", i
, reg
);
3158 PUT_WORD (addr
, DREG (reg
) >> 16);
3160 else if (aop
== 3 && W
== 0)
3162 TRACE_INSN (cpu
, "R%i = [I%i ++ M%i];", reg
, i
, m
);
3164 if (DIS_ALGN_EXPT
& 0x1)
3166 dagadd (cpu
, i
, MREG (m
));
3167 STORE (DREG (reg
), GET_LONG (addr
));
3169 else if (aop
== 3 && W
== 1)
3171 TRACE_INSN (cpu
, "[I%i ++ M%i] = R%i;", i
, m
, reg
);
3173 dagadd (cpu
, i
, MREG (m
));
3174 PUT_LONG (addr
, DREG (reg
));
3177 illegal_instruction (cpu
);
3181 decode_LDST_0 (SIM_CPU
*cpu
, bu16 iw0
)
3184 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3185 | 1 | 0 | 0 | 1 |.sz....|.W.|.aop...|.Z.|.ptr.......|.reg.......|
3186 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3187 int Z
= ((iw0
>> LDST_Z_bits
) & LDST_Z_mask
);
3188 int W
= ((iw0
>> LDST_W_bits
) & LDST_W_mask
);
3189 int sz
= ((iw0
>> LDST_sz_bits
) & LDST_sz_mask
);
3190 int aop
= ((iw0
>> LDST_aop_bits
) & LDST_aop_mask
);
3191 int reg
= ((iw0
>> LDST_reg_bits
) & LDST_reg_mask
);
3192 int ptr
= ((iw0
>> LDST_ptr_bits
) & LDST_ptr_mask
);
3193 const char * const posts
[] = { "++", "--", "" };
3194 const char *post
= posts
[aop
];
3195 const char *ptr_name
= get_preg_name (ptr
);
3197 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDST
);
3198 TRACE_EXTRACT (cpu
, "%s: sz:%i W:%i aop:%i Z:%i ptr:%i reg:%i",
3199 __func__
, sz
, W
, aop
, Z
, ptr
, reg
);
3202 illegal_instruction (cpu
);
3206 if (sz
== 0 && Z
== 0)
3208 TRACE_INSN (cpu
, "R%i = [%s%s];", reg
, ptr_name
, post
);
3209 SET_DREG (reg
, GET_LONG (PREG (ptr
)));
3211 else if (sz
== 0 && Z
== 1)
3213 TRACE_INSN (cpu
, "%s = [%s%s];", get_preg_name (reg
), ptr_name
, post
);
3214 if (aop
< 2 && ptr
== reg
)
3215 illegal_instruction_combination (cpu
);
3216 SET_PREG (reg
, GET_LONG (PREG (ptr
)));
3218 else if (sz
== 1 && Z
== 0)
3220 TRACE_INSN (cpu
, "R%i = W[%s%s] (Z);", reg
, ptr_name
, post
);
3221 SET_DREG (reg
, GET_WORD (PREG (ptr
)));
3223 else if (sz
== 1 && Z
== 1)
3225 TRACE_INSN (cpu
, "R%i = W[%s%s] (X);", reg
, ptr_name
, post
);
3226 SET_DREG (reg
, (bs32
) (bs16
) GET_WORD (PREG (ptr
)));
3228 else if (sz
== 2 && Z
== 0)
3230 TRACE_INSN (cpu
, "R%i = B[%s%s] (Z);", reg
, ptr_name
, post
);
3231 SET_DREG (reg
, GET_BYTE (PREG (ptr
)));
3233 else if (sz
== 2 && Z
== 1)
3235 TRACE_INSN (cpu
, "R%i = B[%s%s] (X);", reg
, ptr_name
, post
);
3236 SET_DREG (reg
, (bs32
) (bs8
) GET_BYTE (PREG (ptr
)));
3239 illegal_instruction (cpu
);
3243 if (sz
== 0 && Z
== 0)
3245 TRACE_INSN (cpu
, "[%s%s] = R%i;", ptr_name
, post
, reg
);
3246 PUT_LONG (PREG (ptr
), DREG (reg
));
3248 else if (sz
== 0 && Z
== 1)
3250 TRACE_INSN (cpu
, "[%s%s] = %s;", ptr_name
, post
, get_preg_name (reg
));
3251 PUT_LONG (PREG (ptr
), PREG (reg
));
3253 else if (sz
== 1 && Z
== 0)
3255 TRACE_INSN (cpu
, "W[%s%s] = R%i;", ptr_name
, post
, reg
);
3256 PUT_WORD (PREG (ptr
), DREG (reg
));
3258 else if (sz
== 2 && Z
== 0)
3260 TRACE_INSN (cpu
, "B[%s%s] = R%i;", ptr_name
, post
, reg
);
3261 PUT_BYTE (PREG (ptr
), DREG (reg
));
3264 illegal_instruction (cpu
);
3268 SET_PREG (ptr
, PREG (ptr
) + (1 << (2 - sz
)));
3270 SET_PREG (ptr
, PREG (ptr
) - (1 << (2 - sz
)));
3274 decode_LDSTiiFP_0 (SIM_CPU
*cpu
, bu16 iw0
)
3277 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3278 | 1 | 0 | 1 | 1 | 1 | 0 |.W.|.offset............|.reg...........|
3279 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3280 /* This isn't exactly a grp:reg as this insn only supports Dregs & Pregs,
3281 but for our usage, its functionality the same thing. */
3282 int grp
= ((iw0
>> 3) & 0x1);
3283 int reg
= ((iw0
>> LDSTiiFP_reg_bits
) & 0x7 /*LDSTiiFP_reg_mask*/);
3284 int offset
= ((iw0
>> LDSTiiFP_offset_bits
) & LDSTiiFP_offset_mask
);
3285 int W
= ((iw0
>> LDSTiiFP_W_bits
) & LDSTiiFP_W_mask
);
3286 bu32 imm
= negimm5s4 (offset
);
3287 bu32 ea
= FPREG
+ imm
;
3288 const char *imm_str
= negimm5s4_str (offset
);
3289 const char *reg_name
= get_allreg_name (grp
, reg
);
3291 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTiiFP
);
3292 TRACE_EXTRACT (cpu
, "%s: W:%i offset:%#x grp:%i reg:%i", __func__
,
3293 W
, offset
, grp
, reg
);
3294 TRACE_DECODE (cpu
, "%s: negimm5s4:%#x", __func__
, imm
);
3298 TRACE_INSN (cpu
, "%s = [FP + %s];", reg_name
, imm_str
);
3299 reg_write (cpu
, grp
, reg
, GET_LONG (ea
));
3303 TRACE_INSN (cpu
, "[FP + %s] = %s;", imm_str
, reg_name
);
3304 PUT_LONG (ea
, reg_read (cpu
, grp
, reg
));
3309 decode_LDSTii_0 (SIM_CPU
*cpu
, bu16 iw0
)
3312 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3313 | 1 | 0 | 1 |.W.|.op....|.offset........|.ptr.......|.reg.......|
3314 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3315 int reg
= ((iw0
>> LDSTii_reg_bit
) & LDSTii_reg_mask
);
3316 int ptr
= ((iw0
>> LDSTii_ptr_bit
) & LDSTii_ptr_mask
);
3317 int offset
= ((iw0
>> LDSTii_offset_bit
) & LDSTii_offset_mask
);
3318 int op
= ((iw0
>> LDSTii_op_bit
) & LDSTii_op_mask
);
3319 int W
= ((iw0
>> LDSTii_W_bit
) & LDSTii_W_mask
);
3321 const char *imm_str
;
3322 const char *ptr_name
= get_preg_name (ptr
);
3324 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTii
);
3325 TRACE_EXTRACT (cpu
, "%s: W:%i op:%i offset:%#x ptr:%i reg:%i",
3326 __func__
, W
, op
, offset
, ptr
, reg
);
3328 if (op
== 0 || op
== 3)
3329 imm
= uimm4s4 (offset
), imm_str
= uimm4s4_str (offset
);
3331 imm
= uimm4s2 (offset
), imm_str
= uimm4s2_str (offset
);
3332 ea
= PREG (ptr
) + imm
;
3334 TRACE_DECODE (cpu
, "%s: uimm4s4/uimm4s2:%#x", __func__
, imm
);
3336 if (W
== 1 && op
== 2)
3337 illegal_instruction (cpu
);
3343 TRACE_INSN (cpu
, "R%i = [%s + %s];", reg
, ptr_name
, imm_str
);
3344 SET_DREG (reg
, GET_LONG (ea
));
3348 TRACE_INSN (cpu
, "R%i = W[%s + %s] (Z);", reg
, ptr_name
, imm_str
);
3349 SET_DREG (reg
, GET_WORD (ea
));
3353 TRACE_INSN (cpu
, "R%i = W[%s + %s] (X);", reg
, ptr_name
, imm_str
);
3354 SET_DREG (reg
, (bs32
) (bs16
) GET_WORD (ea
));
3358 TRACE_INSN (cpu
, "%s = [%s + %s];",
3359 get_preg_name (reg
), ptr_name
, imm_str
);
3360 SET_PREG (reg
, GET_LONG (ea
));
3367 TRACE_INSN (cpu
, "[%s + %s] = R%i;", ptr_name
, imm_str
, reg
);
3368 PUT_LONG (ea
, DREG (reg
));
3372 TRACE_INSN (cpu
, "W[%s + %s] = R%i;", ptr_name
, imm_str
, reg
);
3373 PUT_WORD (ea
, DREG (reg
));
3377 TRACE_INSN (cpu
, "[%s + %s] = %s;",
3378 ptr_name
, imm_str
, get_preg_name (reg
));
3379 PUT_LONG (ea
, PREG (reg
));
3385 decode_LoopSetup_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
, bu32 pc
)
3388 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3389 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |.rop...|.c.|.soffset.......|
3390 |.reg...........| - | - |.eoffset...............................|
3391 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3392 int c
= ((iw0
>> (LoopSetup_c_bits
- 16)) & LoopSetup_c_mask
);
3393 int reg
= ((iw1
>> LoopSetup_reg_bits
) & LoopSetup_reg_mask
);
3394 int rop
= ((iw0
>> (LoopSetup_rop_bits
- 16)) & LoopSetup_rop_mask
);
3395 int soffset
= ((iw0
>> (LoopSetup_soffset_bits
- 16)) & LoopSetup_soffset_mask
);
3396 int eoffset
= ((iw1
>> LoopSetup_eoffset_bits
) & LoopSetup_eoffset_mask
);
3397 int spcrel
= pcrel4 (soffset
);
3398 int epcrel
= lppcrel10 (eoffset
);
3400 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LoopSetup
);
3401 TRACE_EXTRACT (cpu
, "%s: rop:%i c:%i soffset:%i reg:%i eoffset:%i",
3402 __func__
, rop
, c
, soffset
, reg
, eoffset
);
3403 TRACE_DECODE (cpu
, "%s: s_pcrel4:%#x e_lppcrel10:%#x",
3404 __func__
, spcrel
, epcrel
);
3407 illegal_instruction (cpu
);
3410 illegal_instruction_combination (cpu
);
3414 TRACE_INSN (cpu
, "LSETUP (%#x, %#x) LC%i;", spcrel
, epcrel
, c
);
3416 else if (rop
== 1 && reg
<= 7)
3418 TRACE_INSN (cpu
, "LSETUP (%#x, %#x) LC%i = %s;",
3419 spcrel
, epcrel
, c
, get_preg_name (reg
));
3420 SET_LCREG (c
, PREG (reg
));
3422 else if (rop
== 3 && reg
<= 7)
3424 TRACE_INSN (cpu
, "LSETUP (%#x, %#x) LC%i = %s >> 1;",
3425 spcrel
, epcrel
, c
, get_preg_name (reg
));
3426 SET_LCREG (c
, PREG (reg
) >> 1);
3429 illegal_instruction (cpu
);
3431 SET_LTREG (c
, pc
+ spcrel
);
3432 SET_LBREG (c
, pc
+ epcrel
);
3436 decode_LDIMMhalf_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3439 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3440 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 |.Z.|.H.|.S.|.grp...|.reg.......|
3441 |.hword.........................................................|
3442 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3443 int H
= ((iw0
>> (LDIMMhalf_H_bits
- 16)) & LDIMMhalf_H_mask
);
3444 int Z
= ((iw0
>> (LDIMMhalf_Z_bits
- 16)) & LDIMMhalf_Z_mask
);
3445 int S
= ((iw0
>> (LDIMMhalf_S_bits
- 16)) & LDIMMhalf_S_mask
);
3446 int reg
= ((iw0
>> (LDIMMhalf_reg_bits
- 16)) & LDIMMhalf_reg_mask
);
3447 int grp
= ((iw0
>> (LDIMMhalf_grp_bits
- 16)) & LDIMMhalf_grp_mask
);
3448 int hword
= ((iw1
>> LDIMMhalf_hword_bits
) & LDIMMhalf_hword_mask
);
3450 const char *val_str
;
3451 const char *reg_name
= get_allreg_name (grp
, reg
);
3453 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDIMMhalf
);
3454 TRACE_EXTRACT (cpu
, "%s: Z:%i H:%i S:%i grp:%i reg:%i hword:%#x",
3455 __func__
, Z
, H
, S
, grp
, reg
, hword
);
3458 illegal_instruction_combination (cpu
);
3461 val
= imm16 (hword
), val_str
= imm16_str (hword
);
3463 val
= luimm16 (hword
), val_str
= luimm16_str (hword
);
3465 if (H
== 0 && S
== 1 && Z
== 0)
3467 TRACE_INSN (cpu
, "%s = %s (X);", reg_name
, val_str
);
3469 else if (H
== 0 && S
== 0 && Z
== 1)
3471 TRACE_INSN (cpu
, "%s = %s (Z);", reg_name
, val_str
);
3473 else if (H
== 0 && S
== 0 && Z
== 0)
3475 TRACE_INSN (cpu
, "%s.L = %s;", reg_name
, val_str
);
3476 val
= REG_H_L (reg_read (cpu
, grp
, reg
), val
);
3478 else if (H
== 1 && S
== 0 && Z
== 0)
3480 TRACE_INSN (cpu
, "%s.H = %s;", reg_name
, val_str
);
3481 val
= REG_H_L (val
<< 16, reg_read (cpu
, grp
, reg
));
3484 illegal_instruction (cpu
);
3486 reg_write (cpu
, grp
, reg
, val
);
3490 decode_CALLa_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
, bu32 pc
)
3493 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3494 | 1 | 1 | 1 | 0 | 0 | 0 | 1 |.S.|.msw...........................|
3495 |.lsw...........................................................|
3496 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3497 int S
= ((iw0
>> (CALLa_S_bits
- 16)) & CALLa_S_mask
);
3498 int lsw
= ((iw1
>> 0) & 0xffff);
3499 int msw
= ((iw0
>> 0) & 0xff);
3500 int pcrel
= pcrel24 ((msw
<< 16) | lsw
);
3501 bu32 newpc
= pc
+ pcrel
;
3503 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_CALLa
);
3504 TRACE_EXTRACT (cpu
, "%s: S:%i msw:%#x lsw:%#x", __func__
, S
, msw
, lsw
);
3505 TRACE_DECODE (cpu
, "%s: pcrel24:%#x", __func__
, pcrel
);
3507 TRACE_INSN (cpu
, "%s %#x;", S
? "CALL" : "JUMP.L", pcrel
);
3510 illegal_instruction_combination (cpu
);
3514 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "CALL");
3515 SET_RETSREG (hwloop_get_next_pc (cpu
, pc
, 4));
3518 TRACE_BRANCH (cpu
, pc
, newpc
, -1, "JUMP.L");
3521 BFIN_CPU_STATE
.did_jump
= true;
3522 PROFILE_BRANCH_TAKEN (cpu
);
3527 decode_LDSTidxI_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3530 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3531 | 1 | 1 | 1 | 0 | 0 | 1 |.W.|.Z.|.sz....|.ptr.......|.reg.......|
3532 |.offset........................................................|
3533 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3534 int Z
= ((iw0
>> (LDSTidxI_Z_bits
- 16)) & LDSTidxI_Z_mask
);
3535 int W
= ((iw0
>> (LDSTidxI_W_bits
- 16)) & LDSTidxI_W_mask
);
3536 int sz
= ((iw0
>> (LDSTidxI_sz_bits
- 16)) & LDSTidxI_sz_mask
);
3537 int reg
= ((iw0
>> (LDSTidxI_reg_bits
- 16)) & LDSTidxI_reg_mask
);
3538 int ptr
= ((iw0
>> (LDSTidxI_ptr_bits
- 16)) & LDSTidxI_ptr_mask
);
3539 int offset
= ((iw1
>> LDSTidxI_offset_bits
) & LDSTidxI_offset_mask
);
3540 const char *ptr_name
= get_preg_name (ptr
);
3541 bu32 imm_16s4
= imm16s4 (offset
);
3542 bu32 imm_16s2
= imm16s2 (offset
);
3543 bu32 imm_16
= imm16 (offset
);
3545 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_LDSTidxI
);
3546 TRACE_EXTRACT (cpu
, "%s: W:%i Z:%i sz:%i ptr:%i reg:%i offset:%#x",
3547 __func__
, W
, Z
, sz
, ptr
, reg
, offset
);
3550 illegal_instruction (cpu
);
3554 if (sz
== 0 && Z
== 0)
3556 TRACE_INSN (cpu
, "R%i = [%s + %s];",
3557 reg
, ptr_name
, imm16s4_str (offset
));
3558 SET_DREG (reg
, GET_LONG (PREG (ptr
) + imm_16s4
));
3560 else if (sz
== 0 && Z
== 1)
3562 TRACE_INSN (cpu
, "%s = [%s + %s];",
3563 get_preg_name (reg
), ptr_name
, imm16s4_str (offset
));
3564 SET_PREG (reg
, GET_LONG (PREG (ptr
) + imm_16s4
));
3566 else if (sz
== 1 && Z
== 0)
3568 TRACE_INSN (cpu
, "R%i = W[%s + %s] (Z);",
3569 reg
, ptr_name
, imm16s2_str (offset
));
3570 SET_DREG (reg
, GET_WORD (PREG (ptr
) + imm_16s2
));
3572 else if (sz
== 1 && Z
== 1)
3574 TRACE_INSN (cpu
, "R%i = W[%s + %s] (X);",
3575 reg
, ptr_name
, imm16s2_str (offset
));
3576 SET_DREG (reg
, (bs32
) (bs16
) GET_WORD (PREG (ptr
) + imm_16s2
));
3578 else if (sz
== 2 && Z
== 0)
3580 TRACE_INSN (cpu
, "R%i = B[%s + %s] (Z);",
3581 reg
, ptr_name
, imm16_str (offset
));
3582 SET_DREG (reg
, GET_BYTE (PREG (ptr
) + imm_16
));
3584 else if (sz
== 2 && Z
== 1)
3586 TRACE_INSN (cpu
, "R%i = B[%s + %s] (X);",
3587 reg
, ptr_name
, imm16_str (offset
));
3588 SET_DREG (reg
, (bs32
) (bs8
) GET_BYTE (PREG (ptr
) + imm_16
));
3593 if (sz
!= 0 && Z
!= 0)
3594 illegal_instruction (cpu
);
3596 if (sz
== 0 && Z
== 0)
3598 TRACE_INSN (cpu
, "[%s + %s] = R%i;", ptr_name
,
3599 imm16s4_str (offset
), reg
);
3600 PUT_LONG (PREG (ptr
) + imm_16s4
, DREG (reg
));
3602 else if (sz
== 0 && Z
== 1)
3604 TRACE_INSN (cpu
, "[%s + %s] = %s;",
3605 ptr_name
, imm16s4_str (offset
), get_preg_name (reg
));
3606 PUT_LONG (PREG (ptr
) + imm_16s4
, PREG (reg
));
3608 else if (sz
== 1 && Z
== 0)
3610 TRACE_INSN (cpu
, "W[%s + %s] = R%i;",
3611 ptr_name
, imm16s2_str (offset
), reg
);
3612 PUT_WORD (PREG (ptr
) + imm_16s2
, DREG (reg
));
3614 else if (sz
== 2 && Z
== 0)
3616 TRACE_INSN (cpu
, "B[%s + %s] = R%i;",
3617 ptr_name
, imm16_str (offset
), reg
);
3618 PUT_BYTE (PREG (ptr
) + imm_16
, DREG (reg
));
3624 decode_linkage_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3627 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3628 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |.R.|
3629 |.framesize.....................................................|
3630 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3631 int R
= ((iw0
>> (Linkage_R_bits
- 16)) & Linkage_R_mask
);
3632 int framesize
= ((iw1
>> Linkage_framesize_bits
) & Linkage_framesize_mask
);
3635 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_linkage
);
3636 TRACE_EXTRACT (cpu
, "%s: R:%i framesize:%#x", __func__
, R
, framesize
);
3640 int size
= uimm16s4 (framesize
);
3642 TRACE_INSN (cpu
, "LINK %s;", uimm16s4_str (framesize
));
3644 illegal_instruction_combination (cpu
);
3646 PUT_LONG (sp
, RETSREG
);
3648 PUT_LONG (sp
, FPREG
);
3655 /* Restore SP from FP. */
3657 TRACE_INSN (cpu
, "UNLINK;");
3659 illegal_instruction_combination (cpu
);
3660 SET_FPREG (GET_LONG (sp
));
3662 SET_RETSREG (GET_LONG (sp
));
3671 decode_dsp32mac_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3674 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3675 | 1 | 1 | 0 | 0 |.M.| 0 | 0 |.mmod..........|.MM|.P.|.w1|.op1...|
3676 |.h01|.h11|.w0|.op0...|.h00|.h10|.dst.......|.src0......|.src1..|
3677 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3678 int op1
= ((iw0
>> (DSP32Mac_op1_bits
- 16)) & DSP32Mac_op1_mask
);
3679 int w1
= ((iw0
>> (DSP32Mac_w1_bits
- 16)) & DSP32Mac_w1_mask
);
3680 int P
= ((iw0
>> (DSP32Mac_p_bits
- 16)) & DSP32Mac_p_mask
);
3681 int MM
= ((iw0
>> (DSP32Mac_MM_bits
- 16)) & DSP32Mac_MM_mask
);
3682 int mmod
= ((iw0
>> (DSP32Mac_mmod_bits
- 16)) & DSP32Mac_mmod_mask
);
3683 int M
= ((iw0
>> (DSP32Mac_M_bits
- 16)) & DSP32Mac_M_mask
);
3684 int w0
= ((iw1
>> DSP32Mac_w0_bits
) & DSP32Mac_w0_mask
);
3685 int src0
= ((iw1
>> DSP32Mac_src0_bits
) & DSP32Mac_src0_mask
);
3686 int src1
= ((iw1
>> DSP32Mac_src1_bits
) & DSP32Mac_src1_mask
);
3687 int dst
= ((iw1
>> DSP32Mac_dst_bits
) & DSP32Mac_dst_mask
);
3688 int h10
= ((iw1
>> DSP32Mac_h10_bits
) & DSP32Mac_h10_mask
);
3689 int h00
= ((iw1
>> DSP32Mac_h00_bits
) & DSP32Mac_h00_mask
);
3690 int op0
= ((iw1
>> DSP32Mac_op0_bits
) & DSP32Mac_op0_mask
);
3691 int h11
= ((iw1
>> DSP32Mac_h11_bits
) & DSP32Mac_h11_mask
);
3692 int h01
= ((iw1
>> DSP32Mac_h01_bits
) & DSP32Mac_h01_mask
);
3694 bu32 res
= DREG (dst
);
3695 bu32 v_i
= 0, zero
= 0;
3697 static const char * const ops
[] = { "=", "+=", "-=" };
3698 char _buf
[128], *buf
= _buf
;
3701 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32mac
);
3702 TRACE_EXTRACT (cpu
, "%s: M:%i mmod:%i MM:%i P:%i w1:%i op1:%i h01:%i h11:%i "
3703 "w0:%i op0:%i h00:%i h10:%i dst:%i src0:%i src1:%i",
3704 __func__
, M
, mmod
, MM
, P
, w1
, op1
, h01
, h11
, w0
, op0
, h00
, h10
,
3707 if (w0
== 0 && w1
== 0 && op1
== 3 && op0
== 3)
3708 illegal_instruction (cpu
);
3710 if ((w1
|| w0
) && mmod
== M_W32
)
3711 illegal_instruction (cpu
);
3713 if (((1 << mmod
) & (P
? 0x131b : 0x1b5f)) == 0)
3714 illegal_instruction (cpu
);
3716 /* First handle MAC1 side. */
3717 if (w1
== 1 || op1
!= 3)
3719 bu32 res1
= decode_macfunc (cpu
, 1, op1
, h01
, h11
, src0
,
3720 src1
, mmod
, MM
, P
, &v_i
);
3723 buf
+= sprintf (buf
, P
? "R%i" : "R%i.H", dst
+ P
);
3727 buf
+= sprintf (buf
, " = A1");
3728 zero
= !!(res1
== 0);
3733 buf
+= sprintf (buf
, " = (");
3734 buf
+= sprintf (buf
, "A1 %s R%i.%c * R%i.%c", ops
[op1
],
3735 src0
, h01
? 'H' : 'L',
3736 src1
, h11
? 'H' : 'L');
3738 buf
+= sprintf (buf
, ")");
3744 STORE (DREG (dst
+ 1), res1
);
3747 if (res1
& 0xffff0000)
3748 illegal_instruction (cpu
);
3749 res
= REG_H_L (res1
<< 16, res
);
3753 if (w0
== 1 || op0
!= 3)
3756 buf
+= sprintf (buf
, " (M)");
3758 buf
+= sprintf (buf
, ", ");
3762 /* Then handle MAC0 side. */
3763 if (w0
== 1 || op0
!= 3)
3765 bu32 res0
= decode_macfunc (cpu
, 0, op0
, h00
, h10
, src0
,
3766 src1
, mmod
, 0, P
, &v_i
);
3769 buf
+= sprintf (buf
, P
? "R%i" : "R%i.L", dst
);
3773 buf
+= sprintf (buf
, " = A0");
3774 zero
|= !!(res0
== 0);
3779 buf
+= sprintf (buf
, " = (");
3780 buf
+= sprintf (buf
, "A0 %s R%i.%c * R%i.%c", ops
[op0
],
3781 src0
, h00
? 'H' : 'L',
3782 src1
, h10
? 'H' : 'L');
3784 buf
+= sprintf (buf
, ")");
3790 STORE (DREG (dst
), res0
);
3793 if (res0
& 0xffff0000)
3794 illegal_instruction (cpu
);
3795 res
= REG_H_L (res
, res0
);
3800 TRACE_INSN (cpu
, "%s%s;", _buf
, mac_optmode (mmod
, _MM
));
3802 if (!P
&& (w0
|| w1
))
3804 STORE (DREG (dst
), res
);
3805 SET_ASTATREG (v
, v_i
);
3807 SET_ASTATREG (vs
, v_i
);
3811 SET_ASTATREG (v
, v_i
);
3813 SET_ASTATREG (vs
, v_i
);
3815 if (op0
== 3 || op1
== 3)
3816 SET_ASTATREG (az
, zero
);
3820 decode_dsp32mult_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3823 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3824 | 1 | 1 | 0 | 0 |.M.| 0 | 1 |.mmod..........|.MM|.P.|.w1|.op1...|
3825 |.h01|.h11|.w0|.op0...|.h00|.h10|.dst.......|.src0......|.src1..|
3826 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3827 int op1
= ((iw0
>> (DSP32Mac_op1_bits
- 16)) & DSP32Mac_op1_mask
);
3828 int w1
= ((iw0
>> (DSP32Mac_w1_bits
- 16)) & DSP32Mac_w1_mask
);
3829 int P
= ((iw0
>> (DSP32Mac_p_bits
- 16)) & DSP32Mac_p_mask
);
3830 int MM
= ((iw0
>> (DSP32Mac_MM_bits
- 16)) & DSP32Mac_MM_mask
);
3831 int mmod
= ((iw0
>> (DSP32Mac_mmod_bits
- 16)) & DSP32Mac_mmod_mask
);
3832 int M
= ((iw0
>> (DSP32Mac_M_bits
- 16)) & DSP32Mac_M_mask
);
3833 int w0
= ((iw1
>> DSP32Mac_w0_bits
) & DSP32Mac_w0_mask
);
3834 int src0
= ((iw1
>> DSP32Mac_src0_bits
) & DSP32Mac_src0_mask
);
3835 int src1
= ((iw1
>> DSP32Mac_src1_bits
) & DSP32Mac_src1_mask
);
3836 int dst
= ((iw1
>> DSP32Mac_dst_bits
) & DSP32Mac_dst_mask
);
3837 int h10
= ((iw1
>> DSP32Mac_h10_bits
) & DSP32Mac_h10_mask
);
3838 int h00
= ((iw1
>> DSP32Mac_h00_bits
) & DSP32Mac_h00_mask
);
3839 int op0
= ((iw1
>> DSP32Mac_op0_bits
) & DSP32Mac_op0_mask
);
3840 int h11
= ((iw1
>> DSP32Mac_h11_bits
) & DSP32Mac_h11_mask
);
3841 int h01
= ((iw1
>> DSP32Mac_h01_bits
) & DSP32Mac_h01_mask
);
3843 bu32 res
= DREG (dst
);
3844 bu32 sat0
= 0, sat1
= 0;
3845 char _buf
[128], *buf
= _buf
;
3848 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32mult
);
3849 TRACE_EXTRACT (cpu
, "%s: M:%i mmod:%i MM:%i P:%i w1:%i op1:%i h01:%i h11:%i "
3850 "w0:%i op0:%i h00:%i h10:%i dst:%i src0:%i src1:%i",
3851 __func__
, M
, mmod
, MM
, P
, w1
, op1
, h01
, h11
, w0
, op0
, h00
, h10
,
3854 if (w1
== 0 && w0
== 0)
3855 illegal_instruction (cpu
);
3856 if (((1 << mmod
) & (P
? 0x313 : 0x1b57)) == 0)
3857 illegal_instruction (cpu
);
3858 if (P
&& ((dst
& 1) || (op1
!= 0) || (op0
!= 0) || !is_macmod_pmove (mmod
)))
3859 illegal_instruction (cpu
);
3860 if (!P
&& ((op1
!= 0) || (op0
!= 0) || !is_macmod_hmove (mmod
)))
3861 illegal_instruction (cpu
);
3863 /* First handle MAC1 side. */
3866 bu64 r
= decode_multfunc (cpu
, h01
, h11
, src0
, src1
, mmod
, MM
, &sat1
);
3867 bu32 res1
= extract_mult (cpu
, r
, mmod
, MM
, P
, NULL
);
3869 buf
+= sprintf (buf
, P
? "R%i" : "R%i.H", dst
+ P
);
3870 buf
+= sprintf (buf
, " = R%i.%c * R%i.%c",
3871 src0
, h01
? 'H' : 'L',
3872 src1
, h11
? 'H' : 'L');
3876 buf
+= sprintf (buf
, " (M)");
3878 buf
+= sprintf (buf
, ", ");
3882 STORE (DREG (dst
+ 1), res1
);
3885 if (res1
& 0xFFFF0000)
3886 illegal_instruction (cpu
);
3887 res
= REG_H_L (res1
<< 16, res
);
3891 /* First handle MAC0 side. */
3894 bu64 r
= decode_multfunc (cpu
, h00
, h10
, src0
, src1
, mmod
, 0, &sat0
);
3895 bu32 res0
= extract_mult (cpu
, r
, mmod
, 0, P
, NULL
);
3897 buf
+= sprintf (buf
, P
? "R%i" : "R%i.L", dst
);
3898 buf
+= sprintf (buf
, " = R%i.%c * R%i.%c",
3899 src0
, h01
? 'H' : 'L',
3900 src1
, h11
? 'H' : 'L');
3903 STORE (DREG (dst
), res0
);
3906 if (res0
& 0xFFFF0000)
3907 illegal_instruction (cpu
);
3908 res
= REG_H_L (res
, res0
);
3912 TRACE_INSN (cpu
, "%s%s;", _buf
, mac_optmode (mmod
, _MM
));
3914 if (!P
&& (w0
|| w1
))
3915 STORE (DREG (dst
), res
);
3919 STORE (ASTATREG (v
), sat0
| sat1
);
3920 STORE (ASTATREG (v_copy
), sat0
| sat1
);
3922 STORE (ASTATREG (vs
), 1);
3927 decode_dsp32alu_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
3930 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3931 | 1 | 1 | 0 | 0 |.M.| 1 | 0 | - | - | - |.HL|.aopcde............|
3932 |.aop...|.s.|.x.|.dst0......|.dst1......|.src0......|.src1......|
3933 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3934 int s
= ((iw1
>> DSP32Alu_s_bits
) & DSP32Alu_s_mask
);
3935 int x
= ((iw1
>> DSP32Alu_x_bits
) & DSP32Alu_x_mask
);
3936 int aop
= ((iw1
>> DSP32Alu_aop_bits
) & DSP32Alu_aop_mask
);
3937 int src0
= ((iw1
>> DSP32Alu_src0_bits
) & DSP32Alu_src0_mask
);
3938 int src1
= ((iw1
>> DSP32Alu_src1_bits
) & DSP32Alu_src1_mask
);
3939 int dst0
= ((iw1
>> DSP32Alu_dst0_bits
) & DSP32Alu_dst0_mask
);
3940 int dst1
= ((iw1
>> DSP32Alu_dst1_bits
) & DSP32Alu_dst1_mask
);
3941 int M
= ((iw0
>> (DSP32Alu_M_bits
- 16)) & DSP32Alu_M_mask
);
3942 int HL
= ((iw0
>> (DSP32Alu_HL_bits
- 16)) & DSP32Alu_HL_mask
);
3943 int aopcde
= ((iw0
>> (DSP32Alu_aopcde_bits
- 16)) & DSP32Alu_aopcde_mask
);
3945 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32alu
);
3946 TRACE_EXTRACT (cpu
, "%s: M:%i HL:%i aopcde:%i aop:%i s:%i x:%i dst0:%i "
3947 "dst1:%i src0:%i src1:%i",
3948 __func__
, M
, HL
, aopcde
, aop
, s
, x
, dst0
, dst1
, src0
, src1
);
3950 if ((aop
== 0 || aop
== 2) && aopcde
== 9 && HL
== 0 && s
== 0)
3953 TRACE_INSN (cpu
, "A%i.L = R%i.L;", a
, src0
);
3954 SET_AWREG (a
, REG_H_L (AWREG (a
), DREG (src0
)));
3956 else if ((aop
== 0 || aop
== 2) && aopcde
== 9 && HL
== 1 && s
== 0)
3959 TRACE_INSN (cpu
, "A%i.H = R%i.H;", a
, src0
);
3960 SET_AWREG (a
, REG_H_L (DREG (src0
), AWREG (a
)));
3962 else if ((aop
== 1 || aop
== 0) && aopcde
== 5)
3964 bs32 val0
= DREG (src0
);
3965 bs32 val1
= DREG (src1
);
3968 bs32 ovX
, sBit1
, sBit2
, sBitRes1
, sBitRes2
;
3970 TRACE_INSN (cpu
, "R%i.%s = R%i %s R%i (RND12)", dst0
, HL
? "L" : "H",
3971 src0
, aop
& 0x1 ? "-" : "+", src1
);
3973 /* If subtract, just invert and add one. */
3977 /* Get the sign bits, since we need them later. */
3978 sBit1
= !!(val0
& 0x80000000);
3979 sBit2
= !!(val1
& 0x80000000);
3983 sBitRes1
= !!(res
& 0x80000000);
3984 /* Round to the 12th bit. */
3986 sBitRes2
= !!(res
& 0x80000000);
3994 positive_res + positive_round = neg
3995 Shift and upper 4 bits where not the same. */
3996 if ((!(sBit1
^ sBit2
) && (sBit1
^ sBitRes1
))
3997 || (!sBit1
&& !sBit2
&& sBitRes2
)
3998 || ((signRes
!= 0) && (signRes
!= -1)))
4000 /* Both X1 and X2 Neg res is neg overflow. */
4003 /* Both X1 and X2 Pos res is pos overflow. */
4004 else if (!sBit1
&& !sBit2
)
4006 /* Pos+Neg or Neg+Pos take the sign of the result. */
4016 /* Shift up now after overflow detection. */
4024 STORE (DREG (dst0
), REG_H_L (res
<< 16, DREG (dst0
)));
4026 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), res
));
4028 SET_ASTATREG (az
, res
== 0);
4029 SET_ASTATREG (an
, res
& 0x8000);
4030 SET_ASTATREG (v
, ovX
);
4032 SET_ASTATREG (vs
, ovX
);
4034 else if ((aop
== 2 || aop
== 3) && aopcde
== 5)
4036 bs32 val0
= DREG (src0
);
4037 bs32 val1
= DREG (src1
);
4040 TRACE_INSN (cpu
, "R%i.%s = R%i %s R%i (RND20)", dst0
, HL
? "L" : "H",
4041 src0
, aop
& 0x1 ? "-" : "+", src1
);
4043 /* If subtract, just invert and add one. */
4047 res
= (val0
>> 4) + (val1
>> 4) + (((val0
& 0xf) + (val1
& 0xf)) >> 4);
4049 /* Don't sign extend during the shift. */
4050 res
= ((bu32
)res
>> 16);
4052 /* Don't worry about overflows, since we are shifting right. */
4055 STORE (DREG (dst0
), REG_H_L (res
<< 16, DREG (dst0
)));
4057 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), res
));
4059 SET_ASTATREG (az
, res
== 0);
4060 SET_ASTATREG (an
, res
& 0x8000);
4061 SET_ASTATREG (v
, 0);
4063 else if (aopcde
== 2 || aopcde
== 3)
4065 bu32 s1
, s2
, val
, ac0_i
= 0, v_i
= 0;
4067 TRACE_INSN (cpu
, "R%i.%c = R%i.%c %c R%i.%c%s;",
4068 dst0
, HL
? 'H' : 'L',
4069 src0
, aop
& 2 ? 'H' : 'L',
4070 aopcde
== 2 ? '+' : '-',
4071 src1
, aop
& 1 ? 'H' : 'L',
4082 val
= add16 (cpu
, s1
, s2
, &ac0_i
, &v_i
, 0, 0, s
, 0);
4084 val
= sub16 (cpu
, s1
, s2
, &ac0_i
, &v_i
, 0, 0, s
, 0);
4086 SET_ASTATREG (ac0
, ac0_i
);
4087 SET_ASTATREG (v
, v_i
);
4089 SET_DREG_H (dst0
, val
<< 16);
4091 SET_DREG_L (dst0
, val
);
4093 SET_ASTATREG (an
, val
& 0x8000);
4096 else if ((aop
== 0 || aop
== 2) && aopcde
== 9 && s
== 1)
4099 TRACE_INSN (cpu
, "A%i = R%i;", a
, src0
);
4100 SET_AREG32 (a
, DREG (src0
));
4102 else if ((aop
== 1 || aop
== 3) && aopcde
== 9 && s
== 0)
4105 TRACE_INSN (cpu
, "A%i.X = R%i.L;", a
, src0
);
4106 SET_AXREG (a
, (bs8
)DREG (src0
));
4108 else if (aop
== 3 && aopcde
== 11 && (s
== 0 || s
== 1))
4110 bu64 acc0
= get_extended_acc (cpu
, 0);
4111 bu64 acc1
= get_extended_acc (cpu
, 1);
4112 bu32 carry
= (bu40
)acc1
< (bu40
)acc0
;
4115 TRACE_INSN (cpu
, "A0 -= A1%s;", s
? " (W32)" : "");
4118 if ((bs64
)acc0
< -0x8000000000ll
)
4119 acc0
= -0x8000000000ull
, sat
= 1;
4120 else if ((bs64
)acc0
>= 0x7fffffffffll
)
4121 acc0
= 0x7fffffffffull
, sat
= 1;
4125 /* A0 -= A1 (W32) */
4126 if (acc0
& (bu64
)0x8000000000ll
)
4127 acc0
&= 0x80ffffffffll
, sat
= 1;
4129 acc0
&= 0xffffffffll
;
4131 STORE (AXREG (0), (acc0
>> 32) & 0xff);
4132 STORE (AWREG (0), acc0
& 0xffffffff);
4133 STORE (ASTATREG (az
), acc0
== 0);
4134 STORE (ASTATREG (an
), !!(acc0
& (bu64
)0x8000000000ll
));
4135 STORE (ASTATREG (ac0
), carry
);
4136 STORE (ASTATREG (ac0_copy
), carry
);
4137 STORE (ASTATREG (av0
), sat
);
4139 STORE (ASTATREG (av0s
), sat
);
4141 else if ((aop
== 0 || aop
== 1) && aopcde
== 22)
4143 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4145 const char * const opts
[] = { "rndl", "rndh", "tl", "th" };
4147 TRACE_INSN (cpu
, "R%i = BYTEOP2P (R%i:%i, R%i:%i) (%s%s);", dst0
,
4148 src0
+ 1, src0
, src1
+ 1, src1
, opts
[HL
+ (aop
<< 1)],
4152 illegal_instruction_combination (cpu
);
4155 s0H
= DREG (src0
+ 1);
4157 s1H
= DREG (src1
+ 1);
4160 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4161 s1
= algn (s1H
, s1L
, IREG (0) & 3);
4165 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4166 s1
= algn (s1L
, s1H
, IREG (0) & 3);
4170 tmp0
= ((((s1
>> 8) & 0xff) + ((s1
>> 0) & 0xff) +
4171 ((s0
>> 8) & 0xff) + ((s0
>> 0) & 0xff) + i
) >> 2) & 0xff;
4172 tmp1
= ((((s1
>> 24) & 0xff) + ((s1
>> 16) & 0xff) +
4173 ((s0
>> 24) & 0xff) + ((s0
>> 16) & 0xff) + i
) >> 2) & 0xff;
4174 SET_DREG (dst0
, (tmp1
<< (16 + (HL
* 8))) | (tmp0
<< (HL
* 8)));
4176 else if ((aop
== 0 || aop
== 1) && s
== 0 && aopcde
== 8)
4178 TRACE_INSN (cpu
, "A%i = 0;", aop
);
4181 else if (aop
== 2 && s
== 0 && aopcde
== 8)
4183 TRACE_INSN (cpu
, "A1 = A0 = 0;");
4187 else if ((aop
== 0 || aop
== 1 || aop
== 2) && s
== 1 && aopcde
== 8)
4189 bs40 acc0
= get_extended_acc (cpu
, 0);
4190 bs40 acc1
= get_extended_acc (cpu
, 1);
4193 if (aop
== 0 || aop
== 1)
4194 TRACE_INSN (cpu
, "A%i = A%i (S);", aop
, aop
);
4196 TRACE_INSN (cpu
, "A1 = A1 (S), A0 = A0 (S);");
4198 if (aop
== 0 || aop
== 2)
4201 acc0
= saturate_s32 (acc0
, &sat
);
4202 acc0
|= -(acc0
& 0x80000000ull
);
4203 SET_AXREG (0, (acc0
>> 31) & 0xFF);
4204 SET_AWREG (0, acc0
& 0xFFFFFFFF);
4205 SET_ASTATREG (av0
, sat
);
4207 SET_ASTATREG (av0s
, sat
);
4212 if (aop
== 1 || aop
== 2)
4215 acc1
= saturate_s32 (acc1
, &sat
);
4216 acc1
|= -(acc1
& 0x80000000ull
);
4217 SET_AXREG (1, (acc1
>> 31) & 0xFF);
4218 SET_AWREG (1, acc1
& 0xFFFFFFFF);
4219 SET_ASTATREG (av1
, sat
);
4221 SET_ASTATREG (av1s
, sat
);
4226 SET_ASTATREG (az
, (acc0
== 0) || (acc1
== 0));
4227 SET_ASTATREG (an
, ((acc0
>> 31) & 1) || ((acc1
>> 31) & 1));
4229 else if (aop
== 3 && (s
== 0 || s
== 1) && aopcde
== 8)
4231 TRACE_INSN (cpu
, "A%i = A%i;", s
, !s
);
4232 SET_AXREG (s
, AXREG (!s
));
4233 SET_AWREG (s
, AWREG (!s
));
4235 else if (aop
== 3 && HL
== 0 && aopcde
== 16)
4240 TRACE_INSN (cpu
, "A1 = ABS A1 , A0 = ABS A0;");
4243 for (i
= 0; i
< 2; ++i
)
4246 bs40 acc
= get_extended_acc (cpu
, i
);
4250 av
= acc
== ((bs40
)1 << 39);
4252 acc
= ((bs40
)1 << 39) - 1;
4255 SET_ASTATREG (av
[i
], av
);
4257 SET_ASTATREG (avs
[i
], av
);
4260 SET_ASTATREG (az
, az
);
4261 SET_ASTATREG (an
, 0);
4263 else if (aop
== 0 && aopcde
== 23)
4265 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4268 TRACE_INSN (cpu
, "R%i = BYTEOP3P (R%i:%i, R%i:%i) (%s%s);", dst0
,
4269 src0
+ 1, src0
, src1
+ 1, src1
, HL
? "HI" : "LO",
4273 illegal_instruction_combination (cpu
);
4276 s0H
= DREG (src0
+ 1);
4278 s1H
= DREG (src1
+ 1);
4281 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4282 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4286 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4287 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4290 tmp0
= (bs32
)(bs16
)(s0
>> 0) + ((s1
>> ( 0 + (8 * !HL
))) & 0xff);
4291 tmp1
= (bs32
)(bs16
)(s0
>> 16) + ((s1
>> (16 + (8 * !HL
))) & 0xff);
4292 SET_DREG (dst0
, (CLAMP (tmp0
, 0, 255) << ( 0 + (8 * HL
))) |
4293 (CLAMP (tmp1
, 0, 255) << (16 + (8 * HL
))));
4295 else if ((aop
== 0 || aop
== 1) && aopcde
== 16)
4300 TRACE_INSN (cpu
, "A%i = ABS A%i;", HL
, aop
);
4302 acc
= get_extended_acc (cpu
, aop
);
4305 av
= acc
== ((bs40
)1 << 39);
4307 acc
= ((bs40
)1 << 39) - 1;
4310 SET_ASTATREG (av
[HL
], av
);
4312 SET_ASTATREG (avs
[HL
], av
);
4313 SET_ASTATREG (az
, acc
== 0);
4314 SET_ASTATREG (an
, 0);
4316 else if (aop
== 3 && aopcde
== 12)
4318 bs32 res
= DREG (src0
);
4320 bool sBit_a
, sBit_b
;
4322 TRACE_INSN (cpu
, "R%i.%s = R%i (RND);", dst0
, HL
== 0 ? "L" : "H", src0
);
4323 TRACE_DECODE (cpu
, "R%i.%s = R%i:%#x (RND);", dst0
,
4324 HL
== 0 ? "L" : "H", src0
, res
);
4326 sBit_b
= !!(res
& 0x80000000);
4329 sBit_a
= !!(res
& 0x80000000);
4331 /* Overflow if the sign bit changed when we rounded. */
4332 if ((res
>> 16) && (sBit_b
!= sBit_a
))
4347 SET_DREG (dst0
, REG_H_L (DREG (dst0
), res
));
4349 SET_DREG (dst0
, REG_H_L (res
<< 16, DREG (dst0
)));
4351 SET_ASTATREG (az
, res
== 0);
4352 SET_ASTATREG (an
, res
< 0);
4353 SET_ASTATREG (v
, ovX
);
4355 SET_ASTATREG (vs
, ovX
);
4357 else if (aop
== 3 && HL
== 0 && aopcde
== 15)
4359 bu32 hi
= (-(bs16
)(DREG (src0
) >> 16)) << 16;
4360 bu32 lo
= (-(bs16
)(DREG (src0
) & 0xFFFF)) & 0xFFFF;
4363 TRACE_INSN (cpu
, "R%i = -R%i (V);", dst0
, src0
);
4367 if (hi
== 0x80000000)
4383 SET_DREG (dst0
, hi
| lo
);
4385 SET_ASTATREG (v
, v
);
4387 SET_ASTATREG (vs
, 1);
4388 SET_ASTATREG (ac0
, ac0
);
4389 SET_ASTATREG (ac1
, ac1
);
4390 setflags_nz_2x16 (cpu
, DREG (dst0
));
4392 else if (aop
== 3 && HL
== 0 && aopcde
== 14)
4394 TRACE_INSN (cpu
, "A1 = - A1 , A0 = - A0;");
4396 SET_AREG (0, saturate_s40 (-get_extended_acc (cpu
, 0)));
4397 SET_AREG (1, saturate_s40 (-get_extended_acc (cpu
, 1)));
4398 /* XXX: what ASTAT flags need updating ? */
4400 else if ((aop
== 0 || aop
== 1) && (HL
== 0 || HL
== 1) && aopcde
== 14)
4402 bs40 src_acc
= get_extended_acc (cpu
, aop
);
4404 TRACE_INSN (cpu
, "A%i = - A%i;", HL
, aop
);
4406 SET_AREG (HL
, saturate_s40 (-src_acc
));
4408 SET_ASTATREG (az
, AWREG (HL
) == 0 && AXREG (HL
) == 0);
4409 SET_ASTATREG (an
, AXREG (HL
) >> 7);
4410 SET_ASTATREG (ac0
, src_acc
== 0);
4413 SET_ASTATREG (av0
, src_acc
< 0);
4415 SET_ASTATREG (av0s
, 1);
4419 SET_ASTATREG (av1
, src_acc
< 0);
4421 SET_ASTATREG (av1s
, 1);
4424 else if (aop
== 0 && aopcde
== 12)
4426 bs16 tmp0_hi
= DREG (src0
) >> 16;
4427 bs16 tmp0_lo
= DREG (src0
);
4428 bs16 tmp1_hi
= DREG (src1
) >> 16;
4429 bs16 tmp1_lo
= DREG (src1
);
4431 TRACE_INSN (cpu
, "R%i.L = R%i.H = SIGN(R%i.H) * R%i.H + SIGN(R%i.L) * R%i.L;",
4432 dst0
, dst0
, src0
, src1
, src0
, src1
);
4434 if ((tmp0_hi
>> 15) & 1)
4435 tmp1_hi
= ~tmp1_hi
+ 1;
4437 if ((tmp0_lo
>> 15) & 1)
4438 tmp1_lo
= ~tmp1_lo
+ 1;
4440 tmp1_hi
= tmp1_hi
+ tmp1_lo
;
4442 STORE (DREG (dst0
), REG_H_L (tmp1_hi
<< 16, tmp1_hi
));
4444 else if (aopcde
== 0)
4446 bu32 s0
= DREG (src0
);
4447 bu32 s1
= DREG (src1
);
4448 bu32 s0h
= s0
>> 16;
4449 bu32 s0l
= s0
& 0xFFFF;
4450 bu32 s1h
= s1
>> 16;
4451 bu32 s1l
= s1
& 0xFFFF;
4453 bu32 ac1_i
= 0, ac0_i
= 0, v_i
= 0, z_i
= 0, n_i
= 0;
4455 TRACE_INSN (cpu
, "R%i = R%i %c|%c R%i%s;", dst0
, src0
,
4456 (aop
& 2) ? '-' : '+', (aop
& 1) ? '-' : '+', src1
,
4459 t0
= sub16 (cpu
, s0h
, s1h
, &ac1_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4461 t0
= add16 (cpu
, s0h
, s1h
, &ac1_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4464 t1
= sub16 (cpu
, s0l
, s1l
, &ac0_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4466 t1
= add16 (cpu
, s0l
, s1l
, &ac0_i
, &v_i
, &z_i
, &n_i
, s
, 0);
4468 SET_ASTATREG (ac1
, ac1_i
);
4469 SET_ASTATREG (ac0
, ac0_i
);
4470 SET_ASTATREG (az
, z_i
);
4471 SET_ASTATREG (an
, n_i
);
4472 SET_ASTATREG (v
, v_i
);
4474 SET_ASTATREG (vs
, v_i
);
4479 SET_DREG (dst0
, (t1
<< 16) | t0
);
4481 SET_DREG (dst0
, (t0
<< 16) | t1
);
4483 else if (aop
== 1 && aopcde
== 12)
4485 bu32 val0
= ((AWREG (0) >> 16) + (AWREG (0) & 0xFFFF)) & 0xFFFF;
4486 bu32 val1
= ((AWREG (1) >> 16) + (AWREG (1) & 0xFFFF)) & 0xFFFF;
4488 TRACE_INSN (cpu
, "R%i = A1.L + A1.H, R%i = A0.L + A0.H;", dst1
, dst0
);
4491 illegal_instruction_combination (cpu
);
4499 SET_DREG (dst0
, val0
);
4500 SET_DREG (dst1
, val1
);
4503 else if (aopcde
== 1)
4507 bu16 s0L
= DREG (src0
);
4508 bu16 s0H
= DREG (src0
) >> 16;
4509 bu16 s1L
= DREG (src1
);
4510 bu16 s1H
= DREG (src1
) >> 16;
4511 bu32 v_i
= 0, n_i
= 0, z_i
= 0;
4513 TRACE_INSN (cpu
, "R%i = R%i %s R%i, R%i = R%i %s R%i%s;",
4514 dst1
, src0
, HL
? "+|-" : "+|+", src1
,
4515 dst0
, src0
, HL
? "-|+" : "-|-", src1
,
4516 amod0amod2 (s
, x
, aop
));
4519 illegal_instruction_combination (cpu
);
4523 x0
= add16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4524 x1
= add16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4525 d1
= (x0
<< 16) | x1
;
4527 x0
= sub16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4528 x1
= sub16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4530 d0
= (x0
<< 16) | x1
;
4532 d0
= (x1
<< 16) | x0
;
4536 x0
= add16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4537 x1
= sub16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4538 d1
= (x0
<< 16) | x1
;
4540 x0
= sub16 (cpu
, s0H
, s1H
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4541 x1
= add16 (cpu
, s0L
, s1L
, 0, &v_i
, &z_i
, &n_i
, s
, aop
) & 0xffff;
4543 d0
= (x0
<< 16) | x1
;
4545 d0
= (x1
<< 16) | x0
;
4547 SET_ASTATREG (az
, z_i
);
4548 SET_ASTATREG (an
, n_i
);
4549 SET_ASTATREG (v
, v_i
);
4551 SET_ASTATREG (vs
, v_i
);
4553 STORE (DREG (dst0
), d0
);
4554 STORE (DREG (dst1
), d1
);
4556 else if ((aop
== 0 || aop
== 1 || aop
== 2) && aopcde
== 11)
4558 bs40 acc0
= get_extended_acc (cpu
, 0);
4559 bs40 acc1
= get_extended_acc (cpu
, 1);
4560 bu32 v
, dreg
, sat
= 0;
4561 bu32 carry
= !!((bu40
)~acc1
< (bu40
)acc0
);
4564 TRACE_INSN (cpu
, "R%i = (A0 += A1);", dst0
);
4566 TRACE_INSN (cpu
, "R%i.%c = (A0 += A1);", dst0
, HL
? 'H' : 'L');
4568 TRACE_INSN (cpu
, "A0 += A1%s;", s
? " (W32)" : "");
4571 acc0
= saturate_s40_astat (acc0
, &v
);
4573 if (aop
== 2 && s
== 1) /* A0 += A1 (W32) */
4575 if (acc0
& (bs40
)0x8000000000ll
)
4576 acc0
&= 0x80ffffffffll
;
4578 acc0
&= 0xffffffffll
;
4581 STORE (AXREG (0), acc0
>> 32);
4582 STORE (AWREG (0), acc0
);
4583 SET_ASTATREG (av0
, v
&& acc1
);
4585 SET_ASTATREG (av0s
, v
);
4587 if (aop
== 0 || aop
== 1)
4589 if (aop
) /* Dregs_lo = A0 += A1 */
4591 dreg
= saturate_s32 (rnd16 (acc0
) << 16, &sat
);
4593 STORE (DREG (dst0
), REG_H_L (dreg
, DREG (dst0
)));
4595 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), dreg
>> 16));
4597 else /* Dregs = A0 += A1 */
4599 dreg
= saturate_s32 (acc0
, &sat
);
4600 STORE (DREG (dst0
), dreg
);
4603 STORE (ASTATREG (az
), dreg
== 0);
4604 STORE (ASTATREG (an
), !!(dreg
& 0x80000000));
4605 STORE (ASTATREG (ac0
), carry
);
4606 STORE (ASTATREG (ac0_copy
), carry
);
4607 STORE (ASTATREG (v
), sat
);
4608 STORE (ASTATREG (v_copy
), sat
);
4610 STORE (ASTATREG (vs
), sat
);
4614 STORE (ASTATREG (az
), acc0
== 0);
4615 STORE (ASTATREG (an
), !!(acc0
& 0x8000000000ull
));
4616 STORE (ASTATREG (ac0
), carry
);
4617 STORE (ASTATREG (ac0_copy
), carry
);
4620 else if ((aop
== 0 || aop
== 1) && aopcde
== 10)
4622 TRACE_INSN (cpu
, "R%i.L = A%i.X;", dst0
, aop
);
4623 SET_DREG_L (dst0
, (bs8
)AXREG (aop
));
4625 else if (aop
== 0 && aopcde
== 4)
4627 TRACE_INSN (cpu
, "R%i = R%i + R%i%s;", dst0
, src0
, src1
, amod1 (s
, x
));
4628 SET_DREG (dst0
, add32 (cpu
, DREG (src0
), DREG (src1
), 1, s
));
4630 else if (aop
== 1 && aopcde
== 4)
4632 TRACE_INSN (cpu
, "R%i = R%i - R%i%s;", dst0
, src0
, src1
, amod1 (s
, x
));
4633 SET_DREG (dst0
, sub32 (cpu
, DREG (src0
), DREG (src1
), 1, s
, 0));
4635 else if (aop
== 2 && aopcde
== 4)
4637 TRACE_INSN (cpu
, "R%i = R%i + R%i, R%i = R%i - R%i%s;",
4638 dst1
, src0
, src1
, dst0
, src0
, src1
, amod1 (s
, x
));
4641 illegal_instruction_combination (cpu
);
4643 STORE (DREG (dst1
), add32 (cpu
, DREG (src0
), DREG (src1
), 1, s
));
4644 STORE (DREG (dst0
), sub32 (cpu
, DREG (src0
), DREG (src1
), 1, s
, 1));
4646 else if ((aop
== 0 || aop
== 1) && aopcde
== 17)
4648 bs40 acc0
= get_extended_acc (cpu
, 0);
4649 bs40 acc1
= get_extended_acc (cpu
, 1);
4650 bs40 val0
, val1
, sval0
, sval1
;
4653 TRACE_INSN (cpu
, "R%i = A%i + A%i, R%i = A%i - A%i%s",
4654 dst1
, !aop
, aop
, dst0
, !aop
, aop
, amod1 (s
, x
));
4655 TRACE_DECODE (cpu
, "R%i = A%i:%#"PRIx64
" + A%i:%#"PRIx64
", "
4656 "R%i = A%i:%#"PRIx64
" - A%i:%#"PRIx64
"%s",
4657 dst1
, !aop
, aop
? acc0
: acc1
, aop
, aop
? acc1
: acc0
,
4658 dst0
, !aop
, aop
? acc0
: acc1
, aop
, aop
? acc1
: acc0
,
4662 illegal_instruction_combination (cpu
);
4670 sval0
= saturate_s32 (val0
, &sat
);
4672 sval1
= saturate_s32 (val1
, &sat
);
4680 STORE (DREG (dst0
), val0
);
4681 STORE (DREG (dst1
), val1
);
4682 SET_ASTATREG (v
, sat_i
);
4684 SET_ASTATREG (vs
, sat_i
);
4685 SET_ASTATREG (an
, val0
& 0x80000000 || val1
& 0x80000000);
4686 SET_ASTATREG (az
, val0
== 0 || val1
== 0);
4687 SET_ASTATREG (ac1
, (bu40
)~acc0
< (bu40
)acc1
);
4689 SET_ASTATREG (ac0
, !!((bu40
)acc1
<= (bu40
)acc0
));
4691 SET_ASTATREG (ac0
, !!((bu40
)acc0
<= (bu40
)acc1
));
4693 else if (aop
== 0 && aopcde
== 18)
4695 bu40 acc0
= get_extended_acc (cpu
, 0);
4696 bu40 acc1
= get_extended_acc (cpu
, 1);
4697 bu32 s0L
= DREG (src0
);
4698 bu32 s0H
= DREG (src0
+ 1);
4699 bu32 s1L
= DREG (src1
);
4700 bu32 s1H
= DREG (src1
+ 1);
4702 bs16 tmp0
, tmp1
, tmp2
, tmp3
;
4704 /* This instruction is only defined for register pairs R1:0 and R3:2. */
4705 if (!((src0
== 0 || src0
== 2) && (src1
== 0 || src1
== 2)))
4706 illegal_instruction (cpu
);
4708 TRACE_INSN (cpu
, "SAA (R%i:%i, R%i:%i)%s", src0
+ 1, src0
,
4709 src1
+ 1, src1
, s
? " (R)" :"");
4711 /* Bit s determines the order of the two registers from a pair:
4712 if s=0 the low-order bytes come from the low reg in the pair,
4713 and if s=1 the low-order bytes come from the high reg. */
4717 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4718 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4722 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4723 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4726 /* Find the absolute difference between pairs, make it
4727 absolute, then add it to the existing accumulator half. */
4729 tmp0
= ((s0
<< 24) >> 24) - ((s1
<< 24) >> 24);
4730 tmp1
= ((s0
<< 16) >> 24) - ((s1
<< 16) >> 24);
4731 tmp2
= ((s0
<< 8) >> 24) - ((s1
<< 8) >> 24);
4732 tmp3
= ((s0
<< 0) >> 24) - ((s1
<< 0) >> 24);
4734 tmp0
= (tmp0
< 0) ? -tmp0
: tmp0
;
4735 tmp1
= (tmp1
< 0) ? -tmp1
: tmp1
;
4736 tmp2
= (tmp2
< 0) ? -tmp2
: tmp2
;
4737 tmp3
= (tmp3
< 0) ? -tmp3
: tmp3
;
4739 s0L
= saturate_u16 ((bu32
)tmp0
+ ((acc0
>> 0) & 0xffff), 0);
4740 s0H
= saturate_u16 ((bu32
)tmp1
+ ((acc0
>> 16) & 0xffff), 0);
4741 s1L
= saturate_u16 ((bu32
)tmp2
+ ((acc1
>> 0) & 0xffff), 0);
4742 s1H
= saturate_u16 ((bu32
)tmp3
+ ((acc1
>> 16) & 0xffff), 0);
4744 STORE (AWREG (0), (s0H
<< 16) | (s0L
& 0xFFFF));
4745 STORE (AXREG (0), 0);
4746 STORE (AWREG (1), (s1H
<< 16) | (s1L
& 0xFFFF));
4747 STORE (AXREG (1), 0);
4749 else if (aop
== 3 && aopcde
== 18)
4751 TRACE_INSN (cpu
, "DISALGNEXCPT");
4754 else if ((aop
== 0 || aop
== 1) && aopcde
== 20)
4756 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4757 const char * const opts
[] = { "", " (R)", " (T)", " (T, R)" };
4759 TRACE_INSN (cpu
, "R%i = BYTEOP1P (R%i:%i, R%i:%i)%s;", dst0
,
4760 src0
+ 1, src0
, src1
+ 1, src1
, opts
[s
+ (aop
<< 1)]);
4763 illegal_instruction_combination (cpu
);
4766 s0H
= DREG (src0
+ 1);
4768 s1H
= DREG (src1
+ 1);
4771 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4772 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4776 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4777 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4781 (((((s0
>> 0) & 0xff) + ((s1
>> 0) & 0xff) + !aop
) >> 1) << 0) |
4782 (((((s0
>> 8) & 0xff) + ((s1
>> 8) & 0xff) + !aop
) >> 1) << 8) |
4783 (((((s0
>> 16) & 0xff) + ((s1
>> 16) & 0xff) + !aop
) >> 1) << 16) |
4784 (((((s0
>> 24) & 0xff) + ((s1
>> 24) & 0xff) + !aop
) >> 1) << 24));
4786 else if (aop
== 0 && aopcde
== 21)
4788 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4790 TRACE_INSN (cpu
, "(R%i, R%i) = BYTEOP16P (R%i:%i, R%i:%i)%s;", dst1
, dst0
,
4791 src0
+ 1, src0
, src1
+ 1, src1
, s
? " (R)" : "");
4794 illegal_instruction_combination (cpu
);
4797 s0H
= DREG (src0
+ 1);
4799 s1H
= DREG (src1
+ 1);
4802 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4803 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4807 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4808 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4812 ((((s0
>> 0) & 0xff) + ((s1
>> 0) & 0xff)) << 0) |
4813 ((((s0
>> 8) & 0xff) + ((s1
>> 8) & 0xff)) << 16));
4815 ((((s0
>> 16) & 0xff) + ((s1
>> 16) & 0xff)) << 0) |
4816 ((((s0
>> 24) & 0xff) + ((s1
>> 24) & 0xff)) << 16));
4818 else if (aop
== 1 && aopcde
== 21)
4820 bu32 s0
, s0L
, s0H
, s1
, s1L
, s1H
;
4822 TRACE_INSN (cpu
, "(R%i, R%i) = BYTEOP16M (R%i:%i, R%i:%i)%s;", dst1
, dst0
,
4823 src0
+ 1, src0
, src1
+ 1, src1
, s
? " (R)" : "");
4826 illegal_instruction_combination (cpu
);
4829 s0H
= DREG (src0
+ 1);
4831 s1H
= DREG (src1
+ 1);
4834 s0
= algn (s0H
, s0L
, IREG (0) & 3);
4835 s1
= algn (s1H
, s1L
, IREG (1) & 3);
4839 s0
= algn (s0L
, s0H
, IREG (0) & 3);
4840 s1
= algn (s1L
, s1H
, IREG (1) & 3);
4844 (((((s0
>> 0) & 0xff) - ((s1
>> 0) & 0xff)) << 0) & 0xffff) |
4845 (((((s0
>> 8) & 0xff) - ((s1
>> 8) & 0xff)) << 16)));
4847 (((((s0
>> 16) & 0xff) - ((s1
>> 16) & 0xff)) << 0) & 0xffff) |
4848 (((((s0
>> 24) & 0xff) - ((s1
>> 24) & 0xff)) << 16)));
4850 else if (aop
== 1 && aopcde
== 7)
4852 TRACE_INSN (cpu
, "R%i = MIN (R%i, R%i);", dst0
, src0
, src1
);
4853 SET_DREG (dst0
, min32 (cpu
, DREG (src0
), DREG (src1
)));
4855 else if (aop
== 0 && aopcde
== 7)
4857 TRACE_INSN (cpu
, "R%i = MAX (R%i, R%i);", dst0
, src0
, src1
);
4858 SET_DREG (dst0
, max32 (cpu
, DREG (src0
), DREG (src1
)));
4860 else if (aop
== 2 && aopcde
== 7)
4862 bu32 val
= DREG (src0
);
4865 TRACE_INSN (cpu
, "R%i = ABS R%i;", dst0
, src0
);
4869 v
= (val
== 0x80000000);
4872 SET_DREG (dst0
, val
);
4874 SET_ASTATREG (v
, v
);
4876 SET_ASTATREG (vs
, 1);
4877 setflags_nz (cpu
, val
);
4879 else if (aop
== 3 && aopcde
== 7)
4881 bu32 val
= DREG (src0
);
4883 TRACE_INSN (cpu
, "R%i = - R%i %s;", dst0
, src0
, amod1 (s
, 0));
4885 if (s
&& val
== 0x80000000)
4888 SET_ASTATREG (v
, 1);
4889 SET_ASTATREG (vs
, 1);
4891 else if (val
== 0x80000000)
4895 SET_DREG (dst0
, val
);
4897 SET_ASTATREG (az
, val
== 0);
4898 SET_ASTATREG (an
, val
& 0x80000000);
4900 else if (aop
== 2 && aopcde
== 6)
4902 bu32 in
= DREG (src0
);
4903 bu32 hi
= (in
& 0x80000000 ? (bu32
)-(bs16
)(in
>> 16) : in
>> 16) << 16;
4904 bu32 lo
= (in
& 0x8000 ? (bu32
)-(bs16
)(in
& 0xFFFF) : in
) & 0xFFFF;
4907 TRACE_INSN (cpu
, "R%i = ABS R%i (V);", dst0
, src0
);
4910 if (hi
== 0x80000000)
4920 SET_DREG (dst0
, hi
| lo
);
4922 SET_ASTATREG (v
, v
);
4924 SET_ASTATREG (vs
, 1);
4925 setflags_nz_2x16 (cpu
, DREG (dst0
));
4927 else if (aop
== 1 && aopcde
== 6)
4929 TRACE_INSN (cpu
, "R%i = MIN (R%i, R%i) (V);", dst0
, src0
, src1
);
4930 SET_DREG (dst0
, min2x16 (cpu
, DREG (src0
), DREG (src1
)));
4932 else if (aop
== 0 && aopcde
== 6)
4934 TRACE_INSN (cpu
, "R%i = MAX (R%i, R%i) (V);", dst0
, src0
, src1
);
4935 SET_DREG (dst0
, max2x16 (cpu
, DREG (src0
), DREG (src1
)));
4937 else if (aop
== 0 && aopcde
== 24)
4939 TRACE_INSN (cpu
, "R%i = BYTEPACK (R%i, R%i);", dst0
, src0
, src1
);
4941 (((DREG (src0
) >> 0) & 0xff) << 0) |
4942 (((DREG (src0
) >> 16) & 0xff) << 8) |
4943 (((DREG (src1
) >> 0) & 0xff) << 16) |
4944 (((DREG (src1
) >> 16) & 0xff) << 24));
4946 else if (aop
== 1 && aopcde
== 24)
4950 bu8 bytea
, byteb
, bytec
, byted
;
4952 TRACE_INSN (cpu
, "(R%i, R%i) = BYTEUNPACK R%i:%i%s;",
4953 dst1
, dst0
, src0
+ 1, src0
, s
? " (R)" : "");
4956 illegal_instruction_combination (cpu
);
4958 order
= IREG (0) & 0x3;
4960 hi
= src0
, lo
= src0
+ 1;
4962 hi
= src0
+ 1, lo
= src0
;
4963 comb_src
= (((bu64
)DREG (hi
)) << 32) | DREG (lo
);
4964 bytea
= (comb_src
>> (0 + 8 * order
));
4965 byteb
= (comb_src
>> (8 + 8 * order
));
4966 bytec
= (comb_src
>> (16 + 8 * order
));
4967 byted
= (comb_src
>> (24 + 8 * order
));
4968 SET_DREG (dst0
, bytea
| ((bu32
)byteb
<< 16));
4969 SET_DREG (dst1
, bytec
| ((bu32
)byted
<< 16));
4971 else if (aopcde
== 13)
4973 const char *searchmodes
[] = { "GT", "GE", "LT", "LE" };
4975 bs16 a0_lo
, a1_lo
, src_hi
, src_lo
;
4977 TRACE_INSN (cpu
, "(R%i, R%i) = SEARCH R%i (%s);",
4978 dst1
, dst0
, src0
, searchmodes
[aop
]);
4981 illegal_instruction_combination (cpu
);
4983 up_hi
= up_lo
= false;
4986 src_lo
= DREG (src0
);
4987 src_hi
= DREG (src0
) >> 16;
4992 up_hi
= (src_hi
> a1_lo
);
4993 up_lo
= (src_lo
> a0_lo
);
4996 up_hi
= (src_hi
>= a1_lo
);
4997 up_lo
= (src_lo
>= a0_lo
);
5000 up_hi
= (src_hi
< a1_lo
);
5001 up_lo
= (src_lo
< a0_lo
);
5004 up_hi
= (src_hi
<= a1_lo
);
5005 up_lo
= (src_lo
<= a0_lo
);
5011 SET_AREG (1, src_hi
);
5012 SET_DREG (dst1
, PREG (0));
5016 SET_AREG (0, src_lo
);
5017 SET_DREG (dst0
, PREG (0));
5021 illegal_instruction (cpu
);
5025 decode_dsp32shift_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
5028 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5029 | 1 | 1 | 0 | 0 |.M.| 1 | 1 | 0 | 0 | - | - |.sopcde............|
5030 |.sop...|.HLs...|.dst0......| - | - | - |.src0......|.src1......|
5031 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5032 int HLs
= ((iw1
>> DSP32Shift_HLs_bits
) & DSP32Shift_HLs_mask
);
5033 int sop
= ((iw1
>> DSP32Shift_sop_bits
) & DSP32Shift_sop_mask
);
5034 int src0
= ((iw1
>> DSP32Shift_src0_bits
) & DSP32Shift_src0_mask
);
5035 int src1
= ((iw1
>> DSP32Shift_src1_bits
) & DSP32Shift_src1_mask
);
5036 int dst0
= ((iw1
>> DSP32Shift_dst0_bits
) & DSP32Shift_dst0_mask
);
5037 int sopcde
= ((iw0
>> (DSP32Shift_sopcde_bits
- 16)) & DSP32Shift_sopcde_mask
);
5038 int M
= ((iw0
>> (DSP32Shift_M_bits
- 16)) & DSP32Shift_M_mask
);
5040 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32shift
);
5041 TRACE_EXTRACT (cpu
, "%s: M:%i sopcde:%i sop:%i HLs:%i dst0:%i src0:%i src1:%i",
5042 __func__
, M
, sopcde
, sop
, HLs
, dst0
, src0
, src1
);
5044 if ((sop
== 0 || sop
== 1) && sopcde
== 0)
5047 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5049 TRACE_INSN (cpu
, "R%i.%c = ASHIFT R%i.%c BY R%i.L%s;",
5050 dst0
, HLs
< 2 ? 'L' : 'H',
5051 src1
, HLs
& 1 ? 'H' : 'L',
5052 src0
, sop
== 1 ? " (S)" : "");
5055 val
= (bu16
)(DREG (src1
) & 0xFFFF);
5057 val
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5059 /* Positive shift magnitudes produce Logical Left shifts.
5060 Negative shift magnitudes produce Arithmetic Right shifts. */
5062 val
= ashiftrt (cpu
, val
, -shft
, 16);
5064 val
= lshift (cpu
, val
, shft
, 16, sop
== 1);
5067 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), val
));
5069 STORE (DREG (dst0
), REG_H_L (val
<< 16, DREG (dst0
)));
5071 else if (sop
== 2 && sopcde
== 0)
5073 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5076 TRACE_INSN (cpu
, "R%i.%c = LSHIFT R%i.%c BY R%i.L;",
5077 dst0
, HLs
< 2 ? 'L' : 'H',
5078 src1
, HLs
& 1 ? 'H' : 'L', src0
);
5081 val
= (bu16
)(DREG (src1
) & 0xFFFF);
5083 val
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5086 val
= val
>> (-1 * shft
);
5091 SET_DREG (dst0
, REG_H_L (DREG (dst0
), val
));
5093 SET_DREG (dst0
, REG_H_L (val
<< 16, DREG (dst0
)));
5095 SET_ASTATREG (az
, !((val
& 0xFFFF0000) == 0) || ((val
& 0xFFFF) == 0));
5096 SET_ASTATREG (an
, (!!(val
& 0x80000000)) ^ (!!(val
& 0x8000)));
5097 SET_ASTATREG (v
, 0);
5099 else if (sop
== 2 && sopcde
== 3 && (HLs
== 1 || HLs
== 0))
5101 int shift
= imm6 (DREG (src0
) & 0xFFFF);
5103 bu40 acc
= get_unextended_acc (cpu
, HLs
);
5105 TRACE_INSN (cpu
, "A%i = ROT A%i BY R%i.L;", HLs
, HLs
, src0
);
5106 TRACE_DECODE (cpu
, "A%i:%#"PRIx64
" shift:%i CC:%i", HLs
, acc
, shift
, cc
);
5108 acc
= rot40 (acc
, shift
, &cc
);
5109 SET_AREG (HLs
, acc
);
5113 else if (sop
== 0 && sopcde
== 3 && (HLs
== 0 || HLs
== 1))
5115 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5116 bu64 val
= get_extended_acc (cpu
, HLs
);
5119 TRACE_INSN (cpu
, "A%i = ASHIFT A%i BY R%i.L;", HLs
, HLs
, src0
);
5120 TRACE_DECODE (cpu
, "A%i:%#"PRIx64
" shift:%i", HLs
, val
, shft
);
5123 val
= ashiftrt (cpu
, val
, -shft
, 40);
5125 val
= lshift (cpu
, val
, shft
, 40, 0);
5127 STORE (AXREG (HLs
), (val
>> 32) & 0xff);
5128 STORE (AWREG (HLs
), (val
& 0xffffffff));
5130 else if (sop
== 1 && sopcde
== 3 && (HLs
== 0 || HLs
== 1))
5132 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5136 TRACE_INSN (cpu
, "A%i = LSHIFT A%i BY R%i.L;", HLs
, HLs
, src0
);
5137 val
= get_extended_acc (cpu
, HLs
);
5140 val
= lshiftrt (cpu
, val
, -shft
, 40);
5142 val
= lshift (cpu
, val
, shft
, 40, 0);
5144 STORE (AXREG (HLs
), (val
>> 32) & 0xff);
5145 STORE (AWREG (HLs
), (val
& 0xffffffff));
5147 else if ((sop
== 0 || sop
== 1) && sopcde
== 1)
5149 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5153 TRACE_INSN (cpu
, "R%i = ASHIFT R%i BY R%i.L (V%s);",
5154 dst0
, src1
, src0
, sop
== 1 ? ",S" : "");
5156 val0
= (bu16
)DREG (src1
) & 0xFFFF;
5157 val1
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5161 val0
= ashiftrt (cpu
, val0
, -shft
, 16);
5163 val1
= ashiftrt (cpu
, val1
, -shft
, 16);
5167 val0
= lshift (cpu
, val0
, shft
, 16, sop
== 1);
5169 val1
= lshift (cpu
, val1
, shft
, 16, sop
== 1);
5171 SET_ASTAT (ASTAT
| astat
);
5172 STORE (DREG (dst0
), (val1
<< 16) | val0
);
5174 else if ((sop
== 0 || sop
== 1 || sop
== 2) && sopcde
== 2)
5176 /* dregs = [LA]SHIFT dregs BY dregs_lo (opt_S) */
5177 /* sop == 1 : opt_S */
5178 bu32 v
= DREG (src1
);
5179 /* LSHIFT uses sign extended low 6 bits of dregs_lo. */
5180 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5182 TRACE_INSN (cpu
, "R%i = %cSHIFT R%i BY R%i.L%s;", dst0
,
5183 shft
&& sop
!= 2 ? 'A' : 'L', src1
, src0
,
5184 sop
== 1 ? " (S)" : "");
5189 STORE (DREG (dst0
), lshiftrt (cpu
, v
, -shft
, 32));
5191 STORE (DREG (dst0
), ashiftrt (cpu
, v
, -shft
, 32));
5194 STORE (DREG (dst0
), lshift (cpu
, v
, shft
, 32, sop
== 1));
5196 else if (sop
== 3 && sopcde
== 2)
5198 int shift
= imm6 (DREG (src0
) & 0xFFFF);
5199 bu32 src
= DREG (src1
);
5200 bu32 ret
, cc
= CCREG
;
5202 TRACE_INSN (cpu
, "R%i = ROT R%i BY R%i.L;", dst0
, src1
, src0
);
5203 TRACE_DECODE (cpu
, "R%i:%#x R%i:%#x shift:%i CC:%i",
5204 dst0
, DREG (dst0
), src1
, src
, shift
, cc
);
5206 ret
= rot32 (src
, shift
, &cc
);
5207 STORE (DREG (dst0
), ret
);
5211 else if (sop
== 2 && sopcde
== 1)
5213 bs32 shft
= (bs8
)(DREG (src0
) << 2) >> 2;
5217 TRACE_INSN (cpu
, "R%i = LSHIFT R%i BY R%i.L (V);", dst0
, src1
, src0
);
5219 val0
= (bu16
)DREG (src1
) & 0xFFFF;
5220 val1
= (bu16
)((DREG (src1
) & 0xFFFF0000) >> 16);
5224 val0
= lshiftrt (cpu
, val0
, -shft
, 16);
5226 val1
= lshiftrt (cpu
, val1
, -shft
, 16);
5230 val0
= lshift (cpu
, val0
, shft
, 16, 0);
5232 val1
= lshift (cpu
, val1
, shft
, 16, 0);
5234 SET_ASTAT (ASTAT
| astat
);
5235 STORE (DREG (dst0
), (val1
<< 16) | val0
);
5237 else if (sopcde
== 4)
5239 bu32 sv0
= DREG (src0
);
5240 bu32 sv1
= DREG (src1
);
5241 TRACE_INSN (cpu
, "R%i = PACK (R%i.%c, R%i.%c);", dst0
,
5242 src1
, sop
& 2 ? 'H' : 'L',
5243 src0
, sop
& 1 ? 'H' : 'L');
5248 SET_DREG (dst0
, (sv1
<< 16) | (sv0
& 0xFFFF));
5250 else if (sop
== 0 && sopcde
== 5)
5252 bu32 sv1
= DREG (src1
);
5253 TRACE_INSN (cpu
, "R%i.L = SIGNBITS R%i;", dst0
, src1
);
5254 SET_DREG_L (dst0
, signbits (sv1
, 32));
5256 else if (sop
== 1 && sopcde
== 5)
5258 bu32 sv1
= DREG (src1
);
5259 TRACE_INSN (cpu
, "R%i.L = SIGNBITS R%i.L;", dst0
, src1
);
5260 SET_DREG_L (dst0
, signbits (sv1
, 16));
5262 else if (sop
== 2 && sopcde
== 5)
5264 bu32 sv1
= DREG (src1
);
5265 TRACE_INSN (cpu
, "R%i.L = SIGNBITS R%i.H;", dst0
, src1
);
5266 SET_DREG_L (dst0
, signbits (sv1
>> 16, 16));
5268 else if ((sop
== 0 || sop
== 1) && sopcde
== 6)
5270 bu64 acc
= AXREG (sop
);
5271 TRACE_INSN (cpu
, "R%i.L = SIGNBITS A%i;", dst0
, sop
);
5274 SET_DREG_L (dst0
, signbits (acc
, 40) & 0xFFFF);
5276 else if (sop
== 3 && sopcde
== 6)
5278 bu32 v
= ones (DREG (src1
));
5279 TRACE_INSN (cpu
, "R%i.L = ONES R%i;", dst0
, src1
);
5280 SET_DREG_L (dst0
, v
);
5282 else if (sop
== 0 && sopcde
== 7)
5284 bu16 sv1
= (bu16
)signbits (DREG (src1
), 32);
5285 bu16 sv0
= (bu16
)DREG (src0
);
5288 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i, R%i.L);", dst0
, src1
, src0
);
5290 if ((sv1
& 0x1f) < (sv0
& 0x1f))
5294 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), dst_lo
));
5296 else if (sop
== 1 && sopcde
== 7)
5298 /* Exponent adjust on two 16-bit inputs. Select
5299 smallest norm among 3 inputs. */
5300 bs16 src1_hi
= (DREG (src1
) & 0xFFFF0000) >> 16;
5301 bs16 src1_lo
= (DREG (src1
) & 0xFFFF);
5302 bu16 src0_lo
= (DREG (src0
) & 0xFFFF);
5303 bu16 tmp_hi
, tmp_lo
, tmp
;
5305 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i, R%i.L) (V);", dst0
, src1
, src0
);
5307 tmp_hi
= signbits (src1_hi
, 16);
5308 tmp_lo
= signbits (src1_lo
, 16);
5310 if ((tmp_hi
& 0xf) < (tmp_lo
& 0xf))
5311 if ((tmp_hi
& 0xf) < (src0_lo
& 0xf))
5316 if ((tmp_lo
& 0xf) < (src0_lo
& 0xf))
5320 STORE (DREG (dst0
), REG_H_L (DREG (dst0
), tmp
));
5322 else if (sop
== 2 && sopcde
== 7)
5324 /* Exponent adjust on single 16-bit register. */
5326 bu16 src0_lo
= (bu16
)(DREG (src0
) & 0xFFFF);
5328 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i.L, R%i.L);", dst0
, src1
, src0
);
5330 tmp
= signbits (DREG (src1
) & 0xFFFF, 16);
5332 if ((tmp
& 0xf) < (src0_lo
& 0xf))
5333 SET_DREG_L (dst0
, tmp
);
5335 SET_DREG_L (dst0
, src0_lo
);
5337 else if (sop
== 3 && sopcde
== 7)
5340 bu16 src0_lo
= (bu16
)(DREG (src0
) & 0xFFFF);
5342 TRACE_INSN (cpu
, "R%i.L = EXPADJ (R%i.H, R%i.L);", dst0
, src1
, src0
);
5344 tmp
= signbits ((DREG (src1
) & 0xFFFF0000) >> 16, 16);
5346 if ((tmp
& 0xf) < (src0_lo
& 0xf))
5347 SET_DREG_L (dst0
, tmp
);
5349 SET_DREG_L (dst0
, src0_lo
);
5351 else if (sop
== 0 && sopcde
== 8)
5353 bu64 acc
= get_unextended_acc (cpu
, 0);
5356 TRACE_INSN (cpu
, "BITMUX (R%i, R%i, A0) (ASR);", src0
, src1
);
5359 illegal_instruction_combination (cpu
);
5364 (((bu64
)s0
& 1) << 38) |
5365 (((bu64
)s1
& 1) << 39);
5366 SET_DREG (src0
, s0
>> 1);
5367 SET_DREG (src1
, s1
>> 1);
5371 else if (sop
== 1 && sopcde
== 8)
5373 bu64 acc
= get_unextended_acc (cpu
, 0);
5376 TRACE_INSN (cpu
, "BITMUX (R%i, R%i, A0) (ASL);", src0
, src1
);
5379 illegal_instruction_combination (cpu
);
5386 SET_DREG (src0
, s0
<< 1);
5387 SET_DREG (src1
, s1
<< 1);
5391 else if ((sop
== 0 || sop
== 1) && sopcde
== 9)
5393 bs40 acc0
= get_extended_acc (cpu
, 0);
5396 TRACE_INSN (cpu
, "R%i.L = VIT_MAX (R%i) (AS%c);",
5397 dst0
, src1
, sop
& 1 ? 'R' : 'L');
5400 sH
= DREG (src1
) >> 16;
5407 if (((sH
- sL
) & 0x8000) == 0)
5410 acc0
|= (sop
& 1) ? 0x80000000 : 1;
5416 SET_DREG (dst0
, REG_H_L (DREG (dst0
), out
));
5418 else if ((sop
== 2 || sop
== 3) && sopcde
== 9)
5420 bs40 acc0
= get_extended_acc (cpu
, 0);
5421 bs16 s0L
, s0H
, s1L
, s1H
, out0
, out1
;
5423 TRACE_INSN (cpu
, "R%i = VIT_MAX (R%i, R%i) (AS%c);",
5424 dst0
, src1
, src0
, sop
& 1 ? 'R' : 'L');
5427 s0H
= DREG (src0
) >> 16;
5429 s1H
= DREG (src1
) >> 16;
5436 if (((s0H
- s0L
) & 0x8000) == 0)
5439 acc0
|= (sop
& 1) ? 0x40000000 : 2;
5444 if (((s1H
- s1L
) & 0x8000) == 0)
5447 acc0
|= (sop
& 1) ? 0x80000000 : 1;
5453 SET_DREG (dst0
, REG_H_L (out1
<< 16, out0
));
5455 else if (sop
== 0 && sopcde
== 10)
5457 bu32 v
= DREG (src0
);
5458 bu32 x
= DREG (src1
);
5459 bu32 mask
= (1 << (v
& 0x1f)) - 1;
5460 TRACE_INSN (cpu
, "R%i = EXTRACT (R%i, R%i.L) (Z);", dst0
, src1
, src0
);
5461 x
>>= ((v
>> 8) & 0x1f);
5462 SET_DREG (dst0
, x
& mask
);
5463 setflags_logical (cpu
, DREG (dst0
));
5465 else if (sop
== 1 && sopcde
== 10)
5467 bu32 v
= DREG (src0
);
5468 bu32 x
= DREG (src1
);
5469 bu32 sgn
= (1 << (v
& 0x1f)) >> 1;
5470 bu32 mask
= (1 << (v
& 0x1f)) - 1;
5471 TRACE_INSN (cpu
, "R%i = EXTRACT (R%i, R%i.L) (X);", dst0
, src1
, src0
);
5472 x
>>= ((v
>> 8) & 0x1f);
5477 setflags_logical (cpu
, DREG (dst0
));
5479 else if ((sop
== 2 || sop
== 3) && sopcde
== 10)
5481 /* The first dregs is the "background" while the second dregs is the
5482 "foreground". The fg reg is used to overlay the bg reg and is:
5483 | nnnn nnnn | nnnn nnnn | xxxp pppp | xxxL LLLL |
5484 n = the fg bit field
5485 p = bit position in bg reg to start LSB of fg field
5486 L = number of fg bits to extract
5487 Using (X) sign-extends the fg bit field. */
5488 bu32 fg
= DREG (src0
);
5489 bu32 bg
= DREG (src1
);
5490 bu32 len
= fg
& 0x1f;
5491 bu32 mask
= (1 << MIN (16, len
)) - 1;
5492 bu32 fgnd
= (fg
>> 16) & mask
;
5493 int shft
= ((fg
>> 8) & 0x1f);
5495 TRACE_INSN (cpu
, "R%i = DEPOSIT (R%i, R%i)%s;", dst0
, src1
, src0
,
5496 sop
== 3 ? " (X)" : "");
5500 /* Sign extend the fg bit field. */
5502 fgnd
= ((bs32
)(bs16
)(fgnd
<< (16 - len
))) >> (16 - len
);
5508 SET_DREG (dst0
, bg
| fgnd
);
5509 setflags_logical (cpu
, DREG (dst0
));
5511 else if (sop
== 0 && sopcde
== 11)
5513 bu64 acc0
= get_unextended_acc (cpu
, 0);
5515 TRACE_INSN (cpu
, "R%i.L = CC = BXORSHIFT (A0, R%i);", dst0
, src0
);
5518 SET_CCREG (xor_reduce (acc0
, DREG (src0
)));
5519 SET_DREG (dst0
, REG_H_L (DREG (dst0
), CCREG
));
5522 else if (sop
== 1 && sopcde
== 11)
5524 bu64 acc0
= get_unextended_acc (cpu
, 0);
5526 TRACE_INSN (cpu
, "R%i.L = CC = BXOR (A0, R%i);", dst0
, src0
);
5528 SET_CCREG (xor_reduce (acc0
, DREG (src0
)));
5529 SET_DREG (dst0
, REG_H_L (DREG (dst0
), CCREG
));
5531 else if (sop
== 0 && sopcde
== 12)
5533 bu64 acc0
= get_unextended_acc (cpu
, 0);
5534 bu64 acc1
= get_unextended_acc (cpu
, 1);
5536 TRACE_INSN (cpu
, "A0 = BXORSHIFT (A0, A1, CC);");
5538 acc0
= (acc0
<< 1) | (CCREG
^ xor_reduce (acc0
, acc1
));
5541 else if (sop
== 1 && sopcde
== 12)
5543 bu64 acc0
= get_unextended_acc (cpu
, 0);
5544 bu64 acc1
= get_unextended_acc (cpu
, 1);
5546 TRACE_INSN (cpu
, "R%i.L = CC = BXOR (A0, A1, CC);", dst0
);
5548 SET_CCREG (CCREG
^ xor_reduce (acc0
, acc1
));
5549 acc0
= (acc0
<< 1) | CCREG
;
5550 SET_DREG (dst0
, REG_H_L (DREG (dst0
), CCREG
));
5552 else if ((sop
== 0 || sop
== 1 || sop
== 2) && sopcde
== 13)
5554 int shift
= (sop
+ 1) * 8;
5555 TRACE_INSN (cpu
, "R%i = ALIGN%i (R%i, R%i);", dst0
, shift
, src1
, src0
);
5556 SET_DREG (dst0
, (DREG (src1
) << (32 - shift
)) | (DREG (src0
) >> shift
));
5559 illegal_instruction (cpu
);
5563 decode_dsp32shiftimm_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
)
5566 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5567 | 1 | 1 | 0 | 0 |.M.| 1 | 1 | 0 | 1 | - | - |.sopcde............|
5568 |.sop...|.HLs...|.dst0......|.immag.................|.src1......|
5569 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5570 int src1
= ((iw1
>> DSP32ShiftImm_src1_bits
) & DSP32ShiftImm_src1_mask
);
5571 int sop
= ((iw1
>> DSP32ShiftImm_sop_bits
) & DSP32ShiftImm_sop_mask
);
5572 int bit8
= ((iw1
>> 8) & 0x1);
5573 int immag
= ((iw1
>> DSP32ShiftImm_immag_bits
) & DSP32ShiftImm_immag_mask
);
5574 int newimmag
= (-(iw1
>> DSP32ShiftImm_immag_bits
) & DSP32ShiftImm_immag_mask
);
5575 int dst0
= ((iw1
>> DSP32ShiftImm_dst0_bits
) & DSP32ShiftImm_dst0_mask
);
5576 int M
= ((iw0
>> (DSP32ShiftImm_M_bits
- 16)) & DSP32ShiftImm_M_mask
);
5577 int sopcde
= ((iw0
>> (DSP32ShiftImm_sopcde_bits
- 16)) & DSP32ShiftImm_sopcde_mask
);
5578 int HLs
= ((iw1
>> DSP32ShiftImm_HLs_bits
) & DSP32ShiftImm_HLs_mask
);
5580 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32shiftimm
);
5581 TRACE_EXTRACT (cpu
, "%s: M:%i sopcde:%i sop:%i HLs:%i dst0:%i immag:%#x src1:%i",
5582 __func__
, M
, sopcde
, sop
, HLs
, dst0
, immag
, src1
);
5586 bu16 in
= DREG (src1
) >> ((HLs
& 1) ? 16 : 0);
5592 TRACE_INSN (cpu
, "R%i.%c = R%i.%c >>> %i;",
5593 dst0
, (HLs
& 2) ? 'H' : 'L',
5594 src1
, (HLs
& 1) ? 'H' : 'L', newimmag
);
5595 result
= ashiftrt (cpu
, in
, newimmag
, 16);
5597 else if (sop
== 1 && bit8
== 0)
5599 TRACE_INSN (cpu
, "R%i.%c = R%i.%c << %i (S);",
5600 dst0
, (HLs
& 2) ? 'H' : 'L',
5601 src1
, (HLs
& 1) ? 'H' : 'L', immag
);
5602 result
= lshift (cpu
, in
, immag
, 16, 1);
5604 else if (sop
== 1 && bit8
)
5606 TRACE_INSN (cpu
, "R%i.%c = R%i.%c >>> %i (S);",
5607 dst0
, (HLs
& 2) ? 'H' : 'L',
5608 src1
, (HLs
& 1) ? 'H' : 'L', immag
);
5609 result
= lshift (cpu
, in
, immag
, 16, 1);
5611 else if (sop
== 2 && bit8
)
5613 TRACE_INSN (cpu
, "R%i.%c = R%i.%c >> %i;",
5614 dst0
, (HLs
& 2) ? 'H' : 'L',
5615 src1
, (HLs
& 1) ? 'H' : 'L', newimmag
);
5616 result
= lshiftrt (cpu
, in
, newimmag
, 16);
5618 else if (sop
== 2 && bit8
== 0)
5620 TRACE_INSN (cpu
, "R%i.%c = R%i.%c << %i;",
5621 dst0
, (HLs
& 2) ? 'H' : 'L',
5622 src1
, (HLs
& 1) ? 'H' : 'L', immag
);
5623 result
= lshift (cpu
, in
, immag
, 16, 0);
5626 illegal_instruction (cpu
);
5630 STORE (DREG (dst0
), (v
& 0xFFFF) | (result
<< 16));
5632 STORE (DREG (dst0
), (v
& 0xFFFF0000) | result
);
5634 else if (sop
== 2 && sopcde
== 3 && (HLs
== 1 || HLs
== 0))
5636 int shift
= imm6 (immag
);
5638 bu40 acc
= get_unextended_acc (cpu
, HLs
);
5640 TRACE_INSN (cpu
, "A%i = ROT A%i BY %i;", HLs
, HLs
, shift
);
5641 TRACE_DECODE (cpu
, "A%i:%#"PRIx64
" shift:%i CC:%i", HLs
, acc
, shift
, cc
);
5643 acc
= rot40 (acc
, shift
, &cc
);
5644 SET_AREG (HLs
, acc
);
5648 else if (sop
== 0 && sopcde
== 3 && bit8
== 1)
5650 /* Arithmetic shift, so shift in sign bit copies. */
5652 int shift
= uimm5 (newimmag
);
5655 TRACE_INSN (cpu
, "A%i = A%i >>> %i;", HLs
, HLs
, shift
);
5657 acc
= get_extended_acc (cpu
, HLs
);
5659 /* Sign extend again. */
5660 if (acc
& (1ULL << 39))
5661 acc
|= -(1ULL << 39);
5663 acc
&= ~(-(1ULL << 39));
5665 STORE (AXREG (HLs
), (acc
>> 32) & 0xFF);
5666 STORE (AWREG (HLs
), acc
& 0xFFFFFFFF);
5668 else if ((sop
== 0 && sopcde
== 3 && bit8
== 0)
5669 || (sop
== 1 && sopcde
== 3))
5672 int shiftup
= uimm5 (immag
);
5673 int shiftdn
= uimm5 (newimmag
);
5676 TRACE_INSN (cpu
, "A%i = A%i %s %i;", HLs
, HLs
,
5677 sop
== 0 ? "<<" : ">>",
5678 sop
== 0 ? shiftup
: shiftdn
);
5681 /* Logical shift, so shift in zeroes. */
5691 SET_AREG (HLs
, acc
);
5692 SET_ASTATREG (an
, !!(acc
& 0x8000000000ull
));
5693 SET_ASTATREG (az
, acc
== 0);
5695 else if (sop
== 1 && sopcde
== 1 && bit8
== 0)
5697 int count
= imm5 (immag
);
5698 bu16 val0
= DREG (src1
) >> 16;
5699 bu16 val1
= DREG (src1
) & 0xFFFF;
5702 TRACE_INSN (cpu
, "R%i = R%i << %i (V,S);", dst0
, src1
, count
);
5703 val0
= lshift (cpu
, val0
, count
, 16, 1);
5705 val1
= lshift (cpu
, val1
, count
, 16, 1);
5706 SET_ASTAT (ASTAT
| astat
);
5708 STORE (DREG (dst0
), (val0
<< 16) | val1
);
5710 else if (sop
== 2 && sopcde
== 1 && bit8
== 1)
5712 int count
= imm5 (newimmag
);
5713 bu16 val0
= DREG (src1
) & 0xFFFF;
5714 bu16 val1
= DREG (src1
) >> 16;
5717 TRACE_INSN (cpu
, "R%i = R%i >> %i (V);", dst0
, src1
, count
);
5718 val0
= lshiftrt (cpu
, val0
, count
, 16);
5720 val1
= lshiftrt (cpu
, val1
, count
, 16);
5721 SET_ASTAT (ASTAT
| astat
);
5723 STORE (DREG (dst0
), val0
| (val1
<< 16));
5725 else if (sop
== 2 && sopcde
== 1 && bit8
== 0)
5727 int count
= imm5 (immag
);
5728 bu16 val0
= DREG (src1
) & 0xFFFF;
5729 bu16 val1
= DREG (src1
) >> 16;
5732 TRACE_INSN (cpu
, "R%i = R%i << %i (V);", dst0
, src1
, count
);
5733 val0
= lshift (cpu
, val0
, count
, 16, 0);
5735 val1
= lshift (cpu
, val1
, count
, 16, 0);
5736 SET_ASTAT (ASTAT
| astat
);
5738 STORE (DREG (dst0
), val0
| (val1
<< 16));
5740 else if (sopcde
== 1 && (sop
== 0 || (sop
== 1 && bit8
== 1)))
5742 int count
= uimm5 (newimmag
);
5743 bu16 val0
= DREG (src1
) & 0xFFFF;
5744 bu16 val1
= DREG (src1
) >> 16;
5747 TRACE_INSN (cpu
, "R%i = R%i >>> %i %s;", dst0
, src1
, count
,
5748 sop
== 0 ? "(V)" : "(V,S)");
5750 val0
= ashiftrt (cpu
, val0
, count
, 16);
5752 val1
= ashiftrt (cpu
, val1
, count
, 16);
5753 SET_ASTAT (ASTAT
| astat
);
5755 STORE (DREG (dst0
), REG_H_L (val1
<< 16, val0
));
5757 else if (sop
== 1 && sopcde
== 2)
5759 int count
= imm6 (immag
);
5761 TRACE_INSN (cpu
, "R%i = R%i << %i (S);", dst0
, src1
, count
);
5762 STORE (DREG (dst0
), lshift (cpu
, DREG (src1
), count
, 32, 1));
5764 else if (sop
== 2 && sopcde
== 2)
5766 int count
= imm6 (newimmag
);
5768 TRACE_INSN (cpu
, "R%i = R%i >> %i;", dst0
, src1
, count
);
5771 STORE (DREG (dst0
), lshift (cpu
, DREG (src1
), -count
, 32, 0));
5773 STORE (DREG (dst0
), lshiftrt (cpu
, DREG (src1
), count
, 32));
5775 else if (sop
== 3 && sopcde
== 2)
5777 int shift
= imm6 (immag
);
5778 bu32 src
= DREG (src1
);
5779 bu32 ret
, cc
= CCREG
;
5781 TRACE_INSN (cpu
, "R%i = ROT R%i BY %i;", dst0
, src1
, shift
);
5782 TRACE_DECODE (cpu
, "R%i:%#x R%i:%#x shift:%i CC:%i",
5783 dst0
, DREG (dst0
), src1
, src
, shift
, cc
);
5785 ret
= rot32 (src
, shift
, &cc
);
5786 STORE (DREG (dst0
), ret
);
5790 else if (sop
== 0 && sopcde
== 2)
5792 int count
= imm6 (newimmag
);
5794 TRACE_INSN (cpu
, "R%i = R%i >>> %i;", dst0
, src1
, count
);
5797 STORE (DREG (dst0
), lshift (cpu
, DREG (src1
), -count
, 32, 0));
5799 STORE (DREG (dst0
), ashiftrt (cpu
, DREG (src1
), count
, 32));
5802 illegal_instruction (cpu
);
5806 outc (SIM_CPU
*cpu
, char ch
)
5808 SIM_DESC sd
= CPU_STATE (cpu
);
5809 sim_io_printf (sd
, "%c", ch
);
5811 sim_io_flush_stdout (sd
);
5815 decode_psedoDEBUG_0 (SIM_CPU
*cpu
, bu16 iw0
)
5818 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5819 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 |.fn....|.grp.......|.reg.......|
5820 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5821 SIM_DESC sd
= CPU_STATE (cpu
);
5822 int fn
= ((iw0
>> PseudoDbg_fn_bits
) & PseudoDbg_fn_mask
);
5823 int grp
= ((iw0
>> PseudoDbg_grp_bits
) & PseudoDbg_grp_mask
);
5824 int reg
= ((iw0
>> PseudoDbg_reg_bits
) & PseudoDbg_reg_mask
);
5826 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_psedoDEBUG
);
5827 TRACE_EXTRACT (cpu
, "%s: fn:%i grp:%i reg:%i", __func__
, fn
, grp
, reg
);
5829 if ((reg
== 0 || reg
== 1) && fn
== 3)
5831 TRACE_INSN (cpu
, "DBG A%i;", reg
);
5832 sim_io_printf (sd
, "DBG : A%i = %#"PRIx64
"\n", reg
,
5833 get_unextended_acc (cpu
, reg
));
5835 else if (reg
== 3 && fn
== 3)
5837 TRACE_INSN (cpu
, "ABORT;");
5838 cec_exception (cpu
, VEC_SIM_ABORT
);
5841 else if (reg
== 4 && fn
== 3)
5843 TRACE_INSN (cpu
, "HLT;");
5844 cec_exception (cpu
, VEC_SIM_HLT
);
5847 else if (reg
== 5 && fn
== 3)
5848 unhandled_instruction (cpu
, "DBGHALT");
5849 else if (reg
== 6 && fn
== 3)
5850 unhandled_instruction (cpu
, "DBGCMPLX (dregs)");
5851 else if (reg
== 7 && fn
== 3)
5852 unhandled_instruction (cpu
, "DBG");
5853 else if (grp
== 0 && fn
== 2)
5855 TRACE_INSN (cpu
, "OUTC R%i;", reg
);
5856 outc (cpu
, DREG (reg
));
5860 const char *reg_name
= get_allreg_name (grp
, reg
);
5861 TRACE_INSN (cpu
, "DBG %s;", reg_name
);
5862 sim_io_printf (sd
, "DBG : %s = 0x%08x\n", reg_name
,
5863 reg_read (cpu
, grp
, reg
));
5866 unhandled_instruction (cpu
, "PRNT allregs");
5868 illegal_instruction (cpu
);
5872 decode_psedoOChar_0 (SIM_CPU
*cpu
, bu16 iw0
)
5875 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5876 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |.ch............................|
5877 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5878 int ch
= ((iw0
>> PseudoChr_ch_bits
) & PseudoChr_ch_mask
);
5880 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_psedoOChar
);
5881 TRACE_EXTRACT (cpu
, "%s: ch:%#x", __func__
, ch
);
5882 TRACE_INSN (cpu
, "OUTC %#x;", ch
);
5888 decode_psedodbg_assert_0 (SIM_CPU
*cpu
, bu16 iw0
, bu16 iw1
, bu32 pc
)
5891 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5892 | 1 | 1 | 1 | 1 | 0 | - | - | - | dbgop |.grp.......|.regtest...|
5893 |.expected......................................................|
5894 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5895 SIM_DESC sd
= CPU_STATE (cpu
);
5896 int expected
= ((iw1
>> PseudoDbg_Assert_expected_bits
) & PseudoDbg_Assert_expected_mask
);
5897 int dbgop
= ((iw0
>> (PseudoDbg_Assert_dbgop_bits
- 16)) & PseudoDbg_Assert_dbgop_mask
);
5898 int grp
= ((iw0
>> (PseudoDbg_Assert_grp_bits
- 16)) & PseudoDbg_Assert_grp_mask
);
5899 int regtest
= ((iw0
>> (PseudoDbg_Assert_regtest_bits
- 16)) & PseudoDbg_Assert_regtest_mask
);
5901 bu32 val
= reg_read (cpu
, grp
, regtest
);
5902 const char *reg_name
= get_allreg_name (grp
, regtest
);
5903 const char *dbg_name
, *dbg_appd
;
5905 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_psedodbg_assert
);
5906 TRACE_EXTRACT (cpu
, "%s: dbgop:%i grp:%i regtest:%i expected:%#x",
5907 __func__
, dbgop
, grp
, regtest
, expected
);
5909 if (dbgop
== 0 || dbgop
== 2)
5911 dbg_name
= dbgop
== 0 ? "DBGA" : "DBGAL";
5912 dbg_appd
= dbgop
== 0 ? ".L" : "";
5915 else if (dbgop
== 1 || dbgop
== 3)
5917 dbg_name
= dbgop
== 1 ? "DBGA" : "DBGAH";
5918 dbg_appd
= dbgop
== 1 ? ".H" : "";
5922 illegal_instruction (cpu
);
5924 TRACE_INSN (cpu
, "%s (%s%s, 0x%x);", dbg_name
, reg_name
, dbg_appd
, expected
);
5925 if (actual
!= expected
)
5927 sim_io_printf (sd
, "FAIL at %#x: %s (%s%s, 0x%04x), actual value %#x\n",
5928 pc
, dbg_name
, reg_name
, dbg_appd
, expected
, actual
);
5929 cec_exception (cpu
, VEC_SIM_DBGA
);
5935 _interp_insn_bfin (SIM_CPU
*cpu
, bu32 pc
)
5940 BFIN_CPU_STATE
.multi_pc
= pc
;
5942 if ((iw0
& 0xc000) != 0xc000)
5944 /* 16-bit opcode. */
5947 INSN_LEN
= insn_len
;
5949 TRACE_EXTRACT (cpu
, "%s: iw0:%#x", __func__
, iw0
);
5950 if ((iw0
& 0xFF00) == 0x0000)
5951 decode_ProgCtrl_0 (cpu
, iw0
, pc
);
5952 else if ((iw0
& 0xFFC0) == 0x0240)
5953 decode_CaCTRL_0 (cpu
, iw0
);
5954 else if ((iw0
& 0xFF80) == 0x0100)
5955 decode_PushPopReg_0 (cpu
, iw0
);
5956 else if ((iw0
& 0xFE00) == 0x0400)
5957 decode_PushPopMultiple_0 (cpu
, iw0
);
5958 else if ((iw0
& 0xFE00) == 0x0600)
5959 decode_ccMV_0 (cpu
, iw0
);
5960 else if ((iw0
& 0xF800) == 0x0800)
5961 decode_CCflag_0 (cpu
, iw0
);
5962 else if ((iw0
& 0xFFE0) == 0x0200)
5963 decode_CC2dreg_0 (cpu
, iw0
);
5964 else if ((iw0
& 0xFF00) == 0x0300)
5965 decode_CC2stat_0 (cpu
, iw0
);
5966 else if ((iw0
& 0xF000) == 0x1000)
5967 decode_BRCC_0 (cpu
, iw0
, pc
);
5968 else if ((iw0
& 0xF000) == 0x2000)
5969 decode_UJUMP_0 (cpu
, iw0
, pc
);
5970 else if ((iw0
& 0xF000) == 0x3000)
5971 decode_REGMV_0 (cpu
, iw0
);
5972 else if ((iw0
& 0xFC00) == 0x4000)
5973 decode_ALU2op_0 (cpu
, iw0
);
5974 else if ((iw0
& 0xFE00) == 0x4400)
5975 decode_PTR2op_0 (cpu
, iw0
);
5976 else if ((iw0
& 0xF800) == 0x4800)
5977 decode_LOGI2op_0 (cpu
, iw0
);
5978 else if ((iw0
& 0xF000) == 0x5000)
5979 decode_COMP3op_0 (cpu
, iw0
);
5980 else if ((iw0
& 0xF800) == 0x6000)
5981 decode_COMPI2opD_0 (cpu
, iw0
);
5982 else if ((iw0
& 0xF800) == 0x6800)
5983 decode_COMPI2opP_0 (cpu
, iw0
);
5984 else if ((iw0
& 0xF000) == 0x8000)
5985 decode_LDSTpmod_0 (cpu
, iw0
);
5986 else if ((iw0
& 0xFF60) == 0x9E60)
5987 decode_dagMODim_0 (cpu
, iw0
);
5988 else if ((iw0
& 0xFFF0) == 0x9F60)
5989 decode_dagMODik_0 (cpu
, iw0
);
5990 else if ((iw0
& 0xFC00) == 0x9C00)
5991 decode_dspLDST_0 (cpu
, iw0
);
5992 else if ((iw0
& 0xF000) == 0x9000)
5993 decode_LDST_0 (cpu
, iw0
);
5994 else if ((iw0
& 0xFC00) == 0xB800)
5995 decode_LDSTiiFP_0 (cpu
, iw0
);
5996 else if ((iw0
& 0xE000) == 0xA000)
5997 decode_LDSTii_0 (cpu
, iw0
);
6000 TRACE_EXTRACT (cpu
, "%s: no matching 16-bit pattern", __func__
);
6001 illegal_instruction (cpu
);
6006 /* Grab the next 16 bits to determine if it's a 32-bit or 64-bit opcode. */
6007 iw1
= IFETCH (pc
+ 2);
6008 if ((iw0
& BIT_MULTI_INS
) && (iw0
& 0xe800) != 0xe800 /* not linkage */)
6010 SIM_DESC sd
= CPU_STATE (cpu
);
6011 trace_prefix (sd
, cpu
, NULL_CIA
, pc
, TRACE_LINENUM_P (cpu
),
6012 NULL
, 0, "|| %#"PRIx64
, sim_events_time (sd
));
6018 TRACE_EXTRACT (cpu
, "%s: iw0:%#x iw1:%#x insn_len:%i", __func__
,
6019 iw0
, iw1
, insn_len
);
6021 /* Only cache on first run through (in case of parallel insns). */
6023 INSN_LEN
= insn_len
;
6025 if ((iw0
& 0xf7ff) == 0xc003 && (iw1
& 0xfe00) == 0x1800)
6027 PROFILE_COUNT_INSN (cpu
, pc
, BFIN_INSN_dsp32mac
);
6028 TRACE_INSN (cpu
, "MNOP;");
6030 else if (((iw0
& 0xFF80) == 0xE080) && ((iw1
& 0x0C00) == 0x0000))
6031 decode_LoopSetup_0 (cpu
, iw0
, iw1
, pc
);
6032 else if (((iw0
& 0xFF00) == 0xE100) && ((iw1
& 0x0000) == 0x0000))
6033 decode_LDIMMhalf_0 (cpu
, iw0
, iw1
);
6034 else if (((iw0
& 0xFE00) == 0xE200) && ((iw1
& 0x0000) == 0x0000))
6035 decode_CALLa_0 (cpu
, iw0
, iw1
, pc
);
6036 else if (((iw0
& 0xFC00) == 0xE400) && ((iw1
& 0x0000) == 0x0000))
6037 decode_LDSTidxI_0 (cpu
, iw0
, iw1
);
6038 else if (((iw0
& 0xFFFE) == 0xE800) && ((iw1
& 0x0000) == 0x0000))
6039 decode_linkage_0 (cpu
, iw0
, iw1
);
6040 else if (((iw0
& 0xF600) == 0xC000) && ((iw1
& 0x0000) == 0x0000))
6041 decode_dsp32mac_0 (cpu
, iw0
, iw1
);
6042 else if (((iw0
& 0xF600) == 0xC200) && ((iw1
& 0x0000) == 0x0000))
6043 decode_dsp32mult_0 (cpu
, iw0
, iw1
);
6044 else if (((iw0
& 0xF7C0) == 0xC400) && ((iw1
& 0x0000) == 0x0000))
6045 decode_dsp32alu_0 (cpu
, iw0
, iw1
);
6046 else if (((iw0
& 0xF7E0) == 0xC600) && ((iw1
& 0x01C0) == 0x0000))
6047 decode_dsp32shift_0 (cpu
, iw0
, iw1
);
6048 else if (((iw0
& 0xF7E0) == 0xC680) && ((iw1
& 0x0000) == 0x0000))
6049 decode_dsp32shiftimm_0 (cpu
, iw0
, iw1
);
6050 else if ((iw0
& 0xFF00) == 0xF800)
6051 decode_psedoDEBUG_0 (cpu
, iw0
), insn_len
= 2;
6052 else if ((iw0
& 0xFF00) == 0xF900)
6053 decode_psedoOChar_0 (cpu
, iw0
), insn_len
= 2;
6054 else if (((iw0
& 0xFF00) == 0xF000) && ((iw1
& 0x0000) == 0x0000))
6055 decode_psedodbg_assert_0 (cpu
, iw0
, iw1
, pc
);
6058 TRACE_EXTRACT (cpu
, "%s: no matching 32-bit pattern", __func__
);
6059 illegal_instruction (cpu
);
6066 interp_insn_bfin (SIM_CPU
*cpu
, bu32 pc
)
6071 BFIN_CPU_STATE
.n_stores
= 0;
6072 DIS_ALGN_EXPT
&= ~1;
6076 insn_len
= _interp_insn_bfin (cpu
, pc
);
6078 /* Proper display of multiple issue instructions. */
6081 _interp_insn_bfin (cpu
, pc
+ 4);
6082 _interp_insn_bfin (cpu
, pc
+ 6);
6084 for (i
= 0; i
< BFIN_CPU_STATE
.n_stores
; i
++)
6086 bu32
*addr
= BFIN_CPU_STATE
.stores
[i
].addr
;
6087 *addr
= BFIN_CPU_STATE
.stores
[i
].val
;
6088 TRACE_REGISTER (cpu
, "dequeuing write %s = %#x",
6089 get_store_name (cpu
, addr
), *addr
);
6092 cycles_inc (cpu
, CYCLE_DELAY
);
6094 /* Set back to zero in case a pending CEC event occurs
6095 after this this insn. */