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