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