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