mdmx.c revision 1.9.2.1 1 1.1 christos /* Simulation code for the MIPS MDMX ASE.
2 1.9.2.1 perseant Copyright (C) 2002-2023 Free Software Foundation, Inc.
3 1.1 christos Contributed by Ed Satterthwaite and Chris Demetriou, of Broadcom
4 1.1 christos Corporation (SiByte).
5 1.1 christos
6 1.1 christos This file is part of GDB, the GNU debugger.
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.9.2.1 perseant /* This must come before any other includes. */
22 1.9.2.1 perseant #include "defs.h"
23 1.9.2.1 perseant
24 1.1 christos #include <stdio.h>
25 1.1 christos
26 1.1 christos #include "sim-main.h"
27 1.1 christos
28 1.1 christos /* Within mdmx.c we refer to the sim_cpu directly. */
29 1.1 christos #define CPU cpu
30 1.1 christos #define SD (CPU_STATE(CPU))
31 1.1 christos
32 1.1 christos /* XXX FIXME: temporary hack while the impact of making unpredictable()
33 1.1 christos a "normal" (non-igen) function is evaluated. */
34 1.1 christos #undef Unpredictable
35 1.1 christos #define Unpredictable() unpredictable_action (cpu, cia)
36 1.1 christos
37 1.1 christos /* MDMX Representations
38 1.1 christos
39 1.1 christos An 8-bit packed byte element (OB) is always unsigned.
40 1.1 christos The 24-bit accumulators are signed and are represented as 32-bit
41 1.1 christos signed values, which are reduced to 24-bit signed values prior to
42 1.1 christos Round and Clamp operations.
43 1.9.2.1 perseant
44 1.1 christos A 16-bit packed halfword element (QH) is always signed.
45 1.1 christos The 48-bit accumulators are signed and are represented as 64-bit
46 1.1 christos signed values, which are reduced to 48-bit signed values prior to
47 1.1 christos Round and Clamp operations.
48 1.9.2.1 perseant
49 1.1 christos The code below assumes a 2's-complement representation of signed
50 1.1 christos quantities. Care is required to clear extended sign bits when
51 1.1 christos repacking fields.
52 1.9.2.1 perseant
53 1.1 christos The code (and the code for arithmetic shifts in mips.igen) also makes
54 1.1 christos the (not guaranteed portable) assumption that right shifts of signed
55 1.1 christos quantities in C do sign extension. */
56 1.1 christos
57 1.9.2.1 perseant typedef uint64_t unsigned48;
58 1.1 christos #define MASK48 (UNSIGNED64 (0xffffffffffff))
59 1.1 christos
60 1.9.2.1 perseant typedef uint32_t unsigned24;
61 1.1 christos #define MASK24 (UNSIGNED32 (0xffffff))
62 1.1 christos
63 1.1 christos typedef enum {
64 1.1 christos mdmx_ob, /* OB (octal byte) */
65 1.1 christos mdmx_qh /* QH (quad half-word) */
66 1.1 christos } MX_fmt;
67 1.1 christos
68 1.1 christos typedef enum {
69 1.1 christos sel_elem, /* element select */
70 1.1 christos sel_vect, /* vector select */
71 1.1 christos sel_imm /* immediate select */
72 1.1 christos } VT_select;
73 1.1 christos
74 1.9.2.1 perseant #define OB_MAX ((uint8_t)0xFF)
75 1.9.2.1 perseant #define QH_MIN ((int16_t)0x8000)
76 1.9.2.1 perseant #define QH_MAX ((int16_t)0x7FFF)
77 1.1 christos
78 1.9.2.1 perseant #define OB_CLAMP(x) ((uint8_t)((x) > OB_MAX ? OB_MAX : (x)))
79 1.9.2.1 perseant #define QH_CLAMP(x) ((int16_t)((x) < QH_MIN ? QH_MIN : \
80 1.1 christos ((x) > QH_MAX ? QH_MAX : (x))))
81 1.1 christos
82 1.1 christos #define MX_FMT(fmtsel) (((fmtsel) & 0x1) == 0 ? mdmx_ob : mdmx_qh)
83 1.1 christos #define MX_VT(fmtsel) (((fmtsel) & 0x10) == 0 ? sel_elem : \
84 1.1 christos (((fmtsel) & 0x18) == 0x10 ? sel_vect : sel_imm))
85 1.1 christos
86 1.1 christos #define QH_ELEM(v,fmtsel) \
87 1.9.2.1 perseant ((int16_t)(((v) >> (((fmtsel) & 0xC) << 2)) & 0xFFFF))
88 1.1 christos #define OB_ELEM(v,fmtsel) \
89 1.9.2.1 perseant ((uint8_t)(((v) >> (((fmtsel) & 0xE) << 2)) & 0xFF))
90 1.1 christos
91 1.1 christos
92 1.9.2.1 perseant typedef int16_t (*QH_FUNC)(int16_t, int16_t);
93 1.9.2.1 perseant typedef uint8_t (*OB_FUNC)(uint8_t, uint8_t);
94 1.1 christos
95 1.1 christos /* vectorized logical operators */
96 1.1 christos
97 1.9.2.1 perseant static int16_t
98 1.9.2.1 perseant AndQH(int16_t ts, int16_t tt)
99 1.1 christos {
100 1.9.2.1 perseant return (int16_t)((uint16_t)ts & (uint16_t)tt);
101 1.1 christos }
102 1.1 christos
103 1.9.2.1 perseant static uint8_t
104 1.9.2.1 perseant AndOB(uint8_t ts, uint8_t tt)
105 1.1 christos {
106 1.1 christos return ts & tt;
107 1.1 christos }
108 1.1 christos
109 1.9.2.1 perseant static int16_t
110 1.9.2.1 perseant NorQH(int16_t ts, int16_t tt)
111 1.1 christos {
112 1.9.2.1 perseant return (int16_t)(((uint16_t)ts | (uint16_t)tt) ^ 0xFFFF);
113 1.1 christos }
114 1.1 christos
115 1.9.2.1 perseant static uint8_t
116 1.9.2.1 perseant NorOB(uint8_t ts, uint8_t tt)
117 1.1 christos {
118 1.1 christos return (ts | tt) ^ 0xFF;
119 1.1 christos }
120 1.1 christos
121 1.9.2.1 perseant static int16_t
122 1.9.2.1 perseant OrQH(int16_t ts, int16_t tt)
123 1.1 christos {
124 1.9.2.1 perseant return (int16_t)((uint16_t)ts | (uint16_t)tt);
125 1.1 christos }
126 1.1 christos
127 1.9.2.1 perseant static uint8_t
128 1.9.2.1 perseant OrOB(uint8_t ts, uint8_t tt)
129 1.1 christos {
130 1.1 christos return ts | tt;
131 1.1 christos }
132 1.1 christos
133 1.9.2.1 perseant static int16_t
134 1.9.2.1 perseant XorQH(int16_t ts, int16_t tt)
135 1.1 christos {
136 1.9.2.1 perseant return (int16_t)((uint16_t)ts ^ (uint16_t)tt);
137 1.1 christos }
138 1.1 christos
139 1.9.2.1 perseant static uint8_t
140 1.9.2.1 perseant XorOB(uint8_t ts, uint8_t tt)
141 1.1 christos {
142 1.1 christos return ts ^ tt;
143 1.1 christos }
144 1.1 christos
145 1.9.2.1 perseant static int16_t
146 1.9.2.1 perseant SLLQH(int16_t ts, int16_t tt)
147 1.1 christos {
148 1.9.2.1 perseant uint32_t s = (uint32_t)tt & 0xF;
149 1.9.2.1 perseant return (int16_t)(((uint32_t)ts << s) & 0xFFFF);
150 1.1 christos }
151 1.1 christos
152 1.9.2.1 perseant static uint8_t
153 1.9.2.1 perseant SLLOB(uint8_t ts, uint8_t tt)
154 1.1 christos {
155 1.9.2.1 perseant uint32_t s = tt & 0x7;
156 1.1 christos return (ts << s) & 0xFF;
157 1.1 christos }
158 1.1 christos
159 1.9.2.1 perseant static int16_t
160 1.9.2.1 perseant SRLQH(int16_t ts, int16_t tt)
161 1.1 christos {
162 1.9.2.1 perseant uint32_t s = (uint32_t)tt & 0xF;
163 1.9.2.1 perseant return (int16_t)((uint16_t)ts >> s);
164 1.1 christos }
165 1.1 christos
166 1.9.2.1 perseant static uint8_t
167 1.9.2.1 perseant SRLOB(uint8_t ts, uint8_t tt)
168 1.1 christos {
169 1.9.2.1 perseant uint32_t s = tt & 0x7;
170 1.1 christos return ts >> s;
171 1.1 christos }
172 1.1 christos
173 1.1 christos
174 1.1 christos /* Vectorized arithmetic operators. */
175 1.1 christos
176 1.9.2.1 perseant static int16_t
177 1.9.2.1 perseant AddQH(int16_t ts, int16_t tt)
178 1.1 christos {
179 1.9.2.1 perseant int32_t t = (int32_t)ts + (int32_t)tt;
180 1.1 christos return QH_CLAMP(t);
181 1.1 christos }
182 1.1 christos
183 1.9.2.1 perseant static uint8_t
184 1.9.2.1 perseant AddOB(uint8_t ts, uint8_t tt)
185 1.1 christos {
186 1.9.2.1 perseant uint32_t t = (uint32_t)ts + (uint32_t)tt;
187 1.1 christos return OB_CLAMP(t);
188 1.1 christos }
189 1.1 christos
190 1.9.2.1 perseant static int16_t
191 1.9.2.1 perseant SubQH(int16_t ts, int16_t tt)
192 1.1 christos {
193 1.9.2.1 perseant int32_t t = (int32_t)ts - (int32_t)tt;
194 1.1 christos return QH_CLAMP(t);
195 1.1 christos }
196 1.1 christos
197 1.9.2.1 perseant static uint8_t
198 1.9.2.1 perseant SubOB(uint8_t ts, uint8_t tt)
199 1.1 christos {
200 1.9.2.1 perseant int32_t t;
201 1.9.2.1 perseant t = (int32_t)ts - (int32_t)tt;
202 1.1 christos if (t < 0)
203 1.1 christos t = 0;
204 1.9.2.1 perseant return (uint8_t)t;
205 1.1 christos }
206 1.1 christos
207 1.9.2.1 perseant static int16_t
208 1.9.2.1 perseant MinQH(int16_t ts, int16_t tt)
209 1.1 christos {
210 1.1 christos return (ts < tt ? ts : tt);
211 1.1 christos }
212 1.1 christos
213 1.9.2.1 perseant static uint8_t
214 1.9.2.1 perseant MinOB(uint8_t ts, uint8_t tt)
215 1.1 christos {
216 1.1 christos return (ts < tt ? ts : tt);
217 1.1 christos }
218 1.1 christos
219 1.9.2.1 perseant static int16_t
220 1.9.2.1 perseant MaxQH(int16_t ts, int16_t tt)
221 1.1 christos {
222 1.1 christos return (ts > tt ? ts : tt);
223 1.1 christos }
224 1.1 christos
225 1.9.2.1 perseant static uint8_t
226 1.9.2.1 perseant MaxOB(uint8_t ts, uint8_t tt)
227 1.1 christos {
228 1.1 christos return (ts > tt ? ts : tt);
229 1.1 christos }
230 1.1 christos
231 1.9.2.1 perseant static int16_t
232 1.9.2.1 perseant MulQH(int16_t ts, int16_t tt)
233 1.1 christos {
234 1.9.2.1 perseant int32_t t = (int32_t)ts * (int32_t)tt;
235 1.1 christos return QH_CLAMP(t);
236 1.1 christos }
237 1.1 christos
238 1.9.2.1 perseant static uint8_t
239 1.9.2.1 perseant MulOB(uint8_t ts, uint8_t tt)
240 1.1 christos {
241 1.9.2.1 perseant uint32_t t = (uint32_t)ts * (uint32_t)tt;
242 1.1 christos return OB_CLAMP(t);
243 1.1 christos }
244 1.1 christos
245 1.1 christos /* "msgn" and "sra" are defined only for QH format. */
246 1.1 christos
247 1.9.2.1 perseant static int16_t
248 1.9.2.1 perseant MsgnQH(int16_t ts, int16_t tt)
249 1.1 christos {
250 1.9.2.1 perseant int16_t t;
251 1.1 christos if (ts < 0)
252 1.1 christos t = (tt == QH_MIN ? QH_MAX : -tt);
253 1.1 christos else if (ts == 0)
254 1.1 christos t = 0;
255 1.1 christos else
256 1.1 christos t = tt;
257 1.1 christos return t;
258 1.1 christos }
259 1.1 christos
260 1.9.2.1 perseant static int16_t
261 1.9.2.1 perseant SRAQH(int16_t ts, int16_t tt)
262 1.1 christos {
263 1.9.2.1 perseant uint32_t s = (uint32_t)tt & 0xF;
264 1.9.2.1 perseant return (int16_t)((int32_t)ts >> s);
265 1.1 christos }
266 1.1 christos
267 1.1 christos
268 1.1 christos /* "pabsdiff" and "pavg" are defined only for OB format. */
269 1.1 christos
270 1.9.2.1 perseant static uint8_t
271 1.9.2.1 perseant AbsDiffOB(uint8_t ts, uint8_t tt)
272 1.1 christos {
273 1.1 christos return (ts >= tt ? ts - tt : tt - ts);
274 1.1 christos }
275 1.1 christos
276 1.9.2.1 perseant static uint8_t
277 1.9.2.1 perseant AvgOB(uint8_t ts, uint8_t tt)
278 1.1 christos {
279 1.9.2.1 perseant return ((uint32_t)ts + (uint32_t)tt + 1) >> 1;
280 1.1 christos }
281 1.1 christos
282 1.1 christos
283 1.1 christos /* Dispatch tables for operations that update a CPR. */
284 1.1 christos
285 1.1 christos static const QH_FUNC qh_func[] = {
286 1.1 christos AndQH, NorQH, OrQH, XorQH, SLLQH, SRLQH,
287 1.1 christos AddQH, SubQH, MinQH, MaxQH,
288 1.1 christos MulQH, MsgnQH, SRAQH, NULL, NULL
289 1.1 christos };
290 1.1 christos
291 1.1 christos static const OB_FUNC ob_func[] = {
292 1.1 christos AndOB, NorOB, OrOB, XorOB, SLLOB, SRLOB,
293 1.1 christos AddOB, SubOB, MinOB, MaxOB,
294 1.1 christos MulOB, NULL, NULL, AbsDiffOB, AvgOB
295 1.1 christos };
296 1.1 christos
297 1.1 christos /* Auxiliary functions for CPR updates. */
298 1.1 christos
299 1.1 christos /* Vector mapping for QH format. */
300 1.9.2.1 perseant static uint64_t
301 1.9.2.1 perseant qh_vector_op(uint64_t v1, uint64_t v2, QH_FUNC func)
302 1.1 christos {
303 1.9.2.1 perseant uint64_t result = 0;
304 1.1 christos int i;
305 1.9.2.1 perseant int16_t h, h1, h2;
306 1.1 christos
307 1.1 christos for (i = 0; i < 64; i += 16)
308 1.1 christos {
309 1.9.2.1 perseant h1 = (int16_t)(v1 & 0xFFFF); v1 >>= 16;
310 1.9.2.1 perseant h2 = (int16_t)(v2 & 0xFFFF); v2 >>= 16;
311 1.1 christos h = (*func)(h1, h2);
312 1.9.2.1 perseant result |= ((uint64_t)((uint16_t)h) << i);
313 1.1 christos }
314 1.1 christos return result;
315 1.1 christos }
316 1.1 christos
317 1.9.2.1 perseant static uint64_t
318 1.9.2.1 perseant qh_map_op(uint64_t v1, int16_t h2, QH_FUNC func)
319 1.1 christos {
320 1.9.2.1 perseant uint64_t result = 0;
321 1.1 christos int i;
322 1.9.2.1 perseant int16_t h, h1;
323 1.1 christos
324 1.1 christos for (i = 0; i < 64; i += 16)
325 1.1 christos {
326 1.9.2.1 perseant h1 = (int16_t)(v1 & 0xFFFF); v1 >>= 16;
327 1.1 christos h = (*func)(h1, h2);
328 1.9.2.1 perseant result |= ((uint64_t)((uint16_t)h) << i);
329 1.1 christos }
330 1.1 christos return result;
331 1.1 christos }
332 1.1 christos
333 1.1 christos
334 1.1 christos /* Vector operations for OB format. */
335 1.1 christos
336 1.9.2.1 perseant static uint64_t
337 1.9.2.1 perseant ob_vector_op(uint64_t v1, uint64_t v2, OB_FUNC func)
338 1.1 christos {
339 1.9.2.1 perseant uint64_t result = 0;
340 1.1 christos int i;
341 1.9.2.1 perseant uint8_t b, b1, b2;
342 1.1 christos
343 1.1 christos for (i = 0; i < 64; i += 8)
344 1.1 christos {
345 1.1 christos b1 = v1 & 0xFF; v1 >>= 8;
346 1.1 christos b2 = v2 & 0xFF; v2 >>= 8;
347 1.1 christos b = (*func)(b1, b2);
348 1.9.2.1 perseant result |= ((uint64_t)b << i);
349 1.1 christos }
350 1.1 christos return result;
351 1.1 christos }
352 1.1 christos
353 1.9.2.1 perseant static uint64_t
354 1.9.2.1 perseant ob_map_op(uint64_t v1, uint8_t b2, OB_FUNC func)
355 1.1 christos {
356 1.9.2.1 perseant uint64_t result = 0;
357 1.1 christos int i;
358 1.9.2.1 perseant uint8_t b, b1;
359 1.1 christos
360 1.1 christos for (i = 0; i < 64; i += 8)
361 1.1 christos {
362 1.1 christos b1 = v1 & 0xFF; v1 >>= 8;
363 1.1 christos b = (*func)(b1, b2);
364 1.9.2.1 perseant result |= ((uint64_t)b << i);
365 1.1 christos }
366 1.1 christos return result;
367 1.1 christos }
368 1.1 christos
369 1.1 christos
370 1.1 christos /* Primary entry for operations that update CPRs. */
371 1.9.2.1 perseant uint64_t
372 1.1 christos mdmx_cpr_op(sim_cpu *cpu,
373 1.1 christos address_word cia,
374 1.1 christos int op,
375 1.9.2.1 perseant uint64_t op1,
376 1.1 christos int vt,
377 1.9.2.1 perseant MX_fmtsel fmtsel)
378 1.1 christos {
379 1.9.2.1 perseant uint64_t op2;
380 1.9.2.1 perseant uint64_t result = 0;
381 1.1 christos
382 1.1 christos switch (MX_FMT (fmtsel))
383 1.1 christos {
384 1.1 christos case mdmx_qh:
385 1.1 christos switch (MX_VT (fmtsel))
386 1.1 christos {
387 1.1 christos case sel_elem:
388 1.1 christos op2 = ValueFPR(vt, fmt_mdmx);
389 1.1 christos result = qh_map_op(op1, QH_ELEM(op2, fmtsel), qh_func[op]);
390 1.1 christos break;
391 1.1 christos case sel_vect:
392 1.1 christos result = qh_vector_op(op1, ValueFPR(vt, fmt_mdmx), qh_func[op]);
393 1.1 christos break;
394 1.1 christos case sel_imm:
395 1.1 christos result = qh_map_op(op1, vt, qh_func[op]);
396 1.1 christos break;
397 1.1 christos }
398 1.1 christos break;
399 1.1 christos case mdmx_ob:
400 1.1 christos switch (MX_VT (fmtsel))
401 1.1 christos {
402 1.1 christos case sel_elem:
403 1.1 christos op2 = ValueFPR(vt, fmt_mdmx);
404 1.1 christos result = ob_map_op(op1, OB_ELEM(op2, fmtsel), ob_func[op]);
405 1.1 christos break;
406 1.1 christos case sel_vect:
407 1.1 christos result = ob_vector_op(op1, ValueFPR(vt, fmt_mdmx), ob_func[op]);
408 1.1 christos break;
409 1.1 christos case sel_imm:
410 1.1 christos result = ob_map_op(op1, vt, ob_func[op]);
411 1.1 christos break;
412 1.1 christos }
413 1.1 christos break;
414 1.1 christos default:
415 1.1 christos Unpredictable ();
416 1.1 christos }
417 1.1 christos
418 1.1 christos return result;
419 1.1 christos }
420 1.1 christos
421 1.1 christos
422 1.1 christos /* Operations that update CCs */
423 1.1 christos
424 1.1 christos static void
425 1.9.2.1 perseant qh_vector_test(sim_cpu *cpu, uint64_t v1, uint64_t v2, int cond)
426 1.1 christos {
427 1.1 christos int i;
428 1.9.2.1 perseant int16_t h1, h2;
429 1.1 christos int boolean;
430 1.1 christos
431 1.1 christos for (i = 0; i < 4; i++)
432 1.1 christos {
433 1.9.2.1 perseant h1 = (int16_t)(v1 & 0xFFFF); v1 >>= 16;
434 1.9.2.1 perseant h2 = (int16_t)(v2 & 0xFFFF); v2 >>= 16;
435 1.1 christos boolean = ((cond & MX_C_EQ) && (h1 == h2)) ||
436 1.1 christos ((cond & MX_C_LT) && (h1 < h2));
437 1.1 christos SETFCC(i, boolean);
438 1.1 christos }
439 1.1 christos }
440 1.1 christos
441 1.1 christos static void
442 1.9.2.1 perseant qh_map_test(sim_cpu *cpu, uint64_t v1, int16_t h2, int cond)
443 1.1 christos {
444 1.1 christos int i;
445 1.9.2.1 perseant int16_t h1;
446 1.1 christos int boolean;
447 1.1 christos
448 1.1 christos for (i = 0; i < 4; i++)
449 1.1 christos {
450 1.9.2.1 perseant h1 = (int16_t)(v1 & 0xFFFF); v1 >>= 16;
451 1.1 christos boolean = ((cond & MX_C_EQ) && (h1 == h2)) ||
452 1.1 christos ((cond & MX_C_LT) && (h1 < h2));
453 1.1 christos SETFCC(i, boolean);
454 1.1 christos }
455 1.1 christos }
456 1.1 christos
457 1.1 christos static void
458 1.9.2.1 perseant ob_vector_test(sim_cpu *cpu, uint64_t v1, uint64_t v2, int cond)
459 1.1 christos {
460 1.1 christos int i;
461 1.9.2.1 perseant uint8_t b1, b2;
462 1.1 christos int boolean;
463 1.1 christos
464 1.1 christos for (i = 0; i < 8; i++)
465 1.1 christos {
466 1.1 christos b1 = v1 & 0xFF; v1 >>= 8;
467 1.1 christos b2 = v2 & 0xFF; v2 >>= 8;
468 1.1 christos boolean = ((cond & MX_C_EQ) && (b1 == b2)) ||
469 1.1 christos ((cond & MX_C_LT) && (b1 < b2));
470 1.1 christos SETFCC(i, boolean);
471 1.1 christos }
472 1.1 christos }
473 1.1 christos
474 1.1 christos static void
475 1.9.2.1 perseant ob_map_test(sim_cpu *cpu, uint64_t v1, uint8_t b2, int cond)
476 1.1 christos {
477 1.1 christos int i;
478 1.9.2.1 perseant uint8_t b1;
479 1.1 christos int boolean;
480 1.1 christos
481 1.1 christos for (i = 0; i < 8; i++)
482 1.1 christos {
483 1.9.2.1 perseant b1 = (uint8_t)(v1 & 0xFF); v1 >>= 8;
484 1.1 christos boolean = ((cond & MX_C_EQ) && (b1 == b2)) ||
485 1.1 christos ((cond & MX_C_LT) && (b1 < b2));
486 1.1 christos SETFCC(i, boolean);
487 1.1 christos }
488 1.1 christos }
489 1.1 christos
490 1.1 christos
491 1.1 christos void
492 1.1 christos mdmx_cc_op(sim_cpu *cpu,
493 1.1 christos address_word cia,
494 1.1 christos int cond,
495 1.9.2.1 perseant uint64_t v1,
496 1.1 christos int vt,
497 1.1 christos MX_fmtsel fmtsel)
498 1.1 christos {
499 1.9.2.1 perseant uint64_t op2;
500 1.1 christos
501 1.1 christos switch (MX_FMT (fmtsel))
502 1.1 christos {
503 1.1 christos case mdmx_qh:
504 1.1 christos switch (MX_VT (fmtsel))
505 1.1 christos {
506 1.1 christos case sel_elem:
507 1.1 christos op2 = ValueFPR(vt, fmt_mdmx);
508 1.1 christos qh_map_test(cpu, v1, QH_ELEM(op2, fmtsel), cond);
509 1.1 christos break;
510 1.1 christos case sel_vect:
511 1.1 christos qh_vector_test(cpu, v1, ValueFPR(vt, fmt_mdmx), cond);
512 1.1 christos break;
513 1.1 christos case sel_imm:
514 1.1 christos qh_map_test(cpu, v1, vt, cond);
515 1.1 christos break;
516 1.1 christos }
517 1.1 christos break;
518 1.1 christos case mdmx_ob:
519 1.1 christos switch (MX_VT (fmtsel))
520 1.1 christos {
521 1.1 christos case sel_elem:
522 1.1 christos op2 = ValueFPR(vt, fmt_mdmx);
523 1.1 christos ob_map_test(cpu, v1, OB_ELEM(op2, fmtsel), cond);
524 1.1 christos break;
525 1.1 christos case sel_vect:
526 1.1 christos ob_vector_test(cpu, v1, ValueFPR(vt, fmt_mdmx), cond);
527 1.1 christos break;
528 1.1 christos case sel_imm:
529 1.1 christos ob_map_test(cpu, v1, vt, cond);
530 1.1 christos break;
531 1.1 christos }
532 1.1 christos break;
533 1.1 christos default:
534 1.1 christos Unpredictable ();
535 1.1 christos }
536 1.1 christos }
537 1.1 christos
538 1.1 christos
539 1.1 christos /* Pick operations. */
540 1.1 christos
541 1.9.2.1 perseant static uint64_t
542 1.9.2.1 perseant qh_vector_pick(sim_cpu *cpu, uint64_t v1, uint64_t v2, int tf)
543 1.1 christos {
544 1.9.2.1 perseant uint64_t result = 0;
545 1.1 christos int i, s;
546 1.9.2.1 perseant uint16_t h;
547 1.1 christos
548 1.1 christos s = 0;
549 1.1 christos for (i = 0; i < 4; i++)
550 1.1 christos {
551 1.1 christos h = ((GETFCC(i) == tf) ? (v1 & 0xFFFF) : (v2 & 0xFFFF));
552 1.1 christos v1 >>= 16; v2 >>= 16;
553 1.9.2.1 perseant result |= ((uint64_t)h << s);
554 1.1 christos s += 16;
555 1.1 christos }
556 1.1 christos return result;
557 1.1 christos }
558 1.1 christos
559 1.9.2.1 perseant static uint64_t
560 1.9.2.1 perseant qh_map_pick(sim_cpu *cpu, uint64_t v1, int16_t h2, int tf)
561 1.1 christos {
562 1.9.2.1 perseant uint64_t result = 0;
563 1.1 christos int i, s;
564 1.9.2.1 perseant uint16_t h;
565 1.1 christos
566 1.1 christos s = 0;
567 1.1 christos for (i = 0; i < 4; i++)
568 1.1 christos {
569 1.9.2.1 perseant h = (GETFCC(i) == tf) ? (v1 & 0xFFFF) : (uint16_t)h2;
570 1.1 christos v1 >>= 16;
571 1.9.2.1 perseant result |= ((uint64_t)h << s);
572 1.1 christos s += 16;
573 1.1 christos }
574 1.1 christos return result;
575 1.1 christos }
576 1.1 christos
577 1.9.2.1 perseant static uint64_t
578 1.9.2.1 perseant ob_vector_pick(sim_cpu *cpu, uint64_t v1, uint64_t v2, int tf)
579 1.1 christos {
580 1.9.2.1 perseant uint64_t result = 0;
581 1.1 christos int i, s;
582 1.9.2.1 perseant uint8_t b;
583 1.1 christos
584 1.1 christos s = 0;
585 1.1 christos for (i = 0; i < 8; i++)
586 1.1 christos {
587 1.1 christos b = (GETFCC(i) == tf) ? (v1 & 0xFF) : (v2 & 0xFF);
588 1.1 christos v1 >>= 8; v2 >>= 8;
589 1.9.2.1 perseant result |= ((uint64_t)b << s);
590 1.1 christos s += 8;
591 1.1 christos }
592 1.1 christos return result;
593 1.1 christos }
594 1.1 christos
595 1.9.2.1 perseant static uint64_t
596 1.9.2.1 perseant ob_map_pick(sim_cpu *cpu, uint64_t v1, uint8_t b2, int tf)
597 1.1 christos {
598 1.9.2.1 perseant uint64_t result = 0;
599 1.1 christos int i, s;
600 1.9.2.1 perseant uint8_t b;
601 1.1 christos
602 1.1 christos s = 0;
603 1.1 christos for (i = 0; i < 8; i++)
604 1.1 christos {
605 1.1 christos b = (GETFCC(i) == tf) ? (v1 & 0xFF) : b2;
606 1.1 christos v1 >>= 8;
607 1.9.2.1 perseant result |= ((uint64_t)b << s);
608 1.1 christos s += 8;
609 1.1 christos }
610 1.1 christos return result;
611 1.1 christos }
612 1.1 christos
613 1.1 christos
614 1.9.2.1 perseant uint64_t
615 1.1 christos mdmx_pick_op(sim_cpu *cpu,
616 1.1 christos address_word cia,
617 1.1 christos int tf,
618 1.9.2.1 perseant uint64_t v1,
619 1.1 christos int vt,
620 1.1 christos MX_fmtsel fmtsel)
621 1.1 christos {
622 1.9.2.1 perseant uint64_t result = 0;
623 1.9.2.1 perseant uint64_t op2;
624 1.1 christos
625 1.1 christos switch (MX_FMT (fmtsel))
626 1.1 christos {
627 1.1 christos case mdmx_qh:
628 1.1 christos switch (MX_VT (fmtsel))
629 1.1 christos {
630 1.1 christos case sel_elem:
631 1.1 christos op2 = ValueFPR(vt, fmt_mdmx);
632 1.1 christos result = qh_map_pick(cpu, v1, QH_ELEM(op2, fmtsel), tf);
633 1.1 christos break;
634 1.1 christos case sel_vect:
635 1.1 christos result = qh_vector_pick(cpu, v1, ValueFPR(vt, fmt_mdmx), tf);
636 1.1 christos break;
637 1.1 christos case sel_imm:
638 1.1 christos result = qh_map_pick(cpu, v1, vt, tf);
639 1.1 christos break;
640 1.1 christos }
641 1.1 christos break;
642 1.1 christos case mdmx_ob:
643 1.1 christos switch (MX_VT (fmtsel))
644 1.1 christos {
645 1.1 christos case sel_elem:
646 1.1 christos op2 = ValueFPR(vt, fmt_mdmx);
647 1.1 christos result = ob_map_pick(cpu, v1, OB_ELEM(op2, fmtsel), tf);
648 1.1 christos break;
649 1.1 christos case sel_vect:
650 1.1 christos result = ob_vector_pick(cpu, v1, ValueFPR(vt, fmt_mdmx), tf);
651 1.1 christos break;
652 1.1 christos case sel_imm:
653 1.1 christos result = ob_map_pick(cpu, v1, vt, tf);
654 1.1 christos break;
655 1.1 christos }
656 1.1 christos break;
657 1.1 christos default:
658 1.1 christos Unpredictable ();
659 1.1 christos }
660 1.1 christos return result;
661 1.1 christos }
662 1.1 christos
663 1.1 christos
664 1.1 christos /* Accumulators. */
665 1.1 christos
666 1.9.2.1 perseant typedef void (*QH_ACC)(signed48 *a, int16_t ts, int16_t tt);
667 1.1 christos
668 1.1 christos static void
669 1.9.2.1 perseant AccAddAQH(signed48 *a, int16_t ts, int16_t tt)
670 1.1 christos {
671 1.1 christos *a += (signed48)ts + (signed48)tt;
672 1.1 christos }
673 1.1 christos
674 1.1 christos static void
675 1.9.2.1 perseant AccAddLQH(signed48 *a, int16_t ts, int16_t tt)
676 1.1 christos {
677 1.1 christos *a = (signed48)ts + (signed48)tt;
678 1.1 christos }
679 1.1 christos
680 1.1 christos static void
681 1.9.2.1 perseant AccMulAQH(signed48 *a, int16_t ts, int16_t tt)
682 1.1 christos {
683 1.1 christos *a += (signed48)ts * (signed48)tt;
684 1.1 christos }
685 1.1 christos
686 1.1 christos static void
687 1.9.2.1 perseant AccMulLQH(signed48 *a, int16_t ts, int16_t tt)
688 1.1 christos {
689 1.1 christos *a = (signed48)ts * (signed48)tt;
690 1.1 christos }
691 1.1 christos
692 1.1 christos static void
693 1.9.2.1 perseant SubMulAQH(signed48 *a, int16_t ts, int16_t tt)
694 1.1 christos {
695 1.1 christos *a -= (signed48)ts * (signed48)tt;
696 1.1 christos }
697 1.1 christos
698 1.1 christos static void
699 1.9.2.1 perseant SubMulLQH(signed48 *a, int16_t ts, int16_t tt)
700 1.1 christos {
701 1.1 christos *a = -((signed48)ts * (signed48)tt);
702 1.1 christos }
703 1.1 christos
704 1.1 christos static void
705 1.9.2.1 perseant AccSubAQH(signed48 *a, int16_t ts, int16_t tt)
706 1.1 christos {
707 1.1 christos *a += (signed48)ts - (signed48)tt;
708 1.1 christos }
709 1.1 christos
710 1.1 christos static void
711 1.9.2.1 perseant AccSubLQH(signed48 *a, int16_t ts, int16_t tt)
712 1.1 christos {
713 1.1 christos *a = (signed48)ts - (signed48)tt;
714 1.1 christos }
715 1.1 christos
716 1.1 christos
717 1.9.2.1 perseant typedef void (*OB_ACC)(signed24 *acc, uint8_t ts, uint8_t tt);
718 1.1 christos
719 1.1 christos static void
720 1.9.2.1 perseant AccAddAOB(signed24 *a, uint8_t ts, uint8_t tt)
721 1.1 christos {
722 1.1 christos *a += (signed24)ts + (signed24)tt;
723 1.1 christos }
724 1.1 christos
725 1.1 christos static void
726 1.9.2.1 perseant AccAddLOB(signed24 *a, uint8_t ts, uint8_t tt)
727 1.1 christos {
728 1.1 christos *a = (signed24)ts + (signed24)tt;
729 1.1 christos }
730 1.1 christos
731 1.1 christos static void
732 1.9.2.1 perseant AccMulAOB(signed24 *a, uint8_t ts, uint8_t tt)
733 1.1 christos {
734 1.1 christos *a += (signed24)ts * (signed24)tt;
735 1.1 christos }
736 1.1 christos
737 1.1 christos static void
738 1.9.2.1 perseant AccMulLOB(signed24 *a, uint8_t ts, uint8_t tt)
739 1.1 christos {
740 1.1 christos *a = (signed24)ts * (signed24)tt;
741 1.1 christos }
742 1.1 christos
743 1.1 christos static void
744 1.9.2.1 perseant SubMulAOB(signed24 *a, uint8_t ts, uint8_t tt)
745 1.1 christos {
746 1.1 christos *a -= (signed24)ts * (signed24)tt;
747 1.1 christos }
748 1.1 christos
749 1.1 christos static void
750 1.9.2.1 perseant SubMulLOB(signed24 *a, uint8_t ts, uint8_t tt)
751 1.1 christos {
752 1.1 christos *a = -((signed24)ts * (signed24)tt);
753 1.1 christos }
754 1.1 christos
755 1.1 christos static void
756 1.9.2.1 perseant AccSubAOB(signed24 *a, uint8_t ts, uint8_t tt)
757 1.1 christos {
758 1.1 christos *a += (signed24)ts - (signed24)tt;
759 1.1 christos }
760 1.1 christos
761 1.1 christos static void
762 1.9.2.1 perseant AccSubLOB(signed24 *a, uint8_t ts, uint8_t tt)
763 1.1 christos {
764 1.1 christos *a = (signed24)ts - (signed24)tt;
765 1.1 christos }
766 1.1 christos
767 1.1 christos static void
768 1.9.2.1 perseant AccAbsDiffOB(signed24 *a, uint8_t ts, uint8_t tt)
769 1.1 christos {
770 1.9.2.1 perseant uint8_t t = (ts >= tt ? ts - tt : tt - ts);
771 1.1 christos *a += (signed24)t;
772 1.1 christos }
773 1.1 christos
774 1.1 christos
775 1.1 christos /* Dispatch tables for operations that update a CPR. */
776 1.1 christos
777 1.1 christos static const QH_ACC qh_acc[] = {
778 1.9.2.1 perseant AccAddAQH, AccAddLQH, AccMulAQH, AccMulLQH,
779 1.1 christos SubMulAQH, SubMulLQH, AccSubAQH, AccSubLQH,
780 1.1 christos NULL
781 1.1 christos };
782 1.1 christos
783 1.1 christos static const OB_ACC ob_acc[] = {
784 1.1 christos AccAddAOB, AccAddLOB, AccMulAOB, AccMulLOB,
785 1.1 christos SubMulAOB, SubMulLOB, AccSubAOB, AccSubLOB,
786 1.1 christos AccAbsDiffOB
787 1.1 christos };
788 1.1 christos
789 1.1 christos
790 1.1 christos static void
791 1.9.2.1 perseant qh_vector_acc(signed48 a[], uint64_t v1, uint64_t v2, QH_ACC acc)
792 1.1 christos {
793 1.1 christos int i;
794 1.9.2.1 perseant int16_t h1, h2;
795 1.1 christos
796 1.1 christos for (i = 0; i < 4; i++)
797 1.1 christos {
798 1.9.2.1 perseant h1 = (int16_t)(v1 & 0xFFFF); v1 >>= 16;
799 1.9.2.1 perseant h2 = (int16_t)(v2 & 0xFFFF); v2 >>= 16;
800 1.1 christos (*acc)(&a[i], h1, h2);
801 1.1 christos }
802 1.1 christos }
803 1.1 christos
804 1.1 christos static void
805 1.9.2.1 perseant qh_map_acc(signed48 a[], uint64_t v1, int16_t h2, QH_ACC acc)
806 1.1 christos {
807 1.1 christos int i;
808 1.9.2.1 perseant int16_t h1;
809 1.1 christos
810 1.1 christos for (i = 0; i < 4; i++)
811 1.1 christos {
812 1.9.2.1 perseant h1 = (int16_t)(v1 & 0xFFFF); v1 >>= 16;
813 1.1 christos (*acc)(&a[i], h1, h2);
814 1.1 christos }
815 1.1 christos }
816 1.1 christos
817 1.1 christos static void
818 1.9.2.1 perseant ob_vector_acc(signed24 a[], uint64_t v1, uint64_t v2, OB_ACC acc)
819 1.1 christos {
820 1.1 christos int i;
821 1.9.2.1 perseant uint8_t b1, b2;
822 1.1 christos
823 1.1 christos for (i = 0; i < 8; i++)
824 1.1 christos {
825 1.1 christos b1 = v1 & 0xFF; v1 >>= 8;
826 1.1 christos b2 = v2 & 0xFF; v2 >>= 8;
827 1.1 christos (*acc)(&a[i], b1, b2);
828 1.1 christos }
829 1.1 christos }
830 1.1 christos
831 1.1 christos static void
832 1.9.2.1 perseant ob_map_acc(signed24 a[], uint64_t v1, uint8_t b2, OB_ACC acc)
833 1.1 christos {
834 1.1 christos int i;
835 1.9.2.1 perseant uint8_t b1;
836 1.1 christos
837 1.1 christos for (i = 0; i < 8; i++)
838 1.1 christos {
839 1.1 christos b1 = v1 & 0xFF; v1 >>= 8;
840 1.1 christos (*acc)(&a[i], b1, b2);
841 1.1 christos }
842 1.1 christos }
843 1.1 christos
844 1.1 christos
845 1.1 christos /* Primary entry for operations that accumulate */
846 1.1 christos void
847 1.1 christos mdmx_acc_op(sim_cpu *cpu,
848 1.1 christos address_word cia,
849 1.1 christos int op,
850 1.9.2.1 perseant uint64_t op1,
851 1.1 christos int vt,
852 1.9.2.1 perseant MX_fmtsel fmtsel)
853 1.1 christos {
854 1.9.2.1 perseant uint64_t op2;
855 1.1 christos
856 1.1 christos switch (MX_FMT (fmtsel))
857 1.1 christos {
858 1.1 christos case mdmx_qh:
859 1.1 christos switch (MX_VT (fmtsel))
860 1.1 christos {
861 1.1 christos case sel_elem:
862 1.1 christos op2 = ValueFPR(vt, fmt_mdmx);
863 1.1 christos qh_map_acc(ACC.qh, op1, QH_ELEM(op2, fmtsel), qh_acc[op]);
864 1.1 christos break;
865 1.1 christos case sel_vect:
866 1.1 christos qh_vector_acc(ACC.qh, op1, ValueFPR(vt, fmt_mdmx), qh_acc[op]);
867 1.1 christos break;
868 1.1 christos case sel_imm:
869 1.1 christos qh_map_acc(ACC.qh, op1, vt, qh_acc[op]);
870 1.1 christos break;
871 1.1 christos }
872 1.1 christos break;
873 1.1 christos case mdmx_ob:
874 1.1 christos switch (MX_VT (fmtsel))
875 1.1 christos {
876 1.1 christos case sel_elem:
877 1.1 christos op2 = ValueFPR(vt, fmt_mdmx);
878 1.1 christos ob_map_acc(ACC.ob, op1, OB_ELEM(op2, fmtsel), ob_acc[op]);
879 1.1 christos break;
880 1.1 christos case sel_vect:
881 1.1 christos ob_vector_acc(ACC.ob, op1, ValueFPR(vt, fmt_mdmx), ob_acc[op]);
882 1.1 christos break;
883 1.1 christos case sel_imm:
884 1.1 christos ob_map_acc(ACC.ob, op1, vt, ob_acc[op]);
885 1.1 christos break;
886 1.1 christos }
887 1.1 christos break;
888 1.1 christos default:
889 1.1 christos Unpredictable ();
890 1.1 christos }
891 1.1 christos }
892 1.1 christos
893 1.1 christos
894 1.1 christos /* Reading and writing accumulator (no conversion). */
895 1.1 christos
896 1.9.2.1 perseant uint64_t
897 1.1 christos mdmx_rac_op(sim_cpu *cpu,
898 1.1 christos address_word cia,
899 1.1 christos int op,
900 1.9.2.1 perseant int fmt)
901 1.1 christos {
902 1.9.2.1 perseant uint64_t result;
903 1.1 christos unsigned int shift;
904 1.1 christos int i;
905 1.1 christos
906 1.1 christos shift = op; /* L = 00, M = 01, H = 10. */
907 1.1 christos result = 0;
908 1.1 christos
909 1.1 christos switch (fmt)
910 1.1 christos {
911 1.1 christos case MX_FMT_QH:
912 1.1 christos shift <<= 4; /* 16 bits per element. */
913 1.1 christos for (i = 3; i >= 0; --i)
914 1.1 christos {
915 1.1 christos result <<= 16;
916 1.1 christos result |= ((ACC.qh[i] >> shift) & 0xFFFF);
917 1.1 christos }
918 1.1 christos break;
919 1.1 christos case MX_FMT_OB:
920 1.1 christos shift <<= 3; /* 8 bits per element. */
921 1.1 christos for (i = 7; i >= 0; --i)
922 1.1 christos {
923 1.1 christos result <<= 8;
924 1.1 christos result |= ((ACC.ob[i] >> shift) & 0xFF);
925 1.1 christos }
926 1.1 christos break;
927 1.1 christos default:
928 1.1 christos Unpredictable ();
929 1.1 christos }
930 1.1 christos return result;
931 1.1 christos }
932 1.1 christos
933 1.1 christos void
934 1.1 christos mdmx_wacl(sim_cpu *cpu,
935 1.1 christos address_word cia,
936 1.1 christos int fmt,
937 1.9.2.1 perseant uint64_t vs,
938 1.9.2.1 perseant uint64_t vt)
939 1.1 christos {
940 1.1 christos int i;
941 1.1 christos
942 1.1 christos switch (fmt)
943 1.1 christos {
944 1.1 christos case MX_FMT_QH:
945 1.1 christos for (i = 0; i < 4; i++)
946 1.1 christos {
947 1.9.2.1 perseant int32_t s = (int16_t)(vs & 0xFFFF);
948 1.1 christos ACC.qh[i] = ((signed48)s << 16) | (vt & 0xFFFF);
949 1.1 christos vs >>= 16; vt >>= 16;
950 1.1 christos }
951 1.1 christos break;
952 1.1 christos case MX_FMT_OB:
953 1.1 christos for (i = 0; i < 8; i++)
954 1.1 christos {
955 1.9.2.1 perseant int16_t s = (int8_t)(vs & 0xFF);
956 1.1 christos ACC.ob[i] = ((signed24)s << 8) | (vt & 0xFF);
957 1.1 christos vs >>= 8; vt >>= 8;
958 1.1 christos }
959 1.1 christos break;
960 1.1 christos default:
961 1.1 christos Unpredictable ();
962 1.1 christos }
963 1.1 christos }
964 1.1 christos
965 1.1 christos void
966 1.1 christos mdmx_wach(sim_cpu *cpu,
967 1.1 christos address_word cia,
968 1.1 christos int fmt,
969 1.9.2.1 perseant uint64_t vs)
970 1.1 christos {
971 1.1 christos int i;
972 1.1 christos
973 1.1 christos switch (fmt)
974 1.1 christos {
975 1.1 christos case MX_FMT_QH:
976 1.1 christos for (i = 0; i < 4; i++)
977 1.1 christos {
978 1.9.2.1 perseant int32_t s = (int16_t)(vs & 0xFFFF);
979 1.1 christos ACC.qh[i] &= ~((signed48)0xFFFF << 32);
980 1.1 christos ACC.qh[i] |= ((signed48)s << 32);
981 1.1 christos vs >>= 16;
982 1.1 christos }
983 1.1 christos break;
984 1.1 christos case MX_FMT_OB:
985 1.1 christos for (i = 0; i < 8; i++)
986 1.1 christos {
987 1.1 christos ACC.ob[i] &= ~((signed24)0xFF << 16);
988 1.1 christos ACC.ob[i] |= ((signed24)(vs & 0xFF) << 16);
989 1.1 christos vs >>= 8;
990 1.1 christos }
991 1.1 christos break;
992 1.1 christos default:
993 1.1 christos Unpredictable ();
994 1.1 christos }
995 1.1 christos }
996 1.1 christos
997 1.1 christos
998 1.1 christos /* Reading and writing accumulator (rounding conversions).
999 1.1 christos Enumerating function guarantees s >= 0 for QH ops. */
1000 1.1 christos
1001 1.9.2.1 perseant typedef int16_t (*QH_ROUND)(signed48 a, int16_t s);
1002 1.1 christos
1003 1.1 christos #define QH_BIT(n) ((unsigned48)1 << (n))
1004 1.1 christos #define QH_ONES(n) (((unsigned48)1 << (n))-1)
1005 1.1 christos
1006 1.9.2.1 perseant static int16_t
1007 1.9.2.1 perseant RNASQH(signed48 a, int16_t s)
1008 1.1 christos {
1009 1.1 christos signed48 t;
1010 1.9.2.1 perseant int16_t result = 0;
1011 1.1 christos
1012 1.1 christos if (s > 48)
1013 1.1 christos result = 0;
1014 1.1 christos else
1015 1.1 christos {
1016 1.1 christos t = (a >> s);
1017 1.1 christos if ((a & QH_BIT(47)) == 0)
1018 1.1 christos {
1019 1.1 christos if (s > 0 && ((a >> (s-1)) & 1) == 1)
1020 1.1 christos t++;
1021 1.1 christos if (t > QH_MAX)
1022 1.1 christos t = QH_MAX;
1023 1.1 christos }
1024 1.1 christos else
1025 1.1 christos {
1026 1.1 christos if (s > 0 && ((a >> (s-1)) & 1) == 1)
1027 1.1 christos {
1028 1.1 christos if (s > 1 && ((unsigned48)a & QH_ONES(s-1)) != 0)
1029 1.1 christos t++;
1030 1.1 christos }
1031 1.1 christos if (t < QH_MIN)
1032 1.1 christos t = QH_MIN;
1033 1.1 christos }
1034 1.9.2.1 perseant result = (int16_t)t;
1035 1.1 christos }
1036 1.1 christos return result;
1037 1.1 christos }
1038 1.1 christos
1039 1.9.2.1 perseant static int16_t
1040 1.9.2.1 perseant RNAUQH(signed48 a, int16_t s)
1041 1.1 christos {
1042 1.1 christos unsigned48 t;
1043 1.9.2.1 perseant int16_t result;
1044 1.1 christos
1045 1.1 christos if (s > 48)
1046 1.1 christos result = 0;
1047 1.1 christos else if (s == 48)
1048 1.1 christos result = ((unsigned48)a & MASK48) >> 47;
1049 1.1 christos else
1050 1.1 christos {
1051 1.1 christos t = ((unsigned48)a & MASK48) >> s;
1052 1.1 christos if (s > 0 && ((a >> (s-1)) & 1) == 1)
1053 1.1 christos t++;
1054 1.1 christos if (t > 0xFFFF)
1055 1.1 christos t = 0xFFFF;
1056 1.9.2.1 perseant result = (int16_t)t;
1057 1.1 christos }
1058 1.1 christos return result;
1059 1.1 christos }
1060 1.1 christos
1061 1.9.2.1 perseant static int16_t
1062 1.9.2.1 perseant RNESQH(signed48 a, int16_t s)
1063 1.1 christos {
1064 1.1 christos signed48 t;
1065 1.9.2.1 perseant int16_t result = 0;
1066 1.1 christos
1067 1.1 christos if (s > 47)
1068 1.1 christos result = 0;
1069 1.1 christos else
1070 1.1 christos {
1071 1.1 christos t = (a >> s);
1072 1.1 christos if (s > 0 && ((a >> (s-1)) & 1) == 1)
1073 1.1 christos {
1074 1.1 christos if (s == 1 || (a & QH_ONES(s-1)) == 0)
1075 1.1 christos t += t & 1;
1076 1.1 christos else
1077 1.1 christos t += 1;
1078 1.1 christos }
1079 1.1 christos if ((a & QH_BIT(47)) == 0)
1080 1.1 christos {
1081 1.1 christos if (t > QH_MAX)
1082 1.1 christos t = QH_MAX;
1083 1.1 christos }
1084 1.1 christos else
1085 1.1 christos {
1086 1.1 christos if (t < QH_MIN)
1087 1.1 christos t = QH_MIN;
1088 1.1 christos }
1089 1.9.2.1 perseant result = (int16_t)t;
1090 1.1 christos }
1091 1.1 christos return result;
1092 1.1 christos }
1093 1.1 christos
1094 1.9.2.1 perseant static int16_t
1095 1.9.2.1 perseant RNEUQH(signed48 a, int16_t s)
1096 1.1 christos {
1097 1.1 christos unsigned48 t;
1098 1.9.2.1 perseant int16_t result;
1099 1.1 christos
1100 1.1 christos if (s > 48)
1101 1.1 christos result = 0;
1102 1.1 christos else if (s == 48)
1103 1.1 christos result = ((unsigned48)a > QH_BIT(47) ? 1 : 0);
1104 1.1 christos else
1105 1.1 christos {
1106 1.1 christos t = ((unsigned48)a & MASK48) >> s;
1107 1.1 christos if (s > 0 && ((a >> (s-1)) & 1) == 1)
1108 1.1 christos {
1109 1.1 christos if (s > 1 && (a & QH_ONES(s-1)) != 0)
1110 1.1 christos t++;
1111 1.1 christos else
1112 1.1 christos t += t & 1;
1113 1.1 christos }
1114 1.1 christos if (t > 0xFFFF)
1115 1.1 christos t = 0xFFFF;
1116 1.9.2.1 perseant result = (int16_t)t;
1117 1.1 christos }
1118 1.1 christos return result;
1119 1.1 christos }
1120 1.1 christos
1121 1.9.2.1 perseant static int16_t
1122 1.9.2.1 perseant RZSQH(signed48 a, int16_t s)
1123 1.1 christos {
1124 1.1 christos signed48 t;
1125 1.9.2.1 perseant int16_t result = 0;
1126 1.1 christos
1127 1.1 christos if (s > 47)
1128 1.1 christos result = 0;
1129 1.1 christos else
1130 1.1 christos {
1131 1.1 christos t = (a >> s);
1132 1.1 christos if ((a & QH_BIT(47)) == 0)
1133 1.1 christos {
1134 1.1 christos if (t > QH_MAX)
1135 1.1 christos t = QH_MAX;
1136 1.1 christos }
1137 1.1 christos else
1138 1.1 christos {
1139 1.1 christos if (t < QH_MIN)
1140 1.1 christos t = QH_MIN;
1141 1.1 christos }
1142 1.9.2.1 perseant result = (int16_t)t;
1143 1.1 christos }
1144 1.1 christos return result;
1145 1.1 christos }
1146 1.1 christos
1147 1.9.2.1 perseant static int16_t
1148 1.9.2.1 perseant RZUQH(signed48 a, int16_t s)
1149 1.1 christos {
1150 1.1 christos unsigned48 t;
1151 1.9.2.1 perseant int16_t result = 0;
1152 1.1 christos
1153 1.1 christos if (s > 48)
1154 1.1 christos result = 0;
1155 1.1 christos else if (s == 48)
1156 1.1 christos result = ((unsigned48)a > QH_BIT(47) ? 1 : 0);
1157 1.1 christos else
1158 1.1 christos {
1159 1.1 christos t = ((unsigned48)a & MASK48) >> s;
1160 1.1 christos if (t > 0xFFFF)
1161 1.1 christos t = 0xFFFF;
1162 1.9.2.1 perseant result = (int16_t)t;
1163 1.1 christos }
1164 1.1 christos return result;
1165 1.1 christos }
1166 1.1 christos
1167 1.1 christos
1168 1.9.2.1 perseant typedef uint8_t (*OB_ROUND)(signed24 a, uint8_t s);
1169 1.1 christos
1170 1.1 christos #define OB_BIT(n) ((unsigned24)1 << (n))
1171 1.1 christos #define OB_ONES(n) (((unsigned24)1 << (n))-1)
1172 1.1 christos
1173 1.9.2.1 perseant static uint8_t
1174 1.9.2.1 perseant RNAUOB(signed24 a, uint8_t s)
1175 1.1 christos {
1176 1.9.2.1 perseant uint8_t result;
1177 1.1 christos unsigned24 t;
1178 1.1 christos
1179 1.1 christos if (s > 24)
1180 1.1 christos result = 0;
1181 1.1 christos else if (s == 24)
1182 1.1 christos result = ((unsigned24)a & MASK24) >> 23;
1183 1.1 christos else
1184 1.1 christos {
1185 1.1 christos t = ((unsigned24)a & MASK24) >> s;
1186 1.1 christos if (s > 0 && ((a >> (s-1)) & 1) == 1)
1187 1.1 christos t ++;
1188 1.1 christos result = OB_CLAMP(t);
1189 1.1 christos }
1190 1.1 christos return result;
1191 1.1 christos }
1192 1.1 christos
1193 1.9.2.1 perseant static uint8_t
1194 1.9.2.1 perseant RNEUOB(signed24 a, uint8_t s)
1195 1.1 christos {
1196 1.9.2.1 perseant uint8_t result;
1197 1.1 christos unsigned24 t;
1198 1.1 christos
1199 1.1 christos if (s > 24)
1200 1.1 christos result = 0;
1201 1.1 christos else if (s == 24)
1202 1.1 christos result = (((unsigned24)a & MASK24) > OB_BIT(23) ? 1 : 0);
1203 1.1 christos else
1204 1.1 christos {
1205 1.1 christos t = ((unsigned24)a & MASK24) >> s;
1206 1.1 christos if (s > 0 && ((a >> (s-1)) & 1) == 1)
1207 1.1 christos {
1208 1.1 christos if (s > 1 && (a & OB_ONES(s-1)) != 0)
1209 1.1 christos t++;
1210 1.1 christos else
1211 1.1 christos t += t & 1;
1212 1.1 christos }
1213 1.1 christos result = OB_CLAMP(t);
1214 1.1 christos }
1215 1.1 christos return result;
1216 1.1 christos }
1217 1.1 christos
1218 1.9.2.1 perseant static uint8_t
1219 1.9.2.1 perseant RZUOB(signed24 a, uint8_t s)
1220 1.1 christos {
1221 1.9.2.1 perseant uint8_t result;
1222 1.1 christos unsigned24 t;
1223 1.1 christos
1224 1.1 christos if (s >= 24)
1225 1.1 christos result = 0;
1226 1.1 christos else
1227 1.1 christos {
1228 1.1 christos t = ((unsigned24)a & MASK24) >> s;
1229 1.1 christos result = OB_CLAMP(t);
1230 1.1 christos }
1231 1.1 christos return result;
1232 1.1 christos }
1233 1.1 christos
1234 1.1 christos
1235 1.1 christos static const QH_ROUND qh_round[] = {
1236 1.1 christos RNASQH, RNAUQH, RNESQH, RNEUQH, RZSQH, RZUQH
1237 1.1 christos };
1238 1.1 christos
1239 1.1 christos static const OB_ROUND ob_round[] = {
1240 1.1 christos NULL, RNAUOB, NULL, RNEUOB, NULL, RZUOB
1241 1.1 christos };
1242 1.1 christos
1243 1.1 christos
1244 1.9.2.1 perseant static uint64_t
1245 1.9.2.1 perseant qh_vector_round(sim_cpu *cpu, address_word cia, uint64_t v2, QH_ROUND round)
1246 1.1 christos {
1247 1.9.2.1 perseant uint64_t result = 0;
1248 1.1 christos int i, s;
1249 1.9.2.1 perseant int16_t h, h2;
1250 1.1 christos
1251 1.1 christos s = 0;
1252 1.1 christos for (i = 0; i < 4; i++)
1253 1.1 christos {
1254 1.9.2.1 perseant h2 = (int16_t)(v2 & 0xFFFF);
1255 1.1 christos if (h2 >= 0)
1256 1.1 christos h = (*round)(ACC.qh[i], h2);
1257 1.1 christos else
1258 1.1 christos {
1259 1.1 christos UnpredictableResult ();
1260 1.1 christos h = 0xdead;
1261 1.1 christos }
1262 1.1 christos v2 >>= 16;
1263 1.9.2.1 perseant result |= ((uint64_t)((uint16_t)h) << s);
1264 1.1 christos s += 16;
1265 1.1 christos }
1266 1.1 christos return result;
1267 1.1 christos }
1268 1.1 christos
1269 1.9.2.1 perseant static uint64_t
1270 1.9.2.1 perseant qh_map_round(sim_cpu *cpu, address_word cia, int16_t h2, QH_ROUND round)
1271 1.1 christos {
1272 1.9.2.1 perseant uint64_t result = 0;
1273 1.1 christos int i, s;
1274 1.9.2.1 perseant int16_t h;
1275 1.1 christos
1276 1.1 christos s = 0;
1277 1.1 christos for (i = 0; i < 4; i++)
1278 1.1 christos {
1279 1.1 christos if (h2 >= 0)
1280 1.1 christos h = (*round)(ACC.qh[i], h2);
1281 1.1 christos else
1282 1.1 christos {
1283 1.1 christos UnpredictableResult ();
1284 1.1 christos h = 0xdead;
1285 1.1 christos }
1286 1.9.2.1 perseant result |= ((uint64_t)((uint16_t)h) << s);
1287 1.1 christos s += 16;
1288 1.1 christos }
1289 1.1 christos return result;
1290 1.1 christos }
1291 1.1 christos
1292 1.9.2.1 perseant static uint64_t
1293 1.9.2.1 perseant ob_vector_round(sim_cpu *cpu, address_word cia, uint64_t v2, OB_ROUND round)
1294 1.1 christos {
1295 1.9.2.1 perseant uint64_t result = 0;
1296 1.1 christos int i, s;
1297 1.9.2.1 perseant uint8_t b, b2;
1298 1.1 christos
1299 1.1 christos s = 0;
1300 1.1 christos for (i = 0; i < 8; i++)
1301 1.1 christos {
1302 1.1 christos b2 = v2 & 0xFF; v2 >>= 8;
1303 1.1 christos b = (*round)(ACC.ob[i], b2);
1304 1.9.2.1 perseant result |= ((uint64_t)b << s);
1305 1.1 christos s += 8;
1306 1.1 christos }
1307 1.1 christos return result;
1308 1.1 christos }
1309 1.1 christos
1310 1.9.2.1 perseant static uint64_t
1311 1.9.2.1 perseant ob_map_round(sim_cpu *cpu, address_word cia, uint8_t b2, OB_ROUND round)
1312 1.1 christos {
1313 1.9.2.1 perseant uint64_t result = 0;
1314 1.1 christos int i, s;
1315 1.9.2.1 perseant uint8_t b;
1316 1.1 christos
1317 1.1 christos s = 0;
1318 1.1 christos for (i = 0; i < 8; i++)
1319 1.1 christos {
1320 1.1 christos b = (*round)(ACC.ob[i], b2);
1321 1.9.2.1 perseant result |= ((uint64_t)b << s);
1322 1.1 christos s += 8;
1323 1.1 christos }
1324 1.1 christos return result;
1325 1.1 christos }
1326 1.1 christos
1327 1.1 christos
1328 1.9.2.1 perseant uint64_t
1329 1.1 christos mdmx_round_op(sim_cpu *cpu,
1330 1.1 christos address_word cia,
1331 1.1 christos int rm,
1332 1.1 christos int vt,
1333 1.9.2.1 perseant MX_fmtsel fmtsel)
1334 1.1 christos {
1335 1.9.2.1 perseant uint64_t op2;
1336 1.9.2.1 perseant uint64_t result = 0;
1337 1.1 christos
1338 1.1 christos switch (MX_FMT (fmtsel))
1339 1.1 christos {
1340 1.1 christos case mdmx_qh:
1341 1.1 christos switch (MX_VT (fmtsel))
1342 1.1 christos {
1343 1.1 christos case sel_elem:
1344 1.1 christos op2 = ValueFPR(vt, fmt_mdmx);
1345 1.1 christos result = qh_map_round(cpu, cia, QH_ELEM(op2, fmtsel), qh_round[rm]);
1346 1.1 christos break;
1347 1.1 christos case sel_vect:
1348 1.1 christos op2 = ValueFPR(vt, fmt_mdmx);
1349 1.1 christos result = qh_vector_round(cpu, cia, op2, qh_round[rm]);
1350 1.1 christos break;
1351 1.1 christos case sel_imm:
1352 1.1 christos result = qh_map_round(cpu, cia, vt, qh_round[rm]);
1353 1.1 christos break;
1354 1.1 christos }
1355 1.1 christos break;
1356 1.1 christos case mdmx_ob:
1357 1.1 christos switch (MX_VT (fmtsel))
1358 1.1 christos {
1359 1.1 christos case sel_elem:
1360 1.1 christos op2 = ValueFPR(vt, fmt_mdmx);
1361 1.1 christos result = ob_map_round(cpu, cia, OB_ELEM(op2, fmtsel), ob_round[rm]);
1362 1.1 christos break;
1363 1.1 christos case sel_vect:
1364 1.1 christos op2 = ValueFPR(vt, fmt_mdmx);
1365 1.1 christos result = ob_vector_round(cpu, cia, op2, ob_round[rm]);
1366 1.1 christos break;
1367 1.1 christos case sel_imm:
1368 1.1 christos result = ob_map_round(cpu, cia, vt, ob_round[rm]);
1369 1.1 christos break;
1370 1.1 christos }
1371 1.1 christos break;
1372 1.1 christos default:
1373 1.1 christos Unpredictable ();
1374 1.1 christos }
1375 1.1 christos
1376 1.1 christos return result;
1377 1.1 christos }
1378 1.1 christos
1379 1.1 christos
1380 1.1 christos /* Shuffle operation. */
1381 1.1 christos
1382 1.1 christos typedef struct {
1383 1.1 christos enum {vs, ss, vt} source;
1384 1.1 christos unsigned int index;
1385 1.1 christos } sh_map;
1386 1.1 christos
1387 1.1 christos static const sh_map ob_shuffle[][8] = {
1388 1.1 christos /* MDMX 2.0 encodings (3-4, 6-7). */
1389 1.1 christos /* vr5400 encoding (5), otherwise. */
1390 1.1 christos { }, /* RSVD */
1391 1.1 christos {{vt,4}, {vs,4}, {vt,5}, {vs,5}, {vt,6}, {vs,6}, {vt,7}, {vs,7}}, /* RSVD */
1392 1.1 christos {{vt,0}, {vs,0}, {vt,1}, {vs,1}, {vt,2}, {vs,2}, {vt,3}, {vs,3}}, /* RSVD */
1393 1.1 christos {{vs,0}, {ss,0}, {vs,1}, {ss,1}, {vs,2}, {ss,2}, {vs,3}, {ss,3}}, /* upsl */
1394 1.1 christos {{vt,1}, {vt,3}, {vt,5}, {vt,7}, {vs,1}, {vs,3}, {vs,5}, {vs,7}}, /* pach */
1395 1.1 christos {{vt,0}, {vt,2}, {vt,4}, {vt,6}, {vs,0}, {vs,2}, {vs,4}, {vs,6}}, /* pacl */
1396 1.1 christos {{vt,4}, {vs,4}, {vt,5}, {vs,5}, {vt,6}, {vs,6}, {vt,7}, {vs,7}}, /* mixh */
1397 1.1 christos {{vt,0}, {vs,0}, {vt,1}, {vs,1}, {vt,2}, {vs,2}, {vt,3}, {vs,3}} /* mixl */
1398 1.1 christos };
1399 1.1 christos
1400 1.1 christos static const sh_map qh_shuffle[][4] = {
1401 1.1 christos {{vt,2}, {vs,2}, {vt,3}, {vs,3}}, /* mixh */
1402 1.1 christos {{vt,0}, {vs,0}, {vt,1}, {vs,1}}, /* mixl */
1403 1.1 christos {{vt,1}, {vt,3}, {vs,1}, {vs,3}}, /* pach */
1404 1.1 christos { }, /* RSVD */
1405 1.1 christos {{vt,1}, {vs,0}, {vt,3}, {vs,2}}, /* bfla */
1406 1.1 christos { }, /* RSVD */
1407 1.1 christos {{vt,2}, {vt,3}, {vs,2}, {vs,3}}, /* repa */
1408 1.1 christos {{vt,0}, {vt,1}, {vs,0}, {vs,1}} /* repb */
1409 1.1 christos };
1410 1.1 christos
1411 1.1 christos
1412 1.9.2.1 perseant uint64_t
1413 1.1 christos mdmx_shuffle(sim_cpu *cpu,
1414 1.1 christos address_word cia,
1415 1.1 christos int shop,
1416 1.9.2.1 perseant uint64_t op1,
1417 1.9.2.1 perseant uint64_t op2)
1418 1.1 christos {
1419 1.9.2.1 perseant uint64_t result = 0;
1420 1.1 christos int i, s;
1421 1.1 christos int op;
1422 1.1 christos
1423 1.1 christos if ((shop & 0x3) == 0x1) /* QH format. */
1424 1.1 christos {
1425 1.1 christos op = shop >> 2;
1426 1.1 christos s = 0;
1427 1.1 christos for (i = 0; i < 4; i++)
1428 1.1 christos {
1429 1.9.2.1 perseant uint64_t v;
1430 1.1 christos
1431 1.1 christos switch (qh_shuffle[op][i].source)
1432 1.1 christos {
1433 1.1 christos case vs:
1434 1.1 christos v = op1;
1435 1.1 christos break;
1436 1.1 christos case vt:
1437 1.1 christos v = op2;
1438 1.1 christos break;
1439 1.1 christos default:
1440 1.1 christos Unpredictable ();
1441 1.1 christos v = 0;
1442 1.1 christos }
1443 1.1 christos result |= (((v >> 16*qh_shuffle[op][i].index) & 0xFFFF) << s);
1444 1.1 christos s += 16;
1445 1.1 christos }
1446 1.1 christos }
1447 1.1 christos else if ((shop & 0x1) == 0x0) /* OB format. */
1448 1.1 christos {
1449 1.1 christos op = shop >> 1;
1450 1.1 christos s = 0;
1451 1.1 christos for (i = 0; i < 8; i++)
1452 1.1 christos {
1453 1.9.2.1 perseant uint8_t b;
1454 1.1 christos unsigned int ishift = 8*ob_shuffle[op][i].index;
1455 1.1 christos
1456 1.1 christos switch (ob_shuffle[op][i].source)
1457 1.1 christos {
1458 1.1 christos case vs:
1459 1.1 christos b = (op1 >> ishift) & 0xFF;
1460 1.1 christos break;
1461 1.1 christos case ss:
1462 1.1 christos b = ((op1 >> ishift) & 0x80) ? 0xFF : 0;
1463 1.1 christos break;
1464 1.1 christos case vt:
1465 1.1 christos b = (op2 >> ishift) & 0xFF;
1466 1.1 christos break;
1467 1.1 christos default:
1468 1.1 christos Unpredictable ();
1469 1.1 christos b = 0;
1470 1.1 christos }
1471 1.9.2.1 perseant result |= ((uint64_t)b << s);
1472 1.1 christos s += 8;
1473 1.1 christos }
1474 1.1 christos }
1475 1.1 christos else
1476 1.1 christos Unpredictable ();
1477 1.1 christos
1478 1.1 christos return result;
1479 1.1 christos }
1480