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