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