Home | History | Annotate | Line # | Download | only in bfin
bfin-sim.c revision 1.1
      1  1.1  christos /* Simulator for Analog Devices Blackfin processors.
      2  1.1  christos 
      3  1.1  christos    Copyright (C) 2005-2011 Free Software Foundation, Inc.
      4  1.1  christos    Contributed by Analog Devices, Inc.
      5  1.1  christos 
      6  1.1  christos    This file is part of simulators.
      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.1  christos #include "config.h"
     22  1.1  christos 
     23  1.1  christos #include <stdio.h>
     24  1.1  christos #include <stdlib.h>
     25  1.1  christos #include <string.h>
     26  1.1  christos #include <inttypes.h>
     27  1.1  christos 
     28  1.1  christos #include "opcode/bfin.h"
     29  1.1  christos #include "sim-main.h"
     30  1.1  christos #include "dv-bfin_cec.h"
     31  1.1  christos #include "dv-bfin_mmu.h"
     32  1.1  christos 
     33  1.1  christos #define HOST_LONG_WORD_SIZE (sizeof (long) * 8)
     34  1.1  christos 
     35  1.1  christos #define SIGNEXTEND(v, n) \
     36  1.1  christos   (((bs32)(v) << (HOST_LONG_WORD_SIZE - (n))) >> (HOST_LONG_WORD_SIZE - (n)))
     37  1.1  christos 
     38  1.1  christos static __attribute__ ((noreturn)) void
     39  1.1  christos illegal_instruction (SIM_CPU *cpu)
     40  1.1  christos {
     41  1.1  christos   TRACE_INSN (cpu, "ILLEGAL INSTRUCTION");
     42  1.1  christos   while (1)
     43  1.1  christos     cec_exception (cpu, VEC_UNDEF_I);
     44  1.1  christos }
     45  1.1  christos 
     46  1.1  christos static __attribute__ ((noreturn)) void
     47  1.1  christos illegal_instruction_combination (SIM_CPU *cpu)
     48  1.1  christos {
     49  1.1  christos   TRACE_INSN (cpu, "ILLEGAL INSTRUCTION COMBINATION");
     50  1.1  christos   while (1)
     51  1.1  christos     cec_exception (cpu, VEC_ILGAL_I);
     52  1.1  christos }
     53  1.1  christos 
     54  1.1  christos static __attribute__ ((noreturn)) void
     55  1.1  christos unhandled_instruction (SIM_CPU *cpu, const char *insn)
     56  1.1  christos {
     57  1.1  christos   SIM_DESC sd = CPU_STATE (cpu);
     58  1.1  christos   bu16 iw0, iw1;
     59  1.1  christos   bu32 iw2;
     60  1.1  christos 
     61  1.1  christos   TRACE_EVENTS (cpu, "unhandled instruction");
     62  1.1  christos 
     63  1.1  christos   iw0 = IFETCH (PCREG);
     64  1.1  christos   iw1 = IFETCH (PCREG + 2);
     65  1.1  christos   iw2 = ((bu32)iw0 << 16) | iw1;
     66  1.1  christos 
     67  1.1  christos   sim_io_eprintf (sd, "Unhandled instruction at 0x%08x (%s opcode 0x", PCREG, insn);
     68  1.1  christos   if ((iw0 & 0xc000) == 0xc000)
     69  1.1  christos     sim_io_eprintf (sd, "%08x", iw2);
     70  1.1  christos   else
     71  1.1  christos     sim_io_eprintf (sd, "%04x", iw0);
     72  1.1  christos 
     73  1.1  christos   sim_io_eprintf (sd, ") ... aborting\n");
     74  1.1  christos 
     75  1.1  christos   illegal_instruction (cpu);
     76  1.1  christos }
     77  1.1  christos 
     78  1.1  christos static const char * const astat_names[] =
     79  1.1  christos {
     80  1.1  christos   [ 0] = "AZ",
     81  1.1  christos   [ 1] = "AN",
     82  1.1  christos   [ 2] = "AC0_COPY",
     83  1.1  christos   [ 3] = "V_COPY",
     84  1.1  christos   [ 4] = "ASTAT_4",
     85  1.1  christos   [ 5] = "CC",
     86  1.1  christos   [ 6] = "AQ",
     87  1.1  christos   [ 7] = "ASTAT_7",
     88  1.1  christos   [ 8] = "RND_MOD",
     89  1.1  christos   [ 9] = "ASTAT_9",
     90  1.1  christos   [10] = "ASTAT_10",
     91  1.1  christos   [11] = "ASTAT_11",
     92  1.1  christos   [12] = "AC0",
     93  1.1  christos   [13] = "AC1",
     94  1.1  christos   [14] = "ASTAT_14",
     95  1.1  christos   [15] = "ASTAT_15",
     96  1.1  christos   [16] = "AV0",
     97  1.1  christos   [17] = "AV0S",
     98  1.1  christos   [18] = "AV1",
     99  1.1  christos   [19] = "AV1S",
    100  1.1  christos   [20] = "ASTAT_20",
    101  1.1  christos   [21] = "ASTAT_21",
    102  1.1  christos   [22] = "ASTAT_22",
    103  1.1  christos   [23] = "ASTAT_23",
    104  1.1  christos   [24] = "V",
    105  1.1  christos   [25] = "VS",
    106  1.1  christos   [26] = "ASTAT_26",
    107  1.1  christos   [27] = "ASTAT_27",
    108  1.1  christos   [28] = "ASTAT_28",
    109  1.1  christos   [29] = "ASTAT_29",
    110  1.1  christos   [30] = "ASTAT_30",
    111  1.1  christos   [31] = "ASTAT_31",
    112  1.1  christos };
    113  1.1  christos 
    114  1.1  christos typedef enum
    115  1.1  christos {
    116  1.1  christos   c_0, c_1, c_4, c_2, c_uimm2, c_uimm3, c_imm3, c_pcrel4,
    117  1.1  christos   c_imm4, c_uimm4s4, c_uimm4s4d, c_uimm4, c_uimm4s2, c_negimm5s4, c_imm5,
    118  1.1  christos   c_imm5d, c_uimm5, c_imm6, c_imm7, c_imm7d, c_imm8, c_uimm8, c_pcrel8,
    119  1.1  christos   c_uimm8s4, c_pcrel8s4, c_lppcrel10, c_pcrel10, c_pcrel12, c_imm16s4,
    120  1.1  christos   c_luimm16, c_imm16, c_imm16d, c_huimm16, c_rimm16, c_imm16s2, c_uimm16s4,
    121  1.1  christos   c_uimm16s4d, c_uimm16, c_pcrel24, c_uimm32, c_imm32, c_huimm32, c_huimm32e,
    122  1.1  christos } const_forms_t;
    123  1.1  christos 
    124  1.1  christos static const struct
    125  1.1  christos {
    126  1.1  christos   const char *name;
    127  1.1  christos   const int nbits;
    128  1.1  christos   const char reloc;
    129  1.1  christos   const char issigned;
    130  1.1  christos   const char pcrel;
    131  1.1  christos   const char scale;
    132  1.1  christos   const char offset;
    133  1.1  christos   const char negative;
    134  1.1  christos   const char positive;
    135  1.1  christos   const char decimal;
    136  1.1  christos   const char leading;
    137  1.1  christos   const char exact;
    138  1.1  christos } constant_formats[] =
    139  1.1  christos {
    140  1.1  christos   { "0",          0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
    141  1.1  christos   { "1",          0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
    142  1.1  christos   { "4",          0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
    143  1.1  christos   { "2",          0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
    144  1.1  christos   { "uimm2",      2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    145  1.1  christos   { "uimm3",      3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    146  1.1  christos   { "imm3",       3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
    147  1.1  christos   { "pcrel4",     4, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0},
    148  1.1  christos   { "imm4",       4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
    149  1.1  christos   { "uimm4s4",    4, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0},
    150  1.1  christos   { "uimm4s4d",   4, 0, 0, 0, 2, 0, 0, 1, 1, 0, 0},
    151  1.1  christos   { "uimm4",      4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    152  1.1  christos   { "uimm4s2",    4, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0},
    153  1.1  christos   { "negimm5s4",  5, 0, 1, 0, 2, 0, 1, 0, 0, 0, 0},
    154  1.1  christos   { "imm5",       5, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
    155  1.1  christos   { "imm5d",      5, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0},
    156  1.1  christos   { "uimm5",      5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    157  1.1  christos   { "imm6",       6, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
    158  1.1  christos   { "imm7",       7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
    159  1.1  christos   { "imm7d",      7, 0, 1, 0, 0, 0, 0, 0, 1, 3, 0},
    160  1.1  christos   { "imm8",       8, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
    161  1.1  christos   { "uimm8",      8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    162  1.1  christos   { "pcrel8",     8, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0},
    163  1.1  christos   { "uimm8s4",    8, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0},
    164  1.1  christos   { "pcrel8s4",   8, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0},
    165  1.1  christos   { "lppcrel10", 10, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0},
    166  1.1  christos   { "pcrel10",   10, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
    167  1.1  christos   { "pcrel12",   12, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
    168  1.1  christos   { "imm16s4",   16, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0},
    169  1.1  christos   { "luimm16",   16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    170  1.1  christos   { "imm16",     16, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
    171  1.1  christos   { "imm16d",    16, 0, 1, 0, 0, 0, 0, 0, 1, 3, 0},
    172  1.1  christos   { "huimm16",   16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    173  1.1  christos   { "rimm16",    16, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0},
    174  1.1  christos   { "imm16s2",   16, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0},
    175  1.1  christos   { "uimm16s4",  16, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0},
    176  1.1  christos   { "uimm16s4d", 16, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0},
    177  1.1  christos   { "uimm16",    16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    178  1.1  christos   { "pcrel24",   24, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
    179  1.1  christos   { "uimm32",    32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    180  1.1  christos   { "imm32",     32, 0, 1, 0, 0, 0, 0, 0, 1, 3, 0},
    181  1.1  christos   { "huimm32",   32, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    182  1.1  christos   { "huimm32e",  32, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
    183  1.1  christos };
    184  1.1  christos 
    185  1.1  christos static const char *
    186  1.1  christos fmtconst_str (const_forms_t cf, bs32 x, bu32 pc)
    187  1.1  christos {
    188  1.1  christos   static char buf[60];
    189  1.1  christos 
    190  1.1  christos   if (constant_formats[cf].reloc)
    191  1.1  christos     {
    192  1.1  christos       bu32 ea = (((constant_formats[cf].pcrel ? SIGNEXTEND (x, constant_formats[cf].nbits)
    193  1.1  christos 		      : x) + constant_formats[cf].offset) << constant_formats[cf].scale);
    194  1.1  christos       if (constant_formats[cf].pcrel)
    195  1.1  christos 	ea += pc;
    196  1.1  christos      /*if (outf->symbol_at_address_func (ea, outf) || !constant_formats[cf].exact)
    197  1.1  christos        {
    198  1.1  christos 	  outf->print_address_func (ea, outf);
    199  1.1  christos 	  return "";
    200  1.1  christos        }
    201  1.1  christos      else*/
    202  1.1  christos        {
    203  1.1  christos 	  sprintf (buf, "%#x", x);
    204  1.1  christos 	  return buf;
    205  1.1  christos        }
    206  1.1  christos     }
    207  1.1  christos 
    208  1.1  christos   /* Negative constants have an implied sign bit.  */
    209  1.1  christos   if (constant_formats[cf].negative)
    210  1.1  christos     {
    211  1.1  christos       int nb = constant_formats[cf].nbits + 1;
    212  1.1  christos 
    213  1.1  christos       x = x | (1 << constant_formats[cf].nbits);
    214  1.1  christos       x = SIGNEXTEND (x, nb);
    215  1.1  christos     }
    216  1.1  christos   else
    217  1.1  christos     x = constant_formats[cf].issigned ? SIGNEXTEND (x, constant_formats[cf].nbits) : x;
    218  1.1  christos 
    219  1.1  christos   if (constant_formats[cf].offset)
    220  1.1  christos     x += constant_formats[cf].offset;
    221  1.1  christos 
    222  1.1  christos   if (constant_formats[cf].scale)
    223  1.1  christos     x <<= constant_formats[cf].scale;
    224  1.1  christos 
    225  1.1  christos   if (constant_formats[cf].decimal)
    226  1.1  christos     {
    227  1.1  christos       if (constant_formats[cf].leading)
    228  1.1  christos 	{
    229  1.1  christos 	  char ps[10];
    230  1.1  christos 	  sprintf (ps, "%%%ii", constant_formats[cf].leading);
    231  1.1  christos 	  sprintf (buf, ps, x);
    232  1.1  christos 	}
    233  1.1  christos       else
    234  1.1  christos 	sprintf (buf, "%i", x);
    235  1.1  christos     }
    236  1.1  christos   else
    237  1.1  christos     {
    238  1.1  christos       if (constant_formats[cf].issigned && x < 0)
    239  1.1  christos 	sprintf (buf, "-0x%x", abs (x));
    240  1.1  christos       else
    241  1.1  christos 	sprintf (buf, "0x%x", x);
    242  1.1  christos     }
    243  1.1  christos 
    244  1.1  christos   return buf;
    245  1.1  christos }
    246  1.1  christos 
    247  1.1  christos static bu32
    248  1.1  christos fmtconst_val (const_forms_t cf, bu32 x, bu32 pc)
    249  1.1  christos {
    250  1.1  christos   if (0 && constant_formats[cf].reloc)
    251  1.1  christos     {
    252  1.1  christos       bu32 ea = (((constant_formats[cf].pcrel
    253  1.1  christos 		   ? (bu32)SIGNEXTEND (x, constant_formats[cf].nbits)
    254  1.1  christos 		   : x) + constant_formats[cf].offset)
    255  1.1  christos 		 << constant_formats[cf].scale);
    256  1.1  christos       if (constant_formats[cf].pcrel)
    257  1.1  christos 	ea += pc;
    258  1.1  christos 
    259  1.1  christos       return ea;
    260  1.1  christos     }
    261  1.1  christos 
    262  1.1  christos   /* Negative constants have an implied sign bit.  */
    263  1.1  christos   if (constant_formats[cf].negative)
    264  1.1  christos     {
    265  1.1  christos       int nb = constant_formats[cf].nbits + 1;
    266  1.1  christos       x = x | (1 << constant_formats[cf].nbits);
    267  1.1  christos       x = SIGNEXTEND (x, nb);
    268  1.1  christos     }
    269  1.1  christos   else if (constant_formats[cf].issigned)
    270  1.1  christos     x = SIGNEXTEND (x, constant_formats[cf].nbits);
    271  1.1  christos 
    272  1.1  christos   x += constant_formats[cf].offset;
    273  1.1  christos   x <<= constant_formats[cf].scale;
    274  1.1  christos 
    275  1.1  christos   return x;
    276  1.1  christos }
    277  1.1  christos 
    278  1.1  christos #define uimm16s4(x)	fmtconst_val (c_uimm16s4, x, 0)
    279  1.1  christos #define uimm16s4_str(x)	fmtconst_str (c_uimm16s4, x, 0)
    280  1.1  christos #define uimm16s4d(x)	fmtconst_val (c_uimm16s4d, x, 0)
    281  1.1  christos #define pcrel4(x)	fmtconst_val (c_pcrel4, x, pc)
    282  1.1  christos #define pcrel8(x)	fmtconst_val (c_pcrel8, x, pc)
    283  1.1  christos #define pcrel8s4(x)	fmtconst_val (c_pcrel8s4, x, pc)
    284  1.1  christos #define pcrel10(x)	fmtconst_val (c_pcrel10, x, pc)
    285  1.1  christos #define pcrel12(x)	fmtconst_val (c_pcrel12, x, pc)
    286  1.1  christos #define negimm5s4(x)	fmtconst_val (c_negimm5s4, x, 0)
    287  1.1  christos #define negimm5s4_str(x)	fmtconst_str (c_negimm5s4, x, 0)
    288  1.1  christos #define rimm16(x)	fmtconst_val (c_rimm16, x, 0)
    289  1.1  christos #define huimm16(x)	fmtconst_val (c_huimm16, x, 0)
    290  1.1  christos #define imm16(x)	fmtconst_val (c_imm16, x, 0)
    291  1.1  christos #define imm16_str(x)	fmtconst_str (c_imm16, x, 0)
    292  1.1  christos #define imm16d(x)	fmtconst_val (c_imm16d, x, 0)
    293  1.1  christos #define uimm2(x)	fmtconst_val (c_uimm2, x, 0)
    294  1.1  christos #define uimm3(x)	fmtconst_val (c_uimm3, x, 0)
    295  1.1  christos #define uimm3_str(x)	fmtconst_str (c_uimm3, x, 0)
    296  1.1  christos #define luimm16(x)	fmtconst_val (c_luimm16, x, 0)
    297  1.1  christos #define luimm16_str(x)	fmtconst_str (c_luimm16, x, 0)
    298  1.1  christos #define uimm4(x)	fmtconst_val (c_uimm4, x, 0)
    299  1.1  christos #define uimm4_str(x)	fmtconst_str (c_uimm4, x, 0)
    300  1.1  christos #define uimm5(x)	fmtconst_val (c_uimm5, x, 0)
    301  1.1  christos #define uimm5_str(x)	fmtconst_str (c_uimm5, x, 0)
    302  1.1  christos #define imm16s2(x)	fmtconst_val (c_imm16s2, x, 0)
    303  1.1  christos #define imm16s2_str(x)	fmtconst_str (c_imm16s2, x, 0)
    304  1.1  christos #define uimm8(x)	fmtconst_val (c_uimm8, x, 0)
    305  1.1  christos #define imm16s4(x)	fmtconst_val (c_imm16s4, x, 0)
    306  1.1  christos #define imm16s4_str(x)	fmtconst_str (c_imm16s4, x, 0)
    307  1.1  christos #define uimm4s2(x)	fmtconst_val (c_uimm4s2, x, 0)
    308  1.1  christos #define uimm4s2_str(x)	fmtconst_str (c_uimm4s2, x, 0)
    309  1.1  christos #define uimm4s4(x)	fmtconst_val (c_uimm4s4, x, 0)
    310  1.1  christos #define uimm4s4_str(x)	fmtconst_str (c_uimm4s4, x, 0)
    311  1.1  christos #define uimm4s4d(x)	fmtconst_val (c_uimm4s4d, x, 0)
    312  1.1  christos #define lppcrel10(x)	fmtconst_val (c_lppcrel10, x, pc)
    313  1.1  christos #define imm3(x)		fmtconst_val (c_imm3, x, 0)
    314  1.1  christos #define imm3_str(x)	fmtconst_str (c_imm3, x, 0)
    315  1.1  christos #define imm4(x)		fmtconst_val (c_imm4, x, 0)
    316  1.1  christos #define uimm8s4(x)	fmtconst_val (c_uimm8s4, x, 0)
    317  1.1  christos #define imm5(x)		fmtconst_val (c_imm5, x, 0)
    318  1.1  christos #define imm5d(x)	fmtconst_val (c_imm5d, x, 0)
    319  1.1  christos #define imm6(x)		fmtconst_val (c_imm6, x, 0)
    320  1.1  christos #define imm7(x)		fmtconst_val (c_imm7, x, 0)
    321  1.1  christos #define imm7_str(x)	fmtconst_str (c_imm7, x, 0)
    322  1.1  christos #define imm7d(x)	fmtconst_val (c_imm7d, x, 0)
    323  1.1  christos #define imm8(x)		fmtconst_val (c_imm8, x, 0)
    324  1.1  christos #define pcrel24(x)	fmtconst_val (c_pcrel24, x, pc)
    325  1.1  christos #define pcrel24_str(x)	fmtconst_str (c_pcrel24, x, pc)
    326  1.1  christos #define uimm16(x)	fmtconst_val (c_uimm16, x, 0)
    327  1.1  christos #define uimm32(x)	fmtconst_val (c_uimm32, x, 0)
    328  1.1  christos #define imm32(x)	fmtconst_val (c_imm32, x, 0)
    329  1.1  christos #define huimm32(x)	fmtconst_val (c_huimm32, x, 0)
    330  1.1  christos #define huimm32e(x)	fmtconst_val (c_huimm32e, x, 0)
    331  1.1  christos 
    332  1.1  christos /* Table C-4. Core Register Encoding Map.  */
    333  1.1  christos const char * const greg_names[] =
    334  1.1  christos {
    335  1.1  christos   "R0",    "R1",      "R2",     "R3",    "R4",    "R5",    "R6",     "R7",
    336  1.1  christos   "P0",    "P1",      "P2",     "P3",    "P4",    "P5",    "SP",     "FP",
    337  1.1  christos   "I0",    "I1",      "I2",     "I3",    "M0",    "M1",    "M2",     "M3",
    338  1.1  christos   "B0",    "B1",      "B2",     "B3",    "L0",    "L1",    "L2",     "L3",
    339  1.1  christos   "A0.X",  "A0.W",    "A1.X",   "A1.W",  "<res>", "<res>", "ASTAT",  "RETS",
    340  1.1  christos   "<res>", "<res>",   "<res>",  "<res>", "<res>", "<res>", "<res>",  "<res>",
    341  1.1  christos   "LC0",   "LT0",     "LB0",    "LC1",   "LT1",   "LB1",   "CYCLES", "CYCLES2",
    342  1.1  christos   "USP",   "SEQSTAT", "SYSCFG", "RETI",  "RETX",  "RETN",  "RETE",   "EMUDAT",
    343  1.1  christos };
    344  1.1  christos static const char *
    345  1.1  christos get_allreg_name (int grp, int reg)
    346  1.1  christos {
    347  1.1  christos   return greg_names[(grp << 3) | reg];
    348  1.1  christos }
    349  1.1  christos static const char *
    350  1.1  christos get_preg_name (int reg)
    351  1.1  christos {
    352  1.1  christos   return get_allreg_name (1, reg);
    353  1.1  christos }
    354  1.1  christos 
    355  1.1  christos static bool
    356  1.1  christos reg_is_reserved (int grp, int reg)
    357  1.1  christos {
    358  1.1  christos   return (grp == 4 && (reg == 4 || reg == 5)) || (grp == 5);
    359  1.1  christos }
    360  1.1  christos 
    361  1.1  christos static bu32 *
    362  1.1  christos get_allreg (SIM_CPU *cpu, int grp, int reg)
    363  1.1  christos {
    364  1.1  christos   int fullreg = (grp << 3) | reg;
    365  1.1  christos   /* REG_R0, REG_R1, REG_R2, REG_R3, REG_R4, REG_R5, REG_R6, REG_R7,
    366  1.1  christos      REG_P0, REG_P1, REG_P2, REG_P3, REG_P4, REG_P5, REG_SP, REG_FP,
    367  1.1  christos      REG_I0, REG_I1, REG_I2, REG_I3, REG_M0, REG_M1, REG_M2, REG_M3,
    368  1.1  christos      REG_B0, REG_B1, REG_B2, REG_B3, REG_L0, REG_L1, REG_L2, REG_L3,
    369  1.1  christos      REG_A0x, REG_A0w, REG_A1x, REG_A1w, , , REG_ASTAT, REG_RETS,
    370  1.1  christos      , , , , , , , ,
    371  1.1  christos      REG_LC0, REG_LT0, REG_LB0, REG_LC1, REG_LT1, REG_LB1, REG_CYCLES,
    372  1.1  christos      REG_CYCLES2,
    373  1.1  christos      REG_USP, REG_SEQSTAT, REG_SYSCFG, REG_RETI, REG_RETX, REG_RETN, REG_RETE,
    374  1.1  christos      REG_LASTREG  */
    375  1.1  christos   switch (fullreg >> 2)
    376  1.1  christos     {
    377  1.1  christos     case 0: case 1: return &DREG (reg);
    378  1.1  christos     case 2: case 3: return &PREG (reg);
    379  1.1  christos     case 4: return &IREG (reg & 3);
    380  1.1  christos     case 5: return &MREG (reg & 3);
    381  1.1  christos     case 6: return &BREG (reg & 3);
    382  1.1  christos     case 7: return &LREG (reg & 3);
    383  1.1  christos     default:
    384  1.1  christos       switch (fullreg)
    385  1.1  christos 	{
    386  1.1  christos 	case 32: return &AXREG (0);
    387  1.1  christos 	case 33: return &AWREG (0);
    388  1.1  christos 	case 34: return &AXREG (1);
    389  1.1  christos 	case 35: return &AWREG (1);
    390  1.1  christos 	case 39: return &RETSREG;
    391  1.1  christos 	case 48: return &LCREG (0);
    392  1.1  christos 	case 49: return &LTREG (0);
    393  1.1  christos 	case 50: return &LBREG (0);
    394  1.1  christos 	case 51: return &LCREG (1);
    395  1.1  christos 	case 52: return &LTREG (1);
    396  1.1  christos 	case 53: return &LBREG (1);
    397  1.1  christos 	case 54: return &CYCLESREG;
    398  1.1  christos 	case 55: return &CYCLES2REG;
    399  1.1  christos 	case 56: return &USPREG;
    400  1.1  christos 	case 57: return &SEQSTATREG;
    401  1.1  christos 	case 58: return &SYSCFGREG;
    402  1.1  christos 	case 59: return &RETIREG;
    403  1.1  christos 	case 60: return &RETXREG;
    404  1.1  christos 	case 61: return &RETNREG;
    405  1.1  christos 	case 62: return &RETEREG;
    406  1.1  christos 	case 63: return &EMUDAT_INREG;
    407  1.1  christos 	}
    408  1.1  christos       illegal_instruction (cpu);
    409  1.1  christos     }
    410  1.1  christos }
    411  1.1  christos 
    412  1.1  christos static const char *
    413  1.1  christos amod0 (int s0, int x0)
    414  1.1  christos {
    415  1.1  christos   static const char * const mod0[] = {
    416  1.1  christos     "", " (S)", " (CO)", " (SCO)",
    417  1.1  christos   };
    418  1.1  christos   int i = s0 + (x0 << 1);
    419  1.1  christos 
    420  1.1  christos   if (i < ARRAY_SIZE (mod0))
    421  1.1  christos     return mod0[i];
    422  1.1  christos   else
    423  1.1  christos     return "";
    424  1.1  christos }
    425  1.1  christos 
    426  1.1  christos static const char *
    427  1.1  christos amod0amod2 (int s0, int x0, int aop0)
    428  1.1  christos {
    429  1.1  christos   static const char * const mod02[] = {
    430  1.1  christos     "", " (S)", " (CO)", " (SCO)",
    431  1.1  christos     "", "", "", "",
    432  1.1  christos     " (ASR)", " (S, ASR)", " (CO, ASR)", " (SCO, ASR)",
    433  1.1  christos     " (ASL)", " (S, ASL)", " (CO, ASL)", " (SCO, ASL)",
    434  1.1  christos   };
    435  1.1  christos   int i = s0 + (x0 << 1) + (aop0 << 2);
    436  1.1  christos 
    437  1.1  christos   if (i < ARRAY_SIZE (mod02))
    438  1.1  christos     return mod02[i];
    439  1.1  christos   else
    440  1.1  christos     return "";
    441  1.1  christos }
    442  1.1  christos 
    443  1.1  christos static const char *
    444  1.1  christos amod1 (int s0, int x0)
    445  1.1  christos {
    446  1.1  christos   static const char * const mod1[] = {
    447  1.1  christos     " (NS)", " (S)",
    448  1.1  christos   };
    449  1.1  christos   int i = s0 + (x0 << 1);
    450  1.1  christos 
    451  1.1  christos   if (i < ARRAY_SIZE (mod1))
    452  1.1  christos     return mod1[i];
    453  1.1  christos   else
    454  1.1  christos     return "";
    455  1.1  christos }
    456  1.1  christos 
    457  1.1  christos static const char *
    458  1.1  christos mac_optmode (int mmod, int MM)
    459  1.1  christos {
    460  1.1  christos   static const char * const omode[] = {
    461  1.1  christos     [(M_S2RND << 1) + 0] = " (S2RND)",
    462  1.1  christos     [(M_T     << 1) + 0] = " (T)",
    463  1.1  christos     [(M_W32   << 1) + 0] = " (W32)",
    464  1.1  christos     [(M_FU    << 1) + 0] = " (FU)",
    465  1.1  christos     [(M_TFU   << 1) + 0] = " (TFU)",
    466  1.1  christos     [(M_IS    << 1) + 0] = " (IS)",
    467  1.1  christos     [(M_ISS2  << 1) + 0] = " (ISS2)",
    468  1.1  christos     [(M_IH    << 1) + 0] = " (IH)",
    469  1.1  christos     [(M_IU    << 1) + 0] = " (IU)",
    470  1.1  christos     [(M_S2RND << 1) + 1] = " (M, S2RND)",
    471  1.1  christos     [(M_T     << 1) + 1] = " (M, T)",
    472  1.1  christos     [(M_W32   << 1) + 1] = " (M, W32)",
    473  1.1  christos     [(M_FU    << 1) + 1] = " (M, FU)",
    474  1.1  christos     [(M_TFU   << 1) + 1] = " (M, TFU)",
    475  1.1  christos     [(M_IS    << 1) + 1] = " (M, IS)",
    476  1.1  christos     [(M_ISS2  << 1) + 1] = " (M, ISS2)",
    477  1.1  christos     [(M_IH    << 1) + 1] = " (M, IH)",
    478  1.1  christos     [(M_IU    << 1) + 1] = " (M, IU)",
    479  1.1  christos   };
    480  1.1  christos   int i = MM + (mmod << 1);
    481  1.1  christos 
    482  1.1  christos   if (i < ARRAY_SIZE (omode) && omode[i])
    483  1.1  christos     return omode[i];
    484  1.1  christos   else
    485  1.1  christos     return "";
    486  1.1  christos }
    487  1.1  christos 
    488  1.1  christos static const char *
    489  1.1  christos get_store_name (SIM_CPU *cpu, bu32 *p)
    490  1.1  christos {
    491  1.1  christos   if (p >= &DREG (0) && p <= &CYCLESREG)
    492  1.1  christos     return greg_names[p - &DREG (0)];
    493  1.1  christos   else if (p == &AXREG (0))
    494  1.1  christos     return greg_names[4 * 8 + 0];
    495  1.1  christos   else if (p == &AWREG (0))
    496  1.1  christos     return greg_names[4 * 8 + 1];
    497  1.1  christos   else if (p == &AXREG (1))
    498  1.1  christos     return greg_names[4 * 8 + 2];
    499  1.1  christos   else if (p == &AWREG (1))
    500  1.1  christos     return greg_names[4 * 8 + 3];
    501  1.1  christos   else if (p == &ASTATREG (av0))
    502  1.1  christos     return "ASTAT[av0]";
    503  1.1  christos   else if (p == &ASTATREG (av0s))
    504  1.1  christos     return "ASTAT[av0s]";
    505  1.1  christos   else if (p == &ASTATREG (av1))
    506  1.1  christos     return "ASTAT[av1]";
    507  1.1  christos   else if (p == &ASTATREG (av1s))
    508  1.1  christos     return "ASTAT[av1s]";
    509  1.1  christos   else if (p == &ASTATREG (v))
    510  1.1  christos     return "ASTAT[v]";
    511  1.1  christos   else if (p == &ASTATREG (vs))
    512  1.1  christos     return "ASTAT[vs]";
    513  1.1  christos   else if (p == &ASTATREG (v_copy))
    514  1.1  christos     return "ASTAT[v_copy]";
    515  1.1  christos   else if (p == &ASTATREG (az))
    516  1.1  christos     return "ASTAT[az]";
    517  1.1  christos   else if (p == &ASTATREG (an))
    518  1.1  christos     return "ASTAT[an]";
    519  1.1  christos   else if (p == &ASTATREG (az))
    520  1.1  christos     return "ASTAT[az]";
    521  1.1  christos   else if (p == &ASTATREG (ac0))
    522  1.1  christos     return "ASTAT[ac0]";
    523  1.1  christos   else if (p == &ASTATREG (ac0_copy))
    524  1.1  christos     return "ASTAT[ac0_copy]";
    525  1.1  christos   else
    526  1.1  christos     {
    527  1.1  christos       /* Worry about this when we start to STORE() it.  */
    528  1.1  christos       sim_io_eprintf (CPU_STATE (cpu), "STORE(): unknown register\n");
    529  1.1  christos       abort ();
    530  1.1  christos     }
    531  1.1  christos }
    532  1.1  christos 
    533  1.1  christos static void
    534  1.1  christos queue_store (SIM_CPU *cpu, bu32 *addr, bu32 val)
    535  1.1  christos {
    536  1.1  christos   struct store *s = &BFIN_CPU_STATE.stores[BFIN_CPU_STATE.n_stores];
    537  1.1  christos   s->addr = addr;
    538  1.1  christos   s->val = val;
    539  1.1  christos   TRACE_REGISTER (cpu, "queuing write %s = %#x",
    540  1.1  christos 		  get_store_name (cpu, addr), val);
    541  1.1  christos   ++BFIN_CPU_STATE.n_stores;
    542  1.1  christos }
    543  1.1  christos #define STORE(X, Y) \
    544  1.1  christos   do { \
    545  1.1  christos     if (BFIN_CPU_STATE.n_stores == 20) abort (); \
    546  1.1  christos     queue_store (cpu, &(X), (Y)); \
    547  1.1  christos   } while (0)
    548  1.1  christos 
    549  1.1  christos static void
    550  1.1  christos setflags_nz (SIM_CPU *cpu, bu32 val)
    551  1.1  christos {
    552  1.1  christos   SET_ASTATREG (az, val == 0);
    553  1.1  christos   SET_ASTATREG (an, val >> 31);
    554  1.1  christos }
    555  1.1  christos 
    556  1.1  christos static void
    557  1.1  christos setflags_nz_2x16 (SIM_CPU *cpu, bu32 val)
    558  1.1  christos {
    559  1.1  christos   SET_ASTATREG (an, (bs16)val < 0 || (bs16)(val >> 16) < 0);
    560  1.1  christos   SET_ASTATREG (az, (bs16)val == 0 || (bs16)(val >> 16) == 0);
    561  1.1  christos }
    562  1.1  christos 
    563  1.1  christos static void
    564  1.1  christos setflags_logical (SIM_CPU *cpu, bu32 val)
    565  1.1  christos {
    566  1.1  christos   setflags_nz (cpu, val);
    567  1.1  christos   SET_ASTATREG (ac0, 0);
    568  1.1  christos   SET_ASTATREG (v, 0);
    569  1.1  christos }
    570  1.1  christos 
    571  1.1  christos static bu32
    572  1.1  christos add_brev (bu32 addend1, bu32 addend2)
    573  1.1  christos {
    574  1.1  christos   bu32 mask, b, r;
    575  1.1  christos   int i, cy;
    576  1.1  christos 
    577  1.1  christos   mask = 0x80000000;
    578  1.1  christos   r = 0;
    579  1.1  christos   cy = 0;
    580  1.1  christos 
    581  1.1  christos   for (i = 31; i >= 0; --i)
    582  1.1  christos     {
    583  1.1  christos       b = ((addend1 & mask) >> i) + ((addend2 & mask) >> i);
    584  1.1  christos       b += cy;
    585  1.1  christos       cy = b >> 1;
    586  1.1  christos       b &= 1;
    587  1.1  christos       r |= b << i;
    588  1.1  christos       mask >>= 1;
    589  1.1  christos     }
    590  1.1  christos 
    591  1.1  christos   return r;
    592  1.1  christos }
    593  1.1  christos 
    594  1.1  christos /* This is a bit crazy, but we want to simulate the hardware behavior exactly
    595  1.1  christos    rather than worry about the circular buffers being used correctly.  Which
    596  1.1  christos    isn't to say there isn't room for improvement here, just that we want to
    597  1.1  christos    be conservative.  See also dagsub().  */
    598  1.1  christos static bu32
    599  1.1  christos dagadd (SIM_CPU *cpu, int dagno, bs32 M)
    600  1.1  christos {
    601  1.1  christos   bu64 i = IREG (dagno);
    602  1.1  christos   bu64 l = LREG (dagno);
    603  1.1  christos   bu64 b = BREG (dagno);
    604  1.1  christos   bu64 m = (bu32)M;
    605  1.1  christos 
    606  1.1  christos   bu64 LB, IM, IML;
    607  1.1  christos   bu32 im32, iml32, lb32, res;
    608  1.1  christos   bu64 msb, car;
    609  1.1  christos 
    610  1.1  christos   /* A nave implementation that mostly works:
    611  1.1  christos   res = i + m;
    612  1.1  christos   if (l && res >= b + l)
    613  1.1  christos     res -= l;
    614  1.1  christos   STORE (IREG (dagno), res);
    615  1.1  christos    */
    616  1.1  christos 
    617  1.1  christos   msb = (bu64)1 << 31;
    618  1.1  christos   car = (bu64)1 << 32;
    619  1.1  christos 
    620  1.1  christos   IM = i + m;
    621  1.1  christos   im32 = IM;
    622  1.1  christos   LB = l + b;
    623  1.1  christos   lb32 = LB;
    624  1.1  christos 
    625  1.1  christos   if (M < 0)
    626  1.1  christos     {
    627  1.1  christos       IML = i + m + l;
    628  1.1  christos       iml32 = IML;
    629  1.1  christos       if ((i & msb) || (IM & car))
    630  1.1  christos 	res = (im32 < b) ? iml32 : im32;
    631  1.1  christos       else
    632  1.1  christos 	res = (im32 < b) ? im32 : iml32;
    633  1.1  christos     }
    634  1.1  christos   else
    635  1.1  christos     {
    636  1.1  christos       IML = i + m - l;
    637  1.1  christos       iml32 = IML;
    638  1.1  christos       if ((IM & car) == (LB & car))
    639  1.1  christos 	res = (im32 < lb32) ? im32 : iml32;
    640  1.1  christos       else
    641  1.1  christos 	res = (im32 < lb32) ? iml32 : im32;
    642  1.1  christos     }
    643  1.1  christos 
    644  1.1  christos   STORE (IREG (dagno), res);
    645  1.1  christos   return res;
    646  1.1  christos }
    647  1.1  christos 
    648  1.1  christos /* See dagadd() notes above.  */
    649  1.1  christos static bu32
    650  1.1  christos dagsub (SIM_CPU *cpu, int dagno, bs32 M)
    651  1.1  christos {
    652  1.1  christos   bu64 i = IREG (dagno);
    653  1.1  christos   bu64 l = LREG (dagno);
    654  1.1  christos   bu64 b = BREG (dagno);
    655  1.1  christos   bu64 m = (bu32)M;
    656  1.1  christos 
    657  1.1  christos   bu64 mbar = (bu32)(~m + 1);
    658  1.1  christos   bu64 LB, IM, IML;
    659  1.1  christos   bu32 b32, im32, iml32, lb32, res;
    660  1.1  christos   bu64 msb, car;
    661  1.1  christos 
    662  1.1  christos   /* A nave implementation that mostly works:
    663  1.1  christos   res = i - m;
    664  1.1  christos   if (l && newi < b)
    665  1.1  christos     newi += l;
    666  1.1  christos   STORE (IREG (dagno), newi);
    667  1.1  christos    */
    668  1.1  christos 
    669  1.1  christos   msb = (bu64)1 << 31;
    670  1.1  christos   car = (bu64)1 << 32;
    671  1.1  christos 
    672  1.1  christos   IM = i + mbar;
    673  1.1  christos   im32 = IM;
    674  1.1  christos   LB = l + b;
    675  1.1  christos   lb32 = LB;
    676  1.1  christos 
    677  1.1  christos   if (M < 0)
    678  1.1  christos     {
    679  1.1  christos       IML = i + mbar - l;
    680  1.1  christos       iml32 = IML;
    681  1.1  christos       if (!!((i & msb) && (IM & car)) == !!(LB & car))
    682  1.1  christos 	res = (im32 < lb32) ? im32 : iml32;
    683  1.1  christos       else
    684  1.1  christos 	res = (im32 < lb32) ? iml32 : im32;
    685  1.1  christos     }
    686  1.1  christos   else
    687  1.1  christos     {
    688  1.1  christos       IML = i + mbar + l;
    689  1.1  christos       iml32 = IML;
    690  1.1  christos       b32 = b;
    691  1.1  christos       if (M == 0 || IM & car)
    692  1.1  christos 	res = (im32 < b32) ? iml32 : im32;
    693  1.1  christos       else
    694  1.1  christos 	res = (im32 < b32) ? im32 : iml32;
    695  1.1  christos     }
    696  1.1  christos 
    697  1.1  christos   STORE (IREG (dagno), res);
    698  1.1  christos   return res;
    699  1.1  christos }
    700  1.1  christos 
    701  1.1  christos static bu40
    702  1.1  christos ashiftrt (SIM_CPU *cpu, bu40 val, int cnt, int size)
    703  1.1  christos {
    704  1.1  christos   int real_cnt = cnt > size ? size : cnt;
    705  1.1  christos   bu40 sgn = ~(((val & 0xFFFFFFFFFFull) >> (size - 1)) - 1);
    706  1.1  christos   int sgncnt = size - real_cnt;
    707  1.1  christos   if (sgncnt > 16)
    708  1.1  christos     sgn <<= 16, sgncnt -= 16;
    709  1.1  christos   sgn <<= sgncnt;
    710  1.1  christos   if (real_cnt > 16)
    711  1.1  christos     val >>= 16, real_cnt -= 16;
    712  1.1  christos   val >>= real_cnt;
    713  1.1  christos   val |= sgn;
    714  1.1  christos   SET_ASTATREG (an, val >> (size - 1));
    715  1.1  christos   SET_ASTATREG (az, val == 0);
    716  1.1  christos   /* XXX: Need to check ASTAT[v] behavior here.  */
    717  1.1  christos   SET_ASTATREG (v, 0);
    718  1.1  christos   return val;
    719  1.1  christos }
    720  1.1  christos 
    721  1.1  christos static bu64
    722  1.1  christos lshiftrt (SIM_CPU *cpu, bu64 val, int cnt, int size)
    723  1.1  christos {
    724  1.1  christos   int real_cnt = cnt > size ? size : cnt;
    725  1.1  christos   if (real_cnt > 16)
    726  1.1  christos     val >>= 16, real_cnt -= 16;
    727  1.1  christos   val >>= real_cnt;
    728  1.1  christos   switch (size)
    729  1.1  christos     {
    730  1.1  christos     case 16:
    731  1.1  christos       val &= 0xFFFF;
    732  1.1  christos       break;
    733  1.1  christos     case 32:
    734  1.1  christos       val &= 0xFFFFFFFF;
    735  1.1  christos       break;
    736  1.1  christos     case 40:
    737  1.1  christos       val &= 0xFFFFFFFFFFull;
    738  1.1  christos       break;
    739  1.1  christos     default:
    740  1.1  christos       illegal_instruction (cpu);
    741  1.1  christos       break;
    742  1.1  christos     }
    743  1.1  christos   SET_ASTATREG (an, val >> (size - 1));
    744  1.1  christos   SET_ASTATREG (az, val == 0);
    745  1.1  christos   SET_ASTATREG (v, 0);
    746  1.1  christos   return val;
    747  1.1  christos }
    748  1.1  christos 
    749  1.1  christos static bu64
    750  1.1  christos lshift (SIM_CPU *cpu, bu64 val, int cnt, int size, bool saturate)
    751  1.1  christos {
    752  1.1  christos   int i, j, real_cnt = cnt > size ? size : cnt;
    753  1.1  christos   bu64 sgn = ~((val >> (size - 1)) - 1);
    754  1.1  christos   int mask_cnt = size - 1;
    755  1.1  christos   bu64 masked, new_val = val, tmp;
    756  1.1  christos   bu64 mask = ~0;
    757  1.1  christos 
    758  1.1  christos   mask <<= mask_cnt;
    759  1.1  christos   sgn <<= mask_cnt;
    760  1.1  christos   masked = val & mask;
    761  1.1  christos 
    762  1.1  christos   if (real_cnt > 16)
    763  1.1  christos     new_val <<= 16, real_cnt -= 16;
    764  1.1  christos 
    765  1.1  christos   new_val <<= real_cnt;
    766  1.1  christos 
    767  1.1  christos   masked = new_val & mask;
    768  1.1  christos 
    769  1.1  christos   /* If an operation would otherwise cause a positive value to overflow
    770  1.1  christos      and become negative, instead, saturation limits the result to the
    771  1.1  christos      maximum positive value for the size register being used.
    772  1.1  christos 
    773  1.1  christos      Conversely, if an operation would otherwise cause a negative value
    774  1.1  christos      to overflow and become positive, saturation limits the result to the
    775  1.1  christos      maximum negative value for the register size.
    776  1.1  christos 
    777  1.1  christos      However, it's a little more complex than looking at sign bits, we need
    778  1.1  christos      to see if we are shifting the sign information away...  */
    779  1.1  christos   tmp = val & ((~mask << 1) | 1);
    780  1.1  christos 
    781  1.1  christos   j = 0;
    782  1.1  christos   for (i = 1; i <= real_cnt && saturate; i++)
    783  1.1  christos     {
    784  1.1  christos       if ((tmp & ((bu64)1 << (size - 1))) !=
    785  1.1  christos 	  (((val >> mask_cnt) & 0x1) << mask_cnt))
    786  1.1  christos 	j++;
    787  1.1  christos       tmp <<= 1;
    788  1.1  christos     }
    789  1.1  christos   saturate &= (!sgn && (new_val & (1 << mask_cnt)))
    790  1.1  christos 	      || (sgn && !(new_val & (1 << mask_cnt)));
    791  1.1  christos 
    792  1.1  christos   switch (size)
    793  1.1  christos     {
    794  1.1  christos     case 16:
    795  1.1  christos       if (j || (saturate && (new_val & mask)))
    796  1.1  christos 	new_val = sgn == 0 ? 0x7fff : 0x8000, saturate = 1;
    797  1.1  christos       new_val &= 0xFFFF;
    798  1.1  christos       break;
    799  1.1  christos     case 32:
    800  1.1  christos       new_val &= 0xFFFFFFFF;
    801  1.1  christos       masked &= 0xFFFFFFFF;
    802  1.1  christos       if (j || (saturate && ((sgn != masked) || (!sgn && new_val == 0))))
    803  1.1  christos 	new_val = sgn == 0 ? 0x7fffffff : 0x80000000, saturate = 1;
    804  1.1  christos       break;
    805  1.1  christos     case 40:
    806  1.1  christos       new_val &= 0xFFFFFFFFFFull;
    807  1.1  christos       masked &= 0xFFFFFFFFFFull;
    808  1.1  christos       break;
    809  1.1  christos     default:
    810  1.1  christos       illegal_instruction (cpu);
    811  1.1  christos       break;
    812  1.1  christos     }
    813  1.1  christos 
    814  1.1  christos   SET_ASTATREG (an, new_val >> (size - 1));
    815  1.1  christos   SET_ASTATREG (az, new_val == 0);
    816  1.1  christos   SET_ASTATREG (v, !!(saturate || j));
    817  1.1  christos   if (saturate || j)
    818  1.1  christos     SET_ASTATREG (vs, 1);
    819  1.1  christos   return new_val;
    820  1.1  christos }
    821  1.1  christos 
    822  1.1  christos static bu32
    823  1.1  christos algn (bu32 l, bu32 h, bu32 aln)
    824  1.1  christos {
    825  1.1  christos   if (aln == 0)
    826  1.1  christos     return l;
    827  1.1  christos   else
    828  1.1  christos     return (l >> (8 * aln)) | (h << (32 - 8 * aln));
    829  1.1  christos }
    830  1.1  christos 
    831  1.1  christos static bu32
    832  1.1  christos saturate_s16 (bu64 val, bu32 *overflow)
    833  1.1  christos {
    834  1.1  christos   if ((bs64)val < -0x8000ll)
    835  1.1  christos     {
    836  1.1  christos       if (overflow)
    837  1.1  christos 	*overflow = 1;
    838  1.1  christos       return 0x8000;
    839  1.1  christos     }
    840  1.1  christos   if ((bs64)val > 0x7fff)
    841  1.1  christos     {
    842  1.1  christos       if (overflow)
    843  1.1  christos 	*overflow = 1;
    844  1.1  christos       return 0x7fff;
    845  1.1  christos     }
    846  1.1  christos   return val & 0xffff;
    847  1.1  christos }
    848  1.1  christos 
    849  1.1  christos static bu40
    850  1.1  christos rot40 (bu40 val, int shift, bu32 *cc)
    851  1.1  christos {
    852  1.1  christos   const int nbits = 40;
    853  1.1  christos   bu40 ret;
    854  1.1  christos 
    855  1.1  christos   shift = CLAMP (shift, -nbits, nbits);
    856  1.1  christos   if (shift == 0)
    857  1.1  christos     return val;
    858  1.1  christos 
    859  1.1  christos   /* Reduce everything to rotate left.  */
    860  1.1  christos   if (shift < 0)
    861  1.1  christos     shift += nbits + 1;
    862  1.1  christos 
    863  1.1  christos   ret = shift == nbits ? 0 : val << shift;
    864  1.1  christos   ret |= shift == 1 ? 0 : val >> ((nbits + 1) - shift);
    865  1.1  christos   ret |= (bu40)*cc << (shift - 1);
    866  1.1  christos   *cc = (val >> (nbits - shift)) & 1;
    867  1.1  christos 
    868  1.1  christos   return ret;
    869  1.1  christos }
    870  1.1  christos 
    871  1.1  christos static bu32
    872  1.1  christos rot32 (bu32 val, int shift, bu32 *cc)
    873  1.1  christos {
    874  1.1  christos   const int nbits = 32;
    875  1.1  christos   bu32 ret;
    876  1.1  christos 
    877  1.1  christos   shift = CLAMP (shift, -nbits, nbits);
    878  1.1  christos   if (shift == 0)
    879  1.1  christos     return val;
    880  1.1  christos 
    881  1.1  christos   /* Reduce everything to rotate left.  */
    882  1.1  christos   if (shift < 0)
    883  1.1  christos     shift += nbits + 1;
    884  1.1  christos 
    885  1.1  christos   ret = shift == nbits ? 0 : val << shift;
    886  1.1  christos   ret |= shift == 1 ? 0 : val >> ((nbits + 1) - shift);
    887  1.1  christos   ret |= (bu32)*cc << (shift - 1);
    888  1.1  christos   *cc = (val >> (nbits - shift)) & 1;
    889  1.1  christos 
    890  1.1  christos   return ret;
    891  1.1  christos }
    892  1.1  christos 
    893  1.1  christos static bu32
    894  1.1  christos add32 (SIM_CPU *cpu, bu32 a, bu32 b, int carry, int sat)
    895  1.1  christos {
    896  1.1  christos   int flgs = (a >> 31) & 1;
    897  1.1  christos   int flgo = (b >> 31) & 1;
    898  1.1  christos   bu32 v = a + b;
    899  1.1  christos   int flgn = (v >> 31) & 1;
    900  1.1  christos   int overflow = (flgs ^ flgn) & (flgo ^ flgn);
    901  1.1  christos 
    902  1.1  christos   if (sat && overflow)
    903  1.1  christos     {
    904  1.1  christos       v = (bu32)1 << 31;
    905  1.1  christos       if (flgn)
    906  1.1  christos 	v -= 1;
    907  1.1  christos       flgn = (v >> 31) & 1;
    908  1.1  christos     }
    909  1.1  christos 
    910  1.1  christos   SET_ASTATREG (an, flgn);
    911  1.1  christos   if (overflow)
    912  1.1  christos     SET_ASTATREG (vs, 1);
    913  1.1  christos   SET_ASTATREG (v, overflow);
    914  1.1  christos   ASTATREG (v_internal) |= overflow;
    915  1.1  christos   SET_ASTATREG (az, v == 0);
    916  1.1  christos   if (carry)
    917  1.1  christos     SET_ASTATREG (ac0, ~a < b);
    918  1.1  christos 
    919  1.1  christos   return v;
    920  1.1  christos }
    921  1.1  christos 
    922  1.1  christos static bu32
    923  1.1  christos sub32 (SIM_CPU *cpu, bu32 a, bu32 b, int carry, int sat, int parallel)
    924  1.1  christos {
    925  1.1  christos   int flgs = (a >> 31) & 1;
    926  1.1  christos   int flgo = (b >> 31) & 1;
    927  1.1  christos   bu32 v = a - b;
    928  1.1  christos   int flgn = (v >> 31) & 1;
    929  1.1  christos   int overflow = (flgs ^ flgo) & (flgn ^ flgs);
    930  1.1  christos 
    931  1.1  christos   if (sat && overflow)
    932  1.1  christos     {
    933  1.1  christos       v = (bu32)1 << 31;
    934  1.1  christos       if (flgn)
    935  1.1  christos 	v -= 1;
    936  1.1  christos       flgn = (v >> 31) & 1;
    937  1.1  christos     }
    938  1.1  christos 
    939  1.1  christos   if (!parallel || flgn)
    940  1.1  christos     SET_ASTATREG (an, flgn);
    941  1.1  christos   if (overflow)
    942  1.1  christos     SET_ASTATREG (vs, 1);
    943  1.1  christos   if (!parallel || overflow)
    944  1.1  christos     SET_ASTATREG (v, overflow);
    945  1.1  christos   if (!parallel || overflow)
    946  1.1  christos     ASTATREG (v_internal) |= overflow;
    947  1.1  christos   if (!parallel || v == 0)
    948  1.1  christos     SET_ASTATREG (az, v == 0);
    949  1.1  christos   if (carry && (!parallel || b <= a))
    950  1.1  christos     SET_ASTATREG (ac0, b <= a);
    951  1.1  christos 
    952  1.1  christos   return v;
    953  1.1  christos }
    954  1.1  christos 
    955  1.1  christos static bu32
    956  1.1  christos add16 (SIM_CPU *cpu, bu16 a, bu16 b, bu32 *carry, bu32 *overfl,
    957  1.1  christos        bu32 *zero, bu32 *neg, int sat, int scale)
    958  1.1  christos {
    959  1.1  christos   int flgs = (a >> 15) & 1;
    960  1.1  christos   int flgo = (b >> 15) & 1;
    961  1.1  christos   bs64 v = (bs16)a + (bs16)b;
    962  1.1  christos   int flgn = (v >> 15) & 1;
    963  1.1  christos   int overflow = (flgs ^ flgn) & (flgo ^ flgn);
    964  1.1  christos 
    965  1.1  christos   switch (scale)
    966  1.1  christos     {
    967  1.1  christos     case 0:
    968  1.1  christos       break;
    969  1.1  christos     case 2:
    970  1.1  christos       /* (ASR)  */
    971  1.1  christos       v = (a >> 1) + (a & 0x8000) + (b >> 1) + (b & 0x8000)
    972  1.1  christos 	  + (((a & 1) + (b & 1)) >> 1);
    973  1.1  christos       v |= -(v & 0x8000);
    974  1.1  christos       break;
    975  1.1  christos     case 3:
    976  1.1  christos       /* (ASL)  */
    977  1.1  christos       v = (v << 1);
    978  1.1  christos       break;
    979  1.1  christos     default:
    980  1.1  christos       illegal_instruction (cpu);
    981  1.1  christos     }
    982  1.1  christos 
    983  1.1  christos   flgn = (v >> 15) & 1;
    984  1.1  christos   overflow = (flgs ^ flgn) & (flgo ^ flgn);
    985  1.1  christos 
    986  1.1  christos   if (v > (bs64)0xffff)
    987  1.1  christos     overflow = 1;
    988  1.1  christos 
    989  1.1  christos   if (sat)
    990  1.1  christos     v = saturate_s16 (v, 0);
    991  1.1  christos 
    992  1.1  christos   if (neg)
    993  1.1  christos     *neg |= (v >> 15) & 1;
    994  1.1  christos   if (overfl)
    995  1.1  christos     *overfl |= overflow;
    996  1.1  christos   if (zero)
    997  1.1  christos     *zero |= (v & 0xFFFF) == 0;
    998  1.1  christos   if (carry)
    999  1.1  christos       *carry |= ((bu16)~a < (bu16)b);
   1000  1.1  christos 
   1001  1.1  christos   return v & 0xffff;
   1002  1.1  christos }
   1003  1.1  christos 
   1004  1.1  christos static bu32
   1005  1.1  christos sub16 (SIM_CPU *cpu, bu16 a, bu16 b, bu32 *carry, bu32 *overfl,
   1006  1.1  christos        bu32 *zero, bu32 *neg, int sat, int scale)
   1007  1.1  christos {
   1008  1.1  christos   int flgs = (a >> 15) & 1;
   1009  1.1  christos   int flgo = (b >> 15) & 1;
   1010  1.1  christos   bs64 v = (bs16)a - (bs16)b;
   1011  1.1  christos   int flgn = (v >> 15) & 1;
   1012  1.1  christos   int overflow = (flgs ^ flgo) & (flgn ^ flgs);
   1013  1.1  christos 
   1014  1.1  christos   switch (scale)
   1015  1.1  christos     {
   1016  1.1  christos     case 0:
   1017  1.1  christos       break;
   1018  1.1  christos     case 2:
   1019  1.1  christos       /* (ASR)  */
   1020  1.1  christos       if (sat)
   1021  1.1  christos 	v = ((a >> 1) + (a & 0x8000)) - ( (b >> 1) + (b & 0x8000))
   1022  1.1  christos 	    + (((a & 1)-(b & 1)));
   1023  1.1  christos       else
   1024  1.1  christos 	{
   1025  1.1  christos 	  v = ((v & 0xFFFF) >> 1);
   1026  1.1  christos 	  if ((!flgs & !flgo & flgn)
   1027  1.1  christos 	      || (flgs & !flgo & !flgn)
   1028  1.1  christos 	      || (flgs & flgo & flgn)
   1029  1.1  christos 	      || (flgs & !flgo & flgn))
   1030  1.1  christos 	    v |= 0x8000;
   1031  1.1  christos 	}
   1032  1.1  christos       v |= -(v & 0x8000);
   1033  1.1  christos       flgn = (v >> 15) & 1;
   1034  1.1  christos       overflow = (flgs ^ flgo) & (flgn ^ flgs);
   1035  1.1  christos       break;
   1036  1.1  christos     case 3:
   1037  1.1  christos       /* (ASL)  */
   1038  1.1  christos       v <<= 1;
   1039  1.1  christos       if (v > (bs64)0x7fff || v < (bs64)-0xffff)
   1040  1.1  christos 	overflow = 1;
   1041  1.1  christos       break;
   1042  1.1  christos     default:
   1043  1.1  christos       illegal_instruction (cpu);
   1044  1.1  christos     }
   1045  1.1  christos 
   1046  1.1  christos   if (sat)
   1047  1.1  christos     {
   1048  1.1  christos       v = saturate_s16 (v, 0);
   1049  1.1  christos     }
   1050  1.1  christos   if (neg)
   1051  1.1  christos     *neg |= (v >> 15) & 1;
   1052  1.1  christos   if (zero)
   1053  1.1  christos     *zero |= (v & 0xFFFF) == 0;
   1054  1.1  christos   if (overfl)
   1055  1.1  christos     *overfl |= overflow;
   1056  1.1  christos   if (carry)
   1057  1.1  christos     *carry |= (bu16)b <= (bu16)a;
   1058  1.1  christos   return v;
   1059  1.1  christos }
   1060  1.1  christos 
   1061  1.1  christos static bu32
   1062  1.1  christos min32 (SIM_CPU *cpu, bu32 a, bu32 b)
   1063  1.1  christos {
   1064  1.1  christos   int val = a;
   1065  1.1  christos   if ((bs32)a > (bs32)b)
   1066  1.1  christos     val = b;
   1067  1.1  christos   setflags_nz (cpu, val);
   1068  1.1  christos   SET_ASTATREG (v, 0);
   1069  1.1  christos   return val;
   1070  1.1  christos }
   1071  1.1  christos 
   1072  1.1  christos static bu32
   1073  1.1  christos max32 (SIM_CPU *cpu, bu32 a, bu32 b)
   1074  1.1  christos {
   1075  1.1  christos   int val = a;
   1076  1.1  christos   if ((bs32)a < (bs32)b)
   1077  1.1  christos     val = b;
   1078  1.1  christos   setflags_nz (cpu, val);
   1079  1.1  christos   SET_ASTATREG (v, 0);
   1080  1.1  christos   return val;
   1081  1.1  christos }
   1082  1.1  christos 
   1083  1.1  christos static bu32
   1084  1.1  christos min2x16 (SIM_CPU *cpu, bu32 a, bu32 b)
   1085  1.1  christos {
   1086  1.1  christos   int val = a;
   1087  1.1  christos   if ((bs16)a > (bs16)b)
   1088  1.1  christos     val = (val & 0xFFFF0000) | (b & 0xFFFF);
   1089  1.1  christos   if ((bs16)(a >> 16) > (bs16)(b >> 16))
   1090  1.1  christos     val = (val & 0xFFFF) | (b & 0xFFFF0000);
   1091  1.1  christos   setflags_nz_2x16 (cpu, val);
   1092  1.1  christos   SET_ASTATREG (v, 0);
   1093  1.1  christos   return val;
   1094  1.1  christos }
   1095  1.1  christos 
   1096  1.1  christos static bu32
   1097  1.1  christos max2x16 (SIM_CPU *cpu, bu32 a, bu32 b)
   1098  1.1  christos {
   1099  1.1  christos   int val = a;
   1100  1.1  christos   if ((bs16)a < (bs16)b)
   1101  1.1  christos     val = (val & 0xFFFF0000) | (b & 0xFFFF);
   1102  1.1  christos   if ((bs16)(a >> 16) < (bs16)(b >> 16))
   1103  1.1  christos     val = (val & 0xFFFF) | (b & 0xFFFF0000);
   1104  1.1  christos   setflags_nz_2x16 (cpu, val);
   1105  1.1  christos   SET_ASTATREG (v, 0);
   1106  1.1  christos   return val;
   1107  1.1  christos }
   1108  1.1  christos 
   1109  1.1  christos static bu32
   1110  1.1  christos add_and_shift (SIM_CPU *cpu, bu32 a, bu32 b, int shift)
   1111  1.1  christos {
   1112  1.1  christos   int v;
   1113  1.1  christos   ASTATREG (v_internal) = 0;
   1114  1.1  christos   v = add32 (cpu, a, b, 0, 0);
   1115  1.1  christos   while (shift-- > 0)
   1116  1.1  christos     {
   1117  1.1  christos       int x = (v >> 30) & 0x3;
   1118  1.1  christos       if (x == 1 || x == 2)
   1119  1.1  christos 	ASTATREG (v_internal) = 1;
   1120  1.1  christos       v <<= 1;
   1121  1.1  christos     }
   1122  1.1  christos   SET_ASTATREG (az, v == 0);
   1123  1.1  christos   SET_ASTATREG (an, v & 0x80000000);
   1124  1.1  christos   SET_ASTATREG (v, ASTATREG (v_internal));
   1125  1.1  christos   if (ASTATREG (v))
   1126  1.1  christos     SET_ASTATREG (vs, 1);
   1127  1.1  christos   return v;
   1128  1.1  christos }
   1129  1.1  christos 
   1130  1.1  christos static bu32
   1131  1.1  christos xor_reduce (bu64 acc0, bu64 acc1)
   1132  1.1  christos {
   1133  1.1  christos   int i;
   1134  1.1  christos   bu32 v = 0;
   1135  1.1  christos   for (i = 0; i < 40; ++i)
   1136  1.1  christos     {
   1137  1.1  christos       v ^= (acc0 & acc1 & 1);
   1138  1.1  christos       acc0 >>= 1;
   1139  1.1  christos       acc1 >>= 1;
   1140  1.1  christos     }
   1141  1.1  christos   return v;
   1142  1.1  christos }
   1143  1.1  christos 
   1144  1.1  christos /* DIVS ( Dreg, Dreg ) ;
   1145  1.1  christos    Initialize for DIVQ.  Set the AQ status bit based on the signs of
   1146  1.1  christos    the 32-bit dividend and the 16-bit divisor.  Left shift the dividend
   1147  1.1  christos    one bit.  Copy AQ into the dividend LSB.  */
   1148  1.1  christos static bu32
   1149  1.1  christos divs (SIM_CPU *cpu, bu32 pquo, bu16 divisor)
   1150  1.1  christos {
   1151  1.1  christos   bu16 r = pquo >> 16;
   1152  1.1  christos   int aq;
   1153  1.1  christos 
   1154  1.1  christos   aq = (r ^ divisor) >> 15;  /* Extract msb's and compute quotient bit.  */
   1155  1.1  christos   SET_ASTATREG (aq, aq);     /* Update global quotient state.  */
   1156  1.1  christos 
   1157  1.1  christos   pquo <<= 1;
   1158  1.1  christos   pquo |= aq;
   1159  1.1  christos   pquo = (pquo & 0x1FFFF) | (r << 17);
   1160  1.1  christos   return pquo;
   1161  1.1  christos }
   1162  1.1  christos 
   1163  1.1  christos /* DIVQ ( Dreg, Dreg ) ;
   1164  1.1  christos    Based on AQ status bit, either add or subtract the divisor from
   1165  1.1  christos    the dividend.  Then set the AQ status bit based on the MSBs of the
   1166  1.1  christos    32-bit dividend and the 16-bit divisor.  Left shift the dividend one
   1167  1.1  christos    bit.  Copy the logical inverse of AQ into the dividend LSB.  */
   1168  1.1  christos static bu32
   1169  1.1  christos divq (SIM_CPU *cpu, bu32 pquo, bu16 divisor)
   1170  1.1  christos {
   1171  1.1  christos   unsigned short af = pquo >> 16;
   1172  1.1  christos   unsigned short r;
   1173  1.1  christos   int aq;
   1174  1.1  christos 
   1175  1.1  christos   if (ASTATREG (aq))
   1176  1.1  christos     r = divisor + af;
   1177  1.1  christos   else
   1178  1.1  christos     r = af - divisor;
   1179  1.1  christos 
   1180  1.1  christos   aq = (r ^ divisor) >> 15;  /* Extract msb's and compute quotient bit.  */
   1181  1.1  christos   SET_ASTATREG (aq, aq);     /* Update global quotient state.  */
   1182  1.1  christos 
   1183  1.1  christos   pquo <<= 1;
   1184  1.1  christos   pquo |= !aq;
   1185  1.1  christos   pquo = (pquo & 0x1FFFF) | (r << 17);
   1186  1.1  christos   return pquo;
   1187  1.1  christos }
   1188  1.1  christos 
   1189  1.1  christos /* ONES ( Dreg ) ;
   1190  1.1  christos    Count the number of bits set to 1 in the 32bit value.  */
   1191  1.1  christos static bu32
   1192  1.1  christos ones (bu32 val)
   1193  1.1  christos {
   1194  1.1  christos   bu32 i;
   1195  1.1  christos   bu32 ret;
   1196  1.1  christos 
   1197  1.1  christos   ret = 0;
   1198  1.1  christos   for (i = 0; i < 32; ++i)
   1199  1.1  christos     ret += !!(val & (1 << i));
   1200  1.1  christos 
   1201  1.1  christos   return ret;
   1202  1.1  christos }
   1203  1.1  christos 
   1204  1.1  christos static void
   1205  1.1  christos reg_check_sup (SIM_CPU *cpu, int grp, int reg)
   1206  1.1  christos {
   1207  1.1  christos   if (grp == 7)
   1208  1.1  christos     cec_require_supervisor (cpu);
   1209  1.1  christos }
   1210  1.1  christos 
   1211  1.1  christos static void
   1212  1.1  christos reg_write (SIM_CPU *cpu, int grp, int reg, bu32 value)
   1213  1.1  christos {
   1214  1.1  christos   bu32 *whichreg;
   1215  1.1  christos 
   1216  1.1  christos   /* ASTAT is special!  */
   1217  1.1  christos   if (grp == 4 && reg == 6)
   1218  1.1  christos     {
   1219  1.1  christos       SET_ASTAT (value);
   1220  1.1  christos       return;
   1221  1.1  christos     }
   1222  1.1  christos 
   1223  1.1  christos   /* Check supervisor after get_allreg() so exception order is correct.  */
   1224  1.1  christos   whichreg = get_allreg (cpu, grp, reg);
   1225  1.1  christos   reg_check_sup (cpu, grp, reg);
   1226  1.1  christos 
   1227  1.1  christos   if (whichreg == &CYCLES2REG)
   1228  1.1  christos     /* Writes to CYCLES2 goes to the shadow.  */
   1229  1.1  christos     whichreg = &CYCLES2SHDREG;
   1230  1.1  christos   else if (whichreg == &SEQSTATREG)
   1231  1.1  christos     /* Register is read only -- discard writes.  */
   1232  1.1  christos     return;
   1233  1.1  christos   else if (whichreg == &EMUDAT_INREG)
   1234  1.1  christos     /* Writes to EMUDAT goes to the output.  */
   1235  1.1  christos     whichreg = &EMUDAT_OUTREG;
   1236  1.1  christos   else if (whichreg == &LTREG (0) || whichreg == &LTREG (1))
   1237  1.1  christos     /* Writes to LT clears LSB automatically.  */
   1238  1.1  christos     value &= ~0x1;
   1239  1.1  christos   else if (whichreg == &AXREG (0) || whichreg == &AXREG (1))
   1240  1.1  christos     value &= 0xFF;
   1241  1.1  christos 
   1242  1.1  christos   TRACE_REGISTER (cpu, "wrote %s = %#x", get_allreg_name (grp, reg), value);
   1243  1.1  christos 
   1244  1.1  christos   *whichreg = value;
   1245  1.1  christos }
   1246  1.1  christos 
   1247  1.1  christos static bu32
   1248  1.1  christos reg_read (SIM_CPU *cpu, int grp, int reg)
   1249  1.1  christos {
   1250  1.1  christos   bu32 *whichreg;
   1251  1.1  christos   bu32 value;
   1252  1.1  christos 
   1253  1.1  christos   /* ASTAT is special!  */
   1254  1.1  christos   if (grp == 4 && reg == 6)
   1255  1.1  christos     return ASTAT;
   1256  1.1  christos 
   1257  1.1  christos   /* Check supervisor after get_allreg() so exception order is correct.  */
   1258  1.1  christos   whichreg = get_allreg (cpu, grp, reg);
   1259  1.1  christos   reg_check_sup (cpu, grp, reg);
   1260  1.1  christos 
   1261  1.1  christos   value = *whichreg;
   1262  1.1  christos 
   1263  1.1  christos   if (whichreg == &CYCLESREG)
   1264  1.1  christos     /* Reads of CYCLES reloads CYCLES2 from the shadow.  */
   1265  1.1  christos     SET_CYCLES2REG (CYCLES2SHDREG);
   1266  1.1  christos   else if ((whichreg == &AXREG (1) || whichreg == &AXREG (0)) && (value & 0x80))
   1267  1.1  christos     /* Sign extend if necessary.  */
   1268  1.1  christos     value |= 0xFFFFFF00;
   1269  1.1  christos 
   1270  1.1  christos   return value;
   1271  1.1  christos }
   1272  1.1  christos 
   1273  1.1  christos static bu64
   1274  1.1  christos get_extended_cycles (SIM_CPU *cpu)
   1275  1.1  christos {
   1276  1.1  christos   return ((bu64)CYCLES2SHDREG << 32) | CYCLESREG;
   1277  1.1  christos }
   1278  1.1  christos 
   1279  1.1  christos /* We can't re-use sim_events_time() because the CYCLES registers may be
   1280  1.1  christos    written/cleared/reset/stopped/started at any time by software.  */
   1281  1.1  christos static void
   1282  1.1  christos cycles_inc (SIM_CPU *cpu, bu32 inc)
   1283  1.1  christos {
   1284  1.1  christos   bu64 cycles;
   1285  1.1  christos   bu32 cycles2;
   1286  1.1  christos 
   1287  1.1  christos   if (!(SYSCFGREG & SYSCFG_CCEN))
   1288  1.1  christos     return;
   1289  1.1  christos 
   1290  1.1  christos   cycles = get_extended_cycles (cpu) + inc;
   1291  1.1  christos   SET_CYCLESREG (cycles);
   1292  1.1  christos   cycles2 = cycles >> 32;
   1293  1.1  christos   if (CYCLES2SHDREG != cycles2)
   1294  1.1  christos     SET_CYCLES2SHDREG (cycles2);
   1295  1.1  christos }
   1296  1.1  christos 
   1297  1.1  christos static bu64
   1298  1.1  christos get_unextended_acc (SIM_CPU *cpu, int which)
   1299  1.1  christos {
   1300  1.1  christos   return ((bu64)(AXREG (which) & 0xff) << 32) | AWREG (which);
   1301  1.1  christos }
   1302  1.1  christos 
   1303  1.1  christos static bu64
   1304  1.1  christos get_extended_acc (SIM_CPU *cpu, int which)
   1305  1.1  christos {
   1306  1.1  christos   bu64 acc = AXREG (which);
   1307  1.1  christos   /* Sign extend accumulator values before adding.  */
   1308  1.1  christos   if (acc & 0x80)
   1309  1.1  christos     acc |= -0x80;
   1310  1.1  christos   else
   1311  1.1  christos     acc &= 0xFF;
   1312  1.1  christos   acc <<= 32;
   1313  1.1  christos   acc |= AWREG (which);
   1314  1.1  christos   return acc;
   1315  1.1  christos }
   1316  1.1  christos 
   1317  1.1  christos /* Perform a multiplication of D registers SRC0 and SRC1, sign- or
   1318  1.1  christos    zero-extending the result to 64 bit.  H0 and H1 determine whether the
   1319  1.1  christos    high part or the low part of the source registers is used.  Store 1 in
   1320  1.1  christos    *PSAT if saturation occurs, 0 otherwise.  */
   1321  1.1  christos static bu64
   1322  1.1  christos decode_multfunc (SIM_CPU *cpu, int h0, int h1, int src0, int src1, int mmod,
   1323  1.1  christos 		 int MM, bu32 *psat)
   1324  1.1  christos {
   1325  1.1  christos   bu32 s0 = DREG (src0), s1 = DREG (src1);
   1326  1.1  christos   bu32 sgn0, sgn1;
   1327  1.1  christos   bu32 val;
   1328  1.1  christos   bu64 val1;
   1329  1.1  christos 
   1330  1.1  christos   if (h0)
   1331  1.1  christos     s0 >>= 16;
   1332  1.1  christos 
   1333  1.1  christos   if (h1)
   1334  1.1  christos     s1 >>= 16;
   1335  1.1  christos 
   1336  1.1  christos   s0 &= 0xffff;
   1337  1.1  christos   s1 &= 0xffff;
   1338  1.1  christos 
   1339  1.1  christos   sgn0 = -(s0 & 0x8000);
   1340  1.1  christos   sgn1 = -(s1 & 0x8000);
   1341  1.1  christos 
   1342  1.1  christos   if (MM)
   1343  1.1  christos     s0 |= sgn0;
   1344  1.1  christos   else
   1345  1.1  christos     switch (mmod)
   1346  1.1  christos       {
   1347  1.1  christos       case 0:
   1348  1.1  christos       case M_S2RND:
   1349  1.1  christos       case M_T:
   1350  1.1  christos       case M_IS:
   1351  1.1  christos       case M_ISS2:
   1352  1.1  christos       case M_IH:
   1353  1.1  christos       case M_W32:
   1354  1.1  christos 	s0 |= sgn0;
   1355  1.1  christos 	s1 |= sgn1;
   1356  1.1  christos 	break;
   1357  1.1  christos       case M_FU:
   1358  1.1  christos       case M_IU:
   1359  1.1  christos       case M_TFU:
   1360  1.1  christos 	break;
   1361  1.1  christos       default:
   1362  1.1  christos 	illegal_instruction (cpu);
   1363  1.1  christos       }
   1364  1.1  christos 
   1365  1.1  christos   val = s0 * s1;
   1366  1.1  christos   /* Perform shift correction if appropriate for the mode.  */
   1367  1.1  christos   *psat = 0;
   1368  1.1  christos   if (!MM && (mmod == 0 || mmod == M_T || mmod == M_S2RND || mmod == M_W32))
   1369  1.1  christos     {
   1370  1.1  christos       if (val == 0x40000000)
   1371  1.1  christos 	{
   1372  1.1  christos 	  if (mmod == M_W32)
   1373  1.1  christos 	    val = 0x7fffffff;
   1374  1.1  christos 	  else
   1375  1.1  christos 	    val = 0x80000000;
   1376  1.1  christos 	  *psat = 1;
   1377  1.1  christos 	}
   1378  1.1  christos       else
   1379  1.1  christos 	val <<= 1;
   1380  1.1  christos     }
   1381  1.1  christos   val1 = val;
   1382  1.1  christos 
   1383  1.1  christos   if (mmod == 0 || mmod == M_IS || mmod == M_T || mmod == M_S2RND
   1384  1.1  christos       || mmod == M_ISS2 || mmod == M_IH || (MM && mmod == M_FU))
   1385  1.1  christos     val1 |= -(val1 & 0x80000000);
   1386  1.1  christos 
   1387  1.1  christos   if (*psat)
   1388  1.1  christos     val1 &= 0xFFFFFFFFull;
   1389  1.1  christos 
   1390  1.1  christos   return val1;
   1391  1.1  christos }
   1392  1.1  christos 
   1393  1.1  christos static bu40
   1394  1.1  christos saturate_s40_astat (bu64 val, bu32 *v)
   1395  1.1  christos {
   1396  1.1  christos   if ((bs64)val < -((bs64)1 << 39))
   1397  1.1  christos     {
   1398  1.1  christos       *v = 1;
   1399  1.1  christos       return -((bs64)1 << 39);
   1400  1.1  christos     }
   1401  1.1  christos   else if ((bs64)val >= ((bs64)1 << 39) - 1)
   1402  1.1  christos     {
   1403  1.1  christos       *v = 1;
   1404  1.1  christos       return ((bu64)1 << 39) - 1;
   1405  1.1  christos     }
   1406  1.1  christos   *v = 0; /* No overflow.  */
   1407  1.1  christos   return val;
   1408  1.1  christos }
   1409  1.1  christos 
   1410  1.1  christos static bu40
   1411  1.1  christos saturate_s40 (bu64 val)
   1412  1.1  christos {
   1413  1.1  christos   bu32 v;
   1414  1.1  christos   return saturate_s40_astat (val, &v);
   1415  1.1  christos }
   1416  1.1  christos 
   1417  1.1  christos static bu32
   1418  1.1  christos saturate_s32 (bu64 val, bu32 *overflow)
   1419  1.1  christos {
   1420  1.1  christos   if ((bs64)val < -0x80000000ll)
   1421  1.1  christos     {
   1422  1.1  christos       if (overflow)
   1423  1.1  christos 	*overflow = 1;
   1424  1.1  christos       return 0x80000000;
   1425  1.1  christos     }
   1426  1.1  christos   if ((bs64)val > 0x7fffffff)
   1427  1.1  christos     {
   1428  1.1  christos       if (overflow)
   1429  1.1  christos 	*overflow = 1;
   1430  1.1  christos       return 0x7fffffff;
   1431  1.1  christos     }
   1432  1.1  christos   return val;
   1433  1.1  christos }
   1434  1.1  christos 
   1435  1.1  christos static bu32
   1436  1.1  christos saturate_u32 (bu64 val, bu32 *overflow)
   1437  1.1  christos {
   1438  1.1  christos   if (val > 0xffffffff)
   1439  1.1  christos     {
   1440  1.1  christos       if (overflow)
   1441  1.1  christos 	*overflow = 1;
   1442  1.1  christos       return 0xffffffff;
   1443  1.1  christos     }
   1444  1.1  christos   return val;
   1445  1.1  christos }
   1446  1.1  christos 
   1447  1.1  christos static bu32
   1448  1.1  christos saturate_u16 (bu64 val, bu32 *overflow)
   1449  1.1  christos {
   1450  1.1  christos   if (val > 0xffff)
   1451  1.1  christos     {
   1452  1.1  christos       if (overflow)
   1453  1.1  christos 	*overflow = 1;
   1454  1.1  christos       return 0xffff;
   1455  1.1  christos     }
   1456  1.1  christos   return val;
   1457  1.1  christos }
   1458  1.1  christos 
   1459  1.1  christos static bu64
   1460  1.1  christos rnd16 (bu64 val)
   1461  1.1  christos {
   1462  1.1  christos   bu64 sgnbits;
   1463  1.1  christos 
   1464  1.1  christos   /* FIXME: Should honour rounding mode.  */
   1465  1.1  christos   if ((val & 0xffff) > 0x8000
   1466  1.1  christos       || ((val & 0xffff) == 0x8000 && (val & 0x10000)))
   1467  1.1  christos     val += 0x8000;
   1468  1.1  christos 
   1469  1.1  christos   sgnbits = val & 0xffff000000000000ull;
   1470  1.1  christos   val >>= 16;
   1471  1.1  christos   return val | sgnbits;
   1472  1.1  christos }
   1473  1.1  christos 
   1474  1.1  christos static bu64
   1475  1.1  christos trunc16 (bu64 val)
   1476  1.1  christos {
   1477  1.1  christos   bu64 sgnbits = val & 0xffff000000000000ull;
   1478  1.1  christos   val >>= 16;
   1479  1.1  christos   return val | sgnbits;
   1480  1.1  christos }
   1481  1.1  christos 
   1482  1.1  christos static int
   1483  1.1  christos signbits (bu64 val, int size)
   1484  1.1  christos {
   1485  1.1  christos   bu64 mask = (bu64)1 << (size - 1);
   1486  1.1  christos   bu64 bit = val & mask;
   1487  1.1  christos   int count = 0;
   1488  1.1  christos   for (;;)
   1489  1.1  christos     {
   1490  1.1  christos       mask >>= 1;
   1491  1.1  christos       bit >>= 1;
   1492  1.1  christos       if (mask == 0)
   1493  1.1  christos 	break;
   1494  1.1  christos       if ((val & mask) != bit)
   1495  1.1  christos 	break;
   1496  1.1  christos       count++;
   1497  1.1  christos     }
   1498  1.1  christos   if (size == 40)
   1499  1.1  christos     count -= 8;
   1500  1.1  christos 
   1501  1.1  christos   return count;
   1502  1.1  christos }
   1503  1.1  christos 
   1504  1.1  christos /* Extract a 16 or 32 bit value from a 64 bit multiplication result.
   1505  1.1  christos    These 64 bits must be sign- or zero-extended properly from the source
   1506  1.1  christos    we want to extract, either a 32 bit multiply or a 40 bit accumulator.  */
   1507  1.1  christos 
   1508  1.1  christos static bu32
   1509  1.1  christos extract_mult (SIM_CPU *cpu, bu64 res, int mmod, int MM,
   1510  1.1  christos 	      int fullword, bu32 *overflow)
   1511  1.1  christos {
   1512  1.1  christos   if (fullword)
   1513  1.1  christos     switch (mmod)
   1514  1.1  christos       {
   1515  1.1  christos       case 0:
   1516  1.1  christos       case M_IS:
   1517  1.1  christos 	return saturate_s32 (res, overflow);
   1518  1.1  christos       case M_IU:
   1519  1.1  christos 	return saturate_u32 (res, overflow);
   1520  1.1  christos       case M_FU:
   1521  1.1  christos 	if (MM)
   1522  1.1  christos 	  return saturate_s32 (res, overflow);
   1523  1.1  christos 	return saturate_u32 (res, overflow);
   1524  1.1  christos       case M_S2RND:
   1525  1.1  christos       case M_ISS2:
   1526  1.1  christos 	return saturate_s32 (res << 1, overflow);
   1527  1.1  christos       default:
   1528  1.1  christos 	illegal_instruction (cpu);
   1529  1.1  christos       }
   1530  1.1  christos   else
   1531  1.1  christos     switch (mmod)
   1532  1.1  christos       {
   1533  1.1  christos       case 0:
   1534  1.1  christos       case M_W32:
   1535  1.1  christos 	return saturate_s16 (rnd16 (res), overflow);
   1536  1.1  christos       case M_IH:
   1537  1.1  christos 	return saturate_s32 (rnd16 (res), overflow) & 0xFFFF;
   1538  1.1  christos       case M_IS:
   1539  1.1  christos 	return saturate_s16 (res, overflow);
   1540  1.1  christos       case M_FU:
   1541  1.1  christos 	if (MM)
   1542  1.1  christos 	  return saturate_s16 (rnd16 (res), overflow);
   1543  1.1  christos 	return saturate_u16 (rnd16 (res), overflow);
   1544  1.1  christos       case M_IU:
   1545  1.1  christos 	if (MM)
   1546  1.1  christos 	  return saturate_s16 (res, overflow);
   1547  1.1  christos 	return saturate_u16 (res, overflow);
   1548  1.1  christos 
   1549  1.1  christos       case M_T:
   1550  1.1  christos 	return saturate_s16 (trunc16 (res), overflow);
   1551  1.1  christos       case M_TFU:
   1552  1.1  christos 	return saturate_u16 (trunc16 (res), overflow);
   1553  1.1  christos 
   1554  1.1  christos       case M_S2RND:
   1555  1.1  christos 	return saturate_s16 (rnd16 (res << 1), overflow);
   1556  1.1  christos       case M_ISS2:
   1557  1.1  christos 	return saturate_s16 (res << 1, overflow);
   1558  1.1  christos       default:
   1559  1.1  christos 	illegal_instruction (cpu);
   1560  1.1  christos       }
   1561  1.1  christos }
   1562  1.1  christos 
   1563  1.1  christos static bu32
   1564  1.1  christos decode_macfunc (SIM_CPU *cpu, int which, int op, int h0, int h1, int src0,
   1565  1.1  christos 		int src1, int mmod, int MM, int fullword, bu32 *overflow,
   1566  1.1  christos 		bu32 *neg)
   1567  1.1  christos {
   1568  1.1  christos   bu64 acc;
   1569  1.1  christos   bu32 sat = 0, tsat, ret;
   1570  1.1  christos 
   1571  1.1  christos   /* Sign extend accumulator if necessary, otherwise unsigned.  */
   1572  1.1  christos   if (mmod == 0 || mmod == M_T || mmod == M_IS || mmod == M_ISS2
   1573  1.1  christos       || mmod == M_S2RND || mmod == M_IH || mmod == M_W32)
   1574  1.1  christos     acc = get_extended_acc (cpu, which);
   1575  1.1  christos   else
   1576  1.1  christos     acc = get_unextended_acc (cpu, which);
   1577  1.1  christos 
   1578  1.1  christos   if (MM && (mmod == M_T || mmod == M_IS || mmod == M_ISS2
   1579  1.1  christos       || mmod == M_S2RND || mmod == M_IH || mmod == M_W32))
   1580  1.1  christos     acc |= -(acc & 0x80000000);
   1581  1.1  christos 
   1582  1.1  christos   if (op != 3)
   1583  1.1  christos     {
   1584  1.1  christos       bu8 sgn0 = (acc >> 31) & 1;
   1585  1.1  christos       /* This can't saturate, so we don't keep track of the sat flag.  */
   1586  1.1  christos       bu64 res = decode_multfunc (cpu, h0, h1, src0, src1, mmod,
   1587  1.1  christos 				  MM, &tsat);
   1588  1.1  christos 
   1589  1.1  christos       /* Perform accumulation.  */
   1590  1.1  christos       switch (op)
   1591  1.1  christos 	{
   1592  1.1  christos 	case 0:
   1593  1.1  christos 	  acc = res;
   1594  1.1  christos 	  sgn0 = (acc >> 31) & 1;
   1595  1.1  christos 	  break;
   1596  1.1  christos 	case 1:
   1597  1.1  christos 	  acc = acc + res;
   1598  1.1  christos 	  break;
   1599  1.1  christos 	case 2:
   1600  1.1  christos 	  acc = acc - res;
   1601  1.1  christos 	  break;
   1602  1.1  christos 	}
   1603  1.1  christos 
   1604  1.1  christos       /* Saturate.  */
   1605  1.1  christos       switch (mmod)
   1606  1.1  christos 	{
   1607  1.1  christos 	case 0:
   1608  1.1  christos 	case M_T:
   1609  1.1  christos 	case M_IS:
   1610  1.1  christos 	case M_ISS2:
   1611  1.1  christos 	case M_S2RND:
   1612  1.1  christos 	  if ((bs64)acc < -((bs64)1 << 39))
   1613  1.1  christos 	    acc = -((bu64)1 << 39), sat = 1;
   1614  1.1  christos 	  else if ((bs64)acc > 0x7fffffffffll)
   1615  1.1  christos 	    acc = 0x7fffffffffull, sat = 1;
   1616  1.1  christos 	  break;
   1617  1.1  christos 	case M_TFU:
   1618  1.1  christos 	  if (!MM && acc > 0xFFFFFFFFFFull)
   1619  1.1  christos 	    acc = 0x0, sat = 1;
   1620  1.1  christos 	  if (MM && acc > 0xFFFFFFFF)
   1621  1.1  christos 	    acc &= 0xFFFFFFFF;
   1622  1.1  christos 	  break;
   1623  1.1  christos 	case M_IU:
   1624  1.1  christos 	  if (acc & 0x8000000000000000ull)
   1625  1.1  christos 	    acc = 0x0, sat = 1;
   1626  1.1  christos 	  if (acc > 0xFFFFFFFFFFull)
   1627  1.1  christos 	    acc &= 0xFFFFFFFFFFull, sat = 1;
   1628  1.1  christos 	  if (MM && acc > 0xFFFFFFFF)
   1629  1.1  christos 	    acc &= 0xFFFFFFFF;
   1630  1.1  christos 	  if (acc & 0x80000000)
   1631  1.1  christos 	    acc |= 0xffffffff00000000ull;
   1632  1.1  christos 	  break;
   1633  1.1  christos 	case M_FU:
   1634  1.1  christos 	  if (!MM && (bs64)acc < 0)
   1635  1.1  christos 	    acc = 0x0, sat = 1;
   1636  1.1  christos 	  if (MM && (bs64)acc < -((bs64)1 << 39))
   1637  1.1  christos 	    acc = -((bu64)1 << 39), sat = 1;
   1638  1.1  christos 	  if (!MM && (bs64)acc > (bs64)0xFFFFFFFFFFll)
   1639  1.1  christos 	    acc = 0xFFFFFFFFFFull, sat = 1;
   1640  1.1  christos 	  if (MM && acc > 0xFFFFFFFFFFull)
   1641  1.1  christos 	    acc &= 0xFFFFFFFFFFull;
   1642  1.1  christos 	  if (MM && acc & 0x80000000)
   1643  1.1  christos 	    acc |= 0xffffffff00000000ull;
   1644  1.1  christos 	  break;
   1645  1.1  christos 	case M_IH:
   1646  1.1  christos 	  if ((bs64)acc < -0x80000000ll)
   1647  1.1  christos 	    acc = -0x80000000ull, sat = 1;
   1648  1.1  christos 	  else if ((bs64)acc >= 0x7fffffffll)
   1649  1.1  christos 	    acc = 0x7fffffffull, sat = 1;
   1650  1.1  christos 	  break;
   1651  1.1  christos 	case M_W32:
   1652  1.1  christos 	  if (sgn0 && (sgn0 != ((acc >> 31) & 1))
   1653  1.1  christos 	      && (((acc >> 32) & 0xFF) == 0xff))
   1654  1.1  christos 	    acc = 0x80000000;
   1655  1.1  christos 	  acc &= 0xffffffff;
   1656  1.1  christos 	  if (acc & 0x80000000)
   1657  1.1  christos 	    acc |= 0xffffffff00000000ull;
   1658  1.1  christos 	  break;
   1659  1.1  christos 	default:
   1660  1.1  christos 	  illegal_instruction (cpu);
   1661  1.1  christos 	}
   1662  1.1  christos 
   1663  1.1  christos       if (acc & 0x8000000000ull)
   1664  1.1  christos 	*neg = 1;
   1665  1.1  christos 
   1666  1.1  christos       STORE (AXREG (which), (acc >> 32) & 0xff);
   1667  1.1  christos       STORE (AWREG (which), acc & 0xffffffff);
   1668  1.1  christos       STORE (ASTATREG (av[which]), sat);
   1669  1.1  christos       if (sat)
   1670  1.1  christos 	STORE (ASTATREG (avs[which]), sat);
   1671  1.1  christos     }
   1672  1.1  christos 
   1673  1.1  christos   ret = extract_mult (cpu, acc, mmod, MM, fullword, overflow);
   1674  1.1  christos 
   1675  1.1  christos   if (!fullword)
   1676  1.1  christos     {
   1677  1.1  christos       if (ret & 0x8000)
   1678  1.1  christos 	*neg = 1;
   1679  1.1  christos     }
   1680  1.1  christos   else
   1681  1.1  christos     {
   1682  1.1  christos       if (ret & 0x80000000)
   1683  1.1  christos 	*neg = 1;
   1684  1.1  christos     }
   1685  1.1  christos 
   1686  1.1  christos   return ret;
   1687  1.1  christos }
   1688  1.1  christos 
   1689  1.1  christos bu32
   1690  1.1  christos hwloop_get_next_pc (SIM_CPU *cpu, bu32 pc, bu32 insn_len)
   1691  1.1  christos {
   1692  1.1  christos   int i;
   1693  1.1  christos 
   1694  1.1  christos   if (insn_len == 0)
   1695  1.1  christos     return pc;
   1696  1.1  christos 
   1697  1.1  christos   /* If our PC has reached the bottom of a hardware loop,
   1698  1.1  christos      move back up to the top of the hardware loop.  */
   1699  1.1  christos   for (i = 1; i >= 0; --i)
   1700  1.1  christos     if (LCREG (i) > 1 && pc == LBREG (i))
   1701  1.1  christos       {
   1702  1.1  christos 	TRACE_BRANCH (cpu, pc, LTREG (i), i, "Hardware loop %i", i);
   1703  1.1  christos 	return LTREG (i);
   1704  1.1  christos       }
   1705  1.1  christos 
   1706  1.1  christos   return pc + insn_len;
   1707  1.1  christos }
   1708  1.1  christos 
   1709  1.1  christos static void
   1710  1.1  christos decode_ProgCtrl_0 (SIM_CPU *cpu, bu16 iw0, bu32 pc)
   1711  1.1  christos {
   1712  1.1  christos   /* ProgCtrl
   1713  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
   1714  1.1  christos      | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |.prgfunc.......|.poprnd........|
   1715  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
   1716  1.1  christos   int poprnd  = ((iw0 >> ProgCtrl_poprnd_bits) & ProgCtrl_poprnd_mask);
   1717  1.1  christos   int prgfunc = ((iw0 >> ProgCtrl_prgfunc_bits) & ProgCtrl_prgfunc_mask);
   1718  1.1  christos 
   1719  1.1  christos   TRACE_EXTRACT (cpu, "%s: poprnd:%i prgfunc:%i", __func__, poprnd, prgfunc);
   1720  1.1  christos 
   1721  1.1  christos   if (prgfunc == 0 && poprnd == 0)
   1722  1.1  christos     {
   1723  1.1  christos       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_nop);
   1724  1.1  christos       TRACE_INSN (cpu, "NOP;");
   1725  1.1  christos     }
   1726  1.1  christos   else if (prgfunc == 1 && poprnd == 0)
   1727  1.1  christos     {
   1728  1.1  christos       bu32 newpc = RETSREG;
   1729  1.1  christos       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
   1730  1.1  christos       TRACE_INSN (cpu, "RTS;");
   1731  1.1  christos       IFETCH_CHECK (newpc);
   1732  1.1  christos       if (INSN_LEN == 8)
   1733  1.1  christos 	illegal_instruction_combination (cpu);
   1734  1.1  christos       TRACE_BRANCH (cpu, pc, newpc, -1, "RTS");
   1735  1.1  christos       SET_PCREG (newpc);
   1736  1.1  christos       BFIN_CPU_STATE.did_jump = true;
   1737  1.1  christos       CYCLE_DELAY = 5;
   1738  1.1  christos     }
   1739  1.1  christos   else if (prgfunc == 1 && poprnd == 1)
   1740  1.1  christos     {
   1741  1.1  christos       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
   1742  1.1  christos       TRACE_INSN (cpu, "RTI;");
   1743  1.1  christos       /* Do not do IFETCH_CHECK here -- LSB has special meaning.  */
   1744  1.1  christos       if (INSN_LEN == 8)
   1745  1.1  christos 	illegal_instruction_combination (cpu);
   1746  1.1  christos       cec_return (cpu, -1);
   1747  1.1  christos       CYCLE_DELAY = 5;
   1748  1.1  christos     }
   1749  1.1  christos   else if (prgfunc == 1 && poprnd == 2)
   1750  1.1  christos     {
   1751  1.1  christos       bu32 newpc = RETXREG;
   1752  1.1  christos       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
   1753  1.1  christos       TRACE_INSN (cpu, "RTX;");
   1754  1.1  christos       /* XXX: Not sure if this is what the hardware does.  */
   1755  1.1  christos       IFETCH_CHECK (newpc);
   1756  1.1  christos       if (INSN_LEN == 8)
   1757  1.1  christos 	illegal_instruction_combination (cpu);
   1758  1.1  christos       cec_return (cpu, IVG_EVX);
   1759  1.1  christos       CYCLE_DELAY = 5;
   1760  1.1  christos     }
   1761  1.1  christos   else if (prgfunc == 1 && poprnd == 3)
   1762  1.1  christos     {
   1763  1.1  christos       bu32 newpc = RETNREG;
   1764  1.1  christos       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
   1765  1.1  christos       TRACE_INSN (cpu, "RTN;");
   1766  1.1  christos       /* XXX: Not sure if this is what the hardware does.  */
   1767  1.1  christos       IFETCH_CHECK (newpc);
   1768  1.1  christos       if (INSN_LEN == 8)
   1769  1.1  christos 	illegal_instruction_combination (cpu);
   1770  1.1  christos       cec_return (cpu, IVG_NMI);
   1771  1.1  christos       CYCLE_DELAY = 5;
   1772  1.1  christos     }
   1773  1.1  christos   else if (prgfunc == 1 && poprnd == 4)
   1774  1.1  christos     {
   1775  1.1  christos       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
   1776  1.1  christos       TRACE_INSN (cpu, "RTE;");
   1777  1.1  christos       if (INSN_LEN == 8)
   1778  1.1  christos 	illegal_instruction_combination (cpu);
   1779  1.1  christos       cec_return (cpu, IVG_EMU);
   1780  1.1  christos       CYCLE_DELAY = 5;
   1781  1.1  christos     }
   1782  1.1  christos   else if (prgfunc == 2 && poprnd == 0)
   1783  1.1  christos     {
   1784  1.1  christos       SIM_DESC sd = CPU_STATE (cpu);
   1785  1.1  christos       sim_events *events = STATE_EVENTS (sd);
   1786  1.1  christos 
   1787  1.1  christos       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_sync);
   1788  1.1  christos       /* XXX: in supervisor mode, utilizes wake up sources
   1789  1.1  christos          in user mode, it's a NOP ...  */
   1790  1.1  christos       TRACE_INSN (cpu, "IDLE;");
   1791  1.1  christos 
   1792  1.1  christos       if (INSN_LEN == 8)
   1793  1.1  christos 	illegal_instruction_combination (cpu);
   1794  1.1  christos 
   1795  1.1  christos       /* Timewarp !  */
   1796  1.1  christos       if (events->queue)
   1797  1.1  christos 	CYCLE_DELAY = events->time_from_event;
   1798  1.1  christos       else
   1799  1.1  christos 	abort (); /* XXX: Should this ever happen ?  */
   1800  1.1  christos     }
   1801  1.1  christos   else if (prgfunc == 2 && poprnd == 3)
   1802  1.1  christos     {
   1803  1.1  christos       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_sync);
   1804  1.1  christos       /* Just NOP it.  */
   1805  1.1  christos       TRACE_INSN (cpu, "CSYNC;");
   1806  1.1  christos       if (INSN_LEN == 8)
   1807  1.1  christos 	illegal_instruction_combination (cpu);
   1808  1.1  christos       CYCLE_DELAY = 10;
   1809  1.1  christos     }
   1810  1.1  christos   else if (prgfunc == 2 && poprnd == 4)
   1811  1.1  christos     {
   1812  1.1  christos       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_sync);
   1813  1.1  christos       /* Just NOP it.  */
   1814  1.1  christos       TRACE_INSN (cpu, "SSYNC;");
   1815  1.1  christos       if (INSN_LEN == 8)
   1816  1.1  christos 	illegal_instruction_combination (cpu);
   1817  1.1  christos 
   1818  1.1  christos       /* Really 10+, but no model info for this.  */
   1819  1.1  christos       CYCLE_DELAY = 10;
   1820  1.1  christos     }
   1821  1.1  christos   else if (prgfunc == 2 && poprnd == 5)
   1822  1.1  christos     {
   1823  1.1  christos       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_cec);
   1824  1.1  christos       TRACE_INSN (cpu, "EMUEXCPT;");
   1825  1.1  christos       if (INSN_LEN == 8)
   1826  1.1  christos 	illegal_instruction_combination (cpu);
   1827  1.1  christos       cec_exception (cpu, VEC_SIM_TRAP);
   1828  1.1  christos     }
   1829  1.1  christos   else if (prgfunc == 3 && poprnd < 8)
   1830  1.1  christos     {
   1831  1.1  christos       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_cec);
   1832  1.1  christos       TRACE_INSN (cpu, "CLI R%i;", poprnd);
   1833  1.1  christos       if (INSN_LEN == 8)
   1834  1.1  christos 	illegal_instruction_combination (cpu);
   1835  1.1  christos       SET_DREG (poprnd, cec_cli (cpu));
   1836  1.1  christos     }
   1837  1.1  christos   else if (prgfunc == 4 && poprnd < 8)
   1838  1.1  christos     {
   1839  1.1  christos       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_cec);
   1840  1.1  christos       TRACE_INSN (cpu, "STI R%i;", poprnd);
   1841  1.1  christos       if (INSN_LEN == 8)
   1842  1.1  christos 	illegal_instruction_combination (cpu);
   1843  1.1  christos       cec_sti (cpu, DREG (poprnd));
   1844  1.1  christos       CYCLE_DELAY = 3;
   1845  1.1  christos     }
   1846  1.1  christos   else if (prgfunc == 5 && poprnd < 8)
   1847  1.1  christos     {
   1848  1.1  christos       bu32 newpc = PREG (poprnd);
   1849  1.1  christos       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
   1850  1.1  christos       TRACE_INSN (cpu, "JUMP (%s);", get_preg_name (poprnd));
   1851  1.1  christos       IFETCH_CHECK (newpc);
   1852  1.1  christos       if (INSN_LEN == 8)
   1853  1.1  christos 	illegal_instruction_combination (cpu);
   1854  1.1  christos       TRACE_BRANCH (cpu, pc, newpc, -1, "JUMP (Preg)");
   1855  1.1  christos       SET_PCREG (newpc);
   1856  1.1  christos       BFIN_CPU_STATE.did_jump = true;
   1857  1.1  christos       PROFILE_BRANCH_TAKEN (cpu);
   1858  1.1  christos       CYCLE_DELAY = 5;
   1859  1.1  christos     }
   1860  1.1  christos   else if (prgfunc == 6 && poprnd < 8)
   1861  1.1  christos     {
   1862  1.1  christos       bu32 newpc = PREG (poprnd);
   1863  1.1  christos       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
   1864  1.1  christos       TRACE_INSN (cpu, "CALL (%s);", get_preg_name (poprnd));
   1865  1.1  christos       IFETCH_CHECK (newpc);
   1866  1.1  christos       if (INSN_LEN == 8)
   1867  1.1  christos 	illegal_instruction_combination (cpu);
   1868  1.1  christos       TRACE_BRANCH (cpu, pc, newpc, -1, "CALL (Preg)");
   1869  1.1  christos       /* If we're at the end of a hardware loop, RETS is going to be
   1870  1.1  christos          the top of the loop rather than the next instruction.  */
   1871  1.1  christos       SET_RETSREG (hwloop_get_next_pc (cpu, pc, 2));
   1872  1.1  christos       SET_PCREG (newpc);
   1873  1.1  christos       BFIN_CPU_STATE.did_jump = true;
   1874  1.1  christos       PROFILE_BRANCH_TAKEN (cpu);
   1875  1.1  christos       CYCLE_DELAY = 5;
   1876  1.1  christos     }
   1877  1.1  christos   else if (prgfunc == 7 && poprnd < 8)
   1878  1.1  christos     {
   1879  1.1  christos       bu32 newpc = pc + PREG (poprnd);
   1880  1.1  christos       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
   1881  1.1  christos       TRACE_INSN (cpu, "CALL (PC + %s);", get_preg_name (poprnd));
   1882  1.1  christos       IFETCH_CHECK (newpc);
   1883  1.1  christos       if (INSN_LEN == 8)
   1884  1.1  christos 	illegal_instruction_combination (cpu);
   1885  1.1  christos       TRACE_BRANCH (cpu, pc, newpc, -1, "CALL (PC + Preg)");
   1886  1.1  christos       SET_RETSREG (hwloop_get_next_pc (cpu, pc, 2));
   1887  1.1  christos       SET_PCREG (newpc);
   1888  1.1  christos       BFIN_CPU_STATE.did_jump = true;
   1889  1.1  christos       PROFILE_BRANCH_TAKEN (cpu);
   1890  1.1  christos       CYCLE_DELAY = 5;
   1891  1.1  christos     }
   1892  1.1  christos   else if (prgfunc == 8 && poprnd < 8)
   1893  1.1  christos     {
   1894  1.1  christos       bu32 newpc = pc + PREG (poprnd);
   1895  1.1  christos       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
   1896  1.1  christos       TRACE_INSN (cpu, "JUMP (PC + %s);", get_preg_name (poprnd));
   1897  1.1  christos       IFETCH_CHECK (newpc);
   1898  1.1  christos       if (INSN_LEN == 8)
   1899  1.1  christos 	illegal_instruction_combination (cpu);
   1900  1.1  christos       TRACE_BRANCH (cpu, pc, newpc, -1, "JUMP (PC + Preg)");
   1901  1.1  christos       SET_PCREG (newpc);
   1902  1.1  christos       BFIN_CPU_STATE.did_jump = true;
   1903  1.1  christos       PROFILE_BRANCH_TAKEN (cpu);
   1904  1.1  christos       CYCLE_DELAY = 5;
   1905  1.1  christos     }
   1906  1.1  christos   else if (prgfunc == 9)
   1907  1.1  christos     {
   1908  1.1  christos       int raise = uimm4 (poprnd);
   1909  1.1  christos       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_cec);
   1910  1.1  christos       TRACE_INSN (cpu, "RAISE %s;", uimm4_str (raise));
   1911  1.1  christos       if (INSN_LEN == 8)
   1912  1.1  christos 	illegal_instruction_combination (cpu);
   1913  1.1  christos       cec_require_supervisor (cpu);
   1914  1.1  christos       if (raise == IVG_IVHW)
   1915  1.1  christos 	cec_hwerr (cpu, HWERR_RAISE_5);
   1916  1.1  christos       else
   1917  1.1  christos 	cec_latch (cpu, raise);
   1918  1.1  christos       CYCLE_DELAY = 3; /* XXX: Only if IVG is unmasked.  */
   1919  1.1  christos     }
   1920  1.1  christos   else if (prgfunc == 10)
   1921  1.1  christos     {
   1922  1.1  christos       int excpt = uimm4 (poprnd);
   1923  1.1  christos       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_cec);
   1924  1.1  christos       TRACE_INSN (cpu, "EXCPT %s;", uimm4_str (excpt));
   1925  1.1  christos       if (INSN_LEN == 8)
   1926  1.1  christos 	illegal_instruction_combination (cpu);
   1927  1.1  christos       cec_exception (cpu, excpt);
   1928  1.1  christos       CYCLE_DELAY = 3;
   1929  1.1  christos     }
   1930  1.1  christos   else if (prgfunc == 11 && poprnd < 6)
   1931  1.1  christos     {
   1932  1.1  christos       bu32 addr = PREG (poprnd);
   1933  1.1  christos       bu8 byte;
   1934  1.1  christos       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_atomic);
   1935  1.1  christos       TRACE_INSN (cpu, "TESTSET (%s);", get_preg_name (poprnd));
   1936  1.1  christos       if (INSN_LEN == 8)
   1937  1.1  christos 	illegal_instruction_combination (cpu);
   1938  1.1  christos       byte = GET_WORD (addr);
   1939  1.1  christos       SET_CCREG (byte == 0);
   1940  1.1  christos       PUT_BYTE (addr, byte | 0x80);
   1941  1.1  christos       /* Also includes memory stalls, but we don't model that.  */
   1942  1.1  christos       CYCLE_DELAY = 2;
   1943  1.1  christos     }
   1944  1.1  christos   else
   1945  1.1  christos     illegal_instruction (cpu);
   1946  1.1  christos }
   1947  1.1  christos 
   1948  1.1  christos static void
   1949  1.1  christos decode_CaCTRL_0 (SIM_CPU *cpu, bu16 iw0)
   1950  1.1  christos {
   1951  1.1  christos   /* CaCTRL
   1952  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
   1953  1.1  christos      | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 |.a.|.op....|.reg.......|
   1954  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
   1955  1.1  christos   int a   = ((iw0 >> CaCTRL_a_bits) & CaCTRL_a_mask);
   1956  1.1  christos   int op  = ((iw0 >> CaCTRL_op_bits) & CaCTRL_op_mask);
   1957  1.1  christos   int reg = ((iw0 >> CaCTRL_reg_bits) & CaCTRL_reg_mask);
   1958  1.1  christos   bu32 preg = PREG (reg);
   1959  1.1  christos   const char * const sinsn[] = { "PREFETCH", "FLUSHINV", "FLUSH", "IFLUSH", };
   1960  1.1  christos 
   1961  1.1  christos   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_CaCTRL);
   1962  1.1  christos   TRACE_EXTRACT (cpu, "%s: a:%i op:%i reg:%i", __func__, a, op, reg);
   1963  1.1  christos   TRACE_INSN (cpu, "%s [%s%s];", sinsn[op], get_preg_name (reg), a ? "++" : "");
   1964  1.1  christos 
   1965  1.1  christos   if (INSN_LEN == 8)
   1966  1.1  christos     /* None of these can be part of a parallel instruction.  */
   1967  1.1  christos     illegal_instruction_combination (cpu);
   1968  1.1  christos 
   1969  1.1  christos   /* No cache simulation, so these are (mostly) all NOPs.
   1970  1.1  christos      XXX: The hardware takes care of masking to cache lines, but need
   1971  1.1  christos      to check behavior of the post increment.  Should we be aligning
   1972  1.1  christos      the value to the cache line before adding the cache line size, or
   1973  1.1  christos      do we just add the cache line size ?  */
   1974  1.1  christos   if (op == 0)
   1975  1.1  christos     {	/* PREFETCH  */
   1976  1.1  christos       mmu_check_cache_addr (cpu, preg, false, false);
   1977  1.1  christos     }
   1978  1.1  christos   else if (op == 1)
   1979  1.1  christos     {	/* FLUSHINV  */
   1980  1.1  christos       mmu_check_cache_addr (cpu, preg, true, false);
   1981  1.1  christos     }
   1982  1.1  christos   else if (op == 2)
   1983  1.1  christos     {	/* FLUSH  */
   1984  1.1  christos       mmu_check_cache_addr (cpu, preg, true, false);
   1985  1.1  christos     }
   1986  1.1  christos   else if (op == 3)
   1987  1.1  christos     {	/* IFLUSH  */
   1988  1.1  christos       mmu_check_cache_addr (cpu, preg, false, true);
   1989  1.1  christos     }
   1990  1.1  christos 
   1991  1.1  christos   if (a)
   1992  1.1  christos     SET_PREG (reg, preg + BFIN_L1_CACHE_BYTES);
   1993  1.1  christos }
   1994  1.1  christos 
   1995  1.1  christos static void
   1996  1.1  christos decode_PushPopReg_0 (SIM_CPU *cpu, bu16 iw0)
   1997  1.1  christos {
   1998  1.1  christos   /* PushPopReg
   1999  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
   2000  1.1  christos      | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |.W.|.grp.......|.reg.......|
   2001  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
   2002  1.1  christos   int W   = ((iw0 >> PushPopReg_W_bits) & PushPopReg_W_mask);
   2003  1.1  christos   int grp = ((iw0 >> PushPopReg_grp_bits) & PushPopReg_grp_mask);
   2004  1.1  christos   int reg = ((iw0 >> PushPopReg_reg_bits) & PushPopReg_reg_mask);
   2005  1.1  christos   const char *reg_name = get_allreg_name (grp, reg);
   2006  1.1  christos   bu32 value;
   2007  1.1  christos   bu32 sp = SPREG;
   2008  1.1  christos 
   2009  1.1  christos   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_PushPopReg);
   2010  1.1  christos   TRACE_EXTRACT (cpu, "%s: W:%i grp:%i reg:%i", __func__, W, grp, reg);
   2011  1.1  christos   TRACE_DECODE (cpu, "%s: reg:%s", __func__, reg_name);
   2012  1.1  christos 
   2013  1.1  christos   /* Can't push/pop reserved registers  */
   2014  1.1  christos   if (reg_is_reserved (grp, reg))
   2015  1.1  christos     illegal_instruction (cpu);
   2016  1.1  christos 
   2017  1.1  christos   if (W == 0)
   2018  1.1  christos     {
   2019  1.1  christos       /* Dreg and Preg are not supported by this instruction.  */
   2020  1.1  christos       if (grp == 0 || grp == 1)
   2021  1.1  christos 	illegal_instruction (cpu);
   2022  1.1  christos       TRACE_INSN (cpu, "%s = [SP++];", reg_name);
   2023  1.1  christos       /* Can't pop USP while in userspace.  */
   2024  1.1  christos       if (INSN_LEN == 8 || (grp == 7 && reg == 0 && cec_is_user_mode(cpu)))
   2025  1.1  christos 	illegal_instruction_combination (cpu);
   2026  1.1  christos       /* XXX: The valid register check is in reg_write(), so we might
   2027  1.1  christos               incorrectly do a GET_LONG() here ...  */
   2028  1.1  christos       value = GET_LONG (sp);
   2029  1.1  christos       reg_write (cpu, grp, reg, value);
   2030  1.1  christos       if (grp == 7 && reg == 3)
   2031  1.1  christos 	cec_pop_reti (cpu);
   2032  1.1  christos 
   2033  1.1  christos       sp += 4;
   2034  1.1  christos     }
   2035  1.1  christos   else
   2036  1.1  christos     {
   2037  1.1  christos       TRACE_INSN (cpu, "[--SP] = %s;", reg_name);
   2038  1.1  christos       /* Can't push SP.  */
   2039  1.1  christos       if (INSN_LEN == 8 || (grp == 1 && reg == 6))
   2040  1.1  christos 	illegal_instruction_combination (cpu);
   2041  1.1  christos 
   2042  1.1  christos       sp -= 4;
   2043  1.1  christos       value = reg_read (cpu, grp, reg);
   2044  1.1  christos       if (grp == 7 && reg == 3)
   2045  1.1  christos 	cec_push_reti (cpu);
   2046  1.1  christos 
   2047  1.1  christos       PUT_LONG (sp, value);
   2048  1.1  christos     }
   2049  1.1  christos 
   2050  1.1  christos   /* Note: SP update must be delayed until after all reads/writes; see
   2051  1.1  christos            comments in decode_PushPopMultiple_0() for more info.  */
   2052  1.1  christos   SET_SPREG (sp);
   2053  1.1  christos }
   2054  1.1  christos 
   2055  1.1  christos static void
   2056  1.1  christos decode_PushPopMultiple_0 (SIM_CPU *cpu, bu16 iw0)
   2057  1.1  christos {
   2058  1.1  christos   /* PushPopMultiple
   2059  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
   2060  1.1  christos      | 0 | 0 | 0 | 0 | 0 | 1 | 0 |.d.|.p.|.W.|.dr........|.pr........|
   2061  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
   2062  1.1  christos   int p  = ((iw0 >> PushPopMultiple_p_bits) & PushPopMultiple_p_mask);
   2063  1.1  christos   int d  = ((iw0 >> PushPopMultiple_d_bits) & PushPopMultiple_d_mask);
   2064  1.1  christos   int W  = ((iw0 >> PushPopMultiple_W_bits) & PushPopMultiple_W_mask);
   2065  1.1  christos   int dr = ((iw0 >> PushPopMultiple_dr_bits) & PushPopMultiple_dr_mask);
   2066  1.1  christos   int pr = ((iw0 >> PushPopMultiple_pr_bits) & PushPopMultiple_pr_mask);
   2067  1.1  christos   int i;
   2068  1.1  christos   bu32 sp = SPREG;
   2069  1.1  christos 
   2070  1.1  christos   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_PushPopMultiple);
   2071  1.1  christos   TRACE_EXTRACT (cpu, "%s: d:%i p:%i W:%i dr:%i pr:%i",
   2072  1.1  christos 		 __func__, d, p, W, dr, pr);
   2073  1.1  christos 
   2074  1.1  christos   if ((d == 0 && p == 0) || (p && imm5 (pr) > 5)
   2075  1.1  christos       || (d && !p && pr) || (p && !d && dr))
   2076  1.1  christos     illegal_instruction (cpu);
   2077  1.1  christos 
   2078  1.1  christos   if (W == 1)
   2079  1.1  christos     {
   2080  1.1  christos       if (d && p)
   2081  1.1  christos 	TRACE_INSN (cpu, "[--SP] = (R7:%i, P5:%i);", dr, pr);
   2082  1.1  christos       else if (d)
   2083  1.1  christos 	TRACE_INSN (cpu, "[--SP] = (R7:%i);", dr);
   2084  1.1  christos       else
   2085  1.1  christos 	TRACE_INSN (cpu, "[--SP] = (P5:%i);", pr);
   2086  1.1  christos 
   2087  1.1  christos       if (d)
   2088  1.1  christos 	for (i = dr; i < 8; i++)
   2089  1.1  christos 	  {
   2090  1.1  christos 	    sp -= 4;
   2091  1.1  christos 	    PUT_LONG (sp, DREG (i));
   2092  1.1  christos 	  }
   2093  1.1  christos       if (p)
   2094  1.1  christos 	for (i = pr; i < 6; i++)
   2095  1.1  christos 	  {
   2096  1.1  christos 	    sp -= 4;
   2097  1.1  christos 	    PUT_LONG (sp, PREG (i));
   2098  1.1  christos 	  }
   2099  1.1  christos 
   2100  1.1  christos       CYCLE_DELAY = 14;
   2101  1.1  christos     }
   2102  1.1  christos   else
   2103  1.1  christos     {
   2104  1.1  christos       if (d && p)
   2105  1.1  christos 	TRACE_INSN (cpu, "(R7:%i, P5:%i) = [SP++];", dr, pr);
   2106  1.1  christos       else if (d)
   2107  1.1  christos 	TRACE_INSN (cpu, "(R7:%i) = [SP++];", dr);
   2108  1.1  christos       else
   2109  1.1  christos 	TRACE_INSN (cpu, "(P5:%i) = [SP++];", pr);
   2110  1.1  christos 
   2111  1.1  christos       if (p)
   2112  1.1  christos 	for (i = 5; i >= pr; i--)
   2113  1.1  christos 	  {
   2114  1.1  christos 	    SET_PREG (i, GET_LONG (sp));
   2115  1.1  christos 	    sp += 4;
   2116  1.1  christos 	  }
   2117  1.1  christos       if (d)
   2118  1.1  christos 	for (i = 7; i >= dr; i--)
   2119  1.1  christos 	  {
   2120  1.1  christos 	    SET_DREG (i, GET_LONG (sp));
   2121  1.1  christos 	    sp += 4;
   2122  1.1  christos 	  }
   2123  1.1  christos 
   2124  1.1  christos       CYCLE_DELAY = 11;
   2125  1.1  christos     }
   2126  1.1  christos 
   2127  1.1  christos   /* Note: SP update must be delayed until after all reads/writes so that
   2128  1.1  christos            if an exception does occur, the insn may be re-executed as the
   2129  1.1  christos            SP has not yet changed.  */
   2130  1.1  christos   SET_SPREG (sp);
   2131  1.1  christos }
   2132  1.1  christos 
   2133  1.1  christos static void
   2134  1.1  christos decode_ccMV_0 (SIM_CPU *cpu, bu16 iw0)
   2135  1.1  christos {
   2136  1.1  christos   /* ccMV
   2137  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
   2138  1.1  christos      | 0 | 0 | 0 | 0 | 0 | 1 | 1 |.T.|.d.|.s.|.dst.......|.src.......|
   2139  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
   2140  1.1  christos   int s  = ((iw0 >> CCmv_s_bits) & CCmv_s_mask);
   2141  1.1  christos   int d  = ((iw0 >> CCmv_d_bits) & CCmv_d_mask);
   2142  1.1  christos   int T  = ((iw0 >> CCmv_T_bits) & CCmv_T_mask);
   2143  1.1  christos   int src = ((iw0 >> CCmv_src_bits) & CCmv_src_mask);
   2144  1.1  christos   int dst = ((iw0 >> CCmv_dst_bits) & CCmv_dst_mask);
   2145  1.1  christos   int cond = T ? CCREG : ! CCREG;
   2146  1.1  christos 
   2147  1.1  christos   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ccMV);
   2148  1.1  christos   TRACE_EXTRACT (cpu, "%s: T:%i d:%i s:%i dst:%i src:%i",
   2149  1.1  christos 		 __func__, T, d, s, dst, src);
   2150  1.1  christos 
   2151  1.1  christos   TRACE_INSN (cpu, "IF %sCC %s = %s;", T ? "" : "! ",
   2152  1.1  christos 	      get_allreg_name (d, dst),
   2153  1.1  christos 	      get_allreg_name (s, src));
   2154  1.1  christos   if (INSN_LEN == 8)
   2155  1.1  christos     illegal_instruction_combination (cpu);
   2156  1.1  christos 
   2157  1.1  christos   if (cond)
   2158  1.1  christos     reg_write (cpu, d, dst, reg_read (cpu, s, src));
   2159  1.1  christos }
   2160  1.1  christos 
   2161  1.1  christos static void
   2162  1.1  christos decode_CCflag_0 (SIM_CPU *cpu, bu16 iw0)
   2163  1.1  christos {
   2164  1.1  christos   /* CCflag
   2165  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
   2166  1.1  christos      | 0 | 0 | 0 | 0 | 1 |.I.|.opc.......|.G.|.y.........|.x.........|
   2167  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
   2168  1.1  christos   int x = ((iw0 >> CCflag_x_bits) & CCflag_x_mask);
   2169  1.1  christos   int y = ((iw0 >> CCflag_y_bits) & CCflag_y_mask);
   2170  1.1  christos   int I = ((iw0 >> CCflag_I_bits) & CCflag_I_mask);
   2171  1.1  christos   int G = ((iw0 >> CCflag_G_bits) & CCflag_G_mask);
   2172  1.1  christos   int opc = ((iw0 >> CCflag_opc_bits) & CCflag_opc_mask);
   2173  1.1  christos 
   2174  1.1  christos   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_CCflag);
   2175  1.1  christos   TRACE_EXTRACT (cpu, "%s: I:%i opc:%i G:%i y:%i x:%i",
   2176  1.1  christos 		 __func__, I, opc, G, y, x);
   2177  1.1  christos 
   2178  1.1  christos   if (opc > 4)
   2179  1.1  christos     {
   2180  1.1  christos       bs64 acc0 = get_extended_acc (cpu, 0);
   2181  1.1  christos       bs64 acc1 = get_extended_acc (cpu, 1);
   2182  1.1  christos       bs64 diff = acc0 - acc1;
   2183  1.1  christos 
   2184  1.1  christos       if (x != 0 || y != 0)
   2185  1.1  christos 	illegal_instruction (cpu);
   2186  1.1  christos 
   2187  1.1  christos       if (opc == 5 && I == 0 && G == 0)
   2188  1.1  christos 	{
   2189  1.1  christos 	  TRACE_INSN (cpu, "CC = A0 == A1;");
   2190  1.1  christos 	  if (INSN_LEN == 8)
   2191  1.1  christos 	    illegal_instruction_combination (cpu);
   2192  1.1  christos 	  SET_CCREG (acc0 == acc1);
   2193  1.1  christos 	}
   2194  1.1  christos       else if (opc == 6 && I == 0 && G == 0)
   2195  1.1  christos 	{
   2196  1.1  christos 	  TRACE_INSN (cpu, "CC = A0 < A1");
   2197  1.1  christos 	  if (INSN_LEN == 8)
   2198  1.1  christos 	    illegal_instruction_combination (cpu);
   2199  1.1  christos 	  SET_CCREG (acc0 < acc1);
   2200  1.1  christos 	}
   2201  1.1  christos       else if (opc == 7 && I == 0 && G == 0)
   2202  1.1  christos 	{
   2203  1.1  christos 	  TRACE_INSN (cpu, "CC = A0 <= A1");
   2204  1.1  christos 	  if (INSN_LEN == 8)
   2205  1.1  christos 	    illegal_instruction_combination (cpu);
   2206  1.1  christos 	  SET_CCREG (acc0 <= acc1);
   2207  1.1  christos 	}
   2208  1.1  christos       else
   2209  1.1  christos 	illegal_instruction (cpu);
   2210  1.1  christos 
   2211  1.1  christos       SET_ASTATREG (az, diff == 0);
   2212  1.1  christos       SET_ASTATREG (an, diff < 0);
   2213  1.1  christos       SET_ASTATREG (ac0, (bu40)acc1 <= (bu40)acc0);
   2214  1.1  christos     }
   2215  1.1  christos   else
   2216  1.1  christos     {
   2217  1.1  christos       int issigned = opc < 3;
   2218  1.1  christos       const char *sign = issigned ? "" : " (IU)";
   2219  1.1  christos       bu32 srcop = G ? PREG (x) : DREG (x);
   2220  1.1  christos       char s = G ? 'P' : 'R';
   2221  1.1  christos       bu32 dstop = I ? (issigned ? imm3 (y) : uimm3 (y)) : G ? PREG (y) : DREG (y);
   2222  1.1  christos       const char *op;
   2223  1.1  christos       char d = G ? 'P' : 'R';
   2224  1.1  christos       int flgs = srcop >> 31;
   2225  1.1  christos       int flgo = dstop >> 31;
   2226  1.1  christos 
   2227  1.1  christos       bu32 result = srcop - dstop;
   2228  1.1  christos       int cc;
   2229  1.1  christos       int flgn = result >> 31;
   2230  1.1  christos       int overflow = (flgs ^ flgo) & (flgn ^ flgs);
   2231  1.1  christos       int az = result == 0;
   2232  1.1  christos       int ac0 = dstop <= srcop;
   2233  1.1  christos       int an;
   2234  1.1  christos       if (issigned)
   2235  1.1  christos 	an = (flgn && !overflow) || (!flgn && overflow);
   2236  1.1  christos       else
   2237  1.1  christos 	an = dstop > srcop;
   2238  1.1  christos 
   2239  1.1  christos       switch (opc)
   2240  1.1  christos 	{
   2241  1.1  christos 	default: /* Shutup useless gcc warnings.  */
   2242  1.1  christos 	case 0: /* signed  */
   2243  1.1  christos 	  op = "==";
   2244  1.1  christos 	  cc = az;
   2245  1.1  christos 	  break;
   2246  1.1  christos 	case 1:	/* signed  */
   2247  1.1  christos 	  op = "<";
   2248  1.1  christos 	  cc = an;
   2249  1.1  christos 	  break;
   2250  1.1  christos 	case 2:	/* signed  */
   2251  1.1  christos 	  op = "<=";
   2252  1.1  christos 	  cc = an || az;
   2253  1.1  christos 	  break;
   2254  1.1  christos 	case 3:	/* unsigned  */
   2255  1.1  christos 	  op = "<";
   2256  1.1  christos 	  cc = !ac0;
   2257  1.1  christos 	  break;
   2258  1.1  christos 	case 4:	/* unsigned  */
   2259  1.1  christos 	  op = "<=";
   2260  1.1  christos 	  cc = !ac0 || az;
   2261  1.1  christos 	  break;
   2262  1.1  christos 	}
   2263  1.1  christos 
   2264  1.1  christos       if (I)
   2265  1.1  christos 	TRACE_INSN (cpu, "CC = %c%i %s %s%s;", s, x, op,
   2266  1.1  christos 		    issigned ? imm3_str (y) : uimm3_str (y), sign);
   2267  1.1  christos       else
   2268  1.1  christos 	{
   2269  1.1  christos 	  TRACE_DECODE (cpu, "%s %c%i:%x %c%i:%x", __func__,
   2270  1.1  christos 			s, x, srcop,  d, y, dstop);
   2271  1.1  christos 	  TRACE_INSN (cpu, "CC = %c%i %s %c%i%s;", s, x, op, d, y, sign);
   2272  1.1  christos 	}
   2273  1.1  christos 
   2274  1.1  christos       SET_CCREG (cc);
   2275  1.1  christos       /* Pointer compares only touch CC.  */
   2276  1.1  christos       if (!G)
   2277  1.1  christos 	{
   2278  1.1  christos 	  SET_ASTATREG (az, az);
   2279  1.1  christos 	  SET_ASTATREG (an, an);
   2280  1.1  christos 	  SET_ASTATREG (ac0, ac0);
   2281  1.1  christos 	}
   2282  1.1  christos     }
   2283  1.1  christos }
   2284  1.1  christos 
   2285  1.1  christos static void
   2286  1.1  christos decode_CC2dreg_0 (SIM_CPU *cpu, bu16 iw0)
   2287  1.1  christos {
   2288  1.1  christos   /* CC2dreg
   2289  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
   2290  1.1  christos      | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |.op....|.reg.......|
   2291  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
   2292  1.1  christos   int op  = ((iw0 >> CC2dreg_op_bits) & CC2dreg_op_mask);
   2293  1.1  christos   int reg = ((iw0 >> CC2dreg_reg_bits) & CC2dreg_reg_mask);
   2294  1.1  christos 
   2295  1.1  christos   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_CC2dreg);
   2296  1.1  christos   TRACE_EXTRACT (cpu, "%s: op:%i reg:%i", __func__, op, reg);
   2297  1.1  christos 
   2298  1.1  christos   if (op == 0)
   2299  1.1  christos     {
   2300  1.1  christos       TRACE_INSN (cpu, "R%i = CC;", reg);
   2301  1.1  christos       if (INSN_LEN == 8)
   2302  1.1  christos 	illegal_instruction_combination (cpu);
   2303  1.1  christos       SET_DREG (reg, CCREG);
   2304  1.1  christos     }
   2305  1.1  christos   else if (op == 1)
   2306  1.1  christos     {
   2307  1.1  christos       TRACE_INSN (cpu, "CC = R%i;", reg);
   2308  1.1  christos       if (INSN_LEN == 8)
   2309  1.1  christos 	illegal_instruction_combination (cpu);
   2310  1.1  christos       SET_CCREG (DREG (reg) != 0);
   2311  1.1  christos     }
   2312  1.1  christos   else if (op == 3 && reg == 0)
   2313  1.1  christos     {
   2314  1.1  christos       TRACE_INSN (cpu, "CC = !CC;");
   2315  1.1  christos       if (INSN_LEN == 8)
   2316  1.1  christos 	illegal_instruction_combination (cpu);
   2317  1.1  christos       SET_CCREG (!CCREG);
   2318  1.1  christos     }
   2319  1.1  christos   else
   2320  1.1  christos     illegal_instruction (cpu);
   2321  1.1  christos }
   2322  1.1  christos 
   2323  1.1  christos static void
   2324  1.1  christos decode_CC2stat_0 (SIM_CPU *cpu, bu16 iw0)
   2325  1.1  christos {
   2326  1.1  christos   /* CC2stat
   2327  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
   2328  1.1  christos      | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |.D.|.op....|.cbit..............|
   2329  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
   2330  1.1  christos   int D    = ((iw0 >> CC2stat_D_bits) & CC2stat_D_mask);
   2331  1.1  christos   int op   = ((iw0 >> CC2stat_op_bits) & CC2stat_op_mask);
   2332  1.1  christos   int cbit = ((iw0 >> CC2stat_cbit_bits) & CC2stat_cbit_mask);
   2333  1.1  christos   bu32 pval;
   2334  1.1  christos 
   2335  1.1  christos   const char * const op_names[] = { "", "|", "&", "^" } ;
   2336  1.1  christos 
   2337  1.1  christos   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_CC2stat);
   2338  1.1  christos   TRACE_EXTRACT (cpu, "%s: D:%i op:%i cbit:%i", __func__, D, op, cbit);
   2339  1.1  christos 
   2340  1.1  christos   TRACE_INSN (cpu, "%s %s= %s;", D ? astat_names[cbit] : "CC",
   2341  1.1  christos 	      op_names[op], D ? "CC" : astat_names[cbit]);
   2342  1.1  christos 
   2343  1.1  christos   /* CC = CC; is invalid.  */
   2344  1.1  christos   if (cbit == 5)
   2345  1.1  christos     illegal_instruction (cpu);
   2346  1.1  christos 
   2347  1.1  christos   if (INSN_LEN == 8)
   2348  1.1  christos     illegal_instruction_combination (cpu);
   2349  1.1  christos 
   2350  1.1  christos   pval = !!(ASTAT & (1 << cbit));
   2351  1.1  christos   if (D == 0)
   2352  1.1  christos     switch (op)
   2353  1.1  christos       {
   2354  1.1  christos       case 0: SET_CCREG (pval); break;
   2355  1.1  christos       case 1: SET_CCREG (CCREG | pval); break;
   2356  1.1  christos       case 2: SET_CCREG (CCREG & pval); break;
   2357  1.1  christos       case 3: SET_CCREG (CCREG ^ pval); break;
   2358  1.1  christos       }
   2359  1.1  christos   else
   2360  1.1  christos     {
   2361  1.1  christos       switch (op)
   2362  1.1  christos 	{
   2363  1.1  christos 	case 0: pval  = CCREG; break;
   2364  1.1  christos 	case 1: pval |= CCREG; break;
   2365  1.1  christos 	case 2: pval &= CCREG; break;
   2366  1.1  christos 	case 3: pval ^= CCREG; break;
   2367  1.1  christos 	}
   2368  1.1  christos       TRACE_REGISTER (cpu, "wrote ASTAT[%s] = %i", astat_names[cbit], pval);
   2369  1.1  christos       SET_ASTAT ((ASTAT & ~(1 << cbit)) | (pval << cbit));
   2370  1.1  christos     }
   2371  1.1  christos }
   2372  1.1  christos 
   2373  1.1  christos static void
   2374  1.1  christos decode_BRCC_0 (SIM_CPU *cpu, bu16 iw0, bu32 pc)
   2375  1.1  christos {
   2376  1.1  christos   /* BRCC
   2377  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
   2378  1.1  christos      | 0 | 0 | 0 | 1 |.T.|.B.|.offset................................|
   2379  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
   2380  1.1  christos   int B = ((iw0 >> BRCC_B_bits) & BRCC_B_mask);
   2381  1.1  christos   int T = ((iw0 >> BRCC_T_bits) & BRCC_T_mask);
   2382  1.1  christos   int offset = ((iw0 >> BRCC_offset_bits) & BRCC_offset_mask);
   2383  1.1  christos   int cond = T ? CCREG : ! CCREG;
   2384  1.1  christos   int pcrel = pcrel10 (offset);
   2385  1.1  christos 
   2386  1.1  christos   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_BRCC);
   2387  1.1  christos   TRACE_EXTRACT (cpu, "%s: T:%i B:%i offset:%#x", __func__, T, B, offset);
   2388  1.1  christos   TRACE_DECODE (cpu, "%s: pcrel10:%#x", __func__, pcrel);
   2389  1.1  christos 
   2390  1.1  christos   TRACE_INSN (cpu, "IF %sCC JUMP %#x%s;", T ? "" : "! ",
   2391  1.1  christos 	      pcrel, B ? " (bp)" : "");
   2392  1.1  christos 
   2393  1.1  christos   if (INSN_LEN == 8)
   2394  1.1  christos     illegal_instruction_combination (cpu);
   2395  1.1  christos 
   2396  1.1  christos   if (cond)
   2397  1.1  christos     {
   2398  1.1  christos       bu32 newpc = pc + pcrel;
   2399  1.1  christos       TRACE_BRANCH (cpu, pc, newpc, -1, "Conditional JUMP");
   2400  1.1  christos       SET_PCREG (newpc);
   2401  1.1  christos       BFIN_CPU_STATE.did_jump = true;
   2402  1.1  christos       PROFILE_BRANCH_TAKEN (cpu);
   2403  1.1  christos       CYCLE_DELAY = B ? 5 : 9;
   2404  1.1  christos     }
   2405  1.1  christos   else
   2406  1.1  christos     {
   2407  1.1  christos       PROFILE_BRANCH_UNTAKEN (cpu);
   2408  1.1  christos       CYCLE_DELAY = B ? 9 : 1;
   2409  1.1  christos     }
   2410  1.1  christos }
   2411  1.1  christos 
   2412  1.1  christos static void
   2413  1.1  christos decode_UJUMP_0 (SIM_CPU *cpu, bu16 iw0, bu32 pc)
   2414  1.1  christos {
   2415  1.1  christos   /* UJUMP
   2416  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
   2417  1.1  christos      | 0 | 0 | 1 | 0 |.offset........................................|
   2418  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
   2419  1.1  christos   int offset = ((iw0 >> UJump_offset_bits) & UJump_offset_mask);
   2420  1.1  christos   int pcrel = pcrel12 (offset);
   2421  1.1  christos   bu32 newpc = pc + pcrel;
   2422  1.1  christos 
   2423  1.1  christos   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_UJUMP);
   2424  1.1  christos   TRACE_EXTRACT (cpu, "%s: offset:%#x", __func__, offset);
   2425  1.1  christos   TRACE_DECODE (cpu, "%s: pcrel12:%#x", __func__, pcrel);
   2426  1.1  christos 
   2427  1.1  christos   TRACE_INSN (cpu, "JUMP.S %#x;", pcrel);
   2428  1.1  christos 
   2429  1.1  christos   if (INSN_LEN == 8)
   2430  1.1  christos     illegal_instruction_combination (cpu);
   2431  1.1  christos 
   2432  1.1  christos   TRACE_BRANCH (cpu, pc, newpc, -1, "JUMP.S");
   2433  1.1  christos 
   2434  1.1  christos   SET_PCREG (newpc);
   2435  1.1  christos   BFIN_CPU_STATE.did_jump = true;
   2436  1.1  christos   PROFILE_BRANCH_TAKEN (cpu);
   2437  1.1  christos   CYCLE_DELAY = 5;
   2438  1.1  christos }
   2439  1.1  christos 
   2440  1.1  christos static void
   2441  1.1  christos decode_REGMV_0 (SIM_CPU *cpu, bu16 iw0)
   2442  1.1  christos {
   2443  1.1  christos   /* REGMV
   2444  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
   2445  1.1  christos      | 0 | 0 | 1 | 1 |.gd........|.gs........|.dst.......|.src.......|
   2446  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
   2447  1.1  christos   int gs  = ((iw0 >> RegMv_gs_bits) & RegMv_gs_mask);
   2448  1.1  christos   int gd  = ((iw0 >> RegMv_gd_bits) & RegMv_gd_mask);
   2449  1.1  christos   int src = ((iw0 >> RegMv_src_bits) & RegMv_src_mask);
   2450  1.1  christos   int dst = ((iw0 >> RegMv_dst_bits) & RegMv_dst_mask);
   2451  1.1  christos   const char *srcreg_name = get_allreg_name (gs, src);
   2452  1.1  christos   const char *dstreg_name = get_allreg_name (gd, dst);
   2453  1.1  christos 
   2454  1.1  christos   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_REGMV);
   2455  1.1  christos   TRACE_EXTRACT (cpu, "%s: gd:%i gs:%i dst:%i src:%i",
   2456  1.1  christos 		 __func__, gd, gs, dst, src);
   2457  1.1  christos   TRACE_DECODE (cpu, "%s: dst:%s src:%s", __func__, dstreg_name, srcreg_name);
   2458  1.1  christos 
   2459  1.1  christos   TRACE_INSN (cpu, "%s = %s;", dstreg_name, srcreg_name);
   2460  1.1  christos 
   2461  1.1  christos   /* Reserved slots cannot be a src/dst.  */
   2462  1.1  christos   if (reg_is_reserved (gs, src) || reg_is_reserved (gd, dst))
   2463  1.1  christos     goto invalid_move;
   2464  1.1  christos 
   2465  1.1  christos   /* Standard register moves.  */
   2466  1.1  christos   if ((gs < 2)						/* Dregs/Pregs src  */
   2467  1.1  christos       || (gd < 2)					/* Dregs/Pregs dst  */
   2468  1.1  christos       || (gs == 4 && src < 4)				/* Accumulators src  */
   2469  1.1  christos       || (gd == 4 && dst < 4 && (gs < 4))		/* Accumulators dst  */
   2470  1.1  christos       || (gs == 7 && src == 7 && !(gd == 4 && dst < 4))	/* EMUDAT src  */
   2471  1.1  christos       || (gd == 7 && dst == 7)) 			/* EMUDAT dst  */
   2472  1.1  christos     goto valid_move;
   2473  1.1  christos 
   2474  1.1  christos   /* dareg = dareg (IMBL)  */
   2475  1.1  christos   if (gs < 4 && gd < 4)
   2476  1.1  christos     goto valid_move;
   2477  1.1  christos 
   2478  1.1  christos   /* USP can be src to sysregs, but not dagregs.  */
   2479  1.1  christos   if ((gs == 7 && src == 0) && (gd >= 4))
   2480  1.1  christos     goto valid_move;
   2481  1.1  christos 
   2482  1.1  christos   /* USP can move between genregs (only check Accumulators).  */
   2483  1.1  christos   if (((gs == 7 && src == 0) && (gd == 4 && dst < 4))
   2484  1.1  christos       || ((gd == 7 && dst == 0) && (gs == 4 && src < 4)))
   2485  1.1  christos     goto valid_move;
   2486  1.1  christos 
   2487  1.1  christos   /* Still here ?  Invalid reg pair.  */
   2488  1.1  christos  invalid_move:
   2489  1.1  christos   illegal_instruction (cpu);
   2490  1.1  christos 
   2491  1.1  christos  valid_move:
   2492  1.1  christos   reg_write (cpu, gd, dst, reg_read (cpu, gs, src));
   2493  1.1  christos }
   2494  1.1  christos 
   2495  1.1  christos static void
   2496  1.1  christos decode_ALU2op_0 (SIM_CPU *cpu, bu16 iw0)
   2497  1.1  christos {
   2498  1.1  christos   /* ALU2op
   2499  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
   2500  1.1  christos      | 0 | 1 | 0 | 0 | 0 | 0 |.opc...........|.src.......|.dst.......|
   2501  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
   2502  1.1  christos   int src = ((iw0 >> ALU2op_src_bits) & ALU2op_src_mask);
   2503  1.1  christos   int opc = ((iw0 >> ALU2op_opc_bits) & ALU2op_opc_mask);
   2504  1.1  christos   int dst = ((iw0 >> ALU2op_dst_bits) & ALU2op_dst_mask);
   2505  1.1  christos 
   2506  1.1  christos   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ALU2op);
   2507  1.1  christos   TRACE_EXTRACT (cpu, "%s: opc:%i src:%i dst:%i", __func__, opc, src, dst);
   2508  1.1  christos 
   2509  1.1  christos   if (opc == 0)
   2510  1.1  christos     {
   2511  1.1  christos       TRACE_INSN (cpu, "R%i >>>= R%i;", dst, src);
   2512  1.1  christos       SET_DREG (dst, ashiftrt (cpu, DREG (dst), DREG (src), 32));
   2513  1.1  christos     }
   2514  1.1  christos   else if (opc == 1)
   2515  1.1  christos     {
   2516  1.1  christos       bu32 val;
   2517  1.1  christos       TRACE_INSN (cpu, "R%i >>= R%i;", dst, src);
   2518  1.1  christos       if (DREG (src) <= 0x1F)
   2519  1.1  christos 	val = lshiftrt (cpu, DREG (dst), DREG (src), 32);
   2520  1.1  christos       else
   2521  1.1  christos 	val = 0;
   2522  1.1  christos       SET_DREG (dst, val);
   2523  1.1  christos     }
   2524  1.1  christos   else if (opc == 2)
   2525  1.1  christos     {
   2526  1.1  christos       TRACE_INSN (cpu, "R%i <<= R%i;", dst, src);
   2527  1.1  christos       SET_DREG (dst, lshift (cpu, DREG (dst), DREG (src), 32, 0));
   2528  1.1  christos     }
   2529  1.1  christos   else if (opc == 3)
   2530  1.1  christos     {
   2531  1.1  christos       TRACE_INSN (cpu, "R%i *= R%i;", dst, src);
   2532  1.1  christos       SET_DREG (dst, DREG (dst) * DREG (src));
   2533  1.1  christos       CYCLE_DELAY = 3;
   2534  1.1  christos     }
   2535  1.1  christos   else if (opc == 4)
   2536  1.1  christos     {
   2537  1.1  christos       TRACE_INSN (cpu, "R%i = (R%i + R%i) << 1;", dst, dst, src);
   2538  1.1  christos       SET_DREG (dst, add_and_shift (cpu, DREG (dst), DREG (src), 1));
   2539  1.1  christos     }
   2540  1.1  christos   else if (opc == 5)
   2541  1.1  christos     {
   2542  1.1  christos       TRACE_INSN (cpu, "R%i = (R%i + R%i) << 2;", dst, dst, src);
   2543  1.1  christos       SET_DREG (dst, add_and_shift (cpu, DREG (dst), DREG (src), 2));
   2544  1.1  christos     }
   2545  1.1  christos   else if (opc == 8)
   2546  1.1  christos     {
   2547  1.1  christos       TRACE_INSN (cpu, "DIVQ ( R%i, R%i );", dst, src);
   2548  1.1  christos       SET_DREG (dst, divq (cpu, DREG (dst), (bu16)DREG (src)));
   2549  1.1  christos     }
   2550  1.1  christos   else if (opc == 9)
   2551  1.1  christos     {
   2552  1.1  christos       TRACE_INSN (cpu, "DIVS ( R%i, R%i );", dst, src);
   2553  1.1  christos       SET_DREG (dst, divs (cpu, DREG (dst), (bu16)DREG (src)));
   2554  1.1  christos     }
   2555  1.1  christos   else if (opc == 10)
   2556  1.1  christos     {
   2557  1.1  christos       TRACE_INSN (cpu, "R%i = R%i.L (X);", dst, src);
   2558  1.1  christos       SET_DREG (dst, (bs32) (bs16) DREG (src));
   2559  1.1  christos       setflags_logical (cpu, DREG (dst));
   2560  1.1  christos     }
   2561  1.1  christos   else if (opc == 11)
   2562  1.1  christos     {
   2563  1.1  christos       TRACE_INSN (cpu, "R%i = R%i.L (Z);", dst, src);
   2564  1.1  christos       SET_DREG (dst, (bu32) (bu16) DREG (src));
   2565  1.1  christos       setflags_logical (cpu, DREG (dst));
   2566  1.1  christos     }
   2567  1.1  christos   else if (opc == 12)
   2568  1.1  christos     {
   2569  1.1  christos       TRACE_INSN (cpu, "R%i = R%i.B (X);", dst, src);
   2570  1.1  christos       SET_DREG (dst, (bs32) (bs8) DREG (src));
   2571  1.1  christos       setflags_logical (cpu, DREG (dst));
   2572  1.1  christos     }
   2573  1.1  christos   else if (opc == 13)
   2574  1.1  christos     {
   2575  1.1  christos       TRACE_INSN (cpu, "R%i = R%i.B (Z);", dst, src);
   2576  1.1  christos       SET_DREG (dst, (bu32) (bu8) DREG (src));
   2577  1.1  christos       setflags_logical (cpu, DREG (dst));
   2578  1.1  christos     }
   2579  1.1  christos   else if (opc == 14)
   2580  1.1  christos     {
   2581  1.1  christos       bu32 val = DREG (src);
   2582  1.1  christos       TRACE_INSN (cpu, "R%i = - R%i;", dst, src);
   2583  1.1  christos       SET_DREG (dst, -val);
   2584  1.1  christos       setflags_nz (cpu, DREG (dst));
   2585  1.1  christos       SET_ASTATREG (v, val == 0x80000000);
   2586  1.1  christos       if (ASTATREG (v))
   2587  1.1  christos 	SET_ASTATREG (vs, 1);
   2588  1.1  christos       SET_ASTATREG (ac0, val == 0x0);
   2589  1.1  christos       /* XXX: Documentation isn't entirely clear about av0 and av1.  */
   2590  1.1  christos     }
   2591  1.1  christos   else if (opc == 15)
   2592  1.1  christos     {
   2593  1.1  christos       TRACE_INSN (cpu, "R%i = ~ R%i;", dst, src);
   2594  1.1  christos       SET_DREG (dst, ~DREG (src));
   2595  1.1  christos       setflags_logical (cpu, DREG (dst));
   2596  1.1  christos     }
   2597  1.1  christos   else
   2598  1.1  christos     illegal_instruction (cpu);
   2599  1.1  christos }
   2600  1.1  christos 
   2601  1.1  christos static void
   2602  1.1  christos decode_PTR2op_0 (SIM_CPU *cpu, bu16 iw0)
   2603  1.1  christos {
   2604  1.1  christos   /* PTR2op
   2605  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
   2606  1.1  christos      | 0 | 1 | 0 | 0 | 0 | 1 | 0 |.opc.......|.src.......|.dst.......|
   2607  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
   2608  1.1  christos   int src = ((iw0 >> PTR2op_src_bits) & PTR2op_dst_mask);
   2609  1.1  christos   int opc = ((iw0 >> PTR2op_opc_bits) & PTR2op_opc_mask);
   2610  1.1  christos   int dst = ((iw0 >> PTR2op_dst_bits) & PTR2op_dst_mask);
   2611  1.1  christos   const char *src_name = get_preg_name (src);
   2612  1.1  christos   const char *dst_name = get_preg_name (dst);
   2613  1.1  christos 
   2614  1.1  christos   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_PTR2op);
   2615  1.1  christos   TRACE_EXTRACT (cpu, "%s: opc:%i src:%i dst:%i", __func__, opc, src, dst);
   2616  1.1  christos 
   2617  1.1  christos   if (opc == 0)
   2618  1.1  christos     {
   2619  1.1  christos       TRACE_INSN (cpu, "%s -= %s", dst_name, src_name);
   2620  1.1  christos       SET_PREG (dst, PREG (dst) - PREG (src));
   2621  1.1  christos     }
   2622  1.1  christos   else if (opc == 1)
   2623  1.1  christos     {
   2624  1.1  christos       TRACE_INSN (cpu, "%s = %s << 2", dst_name, src_name);
   2625  1.1  christos       SET_PREG (dst, PREG (src) << 2);
   2626  1.1  christos     }
   2627  1.1  christos   else if (opc == 3)
   2628  1.1  christos     {
   2629  1.1  christos       TRACE_INSN (cpu, "%s = %s >> 2", dst_name, src_name);
   2630  1.1  christos       SET_PREG (dst, PREG (src) >> 2);
   2631  1.1  christos     }
   2632  1.1  christos   else if (opc == 4)
   2633  1.1  christos     {
   2634  1.1  christos       TRACE_INSN (cpu, "%s = %s >> 1", dst_name, src_name);
   2635  1.1  christos       SET_PREG (dst, PREG (src) >> 1);
   2636  1.1  christos     }
   2637  1.1  christos   else if (opc == 5)
   2638  1.1  christos     {
   2639  1.1  christos       TRACE_INSN (cpu, "%s += %s (BREV)", dst_name, src_name);
   2640  1.1  christos       SET_PREG (dst, add_brev (PREG (dst), PREG (src)));
   2641  1.1  christos     }
   2642  1.1  christos   else if (opc == 6)
   2643  1.1  christos     {
   2644  1.1  christos       TRACE_INSN (cpu, "%s = (%s + %s) << 1", dst_name, dst_name, src_name);
   2645  1.1  christos       SET_PREG (dst, (PREG (dst) + PREG (src)) << 1);
   2646  1.1  christos     }
   2647  1.1  christos   else if (opc == 7)
   2648  1.1  christos     {
   2649  1.1  christos       TRACE_INSN (cpu, "%s = (%s + %s) << 2", dst_name, dst_name, src_name);
   2650  1.1  christos       SET_PREG (dst, (PREG (dst) + PREG (src)) << 2);
   2651  1.1  christos     }
   2652  1.1  christos   else
   2653  1.1  christos     illegal_instruction (cpu);
   2654  1.1  christos }
   2655  1.1  christos 
   2656  1.1  christos static void
   2657  1.1  christos decode_LOGI2op_0 (SIM_CPU *cpu, bu16 iw0)
   2658  1.1  christos {
   2659  1.1  christos   /* LOGI2op
   2660  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
   2661  1.1  christos      | 0 | 1 | 0 | 0 | 1 |.opc.......|.src...............|.dst.......|
   2662  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
   2663  1.1  christos   int src = ((iw0 >> LOGI2op_src_bits) & LOGI2op_src_mask);
   2664  1.1  christos   int opc = ((iw0 >> LOGI2op_opc_bits) & LOGI2op_opc_mask);
   2665  1.1  christos   int dst = ((iw0 >> LOGI2op_dst_bits) & LOGI2op_dst_mask);
   2666  1.1  christos   int uimm = uimm5 (src);
   2667  1.1  christos   const char *uimm_str = uimm5_str (uimm);
   2668  1.1  christos 
   2669  1.1  christos   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LOGI2op);
   2670  1.1  christos   TRACE_EXTRACT (cpu, "%s: opc:%i src:%i dst:%i", __func__, opc, src, dst);
   2671  1.1  christos   TRACE_DECODE (cpu, "%s: uimm5:%#x", __func__, uimm);
   2672  1.1  christos 
   2673  1.1  christos   if (opc == 0)
   2674  1.1  christos     {
   2675  1.1  christos       TRACE_INSN (cpu, "CC = ! BITTST (R%i, %s);", dst, uimm_str);
   2676  1.1  christos       if (INSN_LEN == 8)
   2677  1.1  christos 	illegal_instruction_combination (cpu);
   2678  1.1  christos       SET_CCREG ((~DREG (dst) >> uimm) & 1);
   2679  1.1  christos     }
   2680  1.1  christos   else if (opc == 1)
   2681  1.1  christos     {
   2682  1.1  christos       TRACE_INSN (cpu, "CC = BITTST (R%i, %s);", dst, uimm_str);
   2683  1.1  christos       if (INSN_LEN == 8)
   2684  1.1  christos 	illegal_instruction_combination (cpu);
   2685  1.1  christos       SET_CCREG ((DREG (dst) >> uimm) & 1);
   2686  1.1  christos     }
   2687  1.1  christos   else if (opc == 2)
   2688  1.1  christos     {
   2689  1.1  christos       TRACE_INSN (cpu, "BITSET (R%i, %s);", dst, uimm_str);
   2690  1.1  christos       if (INSN_LEN == 8)
   2691  1.1  christos 	illegal_instruction_combination (cpu);
   2692  1.1  christos       SET_DREG (dst, DREG (dst) | (1 << uimm));
   2693  1.1  christos       setflags_logical (cpu, DREG (dst));
   2694  1.1  christos     }
   2695  1.1  christos   else if (opc == 3)
   2696  1.1  christos     {
   2697  1.1  christos       TRACE_INSN (cpu, "BITTGL (R%i, %s);", dst, uimm_str);
   2698  1.1  christos       if (INSN_LEN == 8)
   2699  1.1  christos 	illegal_instruction_combination (cpu);
   2700  1.1  christos       SET_DREG (dst, DREG (dst) ^ (1 << uimm));
   2701  1.1  christos       setflags_logical (cpu, DREG (dst));
   2702  1.1  christos     }
   2703  1.1  christos   else if (opc == 4)
   2704  1.1  christos     {
   2705  1.1  christos       TRACE_INSN (cpu, "BITCLR (R%i, %s);", dst, uimm_str);
   2706  1.1  christos       if (INSN_LEN == 8)
   2707  1.1  christos 	illegal_instruction_combination (cpu);
   2708  1.1  christos       SET_DREG (dst, DREG (dst) & ~(1 << uimm));
   2709  1.1  christos       setflags_logical (cpu, DREG (dst));
   2710  1.1  christos     }
   2711  1.1  christos   else if (opc == 5)
   2712  1.1  christos     {
   2713  1.1  christos       TRACE_INSN (cpu, "R%i >>>= %s;", dst, uimm_str);
   2714  1.1  christos       if (INSN_LEN == 8)
   2715  1.1  christos 	illegal_instruction_combination (cpu);
   2716  1.1  christos       SET_DREG (dst, ashiftrt (cpu, DREG (dst), uimm, 32));
   2717  1.1  christos     }
   2718  1.1  christos   else if (opc == 6)
   2719  1.1  christos     {
   2720  1.1  christos       TRACE_INSN (cpu, "R%i >>= %s;", dst, uimm_str);
   2721  1.1  christos       if (INSN_LEN == 8)
   2722  1.1  christos 	illegal_instruction_combination (cpu);
   2723  1.1  christos       SET_DREG (dst, lshiftrt (cpu, DREG (dst), uimm, 32));
   2724  1.1  christos     }
   2725  1.1  christos   else if (opc == 7)
   2726  1.1  christos     {
   2727  1.1  christos       TRACE_INSN (cpu, "R%i <<= %s;", dst, uimm_str);
   2728  1.1  christos       if (INSN_LEN == 8)
   2729  1.1  christos 	illegal_instruction_combination (cpu);
   2730  1.1  christos       SET_DREG (dst, lshift (cpu, DREG (dst), uimm, 32, 0));
   2731  1.1  christos     }
   2732  1.1  christos }
   2733  1.1  christos 
   2734  1.1  christos static void
   2735  1.1  christos decode_COMP3op_0 (SIM_CPU *cpu, bu16 iw0)
   2736  1.1  christos {
   2737  1.1  christos   /* COMP3op
   2738  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
   2739  1.1  christos      | 0 | 1 | 0 | 1 |.opc.......|.dst.......|.src1......|.src0......|
   2740  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
   2741  1.1  christos   int opc  = ((iw0 >> COMP3op_opc_bits) & COMP3op_opc_mask);
   2742  1.1  christos   int dst  = ((iw0 >> COMP3op_dst_bits) & COMP3op_dst_mask);
   2743  1.1  christos   int src0 = ((iw0 >> COMP3op_src0_bits) & COMP3op_src0_mask);
   2744  1.1  christos   int src1 = ((iw0 >> COMP3op_src1_bits) & COMP3op_src1_mask);
   2745  1.1  christos 
   2746  1.1  christos   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_COMP3op);
   2747  1.1  christos   TRACE_EXTRACT (cpu, "%s: opc:%i dst:%i src1:%i src0:%i",
   2748  1.1  christos 		 __func__, opc, dst, src1, src0);
   2749  1.1  christos 
   2750  1.1  christos   if (opc == 0)
   2751  1.1  christos     {
   2752  1.1  christos       TRACE_INSN (cpu, "R%i = R%i + R%i;", dst, src0, src1);
   2753  1.1  christos       SET_DREG (dst, add32 (cpu, DREG (src0), DREG (src1), 1, 0));
   2754  1.1  christos     }
   2755  1.1  christos   else if (opc == 1)
   2756  1.1  christos     {
   2757  1.1  christos       TRACE_INSN (cpu, "R%i = R%i - R%i;", dst, src0, src1);
   2758  1.1  christos       SET_DREG (dst, sub32 (cpu, DREG (src0), DREG (src1), 1, 0, 0));
   2759  1.1  christos     }
   2760  1.1  christos   else if (opc == 2)
   2761  1.1  christos     {
   2762  1.1  christos       TRACE_INSN (cpu, "R%i = R%i & R%i;", dst, src0, src1);
   2763  1.1  christos       SET_DREG (dst, DREG (src0) & DREG (src1));
   2764  1.1  christos       setflags_logical (cpu, DREG (dst));
   2765  1.1  christos     }
   2766  1.1  christos   else if (opc == 3)
   2767  1.1  christos     {
   2768  1.1  christos       TRACE_INSN (cpu, "R%i = R%i | R%i;", dst, src0, src1);
   2769  1.1  christos       SET_DREG (dst, DREG (src0) | DREG (src1));
   2770  1.1  christos       setflags_logical (cpu, DREG (dst));
   2771  1.1  christos     }
   2772  1.1  christos   else if (opc == 4)
   2773  1.1  christos     {
   2774  1.1  christos       TRACE_INSN (cpu, "R%i = R%i ^ R%i;", dst, src0, src1);
   2775  1.1  christos       SET_DREG (dst, DREG (src0) ^ DREG (src1));
   2776  1.1  christos       setflags_logical (cpu, DREG (dst));
   2777  1.1  christos     }
   2778  1.1  christos   else
   2779  1.1  christos     {
   2780  1.1  christos       int shift = opc - 5;
   2781  1.1  christos       const char *dst_name = get_preg_name (dst);
   2782  1.1  christos       const char *src0_name = get_preg_name (src0);
   2783  1.1  christos       const char *src1_name = get_preg_name (src1);
   2784  1.1  christos 
   2785  1.1  christos       /* If src0 == src1 this is disassembled as a shift by 1, but this
   2786  1.1  christos          distinction doesn't matter for our purposes.  */
   2787  1.1  christos       if (shift)
   2788  1.1  christos 	TRACE_INSN (cpu, "%s = (%s + %s) << %#x;",
   2789  1.1  christos 		    dst_name, src0_name, src1_name, shift);
   2790  1.1  christos       else
   2791  1.1  christos 	TRACE_INSN (cpu, "%s = %s + %s",
   2792  1.1  christos 		    dst_name, src0_name, src1_name);
   2793  1.1  christos       SET_PREG (dst, PREG (src0) + (PREG (src1) << shift));
   2794  1.1  christos     }
   2795  1.1  christos }
   2796  1.1  christos 
   2797  1.1  christos static void
   2798  1.1  christos decode_COMPI2opD_0 (SIM_CPU *cpu, bu16 iw0)
   2799  1.1  christos {
   2800  1.1  christos   /* COMPI2opD
   2801  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
   2802  1.1  christos      | 0 | 1 | 1 | 0 | 0 |.op|..src......................|.dst.......|
   2803  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
   2804  1.1  christos   int op  = ((iw0 >> COMPI2opD_op_bits) & COMPI2opD_op_mask);
   2805  1.1  christos   int dst = ((iw0 >> COMPI2opD_dst_bits) & COMPI2opD_dst_mask);
   2806  1.1  christos   int src = ((iw0 >> COMPI2opD_src_bits) & COMPI2opD_src_mask);
   2807  1.1  christos   int imm = imm7 (src);
   2808  1.1  christos 
   2809  1.1  christos   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_COMPI2opD);
   2810  1.1  christos   TRACE_EXTRACT (cpu, "%s: op:%i src:%i dst:%i", __func__, op, src, dst);
   2811  1.1  christos   TRACE_DECODE (cpu, "%s: imm7:%#x", __func__, imm);
   2812  1.1  christos 
   2813  1.1  christos   if (op == 0)
   2814  1.1  christos     {
   2815  1.1  christos       TRACE_INSN (cpu, "R%i = %s (X);", dst, imm7_str (imm));
   2816  1.1  christos       SET_DREG (dst, imm);
   2817  1.1  christos     }
   2818  1.1  christos   else if (op == 1)
   2819  1.1  christos     {
   2820  1.1  christos       TRACE_INSN (cpu, "R%i += %s;", dst, imm7_str (imm));
   2821  1.1  christos       SET_DREG (dst, add32 (cpu, DREG (dst), imm, 1, 0));
   2822  1.1  christos     }
   2823  1.1  christos }
   2824  1.1  christos 
   2825  1.1  christos static void
   2826  1.1  christos decode_COMPI2opP_0 (SIM_CPU *cpu, bu16 iw0)
   2827  1.1  christos {
   2828  1.1  christos   /* COMPI2opP
   2829  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
   2830  1.1  christos      | 0 | 1 | 1 | 0 | 1 |.op|.src.......................|.dst.......|
   2831  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
   2832  1.1  christos   int op  = ((iw0 >> COMPI2opP_op_bits) & COMPI2opP_op_mask);
   2833  1.1  christos   int src = ((iw0 >> COMPI2opP_src_bits) & COMPI2opP_src_mask);
   2834  1.1  christos   int dst = ((iw0 >> COMPI2opP_dst_bits) & COMPI2opP_dst_mask);
   2835  1.1  christos   int imm = imm7 (src);
   2836  1.1  christos   const char *dst_name = get_preg_name (dst);
   2837  1.1  christos 
   2838  1.1  christos   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_COMPI2opP);
   2839  1.1  christos   TRACE_EXTRACT (cpu, "%s: op:%i src:%i dst:%i", __func__, op, src, dst);
   2840  1.1  christos   TRACE_DECODE (cpu, "%s: imm:%#x", __func__, imm);
   2841  1.1  christos 
   2842  1.1  christos   if (op == 0)
   2843  1.1  christos     {
   2844  1.1  christos       TRACE_INSN (cpu, "%s = %s;", dst_name, imm7_str (imm));
   2845  1.1  christos       SET_PREG (dst, imm);
   2846  1.1  christos     }
   2847  1.1  christos   else if (op == 1)
   2848  1.1  christos     {
   2849  1.1  christos       TRACE_INSN (cpu, "%s += %s;", dst_name, imm7_str (imm));
   2850  1.1  christos       SET_PREG (dst, PREG (dst) + imm);
   2851  1.1  christos     }
   2852  1.1  christos }
   2853  1.1  christos 
   2854  1.1  christos static void
   2855  1.1  christos decode_LDSTpmod_0 (SIM_CPU *cpu, bu16 iw0)
   2856  1.1  christos {
   2857  1.1  christos   /* LDSTpmod
   2858  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
   2859  1.1  christos      | 1 | 0 | 0 | 0 |.W.|.aop...|.reg.......|.idx.......|.ptr.......|
   2860  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
   2861  1.1  christos   int W   = ((iw0 >> LDSTpmod_W_bits) & LDSTpmod_W_mask);
   2862  1.1  christos   int aop = ((iw0 >> LDSTpmod_aop_bits) & LDSTpmod_aop_mask);
   2863  1.1  christos   int idx = ((iw0 >> LDSTpmod_idx_bits) & LDSTpmod_idx_mask);
   2864  1.1  christos   int ptr = ((iw0 >> LDSTpmod_ptr_bits) & LDSTpmod_ptr_mask);
   2865  1.1  christos   int reg = ((iw0 >> LDSTpmod_reg_bits) & LDSTpmod_reg_mask);
   2866  1.1  christos   const char *ptr_name = get_preg_name (ptr);
   2867  1.1  christos   const char *idx_name = get_preg_name (idx);
   2868  1.1  christos   bu32 addr, val;
   2869  1.1  christos 
   2870  1.1  christos   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LDSTpmod);
   2871  1.1  christos   TRACE_EXTRACT (cpu, "%s: W:%i aop:%i reg:%i idx:%i ptr:%i",
   2872  1.1  christos 		 __func__, W, aop, reg, idx, ptr);
   2873  1.1  christos 
   2874  1.1  christos   if (aop == 1 && W == 0 && idx == ptr)
   2875  1.1  christos     {
   2876  1.1  christos       TRACE_INSN (cpu, "R%i.L = W[%s];", reg, ptr_name);
   2877  1.1  christos       addr = PREG (ptr);
   2878  1.1  christos       val = GET_WORD (addr);
   2879  1.1  christos       STORE (DREG (reg), (DREG (reg) & 0xFFFF0000) | val);
   2880  1.1  christos     }
   2881  1.1  christos   else if (aop == 2 && W == 0 && idx == ptr)
   2882  1.1  christos     {
   2883  1.1  christos       TRACE_INSN (cpu, "R%i.H = W[%s];", reg, ptr_name);
   2884  1.1  christos       addr = PREG (ptr);
   2885  1.1  christos       val = GET_WORD (addr);
   2886  1.1  christos       STORE (DREG (reg), (DREG (reg) & 0xFFFF) | (val << 16));
   2887  1.1  christos     }
   2888  1.1  christos   else if (aop == 1 && W == 1 && idx == ptr)
   2889  1.1  christos     {
   2890  1.1  christos       TRACE_INSN (cpu, "W[%s] = R%i.L;", ptr_name, reg);
   2891  1.1  christos       addr = PREG (ptr);
   2892  1.1  christos       PUT_WORD (addr, DREG (reg));
   2893  1.1  christos     }
   2894  1.1  christos   else if (aop == 2 && W == 1 && idx == ptr)
   2895  1.1  christos     {
   2896  1.1  christos       TRACE_INSN (cpu, "W[%s] = R%i.H;", ptr_name, reg);
   2897  1.1  christos       addr = PREG (ptr);
   2898  1.1  christos       PUT_WORD (addr, DREG (reg) >> 16);
   2899  1.1  christos     }
   2900  1.1  christos   else if (aop == 0 && W == 0)
   2901  1.1  christos     {
   2902  1.1  christos       TRACE_INSN (cpu, "R%i = [%s ++ %s];", reg, ptr_name, idx_name);
   2903  1.1  christos       addr = PREG (ptr);
   2904  1.1  christos       val = GET_LONG (addr);
   2905  1.1  christos       STORE (DREG (reg), val);
   2906  1.1  christos       if (ptr != idx)
   2907  1.1  christos 	STORE (PREG (ptr), addr + PREG (idx));
   2908  1.1  christos     }
   2909  1.1  christos   else if (aop == 1 && W == 0)
   2910  1.1  christos     {
   2911  1.1  christos       TRACE_INSN (cpu, "R%i.L = W[%s ++ %s];", reg, ptr_name, idx_name);
   2912  1.1  christos       addr = PREG (ptr);
   2913  1.1  christos       val = GET_WORD (addr);
   2914  1.1  christos       STORE (DREG (reg), (DREG (reg) & 0xFFFF0000) | val);
   2915  1.1  christos       if (ptr != idx)
   2916  1.1  christos 	STORE (PREG (ptr), addr + PREG (idx));
   2917  1.1  christos     }
   2918  1.1  christos   else if (aop == 2 && W == 0)
   2919  1.1  christos     {
   2920  1.1  christos       TRACE_INSN (cpu, "R%i.H = W[%s ++ %s];", reg, ptr_name, idx_name);
   2921  1.1  christos       addr = PREG (ptr);
   2922  1.1  christos       val = GET_WORD (addr);
   2923  1.1  christos       STORE (DREG (reg), (DREG (reg) & 0xFFFF) | (val << 16));
   2924  1.1  christos       if (ptr != idx)
   2925  1.1  christos 	STORE (PREG (ptr), addr + PREG (idx));
   2926  1.1  christos     }
   2927  1.1  christos   else if (aop == 3 && W == 0)
   2928  1.1  christos     {
   2929  1.1  christos       TRACE_INSN (cpu, "R%i = W[%s ++ %s] (Z);", reg, ptr_name, idx_name);
   2930  1.1  christos       addr = PREG (ptr);
   2931  1.1  christos       val = GET_WORD (addr);
   2932  1.1  christos       STORE (DREG (reg), val);
   2933  1.1  christos       if (ptr != idx)
   2934  1.1  christos 	STORE (PREG (ptr), addr + PREG (idx));
   2935  1.1  christos     }
   2936  1.1  christos   else if (aop == 3 && W == 1)
   2937  1.1  christos     {
   2938  1.1  christos       TRACE_INSN (cpu, "R%i = W[%s ++ %s] (X);", reg, ptr_name, idx_name);
   2939  1.1  christos       addr = PREG (ptr);
   2940  1.1  christos       val = GET_WORD (addr);
   2941  1.1  christos       STORE (DREG (reg), (bs32) (bs16) val);
   2942  1.1  christos       if (ptr != idx)
   2943  1.1  christos 	STORE (PREG (ptr), addr + PREG (idx));
   2944  1.1  christos     }
   2945  1.1  christos   else if (aop == 0 && W == 1)
   2946  1.1  christos     {
   2947  1.1  christos       TRACE_INSN (cpu, "[%s ++ %s] = R%i;", ptr_name, idx_name, reg);
   2948  1.1  christos       addr = PREG (ptr);
   2949  1.1  christos       PUT_LONG (addr, DREG (reg));
   2950  1.1  christos       if (ptr != idx)
   2951  1.1  christos 	STORE (PREG (ptr), addr + PREG (idx));
   2952  1.1  christos     }
   2953  1.1  christos   else if (aop == 1 && W == 1)
   2954  1.1  christos     {
   2955  1.1  christos       TRACE_INSN (cpu, "W[%s ++ %s] = R%i.L;", ptr_name, idx_name, reg);
   2956  1.1  christos       addr = PREG (ptr);
   2957  1.1  christos       PUT_WORD (addr, DREG (reg));
   2958  1.1  christos       if (ptr != idx)
   2959  1.1  christos 	STORE (PREG (ptr), addr + PREG (idx));
   2960  1.1  christos     }
   2961  1.1  christos   else if (aop == 2 && W == 1)
   2962  1.1  christos     {
   2963  1.1  christos       TRACE_INSN (cpu, "W[%s ++ %s] = R%i.H;", ptr_name, idx_name, reg);
   2964  1.1  christos       addr = PREG (ptr);
   2965  1.1  christos       PUT_WORD (addr, DREG (reg) >> 16);
   2966  1.1  christos       if (ptr != idx)
   2967  1.1  christos 	STORE (PREG (ptr), addr + PREG (idx));
   2968  1.1  christos     }
   2969  1.1  christos   else
   2970  1.1  christos     illegal_instruction (cpu);
   2971  1.1  christos }
   2972  1.1  christos 
   2973  1.1  christos static void
   2974  1.1  christos decode_dagMODim_0 (SIM_CPU *cpu, bu16 iw0)
   2975  1.1  christos {
   2976  1.1  christos   /* dagMODim
   2977  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
   2978  1.1  christos      | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 0 |.br| 1 | 1 |.op|.m.....|.i.....|
   2979  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
   2980  1.1  christos   int i  = ((iw0 >> DagMODim_i_bits) & DagMODim_i_mask);
   2981  1.1  christos   int m  = ((iw0 >> DagMODim_m_bits) & DagMODim_m_mask);
   2982  1.1  christos   int br = ((iw0 >> DagMODim_br_bits) & DagMODim_br_mask);
   2983  1.1  christos   int op = ((iw0 >> DagMODim_op_bits) & DagMODim_op_mask);
   2984  1.1  christos 
   2985  1.1  christos   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dagMODim);
   2986  1.1  christos   TRACE_EXTRACT (cpu, "%s: br:%i op:%i m:%i i:%i", __func__, br, op, m, i);
   2987  1.1  christos 
   2988  1.1  christos   if (op == 0 && br == 1)
   2989  1.1  christos     {
   2990  1.1  christos       TRACE_INSN (cpu, "I%i += M%i (BREV);", i, m);
   2991  1.1  christos       SET_IREG (i, add_brev (IREG (i), MREG (m)));
   2992  1.1  christos     }
   2993  1.1  christos   else if (op == 0)
   2994  1.1  christos     {
   2995  1.1  christos       TRACE_INSN (cpu, "I%i += M%i;", i, m);
   2996  1.1  christos       dagadd (cpu, i, MREG (m));
   2997  1.1  christos     }
   2998  1.1  christos   else if (op == 1 && br == 0)
   2999  1.1  christos     {
   3000  1.1  christos       TRACE_INSN (cpu, "I%i -= M%i;", i, m);
   3001  1.1  christos       dagsub (cpu, i, MREG (m));
   3002  1.1  christos     }
   3003  1.1  christos   else
   3004  1.1  christos     illegal_instruction (cpu);
   3005  1.1  christos }
   3006  1.1  christos 
   3007  1.1  christos static void
   3008  1.1  christos decode_dagMODik_0 (SIM_CPU *cpu, bu16 iw0)
   3009  1.1  christos {
   3010  1.1  christos   /* dagMODik
   3011  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
   3012  1.1  christos      | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 0 |.op....|.i.....|
   3013  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
   3014  1.1  christos   int i  = ((iw0 >> DagMODik_i_bits) & DagMODik_i_mask);
   3015  1.1  christos   int op = ((iw0 >> DagMODik_op_bits) & DagMODik_op_mask);
   3016  1.1  christos 
   3017  1.1  christos   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dagMODik);
   3018  1.1  christos   TRACE_EXTRACT (cpu, "%s: op:%i i:%i", __func__, op, i);
   3019  1.1  christos 
   3020  1.1  christos   if (op == 0)
   3021  1.1  christos     {
   3022  1.1  christos       TRACE_INSN (cpu, "I%i += 2;", i);
   3023  1.1  christos       dagadd (cpu, i, 2);
   3024  1.1  christos     }
   3025  1.1  christos   else if (op == 1)
   3026  1.1  christos     {
   3027  1.1  christos       TRACE_INSN (cpu, "I%i -= 2;", i);
   3028  1.1  christos       dagsub (cpu, i, 2);
   3029  1.1  christos     }
   3030  1.1  christos   else if (op == 2)
   3031  1.1  christos     {
   3032  1.1  christos       TRACE_INSN (cpu, "I%i += 4;", i);
   3033  1.1  christos       dagadd (cpu, i, 4);
   3034  1.1  christos     }
   3035  1.1  christos   else if (op == 3)
   3036  1.1  christos     {
   3037  1.1  christos       TRACE_INSN (cpu, "I%i -= 4;", i);
   3038  1.1  christos       dagsub (cpu, i, 4);
   3039  1.1  christos     }
   3040  1.1  christos   else
   3041  1.1  christos     illegal_instruction (cpu);
   3042  1.1  christos }
   3043  1.1  christos 
   3044  1.1  christos static void
   3045  1.1  christos decode_dspLDST_0 (SIM_CPU *cpu, bu16 iw0)
   3046  1.1  christos {
   3047  1.1  christos   /* dspLDST
   3048  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
   3049  1.1  christos      | 1 | 0 | 0 | 1 | 1 | 1 |.W.|.aop...|.m.....|.i.....|.reg.......|
   3050  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
   3051  1.1  christos   int i   = ((iw0 >> DspLDST_i_bits) & DspLDST_i_mask);
   3052  1.1  christos   int m   = ((iw0 >> DspLDST_m_bits) & DspLDST_m_mask);
   3053  1.1  christos   int W   = ((iw0 >> DspLDST_W_bits) & DspLDST_W_mask);
   3054  1.1  christos   int aop = ((iw0 >> DspLDST_aop_bits) & DspLDST_aop_mask);
   3055  1.1  christos   int reg = ((iw0 >> DspLDST_reg_bits) & DspLDST_reg_mask);
   3056  1.1  christos   bu32 addr;
   3057  1.1  christos 
   3058  1.1  christos   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dspLDST);
   3059  1.1  christos   TRACE_EXTRACT (cpu, "%s: aop:%i m:%i i:%i reg:%i", __func__, aop, m, i, reg);
   3060  1.1  christos 
   3061  1.1  christos   if (aop == 0 && W == 0 && m == 0)
   3062  1.1  christos     {
   3063  1.1  christos       TRACE_INSN (cpu, "R%i = [I%i++];", reg, i);
   3064  1.1  christos       addr = IREG (i);
   3065  1.1  christos       if (DIS_ALGN_EXPT & 0x1)
   3066  1.1  christos 	addr &= ~3;
   3067  1.1  christos       dagadd (cpu, i, 4);
   3068  1.1  christos       STORE (DREG (reg), GET_LONG (addr));
   3069  1.1  christos     }
   3070  1.1  christos   else if (aop == 0 && W == 0 && m == 1)
   3071  1.1  christos     {
   3072  1.1  christos       TRACE_INSN (cpu, "R%i.L = W[I%i++];", reg, i);
   3073  1.1  christos       addr = IREG (i);
   3074  1.1  christos       dagadd (cpu, i, 2);
   3075  1.1  christos       STORE (DREG (reg), (DREG (reg) & 0xFFFF0000) | GET_WORD (addr));
   3076  1.1  christos     }
   3077  1.1  christos   else if (aop == 0 && W == 0 && m == 2)
   3078  1.1  christos     {
   3079  1.1  christos       TRACE_INSN (cpu, "R%i.H = W[I%i++];", reg, i);
   3080  1.1  christos       addr = IREG (i);
   3081  1.1  christos       dagadd (cpu, i, 2);
   3082  1.1  christos       STORE (DREG (reg), (DREG (reg) & 0xFFFF) | (GET_WORD (addr) << 16));
   3083  1.1  christos     }
   3084  1.1  christos   else if (aop == 1 && W == 0 && m == 0)
   3085  1.1  christos     {
   3086  1.1  christos       TRACE_INSN (cpu, "R%i = [I%i--];", reg, i);
   3087  1.1  christos       addr = IREG (i);
   3088  1.1  christos       if (DIS_ALGN_EXPT & 0x1)
   3089  1.1  christos 	addr &= ~3;
   3090  1.1  christos       dagsub (cpu, i, 4);
   3091  1.1  christos       STORE (DREG (reg), GET_LONG (addr));
   3092  1.1  christos     }
   3093  1.1  christos   else if (aop == 1 && W == 0 && m == 1)
   3094  1.1  christos     {
   3095  1.1  christos       TRACE_INSN (cpu, "R%i.L = W[I%i--];", reg, i);
   3096  1.1  christos       addr = IREG (i);
   3097  1.1  christos       dagsub (cpu, i, 2);
   3098  1.1  christos       STORE (DREG (reg), (DREG (reg) & 0xFFFF0000) | GET_WORD (addr));
   3099  1.1  christos     }
   3100  1.1  christos   else if (aop == 1 && W == 0 && m == 2)
   3101  1.1  christos     {
   3102  1.1  christos       TRACE_INSN (cpu, "R%i.H = W[I%i--];", reg, i);
   3103  1.1  christos       addr = IREG (i);
   3104  1.1  christos       dagsub (cpu, i, 2);
   3105  1.1  christos       STORE (DREG (reg), (DREG (reg) & 0xFFFF) | (GET_WORD (addr) << 16));
   3106  1.1  christos     }
   3107  1.1  christos   else if (aop == 2 && W == 0 && m == 0)
   3108  1.1  christos     {
   3109  1.1  christos       TRACE_INSN (cpu, "R%i = [I%i];", reg, i);
   3110  1.1  christos       addr = IREG (i);
   3111  1.1  christos       if (DIS_ALGN_EXPT & 0x1)
   3112  1.1  christos 	addr &= ~3;
   3113  1.1  christos       STORE (DREG (reg), GET_LONG (addr));
   3114  1.1  christos     }
   3115  1.1  christos   else if (aop == 2 && W == 0 && m == 1)
   3116  1.1  christos     {
   3117  1.1  christos       TRACE_INSN (cpu, "R%i.L = W[I%i];", reg, i);
   3118  1.1  christos       addr = IREG (i);
   3119  1.1  christos       STORE (DREG (reg), (DREG (reg) & 0xFFFF0000) | GET_WORD (addr));
   3120  1.1  christos     }
   3121  1.1  christos   else if (aop == 2 && W == 0 && m == 2)
   3122  1.1  christos     {
   3123  1.1  christos       TRACE_INSN (cpu, "R%i.H = W[I%i];", reg, i);
   3124  1.1  christos       addr = IREG (i);
   3125  1.1  christos       STORE (DREG (reg), (DREG (reg) & 0xFFFF) | (GET_WORD (addr) << 16));
   3126  1.1  christos     }
   3127  1.1  christos   else if (aop == 0 && W == 1 && m == 0)
   3128  1.1  christos     {
   3129  1.1  christos       TRACE_INSN (cpu, "[I%i++] = R%i;", i, reg);
   3130  1.1  christos       addr = IREG (i);
   3131  1.1  christos       dagadd (cpu, i, 4);
   3132  1.1  christos       PUT_LONG (addr, DREG (reg));
   3133  1.1  christos     }
   3134  1.1  christos   else if (aop == 0 && W == 1 && m == 1)
   3135  1.1  christos     {
   3136  1.1  christos       TRACE_INSN (cpu, "W[I%i++] = R%i.L;", i, reg);
   3137  1.1  christos       addr = IREG (i);
   3138  1.1  christos       dagadd (cpu, i, 2);
   3139  1.1  christos       PUT_WORD (addr, DREG (reg));
   3140  1.1  christos     }
   3141  1.1  christos   else if (aop == 0 && W == 1 && m == 2)
   3142  1.1  christos     {
   3143  1.1  christos       TRACE_INSN (cpu, "W[I%i++] = R%i.H;", i, reg);
   3144  1.1  christos       addr = IREG (i);
   3145  1.1  christos       dagadd (cpu, i, 2);
   3146  1.1  christos       PUT_WORD (addr, DREG (reg) >> 16);
   3147  1.1  christos     }
   3148  1.1  christos   else if (aop == 1 && W == 1 && m == 0)
   3149  1.1  christos     {
   3150  1.1  christos       TRACE_INSN (cpu, "[I%i--] = R%i;", i, reg);
   3151  1.1  christos       addr = IREG (i);
   3152  1.1  christos       dagsub (cpu, i, 4);
   3153  1.1  christos       PUT_LONG (addr, DREG (reg));
   3154  1.1  christos     }
   3155  1.1  christos   else if (aop == 1 && W == 1 && m == 1)
   3156  1.1  christos     {
   3157  1.1  christos       TRACE_INSN (cpu, "W[I%i--] = R%i.L;", i, reg);
   3158  1.1  christos       addr = IREG (i);
   3159  1.1  christos       dagsub (cpu, i, 2);
   3160  1.1  christos       PUT_WORD (addr, DREG (reg));
   3161  1.1  christos     }
   3162  1.1  christos   else if (aop == 1 && W == 1 && m == 2)
   3163  1.1  christos     {
   3164  1.1  christos       TRACE_INSN (cpu, "W[I%i--] = R%i.H;", i, reg);
   3165  1.1  christos       addr = IREG (i);
   3166  1.1  christos       dagsub (cpu, i, 2);
   3167  1.1  christos       PUT_WORD (addr, DREG (reg) >> 16);
   3168  1.1  christos     }
   3169  1.1  christos   else if (aop == 2 && W == 1 && m == 0)
   3170  1.1  christos     {
   3171  1.1  christos       TRACE_INSN (cpu, "[I%i] = R%i;", i, reg);
   3172  1.1  christos       addr = IREG (i);
   3173  1.1  christos       PUT_LONG (addr, DREG (reg));
   3174  1.1  christos     }
   3175  1.1  christos   else if (aop == 2 && W == 1 && m == 1)
   3176  1.1  christos     {
   3177  1.1  christos       TRACE_INSN (cpu, "W[I%i] = R%i.L;", i, reg);
   3178  1.1  christos       addr = IREG (i);
   3179  1.1  christos       PUT_WORD (addr, DREG (reg));
   3180  1.1  christos     }
   3181  1.1  christos   else if (aop == 2 && W == 1 && m == 2)
   3182  1.1  christos     {
   3183  1.1  christos       TRACE_INSN (cpu, "W[I%i] = R%i.H;", i, reg);
   3184  1.1  christos       addr = IREG (i);
   3185  1.1  christos       PUT_WORD (addr, DREG (reg) >> 16);
   3186  1.1  christos     }
   3187  1.1  christos   else if (aop == 3 && W == 0)
   3188  1.1  christos     {
   3189  1.1  christos       TRACE_INSN (cpu, "R%i = [I%i ++ M%i];", reg, i, m);
   3190  1.1  christos       addr = IREG (i);
   3191  1.1  christos       if (DIS_ALGN_EXPT & 0x1)
   3192  1.1  christos 	addr &= ~3;
   3193  1.1  christos       dagadd (cpu, i, MREG (m));
   3194  1.1  christos       STORE (DREG (reg), GET_LONG (addr));
   3195  1.1  christos     }
   3196  1.1  christos   else if (aop == 3 && W == 1)
   3197  1.1  christos     {
   3198  1.1  christos       TRACE_INSN (cpu, "[I%i ++ M%i] = R%i;", i, m, reg);
   3199  1.1  christos       addr = IREG (i);
   3200  1.1  christos       dagadd (cpu, i, MREG (m));
   3201  1.1  christos       PUT_LONG (addr, DREG (reg));
   3202  1.1  christos     }
   3203  1.1  christos   else
   3204  1.1  christos     illegal_instruction (cpu);
   3205  1.1  christos }
   3206  1.1  christos 
   3207  1.1  christos static void
   3208  1.1  christos decode_LDST_0 (SIM_CPU *cpu, bu16 iw0)
   3209  1.1  christos {
   3210  1.1  christos   /* LDST
   3211  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
   3212  1.1  christos      | 1 | 0 | 0 | 1 |.sz....|.W.|.aop...|.Z.|.ptr.......|.reg.......|
   3213  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
   3214  1.1  christos   int Z   = ((iw0 >> LDST_Z_bits) & LDST_Z_mask);
   3215  1.1  christos   int W   = ((iw0 >> LDST_W_bits) & LDST_W_mask);
   3216  1.1  christos   int sz  = ((iw0 >> LDST_sz_bits) & LDST_sz_mask);
   3217  1.1  christos   int aop = ((iw0 >> LDST_aop_bits) & LDST_aop_mask);
   3218  1.1  christos   int reg = ((iw0 >> LDST_reg_bits) & LDST_reg_mask);
   3219  1.1  christos   int ptr = ((iw0 >> LDST_ptr_bits) & LDST_ptr_mask);
   3220  1.1  christos   const char * const posts[] = { "++", "--", "" };
   3221  1.1  christos   const char *post = posts[aop];
   3222  1.1  christos   const char *ptr_name = get_preg_name (ptr);
   3223  1.1  christos 
   3224  1.1  christos   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LDST);
   3225  1.1  christos   TRACE_EXTRACT (cpu, "%s: sz:%i W:%i aop:%i Z:%i ptr:%i reg:%i",
   3226  1.1  christos 		 __func__, sz, W, aop, Z, ptr, reg);
   3227  1.1  christos 
   3228  1.1  christos   if (aop == 3)
   3229  1.1  christos     illegal_instruction (cpu);
   3230  1.1  christos 
   3231  1.1  christos   if (W == 0)
   3232  1.1  christos     {
   3233  1.1  christos       if (sz == 0 && Z == 0)
   3234  1.1  christos 	{
   3235  1.1  christos 	  TRACE_INSN (cpu, "R%i = [%s%s];", reg, ptr_name, post);
   3236  1.1  christos 	  SET_DREG (reg, GET_LONG (PREG (ptr)));
   3237  1.1  christos 	}
   3238  1.1  christos       else if (sz == 0 && Z == 1)
   3239  1.1  christos 	{
   3240  1.1  christos 	  TRACE_INSN (cpu, "%s = [%s%s];", get_preg_name (reg), ptr_name, post);
   3241  1.1  christos 	  if (aop < 2 && ptr == reg)
   3242  1.1  christos 	    illegal_instruction_combination (cpu);
   3243  1.1  christos 	  SET_PREG (reg, GET_LONG (PREG (ptr)));
   3244  1.1  christos 	}
   3245  1.1  christos       else if (sz == 1 && Z == 0)
   3246  1.1  christos 	{
   3247  1.1  christos 	  TRACE_INSN (cpu, "R%i = W[%s%s] (Z);", reg, ptr_name, post);
   3248  1.1  christos 	  SET_DREG (reg, GET_WORD (PREG (ptr)));
   3249  1.1  christos 	}
   3250  1.1  christos       else if (sz == 1 && Z == 1)
   3251  1.1  christos 	{
   3252  1.1  christos 	  TRACE_INSN (cpu, "R%i = W[%s%s] (X);", reg, ptr_name, post);
   3253  1.1  christos 	  SET_DREG (reg, (bs32) (bs16) GET_WORD (PREG (ptr)));
   3254  1.1  christos 	}
   3255  1.1  christos       else if (sz == 2 && Z == 0)
   3256  1.1  christos 	{
   3257  1.1  christos 	  TRACE_INSN (cpu, "R%i = B[%s%s] (Z);", reg, ptr_name, post);
   3258  1.1  christos 	  SET_DREG (reg, GET_BYTE (PREG (ptr)));
   3259  1.1  christos 	}
   3260  1.1  christos       else if (sz == 2 && Z == 1)
   3261  1.1  christos 	{
   3262  1.1  christos 	  TRACE_INSN (cpu, "R%i = B[%s%s] (X);", reg, ptr_name, post);
   3263  1.1  christos 	  SET_DREG (reg, (bs32) (bs8) GET_BYTE (PREG (ptr)));
   3264  1.1  christos 	}
   3265  1.1  christos       else
   3266  1.1  christos 	illegal_instruction (cpu);
   3267  1.1  christos     }
   3268  1.1  christos   else
   3269  1.1  christos     {
   3270  1.1  christos       if (sz == 0 && Z == 0)
   3271  1.1  christos 	{
   3272  1.1  christos 	  TRACE_INSN (cpu, "[%s%s] = R%i;", ptr_name, post, reg);
   3273  1.1  christos 	  PUT_LONG (PREG (ptr), DREG (reg));
   3274  1.1  christos 	}
   3275  1.1  christos       else if (sz == 0 && Z == 1)
   3276  1.1  christos 	{
   3277  1.1  christos 	  TRACE_INSN (cpu, "[%s%s] = %s;", ptr_name, post, get_preg_name (reg));
   3278  1.1  christos 	  PUT_LONG (PREG (ptr), PREG (reg));
   3279  1.1  christos 	}
   3280  1.1  christos       else if (sz == 1 && Z == 0)
   3281  1.1  christos 	{
   3282  1.1  christos 	  TRACE_INSN (cpu, "W[%s%s] = R%i;", ptr_name, post, reg);
   3283  1.1  christos 	  PUT_WORD (PREG (ptr), DREG (reg));
   3284  1.1  christos 	}
   3285  1.1  christos       else if (sz == 2 && Z == 0)
   3286  1.1  christos 	{
   3287  1.1  christos 	  TRACE_INSN (cpu, "B[%s%s] = R%i;", ptr_name, post, reg);
   3288  1.1  christos 	  PUT_BYTE (PREG (ptr), DREG (reg));
   3289  1.1  christos 	}
   3290  1.1  christos       else
   3291  1.1  christos 	illegal_instruction (cpu);
   3292  1.1  christos     }
   3293  1.1  christos 
   3294  1.1  christos   if (aop == 0)
   3295  1.1  christos     SET_PREG (ptr, PREG (ptr) + (1 << (2 - sz)));
   3296  1.1  christos   if (aop == 1)
   3297  1.1  christos     SET_PREG (ptr, PREG (ptr) - (1 << (2 - sz)));
   3298  1.1  christos }
   3299  1.1  christos 
   3300  1.1  christos static void
   3301  1.1  christos decode_LDSTiiFP_0 (SIM_CPU *cpu, bu16 iw0)
   3302  1.1  christos {
   3303  1.1  christos   /* LDSTiiFP
   3304  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
   3305  1.1  christos      | 1 | 0 | 1 | 1 | 1 | 0 |.W.|.offset............|.reg...........|
   3306  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
   3307  1.1  christos   /* This isn't exactly a grp:reg as this insn only supports Dregs & Pregs,
   3308  1.1  christos      but for our usage, its functionality the same thing.  */
   3309  1.1  christos   int grp = ((iw0 >> 3) & 0x1);
   3310  1.1  christos   int reg = ((iw0 >> LDSTiiFP_reg_bits) & 0x7 /*LDSTiiFP_reg_mask*/);
   3311  1.1  christos   int offset = ((iw0 >> LDSTiiFP_offset_bits) & LDSTiiFP_offset_mask);
   3312  1.1  christos   int W = ((iw0 >> LDSTiiFP_W_bits) & LDSTiiFP_W_mask);
   3313  1.1  christos   bu32 imm = negimm5s4 (offset);
   3314  1.1  christos   bu32 ea = FPREG + imm;
   3315  1.1  christos   const char *imm_str = negimm5s4_str (offset);
   3316  1.1  christos   const char *reg_name = get_allreg_name (grp, reg);
   3317  1.1  christos 
   3318  1.1  christos   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LDSTiiFP);
   3319  1.1  christos   TRACE_EXTRACT (cpu, "%s: W:%i offset:%#x grp:%i reg:%i", __func__,
   3320  1.1  christos 		 W, offset, grp, reg);
   3321  1.1  christos   TRACE_DECODE (cpu, "%s: negimm5s4:%#x", __func__, imm);
   3322  1.1  christos 
   3323  1.1  christos   if (W == 0)
   3324  1.1  christos     {
   3325  1.1  christos       TRACE_INSN (cpu, "%s = [FP + %s];", reg_name, imm_str);
   3326  1.1  christos       reg_write (cpu, grp, reg, GET_LONG (ea));
   3327  1.1  christos     }
   3328  1.1  christos   else
   3329  1.1  christos     {
   3330  1.1  christos       TRACE_INSN (cpu, "[FP + %s] = %s;", imm_str, reg_name);
   3331  1.1  christos       PUT_LONG (ea, reg_read (cpu, grp, reg));
   3332  1.1  christos     }
   3333  1.1  christos }
   3334  1.1  christos 
   3335  1.1  christos static void
   3336  1.1  christos decode_LDSTii_0 (SIM_CPU *cpu, bu16 iw0)
   3337  1.1  christos {
   3338  1.1  christos   /* LDSTii
   3339  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
   3340  1.1  christos      | 1 | 0 | 1 |.W.|.op....|.offset........|.ptr.......|.reg.......|
   3341  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
   3342  1.1  christos   int reg = ((iw0 >> LDSTii_reg_bit) & LDSTii_reg_mask);
   3343  1.1  christos   int ptr = ((iw0 >> LDSTii_ptr_bit) & LDSTii_ptr_mask);
   3344  1.1  christos   int offset = ((iw0 >> LDSTii_offset_bit) & LDSTii_offset_mask);
   3345  1.1  christos   int op = ((iw0 >> LDSTii_op_bit) & LDSTii_op_mask);
   3346  1.1  christos   int W = ((iw0 >> LDSTii_W_bit) & LDSTii_W_mask);
   3347  1.1  christos   bu32 imm, ea;
   3348  1.1  christos   const char *imm_str;
   3349  1.1  christos   const char *ptr_name = get_preg_name (ptr);
   3350  1.1  christos 
   3351  1.1  christos   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LDSTii);
   3352  1.1  christos   TRACE_EXTRACT (cpu, "%s: W:%i op:%i offset:%#x ptr:%i reg:%i",
   3353  1.1  christos 		 __func__, W, op, offset, ptr, reg);
   3354  1.1  christos 
   3355  1.1  christos   if (op == 0 || op == 3)
   3356  1.1  christos     imm = uimm4s4 (offset), imm_str = uimm4s4_str (offset);
   3357  1.1  christos   else
   3358  1.1  christos     imm = uimm4s2 (offset), imm_str = uimm4s2_str (offset);
   3359  1.1  christos   ea = PREG (ptr) + imm;
   3360  1.1  christos 
   3361  1.1  christos   TRACE_DECODE (cpu, "%s: uimm4s4/uimm4s2:%#x", __func__, imm);
   3362  1.1  christos 
   3363  1.1  christos   if (W == 1 && op == 2)
   3364  1.1  christos     illegal_instruction (cpu);
   3365  1.1  christos 
   3366  1.1  christos   if (W == 0)
   3367  1.1  christos     {
   3368  1.1  christos       if (op == 0)
   3369  1.1  christos 	{
   3370  1.1  christos 	  TRACE_INSN (cpu, "R%i = [%s + %s];", reg, ptr_name, imm_str);
   3371  1.1  christos 	  SET_DREG (reg, GET_LONG (ea));
   3372  1.1  christos 	}
   3373  1.1  christos       else if (op == 1)
   3374  1.1  christos 	{
   3375  1.1  christos 	  TRACE_INSN (cpu, "R%i = W[%s + %s] (Z);", reg, ptr_name, imm_str);
   3376  1.1  christos 	  SET_DREG (reg, GET_WORD (ea));
   3377  1.1  christos 	}
   3378  1.1  christos       else if (op == 2)
   3379  1.1  christos 	{
   3380  1.1  christos 	  TRACE_INSN (cpu, "R%i = W[%s + %s] (X);", reg, ptr_name, imm_str);
   3381  1.1  christos 	  SET_DREG (reg, (bs32) (bs16) GET_WORD (ea));
   3382  1.1  christos 	}
   3383  1.1  christos       else if (op == 3)
   3384  1.1  christos 	{
   3385  1.1  christos 	  TRACE_INSN (cpu, "%s = [%s + %s];",
   3386  1.1  christos 		      get_preg_name (reg), ptr_name, imm_str);
   3387  1.1  christos 	  SET_PREG (reg, GET_LONG (ea));
   3388  1.1  christos 	}
   3389  1.1  christos     }
   3390  1.1  christos   else
   3391  1.1  christos     {
   3392  1.1  christos       if (op == 0)
   3393  1.1  christos 	{
   3394  1.1  christos 	  TRACE_INSN (cpu, "[%s + %s] = R%i;", ptr_name, imm_str, reg);
   3395  1.1  christos 	  PUT_LONG (ea, DREG (reg));
   3396  1.1  christos 	}
   3397  1.1  christos       else if (op == 1)
   3398  1.1  christos 	{
   3399  1.1  christos 	  TRACE_INSN (cpu, "W[%s + %s] = R%i;", ptr_name, imm_str, reg);
   3400  1.1  christos 	  PUT_WORD (ea, DREG (reg));
   3401  1.1  christos 	}
   3402  1.1  christos       else if (op == 3)
   3403  1.1  christos 	{
   3404  1.1  christos 	  TRACE_INSN (cpu, "[%s + %s] = %s;",
   3405  1.1  christos 		      ptr_name, imm_str, get_preg_name (reg));
   3406  1.1  christos 	  PUT_LONG (ea, PREG (reg));
   3407  1.1  christos 	}
   3408  1.1  christos     }
   3409  1.1  christos }
   3410  1.1  christos 
   3411  1.1  christos static void
   3412  1.1  christos decode_LoopSetup_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1, bu32 pc)
   3413  1.1  christos {
   3414  1.1  christos   /* LoopSetup
   3415  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
   3416  1.1  christos      | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |.rop...|.c.|.soffset.......|
   3417  1.1  christos      |.reg...........| - | - |.eoffset...............................|
   3418  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
   3419  1.1  christos   int c   = ((iw0 >> (LoopSetup_c_bits - 16)) & LoopSetup_c_mask);
   3420  1.1  christos   int reg = ((iw1 >> LoopSetup_reg_bits) & LoopSetup_reg_mask);
   3421  1.1  christos   int rop = ((iw0 >> (LoopSetup_rop_bits - 16)) & LoopSetup_rop_mask);
   3422  1.1  christos   int soffset = ((iw0 >> (LoopSetup_soffset_bits - 16)) & LoopSetup_soffset_mask);
   3423  1.1  christos   int eoffset = ((iw1 >> LoopSetup_eoffset_bits) & LoopSetup_eoffset_mask);
   3424  1.1  christos   int spcrel = pcrel4 (soffset);
   3425  1.1  christos   int epcrel = lppcrel10 (eoffset);
   3426  1.1  christos 
   3427  1.1  christos   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LoopSetup);
   3428  1.1  christos   TRACE_EXTRACT (cpu, "%s: rop:%i c:%i soffset:%i reg:%i eoffset:%i",
   3429  1.1  christos 		 __func__, rop, c, soffset, reg, eoffset);
   3430  1.1  christos   TRACE_DECODE (cpu, "%s: s_pcrel4:%#x e_lppcrel10:%#x",
   3431  1.1  christos 		__func__, spcrel, epcrel);
   3432  1.1  christos 
   3433  1.1  christos   if (reg > 7)
   3434  1.1  christos     illegal_instruction (cpu);
   3435  1.1  christos 
   3436  1.1  christos   if (INSN_LEN == 8)
   3437  1.1  christos     illegal_instruction_combination (cpu);
   3438  1.1  christos 
   3439  1.1  christos   if (rop == 0)
   3440  1.1  christos     {
   3441  1.1  christos       TRACE_INSN (cpu, "LSETUP (%#x, %#x) LC%i;", spcrel, epcrel, c);
   3442  1.1  christos     }
   3443  1.1  christos   else if (rop == 1 && reg <= 7)
   3444  1.1  christos     {
   3445  1.1  christos       TRACE_INSN (cpu, "LSETUP (%#x, %#x) LC%i = %s;",
   3446  1.1  christos 		  spcrel, epcrel, c, get_preg_name (reg));
   3447  1.1  christos       SET_LCREG (c, PREG (reg));
   3448  1.1  christos     }
   3449  1.1  christos   else if (rop == 3 && reg <= 7)
   3450  1.1  christos     {
   3451  1.1  christos       TRACE_INSN (cpu, "LSETUP (%#x, %#x) LC%i = %s >> 1;",
   3452  1.1  christos 		  spcrel, epcrel, c, get_preg_name (reg));
   3453  1.1  christos       SET_LCREG (c, PREG (reg) >> 1);
   3454  1.1  christos     }
   3455  1.1  christos   else
   3456  1.1  christos     illegal_instruction (cpu);
   3457  1.1  christos 
   3458  1.1  christos   SET_LTREG (c, pc + spcrel);
   3459  1.1  christos   SET_LBREG (c, pc + epcrel);
   3460  1.1  christos }
   3461  1.1  christos 
   3462  1.1  christos static void
   3463  1.1  christos decode_LDIMMhalf_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
   3464  1.1  christos {
   3465  1.1  christos   /* LDIMMhalf
   3466  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
   3467  1.1  christos      | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 |.Z.|.H.|.S.|.grp...|.reg.......|
   3468  1.1  christos      |.hword.........................................................|
   3469  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
   3470  1.1  christos   int H = ((iw0 >> (LDIMMhalf_H_bits - 16)) & LDIMMhalf_H_mask);
   3471  1.1  christos   int Z = ((iw0 >> (LDIMMhalf_Z_bits - 16)) & LDIMMhalf_Z_mask);
   3472  1.1  christos   int S = ((iw0 >> (LDIMMhalf_S_bits - 16)) & LDIMMhalf_S_mask);
   3473  1.1  christos   int reg = ((iw0 >> (LDIMMhalf_reg_bits - 16)) & LDIMMhalf_reg_mask);
   3474  1.1  christos   int grp = ((iw0 >> (LDIMMhalf_grp_bits - 16)) & LDIMMhalf_grp_mask);
   3475  1.1  christos   int hword = ((iw1 >> LDIMMhalf_hword_bits) & LDIMMhalf_hword_mask);
   3476  1.1  christos   bu32 val;
   3477  1.1  christos   const char *val_str;
   3478  1.1  christos   const char *reg_name = get_allreg_name (grp, reg);
   3479  1.1  christos 
   3480  1.1  christos   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LDIMMhalf);
   3481  1.1  christos   TRACE_EXTRACT (cpu, "%s: Z:%i H:%i S:%i grp:%i reg:%i hword:%#x",
   3482  1.1  christos 		 __func__, Z, H, S, grp, reg, hword);
   3483  1.1  christos 
   3484  1.1  christos   if (INSN_LEN == 8)
   3485  1.1  christos     illegal_instruction_combination (cpu);
   3486  1.1  christos 
   3487  1.1  christos   if (S == 1)
   3488  1.1  christos     val = imm16 (hword), val_str = imm16_str (hword);
   3489  1.1  christos   else
   3490  1.1  christos     val = luimm16 (hword), val_str = luimm16_str (hword);
   3491  1.1  christos 
   3492  1.1  christos   if (H == 0 && S == 1 && Z == 0)
   3493  1.1  christos     {
   3494  1.1  christos       TRACE_INSN (cpu, "%s = %s (X);", reg_name, val_str);
   3495  1.1  christos     }
   3496  1.1  christos   else if (H == 0 && S == 0 && Z == 1)
   3497  1.1  christos     {
   3498  1.1  christos       TRACE_INSN (cpu, "%s = %s (Z);", reg_name, val_str);
   3499  1.1  christos     }
   3500  1.1  christos   else if (H == 0 && S == 0 && Z == 0)
   3501  1.1  christos     {
   3502  1.1  christos       TRACE_INSN (cpu, "%s.L = %s;", reg_name, val_str);
   3503  1.1  christos       val = REG_H_L (reg_read (cpu, grp, reg), val);
   3504  1.1  christos     }
   3505  1.1  christos   else if (H == 1 && S == 0 && Z == 0)
   3506  1.1  christos     {
   3507  1.1  christos       TRACE_INSN (cpu, "%s.H = %s;", reg_name, val_str);
   3508  1.1  christos       val = REG_H_L (val << 16, reg_read (cpu, grp, reg));
   3509  1.1  christos     }
   3510  1.1  christos   else
   3511  1.1  christos     illegal_instruction (cpu);
   3512  1.1  christos 
   3513  1.1  christos   reg_write (cpu, grp, reg, val);
   3514  1.1  christos }
   3515  1.1  christos 
   3516  1.1  christos static void
   3517  1.1  christos decode_CALLa_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1, bu32 pc)
   3518  1.1  christos {
   3519  1.1  christos   /* CALLa
   3520  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
   3521  1.1  christos      | 1 | 1 | 1 | 0 | 0 | 0 | 1 |.S.|.msw...........................|
   3522  1.1  christos      |.lsw...........................................................|
   3523  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
   3524  1.1  christos   int S   = ((iw0 >> (CALLa_S_bits - 16)) & CALLa_S_mask);
   3525  1.1  christos   int lsw = ((iw1 >> 0) & 0xffff);
   3526  1.1  christos   int msw = ((iw0 >> 0) & 0xff);
   3527  1.1  christos   int pcrel = pcrel24 ((msw << 16) | lsw);
   3528  1.1  christos   bu32 newpc = pc + pcrel;
   3529  1.1  christos 
   3530  1.1  christos   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_CALLa);
   3531  1.1  christos   TRACE_EXTRACT (cpu, "%s: S:%i msw:%#x lsw:%#x", __func__, S, msw, lsw);
   3532  1.1  christos   TRACE_DECODE (cpu, "%s: pcrel24:%#x", __func__, pcrel);
   3533  1.1  christos 
   3534  1.1  christos   TRACE_INSN (cpu, "%s %#x;", S ? "CALL" : "JUMP.L", pcrel);
   3535  1.1  christos 
   3536  1.1  christos   if (INSN_LEN == 8)
   3537  1.1  christos     illegal_instruction_combination (cpu);
   3538  1.1  christos 
   3539  1.1  christos   if (S == 1)
   3540  1.1  christos     {
   3541  1.1  christos       TRACE_BRANCH (cpu, pc, newpc, -1, "CALL");
   3542  1.1  christos       SET_RETSREG (hwloop_get_next_pc (cpu, pc, 4));
   3543  1.1  christos     }
   3544  1.1  christos   else
   3545  1.1  christos     TRACE_BRANCH (cpu, pc, newpc, -1, "JUMP.L");
   3546  1.1  christos 
   3547  1.1  christos   SET_PCREG (newpc);
   3548  1.1  christos   BFIN_CPU_STATE.did_jump = true;
   3549  1.1  christos   PROFILE_BRANCH_TAKEN (cpu);
   3550  1.1  christos   CYCLE_DELAY = 5;
   3551  1.1  christos }
   3552  1.1  christos 
   3553  1.1  christos static void
   3554  1.1  christos decode_LDSTidxI_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
   3555  1.1  christos {
   3556  1.1  christos   /* LDSTidxI
   3557  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
   3558  1.1  christos      | 1 | 1 | 1 | 0 | 0 | 1 |.W.|.Z.|.sz....|.ptr.......|.reg.......|
   3559  1.1  christos      |.offset........................................................|
   3560  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
   3561  1.1  christos   int Z = ((iw0 >> (LDSTidxI_Z_bits - 16)) & LDSTidxI_Z_mask);
   3562  1.1  christos   int W = ((iw0 >> (LDSTidxI_W_bits - 16)) & LDSTidxI_W_mask);
   3563  1.1  christos   int sz = ((iw0 >> (LDSTidxI_sz_bits - 16)) & LDSTidxI_sz_mask);
   3564  1.1  christos   int reg = ((iw0 >> (LDSTidxI_reg_bits - 16)) & LDSTidxI_reg_mask);
   3565  1.1  christos   int ptr = ((iw0 >> (LDSTidxI_ptr_bits - 16)) & LDSTidxI_ptr_mask);
   3566  1.1  christos   int offset = ((iw1 >> LDSTidxI_offset_bits) & LDSTidxI_offset_mask);
   3567  1.1  christos   const char *ptr_name = get_preg_name (ptr);
   3568  1.1  christos   bu32 imm_16s4 = imm16s4 (offset);
   3569  1.1  christos   bu32 imm_16s2 = imm16s2 (offset);
   3570  1.1  christos   bu32 imm_16 = imm16 (offset);
   3571  1.1  christos 
   3572  1.1  christos   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LDSTidxI);
   3573  1.1  christos   TRACE_EXTRACT (cpu, "%s: W:%i Z:%i sz:%i ptr:%i reg:%i offset:%#x",
   3574  1.1  christos 		 __func__, W, Z, sz, ptr, reg, offset);
   3575  1.1  christos 
   3576  1.1  christos   if (sz == 3)
   3577  1.1  christos     illegal_instruction (cpu);
   3578  1.1  christos 
   3579  1.1  christos   if (W == 0)
   3580  1.1  christos     {
   3581  1.1  christos       if (sz == 0 && Z == 0)
   3582  1.1  christos 	{
   3583  1.1  christos 	  TRACE_INSN (cpu, "R%i = [%s + %s];",
   3584  1.1  christos 		      reg, ptr_name, imm16s4_str (offset));
   3585  1.1  christos 	  SET_DREG (reg, GET_LONG (PREG (ptr) + imm_16s4));
   3586  1.1  christos 	}
   3587  1.1  christos       else if (sz == 0 && Z == 1)
   3588  1.1  christos 	{
   3589  1.1  christos 	  TRACE_INSN (cpu, "%s = [%s + %s];",
   3590  1.1  christos 		      get_preg_name (reg), ptr_name, imm16s4_str (offset));
   3591  1.1  christos 	  SET_PREG (reg, GET_LONG (PREG (ptr) + imm_16s4));
   3592  1.1  christos 	}
   3593  1.1  christos       else if (sz == 1 && Z == 0)
   3594  1.1  christos 	{
   3595  1.1  christos 	  TRACE_INSN (cpu, "R%i = W[%s + %s] (Z);",
   3596  1.1  christos 		      reg, ptr_name, imm16s2_str (offset));
   3597  1.1  christos 	  SET_DREG (reg, GET_WORD (PREG (ptr) + imm_16s2));
   3598  1.1  christos 	}
   3599  1.1  christos       else if (sz == 1 && Z == 1)
   3600  1.1  christos 	{
   3601  1.1  christos 	  TRACE_INSN (cpu, "R%i = W[%s + %s] (X);",
   3602  1.1  christos 		      reg, ptr_name, imm16s2_str (offset));
   3603  1.1  christos 	  SET_DREG (reg, (bs32) (bs16) GET_WORD (PREG (ptr) + imm_16s2));
   3604  1.1  christos 	}
   3605  1.1  christos       else if (sz == 2 && Z == 0)
   3606  1.1  christos 	{
   3607  1.1  christos 	  TRACE_INSN (cpu, "R%i = B[%s + %s] (Z);",
   3608  1.1  christos 		      reg, ptr_name, imm16_str (offset));
   3609  1.1  christos 	  SET_DREG (reg, GET_BYTE (PREG (ptr) + imm_16));
   3610  1.1  christos 	}
   3611  1.1  christos       else if (sz == 2 && Z == 1)
   3612  1.1  christos 	{
   3613  1.1  christos 	  TRACE_INSN (cpu, "R%i = B[%s + %s] (X);",
   3614  1.1  christos 		      reg, ptr_name, imm16_str (offset));
   3615  1.1  christos 	  SET_DREG (reg, (bs32) (bs8) GET_BYTE (PREG (ptr) + imm_16));
   3616  1.1  christos 	}
   3617  1.1  christos     }
   3618  1.1  christos   else
   3619  1.1  christos     {
   3620  1.1  christos       if (sz != 0 && Z != 0)
   3621  1.1  christos 	illegal_instruction (cpu);
   3622  1.1  christos 
   3623  1.1  christos       if (sz == 0 && Z == 0)
   3624  1.1  christos 	{
   3625  1.1  christos 	  TRACE_INSN (cpu, "[%s + %s] = R%i;", ptr_name,
   3626  1.1  christos 		      imm16s4_str (offset), reg);
   3627  1.1  christos 	  PUT_LONG (PREG (ptr) + imm_16s4, DREG (reg));
   3628  1.1  christos 	}
   3629  1.1  christos       else if (sz == 0 && Z == 1)
   3630  1.1  christos 	{
   3631  1.1  christos 	  TRACE_INSN (cpu, "[%s + %s] = %s;",
   3632  1.1  christos 		      ptr_name, imm16s4_str (offset), get_preg_name (reg));
   3633  1.1  christos 	  PUT_LONG (PREG (ptr) + imm_16s4, PREG (reg));
   3634  1.1  christos 	}
   3635  1.1  christos       else if (sz == 1 && Z == 0)
   3636  1.1  christos 	{
   3637  1.1  christos 	  TRACE_INSN (cpu, "W[%s + %s] = R%i;",
   3638  1.1  christos 		      ptr_name, imm16s2_str (offset), reg);
   3639  1.1  christos 	  PUT_WORD (PREG (ptr) + imm_16s2, DREG (reg));
   3640  1.1  christos 	}
   3641  1.1  christos       else if (sz == 2 && Z == 0)
   3642  1.1  christos 	{
   3643  1.1  christos 	  TRACE_INSN (cpu, "B[%s + %s] = R%i;",
   3644  1.1  christos 		      ptr_name, imm16_str (offset), reg);
   3645  1.1  christos 	  PUT_BYTE (PREG (ptr) + imm_16, DREG (reg));
   3646  1.1  christos 	}
   3647  1.1  christos     }
   3648  1.1  christos }
   3649  1.1  christos 
   3650  1.1  christos static void
   3651  1.1  christos decode_linkage_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
   3652  1.1  christos {
   3653  1.1  christos   /* linkage
   3654  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
   3655  1.1  christos      | 1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |.R.|
   3656  1.1  christos      |.framesize.....................................................|
   3657  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
   3658  1.1  christos   int R = ((iw0 >> (Linkage_R_bits - 16)) & Linkage_R_mask);
   3659  1.1  christos   int framesize = ((iw1 >> Linkage_framesize_bits) & Linkage_framesize_mask);
   3660  1.1  christos   bu32 sp;
   3661  1.1  christos 
   3662  1.1  christos   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_linkage);
   3663  1.1  christos   TRACE_EXTRACT (cpu, "%s: R:%i framesize:%#x", __func__, R, framesize);
   3664  1.1  christos 
   3665  1.1  christos   if (R == 0)
   3666  1.1  christos     {
   3667  1.1  christos       int size = uimm16s4 (framesize);
   3668  1.1  christos       sp = SPREG;
   3669  1.1  christos       TRACE_INSN (cpu, "LINK %s;", uimm16s4_str (framesize));
   3670  1.1  christos       if (INSN_LEN == 8)
   3671  1.1  christos 	illegal_instruction_combination (cpu);
   3672  1.1  christos       sp -= 4;
   3673  1.1  christos       PUT_LONG (sp, RETSREG);
   3674  1.1  christos       sp -= 4;
   3675  1.1  christos       PUT_LONG (sp, FPREG);
   3676  1.1  christos       SET_FPREG (sp);
   3677  1.1  christos       sp -= size;
   3678  1.1  christos       CYCLE_DELAY = 3;
   3679  1.1  christos     }
   3680  1.1  christos   else
   3681  1.1  christos     {
   3682  1.1  christos       /* Restore SP from FP.  */
   3683  1.1  christos       sp = FPREG;
   3684  1.1  christos       TRACE_INSN (cpu, "UNLINK;");
   3685  1.1  christos       if (INSN_LEN == 8)
   3686  1.1  christos 	illegal_instruction_combination (cpu);
   3687  1.1  christos       SET_FPREG (GET_LONG (sp));
   3688  1.1  christos       sp += 4;
   3689  1.1  christos       SET_RETSREG (GET_LONG (sp));
   3690  1.1  christos       sp += 4;
   3691  1.1  christos       CYCLE_DELAY = 2;
   3692  1.1  christos     }
   3693  1.1  christos 
   3694  1.1  christos   SET_SPREG (sp);
   3695  1.1  christos }
   3696  1.1  christos 
   3697  1.1  christos static void
   3698  1.1  christos decode_dsp32mac_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
   3699  1.1  christos {
   3700  1.1  christos   /* dsp32mac
   3701  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
   3702  1.1  christos      | 1 | 1 | 0 | 0 |.M.| 0 | 0 |.mmod..........|.MM|.P.|.w1|.op1...|
   3703  1.1  christos      |.h01|.h11|.w0|.op0...|.h00|.h10|.dst.......|.src0......|.src1..|
   3704  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
   3705  1.1  christos   int op1  = ((iw0 >> (DSP32Mac_op1_bits - 16)) & DSP32Mac_op1_mask);
   3706  1.1  christos   int w1   = ((iw0 >> (DSP32Mac_w1_bits - 16)) & DSP32Mac_w1_mask);
   3707  1.1  christos   int P    = ((iw0 >> (DSP32Mac_p_bits - 16)) & DSP32Mac_p_mask);
   3708  1.1  christos   int MM   = ((iw0 >> (DSP32Mac_MM_bits - 16)) & DSP32Mac_MM_mask);
   3709  1.1  christos   int mmod = ((iw0 >> (DSP32Mac_mmod_bits - 16)) & DSP32Mac_mmod_mask);
   3710  1.1  christos   int M    = ((iw0 >> (DSP32Mac_M_bits - 16)) & DSP32Mac_M_mask);
   3711  1.1  christos   int w0   = ((iw1 >> DSP32Mac_w0_bits) & DSP32Mac_w0_mask);
   3712  1.1  christos   int src0 = ((iw1 >> DSP32Mac_src0_bits) & DSP32Mac_src0_mask);
   3713  1.1  christos   int src1 = ((iw1 >> DSP32Mac_src1_bits) & DSP32Mac_src1_mask);
   3714  1.1  christos   int dst  = ((iw1 >> DSP32Mac_dst_bits) & DSP32Mac_dst_mask);
   3715  1.1  christos   int h10  = ((iw1 >> DSP32Mac_h10_bits) & DSP32Mac_h10_mask);
   3716  1.1  christos   int h00  = ((iw1 >> DSP32Mac_h00_bits) & DSP32Mac_h00_mask);
   3717  1.1  christos   int op0  = ((iw1 >> DSP32Mac_op0_bits) & DSP32Mac_op0_mask);
   3718  1.1  christos   int h11  = ((iw1 >> DSP32Mac_h11_bits) & DSP32Mac_h11_mask);
   3719  1.1  christos   int h01  = ((iw1 >> DSP32Mac_h01_bits) & DSP32Mac_h01_mask);
   3720  1.1  christos 
   3721  1.1  christos   bu32 res = DREG (dst);
   3722  1.1  christos   bu32 v_i = 0, zero = 0, n_1 = 0, n_0 = 0;
   3723  1.1  christos 
   3724  1.1  christos   static const char * const ops[] = { "=", "+=", "-=" };
   3725  1.1  christos   char _buf[128], *buf = _buf;
   3726  1.1  christos   int _MM = MM;
   3727  1.1  christos 
   3728  1.1  christos   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dsp32mac);
   3729  1.1  christos   TRACE_EXTRACT (cpu, "%s: M:%i mmod:%i MM:%i P:%i w1:%i op1:%i h01:%i h11:%i "
   3730  1.1  christos 		      "w0:%i op0:%i h00:%i h10:%i dst:%i src0:%i src1:%i",
   3731  1.1  christos 		 __func__, M, mmod, MM, P, w1, op1, h01, h11, w0, op0, h00, h10,
   3732  1.1  christos 		 dst, src0, src1);
   3733  1.1  christos 
   3734  1.1  christos   if (w0 == 0 && w1 == 0 && op1 == 3 && op0 == 3)
   3735  1.1  christos     illegal_instruction (cpu);
   3736  1.1  christos 
   3737  1.1  christos   if ((w1 || w0) && mmod == M_W32)
   3738  1.1  christos     illegal_instruction (cpu);
   3739  1.1  christos 
   3740  1.1  christos   if (((1 << mmod) & (P ? 0x131b : 0x1b5f)) == 0)
   3741  1.1  christos     illegal_instruction (cpu);
   3742  1.1  christos 
   3743  1.1  christos   /* First handle MAC1 side.  */
   3744  1.1  christos   if (w1 == 1 || op1 != 3)
   3745  1.1  christos     {
   3746  1.1  christos       bu32 res1 = decode_macfunc (cpu, 1, op1, h01, h11, src0,
   3747  1.1  christos 				  src1, mmod, MM, P, &v_i, &n_1);
   3748  1.1  christos 
   3749  1.1  christos       if (w1)
   3750  1.1  christos 	buf += sprintf (buf, P ? "R%i" : "R%i.H", dst + P);
   3751  1.1  christos 
   3752  1.1  christos       if (op1 == 3)
   3753  1.1  christos 	{
   3754  1.1  christos 	  buf += sprintf (buf, " = A1");
   3755  1.1  christos 	  zero = !!(res1 == 0);
   3756  1.1  christos 	}
   3757  1.1  christos       else
   3758  1.1  christos 	{
   3759  1.1  christos 	  if (w1)
   3760  1.1  christos 	    buf += sprintf (buf, " = (");
   3761  1.1  christos 	  buf += sprintf (buf, "A1 %s R%i.%c * R%i.%c", ops[op1],
   3762  1.1  christos 			  src0, h01 ? 'H' : 'L',
   3763  1.1  christos 			  src1, h11 ? 'H' : 'L');
   3764  1.1  christos 	  if (w1)
   3765  1.1  christos 	    buf += sprintf (buf, ")");
   3766  1.1  christos 	}
   3767  1.1  christos 
   3768  1.1  christos       if (w1)
   3769  1.1  christos 	{
   3770  1.1  christos 	  if (P)
   3771  1.1  christos 	    STORE (DREG (dst + 1), res1);
   3772  1.1  christos 	  else
   3773  1.1  christos 	    {
   3774  1.1  christos 	      if (res1 & 0xffff0000)
   3775  1.1  christos 		illegal_instruction (cpu);
   3776  1.1  christos 	      res = REG_H_L (res1 << 16, res);
   3777  1.1  christos 	    }
   3778  1.1  christos 	}
   3779  1.1  christos 
   3780  1.1  christos       if (w0 == 1 || op0 != 3)
   3781  1.1  christos 	{
   3782  1.1  christos 	  if (_MM)
   3783  1.1  christos 	    buf += sprintf (buf, " (M)");
   3784  1.1  christos 	  _MM = 0;
   3785  1.1  christos 	  buf += sprintf (buf, ", ");
   3786  1.1  christos 	}
   3787  1.1  christos     }
   3788  1.1  christos 
   3789  1.1  christos   /* Then handle MAC0 side.  */
   3790  1.1  christos   if (w0 == 1 || op0 != 3)
   3791  1.1  christos     {
   3792  1.1  christos       bu32 res0 = decode_macfunc (cpu, 0, op0, h00, h10, src0,
   3793  1.1  christos 				  src1, mmod, 0, P, &v_i, &n_0);
   3794  1.1  christos 
   3795  1.1  christos       if (w0)
   3796  1.1  christos 	buf += sprintf (buf, P ? "R%i" : "R%i.L", dst);
   3797  1.1  christos 
   3798  1.1  christos       if (op0 == 3)
   3799  1.1  christos 	{
   3800  1.1  christos 	  buf += sprintf (buf, " = A0");
   3801  1.1  christos 	  zero |= !!(res0 == 0);
   3802  1.1  christos 	}
   3803  1.1  christos       else
   3804  1.1  christos 	{
   3805  1.1  christos 	  if (w0)
   3806  1.1  christos 	    buf += sprintf (buf, " = (");
   3807  1.1  christos 	  buf += sprintf (buf, "A0 %s R%i.%c * R%i.%c", ops[op0],
   3808  1.1  christos 			  src0, h00 ? 'H' : 'L',
   3809  1.1  christos 			  src1, h10 ? 'H' : 'L');
   3810  1.1  christos 	  if (w0)
   3811  1.1  christos 	    buf += sprintf (buf, ")");
   3812  1.1  christos 	}
   3813  1.1  christos 
   3814  1.1  christos       if (w0)
   3815  1.1  christos 	{
   3816  1.1  christos 	  if (P)
   3817  1.1  christos 	    STORE (DREG (dst), res0);
   3818  1.1  christos 	  else
   3819  1.1  christos 	    {
   3820  1.1  christos 	      if (res0 & 0xffff0000)
   3821  1.1  christos 		illegal_instruction (cpu);
   3822  1.1  christos 	      res = REG_H_L (res, res0);
   3823  1.1  christos 	    }
   3824  1.1  christos 	}
   3825  1.1  christos     }
   3826  1.1  christos 
   3827  1.1  christos   TRACE_INSN (cpu, "%s%s;", _buf, mac_optmode (mmod, _MM));
   3828  1.1  christos 
   3829  1.1  christos   if (!P && (w0 || w1))
   3830  1.1  christos     {
   3831  1.1  christos       STORE (DREG (dst), res);
   3832  1.1  christos       SET_ASTATREG (v, v_i);
   3833  1.1  christos       if (v_i)
   3834  1.1  christos 	SET_ASTATREG (vs, v_i);
   3835  1.1  christos     }
   3836  1.1  christos   else if (P)
   3837  1.1  christos     {
   3838  1.1  christos       SET_ASTATREG (v, v_i);
   3839  1.1  christos       if (v_i)
   3840  1.1  christos 	SET_ASTATREG (vs, v_i);
   3841  1.1  christos     }
   3842  1.1  christos 
   3843  1.1  christos   if ((w0 == 1 && op0 == 3) || (w1 == 1 && op1 == 3))
   3844  1.1  christos     {
   3845  1.1  christos       SET_ASTATREG (az, zero);
   3846  1.1  christos       if (!(w0 == 1 && op0 == 3))
   3847  1.1  christos 	n_0 = 0;
   3848  1.1  christos       if (!(w1 == 1 && op1 == 3))
   3849  1.1  christos 	n_1 = 0;
   3850  1.1  christos       SET_ASTATREG (an, n_1 | n_0);
   3851  1.1  christos     }
   3852  1.1  christos }
   3853  1.1  christos 
   3854  1.1  christos static void
   3855  1.1  christos decode_dsp32mult_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
   3856  1.1  christos {
   3857  1.1  christos   /* dsp32mult
   3858  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
   3859  1.1  christos      | 1 | 1 | 0 | 0 |.M.| 0 | 1 |.mmod..........|.MM|.P.|.w1|.op1...|
   3860  1.1  christos      |.h01|.h11|.w0|.op0...|.h00|.h10|.dst.......|.src0......|.src1..|
   3861  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
   3862  1.1  christos   int op1  = ((iw0 >> (DSP32Mac_op1_bits - 16)) & DSP32Mac_op1_mask);
   3863  1.1  christos   int w1   = ((iw0 >> (DSP32Mac_w1_bits - 16)) & DSP32Mac_w1_mask);
   3864  1.1  christos   int P    = ((iw0 >> (DSP32Mac_p_bits - 16)) & DSP32Mac_p_mask);
   3865  1.1  christos   int MM   = ((iw0 >> (DSP32Mac_MM_bits - 16)) & DSP32Mac_MM_mask);
   3866  1.1  christos   int mmod = ((iw0 >> (DSP32Mac_mmod_bits - 16)) & DSP32Mac_mmod_mask);
   3867  1.1  christos   int M    = ((iw0 >> (DSP32Mac_M_bits - 16)) & DSP32Mac_M_mask);
   3868  1.1  christos   int w0   = ((iw1 >> DSP32Mac_w0_bits) & DSP32Mac_w0_mask);
   3869  1.1  christos   int src0 = ((iw1 >> DSP32Mac_src0_bits) & DSP32Mac_src0_mask);
   3870  1.1  christos   int src1 = ((iw1 >> DSP32Mac_src1_bits) & DSP32Mac_src1_mask);
   3871  1.1  christos   int dst  = ((iw1 >> DSP32Mac_dst_bits) & DSP32Mac_dst_mask);
   3872  1.1  christos   int h10  = ((iw1 >> DSP32Mac_h10_bits) & DSP32Mac_h10_mask);
   3873  1.1  christos   int h00  = ((iw1 >> DSP32Mac_h00_bits) & DSP32Mac_h00_mask);
   3874  1.1  christos   int op0  = ((iw1 >> DSP32Mac_op0_bits) & DSP32Mac_op0_mask);
   3875  1.1  christos   int h11  = ((iw1 >> DSP32Mac_h11_bits) & DSP32Mac_h11_mask);
   3876  1.1  christos   int h01  = ((iw1 >> DSP32Mac_h01_bits) & DSP32Mac_h01_mask);
   3877  1.1  christos 
   3878  1.1  christos   bu32 res = DREG (dst);
   3879  1.1  christos   bu32 sat0 = 0, sat1 = 0, v_i0 = 0, v_i1 = 0;
   3880  1.1  christos   char _buf[128], *buf = _buf;
   3881  1.1  christos   int _MM = MM;
   3882  1.1  christos 
   3883  1.1  christos   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dsp32mult);
   3884  1.1  christos   TRACE_EXTRACT (cpu, "%s: M:%i mmod:%i MM:%i P:%i w1:%i op1:%i h01:%i h11:%i "
   3885  1.1  christos 		      "w0:%i op0:%i h00:%i h10:%i dst:%i src0:%i src1:%i",
   3886  1.1  christos 		 __func__, M, mmod, MM, P, w1, op1, h01, h11, w0, op0, h00, h10,
   3887  1.1  christos 		 dst, src0, src1);
   3888  1.1  christos 
   3889  1.1  christos   if (w1 == 0 && w0 == 0)
   3890  1.1  christos     illegal_instruction (cpu);
   3891  1.1  christos   if (((1 << mmod) & (P ? 0x313 : 0x1b57)) == 0)
   3892  1.1  christos     illegal_instruction (cpu);
   3893  1.1  christos   if (P && ((dst & 1) || (op1 != 0) || (op0 != 0) || !is_macmod_pmove (mmod)))
   3894  1.1  christos     illegal_instruction (cpu);
   3895  1.1  christos   if (!P && ((op1 != 0) || (op0 != 0) || !is_macmod_hmove (mmod)))
   3896  1.1  christos     illegal_instruction (cpu);
   3897  1.1  christos 
   3898  1.1  christos   /* First handle MAC1 side.  */
   3899  1.1  christos   if (w1)
   3900  1.1  christos     {
   3901  1.1  christos       bu64 r = decode_multfunc (cpu, h01, h11, src0, src1, mmod, MM, &sat1);
   3902  1.1  christos       bu32 res1 = extract_mult (cpu, r, mmod, MM, P, &v_i1);
   3903  1.1  christos 
   3904  1.1  christos       buf += sprintf (buf, P ? "R%i" : "R%i.H", dst + P);
   3905  1.1  christos       buf += sprintf (buf, " = R%i.%c * R%i.%c",
   3906  1.1  christos 		      src0, h01 ? 'H' : 'L',
   3907  1.1  christos 		      src1, h11 ? 'H' : 'L');
   3908  1.1  christos       if (w0)
   3909  1.1  christos 	{
   3910  1.1  christos 	  if (_MM)
   3911  1.1  christos 	    buf += sprintf (buf, " (M)");
   3912  1.1  christos 	  _MM = 0;
   3913  1.1  christos 	  buf += sprintf (buf, ", ");
   3914  1.1  christos 	}
   3915  1.1  christos 
   3916  1.1  christos       if (P)
   3917  1.1  christos 	STORE (DREG (dst + 1), res1);
   3918  1.1  christos       else
   3919  1.1  christos 	{
   3920  1.1  christos 	  if (res1 & 0xFFFF0000)
   3921  1.1  christos 	    illegal_instruction (cpu);
   3922  1.1  christos 	  res = REG_H_L (res1 << 16, res);
   3923  1.1  christos 	}
   3924  1.1  christos     }
   3925  1.1  christos 
   3926  1.1  christos   /* First handle MAC0 side.  */
   3927  1.1  christos   if (w0)
   3928  1.1  christos     {
   3929  1.1  christos       bu64 r = decode_multfunc (cpu, h00, h10, src0, src1, mmod, 0, &sat0);
   3930  1.1  christos       bu32 res0 = extract_mult (cpu, r, mmod, 0, P, &v_i0);
   3931  1.1  christos 
   3932  1.1  christos       buf += sprintf (buf, P ? "R%i" : "R%i.L", dst);
   3933  1.1  christos       buf += sprintf (buf, " = R%i.%c * R%i.%c",
   3934  1.1  christos 		      src0, h01 ? 'H' : 'L',
   3935  1.1  christos 		      src1, h11 ? 'H' : 'L');
   3936  1.1  christos 
   3937  1.1  christos       if (P)
   3938  1.1  christos 	STORE (DREG (dst), res0);
   3939  1.1  christos       else
   3940  1.1  christos 	{
   3941  1.1  christos 	  if (res0 & 0xFFFF0000)
   3942  1.1  christos 	    illegal_instruction (cpu);
   3943  1.1  christos 	  res = REG_H_L (res, res0);
   3944  1.1  christos 	}
   3945  1.1  christos     }
   3946  1.1  christos 
   3947  1.1  christos   TRACE_INSN (cpu, "%s%s;", _buf, mac_optmode (mmod, _MM));
   3948  1.1  christos 
   3949  1.1  christos   if (!P && (w0 || w1))
   3950  1.1  christos     STORE (DREG (dst), res);
   3951  1.1  christos 
   3952  1.1  christos   if (w0 || w1)
   3953  1.1  christos     {
   3954  1.1  christos       bu32 v = sat0 | sat1 | v_i0 | v_i1;
   3955  1.1  christos 
   3956  1.1  christos       STORE (ASTATREG (v), v);
   3957  1.1  christos       STORE (ASTATREG (v_copy), v);
   3958  1.1  christos       if (v)
   3959  1.1  christos 	STORE (ASTATREG (vs), v);
   3960  1.1  christos     }
   3961  1.1  christos }
   3962  1.1  christos 
   3963  1.1  christos static void
   3964  1.1  christos decode_dsp32alu_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
   3965  1.1  christos {
   3966  1.1  christos   /* dsp32alu
   3967  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
   3968  1.1  christos      | 1 | 1 | 0 | 0 |.M.| 1 | 0 | - | - | - |.HL|.aopcde............|
   3969  1.1  christos      |.aop...|.s.|.x.|.dst0......|.dst1......|.src0......|.src1......|
   3970  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
   3971  1.1  christos   int s    = ((iw1 >> DSP32Alu_s_bits) & DSP32Alu_s_mask);
   3972  1.1  christos   int x    = ((iw1 >> DSP32Alu_x_bits) & DSP32Alu_x_mask);
   3973  1.1  christos   int aop  = ((iw1 >> DSP32Alu_aop_bits) & DSP32Alu_aop_mask);
   3974  1.1  christos   int src0 = ((iw1 >> DSP32Alu_src0_bits) & DSP32Alu_src0_mask);
   3975  1.1  christos   int src1 = ((iw1 >> DSP32Alu_src1_bits) & DSP32Alu_src1_mask);
   3976  1.1  christos   int dst0 = ((iw1 >> DSP32Alu_dst0_bits) & DSP32Alu_dst0_mask);
   3977  1.1  christos   int dst1 = ((iw1 >> DSP32Alu_dst1_bits) & DSP32Alu_dst1_mask);
   3978  1.1  christos   int M    = ((iw0 >> (DSP32Alu_M_bits - 16)) & DSP32Alu_M_mask);
   3979  1.1  christos   int HL   = ((iw0 >> (DSP32Alu_HL_bits - 16)) & DSP32Alu_HL_mask);
   3980  1.1  christos   int aopcde = ((iw0 >> (DSP32Alu_aopcde_bits - 16)) & DSP32Alu_aopcde_mask);
   3981  1.1  christos 
   3982  1.1  christos   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dsp32alu);
   3983  1.1  christos   TRACE_EXTRACT (cpu, "%s: M:%i HL:%i aopcde:%i aop:%i s:%i x:%i dst0:%i "
   3984  1.1  christos 		      "dst1:%i src0:%i src1:%i",
   3985  1.1  christos 		 __func__, M, HL, aopcde, aop, s, x, dst0, dst1, src0, src1);
   3986  1.1  christos 
   3987  1.1  christos   if ((aop == 0 || aop == 2) && aopcde == 9 && HL == 0 && s == 0)
   3988  1.1  christos     {
   3989  1.1  christos       int a = aop >> 1;
   3990  1.1  christos       TRACE_INSN (cpu, "A%i.L = R%i.L;", a, src0);
   3991  1.1  christos       SET_AWREG (a, REG_H_L (AWREG (a), DREG (src0)));
   3992  1.1  christos     }
   3993  1.1  christos   else if ((aop == 0 || aop == 2) && aopcde == 9 && HL == 1 && s == 0)
   3994  1.1  christos     {
   3995  1.1  christos       int a = aop >> 1;
   3996  1.1  christos       TRACE_INSN (cpu, "A%i.H = R%i.H;", a, src0);
   3997  1.1  christos       SET_AWREG (a, REG_H_L (DREG (src0), AWREG (a)));
   3998  1.1  christos     }
   3999  1.1  christos   else if ((aop == 1 || aop == 0) && aopcde == 5)
   4000  1.1  christos     {
   4001  1.1  christos       bs32 val0 = DREG (src0);
   4002  1.1  christos       bs32 val1 = DREG (src1);
   4003  1.1  christos       bs32 res;
   4004  1.1  christos       bs32 signRes;
   4005  1.1  christos       bs32 ovX, sBit1, sBit2, sBitRes1, sBitRes2;
   4006  1.1  christos 
   4007  1.1  christos       TRACE_INSN (cpu, "R%i.%s = R%i %s R%i (RND12)", dst0, HL ? "L" : "H",
   4008  1.1  christos 		  src0, aop & 0x1 ? "-" : "+", src1);
   4009  1.1  christos 
   4010  1.1  christos       /* If subtract, just invert and add one.  */
   4011  1.1  christos       if (aop & 0x1)
   4012  1.1  christos 	{
   4013  1.1  christos 	  if (val1 == 0x80000000)
   4014  1.1  christos 	    val1 = 0x7FFFFFFF;
   4015  1.1  christos 	  else
   4016  1.1  christos 	    val1 = ~val1 + 1;
   4017  1.1  christos 	}
   4018  1.1  christos 
   4019  1.1  christos       /* Get the sign bits, since we need them later.  */
   4020  1.1  christos       sBit1 = !!(val0 & 0x80000000);
   4021  1.1  christos       sBit2 = !!(val1 & 0x80000000);
   4022  1.1  christos 
   4023  1.1  christos       res = val0 + val1;
   4024  1.1  christos 
   4025  1.1  christos       sBitRes1 = !!(res & 0x80000000);
   4026  1.1  christos       /* Round to the 12th bit.  */
   4027  1.1  christos       res += 0x0800;
   4028  1.1  christos       sBitRes2 = !!(res & 0x80000000);
   4029  1.1  christos 
   4030  1.1  christos       signRes = res;
   4031  1.1  christos       signRes >>= 27;
   4032  1.1  christos 
   4033  1.1  christos       /* Overflow if
   4034  1.1  christos            pos + pos = neg
   4035  1.1  christos            neg + neg = pos
   4036  1.1  christos            positive_res + positive_round = neg
   4037  1.1  christos          Shift and upper 4 bits where not the same.  */
   4038  1.1  christos       if ((!(sBit1 ^ sBit2) && (sBit1 ^ sBitRes1))
   4039  1.1  christos 	  || (!sBit1 && !sBit2 && sBitRes2)
   4040  1.1  christos 	  || ((signRes != 0) && (signRes != -1)))
   4041  1.1  christos 	{
   4042  1.1  christos 	  /* Both X1 and X2 Neg res is neg overflow.  */
   4043  1.1  christos 	  if (sBit1 && sBit2)
   4044  1.1  christos 	    res = 0x80000000;
   4045  1.1  christos 	  /* Both X1 and X2 Pos res is pos overflow.  */
   4046  1.1  christos 	  else if (!sBit1 && !sBit2)
   4047  1.1  christos 	    res = 0x7FFFFFFF;
   4048  1.1  christos 	  /* Pos+Neg or Neg+Pos take the sign of the result.  */
   4049  1.1  christos 	  else if (sBitRes1)
   4050  1.1  christos 	    res = 0x80000000;
   4051  1.1  christos 	  else
   4052  1.1  christos 	    res = 0x7FFFFFFF;
   4053  1.1  christos 
   4054  1.1  christos 	  ovX = 1;
   4055  1.1  christos 	}
   4056  1.1  christos       else
   4057  1.1  christos 	{
   4058  1.1  christos 	  /* Shift up now after overflow detection.  */
   4059  1.1  christos 	  ovX = 0;
   4060  1.1  christos 	  res <<= 4;
   4061  1.1  christos 	}
   4062  1.1  christos 
   4063  1.1  christos       res >>= 16;
   4064  1.1  christos 
   4065  1.1  christos       if (HL)
   4066  1.1  christos 	STORE (DREG (dst0), REG_H_L (res << 16, DREG (dst0)));
   4067  1.1  christos       else
   4068  1.1  christos 	STORE (DREG (dst0), REG_H_L (DREG (dst0), res));
   4069  1.1  christos 
   4070  1.1  christos       SET_ASTATREG (az, res == 0);
   4071  1.1  christos       SET_ASTATREG (an, res & 0x8000);
   4072  1.1  christos       SET_ASTATREG (v, ovX);
   4073  1.1  christos       if (ovX)
   4074  1.1  christos 	SET_ASTATREG (vs, ovX);
   4075  1.1  christos     }
   4076  1.1  christos   else if ((aop == 2 || aop == 3) && aopcde == 5)
   4077  1.1  christos     {
   4078  1.1  christos       bs32 val0 = DREG (src0);
   4079  1.1  christos       bs32 val1 = DREG (src1);
   4080  1.1  christos       bs32 res;
   4081  1.1  christos 
   4082  1.1  christos       TRACE_INSN (cpu, "R%i.%s = R%i %s R%i (RND20)", dst0, HL ? "L" : "H",
   4083  1.1  christos 		  src0, aop & 0x1 ? "-" : "+", src1);
   4084  1.1  christos 
   4085  1.1  christos       /* If subtract, just invert and add one.  */
   4086  1.1  christos       if (aop & 0x1)
   4087  1.1  christos 	val1 = ~val1 + 1;
   4088  1.1  christos 
   4089  1.1  christos       res = (val0 >> 4) + (val1 >> 4) + (((val0 & 0xf) + (val1 & 0xf)) >> 4);
   4090  1.1  christos       res += 0x8000;
   4091  1.1  christos       /* Don't sign extend during the shift.  */
   4092  1.1  christos       res = ((bu32)res >> 16);
   4093  1.1  christos 
   4094  1.1  christos       /* Don't worry about overflows, since we are shifting right.  */
   4095  1.1  christos 
   4096  1.1  christos       if (HL)
   4097  1.1  christos 	STORE (DREG (dst0), REG_H_L (res << 16, DREG (dst0)));
   4098  1.1  christos       else
   4099  1.1  christos 	STORE (DREG (dst0), REG_H_L (DREG (dst0), res));
   4100  1.1  christos 
   4101  1.1  christos       SET_ASTATREG (az, res == 0);
   4102  1.1  christos       SET_ASTATREG (an, res & 0x8000);
   4103  1.1  christos       SET_ASTATREG (v, 0);
   4104  1.1  christos     }
   4105  1.1  christos   else if (aopcde == 2 || aopcde == 3)
   4106  1.1  christos     {
   4107  1.1  christos       bu32 s1, s2, val, ac0_i = 0, v_i = 0;
   4108  1.1  christos 
   4109  1.1  christos       TRACE_INSN (cpu, "R%i.%c = R%i.%c %c R%i.%c%s;",
   4110  1.1  christos 		  dst0, HL ? 'H' : 'L',
   4111  1.1  christos 		  src0, aop & 2 ? 'H' : 'L',
   4112  1.1  christos 		  aopcde == 2 ? '+' : '-',
   4113  1.1  christos 		  src1, aop & 1 ? 'H' : 'L',
   4114  1.1  christos 		  amod1 (s, x));
   4115  1.1  christos 
   4116  1.1  christos       s1 = DREG (src0);
   4117  1.1  christos       s2 = DREG (src1);
   4118  1.1  christos       if (aop & 1)
   4119  1.1  christos 	s2 >>= 16;
   4120  1.1  christos       if (aop & 2)
   4121  1.1  christos 	s1 >>= 16;
   4122  1.1  christos 
   4123  1.1  christos       if (aopcde == 2)
   4124  1.1  christos 	val = add16 (cpu, s1, s2, &ac0_i, &v_i, 0, 0, s, 0);
   4125  1.1  christos       else
   4126  1.1  christos 	val = sub16 (cpu, s1, s2, &ac0_i, &v_i, 0, 0, s, 0);
   4127  1.1  christos 
   4128  1.1  christos       SET_ASTATREG (ac0, ac0_i);
   4129  1.1  christos       SET_ASTATREG (v, v_i);
   4130  1.1  christos       if (v_i)
   4131  1.1  christos 	SET_ASTATREG (vs, v_i);
   4132  1.1  christos 
   4133  1.1  christos       if (HL)
   4134  1.1  christos 	SET_DREG_H (dst0, val << 16);
   4135  1.1  christos       else
   4136  1.1  christos 	SET_DREG_L (dst0, val);
   4137  1.1  christos 
   4138  1.1  christos       SET_ASTATREG (an, val & 0x8000);
   4139  1.1  christos       SET_ASTATREG (az, val == 0);
   4140  1.1  christos     }
   4141  1.1  christos   else if ((aop == 0 || aop == 2) && aopcde == 9 && s == 1)
   4142  1.1  christos     {
   4143  1.1  christos       int a = aop >> 1;
   4144  1.1  christos       TRACE_INSN (cpu, "A%i = R%i;", a, src0);
   4145  1.1  christos       SET_AREG32 (a, DREG (src0));
   4146  1.1  christos     }
   4147  1.1  christos   else if ((aop == 1 || aop == 3) && aopcde == 9 && s == 0)
   4148  1.1  christos     {
   4149  1.1  christos       int a = aop >> 1;
   4150  1.1  christos       TRACE_INSN (cpu, "A%i.X = R%i.L;", a, src0);
   4151  1.1  christos       SET_AXREG (a, (bs8)DREG (src0));
   4152  1.1  christos     }
   4153  1.1  christos   else if (aop == 3 && aopcde == 11 && (s == 0 || s == 1))
   4154  1.1  christos     {
   4155  1.1  christos       bu64 acc0 = get_extended_acc (cpu, 0);
   4156  1.1  christos       bu64 acc1 = get_extended_acc (cpu, 1);
   4157  1.1  christos       bu32 carry = (bu40)acc1 < (bu40)acc0;
   4158  1.1  christos       bu32 sat = 0;
   4159  1.1  christos 
   4160  1.1  christos       TRACE_INSN (cpu, "A0 -= A1%s;", s ? " (W32)" : "");
   4161  1.1  christos 
   4162  1.1  christos       acc0 -= acc1;
   4163  1.1  christos       if ((bs64)acc0 < -0x8000000000ll)
   4164  1.1  christos 	acc0 = -0x8000000000ull, sat = 1;
   4165  1.1  christos       else if ((bs64)acc0 >= 0x7fffffffffll)
   4166  1.1  christos 	acc0 = 0x7fffffffffull, sat = 1;
   4167  1.1  christos 
   4168  1.1  christos       if (s == 1)
   4169  1.1  christos 	{
   4170  1.1  christos 	  /* A0 -= A1 (W32)  */
   4171  1.1  christos 	  if (acc0 & (bu64)0x8000000000ll)
   4172  1.1  christos 	    acc0 &= 0x80ffffffffll, sat = 1;
   4173  1.1  christos 	  else
   4174  1.1  christos 	    acc0 &= 0xffffffffll;
   4175  1.1  christos 	}
   4176  1.1  christos       STORE (AXREG (0), (acc0 >> 32) & 0xff);
   4177  1.1  christos       STORE (AWREG (0), acc0 & 0xffffffff);
   4178  1.1  christos       STORE (ASTATREG (az), acc0 == 0);
   4179  1.1  christos       STORE (ASTATREG (an), !!(acc0 & (bu64)0x8000000000ll));
   4180  1.1  christos       STORE (ASTATREG (ac0), carry);
   4181  1.1  christos       STORE (ASTATREG (ac0_copy), carry);
   4182  1.1  christos       STORE (ASTATREG (av0), sat);
   4183  1.1  christos       if (sat)
   4184  1.1  christos 	STORE (ASTATREG (av0s), sat);
   4185  1.1  christos     }
   4186  1.1  christos   else if ((aop == 0 || aop == 1) && aopcde == 22)
   4187  1.1  christos     {
   4188  1.1  christos       bu32 s0, s0L, s0H, s1, s1L, s1H;
   4189  1.1  christos       bu32 tmp0, tmp1, i;
   4190  1.1  christos       const char * const opts[] = { "rndl", "rndh", "tl", "th" };
   4191  1.1  christos 
   4192  1.1  christos       TRACE_INSN (cpu, "R%i = BYTEOP2P (R%i:%i, R%i:%i) (%s%s);", dst0,
   4193  1.1  christos 		  src0 + 1, src0, src1 + 1, src1, opts[HL + (aop << 1)],
   4194  1.1  christos 		  s ? ", r" : "");
   4195  1.1  christos 
   4196  1.1  christos       s0L = DREG (src0);
   4197  1.1  christos       s0H = DREG (src0 + 1);
   4198  1.1  christos       s1L = DREG (src1);
   4199  1.1  christos       s1H = DREG (src1 + 1);
   4200  1.1  christos       if (s)
   4201  1.1  christos 	{
   4202  1.1  christos 	  s0 = algn (s0H, s0L, IREG (0) & 3);
   4203  1.1  christos 	  s1 = algn (s1H, s1L, IREG (0) & 3);
   4204  1.1  christos 	}
   4205  1.1  christos       else
   4206  1.1  christos 	{
   4207  1.1  christos 	  s0 = algn (s0L, s0H, IREG (0) & 3);
   4208  1.1  christos 	  s1 = algn (s1L, s1H, IREG (0) & 3);
   4209  1.1  christos 	}
   4210  1.1  christos 
   4211  1.1  christos       i = !aop * 2;
   4212  1.1  christos       tmp0 = ((((s1 >>  8) & 0xff) + ((s1 >>  0) & 0xff) +
   4213  1.1  christos 	       ((s0 >>  8) & 0xff) + ((s0 >>  0) & 0xff) + i) >> 2) & 0xff;
   4214  1.1  christos       tmp1 = ((((s1 >> 24) & 0xff) + ((s1 >> 16) & 0xff) +
   4215  1.1  christos 	       ((s0 >> 24) & 0xff) + ((s0 >> 16) & 0xff) + i) >> 2) & 0xff;
   4216  1.1  christos       SET_DREG (dst0, (tmp1 << (16 + (HL * 8))) | (tmp0 << (HL * 8)));
   4217  1.1  christos     }
   4218  1.1  christos   else if ((aop == 0 || aop == 1) && s == 0 && aopcde == 8)
   4219  1.1  christos     {
   4220  1.1  christos       TRACE_INSN (cpu, "A%i = 0;", aop);
   4221  1.1  christos       SET_AREG (aop, 0);
   4222  1.1  christos     }
   4223  1.1  christos   else if (aop == 2 && s == 0 && aopcde == 8)
   4224  1.1  christos     {
   4225  1.1  christos       TRACE_INSN (cpu, "A1 = A0 = 0;");
   4226  1.1  christos       SET_AREG (0, 0);
   4227  1.1  christos       SET_AREG (1, 0);
   4228  1.1  christos     }
   4229  1.1  christos   else if ((aop == 0 || aop == 1 || aop == 2) && s == 1 && aopcde == 8)
   4230  1.1  christos     {
   4231  1.1  christos       bs40 acc0 = get_extended_acc (cpu, 0);
   4232  1.1  christos       bs40 acc1 = get_extended_acc (cpu, 1);
   4233  1.1  christos       bu32 sat;
   4234  1.1  christos 
   4235  1.1  christos       if (aop == 0 || aop == 1)
   4236  1.1  christos 	TRACE_INSN (cpu, "A%i = A%i (S);", aop, aop);
   4237  1.1  christos       else
   4238  1.1  christos 	TRACE_INSN (cpu, "A1 = A1 (S), A0 = A0 (S);");
   4239  1.1  christos 
   4240  1.1  christos       if (aop == 0 || aop == 2)
   4241  1.1  christos 	{
   4242  1.1  christos 	  sat = 0;
   4243  1.1  christos 	  acc0 = saturate_s32 (acc0, &sat);
   4244  1.1  christos 	  acc0 |= -(acc0 & 0x80000000ull);
   4245  1.1  christos 	  SET_AXREG (0, (acc0 >> 31) & 0xFF);
   4246  1.1  christos 	  SET_AWREG (0, acc0 & 0xFFFFFFFF);
   4247  1.1  christos 	  SET_ASTATREG (av0, sat);
   4248  1.1  christos 	  if (sat)
   4249  1.1  christos 	    SET_ASTATREG (av0s, sat);
   4250  1.1  christos 	}
   4251  1.1  christos       else
   4252  1.1  christos 	acc0 = 1;
   4253  1.1  christos 
   4254  1.1  christos       if (aop == 1 || aop == 2)
   4255  1.1  christos 	{
   4256  1.1  christos 	  sat = 0;
   4257  1.1  christos 	  acc1 = saturate_s32 (acc1, &sat);
   4258  1.1  christos 	  acc1 |= -(acc1 & 0x80000000ull);
   4259  1.1  christos 	  SET_AXREG (1, (acc1 >> 31) & 0xFF);
   4260  1.1  christos 	  SET_AWREG (1, acc1 & 0xFFFFFFFF);
   4261  1.1  christos 	  SET_ASTATREG (av1, sat);
   4262  1.1  christos 	  if (sat)
   4263  1.1  christos 	    SET_ASTATREG (av1s, sat);
   4264  1.1  christos 	}
   4265  1.1  christos       else
   4266  1.1  christos 	acc1 = 1;
   4267  1.1  christos 
   4268  1.1  christos       SET_ASTATREG (az, (acc0 == 0) || (acc1 == 0));
   4269  1.1  christos       SET_ASTATREG (an, ((acc0 >> 31) & 1) || ((acc1 >> 31) & 1));
   4270  1.1  christos     }
   4271  1.1  christos   else if (aop == 3 && (s == 0 || s == 1) && aopcde == 8)
   4272  1.1  christos     {
   4273  1.1  christos       TRACE_INSN (cpu, "A%i = A%i;", s, !s);
   4274  1.1  christos       SET_AXREG (s, AXREG (!s));
   4275  1.1  christos       SET_AWREG (s, AWREG (!s));
   4276  1.1  christos     }
   4277  1.1  christos   else if (aop == 3 && HL == 0 && aopcde == 16)
   4278  1.1  christos     {
   4279  1.1  christos       int i;
   4280  1.1  christos       bu32 az;
   4281  1.1  christos 
   4282  1.1  christos       TRACE_INSN (cpu, "A1 = ABS A1 , A0 = ABS A0;");
   4283  1.1  christos 
   4284  1.1  christos       az = 0;
   4285  1.1  christos       for (i = 0; i < 2; ++i)
   4286  1.1  christos 	{
   4287  1.1  christos 	  bu32 av;
   4288  1.1  christos 	  bs40 acc = get_extended_acc (cpu, i);
   4289  1.1  christos 
   4290  1.1  christos 	  if (acc >> 39)
   4291  1.1  christos 	    acc = -acc;
   4292  1.1  christos 	  av = acc == ((bs40)1 << 39);
   4293  1.1  christos 	  if (av)
   4294  1.1  christos 	    acc = ((bs40)1 << 39) - 1;
   4295  1.1  christos 
   4296  1.1  christos 	  SET_AREG (i, acc);
   4297  1.1  christos 	  SET_ASTATREG (av[i], av);
   4298  1.1  christos 	  if (av)
   4299  1.1  christos 	    SET_ASTATREG (avs[i], av);
   4300  1.1  christos 	  az |= (acc == 0);
   4301  1.1  christos 	}
   4302  1.1  christos       SET_ASTATREG (az, az);
   4303  1.1  christos       SET_ASTATREG (an, 0);
   4304  1.1  christos     }
   4305  1.1  christos   else if (aop == 0 && aopcde == 23)
   4306  1.1  christos     {
   4307  1.1  christos       bu32 s0, s0L, s0H, s1, s1L, s1H;
   4308  1.1  christos       bs32 tmp0, tmp1;
   4309  1.1  christos 
   4310  1.1  christos       TRACE_INSN (cpu, "R%i = BYTEOP3P (R%i:%i, R%i:%i) (%s%s);", dst0,
   4311  1.1  christos 		  src0 + 1, src0, src1 + 1, src1, HL ? "HI" : "LO",
   4312  1.1  christos 		  s ? ", R" : "");
   4313  1.1  christos 
   4314  1.1  christos       s0L = DREG (src0);
   4315  1.1  christos       s0H = DREG (src0 + 1);
   4316  1.1  christos       s1L = DREG (src1);
   4317  1.1  christos       s1H = DREG (src1 + 1);
   4318  1.1  christos       if (s)
   4319  1.1  christos 	{
   4320  1.1  christos 	  s0 = algn (s0H, s0L, IREG (0) & 3);
   4321  1.1  christos 	  s1 = algn (s1H, s1L, IREG (1) & 3);
   4322  1.1  christos 	}
   4323  1.1  christos       else
   4324  1.1  christos 	{
   4325  1.1  christos 	  s0 = algn (s0L, s0H, IREG (0) & 3);
   4326  1.1  christos 	  s1 = algn (s1L, s1H, IREG (1) & 3);
   4327  1.1  christos 	}
   4328  1.1  christos 
   4329  1.1  christos       tmp0 = (bs32)(bs16)(s0 >>  0) + ((s1 >> ( 0 + (8 * !HL))) & 0xff);
   4330  1.1  christos       tmp1 = (bs32)(bs16)(s0 >> 16) + ((s1 >> (16 + (8 * !HL))) & 0xff);
   4331  1.1  christos       SET_DREG (dst0, (CLAMP (tmp0, 0, 255) << ( 0 + (8 * HL))) |
   4332  1.1  christos 		      (CLAMP (tmp1, 0, 255) << (16 + (8 * HL))));
   4333  1.1  christos     }
   4334  1.1  christos   else if ((aop == 0 || aop == 1) && aopcde == 16)
   4335  1.1  christos     {
   4336  1.1  christos       bu32 av;
   4337  1.1  christos       bs40 acc;
   4338  1.1  christos 
   4339  1.1  christos       TRACE_INSN (cpu, "A%i = ABS A%i;", HL, aop);
   4340  1.1  christos 
   4341  1.1  christos       acc = get_extended_acc (cpu, aop);
   4342  1.1  christos       if (acc >> 39)
   4343  1.1  christos 	acc = -acc;
   4344  1.1  christos       av = acc == ((bs40)1 << 39);
   4345  1.1  christos       if (av)
   4346  1.1  christos 	acc = ((bs40)1 << 39) - 1;
   4347  1.1  christos       SET_AREG (HL, acc);
   4348  1.1  christos 
   4349  1.1  christos       SET_ASTATREG (av[HL], av);
   4350  1.1  christos       if (av)
   4351  1.1  christos 	SET_ASTATREG (avs[HL], av);
   4352  1.1  christos       SET_ASTATREG (az, acc == 0);
   4353  1.1  christos       SET_ASTATREG (an, 0);
   4354  1.1  christos     }
   4355  1.1  christos   else if (aop == 3 && aopcde == 12)
   4356  1.1  christos     {
   4357  1.1  christos       bs32 res = DREG (src0);
   4358  1.1  christos       bs32 ovX;
   4359  1.1  christos       bool sBit_a, sBit_b;
   4360  1.1  christos 
   4361  1.1  christos       TRACE_INSN (cpu, "R%i.%s = R%i (RND);", dst0, HL == 0 ? "L" : "H", src0);
   4362  1.1  christos       TRACE_DECODE (cpu, "R%i.%s = R%i:%#x (RND);", dst0,
   4363  1.1  christos 		    HL == 0 ? "L" : "H", src0, res);
   4364  1.1  christos 
   4365  1.1  christos       sBit_b = !!(res & 0x80000000);
   4366  1.1  christos 
   4367  1.1  christos       res += 0x8000;
   4368  1.1  christos       sBit_a = !!(res & 0x80000000);
   4369  1.1  christos 
   4370  1.1  christos       /* Overflow if the sign bit changed when we rounded.  */
   4371  1.1  christos       if ((res >> 16) && (sBit_b != sBit_a))
   4372  1.1  christos 	{
   4373  1.1  christos 	  ovX = 1;
   4374  1.1  christos 	  if (!sBit_b)
   4375  1.1  christos 	    res = 0x7FFF;
   4376  1.1  christos 	  else
   4377  1.1  christos 	    res = 0x8000;
   4378  1.1  christos 	}
   4379  1.1  christos       else
   4380  1.1  christos 	{
   4381  1.1  christos 	  res = res >> 16;
   4382  1.1  christos 	  ovX = 0;
   4383  1.1  christos 	}
   4384  1.1  christos 
   4385  1.1  christos       if (!HL)
   4386  1.1  christos 	SET_DREG (dst0, REG_H_L (DREG (dst0), res));
   4387  1.1  christos       else
   4388  1.1  christos 	SET_DREG (dst0, REG_H_L (res << 16, DREG (dst0)));
   4389  1.1  christos 
   4390  1.1  christos       SET_ASTATREG (az, res == 0);
   4391  1.1  christos       SET_ASTATREG (an, res < 0);
   4392  1.1  christos       SET_ASTATREG (v, ovX);
   4393  1.1  christos       if (ovX)
   4394  1.1  christos 	SET_ASTATREG (vs, ovX);
   4395  1.1  christos     }
   4396  1.1  christos   else if (aop == 3 && HL == 0 && aopcde == 15)
   4397  1.1  christos     {
   4398  1.1  christos       bu32 hi = (-(bs16)(DREG (src0) >> 16)) << 16;
   4399  1.1  christos       bu32 lo = (-(bs16)(DREG (src0) & 0xFFFF)) & 0xFFFF;
   4400  1.1  christos       int v, ac0, ac1;
   4401  1.1  christos 
   4402  1.1  christos       TRACE_INSN (cpu, "R%i = -R%i (V);", dst0, src0);
   4403  1.1  christos 
   4404  1.1  christos       v = ac0 = ac1 = 0;
   4405  1.1  christos 
   4406  1.1  christos       if (hi == 0x80000000)
   4407  1.1  christos 	{
   4408  1.1  christos 	  hi = 0x7fff0000;
   4409  1.1  christos 	  v = 1;
   4410  1.1  christos 	}
   4411  1.1  christos       else if (hi == 0)
   4412  1.1  christos 	ac1 = 1;
   4413  1.1  christos 
   4414  1.1  christos       if (lo == 0x8000)
   4415  1.1  christos 	{
   4416  1.1  christos 	  lo = 0x7fff;
   4417  1.1  christos 	  v = 1;
   4418  1.1  christos 	}
   4419  1.1  christos       else if (lo == 0)
   4420  1.1  christos 	ac0 = 1;
   4421  1.1  christos 
   4422  1.1  christos       SET_DREG (dst0, hi | lo);
   4423  1.1  christos 
   4424  1.1  christos       SET_ASTATREG (v, v);
   4425  1.1  christos       if (v)
   4426  1.1  christos 	SET_ASTATREG (vs, 1);
   4427  1.1  christos       SET_ASTATREG (ac0, ac0);
   4428  1.1  christos       SET_ASTATREG (ac1, ac1);
   4429  1.1  christos       setflags_nz_2x16 (cpu, DREG (dst0));
   4430  1.1  christos     }
   4431  1.1  christos   else if (aop == 3 && HL == 0 && aopcde == 14)
   4432  1.1  christos     {
   4433  1.1  christos       TRACE_INSN (cpu, "A1 = - A1 , A0 = - A0;");
   4434  1.1  christos 
   4435  1.1  christos       SET_AREG (0, saturate_s40 (-get_extended_acc (cpu, 0)));
   4436  1.1  christos       SET_AREG (1, saturate_s40 (-get_extended_acc (cpu, 1)));
   4437  1.1  christos       /* XXX: what ASTAT flags need updating ?  */
   4438  1.1  christos     }
   4439  1.1  christos   else if ((aop == 0 || aop == 1) && (HL == 0 || HL == 1) && aopcde == 14)
   4440  1.1  christos     {
   4441  1.1  christos       bs40 src_acc = get_extended_acc (cpu, aop);
   4442  1.1  christos       int v = 0;
   4443  1.1  christos 
   4444  1.1  christos       TRACE_INSN (cpu, "A%i = - A%i;", HL, aop);
   4445  1.1  christos 
   4446  1.1  christos       SET_AREG (HL, saturate_s40_astat (-src_acc, &v));
   4447  1.1  christos 
   4448  1.1  christos       SET_ASTATREG (az, AWREG (HL) == 0 && AXREG (HL) == 0);
   4449  1.1  christos       SET_ASTATREG (an, AXREG (HL) >> 7);
   4450  1.1  christos       if (HL == 0)
   4451  1.1  christos 	{
   4452  1.1  christos 	  SET_ASTATREG (ac0, !src_acc);
   4453  1.1  christos 	  SET_ASTATREG (av0, v);
   4454  1.1  christos 	  if (v)
   4455  1.1  christos 	    SET_ASTATREG (av0s, 1);
   4456  1.1  christos 	}
   4457  1.1  christos       else
   4458  1.1  christos 	{
   4459  1.1  christos 	  SET_ASTATREG (ac1, !src_acc);
   4460  1.1  christos 	  SET_ASTATREG (av1, v);
   4461  1.1  christos 	  if (v)
   4462  1.1  christos 	    SET_ASTATREG (av1s, 1);
   4463  1.1  christos 	}
   4464  1.1  christos     }
   4465  1.1  christos   else if (aop == 0 && aopcde == 12)
   4466  1.1  christos     {
   4467  1.1  christos       bs16 tmp0_hi = DREG (src0) >> 16;
   4468  1.1  christos       bs16 tmp0_lo = DREG (src0);
   4469  1.1  christos       bs16 tmp1_hi = DREG (src1) >> 16;
   4470  1.1  christos       bs16 tmp1_lo = DREG (src1);
   4471  1.1  christos 
   4472  1.1  christos       TRACE_INSN (cpu, "R%i.L = R%i.H = SIGN(R%i.H) * R%i.H + SIGN(R%i.L) * R%i.L;",
   4473  1.1  christos 		  dst0, dst0, src0, src1, src0, src1);
   4474  1.1  christos 
   4475  1.1  christos       if ((tmp0_hi >> 15) & 1)
   4476  1.1  christos 	tmp1_hi = ~tmp1_hi + 1;
   4477  1.1  christos 
   4478  1.1  christos       if ((tmp0_lo >> 15) & 1)
   4479  1.1  christos 	tmp1_lo = ~tmp1_lo + 1;
   4480  1.1  christos 
   4481  1.1  christos       tmp1_hi = tmp1_hi + tmp1_lo;
   4482  1.1  christos 
   4483  1.1  christos       STORE (DREG (dst0), REG_H_L (tmp1_hi << 16, tmp1_hi));
   4484  1.1  christos     }
   4485  1.1  christos   else if (aopcde == 0)
   4486  1.1  christos     {
   4487  1.1  christos       bu32 s0 = DREG (src0);
   4488  1.1  christos       bu32 s1 = DREG (src1);
   4489  1.1  christos       bu32 s0h = s0 >> 16;
   4490  1.1  christos       bu32 s0l = s0 & 0xFFFF;
   4491  1.1  christos       bu32 s1h = s1 >> 16;
   4492  1.1  christos       bu32 s1l = s1 & 0xFFFF;
   4493  1.1  christos       bu32 t0, t1;
   4494  1.1  christos       bu32 ac1_i = 0, ac0_i = 0, v_i = 0, z_i = 0, n_i = 0;
   4495  1.1  christos 
   4496  1.1  christos       TRACE_INSN (cpu, "R%i = R%i %c|%c R%i%s;", dst0, src0,
   4497  1.1  christos 		  (aop & 2) ? '-' : '+', (aop & 1) ? '-' : '+', src1,
   4498  1.1  christos 		  amod0 (s, x));
   4499  1.1  christos       if (aop & 2)
   4500  1.1  christos 	t0 = sub16 (cpu, s0h, s1h, &ac1_i, &v_i, &z_i, &n_i, s, 0);
   4501  1.1  christos       else
   4502  1.1  christos 	t0 = add16 (cpu, s0h, s1h, &ac1_i, &v_i, &z_i, &n_i, s, 0);
   4503  1.1  christos 
   4504  1.1  christos       if (aop & 1)
   4505  1.1  christos 	t1 = sub16 (cpu, s0l, s1l, &ac0_i, &v_i, &z_i, &n_i, s, 0);
   4506  1.1  christos       else
   4507  1.1  christos 	t1 = add16 (cpu, s0l, s1l, &ac0_i, &v_i, &z_i, &n_i, s, 0);
   4508  1.1  christos 
   4509  1.1  christos       SET_ASTATREG (ac1, ac1_i);
   4510  1.1  christos       SET_ASTATREG (ac0, ac0_i);
   4511  1.1  christos       SET_ASTATREG (az, z_i);
   4512  1.1  christos       SET_ASTATREG (an, n_i);
   4513  1.1  christos       SET_ASTATREG (v, v_i);
   4514  1.1  christos       if (v_i)
   4515  1.1  christos 	SET_ASTATREG (vs, v_i);
   4516  1.1  christos 
   4517  1.1  christos       t0 &= 0xFFFF;
   4518  1.1  christos       t1 &= 0xFFFF;
   4519  1.1  christos       if (x)
   4520  1.1  christos 	SET_DREG (dst0, (t1 << 16) | t0);
   4521  1.1  christos       else
   4522  1.1  christos 	SET_DREG (dst0, (t0 << 16) | t1);
   4523  1.1  christos     }
   4524  1.1  christos   else if (aop == 1 && aopcde == 12)
   4525  1.1  christos     {
   4526  1.1  christos       bs32 val0 = (bs16)(AWREG (0) >> 16) + (bs16)AWREG (0);
   4527  1.1  christos       bs32 val1 = (bs16)(AWREG (1) >> 16) + (bs16)AWREG (1);
   4528  1.1  christos 
   4529  1.1  christos       TRACE_INSN (cpu, "R%i = A1.L + A1.H, R%i = A0.L + A0.H;", dst1, dst0);
   4530  1.1  christos 
   4531  1.1  christos       if (dst0 == dst1)
   4532  1.1  christos 	illegal_instruction_combination (cpu);
   4533  1.1  christos 
   4534  1.1  christos       SET_DREG (dst0, val0);
   4535  1.1  christos       SET_DREG (dst1, val1);
   4536  1.1  christos     }
   4537  1.1  christos   else if (aopcde == 1)
   4538  1.1  christos     {
   4539  1.1  christos       bu32 d0, d1;
   4540  1.1  christos       bu32 x0, x1;
   4541  1.1  christos       bu16 s0L = DREG (src0);
   4542  1.1  christos       bu16 s0H = DREG (src0) >> 16;
   4543  1.1  christos       bu16 s1L = DREG (src1);
   4544  1.1  christos       bu16 s1H = DREG (src1) >> 16;
   4545  1.1  christos       bu32 v_i = 0, n_i = 0, z_i = 0;
   4546  1.1  christos 
   4547  1.1  christos       TRACE_INSN (cpu, "R%i = R%i %s R%i, R%i = R%i %s R%i%s;",
   4548  1.1  christos 		  dst1, src0, HL ? "+|-" : "+|+", src1,
   4549  1.1  christos 		  dst0, src0, HL ? "-|+" : "-|-", src1,
   4550  1.1  christos 		  amod0amod2 (s, x, aop));
   4551  1.1  christos 
   4552  1.1  christos       if (dst0 == dst1)
   4553  1.1  christos 	illegal_instruction_combination (cpu);
   4554  1.1  christos 
   4555  1.1  christos       if (HL == 0)
   4556  1.1  christos 	{
   4557  1.1  christos 	  x0 = add16 (cpu, s0H, s1H, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
   4558  1.1  christos 	  x1 = add16 (cpu, s0L, s1L, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
   4559  1.1  christos 	  d1 = (x0 << 16) | x1;
   4560  1.1  christos 
   4561  1.1  christos 	  x0 = sub16 (cpu, s0H, s1H, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
   4562  1.1  christos 	  x1 = sub16 (cpu, s0L, s1L, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
   4563  1.1  christos 	  if (x == 0)
   4564  1.1  christos 	    d0 = (x0 << 16) | x1;
   4565  1.1  christos 	  else
   4566  1.1  christos 	    d0 = (x1 << 16) | x0;
   4567  1.1  christos 	}
   4568  1.1  christos       else
   4569  1.1  christos 	{
   4570  1.1  christos 	  x0 = add16 (cpu, s0H, s1H, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
   4571  1.1  christos 	  x1 = sub16 (cpu, s0L, s1L, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
   4572  1.1  christos 	  d1 = (x0 << 16) | x1;
   4573  1.1  christos 
   4574  1.1  christos 	  x0 = sub16 (cpu, s0H, s1H, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
   4575  1.1  christos 	  x1 = add16 (cpu, s0L, s1L, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
   4576  1.1  christos 	  if (x == 0)
   4577  1.1  christos 	    d0 = (x0 << 16) | x1;
   4578  1.1  christos 	  else
   4579  1.1  christos 	    d0 = (x1 << 16) | x0;
   4580  1.1  christos 	}
   4581  1.1  christos       SET_ASTATREG (az, z_i);
   4582  1.1  christos       SET_ASTATREG (an, n_i);
   4583  1.1  christos       SET_ASTATREG (v, v_i);
   4584  1.1  christos       if (v_i)
   4585  1.1  christos 	SET_ASTATREG (vs, v_i);
   4586  1.1  christos 
   4587  1.1  christos       STORE (DREG (dst0), d0);
   4588  1.1  christos       STORE (DREG (dst1), d1);
   4589  1.1  christos     }
   4590  1.1  christos   else if ((aop == 0 || aop == 1 || aop == 2) && aopcde == 11)
   4591  1.1  christos     {
   4592  1.1  christos       bs40 acc0 = get_extended_acc (cpu, 0);
   4593  1.1  christos       bs40 acc1 = get_extended_acc (cpu, 1);
   4594  1.1  christos       bu32 v, dreg, sat = 0;
   4595  1.1  christos       bu32 carry = !!((bu40)~acc1 < (bu40)acc0);
   4596  1.1  christos 
   4597  1.1  christos       if (aop == 0)
   4598  1.1  christos 	TRACE_INSN (cpu, "R%i = (A0 += A1);", dst0);
   4599  1.1  christos       else if (aop == 1)
   4600  1.1  christos 	TRACE_INSN (cpu, "R%i.%c = (A0 += A1);", dst0, HL ? 'H' : 'L');
   4601  1.1  christos       else
   4602  1.1  christos 	TRACE_INSN (cpu, "A0 += A1%s;", s ? " (W32)" : "");
   4603  1.1  christos 
   4604  1.1  christos       acc0 += acc1;
   4605  1.1  christos       acc0 = saturate_s40_astat (acc0, &v);
   4606  1.1  christos 
   4607  1.1  christos       if (aop == 2 && s == 1)   /* A0 += A1 (W32)  */
   4608  1.1  christos 	{
   4609  1.1  christos 	  if (acc0 & (bs40)0x8000000000ll)
   4610  1.1  christos 	    acc0 &= 0x80ffffffffll;
   4611  1.1  christos 	  else
   4612  1.1  christos 	    acc0 &= 0xffffffffll;
   4613  1.1  christos 	}
   4614  1.1  christos 
   4615  1.1  christos       STORE (AXREG (0), acc0 >> 32);
   4616  1.1  christos       STORE (AWREG (0), acc0);
   4617  1.1  christos       SET_ASTATREG (av0, v && acc1);
   4618  1.1  christos       if (v)
   4619  1.1  christos 	SET_ASTATREG (av0s, v);
   4620  1.1  christos 
   4621  1.1  christos       if (aop == 0 || aop == 1)
   4622  1.1  christos 	{
   4623  1.1  christos 	  if (aop)	/* Dregs_lo = A0 += A1  */
   4624  1.1  christos 	    {
   4625  1.1  christos 	      dreg = saturate_s32 (rnd16 (acc0) << 16, &sat);
   4626  1.1  christos 	      if (HL)
   4627  1.1  christos 		STORE (DREG (dst0), REG_H_L (dreg, DREG (dst0)));
   4628  1.1  christos 	      else
   4629  1.1  christos 		STORE (DREG (dst0), REG_H_L (DREG (dst0), dreg >> 16));
   4630  1.1  christos 	    }
   4631  1.1  christos 	  else		/* Dregs = A0 += A1  */
   4632  1.1  christos 	    {
   4633  1.1  christos 	      dreg = saturate_s32 (acc0, &sat);
   4634  1.1  christos 	      STORE (DREG (dst0), dreg);
   4635  1.1  christos 	    }
   4636  1.1  christos 
   4637  1.1  christos 	  STORE (ASTATREG (az), dreg == 0);
   4638  1.1  christos 	  STORE (ASTATREG (an), !!(dreg & 0x80000000));
   4639  1.1  christos 	  STORE (ASTATREG (ac0), carry);
   4640  1.1  christos 	  STORE (ASTATREG (ac0_copy), carry);
   4641  1.1  christos 	  STORE (ASTATREG (v), sat);
   4642  1.1  christos 	  STORE (ASTATREG (v_copy), sat);
   4643  1.1  christos 	  if (sat)
   4644  1.1  christos 	    STORE (ASTATREG (vs), sat);
   4645  1.1  christos 	}
   4646  1.1  christos       else
   4647  1.1  christos 	{
   4648  1.1  christos 	  STORE (ASTATREG (az), acc0 == 0);
   4649  1.1  christos 	  STORE (ASTATREG (an), !!(acc0 & 0x8000000000ull));
   4650  1.1  christos 	  STORE (ASTATREG (ac0), carry);
   4651  1.1  christos 	  STORE (ASTATREG (ac0_copy), carry);
   4652  1.1  christos 	}
   4653  1.1  christos     }
   4654  1.1  christos   else if ((aop == 0 || aop == 1) && aopcde == 10)
   4655  1.1  christos     {
   4656  1.1  christos       TRACE_INSN (cpu, "R%i.L = A%i.X;", dst0, aop);
   4657  1.1  christos       SET_DREG_L (dst0, (bs8)AXREG (aop));
   4658  1.1  christos     }
   4659  1.1  christos   else if (aop == 0 && aopcde == 4)
   4660  1.1  christos     {
   4661  1.1  christos       TRACE_INSN (cpu, "R%i = R%i + R%i%s;", dst0, src0, src1, amod1 (s, x));
   4662  1.1  christos       SET_DREG (dst0, add32 (cpu, DREG (src0), DREG (src1), 1, s));
   4663  1.1  christos     }
   4664  1.1  christos   else if (aop == 1 && aopcde == 4)
   4665  1.1  christos     {
   4666  1.1  christos       TRACE_INSN (cpu, "R%i = R%i - R%i%s;", dst0, src0, src1, amod1 (s, x));
   4667  1.1  christos       SET_DREG (dst0, sub32 (cpu, DREG (src0), DREG (src1), 1, s, 0));
   4668  1.1  christos     }
   4669  1.1  christos   else if (aop == 2 && aopcde == 4)
   4670  1.1  christos     {
   4671  1.1  christos       TRACE_INSN (cpu, "R%i = R%i + R%i, R%i = R%i - R%i%s;",
   4672  1.1  christos 		  dst1, src0, src1, dst0, src0, src1, amod1 (s, x));
   4673  1.1  christos 
   4674  1.1  christos       if (dst0 == dst1)
   4675  1.1  christos 	illegal_instruction_combination (cpu);
   4676  1.1  christos 
   4677  1.1  christos       STORE (DREG (dst1), add32 (cpu, DREG (src0), DREG (src1), 1, s));
   4678  1.1  christos       STORE (DREG (dst0), sub32 (cpu, DREG (src0), DREG (src1), 1, s, 1));
   4679  1.1  christos     }
   4680  1.1  christos   else if ((aop == 0 || aop == 1) && aopcde == 17)
   4681  1.1  christos     {
   4682  1.1  christos       bs40 acc0 = get_extended_acc (cpu, 0);
   4683  1.1  christos       bs40 acc1 = get_extended_acc (cpu, 1);
   4684  1.1  christos       bs40 val0, val1, sval0, sval1;
   4685  1.1  christos       bu32 sat, sat_i;
   4686  1.1  christos 
   4687  1.1  christos       TRACE_INSN (cpu, "R%i = A%i + A%i, R%i = A%i - A%i%s",
   4688  1.1  christos 		  dst1, !aop, aop, dst0, !aop, aop, amod1 (s, x));
   4689  1.1  christos       TRACE_DECODE (cpu, "R%i = A%i:%#"PRIx64" + A%i:%#"PRIx64", "
   4690  1.1  christos 			 "R%i = A%i:%#"PRIx64" - A%i:%#"PRIx64"%s",
   4691  1.1  christos 		    dst1, !aop, aop ? acc0 : acc1, aop, aop ? acc1 : acc0,
   4692  1.1  christos 		    dst0, !aop, aop ? acc0 : acc1, aop, aop ? acc1 : acc0,
   4693  1.1  christos 		    amod1 (s, x));
   4694  1.1  christos 
   4695  1.1  christos       if (dst0 == dst1)
   4696  1.1  christos 	illegal_instruction_combination (cpu);
   4697  1.1  christos 
   4698  1.1  christos       val1 = acc0 + acc1;
   4699  1.1  christos       if (aop)
   4700  1.1  christos 	val0 = acc0 - acc1;
   4701  1.1  christos       else
   4702  1.1  christos 	val0 = acc1 - acc0;
   4703  1.1  christos 
   4704  1.1  christos       sval0 = saturate_s32 (val0, &sat);
   4705  1.1  christos       sat_i = sat;
   4706  1.1  christos       sval1 = saturate_s32 (val1, &sat);
   4707  1.1  christos       sat_i |= sat;
   4708  1.1  christos       if (s)
   4709  1.1  christos 	{
   4710  1.1  christos 	  val0 = sval0;
   4711  1.1  christos 	  val1 = sval1;
   4712  1.1  christos 	}
   4713  1.1  christos 
   4714  1.1  christos       STORE (DREG (dst0), val0);
   4715  1.1  christos       STORE (DREG (dst1), val1);
   4716  1.1  christos       SET_ASTATREG (v, sat_i);
   4717  1.1  christos       if (sat_i)
   4718  1.1  christos 	SET_ASTATREG (vs, sat_i);
   4719  1.1  christos       SET_ASTATREG (an, val0 & 0x80000000 || val1 & 0x80000000);
   4720  1.1  christos       SET_ASTATREG (az, val0 == 0 || val1 == 0);
   4721  1.1  christos       SET_ASTATREG (ac1, (bu40)~acc0 < (bu40)acc1);
   4722  1.1  christos       if (aop)
   4723  1.1  christos 	SET_ASTATREG (ac0, !!((bu40)acc1 <= (bu40)acc0));
   4724  1.1  christos       else
   4725  1.1  christos 	SET_ASTATREG (ac0, !!((bu40)acc0 <= (bu40)acc1));
   4726  1.1  christos     }
   4727  1.1  christos   else if (aop == 0 && aopcde == 18)
   4728  1.1  christos     {
   4729  1.1  christos       bu40 acc0 = get_extended_acc (cpu, 0);
   4730  1.1  christos       bu40 acc1 = get_extended_acc (cpu, 1);
   4731  1.1  christos       bu32 s0L = DREG (src0);
   4732  1.1  christos       bu32 s0H = DREG (src0 + 1);
   4733  1.1  christos       bu32 s1L = DREG (src1);
   4734  1.1  christos       bu32 s1H = DREG (src1 + 1);
   4735  1.1  christos       bu32 s0, s1;
   4736  1.1  christos       bs16 tmp0, tmp1, tmp2, tmp3;
   4737  1.1  christos 
   4738  1.1  christos       /* This instruction is only defined for register pairs R1:0 and R3:2.  */
   4739  1.1  christos       if (!((src0 == 0 || src0 == 2) && (src1 == 0 || src1 == 2)))
   4740  1.1  christos 	illegal_instruction (cpu);
   4741  1.1  christos 
   4742  1.1  christos       TRACE_INSN (cpu, "SAA (R%i:%i, R%i:%i)%s", src0 + 1, src0,
   4743  1.1  christos 		  src1 + 1, src1, s ? " (R)" :"");
   4744  1.1  christos 
   4745  1.1  christos       /* Bit s determines the order of the two registers from a pair:
   4746  1.1  christos          if s=0 the low-order bytes come from the low reg in the pair,
   4747  1.1  christos          and if s=1 the low-order bytes come from the high reg.  */
   4748  1.1  christos 
   4749  1.1  christos       if (s)
   4750  1.1  christos 	{
   4751  1.1  christos 	  s0 = algn (s0H, s0L, IREG (0) & 3);
   4752  1.1  christos 	  s1 = algn (s1H, s1L, IREG (1) & 3);
   4753  1.1  christos 	}
   4754  1.1  christos       else
   4755  1.1  christos 	{
   4756  1.1  christos 	  s0 = algn (s0L, s0H, IREG (0) & 3);
   4757  1.1  christos 	  s1 = algn (s1L, s1H, IREG (1) & 3);
   4758  1.1  christos 	}
   4759  1.1  christos 
   4760  1.1  christos       /* Find the absolute difference between pairs, make it
   4761  1.1  christos          absolute, then add it to the existing accumulator half.  */
   4762  1.1  christos       /* Byte 0  */
   4763  1.1  christos       tmp0  = ((s0 << 24) >> 24) - ((s1 << 24) >> 24);
   4764  1.1  christos       tmp1  = ((s0 << 16) >> 24) - ((s1 << 16) >> 24);
   4765  1.1  christos       tmp2  = ((s0 <<  8) >> 24) - ((s1 <<  8) >> 24);
   4766  1.1  christos       tmp3  = ((s0 <<  0) >> 24) - ((s1 <<  0) >> 24);
   4767  1.1  christos 
   4768  1.1  christos       tmp0  = (tmp0 < 0) ? -tmp0 : tmp0;
   4769  1.1  christos       tmp1  = (tmp1 < 0) ? -tmp1 : tmp1;
   4770  1.1  christos       tmp2  = (tmp2 < 0) ? -tmp2 : tmp2;
   4771  1.1  christos       tmp3  = (tmp3 < 0) ? -tmp3 : tmp3;
   4772  1.1  christos 
   4773  1.1  christos       s0L = saturate_u16 ((bu32)tmp0 + ((acc0 >>  0) & 0xffff), 0);
   4774  1.1  christos       s0H = saturate_u16 ((bu32)tmp1 + ((acc0 >> 16) & 0xffff), 0);
   4775  1.1  christos       s1L = saturate_u16 ((bu32)tmp2 + ((acc1 >>  0) & 0xffff), 0);
   4776  1.1  christos       s1H = saturate_u16 ((bu32)tmp3 + ((acc1 >> 16) & 0xffff), 0);
   4777  1.1  christos 
   4778  1.1  christos       STORE (AWREG (0), (s0H << 16) | (s0L & 0xFFFF));
   4779  1.1  christos       STORE (AXREG (0), 0);
   4780  1.1  christos       STORE (AWREG (1), (s1H << 16) | (s1L & 0xFFFF));
   4781  1.1  christos       STORE (AXREG (1), 0);
   4782  1.1  christos     }
   4783  1.1  christos   else if (aop == 3 && aopcde == 18)
   4784  1.1  christos     {
   4785  1.1  christos       TRACE_INSN (cpu, "DISALGNEXCPT");
   4786  1.1  christos       DIS_ALGN_EXPT |= 1;
   4787  1.1  christos     }
   4788  1.1  christos   else if ((aop == 0 || aop == 1) && aopcde == 20)
   4789  1.1  christos     {
   4790  1.1  christos       bu32 s0, s0L, s0H, s1, s1L, s1H;
   4791  1.1  christos       const char * const opts[] = { "", " (R)", " (T)", " (T, R)" };
   4792  1.1  christos 
   4793  1.1  christos       TRACE_INSN (cpu, "R%i = BYTEOP1P (R%i:%i, R%i:%i)%s;", dst0,
   4794  1.1  christos 		  src0 + 1, src0, src1 + 1, src1, opts[s + (aop << 1)]);
   4795  1.1  christos 
   4796  1.1  christos       s0L = DREG (src0);
   4797  1.1  christos       s0H = DREG (src0 + 1);
   4798  1.1  christos       s1L = DREG (src1);
   4799  1.1  christos       s1H = DREG (src1 + 1);
   4800  1.1  christos       if (s)
   4801  1.1  christos 	{
   4802  1.1  christos 	  s0 = algn (s0H, s0L, IREG (0) & 3);
   4803  1.1  christos 	  s1 = algn (s1H, s1L, IREG (1) & 3);
   4804  1.1  christos 	}
   4805  1.1  christos       else
   4806  1.1  christos 	{
   4807  1.1  christos 	  s0 = algn (s0L, s0H, IREG (0) & 3);
   4808  1.1  christos 	  s1 = algn (s1L, s1H, IREG (1) & 3);
   4809  1.1  christos 	}
   4810  1.1  christos 
   4811  1.1  christos       SET_DREG (dst0,
   4812  1.1  christos 		(((((s0 >>  0) & 0xff) + ((s1 >>  0) & 0xff) + !aop) >> 1) <<  0) |
   4813  1.1  christos 		(((((s0 >>  8) & 0xff) + ((s1 >>  8) & 0xff) + !aop) >> 1) <<  8) |
   4814  1.1  christos 		(((((s0 >> 16) & 0xff) + ((s1 >> 16) & 0xff) + !aop) >> 1) << 16) |
   4815  1.1  christos 		(((((s0 >> 24) & 0xff) + ((s1 >> 24) & 0xff) + !aop) >> 1) << 24));
   4816  1.1  christos     }
   4817  1.1  christos   else if (aop == 0 && aopcde == 21)
   4818  1.1  christos     {
   4819  1.1  christos       bu32 s0, s0L, s0H, s1, s1L, s1H;
   4820  1.1  christos 
   4821  1.1  christos       TRACE_INSN (cpu, "(R%i, R%i) = BYTEOP16P (R%i:%i, R%i:%i)%s;", dst1, dst0,
   4822  1.1  christos 		  src0 + 1, src0, src1 + 1, src1, s ? " (R)" : "");
   4823  1.1  christos 
   4824  1.1  christos       if (dst0 == dst1)
   4825  1.1  christos 	illegal_instruction_combination (cpu);
   4826  1.1  christos 
   4827  1.1  christos       s0L = DREG (src0);
   4828  1.1  christos       s0H = DREG (src0 + 1);
   4829  1.1  christos       s1L = DREG (src1);
   4830  1.1  christos       s1H = DREG (src1 + 1);
   4831  1.1  christos       if (s)
   4832  1.1  christos 	{
   4833  1.1  christos 	  s0 = algn (s0H, s0L, IREG (0) & 3);
   4834  1.1  christos 	  s1 = algn (s1H, s1L, IREG (1) & 3);
   4835  1.1  christos 	}
   4836  1.1  christos       else
   4837  1.1  christos 	{
   4838  1.1  christos 	  s0 = algn (s0L, s0H, IREG (0) & 3);
   4839  1.1  christos 	  s1 = algn (s1L, s1H, IREG (1) & 3);
   4840  1.1  christos 	}
   4841  1.1  christos 
   4842  1.1  christos       SET_DREG (dst0,
   4843  1.1  christos 		((((s0 >>  0) & 0xff) + ((s1 >>  0) & 0xff)) <<  0) |
   4844  1.1  christos 		((((s0 >>  8) & 0xff) + ((s1 >>  8) & 0xff)) << 16));
   4845  1.1  christos       SET_DREG (dst1,
   4846  1.1  christos 		((((s0 >> 16) & 0xff) + ((s1 >> 16) & 0xff)) <<  0) |
   4847  1.1  christos 		((((s0 >> 24) & 0xff) + ((s1 >> 24) & 0xff)) << 16));
   4848  1.1  christos     }
   4849  1.1  christos   else if (aop == 1 && aopcde == 21)
   4850  1.1  christos     {
   4851  1.1  christos       bu32 s0, s0L, s0H, s1, s1L, s1H;
   4852  1.1  christos 
   4853  1.1  christos       TRACE_INSN (cpu, "(R%i, R%i) = BYTEOP16M (R%i:%i, R%i:%i)%s;", dst1, dst0,
   4854  1.1  christos 		  src0 + 1, src0, src1 + 1, src1, s ? " (R)" : "");
   4855  1.1  christos 
   4856  1.1  christos       if (dst0 == dst1)
   4857  1.1  christos 	illegal_instruction_combination (cpu);
   4858  1.1  christos 
   4859  1.1  christos       s0L = DREG (src0);
   4860  1.1  christos       s0H = DREG (src0 + 1);
   4861  1.1  christos       s1L = DREG (src1);
   4862  1.1  christos       s1H = DREG (src1 + 1);
   4863  1.1  christos       if (s)
   4864  1.1  christos 	{
   4865  1.1  christos 	  s0 = algn (s0H, s0L, IREG (0) & 3);
   4866  1.1  christos 	  s1 = algn (s1H, s1L, IREG (1) & 3);
   4867  1.1  christos 	}
   4868  1.1  christos       else
   4869  1.1  christos 	{
   4870  1.1  christos 	  s0 = algn (s0L, s0H, IREG (0) & 3);
   4871  1.1  christos 	  s1 = algn (s1L, s1H, IREG (1) & 3);
   4872  1.1  christos 	}
   4873  1.1  christos 
   4874  1.1  christos       SET_DREG (dst0,
   4875  1.1  christos 		(((((s0 >>  0) & 0xff) - ((s1 >>  0) & 0xff)) <<  0) & 0xffff) |
   4876  1.1  christos 		(((((s0 >>  8) & 0xff) - ((s1 >>  8) & 0xff)) << 16)));
   4877  1.1  christos       SET_DREG (dst1,
   4878  1.1  christos 		(((((s0 >> 16) & 0xff) - ((s1 >> 16) & 0xff)) <<  0) & 0xffff) |
   4879  1.1  christos 		(((((s0 >> 24) & 0xff) - ((s1 >> 24) & 0xff)) << 16)));
   4880  1.1  christos     }
   4881  1.1  christos   else if (aop == 1 && aopcde == 7)
   4882  1.1  christos     {
   4883  1.1  christos       TRACE_INSN (cpu, "R%i = MIN (R%i, R%i);", dst0, src0, src1);
   4884  1.1  christos       SET_DREG (dst0, min32 (cpu, DREG (src0), DREG (src1)));
   4885  1.1  christos     }
   4886  1.1  christos   else if (aop == 0 && aopcde == 7)
   4887  1.1  christos     {
   4888  1.1  christos       TRACE_INSN (cpu, "R%i = MAX (R%i, R%i);", dst0, src0, src1);
   4889  1.1  christos       SET_DREG (dst0, max32 (cpu, DREG (src0), DREG (src1)));
   4890  1.1  christos     }
   4891  1.1  christos   else if (aop == 2 && aopcde == 7)
   4892  1.1  christos     {
   4893  1.1  christos       bu32 val = DREG (src0);
   4894  1.1  christos       int v;
   4895  1.1  christos 
   4896  1.1  christos       TRACE_INSN (cpu, "R%i = ABS R%i;", dst0, src0);
   4897  1.1  christos 
   4898  1.1  christos       if (val >> 31)
   4899  1.1  christos 	val = -val;
   4900  1.1  christos       v = (val == 0x80000000);
   4901  1.1  christos       if (v)
   4902  1.1  christos 	val = 0x7fffffff;
   4903  1.1  christos       SET_DREG (dst0, val);
   4904  1.1  christos 
   4905  1.1  christos       SET_ASTATREG (v, v);
   4906  1.1  christos       if (v)
   4907  1.1  christos 	SET_ASTATREG (vs, 1);
   4908  1.1  christos       setflags_nz (cpu, val);
   4909  1.1  christos     }
   4910  1.1  christos   else if (aop == 3 && aopcde == 7)
   4911  1.1  christos     {
   4912  1.1  christos       bu32 val = DREG (src0);
   4913  1.1  christos 
   4914  1.1  christos       TRACE_INSN (cpu, "R%i = - R%i %s;", dst0, src0, amod1 (s, 0));
   4915  1.1  christos 
   4916  1.1  christos       if (s && val == 0x80000000)
   4917  1.1  christos 	{
   4918  1.1  christos 	  val = 0x7fffffff;
   4919  1.1  christos 	  SET_ASTATREG (v, 1);
   4920  1.1  christos 	  SET_ASTATREG (vs, 1);
   4921  1.1  christos 	}
   4922  1.1  christos       else if (val == 0x80000000)
   4923  1.1  christos 	val = 0x80000000;
   4924  1.1  christos       else
   4925  1.1  christos 	val = -val;
   4926  1.1  christos       SET_DREG (dst0, val);
   4927  1.1  christos 
   4928  1.1  christos       SET_ASTATREG (az, val == 0);
   4929  1.1  christos       SET_ASTATREG (an, val & 0x80000000);
   4930  1.1  christos     }
   4931  1.1  christos   else if (aop == 2 && aopcde == 6)
   4932  1.1  christos     {
   4933  1.1  christos       bu32 in = DREG (src0);
   4934  1.1  christos       bu32 hi = (in & 0x80000000 ? (bu32)-(bs16)(in >> 16) : in >> 16) << 16;
   4935  1.1  christos       bu32 lo = (in & 0x8000 ? (bu32)-(bs16)(in & 0xFFFF) : in) & 0xFFFF;
   4936  1.1  christos       int v;
   4937  1.1  christos 
   4938  1.1  christos       TRACE_INSN (cpu, "R%i = ABS R%i (V);", dst0, src0);
   4939  1.1  christos 
   4940  1.1  christos       v = 0;
   4941  1.1  christos       if (hi == 0x80000000)
   4942  1.1  christos 	{
   4943  1.1  christos 	  hi = 0x7fff0000;
   4944  1.1  christos 	  v = 1;
   4945  1.1  christos 	}
   4946  1.1  christos       if (lo == 0x8000)
   4947  1.1  christos 	{
   4948  1.1  christos 	  lo = 0x7fff;
   4949  1.1  christos 	  v = 1;
   4950  1.1  christos 	}
   4951  1.1  christos       SET_DREG (dst0, hi | lo);
   4952  1.1  christos 
   4953  1.1  christos       SET_ASTATREG (v, v);
   4954  1.1  christos       if (v)
   4955  1.1  christos 	SET_ASTATREG (vs, 1);
   4956  1.1  christos       setflags_nz_2x16 (cpu, DREG (dst0));
   4957  1.1  christos     }
   4958  1.1  christos   else if (aop == 1 && aopcde == 6)
   4959  1.1  christos     {
   4960  1.1  christos       TRACE_INSN (cpu, "R%i = MIN (R%i, R%i) (V);", dst0, src0, src1);
   4961  1.1  christos       SET_DREG (dst0, min2x16 (cpu, DREG (src0), DREG (src1)));
   4962  1.1  christos     }
   4963  1.1  christos   else if (aop == 0 && aopcde == 6)
   4964  1.1  christos     {
   4965  1.1  christos       TRACE_INSN (cpu, "R%i = MAX (R%i, R%i) (V);", dst0, src0, src1);
   4966  1.1  christos       SET_DREG (dst0, max2x16 (cpu, DREG (src0), DREG (src1)));
   4967  1.1  christos     }
   4968  1.1  christos   else if (aop == 0 && aopcde == 24)
   4969  1.1  christos     {
   4970  1.1  christos       TRACE_INSN (cpu, "R%i = BYTEPACK (R%i, R%i);", dst0, src0, src1);
   4971  1.1  christos       SET_DREG (dst0,
   4972  1.1  christos 	(((DREG (src0) >>  0) & 0xff) <<  0) |
   4973  1.1  christos 	(((DREG (src0) >> 16) & 0xff) <<  8) |
   4974  1.1  christos 	(((DREG (src1) >>  0) & 0xff) << 16) |
   4975  1.1  christos 	(((DREG (src1) >> 16) & 0xff) << 24));
   4976  1.1  christos     }
   4977  1.1  christos   else if (aop == 1 && aopcde == 24)
   4978  1.1  christos     {
   4979  1.1  christos       int order, lo, hi;
   4980  1.1  christos       bu64 comb_src;
   4981  1.1  christos       bu8 bytea, byteb, bytec, byted;
   4982  1.1  christos 
   4983  1.1  christos       TRACE_INSN (cpu, "(R%i, R%i) = BYTEUNPACK R%i:%i%s;",
   4984  1.1  christos 		  dst1, dst0, src0 + 1, src0, s ? " (R)" : "");
   4985  1.1  christos 
   4986  1.1  christos       if (dst0 == dst1)
   4987  1.1  christos 	illegal_instruction_combination (cpu);
   4988  1.1  christos 
   4989  1.1  christos       order = IREG (0) & 0x3;
   4990  1.1  christos       if (s)
   4991  1.1  christos 	hi = src0, lo = src0 + 1;
   4992  1.1  christos       else
   4993  1.1  christos 	hi = src0 + 1, lo = src0;
   4994  1.1  christos       comb_src = (((bu64)DREG (hi)) << 32) | DREG (lo);
   4995  1.1  christos       bytea = (comb_src >> (0 + 8 * order));
   4996  1.1  christos       byteb = (comb_src >> (8 + 8 * order));
   4997  1.1  christos       bytec = (comb_src >> (16 + 8 * order));
   4998  1.1  christos       byted = (comb_src >> (24 + 8 * order));
   4999  1.1  christos       SET_DREG (dst0, bytea | ((bu32)byteb << 16));
   5000  1.1  christos       SET_DREG (dst1, bytec | ((bu32)byted << 16));
   5001  1.1  christos     }
   5002  1.1  christos   else if (aopcde == 13)
   5003  1.1  christos     {
   5004  1.1  christos       const char *searchmodes[] = { "GT", "GE", "LT", "LE" };
   5005  1.1  christos       bool up_hi, up_lo;
   5006  1.1  christos       bs16 a0_lo, a1_lo, src_hi, src_lo;
   5007  1.1  christos 
   5008  1.1  christos       TRACE_INSN (cpu, "(R%i, R%i) = SEARCH R%i (%s);",
   5009  1.1  christos 		  dst1, dst0, src0, searchmodes[aop]);
   5010  1.1  christos 
   5011  1.1  christos       if (dst0 == dst1)
   5012  1.1  christos 	illegal_instruction_combination (cpu);
   5013  1.1  christos 
   5014  1.1  christos       up_hi = up_lo = false;
   5015  1.1  christos       a0_lo = AWREG (0);
   5016  1.1  christos       a1_lo = AWREG (1);
   5017  1.1  christos       src_lo = DREG (src0);
   5018  1.1  christos       src_hi = DREG (src0) >> 16;
   5019  1.1  christos 
   5020  1.1  christos       switch (aop)
   5021  1.1  christos 	{
   5022  1.1  christos 	case 0:
   5023  1.1  christos 	  up_hi = (src_hi > a1_lo);
   5024  1.1  christos 	  up_lo = (src_lo > a0_lo);
   5025  1.1  christos 	  break;
   5026  1.1  christos 	case 1:
   5027  1.1  christos 	  up_hi = (src_hi >= a1_lo);
   5028  1.1  christos 	  up_lo = (src_lo >= a0_lo);
   5029  1.1  christos 	  break;
   5030  1.1  christos 	case 2:
   5031  1.1  christos 	  up_hi = (src_hi < a1_lo);
   5032  1.1  christos 	  up_lo = (src_lo < a0_lo);
   5033  1.1  christos 	  break;
   5034  1.1  christos 	case 3:
   5035  1.1  christos 	  up_hi = (src_hi <= a1_lo);
   5036  1.1  christos 	  up_lo = (src_lo <= a0_lo);
   5037  1.1  christos 	  break;
   5038  1.1  christos 	}
   5039  1.1  christos 
   5040  1.1  christos       if (up_hi)
   5041  1.1  christos 	{
   5042  1.1  christos 	  SET_AREG (1, src_hi);
   5043  1.1  christos 	  SET_DREG (dst1, PREG (0));
   5044  1.1  christos 	}
   5045  1.1  christos       else
   5046  1.1  christos 	SET_AREG (1, a1_lo);
   5047  1.1  christos 
   5048  1.1  christos       if (up_lo)
   5049  1.1  christos 	{
   5050  1.1  christos 	  SET_AREG (0, src_lo);
   5051  1.1  christos 	  SET_DREG (dst0, PREG (0));
   5052  1.1  christos 	}
   5053  1.1  christos       else
   5054  1.1  christos 	SET_AREG (0, a0_lo);
   5055  1.1  christos     }
   5056  1.1  christos   else
   5057  1.1  christos     illegal_instruction (cpu);
   5058  1.1  christos }
   5059  1.1  christos 
   5060  1.1  christos static void
   5061  1.1  christos decode_dsp32shift_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
   5062  1.1  christos {
   5063  1.1  christos   /* dsp32shift
   5064  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
   5065  1.1  christos      | 1 | 1 | 0 | 0 |.M.| 1 | 1 | 0 | 0 | - | - |.sopcde............|
   5066  1.1  christos      |.sop...|.HLs...|.dst0......| - | - | - |.src0......|.src1......|
   5067  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
   5068  1.1  christos   int HLs  = ((iw1 >> DSP32Shift_HLs_bits) & DSP32Shift_HLs_mask);
   5069  1.1  christos   int sop  = ((iw1 >> DSP32Shift_sop_bits) & DSP32Shift_sop_mask);
   5070  1.1  christos   int src0 = ((iw1 >> DSP32Shift_src0_bits) & DSP32Shift_src0_mask);
   5071  1.1  christos   int src1 = ((iw1 >> DSP32Shift_src1_bits) & DSP32Shift_src1_mask);
   5072  1.1  christos   int dst0 = ((iw1 >> DSP32Shift_dst0_bits) & DSP32Shift_dst0_mask);
   5073  1.1  christos   int sopcde = ((iw0 >> (DSP32Shift_sopcde_bits - 16)) & DSP32Shift_sopcde_mask);
   5074  1.1  christos   int M = ((iw0 >> (DSP32Shift_M_bits - 16)) & DSP32Shift_M_mask);
   5075  1.1  christos 
   5076  1.1  christos   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dsp32shift);
   5077  1.1  christos   TRACE_EXTRACT (cpu, "%s: M:%i sopcde:%i sop:%i HLs:%i dst0:%i src0:%i src1:%i",
   5078  1.1  christos 		 __func__, M, sopcde, sop, HLs, dst0, src0, src1);
   5079  1.1  christos 
   5080  1.1  christos   if ((sop == 0 || sop == 1) && sopcde == 0)
   5081  1.1  christos     {
   5082  1.1  christos       bu16 val;
   5083  1.1  christos       bs32 shft = (bs8)(DREG (src0) << 2) >> 2;
   5084  1.1  christos 
   5085  1.1  christos       TRACE_INSN (cpu, "R%i.%c = ASHIFT R%i.%c BY R%i.L%s;",
   5086  1.1  christos 		  dst0, HLs < 2 ? 'L' : 'H',
   5087  1.1  christos 		  src1, HLs & 1 ? 'H' : 'L',
   5088  1.1  christos 		  src0, sop == 1 ? " (S)" : "");
   5089  1.1  christos 
   5090  1.1  christos       if ((HLs & 1) == 0)
   5091  1.1  christos 	val = (bu16)(DREG (src1) & 0xFFFF);
   5092  1.1  christos       else
   5093  1.1  christos 	val = (bu16)((DREG (src1) & 0xFFFF0000) >> 16);
   5094  1.1  christos 
   5095  1.1  christos       /* Positive shift magnitudes produce Logical Left shifts.
   5096  1.1  christos          Negative shift magnitudes produce Arithmetic Right shifts.  */
   5097  1.1  christos       if (shft <= 0)
   5098  1.1  christos 	val = ashiftrt (cpu, val, -shft, 16);
   5099  1.1  christos       else
   5100  1.1  christos 	val = lshift (cpu, val, shft, 16, sop == 1);
   5101  1.1  christos 
   5102  1.1  christos       if ((HLs & 2) == 0)
   5103  1.1  christos 	STORE (DREG (dst0), REG_H_L (DREG (dst0), val));
   5104  1.1  christos       else
   5105  1.1  christos 	STORE (DREG (dst0), REG_H_L (val << 16, DREG (dst0)));
   5106  1.1  christos     }
   5107  1.1  christos   else if (sop == 2 && sopcde == 0)
   5108  1.1  christos     {
   5109  1.1  christos       bs32 shft = (bs8)(DREG (src0) << 2) >> 2;
   5110  1.1  christos       bu16 val;
   5111  1.1  christos 
   5112  1.1  christos       TRACE_INSN (cpu, "R%i.%c = LSHIFT R%i.%c BY R%i.L;",
   5113  1.1  christos 		  dst0, HLs < 2 ? 'L' : 'H',
   5114  1.1  christos 		  src1, HLs & 1 ? 'H' : 'L', src0);
   5115  1.1  christos 
   5116  1.1  christos       if ((HLs & 1) == 0)
   5117  1.1  christos 	val = (bu16)(DREG (src1) & 0xFFFF);
   5118  1.1  christos       else
   5119  1.1  christos 	val = (bu16)((DREG (src1) & 0xFFFF0000) >> 16);
   5120  1.1  christos 
   5121  1.1  christos       if (shft < 0)
   5122  1.1  christos 	val = val >> (-1 * shft);
   5123  1.1  christos       else
   5124  1.1  christos 	val = val << shft;
   5125  1.1  christos 
   5126  1.1  christos       if ((HLs & 2) == 0)
   5127  1.1  christos 	SET_DREG (dst0, REG_H_L (DREG (dst0), val));
   5128  1.1  christos       else
   5129  1.1  christos 	SET_DREG (dst0, REG_H_L (val << 16, DREG (dst0)));
   5130  1.1  christos 
   5131  1.1  christos       SET_ASTATREG (az, !((val & 0xFFFF0000) == 0) || ((val & 0xFFFF) == 0));
   5132  1.1  christos       SET_ASTATREG (an, (!!(val & 0x80000000)) ^ (!!(val & 0x8000)));
   5133  1.1  christos       SET_ASTATREG (v, 0);
   5134  1.1  christos     }
   5135  1.1  christos   else if (sop == 2 && sopcde == 3 && (HLs == 1 || HLs == 0))
   5136  1.1  christos     {
   5137  1.1  christos       int shift = imm6 (DREG (src0) & 0xFFFF);
   5138  1.1  christos       bu32 cc = CCREG;
   5139  1.1  christos       bu40 acc = get_unextended_acc (cpu, HLs);
   5140  1.1  christos 
   5141  1.1  christos       TRACE_INSN (cpu, "A%i = ROT A%i BY R%i.L;", HLs, HLs, src0);
   5142  1.1  christos       TRACE_DECODE (cpu, "A%i:%#"PRIx64" shift:%i CC:%i", HLs, acc, shift, cc);
   5143  1.1  christos 
   5144  1.1  christos       acc = rot40 (acc, shift, &cc);
   5145  1.1  christos       SET_AREG (HLs, acc);
   5146  1.1  christos       if (shift)
   5147  1.1  christos 	SET_CCREG (cc);
   5148  1.1  christos     }
   5149  1.1  christos   else if (sop == 0 && sopcde == 3 && (HLs == 0 || HLs == 1))
   5150  1.1  christos     {
   5151  1.1  christos       bs32 shft = (bs8)(DREG (src0) << 2) >> 2;
   5152  1.1  christos       bu64 val = get_extended_acc (cpu, HLs);
   5153  1.1  christos 
   5154  1.1  christos       HLs = !!HLs;
   5155  1.1  christos       TRACE_INSN (cpu, "A%i = ASHIFT A%i BY R%i.L;", HLs, HLs, src0);
   5156  1.1  christos       TRACE_DECODE (cpu, "A%i:%#"PRIx64" shift:%i", HLs, val, shft);
   5157  1.1  christos 
   5158  1.1  christos       if (shft <= 0)
   5159  1.1  christos 	val = ashiftrt (cpu, val, -shft, 40);
   5160  1.1  christos       else
   5161  1.1  christos 	val = lshift (cpu, val, shft, 40, 0);
   5162  1.1  christos 
   5163  1.1  christos       STORE (AXREG (HLs), (val >> 32) & 0xff);
   5164  1.1  christos       STORE (AWREG (HLs), (val & 0xffffffff));
   5165  1.1  christos     }
   5166  1.1  christos   else if (sop == 1 && sopcde == 3 && (HLs == 0 || HLs == 1))
   5167  1.1  christos     {
   5168  1.1  christos       bs32 shft = (bs8)(DREG (src0) << 2) >> 2;
   5169  1.1  christos       bu64 val;
   5170  1.1  christos 
   5171  1.1  christos       HLs = !!HLs;
   5172  1.1  christos       TRACE_INSN (cpu, "A%i = LSHIFT A%i BY R%i.L;", HLs, HLs, src0);
   5173  1.1  christos       val = get_extended_acc (cpu, HLs);
   5174  1.1  christos 
   5175  1.1  christos       if (shft <= 0)
   5176  1.1  christos 	val = lshiftrt (cpu, val, -shft, 40);
   5177  1.1  christos       else
   5178  1.1  christos 	val = lshift (cpu, val, shft, 40, 0);
   5179  1.1  christos 
   5180  1.1  christos       STORE (AXREG (HLs), (val >> 32) & 0xff);
   5181  1.1  christos       STORE (AWREG (HLs), (val & 0xffffffff));
   5182  1.1  christos     }
   5183  1.1  christos   else if ((sop == 0 || sop == 1) && sopcde == 1)
   5184  1.1  christos     {
   5185  1.1  christos       bs32 shft = (bs8)(DREG (src0) << 2) >> 2;
   5186  1.1  christos       bu16 val0, val1;
   5187  1.1  christos       bu32 astat;
   5188  1.1  christos 
   5189  1.1  christos       TRACE_INSN (cpu, "R%i = ASHIFT R%i BY R%i.L (V%s);",
   5190  1.1  christos 		  dst0, src1, src0, sop == 1 ? ",S" : "");
   5191  1.1  christos 
   5192  1.1  christos       val0 = (bu16)DREG (src1) & 0xFFFF;
   5193  1.1  christos       val1 = (bu16)((DREG (src1) & 0xFFFF0000) >> 16);
   5194  1.1  christos 
   5195  1.1  christos       if (shft <= 0)
   5196  1.1  christos 	{
   5197  1.1  christos 	  val0 = ashiftrt (cpu, val0, -shft, 16);
   5198  1.1  christos 	  astat = ASTAT;
   5199  1.1  christos 	  val1 = ashiftrt (cpu, val1, -shft, 16);
   5200  1.1  christos 	}
   5201  1.1  christos       else
   5202  1.1  christos 	{
   5203  1.1  christos 	  val0 = lshift (cpu, val0, shft, 16, sop == 1);
   5204  1.1  christos 	  astat = ASTAT;
   5205  1.1  christos 	  val1 = lshift (cpu, val1, shft, 16, sop == 1);
   5206  1.1  christos 	}
   5207  1.1  christos       SET_ASTAT (ASTAT | astat);
   5208  1.1  christos       STORE (DREG (dst0), (val1 << 16) | val0);
   5209  1.1  christos     }
   5210  1.1  christos   else if ((sop == 0 || sop == 1 || sop == 2) && sopcde == 2)
   5211  1.1  christos     {
   5212  1.1  christos       /* dregs = [LA]SHIFT dregs BY dregs_lo (opt_S)  */
   5213  1.1  christos       /* sop == 1 : opt_S  */
   5214  1.1  christos       bu32 v = DREG (src1);
   5215  1.1  christos       /* LSHIFT uses sign extended low 6 bits of dregs_lo.  */
   5216  1.1  christos       bs32 shft = (bs8)(DREG (src0) << 2) >> 2;
   5217  1.1  christos 
   5218  1.1  christos       TRACE_INSN (cpu, "R%i = %cSHIFT R%i BY R%i.L%s;", dst0,
   5219  1.1  christos 		  shft && sop != 2 ? 'A' : 'L', src1, src0,
   5220  1.1  christos 		  sop == 1 ? " (S)" : "");
   5221  1.1  christos 
   5222  1.1  christos       if (shft < 0)
   5223  1.1  christos 	{
   5224  1.1  christos 	  if (sop == 2)
   5225  1.1  christos 	    STORE (DREG (dst0), lshiftrt (cpu, v, -shft, 32));
   5226  1.1  christos 	  else
   5227  1.1  christos 	    STORE (DREG (dst0), ashiftrt (cpu, v, -shft, 32));
   5228  1.1  christos 	}
   5229  1.1  christos       else
   5230  1.1  christos 	STORE (DREG (dst0), lshift (cpu, v, shft, 32, sop == 1));
   5231  1.1  christos     }
   5232  1.1  christos   else if (sop == 3 && sopcde == 2)
   5233  1.1  christos     {
   5234  1.1  christos       int shift = imm6 (DREG (src0) & 0xFFFF);
   5235  1.1  christos       bu32 src = DREG (src1);
   5236  1.1  christos       bu32 ret, cc = CCREG;
   5237  1.1  christos 
   5238  1.1  christos       TRACE_INSN (cpu, "R%i = ROT R%i BY R%i.L;", dst0, src1, src0);
   5239  1.1  christos       TRACE_DECODE (cpu, "R%i:%#x R%i:%#x shift:%i CC:%i",
   5240  1.1  christos 		    dst0, DREG (dst0), src1, src, shift, cc);
   5241  1.1  christos 
   5242  1.1  christos       ret = rot32 (src, shift, &cc);
   5243  1.1  christos       STORE (DREG (dst0), ret);
   5244  1.1  christos       if (shift)
   5245  1.1  christos 	SET_CCREG (cc);
   5246  1.1  christos     }
   5247  1.1  christos   else if (sop == 2 && sopcde == 1)
   5248  1.1  christos     {
   5249  1.1  christos       bs32 shft = (bs8)(DREG (src0) << 2) >> 2;
   5250  1.1  christos       bu16 val0, val1;
   5251  1.1  christos       bu32 astat;
   5252  1.1  christos 
   5253  1.1  christos       TRACE_INSN (cpu, "R%i = LSHIFT R%i BY R%i.L (V);", dst0, src1, src0);
   5254  1.1  christos 
   5255  1.1  christos       val0 = (bu16)DREG (src1) & 0xFFFF;
   5256  1.1  christos       val1 = (bu16)((DREG (src1) & 0xFFFF0000) >> 16);
   5257  1.1  christos 
   5258  1.1  christos       if (shft <= 0)
   5259  1.1  christos 	{
   5260  1.1  christos 	  val0 = lshiftrt (cpu, val0, -shft, 16);
   5261  1.1  christos 	  astat = ASTAT;
   5262  1.1  christos 	  val1 = lshiftrt (cpu, val1, -shft, 16);
   5263  1.1  christos 	}
   5264  1.1  christos       else
   5265  1.1  christos 	{
   5266  1.1  christos 	  val0 = lshift (cpu, val0, shft, 16, 0);
   5267  1.1  christos 	  astat = ASTAT;
   5268  1.1  christos 	  val1 = lshift (cpu, val1, shft, 16, 0);
   5269  1.1  christos 	}
   5270  1.1  christos       SET_ASTAT (ASTAT | astat);
   5271  1.1  christos       STORE (DREG (dst0), (val1 << 16) | val0);
   5272  1.1  christos     }
   5273  1.1  christos   else if (sopcde == 4)
   5274  1.1  christos     {
   5275  1.1  christos       bu32 sv0 = DREG (src0);
   5276  1.1  christos       bu32 sv1 = DREG (src1);
   5277  1.1  christos       TRACE_INSN (cpu, "R%i = PACK (R%i.%c, R%i.%c);", dst0,
   5278  1.1  christos 		  src1, sop & 2 ? 'H' : 'L',
   5279  1.1  christos 		  src0, sop & 1 ? 'H' : 'L');
   5280  1.1  christos       if (sop & 1)
   5281  1.1  christos 	sv0 >>= 16;
   5282  1.1  christos       if (sop & 2)
   5283  1.1  christos 	sv1 >>= 16;
   5284  1.1  christos       SET_DREG (dst0, (sv1 << 16) | (sv0 & 0xFFFF));
   5285  1.1  christos     }
   5286  1.1  christos   else if (sop == 0 && sopcde == 5)
   5287  1.1  christos     {
   5288  1.1  christos       bu32 sv1 = DREG (src1);
   5289  1.1  christos       TRACE_INSN (cpu, "R%i.L = SIGNBITS R%i;", dst0, src1);
   5290  1.1  christos       SET_DREG_L (dst0, signbits (sv1, 32));
   5291  1.1  christos     }
   5292  1.1  christos   else if (sop == 1 && sopcde == 5)
   5293  1.1  christos     {
   5294  1.1  christos       bu32 sv1 = DREG (src1);
   5295  1.1  christos       TRACE_INSN (cpu, "R%i.L = SIGNBITS R%i.L;", dst0, src1);
   5296  1.1  christos       SET_DREG_L (dst0, signbits (sv1, 16));
   5297  1.1  christos     }
   5298  1.1  christos   else if (sop == 2 && sopcde == 5)
   5299  1.1  christos     {
   5300  1.1  christos       bu32 sv1 = DREG (src1);
   5301  1.1  christos       TRACE_INSN (cpu, "R%i.L = SIGNBITS R%i.H;", dst0, src1);
   5302  1.1  christos       SET_DREG_L (dst0, signbits (sv1 >> 16, 16));
   5303  1.1  christos     }
   5304  1.1  christos   else if ((sop == 0 || sop == 1) && sopcde == 6)
   5305  1.1  christos     {
   5306  1.1  christos       bu64 acc = AXREG (sop);
   5307  1.1  christos       TRACE_INSN (cpu, "R%i.L = SIGNBITS A%i;", dst0, sop);
   5308  1.1  christos       acc <<= 32;
   5309  1.1  christos       acc |= AWREG (sop);
   5310  1.1  christos       SET_DREG_L (dst0, signbits (acc, 40) & 0xFFFF);
   5311  1.1  christos     }
   5312  1.1  christos   else if (sop == 3 && sopcde == 6)
   5313  1.1  christos     {
   5314  1.1  christos       bu32 v = ones (DREG (src1));
   5315  1.1  christos       TRACE_INSN (cpu, "R%i.L = ONES R%i;", dst0, src1);
   5316  1.1  christos       SET_DREG_L (dst0, v);
   5317  1.1  christos     }
   5318  1.1  christos   else if (sop == 0 && sopcde == 7)
   5319  1.1  christos     {
   5320  1.1  christos       bu16 sv1 = (bu16)signbits (DREG (src1), 32);
   5321  1.1  christos       bu16 sv0 = (bu16)DREG (src0);
   5322  1.1  christos       bu16 dst_lo;
   5323  1.1  christos 
   5324  1.1  christos       TRACE_INSN (cpu, "R%i.L = EXPADJ (R%i, R%i.L);", dst0, src1, src0);
   5325  1.1  christos 
   5326  1.1  christos       if ((sv1 & 0x1f) < (sv0 & 0x1f))
   5327  1.1  christos 	dst_lo = sv1;
   5328  1.1  christos       else
   5329  1.1  christos 	dst_lo = sv0;
   5330  1.1  christos       STORE (DREG (dst0), REG_H_L (DREG (dst0), dst_lo));
   5331  1.1  christos     }
   5332  1.1  christos   else if (sop == 1 && sopcde == 7)
   5333  1.1  christos     {
   5334  1.1  christos       /* Exponent adjust on two 16-bit inputs.  Select
   5335  1.1  christos          smallest norm among 3 inputs.  */
   5336  1.1  christos       bs16 src1_hi = (DREG (src1) & 0xFFFF0000) >> 16;
   5337  1.1  christos       bs16 src1_lo = (DREG (src1) & 0xFFFF);
   5338  1.1  christos       bu16 src0_lo = (DREG (src0) & 0xFFFF);
   5339  1.1  christos       bu16 tmp_hi, tmp_lo, tmp;
   5340  1.1  christos 
   5341  1.1  christos       TRACE_INSN (cpu, "R%i.L = EXPADJ (R%i, R%i.L) (V);", dst0, src1, src0);
   5342  1.1  christos 
   5343  1.1  christos       tmp_hi = signbits (src1_hi, 16);
   5344  1.1  christos       tmp_lo = signbits (src1_lo, 16);
   5345  1.1  christos 
   5346  1.1  christos       if ((tmp_hi & 0xf) < (tmp_lo & 0xf))
   5347  1.1  christos 	if ((tmp_hi & 0xf) < (src0_lo & 0xf))
   5348  1.1  christos 	  tmp = tmp_hi;
   5349  1.1  christos 	else
   5350  1.1  christos 	  tmp = src0_lo;
   5351  1.1  christos       else
   5352  1.1  christos 	if ((tmp_lo & 0xf) < (src0_lo & 0xf))
   5353  1.1  christos 	  tmp = tmp_lo;
   5354  1.1  christos 	else
   5355  1.1  christos 	  tmp = src0_lo;
   5356  1.1  christos       STORE (DREG (dst0), REG_H_L (DREG (dst0), tmp));
   5357  1.1  christos     }
   5358  1.1  christos   else if (sop == 2 && sopcde == 7)
   5359  1.1  christos     {
   5360  1.1  christos       /* Exponent adjust on single 16-bit register.  */
   5361  1.1  christos       bu16 tmp;
   5362  1.1  christos       bu16 src0_lo = (bu16)(DREG (src0) & 0xFFFF);
   5363  1.1  christos 
   5364  1.1  christos       TRACE_INSN (cpu, "R%i.L = EXPADJ (R%i.L, R%i.L);", dst0, src1, src0);
   5365  1.1  christos 
   5366  1.1  christos       tmp = signbits (DREG (src1) & 0xFFFF, 16);
   5367  1.1  christos 
   5368  1.1  christos       if ((tmp & 0xf) < (src0_lo & 0xf))
   5369  1.1  christos 	SET_DREG_L (dst0, tmp);
   5370  1.1  christos       else
   5371  1.1  christos 	SET_DREG_L (dst0, src0_lo);
   5372  1.1  christos     }
   5373  1.1  christos   else if (sop == 3 && sopcde == 7)
   5374  1.1  christos     {
   5375  1.1  christos       bu16 tmp;
   5376  1.1  christos       bu16 src0_lo = (bu16)(DREG (src0) & 0xFFFF);
   5377  1.1  christos 
   5378  1.1  christos       TRACE_INSN (cpu, "R%i.L = EXPADJ (R%i.H, R%i.L);", dst0, src1, src0);
   5379  1.1  christos 
   5380  1.1  christos       tmp = signbits ((DREG (src1) & 0xFFFF0000) >> 16, 16);
   5381  1.1  christos 
   5382  1.1  christos       if ((tmp & 0xf) < (src0_lo & 0xf))
   5383  1.1  christos 	SET_DREG_L (dst0, tmp);
   5384  1.1  christos       else
   5385  1.1  christos 	SET_DREG_L (dst0, src0_lo);
   5386  1.1  christos     }
   5387  1.1  christos   else if (sop == 0 && sopcde == 8)
   5388  1.1  christos     {
   5389  1.1  christos       bu64 acc = get_unextended_acc (cpu, 0);
   5390  1.1  christos       bu32 s0, s1;
   5391  1.1  christos 
   5392  1.1  christos       TRACE_INSN (cpu, "BITMUX (R%i, R%i, A0) (ASR);", src0, src1);
   5393  1.1  christos 
   5394  1.1  christos       if (src0 == src1)
   5395  1.1  christos 	illegal_instruction_combination (cpu);
   5396  1.1  christos 
   5397  1.1  christos       s0 = DREG (src0);
   5398  1.1  christos       s1 = DREG (src1);
   5399  1.1  christos       acc = (acc >> 2) |
   5400  1.1  christos 	(((bu64)s0 & 1) << 38) |
   5401  1.1  christos 	(((bu64)s1 & 1) << 39);
   5402  1.1  christos       SET_DREG (src0, s0 >> 1);
   5403  1.1  christos       SET_DREG (src1, s1 >> 1);
   5404  1.1  christos 
   5405  1.1  christos       SET_AREG (0, acc);
   5406  1.1  christos     }
   5407  1.1  christos   else if (sop == 1 && sopcde == 8)
   5408  1.1  christos     {
   5409  1.1  christos       bu64 acc = get_unextended_acc (cpu, 0);
   5410  1.1  christos       bu32 s0, s1;
   5411  1.1  christos 
   5412  1.1  christos       TRACE_INSN (cpu, "BITMUX (R%i, R%i, A0) (ASL);", src0, src1);
   5413  1.1  christos 
   5414  1.1  christos       if (src0 == src1)
   5415  1.1  christos 	illegal_instruction_combination (cpu);
   5416  1.1  christos 
   5417  1.1  christos       s0 = DREG (src0);
   5418  1.1  christos       s1 = DREG (src1);
   5419  1.1  christos       acc = (acc << 2) |
   5420  1.1  christos 	((s0 >> 31) & 1) |
   5421  1.1  christos 	((s1 >> 30) & 2);
   5422  1.1  christos       SET_DREG (src0, s0 << 1);
   5423  1.1  christos       SET_DREG (src1, s1 << 1);
   5424  1.1  christos 
   5425  1.1  christos       SET_AREG (0, acc);
   5426  1.1  christos     }
   5427  1.1  christos   else if ((sop == 0 || sop == 1) && sopcde == 9)
   5428  1.1  christos     {
   5429  1.1  christos       bs40 acc0 = get_unextended_acc (cpu, 0);
   5430  1.1  christos       bs16 sL, sH, out;
   5431  1.1  christos 
   5432  1.1  christos       TRACE_INSN (cpu, "R%i.L = VIT_MAX (R%i) (AS%c);",
   5433  1.1  christos 		  dst0, src1, sop & 1 ? 'R' : 'L');
   5434  1.1  christos 
   5435  1.1  christos       sL = DREG (src1);
   5436  1.1  christos       sH = DREG (src1) >> 16;
   5437  1.1  christos 
   5438  1.1  christos       if (sop & 1)
   5439  1.1  christos 	acc0 = (acc0 & 0xfeffffffffull) >> 1;
   5440  1.1  christos       else
   5441  1.1  christos 	acc0 <<= 1;
   5442  1.1  christos 
   5443  1.1  christos       if (((sH - sL) & 0x8000) == 0)
   5444  1.1  christos 	{
   5445  1.1  christos 	  out = sH;
   5446  1.1  christos 	  acc0 |= (sop & 1) ? 0x80000000 : 1;
   5447  1.1  christos 	}
   5448  1.1  christos       else
   5449  1.1  christos 	out = sL;
   5450  1.1  christos 
   5451  1.1  christos       SET_AREG (0, acc0);
   5452  1.1  christos       SET_DREG (dst0, REG_H_L (DREG (dst0), out));
   5453  1.1  christos     }
   5454  1.1  christos   else if ((sop == 2 || sop == 3) && sopcde == 9)
   5455  1.1  christos     {
   5456  1.1  christos       bs40 acc0 = get_extended_acc (cpu, 0);
   5457  1.1  christos       bs16 s0L, s0H, s1L, s1H, out0, out1;
   5458  1.1  christos 
   5459  1.1  christos       TRACE_INSN (cpu, "R%i = VIT_MAX (R%i, R%i) (AS%c);",
   5460  1.1  christos 		  dst0, src1, src0, sop & 1 ? 'R' : 'L');
   5461  1.1  christos 
   5462  1.1  christos       s0L = DREG (src0);
   5463  1.1  christos       s0H = DREG (src0) >> 16;
   5464  1.1  christos       s1L = DREG (src1);
   5465  1.1  christos       s1H = DREG (src1) >> 16;
   5466  1.1  christos 
   5467  1.1  christos       if (sop & 1)
   5468  1.1  christos 	acc0 >>= 2;
   5469  1.1  christos       else
   5470  1.1  christos 	acc0 <<= 2;
   5471  1.1  christos 
   5472  1.1  christos       if (((s0H - s0L) & 0x8000) == 0)
   5473  1.1  christos 	{
   5474  1.1  christos 	  out0 = s0H;
   5475  1.1  christos 	  acc0 |= (sop & 1) ? 0x40000000 : 2;
   5476  1.1  christos 	}
   5477  1.1  christos       else
   5478  1.1  christos 	out0 = s0L;
   5479  1.1  christos 
   5480  1.1  christos       if (((s1H - s1L) & 0x8000) == 0)
   5481  1.1  christos 	{
   5482  1.1  christos 	  out1 = s1H;
   5483  1.1  christos 	  acc0 |= (sop & 1) ? 0x80000000 : 1;
   5484  1.1  christos 	}
   5485  1.1  christos       else
   5486  1.1  christos 	out1 = s1L;
   5487  1.1  christos 
   5488  1.1  christos       SET_AREG (0, acc0);
   5489  1.1  christos       SET_DREG (dst0, REG_H_L (out1 << 16, out0));
   5490  1.1  christos     }
   5491  1.1  christos   else if (sop == 0 && sopcde == 10)
   5492  1.1  christos     {
   5493  1.1  christos       bu32 v = DREG (src0);
   5494  1.1  christos       bu32 x = DREG (src1);
   5495  1.1  christos       bu32 mask = (1 << (v & 0x1f)) - 1;
   5496  1.1  christos       TRACE_INSN (cpu, "R%i = EXTRACT (R%i, R%i.L) (Z);", dst0, src1, src0);
   5497  1.1  christos       x >>= ((v >> 8) & 0x1f);
   5498  1.1  christos       SET_DREG (dst0, x & mask);
   5499  1.1  christos       setflags_logical (cpu, DREG (dst0));
   5500  1.1  christos     }
   5501  1.1  christos   else if (sop == 1 && sopcde == 10)
   5502  1.1  christos     {
   5503  1.1  christos       bu32 v = DREG (src0);
   5504  1.1  christos       bu32 x = DREG (src1);
   5505  1.1  christos       bu32 sgn = (1 << (v & 0x1f)) >> 1;
   5506  1.1  christos       bu32 mask = (1 << (v & 0x1f)) - 1;
   5507  1.1  christos       TRACE_INSN (cpu, "R%i = EXTRACT (R%i, R%i.L) (X);", dst0, src1, src0);
   5508  1.1  christos       x >>= ((v >> 8) & 0x1f);
   5509  1.1  christos       x &= mask;
   5510  1.1  christos       if (x & sgn)
   5511  1.1  christos 	x |= ~mask;
   5512  1.1  christos       SET_DREG (dst0, x);
   5513  1.1  christos       setflags_logical (cpu, DREG (dst0));
   5514  1.1  christos     }
   5515  1.1  christos   else if ((sop == 2 || sop == 3) && sopcde == 10)
   5516  1.1  christos     {
   5517  1.1  christos       /* The first dregs is the "background" while the second dregs is the
   5518  1.1  christos          "foreground".  The fg reg is used to overlay the bg reg and is:
   5519  1.1  christos          | nnnn nnnn | nnnn nnnn | xxxp pppp | xxxL LLLL |
   5520  1.1  christos            n = the fg bit field
   5521  1.1  christos            p = bit position in bg reg to start LSB of fg field
   5522  1.1  christos            L = number of fg bits to extract
   5523  1.1  christos          Using (X) sign-extends the fg bit field.  */
   5524  1.1  christos       bu32 fg = DREG (src0);
   5525  1.1  christos       bu32 bg = DREG (src1);
   5526  1.1  christos       bu32 len = fg & 0x1f;
   5527  1.1  christos       bu32 mask = (1 << MIN (16, len)) - 1;
   5528  1.1  christos       bu32 fgnd = (fg >> 16) & mask;
   5529  1.1  christos       int shft = ((fg >> 8) & 0x1f);
   5530  1.1  christos 
   5531  1.1  christos       TRACE_INSN (cpu, "R%i = DEPOSIT (R%i, R%i)%s;", dst0, src1, src0,
   5532  1.1  christos 		  sop == 3 ? " (X)" : "");
   5533  1.1  christos 
   5534  1.1  christos       if (sop == 3)
   5535  1.1  christos 	{
   5536  1.1  christos 	  /* Sign extend the fg bit field.  */
   5537  1.1  christos 	  mask = -1;
   5538  1.1  christos 	  fgnd = ((bs32)(bs16)(fgnd << (16 - len))) >> (16 - len);
   5539  1.1  christos 	}
   5540  1.1  christos       fgnd <<= shft;
   5541  1.1  christos       mask <<= shft;
   5542  1.1  christos       bg &= ~mask;
   5543  1.1  christos 
   5544  1.1  christos       SET_DREG (dst0, bg | fgnd);
   5545  1.1  christos       setflags_logical (cpu, DREG (dst0));
   5546  1.1  christos     }
   5547  1.1  christos   else if (sop == 0 && sopcde == 11)
   5548  1.1  christos     {
   5549  1.1  christos       bu64 acc0 = get_unextended_acc (cpu, 0);
   5550  1.1  christos 
   5551  1.1  christos       TRACE_INSN (cpu, "R%i.L = CC = BXORSHIFT (A0, R%i);", dst0, src0);
   5552  1.1  christos 
   5553  1.1  christos       acc0 <<= 1;
   5554  1.1  christos       SET_CCREG (xor_reduce (acc0, DREG (src0)));
   5555  1.1  christos       SET_DREG (dst0, REG_H_L (DREG (dst0), CCREG));
   5556  1.1  christos       SET_AREG (0, acc0);
   5557  1.1  christos     }
   5558  1.1  christos   else if (sop == 1 && sopcde == 11)
   5559  1.1  christos     {
   5560  1.1  christos       bu64 acc0 = get_unextended_acc (cpu, 0);
   5561  1.1  christos 
   5562  1.1  christos       TRACE_INSN (cpu, "R%i.L = CC = BXOR (A0, R%i);", dst0, src0);
   5563  1.1  christos 
   5564  1.1  christos       SET_CCREG (xor_reduce (acc0, DREG (src0)));
   5565  1.1  christos       SET_DREG (dst0, REG_H_L (DREG (dst0), CCREG));
   5566  1.1  christos     }
   5567  1.1  christos   else if (sop == 0 && sopcde == 12)
   5568  1.1  christos     {
   5569  1.1  christos       bu64 acc0 = get_unextended_acc (cpu, 0);
   5570  1.1  christos       bu64 acc1 = get_unextended_acc (cpu, 1);
   5571  1.1  christos 
   5572  1.1  christos       TRACE_INSN (cpu, "A0 = BXORSHIFT (A0, A1, CC);");
   5573  1.1  christos 
   5574  1.1  christos       acc0 = (acc0 << 1) | (CCREG ^ xor_reduce (acc0, acc1));
   5575  1.1  christos       SET_AREG (0, acc0);
   5576  1.1  christos     }
   5577  1.1  christos   else if (sop == 1 && sopcde == 12)
   5578  1.1  christos     {
   5579  1.1  christos       bu64 acc0 = get_unextended_acc (cpu, 0);
   5580  1.1  christos       bu64 acc1 = get_unextended_acc (cpu, 1);
   5581  1.1  christos 
   5582  1.1  christos       TRACE_INSN (cpu, "R%i.L = CC = BXOR (A0, A1, CC);", dst0);
   5583  1.1  christos 
   5584  1.1  christos       SET_CCREG (CCREG ^ xor_reduce (acc0, acc1));
   5585  1.1  christos       acc0 = (acc0 << 1) | CCREG;
   5586  1.1  christos       SET_DREG (dst0, REG_H_L (DREG (dst0), CCREG));
   5587  1.1  christos     }
   5588  1.1  christos   else if ((sop == 0 || sop == 1 || sop == 2) && sopcde == 13)
   5589  1.1  christos     {
   5590  1.1  christos       int shift = (sop + 1) * 8;
   5591  1.1  christos       TRACE_INSN (cpu, "R%i = ALIGN%i (R%i, R%i);", dst0, shift, src1, src0);
   5592  1.1  christos       SET_DREG (dst0, (DREG (src1) << (32 - shift)) | (DREG (src0) >> shift));
   5593  1.1  christos     }
   5594  1.1  christos   else
   5595  1.1  christos     illegal_instruction (cpu);
   5596  1.1  christos }
   5597  1.1  christos 
   5598  1.1  christos static void
   5599  1.1  christos decode_dsp32shiftimm_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
   5600  1.1  christos {
   5601  1.1  christos   /* dsp32shiftimm
   5602  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
   5603  1.1  christos      | 1 | 1 | 0 | 0 |.M.| 1 | 1 | 0 | 1 | - | - |.sopcde............|
   5604  1.1  christos      |.sop...|.HLs...|.dst0......|.immag.................|.src1......|
   5605  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
   5606  1.1  christos   int src1     = ((iw1 >> DSP32ShiftImm_src1_bits) & DSP32ShiftImm_src1_mask);
   5607  1.1  christos   int sop      = ((iw1 >> DSP32ShiftImm_sop_bits) & DSP32ShiftImm_sop_mask);
   5608  1.1  christos   int bit8     = ((iw1 >> 8) & 0x1);
   5609  1.1  christos   int immag    = ((iw1 >> DSP32ShiftImm_immag_bits) & DSP32ShiftImm_immag_mask);
   5610  1.1  christos   int newimmag = (-(iw1 >> DSP32ShiftImm_immag_bits) & DSP32ShiftImm_immag_mask);
   5611  1.1  christos   int dst0     = ((iw1 >> DSP32ShiftImm_dst0_bits) & DSP32ShiftImm_dst0_mask);
   5612  1.1  christos   int M        = ((iw0 >> (DSP32ShiftImm_M_bits - 16)) & DSP32ShiftImm_M_mask);
   5613  1.1  christos   int sopcde   = ((iw0 >> (DSP32ShiftImm_sopcde_bits - 16)) & DSP32ShiftImm_sopcde_mask);
   5614  1.1  christos   int HLs      = ((iw1 >> DSP32ShiftImm_HLs_bits) & DSP32ShiftImm_HLs_mask);
   5615  1.1  christos 
   5616  1.1  christos   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dsp32shiftimm);
   5617  1.1  christos   TRACE_EXTRACT (cpu, "%s: M:%i sopcde:%i sop:%i HLs:%i dst0:%i immag:%#x src1:%i",
   5618  1.1  christos 		 __func__, M, sopcde, sop, HLs, dst0, immag, src1);
   5619  1.1  christos 
   5620  1.1  christos   if (sopcde == 0)
   5621  1.1  christos     {
   5622  1.1  christos       bu16 in = DREG (src1) >> ((HLs & 1) ? 16 : 0);
   5623  1.1  christos       bu16 result;
   5624  1.1  christos       bu32 v;
   5625  1.1  christos 
   5626  1.1  christos       if (sop == 0)
   5627  1.1  christos 	{
   5628  1.1  christos 	  TRACE_INSN (cpu, "R%i.%c = R%i.%c >>> %i;",
   5629  1.1  christos 		      dst0, (HLs & 2) ? 'H' : 'L',
   5630  1.1  christos 		      src1, (HLs & 1) ? 'H' : 'L', newimmag);
   5631  1.1  christos 	  result = ashiftrt (cpu, in, newimmag, 16);
   5632  1.1  christos 	}
   5633  1.1  christos       else if (sop == 1 && bit8 == 0)
   5634  1.1  christos 	{
   5635  1.1  christos 	  TRACE_INSN (cpu, "R%i.%c = R%i.%c << %i (S);",
   5636  1.1  christos 		      dst0, (HLs & 2) ? 'H' : 'L',
   5637  1.1  christos 		      src1, (HLs & 1) ? 'H' : 'L', immag);
   5638  1.1  christos 	  result = lshift (cpu, in, immag, 16, 1);
   5639  1.1  christos 	}
   5640  1.1  christos       else if (sop == 1 && bit8)
   5641  1.1  christos 	{
   5642  1.1  christos 	  TRACE_INSN (cpu, "R%i.%c = R%i.%c >>> %i (S);",
   5643  1.1  christos 		      dst0, (HLs & 2) ? 'H' : 'L',
   5644  1.1  christos 		      src1, (HLs & 1) ? 'H' : 'L', immag);
   5645  1.1  christos 	  result = lshift (cpu, in, immag, 16, 1);
   5646  1.1  christos 	}
   5647  1.1  christos       else if (sop == 2 && bit8)
   5648  1.1  christos 	{
   5649  1.1  christos 	  TRACE_INSN (cpu, "R%i.%c = R%i.%c >> %i;",
   5650  1.1  christos 		      dst0, (HLs & 2) ? 'H' : 'L',
   5651  1.1  christos 		      src1, (HLs & 1) ? 'H' : 'L', newimmag);
   5652  1.1  christos 	  result = lshiftrt (cpu, in, newimmag, 16);
   5653  1.1  christos 	}
   5654  1.1  christos       else if (sop == 2 && bit8 == 0)
   5655  1.1  christos 	{
   5656  1.1  christos 	  TRACE_INSN (cpu, "R%i.%c = R%i.%c << %i;",
   5657  1.1  christos 		      dst0, (HLs & 2) ? 'H' : 'L',
   5658  1.1  christos 		      src1, (HLs & 1) ? 'H' : 'L', immag);
   5659  1.1  christos 	  result = lshift (cpu, in, immag, 16, 0);
   5660  1.1  christos 	}
   5661  1.1  christos       else
   5662  1.1  christos 	illegal_instruction (cpu);
   5663  1.1  christos 
   5664  1.1  christos       v = DREG (dst0);
   5665  1.1  christos       if (HLs & 2)
   5666  1.1  christos 	STORE (DREG (dst0), (v & 0xFFFF) | (result << 16));
   5667  1.1  christos       else
   5668  1.1  christos 	STORE (DREG (dst0), (v & 0xFFFF0000) | result);
   5669  1.1  christos     }
   5670  1.1  christos   else if (sop == 2 && sopcde == 3 && (HLs == 1 || HLs == 0))
   5671  1.1  christos     {
   5672  1.1  christos       int shift = imm6 (immag);
   5673  1.1  christos       bu32 cc = CCREG;
   5674  1.1  christos       bu40 acc = get_unextended_acc (cpu, HLs);
   5675  1.1  christos 
   5676  1.1  christos       TRACE_INSN (cpu, "A%i = ROT A%i BY %i;", HLs, HLs, shift);
   5677  1.1  christos       TRACE_DECODE (cpu, "A%i:%#"PRIx64" shift:%i CC:%i", HLs, acc, shift, cc);
   5678  1.1  christos 
   5679  1.1  christos       acc = rot40 (acc, shift, &cc);
   5680  1.1  christos       SET_AREG (HLs, acc);
   5681  1.1  christos       if (shift)
   5682  1.1  christos 	SET_CCREG (cc);
   5683  1.1  christos     }
   5684  1.1  christos   else if (sop == 0 && sopcde == 3 && bit8 == 1)
   5685  1.1  christos     {
   5686  1.1  christos       /* Arithmetic shift, so shift in sign bit copies.  */
   5687  1.1  christos       bu64 acc;
   5688  1.1  christos       int shift = uimm5 (newimmag);
   5689  1.1  christos       HLs = !!HLs;
   5690  1.1  christos 
   5691  1.1  christos       TRACE_INSN (cpu, "A%i = A%i >>> %i;", HLs, HLs, shift);
   5692  1.1  christos 
   5693  1.1  christos       acc = get_extended_acc (cpu, HLs);
   5694  1.1  christos       acc >>= shift;
   5695  1.1  christos       /* Sign extend again.  */
   5696  1.1  christos       if (acc & (1ULL << 39))
   5697  1.1  christos 	acc |= -(1ULL << 39);
   5698  1.1  christos       else
   5699  1.1  christos 	acc &= ~(-(1ULL << 39));
   5700  1.1  christos 
   5701  1.1  christos       STORE (AXREG (HLs), (acc >> 32) & 0xFF);
   5702  1.1  christos       STORE (AWREG (HLs), acc & 0xFFFFFFFF);
   5703  1.1  christos     }
   5704  1.1  christos   else if ((sop == 0 && sopcde == 3 && bit8 == 0)
   5705  1.1  christos 	   || (sop == 1 && sopcde == 3))
   5706  1.1  christos     {
   5707  1.1  christos       bu64 acc;
   5708  1.1  christos       int shiftup = uimm5 (immag);
   5709  1.1  christos       int shiftdn = uimm5 (newimmag);
   5710  1.1  christos       HLs = !!HLs;
   5711  1.1  christos 
   5712  1.1  christos       TRACE_INSN (cpu, "A%i = A%i %s %i;", HLs, HLs,
   5713  1.1  christos 		  sop == 0 ? "<<" : ">>",
   5714  1.1  christos 		  sop == 0 ? shiftup : shiftdn);
   5715  1.1  christos 
   5716  1.1  christos       acc = AXREG (HLs);
   5717  1.1  christos       /* Logical shift, so shift in zeroes.  */
   5718  1.1  christos       acc &= 0xFF;
   5719  1.1  christos       acc <<= 32;
   5720  1.1  christos       acc |= AWREG (HLs);
   5721  1.1  christos 
   5722  1.1  christos       if (sop == 0)
   5723  1.1  christos 	acc <<= shiftup;
   5724  1.1  christos       else
   5725  1.1  christos 	acc >>= shiftdn;
   5726  1.1  christos 
   5727  1.1  christos       SET_AREG (HLs, acc);
   5728  1.1  christos       SET_ASTATREG (an, !!(acc & 0x8000000000ull));
   5729  1.1  christos       SET_ASTATREG (az, acc == 0);
   5730  1.1  christos     }
   5731  1.1  christos   else if (sop == 1 && sopcde == 1 && bit8 == 0)
   5732  1.1  christos     {
   5733  1.1  christos       int count = imm5 (immag);
   5734  1.1  christos       bu16 val0 = DREG (src1) >> 16;
   5735  1.1  christos       bu16 val1 = DREG (src1) & 0xFFFF;
   5736  1.1  christos       bu32 astat;
   5737  1.1  christos 
   5738  1.1  christos       TRACE_INSN (cpu, "R%i = R%i << %i (V,S);", dst0, src1, count);
   5739  1.1  christos       val0 = lshift (cpu, val0, count, 16, 1);
   5740  1.1  christos       astat = ASTAT;
   5741  1.1  christos       val1 = lshift (cpu, val1, count, 16, 1);
   5742  1.1  christos       SET_ASTAT (ASTAT | astat);
   5743  1.1  christos 
   5744  1.1  christos       STORE (DREG (dst0), (val0 << 16) | val1);
   5745  1.1  christos     }
   5746  1.1  christos   else if (sop == 2 && sopcde == 1 && bit8 == 1)
   5747  1.1  christos     {
   5748  1.1  christos       int count = imm5 (newimmag);
   5749  1.1  christos       bu16 val0 = DREG (src1) & 0xFFFF;
   5750  1.1  christos       bu16 val1 = DREG (src1) >> 16;
   5751  1.1  christos       bu32 astat;
   5752  1.1  christos 
   5753  1.1  christos       TRACE_INSN (cpu, "R%i = R%i >> %i (V);", dst0, src1, count);
   5754  1.1  christos       val0 = lshiftrt (cpu, val0, count, 16);
   5755  1.1  christos       astat = ASTAT;
   5756  1.1  christos       val1 = lshiftrt (cpu, val1, count, 16);
   5757  1.1  christos       SET_ASTAT (ASTAT | astat);
   5758  1.1  christos 
   5759  1.1  christos       STORE (DREG (dst0), val0 | (val1 << 16));
   5760  1.1  christos     }
   5761  1.1  christos   else if (sop == 2 && sopcde == 1 && bit8 == 0)
   5762  1.1  christos     {
   5763  1.1  christos       int count = imm5 (immag);
   5764  1.1  christos       bu16 val0 = DREG (src1) & 0xFFFF;
   5765  1.1  christos       bu16 val1 = DREG (src1) >> 16;
   5766  1.1  christos       bu32 astat;
   5767  1.1  christos 
   5768  1.1  christos       TRACE_INSN (cpu, "R%i = R%i << %i (V);", dst0, src1, count);
   5769  1.1  christos       val0 = lshift (cpu, val0, count, 16, 0);
   5770  1.1  christos       astat = ASTAT;
   5771  1.1  christos       val1 = lshift (cpu, val1, count, 16, 0);
   5772  1.1  christos       SET_ASTAT (ASTAT | astat);
   5773  1.1  christos 
   5774  1.1  christos       STORE (DREG (dst0), val0 | (val1 << 16));
   5775  1.1  christos     }
   5776  1.1  christos   else if (sopcde == 1 && (sop == 0 || (sop == 1 && bit8 == 1)))
   5777  1.1  christos     {
   5778  1.1  christos       int count = uimm5 (newimmag);
   5779  1.1  christos       bu16 val0 = DREG (src1) & 0xFFFF;
   5780  1.1  christos       bu16 val1 = DREG (src1) >> 16;
   5781  1.1  christos       bu32 astat;
   5782  1.1  christos 
   5783  1.1  christos       TRACE_INSN (cpu, "R%i = R%i >>> %i %s;", dst0, src1, count,
   5784  1.1  christos 		  sop == 0 ? "(V)" : "(V,S)");
   5785  1.1  christos 
   5786  1.1  christos       val0 = ashiftrt (cpu, val0, count, 16);
   5787  1.1  christos       astat = ASTAT;
   5788  1.1  christos       val1 = ashiftrt (cpu, val1, count, 16);
   5789  1.1  christos       SET_ASTAT (ASTAT | astat);
   5790  1.1  christos 
   5791  1.1  christos       STORE (DREG (dst0), REG_H_L (val1 << 16, val0));
   5792  1.1  christos     }
   5793  1.1  christos   else if (sop == 1 && sopcde == 2)
   5794  1.1  christos     {
   5795  1.1  christos       int count = imm6 (immag);
   5796  1.1  christos 
   5797  1.1  christos       TRACE_INSN (cpu, "R%i = R%i << %i (S);", dst0, src1, count);
   5798  1.1  christos       STORE (DREG (dst0), lshift (cpu, DREG (src1), count, 32, 1));
   5799  1.1  christos     }
   5800  1.1  christos   else if (sop == 2 && sopcde == 2)
   5801  1.1  christos     {
   5802  1.1  christos       int count = imm6 (newimmag);
   5803  1.1  christos 
   5804  1.1  christos       TRACE_INSN (cpu, "R%i = R%i >> %i;", dst0, src1, count);
   5805  1.1  christos 
   5806  1.1  christos       if (count < 0)
   5807  1.1  christos 	STORE (DREG (dst0), lshift (cpu, DREG (src1), -count, 32, 0));
   5808  1.1  christos       else
   5809  1.1  christos 	STORE (DREG (dst0), lshiftrt (cpu, DREG (src1), count, 32));
   5810  1.1  christos     }
   5811  1.1  christos   else if (sop == 3 && sopcde == 2)
   5812  1.1  christos     {
   5813  1.1  christos       int shift = imm6 (immag);
   5814  1.1  christos       bu32 src = DREG (src1);
   5815  1.1  christos       bu32 ret, cc = CCREG;
   5816  1.1  christos 
   5817  1.1  christos       TRACE_INSN (cpu, "R%i = ROT R%i BY %i;", dst0, src1, shift);
   5818  1.1  christos       TRACE_DECODE (cpu, "R%i:%#x R%i:%#x shift:%i CC:%i",
   5819  1.1  christos 		    dst0, DREG (dst0), src1, src, shift, cc);
   5820  1.1  christos 
   5821  1.1  christos       ret = rot32 (src, shift, &cc);
   5822  1.1  christos       STORE (DREG (dst0), ret);
   5823  1.1  christos       if (shift)
   5824  1.1  christos 	SET_CCREG (cc);
   5825  1.1  christos     }
   5826  1.1  christos   else if (sop == 0 && sopcde == 2)
   5827  1.1  christos     {
   5828  1.1  christos       int count = imm6 (newimmag);
   5829  1.1  christos 
   5830  1.1  christos       TRACE_INSN (cpu, "R%i = R%i >>> %i;", dst0, src1, count);
   5831  1.1  christos 
   5832  1.1  christos       if (count < 0)
   5833  1.1  christos 	STORE (DREG (dst0), lshift (cpu, DREG (src1), -count, 32, 0));
   5834  1.1  christos       else
   5835  1.1  christos 	STORE (DREG (dst0), ashiftrt (cpu, DREG (src1), count, 32));
   5836  1.1  christos     }
   5837  1.1  christos   else
   5838  1.1  christos     illegal_instruction (cpu);
   5839  1.1  christos }
   5840  1.1  christos 
   5841  1.1  christos static void
   5842  1.1  christos outc (SIM_CPU *cpu, char ch)
   5843  1.1  christos {
   5844  1.1  christos   SIM_DESC sd = CPU_STATE (cpu);
   5845  1.1  christos   sim_io_printf (sd, "%c", ch);
   5846  1.1  christos   if (ch == '\n')
   5847  1.1  christos     sim_io_flush_stdout (sd);
   5848  1.1  christos }
   5849  1.1  christos 
   5850  1.1  christos static void
   5851  1.1  christos decode_psedoDEBUG_0 (SIM_CPU *cpu, bu16 iw0)
   5852  1.1  christos {
   5853  1.1  christos   /* psedoDEBUG
   5854  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
   5855  1.1  christos      | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 |.fn....|.grp.......|.reg.......|
   5856  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
   5857  1.1  christos   SIM_DESC sd = CPU_STATE (cpu);
   5858  1.1  christos   int fn  = ((iw0 >> PseudoDbg_fn_bits) & PseudoDbg_fn_mask);
   5859  1.1  christos   int grp = ((iw0 >> PseudoDbg_grp_bits) & PseudoDbg_grp_mask);
   5860  1.1  christos   int reg = ((iw0 >> PseudoDbg_reg_bits) & PseudoDbg_reg_mask);
   5861  1.1  christos 
   5862  1.1  christos   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_psedoDEBUG);
   5863  1.1  christos   TRACE_EXTRACT (cpu, "%s: fn:%i grp:%i reg:%i", __func__, fn, grp, reg);
   5864  1.1  christos 
   5865  1.1  christos   if ((reg == 0 || reg == 1) && fn == 3)
   5866  1.1  christos     {
   5867  1.1  christos       TRACE_INSN (cpu, "DBG A%i;", reg);
   5868  1.1  christos       sim_io_printf (sd, "DBG : A%i = %#"PRIx64"\n", reg,
   5869  1.1  christos 		     get_unextended_acc (cpu, reg));
   5870  1.1  christos     }
   5871  1.1  christos   else if (reg == 3 && fn == 3)
   5872  1.1  christos     {
   5873  1.1  christos       TRACE_INSN (cpu, "ABORT;");
   5874  1.1  christos       cec_exception (cpu, VEC_SIM_ABORT);
   5875  1.1  christos       SET_DREG (0, 1);
   5876  1.1  christos     }
   5877  1.1  christos   else if (reg == 4 && fn == 3)
   5878  1.1  christos     {
   5879  1.1  christos       TRACE_INSN (cpu, "HLT;");
   5880  1.1  christos       cec_exception (cpu, VEC_SIM_HLT);
   5881  1.1  christos       SET_DREG (0, 0);
   5882  1.1  christos     }
   5883  1.1  christos   else if (reg == 5 && fn == 3)
   5884  1.1  christos     unhandled_instruction (cpu, "DBGHALT");
   5885  1.1  christos   else if (reg == 6 && fn == 3)
   5886  1.1  christos     unhandled_instruction (cpu, "DBGCMPLX (dregs)");
   5887  1.1  christos   else if (reg == 7 && fn == 3)
   5888  1.1  christos     unhandled_instruction (cpu, "DBG");
   5889  1.1  christos   else if (grp == 0 && fn == 2)
   5890  1.1  christos     {
   5891  1.1  christos       TRACE_INSN (cpu, "OUTC R%i;", reg);
   5892  1.1  christos       outc (cpu, DREG (reg));
   5893  1.1  christos     }
   5894  1.1  christos   else if (fn == 0)
   5895  1.1  christos     {
   5896  1.1  christos       const char *reg_name = get_allreg_name (grp, reg);
   5897  1.1  christos       TRACE_INSN (cpu, "DBG %s;", reg_name);
   5898  1.1  christos       sim_io_printf (sd, "DBG : %s = 0x%08x\n", reg_name,
   5899  1.1  christos 		     reg_read (cpu, grp, reg));
   5900  1.1  christos     }
   5901  1.1  christos   else if (fn == 1)
   5902  1.1  christos     unhandled_instruction (cpu, "PRNT allregs");
   5903  1.1  christos   else
   5904  1.1  christos     illegal_instruction (cpu);
   5905  1.1  christos }
   5906  1.1  christos 
   5907  1.1  christos static void
   5908  1.1  christos decode_psedoOChar_0 (SIM_CPU *cpu, bu16 iw0)
   5909  1.1  christos {
   5910  1.1  christos   /* psedoOChar
   5911  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
   5912  1.1  christos      | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |.ch............................|
   5913  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
   5914  1.1  christos   int ch = ((iw0 >> PseudoChr_ch_bits) & PseudoChr_ch_mask);
   5915  1.1  christos 
   5916  1.1  christos   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_psedoOChar);
   5917  1.1  christos   TRACE_EXTRACT (cpu, "%s: ch:%#x", __func__, ch);
   5918  1.1  christos   TRACE_INSN (cpu, "OUTC %#x;", ch);
   5919  1.1  christos 
   5920  1.1  christos   outc (cpu, ch);
   5921  1.1  christos }
   5922  1.1  christos 
   5923  1.1  christos static void
   5924  1.1  christos decode_psedodbg_assert_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1, bu32 pc)
   5925  1.1  christos {
   5926  1.1  christos   /* psedodbg_assert
   5927  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
   5928  1.1  christos      | 1 | 1 | 1 | 1 | 0 | - | - | - | dbgop |.grp.......|.regtest...|
   5929  1.1  christos      |.expected......................................................|
   5930  1.1  christos      +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+  */
   5931  1.1  christos   SIM_DESC sd = CPU_STATE (cpu);
   5932  1.1  christos   int expected = ((iw1 >> PseudoDbg_Assert_expected_bits) & PseudoDbg_Assert_expected_mask);
   5933  1.1  christos   int dbgop    = ((iw0 >> (PseudoDbg_Assert_dbgop_bits - 16)) & PseudoDbg_Assert_dbgop_mask);
   5934  1.1  christos   int grp      = ((iw0 >> (PseudoDbg_Assert_grp_bits - 16)) & PseudoDbg_Assert_grp_mask);
   5935  1.1  christos   int regtest  = ((iw0 >> (PseudoDbg_Assert_regtest_bits - 16)) & PseudoDbg_Assert_regtest_mask);
   5936  1.1  christos   int offset;
   5937  1.1  christos   bu16 actual;
   5938  1.1  christos   bu32 val = reg_read (cpu, grp, regtest);
   5939  1.1  christos   const char *reg_name = get_allreg_name (grp, regtest);
   5940  1.1  christos   const char *dbg_name, *dbg_appd;
   5941  1.1  christos 
   5942  1.1  christos   PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_psedodbg_assert);
   5943  1.1  christos   TRACE_EXTRACT (cpu, "%s: dbgop:%i grp:%i regtest:%i expected:%#x",
   5944  1.1  christos 		 __func__, dbgop, grp, regtest, expected);
   5945  1.1  christos 
   5946  1.1  christos   if (dbgop == 0 || dbgop == 2)
   5947  1.1  christos     {
   5948  1.1  christos       dbg_name = dbgop == 0 ? "DBGA" : "DBGAL";
   5949  1.1  christos       dbg_appd = dbgop == 0 ? ".L" : "";
   5950  1.1  christos       offset = 0;
   5951  1.1  christos     }
   5952  1.1  christos   else if (dbgop == 1 || dbgop == 3)
   5953  1.1  christos     {
   5954  1.1  christos       dbg_name = dbgop == 1 ? "DBGA" : "DBGAH";
   5955  1.1  christos       dbg_appd = dbgop == 1 ? ".H" : "";
   5956  1.1  christos       offset = 16;
   5957  1.1  christos     }
   5958  1.1  christos   else
   5959  1.1  christos     illegal_instruction (cpu);
   5960  1.1  christos 
   5961  1.1  christos   actual = val >> offset;
   5962  1.1  christos 
   5963  1.1  christos   TRACE_INSN (cpu, "%s (%s%s, 0x%x);", dbg_name, reg_name, dbg_appd, expected);
   5964  1.1  christos   if (actual != expected)
   5965  1.1  christos     {
   5966  1.1  christos       sim_io_printf (sd, "FAIL at %#x: %s (%s%s, 0x%04x); actual value %#x\n",
   5967  1.1  christos 		     pc, dbg_name, reg_name, dbg_appd, expected, actual);
   5968  1.1  christos 
   5969  1.1  christos       /* Decode the actual ASTAT bits that are different.  */
   5970  1.1  christos       if (grp == 4 && regtest == 6)
   5971  1.1  christos 	{
   5972  1.1  christos 	  int i;
   5973  1.1  christos 
   5974  1.1  christos 	  sim_io_printf (sd, "Expected ASTAT:\n");
   5975  1.1  christos 	  for (i = 0; i < 16; ++i)
   5976  1.1  christos 	    sim_io_printf (sd, " %8s%c%i%s",
   5977  1.1  christos 			   astat_names[i + offset],
   5978  1.1  christos 			   (((expected >> i) & 1) != ((actual >> i) & 1))
   5979  1.1  christos 				? '!' : ' ',
   5980  1.1  christos 			   (expected >> i) & 1,
   5981  1.1  christos 			   i == 7 ? "\n" : "");
   5982  1.1  christos 	  sim_io_printf (sd, "\n");
   5983  1.1  christos 
   5984  1.1  christos 	  sim_io_printf (sd, "Actual ASTAT:\n");
   5985  1.1  christos 	  for (i = 0; i < 16; ++i)
   5986  1.1  christos 	    sim_io_printf (sd, " %8s%c%i%s",
   5987  1.1  christos 			   astat_names[i + offset],
   5988  1.1  christos 			   (((expected >> i) & 1) != ((actual >> i) & 1))
   5989  1.1  christos 				? '!' : ' ',
   5990  1.1  christos 			   (actual >> i) & 1,
   5991  1.1  christos 			   i == 7 ? "\n" : "");
   5992  1.1  christos 	  sim_io_printf (sd, "\n");
   5993  1.1  christos 	}
   5994  1.1  christos 
   5995  1.1  christos       cec_exception (cpu, VEC_SIM_DBGA);
   5996  1.1  christos       SET_DREG (0, 1);
   5997  1.1  christos     }
   5998  1.1  christos }
   5999  1.1  christos 
   6000  1.1  christos static bu32
   6001  1.1  christos _interp_insn_bfin (SIM_CPU *cpu, bu32 pc)
   6002  1.1  christos {
   6003  1.1  christos   bu32 insn_len;
   6004  1.1  christos   bu16 iw0, iw1;
   6005  1.1  christos 
   6006  1.1  christos   BFIN_CPU_STATE.multi_pc = pc;
   6007  1.1  christos   iw0 = IFETCH (pc);
   6008  1.1  christos   if ((iw0 & 0xc000) != 0xc000)
   6009  1.1  christos     {
   6010  1.1  christos       /* 16-bit opcode.  */
   6011  1.1  christos       insn_len = 2;
   6012  1.1  christos       if (INSN_LEN == 0)
   6013  1.1  christos 	INSN_LEN = insn_len;
   6014  1.1  christos 
   6015  1.1  christos       TRACE_EXTRACT (cpu, "%s: iw0:%#x", __func__, iw0);
   6016  1.1  christos       if ((iw0 & 0xFF00) == 0x0000)
   6017  1.1  christos 	decode_ProgCtrl_0 (cpu, iw0, pc);
   6018  1.1  christos       else if ((iw0 & 0xFFC0) == 0x0240)
   6019  1.1  christos 	decode_CaCTRL_0 (cpu, iw0);
   6020  1.1  christos       else if ((iw0 & 0xFF80) == 0x0100)
   6021  1.1  christos 	decode_PushPopReg_0 (cpu, iw0);
   6022  1.1  christos       else if ((iw0 & 0xFE00) == 0x0400)
   6023  1.1  christos 	decode_PushPopMultiple_0 (cpu, iw0);
   6024  1.1  christos       else if ((iw0 & 0xFE00) == 0x0600)
   6025  1.1  christos 	decode_ccMV_0 (cpu, iw0);
   6026  1.1  christos       else if ((iw0 & 0xF800) == 0x0800)
   6027  1.1  christos 	decode_CCflag_0 (cpu, iw0);
   6028  1.1  christos       else if ((iw0 & 0xFFE0) == 0x0200)
   6029  1.1  christos 	decode_CC2dreg_0 (cpu, iw0);
   6030  1.1  christos       else if ((iw0 & 0xFF00) == 0x0300)
   6031  1.1  christos 	decode_CC2stat_0 (cpu, iw0);
   6032  1.1  christos       else if ((iw0 & 0xF000) == 0x1000)
   6033  1.1  christos 	decode_BRCC_0 (cpu, iw0, pc);
   6034  1.1  christos       else if ((iw0 & 0xF000) == 0x2000)
   6035  1.1  christos 	decode_UJUMP_0 (cpu, iw0, pc);
   6036  1.1  christos       else if ((iw0 & 0xF000) == 0x3000)
   6037  1.1  christos 	decode_REGMV_0 (cpu, iw0);
   6038  1.1  christos       else if ((iw0 & 0xFC00) == 0x4000)
   6039  1.1  christos 	decode_ALU2op_0 (cpu, iw0);
   6040  1.1  christos       else if ((iw0 & 0xFE00) == 0x4400)
   6041  1.1  christos 	decode_PTR2op_0 (cpu, iw0);
   6042  1.1  christos       else if ((iw0 & 0xF800) == 0x4800)
   6043  1.1  christos 	decode_LOGI2op_0 (cpu, iw0);
   6044  1.1  christos       else if ((iw0 & 0xF000) == 0x5000)
   6045  1.1  christos 	decode_COMP3op_0 (cpu, iw0);
   6046  1.1  christos       else if ((iw0 & 0xF800) == 0x6000)
   6047  1.1  christos 	decode_COMPI2opD_0 (cpu, iw0);
   6048  1.1  christos       else if ((iw0 & 0xF800) == 0x6800)
   6049  1.1  christos 	decode_COMPI2opP_0 (cpu, iw0);
   6050  1.1  christos       else if ((iw0 & 0xF000) == 0x8000)
   6051  1.1  christos 	decode_LDSTpmod_0 (cpu, iw0);
   6052  1.1  christos       else if ((iw0 & 0xFF60) == 0x9E60)
   6053  1.1  christos 	decode_dagMODim_0 (cpu, iw0);
   6054  1.1  christos       else if ((iw0 & 0xFFF0) == 0x9F60)
   6055  1.1  christos 	decode_dagMODik_0 (cpu, iw0);
   6056  1.1  christos       else if ((iw0 & 0xFC00) == 0x9C00)
   6057  1.1  christos 	decode_dspLDST_0 (cpu, iw0);
   6058  1.1  christos       else if ((iw0 & 0xF000) == 0x9000)
   6059  1.1  christos 	decode_LDST_0 (cpu, iw0);
   6060  1.1  christos       else if ((iw0 & 0xFC00) == 0xB800)
   6061  1.1  christos 	decode_LDSTiiFP_0 (cpu, iw0);
   6062  1.1  christos       else if ((iw0 & 0xE000) == 0xA000)
   6063  1.1  christos 	decode_LDSTii_0 (cpu, iw0);
   6064  1.1  christos       else
   6065  1.1  christos 	{
   6066  1.1  christos 	  TRACE_EXTRACT (cpu, "%s: no matching 16-bit pattern", __func__);
   6067  1.1  christos 	  illegal_instruction (cpu);
   6068  1.1  christos 	}
   6069  1.1  christos       return insn_len;
   6070  1.1  christos     }
   6071  1.1  christos 
   6072  1.1  christos   /* Grab the next 16 bits to determine if it's a 32-bit or 64-bit opcode.  */
   6073  1.1  christos   iw1 = IFETCH (pc + 2);
   6074  1.1  christos   if ((iw0 & BIT_MULTI_INS) && (iw0 & 0xe800) != 0xe800 /* not linkage  */)
   6075  1.1  christos     {
   6076  1.1  christos       SIM_DESC sd = CPU_STATE (cpu);
   6077  1.1  christos       trace_prefix (sd, cpu, NULL_CIA, pc, TRACE_LINENUM_P (cpu),
   6078  1.1  christos 			NULL, 0, "|| %#"PRIx64, sim_events_time (sd));
   6079  1.1  christos       insn_len = 8;
   6080  1.1  christos     }
   6081  1.1  christos   else
   6082  1.1  christos     insn_len = 4;
   6083  1.1  christos 
   6084  1.1  christos   TRACE_EXTRACT (cpu, "%s: iw0:%#x iw1:%#x insn_len:%i", __func__,
   6085  1.1  christos 		     iw0, iw1, insn_len);
   6086  1.1  christos 
   6087  1.1  christos   /* Only cache on first run through (in case of parallel insns).  */
   6088  1.1  christos   if (INSN_LEN == 0)
   6089  1.1  christos     INSN_LEN = insn_len;
   6090  1.1  christos 
   6091  1.1  christos   if ((iw0 & 0xf7ff) == 0xc003 && (iw1 & 0xfe00) == 0x1800)
   6092  1.1  christos     {
   6093  1.1  christos       PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dsp32mac);
   6094  1.1  christos       TRACE_INSN (cpu, "MNOP;");
   6095  1.1  christos     }
   6096  1.1  christos   else if (((iw0 & 0xFF80) == 0xE080) && ((iw1 & 0x0C00) == 0x0000))
   6097  1.1  christos     decode_LoopSetup_0 (cpu, iw0, iw1, pc);
   6098  1.1  christos   else if (((iw0 & 0xFF00) == 0xE100) && ((iw1 & 0x0000) == 0x0000))
   6099  1.1  christos     decode_LDIMMhalf_0 (cpu, iw0, iw1);
   6100  1.1  christos   else if (((iw0 & 0xFE00) == 0xE200) && ((iw1 & 0x0000) == 0x0000))
   6101  1.1  christos     decode_CALLa_0 (cpu, iw0, iw1, pc);
   6102  1.1  christos   else if (((iw0 & 0xFC00) == 0xE400) && ((iw1 & 0x0000) == 0x0000))
   6103  1.1  christos     decode_LDSTidxI_0 (cpu, iw0, iw1);
   6104  1.1  christos   else if (((iw0 & 0xFFFE) == 0xE800) && ((iw1 & 0x0000) == 0x0000))
   6105  1.1  christos     decode_linkage_0 (cpu, iw0, iw1);
   6106  1.1  christos   else if (((iw0 & 0xF600) == 0xC000) && ((iw1 & 0x0000) == 0x0000))
   6107  1.1  christos     decode_dsp32mac_0 (cpu, iw0, iw1);
   6108  1.1  christos   else if (((iw0 & 0xF600) == 0xC200) && ((iw1 & 0x0000) == 0x0000))
   6109  1.1  christos     decode_dsp32mult_0 (cpu, iw0, iw1);
   6110  1.1  christos   else if (((iw0 & 0xF7C0) == 0xC400) && ((iw1 & 0x0000) == 0x0000))
   6111  1.1  christos     decode_dsp32alu_0 (cpu, iw0, iw1);
   6112  1.1  christos   else if (((iw0 & 0xF7E0) == 0xC600) && ((iw1 & 0x01C0) == 0x0000))
   6113  1.1  christos     decode_dsp32shift_0 (cpu, iw0, iw1);
   6114  1.1  christos   else if (((iw0 & 0xF7E0) == 0xC680) && ((iw1 & 0x0000) == 0x0000))
   6115  1.1  christos     decode_dsp32shiftimm_0 (cpu, iw0, iw1);
   6116  1.1  christos   else if ((iw0 & 0xFF00) == 0xF800)
   6117  1.1  christos     decode_psedoDEBUG_0 (cpu, iw0), insn_len = 2;
   6118  1.1  christos   else if ((iw0 & 0xFF00) == 0xF900)
   6119  1.1  christos     decode_psedoOChar_0 (cpu, iw0), insn_len = 2;
   6120  1.1  christos   else if (((iw0 & 0xFF00) == 0xF000) && ((iw1 & 0x0000) == 0x0000))
   6121  1.1  christos     decode_psedodbg_assert_0 (cpu, iw0, iw1, pc);
   6122  1.1  christos   else
   6123  1.1  christos     {
   6124  1.1  christos       TRACE_EXTRACT (cpu, "%s: no matching 32-bit pattern", __func__);
   6125  1.1  christos       illegal_instruction (cpu);
   6126  1.1  christos     }
   6127  1.1  christos 
   6128  1.1  christos   return insn_len;
   6129  1.1  christos }
   6130  1.1  christos 
   6131  1.1  christos bu32
   6132  1.1  christos interp_insn_bfin (SIM_CPU *cpu, bu32 pc)
   6133  1.1  christos {
   6134  1.1  christos   int i;
   6135  1.1  christos   bu32 insn_len;
   6136  1.1  christos 
   6137  1.1  christos   BFIN_CPU_STATE.n_stores = 0;
   6138  1.1  christos   DIS_ALGN_EXPT &= ~1;
   6139  1.1  christos   CYCLE_DELAY = 1;
   6140  1.1  christos   INSN_LEN = 0;
   6141  1.1  christos 
   6142  1.1  christos   insn_len = _interp_insn_bfin (cpu, pc);
   6143  1.1  christos 
   6144  1.1  christos   /* Proper display of multiple issue instructions.  */
   6145  1.1  christos   if (insn_len == 8)
   6146  1.1  christos     {
   6147  1.1  christos       _interp_insn_bfin (cpu, pc + 4);
   6148  1.1  christos       _interp_insn_bfin (cpu, pc + 6);
   6149  1.1  christos     }
   6150  1.1  christos   for (i = 0; i < BFIN_CPU_STATE.n_stores; i++)
   6151  1.1  christos     {
   6152  1.1  christos       bu32 *addr = BFIN_CPU_STATE.stores[i].addr;
   6153  1.1  christos       *addr = BFIN_CPU_STATE.stores[i].val;
   6154  1.1  christos       TRACE_REGISTER (cpu, "dequeuing write %s = %#x",
   6155  1.1  christos 		      get_store_name (cpu, addr), *addr);
   6156  1.1  christos     }
   6157  1.1  christos 
   6158  1.1  christos   cycles_inc (cpu, CYCLE_DELAY);
   6159  1.1  christos 
   6160  1.1  christos   /* Set back to zero in case a pending CEC event occurs
   6161  1.1  christos      after this this insn.  */
   6162  1.1  christos   INSN_LEN = 0;
   6163  1.1  christos 
   6164  1.1  christos   return insn_len;
   6165  1.1  christos }
   6166