Home | History | Annotate | Line # | Download | only in rx
rx.c revision 1.1.1.6
      1      1.1  christos /* rx.c --- opcode semantics for stand-alone RX simulator.
      2      1.1  christos 
      3  1.1.1.6  christos Copyright (C) 2008-2017 Free Software Foundation, Inc.
      4      1.1  christos Contributed by Red Hat, Inc.
      5      1.1  christos 
      6      1.1  christos This file is part of the GNU simulators.
      7      1.1  christos 
      8      1.1  christos This program is free software; you can redistribute it and/or modify
      9      1.1  christos it under the terms of the GNU General Public License as published by
     10      1.1  christos the Free Software Foundation; either version 3 of the License, or
     11      1.1  christos (at your option) any later version.
     12      1.1  christos 
     13      1.1  christos This program is distributed in the hope that it will be useful,
     14      1.1  christos but WITHOUT ANY WARRANTY; without even the implied warranty of
     15      1.1  christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16      1.1  christos GNU General Public License for more details.
     17      1.1  christos 
     18      1.1  christos You should have received a copy of the GNU General Public License
     19      1.1  christos along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     20      1.1  christos 
     21      1.1  christos #include "config.h"
     22      1.1  christos #include <stdio.h>
     23      1.1  christos #include <stdlib.h>
     24      1.1  christos #include <string.h>
     25      1.1  christos #include <signal.h>
     26  1.1.1.6  christos #include "libiberty.h"
     27      1.1  christos 
     28      1.1  christos #include "opcode/rx.h"
     29      1.1  christos #include "cpu.h"
     30      1.1  christos #include "mem.h"
     31      1.1  christos #include "syscalls.h"
     32      1.1  christos #include "fpu.h"
     33      1.1  christos #include "err.h"
     34      1.1  christos #include "misc.h"
     35      1.1  christos 
     36      1.1  christos #ifdef CYCLE_STATS
     37      1.1  christos static const char * id_names[] = {
     38      1.1  christos   "RXO_unknown",
     39      1.1  christos   "RXO_mov",	/* d = s (signed) */
     40      1.1  christos   "RXO_movbi",	/* d = [s,s2] (signed) */
     41      1.1  christos   "RXO_movbir",	/* [s,s2] = d (signed) */
     42      1.1  christos   "RXO_pushm",	/* s..s2 */
     43      1.1  christos   "RXO_popm",	/* s..s2 */
     44      1.1  christos   "RXO_xchg",	/* s <-> d */
     45      1.1  christos   "RXO_stcc",	/* d = s if cond(s2) */
     46      1.1  christos   "RXO_rtsd",	/* rtsd, 1=imm, 2-0 = reg if reg type */
     47      1.1  christos 
     48      1.1  christos   /* These are all either d OP= s or, if s2 is set, d = s OP s2.  Note
     49      1.1  christos      that d may be "None".  */
     50      1.1  christos   "RXO_and",
     51      1.1  christos   "RXO_or",
     52      1.1  christos   "RXO_xor",
     53      1.1  christos   "RXO_add",
     54      1.1  christos   "RXO_sub",
     55      1.1  christos   "RXO_mul",
     56      1.1  christos   "RXO_div",
     57      1.1  christos   "RXO_divu",
     58      1.1  christos   "RXO_shll",
     59      1.1  christos   "RXO_shar",
     60      1.1  christos   "RXO_shlr",
     61      1.1  christos 
     62      1.1  christos   "RXO_adc",	/* d = d + s + carry */
     63      1.1  christos   "RXO_sbb",	/* d = d - s - ~carry */
     64      1.1  christos   "RXO_abs",	/* d = |s| */
     65      1.1  christos   "RXO_max",	/* d = max(d,s) */
     66      1.1  christos   "RXO_min",	/* d = min(d,s) */
     67      1.1  christos   "RXO_emul",	/* d:64 = d:32 * s */
     68      1.1  christos   "RXO_emulu",	/* d:64 = d:32 * s (unsigned) */
     69      1.1  christos 
     70      1.1  christos   "RXO_rolc",	/* d <<= 1 through carry */
     71      1.1  christos   "RXO_rorc",	/* d >>= 1 through carry*/
     72      1.1  christos   "RXO_rotl",	/* d <<= #s without carry */
     73      1.1  christos   "RXO_rotr",	/* d >>= #s without carry*/
     74      1.1  christos   "RXO_revw",	/* d = revw(s) */
     75      1.1  christos   "RXO_revl",	/* d = revl(s) */
     76      1.1  christos   "RXO_branch",	/* pc = d if cond(s) */
     77      1.1  christos   "RXO_branchrel",/* pc += d if cond(s) */
     78      1.1  christos   "RXO_jsr",	/* pc = d */
     79      1.1  christos   "RXO_jsrrel",	/* pc += d */
     80      1.1  christos   "RXO_rts",
     81      1.1  christos   "RXO_nop",
     82      1.1  christos   "RXO_nop2",
     83      1.1  christos   "RXO_nop3",
     84  1.1.1.5  christos   "RXO_nop4",
     85  1.1.1.5  christos   "RXO_nop5",
     86  1.1.1.5  christos   "RXO_nop6",
     87  1.1.1.5  christos   "RXO_nop7",
     88      1.1  christos 
     89      1.1  christos   "RXO_scmpu",
     90      1.1  christos   "RXO_smovu",
     91      1.1  christos   "RXO_smovb",
     92      1.1  christos   "RXO_suntil",
     93      1.1  christos   "RXO_swhile",
     94      1.1  christos   "RXO_smovf",
     95      1.1  christos   "RXO_sstr",
     96      1.1  christos 
     97      1.1  christos   "RXO_rmpa",
     98      1.1  christos   "RXO_mulhi",
     99      1.1  christos   "RXO_mullo",
    100      1.1  christos   "RXO_machi",
    101      1.1  christos   "RXO_maclo",
    102      1.1  christos   "RXO_mvtachi",
    103      1.1  christos   "RXO_mvtaclo",
    104      1.1  christos   "RXO_mvfachi",
    105      1.1  christos   "RXO_mvfacmi",
    106      1.1  christos   "RXO_mvfaclo",
    107      1.1  christos   "RXO_racw",
    108      1.1  christos 
    109      1.1  christos   "RXO_sat",	/* sat(d) */
    110      1.1  christos   "RXO_satr",
    111      1.1  christos 
    112      1.1  christos   "RXO_fadd",	/* d op= s */
    113      1.1  christos   "RXO_fcmp",
    114      1.1  christos   "RXO_fsub",
    115      1.1  christos   "RXO_ftoi",
    116      1.1  christos   "RXO_fmul",
    117      1.1  christos   "RXO_fdiv",
    118      1.1  christos   "RXO_round",
    119      1.1  christos   "RXO_itof",
    120      1.1  christos 
    121      1.1  christos   "RXO_bset",	/* d |= (1<<s) */
    122      1.1  christos   "RXO_bclr",	/* d &= ~(1<<s) */
    123      1.1  christos   "RXO_btst",	/* s & (1<<s2) */
    124      1.1  christos   "RXO_bnot",	/* d ^= (1<<s) */
    125      1.1  christos   "RXO_bmcc",	/* d<s> = cond(s2) */
    126      1.1  christos 
    127      1.1  christos   "RXO_clrpsw",	/* flag index in d */
    128      1.1  christos   "RXO_setpsw",	/* flag index in d */
    129      1.1  christos   "RXO_mvtipl",	/* new IPL in s */
    130      1.1  christos 
    131      1.1  christos   "RXO_rtfi",
    132      1.1  christos   "RXO_rte",
    133      1.1  christos   "RXO_rtd",	/* undocumented */
    134      1.1  christos   "RXO_brk",
    135      1.1  christos   "RXO_dbt",	/* undocumented */
    136      1.1  christos   "RXO_int",	/* vector id in s */
    137      1.1  christos   "RXO_stop",
    138      1.1  christos   "RXO_wait",
    139      1.1  christos 
    140      1.1  christos   "RXO_sccnd",	/* d = cond(s) ? 1 : 0 */
    141      1.1  christos };
    142      1.1  christos 
    143      1.1  christos static const char * optype_names[] = {
    144      1.1  christos   " -  ",
    145      1.1  christos   "#Imm",	/* #addend */
    146      1.1  christos   " Rn ",	/* Rn */
    147      1.1  christos   "[Rn]",	/* [Rn + addend] */
    148      1.1  christos   "Ps++",	/* [Rn+] */
    149      1.1  christos   "--Pr",	/* [-Rn] */
    150      1.1  christos   " cc ",	/* eq, gtu, etc */
    151      1.1  christos   "Flag",	/* [UIOSZC] */
    152      1.1  christos   "RbRi"	/* [Rb + scale * Ri] */
    153      1.1  christos };
    154      1.1  christos 
    155  1.1.1.6  christos #define N_RXO ARRAY_SIZE (id_names)
    156  1.1.1.6  christos #define N_RXT ARRAY_SIZE (optype_names)
    157  1.1.1.5  christos #define N_MAP 90
    158      1.1  christos 
    159      1.1  christos static unsigned long long benchmark_start_cycle;
    160      1.1  christos static unsigned long long benchmark_end_cycle;
    161      1.1  christos 
    162      1.1  christos static int op_cache[N_RXT][N_RXT][N_RXT];
    163      1.1  christos static int op_cache_rev[N_MAP];
    164      1.1  christos static int op_cache_idx = 0;
    165      1.1  christos 
    166      1.1  christos static int
    167      1.1  christos op_lookup (int a, int b, int c)
    168      1.1  christos {
    169      1.1  christos   if (op_cache[a][b][c])
    170      1.1  christos     return op_cache[a][b][c];
    171      1.1  christos   op_cache_idx ++;
    172      1.1  christos   if (op_cache_idx >= N_MAP)
    173      1.1  christos     {
    174      1.1  christos       printf("op_cache_idx exceeds %d\n", N_MAP);
    175      1.1  christos       exit(1);
    176      1.1  christos     }
    177      1.1  christos   op_cache[a][b][c] = op_cache_idx;
    178      1.1  christos   op_cache_rev[op_cache_idx] = (a<<8) | (b<<4) | c;
    179      1.1  christos   return op_cache_idx;
    180      1.1  christos }
    181      1.1  christos 
    182      1.1  christos static char *
    183      1.1  christos op_cache_string (int map)
    184      1.1  christos {
    185      1.1  christos   static int ci;
    186      1.1  christos   static char cb[5][20];
    187      1.1  christos   int a, b, c;
    188      1.1  christos 
    189      1.1  christos   map = op_cache_rev[map];
    190      1.1  christos   a = (map >> 8) & 15;
    191      1.1  christos   b = (map >> 4) & 15;
    192      1.1  christos   c = (map >> 0) & 15;
    193      1.1  christos   ci = (ci + 1) % 5;
    194      1.1  christos   sprintf(cb[ci], "%s %s %s", optype_names[a], optype_names[b], optype_names[c]);
    195      1.1  christos   return cb[ci];
    196      1.1  christos }
    197      1.1  christos 
    198      1.1  christos static unsigned long long cycles_per_id[N_RXO][N_MAP];
    199      1.1  christos static unsigned long long times_per_id[N_RXO][N_MAP];
    200      1.1  christos static unsigned long long memory_stalls;
    201      1.1  christos static unsigned long long register_stalls;
    202      1.1  christos static unsigned long long branch_stalls;
    203      1.1  christos static unsigned long long branch_alignment_stalls;
    204      1.1  christos static unsigned long long fast_returns;
    205      1.1  christos 
    206      1.1  christos static unsigned long times_per_pair[N_RXO][N_MAP][N_RXO][N_MAP];
    207      1.1  christos static int prev_opcode_id = RXO_unknown;
    208      1.1  christos static int po0;
    209      1.1  christos 
    210      1.1  christos #define STATS(x) x
    211      1.1  christos 
    212      1.1  christos #else
    213      1.1  christos #define STATS(x)
    214      1.1  christos #endif /* CYCLE_STATS */
    215      1.1  christos 
    216      1.1  christos 
    217      1.1  christos #ifdef CYCLE_ACCURATE
    218      1.1  christos 
    219      1.1  christos static int new_rt = -1;
    220      1.1  christos 
    221      1.1  christos /* Number of cycles to add if an insn spans an 8-byte boundary.  */
    222      1.1  christos static int branch_alignment_penalty = 0;
    223      1.1  christos 
    224      1.1  christos #endif
    225      1.1  christos 
    226      1.1  christos static int running_benchmark = 1;
    227      1.1  christos 
    228      1.1  christos #define tprintf if (trace && running_benchmark) printf
    229      1.1  christos 
    230      1.1  christos jmp_buf decode_jmp_buf;
    231      1.1  christos unsigned int rx_cycles = 0;
    232      1.1  christos 
    233      1.1  christos #ifdef CYCLE_ACCURATE
    234      1.1  christos /* If nonzero, memory was read at some point and cycle latency might
    235      1.1  christos    take effect.  */
    236      1.1  christos static int memory_source = 0;
    237      1.1  christos /* If nonzero, memory was written and extra cycles might be
    238      1.1  christos    needed.  */
    239      1.1  christos static int memory_dest = 0;
    240      1.1  christos 
    241      1.1  christos static void
    242      1.1  christos cycles (int throughput)
    243      1.1  christos {
    244      1.1  christos   tprintf("%d cycles\n", throughput);
    245      1.1  christos   regs.cycle_count += throughput;
    246      1.1  christos }
    247      1.1  christos 
    248      1.1  christos /* Number of execution (E) cycles the op uses.  For memory sources, we
    249      1.1  christos    include the load micro-op stall as two extra E cycles.  */
    250      1.1  christos #define E(c) cycles (memory_source ? c + 2 : c)
    251      1.1  christos #define E1 cycles (1)
    252      1.1  christos #define E2 cycles (2)
    253      1.1  christos #define EBIT cycles (memory_source ? 2 : 1)
    254      1.1  christos 
    255      1.1  christos /* Check to see if a read latency must be applied for a given register.  */
    256      1.1  christos #define RL(r) \
    257      1.1  christos   if (regs.rt == r )							\
    258      1.1  christos     {									\
    259      1.1  christos       tprintf("register %d load stall\n", r);				\
    260      1.1  christos       regs.cycle_count ++;						\
    261      1.1  christos       STATS(register_stalls ++);					\
    262      1.1  christos       regs.rt = -1;							\
    263      1.1  christos     }
    264      1.1  christos 
    265      1.1  christos #define RLD(r)					\
    266      1.1  christos   if (memory_source)				\
    267      1.1  christos     {						\
    268      1.1  christos       tprintf ("Rt now %d\n", r);		\
    269      1.1  christos       new_rt = r;				\
    270      1.1  christos     }
    271      1.1  christos 
    272      1.1  christos static int
    273      1.1  christos lsb_count (unsigned long v, int is_signed)
    274      1.1  christos {
    275      1.1  christos   int i, lsb;
    276      1.1  christos   if (is_signed && (v & 0x80000000U))
    277      1.1  christos     v = (unsigned long)(long)(-v);
    278      1.1  christos   for (i=31; i>=0; i--)
    279      1.1  christos     if (v & (1 << i))
    280      1.1  christos       {
    281      1.1  christos 	/* v is 0..31, we want 1=1-2, 2=3-4, 3=5-6, etc. */
    282      1.1  christos 	lsb = (i + 2) / 2;
    283      1.1  christos 	return lsb;
    284      1.1  christos       }
    285      1.1  christos   return 0;
    286      1.1  christos }
    287      1.1  christos 
    288      1.1  christos static int
    289      1.1  christos divu_cycles(unsigned long num, unsigned long den)
    290      1.1  christos {
    291      1.1  christos   int nb = lsb_count (num, 0);
    292      1.1  christos   int db = lsb_count (den, 0);
    293      1.1  christos   int rv;
    294      1.1  christos 
    295      1.1  christos   if (nb < db)
    296      1.1  christos     rv = 2;
    297      1.1  christos   else
    298      1.1  christos     rv = 3 + nb - db;
    299      1.1  christos   E (rv);
    300      1.1  christos   return rv;
    301      1.1  christos }
    302      1.1  christos 
    303      1.1  christos static int
    304      1.1  christos div_cycles(long num, long den)
    305      1.1  christos {
    306      1.1  christos   int nb = lsb_count ((unsigned long)num, 1);
    307      1.1  christos   int db = lsb_count ((unsigned long)den, 1);
    308      1.1  christos   int rv;
    309      1.1  christos 
    310      1.1  christos   if (nb < db)
    311      1.1  christos     rv = 3;
    312      1.1  christos   else
    313      1.1  christos     rv = 5 + nb - db;
    314      1.1  christos   E (rv);
    315      1.1  christos   return rv;
    316      1.1  christos }
    317      1.1  christos 
    318      1.1  christos #else /* !CYCLE_ACCURATE */
    319      1.1  christos 
    320      1.1  christos #define cycles(t)
    321      1.1  christos #define E(c)
    322      1.1  christos #define E1
    323      1.1  christos #define E2
    324      1.1  christos #define EBIT
    325      1.1  christos #define RL(r)
    326      1.1  christos #define RLD(r)
    327      1.1  christos 
    328      1.1  christos #define divu_cycles(n,d)
    329      1.1  christos #define div_cycles(n,d)
    330      1.1  christos 
    331      1.1  christos #endif /* else CYCLE_ACCURATE */
    332      1.1  christos 
    333      1.1  christos static int size2bytes[] = {
    334      1.1  christos   4, 1, 1, 1, 2, 2, 2, 3, 4
    335      1.1  christos };
    336      1.1  christos 
    337      1.1  christos typedef struct {
    338      1.1  christos   unsigned long dpc;
    339      1.1  christos } RX_Data;
    340      1.1  christos 
    341      1.1  christos #define rx_abort() _rx_abort(__FILE__, __LINE__)
    342      1.1  christos static void
    343      1.1  christos _rx_abort (const char *file, int line)
    344      1.1  christos {
    345      1.1  christos   if (strrchr (file, '/'))
    346      1.1  christos     file = strrchr (file, '/') + 1;
    347      1.1  christos   fprintf(stderr, "abort at %s:%d\n", file, line);
    348      1.1  christos   abort();
    349      1.1  christos }
    350      1.1  christos 
    351      1.1  christos static unsigned char *get_byte_base;
    352      1.1  christos static RX_Opcode_Decoded **decode_cache_base;
    353      1.1  christos static SI get_byte_page;
    354      1.1  christos 
    355      1.1  christos void
    356      1.1  christos reset_decoder (void)
    357      1.1  christos {
    358      1.1  christos   get_byte_base = 0;
    359      1.1  christos   decode_cache_base = 0;
    360      1.1  christos   get_byte_page = 0;
    361      1.1  christos }
    362      1.1  christos 
    363      1.1  christos static inline void
    364      1.1  christos maybe_get_mem_page (SI tpc)
    365      1.1  christos {
    366      1.1  christos   if (((tpc ^ get_byte_page) & NONPAGE_MASK) || enable_counting)
    367      1.1  christos     {
    368      1.1  christos       get_byte_page = tpc & NONPAGE_MASK;
    369      1.1  christos       get_byte_base = rx_mem_ptr (get_byte_page, MPA_READING) - get_byte_page;
    370      1.1  christos       decode_cache_base = rx_mem_decode_cache (get_byte_page) - get_byte_page;
    371      1.1  christos     }
    372      1.1  christos }
    373      1.1  christos 
    374      1.1  christos /* This gets called a *lot* so optimize it.  */
    375      1.1  christos static int
    376      1.1  christos rx_get_byte (void *vdata)
    377      1.1  christos {
    378      1.1  christos   RX_Data *rx_data = (RX_Data *)vdata;
    379      1.1  christos   SI tpc = rx_data->dpc;
    380      1.1  christos 
    381      1.1  christos   /* See load.c for an explanation of this.  */
    382      1.1  christos   if (rx_big_endian)
    383      1.1  christos     tpc ^= 3;
    384      1.1  christos 
    385      1.1  christos   maybe_get_mem_page (tpc);
    386      1.1  christos 
    387      1.1  christos   rx_data->dpc ++;
    388      1.1  christos   return get_byte_base [tpc];
    389      1.1  christos }
    390      1.1  christos 
    391      1.1  christos static int
    392      1.1  christos get_op (const RX_Opcode_Decoded *rd, int i)
    393      1.1  christos {
    394      1.1  christos   const RX_Opcode_Operand *o = rd->op + i;
    395      1.1  christos   int addr, rv = 0;
    396      1.1  christos 
    397      1.1  christos   switch (o->type)
    398      1.1  christos     {
    399      1.1  christos     case RX_Operand_None:
    400      1.1  christos       rx_abort ();
    401      1.1  christos 
    402      1.1  christos     case RX_Operand_Immediate:	/* #addend */
    403      1.1  christos       return o->addend;
    404      1.1  christos 
    405      1.1  christos     case RX_Operand_Register:	/* Rn */
    406      1.1  christos       RL (o->reg);
    407      1.1  christos       rv = get_reg (o->reg);
    408      1.1  christos       break;
    409      1.1  christos 
    410      1.1  christos     case RX_Operand_Predec:	/* [-Rn] */
    411      1.1  christos       put_reg (o->reg, get_reg (o->reg) - size2bytes[o->size]);
    412      1.1  christos       /* fall through */
    413      1.1  christos     case RX_Operand_Postinc:	/* [Rn+] */
    414  1.1.1.5  christos     case RX_Operand_Zero_Indirect:	/* [Rn + 0] */
    415      1.1  christos     case RX_Operand_Indirect:	/* [Rn + addend] */
    416      1.1  christos     case RX_Operand_TwoReg:	/* [Rn + scale * R2] */
    417      1.1  christos #ifdef CYCLE_ACCURATE
    418      1.1  christos       RL (o->reg);
    419      1.1  christos       if (o->type == RX_Operand_TwoReg)
    420      1.1  christos 	RL (rd->op[2].reg);
    421      1.1  christos       regs.rt = -1;
    422      1.1  christos       if (regs.m2m == M2M_BOTH)
    423      1.1  christos 	{
    424      1.1  christos 	  tprintf("src memory stall\n");
    425      1.1  christos #ifdef CYCLE_STATS
    426      1.1  christos 	  memory_stalls ++;
    427      1.1  christos #endif
    428      1.1  christos 	  regs.cycle_count ++;
    429      1.1  christos 	  regs.m2m = 0;
    430      1.1  christos 	}
    431      1.1  christos 
    432      1.1  christos       memory_source = 1;
    433      1.1  christos #endif
    434      1.1  christos 
    435      1.1  christos       if (o->type == RX_Operand_TwoReg)
    436      1.1  christos 	addr = get_reg (o->reg) * size2bytes[rd->size] + get_reg (rd->op[2].reg);
    437      1.1  christos       else
    438      1.1  christos 	addr = get_reg (o->reg) + o->addend;
    439      1.1  christos 
    440      1.1  christos       switch (o->size)
    441      1.1  christos 	{
    442  1.1.1.5  christos 	default:
    443      1.1  christos 	case RX_AnySize:
    444      1.1  christos 	  rx_abort ();
    445      1.1  christos 
    446      1.1  christos 	case RX_Byte: /* undefined extension */
    447      1.1  christos 	case RX_UByte:
    448      1.1  christos 	case RX_SByte:
    449      1.1  christos 	  rv = mem_get_qi (addr);
    450      1.1  christos 	  break;
    451      1.1  christos 
    452      1.1  christos 	case RX_Word: /* undefined extension */
    453      1.1  christos 	case RX_UWord:
    454      1.1  christos 	case RX_SWord:
    455      1.1  christos 	  rv = mem_get_hi (addr);
    456      1.1  christos 	  break;
    457      1.1  christos 
    458      1.1  christos 	case RX_3Byte:
    459      1.1  christos 	  rv = mem_get_psi (addr);
    460      1.1  christos 	  break;
    461      1.1  christos 
    462      1.1  christos 	case RX_Long:
    463      1.1  christos 	  rv = mem_get_si (addr);
    464      1.1  christos 	  break;
    465      1.1  christos 	}
    466      1.1  christos 
    467      1.1  christos       if (o->type == RX_Operand_Postinc)
    468      1.1  christos 	put_reg (o->reg, get_reg (o->reg) + size2bytes[o->size]);
    469      1.1  christos 
    470      1.1  christos       break;
    471      1.1  christos 
    472      1.1  christos     case RX_Operand_Condition:	/* eq, gtu, etc */
    473      1.1  christos       return condition_true (o->reg);
    474      1.1  christos 
    475      1.1  christos     case RX_Operand_Flag:	/* [UIOSZC] */
    476      1.1  christos       return (regs.r_psw & (1 << o->reg)) ? 1 : 0;
    477      1.1  christos     }
    478      1.1  christos 
    479      1.1  christos   /* if we've gotten here, we need to clip/extend the value according
    480      1.1  christos      to the size.  */
    481      1.1  christos   switch (o->size)
    482      1.1  christos     {
    483  1.1.1.5  christos     default:
    484      1.1  christos     case RX_AnySize:
    485      1.1  christos       rx_abort ();
    486      1.1  christos 
    487      1.1  christos     case RX_Byte: /* undefined extension */
    488      1.1  christos       rv |= 0xdeadbe00; /* keep them honest */
    489      1.1  christos       break;
    490      1.1  christos 
    491      1.1  christos     case RX_UByte:
    492      1.1  christos       rv &= 0xff;
    493      1.1  christos       break;
    494      1.1  christos 
    495      1.1  christos     case RX_SByte:
    496      1.1  christos       rv = sign_ext (rv, 8);
    497      1.1  christos       break;
    498      1.1  christos 
    499      1.1  christos     case RX_Word: /* undefined extension */
    500      1.1  christos       rv |= 0xdead0000; /* keep them honest */
    501      1.1  christos       break;
    502      1.1  christos 
    503      1.1  christos     case RX_UWord:
    504      1.1  christos       rv &=  0xffff;
    505      1.1  christos       break;
    506      1.1  christos 
    507      1.1  christos     case RX_SWord:
    508      1.1  christos       rv = sign_ext (rv, 16);
    509      1.1  christos       break;
    510      1.1  christos 
    511      1.1  christos     case RX_3Byte:
    512      1.1  christos       rv &= 0xffffff;
    513      1.1  christos       break;
    514      1.1  christos 
    515      1.1  christos     case RX_Long:
    516      1.1  christos       break;
    517      1.1  christos     }
    518      1.1  christos   return rv;
    519      1.1  christos }
    520      1.1  christos 
    521      1.1  christos static void
    522      1.1  christos put_op (const RX_Opcode_Decoded *rd, int i, int v)
    523      1.1  christos {
    524      1.1  christos   const RX_Opcode_Operand *o = rd->op + i;
    525      1.1  christos   int addr;
    526      1.1  christos 
    527      1.1  christos   switch (o->size)
    528      1.1  christos     {
    529  1.1.1.5  christos     default:
    530      1.1  christos     case RX_AnySize:
    531      1.1  christos       if (o->type != RX_Operand_Register)
    532      1.1  christos 	rx_abort ();
    533      1.1  christos       break;
    534      1.1  christos 
    535      1.1  christos     case RX_Byte: /* undefined extension */
    536      1.1  christos       v |= 0xdeadbe00; /* keep them honest */
    537      1.1  christos       break;
    538      1.1  christos 
    539      1.1  christos     case RX_UByte:
    540      1.1  christos       v &= 0xff;
    541      1.1  christos       break;
    542      1.1  christos 
    543      1.1  christos     case RX_SByte:
    544      1.1  christos       v = sign_ext (v, 8);
    545      1.1  christos       break;
    546      1.1  christos 
    547      1.1  christos     case RX_Word: /* undefined extension */
    548      1.1  christos       v |= 0xdead0000; /* keep them honest */
    549      1.1  christos       break;
    550      1.1  christos 
    551      1.1  christos     case RX_UWord:
    552      1.1  christos       v &=  0xffff;
    553      1.1  christos       break;
    554      1.1  christos 
    555      1.1  christos     case RX_SWord:
    556      1.1  christos       v = sign_ext (v, 16);
    557      1.1  christos       break;
    558      1.1  christos 
    559      1.1  christos     case RX_3Byte:
    560      1.1  christos       v &= 0xffffff;
    561      1.1  christos       break;
    562      1.1  christos 
    563      1.1  christos     case RX_Long:
    564      1.1  christos       break;
    565      1.1  christos     }
    566      1.1  christos 
    567      1.1  christos   switch (o->type)
    568      1.1  christos     {
    569      1.1  christos     case RX_Operand_None:
    570      1.1  christos       /* Opcodes like TST and CMP use this.  */
    571      1.1  christos       break;
    572      1.1  christos 
    573      1.1  christos     case RX_Operand_Immediate:	/* #addend */
    574      1.1  christos     case RX_Operand_Condition:	/* eq, gtu, etc */
    575      1.1  christos       rx_abort ();
    576      1.1  christos 
    577      1.1  christos     case RX_Operand_Register:	/* Rn */
    578      1.1  christos       put_reg (o->reg, v);
    579      1.1  christos       RLD (o->reg);
    580      1.1  christos       break;
    581      1.1  christos 
    582      1.1  christos     case RX_Operand_Predec:	/* [-Rn] */
    583      1.1  christos       put_reg (o->reg, get_reg (o->reg) - size2bytes[o->size]);
    584      1.1  christos       /* fall through */
    585      1.1  christos     case RX_Operand_Postinc:	/* [Rn+] */
    586  1.1.1.5  christos     case RX_Operand_Zero_Indirect:	/* [Rn + 0] */
    587      1.1  christos     case RX_Operand_Indirect:	/* [Rn + addend] */
    588      1.1  christos     case RX_Operand_TwoReg:	/* [Rn + scale * R2] */
    589      1.1  christos 
    590      1.1  christos #ifdef CYCLE_ACCURATE
    591      1.1  christos       if (regs.m2m == M2M_BOTH)
    592      1.1  christos 	{
    593      1.1  christos 	  tprintf("dst memory stall\n");
    594      1.1  christos 	  regs.cycle_count ++;
    595      1.1  christos #ifdef CYCLE_STATS
    596      1.1  christos 	  memory_stalls ++;
    597      1.1  christos #endif
    598      1.1  christos 	  regs.m2m = 0;
    599      1.1  christos 	}
    600      1.1  christos       memory_dest = 1;
    601      1.1  christos #endif
    602      1.1  christos 
    603      1.1  christos       if (o->type == RX_Operand_TwoReg)
    604      1.1  christos 	addr = get_reg (o->reg) * size2bytes[rd->size] + get_reg (rd->op[2].reg);
    605      1.1  christos       else
    606      1.1  christos 	addr = get_reg (o->reg) + o->addend;
    607      1.1  christos 
    608      1.1  christos       switch (o->size)
    609      1.1  christos 	{
    610  1.1.1.5  christos 	default:
    611      1.1  christos 	case RX_AnySize:
    612      1.1  christos 	  rx_abort ();
    613      1.1  christos 
    614      1.1  christos 	case RX_Byte: /* undefined extension */
    615      1.1  christos 	case RX_UByte:
    616      1.1  christos 	case RX_SByte:
    617      1.1  christos 	  mem_put_qi (addr, v);
    618      1.1  christos 	  break;
    619      1.1  christos 
    620      1.1  christos 	case RX_Word: /* undefined extension */
    621      1.1  christos 	case RX_UWord:
    622      1.1  christos 	case RX_SWord:
    623      1.1  christos 	  mem_put_hi (addr, v);
    624      1.1  christos 	  break;
    625      1.1  christos 
    626      1.1  christos 	case RX_3Byte:
    627      1.1  christos 	  mem_put_psi (addr, v);
    628      1.1  christos 	  break;
    629      1.1  christos 
    630      1.1  christos 	case RX_Long:
    631      1.1  christos 	  mem_put_si (addr, v);
    632      1.1  christos 	  break;
    633      1.1  christos 	}
    634      1.1  christos 
    635      1.1  christos       if (o->type == RX_Operand_Postinc)
    636      1.1  christos 	put_reg (o->reg, get_reg (o->reg) + size2bytes[o->size]);
    637      1.1  christos 
    638      1.1  christos       break;
    639      1.1  christos 
    640      1.1  christos     case RX_Operand_Flag:	/* [UIOSZC] */
    641      1.1  christos       if (v)
    642      1.1  christos 	regs.r_psw |= (1 << o->reg);
    643      1.1  christos       else
    644      1.1  christos 	regs.r_psw &= ~(1 << o->reg);
    645      1.1  christos       break;
    646      1.1  christos     }
    647      1.1  christos }
    648      1.1  christos 
    649      1.1  christos #define PD(x) put_op (opcode, 0, x)
    650      1.1  christos #define PS(x) put_op (opcode, 1, x)
    651      1.1  christos #define PS2(x) put_op (opcode, 2, x)
    652      1.1  christos #define GD() get_op (opcode, 0)
    653      1.1  christos #define GS() get_op (opcode, 1)
    654      1.1  christos #define GS2() get_op (opcode, 2)
    655      1.1  christos #define DSZ() size2bytes[opcode->op[0].size]
    656      1.1  christos #define SSZ() size2bytes[opcode->op[0].size]
    657      1.1  christos #define S2SZ() size2bytes[opcode->op[0].size]
    658      1.1  christos 
    659      1.1  christos /* "Universal" sources.  */
    660      1.1  christos #define US1() ((opcode->op[2].type == RX_Operand_None) ? GD() : GS())
    661      1.1  christos #define US2() ((opcode->op[2].type == RX_Operand_None) ? GS() : GS2())
    662      1.1  christos 
    663      1.1  christos static void
    664      1.1  christos push(int val)
    665      1.1  christos {
    666      1.1  christos   int rsp = get_reg (sp);
    667      1.1  christos   rsp -= 4;
    668      1.1  christos   put_reg (sp, rsp);
    669      1.1  christos   mem_put_si (rsp, val);
    670      1.1  christos }
    671      1.1  christos 
    672      1.1  christos /* Just like the above, but tag the memory as "pushed pc" so if anyone
    673      1.1  christos    tries to write to it, it will cause an error.  */
    674      1.1  christos static void
    675      1.1  christos pushpc(int val)
    676      1.1  christos {
    677      1.1  christos   int rsp = get_reg (sp);
    678      1.1  christos   rsp -= 4;
    679      1.1  christos   put_reg (sp, rsp);
    680      1.1  christos   mem_put_si (rsp, val);
    681      1.1  christos   mem_set_content_range (rsp, rsp+3, MC_PUSHED_PC);
    682      1.1  christos }
    683      1.1  christos 
    684      1.1  christos static int
    685      1.1  christos pop()
    686      1.1  christos {
    687      1.1  christos   int rv;
    688      1.1  christos   int rsp = get_reg (sp);
    689      1.1  christos   rv = mem_get_si (rsp);
    690      1.1  christos   rsp += 4;
    691      1.1  christos   put_reg (sp, rsp);
    692      1.1  christos   return rv;
    693      1.1  christos }
    694      1.1  christos 
    695      1.1  christos static int
    696      1.1  christos poppc()
    697      1.1  christos {
    698      1.1  christos   int rv;
    699      1.1  christos   int rsp = get_reg (sp);
    700      1.1  christos   if (mem_get_content_type (rsp) != MC_PUSHED_PC)
    701      1.1  christos     execution_error (SIM_ERR_CORRUPT_STACK, rsp);
    702      1.1  christos   rv = mem_get_si (rsp);
    703      1.1  christos   mem_set_content_range (rsp, rsp+3, MC_UNINIT);
    704      1.1  christos   rsp += 4;
    705      1.1  christos   put_reg (sp, rsp);
    706      1.1  christos   return rv;
    707      1.1  christos }
    708      1.1  christos 
    709      1.1  christos #define MATH_OP(vop,c)				\
    710      1.1  christos { \
    711      1.1  christos   umb = US2(); \
    712      1.1  christos   uma = US1(); \
    713      1.1  christos   ll = (unsigned long long) uma vop (unsigned long long) umb vop c; \
    714      1.1  christos   tprintf ("0x%x " #vop " 0x%x " #vop " 0x%x = 0x%llx\n", uma, umb, c, ll); \
    715      1.1  christos   ma = sign_ext (uma, DSZ() * 8);					\
    716      1.1  christos   mb = sign_ext (umb, DSZ() * 8);					\
    717      1.1  christos   sll = (long long) ma vop (long long) mb vop c; \
    718      1.1  christos   tprintf ("%d " #vop " %d " #vop " %d = %lld\n", ma, mb, c, sll); \
    719      1.1  christos   set_oszc (sll, DSZ(), (long long) ll > ((1 vop 1) ? (long long) b2mask[DSZ()] : (long long) -1)); \
    720      1.1  christos   PD (sll); \
    721      1.1  christos   E (1);    \
    722      1.1  christos }
    723      1.1  christos 
    724      1.1  christos #define LOGIC_OP(vop) \
    725      1.1  christos { \
    726      1.1  christos   mb = US2(); \
    727      1.1  christos   ma = US1(); \
    728      1.1  christos   v = ma vop mb; \
    729      1.1  christos   tprintf("0x%x " #vop " 0x%x = 0x%x\n", ma, mb, v); \
    730      1.1  christos   set_sz (v, DSZ()); \
    731      1.1  christos   PD(v); \
    732      1.1  christos   E (1); \
    733      1.1  christos }
    734      1.1  christos 
    735      1.1  christos #define SHIFT_OP(val, type, count, OP, carry_mask)	\
    736      1.1  christos { \
    737      1.1  christos   int i, c=0; \
    738      1.1  christos   count = US2(); \
    739      1.1  christos   val = (type)US1();				\
    740      1.1  christos   tprintf("%lld " #OP " %d\n", val, count); \
    741      1.1  christos   for (i = 0; i < count; i ++) \
    742      1.1  christos     { \
    743      1.1  christos       c = val & carry_mask; \
    744      1.1  christos       val OP 1; \
    745      1.1  christos     } \
    746  1.1.1.3  christos   set_oszc (val, 4, c); \
    747      1.1  christos   PD (val); \
    748      1.1  christos }
    749      1.1  christos 
    750      1.1  christos typedef union {
    751      1.1  christos   int i;
    752      1.1  christos   float f;
    753      1.1  christos } FloatInt;
    754      1.1  christos 
    755      1.1  christos static inline int
    756      1.1  christos float2int (float f)
    757      1.1  christos {
    758      1.1  christos   FloatInt fi;
    759      1.1  christos   fi.f = f;
    760      1.1  christos   return fi.i;
    761      1.1  christos }
    762      1.1  christos 
    763      1.1  christos static inline float
    764      1.1  christos int2float (int i)
    765      1.1  christos {
    766      1.1  christos   FloatInt fi;
    767      1.1  christos   fi.i = i;
    768      1.1  christos   return fi.f;
    769      1.1  christos }
    770      1.1  christos 
    771      1.1  christos static int
    772      1.1  christos fop_fadd (fp_t s1, fp_t s2, fp_t *d)
    773      1.1  christos {
    774      1.1  christos   *d = rxfp_add (s1, s2);
    775      1.1  christos   return 1;
    776      1.1  christos }
    777      1.1  christos 
    778      1.1  christos static int
    779      1.1  christos fop_fmul (fp_t s1, fp_t s2, fp_t *d)
    780      1.1  christos {
    781      1.1  christos   *d = rxfp_mul (s1, s2);
    782      1.1  christos   return 1;
    783      1.1  christos }
    784      1.1  christos 
    785      1.1  christos static int
    786      1.1  christos fop_fdiv (fp_t s1, fp_t s2, fp_t *d)
    787      1.1  christos {
    788      1.1  christos   *d = rxfp_div (s1, s2);
    789      1.1  christos   return 1;
    790      1.1  christos }
    791      1.1  christos 
    792      1.1  christos static int
    793      1.1  christos fop_fsub (fp_t s1, fp_t s2, fp_t *d)
    794      1.1  christos {
    795      1.1  christos   *d = rxfp_sub (s1, s2);
    796      1.1  christos   return 1;
    797      1.1  christos }
    798      1.1  christos 
    799      1.1  christos #define FPPENDING() (regs.r_fpsw & (FPSWBITS_CE | (FPSWBITS_FMASK & (regs.r_fpsw << FPSW_EFSH))))
    800      1.1  christos #define FPCLEAR() regs.r_fpsw &= FPSWBITS_CLEAR
    801      1.1  christos #define FPCHECK() \
    802      1.1  christos   if (FPPENDING()) \
    803      1.1  christos     return do_fp_exception (opcode_pc)
    804      1.1  christos 
    805      1.1  christos #define FLOAT_OP(func) \
    806      1.1  christos { \
    807      1.1  christos   int do_store;   \
    808      1.1  christos   fp_t fa, fb, fc; \
    809      1.1  christos   FPCLEAR(); \
    810      1.1  christos   fb = GS (); \
    811      1.1  christos   fa = GD (); \
    812      1.1  christos   do_store = fop_##func (fa, fb, &fc); \
    813      1.1  christos   tprintf("%g " #func " %g = %g %08x\n", int2float(fa), int2float(fb), int2float(fc), fc); \
    814      1.1  christos   FPCHECK(); \
    815      1.1  christos   if (do_store) \
    816      1.1  christos     PD (fc);	\
    817      1.1  christos   mb = 0; \
    818      1.1  christos   if ((fc & 0x80000000UL) != 0) \
    819      1.1  christos     mb |= FLAGBIT_S; \
    820      1.1  christos   if ((fc & 0x7fffffffUL) == 0)			\
    821      1.1  christos     mb |= FLAGBIT_Z; \
    822      1.1  christos   set_flags (FLAGBIT_S | FLAGBIT_Z, mb); \
    823      1.1  christos }
    824      1.1  christos 
    825      1.1  christos #define carry (FLAG_C ? 1 : 0)
    826      1.1  christos 
    827      1.1  christos static struct {
    828      1.1  christos   unsigned long vaddr;
    829      1.1  christos   const char *str;
    830      1.1  christos   int signal;
    831      1.1  christos } exception_info[] = {
    832      1.1  christos   { 0xFFFFFFD0UL, "priviledged opcode", SIGILL },
    833      1.1  christos   { 0xFFFFFFD4UL, "access violation", SIGSEGV },
    834      1.1  christos   { 0xFFFFFFDCUL, "undefined opcode", SIGILL },
    835      1.1  christos   { 0xFFFFFFE4UL, "floating point", SIGFPE }
    836      1.1  christos };
    837      1.1  christos #define EX_PRIVILEDGED	0
    838      1.1  christos #define EX_ACCESS	1
    839      1.1  christos #define EX_UNDEFINED	2
    840      1.1  christos #define EX_FLOATING	3
    841      1.1  christos #define EXCEPTION(n)  \
    842      1.1  christos   return generate_exception (n, opcode_pc)
    843      1.1  christos 
    844      1.1  christos #define PRIVILEDGED() \
    845      1.1  christos   if (FLAG_PM) \
    846      1.1  christos     EXCEPTION (EX_PRIVILEDGED)
    847      1.1  christos 
    848      1.1  christos static int
    849      1.1  christos generate_exception (unsigned long type, SI opcode_pc)
    850      1.1  christos {
    851      1.1  christos   SI old_psw, old_pc, new_pc;
    852      1.1  christos 
    853      1.1  christos   new_pc = mem_get_si (exception_info[type].vaddr);
    854      1.1  christos   /* 0x00020000 is the value used to initialise the known
    855      1.1  christos      exception vectors (see rx.ld), but it is a reserved
    856      1.1  christos      area of memory so do not try to access it, and if the
    857      1.1  christos      value has not been changed by the program then the
    858      1.1  christos      vector has not been installed.  */
    859      1.1  christos   if (new_pc == 0 || new_pc == 0x00020000)
    860      1.1  christos     {
    861      1.1  christos       if (rx_in_gdb)
    862      1.1  christos 	return RX_MAKE_STOPPED (exception_info[type].signal);
    863      1.1  christos 
    864      1.1  christos       fprintf(stderr, "Unhandled %s exception at pc = %#lx\n",
    865      1.1  christos 	      exception_info[type].str, (unsigned long) opcode_pc);
    866      1.1  christos       if (type == EX_FLOATING)
    867      1.1  christos 	{
    868      1.1  christos 	  int mask = FPPENDING ();
    869      1.1  christos 	  fprintf (stderr, "Pending FP exceptions:");
    870      1.1  christos 	  if (mask & FPSWBITS_FV)
    871      1.1  christos 	    fprintf(stderr, " Invalid");
    872      1.1  christos 	  if (mask & FPSWBITS_FO)
    873      1.1  christos 	    fprintf(stderr, " Overflow");
    874      1.1  christos 	  if (mask & FPSWBITS_FZ)
    875      1.1  christos 	    fprintf(stderr, " Division-by-zero");
    876      1.1  christos 	  if (mask & FPSWBITS_FU)
    877      1.1  christos 	    fprintf(stderr, " Underflow");
    878      1.1  christos 	  if (mask & FPSWBITS_FX)
    879      1.1  christos 	    fprintf(stderr, " Inexact");
    880      1.1  christos 	  if (mask & FPSWBITS_CE)
    881      1.1  christos 	    fprintf(stderr, " Unimplemented");
    882      1.1  christos 	  fprintf(stderr, "\n");
    883      1.1  christos 	}
    884      1.1  christos       return RX_MAKE_EXITED (1);
    885      1.1  christos     }
    886      1.1  christos 
    887      1.1  christos   tprintf ("Triggering %s exception\n", exception_info[type].str);
    888      1.1  christos 
    889      1.1  christos   old_psw = regs.r_psw;
    890      1.1  christos   regs.r_psw &= ~ (FLAGBIT_I | FLAGBIT_U | FLAGBIT_PM);
    891      1.1  christos   old_pc = opcode_pc;
    892      1.1  christos   regs.r_pc = new_pc;
    893      1.1  christos   pushpc (old_psw);
    894      1.1  christos   pushpc (old_pc);
    895      1.1  christos   return RX_MAKE_STEPPED ();
    896      1.1  christos }
    897      1.1  christos 
    898      1.1  christos void
    899      1.1  christos generate_access_exception (void)
    900      1.1  christos {
    901      1.1  christos   int rv;
    902      1.1  christos 
    903      1.1  christos   rv = generate_exception (EX_ACCESS, regs.r_pc);
    904      1.1  christos   if (RX_EXITED (rv))
    905      1.1  christos     longjmp (decode_jmp_buf, rv);
    906      1.1  christos }
    907      1.1  christos 
    908      1.1  christos static int
    909      1.1  christos do_fp_exception (unsigned long opcode_pc)
    910      1.1  christos {
    911      1.1  christos   while (FPPENDING())
    912      1.1  christos     EXCEPTION (EX_FLOATING);
    913      1.1  christos   return RX_MAKE_STEPPED ();
    914      1.1  christos }
    915      1.1  christos 
    916      1.1  christos static int
    917      1.1  christos op_is_memory (const RX_Opcode_Decoded *rd, int i)
    918      1.1  christos {
    919      1.1  christos   switch (rd->op[i].type)
    920      1.1  christos     {
    921      1.1  christos     case RX_Operand_Predec:
    922      1.1  christos     case RX_Operand_Postinc:
    923      1.1  christos     case RX_Operand_Indirect:
    924      1.1  christos       return 1;
    925      1.1  christos     default:
    926      1.1  christos       return 0;
    927      1.1  christos     }
    928      1.1  christos }
    929      1.1  christos #define OM(i) op_is_memory (opcode, i)
    930      1.1  christos 
    931      1.1  christos #define DO_RETURN(x) { longjmp (decode_jmp_buf, x); }
    932      1.1  christos 
    933      1.1  christos int
    934      1.1  christos decode_opcode ()
    935      1.1  christos {
    936      1.1  christos   unsigned int uma=0, umb=0;
    937      1.1  christos   int ma=0, mb=0;
    938      1.1  christos   int opcode_size, v;
    939      1.1  christos   unsigned long long ll;
    940      1.1  christos   long long sll;
    941      1.1  christos   unsigned long opcode_pc;
    942      1.1  christos   RX_Data rx_data;
    943      1.1  christos   const RX_Opcode_Decoded *opcode;
    944      1.1  christos #ifdef CYCLE_STATS
    945      1.1  christos   unsigned long long prev_cycle_count;
    946      1.1  christos #endif
    947      1.1  christos #ifdef CYCLE_ACCURATE
    948      1.1  christos   unsigned int tx;
    949      1.1  christos #endif
    950      1.1  christos 
    951      1.1  christos #ifdef CYCLE_STATS
    952      1.1  christos   prev_cycle_count = regs.cycle_count;
    953      1.1  christos #endif
    954      1.1  christos 
    955      1.1  christos #ifdef CYCLE_ACCURATE
    956      1.1  christos   memory_source = 0;
    957      1.1  christos   memory_dest = 0;
    958      1.1  christos #endif
    959      1.1  christos 
    960      1.1  christos   rx_cycles ++;
    961      1.1  christos 
    962      1.1  christos   maybe_get_mem_page (regs.r_pc);
    963      1.1  christos 
    964      1.1  christos   opcode_pc = regs.r_pc;
    965      1.1  christos 
    966      1.1  christos   /* Note that we don't word-swap this point, there's no point.  */
    967      1.1  christos   if (decode_cache_base[opcode_pc] == NULL)
    968      1.1  christos     {
    969      1.1  christos       RX_Opcode_Decoded *opcode_w;
    970      1.1  christos       rx_data.dpc = opcode_pc;
    971      1.1  christos       opcode_w = decode_cache_base[opcode_pc] = calloc (1, sizeof (RX_Opcode_Decoded));
    972      1.1  christos       opcode_size = rx_decode_opcode (opcode_pc, opcode_w,
    973      1.1  christos 				      rx_get_byte, &rx_data);
    974      1.1  christos       opcode = opcode_w;
    975      1.1  christos     }
    976      1.1  christos   else
    977      1.1  christos     {
    978      1.1  christos       opcode = decode_cache_base[opcode_pc];
    979      1.1  christos       opcode_size = opcode->n_bytes;
    980      1.1  christos     }
    981      1.1  christos 
    982      1.1  christos #ifdef CYCLE_ACCURATE
    983      1.1  christos   if (branch_alignment_penalty)
    984      1.1  christos     {
    985      1.1  christos       if ((regs.r_pc ^ (regs.r_pc + opcode_size - 1)) & ~7)
    986      1.1  christos 	{
    987      1.1  christos 	  tprintf("1 cycle branch alignment penalty\n");
    988      1.1  christos 	  cycles (branch_alignment_penalty);
    989      1.1  christos #ifdef CYCLE_STATS
    990      1.1  christos 	  branch_alignment_stalls ++;
    991      1.1  christos #endif
    992      1.1  christos 	}
    993      1.1  christos       branch_alignment_penalty = 0;
    994      1.1  christos     }
    995      1.1  christos #endif
    996      1.1  christos 
    997      1.1  christos   regs.r_pc += opcode_size;
    998      1.1  christos 
    999      1.1  christos   rx_flagmask = opcode->flags_s;
   1000      1.1  christos   rx_flagand = ~(int)opcode->flags_0;
   1001      1.1  christos   rx_flagor = opcode->flags_1;
   1002      1.1  christos 
   1003      1.1  christos   switch (opcode->id)
   1004      1.1  christos     {
   1005      1.1  christos     case RXO_abs:
   1006      1.1  christos       sll = GS ();
   1007      1.1  christos       tprintf("|%lld| = ", sll);
   1008      1.1  christos       if (sll < 0)
   1009      1.1  christos 	sll = -sll;
   1010      1.1  christos       tprintf("%lld\n", sll);
   1011      1.1  christos       PD (sll);
   1012      1.1  christos       set_osz (sll, 4);
   1013      1.1  christos       E (1);
   1014      1.1  christos       break;
   1015      1.1  christos 
   1016      1.1  christos     case RXO_adc:
   1017      1.1  christos       MATH_OP (+,carry);
   1018      1.1  christos       break;
   1019      1.1  christos 
   1020      1.1  christos     case RXO_add:
   1021      1.1  christos       MATH_OP (+,0);
   1022      1.1  christos       break;
   1023      1.1  christos 
   1024      1.1  christos     case RXO_and:
   1025      1.1  christos       LOGIC_OP (&);
   1026      1.1  christos       break;
   1027      1.1  christos 
   1028      1.1  christos     case RXO_bclr:
   1029      1.1  christos       ma = GD ();
   1030      1.1  christos       mb = GS ();
   1031      1.1  christos       if (opcode->op[0].type == RX_Operand_Register)
   1032      1.1  christos 	mb &= 0x1f;
   1033      1.1  christos       else
   1034      1.1  christos 	mb &= 0x07;
   1035      1.1  christos       ma &= ~(1 << mb);
   1036      1.1  christos       PD (ma);
   1037      1.1  christos       EBIT;
   1038      1.1  christos       break;
   1039      1.1  christos 
   1040      1.1  christos     case RXO_bmcc:
   1041      1.1  christos       ma = GD ();
   1042      1.1  christos       mb = GS ();
   1043      1.1  christos       if (opcode->op[0].type == RX_Operand_Register)
   1044      1.1  christos 	mb &= 0x1f;
   1045      1.1  christos       else
   1046      1.1  christos 	mb &= 0x07;
   1047      1.1  christos       if (GS2 ())
   1048      1.1  christos 	ma |= (1 << mb);
   1049      1.1  christos       else
   1050      1.1  christos 	ma &= ~(1 << mb);
   1051      1.1  christos       PD (ma);
   1052      1.1  christos       EBIT;
   1053      1.1  christos       break;
   1054      1.1  christos 
   1055      1.1  christos     case RXO_bnot:
   1056      1.1  christos       ma = GD ();
   1057      1.1  christos       mb = GS ();
   1058      1.1  christos       if (opcode->op[0].type == RX_Operand_Register)
   1059      1.1  christos 	mb &= 0x1f;
   1060      1.1  christos       else
   1061      1.1  christos 	mb &= 0x07;
   1062      1.1  christos       ma ^= (1 << mb);
   1063      1.1  christos       PD (ma);
   1064      1.1  christos       EBIT;
   1065      1.1  christos       break;
   1066      1.1  christos 
   1067      1.1  christos     case RXO_branch:
   1068      1.1  christos       if (opcode->op[1].type == RX_Operand_None || GS())
   1069      1.1  christos 	{
   1070      1.1  christos #ifdef CYCLE_ACCURATE
   1071      1.1  christos 	  SI old_pc = regs.r_pc;
   1072      1.1  christos 	  int delta;
   1073      1.1  christos #endif
   1074      1.1  christos 	  regs.r_pc = GD();
   1075      1.1  christos #ifdef CYCLE_ACCURATE
   1076      1.1  christos 	  delta = regs.r_pc - old_pc;
   1077      1.1  christos 	  if (delta >= 0 && delta < 16
   1078      1.1  christos 	      && opcode_size > 1)
   1079      1.1  christos 	    {
   1080      1.1  christos 	      tprintf("near forward branch bonus\n");
   1081      1.1  christos 	      cycles (2);
   1082      1.1  christos 	    }
   1083      1.1  christos 	  else
   1084      1.1  christos 	    {
   1085      1.1  christos 	      cycles (3);
   1086      1.1  christos 	      branch_alignment_penalty = 1;
   1087      1.1  christos 	    }
   1088      1.1  christos #ifdef CYCLE_STATS
   1089      1.1  christos 	  branch_stalls ++;
   1090      1.1  christos #endif
   1091      1.1  christos #endif
   1092      1.1  christos 	}
   1093      1.1  christos #ifdef CYCLE_ACCURATE
   1094      1.1  christos       else
   1095      1.1  christos 	cycles (1);
   1096      1.1  christos #endif
   1097      1.1  christos       break;
   1098      1.1  christos 
   1099      1.1  christos     case RXO_branchrel:
   1100      1.1  christos       if (opcode->op[1].type == RX_Operand_None || GS())
   1101      1.1  christos 	{
   1102      1.1  christos 	  int delta = GD();
   1103      1.1  christos 	  regs.r_pc = opcode_pc + delta;
   1104      1.1  christos #ifdef CYCLE_ACCURATE
   1105      1.1  christos 	  /* Note: specs say 3, chip says 2.  */
   1106      1.1  christos 	  if (delta >= 0 && delta < 16
   1107      1.1  christos 	      && opcode_size > 1)
   1108      1.1  christos 	    {
   1109      1.1  christos 	      tprintf("near forward branch bonus\n");
   1110      1.1  christos 	      cycles (2);
   1111      1.1  christos 	    }
   1112      1.1  christos 	  else
   1113      1.1  christos 	    {
   1114      1.1  christos 	      cycles (3);
   1115      1.1  christos 	      branch_alignment_penalty = 1;
   1116      1.1  christos 	    }
   1117      1.1  christos #ifdef CYCLE_STATS
   1118      1.1  christos 	  branch_stalls ++;
   1119      1.1  christos #endif
   1120      1.1  christos #endif
   1121      1.1  christos 	}
   1122      1.1  christos #ifdef CYCLE_ACCURATE
   1123      1.1  christos       else
   1124      1.1  christos 	cycles (1);
   1125      1.1  christos #endif
   1126      1.1  christos       break;
   1127      1.1  christos 
   1128      1.1  christos     case RXO_brk:
   1129      1.1  christos       {
   1130      1.1  christos 	int old_psw = regs.r_psw;
   1131      1.1  christos 	if (rx_in_gdb)
   1132      1.1  christos 	  DO_RETURN (RX_MAKE_HIT_BREAK ());
   1133      1.1  christos 	if (regs.r_intb == 0)
   1134      1.1  christos 	  {
   1135      1.1  christos 	    tprintf("BREAK hit, no vector table.\n");
   1136      1.1  christos 	    DO_RETURN (RX_MAKE_EXITED(1));
   1137      1.1  christos 	  }
   1138      1.1  christos 	regs.r_psw &= ~(FLAGBIT_I | FLAGBIT_U | FLAGBIT_PM);
   1139      1.1  christos 	pushpc (old_psw);
   1140      1.1  christos 	pushpc (regs.r_pc);
   1141      1.1  christos 	regs.r_pc = mem_get_si (regs.r_intb);
   1142      1.1  christos 	cycles(6);
   1143      1.1  christos       }
   1144      1.1  christos       break;
   1145      1.1  christos 
   1146      1.1  christos     case RXO_bset:
   1147      1.1  christos       ma = GD ();
   1148      1.1  christos       mb = GS ();
   1149      1.1  christos       if (opcode->op[0].type == RX_Operand_Register)
   1150      1.1  christos 	mb &= 0x1f;
   1151      1.1  christos       else
   1152      1.1  christos 	mb &= 0x07;
   1153      1.1  christos       ma |= (1 << mb);
   1154      1.1  christos       PD (ma);
   1155      1.1  christos       EBIT;
   1156      1.1  christos       break;
   1157      1.1  christos 
   1158      1.1  christos     case RXO_btst:
   1159      1.1  christos       ma = GS ();
   1160      1.1  christos       mb = GS2 ();
   1161      1.1  christos       if (opcode->op[1].type == RX_Operand_Register)
   1162      1.1  christos 	mb &= 0x1f;
   1163      1.1  christos       else
   1164      1.1  christos 	mb &= 0x07;
   1165      1.1  christos       umb = ma & (1 << mb);
   1166      1.1  christos       set_zc (! umb, umb);
   1167      1.1  christos       EBIT;
   1168      1.1  christos       break;
   1169      1.1  christos 
   1170      1.1  christos     case RXO_clrpsw:
   1171      1.1  christos       v = 1 << opcode->op[0].reg;
   1172      1.1  christos       if (FLAG_PM
   1173      1.1  christos 	  && (v == FLAGBIT_I
   1174      1.1  christos 	      || v == FLAGBIT_U))
   1175      1.1  christos 	break;
   1176      1.1  christos       regs.r_psw &= ~v;
   1177      1.1  christos       cycles (1);
   1178      1.1  christos       break;
   1179      1.1  christos 
   1180      1.1  christos     case RXO_div: /* d = d / s */
   1181      1.1  christos       ma = GS();
   1182      1.1  christos       mb = GD();
   1183      1.1  christos       tprintf("%d / %d = ", mb, ma);
   1184      1.1  christos       if (ma == 0 || (ma == -1 && (unsigned int) mb == 0x80000000))
   1185      1.1  christos 	{
   1186      1.1  christos 	  tprintf("#NAN\n");
   1187      1.1  christos 	  set_flags (FLAGBIT_O, FLAGBIT_O);
   1188      1.1  christos 	  cycles (3);
   1189      1.1  christos 	}
   1190      1.1  christos       else
   1191      1.1  christos 	{
   1192      1.1  christos 	  v = mb/ma;
   1193      1.1  christos 	  tprintf("%d\n", v);
   1194      1.1  christos 	  set_flags (FLAGBIT_O, 0);
   1195      1.1  christos 	  PD (v);
   1196      1.1  christos 	  div_cycles (mb, ma);
   1197      1.1  christos 	}
   1198      1.1  christos       break;
   1199      1.1  christos 
   1200      1.1  christos     case RXO_divu: /* d = d / s */
   1201      1.1  christos       uma = GS();
   1202      1.1  christos       umb = GD();
   1203      1.1  christos       tprintf("%u / %u = ", umb, uma);
   1204      1.1  christos       if (uma == 0)
   1205      1.1  christos 	{
   1206      1.1  christos 	  tprintf("#NAN\n");
   1207      1.1  christos 	  set_flags (FLAGBIT_O, FLAGBIT_O);
   1208      1.1  christos 	  cycles (2);
   1209      1.1  christos 	}
   1210      1.1  christos       else
   1211      1.1  christos 	{
   1212      1.1  christos 	  v = umb / uma;
   1213      1.1  christos 	  tprintf("%u\n", v);
   1214      1.1  christos 	  set_flags (FLAGBIT_O, 0);
   1215      1.1  christos 	  PD (v);
   1216      1.1  christos 	  divu_cycles (umb, uma);
   1217      1.1  christos 	}
   1218      1.1  christos       break;
   1219      1.1  christos 
   1220      1.1  christos     case RXO_emul:
   1221      1.1  christos       ma = GD ();
   1222      1.1  christos       mb = GS ();
   1223      1.1  christos       sll = (long long)ma * (long long)mb;
   1224      1.1  christos       tprintf("%d * %d = %lld\n", ma, mb, sll);
   1225      1.1  christos       put_reg (opcode->op[0].reg, sll);
   1226      1.1  christos       put_reg (opcode->op[0].reg + 1, sll >> 32);
   1227      1.1  christos       E2;
   1228      1.1  christos       break;
   1229      1.1  christos 
   1230      1.1  christos     case RXO_emulu:
   1231      1.1  christos       uma = GD ();
   1232      1.1  christos       umb = GS ();
   1233      1.1  christos       ll = (long long)uma * (long long)umb;
   1234      1.1  christos       tprintf("%#x * %#x = %#llx\n", uma, umb, ll);
   1235      1.1  christos       put_reg (opcode->op[0].reg, ll);
   1236      1.1  christos       put_reg (opcode->op[0].reg + 1, ll >> 32);
   1237      1.1  christos       E2;
   1238      1.1  christos       break;
   1239      1.1  christos 
   1240      1.1  christos     case RXO_fadd:
   1241      1.1  christos       FLOAT_OP (fadd);
   1242      1.1  christos       E (4);
   1243      1.1  christos       break;
   1244      1.1  christos 
   1245      1.1  christos     case RXO_fcmp:
   1246      1.1  christos       ma = GD();
   1247      1.1  christos       mb = GS();
   1248      1.1  christos       FPCLEAR ();
   1249      1.1  christos       rxfp_cmp (ma, mb);
   1250      1.1  christos       FPCHECK ();
   1251      1.1  christos       E (1);
   1252      1.1  christos       break;
   1253      1.1  christos 
   1254      1.1  christos     case RXO_fdiv:
   1255      1.1  christos       FLOAT_OP (fdiv);
   1256      1.1  christos       E (16);
   1257      1.1  christos       break;
   1258      1.1  christos 
   1259      1.1  christos     case RXO_fmul:
   1260      1.1  christos       FLOAT_OP (fmul);
   1261      1.1  christos       E (3);
   1262      1.1  christos       break;
   1263      1.1  christos 
   1264      1.1  christos     case RXO_rtfi:
   1265      1.1  christos       PRIVILEDGED ();
   1266      1.1  christos       regs.r_psw = regs.r_bpsw;
   1267      1.1  christos       regs.r_pc = regs.r_bpc;
   1268      1.1  christos #ifdef CYCLE_ACCURATE
   1269      1.1  christos       regs.fast_return = 0;
   1270      1.1  christos       cycles(3);
   1271      1.1  christos #endif
   1272      1.1  christos       break;
   1273      1.1  christos 
   1274      1.1  christos     case RXO_fsub:
   1275      1.1  christos       FLOAT_OP (fsub);
   1276      1.1  christos       E (4);
   1277      1.1  christos       break;
   1278      1.1  christos 
   1279      1.1  christos     case RXO_ftoi:
   1280      1.1  christos       ma = GS ();
   1281      1.1  christos       FPCLEAR ();
   1282      1.1  christos       mb = rxfp_ftoi (ma, FPRM_ZERO);
   1283      1.1  christos       FPCHECK ();
   1284      1.1  christos       PD (mb);
   1285      1.1  christos       tprintf("(int) %g = %d\n", int2float(ma), mb);
   1286      1.1  christos       set_sz (mb, 4);
   1287      1.1  christos       E (2);
   1288      1.1  christos       break;
   1289      1.1  christos 
   1290      1.1  christos     case RXO_int:
   1291      1.1  christos       v = GS ();
   1292      1.1  christos       if (v == 255)
   1293      1.1  christos 	{
   1294      1.1  christos 	  int rc = rx_syscall (regs.r[5]);
   1295      1.1  christos 	  if (! RX_STEPPED (rc))
   1296      1.1  christos 	    DO_RETURN (rc);
   1297      1.1  christos 	}
   1298      1.1  christos       else
   1299      1.1  christos 	{
   1300      1.1  christos 	  int old_psw = regs.r_psw;
   1301      1.1  christos 	  regs.r_psw &= ~(FLAGBIT_I | FLAGBIT_U | FLAGBIT_PM);
   1302      1.1  christos 	  pushpc (old_psw);
   1303      1.1  christos 	  pushpc (regs.r_pc);
   1304      1.1  christos 	  regs.r_pc = mem_get_si (regs.r_intb + 4 * v);
   1305      1.1  christos 	}
   1306      1.1  christos       cycles (6);
   1307      1.1  christos       break;
   1308      1.1  christos 
   1309      1.1  christos     case RXO_itof:
   1310      1.1  christos       ma = GS ();
   1311      1.1  christos       FPCLEAR ();
   1312      1.1  christos       mb = rxfp_itof (ma, regs.r_fpsw);
   1313      1.1  christos       FPCHECK ();
   1314      1.1  christos       tprintf("(float) %d = %x\n", ma, mb);
   1315      1.1  christos       PD (mb);
   1316      1.1  christos       set_sz (ma, 4);
   1317      1.1  christos       E (2);
   1318      1.1  christos       break;
   1319      1.1  christos 
   1320      1.1  christos     case RXO_jsr:
   1321      1.1  christos     case RXO_jsrrel:
   1322      1.1  christos       {
   1323      1.1  christos #ifdef CYCLE_ACCURATE
   1324      1.1  christos 	int delta;
   1325      1.1  christos 	regs.m2m = 0;
   1326      1.1  christos #endif
   1327      1.1  christos 	v = GD ();
   1328      1.1  christos #ifdef CYCLE_ACCURATE
   1329      1.1  christos 	regs.link_register = regs.r_pc;
   1330      1.1  christos #endif
   1331      1.1  christos 	pushpc (get_reg (pc));
   1332      1.1  christos 	if (opcode->id == RXO_jsrrel)
   1333      1.1  christos 	  v += regs.r_pc;
   1334      1.1  christos #ifdef CYCLE_ACCURATE
   1335      1.1  christos 	delta = v - regs.r_pc;
   1336      1.1  christos #endif
   1337      1.1  christos 	put_reg (pc, v);
   1338      1.1  christos #ifdef CYCLE_ACCURATE
   1339      1.1  christos 	/* Note: docs say 3, chip says 2 */
   1340      1.1  christos 	if (delta >= 0 && delta < 16)
   1341      1.1  christos 	  {
   1342      1.1  christos 	    tprintf ("near forward jsr bonus\n");
   1343      1.1  christos 	    cycles (2);
   1344      1.1  christos 	  }
   1345      1.1  christos 	else
   1346      1.1  christos 	  {
   1347      1.1  christos 	    branch_alignment_penalty = 1;
   1348      1.1  christos 	    cycles (3);
   1349      1.1  christos 	  }
   1350      1.1  christos 	regs.fast_return = 1;
   1351      1.1  christos #endif
   1352      1.1  christos       }
   1353      1.1  christos       break;
   1354      1.1  christos 
   1355      1.1  christos     case RXO_machi:
   1356      1.1  christos       ll = (long long)(signed short)(GS() >> 16) * (long long)(signed short)(GS2 () >> 16);
   1357      1.1  christos       ll <<= 16;
   1358      1.1  christos       put_reg64 (acc64, ll + regs.r_acc);
   1359      1.1  christos       E1;
   1360      1.1  christos       break;
   1361      1.1  christos 
   1362      1.1  christos     case RXO_maclo:
   1363      1.1  christos       ll = (long long)(signed short)(GS()) * (long long)(signed short)(GS2 ());
   1364      1.1  christos       ll <<= 16;
   1365      1.1  christos       put_reg64 (acc64, ll + regs.r_acc);
   1366      1.1  christos       E1;
   1367      1.1  christos       break;
   1368      1.1  christos 
   1369      1.1  christos     case RXO_max:
   1370      1.1  christos       mb = GS();
   1371      1.1  christos       ma = GD();
   1372      1.1  christos       if (ma > mb)
   1373      1.1  christos 	PD (ma);
   1374      1.1  christos       else
   1375      1.1  christos 	PD (mb);
   1376      1.1  christos       E (1);
   1377      1.1  christos       break;
   1378      1.1  christos 
   1379      1.1  christos     case RXO_min:
   1380      1.1  christos       mb = GS();
   1381      1.1  christos       ma = GD();
   1382      1.1  christos       if (ma < mb)
   1383      1.1  christos 	PD (ma);
   1384      1.1  christos       else
   1385      1.1  christos 	PD (mb);
   1386      1.1  christos       E (1);
   1387      1.1  christos       break;
   1388      1.1  christos 
   1389      1.1  christos     case RXO_mov:
   1390      1.1  christos       v = GS ();
   1391      1.1  christos 
   1392      1.1  christos       if (opcode->op[1].type == RX_Operand_Register
   1393      1.1  christos 	  && opcode->op[1].reg == 17 /* PC */)
   1394      1.1  christos 	{
   1395      1.1  christos 	  /* Special case.  We want the address of the insn, not the
   1396      1.1  christos 	     address of the next insn.  */
   1397      1.1  christos 	  v = opcode_pc;
   1398      1.1  christos 	}
   1399      1.1  christos 
   1400      1.1  christos       if (opcode->op[0].type == RX_Operand_Register
   1401      1.1  christos 	  && opcode->op[0].reg == 16 /* PSW */)
   1402      1.1  christos 	{
   1403      1.1  christos 	  /* Special case, LDC and POPC can't ever modify PM.  */
   1404      1.1  christos 	  int pm = regs.r_psw & FLAGBIT_PM;
   1405      1.1  christos 	  v &= ~ FLAGBIT_PM;
   1406      1.1  christos 	  v |= pm;
   1407      1.1  christos 	  if (pm)
   1408      1.1  christos 	    {
   1409      1.1  christos 	      v &= ~ (FLAGBIT_I | FLAGBIT_U | FLAGBITS_IPL);
   1410      1.1  christos 	      v |= pm;
   1411      1.1  christos 	    }
   1412      1.1  christos 	}
   1413      1.1  christos       if (FLAG_PM)
   1414      1.1  christos 	{
   1415      1.1  christos 	  /* various things can't be changed in user mode.  */
   1416      1.1  christos 	  if (opcode->op[0].type == RX_Operand_Register)
   1417      1.1  christos 	    if (opcode->op[0].reg == 32)
   1418      1.1  christos 	      {
   1419      1.1  christos 		v &= ~ (FLAGBIT_I | FLAGBIT_U | FLAGBITS_IPL);
   1420      1.1  christos 		v |= regs.r_psw & (FLAGBIT_I | FLAGBIT_U | FLAGBITS_IPL);
   1421      1.1  christos 	      }
   1422      1.1  christos 	  if (opcode->op[0].reg == 34 /* ISP */
   1423      1.1  christos 	      || opcode->op[0].reg == 37 /* BPSW */
   1424      1.1  christos 	      || opcode->op[0].reg == 39 /* INTB */
   1425      1.1  christos 	      || opcode->op[0].reg == 38 /* VCT */)
   1426      1.1  christos 	    /* These are ignored.  */
   1427      1.1  christos 	    break;
   1428      1.1  christos 	}
   1429      1.1  christos       if (OM(0) && OM(1))
   1430      1.1  christos 	cycles (2);
   1431      1.1  christos       else
   1432      1.1  christos 	cycles (1);
   1433      1.1  christos 
   1434      1.1  christos       PD (v);
   1435      1.1  christos 
   1436      1.1  christos #ifdef CYCLE_ACCURATE
   1437      1.1  christos       if ((opcode->op[0].type == RX_Operand_Predec
   1438      1.1  christos 	   && opcode->op[1].type == RX_Operand_Register)
   1439      1.1  christos 	  || (opcode->op[0].type == RX_Operand_Postinc
   1440      1.1  christos 	      && opcode->op[1].type == RX_Operand_Register))
   1441      1.1  christos 	{
   1442      1.1  christos 	  /* Special case: push reg doesn't cause a memory stall.  */
   1443      1.1  christos 	  memory_dest = 0;
   1444      1.1  christos 	  tprintf("push special case\n");
   1445      1.1  christos 	}
   1446      1.1  christos #endif
   1447      1.1  christos 
   1448      1.1  christos       set_sz (v, DSZ());
   1449      1.1  christos       break;
   1450      1.1  christos 
   1451      1.1  christos     case RXO_movbi:
   1452      1.1  christos       PD (GS ());
   1453      1.1  christos       cycles (1);
   1454      1.1  christos       break;
   1455      1.1  christos 
   1456      1.1  christos     case RXO_movbir:
   1457      1.1  christos       PS (GD ());
   1458      1.1  christos       cycles (1);
   1459      1.1  christos       break;
   1460      1.1  christos 
   1461      1.1  christos     case RXO_mul:
   1462      1.1  christos       v = US2 ();
   1463      1.1  christos       ll = (unsigned long long) US1() * (unsigned long long) v;
   1464      1.1  christos       PD(ll);
   1465      1.1  christos       E (1);
   1466      1.1  christos       break;
   1467      1.1  christos 
   1468      1.1  christos     case RXO_mulhi:
   1469      1.1  christos       v = GS2 ();
   1470      1.1  christos       ll = (long long)(signed short)(GS() >> 16) * (long long)(signed short)(v >> 16);
   1471      1.1  christos       ll <<= 16;
   1472      1.1  christos       put_reg64 (acc64, ll);
   1473      1.1  christos       E1;
   1474      1.1  christos       break;
   1475      1.1  christos 
   1476      1.1  christos     case RXO_mullo:
   1477      1.1  christos       v = GS2 ();
   1478      1.1  christos       ll = (long long)(signed short)(GS()) * (long long)(signed short)(v);
   1479      1.1  christos       ll <<= 16;
   1480      1.1  christos       put_reg64 (acc64, ll);
   1481      1.1  christos       E1;
   1482      1.1  christos       break;
   1483      1.1  christos 
   1484      1.1  christos     case RXO_mvfachi:
   1485      1.1  christos       PD (get_reg (acchi));
   1486      1.1  christos       E1;
   1487      1.1  christos       break;
   1488      1.1  christos 
   1489      1.1  christos     case RXO_mvfaclo:
   1490      1.1  christos       PD (get_reg (acclo));
   1491      1.1  christos       E1;
   1492      1.1  christos       break;
   1493      1.1  christos 
   1494      1.1  christos     case RXO_mvfacmi:
   1495      1.1  christos       PD (get_reg (accmi));
   1496      1.1  christos       E1;
   1497      1.1  christos       break;
   1498      1.1  christos 
   1499      1.1  christos     case RXO_mvtachi:
   1500      1.1  christos       put_reg (acchi, GS ());
   1501      1.1  christos       E1;
   1502      1.1  christos       break;
   1503      1.1  christos 
   1504      1.1  christos     case RXO_mvtaclo:
   1505      1.1  christos       put_reg (acclo, GS ());
   1506      1.1  christos       E1;
   1507      1.1  christos       break;
   1508      1.1  christos 
   1509      1.1  christos     case RXO_mvtipl:
   1510      1.1  christos       regs.r_psw &= ~ FLAGBITS_IPL;
   1511      1.1  christos       regs.r_psw |= (GS () << FLAGSHIFT_IPL) & FLAGBITS_IPL;
   1512      1.1  christos       E1;
   1513      1.1  christos       break;
   1514      1.1  christos 
   1515      1.1  christos     case RXO_nop:
   1516      1.1  christos     case RXO_nop2:
   1517      1.1  christos     case RXO_nop3:
   1518  1.1.1.5  christos     case RXO_nop4:
   1519  1.1.1.5  christos     case RXO_nop5:
   1520  1.1.1.5  christos     case RXO_nop6:
   1521  1.1.1.5  christos     case RXO_nop7:
   1522      1.1  christos       E1;
   1523      1.1  christos       break;
   1524      1.1  christos 
   1525      1.1  christos     case RXO_or:
   1526      1.1  christos       LOGIC_OP (|);
   1527      1.1  christos       break;
   1528      1.1  christos 
   1529      1.1  christos     case RXO_popm:
   1530      1.1  christos       /* POPM cannot pop R0 (sp).  */
   1531      1.1  christos       if (opcode->op[1].reg == 0 || opcode->op[2].reg == 0)
   1532      1.1  christos 	EXCEPTION (EX_UNDEFINED);
   1533      1.1  christos       if (opcode->op[1].reg >= opcode->op[2].reg)
   1534      1.1  christos 	{
   1535      1.1  christos 	  regs.r_pc = opcode_pc;
   1536      1.1  christos 	  DO_RETURN (RX_MAKE_STOPPED (SIGILL));
   1537      1.1  christos 	}
   1538      1.1  christos       for (v = opcode->op[1].reg; v <= opcode->op[2].reg; v++)
   1539      1.1  christos 	{
   1540      1.1  christos 	  cycles (1);
   1541      1.1  christos 	  RLD (v);
   1542      1.1  christos 	  put_reg (v, pop ());
   1543      1.1  christos 	}
   1544      1.1  christos       break;
   1545      1.1  christos 
   1546      1.1  christos     case RXO_pushm:
   1547      1.1  christos       /* PUSHM cannot push R0 (sp).  */
   1548      1.1  christos       if (opcode->op[1].reg == 0 || opcode->op[2].reg == 0)
   1549      1.1  christos 	EXCEPTION (EX_UNDEFINED);
   1550      1.1  christos       if (opcode->op[1].reg >= opcode->op[2].reg)
   1551      1.1  christos 	{
   1552      1.1  christos 	  regs.r_pc = opcode_pc;
   1553      1.1  christos 	  return RX_MAKE_STOPPED (SIGILL);
   1554      1.1  christos 	}
   1555      1.1  christos       for (v = opcode->op[2].reg; v >= opcode->op[1].reg; v--)
   1556      1.1  christos 	{
   1557      1.1  christos 	  RL (v);
   1558      1.1  christos 	  push (get_reg (v));
   1559      1.1  christos 	}
   1560      1.1  christos       cycles (opcode->op[2].reg - opcode->op[1].reg + 1);
   1561      1.1  christos       break;
   1562      1.1  christos 
   1563      1.1  christos     case RXO_racw:
   1564      1.1  christos       ll = get_reg64 (acc64) << GS ();
   1565      1.1  christos       ll += 0x80000000ULL;
   1566      1.1  christos       if ((signed long long)ll > (signed long long)0x00007fff00000000ULL)
   1567      1.1  christos 	ll = 0x00007fff00000000ULL;
   1568      1.1  christos       else if ((signed long long)ll < (signed long long)0xffff800000000000ULL)
   1569      1.1  christos 	ll = 0xffff800000000000ULL;
   1570      1.1  christos       else
   1571      1.1  christos 	ll &= 0xffffffff00000000ULL;
   1572      1.1  christos       put_reg64 (acc64, ll);
   1573      1.1  christos       E1;
   1574      1.1  christos       break;
   1575      1.1  christos 
   1576      1.1  christos     case RXO_rte:
   1577      1.1  christos       PRIVILEDGED ();
   1578      1.1  christos       regs.r_pc = poppc ();
   1579      1.1  christos       regs.r_psw = poppc ();
   1580      1.1  christos       if (FLAG_PM)
   1581      1.1  christos 	regs.r_psw |= FLAGBIT_U;
   1582      1.1  christos #ifdef CYCLE_ACCURATE
   1583      1.1  christos       regs.fast_return = 0;
   1584      1.1  christos       cycles (6);
   1585      1.1  christos #endif
   1586      1.1  christos       break;
   1587      1.1  christos 
   1588      1.1  christos     case RXO_revl:
   1589      1.1  christos       uma = GS ();
   1590      1.1  christos       umb = (((uma >> 24) & 0xff)
   1591      1.1  christos 	     | ((uma >> 8) & 0xff00)
   1592      1.1  christos 	     | ((uma << 8) & 0xff0000)
   1593      1.1  christos 	     | ((uma << 24) & 0xff000000UL));
   1594      1.1  christos       PD (umb);
   1595      1.1  christos       E1;
   1596      1.1  christos       break;
   1597      1.1  christos 
   1598      1.1  christos     case RXO_revw:
   1599      1.1  christos       uma = GS ();
   1600      1.1  christos       umb = (((uma >> 8) & 0x00ff00ff)
   1601      1.1  christos 	     | ((uma << 8) & 0xff00ff00UL));
   1602      1.1  christos       PD (umb);
   1603      1.1  christos       E1;
   1604      1.1  christos       break;
   1605      1.1  christos 
   1606      1.1  christos     case RXO_rmpa:
   1607      1.1  christos       RL(4);
   1608      1.1  christos       RL(5);
   1609      1.1  christos #ifdef CYCLE_ACCURATE
   1610      1.1  christos       tx = regs.r[3];
   1611      1.1  christos #endif
   1612      1.1  christos 
   1613      1.1  christos       while (regs.r[3] != 0)
   1614      1.1  christos 	{
   1615      1.1  christos 	  long long tmp;
   1616      1.1  christos 
   1617      1.1  christos 	  switch (opcode->size)
   1618      1.1  christos 	    {
   1619      1.1  christos 	    case RX_Long:
   1620      1.1  christos 	      ma = mem_get_si (regs.r[1]);
   1621      1.1  christos 	      mb = mem_get_si (regs.r[2]);
   1622      1.1  christos 	      regs.r[1] += 4;
   1623      1.1  christos 	      regs.r[2] += 4;
   1624      1.1  christos 	      break;
   1625      1.1  christos 	    case RX_Word:
   1626      1.1  christos 	      ma = sign_ext (mem_get_hi (regs.r[1]), 16);
   1627      1.1  christos 	      mb = sign_ext (mem_get_hi (regs.r[2]), 16);
   1628      1.1  christos 	      regs.r[1] += 2;
   1629      1.1  christos 	      regs.r[2] += 2;
   1630      1.1  christos 	      break;
   1631      1.1  christos 	    case RX_Byte:
   1632      1.1  christos 	      ma = sign_ext (mem_get_qi (regs.r[1]), 8);
   1633      1.1  christos 	      mb = sign_ext (mem_get_qi (regs.r[2]), 8);
   1634      1.1  christos 	      regs.r[1] += 1;
   1635      1.1  christos 	      regs.r[2] += 1;
   1636      1.1  christos 	      break;
   1637      1.1  christos 	    default:
   1638      1.1  christos 	      abort ();
   1639      1.1  christos 	    }
   1640      1.1  christos 	  /* We do the multiply as a signed value.  */
   1641      1.1  christos 	  sll = (long long)ma * (long long)mb;
   1642      1.1  christos 	  tprintf("        %016llx = %d * %d\n", sll, ma, mb);
   1643      1.1  christos 	  /* but we do the sum as unsigned, while sign extending the operands.  */
   1644      1.1  christos 	  tmp = regs.r[4] + (sll & 0xffffffffUL);
   1645      1.1  christos 	  regs.r[4] = tmp & 0xffffffffUL;
   1646      1.1  christos 	  tmp >>= 32;
   1647      1.1  christos 	  sll >>= 32;
   1648      1.1  christos 	  tmp += regs.r[5] + (sll & 0xffffffffUL);
   1649      1.1  christos 	  regs.r[5] = tmp & 0xffffffffUL;
   1650      1.1  christos 	  tmp >>= 32;
   1651      1.1  christos 	  sll >>= 32;
   1652      1.1  christos 	  tmp += regs.r[6] + (sll & 0xffffffffUL);
   1653      1.1  christos 	  regs.r[6] = tmp & 0xffffffffUL;
   1654      1.1  christos 	  tprintf("%08lx\033[36m%08lx\033[0m%08lx\n",
   1655      1.1  christos 		  (unsigned long) regs.r[6],
   1656      1.1  christos 		  (unsigned long) regs.r[5],
   1657      1.1  christos 		  (unsigned long) regs.r[4]);
   1658      1.1  christos 
   1659      1.1  christos 	  regs.r[3] --;
   1660      1.1  christos 	}
   1661      1.1  christos       if (regs.r[6] & 0x00008000)
   1662      1.1  christos 	regs.r[6] |= 0xffff0000UL;
   1663      1.1  christos       else
   1664      1.1  christos 	regs.r[6] &= 0x0000ffff;
   1665      1.1  christos       ma = (regs.r[6] & 0x80000000UL) ? FLAGBIT_S : 0;
   1666      1.1  christos       if (regs.r[6] != 0 && regs.r[6] != 0xffffffffUL)
   1667      1.1  christos 	set_flags (FLAGBIT_O|FLAGBIT_S, ma | FLAGBIT_O);
   1668      1.1  christos       else
   1669      1.1  christos 	set_flags (FLAGBIT_O|FLAGBIT_S, ma);
   1670      1.1  christos #ifdef CYCLE_ACCURATE
   1671      1.1  christos       switch (opcode->size)
   1672      1.1  christos 	{
   1673      1.1  christos 	case RX_Long:
   1674      1.1  christos 	  cycles (6 + 4 * tx);
   1675      1.1  christos 	  break;
   1676      1.1  christos 	case RX_Word:
   1677      1.1  christos 	  cycles (6 + 5 * (tx / 2) + 4 * (tx % 2));
   1678      1.1  christos 	  break;
   1679      1.1  christos 	case RX_Byte:
   1680      1.1  christos 	  cycles (6 + 7 * (tx / 4) + 4 * (tx % 4));
   1681      1.1  christos 	  break;
   1682      1.1  christos 	default:
   1683      1.1  christos 	  abort ();
   1684      1.1  christos 	}
   1685      1.1  christos #endif
   1686      1.1  christos       break;
   1687      1.1  christos 
   1688      1.1  christos     case RXO_rolc:
   1689      1.1  christos       v = GD ();
   1690      1.1  christos       ma = v & 0x80000000UL;
   1691      1.1  christos       v <<= 1;
   1692      1.1  christos       v |= carry;
   1693      1.1  christos       set_szc (v, 4, ma);
   1694      1.1  christos       PD (v);
   1695      1.1  christos       E1;
   1696      1.1  christos       break;
   1697      1.1  christos 
   1698      1.1  christos     case RXO_rorc:
   1699      1.1  christos       uma = GD ();
   1700      1.1  christos       mb = uma & 1;
   1701      1.1  christos       uma >>= 1;
   1702      1.1  christos       uma |= (carry ? 0x80000000UL : 0);
   1703      1.1  christos       set_szc (uma, 4, mb);
   1704      1.1  christos       PD (uma);
   1705      1.1  christos       E1;
   1706      1.1  christos       break;
   1707      1.1  christos 
   1708      1.1  christos     case RXO_rotl:
   1709      1.1  christos       mb = GS ();
   1710      1.1  christos       uma = GD ();
   1711      1.1  christos       if (mb)
   1712      1.1  christos 	{
   1713      1.1  christos 	  uma = (uma << mb) | (uma >> (32-mb));
   1714      1.1  christos 	  mb = uma & 1;
   1715      1.1  christos 	}
   1716      1.1  christos       set_szc (uma, 4, mb);
   1717      1.1  christos       PD (uma);
   1718      1.1  christos       E1;
   1719      1.1  christos       break;
   1720      1.1  christos 
   1721      1.1  christos     case RXO_rotr:
   1722      1.1  christos       mb = GS ();
   1723      1.1  christos       uma = GD ();
   1724      1.1  christos       if (mb)
   1725      1.1  christos 	{
   1726      1.1  christos 	  uma = (uma >> mb) | (uma << (32-mb));
   1727      1.1  christos 	  mb = uma & 0x80000000;
   1728      1.1  christos 	}
   1729      1.1  christos       set_szc (uma, 4, mb);
   1730      1.1  christos       PD (uma);
   1731      1.1  christos       E1;
   1732      1.1  christos       break;
   1733      1.1  christos 
   1734      1.1  christos     case RXO_round:
   1735      1.1  christos       ma = GS ();
   1736      1.1  christos       FPCLEAR ();
   1737      1.1  christos       mb = rxfp_ftoi (ma, regs.r_fpsw);
   1738      1.1  christos       FPCHECK ();
   1739      1.1  christos       PD (mb);
   1740      1.1  christos       tprintf("(int) %g = %d\n", int2float(ma), mb);
   1741      1.1  christos       set_sz (mb, 4);
   1742      1.1  christos       E (2);
   1743      1.1  christos       break;
   1744      1.1  christos 
   1745      1.1  christos     case RXO_rts:
   1746      1.1  christos       {
   1747      1.1  christos #ifdef CYCLE_ACCURATE
   1748      1.1  christos 	int cyc = 5;
   1749      1.1  christos #endif
   1750      1.1  christos 	regs.r_pc = poppc ();
   1751      1.1  christos #ifdef CYCLE_ACCURATE
   1752      1.1  christos 	/* Note: specs say 5, chip says 3.  */
   1753      1.1  christos 	if (regs.fast_return && regs.link_register == regs.r_pc)
   1754      1.1  christos 	  {
   1755      1.1  christos #ifdef CYCLE_STATS
   1756      1.1  christos 	    fast_returns ++;
   1757      1.1  christos #endif
   1758      1.1  christos 	    tprintf("fast return bonus\n");
   1759      1.1  christos 	    cyc -= 2;
   1760      1.1  christos 	  }
   1761      1.1  christos 	cycles (cyc);
   1762      1.1  christos 	regs.fast_return = 0;
   1763      1.1  christos 	branch_alignment_penalty = 1;
   1764      1.1  christos #endif
   1765      1.1  christos       }
   1766      1.1  christos       break;
   1767      1.1  christos 
   1768      1.1  christos     case RXO_rtsd:
   1769      1.1  christos       if (opcode->op[2].type == RX_Operand_Register)
   1770      1.1  christos 	{
   1771      1.1  christos 	  int i;
   1772      1.1  christos 	  /* RTSD cannot pop R0 (sp).  */
   1773      1.1  christos 	  put_reg (0, get_reg (0) + GS() - (opcode->op[0].reg-opcode->op[2].reg+1)*4);
   1774      1.1  christos 	  if (opcode->op[2].reg == 0)
   1775      1.1  christos 	    EXCEPTION (EX_UNDEFINED);
   1776      1.1  christos #ifdef CYCLE_ACCURATE
   1777      1.1  christos 	  tx = opcode->op[0].reg - opcode->op[2].reg + 1;
   1778      1.1  christos #endif
   1779      1.1  christos 	  for (i = opcode->op[2].reg; i <= opcode->op[0].reg; i ++)
   1780      1.1  christos 	    {
   1781      1.1  christos 	      RLD (i);
   1782      1.1  christos 	      put_reg (i, pop ());
   1783      1.1  christos 	    }
   1784      1.1  christos 	}
   1785      1.1  christos       else
   1786      1.1  christos 	{
   1787      1.1  christos #ifdef CYCLE_ACCURATE
   1788      1.1  christos 	  tx = 0;
   1789      1.1  christos #endif
   1790      1.1  christos 	  put_reg (0, get_reg (0) + GS());
   1791      1.1  christos 	}
   1792      1.1  christos       put_reg (pc, poppc());
   1793      1.1  christos #ifdef CYCLE_ACCURATE
   1794      1.1  christos       if (regs.fast_return && regs.link_register == regs.r_pc)
   1795      1.1  christos 	{
   1796      1.1  christos 	  tprintf("fast return bonus\n");
   1797      1.1  christos #ifdef CYCLE_STATS
   1798      1.1  christos 	  fast_returns ++;
   1799      1.1  christos #endif
   1800      1.1  christos 	  cycles (tx < 3 ? 3 : tx + 1);
   1801      1.1  christos 	}
   1802      1.1  christos       else
   1803      1.1  christos 	{
   1804      1.1  christos 	  cycles (tx < 5 ? 5 : tx + 1);
   1805      1.1  christos 	}
   1806      1.1  christos       regs.fast_return = 0;
   1807      1.1  christos       branch_alignment_penalty = 1;
   1808      1.1  christos #endif
   1809      1.1  christos       break;
   1810      1.1  christos 
   1811      1.1  christos     case RXO_sat:
   1812      1.1  christos       if (FLAG_O && FLAG_S)
   1813      1.1  christos 	PD (0x7fffffffUL);
   1814      1.1  christos       else if (FLAG_O && ! FLAG_S)
   1815      1.1  christos 	PD (0x80000000UL);
   1816      1.1  christos       E1;
   1817      1.1  christos       break;
   1818      1.1  christos 
   1819  1.1.1.2  christos     case RXO_satr:
   1820  1.1.1.2  christos       if (FLAG_O && ! FLAG_S)
   1821  1.1.1.2  christos 	{
   1822  1.1.1.2  christos 	  put_reg (6, 0x0);
   1823  1.1.1.2  christos 	  put_reg (5, 0x7fffffff);
   1824  1.1.1.2  christos 	  put_reg (4, 0xffffffff);
   1825  1.1.1.2  christos 	}
   1826  1.1.1.2  christos       else if (FLAG_O && FLAG_S)
   1827  1.1.1.2  christos 	{
   1828  1.1.1.2  christos 	  put_reg (6, 0xffffffff);
   1829  1.1.1.2  christos 	  put_reg (5, 0x80000000);
   1830  1.1.1.2  christos 	  put_reg (4, 0x0);
   1831  1.1.1.2  christos 	}
   1832  1.1.1.2  christos       E1;
   1833  1.1.1.2  christos       break;
   1834  1.1.1.2  christos 
   1835      1.1  christos     case RXO_sbb:
   1836      1.1  christos       MATH_OP (-, ! carry);
   1837      1.1  christos       break;
   1838      1.1  christos 
   1839      1.1  christos     case RXO_sccnd:
   1840      1.1  christos       if (GS())
   1841      1.1  christos 	PD (1);
   1842      1.1  christos       else
   1843      1.1  christos 	PD (0);
   1844      1.1  christos       E1;
   1845      1.1  christos       break;
   1846      1.1  christos 
   1847      1.1  christos     case RXO_scmpu:
   1848      1.1  christos #ifdef CYCLE_ACCURATE
   1849      1.1  christos       tx = regs.r[3];
   1850      1.1  christos #endif
   1851      1.1  christos       while (regs.r[3] != 0)
   1852      1.1  christos 	{
   1853      1.1  christos 	  uma = mem_get_qi (regs.r[1] ++);
   1854      1.1  christos 	  umb = mem_get_qi (regs.r[2] ++);
   1855      1.1  christos 	  regs.r[3] --;
   1856      1.1  christos 	  if (uma != umb || uma == 0)
   1857      1.1  christos 	    break;
   1858      1.1  christos 	}
   1859      1.1  christos       if (uma == umb)
   1860      1.1  christos 	set_zc (1, 1);
   1861      1.1  christos       else
   1862      1.1  christos 	set_zc (0, ((int)uma - (int)umb) >= 0);
   1863      1.1  christos       cycles (2 + 4 * (tx / 4) + 4 * (tx % 4));
   1864      1.1  christos       break;
   1865      1.1  christos 
   1866      1.1  christos     case RXO_setpsw:
   1867      1.1  christos       v = 1 << opcode->op[0].reg;
   1868      1.1  christos       if (FLAG_PM
   1869      1.1  christos 	  && (v == FLAGBIT_I
   1870      1.1  christos 	      || v == FLAGBIT_U))
   1871      1.1  christos 	break;
   1872      1.1  christos       regs.r_psw |= v;
   1873      1.1  christos       cycles (1);
   1874      1.1  christos       break;
   1875      1.1  christos 
   1876      1.1  christos     case RXO_smovb:
   1877      1.1  christos       RL (3);
   1878      1.1  christos #ifdef CYCLE_ACCURATE
   1879      1.1  christos       tx = regs.r[3];
   1880      1.1  christos #endif
   1881      1.1  christos       while (regs.r[3])
   1882      1.1  christos 	{
   1883      1.1  christos 	  uma = mem_get_qi (regs.r[2] --);
   1884      1.1  christos 	  mem_put_qi (regs.r[1]--, uma);
   1885      1.1  christos 	  regs.r[3] --;
   1886      1.1  christos 	}
   1887      1.1  christos #ifdef CYCLE_ACCURATE
   1888      1.1  christos       if (tx > 3)
   1889      1.1  christos 	cycles (6 + 3 * (tx / 4) + 3 * (tx % 4));
   1890      1.1  christos       else
   1891      1.1  christos 	cycles (2 + 3 * (tx % 4));
   1892      1.1  christos #endif
   1893      1.1  christos       break;
   1894      1.1  christos 
   1895      1.1  christos     case RXO_smovf:
   1896      1.1  christos       RL (3);
   1897      1.1  christos #ifdef CYCLE_ACCURATE
   1898      1.1  christos       tx = regs.r[3];
   1899      1.1  christos #endif
   1900      1.1  christos       while (regs.r[3])
   1901      1.1  christos 	{
   1902      1.1  christos 	  uma = mem_get_qi (regs.r[2] ++);
   1903      1.1  christos 	  mem_put_qi (regs.r[1]++, uma);
   1904      1.1  christos 	  regs.r[3] --;
   1905      1.1  christos 	}
   1906      1.1  christos       cycles (2 + 3 * (int)(tx / 4) + 3 * (tx % 4));
   1907      1.1  christos       break;
   1908      1.1  christos 
   1909      1.1  christos     case RXO_smovu:
   1910      1.1  christos #ifdef CYCLE_ACCURATE
   1911      1.1  christos       tx = regs.r[3];
   1912      1.1  christos #endif
   1913      1.1  christos       while (regs.r[3] != 0)
   1914      1.1  christos 	{
   1915      1.1  christos 	  uma = mem_get_qi (regs.r[2] ++);
   1916      1.1  christos 	  mem_put_qi (regs.r[1]++, uma);
   1917      1.1  christos 	  regs.r[3] --;
   1918      1.1  christos 	  if (uma == 0)
   1919      1.1  christos 	    break;
   1920      1.1  christos 	}
   1921      1.1  christos       cycles (2 + 3 * (int)(tx / 4) + 3 * (tx % 4));
   1922      1.1  christos       break;
   1923      1.1  christos 
   1924      1.1  christos     case RXO_shar: /* d = ma >> mb */
   1925      1.1  christos       SHIFT_OP (sll, int, mb, >>=, 1);
   1926      1.1  christos       E (1);
   1927      1.1  christos       break;
   1928      1.1  christos 
   1929      1.1  christos     case RXO_shll: /* d = ma << mb */
   1930      1.1  christos       SHIFT_OP (ll, int, mb, <<=, 0x80000000UL);
   1931      1.1  christos       E (1);
   1932      1.1  christos       break;
   1933      1.1  christos 
   1934      1.1  christos     case RXO_shlr: /* d = ma >> mb */
   1935      1.1  christos       SHIFT_OP (ll, unsigned int, mb, >>=, 1);
   1936      1.1  christos       E (1);
   1937      1.1  christos       break;
   1938      1.1  christos 
   1939      1.1  christos     case RXO_sstr:
   1940      1.1  christos       RL (3);
   1941      1.1  christos #ifdef CYCLE_ACCURATE
   1942      1.1  christos       tx = regs.r[3];
   1943      1.1  christos #endif
   1944      1.1  christos       switch (opcode->size)
   1945      1.1  christos 	{
   1946      1.1  christos 	case RX_Long:
   1947      1.1  christos 	  while (regs.r[3] != 0)
   1948      1.1  christos 	    {
   1949      1.1  christos 	      mem_put_si (regs.r[1], regs.r[2]);
   1950      1.1  christos 	      regs.r[1] += 4;
   1951      1.1  christos 	      regs.r[3] --;
   1952      1.1  christos 	    }
   1953      1.1  christos 	  cycles (2 + tx);
   1954      1.1  christos 	  break;
   1955      1.1  christos 	case RX_Word:
   1956      1.1  christos 	  while (regs.r[3] != 0)
   1957      1.1  christos 	    {
   1958      1.1  christos 	      mem_put_hi (regs.r[1], regs.r[2]);
   1959      1.1  christos 	      regs.r[1] += 2;
   1960      1.1  christos 	      regs.r[3] --;
   1961      1.1  christos 	    }
   1962      1.1  christos 	  cycles (2 + (int)(tx / 2) + tx % 2);
   1963      1.1  christos 	  break;
   1964      1.1  christos 	case RX_Byte:
   1965      1.1  christos 	  while (regs.r[3] != 0)
   1966      1.1  christos 	    {
   1967      1.1  christos 	      mem_put_qi (regs.r[1], regs.r[2]);
   1968      1.1  christos 	      regs.r[1] ++;
   1969      1.1  christos 	      regs.r[3] --;
   1970      1.1  christos 	    }
   1971      1.1  christos 	  cycles (2 + (int)(tx / 4) + tx % 4);
   1972      1.1  christos 	  break;
   1973      1.1  christos 	default:
   1974      1.1  christos 	  abort ();
   1975      1.1  christos 	}
   1976      1.1  christos       break;
   1977      1.1  christos 
   1978      1.1  christos     case RXO_stcc:
   1979      1.1  christos       if (GS2())
   1980      1.1  christos 	PD (GS ());
   1981      1.1  christos       E1;
   1982      1.1  christos       break;
   1983      1.1  christos 
   1984      1.1  christos     case RXO_stop:
   1985      1.1  christos       PRIVILEDGED ();
   1986      1.1  christos       regs.r_psw |= FLAGBIT_I;
   1987      1.1  christos       DO_RETURN (RX_MAKE_STOPPED(0));
   1988      1.1  christos 
   1989      1.1  christos     case RXO_sub:
   1990      1.1  christos       MATH_OP (-, 0);
   1991      1.1  christos       break;
   1992      1.1  christos 
   1993      1.1  christos     case RXO_suntil:
   1994      1.1  christos       RL(3);
   1995      1.1  christos #ifdef CYCLE_ACCURATE
   1996      1.1  christos       tx = 0;
   1997      1.1  christos #endif
   1998      1.1  christos       if (regs.r[3] == 0)
   1999      1.1  christos 	{
   2000      1.1  christos 	  cycles (3);
   2001      1.1  christos 	  break;
   2002      1.1  christos 	}
   2003      1.1  christos       switch (opcode->size)
   2004      1.1  christos 	{
   2005      1.1  christos 	case RX_Long:
   2006      1.1  christos 	  uma = get_reg (2);
   2007      1.1  christos 	  while (regs.r[3] != 0)
   2008      1.1  christos 	    {
   2009      1.1  christos 	      regs.r[3] --;
   2010      1.1  christos 	      umb = mem_get_si (get_reg (1));
   2011      1.1  christos 	      regs.r[1] += 4;
   2012      1.1  christos #ifdef CYCLE_ACCURATE
   2013      1.1  christos 	      tx ++;
   2014      1.1  christos #endif
   2015      1.1  christos 	      if (umb == uma)
   2016      1.1  christos 		break;
   2017      1.1  christos 	    }
   2018      1.1  christos #ifdef CYCLE_ACCURATE
   2019      1.1  christos 	  cycles (3 + 3 * tx);
   2020      1.1  christos #endif
   2021      1.1  christos 	  break;
   2022      1.1  christos 	case RX_Word:
   2023      1.1  christos 	  uma = get_reg (2) & 0xffff;
   2024      1.1  christos 	  while (regs.r[3] != 0)
   2025      1.1  christos 	    {
   2026      1.1  christos 	      regs.r[3] --;
   2027      1.1  christos 	      umb = mem_get_hi (get_reg (1));
   2028      1.1  christos 	      regs.r[1] += 2;
   2029      1.1  christos #ifdef CYCLE_ACCURATE
   2030      1.1  christos 	      tx ++;
   2031      1.1  christos #endif
   2032      1.1  christos 	      if (umb == uma)
   2033      1.1  christos 		break;
   2034      1.1  christos 	    }
   2035      1.1  christos #ifdef CYCLE_ACCURATE
   2036      1.1  christos 	  cycles (3 + 3 * (tx / 2) + 3 * (tx % 2));
   2037      1.1  christos #endif
   2038      1.1  christos 	  break;
   2039      1.1  christos 	case RX_Byte:
   2040      1.1  christos 	  uma = get_reg (2) & 0xff;
   2041      1.1  christos 	  while (regs.r[3] != 0)
   2042      1.1  christos 	    {
   2043      1.1  christos 	      regs.r[3] --;
   2044      1.1  christos 	      umb = mem_get_qi (regs.r[1]);
   2045      1.1  christos 	      regs.r[1] += 1;
   2046      1.1  christos #ifdef CYCLE_ACCURATE
   2047      1.1  christos 	      tx ++;
   2048      1.1  christos #endif
   2049      1.1  christos 	      if (umb == uma)
   2050      1.1  christos 		break;
   2051      1.1  christos 	    }
   2052      1.1  christos #ifdef CYCLE_ACCURATE
   2053      1.1  christos 	  cycles (3 + 3 * (tx / 4) + 3 * (tx % 4));
   2054      1.1  christos #endif
   2055      1.1  christos 	  break;
   2056      1.1  christos 	default:
   2057      1.1  christos 	  abort();
   2058      1.1  christos 	}
   2059      1.1  christos       if (uma == umb)
   2060      1.1  christos 	set_zc (1, 1);
   2061      1.1  christos       else
   2062      1.1  christos 	set_zc (0, ((int)uma - (int)umb) >= 0);
   2063      1.1  christos       break;
   2064      1.1  christos 
   2065      1.1  christos     case RXO_swhile:
   2066      1.1  christos       RL(3);
   2067      1.1  christos #ifdef CYCLE_ACCURATE
   2068      1.1  christos       tx = 0;
   2069      1.1  christos #endif
   2070      1.1  christos       if (regs.r[3] == 0)
   2071      1.1  christos 	break;
   2072      1.1  christos       switch (opcode->size)
   2073      1.1  christos 	{
   2074      1.1  christos 	case RX_Long:
   2075      1.1  christos 	  uma = get_reg (2);
   2076      1.1  christos 	  while (regs.r[3] != 0)
   2077      1.1  christos 	    {
   2078      1.1  christos 	      regs.r[3] --;
   2079      1.1  christos 	      umb = mem_get_si (get_reg (1));
   2080      1.1  christos 	      regs.r[1] += 4;
   2081      1.1  christos #ifdef CYCLE_ACCURATE
   2082      1.1  christos 	      tx ++;
   2083      1.1  christos #endif
   2084      1.1  christos 	      if (umb != uma)
   2085      1.1  christos 		break;
   2086      1.1  christos 	    }
   2087      1.1  christos #ifdef CYCLE_ACCURATE
   2088      1.1  christos 	  cycles (3 + 3 * tx);
   2089      1.1  christos #endif
   2090      1.1  christos 	  break;
   2091      1.1  christos 	case RX_Word:
   2092      1.1  christos 	  uma = get_reg (2) & 0xffff;
   2093      1.1  christos 	  while (regs.r[3] != 0)
   2094      1.1  christos 	    {
   2095      1.1  christos 	      regs.r[3] --;
   2096      1.1  christos 	      umb = mem_get_hi (get_reg (1));
   2097      1.1  christos 	      regs.r[1] += 2;
   2098      1.1  christos #ifdef CYCLE_ACCURATE
   2099      1.1  christos 	      tx ++;
   2100      1.1  christos #endif
   2101      1.1  christos 	      if (umb != uma)
   2102      1.1  christos 		break;
   2103      1.1  christos 	    }
   2104      1.1  christos #ifdef CYCLE_ACCURATE
   2105      1.1  christos 	  cycles (3 + 3 * (tx / 2) + 3 * (tx % 2));
   2106      1.1  christos #endif
   2107      1.1  christos 	  break;
   2108      1.1  christos 	case RX_Byte:
   2109      1.1  christos 	  uma = get_reg (2) & 0xff;
   2110      1.1  christos 	  while (regs.r[3] != 0)
   2111      1.1  christos 	    {
   2112      1.1  christos 	      regs.r[3] --;
   2113      1.1  christos 	      umb = mem_get_qi (regs.r[1]);
   2114      1.1  christos 	      regs.r[1] += 1;
   2115      1.1  christos #ifdef CYCLE_ACCURATE
   2116      1.1  christos 	      tx ++;
   2117      1.1  christos #endif
   2118      1.1  christos 	      if (umb != uma)
   2119      1.1  christos 		break;
   2120      1.1  christos 	    }
   2121      1.1  christos #ifdef CYCLE_ACCURATE
   2122      1.1  christos 	  cycles (3 + 3 * (tx / 4) + 3 * (tx % 4));
   2123      1.1  christos #endif
   2124      1.1  christos 	  break;
   2125      1.1  christos 	default:
   2126      1.1  christos 	  abort();
   2127      1.1  christos 	}
   2128      1.1  christos       if (uma == umb)
   2129      1.1  christos 	set_zc (1, 1);
   2130      1.1  christos       else
   2131      1.1  christos 	set_zc (0, ((int)uma - (int)umb) >= 0);
   2132      1.1  christos       break;
   2133      1.1  christos 
   2134      1.1  christos     case RXO_wait:
   2135      1.1  christos       PRIVILEDGED ();
   2136      1.1  christos       regs.r_psw |= FLAGBIT_I;
   2137      1.1  christos       DO_RETURN (RX_MAKE_STOPPED(0));
   2138      1.1  christos 
   2139      1.1  christos     case RXO_xchg:
   2140      1.1  christos #ifdef CYCLE_ACCURATE
   2141      1.1  christos       regs.m2m = 0;
   2142      1.1  christos #endif
   2143      1.1  christos       v = GS (); /* This is the memory operand, if any.  */
   2144      1.1  christos       PS (GD ()); /* and this may change the address register.  */
   2145      1.1  christos       PD (v);
   2146      1.1  christos       E2;
   2147      1.1  christos #ifdef CYCLE_ACCURATE
   2148      1.1  christos       /* all M cycles happen during xchg's cycles.  */
   2149      1.1  christos       memory_dest = 0;
   2150      1.1  christos       memory_source = 0;
   2151      1.1  christos #endif
   2152      1.1  christos       break;
   2153      1.1  christos 
   2154      1.1  christos     case RXO_xor:
   2155      1.1  christos       LOGIC_OP (^);
   2156      1.1  christos       break;
   2157      1.1  christos 
   2158      1.1  christos     default:
   2159      1.1  christos       EXCEPTION (EX_UNDEFINED);
   2160      1.1  christos     }
   2161      1.1  christos 
   2162      1.1  christos #ifdef CYCLE_ACCURATE
   2163      1.1  christos   regs.m2m = 0;
   2164      1.1  christos   if (memory_source)
   2165      1.1  christos     regs.m2m |= M2M_SRC;
   2166      1.1  christos   if (memory_dest)
   2167      1.1  christos     regs.m2m |= M2M_DST;
   2168      1.1  christos 
   2169      1.1  christos   regs.rt = new_rt;
   2170      1.1  christos   new_rt = -1;
   2171      1.1  christos #endif
   2172      1.1  christos 
   2173      1.1  christos #ifdef CYCLE_STATS
   2174      1.1  christos   if (prev_cycle_count == regs.cycle_count)
   2175      1.1  christos     {
   2176      1.1  christos       printf("Cycle count not updated! id %s\n", id_names[opcode->id]);
   2177      1.1  christos       abort ();
   2178      1.1  christos     }
   2179      1.1  christos #endif
   2180      1.1  christos 
   2181      1.1  christos #ifdef CYCLE_STATS
   2182      1.1  christos   if (running_benchmark)
   2183      1.1  christos     {
   2184      1.1  christos       int omap = op_lookup (opcode->op[0].type, opcode->op[1].type, opcode->op[2].type);
   2185      1.1  christos 
   2186      1.1  christos 
   2187      1.1  christos       cycles_per_id[opcode->id][omap] += regs.cycle_count - prev_cycle_count;
   2188      1.1  christos       times_per_id[opcode->id][omap] ++;
   2189      1.1  christos 
   2190      1.1  christos       times_per_pair[prev_opcode_id][po0][opcode->id][omap] ++;
   2191      1.1  christos 
   2192      1.1  christos       prev_opcode_id = opcode->id;
   2193      1.1  christos       po0 = omap;
   2194      1.1  christos     }
   2195      1.1  christos #endif
   2196      1.1  christos 
   2197      1.1  christos   return RX_MAKE_STEPPED ();
   2198      1.1  christos }
   2199      1.1  christos 
   2200      1.1  christos #ifdef CYCLE_STATS
   2201      1.1  christos void
   2202      1.1  christos reset_pipeline_stats (void)
   2203      1.1  christos {
   2204      1.1  christos   memset (cycles_per_id, 0, sizeof(cycles_per_id));
   2205      1.1  christos   memset (times_per_id, 0, sizeof(times_per_id));
   2206      1.1  christos   memory_stalls = 0;
   2207      1.1  christos   register_stalls = 0;
   2208      1.1  christos   branch_stalls = 0;
   2209      1.1  christos   branch_alignment_stalls = 0;
   2210      1.1  christos   fast_returns = 0;
   2211      1.1  christos   memset (times_per_pair, 0, sizeof(times_per_pair));
   2212      1.1  christos   running_benchmark = 1;
   2213      1.1  christos 
   2214      1.1  christos   benchmark_start_cycle = regs.cycle_count;
   2215      1.1  christos }
   2216      1.1  christos 
   2217      1.1  christos void
   2218      1.1  christos halt_pipeline_stats (void)
   2219      1.1  christos {
   2220      1.1  christos   running_benchmark = 0;
   2221      1.1  christos   benchmark_end_cycle = regs.cycle_count;
   2222      1.1  christos }
   2223      1.1  christos #endif
   2224      1.1  christos 
   2225      1.1  christos void
   2226      1.1  christos pipeline_stats (void)
   2227      1.1  christos {
   2228      1.1  christos #ifdef CYCLE_STATS
   2229      1.1  christos   int i, o1;
   2230      1.1  christos   int p, p1;
   2231      1.1  christos #endif
   2232      1.1  christos 
   2233      1.1  christos #ifdef CYCLE_ACCURATE
   2234      1.1  christos   if (verbose == 1)
   2235      1.1  christos     {
   2236      1.1  christos       printf ("cycles: %llu\n", regs.cycle_count);
   2237      1.1  christos       return;
   2238      1.1  christos     }
   2239      1.1  christos 
   2240      1.1  christos   printf ("cycles: %13s\n", comma (regs.cycle_count));
   2241      1.1  christos #endif
   2242      1.1  christos 
   2243      1.1  christos #ifdef CYCLE_STATS
   2244      1.1  christos   if (benchmark_start_cycle)
   2245      1.1  christos     printf ("bmark:  %13s\n", comma (benchmark_end_cycle - benchmark_start_cycle));
   2246      1.1  christos 
   2247      1.1  christos   printf("\n");
   2248      1.1  christos   for (i = 0; i < N_RXO; i++)
   2249      1.1  christos     for (o1 = 0; o1 < N_MAP; o1 ++)
   2250      1.1  christos       if (times_per_id[i][o1])
   2251      1.1  christos 	printf("%13s %13s %7.2f  %s %s\n",
   2252      1.1  christos 	       comma (cycles_per_id[i][o1]),
   2253      1.1  christos 	       comma (times_per_id[i][o1]),
   2254      1.1  christos 	       (double)cycles_per_id[i][o1] / times_per_id[i][o1],
   2255      1.1  christos 	       op_cache_string(o1),
   2256      1.1  christos 	       id_names[i]+4);
   2257      1.1  christos 
   2258      1.1  christos   printf("\n");
   2259      1.1  christos   for (p = 0; p < N_RXO; p ++)
   2260      1.1  christos     for (p1 = 0; p1 < N_MAP; p1 ++)
   2261      1.1  christos       for (i = 0; i < N_RXO; i ++)
   2262      1.1  christos 	for (o1 = 0; o1 < N_MAP; o1 ++)
   2263      1.1  christos 	  if (times_per_pair[p][p1][i][o1])
   2264      1.1  christos 	    {
   2265      1.1  christos 	      printf("%13s   %s %-9s  ->  %s %s\n",
   2266      1.1  christos 		     comma (times_per_pair[p][p1][i][o1]),
   2267      1.1  christos 		     op_cache_string(p1),
   2268      1.1  christos 		     id_names[p]+4,
   2269      1.1  christos 		     op_cache_string(o1),
   2270      1.1  christos 		     id_names[i]+4);
   2271      1.1  christos 	    }
   2272      1.1  christos 
   2273      1.1  christos   printf("\n");
   2274      1.1  christos   printf("%13s memory stalls\n", comma (memory_stalls));
   2275      1.1  christos   printf("%13s register stalls\n", comma (register_stalls));
   2276      1.1  christos   printf("%13s branches taken (non-return)\n", comma (branch_stalls));
   2277      1.1  christos   printf("%13s branch alignment stalls\n", comma (branch_alignment_stalls));
   2278      1.1  christos   printf("%13s fast returns\n", comma (fast_returns));
   2279      1.1  christos #endif
   2280      1.1  christos }
   2281