Home | History | Annotate | Line # | Download | only in mips
mdmx.c revision 1.1.1.2
      1 /* Simulation code for the MIPS MDMX ASE.
      2    Copyright (C) 2002-2013 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 }
   1477