Blame sim/rx/rx.c

Packit Service 706eca
/* rx.c --- opcode semantics for stand-alone RX simulator.
Packit Service 706eca
Packit Service 706eca
Copyright (C) 2008-2018 Free Software Foundation, Inc.
Packit Service 706eca
Contributed by Red Hat, Inc.
Packit Service 706eca
Packit Service 706eca
This file is part of the GNU simulators.
Packit Service 706eca
Packit Service 706eca
This program is free software; you can redistribute it and/or modify
Packit Service 706eca
it under the terms of the GNU General Public License as published by
Packit Service 706eca
the Free Software Foundation; either version 3 of the License, or
Packit Service 706eca
(at your option) any later version.
Packit Service 706eca
Packit Service 706eca
This program is distributed in the hope that it will be useful,
Packit Service 706eca
but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 706eca
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 706eca
GNU General Public License for more details.
Packit Service 706eca
Packit Service 706eca
You should have received a copy of the GNU General Public License
Packit Service 706eca
along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
Packit Service 706eca
Packit Service 706eca
#include "config.h"
Packit Service 706eca
#include <stdio.h>
Packit Service 706eca
#include <stdlib.h>
Packit Service 706eca
#include <string.h>
Packit Service 706eca
#include <signal.h>
Packit Service 706eca
#include "libiberty.h"
Packit Service 706eca
Packit Service 706eca
#include "opcode/rx.h"
Packit Service 706eca
#include "cpu.h"
Packit Service 706eca
#include "mem.h"
Packit Service 706eca
#include "syscalls.h"
Packit Service 706eca
#include "fpu.h"
Packit Service 706eca
#include "err.h"
Packit Service 706eca
#include "misc.h"
Packit Service 706eca
Packit Service 706eca
#ifdef CYCLE_STATS
Packit Service 706eca
static const char * id_names[] = {
Packit Service 706eca
  "RXO_unknown",
Packit Service 706eca
  "RXO_mov",	/* d = s (signed) */
Packit Service 706eca
  "RXO_movbi",	/* d = [s,s2] (signed) */
Packit Service 706eca
  "RXO_movbir",	/* [s,s2] = d (signed) */
Packit Service 706eca
  "RXO_pushm",	/* s..s2 */
Packit Service 706eca
  "RXO_popm",	/* s..s2 */
Packit Service 706eca
  "RXO_xchg",	/* s <-> d */
Packit Service 706eca
  "RXO_stcc",	/* d = s if cond(s2) */
Packit Service 706eca
  "RXO_rtsd",	/* rtsd, 1=imm, 2-0 = reg if reg type */
Packit Service 706eca
Packit Service 706eca
  /* These are all either d OP= s or, if s2 is set, d = s OP s2.  Note
Packit Service 706eca
     that d may be "None".  */
Packit Service 706eca
  "RXO_and",
Packit Service 706eca
  "RXO_or",
Packit Service 706eca
  "RXO_xor",
Packit Service 706eca
  "RXO_add",
Packit Service 706eca
  "RXO_sub",
Packit Service 706eca
  "RXO_mul",
Packit Service 706eca
  "RXO_div",
Packit Service 706eca
  "RXO_divu",
Packit Service 706eca
  "RXO_shll",
Packit Service 706eca
  "RXO_shar",
Packit Service 706eca
  "RXO_shlr",
Packit Service 706eca
Packit Service 706eca
  "RXO_adc",	/* d = d + s + carry */
Packit Service 706eca
  "RXO_sbb",	/* d = d - s - ~carry */
Packit Service 706eca
  "RXO_abs",	/* d = |s| */
Packit Service 706eca
  "RXO_max",	/* d = max(d,s) */
Packit Service 706eca
  "RXO_min",	/* d = min(d,s) */
Packit Service 706eca
  "RXO_emul",	/* d:64 = d:32 * s */
Packit Service 706eca
  "RXO_emulu",	/* d:64 = d:32 * s (unsigned) */
Packit Service 706eca
Packit Service 706eca
  "RXO_rolc",	/* d <<= 1 through carry */
Packit Service 706eca
  "RXO_rorc",	/* d >>= 1 through carry*/
Packit Service 706eca
  "RXO_rotl",	/* d <<= #s without carry */
Packit Service 706eca
  "RXO_rotr",	/* d >>= #s without carry*/
Packit Service 706eca
  "RXO_revw",	/* d = revw(s) */
Packit Service 706eca
  "RXO_revl",	/* d = revl(s) */
Packit Service 706eca
  "RXO_branch",	/* pc = d if cond(s) */
Packit Service 706eca
  "RXO_branchrel",/* pc += d if cond(s) */
Packit Service 706eca
  "RXO_jsr",	/* pc = d */
Packit Service 706eca
  "RXO_jsrrel",	/* pc += d */
Packit Service 706eca
  "RXO_rts",
Packit Service 706eca
  "RXO_nop",
Packit Service 706eca
  "RXO_nop2",
Packit Service 706eca
  "RXO_nop3",
Packit Service 706eca
  "RXO_nop4",
Packit Service 706eca
  "RXO_nop5",
Packit Service 706eca
  "RXO_nop6",
Packit Service 706eca
  "RXO_nop7",
Packit Service 706eca
Packit Service 706eca
  "RXO_scmpu",
Packit Service 706eca
  "RXO_smovu",
Packit Service 706eca
  "RXO_smovb",
Packit Service 706eca
  "RXO_suntil",
Packit Service 706eca
  "RXO_swhile",
Packit Service 706eca
  "RXO_smovf",
Packit Service 706eca
  "RXO_sstr",
Packit Service 706eca
Packit Service 706eca
  "RXO_rmpa",
Packit Service 706eca
  "RXO_mulhi",
Packit Service 706eca
  "RXO_mullo",
Packit Service 706eca
  "RXO_machi",
Packit Service 706eca
  "RXO_maclo",
Packit Service 706eca
  "RXO_mvtachi",
Packit Service 706eca
  "RXO_mvtaclo",
Packit Service 706eca
  "RXO_mvfachi",
Packit Service 706eca
  "RXO_mvfacmi",
Packit Service 706eca
  "RXO_mvfaclo",
Packit Service 706eca
  "RXO_racw",
Packit Service 706eca
Packit Service 706eca
  "RXO_sat",	/* sat(d) */
Packit Service 706eca
  "RXO_satr",
Packit Service 706eca
Packit Service 706eca
  "RXO_fadd",	/* d op= s */
Packit Service 706eca
  "RXO_fcmp",
Packit Service 706eca
  "RXO_fsub",
Packit Service 706eca
  "RXO_ftoi",
Packit Service 706eca
  "RXO_fmul",
Packit Service 706eca
  "RXO_fdiv",
Packit Service 706eca
  "RXO_round",
Packit Service 706eca
  "RXO_itof",
Packit Service 706eca
Packit Service 706eca
  "RXO_bset",	/* d |= (1<
Packit Service 706eca
  "RXO_bclr",	/* d &= ~(1<
Packit Service 706eca
  "RXO_btst",	/* s & (1<
Packit Service 706eca
  "RXO_bnot",	/* d ^= (1<
Packit Service 706eca
  "RXO_bmcc",	/* d<s> = cond(s2) */
Packit Service 706eca
Packit Service 706eca
  "RXO_clrpsw",	/* flag index in d */
Packit Service 706eca
  "RXO_setpsw",	/* flag index in d */
Packit Service 706eca
  "RXO_mvtipl",	/* new IPL in s */
Packit Service 706eca
Packit Service 706eca
  "RXO_rtfi",
Packit Service 706eca
  "RXO_rte",
Packit Service 706eca
  "RXO_rtd",	/* undocumented */
Packit Service 706eca
  "RXO_brk",
Packit Service 706eca
  "RXO_dbt",	/* undocumented */
Packit Service 706eca
  "RXO_int",	/* vector id in s */
Packit Service 706eca
  "RXO_stop",
Packit Service 706eca
  "RXO_wait",
Packit Service 706eca
Packit Service 706eca
  "RXO_sccnd",	/* d = cond(s) ? 1 : 0 */
