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