]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/bfin/bfin-sim.c
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / sim / bfin / bfin-sim.c
1 /* Simulator for Analog Devices Blackfin processors.
2
3 Copyright (C) 2005-2024 Free Software Foundation, Inc.
4 Contributed by Analog Devices, Inc.
5
6 This file is part of simulators.
7
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.
12
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.
17
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/>. */
20
21 /* This must come before any other includes. */
22 #include "defs.h"
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <inttypes.h>
28
29 #include "ansidecl.h"
30 #include "opcode/bfin.h"
31 #include "sim-main.h"
32 #include "arch.h"
33 #include "bfin-sim.h"
34 #include "dv-bfin_cec.h"
35 #include "dv-bfin_mmu.h"
36
37 #define HOST_LONG_WORD_SIZE (sizeof (long) * 8)
38
39 #define SIGNEXTEND(v, n) \
40 (((bs32)(v) << (HOST_LONG_WORD_SIZE - (n))) >> (HOST_LONG_WORD_SIZE - (n)))
41
42 static ATTRIBUTE_NORETURN void
43 illegal_instruction (SIM_CPU *cpu)
44 {
45 TRACE_INSN (cpu, "ILLEGAL INSTRUCTION");
46 while (1)
47 cec_exception (cpu, VEC_UNDEF_I);
48 }
49
50 static ATTRIBUTE_NORETURN void
51 illegal_instruction_combination (SIM_CPU *cpu)
52 {
53 TRACE_INSN (cpu, "ILLEGAL INSTRUCTION COMBINATION");
54 while (1)
55 cec_exception (cpu, VEC_ILGAL_I);
56 }
57
58 static ATTRIBUTE_NORETURN void
59 illegal_instruction_or_combination (SIM_CPU *cpu)
60 {
61 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
62 illegal_instruction_combination (cpu);
63 else
64 illegal_instruction (cpu);
65 }
66
67 static ATTRIBUTE_NORETURN void
68 unhandled_instruction (SIM_CPU *cpu, const char *insn)
69 {
70 SIM_DESC sd = CPU_STATE (cpu);
71 bu16 iw0, iw1;
72 bu32 iw2;
73
74 TRACE_EVENTS (cpu, "unhandled instruction");
75
76 iw0 = IFETCH (PCREG);
77 iw1 = IFETCH (PCREG + 2);
78 iw2 = ((bu32)iw0 << 16) | iw1;
79
80 sim_io_eprintf (sd, "Unhandled instruction at 0x%08x (%s opcode 0x", PCREG, insn);
81 if ((iw0 & 0xc000) == 0xc000)
82 sim_io_eprintf (sd, "%08x", iw2);
83 else
84 sim_io_eprintf (sd, "%04x", iw0);
85
86 sim_io_eprintf (sd, ") ... aborting\n");
87
88 illegal_instruction (cpu);
89 }
90
91 static const char * const astat_names[] =
92 {
93 [ 0] = "AZ",
94 [ 1] = "AN",
95 [ 2] = "AC0_COPY",
96 [ 3] = "V_COPY",
97 [ 4] = "ASTAT_4",
98 [ 5] = "CC",
99 [ 6] = "AQ",
100 [ 7] = "ASTAT_7",
101 [ 8] = "RND_MOD",
102 [ 9] = "ASTAT_9",
103 [10] = "ASTAT_10",
104 [11] = "ASTAT_11",
105 [12] = "AC0",
106 [13] = "AC1",
107 [14] = "ASTAT_14",
108 [15] = "ASTAT_15",
109 [16] = "AV0",
110 [17] = "AV0S",
111 [18] = "AV1",
112 [19] = "AV1S",
113 [20] = "ASTAT_20",
114 [21] = "ASTAT_21",
115 [22] = "ASTAT_22",
116 [23] = "ASTAT_23",
117 [24] = "V",
118 [25] = "VS",
119 [26] = "ASTAT_26",
120 [27] = "ASTAT_27",
121 [28] = "ASTAT_28",
122 [29] = "ASTAT_29",
123 [30] = "ASTAT_30",
124 [31] = "ASTAT_31",
125 };
126
127 typedef enum
128 {
129 c_0, c_1, c_4, c_2, c_uimm2, c_uimm3, c_imm3, c_pcrel4,
130 c_imm4, c_uimm4s4, c_uimm4s4d, c_uimm4, c_uimm4s2, c_negimm5s4, c_imm5,
131 c_imm5d, c_uimm5, c_imm6, c_imm7, c_imm7d, c_imm8, c_uimm8, c_pcrel8,
132 c_uimm8s4, c_pcrel8s4, c_lppcrel10, c_pcrel10, c_pcrel12, c_imm16s4,
133 c_luimm16, c_imm16, c_imm16d, c_huimm16, c_rimm16, c_imm16s2, c_uimm16s4,
134 c_uimm16s4d, c_uimm16, c_pcrel24, c_uimm32, c_imm32, c_huimm32, c_huimm32e,
135 } const_forms_t;
136
137 static const struct
138 {
139 const char *name;
140 const int nbits;
141 const char reloc;
142 const char issigned;
143 const char pcrel;
144 const char scale;
145 const char offset;
146 const char negative;
147 const char positive;
148 const char decimal;
149 const char leading;
150 const char exact;
151 } constant_formats[] =
152 {
153 { "0", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
154 { "1", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
155 { "4", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
156 { "2", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
157 { "uimm2", 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
158 { "uimm3", 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
159 { "imm3", 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
160 { "pcrel4", 4, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0},
161 { "imm4", 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
162 { "uimm4s4", 4, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0},
163 { "uimm4s4d", 4, 0, 0, 0, 2, 0, 0, 1, 1, 0, 0},
164 { "uimm4", 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
165 { "uimm4s2", 4, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0},
166 { "negimm5s4", 5, 0, 1, 0, 2, 0, 1, 0, 0, 0, 0},
167 { "imm5", 5, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
168 { "imm5d", 5, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0},
169 { "uimm5", 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
170 { "imm6", 6, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
171 { "imm7", 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
172 { "imm7d", 7, 0, 1, 0, 0, 0, 0, 0, 1, 3, 0},
173 { "imm8", 8, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
174 { "uimm8", 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
175 { "pcrel8", 8, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0},
176 { "uimm8s4", 8, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0},
177 { "pcrel8s4", 8, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0},
178 { "lppcrel10", 10, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0},
179 { "pcrel10", 10, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
180 { "pcrel12", 12, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
181 { "imm16s4", 16, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0},
182 { "luimm16", 16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
183 { "imm16", 16, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
184 { "imm16d", 16, 0, 1, 0, 0, 0, 0, 0, 1, 3, 0},
185 { "huimm16", 16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
186 { "rimm16", 16, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0},
187 { "imm16s2", 16, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0},
188 { "uimm16s4", 16, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0},
189 { "uimm16s4d", 16, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0},
190 { "uimm16", 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
191 { "pcrel24", 24, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
192 { "uimm32", 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
193 { "imm32", 32, 0, 1, 0, 0, 0, 0, 0, 1, 3, 0},
194 { "huimm32", 32, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
195 { "huimm32e", 32, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
196 };
197
198 static const char *
199 fmtconst_str (const_forms_t cf, bs32 x, bu32 pc)
200 {
201 static char buf[60];
202
203 if (constant_formats[cf].reloc)
204 {
205 #if 0
206 bu32 ea = (((constant_formats[cf].pcrel ? SIGNEXTEND (x, constant_formats[cf].nbits)
207 : x) + constant_formats[cf].offset) << constant_formats[cf].scale);
208 if (constant_formats[cf].pcrel)
209 ea += pc;
210 if (outf->symbol_at_address_func (ea, outf) || !constant_formats[cf].exact)
211 {
212 outf->print_address_func (ea, outf);
213 return "";
214 }
215 else
216 #endif
217 {
218 sprintf (buf, "%#x", x);
219 return buf;
220 }
221 }
222
223 /* Negative constants have an implied sign bit. */
224 if (constant_formats[cf].negative)
225 {
226 int nb = constant_formats[cf].nbits + 1;
227
228 x = x | (1 << constant_formats[cf].nbits);
229 x = SIGNEXTEND (x, nb);
230 }
231 else
232 x = constant_formats[cf].issigned ? SIGNEXTEND (x, constant_formats[cf].nbits) : x;
233
234 if (constant_formats[cf].offset)
235 x += constant_formats[cf].offset;
236
237 if (constant_formats[cf].scale)
238 x <<= constant_formats[cf].scale;
239
240 if (constant_formats[cf].decimal)
241 sprintf (buf, "%*i", constant_formats[cf].leading, x);
242 else
243 {
244 if (constant_formats[cf].issigned && x < 0)
245 sprintf (buf, "-0x%x", abs (x));
246 else
247 sprintf (buf, "0x%x", x);
248 }
249
250 return buf;
251 }
252
253 static bu32
254 fmtconst_val (const_forms_t cf, bu32 x, bu32 pc)
255 {
256 if (0 && constant_formats[cf].reloc)
257 {
258 bu32 ea = (((constant_formats[cf].pcrel
259 ? (bu32)SIGNEXTEND (x, constant_formats[cf].nbits)
260 : x) + constant_formats[cf].offset)
261 << constant_formats[cf].scale);
262 if (constant_formats[cf].pcrel)
263 ea += pc;
264
265 return ea;
266 }
267
268 /* Negative constants have an implied sign bit. */
269 if (constant_formats[cf].negative)
270 {
271 int nb = constant_formats[cf].nbits + 1;
272 x = x | (1 << constant_formats[cf].nbits);
273 x = SIGNEXTEND (x, nb);
274 }
275 else if (constant_formats[cf].issigned)
276 x = SIGNEXTEND (x, constant_formats[cf].nbits);
277
278 x += constant_formats[cf].offset;
279 x <<= constant_formats[cf].scale;
280
281 return x;
282 }
283
284 #define uimm16s4(x) fmtconst_val (c_uimm16s4, x, 0)
285 #define uimm16s4_str(x) fmtconst_str (c_uimm16s4, x, 0)
286 #define uimm16s4d(x) fmtconst_val (c_uimm16s4d, x, 0)
287 #define pcrel4(x) fmtconst_val (c_pcrel4, x, pc)
288 #define pcrel8(x) fmtconst_val (c_pcrel8, x, pc)
289 #define pcrel8s4(x) fmtconst_val (c_pcrel8s4, x, pc)
290 #define pcrel10(x) fmtconst_val (c_pcrel10, x, pc)
291 #define pcrel12(x) fmtconst_val (c_pcrel12, x, pc)
292 #define negimm5s4(x) fmtconst_val (c_negimm5s4, x, 0)
293 #define negimm5s4_str(x) fmtconst_str (c_negimm5s4, x, 0)
294 #define rimm16(x) fmtconst_val (c_rimm16, x, 0)
295 #define huimm16(x) fmtconst_val (c_huimm16, x, 0)
296 #define imm16(x) fmtconst_val (c_imm16, x, 0)
297 #define imm16_str(x) fmtconst_str (c_imm16, x, 0)
298 #define imm16d(x) fmtconst_val (c_imm16d, x, 0)
299 #define uimm2(x) fmtconst_val (c_uimm2, x, 0)
300 #define uimm3(x) fmtconst_val (c_uimm3, x, 0)
301 #define uimm3_str(x) fmtconst_str (c_uimm3, x, 0)
302 #define luimm16(x) fmtconst_val (c_luimm16, x, 0)
303 #define luimm16_str(x) fmtconst_str (c_luimm16, x, 0)
304 #define uimm4(x) fmtconst_val (c_uimm4, x, 0)
305 #define uimm4_str(x) fmtconst_str (c_uimm4, x, 0)
306 #define uimm5(x) fmtconst_val (c_uimm5, x, 0)
307 #define uimm5_str(x) fmtconst_str (c_uimm5, x, 0)
308 #define imm16s2(x) fmtconst_val (c_imm16s2, x, 0)
309 #define imm16s2_str(x) fmtconst_str (c_imm16s2, x, 0)
310 #define uimm8(x) fmtconst_val (c_uimm8, x, 0)
311 #define imm16s4(x) fmtconst_val (c_imm16s4, x, 0)
312 #define imm16s4_str(x) fmtconst_str (c_imm16s4, x, 0)
313 #define uimm4s2(x) fmtconst_val (c_uimm4s2, x, 0)
314 #define uimm4s2_str(x) fmtconst_str (c_uimm4s2, x, 0)
315 #define uimm4s4(x) fmtconst_val (c_uimm4s4, x, 0)
316 #define uimm4s4_str(x) fmtconst_str (c_uimm4s4, x, 0)
317 #define uimm4s4d(x) fmtconst_val (c_uimm4s4d, x, 0)
318 #define lppcrel10(x) fmtconst_val (c_lppcrel10, x, pc)
319 #define imm3(x) fmtconst_val (c_imm3, x, 0)
320 #define imm3_str(x) fmtconst_str (c_imm3, x, 0)
321 #define imm4(x) fmtconst_val (c_imm4, x, 0)
322 #define uimm8s4(x) fmtconst_val (c_uimm8s4, x, 0)
323 #define imm5(x) fmtconst_val (c_imm5, x, 0)
324 #define imm5d(x) fmtconst_val (c_imm5d, x, 0)
325 #define imm6(x) fmtconst_val (c_imm6, x, 0)
326 #define imm7(x) fmtconst_val (c_imm7, x, 0)
327 #define imm7_str(x) fmtconst_str (c_imm7, x, 0)
328 #define imm7d(x) fmtconst_val (c_imm7d, x, 0)
329 #define imm8(x) fmtconst_val (c_imm8, x, 0)
330 #define pcrel24(x) fmtconst_val (c_pcrel24, x, pc)
331 #define pcrel24_str(x) fmtconst_str (c_pcrel24, x, pc)
332 #define uimm16(x) fmtconst_val (c_uimm16, x, 0)
333 #define uimm32(x) fmtconst_val (c_uimm32, x, 0)
334 #define imm32(x) fmtconst_val (c_imm32, x, 0)
335 #define huimm32(x) fmtconst_val (c_huimm32, x, 0)
336 #define huimm32e(x) fmtconst_val (c_huimm32e, x, 0)
337
338 /* Table C-4. Core Register Encoding Map. */
339 const char * const greg_names[] =
340 {
341 "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7",
342 "P0", "P1", "P2", "P3", "P4", "P5", "SP", "FP",
343 "I0", "I1", "I2", "I3", "M0", "M1", "M2", "M3",
344 "B0", "B1", "B2", "B3", "L0", "L1", "L2", "L3",
345 "A0.X", "A0.W", "A1.X", "A1.W", "<res>", "<res>", "ASTAT", "RETS",
346 "<res>", "<res>", "<res>", "<res>", "<res>", "<res>", "<res>", "<res>",
347 "LC0", "LT0", "LB0", "LC1", "LT1", "LB1", "CYCLES", "CYCLES2",
348 "USP", "SEQSTAT", "SYSCFG", "RETI", "RETX", "RETN", "RETE", "EMUDAT",
349 };
350 static const char *
351 get_allreg_name (int grp, int reg)
352 {
353 return greg_names[(grp << 3) | reg];
354 }
355 static const char *
356 get_preg_name (int reg)
357 {
358 return get_allreg_name (1, reg);
359 }
360
361 static bool
362 reg_is_reserved (int grp, int reg)
363 {
364 return (grp == 4 && (reg == 4 || reg == 5)) || (grp == 5);
365 }
366
367 static bu32 *
368 get_allreg (SIM_CPU *cpu, int grp, int reg)
369 {
370 int fullreg = (grp << 3) | reg;
371 /* REG_R0, REG_R1, REG_R2, REG_R3, REG_R4, REG_R5, REG_R6, REG_R7,
372 REG_P0, REG_P1, REG_P2, REG_P3, REG_P4, REG_P5, REG_SP, REG_FP,
373 REG_I0, REG_I1, REG_I2, REG_I3, REG_M0, REG_M1, REG_M2, REG_M3,
374 REG_B0, REG_B1, REG_B2, REG_B3, REG_L0, REG_L1, REG_L2, REG_L3,
375 REG_A0x, REG_A0w, REG_A1x, REG_A1w, , , REG_ASTAT, REG_RETS,
376 , , , , , , , ,
377 REG_LC0, REG_LT0, REG_LB0, REG_LC1, REG_LT1, REG_LB1, REG_CYCLES,
378 REG_CYCLES2,
379 REG_USP, REG_SEQSTAT, REG_SYSCFG, REG_RETI, REG_RETX, REG_RETN, REG_RETE,
380 REG_LASTREG */
381 switch (fullreg >> 2)
382 {
383 case 0: case 1: return &DREG (reg);
384 case 2: case 3: return &PREG (reg);
385 case 4: return &IREG (reg & 3);
386 case 5: return &MREG (reg & 3);
387 case 6: return &BREG (reg & 3);
388 case 7: return &LREG (reg & 3);
389 default:
390 switch (fullreg)
391 {
392 case 32: return &AXREG (0);
393 case 33: return &AWREG (0);
394 case 34: return &AXREG (1);
395 case 35: return &AWREG (1);
396 case 39: return &RETSREG;
397 case 48: return &LCREG (0);
398 case 49: return &LTREG (0);
399 case 50: return &LBREG (0);
400 case 51: return &LCREG (1);
401 case 52: return &LTREG (1);
402 case 53: return &LBREG (1);
403 case 54: return &CYCLESREG;
404 case 55: return &CYCLES2REG;
405 case 56: return &USPREG;
406 case 57: return &SEQSTATREG;
407 case 58: return &SYSCFGREG;
408 case 59: return &RETIREG;
409 case 60: return &RETXREG;
410 case 61: return &RETNREG;
411 case 62: return &RETEREG;
412 case 63: return &EMUDAT_INREG;
413 }
414 illegal_instruction (cpu);
415 }
416 }
417
418 static const char *
419 amod0 (int s0, int x0)
420 {
421 static const char * const mod0[] = {
422 "", " (S)", " (CO)", " (SCO)",
423 };
424 int i = s0 + (x0 << 1);
425
426 if (i < ARRAY_SIZE (mod0))
427 return mod0[i];
428 else
429 return "";
430 }
431
432 static const char *
433 amod0amod2 (int s0, int x0, int aop0)
434 {
435 static const char * const mod02[] = {
436 "", " (S)", " (CO)", " (SCO)",
437 "", "", "", "",
438 " (ASR)", " (S, ASR)", " (CO, ASR)", " (SCO, ASR)",
439 " (ASL)", " (S, ASL)", " (CO, ASL)", " (SCO, ASL)",
440 };
441 int i = s0 + (x0 << 1) + (aop0 << 2);
442
443 if (i < ARRAY_SIZE (mod02))
444 return mod02[i];
445 else
446 return "";
447 }
448
449 static const char *
450 amod1 (int s0, int x0)
451 {
452 static const char * const mod1[] = {
453 " (NS)", " (S)",
454 };
455 int i = s0 + (x0 << 1);
456
457 if (i < ARRAY_SIZE (mod1))
458 return mod1[i];
459 else
460 return "";
461 }
462
463 static const char *
464 mac_optmode (int mmod, int MM)
465 {
466 static const char * const omode[] = {
467 [(M_S2RND << 1) + 0] = " (S2RND)",
468 [(M_T << 1) + 0] = " (T)",
469 [(M_W32 << 1) + 0] = " (W32)",
470 [(M_FU << 1) + 0] = " (FU)",
471 [(M_TFU << 1) + 0] = " (TFU)",
472 [(M_IS << 1) + 0] = " (IS)",
473 [(M_ISS2 << 1) + 0] = " (ISS2)",
474 [(M_IH << 1) + 0] = " (IH)",
475 [(M_IU << 1) + 0] = " (IU)",
476 [(M_S2RND << 1) + 1] = " (M, S2RND)",
477 [(M_T << 1) + 1] = " (M, T)",
478 [(M_W32 << 1) + 1] = " (M, W32)",
479 [(M_FU << 1) + 1] = " (M, FU)",
480 [(M_TFU << 1) + 1] = " (M, TFU)",
481 [(M_IS << 1) + 1] = " (M, IS)",
482 [(M_ISS2 << 1) + 1] = " (M, ISS2)",
483 [(M_IH << 1) + 1] = " (M, IH)",
484 [(M_IU << 1) + 1] = " (M, IU)",
485 };
486 int i = MM + (mmod << 1);
487
488 if (i < ARRAY_SIZE (omode) && omode[i])
489 return omode[i];
490 else
491 return "";
492 }
493
494 static const char *
495 get_store_name (SIM_CPU *cpu, bu32 *p)
496 {
497 if (p >= &DREG (0) && p <= &CYCLESREG)
498 return greg_names[p - &DREG (0)];
499 else if (p == &AXREG (0))
500 return greg_names[4 * 8 + 0];
501 else if (p == &AWREG (0))
502 return greg_names[4 * 8 + 1];
503 else if (p == &AXREG (1))
504 return greg_names[4 * 8 + 2];
505 else if (p == &AWREG (1))
506 return greg_names[4 * 8 + 3];
507 else if (p == &ASTATREG (ac0))
508 return "ASTAT[ac0]";
509 else if (p == &ASTATREG (ac0_copy))
510 return "ASTAT[ac0_copy]";
511 else if (p == &ASTATREG (ac1))
512 return "ASTAT[ac1]";
513 else if (p == &ASTATREG (an))
514 return "ASTAT[an]";
515 else if (p == &ASTATREG (aq))
516 return "ASTAT[aq]";
517 else if (p == &ASTATREG (av0))
518 return "ASTAT[av0]";
519 else if (p == &ASTATREG (av0s))
520 return "ASTAT[av0s]";
521 else if (p == &ASTATREG (av1))
522 return "ASTAT[av1]";
523 else if (p == &ASTATREG (av1s))
524 return "ASTAT[av1s]";
525 else if (p == &ASTATREG (az))
526 return "ASTAT[az]";
527 else if (p == &ASTATREG (v))
528 return "ASTAT[v]";
529 else if (p == &ASTATREG (v_copy))
530 return "ASTAT[v_copy]";
531 else if (p == &ASTATREG (vs))
532 return "ASTAT[vs]";
533 else
534 {
535 /* Worry about this when we start to STORE() it. */
536 sim_io_eprintf (CPU_STATE (cpu), "STORE(): unknown register\n");
537 abort ();
538 }
539 }
540
541 static void
542 queue_store (SIM_CPU *cpu, bu32 *addr, bu32 val)
543 {
544 struct store *s = &BFIN_CPU_STATE.stores[BFIN_CPU_STATE.n_stores];
545 s->addr = addr;
546 s->val = val;
547 TRACE_REGISTER (cpu, "queuing write %s = %#x",
548 get_store_name (cpu, addr), val);
549 ++BFIN_CPU_STATE.n_stores;
550 }
551 #define STORE(X, Y) \
552 do { \
553 if (BFIN_CPU_STATE.n_stores == 20) abort (); \
554 queue_store (cpu, &(X), (Y)); \
555 } while (0)
556
557 static void
558 setflags_nz (SIM_CPU *cpu, bu32 val)
559 {
560 SET_ASTATREG (az, val == 0);
561 SET_ASTATREG (an, val >> 31);
562 }
563
564 static void
565 setflags_nz_2x16 (SIM_CPU *cpu, bu32 val)
566 {
567 SET_ASTATREG (an, (bs16)val < 0 || (bs16)(val >> 16) < 0);
568 SET_ASTATREG (az, (bs16)val == 0 || (bs16)(val >> 16) == 0);
569 }
570
571 static void
572 setflags_logical (SIM_CPU *cpu, bu32 val)
573 {
574 setflags_nz (cpu, val);
575 SET_ASTATREG (ac0, 0);
576 SET_ASTATREG (v, 0);
577 }
578
579 static bu32
580 add_brev (bu32 addend1, bu32 addend2)
581 {
582 bu32 mask, b, r;
583 int i, cy;
584
585 mask = 0x80000000;
586 r = 0;
587 cy = 0;
588
589 for (i = 31; i >= 0; --i)
590 {
591 b = ((addend1 & mask) >> i) + ((addend2 & mask) >> i);
592 b += cy;
593 cy = b >> 1;
594 b &= 1;
595 r |= b << i;
596 mask >>= 1;
597 }
598
599 return r;
600 }
601
602 /* This is a bit crazy, but we want to simulate the hardware behavior exactly
603 rather than worry about the circular buffers being used correctly. Which
604 isn't to say there isn't room for improvement here, just that we want to
605 be conservative. See also dagsub(). */
606 static bu32
607 dagadd (SIM_CPU *cpu, int dagno, bs32 M)
608 {
609 bu64 i = IREG (dagno);
610 bu64 l = LREG (dagno);
611 bu64 b = BREG (dagno);
612 bu64 m = (bu32)M;
613
614 bu64 LB, IM, IML;
615 bu32 im32, iml32, lb32, res;
616 bu64 msb, car;
617
618 /* A naïve implementation that mostly works:
619 res = i + m;
620 if (l && res >= b + l)
621 res -= l;
622 STORE (IREG (dagno), res);
623 */
624
625 msb = (bu64)1 << 31;
626 car = (bu64)1 << 32;
627
628 IM = i + m;
629 im32 = IM;
630 LB = l + b;
631 lb32 = LB;
632
633 if (M < 0)
634 {
635 IML = i + m + l;
636 iml32 = IML;
637 if ((i & msb) || (IM & car))
638 res = (im32 < b) ? iml32 : im32;
639 else
640 res = (im32 < b) ? im32 : iml32;
641 }
642 else
643 {
644 IML = i + m - l;
645 iml32 = IML;
646 if ((IM & car) == (LB & car))
647 res = (im32 < lb32) ? im32 : iml32;
648 else
649 res = (im32 < lb32) ? iml32 : im32;
650 }
651
652 STORE (IREG (dagno), res);
653 return res;
654 }
655
656 /* See dagadd() notes above. */
657 static bu32
658 dagsub (SIM_CPU *cpu, int dagno, bs32 M)
659 {
660 bu64 i = IREG (dagno);
661 bu64 l = LREG (dagno);
662 bu64 b = BREG (dagno);
663 bu64 m = (bu32)M;
664
665 bu64 mbar = (bu32)(~m + 1);
666 bu64 LB, IM, IML;
667 bu32 b32, im32, iml32, lb32, res;
668 bu64 msb, car;
669
670 /* A naïve implementation that mostly works:
671 res = i - m;
672 if (l && newi < b)
673 newi += l;
674 STORE (IREG (dagno), newi);
675 */
676
677 msb = (bu64)1 << 31;
678 car = (bu64)1 << 32;
679
680 IM = i + mbar;
681 im32 = IM;
682 LB = l + b;
683 lb32 = LB;
684
685 if (M < 0)
686 {
687 IML = i + mbar - l;
688 iml32 = IML;
689 if (!!((i & msb) && (IM & car)) == !!(LB & car))
690 res = (im32 < lb32) ? im32 : iml32;
691 else
692 res = (im32 < lb32) ? iml32 : im32;
693 }
694 else
695 {
696 IML = i + mbar + l;
697 iml32 = IML;
698 b32 = b;
699 if (M == 0 || IM & car)
700 res = (im32 < b32) ? iml32 : im32;
701 else
702 res = (im32 < b32) ? im32 : iml32;
703 }
704
705 STORE (IREG (dagno), res);
706 return res;
707 }
708
709 static bu40
710 ashiftrt (SIM_CPU *cpu, bu40 val, int cnt, int size)
711 {
712 int real_cnt = cnt > size ? size : cnt;
713 bu40 sgn = ~(((val & 0xFFFFFFFFFFull) >> (size - 1)) - 1);
714 int sgncnt = size - real_cnt;
715 if (sgncnt > 16)
716 sgn <<= 16, sgncnt -= 16;
717 sgn <<= sgncnt;
718 if (real_cnt > 16)
719 val >>= 16, real_cnt -= 16;
720 val >>= real_cnt;
721 val |= sgn;
722 SET_ASTATREG (an, val >> (size - 1));
723 SET_ASTATREG (az, val == 0);
724 if (size != 40)
725 SET_ASTATREG (v, 0);
726 return val;
727 }
728
729 static bu64
730 lshiftrt (SIM_CPU *cpu, bu64 val, int cnt, int size)
731 {
732 int real_cnt = cnt > size ? size : cnt;
733 if (real_cnt > 16)
734 val >>= 16, real_cnt -= 16;
735 val >>= real_cnt;
736 switch (size)
737 {
738 case 16:
739 val &= 0xFFFF;
740 break;
741 case 32:
742 val &= 0xFFFFFFFF;
743 break;
744 case 40:
745 val &= 0xFFFFFFFFFFull;
746 break;
747 default:
748 illegal_instruction (cpu);
749 break;
750 }
751 SET_ASTATREG (an, val >> (size - 1));
752 SET_ASTATREG (az, val == 0);
753 if (size != 40)
754 SET_ASTATREG (v, 0);
755 return val;
756 }
757
758 static bu64
759 lshift (SIM_CPU *cpu, bu64 val, int cnt, int size, bool saturate, bool overflow)
760 {
761 int v_i, real_cnt = cnt > size ? size : cnt;
762 bu64 sgn = ~((val >> (size - 1)) - 1);
763 int mask_cnt = size - 1;
764 bu64 masked, new_val = val;
765 bu64 mask = ~0;
766
767 mask <<= mask_cnt;
768 sgn <<= mask_cnt;
769 masked = val & mask;
770
771 if (real_cnt > 16)
772 new_val <<= 16, real_cnt -= 16;
773
774 new_val <<= real_cnt;
775
776 masked = new_val & mask;
777
778 /* If an operation would otherwise cause a positive value to overflow
779 and become negative, instead, saturation limits the result to the
780 maximum positive value for the size register being used.
781
782 Conversely, if an operation would otherwise cause a negative value
783 to overflow and become positive, saturation limits the result to the
784 maximum negative value for the register size.
785
786 However, it's a little more complex than looking at sign bits, we need
787 to see if we are shifting the sign information away... */
788 if (((val << cnt) >> size) == 0
789 || (((val << cnt) >> size) == ~((bu32)~0 << cnt)
790 && ((new_val >> (size - 1)) & 0x1)))
791 v_i = 0;
792 else
793 v_i = 1;
794
795 switch (size)
796 {
797 case 16:
798 new_val &= 0xFFFF;
799 if (saturate && (v_i || ((val >> (size - 1)) != (new_val >> (size - 1)))))
800 {
801 new_val = (val >> (size - 1)) == 0 ? 0x7fff : 0x8000;
802 v_i = 1;
803 }
804 break;
805 case 32:
806 new_val &= 0xFFFFFFFF;
807 masked &= 0xFFFFFFFF;
808 sgn &= 0xFFFFFFFF;
809 if (saturate
810 && (v_i
811 || (sgn != masked)
812 || (!sgn && new_val == 0 && val != 0)))
813 {
814 new_val = sgn == 0 ? 0x7fffffff : 0x80000000;
815 v_i = 1;
816 }
817 break;
818 case 40:
819 new_val &= 0xFFFFFFFFFFull;
820 masked &= 0xFFFFFFFFFFull;
821 break;
822 default:
823 illegal_instruction (cpu);
824 break;
825 }
826
827 SET_ASTATREG (an, new_val >> (size - 1));
828 SET_ASTATREG (az, new_val == 0);
829 if (size != 40)
830 {
831 SET_ASTATREG (v, overflow && v_i);
832 if (overflow && v_i)
833 SET_ASTATREG (vs, 1);
834 }
835
836 return new_val;
837 }
838
839 static bu32
840 algn (bu32 l, bu32 h, bu32 aln)
841 {
842 if (aln == 0)
843 return l;
844 else
845 return (l >> (8 * aln)) | (h << (32 - 8 * aln));
846 }
847
848 static bu32
849 saturate_s16 (bu64 val, bu32 *overflow)
850 {
851 if ((bs64)val < -0x8000ll)
852 {
853 if (overflow)
854 *overflow = 1;
855 return 0x8000;
856 }
857 if ((bs64)val > 0x7fff)
858 {
859 if (overflow)
860 *overflow = 1;
861 return 0x7fff;
862 }
863 return val & 0xffff;
864 }
865
866 static bu40
867 rot40 (bu40 val, int shift, bu32 *cc)
868 {
869 const int nbits = 40;
870 bu40 ret;
871
872 shift = CLAMP (shift, -nbits, nbits);
873 if (shift == 0)
874 return val;
875
876 /* Reduce everything to rotate left. */
877 if (shift < 0)
878 shift += nbits + 1;
879
880 ret = shift == nbits ? 0 : val << shift;
881 ret |= shift == 1 ? 0 : val >> ((nbits + 1) - shift);
882 ret |= (bu40)*cc << (shift - 1);
883 *cc = (val >> (nbits - shift)) & 1;
884
885 return ret;
886 }
887
888 static bu32
889 rot32 (bu32 val, int shift, bu32 *cc)
890 {
891 const int nbits = 32;
892 bu32 ret;
893
894 shift = CLAMP (shift, -nbits, nbits);
895 if (shift == 0)
896 return val;
897
898 /* Reduce everything to rotate left. */
899 if (shift < 0)
900 shift += nbits + 1;
901
902 ret = shift == nbits ? 0 : val << shift;
903 ret |= shift == 1 ? 0 : val >> ((nbits + 1) - shift);
904 ret |= (bu32)*cc << (shift - 1);
905 *cc = (val >> (nbits - shift)) & 1;
906
907 return ret;
908 }
909
910 static bu32
911 add32 (SIM_CPU *cpu, bu32 a, bu32 b, int carry, int sat)
912 {
913 int flgs = (a >> 31) & 1;
914 int flgo = (b >> 31) & 1;
915 bu32 v = a + b;
916 int flgn = (v >> 31) & 1;
917 int overflow = (flgs ^ flgn) & (flgo ^ flgn);
918
919 if (sat && overflow)
920 {
921 v = (bu32)1 << 31;
922 if (flgn)
923 v -= 1;
924 flgn = (v >> 31) & 1;
925 }
926
927 SET_ASTATREG (an, flgn);
928 if (overflow)
929 SET_ASTATREG (vs, 1);
930 SET_ASTATREG (v, overflow);
931 ASTATREG (v_internal) |= overflow;
932 SET_ASTATREG (az, v == 0);
933 if (carry)
934 SET_ASTATREG (ac0, ~a < b);
935
936 return v;
937 }
938
939 static bu32
940 sub32 (SIM_CPU *cpu, bu32 a, bu32 b, int carry, int sat, int parallel)
941 {
942 int flgs = (a >> 31) & 1;
943 int flgo = (b >> 31) & 1;
944 bu32 v = a - b;
945 int flgn = (v >> 31) & 1;
946 int overflow = (flgs ^ flgo) & (flgn ^ flgs);
947
948 if (sat && overflow)
949 {
950 v = (bu32)1 << 31;
951 if (flgn)
952 v -= 1;
953 flgn = (v >> 31) & 1;
954 }
955
956 if (!parallel || flgn)
957 SET_ASTATREG (an, flgn);
958 if (overflow)
959 SET_ASTATREG (vs, 1);
960 if (!parallel || overflow)
961 SET_ASTATREG (v, overflow);
962 if (!parallel || overflow)
963 ASTATREG (v_internal) |= overflow;
964 if (!parallel || v == 0)
965 SET_ASTATREG (az, v == 0);
966 if (carry && (!parallel || b <= a))
967 SET_ASTATREG (ac0, b <= a);
968
969 return v;
970 }
971
972 static bu32
973 add16 (SIM_CPU *cpu, bu16 a, bu16 b, bu32 *carry, bu32 *overfl,
974 bu32 *zero, bu32 *neg, int sat, int scale)
975 {
976 int flgs = (a >> 15) & 1;
977 int flgo = (b >> 15) & 1;
978 bs64 v = (bs16)a + (bs16)b;
979 int flgn = (v >> 15) & 1;
980 int overflow = (flgs ^ flgn) & (flgo ^ flgn);
981
982 switch (scale)
983 {
984 case 0:
985 break;
986 case 2:
987 /* (ASR) */
988 v = (a >> 1) + (a & 0x8000) + (b >> 1) + (b & 0x8000)
989 + (((a & 1) + (b & 1)) >> 1);
990 v |= -(v & 0x8000);
991 break;
992 case 3:
993 /* (ASL) */
994 v = (v << 1);
995 break;
996 default:
997 illegal_instruction (cpu);
998 }
999
1000 flgn = (v >> 15) & 1;
1001 overflow = (flgs ^ flgn) & (flgo ^ flgn);
1002
1003 if (v > (bs64)0xffff)
1004 overflow = 1;
1005
1006 if (sat)
1007 v = saturate_s16 (v, 0);
1008
1009 if (neg)
1010 *neg |= (v >> 15) & 1;
1011 if (overfl)
1012 *overfl |= overflow;
1013 if (zero)
1014 *zero |= (v & 0xFFFF) == 0;
1015 if (carry)
1016 *carry |= ((bu16)~a < (bu16)b);
1017
1018 return v & 0xffff;
1019 }
1020
1021 static bu32
1022 sub16 (SIM_CPU *cpu, bu16 a, bu16 b, bu32 *carry, bu32 *overfl,
1023 bu32 *zero, bu32 *neg, int sat, int scale)
1024 {
1025 int flgs = (a >> 15) & 1;
1026 int flgo = (b >> 15) & 1;
1027 bs64 v = (bs16)a - (bs16)b;
1028 int flgn = (v >> 15) & 1;
1029 int overflow = (flgs ^ flgo) & (flgn ^ flgs);
1030
1031 switch (scale)
1032 {
1033 case 0:
1034 break;
1035 case 2:
1036 /* (ASR) */
1037 if (sat)
1038 v = ((a >> 1) + (a & 0x8000)) - ( (b >> 1) + (b & 0x8000))
1039 + (((a & 1)-(b & 1)));
1040 else
1041 {
1042 v = ((v & 0xFFFF) >> 1);
1043 if ((!flgs & !flgo & flgn)
1044 || (flgs & !flgo & !flgn)
1045 || (flgs & flgo & flgn)
1046 || (flgs & !flgo & flgn))
1047 v |= 0x8000;
1048 }
1049 v |= -(v & 0x8000);
1050 flgn = (v >> 15) & 1;
1051 overflow = (flgs ^ flgo) & (flgn ^ flgs);
1052 break;
1053 case 3:
1054 /* (ASL) */
1055 v <<= 1;
1056 if (v > (bs64)0x7fff || v < (bs64)-0xffff)
1057 overflow = 1;
1058 break;
1059 default:
1060 illegal_instruction (cpu);
1061 }
1062
1063 if (sat)
1064 {
1065 v = saturate_s16 (v, 0);
1066 }
1067 if (neg)
1068 *neg |= (v >> 15) & 1;
1069 if (zero)
1070 *zero |= (v & 0xFFFF) == 0;
1071 if (overfl)
1072 *overfl |= overflow;
1073 if (carry)
1074 *carry |= (bu16)b <= (bu16)a;
1075 return v;
1076 }
1077
1078 static bu32
1079 min32 (SIM_CPU *cpu, bu32 a, bu32 b)
1080 {
1081 int val = a;
1082 if ((bs32)a > (bs32)b)
1083 val = b;
1084 setflags_nz (cpu, val);
1085 SET_ASTATREG (v, 0);
1086 return val;
1087 }
1088
1089 static bu32
1090 max32 (SIM_CPU *cpu, bu32 a, bu32 b)
1091 {
1092 int val = a;
1093 if ((bs32)a < (bs32)b)
1094 val = b;
1095 setflags_nz (cpu, val);
1096 SET_ASTATREG (v, 0);
1097 return val;
1098 }
1099
1100 static bu32
1101 min2x16 (SIM_CPU *cpu, bu32 a, bu32 b)
1102 {
1103 int val = a;
1104 if ((bs16)a > (bs16)b)
1105 val = (val & 0xFFFF0000) | (b & 0xFFFF);
1106 if ((bs16)(a >> 16) > (bs16)(b >> 16))
1107 val = (val & 0xFFFF) | (b & 0xFFFF0000);
1108 setflags_nz_2x16 (cpu, val);
1109 SET_ASTATREG (v, 0);
1110 return val;
1111 }
1112
1113 static bu32
1114 max2x16 (SIM_CPU *cpu, bu32 a, bu32 b)
1115 {
1116 int val = a;
1117 if ((bs16)a < (bs16)b)
1118 val = (val & 0xFFFF0000) | (b & 0xFFFF);
1119 if ((bs16)(a >> 16) < (bs16)(b >> 16))
1120 val = (val & 0xFFFF) | (b & 0xFFFF0000);
1121 setflags_nz_2x16 (cpu, val);
1122 SET_ASTATREG (v, 0);
1123 return val;
1124 }
1125
1126 static bu32
1127 add_and_shift (SIM_CPU *cpu, bu32 a, bu32 b, int shift)
1128 {
1129 int v;
1130 ASTATREG (v_internal) = 0;
1131 v = add32 (cpu, a, b, 0, 0);
1132 while (shift-- > 0)
1133 {
1134 int x = (v >> 30) & 0x3;
1135 if (x == 1 || x == 2)
1136 ASTATREG (v_internal) = 1;
1137 v <<= 1;
1138 }
1139 SET_ASTATREG (az, v == 0);
1140 SET_ASTATREG (an, v & 0x80000000);
1141 SET_ASTATREG (v, ASTATREG (v_internal));
1142 if (ASTATREG (v))
1143 SET_ASTATREG (vs, 1);
1144 return v;
1145 }
1146
1147 static bu32
1148 xor_reduce (bu64 acc0, bu64 acc1)
1149 {
1150 int i;
1151 bu32 v = 0;
1152 for (i = 0; i < 40; ++i)
1153 {
1154 v ^= (acc0 & acc1 & 1);
1155 acc0 >>= 1;
1156 acc1 >>= 1;
1157 }
1158 return v;
1159 }
1160
1161 /* DIVS ( Dreg, Dreg ) ;
1162 Initialize for DIVQ. Set the AQ status bit based on the signs of
1163 the 32-bit dividend and the 16-bit divisor. Left shift the dividend
1164 one bit. Copy AQ into the dividend LSB. */
1165 static bu32
1166 divs (SIM_CPU *cpu, bu32 pquo, bu16 divisor)
1167 {
1168 bu16 r = pquo >> 16;
1169 int aq;
1170
1171 aq = (r ^ divisor) >> 15; /* Extract msb's and compute quotient bit. */
1172 SET_ASTATREG (aq, aq); /* Update global quotient state. */
1173
1174 pquo <<= 1;
1175 pquo |= aq;
1176 pquo = (pquo & 0x1FFFF) | (r << 17);
1177 return pquo;
1178 }
1179
1180 /* DIVQ ( Dreg, Dreg ) ;
1181 Based on AQ status bit, either add or subtract the divisor from
1182 the dividend. Then set the AQ status bit based on the MSBs of the
1183 32-bit dividend and the 16-bit divisor. Left shift the dividend one
1184 bit. Copy the logical inverse of AQ into the dividend LSB. */
1185 static bu32
1186 divq (SIM_CPU *cpu, bu32 pquo, bu16 divisor)
1187 {
1188 unsigned short af = pquo >> 16;
1189 unsigned short r;
1190 int aq;
1191
1192 if (ASTATREG (aq))
1193 r = divisor + af;
1194 else
1195 r = af - divisor;
1196
1197 aq = (r ^ divisor) >> 15; /* Extract msb's and compute quotient bit. */
1198 SET_ASTATREG (aq, aq); /* Update global quotient state. */
1199
1200 pquo <<= 1;
1201 pquo |= !aq;
1202 pquo = (pquo & 0x1FFFF) | (r << 17);
1203 return pquo;
1204 }
1205
1206 /* ONES ( Dreg ) ;
1207 Count the number of bits set to 1 in the 32bit value. */
1208 static bu32
1209 ones (bu32 val)
1210 {
1211 bu32 i;
1212 bu32 ret;
1213
1214 ret = 0;
1215 for (i = 0; i < 32; ++i)
1216 ret += !!(val & (1 << i));
1217
1218 return ret;
1219 }
1220
1221 static void
1222 reg_check_sup (SIM_CPU *cpu, int grp, int reg)
1223 {
1224 if (grp == 7)
1225 cec_require_supervisor (cpu);
1226 }
1227
1228 static void
1229 reg_write (SIM_CPU *cpu, int grp, int reg, bu32 value)
1230 {
1231 bu32 *whichreg;
1232
1233 /* ASTAT is special! */
1234 if (grp == 4 && reg == 6)
1235 {
1236 SET_ASTAT (value);
1237 return;
1238 }
1239
1240 /* Check supervisor after get_allreg() so exception order is correct. */
1241 whichreg = get_allreg (cpu, grp, reg);
1242 reg_check_sup (cpu, grp, reg);
1243
1244 if (whichreg == &CYCLES2REG)
1245 /* Writes to CYCLES2 goes to the shadow. */
1246 whichreg = &CYCLES2SHDREG;
1247 else if (whichreg == &SEQSTATREG)
1248 /* Register is read only -- discard writes. */
1249 return;
1250 else if (whichreg == &EMUDAT_INREG)
1251 /* Writes to EMUDAT goes to the output. */
1252 whichreg = &EMUDAT_OUTREG;
1253 else if (whichreg == &LTREG (0) || whichreg == &LTREG (1))
1254 /* Writes to LT clears LSB automatically. */
1255 value &= ~0x1;
1256 else if (whichreg == &AXREG (0) || whichreg == &AXREG (1))
1257 value &= 0xFF;
1258
1259 TRACE_REGISTER (cpu, "wrote %s = %#x", get_allreg_name (grp, reg), value);
1260
1261 *whichreg = value;
1262 }
1263
1264 static bu32
1265 reg_read (SIM_CPU *cpu, int grp, int reg)
1266 {
1267 bu32 *whichreg;
1268 bu32 value;
1269
1270 /* ASTAT is special! */
1271 if (grp == 4 && reg == 6)
1272 return ASTAT;
1273
1274 /* Check supervisor after get_allreg() so exception order is correct. */
1275 whichreg = get_allreg (cpu, grp, reg);
1276 reg_check_sup (cpu, grp, reg);
1277
1278 value = *whichreg;
1279
1280 if (whichreg == &CYCLESREG)
1281 /* Reads of CYCLES reloads CYCLES2 from the shadow. */
1282 SET_CYCLES2REG (CYCLES2SHDREG);
1283 else if ((whichreg == &AXREG (1) || whichreg == &AXREG (0)) && (value & 0x80))
1284 /* Sign extend if necessary. */
1285 value |= 0xFFFFFF00;
1286
1287 return value;
1288 }
1289
1290 static bu64
1291 get_extended_cycles (SIM_CPU *cpu)
1292 {
1293 return ((bu64)CYCLES2SHDREG << 32) | CYCLESREG;
1294 }
1295
1296 /* We can't re-use sim_events_time() because the CYCLES registers may be
1297 written/cleared/reset/stopped/started at any time by software. */
1298 static void
1299 cycles_inc (SIM_CPU *cpu, bu32 inc)
1300 {
1301 bu64 cycles;
1302 bu32 cycles2;
1303
1304 if (!(SYSCFGREG & SYSCFG_CCEN))
1305 return;
1306
1307 cycles = get_extended_cycles (cpu) + inc;
1308 SET_CYCLESREG (cycles);
1309 cycles2 = cycles >> 32;
1310 if (CYCLES2SHDREG != cycles2)
1311 SET_CYCLES2SHDREG (cycles2);
1312 }
1313
1314 static bu64
1315 get_unextended_acc (SIM_CPU *cpu, int which)
1316 {
1317 return ((bu64)(AXREG (which) & 0xff) << 32) | AWREG (which);
1318 }
1319
1320 static bu64
1321 get_extended_acc (SIM_CPU *cpu, int which)
1322 {
1323 bu64 acc = AXREG (which);
1324 /* Sign extend accumulator values before adding. */
1325 if (acc & 0x80)
1326 acc |= -0x80;
1327 else
1328 acc &= 0xFF;
1329 acc <<= 32;
1330 acc |= AWREG (which);
1331 return acc;
1332 }
1333
1334 /* Perform a multiplication of D registers SRC0 and SRC1, sign- or
1335 zero-extending the result to 64 bit. H0 and H1 determine whether the
1336 high part or the low part of the source registers is used. Store 1 in
1337 *PSAT if saturation occurs, 0 otherwise. */
1338 static bu64
1339 decode_multfunc (SIM_CPU *cpu, int h0, int h1, int src0, int src1, int mmod,
1340 int MM, bu32 *psat)
1341 {
1342 bu32 s0 = DREG (src0), s1 = DREG (src1);
1343 bu32 sgn0, sgn1;
1344 bu32 val;
1345 bu64 val1;
1346
1347 if (h0)
1348 s0 >>= 16;
1349
1350 if (h1)
1351 s1 >>= 16;
1352
1353 s0 &= 0xffff;
1354 s1 &= 0xffff;
1355
1356 sgn0 = -(s0 & 0x8000);
1357 sgn1 = -(s1 & 0x8000);
1358
1359 if (MM)
1360 s0 |= sgn0;
1361 else
1362 switch (mmod)
1363 {
1364 case 0:
1365 case M_S2RND:
1366 case M_T:
1367 case M_IS:
1368 case M_ISS2:
1369 case M_IH:
1370 case M_W32:
1371 s0 |= sgn0;
1372 s1 |= sgn1;
1373 break;
1374 case M_FU:
1375 case M_IU:
1376 case M_TFU:
1377 break;
1378 default:
1379 illegal_instruction (cpu);
1380 }
1381
1382 val = s0 * s1;
1383 /* Perform shift correction if appropriate for the mode. */
1384 *psat = 0;
1385 if (!MM && (mmod == 0 || mmod == M_T || mmod == M_S2RND || mmod == M_W32))
1386 {
1387 if (val == 0x40000000)
1388 {
1389 if (mmod == M_W32)
1390 val = 0x7fffffff;
1391 else
1392 val = 0x80000000;
1393 *psat = 1;
1394 }
1395 else
1396 val <<= 1;
1397 }
1398 val1 = val;
1399
1400 /* In signed modes, sign extend. */
1401 if (is_macmod_signed (mmod) || MM)
1402 val1 |= -(val1 & 0x80000000);
1403
1404 if (*psat)
1405 val1 &= 0xFFFFFFFFull;
1406
1407 return val1;
1408 }
1409
1410 static bu40
1411 saturate_s40_astat (bu64 val, bu32 *v)
1412 {
1413 if ((bs64)val < -((bs64)1 << 39))
1414 {
1415 *v = 1;
1416 return -((bs64)1 << 39);
1417 }
1418 else if ((bs64)val > ((bs64)1 << 39) - 1)
1419 {
1420 *v = 1;
1421 return ((bu64)1 << 39) - 1;
1422 }
1423 *v = 0; /* No overflow. */
1424 return val;
1425 }
1426
1427 static bu40
1428 saturate_s40 (bu64 val)
1429 {
1430 bu32 v;
1431 return saturate_s40_astat (val, &v);
1432 }
1433
1434 static bu32
1435 saturate_s32 (bu64 val, bu32 *overflow)
1436 {
1437 if ((bs64)val < -0x80000000ll)
1438 {
1439 if (overflow)
1440 *overflow = 1;
1441 return 0x80000000;
1442 }
1443 if ((bs64)val > 0x7fffffff)
1444 {
1445 if (overflow)
1446 *overflow = 1;
1447 return 0x7fffffff;
1448 }
1449 return val;
1450 }
1451
1452 static bu32
1453 saturate_u32 (bu64 val, bu32 *overflow)
1454 {
1455 if (val > 0xffffffff)
1456 {
1457 if (overflow)
1458 *overflow = 1;
1459 return 0xffffffff;
1460 }
1461 return val;
1462 }
1463
1464 static bu32
1465 saturate_u16 (bu64 val, bu32 *overflow)
1466 {
1467 if (val > 0xffff)
1468 {
1469 if (overflow)
1470 *overflow = 1;
1471 return 0xffff;
1472 }
1473 return val;
1474 }
1475
1476 static bu64
1477 rnd16 (bu64 val)
1478 {
1479 bu64 sgnbits;
1480
1481 /* FIXME: Should honour rounding mode. */
1482 if ((val & 0xffff) > 0x8000
1483 || ((val & 0xffff) == 0x8000 && (val & 0x10000)))
1484 val += 0x8000;
1485
1486 sgnbits = val & 0xffff000000000000ull;
1487 val >>= 16;
1488 return val | sgnbits;
1489 }
1490
1491 static bu64
1492 trunc16 (bu64 val)
1493 {
1494 bu64 sgnbits = val & 0xffff000000000000ull;
1495 val >>= 16;
1496 return val | sgnbits;
1497 }
1498
1499 static int
1500 signbits (bu64 val, int size)
1501 {
1502 bu64 mask = (bu64)1 << (size - 1);
1503 bu64 bit = val & mask;
1504 int count = 0;
1505 for (;;)
1506 {
1507 mask >>= 1;
1508 bit >>= 1;
1509 if (mask == 0)
1510 break;
1511 if ((val & mask) != bit)
1512 break;
1513 count++;
1514 }
1515 if (size == 40)
1516 count -= 8;
1517
1518 return count;
1519 }
1520
1521 /* Extract a 16 or 32 bit value from a 64 bit multiplication result.
1522 These 64 bits must be sign- or zero-extended properly from the source
1523 we want to extract, either a 32 bit multiply or a 40 bit accumulator. */
1524
1525 static bu32
1526 extract_mult (SIM_CPU *cpu, bu64 res, int mmod, int MM,
1527 int fullword, bu32 *overflow)
1528 {
1529 if (fullword)
1530 switch (mmod)
1531 {
1532 case 0:
1533 case M_IS:
1534 return saturate_s32 (res, overflow);
1535 case M_IU:
1536 if (MM)
1537 return saturate_s32 (res, overflow);
1538 return saturate_u32 (res, overflow);
1539 case M_FU:
1540 if (MM)
1541 return saturate_s32 (res, overflow);
1542 return saturate_u32 (res, overflow);
1543 case M_S2RND:
1544 case M_ISS2:
1545 return saturate_s32 (res << 1, overflow);
1546 default:
1547 illegal_instruction (cpu);
1548 }
1549 else
1550 switch (mmod)
1551 {
1552 case 0:
1553 case M_W32:
1554 case M_IH:
1555 return saturate_s16 (rnd16 (res), overflow);
1556 case M_IS:
1557 return saturate_s16 (res, overflow);
1558 case M_FU:
1559 if (MM)
1560 return saturate_s16 (rnd16 (res), overflow);
1561 return saturate_u16 (rnd16 (res), overflow);
1562 case M_IU:
1563 if (MM)
1564 return saturate_s16 (res, overflow);
1565 return saturate_u16 (res, overflow);
1566
1567 case M_T:
1568 return saturate_s16 (trunc16 (res), overflow);
1569 case M_TFU:
1570 if (MM)
1571 return saturate_s16 (trunc16 (res), overflow);
1572 return saturate_u16 (trunc16 (res), overflow);
1573
1574 case M_S2RND:
1575 return saturate_s16 (rnd16 (res << 1), overflow);
1576 case M_ISS2:
1577 return saturate_s16 (res << 1, overflow);
1578 default:
1579 illegal_instruction (cpu);
1580 }
1581 }
1582
1583 static bu32
1584 decode_macfunc (SIM_CPU *cpu, int which, int op, int h0, int h1, int src0,
1585 int src1, int mmod, int MM, int fullword, bu32 *overflow,
1586 bu32 *neg)
1587 {
1588 bu64 acc;
1589 bu32 sat = 0, tsat, ret;
1590
1591 /* Sign extend accumulator if necessary, otherwise unsigned. */
1592 if (is_macmod_signed (mmod) || MM)
1593 acc = get_extended_acc (cpu, which);
1594 else
1595 acc = get_unextended_acc (cpu, which);
1596
1597 if (op != 3)
1598 {
1599 /* TODO: Figure out how the 32-bit sign is used. */
1600 ATTRIBUTE_UNUSED bu8 sgn0 = (acc >> 31) & 1;
1601 bu8 sgn40 = (acc >> 39) & 1;
1602 bu40 nosat_acc;
1603
1604 /* This can't saturate, so we don't keep track of the sat flag. */
1605 bu64 res = decode_multfunc (cpu, h0, h1, src0, src1, mmod,
1606 MM, &tsat);
1607
1608 /* Perform accumulation. */
1609 switch (op)
1610 {
1611 case 0:
1612 acc = res;
1613 sgn0 = (acc >> 31) & 1;
1614 break;
1615 case 1:
1616 acc = acc + res;
1617 break;
1618 case 2:
1619 acc = acc - res;
1620 break;
1621 }
1622
1623 nosat_acc = acc;
1624 /* Saturate. */
1625 switch (mmod)
1626 {
1627 case 0:
1628 case M_T:
1629 case M_IS:
1630 case M_ISS2:
1631 case M_S2RND:
1632 if ((bs64)acc < -((bs64)1 << 39))
1633 acc = -((bu64)1 << 39), sat = 1;
1634 else if ((bs64)acc > 0x7fffffffffll)
1635 acc = 0x7fffffffffull, sat = 1;
1636 break;
1637 case M_TFU:
1638 if (MM)
1639 {
1640 if ((bs64)acc < -((bs64)1 << 39))
1641 acc = -((bu64)1 << 39), sat = 1;
1642 if ((bs64)acc > 0x7FFFFFFFFFll)
1643 acc = 0x7FFFFFFFFFull, sat = 1;
1644 }
1645 else
1646 {
1647 if ((bs64)acc < 0)
1648 acc = 0, sat = 1;
1649 if ((bs64)acc > 0xFFFFFFFFFFull)
1650 acc = 0xFFFFFFFFFFull, sat = 1;
1651 }
1652 break;
1653 case M_IU:
1654 if (!MM && acc & 0x8000000000000000ull)
1655 acc = 0x0, sat = 1;
1656 if (!MM && acc > 0xFFFFFFFFFFull)
1657 acc = 0xFFFFFFFFFFull, sat = 1;
1658 if (MM && acc > 0xFFFFFFFFFFull)
1659 acc &= 0xFFFFFFFFFFull;
1660 if (acc & 0x8000000000ull)
1661 acc |= 0xffffff0000000000ull;
1662 break;
1663 case M_FU:
1664 if (MM)
1665 {
1666 if ((bs64)acc < -((bs64)1 << 39))
1667 acc = -((bu64)1 << 39), sat = 1;
1668 if ((bs64)acc > 0x7FFFFFFFFFll)
1669 acc = 0x7FFFFFFFFFull, sat = 1;
1670 else if (acc & 0x8000000000ull)
1671 acc |= 0xffffff0000000000ull;
1672 }
1673 else
1674 {
1675 if ((bs64)acc < 0)
1676 acc = 0x0, sat = 1;
1677 else if ((bs64)acc > (bs64)0xFFFFFFFFFFll)
1678 acc = 0xFFFFFFFFFFull, sat = 1;
1679 }
1680 break;
1681 case M_IH:
1682 if ((bs64)acc < -0x80000000ll)
1683 acc = -0x80000000ull, sat = 1;
1684 else if ((bs64)acc > 0x7fffffffll)
1685 acc = 0x7fffffffull, sat = 1;
1686 break;
1687 case M_W32:
1688 /* check max negative value */
1689 if (sgn40 && ((acc >> 31) != 0x1ffffffff)
1690 && ((acc >> 31) != 0x0))
1691 acc = 0x80000000, sat = 1;
1692 if (!sat && !sgn40 && ((acc >> 31) != 0x0)
1693 && ((acc >> 31) != 0x1ffffffff))
1694 acc = 0x7FFFFFFF, sat = 1;
1695 acc &= 0xffffffff;
1696 if (acc & 0x80000000)
1697 acc |= 0xffffffff00000000ull;
1698 if (tsat)
1699 sat = 1;
1700 break;
1701 default:
1702 illegal_instruction (cpu);
1703 }
1704
1705 if (acc & 0x8000000000ull)
1706 *neg = 1;
1707
1708 STORE (AXREG (which), (acc >> 32) & 0xff);
1709 STORE (AWREG (which), acc & 0xffffffff);
1710 STORE (ASTATREG (av[which]), sat);
1711 if (sat)
1712 STORE (ASTATREG (avs[which]), sat);
1713
1714 /* Figure out the overflow bit. */
1715 if (sat)
1716 {
1717 if (fullword)
1718 *overflow = 1;
1719 else
1720 ret = extract_mult (cpu, nosat_acc, mmod, MM, fullword, overflow);
1721 }
1722 }
1723
1724 ret = extract_mult (cpu, acc, mmod, MM, fullword, overflow);
1725
1726 if (!fullword)
1727 {
1728 if (ret & 0x8000)
1729 *neg = 1;
1730 }
1731 else
1732 {
1733 if (ret & 0x80000000)
1734 *neg = 1;
1735 }
1736
1737 return ret;
1738 }
1739
1740 bu32
1741 hwloop_get_next_pc (SIM_CPU *cpu, bu32 pc, bu32 insn_len)
1742 {
1743 int i;
1744
1745 if (insn_len == 0)
1746 return pc;
1747
1748 /* If our PC has reached the bottom of a hardware loop,
1749 move back up to the top of the hardware loop. */
1750 for (i = 1; i >= 0; --i)
1751 if (LCREG (i) > 1 && pc == LBREG (i))
1752 {
1753 BFIN_TRACE_BRANCH (cpu, pc, LTREG (i), i, "Hardware loop %i", i);
1754 return LTREG (i);
1755 }
1756
1757 return pc + insn_len;
1758 }
1759
1760 static void
1761 decode_ProgCtrl_0 (SIM_CPU *cpu, bu16 iw0, bu32 pc)
1762 {
1763 /* ProgCtrl
1764 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
1765 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |.prgfunc.......|.poprnd........|
1766 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
1767 int poprnd = ((iw0 >> ProgCtrl_poprnd_bits) & ProgCtrl_poprnd_mask);
1768 int prgfunc = ((iw0 >> ProgCtrl_prgfunc_bits) & ProgCtrl_prgfunc_mask);
1769
1770 TRACE_EXTRACT (cpu, "%s: poprnd:%i prgfunc:%i", __func__, poprnd, prgfunc);
1771
1772 if (prgfunc == 0 && poprnd == 0)
1773 {
1774 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_nop);
1775 TRACE_INSN (cpu, "NOP;");
1776 }
1777 else if (prgfunc == 1 && poprnd == 0)
1778 {
1779 bu32 newpc = RETSREG;
1780 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
1781 TRACE_INSN (cpu, "RTS;");
1782 IFETCH_CHECK (newpc);
1783 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
1784 illegal_instruction_combination (cpu);
1785 BFIN_TRACE_BRANCH (cpu, pc, newpc, -1, "RTS");
1786 SET_PCREG (newpc);
1787 BFIN_CPU_STATE.did_jump = true;
1788 CYCLE_DELAY = 5;
1789 }
1790 else if (prgfunc == 1 && poprnd == 1)
1791 {
1792 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
1793 TRACE_INSN (cpu, "RTI;");
1794 /* Do not do IFETCH_CHECK here -- LSB has special meaning. */
1795 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
1796 illegal_instruction_combination (cpu);
1797 cec_return (cpu, -1);
1798 CYCLE_DELAY = 5;
1799 }
1800 else if (prgfunc == 1 && poprnd == 2)
1801 {
1802 bu32 newpc = RETXREG;
1803 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
1804 TRACE_INSN (cpu, "RTX;");
1805 /* XXX: Not sure if this is what the hardware does. */
1806 IFETCH_CHECK (newpc);
1807 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
1808 illegal_instruction_combination (cpu);
1809 cec_return (cpu, IVG_EVX);
1810 CYCLE_DELAY = 5;
1811 }
1812 else if (prgfunc == 1 && poprnd == 3)
1813 {
1814 bu32 newpc = RETNREG;
1815 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
1816 TRACE_INSN (cpu, "RTN;");
1817 /* XXX: Not sure if this is what the hardware does. */
1818 IFETCH_CHECK (newpc);
1819 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
1820 illegal_instruction_combination (cpu);
1821 cec_return (cpu, IVG_NMI);
1822 CYCLE_DELAY = 5;
1823 }
1824 else if (prgfunc == 1 && poprnd == 4)
1825 {
1826 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
1827 TRACE_INSN (cpu, "RTE;");
1828 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
1829 illegal_instruction_combination (cpu);
1830 cec_return (cpu, IVG_EMU);
1831 CYCLE_DELAY = 5;
1832 }
1833 else if (prgfunc == 2 && poprnd == 0)
1834 {
1835 SIM_DESC sd = CPU_STATE (cpu);
1836 sim_events *events = STATE_EVENTS (sd);
1837
1838 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_sync);
1839 /* XXX: in supervisor mode, utilizes wake up sources
1840 in user mode, it's a NOP ... */
1841 TRACE_INSN (cpu, "IDLE;");
1842
1843 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
1844 illegal_instruction_combination (cpu);
1845
1846 /* Timewarp ! */
1847 if (events->queue)
1848 CYCLE_DELAY = events->time_from_event;
1849 else
1850 abort (); /* XXX: Should this ever happen ? */
1851 }
1852 else if (prgfunc == 2 && poprnd == 3)
1853 {
1854 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_sync);
1855 /* Just NOP it. */
1856 TRACE_INSN (cpu, "CSYNC;");
1857 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
1858 illegal_instruction_combination (cpu);
1859 CYCLE_DELAY = 10;
1860 }
1861 else if (prgfunc == 2 && poprnd == 4)
1862 {
1863 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_sync);
1864 /* Just NOP it. */
1865 TRACE_INSN (cpu, "SSYNC;");
1866 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
1867 illegal_instruction_combination (cpu);
1868
1869 /* Really 10+, but no model info for this. */
1870 CYCLE_DELAY = 10;
1871 }
1872 else if (prgfunc == 2 && poprnd == 5)
1873 {
1874 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_cec);
1875 TRACE_INSN (cpu, "EMUEXCPT;");
1876 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
1877 illegal_instruction_combination (cpu);
1878 cec_exception (cpu, VEC_SIM_TRAP);
1879 }
1880 else if (prgfunc == 3 && poprnd < 8)
1881 {
1882 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_cec);
1883 TRACE_INSN (cpu, "CLI R%i;", poprnd);
1884 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
1885 illegal_instruction_combination (cpu);
1886 SET_DREG (poprnd, cec_cli (cpu));
1887 }
1888 else if (prgfunc == 4 && poprnd < 8)
1889 {
1890 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_cec);
1891 TRACE_INSN (cpu, "STI R%i;", poprnd);
1892 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
1893 illegal_instruction_combination (cpu);
1894 cec_sti (cpu, DREG (poprnd));
1895 CYCLE_DELAY = 3;
1896 }
1897 else if (prgfunc == 5 && poprnd < 8)
1898 {
1899 bu32 newpc = PREG (poprnd);
1900 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
1901 TRACE_INSN (cpu, "JUMP (%s);", get_preg_name (poprnd));
1902 IFETCH_CHECK (newpc);
1903 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
1904 illegal_instruction_combination (cpu);
1905 BFIN_TRACE_BRANCH (cpu, pc, newpc, -1, "JUMP (Preg)");
1906 SET_PCREG (newpc);
1907 BFIN_CPU_STATE.did_jump = true;
1908 PROFILE_BRANCH_TAKEN (cpu);
1909 CYCLE_DELAY = 5;
1910 }
1911 else if (prgfunc == 6 && poprnd < 8)
1912 {
1913 bu32 newpc = PREG (poprnd);
1914 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
1915 TRACE_INSN (cpu, "CALL (%s);", get_preg_name (poprnd));
1916 IFETCH_CHECK (newpc);
1917 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
1918 illegal_instruction_combination (cpu);
1919 BFIN_TRACE_BRANCH (cpu, pc, newpc, -1, "CALL (Preg)");
1920 /* If we're at the end of a hardware loop, RETS is going to be
1921 the top of the loop rather than the next instruction. */
1922 SET_RETSREG (hwloop_get_next_pc (cpu, pc, 2));
1923 SET_PCREG (newpc);
1924 BFIN_CPU_STATE.did_jump = true;
1925 PROFILE_BRANCH_TAKEN (cpu);
1926 CYCLE_DELAY = 5;
1927 }
1928 else if (prgfunc == 7 && poprnd < 8)
1929 {
1930 bu32 newpc = pc + PREG (poprnd);
1931 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
1932 TRACE_INSN (cpu, "CALL (PC + %s);", get_preg_name (poprnd));
1933 IFETCH_CHECK (newpc);
1934 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
1935 illegal_instruction_combination (cpu);
1936 BFIN_TRACE_BRANCH (cpu, pc, newpc, -1, "CALL (PC + Preg)");
1937 SET_RETSREG (hwloop_get_next_pc (cpu, pc, 2));
1938 SET_PCREG (newpc);
1939 BFIN_CPU_STATE.did_jump = true;
1940 PROFILE_BRANCH_TAKEN (cpu);
1941 CYCLE_DELAY = 5;
1942 }
1943 else if (prgfunc == 8 && poprnd < 8)
1944 {
1945 bu32 newpc = pc + PREG (poprnd);
1946 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
1947 TRACE_INSN (cpu, "JUMP (PC + %s);", get_preg_name (poprnd));
1948 IFETCH_CHECK (newpc);
1949 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
1950 illegal_instruction_combination (cpu);
1951 BFIN_TRACE_BRANCH (cpu, pc, newpc, -1, "JUMP (PC + Preg)");
1952 SET_PCREG (newpc);
1953 BFIN_CPU_STATE.did_jump = true;
1954 PROFILE_BRANCH_TAKEN (cpu);
1955 CYCLE_DELAY = 5;
1956 }
1957 else if (prgfunc == 9)
1958 {
1959 int raise = uimm4 (poprnd);
1960 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_cec);
1961 TRACE_INSN (cpu, "RAISE %s;", uimm4_str (raise));
1962 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
1963 illegal_instruction_combination (cpu);
1964 cec_require_supervisor (cpu);
1965 if (raise == IVG_IVHW)
1966 cec_hwerr (cpu, HWERR_RAISE_5);
1967 else
1968 cec_latch (cpu, raise);
1969 CYCLE_DELAY = 3; /* XXX: Only if IVG is unmasked. */
1970 }
1971 else if (prgfunc == 10)
1972 {
1973 int excpt = uimm4 (poprnd);
1974 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_cec);
1975 TRACE_INSN (cpu, "EXCPT %s;", uimm4_str (excpt));
1976 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
1977 illegal_instruction_combination (cpu);
1978 cec_exception (cpu, excpt);
1979 CYCLE_DELAY = 3;
1980 }
1981 else if (prgfunc == 11 && poprnd < 6)
1982 {
1983 bu32 addr = PREG (poprnd);
1984 bu8 byte;
1985 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_atomic);
1986 TRACE_INSN (cpu, "TESTSET (%s);", get_preg_name (poprnd));
1987 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
1988 illegal_instruction_combination (cpu);
1989 byte = GET_WORD (addr);
1990 SET_CCREG (byte == 0);
1991 PUT_BYTE (addr, byte | 0x80);
1992 /* Also includes memory stalls, but we don't model that. */
1993 CYCLE_DELAY = 2;
1994 }
1995 else
1996 illegal_instruction_or_combination (cpu);
1997 }
1998
1999 static void
2000 decode_CaCTRL_0 (SIM_CPU *cpu, bu16 iw0)
2001 {
2002 /* CaCTRL
2003 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2004 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 |.a.|.op....|.reg.......|
2005 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2006 int a = ((iw0 >> CaCTRL_a_bits) & CaCTRL_a_mask);
2007 int op = ((iw0 >> CaCTRL_op_bits) & CaCTRL_op_mask);
2008 int reg = ((iw0 >> CaCTRL_reg_bits) & CaCTRL_reg_mask);
2009 bu32 preg = PREG (reg);
2010 const char * const sinsn[] = { "PREFETCH", "FLUSHINV", "FLUSH", "IFLUSH", };
2011
2012 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_CaCTRL);
2013 TRACE_EXTRACT (cpu, "%s: a:%i op:%i reg:%i", __func__, a, op, reg);
2014 TRACE_INSN (cpu, "%s [%s%s];", sinsn[op], get_preg_name (reg), a ? "++" : "");
2015
2016 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2017 /* None of these can be part of a parallel instruction. */
2018 illegal_instruction_combination (cpu);
2019
2020 /* No cache simulation, so these are (mostly) all NOPs.
2021 XXX: The hardware takes care of masking to cache lines, but need
2022 to check behavior of the post increment. Should we be aligning
2023 the value to the cache line before adding the cache line size, or
2024 do we just add the cache line size ? */
2025 if (op == 0)
2026 { /* PREFETCH */
2027 mmu_check_cache_addr (cpu, preg, false, false);
2028 }
2029 else if (op == 1)
2030 { /* FLUSHINV */
2031 mmu_check_cache_addr (cpu, preg, true, false);
2032 }
2033 else if (op == 2)
2034 { /* FLUSH */
2035 mmu_check_cache_addr (cpu, preg, true, false);
2036 }
2037 else if (op == 3)
2038 { /* IFLUSH */
2039 mmu_check_cache_addr (cpu, preg, false, true);
2040 }
2041
2042 if (a)
2043 SET_PREG (reg, preg + BFIN_L1_CACHE_BYTES);
2044 }
2045
2046 static void
2047 decode_PushPopReg_0 (SIM_CPU *cpu, bu16 iw0)
2048 {
2049 /* PushPopReg
2050 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2051 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |.W.|.grp.......|.reg.......|
2052 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2053 int W = ((iw0 >> PushPopReg_W_bits) & PushPopReg_W_mask);
2054 int grp = ((iw0 >> PushPopReg_grp_bits) & PushPopReg_grp_mask);
2055 int reg = ((iw0 >> PushPopReg_reg_bits) & PushPopReg_reg_mask);
2056 const char *reg_name = get_allreg_name (grp, reg);
2057 bu32 value;
2058 bu32 sp = SPREG;
2059
2060 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_PushPopReg);
2061 TRACE_EXTRACT (cpu, "%s: W:%i grp:%i reg:%i", __func__, W, grp, reg);
2062 TRACE_DECODE (cpu, "%s: reg:%s", __func__, reg_name);
2063
2064 /* Can't push/pop reserved registers */
2065 if (reg_is_reserved (grp, reg))
2066 illegal_instruction_or_combination (cpu);
2067
2068 if (W == 0)
2069 {
2070 /* Dreg and Preg are not supported by this instruction. */
2071 if (grp == 0 || grp == 1)
2072 illegal_instruction_or_combination (cpu);
2073 TRACE_INSN (cpu, "%s = [SP++];", reg_name);
2074 /* Can't pop USP while in userspace. */
2075 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE
2076 || (grp == 7 && reg == 0 && cec_is_user_mode(cpu)))
2077 illegal_instruction_combination (cpu);
2078 /* XXX: The valid register check is in reg_write(), so we might
2079 incorrectly do a GET_LONG() here ... */
2080 value = GET_LONG (sp);
2081 reg_write (cpu, grp, reg, value);
2082 if (grp == 7 && reg == 3)
2083 cec_pop_reti (cpu);
2084
2085 sp += 4;
2086 }
2087 else
2088 {
2089 TRACE_INSN (cpu, "[--SP] = %s;", reg_name);
2090 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2091 illegal_instruction_combination (cpu);
2092
2093 sp -= 4;
2094 value = reg_read (cpu, grp, reg);
2095 if (grp == 7 && reg == 3)
2096 cec_push_reti (cpu);
2097
2098 PUT_LONG (sp, value);
2099 }
2100
2101 /* Note: SP update must be delayed until after all reads/writes; see
2102 comments in decode_PushPopMultiple_0() for more info. */
2103 SET_SPREG (sp);
2104 }
2105
2106 static void
2107 decode_PushPopMultiple_0 (SIM_CPU *cpu, bu16 iw0)
2108 {
2109 /* PushPopMultiple
2110 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2111 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |.d.|.p.|.W.|.dr........|.pr........|
2112 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2113 int p = ((iw0 >> PushPopMultiple_p_bits) & PushPopMultiple_p_mask);
2114 int d = ((iw0 >> PushPopMultiple_d_bits) & PushPopMultiple_d_mask);
2115 int W = ((iw0 >> PushPopMultiple_W_bits) & PushPopMultiple_W_mask);
2116 int dr = ((iw0 >> PushPopMultiple_dr_bits) & PushPopMultiple_dr_mask);
2117 int pr = ((iw0 >> PushPopMultiple_pr_bits) & PushPopMultiple_pr_mask);
2118 int i;
2119 bu32 sp = SPREG;
2120
2121 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_PushPopMultiple);
2122 TRACE_EXTRACT (cpu, "%s: d:%i p:%i W:%i dr:%i pr:%i",
2123 __func__, d, p, W, dr, pr);
2124
2125 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2126 illegal_instruction_combination (cpu);
2127
2128 if ((d == 0 && p == 0) || (p && imm5 (pr) > 5)
2129 || (d && !p && pr) || (p && !d && dr))
2130 illegal_instruction (cpu);
2131
2132 if (W == 1)
2133 {
2134 if (d && p)
2135 TRACE_INSN (cpu, "[--SP] = (R7:%i, P5:%i);", dr, pr);
2136 else if (d)
2137 TRACE_INSN (cpu, "[--SP] = (R7:%i);", dr);
2138 else
2139 TRACE_INSN (cpu, "[--SP] = (P5:%i);", pr);
2140
2141 if (d)
2142 for (i = dr; i < 8; i++)
2143 {
2144 sp -= 4;
2145 PUT_LONG (sp, DREG (i));
2146 }
2147 if (p)
2148 for (i = pr; i < 6; i++)
2149 {
2150 sp -= 4;
2151 PUT_LONG (sp, PREG (i));
2152 }
2153
2154 CYCLE_DELAY = 14;
2155 }
2156 else
2157 {
2158 if (d && p)
2159 TRACE_INSN (cpu, "(R7:%i, P5:%i) = [SP++];", dr, pr);
2160 else if (d)
2161 TRACE_INSN (cpu, "(R7:%i) = [SP++];", dr);
2162 else
2163 TRACE_INSN (cpu, "(P5:%i) = [SP++];", pr);
2164
2165 if (p)
2166 for (i = 5; i >= pr; i--)
2167 {
2168 SET_PREG (i, GET_LONG (sp));
2169 sp += 4;
2170 }
2171 if (d)
2172 for (i = 7; i >= dr; i--)
2173 {
2174 SET_DREG (i, GET_LONG (sp));
2175 sp += 4;
2176 }
2177
2178 CYCLE_DELAY = 11;
2179 }
2180
2181 /* Note: SP update must be delayed until after all reads/writes so that
2182 if an exception does occur, the insn may be re-executed as the
2183 SP has not yet changed. */
2184 SET_SPREG (sp);
2185 }
2186
2187 static void
2188 decode_ccMV_0 (SIM_CPU *cpu, bu16 iw0)
2189 {
2190 /* ccMV
2191 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2192 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |.T.|.d.|.s.|.dst.......|.src.......|
2193 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2194 int s = ((iw0 >> CCmv_s_bits) & CCmv_s_mask);
2195 int d = ((iw0 >> CCmv_d_bits) & CCmv_d_mask);
2196 int T = ((iw0 >> CCmv_T_bits) & CCmv_T_mask);
2197 int src = ((iw0 >> CCmv_src_bits) & CCmv_src_mask);
2198 int dst = ((iw0 >> CCmv_dst_bits) & CCmv_dst_mask);
2199 int cond = T ? CCREG : ! CCREG;
2200
2201 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ccMV);
2202 TRACE_EXTRACT (cpu, "%s: T:%i d:%i s:%i dst:%i src:%i",
2203 __func__, T, d, s, dst, src);
2204
2205 TRACE_INSN (cpu, "IF %sCC %s = %s;", T ? "" : "! ",
2206 get_allreg_name (d, dst),
2207 get_allreg_name (s, src));
2208 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2209 illegal_instruction_combination (cpu);
2210
2211 if (cond)
2212 reg_write (cpu, d, dst, reg_read (cpu, s, src));
2213 }
2214
2215 static void
2216 decode_CCflag_0 (SIM_CPU *cpu, bu16 iw0)
2217 {
2218 /* CCflag
2219 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2220 | 0 | 0 | 0 | 0 | 1 |.I.|.opc.......|.G.|.y.........|.x.........|
2221 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2222 int x = ((iw0 >> CCflag_x_bits) & CCflag_x_mask);
2223 int y = ((iw0 >> CCflag_y_bits) & CCflag_y_mask);
2224 int I = ((iw0 >> CCflag_I_bits) & CCflag_I_mask);
2225 int G = ((iw0 >> CCflag_G_bits) & CCflag_G_mask);
2226 int opc = ((iw0 >> CCflag_opc_bits) & CCflag_opc_mask);
2227
2228 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_CCflag);
2229 TRACE_EXTRACT (cpu, "%s: I:%i opc:%i G:%i y:%i x:%i",
2230 __func__, I, opc, G, y, x);
2231
2232 if (opc > 4)
2233 {
2234 bs64 acc0 = get_extended_acc (cpu, 0);
2235 bs64 acc1 = get_extended_acc (cpu, 1);
2236 bs64 diff = acc0 - acc1;
2237
2238 if (x != 0 || y != 0)
2239 illegal_instruction_or_combination (cpu);
2240
2241 if (opc == 5 && I == 0 && G == 0)
2242 {
2243 TRACE_INSN (cpu, "CC = A0 == A1;");
2244 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2245 illegal_instruction_combination (cpu);
2246 SET_CCREG (acc0 == acc1);
2247 }
2248 else if (opc == 6 && I == 0 && G == 0)
2249 {
2250 TRACE_INSN (cpu, "CC = A0 < A1");
2251 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2252 illegal_instruction_combination (cpu);
2253 SET_CCREG (acc0 < acc1);
2254 }
2255 else if (opc == 7 && I == 0 && G == 0)
2256 {
2257 TRACE_INSN (cpu, "CC = A0 <= A1");
2258 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2259 illegal_instruction_combination (cpu);
2260 SET_CCREG (acc0 <= acc1);
2261 }
2262 else
2263 illegal_instruction_or_combination (cpu);
2264
2265 SET_ASTATREG (az, diff == 0);
2266 SET_ASTATREG (an, diff < 0);
2267 SET_ASTATREG (ac0, (bu40)acc1 <= (bu40)acc0);
2268 }
2269 else
2270 {
2271 int issigned = opc < 3;
2272 const char *sign = issigned ? "" : " (IU)";
2273 bu32 srcop = G ? PREG (x) : DREG (x);
2274 char s = G ? 'P' : 'R';
2275 bu32 dstop = I ? (issigned ? imm3 (y) : uimm3 (y)) : G ? PREG (y) : DREG (y);
2276 const char *op;
2277 char d = G ? 'P' : 'R';
2278 int flgs = srcop >> 31;
2279 int flgo = dstop >> 31;
2280
2281 bu32 result = srcop - dstop;
2282 int cc;
2283 int flgn = result >> 31;
2284 int overflow = (flgs ^ flgo) & (flgn ^ flgs);
2285 int az = result == 0;
2286 int ac0 = dstop <= srcop;
2287 int an;
2288 if (issigned)
2289 an = (flgn && !overflow) || (!flgn && overflow);
2290 else
2291 an = dstop > srcop;
2292
2293 switch (opc)
2294 {
2295 default: /* Shutup useless gcc warnings. */
2296 case 0: /* signed */
2297 op = "==";
2298 cc = az;
2299 break;
2300 case 1: /* signed */
2301 op = "<";
2302 cc = an;
2303 break;
2304 case 2: /* signed */
2305 op = "<=";
2306 cc = an || az;
2307 break;
2308 case 3: /* unsigned */
2309 op = "<";
2310 cc = !ac0;
2311 break;
2312 case 4: /* unsigned */
2313 op = "<=";
2314 cc = !ac0 || az;
2315 break;
2316 }
2317
2318 if (I)
2319 TRACE_INSN (cpu, "CC = %c%i %s %s%s;", s, x, op,
2320 issigned ? imm3_str (y) : uimm3_str (y), sign);
2321 else
2322 {
2323 TRACE_DECODE (cpu, "%s %c%i:%x %c%i:%x", __func__,
2324 s, x, srcop, d, y, dstop);
2325 TRACE_INSN (cpu, "CC = %c%i %s %c%i%s;", s, x, op, d, y, sign);
2326 }
2327
2328 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2329 illegal_instruction_combination (cpu);
2330
2331 SET_CCREG (cc);
2332 /* Pointer compares only touch CC. */
2333 if (!G)
2334 {
2335 SET_ASTATREG (az, az);
2336 SET_ASTATREG (an, an);
2337 SET_ASTATREG (ac0, ac0);
2338 }
2339 }
2340 }
2341
2342 static void
2343 decode_CC2dreg_0 (SIM_CPU *cpu, bu16 iw0)
2344 {
2345 /* CC2dreg
2346 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2347 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |.op....|.reg.......|
2348 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2349 int op = ((iw0 >> CC2dreg_op_bits) & CC2dreg_op_mask);
2350 int reg = ((iw0 >> CC2dreg_reg_bits) & CC2dreg_reg_mask);
2351
2352 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_CC2dreg);
2353 TRACE_EXTRACT (cpu, "%s: op:%i reg:%i", __func__, op, reg);
2354
2355 if (op == 0)
2356 {
2357 TRACE_INSN (cpu, "R%i = CC;", reg);
2358 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2359 illegal_instruction_combination (cpu);
2360 SET_DREG (reg, CCREG);
2361 }
2362 else if (op == 1)
2363 {
2364 TRACE_INSN (cpu, "CC = R%i;", reg);
2365 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2366 illegal_instruction_combination (cpu);
2367 SET_CCREG (DREG (reg) != 0);
2368 }
2369 else if (op == 3 && reg == 0)
2370 {
2371 TRACE_INSN (cpu, "CC = !CC;");
2372 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2373 illegal_instruction_combination (cpu);
2374 SET_CCREG (!CCREG);
2375 }
2376 else
2377 illegal_instruction_or_combination (cpu);
2378 }
2379
2380 static void
2381 decode_CC2stat_0 (SIM_CPU *cpu, bu16 iw0)
2382 {
2383 /* CC2stat
2384 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2385 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |.D.|.op....|.cbit..............|
2386 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2387 int D = ((iw0 >> CC2stat_D_bits) & CC2stat_D_mask);
2388 int op = ((iw0 >> CC2stat_op_bits) & CC2stat_op_mask);
2389 int cbit = ((iw0 >> CC2stat_cbit_bits) & CC2stat_cbit_mask);
2390 bu32 pval;
2391
2392 const char * const op_names[] = { "", "|", "&", "^" } ;
2393
2394 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_CC2stat);
2395 TRACE_EXTRACT (cpu, "%s: D:%i op:%i cbit:%i", __func__, D, op, cbit);
2396
2397 TRACE_INSN (cpu, "%s %s= %s;", D ? astat_names[cbit] : "CC",
2398 op_names[op], D ? "CC" : astat_names[cbit]);
2399
2400 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2401 illegal_instruction_combination (cpu);
2402
2403 /* CC = CC; is invalid. */
2404 if (cbit == 5)
2405 illegal_instruction (cpu);
2406
2407 pval = !!(ASTAT & (1 << cbit));
2408 if (D == 0)
2409 switch (op)
2410 {
2411 case 0: SET_CCREG (pval); break;
2412 case 1: SET_CCREG (CCREG | pval); break;
2413 case 2: SET_CCREG (CCREG & pval); break;
2414 case 3: SET_CCREG (CCREG ^ pval); break;
2415 }
2416 else
2417 {
2418 switch (op)
2419 {
2420 case 0: pval = CCREG; break;
2421 case 1: pval |= CCREG; break;
2422 case 2: pval &= CCREG; break;
2423 case 3: pval ^= CCREG; break;
2424 }
2425 TRACE_REGISTER (cpu, "wrote ASTAT[%s] = %i", astat_names[cbit], pval);
2426 SET_ASTAT ((ASTAT & ~(1 << cbit)) | (pval << cbit));
2427 }
2428 }
2429
2430 static void
2431 decode_BRCC_0 (SIM_CPU *cpu, bu16 iw0, bu32 pc)
2432 {
2433 /* BRCC
2434 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2435 | 0 | 0 | 0 | 1 |.T.|.B.|.offset................................|
2436 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2437 int B = ((iw0 >> BRCC_B_bits) & BRCC_B_mask);
2438 int T = ((iw0 >> BRCC_T_bits) & BRCC_T_mask);
2439 int offset = ((iw0 >> BRCC_offset_bits) & BRCC_offset_mask);
2440 int cond = T ? CCREG : ! CCREG;
2441 int pcrel = pcrel10 (offset);
2442
2443 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_BRCC);
2444 TRACE_EXTRACT (cpu, "%s: T:%i B:%i offset:%#x", __func__, T, B, offset);
2445 TRACE_DECODE (cpu, "%s: pcrel10:%#x", __func__, pcrel);
2446
2447 TRACE_INSN (cpu, "IF %sCC JUMP %#x%s;", T ? "" : "! ",
2448 pcrel, B ? " (bp)" : "");
2449
2450 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2451 illegal_instruction_combination (cpu);
2452
2453 if (cond)
2454 {
2455 bu32 newpc = pc + pcrel;
2456 BFIN_TRACE_BRANCH (cpu, pc, newpc, -1, "Conditional JUMP");
2457 SET_PCREG (newpc);
2458 BFIN_CPU_STATE.did_jump = true;
2459 PROFILE_BRANCH_TAKEN (cpu);
2460 CYCLE_DELAY = B ? 5 : 9;
2461 }
2462 else
2463 {
2464 PROFILE_BRANCH_UNTAKEN (cpu);
2465 CYCLE_DELAY = B ? 9 : 1;
2466 }
2467 }
2468
2469 static void
2470 decode_UJUMP_0 (SIM_CPU *cpu, bu16 iw0, bu32 pc)
2471 {
2472 /* UJUMP
2473 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2474 | 0 | 0 | 1 | 0 |.offset........................................|
2475 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2476 int offset = ((iw0 >> UJump_offset_bits) & UJump_offset_mask);
2477 int pcrel = pcrel12 (offset);
2478 bu32 newpc = pc + pcrel;
2479
2480 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_UJUMP);
2481 TRACE_EXTRACT (cpu, "%s: offset:%#x", __func__, offset);
2482 TRACE_DECODE (cpu, "%s: pcrel12:%#x", __func__, pcrel);
2483
2484 TRACE_INSN (cpu, "JUMP.S %#x;", pcrel);
2485
2486 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2487 illegal_instruction_combination (cpu);
2488
2489 BFIN_TRACE_BRANCH (cpu, pc, newpc, -1, "JUMP.S");
2490
2491 SET_PCREG (newpc);
2492 BFIN_CPU_STATE.did_jump = true;
2493 PROFILE_BRANCH_TAKEN (cpu);
2494 CYCLE_DELAY = 5;
2495 }
2496
2497 static void
2498 decode_REGMV_0 (SIM_CPU *cpu, bu16 iw0)
2499 {
2500 /* REGMV
2501 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2502 | 0 | 0 | 1 | 1 |.gd........|.gs........|.dst.......|.src.......|
2503 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2504 int gs = ((iw0 >> RegMv_gs_bits) & RegMv_gs_mask);
2505 int gd = ((iw0 >> RegMv_gd_bits) & RegMv_gd_mask);
2506 int src = ((iw0 >> RegMv_src_bits) & RegMv_src_mask);
2507 int dst = ((iw0 >> RegMv_dst_bits) & RegMv_dst_mask);
2508 const char *srcreg_name = get_allreg_name (gs, src);
2509 const char *dstreg_name = get_allreg_name (gd, dst);
2510
2511 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_REGMV);
2512 TRACE_EXTRACT (cpu, "%s: gd:%i gs:%i dst:%i src:%i",
2513 __func__, gd, gs, dst, src);
2514 TRACE_DECODE (cpu, "%s: dst:%s src:%s", __func__, dstreg_name, srcreg_name);
2515
2516 TRACE_INSN (cpu, "%s = %s;", dstreg_name, srcreg_name);
2517
2518 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2519 illegal_instruction_combination (cpu);
2520
2521 /* Reserved slots cannot be a src/dst. */
2522 if (reg_is_reserved (gs, src) || reg_is_reserved (gd, dst))
2523 goto invalid_move;
2524
2525 /* Standard register moves. */
2526 if ((gs < 2) /* Dregs/Pregs src */
2527 || (gd < 2) /* Dregs/Pregs dst */
2528 || (gs == 4 && src < 4) /* Accumulators src */
2529 || (gd == 4 && dst < 4 && (gs < 4)) /* Accumulators dst */
2530 || (gs == 7 && src == 7 && !(gd == 4 && dst < 4)) /* EMUDAT src */
2531 || (gd == 7 && dst == 7)) /* EMUDAT dst */
2532 goto valid_move;
2533
2534 /* dareg = dareg (IMBL) */
2535 if (gs < 4 && gd < 4)
2536 goto valid_move;
2537
2538 /* USP can be src to sysregs, but not dagregs. */
2539 if ((gs == 7 && src == 0) && (gd >= 4))
2540 goto valid_move;
2541
2542 /* USP can move between genregs (only check Accumulators). */
2543 if (((gs == 7 && src == 0) && (gd == 4 && dst < 4))
2544 || ((gd == 7 && dst == 0) && (gs == 4 && src < 4)))
2545 goto valid_move;
2546
2547 /* Still here ? Invalid reg pair. */
2548 invalid_move:
2549 illegal_instruction (cpu);
2550
2551 valid_move:
2552 reg_write (cpu, gd, dst, reg_read (cpu, gs, src));
2553 }
2554
2555 static void
2556 decode_ALU2op_0 (SIM_CPU *cpu, bu16 iw0)
2557 {
2558 /* ALU2op
2559 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2560 | 0 | 1 | 0 | 0 | 0 | 0 |.opc...........|.src.......|.dst.......|
2561 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2562 int src = ((iw0 >> ALU2op_src_bits) & ALU2op_src_mask);
2563 int opc = ((iw0 >> ALU2op_opc_bits) & ALU2op_opc_mask);
2564 int dst = ((iw0 >> ALU2op_dst_bits) & ALU2op_dst_mask);
2565
2566 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ALU2op);
2567 TRACE_EXTRACT (cpu, "%s: opc:%i src:%i dst:%i", __func__, opc, src, dst);
2568
2569 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2570 illegal_instruction_combination (cpu);
2571
2572 if (opc == 0)
2573 {
2574 TRACE_INSN (cpu, "R%i >>>= R%i;", dst, src);
2575 SET_DREG (dst, ashiftrt (cpu, DREG (dst), DREG (src), 32));
2576 }
2577 else if (opc == 1)
2578 {
2579 bu32 val;
2580 TRACE_INSN (cpu, "R%i >>= R%i;", dst, src);
2581 if (DREG (src) <= 0x1F)
2582 val = lshiftrt (cpu, DREG (dst), DREG (src), 32);
2583 else
2584 val = 0;
2585 SET_DREG (dst, val);
2586 }
2587 else if (opc == 2)
2588 {
2589 TRACE_INSN (cpu, "R%i <<= R%i;", dst, src);
2590 SET_DREG (dst, lshift (cpu, DREG (dst), DREG (src), 32, 0, 0));
2591 }
2592 else if (opc == 3)
2593 {
2594 TRACE_INSN (cpu, "R%i *= R%i;", dst, src);
2595 SET_DREG (dst, DREG (dst) * DREG (src));
2596 CYCLE_DELAY = 3;
2597 }
2598 else if (opc == 4)
2599 {
2600 TRACE_INSN (cpu, "R%i = (R%i + R%i) << 1;", dst, dst, src);
2601 SET_DREG (dst, add_and_shift (cpu, DREG (dst), DREG (src), 1));
2602 }
2603 else if (opc == 5)
2604 {
2605 TRACE_INSN (cpu, "R%i = (R%i + R%i) << 2;", dst, dst, src);
2606 SET_DREG (dst, add_and_shift (cpu, DREG (dst), DREG (src), 2));
2607 }
2608 else if (opc == 8)
2609 {
2610 TRACE_INSN (cpu, "DIVQ ( R%i, R%i );", dst, src);
2611 SET_DREG (dst, divq (cpu, DREG (dst), (bu16)DREG (src)));
2612 }
2613 else if (opc == 9)
2614 {
2615 TRACE_INSN (cpu, "DIVS ( R%i, R%i );", dst, src);
2616 SET_DREG (dst, divs (cpu, DREG (dst), (bu16)DREG (src)));
2617 }
2618 else if (opc == 10)
2619 {
2620 TRACE_INSN (cpu, "R%i = R%i.L (X);", dst, src);
2621 SET_DREG (dst, (bs32) (bs16) DREG (src));
2622 setflags_logical (cpu, DREG (dst));
2623 }
2624 else if (opc == 11)
2625 {
2626 TRACE_INSN (cpu, "R%i = R%i.L (Z);", dst, src);
2627 SET_DREG (dst, (bu32) (bu16) DREG (src));
2628 setflags_logical (cpu, DREG (dst));
2629 }
2630 else if (opc == 12)
2631 {
2632 TRACE_INSN (cpu, "R%i = R%i.B (X);", dst, src);
2633 SET_DREG (dst, (bs32) (bs8) DREG (src));
2634 setflags_logical (cpu, DREG (dst));
2635 }
2636 else if (opc == 13)
2637 {
2638 TRACE_INSN (cpu, "R%i = R%i.B (Z);", dst, src);
2639 SET_DREG (dst, (bu32) (bu8) DREG (src));
2640 setflags_logical (cpu, DREG (dst));
2641 }
2642 else if (opc == 14)
2643 {
2644 bu32 val = DREG (src);
2645 TRACE_INSN (cpu, "R%i = - R%i;", dst, src);
2646 SET_DREG (dst, -val);
2647 setflags_nz (cpu, DREG (dst));
2648 SET_ASTATREG (v, val == 0x80000000);
2649 if (ASTATREG (v))
2650 SET_ASTATREG (vs, 1);
2651 SET_ASTATREG (ac0, val == 0x0);
2652 /* XXX: Documentation isn't entirely clear about av0 and av1. */
2653 }
2654 else if (opc == 15)
2655 {
2656 TRACE_INSN (cpu, "R%i = ~ R%i;", dst, src);
2657 SET_DREG (dst, ~DREG (src));
2658 setflags_logical (cpu, DREG (dst));
2659 }
2660 else
2661 illegal_instruction (cpu);
2662 }
2663
2664 static void
2665 decode_PTR2op_0 (SIM_CPU *cpu, bu16 iw0)
2666 {
2667 /* PTR2op
2668 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2669 | 0 | 1 | 0 | 0 | 0 | 1 | 0 |.opc.......|.src.......|.dst.......|
2670 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2671 int src = ((iw0 >> PTR2op_src_bits) & PTR2op_dst_mask);
2672 int opc = ((iw0 >> PTR2op_opc_bits) & PTR2op_opc_mask);
2673 int dst = ((iw0 >> PTR2op_dst_bits) & PTR2op_dst_mask);
2674 const char *src_name = get_preg_name (src);
2675 const char *dst_name = get_preg_name (dst);
2676
2677 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_PTR2op);
2678 TRACE_EXTRACT (cpu, "%s: opc:%i src:%i dst:%i", __func__, opc, src, dst);
2679
2680 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2681 illegal_instruction_combination (cpu);
2682
2683 if (opc == 0)
2684 {
2685 TRACE_INSN (cpu, "%s -= %s", dst_name, src_name);
2686 SET_PREG (dst, PREG (dst) - PREG (src));
2687 }
2688 else if (opc == 1)
2689 {
2690 TRACE_INSN (cpu, "%s = %s << 2", dst_name, src_name);
2691 SET_PREG (dst, PREG (src) << 2);
2692 }
2693 else if (opc == 3)
2694 {
2695 TRACE_INSN (cpu, "%s = %s >> 2", dst_name, src_name);
2696 SET_PREG (dst, PREG (src) >> 2);
2697 }
2698 else if (opc == 4)
2699 {
2700 TRACE_INSN (cpu, "%s = %s >> 1", dst_name, src_name);
2701 SET_PREG (dst, PREG (src) >> 1);
2702 }
2703 else if (opc == 5)
2704 {
2705 TRACE_INSN (cpu, "%s += %s (BREV)", dst_name, src_name);
2706 SET_PREG (dst, add_brev (PREG (dst), PREG (src)));
2707 }
2708 else if (opc == 6)
2709 {
2710 TRACE_INSN (cpu, "%s = (%s + %s) << 1", dst_name, dst_name, src_name);
2711 SET_PREG (dst, (PREG (dst) + PREG (src)) << 1);
2712 }
2713 else if (opc == 7)
2714 {
2715 TRACE_INSN (cpu, "%s = (%s + %s) << 2", dst_name, dst_name, src_name);
2716 SET_PREG (dst, (PREG (dst) + PREG (src)) << 2);
2717 }
2718 else
2719 illegal_instruction (cpu);
2720 }
2721
2722 static void
2723 decode_LOGI2op_0 (SIM_CPU *cpu, bu16 iw0)
2724 {
2725 /* LOGI2op
2726 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2727 | 0 | 1 | 0 | 0 | 1 |.opc.......|.src...............|.dst.......|
2728 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2729 int src = ((iw0 >> LOGI2op_src_bits) & LOGI2op_src_mask);
2730 int opc = ((iw0 >> LOGI2op_opc_bits) & LOGI2op_opc_mask);
2731 int dst = ((iw0 >> LOGI2op_dst_bits) & LOGI2op_dst_mask);
2732 int uimm = uimm5 (src);
2733 const char *uimm_str = uimm5_str (uimm);
2734
2735 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LOGI2op);
2736 TRACE_EXTRACT (cpu, "%s: opc:%i src:%i dst:%i", __func__, opc, src, dst);
2737 TRACE_DECODE (cpu, "%s: uimm5:%#x", __func__, uimm);
2738
2739 if (opc == 0)
2740 {
2741 TRACE_INSN (cpu, "CC = ! BITTST (R%i, %s);", dst, uimm_str);
2742 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2743 illegal_instruction_combination (cpu);
2744 SET_CCREG ((~DREG (dst) >> uimm) & 1);
2745 }
2746 else if (opc == 1)
2747 {
2748 TRACE_INSN (cpu, "CC = BITTST (R%i, %s);", dst, uimm_str);
2749 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2750 illegal_instruction_combination (cpu);
2751 SET_CCREG ((DREG (dst) >> uimm) & 1);
2752 }
2753 else if (opc == 2)
2754 {
2755 TRACE_INSN (cpu, "BITSET (R%i, %s);", dst, uimm_str);
2756 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2757 illegal_instruction_combination (cpu);
2758 SET_DREG (dst, DREG (dst) | (1 << uimm));
2759 setflags_logical (cpu, DREG (dst));
2760 }
2761 else if (opc == 3)
2762 {
2763 TRACE_INSN (cpu, "BITTGL (R%i, %s);", dst, uimm_str);
2764 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2765 illegal_instruction_combination (cpu);
2766 SET_DREG (dst, DREG (dst) ^ (1 << uimm));
2767 setflags_logical (cpu, DREG (dst));
2768 }
2769 else if (opc == 4)
2770 {
2771 TRACE_INSN (cpu, "BITCLR (R%i, %s);", dst, uimm_str);
2772 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2773 illegal_instruction_combination (cpu);
2774 SET_DREG (dst, DREG (dst) & ~(1 << uimm));
2775 setflags_logical (cpu, DREG (dst));
2776 }
2777 else if (opc == 5)
2778 {
2779 TRACE_INSN (cpu, "R%i >>>= %s;", dst, uimm_str);
2780 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2781 illegal_instruction_combination (cpu);
2782 SET_DREG (dst, ashiftrt (cpu, DREG (dst), uimm, 32));
2783 }
2784 else if (opc == 6)
2785 {
2786 TRACE_INSN (cpu, "R%i >>= %s;", dst, uimm_str);
2787 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2788 illegal_instruction_combination (cpu);
2789 SET_DREG (dst, lshiftrt (cpu, DREG (dst), uimm, 32));
2790 }
2791 else if (opc == 7)
2792 {
2793 TRACE_INSN (cpu, "R%i <<= %s;", dst, uimm_str);
2794 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2795 illegal_instruction_combination (cpu);
2796 SET_DREG (dst, lshift (cpu, DREG (dst), uimm, 32, 0, 0));
2797 }
2798 }
2799
2800 static void
2801 decode_COMP3op_0 (SIM_CPU *cpu, bu16 iw0)
2802 {
2803 /* COMP3op
2804 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2805 | 0 | 1 | 0 | 1 |.opc.......|.dst.......|.src1......|.src0......|
2806 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2807 int opc = ((iw0 >> COMP3op_opc_bits) & COMP3op_opc_mask);
2808 int dst = ((iw0 >> COMP3op_dst_bits) & COMP3op_dst_mask);
2809 int src0 = ((iw0 >> COMP3op_src0_bits) & COMP3op_src0_mask);
2810 int src1 = ((iw0 >> COMP3op_src1_bits) & COMP3op_src1_mask);
2811
2812 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_COMP3op);
2813 TRACE_EXTRACT (cpu, "%s: opc:%i dst:%i src1:%i src0:%i",
2814 __func__, opc, dst, src1, src0);
2815
2816 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2817 illegal_instruction_combination (cpu);
2818
2819 if (opc == 0)
2820 {
2821 TRACE_INSN (cpu, "R%i = R%i + R%i;", dst, src0, src1);
2822 SET_DREG (dst, add32 (cpu, DREG (src0), DREG (src1), 1, 0));
2823 }
2824 else if (opc == 1)
2825 {
2826 TRACE_INSN (cpu, "R%i = R%i - R%i;", dst, src0, src1);
2827 SET_DREG (dst, sub32 (cpu, DREG (src0), DREG (src1), 1, 0, 0));
2828 }
2829 else if (opc == 2)
2830 {
2831 TRACE_INSN (cpu, "R%i = R%i & R%i;", dst, src0, src1);
2832 SET_DREG (dst, DREG (src0) & DREG (src1));
2833 setflags_logical (cpu, DREG (dst));
2834 }
2835 else if (opc == 3)
2836 {
2837 TRACE_INSN (cpu, "R%i = R%i | R%i;", dst, src0, src1);
2838 SET_DREG (dst, DREG (src0) | DREG (src1));
2839 setflags_logical (cpu, DREG (dst));
2840 }
2841 else if (opc == 4)
2842 {
2843 TRACE_INSN (cpu, "R%i = R%i ^ R%i;", dst, src0, src1);
2844 SET_DREG (dst, DREG (src0) ^ DREG (src1));
2845 setflags_logical (cpu, DREG (dst));
2846 }
2847 else
2848 {
2849 int shift = opc - 5;
2850 const char *dst_name = get_preg_name (dst);
2851 const char *src0_name = get_preg_name (src0);
2852 const char *src1_name = get_preg_name (src1);
2853
2854 /* If src0 == src1 this is disassembled as a shift by 1, but this
2855 distinction doesn't matter for our purposes. */
2856 if (shift)
2857 TRACE_INSN (cpu, "%s = (%s + %s) << %#x;",
2858 dst_name, src0_name, src1_name, shift);
2859 else
2860 TRACE_INSN (cpu, "%s = %s + %s",
2861 dst_name, src0_name, src1_name);
2862 SET_PREG (dst, PREG (src0) + (PREG (src1) << shift));
2863 }
2864 }
2865
2866 static void
2867 decode_COMPI2opD_0 (SIM_CPU *cpu, bu16 iw0)
2868 {
2869 /* COMPI2opD
2870 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2871 | 0 | 1 | 1 | 0 | 0 |.op|..src......................|.dst.......|
2872 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2873 int op = ((iw0 >> COMPI2opD_op_bits) & COMPI2opD_op_mask);
2874 int dst = ((iw0 >> COMPI2opD_dst_bits) & COMPI2opD_dst_mask);
2875 int src = ((iw0 >> COMPI2opD_src_bits) & COMPI2opD_src_mask);
2876 int imm = imm7 (src);
2877
2878 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_COMPI2opD);
2879 TRACE_EXTRACT (cpu, "%s: op:%i src:%i dst:%i", __func__, op, src, dst);
2880 TRACE_DECODE (cpu, "%s: imm7:%#x", __func__, imm);
2881
2882 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2883 illegal_instruction_combination (cpu);
2884
2885 if (op == 0)
2886 {
2887 TRACE_INSN (cpu, "R%i = %s (X);", dst, imm7_str (imm));
2888 SET_DREG (dst, imm);
2889 }
2890 else if (op == 1)
2891 {
2892 TRACE_INSN (cpu, "R%i += %s;", dst, imm7_str (imm));
2893 SET_DREG (dst, add32 (cpu, DREG (dst), imm, 1, 0));
2894 }
2895 }
2896
2897 static void
2898 decode_COMPI2opP_0 (SIM_CPU *cpu, bu16 iw0)
2899 {
2900 /* COMPI2opP
2901 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2902 | 0 | 1 | 1 | 0 | 1 |.op|.src.......................|.dst.......|
2903 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2904 int op = ((iw0 >> COMPI2opP_op_bits) & COMPI2opP_op_mask);
2905 int src = ((iw0 >> COMPI2opP_src_bits) & COMPI2opP_src_mask);
2906 int dst = ((iw0 >> COMPI2opP_dst_bits) & COMPI2opP_dst_mask);
2907 int imm = imm7 (src);
2908 const char *dst_name = get_preg_name (dst);
2909
2910 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_COMPI2opP);
2911 TRACE_EXTRACT (cpu, "%s: op:%i src:%i dst:%i", __func__, op, src, dst);
2912 TRACE_DECODE (cpu, "%s: imm:%#x", __func__, imm);
2913
2914 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
2915 illegal_instruction_combination (cpu);
2916
2917 if (op == 0)
2918 {
2919 TRACE_INSN (cpu, "%s = %s;", dst_name, imm7_str (imm));
2920 SET_PREG (dst, imm);
2921 }
2922 else if (op == 1)
2923 {
2924 TRACE_INSN (cpu, "%s += %s;", dst_name, imm7_str (imm));
2925 SET_PREG (dst, PREG (dst) + imm);
2926 }
2927 }
2928
2929 static void
2930 decode_LDSTpmod_0 (SIM_CPU *cpu, bu16 iw0)
2931 {
2932 /* LDSTpmod
2933 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
2934 | 1 | 0 | 0 | 0 |.W.|.aop...|.reg.......|.idx.......|.ptr.......|
2935 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
2936 int W = ((iw0 >> LDSTpmod_W_bits) & LDSTpmod_W_mask);
2937 int aop = ((iw0 >> LDSTpmod_aop_bits) & LDSTpmod_aop_mask);
2938 int idx = ((iw0 >> LDSTpmod_idx_bits) & LDSTpmod_idx_mask);
2939 int ptr = ((iw0 >> LDSTpmod_ptr_bits) & LDSTpmod_ptr_mask);
2940 int reg = ((iw0 >> LDSTpmod_reg_bits) & LDSTpmod_reg_mask);
2941 const char *ptr_name = get_preg_name (ptr);
2942 const char *idx_name = get_preg_name (idx);
2943 bu32 addr, val;
2944
2945 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LDSTpmod);
2946 TRACE_EXTRACT (cpu, "%s: W:%i aop:%i reg:%i idx:%i ptr:%i",
2947 __func__, W, aop, reg, idx, ptr);
2948
2949 if (PARALLEL_GROUP == BFIN_PARALLEL_GROUP2)
2950 illegal_instruction_combination (cpu);
2951
2952 if (aop == 1 && W == 0 && idx == ptr)
2953 {
2954 TRACE_INSN (cpu, "R%i.L = W[%s];", reg, ptr_name);
2955 addr = PREG (ptr);
2956 val = GET_WORD (addr);
2957 STORE (DREG (reg), (DREG (reg) & 0xFFFF0000) | val);
2958 }
2959 else if (aop == 2 && W == 0 && idx == ptr)
2960 {
2961 TRACE_INSN (cpu, "R%i.H = W[%s];", reg, ptr_name);
2962 addr = PREG (ptr);
2963 val = GET_WORD (addr);
2964 STORE (DREG (reg), (DREG (reg) & 0xFFFF) | (val << 16));
2965 }
2966 else if (aop == 1 && W == 1 && idx == ptr)
2967 {
2968 TRACE_INSN (cpu, "W[%s] = R%i.L;", ptr_name, reg);
2969 addr = PREG (ptr);
2970 PUT_WORD (addr, DREG (reg));
2971 }
2972 else if (aop == 2 && W == 1 && idx == ptr)
2973 {
2974 TRACE_INSN (cpu, "W[%s] = R%i.H;", ptr_name, reg);
2975 addr = PREG (ptr);
2976 PUT_WORD (addr, DREG (reg) >> 16);
2977 }
2978 else if (aop == 0 && W == 0)
2979 {
2980 TRACE_INSN (cpu, "R%i = [%s ++ %s];", reg, ptr_name, idx_name);
2981 addr = PREG (ptr);
2982 val = GET_LONG (addr);
2983 STORE (DREG (reg), val);
2984 if (ptr != idx)
2985 STORE (PREG (ptr), addr + PREG (idx));
2986 }
2987 else if (aop == 1 && W == 0)
2988 {
2989 TRACE_INSN (cpu, "R%i.L = W[%s ++ %s];", reg, ptr_name, idx_name);
2990 addr = PREG (ptr);
2991 val = GET_WORD (addr);
2992 STORE (DREG (reg), (DREG (reg) & 0xFFFF0000) | val);
2993 if (ptr != idx)
2994 STORE (PREG (ptr), addr + PREG (idx));
2995 }
2996 else if (aop == 2 && W == 0)
2997 {
2998 TRACE_INSN (cpu, "R%i.H = W[%s ++ %s];", reg, ptr_name, idx_name);
2999 addr = PREG (ptr);
3000 val = GET_WORD (addr);
3001 STORE (DREG (reg), (DREG (reg) & 0xFFFF) | (val << 16));
3002 if (ptr != idx)
3003 STORE (PREG (ptr), addr + PREG (idx));
3004 }
3005 else if (aop == 3 && W == 0)
3006 {
3007 TRACE_INSN (cpu, "R%i = W[%s ++ %s] (Z);", reg, ptr_name, idx_name);
3008 addr = PREG (ptr);
3009 val = GET_WORD (addr);
3010 STORE (DREG (reg), val);
3011 if (ptr != idx)
3012 STORE (PREG (ptr), addr + PREG (idx));
3013 }
3014 else if (aop == 3 && W == 1)
3015 {
3016 TRACE_INSN (cpu, "R%i = W[%s ++ %s] (X);", reg, ptr_name, idx_name);
3017 addr = PREG (ptr);
3018 val = GET_WORD (addr);
3019 STORE (DREG (reg), (bs32) (bs16) val);
3020 if (ptr != idx)
3021 STORE (PREG (ptr), addr + PREG (idx));
3022 }
3023 else if (aop == 0 && W == 1)
3024 {
3025 TRACE_INSN (cpu, "[%s ++ %s] = R%i;", ptr_name, idx_name, reg);
3026 addr = PREG (ptr);
3027 PUT_LONG (addr, DREG (reg));
3028 if (ptr != idx)
3029 STORE (PREG (ptr), addr + PREG (idx));
3030 }
3031 else if (aop == 1 && W == 1)
3032 {
3033 TRACE_INSN (cpu, "W[%s ++ %s] = R%i.L;", ptr_name, idx_name, reg);
3034 addr = PREG (ptr);
3035 PUT_WORD (addr, DREG (reg));
3036 if (ptr != idx)
3037 STORE (PREG (ptr), addr + PREG (idx));
3038 }
3039 else if (aop == 2 && W == 1)
3040 {
3041 TRACE_INSN (cpu, "W[%s ++ %s] = R%i.H;", ptr_name, idx_name, reg);
3042 addr = PREG (ptr);
3043 PUT_WORD (addr, DREG (reg) >> 16);
3044 if (ptr != idx)
3045 STORE (PREG (ptr), addr + PREG (idx));
3046 }
3047 else
3048 illegal_instruction_or_combination (cpu);
3049 }
3050
3051 static void
3052 decode_dagMODim_0 (SIM_CPU *cpu, bu16 iw0)
3053 {
3054 /* dagMODim
3055 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3056 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 0 |.br| 1 | 1 |.op|.m.....|.i.....|
3057 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3058 int i = ((iw0 >> DagMODim_i_bits) & DagMODim_i_mask);
3059 int m = ((iw0 >> DagMODim_m_bits) & DagMODim_m_mask);
3060 int br = ((iw0 >> DagMODim_br_bits) & DagMODim_br_mask);
3061 int op = ((iw0 >> DagMODim_op_bits) & DagMODim_op_mask);
3062
3063 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dagMODim);
3064 TRACE_EXTRACT (cpu, "%s: br:%i op:%i m:%i i:%i", __func__, br, op, m, i);
3065
3066 if (PARALLEL_GROUP == BFIN_PARALLEL_GROUP2)
3067 illegal_instruction_combination (cpu);
3068
3069 if (op == 0 && br == 1)
3070 {
3071 TRACE_INSN (cpu, "I%i += M%i (BREV);", i, m);
3072 SET_IREG (i, add_brev (IREG (i), MREG (m)));
3073 }
3074 else if (op == 0)
3075 {
3076 TRACE_INSN (cpu, "I%i += M%i;", i, m);
3077 dagadd (cpu, i, MREG (m));
3078 }
3079 else if (op == 1 && br == 0)
3080 {
3081 TRACE_INSN (cpu, "I%i -= M%i;", i, m);
3082 dagsub (cpu, i, MREG (m));
3083 }
3084 else
3085 illegal_instruction_or_combination (cpu);
3086 }
3087
3088 static void
3089 decode_dagMODik_0 (SIM_CPU *cpu, bu16 iw0)
3090 {
3091 /* dagMODik
3092 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3093 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 0 |.op....|.i.....|
3094 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3095 int i = ((iw0 >> DagMODik_i_bits) & DagMODik_i_mask);
3096 int op = ((iw0 >> DagMODik_op_bits) & DagMODik_op_mask);
3097
3098 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dagMODik);
3099 TRACE_EXTRACT (cpu, "%s: op:%i i:%i", __func__, op, i);
3100
3101 if (PARALLEL_GROUP == BFIN_PARALLEL_GROUP2)
3102 illegal_instruction_combination (cpu);
3103
3104 if (op == 0)
3105 {
3106 TRACE_INSN (cpu, "I%i += 2;", i);
3107 dagadd (cpu, i, 2);
3108 }
3109 else if (op == 1)
3110 {
3111 TRACE_INSN (cpu, "I%i -= 2;", i);
3112 dagsub (cpu, i, 2);
3113 }
3114 else if (op == 2)
3115 {
3116 TRACE_INSN (cpu, "I%i += 4;", i);
3117 dagadd (cpu, i, 4);
3118 }
3119 else if (op == 3)
3120 {
3121 TRACE_INSN (cpu, "I%i -= 4;", i);
3122 dagsub (cpu, i, 4);
3123 }
3124 else
3125 illegal_instruction_or_combination (cpu);
3126 }
3127
3128 static void
3129 decode_dspLDST_0 (SIM_CPU *cpu, bu16 iw0)
3130 {
3131 /* dspLDST
3132 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3133 | 1 | 0 | 0 | 1 | 1 | 1 |.W.|.aop...|.m.....|.i.....|.reg.......|
3134 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3135 int i = ((iw0 >> DspLDST_i_bits) & DspLDST_i_mask);
3136 int m = ((iw0 >> DspLDST_m_bits) & DspLDST_m_mask);
3137 int W = ((iw0 >> DspLDST_W_bits) & DspLDST_W_mask);
3138 int aop = ((iw0 >> DspLDST_aop_bits) & DspLDST_aop_mask);
3139 int reg = ((iw0 >> DspLDST_reg_bits) & DspLDST_reg_mask);
3140 bu32 addr;
3141
3142 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dspLDST);
3143 TRACE_EXTRACT (cpu, "%s: aop:%i m:%i i:%i reg:%i", __func__, aop, m, i, reg);
3144
3145 if (aop == 0 && W == 0 && m == 0)
3146 {
3147 TRACE_INSN (cpu, "R%i = [I%i++];", reg, i);
3148 addr = IREG (i);
3149 if (DIS_ALGN_EXPT & 0x1)
3150 addr &= ~3;
3151 dagadd (cpu, i, 4);
3152 STORE (DREG (reg), GET_LONG (addr));
3153 }
3154 else if (aop == 0 && W == 0 && m == 1)
3155 {
3156 TRACE_INSN (cpu, "R%i.L = W[I%i++];", reg, i);
3157 addr = IREG (i);
3158 dagadd (cpu, i, 2);
3159 STORE (DREG (reg), (DREG (reg) & 0xFFFF0000) | GET_WORD (addr));
3160 }
3161 else if (aop == 0 && W == 0 && m == 2)
3162 {
3163 TRACE_INSN (cpu, "R%i.H = W[I%i++];", reg, i);
3164 addr = IREG (i);
3165 dagadd (cpu, i, 2);
3166 STORE (DREG (reg), (DREG (reg) & 0xFFFF) | (GET_WORD (addr) << 16));
3167 }
3168 else if (aop == 1 && W == 0 && m == 0)
3169 {
3170 TRACE_INSN (cpu, "R%i = [I%i--];", reg, i);
3171 addr = IREG (i);
3172 if (DIS_ALGN_EXPT & 0x1)
3173 addr &= ~3;
3174 dagsub (cpu, i, 4);
3175 STORE (DREG (reg), GET_LONG (addr));
3176 }
3177 else if (aop == 1 && W == 0 && m == 1)
3178 {
3179 TRACE_INSN (cpu, "R%i.L = W[I%i--];", reg, i);
3180 addr = IREG (i);
3181 dagsub (cpu, i, 2);
3182 STORE (DREG (reg), (DREG (reg) & 0xFFFF0000) | GET_WORD (addr));
3183 }
3184 else if (aop == 1 && W == 0 && m == 2)
3185 {
3186 TRACE_INSN (cpu, "R%i.H = W[I%i--];", reg, i);
3187 addr = IREG (i);
3188 dagsub (cpu, i, 2);
3189 STORE (DREG (reg), (DREG (reg) & 0xFFFF) | (GET_WORD (addr) << 16));
3190 }
3191 else if (aop == 2 && W == 0 && m == 0)
3192 {
3193 TRACE_INSN (cpu, "R%i = [I%i];", reg, i);
3194 addr = IREG (i);
3195 if (DIS_ALGN_EXPT & 0x1)
3196 addr &= ~3;
3197 STORE (DREG (reg), GET_LONG (addr));
3198 }
3199 else if (aop == 2 && W == 0 && m == 1)
3200 {
3201 TRACE_INSN (cpu, "R%i.L = W[I%i];", reg, i);
3202 addr = IREG (i);
3203 STORE (DREG (reg), (DREG (reg) & 0xFFFF0000) | GET_WORD (addr));
3204 }
3205 else if (aop == 2 && W == 0 && m == 2)
3206 {
3207 TRACE_INSN (cpu, "R%i.H = W[I%i];", reg, i);
3208 addr = IREG (i);
3209 STORE (DREG (reg), (DREG (reg) & 0xFFFF) | (GET_WORD (addr) << 16));
3210 }
3211 else if (aop == 0 && W == 1 && m == 0)
3212 {
3213 TRACE_INSN (cpu, "[I%i++] = R%i;", i, reg);
3214 addr = IREG (i);
3215 dagadd (cpu, i, 4);
3216 PUT_LONG (addr, DREG (reg));
3217 }
3218 else if (aop == 0 && W == 1 && m == 1)
3219 {
3220 TRACE_INSN (cpu, "W[I%i++] = R%i.L;", i, reg);
3221 addr = IREG (i);
3222 dagadd (cpu, i, 2);
3223 PUT_WORD (addr, DREG (reg));
3224 }
3225 else if (aop == 0 && W == 1 && m == 2)
3226 {
3227 TRACE_INSN (cpu, "W[I%i++] = R%i.H;", i, reg);
3228 addr = IREG (i);
3229 dagadd (cpu, i, 2);
3230 PUT_WORD (addr, DREG (reg) >> 16);
3231 }
3232 else if (aop == 1 && W == 1 && m == 0)
3233 {
3234 TRACE_INSN (cpu, "[I%i--] = R%i;", i, reg);
3235 addr = IREG (i);
3236 dagsub (cpu, i, 4);
3237 PUT_LONG (addr, DREG (reg));
3238 }
3239 else if (aop == 1 && W == 1 && m == 1)
3240 {
3241 TRACE_INSN (cpu, "W[I%i--] = R%i.L;", i, reg);
3242 addr = IREG (i);
3243 dagsub (cpu, i, 2);
3244 PUT_WORD (addr, DREG (reg));
3245 }
3246 else if (aop == 1 && W == 1 && m == 2)
3247 {
3248 TRACE_INSN (cpu, "W[I%i--] = R%i.H;", i, reg);
3249 addr = IREG (i);
3250 dagsub (cpu, i, 2);
3251 PUT_WORD (addr, DREG (reg) >> 16);
3252 }
3253 else if (aop == 2 && W == 1 && m == 0)
3254 {
3255 TRACE_INSN (cpu, "[I%i] = R%i;", i, reg);
3256 addr = IREG (i);
3257 PUT_LONG (addr, DREG (reg));
3258 }
3259 else if (aop == 2 && W == 1 && m == 1)
3260 {
3261 TRACE_INSN (cpu, "W[I%i] = R%i.L;", i, reg);
3262 addr = IREG (i);
3263 PUT_WORD (addr, DREG (reg));
3264 }
3265 else if (aop == 2 && W == 1 && m == 2)
3266 {
3267 TRACE_INSN (cpu, "W[I%i] = R%i.H;", i, reg);
3268 addr = IREG (i);
3269 PUT_WORD (addr, DREG (reg) >> 16);
3270 }
3271 else if (aop == 3 && W == 0)
3272 {
3273 TRACE_INSN (cpu, "R%i = [I%i ++ M%i];", reg, i, m);
3274 addr = IREG (i);
3275 if (DIS_ALGN_EXPT & 0x1)
3276 addr &= ~3;
3277 dagadd (cpu, i, MREG (m));
3278 STORE (DREG (reg), GET_LONG (addr));
3279 }
3280 else if (aop == 3 && W == 1)
3281 {
3282 TRACE_INSN (cpu, "[I%i ++ M%i] = R%i;", i, m, reg);
3283 addr = IREG (i);
3284 dagadd (cpu, i, MREG (m));
3285 PUT_LONG (addr, DREG (reg));
3286 }
3287 else
3288 illegal_instruction_or_combination (cpu);
3289 }
3290
3291 static void
3292 decode_LDST_0 (SIM_CPU *cpu, bu16 iw0)
3293 {
3294 /* LDST
3295 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3296 | 1 | 0 | 0 | 1 |.sz....|.W.|.aop...|.Z.|.ptr.......|.reg.......|
3297 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3298 int Z = ((iw0 >> LDST_Z_bits) & LDST_Z_mask);
3299 int W = ((iw0 >> LDST_W_bits) & LDST_W_mask);
3300 int sz = ((iw0 >> LDST_sz_bits) & LDST_sz_mask);
3301 int aop = ((iw0 >> LDST_aop_bits) & LDST_aop_mask);
3302 int reg = ((iw0 >> LDST_reg_bits) & LDST_reg_mask);
3303 int ptr = ((iw0 >> LDST_ptr_bits) & LDST_ptr_mask);
3304 const char * const posts[] = { "++", "--", "", "<INV>" };
3305 const char *post = posts[aop];
3306 const char *ptr_name = get_preg_name (ptr);
3307
3308 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LDST);
3309 TRACE_EXTRACT (cpu, "%s: sz:%i W:%i aop:%i Z:%i ptr:%i reg:%i",
3310 __func__, sz, W, aop, Z, ptr, reg);
3311
3312 if (aop == 3 || PARALLEL_GROUP == BFIN_PARALLEL_GROUP2)
3313 illegal_instruction_or_combination (cpu);
3314
3315 if (W == 0)
3316 {
3317 if (sz == 0 && Z == 0)
3318 {
3319 TRACE_INSN (cpu, "R%i = [%s%s];", reg, ptr_name, post);
3320 SET_DREG (reg, GET_LONG (PREG (ptr)));
3321 }
3322 else if (sz == 0 && Z == 1)
3323 {
3324 TRACE_INSN (cpu, "%s = [%s%s];", get_preg_name (reg), ptr_name, post);
3325 if (aop < 2 && ptr == reg)
3326 illegal_instruction_combination (cpu);
3327 SET_PREG (reg, GET_LONG (PREG (ptr)));
3328 }
3329 else if (sz == 1 && Z == 0)
3330 {
3331 TRACE_INSN (cpu, "R%i = W[%s%s] (Z);", reg, ptr_name, post);
3332 SET_DREG (reg, GET_WORD (PREG (ptr)));
3333 }
3334 else if (sz == 1 && Z == 1)
3335 {
3336 TRACE_INSN (cpu, "R%i = W[%s%s] (X);", reg, ptr_name, post);
3337 SET_DREG (reg, (bs32) (bs16) GET_WORD (PREG (ptr)));
3338 }
3339 else if (sz == 2 && Z == 0)
3340 {
3341 TRACE_INSN (cpu, "R%i = B[%s%s] (Z);", reg, ptr_name, post);
3342 SET_DREG (reg, GET_BYTE (PREG (ptr)));
3343 }
3344 else if (sz == 2 && Z == 1)
3345 {
3346 TRACE_INSN (cpu, "R%i = B[%s%s] (X);", reg, ptr_name, post);
3347 SET_DREG (reg, (bs32) (bs8) GET_BYTE (PREG (ptr)));
3348 }
3349 else
3350 illegal_instruction_or_combination (cpu);
3351 }
3352 else
3353 {
3354 if (sz == 0 && Z == 0)
3355 {
3356 TRACE_INSN (cpu, "[%s%s] = R%i;", ptr_name, post, reg);
3357 PUT_LONG (PREG (ptr), DREG (reg));
3358 }
3359 else if (sz == 0 && Z == 1)
3360 {
3361 TRACE_INSN (cpu, "[%s%s] = %s;", ptr_name, post, get_preg_name (reg));
3362 PUT_LONG (PREG (ptr), PREG (reg));
3363 }
3364 else if (sz == 1 && Z == 0)
3365 {
3366 TRACE_INSN (cpu, "W[%s%s] = R%i;", ptr_name, post, reg);
3367 PUT_WORD (PREG (ptr), DREG (reg));
3368 }
3369 else if (sz == 2 && Z == 0)
3370 {
3371 TRACE_INSN (cpu, "B[%s%s] = R%i;", ptr_name, post, reg);
3372 PUT_BYTE (PREG (ptr), DREG (reg));
3373 }
3374 else
3375 illegal_instruction_or_combination (cpu);
3376 }
3377
3378 if (aop == 0)
3379 SET_PREG (ptr, PREG (ptr) + (1 << (2 - sz)));
3380 if (aop == 1)
3381 SET_PREG (ptr, PREG (ptr) - (1 << (2 - sz)));
3382 }
3383
3384 static void
3385 decode_LDSTiiFP_0 (SIM_CPU *cpu, bu16 iw0)
3386 {
3387 /* LDSTiiFP
3388 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3389 | 1 | 0 | 1 | 1 | 1 | 0 |.W.|.offset............|.reg...........|
3390 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3391 /* This isn't exactly a grp:reg as this insn only supports Dregs & Pregs,
3392 but for our usage, its functionality the same thing. */
3393 int grp = ((iw0 >> 3) & 0x1);
3394 int reg = ((iw0 >> LDSTiiFP_reg_bits) & 0x7 /*LDSTiiFP_reg_mask*/);
3395 int offset = ((iw0 >> LDSTiiFP_offset_bits) & LDSTiiFP_offset_mask);
3396 int W = ((iw0 >> LDSTiiFP_W_bits) & LDSTiiFP_W_mask);
3397 bu32 imm = negimm5s4 (offset);
3398 bu32 ea = FPREG + imm;
3399 const char *imm_str = negimm5s4_str (offset);
3400 const char *reg_name = get_allreg_name (grp, reg);
3401
3402 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LDSTiiFP);
3403 TRACE_EXTRACT (cpu, "%s: W:%i offset:%#x grp:%i reg:%i", __func__,
3404 W, offset, grp, reg);
3405 TRACE_DECODE (cpu, "%s: negimm5s4:%#x", __func__, imm);
3406
3407 if (PARALLEL_GROUP == BFIN_PARALLEL_GROUP2)
3408 illegal_instruction_or_combination (cpu);
3409
3410 if (W == 0)
3411 {
3412 TRACE_INSN (cpu, "%s = [FP + %s];", reg_name, imm_str);
3413 reg_write (cpu, grp, reg, GET_LONG (ea));
3414 }
3415 else
3416 {
3417 TRACE_INSN (cpu, "[FP + %s] = %s;", imm_str, reg_name);
3418 PUT_LONG (ea, reg_read (cpu, grp, reg));
3419 }
3420 }
3421
3422 static void
3423 decode_LDSTii_0 (SIM_CPU *cpu, bu16 iw0)
3424 {
3425 /* LDSTii
3426 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3427 | 1 | 0 | 1 |.W.|.op....|.offset........|.ptr.......|.reg.......|
3428 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3429 int reg = ((iw0 >> LDSTii_reg_bit) & LDSTii_reg_mask);
3430 int ptr = ((iw0 >> LDSTii_ptr_bit) & LDSTii_ptr_mask);
3431 int offset = ((iw0 >> LDSTii_offset_bit) & LDSTii_offset_mask);
3432 int op = ((iw0 >> LDSTii_op_bit) & LDSTii_op_mask);
3433 int W = ((iw0 >> LDSTii_W_bit) & LDSTii_W_mask);
3434 bu32 imm, ea;
3435 const char *imm_str;
3436 const char *ptr_name = get_preg_name (ptr);
3437
3438 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LDSTii);
3439 TRACE_EXTRACT (cpu, "%s: W:%i op:%i offset:%#x ptr:%i reg:%i",
3440 __func__, W, op, offset, ptr, reg);
3441
3442 if (op == 0 || op == 3)
3443 imm = uimm4s4 (offset), imm_str = uimm4s4_str (offset);
3444 else
3445 imm = uimm4s2 (offset), imm_str = uimm4s2_str (offset);
3446 ea = PREG (ptr) + imm;
3447
3448 TRACE_DECODE (cpu, "%s: uimm4s4/uimm4s2:%#x", __func__, imm);
3449
3450 if (PARALLEL_GROUP == BFIN_PARALLEL_GROUP2)
3451 illegal_instruction_combination (cpu);
3452
3453 if (W == 1 && op == 2)
3454 illegal_instruction (cpu);
3455
3456 if (W == 0)
3457 {
3458 if (op == 0)
3459 {
3460 TRACE_INSN (cpu, "R%i = [%s + %s];", reg, ptr_name, imm_str);
3461 SET_DREG (reg, GET_LONG (ea));
3462 }
3463 else if (op == 1)
3464 {
3465 TRACE_INSN (cpu, "R%i = W[%s + %s] (Z);", reg, ptr_name, imm_str);
3466 SET_DREG (reg, GET_WORD (ea));
3467 }
3468 else if (op == 2)
3469 {
3470 TRACE_INSN (cpu, "R%i = W[%s + %s] (X);", reg, ptr_name, imm_str);
3471 SET_DREG (reg, (bs32) (bs16) GET_WORD (ea));
3472 }
3473 else if (op == 3)
3474 {
3475 TRACE_INSN (cpu, "%s = [%s + %s];",
3476 get_preg_name (reg), ptr_name, imm_str);
3477 SET_PREG (reg, GET_LONG (ea));
3478 }
3479 }
3480 else
3481 {
3482 if (op == 0)
3483 {
3484 TRACE_INSN (cpu, "[%s + %s] = R%i;", ptr_name, imm_str, reg);
3485 PUT_LONG (ea, DREG (reg));
3486 }
3487 else if (op == 1)
3488 {
3489 TRACE_INSN (cpu, "W[%s + %s] = R%i;", ptr_name, imm_str, reg);
3490 PUT_WORD (ea, DREG (reg));
3491 }
3492 else if (op == 3)
3493 {
3494 TRACE_INSN (cpu, "[%s + %s] = %s;",
3495 ptr_name, imm_str, get_preg_name (reg));
3496 PUT_LONG (ea, PREG (reg));
3497 }
3498 }
3499 }
3500
3501 static void
3502 decode_LoopSetup_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1, bu32 pc)
3503 {
3504 /* LoopSetup
3505 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3506 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |.rop...|.c.|.soffset.......|
3507 |.reg...........| - | - |.eoffset...............................|
3508 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3509 int c = ((iw0 >> (LoopSetup_c_bits - 16)) & LoopSetup_c_mask);
3510 int reg = ((iw1 >> LoopSetup_reg_bits) & LoopSetup_reg_mask);
3511 int rop = ((iw0 >> (LoopSetup_rop_bits - 16)) & LoopSetup_rop_mask);
3512 int soffset = ((iw0 >> (LoopSetup_soffset_bits - 16)) & LoopSetup_soffset_mask);
3513 int eoffset = ((iw1 >> LoopSetup_eoffset_bits) & LoopSetup_eoffset_mask);
3514 int spcrel = pcrel4 (soffset);
3515 int epcrel = lppcrel10 (eoffset);
3516
3517 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LoopSetup);
3518 TRACE_EXTRACT (cpu, "%s: rop:%i c:%i soffset:%i reg:%i eoffset:%i",
3519 __func__, rop, c, soffset, reg, eoffset);
3520 TRACE_DECODE (cpu, "%s: s_pcrel4:%#x e_lppcrel10:%#x",
3521 __func__, spcrel, epcrel);
3522
3523 if (reg > 7)
3524 illegal_instruction (cpu);
3525
3526 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
3527 illegal_instruction_combination (cpu);
3528
3529 if (rop == 0)
3530 {
3531 TRACE_INSN (cpu, "LSETUP (%#x, %#x) LC%i;", spcrel, epcrel, c);
3532 }
3533 else if (rop == 1 && reg <= 7)
3534 {
3535 TRACE_INSN (cpu, "LSETUP (%#x, %#x) LC%i = %s;",
3536 spcrel, epcrel, c, get_preg_name (reg));
3537 SET_LCREG (c, PREG (reg));
3538 }
3539 else if (rop == 3 && reg <= 7)
3540 {
3541 TRACE_INSN (cpu, "LSETUP (%#x, %#x) LC%i = %s >> 1;",
3542 spcrel, epcrel, c, get_preg_name (reg));
3543 SET_LCREG (c, PREG (reg) >> 1);
3544 }
3545 else
3546 illegal_instruction (cpu);
3547
3548 SET_LTREG (c, pc + spcrel);
3549 SET_LBREG (c, pc + epcrel);
3550 }
3551
3552 static void
3553 decode_LDIMMhalf_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
3554 {
3555 /* LDIMMhalf
3556 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3557 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 |.Z.|.H.|.S.|.grp...|.reg.......|
3558 |.hword.........................................................|
3559 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3560 int H = ((iw0 >> (LDIMMhalf_H_bits - 16)) & LDIMMhalf_H_mask);
3561 int Z = ((iw0 >> (LDIMMhalf_Z_bits - 16)) & LDIMMhalf_Z_mask);
3562 int S = ((iw0 >> (LDIMMhalf_S_bits - 16)) & LDIMMhalf_S_mask);
3563 int reg = ((iw0 >> (LDIMMhalf_reg_bits - 16)) & LDIMMhalf_reg_mask);
3564 int grp = ((iw0 >> (LDIMMhalf_grp_bits - 16)) & LDIMMhalf_grp_mask);
3565 int hword = ((iw1 >> LDIMMhalf_hword_bits) & LDIMMhalf_hword_mask);
3566 bu32 val;
3567 const char *val_str;
3568 const char *reg_name = get_allreg_name (grp, reg);
3569
3570 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LDIMMhalf);
3571 TRACE_EXTRACT (cpu, "%s: Z:%i H:%i S:%i grp:%i reg:%i hword:%#x",
3572 __func__, Z, H, S, grp, reg, hword);
3573
3574 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
3575 illegal_instruction_combination (cpu);
3576
3577 if (S == 1)
3578 val = imm16 (hword), val_str = imm16_str (hword);
3579 else
3580 val = luimm16 (hword), val_str = luimm16_str (hword);
3581
3582 if (H == 0 && S == 1 && Z == 0)
3583 {
3584 TRACE_INSN (cpu, "%s = %s (X);", reg_name, val_str);
3585 }
3586 else if (H == 0 && S == 0 && Z == 1)
3587 {
3588 TRACE_INSN (cpu, "%s = %s (Z);", reg_name, val_str);
3589 }
3590 else if (H == 0 && S == 0 && Z == 0)
3591 {
3592 TRACE_INSN (cpu, "%s.L = %s;", reg_name, val_str);
3593 val = REG_H_L (reg_read (cpu, grp, reg), val);
3594 }
3595 else if (H == 1 && S == 0 && Z == 0)
3596 {
3597 TRACE_INSN (cpu, "%s.H = %s;", reg_name, val_str);
3598 val = REG_H_L (val << 16, reg_read (cpu, grp, reg));
3599 }
3600 else
3601 illegal_instruction (cpu);
3602
3603 reg_write (cpu, grp, reg, val);
3604 }
3605
3606 static void
3607 decode_CALLa_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1, bu32 pc)
3608 {
3609 /* CALLa
3610 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3611 | 1 | 1 | 1 | 0 | 0 | 0 | 1 |.S.|.msw...........................|
3612 |.lsw...........................................................|
3613 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3614 int S = ((iw0 >> (CALLa_S_bits - 16)) & CALLa_S_mask);
3615 int lsw = ((iw1 >> 0) & 0xffff);
3616 int msw = ((iw0 >> 0) & 0xff);
3617 int pcrel = pcrel24 ((msw << 16) | lsw);
3618 bu32 newpc = pc + pcrel;
3619
3620 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_CALLa);
3621 TRACE_EXTRACT (cpu, "%s: S:%i msw:%#x lsw:%#x", __func__, S, msw, lsw);
3622 TRACE_DECODE (cpu, "%s: pcrel24:%#x", __func__, pcrel);
3623
3624 TRACE_INSN (cpu, "%s %#x;", S ? "CALL" : "JUMP.L", pcrel);
3625
3626 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
3627 illegal_instruction_combination (cpu);
3628
3629 if (S == 1)
3630 {
3631 BFIN_TRACE_BRANCH (cpu, pc, newpc, -1, "CALL");
3632 SET_RETSREG (hwloop_get_next_pc (cpu, pc, 4));
3633 }
3634 else
3635 BFIN_TRACE_BRANCH (cpu, pc, newpc, -1, "JUMP.L");
3636
3637 SET_PCREG (newpc);
3638 BFIN_CPU_STATE.did_jump = true;
3639 PROFILE_BRANCH_TAKEN (cpu);
3640 CYCLE_DELAY = 5;
3641 }
3642
3643 static void
3644 decode_LDSTidxI_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
3645 {
3646 /* LDSTidxI
3647 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3648 | 1 | 1 | 1 | 0 | 0 | 1 |.W.|.Z.|.sz....|.ptr.......|.reg.......|
3649 |.offset........................................................|
3650 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3651 int Z = ((iw0 >> (LDSTidxI_Z_bits - 16)) & LDSTidxI_Z_mask);
3652 int W = ((iw0 >> (LDSTidxI_W_bits - 16)) & LDSTidxI_W_mask);
3653 int sz = ((iw0 >> (LDSTidxI_sz_bits - 16)) & LDSTidxI_sz_mask);
3654 int reg = ((iw0 >> (LDSTidxI_reg_bits - 16)) & LDSTidxI_reg_mask);
3655 int ptr = ((iw0 >> (LDSTidxI_ptr_bits - 16)) & LDSTidxI_ptr_mask);
3656 int offset = ((iw1 >> LDSTidxI_offset_bits) & LDSTidxI_offset_mask);
3657 const char *ptr_name = get_preg_name (ptr);
3658 bu32 imm_16s4 = imm16s4 (offset);
3659 bu32 imm_16s2 = imm16s2 (offset);
3660 bu32 imm_16 = imm16 (offset);
3661
3662 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LDSTidxI);
3663 TRACE_EXTRACT (cpu, "%s: W:%i Z:%i sz:%i ptr:%i reg:%i offset:%#x",
3664 __func__, W, Z, sz, ptr, reg, offset);
3665
3666 if (sz == 3)
3667 illegal_instruction (cpu);
3668
3669 if (W == 0)
3670 {
3671 if (sz == 0 && Z == 0)
3672 {
3673 TRACE_INSN (cpu, "R%i = [%s + %s];",
3674 reg, ptr_name, imm16s4_str (offset));
3675 SET_DREG (reg, GET_LONG (PREG (ptr) + imm_16s4));
3676 }
3677 else if (sz == 0 && Z == 1)
3678 {
3679 TRACE_INSN (cpu, "%s = [%s + %s];",
3680 get_preg_name (reg), ptr_name, imm16s4_str (offset));
3681 SET_PREG (reg, GET_LONG (PREG (ptr) + imm_16s4));
3682 }
3683 else if (sz == 1 && Z == 0)
3684 {
3685 TRACE_INSN (cpu, "R%i = W[%s + %s] (Z);",
3686 reg, ptr_name, imm16s2_str (offset));
3687 SET_DREG (reg, GET_WORD (PREG (ptr) + imm_16s2));
3688 }
3689 else if (sz == 1 && Z == 1)
3690 {
3691 TRACE_INSN (cpu, "R%i = W[%s + %s] (X);",
3692 reg, ptr_name, imm16s2_str (offset));
3693 SET_DREG (reg, (bs32) (bs16) GET_WORD (PREG (ptr) + imm_16s2));
3694 }
3695 else if (sz == 2 && Z == 0)
3696 {
3697 TRACE_INSN (cpu, "R%i = B[%s + %s] (Z);",
3698 reg, ptr_name, imm16_str (offset));
3699 SET_DREG (reg, GET_BYTE (PREG (ptr) + imm_16));
3700 }
3701 else if (sz == 2 && Z == 1)
3702 {
3703 TRACE_INSN (cpu, "R%i = B[%s + %s] (X);",
3704 reg, ptr_name, imm16_str (offset));
3705 SET_DREG (reg, (bs32) (bs8) GET_BYTE (PREG (ptr) + imm_16));
3706 }
3707 }
3708 else
3709 {
3710 if (sz != 0 && Z != 0)
3711 illegal_instruction (cpu);
3712
3713 if (sz == 0 && Z == 0)
3714 {
3715 TRACE_INSN (cpu, "[%s + %s] = R%i;", ptr_name,
3716 imm16s4_str (offset), reg);
3717 PUT_LONG (PREG (ptr) + imm_16s4, DREG (reg));
3718 }
3719 else if (sz == 0 && Z == 1)
3720 {
3721 TRACE_INSN (cpu, "[%s + %s] = %s;",
3722 ptr_name, imm16s4_str (offset), get_preg_name (reg));
3723 PUT_LONG (PREG (ptr) + imm_16s4, PREG (reg));
3724 }
3725 else if (sz == 1 && Z == 0)
3726 {
3727 TRACE_INSN (cpu, "W[%s + %s] = R%i;",
3728 ptr_name, imm16s2_str (offset), reg);
3729 PUT_WORD (PREG (ptr) + imm_16s2, DREG (reg));
3730 }
3731 else if (sz == 2 && Z == 0)
3732 {
3733 TRACE_INSN (cpu, "B[%s + %s] = R%i;",
3734 ptr_name, imm16_str (offset), reg);
3735 PUT_BYTE (PREG (ptr) + imm_16, DREG (reg));
3736 }
3737 }
3738 }
3739
3740 static void
3741 decode_linkage_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
3742 {
3743 /* linkage
3744 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3745 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |.R.|
3746 |.framesize.....................................................|
3747 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3748 int R = ((iw0 >> (Linkage_R_bits - 16)) & Linkage_R_mask);
3749 int framesize = ((iw1 >> Linkage_framesize_bits) & Linkage_framesize_mask);
3750 bu32 sp;
3751
3752 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_linkage);
3753 TRACE_EXTRACT (cpu, "%s: R:%i framesize:%#x", __func__, R, framesize);
3754
3755 if (R == 0)
3756 {
3757 int size = uimm16s4 (framesize);
3758 sp = SPREG;
3759 TRACE_INSN (cpu, "LINK %s;", uimm16s4_str (framesize));
3760 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
3761 illegal_instruction_combination (cpu);
3762 sp -= 4;
3763 PUT_LONG (sp, RETSREG);
3764 sp -= 4;
3765 PUT_LONG (sp, FPREG);
3766 SET_FPREG (sp);
3767 sp -= size;
3768 CYCLE_DELAY = 3;
3769 }
3770 else
3771 {
3772 /* Restore SP from FP. */
3773 sp = FPREG;
3774 TRACE_INSN (cpu, "UNLINK;");
3775 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
3776 illegal_instruction_combination (cpu);
3777 SET_FPREG (GET_LONG (sp));
3778 sp += 4;
3779 SET_RETSREG (GET_LONG (sp));
3780 sp += 4;
3781 CYCLE_DELAY = 2;
3782 }
3783
3784 SET_SPREG (sp);
3785 }
3786
3787 static void
3788 decode_dsp32mac_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
3789 {
3790 /* dsp32mac
3791 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3792 | 1 | 1 | 0 | 0 |.M.| 0 | 0 |.mmod..........|.MM|.P.|.w1|.op1...|
3793 |.h01|.h11|.w0|.op0...|.h00|.h10|.dst.......|.src0......|.src1..|
3794 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3795 int op1 = ((iw0 >> (DSP32Mac_op1_bits - 16)) & DSP32Mac_op1_mask);
3796 int w1 = ((iw0 >> (DSP32Mac_w1_bits - 16)) & DSP32Mac_w1_mask);
3797 int P = ((iw0 >> (DSP32Mac_p_bits - 16)) & DSP32Mac_p_mask);
3798 int MM = ((iw0 >> (DSP32Mac_MM_bits - 16)) & DSP32Mac_MM_mask);
3799 int mmod = ((iw0 >> (DSP32Mac_mmod_bits - 16)) & DSP32Mac_mmod_mask);
3800 int M = ((iw0 >> (DSP32Mac_M_bits - 16)) & DSP32Mac_M_mask);
3801 int w0 = ((iw1 >> DSP32Mac_w0_bits) & DSP32Mac_w0_mask);
3802 int src0 = ((iw1 >> DSP32Mac_src0_bits) & DSP32Mac_src0_mask);
3803 int src1 = ((iw1 >> DSP32Mac_src1_bits) & DSP32Mac_src1_mask);
3804 int dst = ((iw1 >> DSP32Mac_dst_bits) & DSP32Mac_dst_mask);
3805 int h10 = ((iw1 >> DSP32Mac_h10_bits) & DSP32Mac_h10_mask);
3806 int h00 = ((iw1 >> DSP32Mac_h00_bits) & DSP32Mac_h00_mask);
3807 int op0 = ((iw1 >> DSP32Mac_op0_bits) & DSP32Mac_op0_mask);
3808 int h11 = ((iw1 >> DSP32Mac_h11_bits) & DSP32Mac_h11_mask);
3809 int h01 = ((iw1 >> DSP32Mac_h01_bits) & DSP32Mac_h01_mask);
3810
3811 bu32 res = DREG (dst);
3812 bu32 v_0 = 0, v_1 = 0, zero = 0, n_1 = 0, n_0 = 0;
3813
3814 static const char * const ops[] = { "=", "+=", "-=" };
3815 char _buf[128], *buf = _buf;
3816 int _MM = MM;
3817
3818 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dsp32mac);
3819 TRACE_EXTRACT (cpu, "%s: M:%i mmod:%i MM:%i P:%i w1:%i op1:%i h01:%i h11:%i "
3820 "w0:%i op0:%i h00:%i h10:%i dst:%i src0:%i src1:%i",
3821 __func__, M, mmod, MM, P, w1, op1, h01, h11, w0, op0, h00, h10,
3822 dst, src0, src1);
3823
3824 if (w0 == 0 && w1 == 0 && op1 == 3 && op0 == 3)
3825 illegal_instruction (cpu);
3826
3827 if ((w1 || w0) && mmod == M_W32)
3828 illegal_instruction (cpu);
3829
3830 if (((1 << mmod) & (P ? 0x131b : 0x1b5f)) == 0)
3831 illegal_instruction (cpu);
3832
3833 /* First handle MAC1 side. */
3834 if (w1 == 1 || op1 != 3)
3835 {
3836 bu32 res1 = decode_macfunc (cpu, 1, op1, h01, h11, src0,
3837 src1, mmod, MM, P, &v_1, &n_1);
3838
3839 if (w1)
3840 buf += sprintf (buf, P ? "R%i" : "R%i.H", dst + P);
3841
3842 if (op1 == 3)
3843 {
3844 buf += sprintf (buf, " = A1");
3845 zero = !!(res1 == 0);
3846 }
3847 else
3848 {
3849 if (w1)
3850 buf += sprintf (buf, " = (");
3851 buf += sprintf (buf, "A1 %s R%i.%c * R%i.%c", ops[op1],
3852 src0, h01 ? 'H' : 'L',
3853 src1, h11 ? 'H' : 'L');
3854 if (w1)
3855 buf += sprintf (buf, ")");
3856 }
3857
3858 if (w1)
3859 {
3860 if (P)
3861 STORE (DREG (dst + 1), res1);
3862 else
3863 {
3864 if (res1 & 0xffff0000)
3865 illegal_instruction (cpu);
3866 res = REG_H_L (res1 << 16, res);
3867 }
3868 }
3869 else
3870 v_1 = 0;
3871
3872 if (w0 == 1 || op0 != 3)
3873 {
3874 if (_MM)
3875 buf += sprintf (buf, " (M)");
3876 _MM = 0;
3877 buf += sprintf (buf, ", ");
3878 }
3879 }
3880
3881 /* Then handle MAC0 side. */
3882 if (w0 == 1 || op0 != 3)
3883 {
3884 bu32 res0 = decode_macfunc (cpu, 0, op0, h00, h10, src0,
3885 src1, mmod, 0, P, &v_0, &n_0);
3886
3887 if (w0)
3888 buf += sprintf (buf, P ? "R%i" : "R%i.L", dst);
3889
3890 if (op0 == 3)
3891 {
3892 buf += sprintf (buf, " = A0");
3893 zero |= !!(res0 == 0);
3894 }
3895 else
3896 {
3897 if (w0)
3898 buf += sprintf (buf, " = (");
3899 buf += sprintf (buf, "A0 %s R%i.%c * R%i.%c", ops[op0],
3900 src0, h00 ? 'H' : 'L',
3901 src1, h10 ? 'H' : 'L');
3902 if (w0)
3903 buf += sprintf (buf, ")");
3904 }
3905
3906 if (w0)
3907 {
3908 if (P)
3909 STORE (DREG (dst), res0);
3910 else
3911 {
3912 if (res0 & 0xffff0000)
3913 illegal_instruction (cpu);
3914 res = REG_H_L (res, res0);
3915 }
3916 }
3917 else
3918 v_0 = 0;
3919 }
3920
3921 TRACE_INSN (cpu, "%s%s;", _buf, mac_optmode (mmod, _MM));
3922
3923 if (!P && (w0 || w1))
3924 {
3925 STORE (DREG (dst), res);
3926 SET_ASTATREG (v, v_0 | v_1);
3927 if (v_0 || v_1)
3928 SET_ASTATREG (vs, 1);
3929 }
3930 else if (P)
3931 {
3932 SET_ASTATREG (v, v_0 | v_1);
3933 if (v_0 || v_1)
3934 SET_ASTATREG (vs, 1);
3935 }
3936
3937 if ((w0 == 1 && op0 == 3) || (w1 == 1 && op1 == 3))
3938 {
3939 SET_ASTATREG (az, zero);
3940 if (!(w0 == 1 && op0 == 3))
3941 n_0 = 0;
3942 if (!(w1 == 1 && op1 == 3))
3943 n_1 = 0;
3944 SET_ASTATREG (an, n_1 | n_0);
3945 }
3946 }
3947
3948 static void
3949 decode_dsp32mult_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
3950 {
3951 /* dsp32mult
3952 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
3953 | 1 | 1 | 0 | 0 |.M.| 0 | 1 |.mmod..........|.MM|.P.|.w1|.op1...|
3954 |.h01|.h11|.w0|.op0...|.h00|.h10|.dst.......|.src0......|.src1..|
3955 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
3956 int op1 = ((iw0 >> (DSP32Mac_op1_bits - 16)) & DSP32Mac_op1_mask);
3957 int w1 = ((iw0 >> (DSP32Mac_w1_bits - 16)) & DSP32Mac_w1_mask);
3958 int P = ((iw0 >> (DSP32Mac_p_bits - 16)) & DSP32Mac_p_mask);
3959 int MM = ((iw0 >> (DSP32Mac_MM_bits - 16)) & DSP32Mac_MM_mask);
3960 int mmod = ((iw0 >> (DSP32Mac_mmod_bits - 16)) & DSP32Mac_mmod_mask);
3961 int M = ((iw0 >> (DSP32Mac_M_bits - 16)) & DSP32Mac_M_mask);
3962 int w0 = ((iw1 >> DSP32Mac_w0_bits) & DSP32Mac_w0_mask);
3963 int src0 = ((iw1 >> DSP32Mac_src0_bits) & DSP32Mac_src0_mask);
3964 int src1 = ((iw1 >> DSP32Mac_src1_bits) & DSP32Mac_src1_mask);
3965 int dst = ((iw1 >> DSP32Mac_dst_bits) & DSP32Mac_dst_mask);
3966 int h10 = ((iw1 >> DSP32Mac_h10_bits) & DSP32Mac_h10_mask);
3967 int h00 = ((iw1 >> DSP32Mac_h00_bits) & DSP32Mac_h00_mask);
3968 int op0 = ((iw1 >> DSP32Mac_op0_bits) & DSP32Mac_op0_mask);
3969 int h11 = ((iw1 >> DSP32Mac_h11_bits) & DSP32Mac_h11_mask);
3970 int h01 = ((iw1 >> DSP32Mac_h01_bits) & DSP32Mac_h01_mask);
3971
3972 bu32 res = DREG (dst);
3973 bu32 sat0 = 0, sat1 = 0, v_i0 = 0, v_i1 = 0;
3974 char _buf[128], *buf = _buf;
3975 int _MM = MM;
3976
3977 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dsp32mult);
3978 TRACE_EXTRACT (cpu, "%s: M:%i mmod:%i MM:%i P:%i w1:%i op1:%i h01:%i h11:%i "
3979 "w0:%i op0:%i h00:%i h10:%i dst:%i src0:%i src1:%i",
3980 __func__, M, mmod, MM, P, w1, op1, h01, h11, w0, op0, h00, h10,
3981 dst, src0, src1);
3982
3983 if (w1 == 0 && w0 == 0)
3984 illegal_instruction (cpu);
3985 if (((1 << mmod) & (P ? 0x313 : 0x1b57)) == 0)
3986 illegal_instruction (cpu);
3987 if (P && ((dst & 1) || (op1 != 0) || (op0 != 0) || !is_macmod_pmove (mmod)))
3988 illegal_instruction (cpu);
3989 if (!P && ((op1 != 0) || (op0 != 0) || !is_macmod_hmove (mmod)))
3990 illegal_instruction (cpu);
3991
3992 /* First handle MAC1 side. */
3993 if (w1)
3994 {
3995 bu64 r = decode_multfunc (cpu, h01, h11, src0, src1, mmod, MM, &sat1);
3996 bu32 res1 = extract_mult (cpu, r, mmod, MM, P, &v_i1);
3997
3998 buf += sprintf (buf, P ? "R%i" : "R%i.H", dst + P);
3999 buf += sprintf (buf, " = R%i.%c * R%i.%c",
4000 src0, h01 ? 'H' : 'L',
4001 src1, h11 ? 'H' : 'L');
4002 if (w0)
4003 {
4004 if (_MM)
4005 buf += sprintf (buf, " (M)");
4006 _MM = 0;
4007 buf += sprintf (buf, ", ");
4008 }
4009
4010 if (P)
4011 STORE (DREG (dst + 1), res1);
4012 else
4013 {
4014 if (res1 & 0xFFFF0000)
4015 illegal_instruction (cpu);
4016 res = REG_H_L (res1 << 16, res);
4017 }
4018 }
4019
4020 /* First handle MAC0 side. */
4021 if (w0)
4022 {
4023 bu64 r = decode_multfunc (cpu, h00, h10, src0, src1, mmod, 0, &sat0);
4024 bu32 res0 = extract_mult (cpu, r, mmod, 0, P, &v_i0);
4025
4026 buf += sprintf (buf, P ? "R%i" : "R%i.L", dst);
4027 buf += sprintf (buf, " = R%i.%c * R%i.%c",
4028 src0, h01 ? 'H' : 'L',
4029 src1, h11 ? 'H' : 'L');
4030
4031 if (P)
4032 STORE (DREG (dst), res0);
4033 else
4034 {
4035 if (res0 & 0xFFFF0000)
4036 illegal_instruction (cpu);
4037 res = REG_H_L (res, res0);
4038 }
4039 }
4040
4041 TRACE_INSN (cpu, "%s%s;", _buf, mac_optmode (mmod, _MM));
4042
4043 if (!P && (w0 || w1))
4044 STORE (DREG (dst), res);
4045
4046 if (w0 || w1)
4047 {
4048 bu32 v = sat0 | sat1 | v_i0 | v_i1;
4049
4050 STORE (ASTATREG (v), v);
4051 STORE (ASTATREG (v_copy), v);
4052 if (v)
4053 STORE (ASTATREG (vs), v);
4054 }
4055 }
4056
4057 static void
4058 decode_dsp32alu_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
4059 {
4060 /* dsp32alu
4061 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
4062 | 1 | 1 | 0 | 0 |.M.| 1 | 0 | - | - | - |.HL|.aopcde............|
4063 |.aop...|.s.|.x.|.dst0......|.dst1......|.src0......|.src1......|
4064 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
4065 int s = ((iw1 >> DSP32Alu_s_bits) & DSP32Alu_s_mask);
4066 int x = ((iw1 >> DSP32Alu_x_bits) & DSP32Alu_x_mask);
4067 int aop = ((iw1 >> DSP32Alu_aop_bits) & DSP32Alu_aop_mask);
4068 int src0 = ((iw1 >> DSP32Alu_src0_bits) & DSP32Alu_src0_mask);
4069 int src1 = ((iw1 >> DSP32Alu_src1_bits) & DSP32Alu_src1_mask);
4070 int dst0 = ((iw1 >> DSP32Alu_dst0_bits) & DSP32Alu_dst0_mask);
4071 int dst1 = ((iw1 >> DSP32Alu_dst1_bits) & DSP32Alu_dst1_mask);
4072 int M = ((iw0 >> (DSP32Alu_M_bits - 16)) & DSP32Alu_M_mask);
4073 int HL = ((iw0 >> (DSP32Alu_HL_bits - 16)) & DSP32Alu_HL_mask);
4074 int aopcde = ((iw0 >> (DSP32Alu_aopcde_bits - 16)) & DSP32Alu_aopcde_mask);
4075
4076 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dsp32alu);
4077 TRACE_EXTRACT (cpu, "%s: M:%i HL:%i aopcde:%i aop:%i s:%i x:%i dst0:%i "
4078 "dst1:%i src0:%i src1:%i",
4079 __func__, M, HL, aopcde, aop, s, x, dst0, dst1, src0, src1);
4080
4081 if ((aop == 0 || aop == 2) && aopcde == 9 && x == 0 && s == 0 && HL == 0)
4082 {
4083 int a = aop >> 1;
4084 TRACE_INSN (cpu, "A%i.L = R%i.L;", a, src0);
4085 SET_AWREG (a, REG_H_L (AWREG (a), DREG (src0)));
4086 }
4087 else if ((aop == 0 || aop == 2) && aopcde == 9 && x == 0 && s == 0 && HL == 1)
4088 {
4089 int a = aop >> 1;
4090 TRACE_INSN (cpu, "A%i.H = R%i.H;", a, src0);
4091 SET_AWREG (a, REG_H_L (DREG (src0), AWREG (a)));
4092 }
4093 else if ((aop == 1 || aop == 0) && aopcde == 5 && x == 0 && s == 0)
4094 {
4095 bs32 val0 = DREG (src0);
4096 bs32 val1 = DREG (src1);
4097 bs32 res;
4098 bs32 signRes;
4099 bs32 ovX, sBit1, sBit2, sBitRes1, sBitRes2;
4100
4101 TRACE_INSN (cpu, "R%i.%s = R%i %s R%i (RND12)", dst0, HL ? "L" : "H",
4102 src0, aop & 0x1 ? "-" : "+", src1);
4103
4104 /* If subtract, just invert and add one. */
4105 if (aop & 0x1)
4106 {
4107 if (val1 == 0x80000000)
4108 val1 = 0x7FFFFFFF;
4109 else
4110 val1 = ~val1 + 1;
4111 }
4112
4113 /* Get the sign bits, since we need them later. */
4114 sBit1 = !!(val0 & 0x80000000);
4115 sBit2 = !!(val1 & 0x80000000);
4116
4117 res = val0 + val1;
4118
4119 sBitRes1 = !!(res & 0x80000000);
4120 /* Round to the 12th bit. */
4121 res += 0x0800;
4122 sBitRes2 = !!(res & 0x80000000);
4123
4124 signRes = res;
4125 signRes >>= 27;
4126
4127 /* Overflow if
4128 pos + pos = neg
4129 neg + neg = pos
4130 positive_res + positive_round = neg
4131 Shift and upper 4 bits where not the same. */
4132 if ((!(sBit1 ^ sBit2) && (sBit1 ^ sBitRes1))
4133 || (!sBit1 && !sBit2 && sBitRes2)
4134 || ((signRes != 0) && (signRes != -1)))
4135 {
4136 /* Both X1 and X2 Neg res is neg overflow. */
4137 if (sBit1 && sBit2)
4138 res = 0x80000000;
4139 /* Both X1 and X2 Pos res is pos overflow. */
4140 else if (!sBit1 && !sBit2)
4141 res = 0x7FFFFFFF;
4142 /* Pos+Neg or Neg+Pos take the sign of the result. */
4143 else if (sBitRes1)
4144 res = 0x80000000;
4145 else
4146 res = 0x7FFFFFFF;
4147
4148 ovX = 1;
4149 }
4150 else
4151 {
4152 /* Shift up now after overflow detection. */
4153 ovX = 0;
4154 res <<= 4;
4155 }
4156
4157 res >>= 16;
4158
4159 if (HL)
4160 STORE (DREG (dst0), REG_H_L (res << 16, DREG (dst0)));
4161 else
4162 STORE (DREG (dst0), REG_H_L (DREG (dst0), res));
4163
4164 SET_ASTATREG (az, res == 0);
4165 SET_ASTATREG (an, res & 0x8000);
4166 SET_ASTATREG (v, ovX);
4167 if (ovX)
4168 SET_ASTATREG (vs, ovX);
4169 }
4170 else if ((aop == 2 || aop == 3) && aopcde == 5 && x == 1 && s == 0)
4171 {
4172 bs32 val0 = DREG (src0);
4173 bs32 val1 = DREG (src1);
4174 bs32 res;
4175
4176 TRACE_INSN (cpu, "R%i.%s = R%i %s R%i (RND20)", dst0, HL ? "L" : "H",
4177 src0, aop & 0x1 ? "-" : "+", src1);
4178
4179 /* If subtract, just invert and add one. */
4180 if (aop & 0x1)
4181 val1 = ~val1 + 1;
4182
4183 res = (val0 >> 4) + (val1 >> 4) + (((val0 & 0xf) + (val1 & 0xf)) >> 4);
4184 res += 0x8000;
4185 /* Don't sign extend during the shift. */
4186 res = ((bu32)res >> 16);
4187
4188 /* Don't worry about overflows, since we are shifting right. */
4189
4190 if (HL)
4191 STORE (DREG (dst0), REG_H_L (res << 16, DREG (dst0)));
4192 else
4193 STORE (DREG (dst0), REG_H_L (DREG (dst0), res));
4194
4195 SET_ASTATREG (az, res == 0);
4196 SET_ASTATREG (an, res & 0x8000);
4197 SET_ASTATREG (v, 0);
4198 }
4199 else if ((aopcde == 2 || aopcde == 3) && x == 0)
4200 {
4201 bu32 s1, s2, val, ac0_i = 0, v_i = 0;
4202
4203 TRACE_INSN (cpu, "R%i.%c = R%i.%c %c R%i.%c%s;",
4204 dst0, HL ? 'H' : 'L',
4205 src0, aop & 2 ? 'H' : 'L',
4206 aopcde == 2 ? '+' : '-',
4207 src1, aop & 1 ? 'H' : 'L',
4208 amod1 (s, x));
4209
4210 s1 = DREG (src0);
4211 s2 = DREG (src1);
4212 if (aop & 1)
4213 s2 >>= 16;
4214 if (aop & 2)
4215 s1 >>= 16;
4216
4217 if (aopcde == 2)
4218 val = add16 (cpu, s1, s2, &ac0_i, &v_i, 0, 0, s, 0);
4219 else
4220 val = sub16 (cpu, s1, s2, &ac0_i, &v_i, 0, 0, s, 0);
4221
4222 SET_ASTATREG (ac0, ac0_i);
4223 SET_ASTATREG (v, v_i);
4224 if (v_i)
4225 SET_ASTATREG (vs, v_i);
4226
4227 if (HL)
4228 SET_DREG_H (dst0, val << 16);
4229 else
4230 SET_DREG_L (dst0, val);
4231
4232 SET_ASTATREG (an, val & 0x8000);
4233 SET_ASTATREG (az, val == 0);
4234 }
4235 else if ((aop == 0 || aop == 2) && aopcde == 9 && x == 0 && s == 1 && HL == 0)
4236 {
4237 int a = aop >> 1;
4238 TRACE_INSN (cpu, "A%i = R%i;", a, src0);
4239 SET_AREG32 (a, DREG (src0));
4240 }
4241 else if ((aop == 1 || aop == 3) && aopcde == 9 && x == 0 && s == 0 && HL == 0)
4242 {
4243 int a = aop >> 1;
4244 TRACE_INSN (cpu, "A%i.X = R%i.L;", a, src0);
4245 SET_AXREG (a, (bs8)DREG (src0));
4246 }
4247 else if (aop == 3 && aopcde == 11 && x == 0 && HL == 0)
4248 {
4249 bu64 acc0 = get_extended_acc (cpu, 0);
4250 bu64 acc1 = get_extended_acc (cpu, 1);
4251 bu32 carry = (bu40)acc1 < (bu40)acc0;
4252 bu32 sat = 0;
4253
4254 TRACE_INSN (cpu, "A0 -= A1%s;", s ? " (W32)" : "");
4255
4256 acc0 -= acc1;
4257 if ((bs64)acc0 < -0x8000000000ll)
4258 acc0 = -0x8000000000ull, sat = 1;
4259 else if ((bs64)acc0 >= 0x7fffffffffll)
4260 acc0 = 0x7fffffffffull, sat = 1;
4261
4262 if (s == 1)
4263 {
4264 /* A0 -= A1 (W32) */
4265 if (acc0 & (bu64)0x8000000000ll)
4266 acc0 &= 0x80ffffffffll, sat = 1;
4267 else
4268 acc0 &= 0xffffffffll;
4269 }
4270 STORE (AXREG (0), (acc0 >> 32) & 0xff);
4271 STORE (AWREG (0), acc0 & 0xffffffff);
4272 STORE (ASTATREG (az), acc0 == 0);
4273 STORE (ASTATREG (an), !!(acc0 & (bu64)0x8000000000ll));
4274 STORE (ASTATREG (ac0), carry);
4275 STORE (ASTATREG (ac0_copy), carry);
4276 STORE (ASTATREG (av0), sat);
4277 if (sat)
4278 STORE (ASTATREG (av0s), sat);
4279 }
4280 else if ((aop == 0 || aop == 1) && aopcde == 22 && x == 0)
4281 {
4282 bu32 s0, s0L, s0H, s1, s1L, s1H;
4283 bu32 tmp0, tmp1, i;
4284 const char * const opts[] = { "rndl", "rndh", "tl", "th" };
4285
4286 TRACE_INSN (cpu, "R%i = BYTEOP2P (R%i:%i, R%i:%i) (%s%s);", dst0,
4287 src0 + 1, src0, src1 + 1, src1, opts[HL + (aop << 1)],
4288 s ? ", r" : "");
4289
4290 if ((src1 != 0 && src1 != 2) || (src0 != 0 && src0 != 2))
4291 illegal_instruction (cpu);
4292
4293 s0L = DREG (src0);
4294 s0H = DREG (src0 + 1);
4295 s1L = DREG (src1);
4296 s1H = DREG (src1 + 1);
4297 if (s)
4298 {
4299 s0 = algn (s0H, s0L, IREG (0) & 3);
4300 s1 = algn (s1H, s1L, IREG (0) & 3);
4301 }
4302 else
4303 {
4304 s0 = algn (s0L, s0H, IREG (0) & 3);
4305 s1 = algn (s1L, s1H, IREG (0) & 3);
4306 }
4307
4308 i = !aop * 2;
4309 tmp0 = ((((s1 >> 8) & 0xff) + ((s1 >> 0) & 0xff) +
4310 ((s0 >> 8) & 0xff) + ((s0 >> 0) & 0xff) + i) >> 2) & 0xff;
4311 tmp1 = ((((s1 >> 24) & 0xff) + ((s1 >> 16) & 0xff) +
4312 ((s0 >> 24) & 0xff) + ((s0 >> 16) & 0xff) + i) >> 2) & 0xff;
4313 STORE (DREG (dst0), (tmp1 << (16 + (HL * 8))) | (tmp0 << (HL * 8)));
4314
4315 /* Implicit DISALGNEXCPT in parallel. */
4316 DIS_ALGN_EXPT |= 1;
4317 }
4318 else if ((aop == 0 || aop == 1) && aopcde == 8 && x == 0 && s == 0 && HL == 0)
4319 {
4320 TRACE_INSN (cpu, "A%i = 0;", aop);
4321 SET_AREG (aop, 0);
4322 }
4323 else if (aop == 2 && aopcde == 8 && x == 0 && s == 0 && HL == 0)
4324 {
4325 TRACE_INSN (cpu, "A1 = A0 = 0;");
4326 SET_AREG (0, 0);
4327 SET_AREG (1, 0);
4328 }
4329 else if ((aop == 0 || aop == 1 || aop == 2) && s == 1 && aopcde == 8
4330 && x == 0 && HL == 0)
4331 {
4332 bs40 acc0 = get_extended_acc (cpu, 0);
4333 bs40 acc1 = get_extended_acc (cpu, 1);
4334 bu32 sat;
4335
4336 if (aop == 0 || aop == 1)
4337 TRACE_INSN (cpu, "A%i = A%i (S);", aop, aop);
4338 else
4339 TRACE_INSN (cpu, "A1 = A1 (S), A0 = A0 (S);");
4340
4341 if (aop == 0 || aop == 2)
4342 {
4343 sat = 0;
4344 acc0 = saturate_s32 (acc0, &sat);
4345 acc0 |= -(acc0 & 0x80000000ull);
4346 SET_AXREG (0, (acc0 >> 31) & 0xFF);
4347 SET_AWREG (0, acc0 & 0xFFFFFFFF);
4348 SET_ASTATREG (av0, sat);
4349 if (sat)
4350 SET_ASTATREG (av0s, sat);
4351 }
4352 else
4353 acc0 = 1;
4354
4355 if (aop == 1 || aop == 2)
4356 {
4357 sat = 0;
4358 acc1 = saturate_s32 (acc1, &sat);
4359 acc1 |= -(acc1 & 0x80000000ull);
4360 SET_AXREG (1, (acc1 >> 31) & 0xFF);
4361 SET_AWREG (1, acc1 & 0xFFFFFFFF);
4362 SET_ASTATREG (av1, sat);
4363 if (sat)
4364 SET_ASTATREG (av1s, sat);
4365 }
4366 else
4367 acc1 = 1;
4368
4369 SET_ASTATREG (az, (acc0 == 0) || (acc1 == 0));
4370 SET_ASTATREG (an, ((acc0 >> 31) & 1) || ((acc1 >> 31) & 1));
4371 }
4372 else if (aop == 3 && aopcde == 8 && x == 0 && HL == 0)
4373 {
4374 TRACE_INSN (cpu, "A%i = A%i;", s, !s);
4375 SET_AXREG (s, AXREG (!s));
4376 SET_AWREG (s, AWREG (!s));
4377 }
4378 else if (aop == 3 && HL == 0 && aopcde == 16 && x == 0 && s == 0)
4379 {
4380 int i;
4381 bu32 az;
4382
4383 TRACE_INSN (cpu, "A1 = ABS A1 , A0 = ABS A0;");
4384
4385 az = 0;
4386 for (i = 0; i < 2; ++i)
4387 {
4388 bu32 av;
4389 bs40 acc = get_extended_acc (cpu, i);
4390
4391 if (acc >> 39)
4392 acc = -acc;
4393 av = acc == ((bs40)1 << 39);
4394 if (av)
4395 acc = ((bs40)1 << 39) - 1;
4396
4397 SET_AREG (i, acc);
4398 SET_ASTATREG (av[i], av);
4399 if (av)
4400 SET_ASTATREG (avs[i], av);
4401 az |= (acc == 0);
4402 }
4403 SET_ASTATREG (az, az);
4404 SET_ASTATREG (an, 0);
4405 }
4406 else if (aop == 0 && aopcde == 23 && x == 0)
4407 {
4408 bu32 s0, s0L, s0H, s1, s1L, s1H;
4409 bs32 tmp0, tmp1;
4410
4411 TRACE_INSN (cpu, "R%i = BYTEOP3P (R%i:%i, R%i:%i) (%s%s);", dst0,
4412 src0 + 1, src0, src1 + 1, src1, HL ? "HI" : "LO",
4413 s ? ", R" : "");
4414
4415 if ((src1 != 0 && src1 != 2) || (src0 != 0 && src0 != 2))
4416 illegal_instruction (cpu);
4417
4418 s0L = DREG (src0);
4419 s0H = DREG (src0 + 1);
4420 s1L = DREG (src1);
4421 s1H = DREG (src1 + 1);
4422 if (s)
4423 {
4424 s0 = algn (s0H, s0L, IREG (0) & 3);
4425 s1 = algn (s1H, s1L, IREG (1) & 3);
4426 }
4427 else
4428 {
4429 s0 = algn (s0L, s0H, IREG (0) & 3);
4430 s1 = algn (s1L, s1H, IREG (1) & 3);
4431 }
4432
4433 tmp0 = (bs32)(bs16)(s0 >> 0) + ((s1 >> ( 0 + (8 * !HL))) & 0xff);
4434 tmp1 = (bs32)(bs16)(s0 >> 16) + ((s1 >> (16 + (8 * !HL))) & 0xff);
4435 STORE (DREG (dst0), (CLAMP (tmp0, 0, 255) << ( 0 + (8 * HL))) |
4436 (CLAMP (tmp1, 0, 255) << (16 + (8 * HL))));
4437
4438 /* Implicit DISALGNEXCPT in parallel. */
4439 DIS_ALGN_EXPT |= 1;
4440 }
4441 else if ((aop == 0 || aop == 1) && aopcde == 16 && x == 0 && s == 0)
4442 {
4443 bu32 av;
4444 bs40 acc;
4445
4446 TRACE_INSN (cpu, "A%i = ABS A%i;", HL, aop);
4447
4448 acc = get_extended_acc (cpu, aop);
4449 if (acc >> 39)
4450 acc = -acc;
4451 av = acc == ((bs40)1 << 39);
4452 if (av)
4453 acc = ((bs40)1 << 39) - 1;
4454 SET_AREG (HL, acc);
4455
4456 SET_ASTATREG (av[HL], av);
4457 if (av)
4458 SET_ASTATREG (avs[HL], av);
4459 SET_ASTATREG (az, acc == 0);
4460 SET_ASTATREG (an, 0);
4461 }
4462 else if (aop == 3 && aopcde == 12 && x == 0 && s == 0)
4463 {
4464 bs32 res = DREG (src0);
4465 bs32 ovX;
4466 bool sBit_a, sBit_b;
4467
4468 TRACE_INSN (cpu, "R%i.%s = R%i (RND);", dst0, HL == 0 ? "L" : "H", src0);
4469 TRACE_DECODE (cpu, "R%i.%s = R%i:%#x (RND);", dst0,
4470 HL == 0 ? "L" : "H", src0, res);
4471
4472 sBit_b = !!(res & 0x80000000);
4473
4474 res += 0x8000;
4475 sBit_a = !!(res & 0x80000000);
4476
4477 /* Overflow if the sign bit changed when we rounded. */
4478 if ((res >> 16) && (sBit_b != sBit_a))
4479 {
4480 ovX = 1;
4481 if (!sBit_b)
4482 res = 0x7FFF;
4483 else
4484 res = 0x8000;
4485 }
4486 else
4487 {
4488 res = res >> 16;
4489 ovX = 0;
4490 }
4491
4492 if (!HL)
4493 SET_DREG (dst0, REG_H_L (DREG (dst0), res));
4494 else
4495 SET_DREG (dst0, REG_H_L (res << 16, DREG (dst0)));
4496
4497 SET_ASTATREG (az, res == 0);
4498 SET_ASTATREG (an, res < 0);
4499 SET_ASTATREG (v, ovX);
4500 if (ovX)
4501 SET_ASTATREG (vs, ovX);
4502 }
4503 else if (aop == 3 && HL == 0 && aopcde == 15 && x == 0 && s == 0)
4504 {
4505 bu32 hi = (-(bs16)(DREG (src0) >> 16)) << 16;
4506 bu32 lo = (-(bs16)(DREG (src0) & 0xFFFF)) & 0xFFFF;
4507 int v, ac0, ac1;
4508
4509 TRACE_INSN (cpu, "R%i = -R%i (V);", dst0, src0);
4510
4511 v = ac0 = ac1 = 0;
4512
4513 if (hi == 0x80000000)
4514 {
4515 hi = 0x7fff0000;
4516 v = 1;
4517 }
4518 else if (hi == 0)
4519 ac1 = 1;
4520
4521 if (lo == 0x8000)
4522 {
4523 lo = 0x7fff;
4524 v = 1;
4525 }
4526 else if (lo == 0)
4527 ac0 = 1;
4528
4529 SET_DREG (dst0, hi | lo);
4530
4531 SET_ASTATREG (v, v);
4532 if (v)
4533 SET_ASTATREG (vs, 1);
4534 SET_ASTATREG (ac0, ac0);
4535 SET_ASTATREG (ac1, ac1);
4536 setflags_nz_2x16 (cpu, DREG (dst0));
4537 }
4538 else if (aop == 3 && HL == 0 && aopcde == 14 && x == 0 && s == 0)
4539 {
4540 TRACE_INSN (cpu, "A1 = - A1 , A0 = - A0;");
4541
4542 SET_AREG (0, saturate_s40 (-get_extended_acc (cpu, 0)));
4543 SET_AREG (1, saturate_s40 (-get_extended_acc (cpu, 1)));
4544 /* XXX: what ASTAT flags need updating ? */
4545 }
4546 else if ((aop == 0 || aop == 1) && aopcde == 14 && x == 0 && s == 0)
4547 {
4548 bs40 src_acc = get_extended_acc (cpu, aop);
4549 bu32 v = 0;
4550
4551 TRACE_INSN (cpu, "A%i = - A%i;", HL, aop);
4552
4553 SET_AREG (HL, saturate_s40_astat (-src_acc, &v));
4554
4555 SET_ASTATREG (az, AWREG (HL) == 0 && AXREG (HL) == 0);
4556 SET_ASTATREG (an, AXREG (HL) >> 7);
4557 if (HL == 0)
4558 {
4559 SET_ASTATREG (ac0, !src_acc);
4560 SET_ASTATREG (av0, v);
4561 if (v)
4562 SET_ASTATREG (av0s, 1);
4563 }
4564 else
4565 {
4566 SET_ASTATREG (ac1, !src_acc);
4567 SET_ASTATREG (av1, v);
4568 if (v)
4569 SET_ASTATREG (av1s, 1);
4570 }
4571 }
4572 else if (aop == 0 && aopcde == 12 && x == 0 && s == 0 && HL == 0)
4573 {
4574 bs16 tmp0_hi = DREG (src0) >> 16;
4575 bs16 tmp0_lo = DREG (src0);
4576 bs16 tmp1_hi = DREG (src1) >> 16;
4577 bs16 tmp1_lo = DREG (src1);
4578
4579 TRACE_INSN (cpu, "R%i.L = R%i.H = SIGN(R%i.H) * R%i.H + SIGN(R%i.L) * R%i.L;",
4580 dst0, dst0, src0, src1, src0, src1);
4581
4582 if ((tmp0_hi >> 15) & 1)
4583 tmp1_hi = ~tmp1_hi + 1;
4584
4585 if ((tmp0_lo >> 15) & 1)
4586 tmp1_lo = ~tmp1_lo + 1;
4587
4588 tmp1_hi = tmp1_hi + tmp1_lo;
4589
4590 STORE (DREG (dst0), REG_H_L (tmp1_hi << 16, tmp1_hi));
4591 }
4592 else if (aopcde == 0 && HL == 0)
4593 {
4594 bu32 s0 = DREG (src0);
4595 bu32 s1 = DREG (src1);
4596 bu32 s0h = s0 >> 16;
4597 bu32 s0l = s0 & 0xFFFF;
4598 bu32 s1h = s1 >> 16;
4599 bu32 s1l = s1 & 0xFFFF;
4600 bu32 t0, t1;
4601 bu32 ac1_i = 0, ac0_i = 0, v_i = 0, z_i = 0, n_i = 0;
4602
4603 TRACE_INSN (cpu, "R%i = R%i %c|%c R%i%s;", dst0, src0,
4604 (aop & 2) ? '-' : '+', (aop & 1) ? '-' : '+', src1,
4605 amod0 (s, x));
4606 if (aop & 2)
4607 t0 = sub16 (cpu, s0h, s1h, &ac1_i, &v_i, &z_i, &n_i, s, 0);
4608 else
4609 t0 = add16 (cpu, s0h, s1h, &ac1_i, &v_i, &z_i, &n_i, s, 0);
4610
4611 if (aop & 1)
4612 t1 = sub16 (cpu, s0l, s1l, &ac0_i, &v_i, &z_i, &n_i, s, 0);
4613 else
4614 t1 = add16 (cpu, s0l, s1l, &ac0_i, &v_i, &z_i, &n_i, s, 0);
4615
4616 SET_ASTATREG (ac1, ac1_i);
4617 SET_ASTATREG (ac0, ac0_i);
4618 SET_ASTATREG (az, z_i);
4619 SET_ASTATREG (an, n_i);
4620 SET_ASTATREG (v, v_i);
4621 if (v_i)
4622 SET_ASTATREG (vs, v_i);
4623
4624 t0 &= 0xFFFF;
4625 t1 &= 0xFFFF;
4626 if (x)
4627 SET_DREG (dst0, (t1 << 16) | t0);
4628 else
4629 SET_DREG (dst0, (t0 << 16) | t1);
4630 }
4631 else if (aop == 1 && aopcde == 12 && x == 0 && s == 0 && HL == 0)
4632 {
4633 bs32 val0 = (bs16)(AWREG (0) >> 16) + (bs16)AWREG (0);
4634 bs32 val1 = (bs16)(AWREG (1) >> 16) + (bs16)AWREG (1);
4635
4636 TRACE_INSN (cpu, "R%i = A1.L + A1.H, R%i = A0.L + A0.H;", dst1, dst0);
4637
4638 if (dst0 == dst1)
4639 illegal_instruction_combination (cpu);
4640
4641 SET_DREG (dst0, val0);
4642 SET_DREG (dst1, val1);
4643 }
4644 else if ((aop == 0 || aop == 2 || aop == 3) && aopcde == 1)
4645 {
4646 bu32 d0, d1;
4647 bu32 x0, x1;
4648 bu16 s0L = DREG (src0);
4649 bu16 s0H = DREG (src0) >> 16;
4650 bu16 s1L = DREG (src1);
4651 bu16 s1H = DREG (src1) >> 16;
4652 bu32 v_i = 0, n_i = 0, z_i = 0;
4653
4654 TRACE_INSN (cpu, "R%i = R%i %s R%i, R%i = R%i %s R%i%s;",
4655 dst1, src0, HL ? "+|-" : "+|+", src1,
4656 dst0, src0, HL ? "-|+" : "-|-", src1,
4657 amod0amod2 (s, x, aop));
4658
4659 if (dst0 == dst1)
4660 illegal_instruction_combination (cpu);
4661
4662 if (HL == 0)
4663 {
4664 x0 = add16 (cpu, s0H, s1H, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
4665 x1 = add16 (cpu, s0L, s1L, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
4666 d1 = (x0 << 16) | x1;
4667
4668 x0 = sub16 (cpu, s0H, s1H, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
4669 x1 = sub16 (cpu, s0L, s1L, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
4670 if (x == 0)
4671 d0 = (x0 << 16) | x1;
4672 else
4673 d0 = (x1 << 16) | x0;
4674 }
4675 else
4676 {
4677 x0 = add16 (cpu, s0H, s1H, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
4678 x1 = sub16 (cpu, s0L, s1L, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
4679 d1 = (x0 << 16) | x1;
4680
4681 x0 = sub16 (cpu, s0H, s1H, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
4682 x1 = add16 (cpu, s0L, s1L, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
4683 if (x == 0)
4684 d0 = (x0 << 16) | x1;
4685 else
4686 d0 = (x1 << 16) | x0;
4687 }
4688 SET_ASTATREG (az, z_i);
4689 SET_ASTATREG (an, n_i);
4690 SET_ASTATREG (v, v_i);
4691 if (v_i)
4692 SET_ASTATREG (vs, v_i);
4693
4694 STORE (DREG (dst0), d0);
4695 STORE (DREG (dst1), d1);
4696 }
4697 else if ((aop == 0 || aop == 1 || aop == 2) && aopcde == 11 && x == 0)
4698 {
4699 bs40 acc0 = get_extended_acc (cpu, 0);
4700 bs40 acc1 = get_extended_acc (cpu, 1);
4701 bu32 v, dreg, sat = 0;
4702 bu32 carry = !!((bu40)~acc1 < (bu40)acc0);
4703
4704 if (aop == 0)
4705 {
4706 if (s != 0 || HL != 0)
4707 illegal_instruction (cpu);
4708 TRACE_INSN (cpu, "R%i = (A0 += A1);", dst0);
4709 }
4710 else if (aop == 1)
4711 {
4712 if (s != 0)
4713 illegal_instruction (cpu);
4714 TRACE_INSN (cpu, "R%i.%c = (A0 += A1);", dst0, HL ? 'H' : 'L');
4715 }
4716 else
4717 {
4718 if (HL != 0)
4719 illegal_instruction (cpu);
4720 TRACE_INSN (cpu, "A0 += A1%s;", s ? " (W32)" : "");
4721 }
4722
4723 acc0 += acc1;
4724 acc0 = saturate_s40_astat (acc0, &v);
4725
4726 if (aop == 2 && s == 1) /* A0 += A1 (W32) */
4727 {
4728 if (acc0 & (bs40)0x8000000000ll)
4729 acc0 &= 0x80ffffffffll;
4730 else
4731 acc0 &= 0xffffffffll;
4732 }
4733
4734 STORE (AXREG (0), acc0 >> 32);
4735 STORE (AWREG (0), acc0);
4736 SET_ASTATREG (av0, v && acc1);
4737 if (v)
4738 SET_ASTATREG (av0s, v);
4739
4740 if (aop == 0 || aop == 1)
4741 {
4742 if (aop) /* Dregs_lo = A0 += A1 */
4743 {
4744 dreg = saturate_s32 (rnd16 (acc0) << 16, &sat);
4745 if (HL)
4746 STORE (DREG (dst0), REG_H_L (dreg, DREG (dst0)));
4747 else
4748 STORE (DREG (dst0), REG_H_L (DREG (dst0), dreg >> 16));
4749 }
4750 else /* Dregs = A0 += A1 */
4751 {
4752 dreg = saturate_s32 (acc0, &sat);
4753 STORE (DREG (dst0), dreg);
4754 }
4755
4756 STORE (ASTATREG (az), dreg == 0);
4757 STORE (ASTATREG (an), !!(dreg & 0x80000000));
4758 STORE (ASTATREG (ac0), carry);
4759 STORE (ASTATREG (ac0_copy), carry);
4760 STORE (ASTATREG (v), sat);
4761 STORE (ASTATREG (v_copy), sat);
4762 if (sat)
4763 STORE (ASTATREG (vs), sat);
4764 }
4765 else
4766 {
4767 STORE (ASTATREG (az), acc0 == 0);
4768 STORE (ASTATREG (an), !!(acc0 & 0x8000000000ull));
4769 STORE (ASTATREG (ac0), carry);
4770 STORE (ASTATREG (ac0_copy), carry);
4771 }
4772 }
4773 else if ((aop == 0 || aop == 1) && aopcde == 10 && x == 0 && s == 0 && HL == 0)
4774 {
4775 TRACE_INSN (cpu, "R%i.L = A%i.X;", dst0, aop);
4776 SET_DREG_L (dst0, (bs8)AXREG (aop));
4777 }
4778 else if (aop == 0 && aopcde == 4 && x == 0 && HL == 0)
4779 {
4780 TRACE_INSN (cpu, "R%i = R%i + R%i%s;", dst0, src0, src1, amod1 (s, x));
4781 SET_DREG (dst0, add32 (cpu, DREG (src0), DREG (src1), 1, s));
4782 }
4783 else if (aop == 1 && aopcde == 4 && x == 0 && HL == 0)
4784 {
4785 TRACE_INSN (cpu, "R%i = R%i - R%i%s;", dst0, src0, src1, amod1 (s, x));
4786 SET_DREG (dst0, sub32 (cpu, DREG (src0), DREG (src1), 1, s, 0));
4787 }
4788 else if (aop == 2 && aopcde == 4 && x == 0 && HL == 0)
4789 {
4790 TRACE_INSN (cpu, "R%i = R%i + R%i, R%i = R%i - R%i%s;",
4791 dst1, src0, src1, dst0, src0, src1, amod1 (s, x));
4792
4793 if (dst0 == dst1)
4794 illegal_instruction_combination (cpu);
4795
4796 STORE (DREG (dst1), add32 (cpu, DREG (src0), DREG (src1), 1, s));
4797 STORE (DREG (dst0), sub32 (cpu, DREG (src0), DREG (src1), 1, s, 1));
4798 }
4799 else if ((aop == 0 || aop == 1) && aopcde == 17 && x == 0 && HL == 0)
4800 {
4801 bs40 acc0 = get_extended_acc (cpu, 0);
4802 bs40 acc1 = get_extended_acc (cpu, 1);
4803 bs40 val0, val1, sval0, sval1;
4804 bu32 sat, sat_i;
4805
4806 TRACE_INSN (cpu, "R%i = A%i + A%i, R%i = A%i - A%i%s",
4807 dst1, !aop, aop, dst0, !aop, aop, amod1 (s, x));
4808 TRACE_DECODE (cpu, "R%i = A%i:%#"PRIx64" + A%i:%#"PRIx64", "
4809 "R%i = A%i:%#"PRIx64" - A%i:%#"PRIx64"%s",
4810 dst1, !aop, aop ? acc0 : acc1, aop, aop ? acc1 : acc0,
4811 dst0, !aop, aop ? acc0 : acc1, aop, aop ? acc1 : acc0,
4812 amod1 (s, x));
4813
4814 if (dst0 == dst1)
4815 illegal_instruction_combination (cpu);
4816
4817 val1 = acc0 + acc1;
4818 if (aop)
4819 val0 = acc0 - acc1;
4820 else
4821 val0 = acc1 - acc0;
4822
4823 sval0 = saturate_s32 (val0, &sat);
4824 sat_i = sat;
4825 sval1 = saturate_s32 (val1, &sat);
4826 sat_i |= sat;
4827 if (s)
4828 {
4829 val0 = sval0;
4830 val1 = sval1;
4831 }
4832
4833 STORE (DREG (dst0), val0);
4834 STORE (DREG (dst1), val1);
4835 SET_ASTATREG (v, sat_i);
4836 if (sat_i)
4837 SET_ASTATREG (vs, sat_i);
4838 SET_ASTATREG (an, val0 & 0x80000000 || val1 & 0x80000000);
4839 SET_ASTATREG (az, val0 == 0 || val1 == 0);
4840 SET_ASTATREG (ac1, (bu40)~acc0 < (bu40)acc1);
4841 if (aop)
4842 SET_ASTATREG (ac0, !!((bu40)acc1 <= (bu40)acc0));
4843 else
4844 SET_ASTATREG (ac0, !!((bu40)acc0 <= (bu40)acc1));
4845 }
4846 else if (aop == 0 && aopcde == 18 && x == 0 && HL == 0)
4847 {
4848 bu40 acc0 = get_extended_acc (cpu, 0);
4849 bu40 acc1 = get_extended_acc (cpu, 1);
4850 bu32 s0L = DREG (src0);
4851 bu32 s0H = DREG (src0 + 1);
4852 bu32 s1L = DREG (src1);
4853 bu32 s1H = DREG (src1 + 1);
4854 bu32 s0, s1;
4855 bs16 tmp0, tmp1, tmp2, tmp3;
4856
4857 /* This instruction is only defined for register pairs R1:0 and R3:2. */
4858 if (!((src0 == 0 || src0 == 2) && (src1 == 0 || src1 == 2)))
4859 illegal_instruction (cpu);
4860
4861 TRACE_INSN (cpu, "SAA (R%i:%i, R%i:%i)%s", src0 + 1, src0,
4862 src1 + 1, src1, s ? " (R)" :"");
4863
4864 /* Bit s determines the order of the two registers from a pair:
4865 if s=0 the low-order bytes come from the low reg in the pair,
4866 and if s=1 the low-order bytes come from the high reg. */
4867
4868 if (s)
4869 {
4870 s0 = algn (s0H, s0L, IREG (0) & 3);
4871 s1 = algn (s1H, s1L, IREG (1) & 3);
4872 }
4873 else
4874 {
4875 s0 = algn (s0L, s0H, IREG (0) & 3);
4876 s1 = algn (s1L, s1H, IREG (1) & 3);
4877 }
4878
4879 /* Find the absolute difference between pairs, make it
4880 absolute, then add it to the existing accumulator half. */
4881 /* Byte 0 */
4882 tmp0 = ((s0 << 24) >> 24) - ((s1 << 24) >> 24);
4883 tmp1 = ((s0 << 16) >> 24) - ((s1 << 16) >> 24);
4884 tmp2 = ((s0 << 8) >> 24) - ((s1 << 8) >> 24);
4885 tmp3 = ((s0 << 0) >> 24) - ((s1 << 0) >> 24);
4886
4887 tmp0 = (tmp0 < 0) ? -tmp0 : tmp0;
4888 tmp1 = (tmp1 < 0) ? -tmp1 : tmp1;
4889 tmp2 = (tmp2 < 0) ? -tmp2 : tmp2;
4890 tmp3 = (tmp3 < 0) ? -tmp3 : tmp3;
4891
4892 s0L = saturate_u16 ((bu32)tmp0 + ((acc0 >> 0) & 0xffff), 0);
4893 s0H = saturate_u16 ((bu32)tmp1 + ((acc0 >> 16) & 0xffff), 0);
4894 s1L = saturate_u16 ((bu32)tmp2 + ((acc1 >> 0) & 0xffff), 0);
4895 s1H = saturate_u16 ((bu32)tmp3 + ((acc1 >> 16) & 0xffff), 0);
4896
4897 STORE (AWREG (0), (s0H << 16) | (s0L & 0xFFFF));
4898 STORE (AXREG (0), 0);
4899 STORE (AWREG (1), (s1H << 16) | (s1L & 0xFFFF));
4900 STORE (AXREG (1), 0);
4901
4902 /* Implicit DISALGNEXCPT in parallel. */
4903 DIS_ALGN_EXPT |= 1;
4904 }
4905 else if (aop == 3 && aopcde == 18 && x == 0 && s == 0 && HL == 0)
4906 {
4907 TRACE_INSN (cpu, "DISALGNEXCPT");
4908 DIS_ALGN_EXPT |= 1;
4909 }
4910 else if ((aop == 0 || aop == 1) && aopcde == 20 && x == 0 && HL == 0)
4911 {
4912 bu32 s0, s0L, s0H, s1, s1L, s1H;
4913 const char * const opts[] = { "", " (R)", " (T)", " (T, R)" };
4914
4915 TRACE_INSN (cpu, "R%i = BYTEOP1P (R%i:%i, R%i:%i)%s;", dst0,
4916 src0 + 1, src0, src1 + 1, src1, opts[s + (aop << 1)]);
4917
4918 if ((src1 != 0 && src1 != 2) || (src0 != 0 && src0 != 2))
4919 illegal_instruction (cpu);
4920
4921 s0L = DREG (src0);
4922 s0H = DREG (src0 + 1);
4923 s1L = DREG (src1);
4924 s1H = DREG (src1 + 1);
4925 if (s)
4926 {
4927 s0 = algn (s0H, s0L, IREG (0) & 3);
4928 s1 = algn (s1H, s1L, IREG (1) & 3);
4929 }
4930 else
4931 {
4932 s0 = algn (s0L, s0H, IREG (0) & 3);
4933 s1 = algn (s1L, s1H, IREG (1) & 3);
4934 }
4935
4936 STORE (DREG (dst0),
4937 (((((s0 >> 0) & 0xff) + ((s1 >> 0) & 0xff) + !aop) >> 1) << 0) |
4938 (((((s0 >> 8) & 0xff) + ((s1 >> 8) & 0xff) + !aop) >> 1) << 8) |
4939 (((((s0 >> 16) & 0xff) + ((s1 >> 16) & 0xff) + !aop) >> 1) << 16) |
4940 (((((s0 >> 24) & 0xff) + ((s1 >> 24) & 0xff) + !aop) >> 1) << 24));
4941
4942 /* Implicit DISALGNEXCPT in parallel. */
4943 DIS_ALGN_EXPT |= 1;
4944 }
4945 else if (aop == 0 && aopcde == 21 && x == 0 && HL == 0)
4946 {
4947 bu32 s0, s0L, s0H, s1, s1L, s1H;
4948
4949 TRACE_INSN (cpu, "(R%i, R%i) = BYTEOP16P (R%i:%i, R%i:%i)%s;", dst1, dst0,
4950 src0 + 1, src0, src1 + 1, src1, s ? " (R)" : "");
4951
4952 if ((src1 != 0 && src1 != 2) || (src0 != 0 && src0 != 2))
4953 illegal_instruction (cpu);
4954
4955 if (dst0 == dst1)
4956 illegal_instruction_combination (cpu);
4957
4958 s0L = DREG (src0);
4959 s0H = DREG (src0 + 1);
4960 s1L = DREG (src1);
4961 s1H = DREG (src1 + 1);
4962 if (s)
4963 {
4964 s0 = algn (s0H, s0L, IREG (0) & 3);
4965 s1 = algn (s1H, s1L, IREG (1) & 3);
4966 }
4967 else
4968 {
4969 s0 = algn (s0L, s0H, IREG (0) & 3);
4970 s1 = algn (s1L, s1H, IREG (1) & 3);
4971 }
4972
4973 STORE (DREG (dst0),
4974 ((((s0 >> 0) & 0xff) + ((s1 >> 0) & 0xff)) << 0) |
4975 ((((s0 >> 8) & 0xff) + ((s1 >> 8) & 0xff)) << 16));
4976 STORE (DREG (dst1),
4977 ((((s0 >> 16) & 0xff) + ((s1 >> 16) & 0xff)) << 0) |
4978 ((((s0 >> 24) & 0xff) + ((s1 >> 24) & 0xff)) << 16));
4979
4980 /* Implicit DISALGNEXCPT in parallel. */
4981 DIS_ALGN_EXPT |= 1;
4982 }
4983 else if (aop == 1 && aopcde == 21 && x == 0 && HL == 0)
4984 {
4985 bu32 s0, s0L, s0H, s1, s1L, s1H;
4986
4987 TRACE_INSN (cpu, "(R%i, R%i) = BYTEOP16M (R%i:%i, R%i:%i)%s;", dst1, dst0,
4988 src0 + 1, src0, src1 + 1, src1, s ? " (R)" : "");
4989
4990 if ((src1 != 0 && src1 != 2) || (src0 != 0 && src0 != 2))
4991 illegal_instruction (cpu);
4992
4993 if (dst0 == dst1)
4994 illegal_instruction_combination (cpu);
4995
4996 s0L = DREG (src0);
4997 s0H = DREG (src0 + 1);
4998 s1L = DREG (src1);
4999 s1H = DREG (src1 + 1);
5000 if (s)
5001 {
5002 s0 = algn (s0H, s0L, IREG (0) & 3);
5003 s1 = algn (s1H, s1L, IREG (1) & 3);
5004 }
5005 else
5006 {
5007 s0 = algn (s0L, s0H, IREG (0) & 3);
5008 s1 = algn (s1L, s1H, IREG (1) & 3);
5009 }
5010
5011 STORE (DREG (dst0),
5012 (((((s0 >> 0) & 0xff) - ((s1 >> 0) & 0xff)) << 0) & 0xffff) |
5013 (((((s0 >> 8) & 0xff) - ((s1 >> 8) & 0xff)) << 16)));
5014 STORE (DREG (dst1),
5015 (((((s0 >> 16) & 0xff) - ((s1 >> 16) & 0xff)) << 0) & 0xffff) |
5016 (((((s0 >> 24) & 0xff) - ((s1 >> 24) & 0xff)) << 16)));
5017
5018 /* Implicit DISALGNEXCPT in parallel. */
5019 DIS_ALGN_EXPT |= 1;
5020 }
5021 else if (aop == 1 && aopcde == 7 && x == 0 && s == 0 && HL == 0)
5022 {
5023 TRACE_INSN (cpu, "R%i = MIN (R%i, R%i);", dst0, src0, src1);
5024 SET_DREG (dst0, min32 (cpu, DREG (src0), DREG (src1)));
5025 }
5026 else if (aop == 0 && aopcde == 7 && x == 0 && s == 0 && HL == 0)
5027 {
5028 TRACE_INSN (cpu, "R%i = MAX (R%i, R%i);", dst0, src0, src1);
5029 SET_DREG (dst0, max32 (cpu, DREG (src0), DREG (src1)));
5030 }
5031 else if (aop == 2 && aopcde == 7 && x == 0 && s == 0 && HL == 0)
5032 {
5033 bu32 val = DREG (src0);
5034 int v;
5035
5036 TRACE_INSN (cpu, "R%i = ABS R%i;", dst0, src0);
5037
5038 if (val >> 31)
5039 val = -val;
5040 v = (val == 0x80000000);
5041 if (v)
5042 val = 0x7fffffff;
5043 SET_DREG (dst0, val);
5044
5045 SET_ASTATREG (v, v);
5046 if (v)
5047 SET_ASTATREG (vs, 1);
5048 setflags_nz (cpu, val);
5049 }
5050 else if (aop == 3 && aopcde == 7 && x == 0 && HL == 0)
5051 {
5052 bu32 val = DREG (src0);
5053
5054 TRACE_INSN (cpu, "R%i = - R%i%s;", dst0, src0, amod1 (s, 0));
5055
5056 if (s && val == 0x80000000)
5057 {
5058 val = 0x7fffffff;
5059 SET_ASTATREG (v, 1);
5060 SET_ASTATREG (vs, 1);
5061 }
5062 else if (val == 0x80000000)
5063 val = 0x80000000;
5064 else
5065 val = -val;
5066 SET_DREG (dst0, val);
5067
5068 SET_ASTATREG (az, val == 0);
5069 SET_ASTATREG (an, val & 0x80000000);
5070 }
5071 else if (aop == 2 && aopcde == 6 && x == 0 && s == 0 && HL == 0)
5072 {
5073 bu32 in = DREG (src0);
5074 bu32 hi = (in & 0x80000000 ? (bu32)-(bs16)(in >> 16) : in >> 16) << 16;
5075 bu32 lo = (in & 0x8000 ? (bu32)-(bs16)(in & 0xFFFF) : in) & 0xFFFF;
5076 int v;
5077
5078 TRACE_INSN (cpu, "R%i = ABS R%i (V);", dst0, src0);
5079
5080 v = 0;
5081 if (hi == 0x80000000)
5082 {
5083 hi = 0x7fff0000;
5084 v = 1;
5085 }
5086 if (lo == 0x8000)
5087 {
5088 lo = 0x7fff;
5089 v = 1;
5090 }
5091 SET_DREG (dst0, hi | lo);
5092
5093 SET_ASTATREG (v, v);
5094 if (v)
5095 SET_ASTATREG (vs, 1);
5096 setflags_nz_2x16 (cpu, DREG (dst0));
5097 }
5098 else if (aop == 1 && aopcde == 6 && x == 0 && s == 0 && HL == 0)
5099 {
5100 TRACE_INSN (cpu, "R%i = MIN (R%i, R%i) (V);", dst0, src0, src1);
5101 SET_DREG (dst0, min2x16 (cpu, DREG (src0), DREG (src1)));
5102 }
5103 else if (aop == 0 && aopcde == 6 && x == 0 && s == 0 && HL == 0)
5104 {
5105 TRACE_INSN (cpu, "R%i = MAX (R%i, R%i) (V);", dst0, src0, src1);
5106 SET_DREG (dst0, max2x16 (cpu, DREG (src0), DREG (src1)));
5107 }
5108 else if (aop == 0 && aopcde == 24 && x == 0 && s == 0 && HL == 0)
5109 {
5110 TRACE_INSN (cpu, "R%i = BYTEPACK (R%i, R%i);", dst0, src0, src1);
5111 STORE (DREG (dst0),
5112 (((DREG (src0) >> 0) & 0xff) << 0) |
5113 (((DREG (src0) >> 16) & 0xff) << 8) |
5114 (((DREG (src1) >> 0) & 0xff) << 16) |
5115 (((DREG (src1) >> 16) & 0xff) << 24));
5116
5117 /* Implicit DISALGNEXCPT in parallel. */
5118 DIS_ALGN_EXPT |= 1;
5119 }
5120 else if (aop == 1 && aopcde == 24 && x == 0 && HL == 0)
5121 {
5122 int order, lo, hi;
5123 bu64 comb_src;
5124 bu8 bytea, byteb, bytec, byted;
5125
5126 TRACE_INSN (cpu, "(R%i, R%i) = BYTEUNPACK R%i:%i%s;",
5127 dst1, dst0, src0 + 1, src0, s ? " (R)" : "");
5128
5129 if ((src1 != 0 && src1 != 2) || (src0 != 0 && src0 != 2))
5130 illegal_instruction (cpu);
5131
5132 if (dst0 == dst1)
5133 illegal_instruction_combination (cpu);
5134
5135 order = IREG (0) & 0x3;
5136 if (s)
5137 hi = src0, lo = src0 + 1;
5138 else
5139 hi = src0 + 1, lo = src0;
5140 comb_src = (((bu64)DREG (hi)) << 32) | DREG (lo);
5141 bytea = (comb_src >> (0 + 8 * order));
5142 byteb = (comb_src >> (8 + 8 * order));
5143 bytec = (comb_src >> (16 + 8 * order));
5144 byted = (comb_src >> (24 + 8 * order));
5145 STORE (DREG (dst0), bytea | ((bu32)byteb << 16));
5146 STORE (DREG (dst1), bytec | ((bu32)byted << 16));
5147
5148 /* Implicit DISALGNEXCPT in parallel. */
5149 DIS_ALGN_EXPT |= 1;
5150 }
5151 else if (aopcde == 13 && HL == 0 && x == 0 && s == 0)
5152 {
5153 const char *searchmodes[] = { "GT", "GE", "LT", "LE" };
5154 bool up_hi, up_lo;
5155 bs16 a0_lo, a1_lo, src_hi, src_lo;
5156
5157 TRACE_INSN (cpu, "(R%i, R%i) = SEARCH R%i (%s);",
5158 dst1, dst0, src0, searchmodes[aop]);
5159
5160 /* XXX: The parallel version is a bit weird in its limits:
5161
5162 This instruction can be issued in parallel with the combination of one
5163 16-bit length load instruction to the P0 register and one 16-bit NOP.
5164 No other instructions can be issued in parallel with the Vector Search
5165 instruction. Note the following legal and illegal forms.
5166 (r1, r0) = search r2 (LT) || r2 = [p0++p3]; // ILLEGAL
5167 (r1, r0) = search r2 (LT) || r2 = [p0++]; // LEGAL
5168 (r1, r0) = search r2 (LT) || r2 = [p0++]; // LEGAL
5169
5170 Unfortunately, our parallel insn state doesn't (currently) track enough
5171 details to be able to check this. */
5172
5173 if (dst0 == dst1)
5174 illegal_instruction_combination (cpu);
5175
5176 up_hi = up_lo = false;
5177 a0_lo = AWREG (0);
5178 a1_lo = AWREG (1);
5179 src_lo = DREG (src0);
5180 src_hi = DREG (src0) >> 16;
5181
5182 switch (aop)
5183 {
5184 case 0:
5185 up_hi = (src_hi > a1_lo);
5186 up_lo = (src_lo > a0_lo);
5187 break;
5188 case 1:
5189 up_hi = (src_hi >= a1_lo);
5190 up_lo = (src_lo >= a0_lo);
5191 break;
5192 case 2:
5193 up_hi = (src_hi < a1_lo);
5194 up_lo = (src_lo < a0_lo);
5195 break;
5196 case 3:
5197 up_hi = (src_hi <= a1_lo);
5198 up_lo = (src_lo <= a0_lo);
5199 break;
5200 }
5201
5202 if (up_hi)
5203 {
5204 SET_AREG (1, src_hi);
5205 SET_DREG (dst1, PREG (0));
5206 }
5207 else
5208 SET_AREG (1, a1_lo);
5209
5210 if (up_lo)
5211 {
5212 SET_AREG (0, src_lo);
5213 SET_DREG (dst0, PREG (0));
5214 }
5215 else
5216 SET_AREG (0, a0_lo);
5217 }
5218 else
5219 illegal_instruction (cpu);
5220 }
5221
5222 static void
5223 decode_dsp32shift_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
5224 {
5225 /* dsp32shift
5226 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5227 | 1 | 1 | 0 | 0 |.M.| 1 | 1 | 0 | 0 | - | - |.sopcde............|
5228 |.sop...|.HLs...|.dst0......| - | - | - |.src0......|.src1......|
5229 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5230 int HLs = ((iw1 >> DSP32Shift_HLs_bits) & DSP32Shift_HLs_mask);
5231 int sop = ((iw1 >> DSP32Shift_sop_bits) & DSP32Shift_sop_mask);
5232 int src0 = ((iw1 >> DSP32Shift_src0_bits) & DSP32Shift_src0_mask);
5233 int src1 = ((iw1 >> DSP32Shift_src1_bits) & DSP32Shift_src1_mask);
5234 int dst0 = ((iw1 >> DSP32Shift_dst0_bits) & DSP32Shift_dst0_mask);
5235 int sopcde = ((iw0 >> (DSP32Shift_sopcde_bits - 16)) & DSP32Shift_sopcde_mask);
5236 int M = ((iw0 >> (DSP32Shift_M_bits - 16)) & DSP32Shift_M_mask);
5237
5238 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dsp32shift);
5239 TRACE_EXTRACT (cpu, "%s: M:%i sopcde:%i sop:%i HLs:%i dst0:%i src0:%i src1:%i",
5240 __func__, M, sopcde, sop, HLs, dst0, src0, src1);
5241
5242 if ((sop == 0 || sop == 1) && sopcde == 0)
5243 {
5244 bu16 val;
5245 bs32 shft = (bs8)(DREG (src0) << 2) >> 2;
5246
5247 TRACE_INSN (cpu, "R%i.%c = ASHIFT R%i.%c BY R%i.L%s;",
5248 dst0, HLs < 2 ? 'L' : 'H',
5249 src1, HLs & 1 ? 'H' : 'L',
5250 src0, sop == 1 ? " (S)" : "");
5251
5252 if ((HLs & 1) == 0)
5253 val = (bu16)(DREG (src1) & 0xFFFF);
5254 else
5255 val = (bu16)((DREG (src1) & 0xFFFF0000) >> 16);
5256
5257 /* Positive shift magnitudes produce Logical Left shifts.
5258 Negative shift magnitudes produce Arithmetic Right shifts. */
5259 if (shft <= 0)
5260 val = ashiftrt (cpu, val, -shft, 16);
5261 else
5262 {
5263 int sgn = (val >> 15) & 0x1;
5264
5265 val = lshift (cpu, val, shft, 16, sop == 1, 1);
5266 if (((val >> 15) & 0x1) != sgn)
5267 {
5268 SET_ASTATREG (v, 1);
5269 SET_ASTATREG (vs, 1);
5270 }
5271 }
5272
5273 if ((HLs & 2) == 0)
5274 STORE (DREG (dst0), REG_H_L (DREG (dst0), val));
5275 else
5276 STORE (DREG (dst0), REG_H_L (val << 16, DREG (dst0)));
5277 }
5278 else if (sop == 2 && sopcde == 0)
5279 {
5280 bs32 shft = (bs8)(DREG (src0) << 2) >> 2;
5281 bu16 val;
5282
5283 TRACE_INSN (cpu, "R%i.%c = LSHIFT R%i.%c BY R%i.L;",
5284 dst0, HLs < 2 ? 'L' : 'H',
5285 src1, HLs & 1 ? 'H' : 'L', src0);
5286
5287 if ((HLs & 1) == 0)
5288 val = (bu16)(DREG (src1) & 0xFFFF);
5289 else
5290 val = (bu16)((DREG (src1) & 0xFFFF0000) >> 16);
5291
5292 if (shft < 0)
5293 val = val >> (-1 * shft);
5294 else
5295 val = val << shft;
5296
5297 if ((HLs & 2) == 0)
5298 SET_DREG (dst0, REG_H_L (DREG (dst0), val));
5299 else
5300 SET_DREG (dst0, REG_H_L (val << 16, DREG (dst0)));
5301
5302 SET_ASTATREG (az, !((val & 0xFFFF0000) == 0) || ((val & 0xFFFF) == 0));
5303 SET_ASTATREG (an, (!!(val & 0x80000000)) ^ (!!(val & 0x8000)));
5304 SET_ASTATREG (v, 0);
5305 }
5306 else if (sop == 2 && sopcde == 3 && (HLs == 1 || HLs == 0))
5307 {
5308 int shift = imm6 (DREG (src0) & 0xFFFF);
5309 bu32 cc = CCREG;
5310 bu40 acc = get_unextended_acc (cpu, HLs);
5311
5312 TRACE_INSN (cpu, "A%i = ROT A%i BY R%i.L;", HLs, HLs, src0);
5313 TRACE_DECODE (cpu, "A%i:%#"PRIx64" shift:%i CC:%i", HLs, acc, shift, cc);
5314
5315 acc = rot40 (acc, shift, &cc);
5316 SET_AREG (HLs, acc);
5317 if (shift)
5318 SET_CCREG (cc);
5319 }
5320 else if (sop == 0 && sopcde == 3 && (HLs == 0 || HLs == 1))
5321 {
5322 bs32 shft = (bs8)(DREG (src0) << 2) >> 2;
5323 bu64 acc = get_extended_acc (cpu, HLs);
5324 bu64 val;
5325
5326 HLs = !!HLs;
5327 TRACE_INSN (cpu, "A%i = ASHIFT A%i BY R%i.L;", HLs, HLs, src0);
5328 TRACE_DECODE (cpu, "A%i:%#"PRIx64" shift:%i", HLs, acc, shft);
5329
5330 if (shft <= 0)
5331 val = ashiftrt (cpu, acc, -shft, 40);
5332 else
5333 val = lshift (cpu, acc, shft, 40, 0, 0);
5334
5335 STORE (AXREG (HLs), (val >> 32) & 0xff);
5336 STORE (AWREG (HLs), (val & 0xffffffff));
5337 STORE (ASTATREG (av[HLs]), 0);
5338 }
5339 else if (sop == 1 && sopcde == 3 && (HLs == 0 || HLs == 1))
5340 {
5341 bs32 shft = (bs8)(DREG (src0) << 2) >> 2;
5342 bu64 acc = get_unextended_acc (cpu, HLs);
5343 bu64 val;
5344
5345 HLs = !!HLs;
5346 TRACE_INSN (cpu, "A%i = LSHIFT A%i BY R%i.L;", HLs, HLs, src0);
5347 TRACE_DECODE (cpu, "A%i:%#"PRIx64" shift:%i", HLs, acc, shft);
5348
5349 if (shft <= 0)
5350 val = lshiftrt (cpu, acc, -shft, 40);
5351 else
5352 val = lshift (cpu, acc, shft, 40, 0, 0);
5353
5354 STORE (AXREG (HLs), (val >> 32) & 0xff);
5355 STORE (AWREG (HLs), (val & 0xffffffff));
5356 STORE (ASTATREG (av[HLs]), 0);
5357 }
5358 else if (HLs != 0)
5359 /* All the insns after this point don't use HLs. */
5360 illegal_instruction (cpu);
5361 else if ((sop == 0 || sop == 1) && sopcde == 1 && HLs == 0)
5362 {
5363 bs32 shft = (bs8)(DREG (src0) << 2) >> 2;
5364 bu16 val0, val1;
5365 bu32 astat;
5366
5367 TRACE_INSN (cpu, "R%i = ASHIFT R%i BY R%i.L (V%s);",
5368 dst0, src1, src0, sop == 1 ? ",S" : "");
5369
5370 val0 = (bu16)DREG (src1) & 0xFFFF;
5371 val1 = (bu16)((DREG (src1) & 0xFFFF0000) >> 16);
5372
5373 if (shft <= 0)
5374 {
5375 val0 = ashiftrt (cpu, val0, -shft, 16);
5376 astat = ASTAT;
5377 val1 = ashiftrt (cpu, val1, -shft, 16);
5378 }
5379 else
5380 {
5381 int sgn0 = (val0 >> 15) & 0x1;
5382 int sgn1 = (val1 >> 15) & 0x1;
5383
5384 val0 = lshift (cpu, val0, shft, 16, sop == 1, 1);
5385 astat = ASTAT;
5386 val1 = lshift (cpu, val1, shft, 16, sop == 1, 1);
5387
5388 if ((sgn0 != ((val0 >> 15) & 0x1)) || (sgn1 != ((val1 >> 15) & 0x1)))
5389 {
5390 SET_ASTATREG (v, 1);
5391 SET_ASTATREG (vs, 1);
5392 }
5393 }
5394 SET_ASTAT (ASTAT | astat);
5395 STORE (DREG (dst0), (val1 << 16) | val0);
5396 }
5397 else if ((sop == 0 || sop == 1 || sop == 2) && sopcde == 2)
5398 {
5399 /* dregs = [LA]SHIFT dregs BY dregs_lo (opt_S) */
5400 /* sop == 1 : opt_S */
5401 bu32 v = DREG (src1);
5402 /* LSHIFT uses sign extended low 6 bits of dregs_lo. */
5403 bs32 shft = (bs8)(DREG (src0) << 2) >> 2;
5404
5405 TRACE_INSN (cpu, "R%i = %cSHIFT R%i BY R%i.L%s;", dst0,
5406 shft && sop != 2 ? 'A' : 'L', src1, src0,
5407 sop == 1 ? " (S)" : "");
5408
5409 if (shft < 0)
5410 {
5411 if (sop == 2)
5412 STORE (DREG (dst0), lshiftrt (cpu, v, -shft, 32));
5413 else
5414 STORE (DREG (dst0), ashiftrt (cpu, v, -shft, 32));
5415 }
5416 else
5417 {
5418 bu32 val = lshift (cpu, v, shft, 32, sop == 1, 1);
5419
5420 STORE (DREG (dst0), val);
5421 if (((v >> 31) & 0x1) != ((val >> 31) & 0x1))
5422 {
5423 SET_ASTATREG (v, 1);
5424 SET_ASTATREG (vs, 1);
5425 }
5426 }
5427 }
5428 else if (sop == 3 && sopcde == 2)
5429 {
5430 int shift = imm6 (DREG (src0) & 0xFFFF);
5431 bu32 src = DREG (src1);
5432 bu32 ret, cc = CCREG;
5433
5434 TRACE_INSN (cpu, "R%i = ROT R%i BY R%i.L;", dst0, src1, src0);
5435 TRACE_DECODE (cpu, "R%i:%#x R%i:%#x shift:%i CC:%i",
5436 dst0, DREG (dst0), src1, src, shift, cc);
5437
5438 ret = rot32 (src, shift, &cc);
5439 STORE (DREG (dst0), ret);
5440 if (shift)
5441 SET_CCREG (cc);
5442 }
5443 else if (sop == 2 && sopcde == 1 && HLs == 0)
5444 {
5445 bs32 shft = (bs8)(DREG (src0) << 2) >> 2;
5446 bu16 val0, val1;
5447 bu32 astat;
5448
5449 TRACE_INSN (cpu, "R%i = LSHIFT R%i BY R%i.L (V);", dst0, src1, src0);
5450
5451 val0 = (bu16)DREG (src1) & 0xFFFF;
5452 val1 = (bu16)((DREG (src1) & 0xFFFF0000) >> 16);
5453
5454 if (shft <= 0)
5455 {
5456 val0 = lshiftrt (cpu, val0, -shft, 16);
5457 astat = ASTAT;
5458 val1 = lshiftrt (cpu, val1, -shft, 16);
5459 }
5460 else
5461 {
5462 val0 = lshift (cpu, val0, shft, 16, 0, 0);
5463 astat = ASTAT;
5464 val1 = lshift (cpu, val1, shft, 16, 0, 0);
5465 }
5466 SET_ASTAT (ASTAT | astat);
5467 STORE (DREG (dst0), (val1 << 16) | val0);
5468 }
5469 else if (sopcde == 4)
5470 {
5471 bu32 sv0 = DREG (src0);
5472 bu32 sv1 = DREG (src1);
5473 TRACE_INSN (cpu, "R%i = PACK (R%i.%c, R%i.%c);", dst0,
5474 src1, sop & 2 ? 'H' : 'L',
5475 src0, sop & 1 ? 'H' : 'L');
5476 if (sop & 1)
5477 sv0 >>= 16;
5478 if (sop & 2)
5479 sv1 >>= 16;
5480 STORE (DREG (dst0), (sv1 << 16) | (sv0 & 0xFFFF));
5481 }
5482 else if (sop == 0 && sopcde == 5)
5483 {
5484 bu32 sv1 = DREG (src1);
5485 TRACE_INSN (cpu, "R%i.L = SIGNBITS R%i;", dst0, src1);
5486 SET_DREG_L (dst0, signbits (sv1, 32));
5487 }
5488 else if (sop == 1 && sopcde == 5)
5489 {
5490 bu32 sv1 = DREG (src1);
5491 TRACE_INSN (cpu, "R%i.L = SIGNBITS R%i.L;", dst0, src1);
5492 SET_DREG_L (dst0, signbits (sv1, 16));
5493 }
5494 else if (sop == 2 && sopcde == 5)
5495 {
5496 bu32 sv1 = DREG (src1);
5497 TRACE_INSN (cpu, "R%i.L = SIGNBITS R%i.H;", dst0, src1);
5498 SET_DREG_L (dst0, signbits (sv1 >> 16, 16));
5499 }
5500 else if ((sop == 0 || sop == 1) && sopcde == 6)
5501 {
5502 bu64 acc = AXREG (sop);
5503 TRACE_INSN (cpu, "R%i.L = SIGNBITS A%i;", dst0, sop);
5504 acc <<= 32;
5505 acc |= AWREG (sop);
5506 SET_DREG_L (dst0, signbits (acc, 40) & 0xFFFF);
5507 }
5508 else if (sop == 3 && sopcde == 6)
5509 {
5510 bu32 v = ones (DREG (src1));
5511 TRACE_INSN (cpu, "R%i.L = ONES R%i;", dst0, src1);
5512 SET_DREG_L (dst0, v);
5513 }
5514 else if (sop == 0 && sopcde == 7)
5515 {
5516 bu16 sv1 = (bu16)signbits (DREG (src1), 32);
5517 bu16 sv0 = (bu16)DREG (src0);
5518 bu16 dst_lo;
5519
5520 TRACE_INSN (cpu, "R%i.L = EXPADJ (R%i, R%i.L);", dst0, src1, src0);
5521
5522 if ((sv1 & 0x1f) < (sv0 & 0x1f))
5523 dst_lo = sv1;
5524 else
5525 dst_lo = sv0;
5526 STORE (DREG (dst0), REG_H_L (DREG (dst0), dst_lo));
5527 }
5528 else if (sop == 1 && sopcde == 7)
5529 {
5530 /* Exponent adjust on two 16-bit inputs. Select
5531 smallest norm among 3 inputs. */
5532 bs16 src1_hi = (DREG (src1) & 0xFFFF0000) >> 16;
5533 bs16 src1_lo = (DREG (src1) & 0xFFFF);
5534 bu16 src0_lo = (DREG (src0) & 0xFFFF);
5535 bu16 tmp_hi, tmp_lo, tmp;
5536
5537 TRACE_INSN (cpu, "R%i.L = EXPADJ (R%i, R%i.L) (V);", dst0, src1, src0);
5538
5539 tmp_hi = signbits (src1_hi, 16);
5540 tmp_lo = signbits (src1_lo, 16);
5541
5542 if ((tmp_hi & 0xf) < (tmp_lo & 0xf))
5543 if ((tmp_hi & 0xf) < (src0_lo & 0xf))
5544 tmp = tmp_hi;
5545 else
5546 tmp = src0_lo;
5547 else
5548 if ((tmp_lo & 0xf) < (src0_lo & 0xf))
5549 tmp = tmp_lo;
5550 else
5551 tmp = src0_lo;
5552 STORE (DREG (dst0), REG_H_L (DREG (dst0), tmp));
5553 }
5554 else if (sop == 2 && sopcde == 7)
5555 {
5556 /* Exponent adjust on single 16-bit register. */
5557 bu16 tmp;
5558 bu16 src0_lo = (bu16)(DREG (src0) & 0xFFFF);
5559
5560 TRACE_INSN (cpu, "R%i.L = EXPADJ (R%i.L, R%i.L);", dst0, src1, src0);
5561
5562 tmp = signbits (DREG (src1) & 0xFFFF, 16);
5563
5564 if ((tmp & 0xf) < (src0_lo & 0xf))
5565 SET_DREG_L (dst0, tmp);
5566 else
5567 SET_DREG_L (dst0, src0_lo);
5568 }
5569 else if (sop == 3 && sopcde == 7)
5570 {
5571 bu16 tmp;
5572 bu16 src0_lo = (bu16)(DREG (src0) & 0xFFFF);
5573
5574 TRACE_INSN (cpu, "R%i.L = EXPADJ (R%i.H, R%i.L);", dst0, src1, src0);
5575
5576 tmp = signbits ((DREG (src1) & 0xFFFF0000) >> 16, 16);
5577
5578 if ((tmp & 0xf) < (src0_lo & 0xf))
5579 SET_DREG_L (dst0, tmp);
5580 else
5581 SET_DREG_L (dst0, src0_lo);
5582 }
5583 else if (sop == 0 && sopcde == 8)
5584 {
5585 bu64 acc = get_unextended_acc (cpu, 0);
5586 bu32 s0, s1;
5587
5588 TRACE_INSN (cpu, "BITMUX (R%i, R%i, A0) (ASR);", src0, src1);
5589
5590 if (src0 == src1)
5591 illegal_instruction_combination (cpu);
5592
5593 s0 = DREG (src0);
5594 s1 = DREG (src1);
5595 acc = (acc >> 2) |
5596 (((bu64)s0 & 1) << 38) |
5597 (((bu64)s1 & 1) << 39);
5598 STORE (DREG (src0), s0 >> 1);
5599 STORE (DREG (src1), s1 >> 1);
5600
5601 SET_AREG (0, acc);
5602 }
5603 else if (sop == 1 && sopcde == 8)
5604 {
5605 bu64 acc = get_unextended_acc (cpu, 0);
5606 bu32 s0, s1;
5607
5608 TRACE_INSN (cpu, "BITMUX (R%i, R%i, A0) (ASL);", src0, src1);
5609
5610 if (src0 == src1)
5611 illegal_instruction_combination (cpu);
5612
5613 s0 = DREG (src0);
5614 s1 = DREG (src1);
5615 acc = (acc << 2) |
5616 ((s0 >> 31) & 1) |
5617 ((s1 >> 30) & 2);
5618 STORE (DREG (src0), s0 << 1);
5619 STORE (DREG (src1), s1 << 1);
5620
5621 SET_AREG (0, acc);
5622 }
5623 else if ((sop == 0 || sop == 1) && sopcde == 9)
5624 {
5625 bs40 acc0 = get_unextended_acc (cpu, 0);
5626 bs16 sL, sH, out;
5627
5628 TRACE_INSN (cpu, "R%i.L = VIT_MAX (R%i) (AS%c);",
5629 dst0, src1, sop & 1 ? 'R' : 'L');
5630
5631 sL = DREG (src1);
5632 sH = DREG (src1) >> 16;
5633
5634 if (sop & 1)
5635 acc0 = (acc0 & 0xfeffffffffull) >> 1;
5636 else
5637 acc0 <<= 1;
5638
5639 if (((sH - sL) & 0x8000) == 0)
5640 {
5641 out = sH;
5642 acc0 |= (sop & 1) ? 0x80000000 : 1;
5643 }
5644 else
5645 out = sL;
5646
5647 SET_AREG (0, acc0);
5648 STORE (DREG (dst0), REG_H_L (DREG (dst0), out));
5649 }
5650 else if ((sop == 2 || sop == 3) && sopcde == 9)
5651 {
5652 bs40 acc0 = get_extended_acc (cpu, 0);
5653 bs16 s0L, s0H, s1L, s1H, out0, out1;
5654
5655 TRACE_INSN (cpu, "R%i = VIT_MAX (R%i, R%i) (AS%c);",
5656 dst0, src1, src0, sop & 1 ? 'R' : 'L');
5657
5658 s0L = DREG (src0);
5659 s0H = DREG (src0) >> 16;
5660 s1L = DREG (src1);
5661 s1H = DREG (src1) >> 16;
5662
5663 if (sop & 1)
5664 acc0 >>= 2;
5665 else
5666 acc0 <<= 2;
5667
5668 if (((s0H - s0L) & 0x8000) == 0)
5669 {
5670 out0 = s0H;
5671 acc0 |= (sop & 1) ? 0x40000000 : 2;
5672 }
5673 else
5674 out0 = s0L;
5675
5676 if (((s1H - s1L) & 0x8000) == 0)
5677 {
5678 out1 = s1H;
5679 acc0 |= (sop & 1) ? 0x80000000 : 1;
5680 }
5681 else
5682 out1 = s1L;
5683
5684 SET_AREG (0, acc0);
5685 STORE (DREG (dst0), REG_H_L (out1 << 16, out0));
5686 }
5687 else if (sop == 0 && sopcde == 10)
5688 {
5689 bu32 v = DREG (src0);
5690 bu32 x = DREG (src1);
5691 bu32 mask = (1 << (v & 0x1f)) - 1;
5692
5693 TRACE_INSN (cpu, "R%i = EXTRACT (R%i, R%i.L) (Z);", dst0, src1, src0);
5694
5695 x >>= ((v >> 8) & 0x1f);
5696 x &= mask;
5697 STORE (DREG (dst0), x);
5698 setflags_logical (cpu, x);
5699 }
5700 else if (sop == 1 && sopcde == 10)
5701 {
5702 bu32 v = DREG (src0);
5703 bu32 x = DREG (src1);
5704 bu32 sgn = (1 << (v & 0x1f)) >> 1;
5705 bu32 mask = (1 << (v & 0x1f)) - 1;
5706
5707 TRACE_INSN (cpu, "R%i = EXTRACT (R%i, R%i.L) (X);", dst0, src1, src0);
5708
5709 x >>= ((v >> 8) & 0x1f);
5710 x &= mask;
5711 if (x & sgn)
5712 x |= ~mask;
5713 STORE (DREG (dst0), x);
5714 setflags_logical (cpu, x);
5715 }
5716 else if ((sop == 2 || sop == 3) && sopcde == 10)
5717 {
5718 /* The first dregs is the "background" while the second dregs is the
5719 "foreground". The fg reg is used to overlay the bg reg and is:
5720 | nnnn nnnn | nnnn nnnn | xxxp pppp | xxxL LLLL |
5721 n = the fg bit field
5722 p = bit position in bg reg to start LSB of fg field
5723 L = number of fg bits to extract
5724 Using (X) sign-extends the fg bit field. */
5725 bu32 fg = DREG (src0);
5726 bu32 bg = DREG (src1);
5727 bu32 len = fg & 0x1f;
5728 bu32 mask = (1 << min (16, len)) - 1;
5729 bu32 fgnd = (fg >> 16) & mask;
5730 int shft = ((fg >> 8) & 0x1f);
5731
5732 TRACE_INSN (cpu, "R%i = DEPOSIT (R%i, R%i)%s;", dst0, src1, src0,
5733 sop == 3 ? " (X)" : "");
5734
5735 if (sop == 3)
5736 {
5737 /* Sign extend the fg bit field. */
5738 mask = -1;
5739 fgnd = ((bs32)(bs16)(fgnd << (16 - len))) >> (16 - len);
5740 }
5741 fgnd <<= shft;
5742 mask <<= shft;
5743 bg &= ~mask;
5744
5745 bg |= fgnd;
5746 STORE (DREG (dst0), bg);
5747 setflags_logical (cpu, bg);
5748 }
5749 else if (sop == 0 && sopcde == 11)
5750 {
5751 bu64 acc0 = get_unextended_acc (cpu, 0);
5752
5753 TRACE_INSN (cpu, "R%i.L = CC = BXORSHIFT (A0, R%i);", dst0, src0);
5754
5755 acc0 <<= 1;
5756 SET_CCREG (xor_reduce (acc0, DREG (src0)));
5757 SET_DREG (dst0, REG_H_L (DREG (dst0), CCREG));
5758 SET_AREG (0, acc0);
5759 }
5760 else if (sop == 1 && sopcde == 11)
5761 {
5762 bu64 acc0 = get_unextended_acc (cpu, 0);
5763
5764 TRACE_INSN (cpu, "R%i.L = CC = BXOR (A0, R%i);", dst0, src0);
5765
5766 SET_CCREG (xor_reduce (acc0, DREG (src0)));
5767 SET_DREG (dst0, REG_H_L (DREG (dst0), CCREG));
5768 }
5769 else if (sop == 0 && sopcde == 12)
5770 {
5771 bu64 acc0 = get_unextended_acc (cpu, 0);
5772 bu64 acc1 = get_unextended_acc (cpu, 1);
5773
5774 TRACE_INSN (cpu, "A0 = BXORSHIFT (A0, A1, CC);");
5775
5776 acc0 = (acc0 << 1) | (CCREG ^ xor_reduce (acc0, acc1));
5777 SET_AREG (0, acc0);
5778 }
5779 else if (sop == 1 && sopcde == 12)
5780 {
5781 bu64 acc0 = get_unextended_acc (cpu, 0);
5782 bu64 acc1 = get_unextended_acc (cpu, 1);
5783
5784 TRACE_INSN (cpu, "R%i.L = CC = BXOR (A0, A1, CC);", dst0);
5785
5786 SET_CCREG (CCREG ^ xor_reduce (acc0, acc1));
5787 acc0 = (acc0 << 1) | CCREG;
5788 SET_DREG (dst0, REG_H_L (DREG (dst0), CCREG));
5789 }
5790 else if ((sop == 0 || sop == 1 || sop == 2) && sopcde == 13)
5791 {
5792 int shift = (sop + 1) * 8;
5793 TRACE_INSN (cpu, "R%i = ALIGN%i (R%i, R%i);", dst0, shift, src1, src0);
5794 STORE (DREG (dst0), (DREG (src1) << (32 - shift)) | (DREG (src0) >> shift));
5795 }
5796 else
5797 illegal_instruction (cpu);
5798 }
5799
5800 static bu64
5801 sgn_extend (bu40 org, bu40 val, int size)
5802 {
5803 bu64 ret = val;
5804
5805 if (org & (1ULL << (size - 1)))
5806 {
5807 /* We need to shift in to the MSB which is set. */
5808 int n;
5809
5810 for (n = 40; n >= 0; n--)
5811 if (ret & (1ULL << n))
5812 break;
5813 ret |= (-1ULL << n);
5814 }
5815 else
5816 ret &= ~(-1ULL << 39);
5817
5818 return ret;
5819 }
5820 static void
5821 decode_dsp32shiftimm_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
5822 {
5823 /* dsp32shiftimm
5824 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
5825 | 1 | 1 | 0 | 0 |.M.| 1 | 1 | 0 | 1 | - | - |.sopcde............|
5826 |.sop...|.HLs...|.dst0......|.immag.................|.src1......|
5827 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
5828 int src1 = ((iw1 >> DSP32ShiftImm_src1_bits) & DSP32ShiftImm_src1_mask);
5829 int sop = ((iw1 >> DSP32ShiftImm_sop_bits) & DSP32ShiftImm_sop_mask);
5830 int bit8 = ((iw1 >> 8) & 0x1);
5831 int immag = ((iw1 >> DSP32ShiftImm_immag_bits) & DSP32ShiftImm_immag_mask);
5832 int newimmag = (-(iw1 >> DSP32ShiftImm_immag_bits) & DSP32ShiftImm_immag_mask);
5833 int dst0 = ((iw1 >> DSP32ShiftImm_dst0_bits) & DSP32ShiftImm_dst0_mask);
5834 int M = ((iw0 >> (DSP32ShiftImm_M_bits - 16)) & DSP32ShiftImm_M_mask);
5835 int sopcde = ((iw0 >> (DSP32ShiftImm_sopcde_bits - 16)) & DSP32ShiftImm_sopcde_mask);
5836 int HLs = ((iw1 >> DSP32ShiftImm_HLs_bits) & DSP32ShiftImm_HLs_mask);
5837
5838 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dsp32shiftimm);
5839 TRACE_EXTRACT (cpu, "%s: M:%i sopcde:%i sop:%i HLs:%i dst0:%i immag:%#x src1:%i",
5840 __func__, M, sopcde, sop, HLs, dst0, immag, src1);
5841
5842 if (sopcde == 0)
5843 {
5844 bu16 in = DREG (src1) >> ((HLs & 1) ? 16 : 0);
5845 bu16 result;
5846 bu32 v;
5847
5848 if (sop == 0)
5849 {
5850 TRACE_INSN (cpu, "R%i.%c = R%i.%c >>> %i;",
5851 dst0, (HLs & 2) ? 'H' : 'L',
5852 src1, (HLs & 1) ? 'H' : 'L', newimmag);
5853 if (newimmag > 16)
5854 {
5855 result = lshift (cpu, in, 16 - (newimmag & 0xF), 16, 0, 1);
5856 if (((result >> 15) & 0x1) != ((in >> 15) & 0x1))
5857 {
5858 SET_ASTATREG (v, 1);
5859 SET_ASTATREG (vs, 1);
5860 }
5861 }
5862 else
5863 result = ashiftrt (cpu, in, newimmag, 16);
5864 }
5865 else if (sop == 1 && bit8 == 0)
5866 {
5867 TRACE_INSN (cpu, "R%i.%c = R%i.%c << %i (S);",
5868 dst0, (HLs & 2) ? 'H' : 'L',
5869 src1, (HLs & 1) ? 'H' : 'L', immag);
5870 result = lshift (cpu, in, immag, 16, 1, 1);
5871 }
5872 else if (sop == 1 && bit8)
5873 {
5874 TRACE_INSN (cpu, "R%i.%c = R%i.%c >>> %i (S);",
5875 dst0, (HLs & 2) ? 'H' : 'L',
5876 src1, (HLs & 1) ? 'H' : 'L', newimmag);
5877 if (newimmag > 16)
5878 {
5879 int shift = 32 - newimmag;
5880 bu16 inshift = in << shift;
5881
5882 if (((inshift & ~0xFFFF)
5883 && ((inshift & ~0xFFFF) >> 16) != ~((bu32)~0 << shift))
5884 || (inshift & 0x8000) != (in & 0x8000))
5885 {
5886 if (in & 0x8000)
5887 result = 0x8000;
5888 else
5889 result = 0x7fff;
5890 SET_ASTATREG (v, 1);
5891 SET_ASTATREG (vs, 1);
5892 }
5893 else
5894 {
5895 result = inshift;
5896 SET_ASTATREG (v, 0);
5897 }
5898
5899 SET_ASTATREG (az, !result);
5900 SET_ASTATREG (an, !!(result & 0x8000));
5901 }
5902 else
5903 {
5904 result = ashiftrt (cpu, in, newimmag, 16);
5905 result = sgn_extend (in, result, 16);
5906 }
5907 }
5908 else if (sop == 2 && bit8)
5909 {
5910 TRACE_INSN (cpu, "R%i.%c = R%i.%c >> %i;",
5911 dst0, (HLs & 2) ? 'H' : 'L',
5912 src1, (HLs & 1) ? 'H' : 'L', newimmag);
5913 result = lshiftrt (cpu, in, newimmag, 16);
5914 }
5915 else if (sop == 2 && bit8 == 0)
5916 {
5917 TRACE_INSN (cpu, "R%i.%c = R%i.%c << %i;",
5918 dst0, (HLs & 2) ? 'H' : 'L',
5919 src1, (HLs & 1) ? 'H' : 'L', immag);
5920 result = lshift (cpu, in, immag, 16, 0, 1);
5921 }
5922 else
5923 illegal_instruction (cpu);
5924
5925 v = DREG (dst0);
5926 if (HLs & 2)
5927 STORE (DREG (dst0), (v & 0xFFFF) | (result << 16));
5928 else
5929 STORE (DREG (dst0), (v & 0xFFFF0000) | result);
5930 }
5931 else if (sop == 2 && sopcde == 3 && (HLs == 1 || HLs == 0))
5932 {
5933 int shift = imm6 (immag);
5934 bu32 cc = CCREG;
5935 bu40 acc = get_unextended_acc (cpu, HLs);
5936
5937 TRACE_INSN (cpu, "A%i = ROT A%i BY %i;", HLs, HLs, shift);
5938 TRACE_DECODE (cpu, "A%i:%#"PRIx64" shift:%i CC:%i", HLs, acc, shift, cc);
5939
5940 acc = rot40 (acc, shift, &cc);
5941 SET_AREG (HLs, acc);
5942 if (shift)
5943 SET_CCREG (cc);
5944 }
5945 else if (sop == 0 && sopcde == 3 && bit8 == 1 && HLs < 2)
5946 {
5947 /* Arithmetic shift, so shift in sign bit copies. */
5948 bu64 acc, val;
5949 int shift = uimm5 (newimmag);
5950
5951 TRACE_INSN (cpu, "A%i = A%i >>> %i;", HLs, HLs, shift);
5952
5953 acc = get_extended_acc (cpu, HLs);
5954 val = acc >> shift;
5955
5956 /* Sign extend again. */
5957 val = sgn_extend (acc, val, 40);
5958
5959 STORE (AXREG (HLs), (val >> 32) & 0xFF);
5960 STORE (AWREG (HLs), val & 0xFFFFFFFF);
5961 STORE (ASTATREG (an), !!(val & (1ULL << 39)));
5962 STORE (ASTATREG (az), !val);
5963 STORE (ASTATREG (av[HLs]), 0);
5964 }
5965 else if (((sop == 0 && sopcde == 3 && bit8 == 0)
5966 || (sop == 1 && sopcde == 3)) && HLs < 2)
5967 {
5968 bu64 acc;
5969 int shiftup = uimm5 (immag);
5970 int shiftdn = uimm5 (newimmag);
5971
5972 TRACE_INSN (cpu, "A%i = A%i %s %i;", HLs, HLs,
5973 sop == 0 ? "<<" : ">>",
5974 sop == 0 ? shiftup : shiftdn);
5975
5976 acc = AXREG (HLs);
5977 /* Logical shift, so shift in zeroes. */
5978 acc &= 0xFF;
5979 acc <<= 32;
5980 acc |= AWREG (HLs);
5981
5982 if (sop == 0)
5983 acc <<= shiftup;
5984 else
5985 {
5986 if (shiftdn <= 32)
5987 acc >>= shiftdn;
5988 else
5989 acc <<= 32 - (shiftdn & 0x1f);
5990 }
5991
5992 SET_AREG (HLs, acc);
5993 SET_ASTATREG (av[HLs], 0);
5994 SET_ASTATREG (an, !!(acc & 0x8000000000ull));
5995 SET_ASTATREG (az, (acc & 0xFFFFFFFFFF) == 0);
5996 }
5997 else if (HLs != 0)
5998 /* All the insns after this point don't use HLs. */
5999 illegal_instruction (cpu);
6000 else if (sop == 1 && sopcde == 1 && bit8 == 0)
6001 {
6002 int count = imm5 (immag);
6003 bu16 val0 = DREG (src1) >> 16;
6004 bu16 val1 = DREG (src1) & 0xFFFF;
6005 bu32 astat;
6006
6007 TRACE_INSN (cpu, "R%i = R%i << %i (V,S);", dst0, src1, count);
6008 if (count >= 0)
6009 {
6010 val0 = lshift (cpu, val0, count, 16, 1, 1);
6011 astat = ASTAT;
6012 val1 = lshift (cpu, val1, count, 16, 1, 1);
6013 }
6014 else
6015 {
6016 val0 = ashiftrt (cpu, val0, -count, 16);
6017 astat = ASTAT;
6018 val1 = ashiftrt (cpu, val1, -count, 16);
6019 }
6020 SET_ASTAT (ASTAT | astat);
6021
6022 STORE (DREG (dst0), (val0 << 16) | val1);
6023 }
6024 else if (sop == 2 && sopcde == 1 && bit8 == 1)
6025 {
6026 int count = imm5 (newimmag);
6027 bu16 val0 = DREG (src1) & 0xFFFF;
6028 bu16 val1 = DREG (src1) >> 16;
6029 bu32 astat;
6030
6031 TRACE_INSN (cpu, "R%i = R%i >> %i (V);", dst0, src1, count);
6032 val0 = lshiftrt (cpu, val0, count, 16);
6033 astat = ASTAT;
6034 val1 = lshiftrt (cpu, val1, count, 16);
6035 SET_ASTAT (ASTAT | astat);
6036
6037 STORE (DREG (dst0), val0 | (val1 << 16));
6038 }
6039 else if (sop == 2 && sopcde == 1 && bit8 == 0)
6040 {
6041 int count = imm5 (immag);
6042 bu16 val0 = DREG (src1) & 0xFFFF;
6043 bu16 val1 = DREG (src1) >> 16;
6044 bu32 astat;
6045
6046 TRACE_INSN (cpu, "R%i = R%i << %i (V);", dst0, src1, count);
6047 val0 = lshift (cpu, val0, count, 16, 0, 1);
6048 astat = ASTAT;
6049 val1 = lshift (cpu, val1, count, 16, 0, 1);
6050 SET_ASTAT (ASTAT | astat);
6051
6052 STORE (DREG (dst0), val0 | (val1 << 16));
6053 }
6054 else if (sopcde == 1 && (sop == 0 || (sop == 1 && bit8 == 1)))
6055 {
6056 int count = uimm5 (newimmag);
6057 bu16 val0 = DREG (src1) & 0xFFFF;
6058 bu16 val1 = DREG (src1) >> 16;
6059 bu32 astat;
6060
6061 TRACE_INSN (cpu, "R%i = R%i >>> %i %s;", dst0, src1, count,
6062 sop == 0 ? "(V)" : "(V,S)");
6063
6064 if (count > 16)
6065 {
6066 int sgn0 = (val0 >> 15) & 0x1;
6067 int sgn1 = (val1 >> 15) & 0x1;
6068
6069 val0 = lshift (cpu, val0, 16 - (count & 0xF), 16, 0, 1);
6070 astat = ASTAT;
6071 val1 = lshift (cpu, val1, 16 - (count & 0xF), 16, 0, 1);
6072
6073 if ((sgn0 != ((val0 >> 15) & 0x1)) || (sgn1 != ((val1 >> 15) & 0x1)))
6074 {
6075 SET_ASTATREG (v, 1);
6076 SET_ASTATREG (vs, 1);
6077 }
6078 }
6079 else
6080 {
6081 val0 = ashiftrt (cpu, val0, count, 16);
6082 astat = ASTAT;
6083 val1 = ashiftrt (cpu, val1, count, 16);
6084 }
6085
6086 SET_ASTAT (ASTAT | astat);
6087
6088 STORE (DREG (dst0), REG_H_L (val1 << 16, val0));
6089 }
6090 else if (sop == 1 && sopcde == 2)
6091 {
6092 int count = imm6 (immag);
6093
6094 TRACE_INSN (cpu, "R%i = R%i << %i (S);", dst0, src1, count);
6095
6096 if (count < 0)
6097 STORE (DREG (dst0), ashiftrt (cpu, DREG (src1), -count, 32));
6098 else
6099 STORE (DREG (dst0), lshift (cpu, DREG (src1), count, 32, 1, 1));
6100 }
6101 else if (sop == 2 && sopcde == 2)
6102 {
6103 int count = imm6 (newimmag);
6104
6105 TRACE_INSN (cpu, "R%i = R%i >> %i;", dst0, src1, count);
6106
6107 if (count < 0)
6108 STORE (DREG (dst0), lshift (cpu, DREG (src1), -count, 32, 0, 1));
6109 else
6110 STORE (DREG (dst0), lshiftrt (cpu, DREG (src1), count, 32));
6111 }
6112 else if (sop == 3 && sopcde == 2)
6113 {
6114 int shift = imm6 (immag);
6115 bu32 src = DREG (src1);
6116 bu32 ret, cc = CCREG;
6117
6118 TRACE_INSN (cpu, "R%i = ROT R%i BY %i;", dst0, src1, shift);
6119 TRACE_DECODE (cpu, "R%i:%#x R%i:%#x shift:%i CC:%i",
6120 dst0, DREG (dst0), src1, src, shift, cc);
6121
6122 ret = rot32 (src, shift, &cc);
6123 STORE (DREG (dst0), ret);
6124 if (shift)
6125 SET_CCREG (cc);
6126 }
6127 else if (sop == 0 && sopcde == 2)
6128 {
6129 int count = imm6 (newimmag);
6130
6131 TRACE_INSN (cpu, "R%i = R%i >>> %i;", dst0, src1, count);
6132
6133 if (count < 0)
6134 STORE (DREG (dst0), lshift (cpu, DREG (src1), -count, 32, 0, 1));
6135 else
6136 STORE (DREG (dst0), ashiftrt (cpu, DREG (src1), count, 32));
6137 }
6138 else
6139 illegal_instruction (cpu);
6140 }
6141
6142 static void
6143 outc (SIM_CPU *cpu, char ch)
6144 {
6145 SIM_DESC sd = CPU_STATE (cpu);
6146 sim_io_printf (sd, "%c", ch);
6147 if (ch == '\n')
6148 sim_io_flush_stdout (sd);
6149 }
6150
6151 static void
6152 decode_psedoDEBUG_0 (SIM_CPU *cpu, bu16 iw0)
6153 {
6154 /* psedoDEBUG
6155 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
6156 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 |.fn....|.grp.......|.reg.......|
6157 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
6158 SIM_DESC sd = CPU_STATE (cpu);
6159 int fn = ((iw0 >> PseudoDbg_fn_bits) & PseudoDbg_fn_mask);
6160 int grp = ((iw0 >> PseudoDbg_grp_bits) & PseudoDbg_grp_mask);
6161 int reg = ((iw0 >> PseudoDbg_reg_bits) & PseudoDbg_reg_mask);
6162
6163 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_psedoDEBUG);
6164 TRACE_EXTRACT (cpu, "%s: fn:%i grp:%i reg:%i", __func__, fn, grp, reg);
6165
6166 if ((reg == 0 || reg == 1) && fn == 3)
6167 {
6168 TRACE_INSN (cpu, "DBG A%i;", reg);
6169 sim_io_printf (sd, "DBG : A%i = %#"PRIx64"\n", reg,
6170 get_unextended_acc (cpu, reg));
6171 }
6172 else if (reg == 3 && fn == 3)
6173 {
6174 TRACE_INSN (cpu, "ABORT;");
6175 cec_exception (cpu, VEC_SIM_ABORT);
6176 SET_DREG (0, 1);
6177 }
6178 else if (reg == 4 && fn == 3)
6179 {
6180 TRACE_INSN (cpu, "HLT;");
6181 cec_exception (cpu, VEC_SIM_HLT);
6182 SET_DREG (0, 0);
6183 }
6184 else if (reg == 5 && fn == 3)
6185 unhandled_instruction (cpu, "DBGHALT");
6186 else if (reg == 6 && fn == 3)
6187 unhandled_instruction (cpu, "DBGCMPLX (dregs)");
6188 else if (reg == 7 && fn == 3)
6189 unhandled_instruction (cpu, "DBG");
6190 else if (grp == 0 && fn == 2)
6191 {
6192 TRACE_INSN (cpu, "OUTC R%i;", reg);
6193 outc (cpu, DREG (reg));
6194 }
6195 else if (fn == 0)
6196 {
6197 const char *reg_name = get_allreg_name (grp, reg);
6198 TRACE_INSN (cpu, "DBG %s;", reg_name);
6199 sim_io_printf (sd, "DBG : %s = 0x%08x\n", reg_name,
6200 reg_read (cpu, grp, reg));
6201 }
6202 else if (fn == 1)
6203 unhandled_instruction (cpu, "PRNT allregs");
6204 else
6205 illegal_instruction (cpu);
6206 }
6207
6208 static void
6209 decode_psedoOChar_0 (SIM_CPU *cpu, bu16 iw0)
6210 {
6211 /* psedoOChar
6212 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
6213 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |.ch............................|
6214 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
6215 int ch = ((iw0 >> PseudoChr_ch_bits) & PseudoChr_ch_mask);
6216
6217 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_psedoOChar);
6218 TRACE_EXTRACT (cpu, "%s: ch:%#x", __func__, ch);
6219 TRACE_INSN (cpu, "OUTC %#x;", ch);
6220
6221 outc (cpu, ch);
6222 }
6223
6224 static void
6225 decode_psedodbg_assert_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1, bu32 pc)
6226 {
6227 /* psedodbg_assert
6228 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
6229 | 1 | 1 | 1 | 1 | 0 | - | - | - | dbgop |.grp.......|.regtest...|
6230 |.expected......................................................|
6231 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
6232 SIM_DESC sd = CPU_STATE (cpu);
6233 int expected = ((iw1 >> PseudoDbg_Assert_expected_bits) & PseudoDbg_Assert_expected_mask);
6234 int dbgop = ((iw0 >> (PseudoDbg_Assert_dbgop_bits - 16)) & PseudoDbg_Assert_dbgop_mask);
6235 int grp = ((iw0 >> (PseudoDbg_Assert_grp_bits - 16)) & PseudoDbg_Assert_grp_mask);
6236 int regtest = ((iw0 >> (PseudoDbg_Assert_regtest_bits - 16)) & PseudoDbg_Assert_regtest_mask);
6237 int offset;
6238 bu16 actual;
6239 bu32 val = reg_read (cpu, grp, regtest);
6240 const char *reg_name = get_allreg_name (grp, regtest);
6241 const char *dbg_name, *dbg_appd;
6242
6243 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_psedodbg_assert);
6244 TRACE_EXTRACT (cpu, "%s: dbgop:%i grp:%i regtest:%i expected:%#x",
6245 __func__, dbgop, grp, regtest, expected);
6246
6247 if (dbgop == 0 || dbgop == 2)
6248 {
6249 dbg_name = dbgop == 0 ? "DBGA" : "DBGAL";
6250 dbg_appd = dbgop == 0 ? ".L" : "";
6251 offset = 0;
6252 }
6253 else if (dbgop == 1 || dbgop == 3)
6254 {
6255 dbg_name = dbgop == 1 ? "DBGA" : "DBGAH";
6256 dbg_appd = dbgop == 1 ? ".H" : "";
6257 offset = 16;
6258 }
6259 else
6260 illegal_instruction (cpu);
6261
6262 actual = val >> offset;
6263
6264 TRACE_INSN (cpu, "%s (%s%s, 0x%x);", dbg_name, reg_name, dbg_appd, expected);
6265 if (actual != expected)
6266 {
6267 sim_io_printf (sd, "FAIL at %#x: %s (%s%s, 0x%04x); actual value %#x\n",
6268 pc, dbg_name, reg_name, dbg_appd, expected, actual);
6269
6270 /* Decode the actual ASTAT bits that are different. */
6271 if (grp == 4 && regtest == 6)
6272 {
6273 int i;
6274
6275 sim_io_printf (sd, "Expected ASTAT:\n");
6276 for (i = 0; i < 16; ++i)
6277 sim_io_printf (sd, " %8s%c%i%s",
6278 astat_names[i + offset],
6279 (((expected >> i) & 1) != ((actual >> i) & 1))
6280 ? '!' : ' ',
6281 (expected >> i) & 1,
6282 i == 7 ? "\n" : "");
6283 sim_io_printf (sd, "\n");
6284
6285 sim_io_printf (sd, "Actual ASTAT:\n");
6286 for (i = 0; i < 16; ++i)
6287 sim_io_printf (sd, " %8s%c%i%s",
6288 astat_names[i + offset],
6289 (((expected >> i) & 1) != ((actual >> i) & 1))
6290 ? '!' : ' ',
6291 (actual >> i) & 1,
6292 i == 7 ? "\n" : "");
6293 sim_io_printf (sd, "\n");
6294 }
6295
6296 cec_exception (cpu, VEC_SIM_DBGA);
6297 SET_DREG (0, 1);
6298 }
6299 }
6300
6301 static bu32
6302 _interp_insn_bfin (SIM_CPU *cpu, bu32 pc)
6303 {
6304 bu32 insn_len;
6305 bu16 iw0, iw1;
6306
6307 BFIN_CPU_STATE.multi_pc = pc;
6308 iw0 = IFETCH (pc);
6309 if ((iw0 & 0xc000) != 0xc000)
6310 {
6311 /* 16-bit opcode. */
6312 insn_len = 2;
6313 if (INSN_LEN == 0)
6314 INSN_LEN = insn_len;
6315
6316 TRACE_EXTRACT (cpu, "%s: iw0:%#x", __func__, iw0);
6317 if ((iw0 & 0xFF00) == 0x0000)
6318 decode_ProgCtrl_0 (cpu, iw0, pc);
6319 else if ((iw0 & 0xFFC0) == 0x0240)
6320 decode_CaCTRL_0 (cpu, iw0);
6321 else if ((iw0 & 0xFF80) == 0x0100)
6322 decode_PushPopReg_0 (cpu, iw0);
6323 else if ((iw0 & 0xFE00) == 0x0400)
6324 decode_PushPopMultiple_0 (cpu, iw0);
6325 else if ((iw0 & 0xFE00) == 0x0600)
6326 decode_ccMV_0 (cpu, iw0);
6327 else if ((iw0 & 0xF800) == 0x0800)
6328 decode_CCflag_0 (cpu, iw0);
6329 else if ((iw0 & 0xFFE0) == 0x0200)
6330 decode_CC2dreg_0 (cpu, iw0);
6331 else if ((iw0 & 0xFF00) == 0x0300)
6332 decode_CC2stat_0 (cpu, iw0);
6333 else if ((iw0 & 0xF000) == 0x1000)
6334 decode_BRCC_0 (cpu, iw0, pc);
6335 else if ((iw0 & 0xF000) == 0x2000)
6336 decode_UJUMP_0 (cpu, iw0, pc);
6337 else if ((iw0 & 0xF000) == 0x3000)
6338 decode_REGMV_0 (cpu, iw0);
6339 else if ((iw0 & 0xFC00) == 0x4000)
6340 decode_ALU2op_0 (cpu, iw0);
6341 else if ((iw0 & 0xFE00) == 0x4400)
6342 decode_PTR2op_0 (cpu, iw0);
6343 else if ((iw0 & 0xF800) == 0x4800)
6344 decode_LOGI2op_0 (cpu, iw0);
6345 else if ((iw0 & 0xF000) == 0x5000)
6346 decode_COMP3op_0 (cpu, iw0);
6347 else if ((iw0 & 0xF800) == 0x6000)
6348 decode_COMPI2opD_0 (cpu, iw0);
6349 else if ((iw0 & 0xF800) == 0x6800)
6350 decode_COMPI2opP_0 (cpu, iw0);
6351 else if ((iw0 & 0xF000) == 0x8000)
6352 decode_LDSTpmod_0 (cpu, iw0);
6353 else if ((iw0 & 0xFF60) == 0x9E60)
6354 decode_dagMODim_0 (cpu, iw0);
6355 else if ((iw0 & 0xFFF0) == 0x9F60)
6356 decode_dagMODik_0 (cpu, iw0);
6357 else if ((iw0 & 0xFC00) == 0x9C00)
6358 decode_dspLDST_0 (cpu, iw0);
6359 else if ((iw0 & 0xF000) == 0x9000)
6360 decode_LDST_0 (cpu, iw0);
6361 else if ((iw0 & 0xFC00) == 0xB800)
6362 decode_LDSTiiFP_0 (cpu, iw0);
6363 else if ((iw0 & 0xE000) == 0xA000)
6364 decode_LDSTii_0 (cpu, iw0);
6365 else
6366 {
6367 TRACE_EXTRACT (cpu, "%s: no matching 16-bit pattern", __func__);
6368 illegal_instruction_or_combination (cpu);
6369 }
6370 return insn_len;
6371 }
6372
6373 /* Grab the next 16 bits to determine if it's a 32-bit or 64-bit opcode. */
6374 iw1 = IFETCH (pc + 2);
6375 if ((iw0 & BIT_MULTI_INS) && (iw0 & 0xe800) != 0xe800 /* not linkage */)
6376 {
6377 SIM_DESC sd = CPU_STATE (cpu);
6378 trace_prefix (sd, cpu, NULL_CIA, pc, TRACE_LINENUM_P (cpu),
6379 NULL, 0, "|| %#"PRIx64, sim_events_time (sd));
6380 insn_len = 8;
6381 PARALLEL_GROUP = BFIN_PARALLEL_GROUP0;
6382 }
6383 else
6384 insn_len = 4;
6385
6386 TRACE_EXTRACT (cpu, "%s: iw0:%#x iw1:%#x insn_len:%i", __func__,
6387 iw0, iw1, insn_len);
6388
6389 /* Only cache on first run through (in case of parallel insns). */
6390 if (INSN_LEN == 0)
6391 INSN_LEN = insn_len;
6392 else
6393 /* Once you're past the first slot, only 16bit insns are valid. */
6394 illegal_instruction_combination (cpu);
6395
6396 if ((iw0 & 0xf7ff) == 0xc003 && (iw1 & 0xfe00) == 0x1800)
6397 {
6398 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dsp32mac);
6399 TRACE_INSN (cpu, "MNOP;");
6400 }
6401 else if (((iw0 & 0xFF80) == 0xE080) && ((iw1 & 0x0C00) == 0x0000))
6402 decode_LoopSetup_0 (cpu, iw0, iw1, pc);
6403 else if (((iw0 & 0xFF00) == 0xE100) && ((iw1 & 0x0000) == 0x0000))
6404 decode_LDIMMhalf_0 (cpu, iw0, iw1);
6405 else if (((iw0 & 0xFE00) == 0xE200) && ((iw1 & 0x0000) == 0x0000))
6406 decode_CALLa_0 (cpu, iw0, iw1, pc);
6407 else if (((iw0 & 0xFC00) == 0xE400) && ((iw1 & 0x0000) == 0x0000))
6408 decode_LDSTidxI_0 (cpu, iw0, iw1);
6409 else if (((iw0 & 0xFFFE) == 0xE800) && ((iw1 & 0x0000) == 0x0000))
6410 decode_linkage_0 (cpu, iw0, iw1);
6411 else if (((iw0 & 0xF600) == 0xC000) && ((iw1 & 0x0000) == 0x0000))
6412 decode_dsp32mac_0 (cpu, iw0, iw1);
6413 else if (((iw0 & 0xF600) == 0xC200) && ((iw1 & 0x0000) == 0x0000))
6414 decode_dsp32mult_0 (cpu, iw0, iw1);
6415 else if (((iw0 & 0xF7C0) == 0xC400) && ((iw1 & 0x0000) == 0x0000))
6416 decode_dsp32alu_0 (cpu, iw0, iw1);
6417 else if (((iw0 & 0xF7E0) == 0xC600) && ((iw1 & 0x01C0) == 0x0000))
6418 decode_dsp32shift_0 (cpu, iw0, iw1);
6419 else if (((iw0 & 0xF7E0) == 0xC680) && ((iw1 & 0x0000) == 0x0000))
6420 decode_dsp32shiftimm_0 (cpu, iw0, iw1);
6421 else if ((iw0 & 0xFF00) == 0xF800)
6422 decode_psedoDEBUG_0 (cpu, iw0), insn_len = 2;
6423 else if ((iw0 & 0xFF00) == 0xF900)
6424 decode_psedoOChar_0 (cpu, iw0), insn_len = 2;
6425 else if (((iw0 & 0xFF00) == 0xF000) && ((iw1 & 0x0000) == 0x0000))
6426 decode_psedodbg_assert_0 (cpu, iw0, iw1, pc);
6427 else
6428 {
6429 TRACE_EXTRACT (cpu, "%s: no matching 32-bit pattern", __func__);
6430 illegal_instruction (cpu);
6431 }
6432
6433 return insn_len;
6434 }
6435
6436 bu32
6437 interp_insn_bfin (SIM_CPU *cpu, bu32 pc)
6438 {
6439 int i;
6440 bu32 insn_len;
6441
6442 BFIN_CPU_STATE.n_stores = 0;
6443 PARALLEL_GROUP = BFIN_PARALLEL_NONE;
6444 DIS_ALGN_EXPT &= ~1;
6445 CYCLE_DELAY = 1;
6446 INSN_LEN = 0;
6447
6448 insn_len = _interp_insn_bfin (cpu, pc);
6449
6450 /* Proper display of multiple issue instructions. */
6451 if (insn_len == 8)
6452 {
6453 PARALLEL_GROUP = BFIN_PARALLEL_GROUP1;
6454 _interp_insn_bfin (cpu, pc + 4);
6455 PARALLEL_GROUP = BFIN_PARALLEL_GROUP2;
6456 _interp_insn_bfin (cpu, pc + 6);
6457 }
6458 for (i = 0; i < BFIN_CPU_STATE.n_stores; i++)
6459 {
6460 bu32 *addr = BFIN_CPU_STATE.stores[i].addr;
6461 *addr = BFIN_CPU_STATE.stores[i].val;
6462 TRACE_REGISTER (cpu, "dequeuing write %s = %#x",
6463 get_store_name (cpu, addr), *addr);
6464 }
6465
6466 cycles_inc (cpu, CYCLE_DELAY);
6467
6468 /* Set back to zero in case a pending CEC event occurs
6469 after this this insn. */
6470 INSN_LEN = 0;
6471
6472 return insn_len;
6473 }