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