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