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