OSDN Git Service

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