Fix up mix of man(7)/mdoc(7).
[netbsd-mini2440.git] / gnu / dist / gdb6 / sim / mips / mdmx.c
blob3af59b06dcbe53fab48946b55186c2eb18004527
1 /* Simulation code for the MIPS MDMX ASE.
2 Copyright (C) 2002 Free Software Foundation, Inc.
3 Contributed by Ed Satterthwaite and Chris Demetriou, of Broadcom
4 Corporation (SiByte).
6 This file is part of GDB, the GNU debugger.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License along
19 with this program; if not, write to the Free Software Foundation, Inc.,
20 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
22 #include <stdio.h>
24 #include "sim-main.h"
26 /* Within mdmx.c we refer to the sim_cpu directly. */
27 #define CPU cpu
28 #define SD (CPU_STATE(CPU))
30 /* XXX FIXME: temporary hack while the impact of making unpredictable()
31 a "normal" (non-igen) function is evaluated. */
32 #undef Unpredictable
33 #define Unpredictable() unpredictable_action (cpu, cia)
35 /* MDMX Representations
37 An 8-bit packed byte element (OB) is always unsigned.
38 The 24-bit accumulators are signed and are represented as 32-bit
39 signed values, which are reduced to 24-bit signed values prior to
40 Round and Clamp operations.
42 A 16-bit packed halfword element (QH) is always signed.
43 The 48-bit accumulators are signed and are represented as 64-bit
44 signed values, which are reduced to 48-bit signed values prior to
45 Round and Clamp operations.
47 The code below assumes a 2's-complement representation of signed
48 quantities. Care is required to clear extended sign bits when
49 repacking fields.
51 The code (and the code for arithmetic shifts in mips.igen) also makes
52 the (not guaranteed portable) assumption that right shifts of signed
53 quantities in C do sign extension. */
55 typedef unsigned64 unsigned48;
56 #define MASK48 (UNSIGNED64 (0xffffffffffff))
58 typedef unsigned32 unsigned24;
59 #define MASK24 (UNSIGNED32 (0xffffff))
61 typedef enum {
62 mdmx_ob, /* OB (octal byte) */
63 mdmx_qh /* QH (quad half-word) */
64 } MX_fmt;
66 typedef enum {
67 sel_elem, /* element select */
68 sel_vect, /* vector select */
69 sel_imm /* immediate select */
70 } VT_select;
72 #define OB_MAX ((unsigned8)0xFF)
73 #define QH_MIN ((signed16)0x8000)
74 #define QH_MAX ((signed16)0x7FFF)
76 #define OB_CLAMP(x) ((unsigned8)((x) > OB_MAX ? OB_MAX : (x)))
77 #define QH_CLAMP(x) ((signed16)((x) < QH_MIN ? QH_MIN : \
78 ((x) > QH_MAX ? QH_MAX : (x))))
80 #define MX_FMT(fmtsel) (((fmtsel) & 0x1) == 0 ? mdmx_ob : mdmx_qh)
81 #define MX_VT(fmtsel) (((fmtsel) & 0x10) == 0 ? sel_elem : \
82 (((fmtsel) & 0x18) == 0x10 ? sel_vect : sel_imm))
84 #define QH_ELEM(v,fmtsel) \
85 ((signed16)(((v) >> (((fmtsel) & 0xC) << 2)) & 0xFFFF))
86 #define OB_ELEM(v,fmtsel) \
87 ((unsigned8)(((v) >> (((fmtsel) & 0xE) << 2)) & 0xFF))
90 typedef signed16 (*QH_FUNC)(signed16, signed16);
91 typedef unsigned8 (*OB_FUNC)(unsigned8, unsigned8);
93 /* vectorized logical operators */
95 static signed16
96 AndQH(signed16 ts, signed16 tt)
98 return (signed16)((unsigned16)ts & (unsigned16)tt);
101 static unsigned8
102 AndOB(unsigned8 ts, unsigned8 tt)
104 return ts & tt;
107 static signed16
108 NorQH(signed16 ts, signed16 tt)
110 return (signed16)(((unsigned16)ts | (unsigned16)tt) ^ 0xFFFF);
113 static unsigned8
114 NorOB(unsigned8 ts, unsigned8 tt)
116 return (ts | tt) ^ 0xFF;
119 static signed16
120 OrQH(signed16 ts, signed16 tt)
122 return (signed16)((unsigned16)ts | (unsigned16)tt);
125 static unsigned8
126 OrOB(unsigned8 ts, unsigned8 tt)
128 return ts | tt;
131 static signed16
132 XorQH(signed16 ts, signed16 tt)
134 return (signed16)((unsigned16)ts ^ (unsigned16)tt);
137 static unsigned8
138 XorOB(unsigned8 ts, unsigned8 tt)
140 return ts ^ tt;
143 static signed16
144 SLLQH(signed16 ts, signed16 tt)
146 unsigned32 s = (unsigned32)tt & 0xF;
147 return (signed16)(((unsigned32)ts << s) & 0xFFFF);
150 static unsigned8
151 SLLOB(unsigned8 ts, unsigned8 tt)
153 unsigned32 s = tt & 0x7;
154 return (ts << s) & 0xFF;
157 static signed16
158 SRLQH(signed16 ts, signed16 tt)
160 unsigned32 s = (unsigned32)tt & 0xF;
161 return (signed16)((unsigned16)ts >> s);
164 static unsigned8
165 SRLOB(unsigned8 ts, unsigned8 tt)
167 unsigned32 s = tt & 0x7;
168 return ts >> s;
172 /* Vectorized arithmetic operators. */
174 static signed16
175 AddQH(signed16 ts, signed16 tt)
177 signed32 t = (signed32)ts + (signed32)tt;
178 return QH_CLAMP(t);
181 static unsigned8
182 AddOB(unsigned8 ts, unsigned8 tt)
184 unsigned32 t = (unsigned32)ts + (unsigned32)tt;
185 return OB_CLAMP(t);
188 static signed16
189 SubQH(signed16 ts, signed16 tt)
191 signed32 t = (signed32)ts - (signed32)tt;
192 return QH_CLAMP(t);
195 static unsigned8
196 SubOB(unsigned8 ts, unsigned8 tt)
198 signed32 t;
199 t = (signed32)ts - (signed32)tt;
200 if (t < 0)
201 t = 0;
202 return (unsigned8)t;
205 static signed16
206 MinQH(signed16 ts, signed16 tt)
208 return (ts < tt ? ts : tt);
211 static unsigned8
212 MinOB(unsigned8 ts, unsigned8 tt)
214 return (ts < tt ? ts : tt);
217 static signed16
218 MaxQH(signed16 ts, signed16 tt)
220 return (ts > tt ? ts : tt);
223 static unsigned8
224 MaxOB(unsigned8 ts, unsigned8 tt)
226 return (ts > tt ? ts : tt);
229 static signed16
230 MulQH(signed16 ts, signed16 tt)
232 signed32 t = (signed32)ts * (signed32)tt;
233 return QH_CLAMP(t);
236 static unsigned8
237 MulOB(unsigned8 ts, unsigned8 tt)
239 unsigned32 t = (unsigned32)ts * (unsigned32)tt;
240 return OB_CLAMP(t);
243 /* "msgn" and "sra" are defined only for QH format. */
245 static signed16
246 MsgnQH(signed16 ts, signed16 tt)
248 signed16 t;
249 if (ts < 0)
250 t = (tt == QH_MIN ? QH_MAX : -tt);
251 else if (ts == 0)
252 t = 0;
253 else
254 t = tt;
255 return t;
258 static signed16
259 SRAQH(signed16 ts, signed16 tt)
261 unsigned32 s = (unsigned32)tt & 0xF;
262 return (signed16)((signed32)ts >> s);
266 /* "pabsdiff" and "pavg" are defined only for OB format. */
268 static unsigned8
269 AbsDiffOB(unsigned8 ts, unsigned8 tt)
271 return (ts >= tt ? ts - tt : tt - ts);
274 static unsigned8
275 AvgOB(unsigned8 ts, unsigned8 tt)
277 return ((unsigned32)ts + (unsigned32)tt + 1) >> 1;
281 /* Dispatch tables for operations that update a CPR. */
283 static const QH_FUNC qh_func[] = {
284 AndQH, NorQH, OrQH, XorQH, SLLQH, SRLQH,
285 AddQH, SubQH, MinQH, MaxQH,
286 MulQH, MsgnQH, SRAQH, NULL, NULL
289 static const OB_FUNC ob_func[] = {
290 AndOB, NorOB, OrOB, XorOB, SLLOB, SRLOB,
291 AddOB, SubOB, MinOB, MaxOB,
292 MulOB, NULL, NULL, AbsDiffOB, AvgOB
295 /* Auxiliary functions for CPR updates. */
297 /* Vector mapping for QH format. */
298 static unsigned64
299 qh_vector_op(unsigned64 v1, unsigned64 v2, QH_FUNC func)
301 unsigned64 result = 0;
302 int i;
303 signed16 h, h1, h2;
305 for (i = 0; i < 64; i += 16)
307 h1 = (signed16)(v1 & 0xFFFF); v1 >>= 16;
308 h2 = (signed16)(v2 & 0xFFFF); v2 >>= 16;
309 h = (*func)(h1, h2);
310 result |= ((unsigned64)((unsigned16)h) << i);
312 return result;
315 static unsigned64
316 qh_map_op(unsigned64 v1, signed16 h2, QH_FUNC func)
318 unsigned64 result = 0;
319 int i;
320 signed16 h, h1;
322 for (i = 0; i < 64; i += 16)
324 h1 = (signed16)(v1 & 0xFFFF); v1 >>= 16;
325 h = (*func)(h1, h2);
326 result |= ((unsigned64)((unsigned16)h) << i);
328 return result;
332 /* Vector operations for OB format. */
334 static unsigned64
335 ob_vector_op(unsigned64 v1, unsigned64 v2, OB_FUNC func)
337 unsigned64 result = 0;
338 int i;
339 unsigned8 b, b1, b2;
341 for (i = 0; i < 64; i += 8)
343 b1 = v1 & 0xFF; v1 >>= 8;
344 b2 = v2 & 0xFF; v2 >>= 8;
345 b = (*func)(b1, b2);
346 result |= ((unsigned64)b << i);
348 return result;
351 static unsigned64
352 ob_map_op(unsigned64 v1, unsigned8 b2, OB_FUNC func)
354 unsigned64 result = 0;
355 int i;
356 unsigned8 b, b1;
358 for (i = 0; i < 64; i += 8)
360 b1 = v1 & 0xFF; v1 >>= 8;
361 b = (*func)(b1, b2);
362 result |= ((unsigned64)b << i);
364 return result;
368 /* Primary entry for operations that update CPRs. */
369 unsigned64
370 mdmx_cpr_op(sim_cpu *cpu,
371 address_word cia,
372 int op,
373 unsigned64 op1,
374 int vt,
375 MX_fmtsel fmtsel)
377 unsigned64 op2;
378 unsigned64 result = 0;
380 switch (MX_FMT (fmtsel))
382 case mdmx_qh:
383 switch (MX_VT (fmtsel))
385 case sel_elem:
386 op2 = ValueFPR(vt, fmt_mdmx);
387 result = qh_map_op(op1, QH_ELEM(op2, fmtsel), qh_func[op]);
388 break;
389 case sel_vect:
390 result = qh_vector_op(op1, ValueFPR(vt, fmt_mdmx), qh_func[op]);
391 break;
392 case sel_imm:
393 result = qh_map_op(op1, vt, qh_func[op]);
394 break;
396 break;
397 case mdmx_ob:
398 switch (MX_VT (fmtsel))
400 case sel_elem:
401 op2 = ValueFPR(vt, fmt_mdmx);
402 result = ob_map_op(op1, OB_ELEM(op2, fmtsel), ob_func[op]);
403 break;
404 case sel_vect:
405 result = ob_vector_op(op1, ValueFPR(vt, fmt_mdmx), ob_func[op]);
406 break;
407 case sel_imm:
408 result = ob_map_op(op1, vt, ob_func[op]);
409 break;
411 break;
412 default:
413 Unpredictable ();
416 return result;
420 /* Operations that update CCs */
422 static void
423 qh_vector_test(sim_cpu *cpu, unsigned64 v1, unsigned64 v2, int cond)
425 int i;
426 signed16 h1, h2;
427 int boolean;
429 for (i = 0; i < 4; i++)
431 h1 = (signed16)(v1 & 0xFFFF); v1 >>= 16;
432 h2 = (signed16)(v2 & 0xFFFF); v2 >>= 16;
433 boolean = ((cond & MX_C_EQ) && (h1 == h2)) ||
434 ((cond & MX_C_LT) && (h1 < h2));
435 SETFCC(i, boolean);
439 static void
440 qh_map_test(sim_cpu *cpu, unsigned64 v1, signed16 h2, int cond)
442 int i;
443 signed16 h1;
444 int boolean;
446 for (i = 0; i < 4; i++)
448 h1 = (signed16)(v1 & 0xFFFF); v1 >>= 16;
449 boolean = ((cond & MX_C_EQ) && (h1 == h2)) ||
450 ((cond & MX_C_LT) && (h1 < h2));
451 SETFCC(i, boolean);
455 static void
456 ob_vector_test(sim_cpu *cpu, unsigned64 v1, unsigned64 v2, int cond)
458 int i;
459 unsigned8 b1, b2;
460 int boolean;
462 for (i = 0; i < 8; i++)
464 b1 = v1 & 0xFF; v1 >>= 8;
465 b2 = v2 & 0xFF; v2 >>= 8;
466 boolean = ((cond & MX_C_EQ) && (b1 == b2)) ||
467 ((cond & MX_C_LT) && (b1 < b2));
468 SETFCC(i, boolean);
472 static void
473 ob_map_test(sim_cpu *cpu, unsigned64 v1, unsigned8 b2, int cond)
475 int i;
476 unsigned8 b1;
477 int boolean;
479 for (i = 0; i < 8; i++)
481 b1 = (unsigned8)(v1 & 0xFF); v1 >>= 8;
482 boolean = ((cond & MX_C_EQ) && (b1 == b2)) ||
483 ((cond & MX_C_LT) && (b1 < b2));
484 SETFCC(i, boolean);
489 void
490 mdmx_cc_op(sim_cpu *cpu,
491 address_word cia,
492 int cond,
493 unsigned64 v1,
494 int vt,
495 MX_fmtsel fmtsel)
497 unsigned64 op2;
499 switch (MX_FMT (fmtsel))
501 case mdmx_qh:
502 switch (MX_VT (fmtsel))
504 case sel_elem:
505 op2 = ValueFPR(vt, fmt_mdmx);
506 qh_map_test(cpu, v1, QH_ELEM(op2, fmtsel), cond);
507 break;
508 case sel_vect:
509 qh_vector_test(cpu, v1, ValueFPR(vt, fmt_mdmx), cond);
510 break;
511 case sel_imm:
512 qh_map_test(cpu, v1, vt, cond);
513 break;
515 break;
516 case mdmx_ob:
517 switch (MX_VT (fmtsel))
519 case sel_elem:
520 op2 = ValueFPR(vt, fmt_mdmx);
521 ob_map_test(cpu, v1, OB_ELEM(op2, fmtsel), cond);
522 break;
523 case sel_vect:
524 ob_vector_test(cpu, v1, ValueFPR(vt, fmt_mdmx), cond);
525 break;
526 case sel_imm:
527 ob_map_test(cpu, v1, vt, cond);
528 break;
530 break;
531 default:
532 Unpredictable ();
537 /* Pick operations. */
539 static unsigned64
540 qh_vector_pick(sim_cpu *cpu, unsigned64 v1, unsigned64 v2, int tf)
542 unsigned64 result = 0;
543 int i, s;
544 unsigned16 h;
546 s = 0;
547 for (i = 0; i < 4; i++)
549 h = ((GETFCC(i) == tf) ? (v1 & 0xFFFF) : (v2 & 0xFFFF));
550 v1 >>= 16; v2 >>= 16;
551 result |= ((unsigned64)h << s);
552 s += 16;
554 return result;
557 static unsigned64
558 qh_map_pick(sim_cpu *cpu, unsigned64 v1, signed16 h2, int tf)
560 unsigned64 result = 0;
561 int i, s;
562 unsigned16 h;
564 s = 0;
565 for (i = 0; i < 4; i++)
567 h = (GETFCC(i) == tf) ? (v1 & 0xFFFF) : (unsigned16)h2;
568 v1 >>= 16;
569 result |= ((unsigned64)h << s);
570 s += 16;
572 return result;
575 static unsigned64
576 ob_vector_pick(sim_cpu *cpu, unsigned64 v1, unsigned64 v2, int tf)
578 unsigned64 result = 0;
579 int i, s;
580 unsigned8 b;
582 s = 0;
583 for (i = 0; i < 8; i++)
585 b = (GETFCC(i) == tf) ? (v1 & 0xFF) : (v2 & 0xFF);
586 v1 >>= 8; v2 >>= 8;
587 result |= ((unsigned64)b << s);
588 s += 8;
590 return result;
593 static unsigned64
594 ob_map_pick(sim_cpu *cpu, unsigned64 v1, unsigned8 b2, int tf)
596 unsigned64 result = 0;
597 int i, s;
598 unsigned8 b;
600 s = 0;
601 for (i = 0; i < 8; i++)
603 b = (GETFCC(i) == tf) ? (v1 & 0xFF) : b2;
604 v1 >>= 8;
605 result |= ((unsigned64)b << s);
606 s += 8;
608 return result;
612 unsigned64
613 mdmx_pick_op(sim_cpu *cpu,
614 address_word cia,
615 int tf,
616 unsigned64 v1,
617 int vt,
618 MX_fmtsel fmtsel)
620 unsigned64 result = 0;
621 unsigned64 op2;
623 switch (MX_FMT (fmtsel))
625 case mdmx_qh:
626 switch (MX_VT (fmtsel))
628 case sel_elem:
629 op2 = ValueFPR(vt, fmt_mdmx);
630 result = qh_map_pick(cpu, v1, QH_ELEM(op2, fmtsel), tf);
631 break;
632 case sel_vect:
633 result = qh_vector_pick(cpu, v1, ValueFPR(vt, fmt_mdmx), tf);
634 break;
635 case sel_imm:
636 result = qh_map_pick(cpu, v1, vt, tf);
637 break;
639 break;
640 case mdmx_ob:
641 switch (MX_VT (fmtsel))
643 case sel_elem:
644 op2 = ValueFPR(vt, fmt_mdmx);
645 result = ob_map_pick(cpu, v1, OB_ELEM(op2, fmtsel), tf);
646 break;
647 case sel_vect:
648 result = ob_vector_pick(cpu, v1, ValueFPR(vt, fmt_mdmx), tf);
649 break;
650 case sel_imm:
651 result = ob_map_pick(cpu, v1, vt, tf);
652 break;
654 break;
655 default:
656 Unpredictable ();
658 return result;
662 /* Accumulators. */
664 typedef void (*QH_ACC)(signed48 *a, signed16 ts, signed16 tt);
666 static void
667 AccAddAQH(signed48 *a, signed16 ts, signed16 tt)
669 *a += (signed48)ts + (signed48)tt;
672 static void
673 AccAddLQH(signed48 *a, signed16 ts, signed16 tt)
675 *a = (signed48)ts + (signed48)tt;
678 static void
679 AccMulAQH(signed48 *a, signed16 ts, signed16 tt)
681 *a += (signed48)ts * (signed48)tt;
684 static void
685 AccMulLQH(signed48 *a, signed16 ts, signed16 tt)
687 *a = (signed48)ts * (signed48)tt;
690 static void
691 SubMulAQH(signed48 *a, signed16 ts, signed16 tt)
693 *a -= (signed48)ts * (signed48)tt;
696 static void
697 SubMulLQH(signed48 *a, signed16 ts, signed16 tt)
699 *a = -((signed48)ts * (signed48)tt);
702 static void
703 AccSubAQH(signed48 *a, signed16 ts, signed16 tt)
705 *a += (signed48)ts - (signed48)tt;
708 static void
709 AccSubLQH(signed48 *a, signed16 ts, signed16 tt)
711 *a = (signed48)ts - (signed48)tt;
715 typedef void (*OB_ACC)(signed24 *acc, unsigned8 ts, unsigned8 tt);
717 static void
718 AccAddAOB(signed24 *a, unsigned8 ts, unsigned8 tt)
720 *a += (signed24)ts + (signed24)tt;
723 static void
724 AccAddLOB(signed24 *a, unsigned8 ts, unsigned8 tt)
726 *a = (signed24)ts + (signed24)tt;
729 static void
730 AccMulAOB(signed24 *a, unsigned8 ts, unsigned8 tt)
732 *a += (signed24)ts * (signed24)tt;
735 static void
736 AccMulLOB(signed24 *a, unsigned8 ts, unsigned8 tt)
738 *a = (signed24)ts * (signed24)tt;
741 static void
742 SubMulAOB(signed24 *a, unsigned8 ts, unsigned8 tt)
744 *a -= (signed24)ts * (signed24)tt;
747 static void
748 SubMulLOB(signed24 *a, unsigned8 ts, unsigned8 tt)
750 *a = -((signed24)ts * (signed24)tt);
753 static void
754 AccSubAOB(signed24 *a, unsigned8 ts, unsigned8 tt)
756 *a += (signed24)ts - (signed24)tt;
759 static void
760 AccSubLOB(signed24 *a, unsigned8 ts, unsigned8 tt)
762 *a = (signed24)ts - (signed24)tt;
765 static void
766 AccAbsDiffOB(signed24 *a, unsigned8 ts, unsigned8 tt)
768 unsigned8 t = (ts >= tt ? ts - tt : tt - ts);
769 *a += (signed24)t;
773 /* Dispatch tables for operations that update a CPR. */
775 static const QH_ACC qh_acc[] = {
776 AccAddAQH, AccAddAQH, AccMulAQH, AccMulLQH,
777 SubMulAQH, SubMulLQH, AccSubAQH, AccSubLQH,
778 NULL
781 static const OB_ACC ob_acc[] = {
782 AccAddAOB, AccAddLOB, AccMulAOB, AccMulLOB,
783 SubMulAOB, SubMulLOB, AccSubAOB, AccSubLOB,
784 AccAbsDiffOB
788 static void
789 qh_vector_acc(signed48 a[], unsigned64 v1, unsigned64 v2, QH_ACC acc)
791 int i;
792 signed16 h1, h2;
794 for (i = 0; i < 4; i++)
796 h1 = (signed16)(v1 & 0xFFFF); v1 >>= 16;
797 h2 = (signed16)(v2 & 0xFFFF); v2 >>= 16;
798 (*acc)(&a[i], h1, h2);
802 static void
803 qh_map_acc(signed48 a[], unsigned64 v1, signed16 h2, QH_ACC acc)
805 int i;
806 signed16 h1;
808 for (i = 0; i < 4; i++)
810 h1 = (signed16)(v1 & 0xFFFF); v1 >>= 16;
811 (*acc)(&a[i], h1, h2);
815 static void
816 ob_vector_acc(signed24 a[], unsigned64 v1, unsigned64 v2, OB_ACC acc)
818 int i;
819 unsigned8 b1, b2;
821 for (i = 0; i < 8; i++)
823 b1 = v1 & 0xFF; v1 >>= 8;
824 b2 = v2 & 0xFF; v2 >>= 8;
825 (*acc)(&a[i], b1, b2);
829 static void
830 ob_map_acc(signed24 a[], unsigned64 v1, unsigned8 b2, OB_ACC acc)
832 int i;
833 unsigned8 b1;
835 for (i = 0; i < 8; i++)
837 b1 = v1 & 0xFF; v1 >>= 8;
838 (*acc)(&a[i], b1, b2);
843 /* Primary entry for operations that accumulate */
844 void
845 mdmx_acc_op(sim_cpu *cpu,
846 address_word cia,
847 int op,
848 unsigned64 op1,
849 int vt,
850 MX_fmtsel fmtsel)
852 unsigned64 op2;
854 switch (MX_FMT (fmtsel))
856 case mdmx_qh:
857 switch (MX_VT (fmtsel))
859 case sel_elem:
860 op2 = ValueFPR(vt, fmt_mdmx);
861 qh_map_acc(ACC.qh, op1, QH_ELEM(op2, fmtsel), qh_acc[op]);
862 break;
863 case sel_vect:
864 qh_vector_acc(ACC.qh, op1, ValueFPR(vt, fmt_mdmx), qh_acc[op]);
865 break;
866 case sel_imm:
867 qh_map_acc(ACC.qh, op1, vt, qh_acc[op]);
868 break;
870 break;
871 case mdmx_ob:
872 switch (MX_VT (fmtsel))
874 case sel_elem:
875 op2 = ValueFPR(vt, fmt_mdmx);
876 ob_map_acc(ACC.ob, op1, OB_ELEM(op2, fmtsel), ob_acc[op]);
877 break;
878 case sel_vect:
879 ob_vector_acc(ACC.ob, op1, ValueFPR(vt, fmt_mdmx), ob_acc[op]);
880 break;
881 case sel_imm:
882 ob_map_acc(ACC.ob, op1, vt, ob_acc[op]);
883 break;
885 break;
886 default:
887 Unpredictable ();
892 /* Reading and writing accumulator (no conversion). */
894 unsigned64
895 mdmx_rac_op(sim_cpu *cpu,
896 address_word cia,
897 int op,
898 int fmt)
900 unsigned64 result;
901 unsigned int shift;
902 int i;
904 shift = op; /* L = 00, M = 01, H = 10. */
905 result = 0;
907 switch (fmt)
909 case MX_FMT_QH:
910 shift <<= 4; /* 16 bits per element. */
911 for (i = 3; i >= 0; --i)
913 result <<= 16;
914 result |= ((ACC.qh[i] >> shift) & 0xFFFF);
916 break;
917 case MX_FMT_OB:
918 shift <<= 3; /* 8 bits per element. */
919 for (i = 7; i >= 0; --i)
921 result <<= 8;
922 result |= ((ACC.ob[i] >> shift) & 0xFF);
924 break;
925 default:
926 Unpredictable ();
928 return result;
931 void
932 mdmx_wacl(sim_cpu *cpu,
933 address_word cia,
934 int fmt,
935 unsigned64 vs,
936 unsigned64 vt)
938 int i;
940 switch (fmt)
942 case MX_FMT_QH:
943 for (i = 0; i < 4; i++)
945 signed32 s = (signed16)(vs & 0xFFFF);
946 ACC.qh[i] = ((signed48)s << 16) | (vt & 0xFFFF);
947 vs >>= 16; vt >>= 16;
949 break;
950 case MX_FMT_OB:
951 for (i = 0; i < 8; i++)
953 signed16 s = (signed8)(vs & 0xFF);
954 ACC.ob[i] = ((signed24)s << 8) | (vt & 0xFF);
955 vs >>= 8; vt >>= 8;
957 break;
958 default:
959 Unpredictable ();
963 void
964 mdmx_wach(sim_cpu *cpu,
965 address_word cia,
966 int fmt,
967 unsigned64 vs)
969 int i;
971 switch (fmt)
973 case MX_FMT_QH:
974 for (i = 0; i < 4; i++)
976 signed32 s = (signed16)(vs & 0xFFFF);
977 ACC.qh[i] &= ~((signed48)0xFFFF << 32);
978 ACC.qh[i] |= ((signed48)s << 32);
979 vs >>= 16;
981 break;
982 case MX_FMT_OB:
983 for (i = 0; i < 8; i++)
985 ACC.ob[i] &= ~((signed24)0xFF << 16);
986 ACC.ob[i] |= ((signed24)(vs & 0xFF) << 16);
987 vs >>= 8;
989 break;
990 default:
991 Unpredictable ();
996 /* Reading and writing accumulator (rounding conversions).
997 Enumerating function guarantees s >= 0 for QH ops. */
999 typedef signed16 (*QH_ROUND)(signed48 a, signed16 s);
1001 #define QH_BIT(n) ((unsigned48)1 << (n))
1002 #define QH_ONES(n) (((unsigned48)1 << (n))-1)
1004 static signed16
1005 RNASQH(signed48 a, signed16 s)
1007 signed48 t;
1008 signed16 result = 0;
1010 if (s > 48)
1011 result = 0;
1012 else
1014 t = (a >> s);
1015 if ((a & QH_BIT(47)) == 0)
1017 if (s > 0 && ((a >> (s-1)) & 1) == 1)
1018 t++;
1019 if (t > QH_MAX)
1020 t = QH_MAX;
1022 else
1024 if (s > 0 && ((a >> (s-1)) & 1) == 1)
1026 if (s > 1 && ((unsigned48)a & QH_ONES(s-1)) != 0)
1027 t++;
1029 if (t < QH_MIN)
1030 t = QH_MIN;
1032 result = (signed16)t;
1034 return result;
1037 static signed16
1038 RNAUQH(signed48 a, signed16 s)
1040 unsigned48 t;
1041 signed16 result;
1043 if (s > 48)
1044 result = 0;
1045 else if (s == 48)
1046 result = ((unsigned48)a & MASK48) >> 47;
1047 else
1049 t = ((unsigned48)a & MASK48) >> s;
1050 if (s > 0 && ((a >> (s-1)) & 1) == 1)
1051 t++;
1052 if (t > 0xFFFF)
1053 t = 0xFFFF;
1054 result = (signed16)t;
1056 return result;
1059 static signed16
1060 RNESQH(signed48 a, signed16 s)
1062 signed48 t;
1063 signed16 result = 0;
1065 if (s > 47)
1066 result = 0;
1067 else
1069 t = (a >> s);
1070 if (s > 0 && ((a >> (s-1)) & 1) == 1)
1072 if (s == 1 || (a & QH_ONES(s-1)) == 0)
1073 t += t & 1;
1074 else
1075 t += 1;
1077 if ((a & QH_BIT(47)) == 0)
1079 if (t > QH_MAX)
1080 t = QH_MAX;
1082 else
1084 if (t < QH_MIN)
1085 t = QH_MIN;
1087 result = (signed16)t;
1089 return result;
1092 static signed16
1093 RNEUQH(signed48 a, signed16 s)
1095 unsigned48 t;
1096 signed16 result;
1098 if (s > 48)
1099 result = 0;
1100 else if (s == 48)
1101 result = ((unsigned48)a > QH_BIT(47) ? 1 : 0);
1102 else
1104 t = ((unsigned48)a & MASK48) >> s;
1105 if (s > 0 && ((a >> (s-1)) & 1) == 1)
1107 if (s > 1 && (a & QH_ONES(s-1)) != 0)
1108 t++;
1109 else
1110 t += t & 1;
1112 if (t > 0xFFFF)
1113 t = 0xFFFF;
1114 result = (signed16)t;
1116 return result;
1119 static signed16
1120 RZSQH(signed48 a, signed16 s)
1122 signed48 t;
1123 signed16 result = 0;
1125 if (s > 47)
1126 result = 0;
1127 else
1129 t = (a >> s);
1130 if ((a & QH_BIT(47)) == 0)
1132 if (t > QH_MAX)
1133 t = QH_MAX;
1135 else
1137 if (t < QH_MIN)
1138 t = QH_MIN;
1140 result = (signed16)t;
1142 return result;
1145 static signed16
1146 RZUQH(signed48 a, signed16 s)
1148 unsigned48 t;
1149 signed16 result = 0;
1151 if (s > 48)
1152 result = 0;
1153 else if (s == 48)
1154 result = ((unsigned48)a > QH_BIT(47) ? 1 : 0);
1155 else
1157 t = ((unsigned48)a & MASK48) >> s;
1158 if (t > 0xFFFF)
1159 t = 0xFFFF;
1160 result = (signed16)t;
1162 return result;
1166 typedef unsigned8 (*OB_ROUND)(signed24 a, unsigned8 s);
1168 #define OB_BIT(n) ((unsigned24)1 << (n))
1169 #define OB_ONES(n) (((unsigned24)1 << (n))-1)
1171 static unsigned8
1172 RNAUOB(signed24 a, unsigned8 s)
1174 unsigned8 result;
1175 unsigned24 t;
1177 if (s > 24)
1178 result = 0;
1179 else if (s == 24)
1180 result = ((unsigned24)a & MASK24) >> 23;
1181 else
1183 t = ((unsigned24)a & MASK24) >> s;
1184 if (s > 0 && ((a >> (s-1)) & 1) == 1)
1185 t ++;
1186 result = OB_CLAMP(t);
1188 return result;
1191 static unsigned8
1192 RNEUOB(signed24 a, unsigned8 s)
1194 unsigned8 result;
1195 unsigned24 t;
1197 if (s > 24)
1198 result = 0;
1199 else if (s == 24)
1200 result = (((unsigned24)a & MASK24) > OB_BIT(23) ? 1 : 0);
1201 else
1203 t = ((unsigned24)a & MASK24) >> s;
1204 if (s > 0 && ((a >> (s-1)) & 1) == 1)
1206 if (s > 1 && (a & OB_ONES(s-1)) != 0)
1207 t++;
1208 else
1209 t += t & 1;
1211 result = OB_CLAMP(t);
1213 return result;
1216 static unsigned8
1217 RZUOB(signed24 a, unsigned8 s)
1219 unsigned8 result;
1220 unsigned24 t;
1222 if (s >= 24)
1223 result = 0;
1224 else
1226 t = ((unsigned24)a & MASK24) >> s;
1227 result = OB_CLAMP(t);
1229 return result;
1233 static const QH_ROUND qh_round[] = {
1234 RNASQH, RNAUQH, RNESQH, RNEUQH, RZSQH, RZUQH
1237 static const OB_ROUND ob_round[] = {
1238 NULL, RNAUOB, NULL, RNEUOB, NULL, RZUOB
1242 static unsigned64
1243 qh_vector_round(sim_cpu *cpu, address_word cia, unsigned64 v2, QH_ROUND round)
1245 unsigned64 result = 0;
1246 int i, s;
1247 signed16 h, h2;
1249 s = 0;
1250 for (i = 0; i < 4; i++)
1252 h2 = (signed16)(v2 & 0xFFFF);
1253 if (h2 >= 0)
1254 h = (*round)(ACC.qh[i], h2);
1255 else
1257 UnpredictableResult ();
1258 h = 0xdead;
1260 v2 >>= 16;
1261 result |= ((unsigned64)((unsigned16)h) << s);
1262 s += 16;
1264 return result;
1267 static unsigned64
1268 qh_map_round(sim_cpu *cpu, address_word cia, signed16 h2, QH_ROUND round)
1270 unsigned64 result = 0;
1271 int i, s;
1272 signed16 h;
1274 s = 0;
1275 for (i = 0; i < 4; i++)
1277 if (h2 >= 0)
1278 h = (*round)(ACC.qh[i], h2);
1279 else
1281 UnpredictableResult ();
1282 h = 0xdead;
1284 result |= ((unsigned64)((unsigned16)h) << s);
1285 s += 16;
1287 return result;
1290 static unsigned64
1291 ob_vector_round(sim_cpu *cpu, address_word cia, unsigned64 v2, OB_ROUND round)
1293 unsigned64 result = 0;
1294 int i, s;
1295 unsigned8 b, b2;
1297 s = 0;
1298 for (i = 0; i < 8; i++)
1300 b2 = v2 & 0xFF; v2 >>= 8;
1301 b = (*round)(ACC.ob[i], b2);
1302 result |= ((unsigned64)b << s);
1303 s += 8;
1305 return result;
1308 static unsigned64
1309 ob_map_round(sim_cpu *cpu, address_word cia, unsigned8 b2, OB_ROUND round)
1311 unsigned64 result = 0;
1312 int i, s;
1313 unsigned8 b;
1315 s = 0;
1316 for (i = 0; i < 8; i++)
1318 b = (*round)(ACC.ob[i], b2);
1319 result |= ((unsigned64)b << s);
1320 s += 8;
1322 return result;
1326 unsigned64
1327 mdmx_round_op(sim_cpu *cpu,
1328 address_word cia,
1329 int rm,
1330 int vt,
1331 MX_fmtsel fmtsel)
1333 unsigned64 op2;
1334 unsigned64 result = 0;
1336 switch (MX_FMT (fmtsel))
1338 case mdmx_qh:
1339 switch (MX_VT (fmtsel))
1341 case sel_elem:
1342 op2 = ValueFPR(vt, fmt_mdmx);
1343 result = qh_map_round(cpu, cia, QH_ELEM(op2, fmtsel), qh_round[rm]);
1344 break;
1345 case sel_vect:
1346 op2 = ValueFPR(vt, fmt_mdmx);
1347 result = qh_vector_round(cpu, cia, op2, qh_round[rm]);
1348 break;
1349 case sel_imm:
1350 result = qh_map_round(cpu, cia, vt, qh_round[rm]);
1351 break;
1353 break;
1354 case mdmx_ob:
1355 switch (MX_VT (fmtsel))
1357 case sel_elem:
1358 op2 = ValueFPR(vt, fmt_mdmx);
1359 result = ob_map_round(cpu, cia, OB_ELEM(op2, fmtsel), ob_round[rm]);
1360 break;
1361 case sel_vect:
1362 op2 = ValueFPR(vt, fmt_mdmx);
1363 result = ob_vector_round(cpu, cia, op2, ob_round[rm]);
1364 break;
1365 case sel_imm:
1366 result = ob_map_round(cpu, cia, vt, ob_round[rm]);
1367 break;
1369 break;
1370 default:
1371 Unpredictable ();
1374 return result;
1378 /* Shuffle operation. */
1380 typedef struct {
1381 enum {vs, ss, vt} source;
1382 unsigned int index;
1383 } sh_map;
1385 static const sh_map ob_shuffle[][8] = {
1386 /* MDMX 2.0 encodings (3-4, 6-7). */
1387 /* vr5400 encoding (5), otherwise. */
1388 { }, /* RSVD */
1389 {{vt,4}, {vs,4}, {vt,5}, {vs,5}, {vt,6}, {vs,6}, {vt,7}, {vs,7}}, /* RSVD */
1390 {{vt,0}, {vs,0}, {vt,1}, {vs,1}, {vt,2}, {vs,2}, {vt,3}, {vs,3}}, /* RSVD */
1391 {{vs,0}, {ss,0}, {vs,1}, {ss,1}, {vs,2}, {ss,2}, {vs,3}, {ss,3}}, /* upsl */
1392 {{vt,1}, {vt,3}, {vt,5}, {vt,7}, {vs,1}, {vs,3}, {vs,5}, {vs,7}}, /* pach */
1393 {{vt,0}, {vt,2}, {vt,4}, {vt,6}, {vs,0}, {vs,2}, {vs,4}, {vs,6}}, /* pacl */
1394 {{vt,4}, {vs,4}, {vt,5}, {vs,5}, {vt,6}, {vs,6}, {vt,7}, {vs,7}}, /* mixh */
1395 {{vt,0}, {vs,0}, {vt,1}, {vs,1}, {vt,2}, {vs,2}, {vt,3}, {vs,3}} /* mixl */
1398 static const sh_map qh_shuffle[][4] = {
1399 {{vt,2}, {vs,2}, {vt,3}, {vs,3}}, /* mixh */
1400 {{vt,0}, {vs,0}, {vt,1}, {vs,1}}, /* mixl */
1401 {{vt,1}, {vt,3}, {vs,1}, {vs,3}}, /* pach */
1402 { }, /* RSVD */
1403 {{vt,1}, {vs,0}, {vt,3}, {vs,2}}, /* bfla */
1404 { }, /* RSVD */
1405 {{vt,2}, {vt,3}, {vs,2}, {vs,3}}, /* repa */
1406 {{vt,0}, {vt,1}, {vs,0}, {vs,1}} /* repb */
1410 unsigned64
1411 mdmx_shuffle(sim_cpu *cpu,
1412 address_word cia,
1413 int shop,
1414 unsigned64 op1,
1415 unsigned64 op2)
1417 unsigned64 result = 0;
1418 int i, s;
1419 int op;
1421 if ((shop & 0x3) == 0x1) /* QH format. */
1423 op = shop >> 2;
1424 s = 0;
1425 for (i = 0; i < 4; i++)
1427 unsigned64 v;
1429 switch (qh_shuffle[op][i].source)
1431 case vs:
1432 v = op1;
1433 break;
1434 case vt:
1435 v = op2;
1436 break;
1437 default:
1438 Unpredictable ();
1439 v = 0;
1441 result |= (((v >> 16*qh_shuffle[op][i].index) & 0xFFFF) << s);
1442 s += 16;
1445 else if ((shop & 0x1) == 0x0) /* OB format. */
1447 op = shop >> 1;
1448 s = 0;
1449 for (i = 0; i < 8; i++)
1451 unsigned8 b;
1452 unsigned int ishift = 8*ob_shuffle[op][i].index;
1454 switch (ob_shuffle[op][i].source)
1456 case vs:
1457 b = (op1 >> ishift) & 0xFF;
1458 break;
1459 case ss:
1460 b = ((op1 >> ishift) & 0x80) ? 0xFF : 0;
1461 break;
1462 case vt:
1463 b = (op2 >> ishift) & 0xFF;
1464 break;
1465 default:
1466 Unpredictable ();
1467 b = 0;
1469 result |= ((unsigned64)b << s);
1470 s += 8;
1473 else
1474 Unpredictable ();
1476 return result;