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