Packit Service 706eca
};
Packit Service 706eca
Packit Service 706eca
static const char * optype_names[] = {
Packit Service 706eca
  " -  ",
Packit Service 706eca
  "#Imm",	/* #addend */
Packit Service 706eca
  " Rn ",	/* Rn */
Packit Service 706eca
  "[Rn]",	/* [Rn + addend] */
Packit Service 706eca
  "Ps++",	/* [Rn+] */
Packit Service 706eca
  "--Pr",	/* [-Rn] */
Packit Service 706eca
  " cc ",	/* eq, gtu, etc */
Packit Service 706eca
  "Flag",	/* [UIOSZC] */
Packit Service 706eca
  "RbRi"	/* [Rb + scale * Ri] */
Packit Service 706eca
};
Packit Service 706eca
Packit Service 706eca
#define N_RXO ARRAY_SIZE (id_names)
Packit Service 706eca
#define N_RXT ARRAY_SIZE (optype_names)
Packit Service 706eca
#define N_MAP 90
Packit Service 706eca
Packit Service 706eca
static unsigned long long benchmark_start_cycle;
Packit Service 706eca
static unsigned long long benchmark_end_cycle;
Packit Service 706eca
Packit Service 706eca
static int op_cache[N_RXT][N_RXT][N_RXT];
Packit Service 706eca
static int op_cache_rev[N_MAP];
Packit Service 706eca
static int op_cache_idx = 0;
Packit Service 706eca
Packit Service 706eca
static int
Packit Service 706eca
op_lookup (int a, int b, int c)
Packit Service 706eca
{
Packit Service 706eca
  if (op_cache[a][b][c])
Packit Service 706eca
    return op_cache[a][b][c];
Packit Service 706eca
  op_cache_idx ++;
Packit Service 706eca
  if (op_cache_idx >= N_MAP)
Packit Service 706eca
    {
Packit Service 706eca
      printf("op_cache_idx exceeds %d\n", N_MAP);
Packit Service 706eca
      exit(1);
Packit Service 706eca
    }
Packit Service 706eca
  op_cache[a][b][c] = op_cache_idx;
Packit Service 706eca
  op_cache_rev[op_cache_idx] = (a<<8) | (b<<4) | c;
Packit Service 706eca
  return op_cache_idx;
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
static char *
Packit Service 706eca
op_cache_string (int map)
Packit Service 706eca
{
Packit Service 706eca
  static int ci;
Packit Service 706eca
  static char cb[5][20];
Packit Service 706eca
  int a, b, c;
Packit Service 706eca
Packit Service 706eca
  map = op_cache_rev[map];
Packit Service 706eca
  a = (map >> 8) & 15;
Packit Service 706eca
  b = (map >> 4) & 15;
Packit Service 706eca
  c = (map >> 0) & 15;
Packit Service 706eca
  ci = (ci + 1) % 5;
Packit Service 706eca
  sprintf(cb[ci], "%s %s %s", optype_names[a], optype_names[b], optype_names[c]);
Packit Service 706eca
  return cb[ci];
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
static unsigned long long cycles_per_id[N_RXO][N_MAP];
Packit Service 706eca
static unsigned long long times_per_id[N_RXO][N_MAP];
Packit Service 706eca
static unsigned long long memory_stalls;
Packit Service 706eca
static unsigned long long register_stalls;
Packit Service 706eca
static unsigned long long branch_stalls;
Packit Service 706eca
static unsigned long long branch_alignment_stalls;
Packit Service 706eca
static unsigned long long fast_returns;
Packit Service 706eca
Packit Service 706eca
static unsigned long times_per_pair[N_RXO][N_MAP][N_RXO][N_MAP];
Packit Service 706eca
static int prev_opcode_id = RXO_unknown;
Packit Service 706eca
static int po0;
Packit Service 706eca
Packit Service 706eca
#define STATS(x) x
Packit Service 706eca
Packit Service 706eca
#else
Packit Service 706eca
#define STATS(x)
Packit Service 706eca
#endif /* CYCLE_STATS */
Packit Service 706eca
Packit Service 706eca
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
Packit Service 706eca
static int new_rt = -1;
Packit Service 706eca
Packit Service 706eca
/* Number of cycles to add if an insn spans an 8-byte boundary.  */
Packit Service 706eca
static int branch_alignment_penalty = 0;
Packit Service 706eca
Packit Service 706eca
#endif
Packit Service 706eca
Packit Service 706eca
static int running_benchmark = 1;
Packit Service 706eca
Packit Service 706eca
#define tprintf if (trace && running_benchmark) printf
Packit Service 706eca
Packit Service 706eca
jmp_buf decode_jmp_buf;
Packit Service 706eca
unsigned int rx_cycles = 0;
Packit Service 706eca
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
/* If nonzero, memory was read at some point and cycle latency might
Packit Service 706eca
   take effect.  */
Packit Service 706eca
static int memory_source = 0;
Packit Service 706eca
/* If nonzero, memory was written and extra cycles might be
Packit Service 706eca
   needed.  */
Packit Service 706eca
static int memory_dest = 0;
Packit Service 706eca
Packit Service 706eca
static void
Packit Service 706eca
cycles (int throughput)
Packit Service 706eca
{
Packit Service 706eca
  tprintf("%d cycles\n", throughput);
Packit Service 706eca
  regs.cycle_count += throughput;
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
/* Number of execution (E) cycles the op uses.  For memory sources, we
Packit Service 706eca
   include the load micro-op stall as two extra E cycles.  */
Packit Service 706eca
#define E(c) cycles (memory_source ? c + 2 : c)
Packit Service 706eca
#define E1 cycles (1)
Packit Service 706eca
#define E2 cycles (2)
Packit Service 706eca
#define EBIT cycles (memory_source ? 2 : 1)
Packit Service 706eca
Packit Service 706eca
/* Check to see if a read latency must be applied for a given register.  */
Packit Service 706eca
#define RL(r) \
Packit Service 706eca
  if (regs.rt == r )							\
Packit Service 706eca
    {									\
Packit Service 706eca
      tprintf("register %d load stall\n", r);				\
Packit Service 706eca
      regs.cycle_count ++;						\
Packit Service 706eca
      STATS(register_stalls ++);					\
Packit Service 706eca
      regs.rt = -1;							\
Packit Service 706eca
    }
Packit Service 706eca
Packit Service 706eca
#define RLD(r)					\
Packit Service 706eca
  if (memory_source)				\
Packit Service 706eca
    {						\
Packit Service 706eca
      tprintf ("Rt now %d\n", r);		\
Packit Service 706eca
      new_rt = r;				\
Packit Service 706eca
    }
Packit Service 706eca
Packit Service 706eca
static int
Packit Service 706eca
lsb_count (unsigned long v, int is_signed)
Packit Service 706eca
{
Packit Service 706eca
  int i, lsb;
Packit Service 706eca
  if (is_signed && (v & 0x80000000U))
Packit Service 706eca
    v = (unsigned long)(long)(-v);
Packit Service 706eca
  for (i=31; i>=0; i--)
Packit Service 706eca
    if (v & (1 << i))
Packit Service 706eca
      {
Packit Service 706eca
	/* v is 0..31, we want 1=1-2, 2=3-4, 3=5-6, etc. */
Packit Service 706eca
	lsb = (i + 2) / 2;
Packit Service 706eca
	return lsb;
Packit Service 706eca
      }
Packit Service 706eca
  return 0;
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
static int
Packit Service 706eca
divu_cycles(unsigned long num, unsigned long den)
Packit Service 706eca
{
Packit Service 706eca
  int nb = lsb_count (num, 0);
Packit Service 706eca
  int db = lsb_count (den, 0);
Packit Service 706eca
  int rv;
Packit Service 706eca
Packit Service 706eca
  if (nb < db)
Packit Service 706eca
    rv = 2;
Packit Service 706eca
  else
Packit Service 706eca
    rv = 3 + nb - db;
Packit Service 706eca
  E (rv);
Packit Service 706eca
  return rv;
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
static int
Packit Service 706eca
div_cycles(long num, long den)
Packit Service 706eca
{
Packit Service 706eca
  int nb = lsb_count ((unsigned long)num, 1);
Packit Service 706eca
  int db = lsb_count ((unsigned long)den, 1);
Packit Service 706eca
  int rv;
Packit Service 706eca
Packit Service 706eca
  if (nb < db)
Packit Service 706eca
    rv = 3;
Packit Service 706eca
  else
Packit Service 706eca
    rv = 5 + nb - db;
Packit Service 706eca
  E (rv);
Packit Service 706eca
  return rv;
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
#else /* !CYCLE_ACCURATE */
Packit Service 706eca
Packit Service 706eca
#define cycles(t)
Packit Service 706eca
#define E(c)
Packit Service 706eca
#define E1
Packit Service 706eca
#define E2
Packit Service 706eca
#define EBIT
Packit Service 706eca
#define RL(r)
Packit Service 706eca
#define RLD(r)
Packit Service 706eca
Packit Service 706eca
#define divu_cycles(n,d)
Packit Service 706eca
#define div_cycles(n,d)
Packit Service 706eca
Packit Service 706eca
#endif /* else CYCLE_ACCURATE */
Packit Service 706eca
Packit Service 706eca
static int size2bytes[] = {
Packit Service 706eca
  4, 1, 1, 1, 2, 2, 2, 3, 4
Packit Service 706eca
};
Packit Service 706eca
Packit Service 706eca
typedef struct {
Packit Service 706eca
  unsigned long dpc;
Packit Service 706eca
} RX_Data;
Packit Service 706eca
Packit Service 706eca
#define rx_abort() _rx_abort(__FILE__, __LINE__)
Packit Service 706eca
static void
Packit Service 706eca
_rx_abort (const char *file, int line)
Packit Service 706eca
{
Packit Service 706eca
  if (strrchr (file, '/'))
Packit Service 706eca
    file = strrchr (file, '/') + 1;
Packit Service 706eca
  fprintf(stderr, "abort at %s:%d\n", file, line);
Packit Service 706eca
  abort();
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
static unsigned char *get_byte_base;
Packit Service 706eca
static RX_Opcode_Decoded **decode_cache_base;
Packit Service 706eca
static SI get_byte_page;
Packit Service 706eca
Packit Service 706eca
void
Packit Service 706eca
reset_decoder (void)
Packit Service 706eca
{
Packit Service 706eca
  get_byte_base = 0;
Packit Service 706eca
  decode_cache_base = 0;
Packit Service 706eca
  get_byte_page = 0;
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
static inline void
Packit Service 706eca
maybe_get_mem_page (SI tpc)
Packit Service 706eca
{
Packit Service 706eca
  if (((tpc ^ get_byte_page) & NONPAGE_MASK) || enable_counting)
Packit Service 706eca
    {
Packit Service 706eca
      get_byte_page = tpc & NONPAGE_MASK;
Packit Service 706eca
      get_byte_base = rx_mem_ptr (get_byte_page, MPA_READING) - get_byte_page;
Packit Service 706eca
      decode_cache_base = rx_mem_decode_cache (get_byte_page) - get_byte_page;
Packit Service 706eca
    }
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
/* This gets called a *lot* so optimize it.  */
Packit Service 706eca
static int
Packit Service 706eca
rx_get_byte (void *vdata)
Packit Service 706eca
{
Packit Service 706eca
  RX_Data *rx_data = (RX_Data *)vdata;
Packit Service 706eca
  SI tpc = rx_data->dpc;
Packit Service 706eca
Packit Service 706eca
  /* See load.c for an explanation of this.  */
Packit Service 706eca
  if (rx_big_endian)
Packit Service 706eca
    tpc ^= 3;
Packit Service 706eca
Packit Service 706eca
  maybe_get_mem_page (tpc);
Packit Service 706eca
Packit Service 706eca
  rx_data->dpc ++;
Packit Service 706eca
  return get_byte_base [tpc];
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
static int
Packit Service 706eca
get_op (const RX_Opcode_Decoded *rd, int i)
Packit Service 706eca
{
Packit Service 706eca
  const RX_Opcode_Operand *o = rd->op + i;
Packit Service 706eca
  int addr, rv = 0;
Packit Service 706eca
Packit Service 706eca
  switch (o->type)
Packit Service 706eca
    {
Packit Service 706eca
    case RX_Operand_None:
Packit Service 706eca
      rx_abort ();
Packit Service 706eca
Packit Service 706eca
    case RX_Operand_Immediate:	/* #addend */
Packit Service 706eca
      return o->addend;
Packit Service 706eca
Packit Service 706eca
    case RX_Operand_Register:	/* Rn */
Packit Service 706eca
      RL (o->reg);
Packit Service 706eca
      rv = get_reg (o->reg);
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RX_Operand_Predec:	/* [-Rn] */
Packit Service 706eca
      put_reg (o->reg, get_reg (o->reg) - size2bytes[o->size]);
Packit Service 706eca
      /* fall through */
Packit Service 706eca
    case RX_Operand_Postinc:	/* [Rn+] */
Packit Service 706eca
    case RX_Operand_Zero_Indirect:	/* [Rn + 0] */
Packit Service 706eca
    case RX_Operand_Indirect:	/* [Rn + addend] */
Packit Service 706eca
    case RX_Operand_TwoReg:	/* [Rn + scale * R2] */
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
      RL (o->reg);
Packit Service 706eca
      if (o->type == RX_Operand_TwoReg)
Packit Service 706eca
	RL (rd->op[2].reg);
Packit Service 706eca
      regs.rt = -1;
Packit Service 706eca
      if (regs.m2m == M2M_BOTH)
Packit Service 706eca
	{
Packit Service 706eca
	  tprintf("src memory stall\n");
Packit Service 706eca
#ifdef CYCLE_STATS
Packit Service 706eca
	  memory_stalls ++;
Packit Service 706eca
#endif
Packit Service 706eca
	  regs.cycle_count ++;
Packit Service 706eca
	  regs.m2m = 0;
Packit Service 706eca
	}
Packit Service 706eca
Packit Service 706eca
      memory_source = 1;
Packit Service 706eca
#endif
Packit Service 706eca
Packit Service 706eca
      if (o->type == RX_Operand_TwoReg)
Packit Service 706eca
	addr = get_reg (o->reg) * size2bytes[rd->size] + get_reg (rd->op[2].reg);
Packit Service 706eca
      else
Packit Service 706eca
	addr = get_reg (o->reg) + o->addend;
Packit Service 706eca
Packit Service 706eca
      switch (o->size)
Packit Service 706eca
	{
Packit Service 706eca
	default:
Packit Service 706eca
	case RX_AnySize:
Packit Service 706eca
	  rx_abort ();
Packit Service 706eca
Packit Service 706eca
	case RX_Byte: /* undefined extension */
Packit Service 706eca
	case RX_UByte:
Packit Service 706eca
	case RX_SByte:
Packit Service 706eca
	  rv = mem_get_qi (addr);
Packit Service 706eca
	  break;
Packit Service 706eca
Packit Service 706eca
	case RX_Word: /* undefined extension */
Packit Service 706eca
	case RX_UWord:
Packit Service 706eca
	case RX_SWord:
Packit Service 706eca
	  rv = mem_get_hi (addr);
Packit Service 706eca
	  break;
Packit Service 706eca
Packit Service 706eca
	case RX_3Byte:
Packit Service 706eca
	  rv = mem_get_psi (addr);
Packit Service 706eca
	  break;
Packit Service 706eca
Packit Service 706eca
	case RX_Long:
Packit Service 706eca
	  rv = mem_get_si (addr);
Packit Service 706eca
	  break;
Packit Service 706eca
	}
Packit Service 706eca
Packit Service 706eca
      if (o->type == RX_Operand_Postinc)
Packit Service 706eca
	put_reg (o->reg, get_reg (o->reg) + size2bytes[o->size]);
Packit Service 706eca
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RX_Operand_Condition:	/* eq, gtu, etc */
Packit Service 706eca
      return condition_true (o->reg);
Packit Service 706eca
Packit Service 706eca
    case RX_Operand_Flag:	/* [UIOSZC] */
Packit Service 706eca
      return (regs.r_psw & (1 << o->reg)) ? 1 : 0;
Packit Service 706eca
    }
Packit Service 706eca
Packit Service 706eca
  /* if we've gotten here, we need to clip/extend the value according
Packit Service 706eca
     to the size.  */
Packit Service 706eca
  switch (o->size)
Packit Service 706eca
    {
Packit Service 706eca
    default:
Packit Service 706eca
    case RX_AnySize:
Packit Service 706eca
      rx_abort ();
Packit Service 706eca
Packit Service 706eca
    case RX_Byte: /* undefined extension */
Packit Service 706eca
      rv |= 0xdeadbe00; /* keep them honest */
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RX_UByte:
Packit Service 706eca
      rv &= 0xff;
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RX_SByte:
Packit Service 706eca
      rv = sign_ext (rv, 8);
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RX_Word: /* undefined extension */
Packit Service 706eca
      rv |= 0xdead0000; /* keep them honest */
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RX_UWord:
Packit Service 706eca
      rv &=  0xffff;
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RX_SWord:
Packit Service 706eca
      rv = sign_ext (rv, 16);
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RX_3Byte:
Packit Service 706eca
      rv &= 0xffffff;
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RX_Long:
Packit Service 706eca
      break;
Packit Service 706eca
    }
Packit Service 706eca
  return rv;
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
static void
Packit Service 706eca
put_op (const RX_Opcode_Decoded *rd, int i, int v)
Packit Service 706eca
{
Packit Service 706eca
  const RX_Opcode_Operand *o = rd->op + i;
Packit Service 706eca
  int addr;
Packit Service 706eca
Packit Service 706eca
  switch (o->size)
Packit Service 706eca
    {
Packit Service 706eca
    default:
Packit Service 706eca
    case RX_AnySize:
Packit Service 706eca
      if (o->type != RX_Operand_Register)
Packit Service 706eca
	rx_abort ();
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RX_Byte: /* undefined extension */
Packit Service 706eca
      v |= 0xdeadbe00; /* keep them honest */
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RX_UByte:
Packit Service 706eca
      v &= 0xff;
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RX_SByte:
Packit Service 706eca
      v = sign_ext (v, 8);
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RX_Word: /* undefined extension */
Packit Service 706eca
      v |= 0xdead0000; /* keep them honest */
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RX_UWord:
Packit Service 706eca
      v &=  0xffff;
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RX_SWord:
Packit Service 706eca
      v = sign_ext (v, 16);
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RX_3Byte:
Packit Service 706eca
      v &= 0xffffff;
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RX_Long:
Packit Service 706eca
      break;
Packit Service 706eca
    }
Packit Service 706eca
Packit Service 706eca
  switch (o->type)
Packit Service 706eca
    {
Packit Service 706eca
    case RX_Operand_None:
Packit Service 706eca
      /* Opcodes like TST and CMP use this.  */
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RX_Operand_Immediate:	/* #addend */
Packit Service 706eca
    case RX_Operand_Condition:	/* eq, gtu, etc */
Packit Service 706eca
      rx_abort ();
Packit Service 706eca
Packit Service 706eca
    case RX_Operand_Register:	/* Rn */
Packit Service 706eca
      put_reg (o->reg, v);
Packit Service 706eca
      RLD (o->reg);
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RX_Operand_Predec:	/* [-Rn] */
Packit Service 706eca
      put_reg (o->reg, get_reg (o->reg) - size2bytes[o->size]);
Packit Service 706eca
      /* fall through */
Packit Service 706eca
    case RX_Operand_Postinc:	/* [Rn+] */
Packit Service 706eca
    case RX_Operand_Zero_Indirect:	/* [Rn + 0] */
Packit Service 706eca
    case RX_Operand_Indirect:	/* [Rn + addend] */
Packit Service 706eca
    case RX_Operand_TwoReg:	/* [Rn + scale * R2] */
Packit Service 706eca
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
      if (regs.m2m == M2M_BOTH)
Packit Service 706eca
	{
Packit Service 706eca
	  tprintf("dst memory stall\n");
Packit Service 706eca
	  regs.cycle_count ++;
Packit Service 706eca
#ifdef CYCLE_STATS
Packit Service 706eca
	  memory_stalls ++;
Packit Service 706eca
#endif
Packit Service 706eca
	  regs.m2m = 0;
Packit Service 706eca
	}
Packit Service 706eca
      memory_dest = 1;
Packit Service 706eca
#endif
Packit Service 706eca
Packit Service 706eca
      if (o->type == RX_Operand_TwoReg)
Packit Service 706eca
	addr = get_reg (o->reg) * size2bytes[rd->size] + get_reg (rd->op[2].reg);
Packit Service 706eca
      else
Packit Service 706eca
	addr = get_reg (o->reg) + o->addend;
Packit Service 706eca
Packit Service 706eca
      switch (o->size)
Packit Service 706eca
	{
Packit Service 706eca
	default:
Packit Service 706eca
	case RX_AnySize:
Packit Service 706eca
	  rx_abort ();
Packit Service 706eca
Packit Service 706eca
	case RX_Byte: /* undefined extension */
Packit Service 706eca
	case RX_UByte:
Packit Service 706eca
	case RX_SByte:
Packit Service 706eca
	  mem_put_qi (addr, v);
Packit Service 706eca
	  break;
Packit Service 706eca
Packit Service 706eca
	case RX_Word: /* undefined extension */
Packit Service 706eca
	case RX_UWord:
Packit Service 706eca
	case RX_SWord:
Packit Service 706eca
	  mem_put_hi (addr, v);
Packit Service 706eca
	  break;
Packit Service 706eca
Packit Service 706eca
	case RX_3Byte:
Packit Service 706eca
	  mem_put_psi (addr, v);
Packit Service 706eca
	  break;
Packit Service 706eca
Packit Service 706eca
	case RX_Long:
Packit Service 706eca
	  mem_put_si (addr, v);
Packit Service 706eca
	  break;
Packit Service 706eca
	}
Packit Service 706eca
Packit Service 706eca
      if (o->type == RX_Operand_Postinc)
Packit Service 706eca
	put_reg (o->reg, get_reg (o->reg) + size2bytes[o->size]);
Packit Service 706eca
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RX_Operand_Flag:	/* [UIOSZC] */
Packit Service 706eca
      if (v)
Packit Service 706eca
	regs.r_psw |= (1 << o->reg);
Packit Service 706eca
      else
Packit Service 706eca
	regs.r_psw &= ~(1 << o->reg);
Packit Service 706eca
      break;
Packit Service 706eca
    }
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
#define PD(x) put_op (opcode, 0, x)
Packit Service 706eca
#define PS(x) put_op (opcode, 1, x)
Packit Service 706eca
#define PS2(x) put_op (opcode, 2, x)
Packit Service 706eca
#define GD() get_op (opcode, 0)
Packit Service 706eca
#define GS() get_op (opcode, 1)
Packit Service 706eca
#define GS2() get_op (opcode, 2)
Packit Service 706eca
#define DSZ() size2bytes[opcode->op[0].size]
Packit Service 706eca
#define SSZ() size2bytes[opcode->op[0].size]
Packit Service 706eca
#define S2SZ() size2bytes[opcode->op[0].size]
Packit Service 706eca
Packit Service 706eca
/* "Universal" sources.  */
Packit Service 706eca
#define US1() ((opcode->op[2].type == RX_Operand_None) ? GD() : GS())
Packit Service 706eca
#define US2() ((opcode->op[2].type == RX_Operand_None) ? GS() : GS2())
Packit Service 706eca
Packit Service 706eca
static void
Packit Service 706eca
push(int val)
Packit Service 706eca
{
Packit Service 706eca
  int rsp = get_reg (sp);
Packit Service 706eca
  rsp -= 4;
Packit Service 706eca
  put_reg (sp, rsp);
Packit Service 706eca
  mem_put_si (rsp, val);
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
/* Just like the above, but tag the memory as "pushed pc" so if anyone
Packit Service 706eca
   tries to write to it, it will cause an error.  */
Packit Service 706eca
static void
Packit Service 706eca
pushpc(int val)
Packit Service 706eca
{
Packit Service 706eca
  int rsp = get_reg (sp);
Packit Service 706eca
  rsp -= 4;
Packit Service 706eca
  put_reg (sp, rsp);
Packit Service 706eca
  mem_put_si (rsp, val);
Packit Service 706eca
  mem_set_content_range (rsp, rsp+3, MC_PUSHED_PC);
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
static int
Packit Service 706eca
pop()
Packit Service 706eca
{
Packit Service 706eca
  int rv;
Packit Service 706eca
  int rsp = get_reg (sp);
Packit Service 706eca
  rv = mem_get_si (rsp);
Packit Service 706eca
  rsp += 4;
Packit Service 706eca
  put_reg (sp, rsp);
Packit Service 706eca
  return rv;
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
static int
Packit Service 706eca
poppc()
Packit Service 706eca
{
Packit Service 706eca
  int rv;
Packit Service 706eca
  int rsp = get_reg (sp);
Packit Service 706eca
  if (mem_get_content_type (rsp) != MC_PUSHED_PC)
Packit Service 706eca
    execution_error (SIM_ERR_CORRUPT_STACK, rsp);
Packit Service 706eca
  rv = mem_get_si (rsp);
Packit Service 706eca
  mem_set_content_range (rsp, rsp+3, MC_UNINIT);
Packit Service 706eca
  rsp += 4;
Packit Service 706eca
  put_reg (sp, rsp);
Packit Service 706eca
  return rv;
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
#define MATH_OP(vop,c)				\
Packit Service 706eca
{ \
Packit Service 706eca
  umb = US2(); \
Packit Service 706eca
  uma = US1(); \
Packit Service 706eca
  ll = (unsigned long long) uma vop (unsigned long long) umb vop c; \
Packit Service 706eca
  tprintf ("0x%x " #vop " 0x%x " #vop " 0x%x = 0x%llx\n", uma, umb, c, ll); \
Packit Service 706eca
  ma = sign_ext (uma, DSZ() * 8);					\
Packit Service 706eca
  mb = sign_ext (umb, DSZ() * 8);					\
Packit Service 706eca
  sll = (long long) ma vop (long long) mb vop c; \
Packit Service 706eca
  tprintf ("%d " #vop " %d " #vop " %d = %lld\n", ma, mb, c, sll); \
Packit Service 706eca
  set_oszc (sll, DSZ(), (long long) ll > ((1 vop 1) ? (long long) b2mask[DSZ()] : (long long) -1)); \
Packit Service 706eca
  PD (sll); \
Packit Service 706eca
  E (1);    \
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
#define LOGIC_OP(vop) \
Packit Service 706eca
{ \
Packit Service 706eca
  mb = US2(); \
Packit Service 706eca
  ma = US1(); \
Packit Service 706eca
  v = ma vop mb; \
Packit Service 706eca
  tprintf("0x%x " #vop " 0x%x = 0x%x\n", ma, mb, v); \
Packit Service 706eca
  set_sz (v, DSZ()); \
Packit Service 706eca
  PD(v); \
Packit Service 706eca
  E (1); \
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
#define SHIFT_OP(val, type, count, OP, carry_mask)	\
Packit Service 706eca
{ \
Packit Service 706eca
  int i, c=0; \
Packit Service 706eca
  count = US2(); \
Packit Service 706eca
  val = (type)US1();				\
Packit Service 706eca
  tprintf("%lld " #OP " %d\n", val, count); \
Packit Service 706eca
  for (i = 0; i < count; i ++) \
Packit Service 706eca
    { \
Packit Service 706eca
      c = val & carry_mask; \
Packit Service 706eca
      val OP 1; \
Packit Service 706eca
    } \
Packit Service 706eca
  set_oszc (val, 4, c); \
Packit Service 706eca
  PD (val); \
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
typedef union {
Packit Service 706eca
  int i;
Packit Service 706eca
  float f;
Packit Service 706eca
} FloatInt;
Packit Service 706eca
Packit Service 706eca
static inline int
Packit Service 706eca
float2int (float f)
Packit Service 706eca
{
Packit Service 706eca
  FloatInt fi;
Packit Service 706eca
  fi.f = f;
Packit Service 706eca
  return fi.i;
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
static inline float
Packit Service 706eca
int2float (int i)
Packit Service 706eca
{
Packit Service 706eca
  FloatInt fi;
Packit Service 706eca
  fi.i = i;
Packit Service 706eca
  return fi.f;
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
static int
Packit Service 706eca
fop_fadd (fp_t s1, fp_t s2, fp_t *d)
Packit Service 706eca
{
Packit Service 706eca
  *d = rxfp_add (s1, s2);
Packit Service 706eca
  return 1;
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
static int
Packit Service 706eca
fop_fmul (fp_t s1, fp_t s2, fp_t *d)
Packit Service 706eca
{
Packit Service 706eca
  *d = rxfp_mul (s1, s2);
Packit Service 706eca
  return 1;
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
static int
Packit Service 706eca
fop_fdiv (fp_t s1, fp_t s2, fp_t *d)
Packit Service 706eca
{
Packit Service 706eca
  *d = rxfp_div (s1, s2);
Packit Service 706eca
  return 1;
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
static int
Packit Service 706eca
fop_fsub (fp_t s1, fp_t s2, fp_t *d)
Packit Service 706eca
{
Packit Service 706eca
  *d = rxfp_sub (s1, s2);
Packit Service 706eca
  return 1;
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
#define FPPENDING() (regs.r_fpsw & (FPSWBITS_CE | (FPSWBITS_FMASK & (regs.r_fpsw << FPSW_EFSH))))
Packit Service 706eca
#define FPCLEAR() regs.r_fpsw &= FPSWBITS_CLEAR
Packit Service 706eca
#define FPCHECK() \
Packit Service 706eca
  if (FPPENDING()) \
Packit Service 706eca
    return do_fp_exception (opcode_pc)
Packit Service 706eca
Packit Service 706eca
#define FLOAT_OP(func) \
Packit Service 706eca
{ \
Packit Service 706eca
  int do_store;   \
Packit Service 706eca
  fp_t fa, fb, fc; \
Packit Service 706eca
  FPCLEAR(); \
Packit Service 706eca
  fb = GS (); \
Packit Service 706eca
  fa = GD (); \
Packit Service 706eca
  do_store = fop_##func (fa, fb, &fc); \
Packit Service 706eca
  tprintf("%g " #func " %g = %g %08x\n", int2float(fa), int2float(fb), int2float(fc), fc); \
Packit Service 706eca
  FPCHECK(); \
Packit Service 706eca
  if (do_store) \
Packit Service 706eca
    PD (fc);	\
Packit Service 706eca
  mb = 0; \
Packit Service 706eca
  if ((fc & 0x80000000UL) != 0) \
Packit Service 706eca
    mb |= FLAGBIT_S; \
Packit Service 706eca
  if ((fc & 0x7fffffffUL) == 0)			\
Packit Service 706eca
    mb |= FLAGBIT_Z; \
Packit Service 706eca
  set_flags (FLAGBIT_S | FLAGBIT_Z, mb); \
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
#define carry (FLAG_C ? 1 : 0)
Packit Service 706eca
Packit Service 706eca
static struct {
Packit Service 706eca
  unsigned long vaddr;
Packit Service 706eca
  const char *str;
Packit Service 706eca
  int signal;
Packit Service 706eca
} exception_info[] = {
Packit Service 706eca
  { 0xFFFFFFD0UL, "priviledged opcode", SIGILL },
Packit Service 706eca
  { 0xFFFFFFD4UL, "access violation", SIGSEGV },
Packit Service 706eca
  { 0xFFFFFFDCUL, "undefined opcode", SIGILL },
Packit Service 706eca
  { 0xFFFFFFE4UL, "floating point", SIGFPE }
Packit Service 706eca
};
Packit Service 706eca
#define EX_PRIVILEDGED	0
Packit Service 706eca
#define EX_ACCESS	1
Packit Service 706eca
#define EX_UNDEFINED	2
Packit Service 706eca
#define EX_FLOATING	3
Packit Service 706eca
#define EXCEPTION(n)  \
Packit Service 706eca
  return generate_exception (n, opcode_pc)
Packit Service 706eca
Packit Service 706eca
#define PRIVILEDGED() \
Packit Service 706eca
  if (FLAG_PM) \
Packit Service 706eca
    EXCEPTION (EX_PRIVILEDGED)
Packit Service 706eca
Packit Service 706eca
static int
Packit Service 706eca
generate_exception (unsigned long type, SI opcode_pc)
Packit Service 706eca
{
Packit Service 706eca
  SI old_psw, old_pc, new_pc;
Packit Service 706eca
Packit Service 706eca
  new_pc = mem_get_si (exception_info[type].vaddr);
Packit Service 706eca
  /* 0x00020000 is the value used to initialise the known
Packit Service 706eca
     exception vectors (see rx.ld), but it is a reserved
Packit Service 706eca
     area of memory so do not try to access it, and if the
Packit Service 706eca
     value has not been changed by the program then the
Packit Service 706eca
     vector has not been installed.  */
Packit Service 706eca
  if (new_pc == 0 || new_pc == 0x00020000)
Packit Service 706eca
    {
Packit Service 706eca
      if (rx_in_gdb)
Packit Service 706eca
	return RX_MAKE_STOPPED (exception_info[type].signal);
Packit Service 706eca
Packit Service 706eca
      fprintf(stderr, "Unhandled %s exception at pc = %#lx\n",
Packit Service 706eca
	      exception_info[type].str, (unsigned long) opcode_pc);
Packit Service 706eca
      if (type == EX_FLOATING)
Packit Service 706eca
	{
Packit Service 706eca
	  int mask = FPPENDING ();
Packit Service 706eca
	  fprintf (stderr, "Pending FP exceptions:");
Packit Service 706eca
	  if (mask & FPSWBITS_FV)
Packit Service 706eca
	    fprintf(stderr, " Invalid");
Packit Service 706eca
	  if (mask & FPSWBITS_FO)
Packit Service 706eca
	    fprintf(stderr, " Overflow");
Packit Service 706eca
	  if (mask & FPSWBITS_FZ)
Packit Service 706eca
	    fprintf(stderr, " Division-by-zero");
Packit Service 706eca
	  if (mask & FPSWBITS_FU)
Packit Service 706eca
	    fprintf(stderr, " Underflow");
Packit Service 706eca
	  if (mask & FPSWBITS_FX)
Packit Service 706eca
	    fprintf(stderr, " Inexact");
Packit Service 706eca
	  if (mask & FPSWBITS_CE)
Packit Service 706eca
	    fprintf(stderr, " Unimplemented");
Packit Service 706eca
	  fprintf(stderr, "\n");
Packit Service 706eca
	}
Packit Service 706eca
      return RX_MAKE_EXITED (1);
Packit Service 706eca
    }
Packit Service 706eca
Packit Service 706eca
  tprintf ("Triggering %s exception\n", exception_info[type].str);
Packit Service 706eca
Packit Service 706eca
  old_psw = regs.r_psw;
Packit Service 706eca
  regs.r_psw &= ~ (FLAGBIT_I | FLAGBIT_U | FLAGBIT_PM);
Packit Service 706eca
  old_pc = opcode_pc;
Packit Service 706eca
  regs.r_pc = new_pc;
Packit Service 706eca
  pushpc (old_psw);
Packit Service 706eca
  pushpc (old_pc);
Packit Service 706eca
  return RX_MAKE_STEPPED ();
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
void
Packit Service 706eca
generate_access_exception (void)
Packit Service 706eca
{
Packit Service 706eca
  int rv;
Packit Service 706eca
Packit Service 706eca
  rv = generate_exception (EX_ACCESS, regs.r_pc);
Packit Service 706eca
  if (RX_EXITED (rv))
Packit Service 706eca
    longjmp (decode_jmp_buf, rv);
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
static int
Packit Service 706eca
do_fp_exception (unsigned long opcode_pc)
Packit Service 706eca
{
Packit Service 706eca
  while (FPPENDING())
Packit Service 706eca
    EXCEPTION (EX_FLOATING);
Packit Service 706eca
  return RX_MAKE_STEPPED ();
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
static int
Packit Service 706eca
op_is_memory (const RX_Opcode_Decoded *rd, int i)
Packit Service 706eca
{
Packit Service 706eca
  switch (rd->op[i].type)
Packit Service 706eca
    {
Packit Service 706eca
    case RX_Operand_Predec:
Packit Service 706eca
    case RX_Operand_Postinc:
Packit Service 706eca
    case RX_Operand_Indirect:
Packit Service 706eca
      return 1;
Packit Service 706eca
    default:
Packit Service 706eca
      return 0;
Packit Service 706eca
    }
Packit Service 706eca
}
Packit Service 706eca
#define OM(i) op_is_memory (opcode, i)
Packit Service 706eca
Packit Service 706eca
#define DO_RETURN(x) { longjmp (decode_jmp_buf, x); }
Packit Service 706eca
Packit Service 706eca
int
Packit Service 706eca
decode_opcode ()
Packit Service 706eca
{
Packit Service 706eca
  unsigned int uma=0, umb=0;
Packit Service 706eca
  int ma=0, mb=0;
Packit Service 706eca
  int opcode_size, v;
Packit Service 706eca
  unsigned long long ll;
Packit Service 706eca
  long long sll;
Packit Service 706eca
  unsigned long opcode_pc;
Packit Service 706eca
  RX_Data rx_data;
Packit Service 706eca
  const RX_Opcode_Decoded *opcode;
Packit Service 706eca
#ifdef CYCLE_STATS
Packit Service 706eca
  unsigned long long prev_cycle_count;
Packit Service 706eca
#endif
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
  unsigned int tx;
Packit Service 706eca
#endif
Packit Service 706eca
Packit Service 706eca
#ifdef CYCLE_STATS
Packit Service 706eca
  prev_cycle_count = regs.cycle_count;
Packit Service 706eca
#endif
Packit Service 706eca
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
  memory_source = 0;
Packit Service 706eca
  memory_dest = 0;
Packit Service 706eca
#endif
Packit Service 706eca
Packit Service 706eca
  rx_cycles ++;
Packit Service 706eca
Packit Service 706eca
  maybe_get_mem_page (regs.r_pc);
Packit Service 706eca
Packit Service 706eca
  opcode_pc = regs.r_pc;
Packit Service 706eca
Packit Service 706eca
  /* Note that we don't word-swap this point, there's no point.  */
Packit Service 706eca
  if (decode_cache_base[opcode_pc] == NULL)
Packit Service 706eca
    {
Packit Service 706eca
      RX_Opcode_Decoded *opcode_w;
Packit Service 706eca
      rx_data.dpc = opcode_pc;
Packit Service 706eca
      opcode_w = decode_cache_base[opcode_pc] = calloc (1, sizeof (RX_Opcode_Decoded));
Packit Service 706eca
      opcode_size = rx_decode_opcode (opcode_pc, opcode_w,
Packit Service 706eca
				      rx_get_byte, &rx_data);
Packit Service 706eca
      opcode = opcode_w;
Packit Service 706eca
    }
Packit Service 706eca
  else
Packit Service 706eca
    {
Packit Service 706eca
      opcode = decode_cache_base[opcode_pc];
Packit Service 706eca
      opcode_size = opcode->n_bytes;
Packit Service 706eca
    }
Packit Service 706eca
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
  if (branch_alignment_penalty)
Packit Service 706eca
    {
Packit Service 706eca
      if ((regs.r_pc ^ (regs.r_pc + opcode_size - 1)) & ~7)
Packit Service 706eca
	{
Packit Service 706eca
	  tprintf("1 cycle branch alignment penalty\n");
Packit Service 706eca
	  cycles (branch_alignment_penalty);
Packit Service 706eca
#ifdef CYCLE_STATS
Packit Service 706eca
	  branch_alignment_stalls ++;
Packit Service 706eca
#endif
Packit Service 706eca
	}
Packit Service 706eca
      branch_alignment_penalty = 0;
Packit Service 706eca
    }
Packit Service 706eca
#endif
Packit Service 706eca
Packit Service 706eca
  regs.r_pc += opcode_size;
Packit Service 706eca
Packit Service 706eca
  rx_flagmask = opcode->flags_s;
Packit Service 706eca
  rx_flagand = ~(int)opcode->flags_0;
Packit Service 706eca
  rx_flagor = opcode->flags_1;
Packit Service 706eca
Packit Service 706eca
  switch (opcode->id)
Packit Service 706eca
    {
Packit Service 706eca
    case RXO_abs:
Packit Service 706eca
      sll = GS ();
Packit Service 706eca
      tprintf("|%lld| = ", sll);
Packit Service 706eca
      if (sll < 0)
Packit Service 706eca
	sll = -sll;
Packit Service 706eca
      tprintf("%lld\n", sll);
Packit Service 706eca
      PD (sll);
Packit Service 706eca
      set_osz (sll, 4);
Packit Service 706eca
      E (1);
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_adc:
Packit Service 706eca
      MATH_OP (+,carry);
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_add:
Packit Service 706eca
      MATH_OP (+,0);
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_and:
Packit Service 706eca
      LOGIC_OP (&);
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_bclr:
Packit Service 706eca
      ma = GD ();
Packit Service 706eca
      mb = GS ();
Packit Service 706eca
      if (opcode->op[0].type == RX_Operand_Register)
Packit Service 706eca
	mb &= 0x1f;
Packit Service 706eca
      else
Packit Service 706eca
	mb &= 0x07;
Packit Service 706eca
      ma &= ~(1 << mb);
Packit Service 706eca
      PD (ma);
Packit Service 706eca
      EBIT;
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_bmcc:
Packit Service 706eca
      ma = GD ();
Packit Service 706eca
      mb = GS ();
Packit Service 706eca
      if (opcode->op[0].type == RX_Operand_Register)
Packit Service 706eca
	mb &= 0x1f;
Packit Service 706eca
      else
Packit Service 706eca
	mb &= 0x07;
Packit Service 706eca
      if (GS2 ())
Packit Service 706eca
	ma |= (1 << mb);
Packit Service 706eca
      else
Packit Service 706eca
	ma &= ~(1 << mb);
Packit Service 706eca
      PD (ma);
Packit Service 706eca
      EBIT;
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_bnot:
Packit Service 706eca
      ma = GD ();
Packit Service 706eca
      mb = GS ();
Packit Service 706eca
      if (opcode->op[0].type == RX_Operand_Register)
Packit Service 706eca
	mb &= 0x1f;
Packit Service 706eca
      else
Packit Service 706eca
	mb &= 0x07;
Packit Service 706eca
      ma ^= (1 << mb);
Packit Service 706eca
      PD (ma);
Packit Service 706eca
      EBIT;
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_branch:
Packit Service 706eca
      if (opcode->op[1].type == RX_Operand_None || GS())
Packit Service 706eca
	{
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
	  SI old_pc = regs.r_pc;
Packit Service 706eca
	  int delta;
Packit Service 706eca
#endif
Packit Service 706eca
	  regs.r_pc = GD();
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
	  delta = regs.r_pc - old_pc;
Packit Service 706eca
	  if (delta >= 0 && delta < 16
Packit Service 706eca
	      && opcode_size > 1)
Packit Service 706eca
	    {
Packit Service 706eca
	      tprintf("near forward branch bonus\n");
Packit Service 706eca
	      cycles (2);
Packit Service 706eca
	    }
Packit Service 706eca
	  else
Packit Service 706eca
	    {
Packit Service 706eca
	      cycles (3);
Packit Service 706eca
	      branch_alignment_penalty = 1;
Packit Service 706eca
	    }
Packit Service 706eca
#ifdef CYCLE_STATS
Packit Service 706eca
	  branch_stalls ++;
Packit Service 706eca
#endif
Packit Service 706eca
#endif
Packit Service 706eca
	}
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
      else
Packit Service 706eca
	cycles (1);
Packit Service 706eca
#endif
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_branchrel:
Packit Service 706eca
      if (opcode->op[1].type == RX_Operand_None || GS())
Packit Service 706eca
	{
Packit Service 706eca
	  int delta = GD();
Packit Service 706eca
	  regs.r_pc = opcode_pc + delta;
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
	  /* Note: specs say 3, chip says 2.  */
Packit Service 706eca
	  if (delta >= 0 && delta < 16
Packit Service 706eca
	      && opcode_size > 1)
Packit Service 706eca
	    {
Packit Service 706eca
	      tprintf("near forward branch bonus\n");
Packit Service 706eca
	      cycles (2);
Packit Service 706eca
	    }
Packit Service 706eca
	  else
Packit Service 706eca
	    {
Packit Service 706eca
	      cycles (3);
Packit Service 706eca
	      branch_alignment_penalty = 1;
Packit Service 706eca
	    }
Packit Service 706eca
#ifdef CYCLE_STATS
Packit Service 706eca
	  branch_stalls ++;
Packit Service 706eca
#endif
Packit Service 706eca
#endif
Packit Service 706eca
	}
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
      else
Packit Service 706eca
	cycles (1);
Packit Service 706eca
#endif
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_brk:
Packit Service 706eca
      {
Packit Service 706eca
	int old_psw = regs.r_psw;
Packit Service 706eca
	if (rx_in_gdb)
Packit Service 706eca
	  DO_RETURN (RX_MAKE_HIT_BREAK ());
Packit Service 706eca
	if (regs.r_intb == 0)
Packit Service 706eca
	  {
Packit Service 706eca
	    tprintf("BREAK hit, no vector table.\n");
Packit Service 706eca
	    DO_RETURN (RX_MAKE_EXITED(1));
Packit Service 706eca
	  }
Packit Service 706eca
	regs.r_psw &= ~(FLAGBIT_I | FLAGBIT_U | FLAGBIT_PM);
Packit Service 706eca
	pushpc (old_psw);
Packit Service 706eca
	pushpc (regs.r_pc);
Packit Service 706eca
	regs.r_pc = mem_get_si (regs.r_intb);
Packit Service 706eca
	cycles(6);
Packit Service 706eca
      }
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_bset:
Packit Service 706eca
      ma = GD ();
Packit Service 706eca
      mb = GS ();
Packit Service 706eca
      if (opcode->op[0].type == RX_Operand_Register)
Packit Service 706eca
	mb &= 0x1f;
Packit Service 706eca
      else
Packit Service 706eca
	mb &= 0x07;
Packit Service 706eca
      ma |= (1 << mb);
Packit Service 706eca
      PD (ma);
Packit Service 706eca
      EBIT;
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_btst:
Packit Service 706eca
      ma = GS ();
Packit Service 706eca
      mb = GS2 ();
Packit Service 706eca
      if (opcode->op[1].type == RX_Operand_Register)
Packit Service 706eca
	mb &= 0x1f;
Packit Service 706eca
      else
Packit Service 706eca
	mb &= 0x07;
Packit Service 706eca
      umb = ma & (1 << mb);
Packit Service 706eca
      set_zc (! umb, umb);
Packit Service 706eca
      EBIT;
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_clrpsw:
Packit Service 706eca
      v = 1 << opcode->op[0].reg;
Packit Service 706eca
      if (FLAG_PM
Packit Service 706eca
	  && (v == FLAGBIT_I
Packit Service 706eca
	      || v == FLAGBIT_U))
Packit Service 706eca
	break;
Packit Service 706eca
      regs.r_psw &= ~v;
Packit Service 706eca
      cycles (1);
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_div: /* d = d / s */
Packit Service 706eca
      ma = GS();
Packit Service 706eca
      mb = GD();
Packit Service 706eca
      tprintf("%d / %d = ", mb, ma);
Packit Service 706eca
      if (ma == 0 || (ma == -1 && (unsigned int) mb == 0x80000000))
Packit Service 706eca
	{
Packit Service 706eca
	  tprintf("#NAN\n");
Packit Service 706eca
	  set_flags (FLAGBIT_O, FLAGBIT_O);
Packit Service 706eca
	  cycles (3);
Packit Service 706eca
	}
Packit Service 706eca
      else
Packit Service 706eca
	{
Packit Service 706eca
	  v = mb/ma;
Packit Service 706eca
	  tprintf("%d\n", v);
Packit Service 706eca
	  set_flags (FLAGBIT_O, 0);
Packit Service 706eca
	  PD (v);
Packit Service 706eca
	  div_cycles (mb, ma);
Packit Service 706eca
	}
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_divu: /* d = d / s */
Packit Service 706eca
      uma = GS();
Packit Service 706eca
      umb = GD();
Packit Service 706eca
      tprintf("%u / %u = ", umb, uma);
Packit Service 706eca
      if (uma == 0)
Packit Service 706eca
	{
Packit Service 706eca
	  tprintf("#NAN\n");
Packit Service 706eca
	  set_flags (FLAGBIT_O, FLAGBIT_O);
Packit Service 706eca
	  cycles (2);
Packit Service 706eca
	}
Packit Service 706eca
      else
Packit Service 706eca
	{
Packit Service 706eca
	  v = umb / uma;
Packit Service 706eca
	  tprintf("%u\n", v);
Packit Service 706eca
	  set_flags (FLAGBIT_O, 0);
Packit Service 706eca
	  PD (v);
Packit Service 706eca
	  divu_cycles (umb, uma);
Packit Service 706eca
	}
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_emul:
Packit Service 706eca
      ma = GD ();
Packit Service 706eca
      mb = GS ();
Packit Service 706eca
      sll = (long long)ma * (long long)mb;
Packit Service 706eca
      tprintf("%d * %d = %lld\n", ma, mb, sll);
Packit Service 706eca
      put_reg (opcode->op[0].reg, sll);
Packit Service 706eca
      put_reg (opcode->op[0].reg + 1, sll >> 32);
Packit Service 706eca
      E2;
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_emulu:
Packit Service 706eca
      uma = GD ();
Packit Service 706eca
      umb = GS ();
Packit Service 706eca
      ll = (long long)uma * (long long)umb;
Packit Service 706eca
      tprintf("%#x * %#x = %#llx\n", uma, umb, ll);
Packit Service 706eca
      put_reg (opcode->op[0].reg, ll);
Packit Service 706eca
      put_reg (opcode->op[0].reg + 1, ll >> 32);
Packit Service 706eca
      E2;
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_fadd:
Packit Service 706eca
      FLOAT_OP (fadd);
Packit Service 706eca
      E (4);
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_fcmp:
Packit Service 706eca
      ma = GD();
Packit Service 706eca
      mb = GS();
Packit Service 706eca
      FPCLEAR ();
Packit Service 706eca
      rxfp_cmp (ma, mb);
Packit Service 706eca
      FPCHECK ();
Packit Service 706eca
      E (1);
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_fdiv:
Packit Service 706eca
      FLOAT_OP (fdiv);
Packit Service 706eca
      E (16);
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_fmul:
Packit Service 706eca
      FLOAT_OP (fmul);
Packit Service 706eca
      E (3);
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_rtfi:
Packit Service 706eca
      PRIVILEDGED ();
Packit Service 706eca
      regs.r_psw = regs.r_bpsw;
Packit Service 706eca
      regs.r_pc = regs.r_bpc;
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
      regs.fast_return = 0;
Packit Service 706eca
      cycles(3);
Packit Service 706eca
#endif
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_fsub:
Packit Service 706eca
      FLOAT_OP (fsub);
Packit Service 706eca
      E (4);
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_ftoi:
Packit Service 706eca
      ma = GS ();
Packit Service 706eca
      FPCLEAR ();
Packit Service 706eca
      mb = rxfp_ftoi (ma, FPRM_ZERO);
Packit Service 706eca
      FPCHECK ();
Packit Service 706eca
      PD (mb);
Packit Service 706eca
      tprintf("(int) %g = %d\n", int2float(ma), mb);
Packit Service 706eca
      set_sz (mb, 4);
Packit Service 706eca
      E (2);
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_int:
Packit Service 706eca
      v = GS ();
Packit Service 706eca
      if (v == 255)
Packit Service 706eca
	{
Packit Service 706eca
	  int rc = rx_syscall (regs.r[5]);
Packit Service 706eca
	  if (! RX_STEPPED (rc))
Packit Service 706eca
	    DO_RETURN (rc);
Packit Service 706eca
	}
Packit Service 706eca
      else
Packit Service 706eca
	{
Packit Service 706eca
	  int old_psw = regs.r_psw;
Packit Service 706eca
	  regs.r_psw &= ~(FLAGBIT_I | FLAGBIT_U | FLAGBIT_PM);
Packit Service 706eca
	  pushpc (old_psw);
Packit Service 706eca
	  pushpc (regs.r_pc);
Packit Service 706eca
	  regs.r_pc = mem_get_si (regs.r_intb + 4 * v);
Packit Service 706eca
	}
Packit Service 706eca
      cycles (6);
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_itof:
Packit Service 706eca
      ma = GS ();
Packit Service 706eca
      FPCLEAR ();
Packit Service 706eca
      mb = rxfp_itof (ma, regs.r_fpsw);
Packit Service 706eca
      FPCHECK ();
Packit Service 706eca
      tprintf("(float) %d = %x\n", ma, mb);
Packit Service 706eca
      PD (mb);
Packit Service 706eca
      set_sz (ma, 4);
Packit Service 706eca
      E (2);
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_jsr:
Packit Service 706eca
    case RXO_jsrrel:
Packit Service 706eca
      {
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
	int delta;
Packit Service 706eca
	regs.m2m = 0;
Packit Service 706eca
#endif
Packit Service 706eca
	v = GD ();
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
	regs.link_register = regs.r_pc;
Packit Service 706eca
#endif
Packit Service 706eca
	pushpc (get_reg (pc));
Packit Service 706eca
	if (opcode->id == RXO_jsrrel)
Packit Service 706eca
	  v += regs.r_pc;
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
	delta = v - regs.r_pc;
Packit Service 706eca
#endif
Packit Service 706eca
	put_reg (pc, v);
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
	/* Note: docs say 3, chip says 2 */
Packit Service 706eca
	if (delta >= 0 && delta < 16)
Packit Service 706eca
	  {
Packit Service 706eca
	    tprintf ("near forward jsr bonus\n");
Packit Service 706eca
	    cycles (2);
Packit Service 706eca
	  }
Packit Service 706eca
	else
Packit Service 706eca
	  {
Packit Service 706eca
	    branch_alignment_penalty = 1;
Packit Service 706eca
	    cycles (3);
Packit Service 706eca
	  }
Packit Service 706eca
	regs.fast_return = 1;
Packit Service 706eca
#endif
Packit Service 706eca
      }
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_machi:
Packit Service 706eca
      ll = (long long)(signed short)(GS() >> 16) * (long long)(signed short)(GS2 () >> 16);
Packit Service 706eca
      ll <<= 16;
Packit Service 706eca
      put_reg64 (acc64, ll + regs.r_acc);
Packit Service 706eca
      E1;
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_maclo:
Packit Service 706eca
      ll = (long long)(signed short)(GS()) * (long long)(signed short)(GS2 ());
Packit Service 706eca
      ll <<= 16;
Packit Service 706eca
      put_reg64 (acc64, ll + regs.r_acc);
Packit Service 706eca
      E1;
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_max:
Packit Service 706eca
      mb = GS();
Packit Service 706eca
      ma = GD();
Packit Service 706eca
      if (ma > mb)
Packit Service 706eca
	PD (ma);
Packit Service 706eca
      else
Packit Service 706eca
	PD (mb);
Packit Service 706eca
      E (1);
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_min:
Packit Service 706eca
      mb = GS();
Packit Service 706eca
      ma = GD();
Packit Service 706eca
      if (ma < mb)
Packit Service 706eca
	PD (ma);
Packit Service 706eca
      else
Packit Service 706eca
	PD (mb);
Packit Service 706eca
      E (1);
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_mov:
Packit Service 706eca
      v = GS ();
Packit Service 706eca
Packit Service 706eca
      if (opcode->op[1].type == RX_Operand_Register
Packit Service 706eca
	  && opcode->op[1].reg == 17 /* PC */)
Packit Service 706eca
	{
Packit Service 706eca
	  /* Special case.  We want the address of the insn, not the
Packit Service 706eca
	     address of the next insn.  */
Packit Service 706eca
	  v = opcode_pc;
Packit Service 706eca
	}
Packit Service 706eca
Packit Service 706eca
      if (opcode->op[0].type == RX_Operand_Register
Packit Service 706eca
	  && opcode->op[0].reg == 16 /* PSW */)
Packit Service 706eca
	{
Packit Service 706eca
	  /* Special case, LDC and POPC can't ever modify PM.  */
Packit Service 706eca
	  int pm = regs.r_psw & FLAGBIT_PM;
Packit Service 706eca
	  v &= ~ FLAGBIT_PM;
Packit Service 706eca
	  v |= pm;
Packit Service 706eca
	  if (pm)
Packit Service 706eca
	    {
Packit Service 706eca
	      v &= ~ (FLAGBIT_I | FLAGBIT_U | FLAGBITS_IPL);
Packit Service 706eca
	      v |= pm;
Packit Service 706eca
	    }
Packit Service 706eca
	}
Packit Service 706eca
      if (FLAG_PM)
Packit Service 706eca
	{
Packit Service 706eca
	  /* various things can't be changed in user mode.  */
Packit Service 706eca
	  if (opcode->op[0].type == RX_Operand_Register)
Packit Service 706eca
	    if (opcode->op[0].reg == 32)
Packit Service 706eca
	      {
Packit Service 706eca
		v &= ~ (FLAGBIT_I | FLAGBIT_U | FLAGBITS_IPL);
Packit Service 706eca
		v |= regs.r_psw & (FLAGBIT_I | FLAGBIT_U | FLAGBITS_IPL);
Packit Service 706eca
	      }
Packit Service 706eca
	  if (opcode->op[0].reg == 34 /* ISP */
Packit Service 706eca
	      || opcode->op[0].reg == 37 /* BPSW */
Packit Service 706eca
	      || opcode->op[0].reg == 39 /* INTB */
Packit Service 706eca
	      || opcode->op[0].reg == 38 /* VCT */)
Packit Service 706eca
	    /* These are ignored.  */
Packit Service 706eca
	    break;
Packit Service 706eca
	}
Packit Service 706eca
      if (OM(0) && OM(1))
Packit Service 706eca
	cycles (2);
Packit Service 706eca
      else
Packit Service 706eca
	cycles (1);
Packit Service 706eca
Packit Service 706eca
      PD (v);
Packit Service 706eca
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
      if ((opcode->op[0].type == RX_Operand_Predec
Packit Service 706eca
	   && opcode->op[1].type == RX_Operand_Register)
Packit Service 706eca
	  || (opcode->op[0].type == RX_Operand_Postinc
Packit Service 706eca
	      && opcode->op[1].type == RX_Operand_Register))
Packit Service 706eca
	{
Packit Service 706eca
	  /* Special case: push reg doesn't cause a memory stall.  */
Packit Service 706eca
	  memory_dest = 0;
Packit Service 706eca
	  tprintf("push special case\n");
Packit Service 706eca
	}
Packit Service 706eca
#endif
Packit Service 706eca
Packit Service 706eca
      set_sz (v, DSZ());
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_movbi:
Packit Service 706eca
      PD (GS ());
Packit Service 706eca
      cycles (1);
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_movbir:
Packit Service 706eca
      PS (GD ());
Packit Service 706eca
      cycles (1);
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_mul:
Packit Service 706eca
      v = US2 ();
Packit Service 706eca
      ll = (unsigned long long) US1() * (unsigned long long) v;
Packit Service 706eca
      PD(ll);
Packit Service 706eca
      E (1);
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_mulhi:
Packit Service 706eca
      v = GS2 ();
Packit Service 706eca
      ll = (long long)(signed short)(GS() >> 16) * (long long)(signed short)(v >> 16);
Packit Service 706eca
      ll <<= 16;
Packit Service 706eca
      put_reg64 (acc64, ll);
Packit Service 706eca
      E1;
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_mullo:
Packit Service 706eca
      v = GS2 ();
Packit Service 706eca
      ll = (long long)(signed short)(GS()) * (long long)(signed short)(v);
Packit Service 706eca
      ll <<= 16;
Packit Service 706eca
      put_reg64 (acc64, ll);
Packit Service 706eca
      E1;
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_mvfachi:
Packit Service 706eca
      PD (get_reg (acchi));
Packit Service 706eca
      E1;
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_mvfaclo:
Packit Service 706eca
      PD (get_reg (acclo));
Packit Service 706eca
      E1;
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_mvfacmi:
Packit Service 706eca
      PD (get_reg (accmi));
Packit Service 706eca
      E1;
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_mvtachi:
Packit Service 706eca
      put_reg (acchi, GS ());
Packit Service 706eca
      E1;
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_mvtaclo:
Packit Service 706eca
      put_reg (acclo, GS ());
Packit Service 706eca
      E1;
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_mvtipl:
Packit Service 706eca
      regs.r_psw &= ~ FLAGBITS_IPL;
Packit Service 706eca
      regs.r_psw |= (GS () << FLAGSHIFT_IPL) & FLAGBITS_IPL;
Packit Service 706eca
      E1;
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_nop:
Packit Service 706eca
    case RXO_nop2:
Packit Service 706eca
    case RXO_nop3:
Packit Service 706eca
    case RXO_nop4:
Packit Service 706eca
    case RXO_nop5:
Packit Service 706eca
    case RXO_nop6:
Packit Service 706eca
    case RXO_nop7:
Packit Service 706eca
      E1;
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_or:
Packit Service 706eca
      LOGIC_OP (|);
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_popm:
Packit Service 706eca
      /* POPM cannot pop R0 (sp).  */
Packit Service 706eca
      if (opcode->op[1].reg == 0 || opcode->op[2].reg == 0)
Packit Service 706eca
	EXCEPTION (EX_UNDEFINED);
Packit Service 706eca
      if (opcode->op[1].reg >= opcode->op[2].reg)
Packit Service 706eca
	{
Packit Service 706eca
	  regs.r_pc = opcode_pc;
Packit Service 706eca
	  DO_RETURN (RX_MAKE_STOPPED (SIGILL));
Packit Service 706eca
	}
Packit Service 706eca
      for (v = opcode->op[1].reg; v <= opcode->op[2].reg; v++)
Packit Service 706eca
	{
Packit Service 706eca
	  cycles (1);
Packit Service 706eca
	  RLD (v);
Packit Service 706eca
	  put_reg (v, pop ());
Packit Service 706eca
	}
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_pushm:
Packit Service 706eca
      /* PUSHM cannot push R0 (sp).  */
Packit Service 706eca
      if (opcode->op[1].reg == 0 || opcode->op[2].reg == 0)
Packit Service 706eca
	EXCEPTION (EX_UNDEFINED);
Packit Service 706eca
      if (opcode->op[1].reg >= opcode->op[2].reg)
Packit Service 706eca
	{
Packit Service 706eca
	  regs.r_pc = opcode_pc;
Packit Service 706eca
	  return RX_MAKE_STOPPED (SIGILL);
Packit Service 706eca
	}
Packit Service 706eca
      for (v = opcode->op[2].reg; v >= opcode->op[1].reg; v--)
Packit Service 706eca
	{
Packit Service 706eca
	  RL (v);
Packit Service 706eca
	  push (get_reg (v));
Packit Service 706eca
	}
Packit Service 706eca
      cycles (opcode->op[2].reg - opcode->op[1].reg + 1);
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_racw:
Packit Service 706eca
      ll = get_reg64 (acc64) << GS ();
Packit Service 706eca
      ll += 0x80000000ULL;
Packit Service 706eca
      if ((signed long long)ll > (signed long long)0x00007fff00000000ULL)
Packit Service 706eca
	ll = 0x00007fff00000000ULL;
Packit Service 706eca
      else if ((signed long long)ll < (signed long long)0xffff800000000000ULL)
Packit Service 706eca
	ll = 0xffff800000000000ULL;
Packit Service 706eca
      else
Packit Service 706eca
	ll &= 0xffffffff00000000ULL;
Packit Service 706eca
      put_reg64 (acc64, ll);
Packit Service 706eca
      E1;
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_rte:
Packit Service 706eca
      PRIVILEDGED ();
Packit Service 706eca
      regs.r_pc = poppc ();
Packit Service 706eca
      regs.r_psw = poppc ();
Packit Service 706eca
      if (FLAG_PM)
Packit Service 706eca
	regs.r_psw |= FLAGBIT_U;
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
      regs.fast_return = 0;
Packit Service 706eca
      cycles (6);
Packit Service 706eca
#endif
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_revl:
Packit Service 706eca
      uma = GS ();
Packit Service 706eca
      umb = (((uma >> 24) & 0xff)
Packit Service 706eca
	     | ((uma >> 8) & 0xff00)
Packit Service 706eca
	     | ((uma << 8) & 0xff0000)
Packit Service 706eca
	     | ((uma << 24) & 0xff000000UL));
Packit Service 706eca
      PD (umb);
Packit Service 706eca
      E1;
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_revw:
Packit Service 706eca
      uma = GS ();
Packit Service 706eca
      umb = (((uma >> 8) & 0x00ff00ff)
Packit Service 706eca
	     | ((uma << 8) & 0xff00ff00UL));
Packit Service 706eca
      PD (umb);
Packit Service 706eca
      E1;
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_rmpa:
Packit Service 706eca
      RL(4);
Packit Service 706eca
      RL(5);
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
      tx = regs.r[3];
Packit Service 706eca
#endif
Packit Service 706eca
Packit Service 706eca
      while (regs.r[3] != 0)
Packit Service 706eca
	{
Packit Service 706eca
	  long long tmp;
Packit Service 706eca
Packit Service 706eca
	  switch (opcode->size)
Packit Service 706eca
	    {
Packit Service 706eca
	    case RX_Long:
Packit Service 706eca
	      ma = mem_get_si (regs.r[1]);
Packit Service 706eca
	      mb = mem_get_si (regs.r[2]);
Packit Service 706eca
	      regs.r[1] += 4;
Packit Service 706eca
	      regs.r[2] += 4;
Packit Service 706eca
	      break;
Packit Service 706eca
	    case RX_Word:
Packit Service 706eca
	      ma = sign_ext (mem_get_hi (regs.r[1]), 16);
Packit Service 706eca
	      mb = sign_ext (mem_get_hi (regs.r[2]), 16);
Packit Service 706eca
	      regs.r[1] += 2;
Packit Service 706eca
	      regs.r[2] += 2;
Packit Service 706eca
	      break;
Packit Service 706eca
	    case RX_Byte:
Packit Service 706eca
	      ma = sign_ext (mem_get_qi (regs.r[1]), 8);
Packit Service 706eca
	      mb = sign_ext (mem_get_qi (regs.r[2]), 8);
Packit Service 706eca
	      regs.r[1] += 1;
Packit Service 706eca
	      regs.r[2] += 1;
Packit Service 706eca
	      break;
Packit Service 706eca
	    default:
Packit Service 706eca
	      abort ();
Packit Service 706eca
	    }
Packit Service 706eca
	  /* We do the multiply as a signed value.  */
Packit Service 706eca
	  sll = (long long)ma * (long long)mb;
Packit Service 706eca
	  tprintf("        %016llx = %d * %d\n", sll, ma, mb);
Packit Service 706eca
	  /* but we do the sum as unsigned, while sign extending the operands.  */
Packit Service 706eca
	  tmp = regs.r[4] + (sll & 0xffffffffUL);
Packit Service 706eca
	  regs.r[4] = tmp & 0xffffffffUL;
Packit Service 706eca
	  tmp >>= 32;
Packit Service 706eca
	  sll >>= 32;
Packit Service 706eca
	  tmp += regs.r[5] + (sll & 0xffffffffUL);
Packit Service 706eca
	  regs.r[5] = tmp & 0xffffffffUL;
Packit Service 706eca
	  tmp >>= 32;
Packit Service 706eca
	  sll >>= 32;
Packit Service 706eca
	  tmp += regs.r[6] + (sll & 0xffffffffUL);
Packit Service 706eca
	  regs.r[6] = tmp & 0xffffffffUL;
Packit Service 706eca
	  tprintf("%08lx\033[36m%08lx\033[0m%08lx\n",
Packit Service 706eca
		  (unsigned long) regs.r[6],
Packit Service 706eca
		  (unsigned long) regs.r[5],
Packit Service 706eca
		  (unsigned long) regs.r[4]);
Packit Service 706eca
Packit Service 706eca
	  regs.r[3] --;
Packit Service 706eca
	}
Packit Service 706eca
      if (regs.r[6] & 0x00008000)
Packit Service 706eca
	regs.r[6] |= 0xffff0000UL;
Packit Service 706eca
      else
Packit Service 706eca
	regs.r[6] &= 0x0000ffff;
Packit Service 706eca
      ma = (regs.r[6] & 0x80000000UL) ? FLAGBIT_S : 0;
Packit Service 706eca
      if (regs.r[6] != 0 && regs.r[6] != 0xffffffffUL)
Packit Service 706eca
	set_flags (FLAGBIT_O|FLAGBIT_S, ma | FLAGBIT_O);
Packit Service 706eca
      else
Packit Service 706eca
	set_flags (FLAGBIT_O|FLAGBIT_S, ma);
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
      switch (opcode->size)
Packit Service 706eca
	{
Packit Service 706eca
	case RX_Long:
Packit Service 706eca
	  cycles (6 + 4 * tx);
Packit Service 706eca
	  break;
Packit Service 706eca
	case RX_Word:
Packit Service 706eca
	  cycles (6 + 5 * (tx / 2) + 4 * (tx % 2));
Packit Service 706eca
	  break;
Packit Service 706eca
	case RX_Byte:
Packit Service 706eca
	  cycles (6 + 7 * (tx / 4) + 4 * (tx % 4));
Packit Service 706eca
	  break;
Packit Service 706eca
	default:
Packit Service 706eca
	  abort ();
Packit Service 706eca
	}
Packit Service 706eca
#endif
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_rolc:
Packit Service 706eca
      v = GD ();
Packit Service 706eca
      ma = v & 0x80000000UL;
Packit Service 706eca
      v <<= 1;
Packit Service 706eca
      v |= carry;
Packit Service 706eca
      set_szc (v, 4, ma);
Packit Service 706eca
      PD (v);
Packit Service 706eca
      E1;
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_rorc:
Packit Service 706eca
      uma = GD ();
Packit Service 706eca
      mb = uma & 1;
Packit Service 706eca
      uma >>= 1;
Packit Service 706eca
      uma |= (carry ? 0x80000000UL : 0);
Packit Service 706eca
      set_szc (uma, 4, mb);
Packit Service 706eca
      PD (uma);
Packit Service 706eca
      E1;
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_rotl:
Packit Service 706eca
      mb = GS ();
Packit Service 706eca
      uma = GD ();
Packit Service 706eca
      if (mb)
Packit Service 706eca
	{
Packit Service 706eca
	  uma = (uma << mb) | (uma >> (32-mb));
Packit Service 706eca
	  mb = uma & 1;
Packit Service 706eca
	}
Packit Service 706eca
      set_szc (uma, 4, mb);
Packit Service 706eca
      PD (uma);
Packit Service 706eca
      E1;
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_rotr:
Packit Service 706eca
      mb = GS ();
Packit Service 706eca
      uma = GD ();
Packit Service 706eca
      if (mb)
Packit Service 706eca
	{
Packit Service 706eca
	  uma = (uma >> mb) | (uma << (32-mb));
Packit Service 706eca
	  mb = uma & 0x80000000;
Packit Service 706eca
	}
Packit Service 706eca
      set_szc (uma, 4, mb);
Packit Service 706eca
      PD (uma);
Packit Service 706eca
      E1;
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_round:
Packit Service 706eca
      ma = GS ();
Packit Service 706eca
      FPCLEAR ();
Packit Service 706eca
      mb = rxfp_ftoi (ma, regs.r_fpsw);
Packit Service 706eca
      FPCHECK ();
Packit Service 706eca
      PD (mb);
Packit Service 706eca
      tprintf("(int) %g = %d\n", int2float(ma), mb);
Packit Service 706eca
      set_sz (mb, 4);
Packit Service 706eca
      E (2);
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_rts:
Packit Service 706eca
      {
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
	int cyc = 5;
Packit Service 706eca
#endif
Packit Service 706eca
	regs.r_pc = poppc ();
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
	/* Note: specs say 5, chip says 3.  */
Packit Service 706eca
	if (regs.fast_return && regs.link_register == regs.r_pc)
Packit Service 706eca
	  {
Packit Service 706eca
#ifdef CYCLE_STATS
Packit Service 706eca
	    fast_returns ++;
Packit Service 706eca
#endif
Packit Service 706eca
	    tprintf("fast return bonus\n");
Packit Service 706eca
	    cyc -= 2;
Packit Service 706eca
	  }
Packit Service 706eca
	cycles (cyc);
Packit Service 706eca
	regs.fast_return = 0;
Packit Service 706eca
	branch_alignment_penalty = 1;
Packit Service 706eca
#endif
Packit Service 706eca
      }
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_rtsd:
Packit Service 706eca
      if (opcode->op[2].type == RX_Operand_Register)
Packit Service 706eca
	{
Packit Service 706eca
	  int i;
Packit Service 706eca
	  /* RTSD cannot pop R0 (sp).  */
Packit Service 706eca
	  put_reg (0, get_reg (0) + GS() - (opcode->op[0].reg-opcode->op[2].reg+1)*4);
Packit Service 706eca
	  if (opcode->op[2].reg == 0)
Packit Service 706eca
	    EXCEPTION (EX_UNDEFINED);
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
	  tx = opcode->op[0].reg - opcode->op[2].reg + 1;
Packit Service 706eca
#endif
Packit Service 706eca
	  for (i = opcode->op[2].reg; i <= opcode->op[0].reg; i ++)
Packit Service 706eca
	    {
Packit Service 706eca
	      RLD (i);
Packit Service 706eca
	      put_reg (i, pop ());
Packit Service 706eca
	    }
Packit Service 706eca
	}
Packit Service 706eca
      else
Packit Service 706eca
	{
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
	  tx = 0;
Packit Service 706eca
#endif
Packit Service 706eca
	  put_reg (0, get_reg (0) + GS());
Packit Service 706eca
	}
Packit Service 706eca
      put_reg (pc, poppc());
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
      if (regs.fast_return && regs.link_register == regs.r_pc)
Packit Service 706eca
	{
Packit Service 706eca
	  tprintf("fast return bonus\n");
Packit Service 706eca
#ifdef CYCLE_STATS
Packit Service 706eca
	  fast_returns ++;
Packit Service 706eca
#endif
Packit Service 706eca
	  cycles (tx < 3 ? 3 : tx + 1);
Packit Service 706eca
	}
Packit Service 706eca
      else
Packit Service 706eca
	{
Packit Service 706eca
	  cycles (tx < 5 ? 5 : tx + 1);
Packit Service 706eca
	}
Packit Service 706eca
      regs.fast_return = 0;
Packit Service 706eca
      branch_alignment_penalty = 1;
Packit Service 706eca
#endif
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_sat:
Packit Service 706eca
      if (FLAG_O && FLAG_S)
Packit Service 706eca
	PD (0x7fffffffUL);
Packit Service 706eca
      else if (FLAG_O && ! FLAG_S)
Packit Service 706eca
	PD (0x80000000UL);
Packit Service 706eca
      E1;
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_satr:
Packit Service 706eca
      if (FLAG_O && ! FLAG_S)
Packit Service 706eca
	{
Packit Service 706eca
	  put_reg (6, 0x0);
Packit Service 706eca
	  put_reg (5, 0x7fffffff);
Packit Service 706eca
	  put_reg (4, 0xffffffff);
Packit Service 706eca
	}
Packit Service 706eca
      else if (FLAG_O && FLAG_S)
Packit Service 706eca
	{
Packit Service 706eca
	  put_reg (6, 0xffffffff);
Packit Service 706eca
	  put_reg (5, 0x80000000);
Packit Service 706eca
	  put_reg (4, 0x0);
Packit Service 706eca
	}
Packit Service 706eca
      E1;
Packit Service 706eca
      break;
Packit Service 706eca
      
Packit Service 706eca
    case RXO_sbb:
Packit Service 706eca
      MATH_OP (-, ! carry);
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_sccnd:
Packit Service 706eca
      if (GS())
Packit Service 706eca
	PD (1);
Packit Service 706eca
      else
Packit Service 706eca
	PD (0);
Packit Service 706eca
      E1;
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_scmpu:
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
      tx = regs.r[3];
Packit Service 706eca
#endif
Packit Service 706eca
      while (regs.r[3] != 0)
Packit Service 706eca
	{
Packit Service 706eca
	  uma = mem_get_qi (regs.r[1] ++);
Packit Service 706eca
	  umb = mem_get_qi (regs.r[2] ++);
Packit Service 706eca
	  regs.r[3] --;
Packit Service 706eca
	  if (uma != umb || uma == 0)
Packit Service 706eca
	    break;
Packit Service 706eca
	}
Packit Service 706eca
      if (uma == umb)
Packit Service 706eca
	set_zc (1, 1);
Packit Service 706eca
      else
Packit Service 706eca
	set_zc (0, ((int)uma - (int)umb) >= 0);
Packit Service 706eca
      cycles (2 + 4 * (tx / 4) + 4 * (tx % 4));
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_setpsw:
Packit Service 706eca
      v = 1 << opcode->op[0].reg;
Packit Service 706eca
      if (FLAG_PM
Packit Service 706eca
	  && (v == FLAGBIT_I
Packit Service 706eca
	      || v == FLAGBIT_U))
Packit Service 706eca
	break;
Packit Service 706eca
      regs.r_psw |= v;
Packit Service 706eca
      cycles (1);
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_smovb:
Packit Service 706eca
      RL (3);
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
      tx = regs.r[3];
Packit Service 706eca
#endif
Packit Service 706eca
      while (regs.r[3])
Packit Service 706eca
	{
Packit Service 706eca
	  uma = mem_get_qi (regs.r[2] --);
Packit Service 706eca
	  mem_put_qi (regs.r[1]--, uma);
Packit Service 706eca
	  regs.r[3] --;
Packit Service 706eca
	}
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
      if (tx > 3)
Packit Service 706eca
	cycles (6 + 3 * (tx / 4) + 3 * (tx % 4));
Packit Service 706eca
      else
Packit Service 706eca
	cycles (2 + 3 * (tx % 4));
Packit Service 706eca
#endif
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_smovf:
Packit Service 706eca
      RL (3);
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
      tx = regs.r[3];
Packit Service 706eca
#endif
Packit Service 706eca
      while (regs.r[3])
Packit Service 706eca
	{
Packit Service 706eca
	  uma = mem_get_qi (regs.r[2] ++);
Packit Service 706eca
	  mem_put_qi (regs.r[1]++, uma);
Packit Service 706eca
	  regs.r[3] --;
Packit Service 706eca
	}
Packit Service 706eca
      cycles (2 + 3 * (int)(tx / 4) + 3 * (tx % 4));
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_smovu:
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
      tx = regs.r[3];
Packit Service 706eca
#endif
Packit Service 706eca
      while (regs.r[3] != 0)
Packit Service 706eca
	{
Packit Service 706eca
	  uma = mem_get_qi (regs.r[2] ++);
Packit Service 706eca
	  mem_put_qi (regs.r[1]++, uma);
Packit Service 706eca
	  regs.r[3] --;
Packit Service 706eca
	  if (uma == 0)
Packit Service 706eca
	    break;
Packit Service 706eca
	}
Packit Service 706eca
      cycles (2 + 3 * (int)(tx / 4) + 3 * (tx % 4));
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_shar: /* d = ma >> mb */
Packit Service 706eca
      SHIFT_OP (sll, int, mb, >>=, 1);
Packit Service 706eca
      E (1);
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_shll: /* d = ma << mb */
Packit Service 706eca
      SHIFT_OP (ll, int, mb, <<=, 0x80000000UL);
Packit Service 706eca
      E (1);
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_shlr: /* d = ma >> mb */
Packit Service 706eca
      SHIFT_OP (ll, unsigned int, mb, >>=, 1);
Packit Service 706eca
      E (1);
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_sstr:
Packit Service 706eca
      RL (3);
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
      tx = regs.r[3];
Packit Service 706eca
#endif
Packit Service 706eca
      switch (opcode->size)
Packit Service 706eca
	{
Packit Service 706eca
	case RX_Long:
Packit Service 706eca
	  while (regs.r[3] != 0)
Packit Service 706eca
	    {
Packit Service 706eca
	      mem_put_si (regs.r[1], regs.r[2]);
Packit Service 706eca
	      regs.r[1] += 4;
Packit Service 706eca
	      regs.r[3] --;
Packit Service 706eca
	    }
Packit Service 706eca
	  cycles (2 + tx);
Packit Service 706eca
	  break;
Packit Service 706eca
	case RX_Word:
Packit Service 706eca
	  while (regs.r[3] != 0)
Packit Service 706eca
	    {
Packit Service 706eca
	      mem_put_hi (regs.r[1], regs.r[2]);
Packit Service 706eca
	      regs.r[1] += 2;
Packit Service 706eca
	      regs.r[3] --;
Packit Service 706eca
	    }
Packit Service 706eca
	  cycles (2 + (int)(tx / 2) + tx % 2);
Packit Service 706eca
	  break;
Packit Service 706eca
	case RX_Byte:
Packit Service 706eca
	  while (regs.r[3] != 0)
Packit Service 706eca
	    {
Packit Service 706eca
	      mem_put_qi (regs.r[1], regs.r[2]);
Packit Service 706eca
	      regs.r[1] ++;
Packit Service 706eca
	      regs.r[3] --;
Packit Service 706eca
	    }
Packit Service 706eca
	  cycles (2 + (int)(tx / 4) + tx % 4);
Packit Service 706eca
	  break;
Packit Service 706eca
	default:
Packit Service 706eca
	  abort ();
Packit Service 706eca
	}
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_stcc:
Packit Service 706eca
      if (GS2())
Packit Service 706eca
	PD (GS ());
Packit Service 706eca
      E1;
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_stop:
Packit Service 706eca
      PRIVILEDGED ();
Packit Service 706eca
      regs.r_psw |= FLAGBIT_I;
Packit Service 706eca
      DO_RETURN (RX_MAKE_STOPPED(0));
Packit Service 706eca
Packit Service 706eca
    case RXO_sub:
Packit Service 706eca
      MATH_OP (-, 0);
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_suntil:
Packit Service 706eca
      RL(3);
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
      tx = 0;
Packit Service 706eca
#endif
Packit Service 706eca
      if (regs.r[3] == 0)
Packit Service 706eca
	{
Packit Service 706eca
	  cycles (3);
Packit Service 706eca
	  break;
Packit Service 706eca
	}
Packit Service 706eca
      switch (opcode->size)
Packit Service 706eca
	{
Packit Service 706eca
	case RX_Long:
Packit Service 706eca
	  uma = get_reg (2);
Packit Service 706eca
	  while (regs.r[3] != 0)
Packit Service 706eca
	    {
Packit Service 706eca
	      regs.r[3] --;
Packit Service 706eca
	      umb = mem_get_si (get_reg (1));
Packit Service 706eca
	      regs.r[1] += 4;
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
	      tx ++;
Packit Service 706eca
#endif
Packit Service 706eca
	      if (umb == uma)
Packit Service 706eca
		break;
Packit Service 706eca
	    }
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
	  cycles (3 + 3 * tx);
Packit Service 706eca
#endif
Packit Service 706eca
	  break;
Packit Service 706eca
	case RX_Word:
Packit Service 706eca
	  uma = get_reg (2) & 0xffff;
Packit Service 706eca
	  while (regs.r[3] != 0)
Packit Service 706eca
	    {
Packit Service 706eca
	      regs.r[3] --;
Packit Service 706eca
	      umb = mem_get_hi (get_reg (1));
Packit Service 706eca
	      regs.r[1] += 2;
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
	      tx ++;
Packit Service 706eca
#endif
Packit Service 706eca
	      if (umb == uma)
Packit Service 706eca
		break;
Packit Service 706eca
	    }
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
	  cycles (3 + 3 * (tx / 2) + 3 * (tx % 2));
Packit Service 706eca
#endif
Packit Service 706eca
	  break;
Packit Service 706eca
	case RX_Byte:
Packit Service 706eca
	  uma = get_reg (2) & 0xff;
Packit Service 706eca
	  while (regs.r[3] != 0)
Packit Service 706eca
	    {
Packit Service 706eca
	      regs.r[3] --;
Packit Service 706eca
	      umb = mem_get_qi (regs.r[1]);
Packit Service 706eca
	      regs.r[1] += 1;
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
	      tx ++;
Packit Service 706eca
#endif
Packit Service 706eca
	      if (umb == uma)
Packit Service 706eca
		break;
Packit Service 706eca
	    }
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
	  cycles (3 + 3 * (tx / 4) + 3 * (tx % 4));
Packit Service 706eca
#endif
Packit Service 706eca
	  break;
Packit Service 706eca
	default:
Packit Service 706eca
	  abort();
Packit Service 706eca
	}
Packit Service 706eca
      if (uma == umb)
Packit Service 706eca
	set_zc (1, 1);
Packit Service 706eca
      else
Packit Service 706eca
	set_zc (0, ((int)uma - (int)umb) >= 0);
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_swhile:
Packit Service 706eca
      RL(3);
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
      tx = 0;
Packit Service 706eca
#endif
Packit Service 706eca
      if (regs.r[3] == 0)
Packit Service 706eca
	break;
Packit Service 706eca
      switch (opcode->size)
Packit Service 706eca
	{
Packit Service 706eca
	case RX_Long:
Packit Service 706eca
	  uma = get_reg (2);
Packit Service 706eca
	  while (regs.r[3] != 0)
Packit Service 706eca
	    {
Packit Service 706eca
	      regs.r[3] --;
Packit Service 706eca
	      umb = mem_get_si (get_reg (1));
Packit Service 706eca
	      regs.r[1] += 4;
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
	      tx ++;
Packit Service 706eca
#endif
Packit Service 706eca
	      if (umb != uma)
Packit Service 706eca
		break;
Packit Service 706eca
	    }
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
	  cycles (3 + 3 * tx);
Packit Service 706eca
#endif
Packit Service 706eca
	  break;
Packit Service 706eca
	case RX_Word:
Packit Service 706eca
	  uma = get_reg (2) & 0xffff;
Packit Service 706eca
	  while (regs.r[3] != 0)
Packit Service 706eca
	    {
Packit Service 706eca
	      regs.r[3] --;
Packit Service 706eca
	      umb = mem_get_hi (get_reg (1));
Packit Service 706eca
	      regs.r[1] += 2;
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
	      tx ++;
Packit Service 706eca
#endif
Packit Service 706eca
	      if (umb != uma)
Packit Service 706eca
		break;
Packit Service 706eca
	    }
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
	  cycles (3 + 3 * (tx / 2) + 3 * (tx % 2));
Packit Service 706eca
#endif
Packit Service 706eca
	  break;
Packit Service 706eca
	case RX_Byte:
Packit Service 706eca
	  uma = get_reg (2) & 0xff;
Packit Service 706eca
	  while (regs.r[3] != 0)
Packit Service 706eca
	    {
Packit Service 706eca
	      regs.r[3] --;
Packit Service 706eca
	      umb = mem_get_qi (regs.r[1]);
Packit Service 706eca
	      regs.r[1] += 1;
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
	      tx ++;
Packit Service 706eca
#endif
Packit Service 706eca
	      if (umb != uma)
Packit Service 706eca
		break;
Packit Service 706eca
	    }
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
	  cycles (3 + 3 * (tx / 4) + 3 * (tx % 4));
Packit Service 706eca
#endif
Packit Service 706eca
	  break;
Packit Service 706eca
	default:
Packit Service 706eca
	  abort();
Packit Service 706eca
	}
Packit Service 706eca
      if (uma == umb)
Packit Service 706eca
	set_zc (1, 1);
Packit Service 706eca
      else
Packit Service 706eca
	set_zc (0, ((int)uma - (int)umb) >= 0);
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_wait:
Packit Service 706eca
      PRIVILEDGED ();
Packit Service 706eca
      regs.r_psw |= FLAGBIT_I;
Packit Service 706eca
      DO_RETURN (RX_MAKE_STOPPED(0));
Packit Service 706eca
Packit Service 706eca
    case RXO_xchg:
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
      regs.m2m = 0;
Packit Service 706eca
#endif
Packit Service 706eca
      v = GS (); /* This is the memory operand, if any.  */
Packit Service 706eca
      PS (GD ()); /* and this may change the address register.  */
Packit Service 706eca
      PD (v);
Packit Service 706eca
      E2;
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
      /* all M cycles happen during xchg's cycles.  */
Packit Service 706eca
      memory_dest = 0;
Packit Service 706eca
      memory_source = 0;
Packit Service 706eca
#endif
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    case RXO_xor:
Packit Service 706eca
      LOGIC_OP (^);
Packit Service 706eca
      break;
Packit Service 706eca
Packit Service 706eca
    default:
Packit Service 706eca
      EXCEPTION (EX_UNDEFINED);
Packit Service 706eca
    }
Packit Service 706eca
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
  regs.m2m = 0;
Packit Service 706eca
  if (memory_source)
Packit Service 706eca
    regs.m2m |= M2M_SRC;
Packit Service 706eca
  if (memory_dest)
Packit Service 706eca
    regs.m2m |= M2M_DST;
Packit Service 706eca
Packit Service 706eca
  regs.rt = new_rt;
Packit Service 706eca
  new_rt = -1;
Packit Service 706eca
#endif
Packit Service 706eca
Packit Service 706eca
#ifdef CYCLE_STATS
Packit Service 706eca
  if (prev_cycle_count == regs.cycle_count)
Packit Service 706eca
    {
Packit Service 706eca
      printf("Cycle count not updated! id %s\n", id_names[opcode->id]);
Packit Service 706eca
      abort ();
Packit Service 706eca
    }
Packit Service 706eca
#endif
Packit Service 706eca
Packit Service 706eca
#ifdef CYCLE_STATS
Packit Service 706eca
  if (running_benchmark)
Packit Service 706eca
    {
Packit Service 706eca
      int omap = op_lookup (opcode->op[0].type, opcode->op[1].type, opcode->op[2].type);
Packit Service 706eca
Packit Service 706eca
Packit Service 706eca
      cycles_per_id[opcode->id][omap] += regs.cycle_count - prev_cycle_count;
Packit Service 706eca
      times_per_id[opcode->id][omap] ++;
Packit Service 706eca
Packit Service 706eca
      times_per_pair[prev_opcode_id][po0][opcode->id][omap] ++;
Packit Service 706eca
Packit Service 706eca
      prev_opcode_id = opcode->id;
Packit Service 706eca
      po0 = omap;
Packit Service 706eca
    }
Packit Service 706eca
#endif
Packit Service 706eca
Packit Service 706eca
  return RX_MAKE_STEPPED ();
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
#ifdef CYCLE_STATS
Packit Service 706eca
void
Packit Service 706eca
reset_pipeline_stats (void)
Packit Service 706eca
{
Packit Service 706eca
  memset (cycles_per_id, 0, sizeof(cycles_per_id));
Packit Service 706eca
  memset (times_per_id, 0, sizeof(times_per_id));
Packit Service 706eca
  memory_stalls = 0;
Packit Service 706eca
  register_stalls = 0;
Packit Service 706eca
  branch_stalls = 0;
Packit Service 706eca
  branch_alignment_stalls = 0;
Packit Service 706eca
  fast_returns = 0;
Packit Service 706eca
  memset (times_per_pair, 0, sizeof(times_per_pair));
Packit Service 706eca
  running_benchmark = 1;
Packit Service 706eca
Packit Service 706eca
  benchmark_start_cycle = regs.cycle_count;
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
void
Packit Service 706eca
halt_pipeline_stats (void)
Packit Service 706eca
{
Packit Service 706eca
  running_benchmark = 0;
Packit Service 706eca
  benchmark_end_cycle = regs.cycle_count;
Packit Service 706eca
}
Packit Service 706eca
#endif
Packit Service 706eca
Packit Service 706eca
void
Packit Service 706eca
pipeline_stats (void)
Packit Service 706eca
{
Packit Service 706eca
#ifdef CYCLE_STATS
Packit Service 706eca
  int i, o1;
Packit Service 706eca
  int p, p1;
Packit Service 706eca
#endif
Packit Service 706eca
Packit Service 706eca
#ifdef CYCLE_ACCURATE
Packit Service 706eca
  if (verbose == 1)
Packit Service 706eca
    {
Packit Service 706eca
      printf ("cycles: %llu\n", regs.cycle_count);
Packit Service 706eca
      return;
Packit Service 706eca
    }
Packit Service 706eca
Packit Service 706eca
  printf ("cycles: %13s\n", comma (regs.cycle_count));
Packit Service 706eca
#endif
Packit Service 706eca
Packit Service 706eca
#ifdef CYCLE_STATS
Packit Service 706eca
  if (benchmark_start_cycle)
Packit Service 706eca
    printf ("bmark:  %13s\n", comma (benchmark_end_cycle - benchmark_start_cycle));
Packit Service 706eca
Packit Service 706eca
  printf("\n");
Packit Service 706eca
  for (i = 0; i < N_RXO; i++)
Packit Service 706eca
    for (o1 = 0; o1 < N_MAP; o1 ++)
Packit Service 706eca
      if (times_per_id[i][o1])
Packit Service 706eca
	printf("%13s %13s %7.2f  %s %s\n",
Packit Service 706eca
	       comma (cycles_per_id[i][o1]),
Packit Service 706eca
	       comma (times_per_id[i][o1]),
Packit Service 706eca
	       (double)cycles_per_id[i][o1] / times_per_id[i][o1],
Packit Service 706eca
	       op_cache_string(o1),
Packit Service 706eca
	       id_names[i]+4);
Packit Service 706eca
Packit Service 706eca
  printf("\n");
Packit Service 706eca
  for (p = 0; p < N_RXO; p ++)
Packit Service 706eca
    for (p1 = 0; p1 < N_MAP; p1 ++)
Packit Service 706eca
      for (i = 0; i < N_RXO; i ++)
Packit Service 706eca
	for (o1 = 0; o1 < N_MAP; o1 ++)
Packit Service 706eca
	  if (times_per_pair[p][p1][i][o1])
Packit Service 706eca
	    {
Packit Service 706eca
	      printf("%13s   %s %-9s  ->  %s %s\n",
Packit Service 706eca
		     comma (times_per_pair[p][p1][i][o1]),
Packit Service 706eca
		     op_cache_string(p1),
Packit Service 706eca
		     id_names[p]+4,
Packit Service 706eca
		     op_cache_string(o1),
Packit Service 706eca
		     id_names[i]+4);
Packit Service 706eca
	    }
Packit Service 706eca
Packit Service 706eca
  printf("\n");
Packit Service 706eca
  printf("%13s memory stalls\n", comma (memory_stalls));
Packit Service 706eca
  printf("%13s register stalls\n", comma (register_stalls));
Packit Service 706eca
  printf("%13s branches taken (non-return)\n", comma (branch_stalls));
Packit Service 706eca
  printf("%13s branch alignment stalls\n", comma (branch_alignment_stalls));
Packit Service 706eca
  printf("%13s fast returns\n", comma (fast_returns));
Packit Service 706eca
#endif
Packit Service 706eca
}