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