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