OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-6.8/] [sim/] [sh/] [interp.c] - Diff between revs 24 and 157

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 24 Rev 157
/* Simulator for the Renesas (formerly Hitachi) / SuperH Inc. SH architecture.
/* Simulator for the Renesas (formerly Hitachi) / SuperH Inc. SH architecture.
 
 
   Written by Steve Chamberlain of Cygnus Support.
   Written by Steve Chamberlain of Cygnus Support.
   sac@cygnus.com
   sac@cygnus.com
 
 
   This file is part of SH sim
   This file is part of SH sim
 
 
 
 
                THIS SOFTWARE IS NOT COPYRIGHTED
                THIS SOFTWARE IS NOT COPYRIGHTED
 
 
   Cygnus offers the following for use in the public domain.  Cygnus
   Cygnus offers the following for use in the public domain.  Cygnus
   makes no warranty with regard to the software or it's performance
   makes no warranty with regard to the software or it's performance
   and the user accepts the software "AS IS" with all faults.
   and the user accepts the software "AS IS" with all faults.
 
 
   CYGNUS DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO
   CYGNUS DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO
   THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
   THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 
 
*/
*/
 
 
#include "config.h"
#include "config.h"
 
 
#include <signal.h>
#include <signal.h>
#ifdef HAVE_UNISTD_H
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#include <unistd.h>
#endif
#endif
#ifdef HAVE_MMAP
#ifdef HAVE_MMAP
#include <sys/mman.h>
#include <sys/mman.h>
# ifndef MAP_FAILED
# ifndef MAP_FAILED
#  define MAP_FAILED -1
#  define MAP_FAILED -1
# endif
# endif
# if !defined (MAP_ANONYMOUS) && defined (MAP_ANON)
# if !defined (MAP_ANONYMOUS) && defined (MAP_ANON)
#  define MAP_ANONYMOUS MAP_ANON
#  define MAP_ANONYMOUS MAP_ANON
# endif
# endif
#endif
#endif
 
 
#include "sysdep.h"
#include "sysdep.h"
#include "bfd.h"
#include "bfd.h"
#include "gdb/callback.h"
#include "gdb/callback.h"
#include "gdb/remote-sim.h"
#include "gdb/remote-sim.h"
#include "gdb/sim-sh.h"
#include "gdb/sim-sh.h"
 
 
/* This file is local - if newlib changes, then so should this.  */
/* This file is local - if newlib changes, then so should this.  */
#include "syscall.h"
#include "syscall.h"
 
 
#include <math.h>
#include <math.h>
 
 
#ifdef _WIN32
#ifdef _WIN32
#include <float.h>              /* Needed for _isnan() */
#include <float.h>              /* Needed for _isnan() */
#define isnan _isnan
#define isnan _isnan
#endif
#endif
 
 
#ifndef SIGBUS
#ifndef SIGBUS
#define SIGBUS SIGSEGV
#define SIGBUS SIGSEGV
#endif
#endif
 
 
#ifndef SIGQUIT
#ifndef SIGQUIT
#define SIGQUIT SIGTERM
#define SIGQUIT SIGTERM
#endif
#endif
 
 
#ifndef SIGTRAP
#ifndef SIGTRAP
#define SIGTRAP 5
#define SIGTRAP 5
#endif
#endif
 
 
extern unsigned short sh_jump_table[], sh_dsp_table[0x1000], ppi_table[];
extern unsigned short sh_jump_table[], sh_dsp_table[0x1000], ppi_table[];
 
 
int sim_write (SIM_DESC sd, SIM_ADDR addr, unsigned char *buffer, int size);
int sim_write (SIM_DESC sd, SIM_ADDR addr, unsigned char *buffer, int size);
 
 
#define O_RECOMPILE 85
#define O_RECOMPILE 85
#define DEFINE_TABLE
#define DEFINE_TABLE
#define DISASSEMBLER_TABLE
#define DISASSEMBLER_TABLE
 
 
/* Define the rate at which the simulator should poll the host
/* Define the rate at which the simulator should poll the host
   for a quit. */
   for a quit. */
#define POLL_QUIT_INTERVAL 0x60000
#define POLL_QUIT_INTERVAL 0x60000
 
 
typedef struct
typedef struct
{
{
  int regs[20];
  int regs[20];
} regstacktype;
} regstacktype;
 
 
typedef union
typedef union
{
{
 
 
  struct
  struct
  {
  {
    int regs[16];
    int regs[16];
    int pc;
    int pc;
 
 
    /* System registers.  For sh-dsp this also includes A0 / X0 / X1 / Y0 / Y1
    /* System registers.  For sh-dsp this also includes A0 / X0 / X1 / Y0 / Y1
       which are located in fregs, i.e. strictly speaking, these are
       which are located in fregs, i.e. strictly speaking, these are
       out-of-bounds accesses of sregs.i .  This wart of the code could be
       out-of-bounds accesses of sregs.i .  This wart of the code could be
       fixed by making fregs part of sregs, and including pc too - to avoid
       fixed by making fregs part of sregs, and including pc too - to avoid
       alignment repercussions - but this would cause very onerous union /
       alignment repercussions - but this would cause very onerous union /
       structure nesting, which would only be managable with anonymous
       structure nesting, which would only be managable with anonymous
       unions and structs.  */
       unions and structs.  */
    union
    union
      {
      {
        struct
        struct
          {
          {
            int mach;
            int mach;
            int macl;
            int macl;
            int pr;
            int pr;
            int dummy3, dummy4;
            int dummy3, dummy4;
            int fpul; /* A1 for sh-dsp -  but only for movs etc.  */
            int fpul; /* A1 for sh-dsp -  but only for movs etc.  */
            int fpscr; /* dsr for sh-dsp */
            int fpscr; /* dsr for sh-dsp */
          } named;
          } named;
        int i[7];
        int i[7];
      } sregs;
      } sregs;
 
 
    /* sh3e / sh-dsp */
    /* sh3e / sh-dsp */
    union fregs_u
    union fregs_u
      {
      {
        float f[16];
        float f[16];
        double d[8];
        double d[8];
        int i[16];
        int i[16];
      }
      }
    fregs[2];
    fregs[2];
 
 
    /* Control registers; on the SH4, ldc / stc is privileged, except when
    /* Control registers; on the SH4, ldc / stc is privileged, except when
       accessing gbr.  */
       accessing gbr.  */
    union
    union
      {
      {
        struct
        struct
          {
          {
            int sr;
            int sr;
            int gbr;
            int gbr;
            int vbr;
            int vbr;
            int ssr;
            int ssr;
            int spc;
            int spc;
            int mod;
            int mod;
            /* sh-dsp */
            /* sh-dsp */
            int rs;
            int rs;
            int re;
            int re;
            /* sh3 */
            /* sh3 */
            int bank[8];
            int bank[8];
            int dbr;            /* debug base register */
            int dbr;            /* debug base register */
            int sgr;            /* saved gr15 */
            int sgr;            /* saved gr15 */
            int ldst;           /* load/store flag (boolean) */
            int ldst;           /* load/store flag (boolean) */
            int tbr;
            int tbr;
            int ibcr;           /* sh2a bank control register */
            int ibcr;           /* sh2a bank control register */
            int ibnr;           /* sh2a bank number register */
            int ibnr;           /* sh2a bank number register */
          } named;
          } named;
        int i[16];
        int i[16];
      } cregs;
      } cregs;
 
 
    unsigned char *insn_end;
    unsigned char *insn_end;
 
 
    int ticks;
    int ticks;
    int stalls;
    int stalls;
    int memstalls;
    int memstalls;
    int cycles;
    int cycles;
    int insts;
    int insts;
 
 
    int prevlock;
    int prevlock;
    int thislock;
    int thislock;
    int exception;
    int exception;
 
 
    int end_of_registers;
    int end_of_registers;
 
 
    int msize;
    int msize;
#define PROFILE_FREQ 1
#define PROFILE_FREQ 1
#define PROFILE_SHIFT 2
#define PROFILE_SHIFT 2
    int profile;
    int profile;
    unsigned short *profile_hist;
    unsigned short *profile_hist;
    unsigned char *memory;
    unsigned char *memory;
    int xyram_select, xram_start, yram_start;
    int xyram_select, xram_start, yram_start;
    unsigned char *xmem;
    unsigned char *xmem;
    unsigned char *ymem;
    unsigned char *ymem;
    unsigned char *xmem_offset;
    unsigned char *xmem_offset;
    unsigned char *ymem_offset;
    unsigned char *ymem_offset;
    unsigned long bfd_mach;
    unsigned long bfd_mach;
    regstacktype *regstack;
    regstacktype *regstack;
  }
  }
  asregs;
  asregs;
  int asints[40];
  int asints[40];
} saved_state_type;
} saved_state_type;
 
 
saved_state_type saved_state;
saved_state_type saved_state;
 
 
struct loop_bounds { unsigned char *start, *end; };
struct loop_bounds { unsigned char *start, *end; };
 
 
/* These variables are at file scope so that functions other than
/* These variables are at file scope so that functions other than
   sim_resume can use the fetch/store macros */
   sim_resume can use the fetch/store macros */
 
 
static int target_little_endian;
static int target_little_endian;
static int global_endianw, endianb;
static int global_endianw, endianb;
static int target_dsp;
static int target_dsp;
static int host_little_endian;
static int host_little_endian;
static char **prog_argv;
static char **prog_argv;
 
 
static int maskw = 0;
static int maskw = 0;
static int maskl = 0;
static int maskl = 0;
 
 
static SIM_OPEN_KIND sim_kind;
static SIM_OPEN_KIND sim_kind;
static char *myname;
static char *myname;
static int   tracing = 0;
static int   tracing = 0;
 
 
 
 
/* Short hand definitions of the registers */
/* Short hand definitions of the registers */
 
 
#define SBIT(x) ((x)&sbit)
#define SBIT(x) ((x)&sbit)
#define R0      saved_state.asregs.regs[0]
#define R0      saved_state.asregs.regs[0]
#define Rn      saved_state.asregs.regs[n]
#define Rn      saved_state.asregs.regs[n]
#define Rm      saved_state.asregs.regs[m]
#define Rm      saved_state.asregs.regs[m]
#define UR0     (unsigned int) (saved_state.asregs.regs[0])
#define UR0     (unsigned int) (saved_state.asregs.regs[0])
#define UR      (unsigned int) R
#define UR      (unsigned int) R
#define UR      (unsigned int) R
#define UR      (unsigned int) R
#define SR0     saved_state.asregs.regs[0]
#define SR0     saved_state.asregs.regs[0]
#define CREG(n) (saved_state.asregs.cregs.i[(n)])
#define CREG(n) (saved_state.asregs.cregs.i[(n)])
#define GBR     saved_state.asregs.cregs.named.gbr
#define GBR     saved_state.asregs.cregs.named.gbr
#define VBR     saved_state.asregs.cregs.named.vbr
#define VBR     saved_state.asregs.cregs.named.vbr
#define DBR     saved_state.asregs.cregs.named.dbr
#define DBR     saved_state.asregs.cregs.named.dbr
#define TBR     saved_state.asregs.cregs.named.tbr
#define TBR     saved_state.asregs.cregs.named.tbr
#define IBCR    saved_state.asregs.cregs.named.ibcr
#define IBCR    saved_state.asregs.cregs.named.ibcr
#define IBNR    saved_state.asregs.cregs.named.ibnr
#define IBNR    saved_state.asregs.cregs.named.ibnr
#define BANKN   (saved_state.asregs.cregs.named.ibnr & 0x1ff)
#define BANKN   (saved_state.asregs.cregs.named.ibnr & 0x1ff)
#define ME      ((saved_state.asregs.cregs.named.ibnr >> 14) & 0x3)
#define ME      ((saved_state.asregs.cregs.named.ibnr >> 14) & 0x3)
#define SSR     saved_state.asregs.cregs.named.ssr
#define SSR     saved_state.asregs.cregs.named.ssr
#define SPC     saved_state.asregs.cregs.named.spc
#define SPC     saved_state.asregs.cregs.named.spc
#define SGR     saved_state.asregs.cregs.named.sgr
#define SGR     saved_state.asregs.cregs.named.sgr
#define SREG(n) (saved_state.asregs.sregs.i[(n)])
#define SREG(n) (saved_state.asregs.sregs.i[(n)])
#define MACH    saved_state.asregs.sregs.named.mach
#define MACH    saved_state.asregs.sregs.named.mach
#define MACL    saved_state.asregs.sregs.named.macl
#define MACL    saved_state.asregs.sregs.named.macl
#define PR      saved_state.asregs.sregs.named.pr
#define PR      saved_state.asregs.sregs.named.pr
#define FPUL    saved_state.asregs.sregs.named.fpul
#define FPUL    saved_state.asregs.sregs.named.fpul
 
 
#define PC insn_ptr
#define PC insn_ptr
 
 
 
 
 
 
/* Alternate bank of registers r0-r7 */
/* Alternate bank of registers r0-r7 */
 
 
/* Note: code controling SR handles flips between BANK0 and BANK1 */
/* Note: code controling SR handles flips between BANK0 and BANK1 */
#define Rn_BANK(n) (saved_state.asregs.cregs.named.bank[(n)])
#define Rn_BANK(n) (saved_state.asregs.cregs.named.bank[(n)])
#define SET_Rn_BANK(n, EXP) do { saved_state.asregs.cregs.named.bank[(n)] = (EXP); } while (0)
#define SET_Rn_BANK(n, EXP) do { saved_state.asregs.cregs.named.bank[(n)] = (EXP); } while (0)
 
 
 
 
/* Manipulate SR */
/* Manipulate SR */
 
 
#define SR_MASK_BO  (1 << 14)
#define SR_MASK_BO  (1 << 14)
#define SR_MASK_CS  (1 << 13)
#define SR_MASK_CS  (1 << 13)
#define SR_MASK_DMY (1 << 11)
#define SR_MASK_DMY (1 << 11)
#define SR_MASK_DMX (1 << 10)
#define SR_MASK_DMX (1 << 10)
#define SR_MASK_M (1 << 9)
#define SR_MASK_M (1 << 9)
#define SR_MASK_Q (1 << 8)
#define SR_MASK_Q (1 << 8)
#define SR_MASK_I (0xf << 4)
#define SR_MASK_I (0xf << 4)
#define SR_MASK_S (1 << 1)
#define SR_MASK_S (1 << 1)
#define SR_MASK_T (1 << 0)
#define SR_MASK_T (1 << 0)
 
 
#define SR_MASK_BL (1 << 28)
#define SR_MASK_BL (1 << 28)
#define SR_MASK_RB (1 << 29)
#define SR_MASK_RB (1 << 29)
#define SR_MASK_MD (1 << 30)
#define SR_MASK_MD (1 << 30)
#define SR_MASK_RC 0x0fff0000
#define SR_MASK_RC 0x0fff0000
#define SR_RC_INCREMENT -0x00010000
#define SR_RC_INCREMENT -0x00010000
 
 
#define BO      ((saved_state.asregs.cregs.named.sr & SR_MASK_BO) != 0)
#define BO      ((saved_state.asregs.cregs.named.sr & SR_MASK_BO) != 0)
#define CS      ((saved_state.asregs.cregs.named.sr & SR_MASK_CS) != 0)
#define CS      ((saved_state.asregs.cregs.named.sr & SR_MASK_CS) != 0)
#define M       ((saved_state.asregs.cregs.named.sr & SR_MASK_M) != 0)
#define M       ((saved_state.asregs.cregs.named.sr & SR_MASK_M) != 0)
#define Q       ((saved_state.asregs.cregs.named.sr & SR_MASK_Q) != 0)
#define Q       ((saved_state.asregs.cregs.named.sr & SR_MASK_Q) != 0)
#define S       ((saved_state.asregs.cregs.named.sr & SR_MASK_S) != 0)
#define S       ((saved_state.asregs.cregs.named.sr & SR_MASK_S) != 0)
#define T       ((saved_state.asregs.cregs.named.sr & SR_MASK_T) != 0)
#define T       ((saved_state.asregs.cregs.named.sr & SR_MASK_T) != 0)
#define LDST    ((saved_state.asregs.cregs.named.ldst) != 0)
#define LDST    ((saved_state.asregs.cregs.named.ldst) != 0)
 
 
#define SR_BL ((saved_state.asregs.cregs.named.sr & SR_MASK_BL) != 0)
#define SR_BL ((saved_state.asregs.cregs.named.sr & SR_MASK_BL) != 0)
#define SR_RB ((saved_state.asregs.cregs.named.sr & SR_MASK_RB) != 0)
#define SR_RB ((saved_state.asregs.cregs.named.sr & SR_MASK_RB) != 0)
#define SR_MD ((saved_state.asregs.cregs.named.sr & SR_MASK_MD) != 0)
#define SR_MD ((saved_state.asregs.cregs.named.sr & SR_MASK_MD) != 0)
#define SR_DMY ((saved_state.asregs.cregs.named.sr & SR_MASK_DMY) != 0)
#define SR_DMY ((saved_state.asregs.cregs.named.sr & SR_MASK_DMY) != 0)
#define SR_DMX ((saved_state.asregs.cregs.named.sr & SR_MASK_DMX) != 0)
#define SR_DMX ((saved_state.asregs.cregs.named.sr & SR_MASK_DMX) != 0)
#define SR_RC ((saved_state.asregs.cregs.named.sr & SR_MASK_RC))
#define SR_RC ((saved_state.asregs.cregs.named.sr & SR_MASK_RC))
 
 
/* Note: don't use this for privileged bits */
/* Note: don't use this for privileged bits */
#define SET_SR_BIT(EXP, BIT) \
#define SET_SR_BIT(EXP, BIT) \
do { \
do { \
  if ((EXP) & 1) \
  if ((EXP) & 1) \
    saved_state.asregs.cregs.named.sr |= (BIT); \
    saved_state.asregs.cregs.named.sr |= (BIT); \
  else \
  else \
    saved_state.asregs.cregs.named.sr &= ~(BIT); \
    saved_state.asregs.cregs.named.sr &= ~(BIT); \
} while (0)
} while (0)
 
 
#define SET_SR_BO(EXP) SET_SR_BIT ((EXP), SR_MASK_BO)
#define SET_SR_BO(EXP) SET_SR_BIT ((EXP), SR_MASK_BO)
#define SET_SR_CS(EXP) SET_SR_BIT ((EXP), SR_MASK_CS)
#define SET_SR_CS(EXP) SET_SR_BIT ((EXP), SR_MASK_CS)
#define SET_BANKN(EXP) \
#define SET_BANKN(EXP) \
do { \
do { \
  IBNR = (IBNR & 0xfe00) | (EXP & 0x1f); \
  IBNR = (IBNR & 0xfe00) | (EXP & 0x1f); \
} while (0)
} while (0)
#define SET_ME(EXP) \
#define SET_ME(EXP) \
do { \
do { \
  IBNR = (IBNR & 0x3fff) | ((EXP & 0x3) << 14); \
  IBNR = (IBNR & 0x3fff) | ((EXP & 0x3) << 14); \
} while (0)
} while (0)
#define SET_SR_M(EXP) SET_SR_BIT ((EXP), SR_MASK_M)
#define SET_SR_M(EXP) SET_SR_BIT ((EXP), SR_MASK_M)
#define SET_SR_Q(EXP) SET_SR_BIT ((EXP), SR_MASK_Q)
#define SET_SR_Q(EXP) SET_SR_BIT ((EXP), SR_MASK_Q)
#define SET_SR_S(EXP) SET_SR_BIT ((EXP), SR_MASK_S)
#define SET_SR_S(EXP) SET_SR_BIT ((EXP), SR_MASK_S)
#define SET_SR_T(EXP) SET_SR_BIT ((EXP), SR_MASK_T)
#define SET_SR_T(EXP) SET_SR_BIT ((EXP), SR_MASK_T)
#define SET_LDST(EXP) (saved_state.asregs.cregs.named.ldst = ((EXP) != 0))
#define SET_LDST(EXP) (saved_state.asregs.cregs.named.ldst = ((EXP) != 0))
 
 
/* stc currently relies on being able to read SR without modifications.  */
/* stc currently relies on being able to read SR without modifications.  */
#define GET_SR() (saved_state.asregs.cregs.named.sr - 0)
#define GET_SR() (saved_state.asregs.cregs.named.sr - 0)
 
 
#define SET_SR(x) set_sr (x)
#define SET_SR(x) set_sr (x)
 
 
#define SET_RC(x) \
#define SET_RC(x) \
  (saved_state.asregs.cregs.named.sr \
  (saved_state.asregs.cregs.named.sr \
   = saved_state.asregs.cregs.named.sr & 0xf000ffff | ((x) & 0xfff) << 16)
   = saved_state.asregs.cregs.named.sr & 0xf000ffff | ((x) & 0xfff) << 16)
 
 
/* Manipulate FPSCR */
/* Manipulate FPSCR */
 
 
#define FPSCR_MASK_FR (1 << 21)
#define FPSCR_MASK_FR (1 << 21)
#define FPSCR_MASK_SZ (1 << 20)
#define FPSCR_MASK_SZ (1 << 20)
#define FPSCR_MASK_PR (1 << 19)
#define FPSCR_MASK_PR (1 << 19)
 
 
#define FPSCR_FR  ((GET_FPSCR () & FPSCR_MASK_FR) != 0)
#define FPSCR_FR  ((GET_FPSCR () & FPSCR_MASK_FR) != 0)
#define FPSCR_SZ  ((GET_FPSCR () & FPSCR_MASK_SZ) != 0)
#define FPSCR_SZ  ((GET_FPSCR () & FPSCR_MASK_SZ) != 0)
#define FPSCR_PR  ((GET_FPSCR () & FPSCR_MASK_PR) != 0)
#define FPSCR_PR  ((GET_FPSCR () & FPSCR_MASK_PR) != 0)
 
 
/* Count the number of arguments in an argv.  */
/* Count the number of arguments in an argv.  */
static int
static int
count_argc (char **argv)
count_argc (char **argv)
{
{
  int i;
  int i;
 
 
  if (! argv)
  if (! argv)
    return -1;
    return -1;
 
 
  for (i = 0; argv[i] != NULL; ++i)
  for (i = 0; argv[i] != NULL; ++i)
    continue;
    continue;
  return i;
  return i;
}
}
 
 
static void
static void
set_fpscr1 (x)
set_fpscr1 (x)
        int x;
        int x;
{
{
  int old = saved_state.asregs.sregs.named.fpscr;
  int old = saved_state.asregs.sregs.named.fpscr;
  saved_state.asregs.sregs.named.fpscr = (x);
  saved_state.asregs.sregs.named.fpscr = (x);
  /* swap the floating point register banks */
  /* swap the floating point register banks */
  if ((saved_state.asregs.sregs.named.fpscr ^ old) & FPSCR_MASK_FR
  if ((saved_state.asregs.sregs.named.fpscr ^ old) & FPSCR_MASK_FR
      /* Ignore bit change if simulating sh-dsp.  */
      /* Ignore bit change if simulating sh-dsp.  */
      && ! target_dsp)
      && ! target_dsp)
    {
    {
      union fregs_u tmpf = saved_state.asregs.fregs[0];
      union fregs_u tmpf = saved_state.asregs.fregs[0];
      saved_state.asregs.fregs[0] = saved_state.asregs.fregs[1];
      saved_state.asregs.fregs[0] = saved_state.asregs.fregs[1];
      saved_state.asregs.fregs[1] = tmpf;
      saved_state.asregs.fregs[1] = tmpf;
    }
    }
}
}
 
 
/* sts relies on being able to read fpscr directly.  */
/* sts relies on being able to read fpscr directly.  */
#define GET_FPSCR()  (saved_state.asregs.sregs.named.fpscr)
#define GET_FPSCR()  (saved_state.asregs.sregs.named.fpscr)
#define SET_FPSCR(x) \
#define SET_FPSCR(x) \
do { \
do { \
  set_fpscr1 (x); \
  set_fpscr1 (x); \
} while (0)
} while (0)
 
 
#define DSR  (saved_state.asregs.sregs.named.fpscr)
#define DSR  (saved_state.asregs.sregs.named.fpscr)
 
 
int
int
fail ()
fail ()
{
{
  abort ();
  abort ();
}
}
 
 
#define RAISE_EXCEPTION(x) \
#define RAISE_EXCEPTION(x) \
  (saved_state.asregs.exception = x, saved_state.asregs.insn_end = 0)
  (saved_state.asregs.exception = x, saved_state.asregs.insn_end = 0)
 
 
#define RAISE_EXCEPTION_IF_IN_DELAY_SLOT() \
#define RAISE_EXCEPTION_IF_IN_DELAY_SLOT() \
  if (in_delay_slot) RAISE_EXCEPTION (SIGILL)
  if (in_delay_slot) RAISE_EXCEPTION (SIGILL)
 
 
/* This function exists mainly for the purpose of setting a breakpoint to
/* This function exists mainly for the purpose of setting a breakpoint to
   catch simulated bus errors when running the simulator under GDB.  */
   catch simulated bus errors when running the simulator under GDB.  */
 
 
void
void
raise_exception (x)
raise_exception (x)
     int x;
     int x;
{
{
  RAISE_EXCEPTION (x);
  RAISE_EXCEPTION (x);
}
}
 
 
void
void
raise_buserror ()
raise_buserror ()
{
{
  raise_exception (SIGBUS);
  raise_exception (SIGBUS);
}
}
 
 
#define PROCESS_SPECIAL_ADDRESS(addr, endian, ptr, bits_written, \
#define PROCESS_SPECIAL_ADDRESS(addr, endian, ptr, bits_written, \
                                forbidden_addr_bits, data, retval) \
                                forbidden_addr_bits, data, retval) \
do { \
do { \
  if (addr & forbidden_addr_bits) \
  if (addr & forbidden_addr_bits) \
    { \
    { \
      raise_buserror (); \
      raise_buserror (); \
      return retval; \
      return retval; \
    } \
    } \
  else if ((addr & saved_state.asregs.xyram_select) \
  else if ((addr & saved_state.asregs.xyram_select) \
           == saved_state.asregs.xram_start) \
           == saved_state.asregs.xram_start) \
    ptr = (void *) &saved_state.asregs.xmem_offset[addr ^ endian]; \
    ptr = (void *) &saved_state.asregs.xmem_offset[addr ^ endian]; \
  else if ((addr & saved_state.asregs.xyram_select) \
  else if ((addr & saved_state.asregs.xyram_select) \
           == saved_state.asregs.yram_start) \
           == saved_state.asregs.yram_start) \
    ptr = (void *) &saved_state.asregs.ymem_offset[addr ^ endian]; \
    ptr = (void *) &saved_state.asregs.ymem_offset[addr ^ endian]; \
  else if ((unsigned) addr >> 24 == 0xf0 \
  else if ((unsigned) addr >> 24 == 0xf0 \
           && bits_written == 32 && (data & 1) == 0) \
           && bits_written == 32 && (data & 1) == 0) \
    /* This invalidates (if not associative) or might invalidate \
    /* This invalidates (if not associative) or might invalidate \
       (if associative) an instruction cache line.  This is used for \
       (if associative) an instruction cache line.  This is used for \
       trampolines.  Since we don't simulate the cache, this is a no-op \
       trampolines.  Since we don't simulate the cache, this is a no-op \
       as far as the simulator is concerned.  */ \
       as far as the simulator is concerned.  */ \
    return retval; \
    return retval; \
  else \
  else \
    { \
    { \
      if (bits_written == 8 && addr > 0x5000000) \
      if (bits_written == 8 && addr > 0x5000000) \
        IOMEM (addr, 1, data); \
        IOMEM (addr, 1, data); \
      /* We can't do anything useful with the other stuff, so fail.  */ \
      /* We can't do anything useful with the other stuff, so fail.  */ \
      raise_buserror (); \
      raise_buserror (); \
      return retval; \
      return retval; \
    } \
    } \
} while (0)
} while (0)
 
 
/* FIXME: sim_resume should be renamed to sim_engine_run.  sim_resume
/* FIXME: sim_resume should be renamed to sim_engine_run.  sim_resume
   being implemented by ../common/sim_resume.c and the below should
   being implemented by ../common/sim_resume.c and the below should
   make a call to sim_engine_halt */
   make a call to sim_engine_halt */
 
 
#define BUSERROR(addr, mask) ((addr) & (mask))
#define BUSERROR(addr, mask) ((addr) & (mask))
 
 
#define WRITE_BUSERROR(addr, mask, data, addr_func) \
#define WRITE_BUSERROR(addr, mask, data, addr_func) \
  do \
  do \
    { \
    { \
      if (addr & mask) \
      if (addr & mask) \
        { \
        { \
          addr_func (addr, data); \
          addr_func (addr, data); \
          return; \
          return; \
        } \
        } \
    } \
    } \
  while (0)
  while (0)
 
 
#define READ_BUSERROR(addr, mask, addr_func) \
#define READ_BUSERROR(addr, mask, addr_func) \
  do \
  do \
    { \
    { \
      if (addr & mask) \
      if (addr & mask) \
        return addr_func (addr); \
        return addr_func (addr); \
    } \
    } \
  while (0)
  while (0)
 
 
/* Define this to enable register lifetime checking.
/* Define this to enable register lifetime checking.
   The compiler generates "add #0,rn" insns to mark registers as invalid,
   The compiler generates "add #0,rn" insns to mark registers as invalid,
   the simulator uses this info to call fail if it finds a ref to an invalid
   the simulator uses this info to call fail if it finds a ref to an invalid
   register before a def
   register before a def
 
 
   #define PARANOID
   #define PARANOID
*/
*/
 
 
#ifdef PARANOID
#ifdef PARANOID
int valid[16];
int valid[16];
#define CREF(x)  if (!valid[x]) fail ();
#define CREF(x)  if (!valid[x]) fail ();
#define CDEF(x)  valid[x] = 1;
#define CDEF(x)  valid[x] = 1;
#define UNDEF(x) valid[x] = 0;
#define UNDEF(x) valid[x] = 0;
#else
#else
#define CREF(x)
#define CREF(x)
#define CDEF(x)
#define CDEF(x)
#define UNDEF(x)
#define UNDEF(x)
#endif
#endif
 
 
static void parse_and_set_memory_size PARAMS ((char *str));
static void parse_and_set_memory_size PARAMS ((char *str));
static int IOMEM PARAMS ((int addr, int write, int value));
static int IOMEM PARAMS ((int addr, int write, int value));
static struct loop_bounds get_loop_bounds PARAMS ((int, int, unsigned char *,
static struct loop_bounds get_loop_bounds PARAMS ((int, int, unsigned char *,
                                                   unsigned char *, int, int));
                                                   unsigned char *, int, int));
static void process_wlat_addr PARAMS ((int, int));
static void process_wlat_addr PARAMS ((int, int));
static void process_wwat_addr PARAMS ((int, int));
static void process_wwat_addr PARAMS ((int, int));
static void process_wbat_addr PARAMS ((int, int));
static void process_wbat_addr PARAMS ((int, int));
static int process_rlat_addr PARAMS ((int));
static int process_rlat_addr PARAMS ((int));
static int process_rwat_addr PARAMS ((int));
static int process_rwat_addr PARAMS ((int));
static int process_rbat_addr PARAMS ((int));
static int process_rbat_addr PARAMS ((int));
static void INLINE wlat_fast PARAMS ((unsigned char *, int, int, int));
static void INLINE wlat_fast PARAMS ((unsigned char *, int, int, int));
static void INLINE wwat_fast PARAMS ((unsigned char *, int, int, int, int));
static void INLINE wwat_fast PARAMS ((unsigned char *, int, int, int, int));
static void INLINE wbat_fast PARAMS ((unsigned char *, int, int, int));
static void INLINE wbat_fast PARAMS ((unsigned char *, int, int, int));
static int INLINE rlat_fast PARAMS ((unsigned char *, int, int));
static int INLINE rlat_fast PARAMS ((unsigned char *, int, int));
static int INLINE rwat_fast PARAMS ((unsigned char *, int, int, int));
static int INLINE rwat_fast PARAMS ((unsigned char *, int, int, int));
static int INLINE rbat_fast PARAMS ((unsigned char *, int, int));
static int INLINE rbat_fast PARAMS ((unsigned char *, int, int));
 
 
static host_callback *callback;
static host_callback *callback;
 
 
 
 
 
 
/* Floating point registers */
/* Floating point registers */
 
 
#define DR(n) (get_dr (n))
#define DR(n) (get_dr (n))
static double
static double
get_dr (n)
get_dr (n)
     int n;
     int n;
{
{
  n = (n & ~1);
  n = (n & ~1);
  if (host_little_endian)
  if (host_little_endian)
    {
    {
      union
      union
      {
      {
        int i[2];
        int i[2];
        double d;
        double d;
      } dr;
      } dr;
      dr.i[1] = saved_state.asregs.fregs[0].i[n + 0];
      dr.i[1] = saved_state.asregs.fregs[0].i[n + 0];
      dr.i[0] = saved_state.asregs.fregs[0].i[n + 1];
      dr.i[0] = saved_state.asregs.fregs[0].i[n + 1];
      return dr.d;
      return dr.d;
    }
    }
  else
  else
    return (saved_state.asregs.fregs[0].d[n >> 1]);
    return (saved_state.asregs.fregs[0].d[n >> 1]);
}
}
 
 
#define SET_DR(n, EXP) set_dr ((n), (EXP))
#define SET_DR(n, EXP) set_dr ((n), (EXP))
static void
static void
set_dr (n, exp)
set_dr (n, exp)
     int n;
     int n;
     double exp;
     double exp;
{
{
  n = (n & ~1);
  n = (n & ~1);
  if (host_little_endian)
  if (host_little_endian)
    {
    {
      union
      union
      {
      {
        int i[2];
        int i[2];
        double d;
        double d;
      } dr;
      } dr;
      dr.d = exp;
      dr.d = exp;
      saved_state.asregs.fregs[0].i[n + 0] = dr.i[1];
      saved_state.asregs.fregs[0].i[n + 0] = dr.i[1];
      saved_state.asregs.fregs[0].i[n + 1] = dr.i[0];
      saved_state.asregs.fregs[0].i[n + 1] = dr.i[0];
    }
    }
  else
  else
    saved_state.asregs.fregs[0].d[n >> 1] = exp;
    saved_state.asregs.fregs[0].d[n >> 1] = exp;
}
}
 
 
#define SET_FI(n,EXP) (saved_state.asregs.fregs[0].i[(n)] = (EXP))
#define SET_FI(n,EXP) (saved_state.asregs.fregs[0].i[(n)] = (EXP))
#define FI(n) (saved_state.asregs.fregs[0].i[(n)])
#define FI(n) (saved_state.asregs.fregs[0].i[(n)])
 
 
#define FR(n) (saved_state.asregs.fregs[0].f[(n)])
#define FR(n) (saved_state.asregs.fregs[0].f[(n)])
#define SET_FR(n,EXP) (saved_state.asregs.fregs[0].f[(n)] = (EXP))
#define SET_FR(n,EXP) (saved_state.asregs.fregs[0].f[(n)] = (EXP))
 
 
#define XD_TO_XF(n) ((((n) & 1) << 5) | ((n) & 0x1e))
#define XD_TO_XF(n) ((((n) & 1) << 5) | ((n) & 0x1e))
#define XF(n) (saved_state.asregs.fregs[(n) >> 5].i[(n) & 0x1f])
#define XF(n) (saved_state.asregs.fregs[(n) >> 5].i[(n) & 0x1f])
#define SET_XF(n,EXP) (saved_state.asregs.fregs[(n) >> 5].i[(n) & 0x1f] = (EXP))
#define SET_XF(n,EXP) (saved_state.asregs.fregs[(n) >> 5].i[(n) & 0x1f] = (EXP))
 
 
#define RS saved_state.asregs.cregs.named.rs
#define RS saved_state.asregs.cregs.named.rs
#define RE saved_state.asregs.cregs.named.re
#define RE saved_state.asregs.cregs.named.re
#define MOD (saved_state.asregs.cregs.named.mod)
#define MOD (saved_state.asregs.cregs.named.mod)
#define SET_MOD(i) \
#define SET_MOD(i) \
(MOD = (i), \
(MOD = (i), \
 MOD_ME = (unsigned) MOD >> 16 | (SR_DMY ? ~0xffff : (SR_DMX ? 0 : 0x10000)), \
 MOD_ME = (unsigned) MOD >> 16 | (SR_DMY ? ~0xffff : (SR_DMX ? 0 : 0x10000)), \
 MOD_DELTA = (MOD & 0xffff) - ((unsigned) MOD >> 16))
 MOD_DELTA = (MOD & 0xffff) - ((unsigned) MOD >> 16))
 
 
#define DSP_R(n) saved_state.asregs.sregs.i[(n)]
#define DSP_R(n) saved_state.asregs.sregs.i[(n)]
#define DSP_GRD(n) DSP_R ((n) + 8)
#define DSP_GRD(n) DSP_R ((n) + 8)
#define GET_DSP_GRD(n) ((n | 2) == 7 ? SEXT (DSP_GRD (n)) : SIGN32 (DSP_R (n)))
#define GET_DSP_GRD(n) ((n | 2) == 7 ? SEXT (DSP_GRD (n)) : SIGN32 (DSP_R (n)))
#define A1 DSP_R (5)
#define A1 DSP_R (5)
#define A0 DSP_R (7)
#define A0 DSP_R (7)
#define X0 DSP_R (8)
#define X0 DSP_R (8)
#define X1 DSP_R (9)
#define X1 DSP_R (9)
#define Y0 DSP_R (10)
#define Y0 DSP_R (10)
#define Y1 DSP_R (11)
#define Y1 DSP_R (11)
#define M0 DSP_R (12)
#define M0 DSP_R (12)
#define A1G DSP_R (13)
#define A1G DSP_R (13)
#define M1 DSP_R (14)
#define M1 DSP_R (14)
#define A0G DSP_R (15)
#define A0G DSP_R (15)
/* DSP_R (16) / DSP_GRD (16) are used as a fake destination for pcmp.  */
/* DSP_R (16) / DSP_GRD (16) are used as a fake destination for pcmp.  */
#define MOD_ME DSP_GRD (17)
#define MOD_ME DSP_GRD (17)
#define MOD_DELTA DSP_GRD (18)
#define MOD_DELTA DSP_GRD (18)
 
 
#define FP_OP(n, OP, m) \
#define FP_OP(n, OP, m) \
{ \
{ \
  if (FPSCR_PR) \
  if (FPSCR_PR) \
    { \
    { \
      if (((n) & 1) || ((m) & 1)) \
      if (((n) & 1) || ((m) & 1)) \
        RAISE_EXCEPTION (SIGILL); \
        RAISE_EXCEPTION (SIGILL); \
      else \
      else \
        SET_DR (n, (DR (n) OP DR (m))); \
        SET_DR (n, (DR (n) OP DR (m))); \
    } \
    } \
  else \
  else \
    SET_FR (n, (FR (n) OP FR (m))); \
    SET_FR (n, (FR (n) OP FR (m))); \
} while (0)
} while (0)
 
 
#define FP_UNARY(n, OP) \
#define FP_UNARY(n, OP) \
{ \
{ \
  if (FPSCR_PR) \
  if (FPSCR_PR) \
    { \
    { \
      if ((n) & 1) \
      if ((n) & 1) \
        RAISE_EXCEPTION (SIGILL); \
        RAISE_EXCEPTION (SIGILL); \
      else \
      else \
        SET_DR (n, (OP (DR (n)))); \
        SET_DR (n, (OP (DR (n)))); \
    } \
    } \
  else \
  else \
    SET_FR (n, (OP (FR (n)))); \
    SET_FR (n, (OP (FR (n)))); \
} while (0)
} while (0)
 
 
#define FP_CMP(n, OP, m) \
#define FP_CMP(n, OP, m) \
{ \
{ \
  if (FPSCR_PR) \
  if (FPSCR_PR) \
    { \
    { \
      if (((n) & 1) || ((m) & 1)) \
      if (((n) & 1) || ((m) & 1)) \
        RAISE_EXCEPTION (SIGILL); \
        RAISE_EXCEPTION (SIGILL); \
      else \
      else \
        SET_SR_T (DR (n) OP DR (m)); \
        SET_SR_T (DR (n) OP DR (m)); \
    } \
    } \
  else \
  else \
    SET_SR_T (FR (n) OP FR (m)); \
    SET_SR_T (FR (n) OP FR (m)); \
} while (0)
} while (0)
 
 
static void
static void
set_sr (new_sr)
set_sr (new_sr)
     int new_sr;
     int new_sr;
{
{
  /* do we need to swap banks */
  /* do we need to swap banks */
  int old_gpr = SR_MD && SR_RB;
  int old_gpr = SR_MD && SR_RB;
  int new_gpr = (new_sr & SR_MASK_MD) && (new_sr & SR_MASK_RB);
  int new_gpr = (new_sr & SR_MASK_MD) && (new_sr & SR_MASK_RB);
  if (old_gpr != new_gpr)
  if (old_gpr != new_gpr)
    {
    {
      int i, tmp;
      int i, tmp;
      for (i = 0; i < 8; i++)
      for (i = 0; i < 8; i++)
        {
        {
          tmp = saved_state.asregs.cregs.named.bank[i];
          tmp = saved_state.asregs.cregs.named.bank[i];
          saved_state.asregs.cregs.named.bank[i] = saved_state.asregs.regs[i];
          saved_state.asregs.cregs.named.bank[i] = saved_state.asregs.regs[i];
          saved_state.asregs.regs[i] = tmp;
          saved_state.asregs.regs[i] = tmp;
        }
        }
    }
    }
  saved_state.asregs.cregs.named.sr = new_sr;
  saved_state.asregs.cregs.named.sr = new_sr;
  SET_MOD (MOD);
  SET_MOD (MOD);
}
}
 
 
static void INLINE
static void INLINE
wlat_fast (memory, x, value, maskl)
wlat_fast (memory, x, value, maskl)
     unsigned char *memory;
     unsigned char *memory;
{
{
  int v = value;
  int v = value;
  unsigned int *p = (unsigned int *) (memory + x);
  unsigned int *p = (unsigned int *) (memory + x);
  WRITE_BUSERROR (x, maskl, v, process_wlat_addr);
  WRITE_BUSERROR (x, maskl, v, process_wlat_addr);
  *p = v;
  *p = v;
}
}
 
 
static void INLINE
static void INLINE
wwat_fast (memory, x, value, maskw, endianw)
wwat_fast (memory, x, value, maskw, endianw)
     unsigned char *memory;
     unsigned char *memory;
{
{
  int v = value;
  int v = value;
  unsigned short *p = (unsigned short *) (memory + (x ^ endianw));
  unsigned short *p = (unsigned short *) (memory + (x ^ endianw));
  WRITE_BUSERROR (x, maskw, v, process_wwat_addr);
  WRITE_BUSERROR (x, maskw, v, process_wwat_addr);
  *p = v;
  *p = v;
}
}
 
 
static void INLINE
static void INLINE
wbat_fast (memory, x, value, maskb)
wbat_fast (memory, x, value, maskb)
     unsigned char *memory;
     unsigned char *memory;
{
{
  unsigned char *p = memory + (x ^ endianb);
  unsigned char *p = memory + (x ^ endianb);
  WRITE_BUSERROR (x, maskb, value, process_wbat_addr);
  WRITE_BUSERROR (x, maskb, value, process_wbat_addr);
 
 
  p[0] = value;
  p[0] = value;
}
}
 
 
/* Read functions */
/* Read functions */
 
 
static int INLINE
static int INLINE
rlat_fast (memory, x, maskl)
rlat_fast (memory, x, maskl)
     unsigned char *memory;
     unsigned char *memory;
{
{
  unsigned int *p = (unsigned int *) (memory + x);
  unsigned int *p = (unsigned int *) (memory + x);
  READ_BUSERROR (x, maskl, process_rlat_addr);
  READ_BUSERROR (x, maskl, process_rlat_addr);
 
 
  return *p;
  return *p;
}
}
 
 
static int INLINE
static int INLINE
rwat_fast (memory, x, maskw, endianw)
rwat_fast (memory, x, maskw, endianw)
     unsigned char *memory;
     unsigned char *memory;
     int x, maskw, endianw;
     int x, maskw, endianw;
{
{
  unsigned short *p = (unsigned short *) (memory + (x ^ endianw));
  unsigned short *p = (unsigned short *) (memory + (x ^ endianw));
  READ_BUSERROR (x, maskw, process_rwat_addr);
  READ_BUSERROR (x, maskw, process_rwat_addr);
 
 
  return *p;
  return *p;
}
}
 
 
static int INLINE
static int INLINE
riat_fast (insn_ptr, endianw)
riat_fast (insn_ptr, endianw)
     unsigned char *insn_ptr;
     unsigned char *insn_ptr;
{
{
  unsigned short *p = (unsigned short *) ((size_t) insn_ptr ^ endianw);
  unsigned short *p = (unsigned short *) ((size_t) insn_ptr ^ endianw);
 
 
  return *p;
  return *p;
}
}
 
 
static int INLINE
static int INLINE
rbat_fast (memory, x, maskb)
rbat_fast (memory, x, maskb)
     unsigned char *memory;
     unsigned char *memory;
{
{
  unsigned char *p = memory + (x ^ endianb);
  unsigned char *p = memory + (x ^ endianb);
  READ_BUSERROR (x, maskb, process_rbat_addr);
  READ_BUSERROR (x, maskb, process_rbat_addr);
 
 
  return *p;
  return *p;
}
}
 
 
#define RWAT(x)         (rwat_fast (memory, x, maskw, endianw))
#define RWAT(x)         (rwat_fast (memory, x, maskw, endianw))
#define RLAT(x)         (rlat_fast (memory, x, maskl))
#define RLAT(x)         (rlat_fast (memory, x, maskl))
#define RBAT(x)         (rbat_fast (memory, x, maskb))
#define RBAT(x)         (rbat_fast (memory, x, maskb))
#define RIAT(p)         (riat_fast ((p), endianw))
#define RIAT(p)         (riat_fast ((p), endianw))
#define WWAT(x,v)       (wwat_fast (memory, x, v, maskw, endianw))
#define WWAT(x,v)       (wwat_fast (memory, x, v, maskw, endianw))
#define WLAT(x,v)       (wlat_fast (memory, x, v, maskl))
#define WLAT(x,v)       (wlat_fast (memory, x, v, maskl))
#define WBAT(x,v)       (wbat_fast (memory, x, v, maskb))
#define WBAT(x,v)       (wbat_fast (memory, x, v, maskb))
 
 
#define RUWAT(x)  (RWAT (x) & 0xffff)
#define RUWAT(x)  (RWAT (x) & 0xffff)
#define RSWAT(x)  ((short) (RWAT (x)))
#define RSWAT(x)  ((short) (RWAT (x)))
#define RSLAT(x)  ((long) (RLAT (x)))
#define RSLAT(x)  ((long) (RLAT (x)))
#define RSBAT(x)  (SEXT (RBAT (x)))
#define RSBAT(x)  (SEXT (RBAT (x)))
 
 
#define RDAT(x, n) (do_rdat (memory, (x), (n), (maskl)))
#define RDAT(x, n) (do_rdat (memory, (x), (n), (maskl)))
static int
static int
do_rdat (memory, x, n, maskl)
do_rdat (memory, x, n, maskl)
     char *memory;
     char *memory;
     int x;
     int x;
     int n;
     int n;
     int maskl;
     int maskl;
{
{
  int f0;
  int f0;
  int f1;
  int f1;
  int i = (n & 1);
  int i = (n & 1);
  int j = (n & ~1);
  int j = (n & ~1);
  f0 = rlat_fast (memory, x + 0, maskl);
  f0 = rlat_fast (memory, x + 0, maskl);
  f1 = rlat_fast (memory, x + 4, maskl);
  f1 = rlat_fast (memory, x + 4, maskl);
  saved_state.asregs.fregs[i].i[(j + 0)] = f0;
  saved_state.asregs.fregs[i].i[(j + 0)] = f0;
  saved_state.asregs.fregs[i].i[(j + 1)] = f1;
  saved_state.asregs.fregs[i].i[(j + 1)] = f1;
  return 0;
  return 0;
}
}
 
 
#define WDAT(x, n) (do_wdat (memory, (x), (n), (maskl)))
#define WDAT(x, n) (do_wdat (memory, (x), (n), (maskl)))
static int
static int
do_wdat (memory, x, n, maskl)
do_wdat (memory, x, n, maskl)
     char *memory;
     char *memory;
     int x;
     int x;
     int n;
     int n;
     int maskl;
     int maskl;
{
{
  int f0;
  int f0;
  int f1;
  int f1;
  int i = (n & 1);
  int i = (n & 1);
  int j = (n & ~1);
  int j = (n & ~1);
  f0 = saved_state.asregs.fregs[i].i[(j + 0)];
  f0 = saved_state.asregs.fregs[i].i[(j + 0)];
  f1 = saved_state.asregs.fregs[i].i[(j + 1)];
  f1 = saved_state.asregs.fregs[i].i[(j + 1)];
  wlat_fast (memory, (x + 0), f0, maskl);
  wlat_fast (memory, (x + 0), f0, maskl);
  wlat_fast (memory, (x + 4), f1, maskl);
  wlat_fast (memory, (x + 4), f1, maskl);
  return 0;
  return 0;
}
}
 
 
static void
static void
process_wlat_addr (addr, value)
process_wlat_addr (addr, value)
     int addr;
     int addr;
     int value;
     int value;
{
{
  unsigned int *ptr;
  unsigned int *ptr;
 
 
  PROCESS_SPECIAL_ADDRESS (addr, endianb, ptr, 32, 3, value, );
  PROCESS_SPECIAL_ADDRESS (addr, endianb, ptr, 32, 3, value, );
  *ptr = value;
  *ptr = value;
}
}
 
 
static void
static void
process_wwat_addr (addr, value)
process_wwat_addr (addr, value)
     int addr;
     int addr;
     int value;
     int value;
{
{
  unsigned short *ptr;
  unsigned short *ptr;
 
 
  PROCESS_SPECIAL_ADDRESS (addr, endianb, ptr, 16, 1, value, );
  PROCESS_SPECIAL_ADDRESS (addr, endianb, ptr, 16, 1, value, );
  *ptr = value;
  *ptr = value;
}
}
 
 
static void
static void
process_wbat_addr (addr, value)
process_wbat_addr (addr, value)
     int addr;
     int addr;
     int value;
     int value;
{
{
  unsigned char *ptr;
  unsigned char *ptr;
 
 
  PROCESS_SPECIAL_ADDRESS (addr, endianb, ptr, 8, 0, value, );
  PROCESS_SPECIAL_ADDRESS (addr, endianb, ptr, 8, 0, value, );
  *ptr = value;
  *ptr = value;
}
}
 
 
static int
static int
process_rlat_addr (addr)
process_rlat_addr (addr)
     int addr;
     int addr;
{
{
  unsigned char *ptr;
  unsigned char *ptr;
 
 
  PROCESS_SPECIAL_ADDRESS (addr, endianb, ptr, -32, 3, -1, 0);
  PROCESS_SPECIAL_ADDRESS (addr, endianb, ptr, -32, 3, -1, 0);
  return *ptr;
  return *ptr;
}
}
 
 
static int
static int
process_rwat_addr (addr)
process_rwat_addr (addr)
     int addr;
     int addr;
{
{
  unsigned char *ptr;
  unsigned char *ptr;
 
 
  PROCESS_SPECIAL_ADDRESS (addr, endianb, ptr, -16, 1, -1, 0);
  PROCESS_SPECIAL_ADDRESS (addr, endianb, ptr, -16, 1, -1, 0);
  return *ptr;
  return *ptr;
}
}
 
 
static int
static int
process_rbat_addr (addr)
process_rbat_addr (addr)
     int addr;
     int addr;
{
{
  unsigned char *ptr;
  unsigned char *ptr;
 
 
  PROCESS_SPECIAL_ADDRESS (addr, endianb, ptr, -8, 0, -1, 0);
  PROCESS_SPECIAL_ADDRESS (addr, endianb, ptr, -8, 0, -1, 0);
  return *ptr;
  return *ptr;
}
}
 
 
#define SEXT(x)         (((x &  0xff) ^ (~0x7f))+0x80)
#define SEXT(x)         (((x &  0xff) ^ (~0x7f))+0x80)
#define SEXT12(x)       (((x & 0xfff) ^ 0x800) - 0x800)
#define SEXT12(x)       (((x & 0xfff) ^ 0x800) - 0x800)
#define SEXTW(y)        ((int) ((short) y))
#define SEXTW(y)        ((int) ((short) y))
#if 0
#if 0
#define SEXT32(x)       ((int) ((x & 0xffffffff) ^ 0x80000000U) - 0x7fffffff - 1)
#define SEXT32(x)       ((int) ((x & 0xffffffff) ^ 0x80000000U) - 0x7fffffff - 1)
#else
#else
#define SEXT32(x)       ((int) (x))
#define SEXT32(x)       ((int) (x))
#endif
#endif
#define SIGN32(x)       (SEXT32 (x) >> 31)
#define SIGN32(x)       (SEXT32 (x) >> 31)
 
 
/* convert pointer from target to host value.  */
/* convert pointer from target to host value.  */
#define PT2H(x) ((x) + memory)
#define PT2H(x) ((x) + memory)
/* convert pointer from host to target value.  */
/* convert pointer from host to target value.  */
#define PH2T(x) ((x) - memory)
#define PH2T(x) ((x) - memory)
 
 
#define SKIP_INSN(p) ((p) += ((RIAT (p) & 0xfc00) == 0xf800 ? 4 : 2))
#define SKIP_INSN(p) ((p) += ((RIAT (p) & 0xfc00) == 0xf800 ? 4 : 2))
 
 
#define SET_NIP(x) nip = (x); CHECK_INSN_PTR (nip);
#define SET_NIP(x) nip = (x); CHECK_INSN_PTR (nip);
 
 
static int in_delay_slot = 0;
static int in_delay_slot = 0;
#define Delay_Slot(TEMPPC)      iword = RIAT (TEMPPC); in_delay_slot = 1; goto top;
#define Delay_Slot(TEMPPC)      iword = RIAT (TEMPPC); in_delay_slot = 1; goto top;
 
 
#define CHECK_INSN_PTR(p) \
#define CHECK_INSN_PTR(p) \
do { \
do { \
  if (saved_state.asregs.exception || PH2T (p) & maskw) \
  if (saved_state.asregs.exception || PH2T (p) & maskw) \
    saved_state.asregs.insn_end = 0; \
    saved_state.asregs.insn_end = 0; \
  else if (p < loop.end) \
  else if (p < loop.end) \
    saved_state.asregs.insn_end = loop.end; \
    saved_state.asregs.insn_end = loop.end; \
  else \
  else \
    saved_state.asregs.insn_end = mem_end; \
    saved_state.asregs.insn_end = mem_end; \
} while (0)
} while (0)
 
 
#ifdef ACE_FAST
#ifdef ACE_FAST
 
 
#define MA(n)
#define MA(n)
#define L(x)
#define L(x)
#define TL(x)
#define TL(x)
#define TB(x)
#define TB(x)
 
 
#else
#else
 
 
#define MA(n) \
#define MA(n) \
  do { memstalls += ((((int) PC & 3) != 0) ? (n) : ((n) - 1)); } while (0)
  do { memstalls += ((((int) PC & 3) != 0) ? (n) : ((n) - 1)); } while (0)
 
 
#define L(x)   thislock = x;
#define L(x)   thislock = x;
#define TL(x)  if ((x) == prevlock) stalls++;
#define TL(x)  if ((x) == prevlock) stalls++;
#define TB(x,y)  if ((x) == prevlock || (y) == prevlock) stalls++;
#define TB(x,y)  if ((x) == prevlock || (y) == prevlock) stalls++;
 
 
#endif
#endif
 
 
#if defined(__GO32__)
#if defined(__GO32__)
int sim_memory_size = 19;
int sim_memory_size = 19;
#else
#else
int sim_memory_size = 24;
int sim_memory_size = 24;
#endif
#endif
 
 
static int sim_profile_size = 17;
static int sim_profile_size = 17;
static int nsamples;
static int nsamples;
 
 
#undef TB
#undef TB
#define TB(x,y)
#define TB(x,y)
 
 
#define SMR1 (0x05FFFEC8)       /* Channel 1  serial mode register */
#define SMR1 (0x05FFFEC8)       /* Channel 1  serial mode register */
#define BRR1 (0x05FFFEC9)       /* Channel 1  bit rate register */
#define BRR1 (0x05FFFEC9)       /* Channel 1  bit rate register */
#define SCR1 (0x05FFFECA)       /* Channel 1  serial control register */
#define SCR1 (0x05FFFECA)       /* Channel 1  serial control register */
#define TDR1 (0x05FFFECB)       /* Channel 1  transmit data register */
#define TDR1 (0x05FFFECB)       /* Channel 1  transmit data register */
#define SSR1 (0x05FFFECC)       /* Channel 1  serial status register */
#define SSR1 (0x05FFFECC)       /* Channel 1  serial status register */
#define RDR1 (0x05FFFECD)       /* Channel 1  receive data register */
#define RDR1 (0x05FFFECD)       /* Channel 1  receive data register */
 
 
#define SCI_RDRF         0x40   /* Recieve data register full */
#define SCI_RDRF         0x40   /* Recieve data register full */
#define SCI_TDRE        0x80    /* Transmit data register empty */
#define SCI_TDRE        0x80    /* Transmit data register empty */
 
 
static int
static int
IOMEM (addr, write, value)
IOMEM (addr, write, value)
     int addr;
     int addr;
     int write;
     int write;
     int value;
     int value;
{
{
  if (write)
  if (write)
    {
    {
      switch (addr)
      switch (addr)
        {
        {
        case TDR1:
        case TDR1:
          if (value != '\r')
          if (value != '\r')
            {
            {
              putchar (value);
              putchar (value);
              fflush (stdout);
              fflush (stdout);
            }
            }
          break;
          break;
        }
        }
    }
    }
  else
  else
    {
    {
      switch (addr)
      switch (addr)
        {
        {
        case RDR1:
        case RDR1:
          return getchar ();
          return getchar ();
        }
        }
    }
    }
  return 0;
  return 0;
}
}
 
 
static int
static int
get_now ()
get_now ()
{
{
  return time ((long *) 0);
  return time ((long *) 0);
}
}
 
 
static int
static int
now_persec ()
now_persec ()
{
{
  return 1;
  return 1;
}
}
 
 
static FILE *profile_file;
static FILE *profile_file;
 
 
static unsigned INLINE
static unsigned INLINE
swap (n)
swap (n)
     unsigned n;
     unsigned n;
{
{
  if (endianb)
  if (endianb)
    n = (n << 24 | (n & 0xff00) << 8
    n = (n << 24 | (n & 0xff00) << 8
         | (n & 0xff0000) >> 8 | (n & 0xff000000) >> 24);
         | (n & 0xff0000) >> 8 | (n & 0xff000000) >> 24);
  return n;
  return n;
}
}
 
 
static unsigned short INLINE
static unsigned short INLINE
swap16 (n)
swap16 (n)
     unsigned short n;
     unsigned short n;
{
{
  if (endianb)
  if (endianb)
    n = n << 8 | (n & 0xff00) >> 8;
    n = n << 8 | (n & 0xff00) >> 8;
  return n;
  return n;
}
}
 
 
static void
static void
swapout (n)
swapout (n)
     int n;
     int n;
{
{
  if (profile_file)
  if (profile_file)
    {
    {
      union { char b[4]; int n; } u;
      union { char b[4]; int n; } u;
      u.n = swap (n);
      u.n = swap (n);
      fwrite (u.b, 4, 1, profile_file);
      fwrite (u.b, 4, 1, profile_file);
    }
    }
}
}
 
 
static void
static void
swapout16 (n)
swapout16 (n)
     int n;
     int n;
{
{
  union { char b[4]; int n; } u;
  union { char b[4]; int n; } u;
  u.n = swap16 (n);
  u.n = swap16 (n);
  fwrite (u.b, 2, 1, profile_file);
  fwrite (u.b, 2, 1, profile_file);
}
}
 
 
/* Turn a pointer in a register into a pointer into real memory. */
/* Turn a pointer in a register into a pointer into real memory. */
 
 
static char *
static char *
ptr (x)
ptr (x)
     int x;
     int x;
{
{
  return (char *) (x + saved_state.asregs.memory);
  return (char *) (x + saved_state.asregs.memory);
}
}
 
 
/* STR points to a zero-terminated string in target byte order.  Return
/* STR points to a zero-terminated string in target byte order.  Return
   the number of bytes that need to be converted to host byte order in order
   the number of bytes that need to be converted to host byte order in order
   to use this string as a zero-terminated string on the host.
   to use this string as a zero-terminated string on the host.
   (Not counting the rounding up needed to operate on entire words.)  */
   (Not counting the rounding up needed to operate on entire words.)  */
static int
static int
strswaplen (str)
strswaplen (str)
     int str;
     int str;
{
{
  unsigned char *memory = saved_state.asregs.memory;
  unsigned char *memory = saved_state.asregs.memory;
  int start, end;
  int start, end;
  int endian = endianb;
  int endian = endianb;
 
 
  if (! endian)
  if (! endian)
    return 0;
    return 0;
  end = str;
  end = str;
  for (end = str; memory[end ^ endian]; end++) ;
  for (end = str; memory[end ^ endian]; end++) ;
  return end - str + 1;
  return end - str + 1;
}
}
 
 
static void
static void
strnswap (str, len)
strnswap (str, len)
     int str;
     int str;
     int len;
     int len;
{
{
  int *start, *end;
  int *start, *end;
 
 
  if (! endianb || ! len)
  if (! endianb || ! len)
    return;
    return;
  start = (int *) ptr (str & ~3);
  start = (int *) ptr (str & ~3);
  end = (int *) ptr (str + len);
  end = (int *) ptr (str + len);
  do
  do
    {
    {
      int old = *start;
      int old = *start;
      *start = (old << 24 | (old & 0xff00) << 8
      *start = (old << 24 | (old & 0xff00) << 8
                | (old & 0xff0000) >> 8 | (old & 0xff000000) >> 24);
                | (old & 0xff0000) >> 8 | (old & 0xff000000) >> 24);
      start++;
      start++;
    }
    }
  while (start < end);
  while (start < end);
}
}
 
 
/* Simulate a monitor trap, put the result into r0 and errno into r1
/* Simulate a monitor trap, put the result into r0 and errno into r1
   return offset by which to adjust pc.  */
   return offset by which to adjust pc.  */
 
 
static int
static int
trap (i, regs, insn_ptr, memory, maskl, maskw, endianw)
trap (i, regs, insn_ptr, memory, maskl, maskw, endianw)
     int i;
     int i;
     int *regs;
     int *regs;
     unsigned char *insn_ptr;
     unsigned char *insn_ptr;
     unsigned char *memory;
     unsigned char *memory;
{
{
  switch (i)
  switch (i)
    {
    {
    case 1:
    case 1:
      printf ("%c", regs[0]);
      printf ("%c", regs[0]);
      break;
      break;
    case 2:
    case 2:
      raise_exception (SIGQUIT);
      raise_exception (SIGQUIT);
      break;
      break;
    case 3:                     /* FIXME: for backwards compat, should be removed */
    case 3:                     /* FIXME: for backwards compat, should be removed */
    case 33:
    case 33:
      {
      {
        unsigned int countp = * (unsigned int *) (insn_ptr + 4);
        unsigned int countp = * (unsigned int *) (insn_ptr + 4);
 
 
        WLAT (countp, RLAT (countp) + 1);
        WLAT (countp, RLAT (countp) + 1);
        return 6;
        return 6;
      }
      }
    case 34:
    case 34:
      {
      {
        extern int errno;
        extern int errno;
        int perrno = errno;
        int perrno = errno;
        errno = 0;
        errno = 0;
 
 
        switch (regs[4])
        switch (regs[4])
          {
          {
 
 
#if !defined(__GO32__) && !defined(_WIN32)
#if !defined(__GO32__) && !defined(_WIN32)
          case SYS_fork:
          case SYS_fork:
            regs[0] = fork ();
            regs[0] = fork ();
            break;
            break;
/* This would work only if endianness matched between host and target.
/* This would work only if endianness matched between host and target.
   Besides, it's quite dangerous.  */
   Besides, it's quite dangerous.  */
#if 0
#if 0
          case SYS_execve:
          case SYS_execve:
            regs[0] = execve (ptr (regs[5]), (char **) ptr (regs[6]),
            regs[0] = execve (ptr (regs[5]), (char **) ptr (regs[6]),
                              (char **) ptr (regs[7]));
                              (char **) ptr (regs[7]));
            break;
            break;
          case SYS_execv:
          case SYS_execv:
            regs[0] = execve (ptr (regs[5]), (char **) ptr (regs[6]), 0);
            regs[0] = execve (ptr (regs[5]), (char **) ptr (regs[6]), 0);
            break;
            break;
#endif
#endif
          case SYS_pipe:
          case SYS_pipe:
            {
            {
              regs[0] = (BUSERROR (regs[5], maskl)
              regs[0] = (BUSERROR (regs[5], maskl)
                         ? -EINVAL
                         ? -EINVAL
                         : pipe ((int *) ptr (regs[5])));
                         : pipe ((int *) ptr (regs[5])));
            }
            }
            break;
            break;
 
 
          case SYS_wait:
          case SYS_wait:
            regs[0] = wait (ptr (regs[5]));
            regs[0] = wait (ptr (regs[5]));
            break;
            break;
#endif /* !defined(__GO32__) && !defined(_WIN32) */
#endif /* !defined(__GO32__) && !defined(_WIN32) */
 
 
          case SYS_read:
          case SYS_read:
            strnswap (regs[6], regs[7]);
            strnswap (regs[6], regs[7]);
            regs[0]
            regs[0]
              = callback->read (callback, regs[5], ptr (regs[6]), regs[7]);
              = callback->read (callback, regs[5], ptr (regs[6]), regs[7]);
            strnswap (regs[6], regs[7]);
            strnswap (regs[6], regs[7]);
            break;
            break;
          case SYS_write:
          case SYS_write:
            strnswap (regs[6], regs[7]);
            strnswap (regs[6], regs[7]);
            if (regs[5] == 1)
            if (regs[5] == 1)
              regs[0] = (int) callback->write_stdout (callback,
              regs[0] = (int) callback->write_stdout (callback,
                                                      ptr (regs[6]), regs[7]);
                                                      ptr (regs[6]), regs[7]);
            else
            else
              regs[0] = (int) callback->write (callback, regs[5],
              regs[0] = (int) callback->write (callback, regs[5],
                                               ptr (regs[6]), regs[7]);
                                               ptr (regs[6]), regs[7]);
            strnswap (regs[6], regs[7]);
            strnswap (regs[6], regs[7]);
            break;
            break;
          case SYS_lseek:
          case SYS_lseek:
            regs[0] = callback->lseek (callback,regs[5], regs[6], regs[7]);
            regs[0] = callback->lseek (callback,regs[5], regs[6], regs[7]);
            break;
            break;
          case SYS_close:
          case SYS_close:
            regs[0] = callback->close (callback,regs[5]);
            regs[0] = callback->close (callback,regs[5]);
            break;
            break;
          case SYS_open:
          case SYS_open:
            {
            {
              int len = strswaplen (regs[5]);
              int len = strswaplen (regs[5]);
              strnswap (regs[5], len);
              strnswap (regs[5], len);
              regs[0] = callback->open (callback, ptr (regs[5]), regs[6]);
              regs[0] = callback->open (callback, ptr (regs[5]), regs[6]);
              strnswap (regs[5], len);
              strnswap (regs[5], len);
              break;
              break;
            }
            }
          case SYS_exit:
          case SYS_exit:
            /* EXIT - caller can look in r5 to work out the reason */
            /* EXIT - caller can look in r5 to work out the reason */
            raise_exception (SIGQUIT);
            raise_exception (SIGQUIT);
            regs[0] = regs[5];
            regs[0] = regs[5];
            break;
            break;
 
 
          case SYS_stat:        /* added at hmsi */
          case SYS_stat:        /* added at hmsi */
            /* stat system call */
            /* stat system call */
            {
            {
              struct stat host_stat;
              struct stat host_stat;
              int buf;
              int buf;
              int len = strswaplen (regs[5]);
              int len = strswaplen (regs[5]);
 
 
              strnswap (regs[5], len);
              strnswap (regs[5], len);
              regs[0] = stat (ptr (regs[5]), &host_stat);
              regs[0] = stat (ptr (regs[5]), &host_stat);
              strnswap (regs[5], len);
              strnswap (regs[5], len);
 
 
              buf = regs[6];
              buf = regs[6];
 
 
              WWAT (buf, host_stat.st_dev);
              WWAT (buf, host_stat.st_dev);
              buf += 2;
              buf += 2;
              WWAT (buf, host_stat.st_ino);
              WWAT (buf, host_stat.st_ino);
              buf += 2;
              buf += 2;
              WLAT (buf, host_stat.st_mode);
              WLAT (buf, host_stat.st_mode);
              buf += 4;
              buf += 4;
              WWAT (buf, host_stat.st_nlink);
              WWAT (buf, host_stat.st_nlink);
              buf += 2;
              buf += 2;
              WWAT (buf, host_stat.st_uid);
              WWAT (buf, host_stat.st_uid);
              buf += 2;
              buf += 2;
              WWAT (buf, host_stat.st_gid);
              WWAT (buf, host_stat.st_gid);
              buf += 2;
              buf += 2;
              WWAT (buf, host_stat.st_rdev);
              WWAT (buf, host_stat.st_rdev);
              buf += 2;
              buf += 2;
              WLAT (buf, host_stat.st_size);
              WLAT (buf, host_stat.st_size);
              buf += 4;
              buf += 4;
              WLAT (buf, host_stat.st_atime);
              WLAT (buf, host_stat.st_atime);
              buf += 4;
              buf += 4;
              WLAT (buf, 0);
              WLAT (buf, 0);
              buf += 4;
              buf += 4;
              WLAT (buf, host_stat.st_mtime);
              WLAT (buf, host_stat.st_mtime);
              buf += 4;
              buf += 4;
              WLAT (buf, 0);
              WLAT (buf, 0);
              buf += 4;
              buf += 4;
              WLAT (buf, host_stat.st_ctime);
              WLAT (buf, host_stat.st_ctime);
              buf += 4;
              buf += 4;
              WLAT (buf, 0);
              WLAT (buf, 0);
              buf += 4;
              buf += 4;
              WLAT (buf, 0);
              WLAT (buf, 0);
              buf += 4;
              buf += 4;
              WLAT (buf, 0);
              WLAT (buf, 0);
              buf += 4;
              buf += 4;
            }
            }
            break;
            break;
 
 
#ifndef _WIN32
#ifndef _WIN32
          case SYS_chown:
          case SYS_chown:
            {
            {
              int len = strswaplen (regs[5]);
              int len = strswaplen (regs[5]);
 
 
              strnswap (regs[5], len);
              strnswap (regs[5], len);
              regs[0] = chown (ptr (regs[5]), regs[6], regs[7]);
              regs[0] = chown (ptr (regs[5]), regs[6], regs[7]);
              strnswap (regs[5], len);
              strnswap (regs[5], len);
              break;
              break;
            }
            }
#endif /* _WIN32 */
#endif /* _WIN32 */
          case SYS_chmod:
          case SYS_chmod:
            {
            {
              int len = strswaplen (regs[5]);
              int len = strswaplen (regs[5]);
 
 
              strnswap (regs[5], len);
              strnswap (regs[5], len);
              regs[0] = chmod (ptr (regs[5]), regs[6]);
              regs[0] = chmod (ptr (regs[5]), regs[6]);
              strnswap (regs[5], len);
              strnswap (regs[5], len);
              break;
              break;
            }
            }
          case SYS_utime:
          case SYS_utime:
            {
            {
              /* Cast the second argument to void *, to avoid type mismatch
              /* Cast the second argument to void *, to avoid type mismatch
                 if a prototype is present.  */
                 if a prototype is present.  */
              int len = strswaplen (regs[5]);
              int len = strswaplen (regs[5]);
 
 
              strnswap (regs[5], len);
              strnswap (regs[5], len);
              regs[0] = utime (ptr (regs[5]), (void *) ptr (regs[6]));
              regs[0] = utime (ptr (regs[5]), (void *) ptr (regs[6]));
              strnswap (regs[5], len);
              strnswap (regs[5], len);
              break;
              break;
            }
            }
          case SYS_argc:
          case SYS_argc:
            regs[0] = count_argc (prog_argv);
            regs[0] = count_argc (prog_argv);
            break;
            break;
          case SYS_argnlen:
          case SYS_argnlen:
            if (regs[5] < count_argc (prog_argv))
            if (regs[5] < count_argc (prog_argv))
              regs[0] = strlen (prog_argv[regs[5]]);
              regs[0] = strlen (prog_argv[regs[5]]);
            else
            else
              regs[0] = -1;
              regs[0] = -1;
            break;
            break;
          case SYS_argn:
          case SYS_argn:
            if (regs[5] < count_argc (prog_argv))
            if (regs[5] < count_argc (prog_argv))
              {
              {
                /* Include the termination byte.  */
                /* Include the termination byte.  */
                int i = strlen (prog_argv[regs[5]]) + 1;
                int i = strlen (prog_argv[regs[5]]) + 1;
                regs[0] = sim_write (0, regs[6], prog_argv[regs[5]], i);
                regs[0] = sim_write (0, regs[6], prog_argv[regs[5]], i);
              }
              }
            else
            else
              regs[0] = -1;
              regs[0] = -1;
            break;
            break;
          case SYS_time:
          case SYS_time:
            regs[0] = get_now ();
            regs[0] = get_now ();
            break;
            break;
          case SYS_ftruncate:
          case SYS_ftruncate:
            regs[0] = callback->ftruncate (callback, regs[5], regs[6]);
            regs[0] = callback->ftruncate (callback, regs[5], regs[6]);
            break;
            break;
          case SYS_truncate:
          case SYS_truncate:
            {
            {
              int len = strswaplen (regs[5]);
              int len = strswaplen (regs[5]);
              strnswap (regs[5], len);
              strnswap (regs[5], len);
              regs[0] = callback->truncate (callback, ptr (regs[5]), regs[6]);
              regs[0] = callback->truncate (callback, ptr (regs[5]), regs[6]);
              strnswap (regs[5], len);
              strnswap (regs[5], len);
              break;
              break;
            }
            }
          default:
          default:
            regs[0] = -1;
            regs[0] = -1;
            break;
            break;
          }
          }
        regs[1] = callback->get_errno (callback);
        regs[1] = callback->get_errno (callback);
        errno = perrno;
        errno = perrno;
      }
      }
      break;
      break;
 
 
    case 13:    /* Set IBNR */
    case 13:    /* Set IBNR */
      IBNR = regs[0] & 0xffff;
      IBNR = regs[0] & 0xffff;
      break;
      break;
    case 14:    /* Set IBCR */
    case 14:    /* Set IBCR */
      IBCR = regs[0] & 0xffff;
      IBCR = regs[0] & 0xffff;
      break;
      break;
    case 0xc3:
    case 0xc3:
    case 255:
    case 255:
      raise_exception (SIGTRAP);
      raise_exception (SIGTRAP);
      if (i == 0xc3)
      if (i == 0xc3)
        return -2;
        return -2;
      break;
      break;
    }
    }
  return 0;
  return 0;
}
}
 
 
void
void
control_c (sig, code, scp, addr)
control_c (sig, code, scp, addr)
     int sig;
     int sig;
     int code;
     int code;
     char *scp;
     char *scp;
     char *addr;
     char *addr;
{
{
  raise_exception (SIGINT);
  raise_exception (SIGINT);
}
}
 
 
static int
static int
div1 (R, iRn2, iRn1/*, T*/)
div1 (R, iRn2, iRn1/*, T*/)
     int *R;
     int *R;
     int iRn1;
     int iRn1;
     int iRn2;
     int iRn2;
     /* int T;*/
     /* int T;*/
{
{
  unsigned long tmp0;
  unsigned long tmp0;
  unsigned char old_q, tmp1;
  unsigned char old_q, tmp1;
 
 
  old_q = Q;
  old_q = Q;
  SET_SR_Q ((unsigned char) ((0x80000000 & R[iRn1]) != 0));
  SET_SR_Q ((unsigned char) ((0x80000000 & R[iRn1]) != 0));
  R[iRn1] <<= 1;
  R[iRn1] <<= 1;
  R[iRn1] |= (unsigned long) T;
  R[iRn1] |= (unsigned long) T;
 
 
  switch (old_q)
  switch (old_q)
    {
    {
    case 0:
    case 0:
      switch (M)
      switch (M)
        {
        {
        case 0:
        case 0:
          tmp0 = R[iRn1];
          tmp0 = R[iRn1];
          R[iRn1] -= R[iRn2];
          R[iRn1] -= R[iRn2];
          tmp1 = (R[iRn1] > tmp0);
          tmp1 = (R[iRn1] > tmp0);
          switch (Q)
          switch (Q)
            {
            {
            case 0:
            case 0:
              SET_SR_Q (tmp1);
              SET_SR_Q (tmp1);
              break;
              break;
            case 1:
            case 1:
              SET_SR_Q ((unsigned char) (tmp1 == 0));
              SET_SR_Q ((unsigned char) (tmp1 == 0));
              break;
              break;
            }
            }
          break;
          break;
        case 1:
        case 1:
          tmp0 = R[iRn1];
          tmp0 = R[iRn1];
          R[iRn1] += R[iRn2];
          R[iRn1] += R[iRn2];
          tmp1 = (R[iRn1] < tmp0);
          tmp1 = (R[iRn1] < tmp0);
          switch (Q)
          switch (Q)
            {
            {
            case 0:
            case 0:
              SET_SR_Q ((unsigned char) (tmp1 == 0));
              SET_SR_Q ((unsigned char) (tmp1 == 0));
              break;
              break;
            case 1:
            case 1:
              SET_SR_Q (tmp1);
              SET_SR_Q (tmp1);
              break;
              break;
            }
            }
          break;
          break;
        }
        }
      break;
      break;
    case 1:
    case 1:
      switch (M)
      switch (M)
        {
        {
        case 0:
        case 0:
          tmp0 = R[iRn1];
          tmp0 = R[iRn1];
          R[iRn1] += R[iRn2];
          R[iRn1] += R[iRn2];
          tmp1 = (R[iRn1] < tmp0);
          tmp1 = (R[iRn1] < tmp0);
          switch (Q)
          switch (Q)
            {
            {
            case 0:
            case 0:
              SET_SR_Q (tmp1);
              SET_SR_Q (tmp1);
              break;
              break;
            case 1:
            case 1:
              SET_SR_Q ((unsigned char) (tmp1 == 0));
              SET_SR_Q ((unsigned char) (tmp1 == 0));
              break;
              break;
            }
            }
          break;
          break;
        case 1:
        case 1:
          tmp0 = R[iRn1];
          tmp0 = R[iRn1];
          R[iRn1] -= R[iRn2];
          R[iRn1] -= R[iRn2];
          tmp1 = (R[iRn1] > tmp0);
          tmp1 = (R[iRn1] > tmp0);
          switch (Q)
          switch (Q)
            {
            {
            case 0:
            case 0:
              SET_SR_Q ((unsigned char) (tmp1 == 0));
              SET_SR_Q ((unsigned char) (tmp1 == 0));
              break;
              break;
            case 1:
            case 1:
              SET_SR_Q (tmp1);
              SET_SR_Q (tmp1);
              break;
              break;
            }
            }
          break;
          break;
        }
        }
      break;
      break;
    }
    }
  /*T = (Q == M);*/
  /*T = (Q == M);*/
  SET_SR_T (Q == M);
  SET_SR_T (Q == M);
  /*return T;*/
  /*return T;*/
}
}
 
 
static void
static void
dmul (sign, rm, rn)
dmul (sign, rm, rn)
     int sign;
     int sign;
     unsigned int rm;
     unsigned int rm;
     unsigned int rn;
     unsigned int rn;
{
{
  unsigned long RnL, RnH;
  unsigned long RnL, RnH;
  unsigned long RmL, RmH;
  unsigned long RmL, RmH;
  unsigned long temp0, temp1, temp2, temp3;
  unsigned long temp0, temp1, temp2, temp3;
  unsigned long Res2, Res1, Res0;
  unsigned long Res2, Res1, Res0;
 
 
  RnL = rn & 0xffff;
  RnL = rn & 0xffff;
  RnH = (rn >> 16) & 0xffff;
  RnH = (rn >> 16) & 0xffff;
  RmL = rm & 0xffff;
  RmL = rm & 0xffff;
  RmH = (rm >> 16) & 0xffff;
  RmH = (rm >> 16) & 0xffff;
  temp0 = RmL * RnL;
  temp0 = RmL * RnL;
  temp1 = RmH * RnL;
  temp1 = RmH * RnL;
  temp2 = RmL * RnH;
  temp2 = RmL * RnH;
  temp3 = RmH * RnH;
  temp3 = RmH * RnH;
  Res2 = 0;
  Res2 = 0;
  Res1 = temp1 + temp2;
  Res1 = temp1 + temp2;
  if (Res1 < temp1)
  if (Res1 < temp1)
    Res2 += 0x00010000;
    Res2 += 0x00010000;
  temp1 = (Res1 << 16) & 0xffff0000;
  temp1 = (Res1 << 16) & 0xffff0000;
  Res0 = temp0 + temp1;
  Res0 = temp0 + temp1;
  if (Res0 < temp0)
  if (Res0 < temp0)
    Res2 += 1;
    Res2 += 1;
  Res2 += ((Res1 >> 16) & 0xffff) + temp3;
  Res2 += ((Res1 >> 16) & 0xffff) + temp3;
 
 
  if (sign)
  if (sign)
    {
    {
      if (rn & 0x80000000)
      if (rn & 0x80000000)
        Res2 -= rm;
        Res2 -= rm;
      if (rm & 0x80000000)
      if (rm & 0x80000000)
        Res2 -= rn;
        Res2 -= rn;
    }
    }
 
 
  MACH = Res2;
  MACH = Res2;
  MACL = Res0;
  MACL = Res0;
}
}
 
 
static void
static void
macw (regs, memory, n, m, endianw)
macw (regs, memory, n, m, endianw)
     int *regs;
     int *regs;
     unsigned char *memory;
     unsigned char *memory;
     int m, n;
     int m, n;
     int endianw;
     int endianw;
{
{
  long tempm, tempn;
  long tempm, tempn;
  long prod, macl, sum;
  long prod, macl, sum;
 
 
  tempm=RSWAT (regs[m]); regs[m]+=2;
  tempm=RSWAT (regs[m]); regs[m]+=2;
  tempn=RSWAT (regs[n]); regs[n]+=2;
  tempn=RSWAT (regs[n]); regs[n]+=2;
 
 
  macl = MACL;
  macl = MACL;
  prod = (long) (short) tempm * (long) (short) tempn;
  prod = (long) (short) tempm * (long) (short) tempn;
  sum = prod + macl;
  sum = prod + macl;
  if (S)
  if (S)
    {
    {
      if ((~(prod ^ macl) & (sum ^ prod)) < 0)
      if ((~(prod ^ macl) & (sum ^ prod)) < 0)
        {
        {
          /* MACH's lsb is a sticky overflow bit.  */
          /* MACH's lsb is a sticky overflow bit.  */
          MACH |= 1;
          MACH |= 1;
          /* Store the smallest negative number in MACL if prod is
          /* Store the smallest negative number in MACL if prod is
             negative, and the largest positive number otherwise.  */
             negative, and the largest positive number otherwise.  */
          sum = 0x7fffffff + (prod < 0);
          sum = 0x7fffffff + (prod < 0);
        }
        }
    }
    }
  else
  else
    {
    {
      long mach;
      long mach;
      /* Add to MACH the sign extended product, and carry from low sum.  */
      /* Add to MACH the sign extended product, and carry from low sum.  */
      mach = MACH + (-(prod < 0)) + ((unsigned long) sum < prod);
      mach = MACH + (-(prod < 0)) + ((unsigned long) sum < prod);
      /* Sign extend at 10:th bit in MACH.  */
      /* Sign extend at 10:th bit in MACH.  */
      MACH = (mach & 0x1ff) | -(mach & 0x200);
      MACH = (mach & 0x1ff) | -(mach & 0x200);
    }
    }
  MACL = sum;
  MACL = sum;
}
}
 
 
static void
static void
macl (regs, memory, n, m)
macl (regs, memory, n, m)
     int *regs;
     int *regs;
     unsigned char *memory;
     unsigned char *memory;
     int m, n;
     int m, n;
{
{
  long tempm, tempn;
  long tempm, tempn;
  long macl, mach;
  long macl, mach;
  long long ans;
  long long ans;
  long long mac64;
  long long mac64;
 
 
  tempm = RSLAT (regs[m]);
  tempm = RSLAT (regs[m]);
  regs[m] += 4;
  regs[m] += 4;
 
 
  tempn = RSLAT (regs[n]);
  tempn = RSLAT (regs[n]);
  regs[n] += 4;
  regs[n] += 4;
 
 
  mach = MACH;
  mach = MACH;
  macl = MACL;
  macl = MACL;
 
 
  mac64 = ((long long) macl & 0xffffffff) |
  mac64 = ((long long) macl & 0xffffffff) |
          ((long long) mach & 0xffffffff) << 32;
          ((long long) mach & 0xffffffff) << 32;
 
 
  ans = (long long) tempm * (long long) tempn; /* Multiply 32bit * 32bit */
  ans = (long long) tempm * (long long) tempn; /* Multiply 32bit * 32bit */
 
 
  mac64 += ans; /* Accumulate 64bit + 64 bit */
  mac64 += ans; /* Accumulate 64bit + 64 bit */
 
 
  macl = (long) (mac64 & 0xffffffff);
  macl = (long) (mac64 & 0xffffffff);
  mach = (long) ((mac64 >> 32) & 0xffffffff);
  mach = (long) ((mac64 >> 32) & 0xffffffff);
 
 
  if (S)  /* Store only 48 bits of the result */
  if (S)  /* Store only 48 bits of the result */
    {
    {
      if (mach < 0) /* Result is negative */
      if (mach < 0) /* Result is negative */
        {
        {
          mach = mach & 0x0000ffff; /* Mask higher 16 bits */
          mach = mach & 0x0000ffff; /* Mask higher 16 bits */
          mach |= 0xffff8000; /* Sign extend higher 16 bits */
          mach |= 0xffff8000; /* Sign extend higher 16 bits */
        }
        }
      else
      else
        mach = mach & 0x00007fff; /* Postive Result */
        mach = mach & 0x00007fff; /* Postive Result */
    }
    }
 
 
  MACL = macl;
  MACL = macl;
  MACH = mach;
  MACH = mach;
}
}
 
 
enum {
enum {
  B_BCLR = 0,
  B_BCLR = 0,
  B_BSET = 1,
  B_BSET = 1,
  B_BST  = 2,
  B_BST  = 2,
  B_BLD  = 3,
  B_BLD  = 3,
  B_BAND = 4,
  B_BAND = 4,
  B_BOR  = 5,
  B_BOR  = 5,
  B_BXOR = 6,
  B_BXOR = 6,
  B_BLDNOT = 11,
  B_BLDNOT = 11,
  B_BANDNOT = 12,
  B_BANDNOT = 12,
  B_BORNOT = 13,
  B_BORNOT = 13,
 
 
  MOVB_RM = 0x0000,
  MOVB_RM = 0x0000,
  MOVW_RM = 0x1000,
  MOVW_RM = 0x1000,
  MOVL_RM = 0x2000,
  MOVL_RM = 0x2000,
  FMOV_RM = 0x3000,
  FMOV_RM = 0x3000,
  MOVB_MR = 0x4000,
  MOVB_MR = 0x4000,
  MOVW_MR = 0x5000,
  MOVW_MR = 0x5000,
  MOVL_MR = 0x6000,
  MOVL_MR = 0x6000,
  FMOV_MR = 0x7000,
  FMOV_MR = 0x7000,
  MOVU_BMR = 0x8000,
  MOVU_BMR = 0x8000,
  MOVU_WMR = 0x9000,
  MOVU_WMR = 0x9000,
};
};
 
 
/* Do extended displacement move instructions.  */
/* Do extended displacement move instructions.  */
void
void
do_long_move_insn (int op, int disp12, int m, int n, int *thatlock)
do_long_move_insn (int op, int disp12, int m, int n, int *thatlock)
{
{
  int memstalls = 0;
  int memstalls = 0;
  int thislock = *thatlock;
  int thislock = *thatlock;
  int endianw = global_endianw;
  int endianw = global_endianw;
  int *R = &(saved_state.asregs.regs[0]);
  int *R = &(saved_state.asregs.regs[0]);
  unsigned char *memory = saved_state.asregs.memory;
  unsigned char *memory = saved_state.asregs.memory;
  int maskb = ~((saved_state.asregs.msize - 1) & ~0);
  int maskb = ~((saved_state.asregs.msize - 1) & ~0);
  unsigned char *insn_ptr = PT2H (saved_state.asregs.pc);
  unsigned char *insn_ptr = PT2H (saved_state.asregs.pc);
 
 
  switch (op) {
  switch (op) {
  case MOVB_RM:         /* signed */
  case MOVB_RM:         /* signed */
    WBAT (disp12 * 1 + R[n], R[m]);
    WBAT (disp12 * 1 + R[n], R[m]);
    break;
    break;
  case MOVW_RM:
  case MOVW_RM:
    WWAT (disp12 * 2 + R[n], R[m]);
    WWAT (disp12 * 2 + R[n], R[m]);
    break;
    break;
  case MOVL_RM:
  case MOVL_RM:
    WLAT (disp12 * 4 + R[n], R[m]);
    WLAT (disp12 * 4 + R[n], R[m]);
    break;
    break;
  case FMOV_RM:         /* floating point */
  case FMOV_RM:         /* floating point */
    if (FPSCR_SZ)
    if (FPSCR_SZ)
      {
      {
        MA (1);
        MA (1);
        WDAT (R[n] + 8 * disp12, m);
        WDAT (R[n] + 8 * disp12, m);
      }
      }
    else
    else
      WLAT (R[n] + 4 * disp12, FI (m));
      WLAT (R[n] + 4 * disp12, FI (m));
    break;
    break;
  case MOVB_MR:
  case MOVB_MR:
    R[n] = RSBAT (disp12 * 1 + R[m]);
    R[n] = RSBAT (disp12 * 1 + R[m]);
    L (n);
    L (n);
    break;
    break;
  case MOVW_MR:
  case MOVW_MR:
    R[n] = RSWAT (disp12 * 2 + R[m]);
    R[n] = RSWAT (disp12 * 2 + R[m]);
    L (n);
    L (n);
    break;
    break;
  case MOVL_MR:
  case MOVL_MR:
    R[n] = RLAT (disp12 * 4 + R[m]);
    R[n] = RLAT (disp12 * 4 + R[m]);
    L (n);
    L (n);
    break;
    break;
  case FMOV_MR:
  case FMOV_MR:
    if (FPSCR_SZ) {
    if (FPSCR_SZ) {
      MA (1);
      MA (1);
      RDAT (R[m] + 8 * disp12, n);
      RDAT (R[m] + 8 * disp12, n);
    }
    }
    else
    else
      SET_FI (n, RLAT (R[m] + 4 * disp12));
      SET_FI (n, RLAT (R[m] + 4 * disp12));
    break;
    break;
  case MOVU_BMR:        /* unsigned */
  case MOVU_BMR:        /* unsigned */
    R[n] = RBAT (disp12 * 1 + R[m]);
    R[n] = RBAT (disp12 * 1 + R[m]);
    L (n);
    L (n);
    break;
    break;
  case MOVU_WMR:
  case MOVU_WMR:
    R[n] = RWAT (disp12 * 2 + R[m]);
    R[n] = RWAT (disp12 * 2 + R[m]);
    L (n);
    L (n);
    break;
    break;
  default:
  default:
    RAISE_EXCEPTION (SIGINT);
    RAISE_EXCEPTION (SIGINT);
    exit (1);
    exit (1);
  }
  }
  saved_state.asregs.memstalls += memstalls;
  saved_state.asregs.memstalls += memstalls;
  *thatlock = thislock;
  *thatlock = thislock;
}
}
 
 
/* Do binary logical bit-manipulation insns.  */
/* Do binary logical bit-manipulation insns.  */
void
void
do_blog_insn (int imm, int addr, int binop,
do_blog_insn (int imm, int addr, int binop,
              unsigned char *memory, int maskb)
              unsigned char *memory, int maskb)
{
{
  int oldval = RBAT (addr);
  int oldval = RBAT (addr);
 
 
  switch (binop) {
  switch (binop) {
  case B_BCLR:  /* bclr.b */
  case B_BCLR:  /* bclr.b */
    WBAT (addr, oldval & ~imm);
    WBAT (addr, oldval & ~imm);
    break;
    break;
  case B_BSET:  /* bset.b */
  case B_BSET:  /* bset.b */
    WBAT (addr, oldval | imm);
    WBAT (addr, oldval | imm);
    break;
    break;
  case B_BST:   /* bst.b */
  case B_BST:   /* bst.b */
    if (T)
    if (T)
      WBAT (addr, oldval | imm);
      WBAT (addr, oldval | imm);
    else
    else
      WBAT (addr, oldval & ~imm);
      WBAT (addr, oldval & ~imm);
    break;
    break;
  case B_BLD:   /* bld.b */
  case B_BLD:   /* bld.b */
    SET_SR_T ((oldval & imm) != 0);
    SET_SR_T ((oldval & imm) != 0);
    break;
    break;
  case B_BAND:  /* band.b */
  case B_BAND:  /* band.b */
    SET_SR_T (T && ((oldval & imm) != 0));
    SET_SR_T (T && ((oldval & imm) != 0));
    break;
    break;
  case B_BOR:   /* bor.b */
  case B_BOR:   /* bor.b */
    SET_SR_T (T || ((oldval & imm) != 0));
    SET_SR_T (T || ((oldval & imm) != 0));
    break;
    break;
  case B_BXOR:  /* bxor.b */
  case B_BXOR:  /* bxor.b */
    SET_SR_T (T ^ ((oldval & imm) != 0));
    SET_SR_T (T ^ ((oldval & imm) != 0));
    break;
    break;
  case B_BLDNOT:        /* bldnot.b */
  case B_BLDNOT:        /* bldnot.b */
    SET_SR_T ((oldval & imm) == 0);
    SET_SR_T ((oldval & imm) == 0);
    break;
    break;
  case B_BANDNOT:       /* bandnot.b */
  case B_BANDNOT:       /* bandnot.b */
    SET_SR_T (T && ((oldval & imm) == 0));
    SET_SR_T (T && ((oldval & imm) == 0));
    break;
    break;
  case B_BORNOT:        /* bornot.b */
  case B_BORNOT:        /* bornot.b */
    SET_SR_T (T || ((oldval & imm) == 0));
    SET_SR_T (T || ((oldval & imm) == 0));
    break;
    break;
  }
  }
}
}
float
float
fsca_s (int in, double (*f) (double))
fsca_s (int in, double (*f) (double))
{
{
  double rad = ldexp ((in & 0xffff), -15) * 3.141592653589793238462643383;
  double rad = ldexp ((in & 0xffff), -15) * 3.141592653589793238462643383;
  double result = (*f) (rad);
  double result = (*f) (rad);
  double error, upper, lower, frac;
  double error, upper, lower, frac;
  int exp;
  int exp;
 
 
  /* Search the value with the maximum error that is still within the
  /* Search the value with the maximum error that is still within the
     architectural spec.  */
     architectural spec.  */
  error = ldexp (1., -21);
  error = ldexp (1., -21);
  /* compensate for calculation inaccuracy by reducing error.  */
  /* compensate for calculation inaccuracy by reducing error.  */
  error = error - ldexp (1., -50);
  error = error - ldexp (1., -50);
  upper = result + error;
  upper = result + error;
  frac = frexp (upper, &exp);
  frac = frexp (upper, &exp);
  upper = ldexp (floor (ldexp (frac, 24)), exp - 24);
  upper = ldexp (floor (ldexp (frac, 24)), exp - 24);
  lower = result - error;
  lower = result - error;
  frac = frexp (lower, &exp);
  frac = frexp (lower, &exp);
  lower = ldexp (ceil (ldexp (frac, 24)), exp - 24);
  lower = ldexp (ceil (ldexp (frac, 24)), exp - 24);
  return abs (upper - result) >= abs (lower - result) ? upper : lower;
  return abs (upper - result) >= abs (lower - result) ? upper : lower;
}
}
 
 
float
float
fsrra_s (float in)
fsrra_s (float in)
{
{
  double result = 1. / sqrt (in);
  double result = 1. / sqrt (in);
  int exp;
  int exp;
  double frac, upper, lower, error, eps;
  double frac, upper, lower, error, eps;
 
 
  /* refine result */
  /* refine result */
  result = result - (result * result * in - 1) * 0.5 * result;
  result = result - (result * result * in - 1) * 0.5 * result;
  /* Search the value with the maximum error that is still within the
  /* Search the value with the maximum error that is still within the
     architectural spec.  */
     architectural spec.  */
  frac = frexp (result, &exp);
  frac = frexp (result, &exp);
  frac = ldexp (frac, 24);
  frac = ldexp (frac, 24);
  error = 4.0; /* 1 << 24-1-21 */
  error = 4.0; /* 1 << 24-1-21 */
  /* use eps to compensate for possible 1 ulp error in our 'exact' result.  */
  /* use eps to compensate for possible 1 ulp error in our 'exact' result.  */
  eps = ldexp (1., -29);
  eps = ldexp (1., -29);
  upper = floor (frac + error - eps);
  upper = floor (frac + error - eps);
  if (upper > 16777216.)
  if (upper > 16777216.)
    upper = floor ((frac + error - eps) * 0.5) * 2.;
    upper = floor ((frac + error - eps) * 0.5) * 2.;
  lower = ceil ((frac - error + eps) * 2) * .5;
  lower = ceil ((frac - error + eps) * 2) * .5;
  if (lower > 8388608.)
  if (lower > 8388608.)
    lower = ceil (frac - error + eps);
    lower = ceil (frac - error + eps);
  upper = ldexp (upper, exp - 24);
  upper = ldexp (upper, exp - 24);
  lower = ldexp (lower, exp - 24);
  lower = ldexp (lower, exp - 24);
  return upper - result >= result - lower ? upper : lower;
  return upper - result >= result - lower ? upper : lower;
}
}
 
 
 
 
/* GET_LOOP_BOUNDS {EXTENDED}
/* GET_LOOP_BOUNDS {EXTENDED}
   These two functions compute the actual starting and ending point
   These two functions compute the actual starting and ending point
   of the repeat loop, based on the RS and RE registers (repeat start,
   of the repeat loop, based on the RS and RE registers (repeat start,
   repeat stop).  The extended version is called for LDRC, and the
   repeat stop).  The extended version is called for LDRC, and the
   regular version is called for SETRC.  The difference is that for
   regular version is called for SETRC.  The difference is that for
   LDRC, the loop start and end instructions are literally the ones
   LDRC, the loop start and end instructions are literally the ones
   pointed to by RS and RE -- for SETRC, they're not (see docs).  */
   pointed to by RS and RE -- for SETRC, they're not (see docs).  */
 
 
static struct loop_bounds
static struct loop_bounds
get_loop_bounds_ext (rs, re, memory, mem_end, maskw, endianw)
get_loop_bounds_ext (rs, re, memory, mem_end, maskw, endianw)
     int rs, re;
     int rs, re;
     unsigned char *memory, *mem_end;
     unsigned char *memory, *mem_end;
     int maskw, endianw;
     int maskw, endianw;
{
{
  struct loop_bounds loop;
  struct loop_bounds loop;
 
 
  /* FIXME: should I verify RS < RE?  */
  /* FIXME: should I verify RS < RE?  */
  loop.start = PT2H (RS);       /* FIXME not using the params?  */
  loop.start = PT2H (RS);       /* FIXME not using the params?  */
  loop.end   = PT2H (RE & ~1);  /* Ignore bit 0 of RE.  */
  loop.end   = PT2H (RE & ~1);  /* Ignore bit 0 of RE.  */
  SKIP_INSN (loop.end);
  SKIP_INSN (loop.end);
  if (loop.end >= mem_end)
  if (loop.end >= mem_end)
    loop.end = PT2H (0);
    loop.end = PT2H (0);
  return loop;
  return loop;
}
}
 
 
static struct loop_bounds
static struct loop_bounds
get_loop_bounds (rs, re, memory, mem_end, maskw, endianw)
get_loop_bounds (rs, re, memory, mem_end, maskw, endianw)
     int rs, re;
     int rs, re;
     unsigned char *memory, *mem_end;
     unsigned char *memory, *mem_end;
     int maskw, endianw;
     int maskw, endianw;
{
{
  struct loop_bounds loop;
  struct loop_bounds loop;
 
 
  if (SR_RC)
  if (SR_RC)
    {
    {
      if (RS >= RE)
      if (RS >= RE)
        {
        {
          loop.start = PT2H (RE - 4);
          loop.start = PT2H (RE - 4);
          SKIP_INSN (loop.start);
          SKIP_INSN (loop.start);
          loop.end = loop.start;
          loop.end = loop.start;
          if (RS - RE == 0)
          if (RS - RE == 0)
            SKIP_INSN (loop.end);
            SKIP_INSN (loop.end);
          if (RS - RE <= 2)
          if (RS - RE <= 2)
            SKIP_INSN (loop.end);
            SKIP_INSN (loop.end);
          SKIP_INSN (loop.end);
          SKIP_INSN (loop.end);
        }
        }
      else
      else
        {
        {
          loop.start = PT2H (RS);
          loop.start = PT2H (RS);
          loop.end = PT2H (RE - 4);
          loop.end = PT2H (RE - 4);
          SKIP_INSN (loop.end);
          SKIP_INSN (loop.end);
          SKIP_INSN (loop.end);
          SKIP_INSN (loop.end);
          SKIP_INSN (loop.end);
          SKIP_INSN (loop.end);
          SKIP_INSN (loop.end);
          SKIP_INSN (loop.end);
        }
        }
      if (loop.end >= mem_end)
      if (loop.end >= mem_end)
        loop.end = PT2H (0);
        loop.end = PT2H (0);
    }
    }
  else
  else
    loop.end = PT2H (0);
    loop.end = PT2H (0);
 
 
  return loop;
  return loop;
}
}
 
 
static void ppi_insn ();
static void ppi_insn ();
 
 
#include "ppi.c"
#include "ppi.c"
 
 
/* Provide calloc / free versions that use an anonymous mmap.  This can
/* Provide calloc / free versions that use an anonymous mmap.  This can
   significantly cut the start-up time when a large simulator memory is
   significantly cut the start-up time when a large simulator memory is
   required, because pages are only zeroed on demand.  */
   required, because pages are only zeroed on demand.  */
#ifdef MAP_ANONYMOUS
#ifdef MAP_ANONYMOUS
void *
void *
mcalloc (size_t nmemb, size_t size)
mcalloc (size_t nmemb, size_t size)
{
{
  void *page;
  void *page;
 
 
  if (nmemb != 1)
  if (nmemb != 1)
    size *= nmemb;
    size *= nmemb;
  return mmap (0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,
  return mmap (0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,
               -1, 0);
               -1, 0);
}
}
 
 
#define mfree(start,length) munmap ((start), (length))
#define mfree(start,length) munmap ((start), (length))
#else
#else
#define mcalloc calloc
#define mcalloc calloc
#define mfree(start,length) free(start)
#define mfree(start,length) free(start)
#endif
#endif
 
 
/* Set the memory size to the power of two provided. */
/* Set the memory size to the power of two provided. */
 
 
void
void
sim_size (power)
sim_size (power)
     int power;
     int power;
 
 
{
{
  sim_memory_size = power;
  sim_memory_size = power;
 
 
  if (saved_state.asregs.memory)
  if (saved_state.asregs.memory)
    {
    {
      mfree (saved_state.asregs.memory, saved_state.asregs.msize);
      mfree (saved_state.asregs.memory, saved_state.asregs.msize);
    }
    }
 
 
  saved_state.asregs.msize = 1 << power;
  saved_state.asregs.msize = 1 << power;
 
 
  saved_state.asregs.memory =
  saved_state.asregs.memory =
    (unsigned char *) mcalloc (1, saved_state.asregs.msize);
    (unsigned char *) mcalloc (1, saved_state.asregs.msize);
 
 
  if (!saved_state.asregs.memory)
  if (!saved_state.asregs.memory)
    {
    {
      fprintf (stderr,
      fprintf (stderr,
               "Not enough VM for simulation of %d bytes of RAM\n",
               "Not enough VM for simulation of %d bytes of RAM\n",
               saved_state.asregs.msize);
               saved_state.asregs.msize);
 
 
      saved_state.asregs.msize = 1;
      saved_state.asregs.msize = 1;
      saved_state.asregs.memory = (unsigned char *) mcalloc (1, 1);
      saved_state.asregs.memory = (unsigned char *) mcalloc (1, 1);
    }
    }
}
}
 
 
static void
static void
init_dsp (abfd)
init_dsp (abfd)
     struct bfd *abfd;
     struct bfd *abfd;
{
{
  int was_dsp = target_dsp;
  int was_dsp = target_dsp;
  unsigned long mach = bfd_get_mach (abfd);
  unsigned long mach = bfd_get_mach (abfd);
 
 
  if (mach == bfd_mach_sh_dsp  ||
  if (mach == bfd_mach_sh_dsp  ||
      mach == bfd_mach_sh4al_dsp ||
      mach == bfd_mach_sh4al_dsp ||
      mach == bfd_mach_sh3_dsp)
      mach == bfd_mach_sh3_dsp)
    {
    {
      int ram_area_size, xram_start, yram_start;
      int ram_area_size, xram_start, yram_start;
      int new_select;
      int new_select;
 
 
      target_dsp = 1;
      target_dsp = 1;
      if (mach == bfd_mach_sh_dsp)
      if (mach == bfd_mach_sh_dsp)
        {
        {
          /* SH7410 (orig. sh-sdp):
          /* SH7410 (orig. sh-sdp):
             4KB each for X & Y memory;
             4KB each for X & Y memory;
             On-chip X RAM 0x0800f000-0x0800ffff
             On-chip X RAM 0x0800f000-0x0800ffff
             On-chip Y RAM 0x0801f000-0x0801ffff  */
             On-chip Y RAM 0x0801f000-0x0801ffff  */
          xram_start = 0x0800f000;
          xram_start = 0x0800f000;
          ram_area_size = 0x1000;
          ram_area_size = 0x1000;
        }
        }
      if (mach == bfd_mach_sh3_dsp || mach == bfd_mach_sh4al_dsp)
      if (mach == bfd_mach_sh3_dsp || mach == bfd_mach_sh4al_dsp)
        {
        {
          /* SH7612:
          /* SH7612:
             8KB each for X & Y memory;
             8KB each for X & Y memory;
             On-chip X RAM 0x1000e000-0x1000ffff
             On-chip X RAM 0x1000e000-0x1000ffff
             On-chip Y RAM 0x1001e000-0x1001ffff  */
             On-chip Y RAM 0x1001e000-0x1001ffff  */
          xram_start = 0x1000e000;
          xram_start = 0x1000e000;
          ram_area_size = 0x2000;
          ram_area_size = 0x2000;
        }
        }
      yram_start = xram_start + 0x10000;
      yram_start = xram_start + 0x10000;
      new_select = ~(ram_area_size - 1);
      new_select = ~(ram_area_size - 1);
      if (saved_state.asregs.xyram_select != new_select)
      if (saved_state.asregs.xyram_select != new_select)
        {
        {
          saved_state.asregs.xyram_select = new_select;
          saved_state.asregs.xyram_select = new_select;
          free (saved_state.asregs.xmem);
          free (saved_state.asregs.xmem);
          free (saved_state.asregs.ymem);
          free (saved_state.asregs.ymem);
          saved_state.asregs.xmem =
          saved_state.asregs.xmem =
            (unsigned char *) calloc (1, ram_area_size);
            (unsigned char *) calloc (1, ram_area_size);
          saved_state.asregs.ymem =
          saved_state.asregs.ymem =
            (unsigned char *) calloc (1, ram_area_size);
            (unsigned char *) calloc (1, ram_area_size);
 
 
          /* Disable use of X / Y mmeory if not allocated.  */
          /* Disable use of X / Y mmeory if not allocated.  */
          if (! saved_state.asregs.xmem || ! saved_state.asregs.ymem)
          if (! saved_state.asregs.xmem || ! saved_state.asregs.ymem)
            {
            {
              saved_state.asregs.xyram_select = 0;
              saved_state.asregs.xyram_select = 0;
              if (saved_state.asregs.xmem)
              if (saved_state.asregs.xmem)
                free (saved_state.asregs.xmem);
                free (saved_state.asregs.xmem);
              if (saved_state.asregs.ymem)
              if (saved_state.asregs.ymem)
                free (saved_state.asregs.ymem);
                free (saved_state.asregs.ymem);
            }
            }
        }
        }
      saved_state.asregs.xram_start = xram_start;
      saved_state.asregs.xram_start = xram_start;
      saved_state.asregs.yram_start = yram_start;
      saved_state.asregs.yram_start = yram_start;
      saved_state.asregs.xmem_offset = saved_state.asregs.xmem - xram_start;
      saved_state.asregs.xmem_offset = saved_state.asregs.xmem - xram_start;
      saved_state.asregs.ymem_offset = saved_state.asregs.ymem - yram_start;
      saved_state.asregs.ymem_offset = saved_state.asregs.ymem - yram_start;
    }
    }
  else
  else
    {
    {
      target_dsp = 0;
      target_dsp = 0;
      if (saved_state.asregs.xyram_select)
      if (saved_state.asregs.xyram_select)
        {
        {
          saved_state.asregs.xyram_select = 0;
          saved_state.asregs.xyram_select = 0;
          free (saved_state.asregs.xmem);
          free (saved_state.asregs.xmem);
          free (saved_state.asregs.ymem);
          free (saved_state.asregs.ymem);
        }
        }
    }
    }
 
 
  if (! saved_state.asregs.xyram_select)
  if (! saved_state.asregs.xyram_select)
    {
    {
      saved_state.asregs.xram_start = 1;
      saved_state.asregs.xram_start = 1;
      saved_state.asregs.yram_start = 1;
      saved_state.asregs.yram_start = 1;
    }
    }
 
 
  if (saved_state.asregs.regstack == NULL)
  if (saved_state.asregs.regstack == NULL)
    saved_state.asregs.regstack =
    saved_state.asregs.regstack =
      calloc (512, sizeof *saved_state.asregs.regstack);
      calloc (512, sizeof *saved_state.asregs.regstack);
 
 
  if (target_dsp != was_dsp)
  if (target_dsp != was_dsp)
    {
    {
      int i, tmp;
      int i, tmp;
 
 
      for (i = (sizeof sh_dsp_table / sizeof sh_dsp_table[0]) - 1; i >= 0; i--)
      for (i = (sizeof sh_dsp_table / sizeof sh_dsp_table[0]) - 1; i >= 0; i--)
        {
        {
          tmp = sh_jump_table[0xf000 + i];
          tmp = sh_jump_table[0xf000 + i];
          sh_jump_table[0xf000 + i] = sh_dsp_table[i];
          sh_jump_table[0xf000 + i] = sh_dsp_table[i];
          sh_dsp_table[i] = tmp;
          sh_dsp_table[i] = tmp;
        }
        }
    }
    }
}
}
 
 
static void
static void
init_pointers ()
init_pointers ()
{
{
  host_little_endian = 0;
  host_little_endian = 0;
  * (char*) &host_little_endian = 1;
  * (char*) &host_little_endian = 1;
  host_little_endian &= 1;
  host_little_endian &= 1;
 
 
  if (saved_state.asregs.msize != 1 << sim_memory_size)
  if (saved_state.asregs.msize != 1 << sim_memory_size)
    {
    {
      sim_size (sim_memory_size);
      sim_size (sim_memory_size);
    }
    }
 
 
  if (saved_state.asregs.profile && !profile_file)
  if (saved_state.asregs.profile && !profile_file)
    {
    {
      profile_file = fopen ("gmon.out", "wb");
      profile_file = fopen ("gmon.out", "wb");
      /* Seek to where to put the call arc data */
      /* Seek to where to put the call arc data */
      nsamples = (1 << sim_profile_size);
      nsamples = (1 << sim_profile_size);
 
 
      fseek (profile_file, nsamples * 2 + 12, 0);
      fseek (profile_file, nsamples * 2 + 12, 0);
 
 
      if (!profile_file)
      if (!profile_file)
        {
        {
          fprintf (stderr, "Can't open gmon.out\n");
          fprintf (stderr, "Can't open gmon.out\n");
        }
        }
      else
      else
        {
        {
          saved_state.asregs.profile_hist =
          saved_state.asregs.profile_hist =
            (unsigned short *) calloc (64, (nsamples * sizeof (short) / 64));
            (unsigned short *) calloc (64, (nsamples * sizeof (short) / 64));
        }
        }
    }
    }
}
}
 
 
static void
static void
dump_profile ()
dump_profile ()
{
{
  unsigned int minpc;
  unsigned int minpc;
  unsigned int maxpc;
  unsigned int maxpc;
  unsigned short *p;
  unsigned short *p;
  int i;
  int i;
 
 
  p = saved_state.asregs.profile_hist;
  p = saved_state.asregs.profile_hist;
  minpc = 0;
  minpc = 0;
  maxpc = (1 << sim_profile_size);
  maxpc = (1 << sim_profile_size);
 
 
  fseek (profile_file, 0L, 0);
  fseek (profile_file, 0L, 0);
  swapout (minpc << PROFILE_SHIFT);
  swapout (minpc << PROFILE_SHIFT);
  swapout (maxpc << PROFILE_SHIFT);
  swapout (maxpc << PROFILE_SHIFT);
  swapout (nsamples * 2 + 12);
  swapout (nsamples * 2 + 12);
  for (i = 0; i < nsamples; i++)
  for (i = 0; i < nsamples; i++)
    swapout16 (saved_state.asregs.profile_hist[i]);
    swapout16 (saved_state.asregs.profile_hist[i]);
 
 
}
}
 
 
static void
static void
gotcall (from, to)
gotcall (from, to)
     int from;
     int from;
     int to;
     int to;
{
{
  swapout (from);
  swapout (from);
  swapout (to);
  swapout (to);
  swapout (1);
  swapout (1);
}
}
 
 
#define MMASKB ((saved_state.asregs.msize -1) & ~0)
#define MMASKB ((saved_state.asregs.msize -1) & ~0)
 
 
int
int
sim_stop (sd)
sim_stop (sd)
     SIM_DESC sd;
     SIM_DESC sd;
{
{
  raise_exception (SIGINT);
  raise_exception (SIGINT);
  return 1;
  return 1;
}
}
 
 
void
void
sim_resume (sd, step, siggnal)
sim_resume (sd, step, siggnal)
     SIM_DESC sd;
     SIM_DESC sd;
     int step, siggnal;
     int step, siggnal;
{
{
  register unsigned char *insn_ptr;
  register unsigned char *insn_ptr;
  unsigned char *mem_end;
  unsigned char *mem_end;
  struct loop_bounds loop;
  struct loop_bounds loop;
  register int cycles = 0;
  register int cycles = 0;
  register int stalls = 0;
  register int stalls = 0;
  register int memstalls = 0;
  register int memstalls = 0;
  register int insts = 0;
  register int insts = 0;
  register int prevlock;
  register int prevlock;
#if 1
#if 1
  int thislock;
  int thislock;
#else
#else
  register int thislock;
  register int thislock;
#endif
#endif
  register unsigned int doprofile;
  register unsigned int doprofile;
  register int pollcount = 0;
  register int pollcount = 0;
  /* endianw is used for every insn fetch, hence it makes sense to cache it.
  /* endianw is used for every insn fetch, hence it makes sense to cache it.
     endianb is used less often.  */
     endianb is used less often.  */
  register int endianw = global_endianw;
  register int endianw = global_endianw;
 
 
  int tick_start = get_now ();
  int tick_start = get_now ();
  void (*prev) ();
  void (*prev) ();
  void (*prev_fpe) ();
  void (*prev_fpe) ();
 
 
  register unsigned short *jump_table = sh_jump_table;
  register unsigned short *jump_table = sh_jump_table;
 
 
  register int *R = &(saved_state.asregs.regs[0]);
  register int *R = &(saved_state.asregs.regs[0]);
  /*register int T;*/
  /*register int T;*/
#ifndef PR
#ifndef PR
  register int PR;
  register int PR;
#endif
#endif
 
 
  register int maskb = ~((saved_state.asregs.msize - 1) & ~0);
  register int maskb = ~((saved_state.asregs.msize - 1) & ~0);
  register int maskw = ~((saved_state.asregs.msize - 1) & ~1);
  register int maskw = ~((saved_state.asregs.msize - 1) & ~1);
  register int maskl = ~((saved_state.asregs.msize - 1) & ~3);
  register int maskl = ~((saved_state.asregs.msize - 1) & ~3);
  register unsigned char *memory;
  register unsigned char *memory;
  register unsigned int sbit = ((unsigned int) 1 << 31);
  register unsigned int sbit = ((unsigned int) 1 << 31);
 
 
  prev = signal (SIGINT, control_c);
  prev = signal (SIGINT, control_c);
  prev_fpe = signal (SIGFPE, SIG_IGN);
  prev_fpe = signal (SIGFPE, SIG_IGN);
 
 
  init_pointers ();
  init_pointers ();
  saved_state.asregs.exception = 0;
  saved_state.asregs.exception = 0;
 
 
  memory = saved_state.asregs.memory;
  memory = saved_state.asregs.memory;
  mem_end = memory + saved_state.asregs.msize;
  mem_end = memory + saved_state.asregs.msize;
 
 
  if (RE & 1)
  if (RE & 1)
    loop = get_loop_bounds_ext (RS, RE, memory, mem_end, maskw, endianw);
    loop = get_loop_bounds_ext (RS, RE, memory, mem_end, maskw, endianw);
  else
  else
    loop = get_loop_bounds     (RS, RE, memory, mem_end, maskw, endianw);
    loop = get_loop_bounds     (RS, RE, memory, mem_end, maskw, endianw);
 
 
  insn_ptr = PT2H (saved_state.asregs.pc);
  insn_ptr = PT2H (saved_state.asregs.pc);
  CHECK_INSN_PTR (insn_ptr);
  CHECK_INSN_PTR (insn_ptr);
 
 
#ifndef PR
#ifndef PR
  PR = saved_state.asregs.sregs.named.pr;
  PR = saved_state.asregs.sregs.named.pr;
#endif
#endif
  /*T = GET_SR () & SR_MASK_T;*/
  /*T = GET_SR () & SR_MASK_T;*/
  prevlock = saved_state.asregs.prevlock;
  prevlock = saved_state.asregs.prevlock;
  thislock = saved_state.asregs.thislock;
  thislock = saved_state.asregs.thislock;
  doprofile = saved_state.asregs.profile;
  doprofile = saved_state.asregs.profile;
 
 
  /* If profiling not enabled, disable it by asking for
  /* If profiling not enabled, disable it by asking for
     profiles infrequently. */
     profiles infrequently. */
  if (doprofile == 0)
  if (doprofile == 0)
    doprofile = ~0;
    doprofile = ~0;
 
 
 loop:
 loop:
  if (step && insn_ptr < saved_state.asregs.insn_end)
  if (step && insn_ptr < saved_state.asregs.insn_end)
    {
    {
      if (saved_state.asregs.exception)
      if (saved_state.asregs.exception)
        /* This can happen if we've already been single-stepping and
        /* This can happen if we've already been single-stepping and
           encountered a loop end.  */
           encountered a loop end.  */
        saved_state.asregs.insn_end = insn_ptr;
        saved_state.asregs.insn_end = insn_ptr;
      else
      else
        {
        {
          saved_state.asregs.exception = SIGTRAP;
          saved_state.asregs.exception = SIGTRAP;
          saved_state.asregs.insn_end = insn_ptr + 2;
          saved_state.asregs.insn_end = insn_ptr + 2;
        }
        }
    }
    }
 
 
  while (insn_ptr < saved_state.asregs.insn_end)
  while (insn_ptr < saved_state.asregs.insn_end)
    {
    {
      register unsigned int iword = RIAT (insn_ptr);
      register unsigned int iword = RIAT (insn_ptr);
      register unsigned int ult;
      register unsigned int ult;
      register unsigned char *nip = insn_ptr + 2;
      register unsigned char *nip = insn_ptr + 2;
 
 
#ifndef ACE_FAST
#ifndef ACE_FAST
      insts++;
      insts++;
#endif
#endif
    top:
    top:
      if (tracing)
      if (tracing)
        fprintf (stderr, "PC: %08x, insn: %04x\n", PH2T (insn_ptr), iword);
        fprintf (stderr, "PC: %08x, insn: %04x\n", PH2T (insn_ptr), iword);
 
 
#include "code.c"
#include "code.c"
 
 
 
 
      in_delay_slot = 0;
      in_delay_slot = 0;
      insn_ptr = nip;
      insn_ptr = nip;
 
 
      if (--pollcount < 0)
      if (--pollcount < 0)
        {
        {
          pollcount = POLL_QUIT_INTERVAL;
          pollcount = POLL_QUIT_INTERVAL;
          if ((*callback->poll_quit) != NULL
          if ((*callback->poll_quit) != NULL
              && (*callback->poll_quit) (callback))
              && (*callback->poll_quit) (callback))
            {
            {
              sim_stop (sd);
              sim_stop (sd);
            }
            }
        }
        }
 
 
#ifndef ACE_FAST
#ifndef ACE_FAST
      prevlock = thislock;
      prevlock = thislock;
      thislock = 30;
      thislock = 30;
      cycles++;
      cycles++;
 
 
      if (cycles >= doprofile)
      if (cycles >= doprofile)
        {
        {
 
 
          saved_state.asregs.cycles += doprofile;
          saved_state.asregs.cycles += doprofile;
          cycles -= doprofile;
          cycles -= doprofile;
          if (saved_state.asregs.profile_hist)
          if (saved_state.asregs.profile_hist)
            {
            {
              int n = PH2T (insn_ptr) >> PROFILE_SHIFT;
              int n = PH2T (insn_ptr) >> PROFILE_SHIFT;
              if (n < nsamples)
              if (n < nsamples)
                {
                {
                  int i = saved_state.asregs.profile_hist[n];
                  int i = saved_state.asregs.profile_hist[n];
                  if (i < 65000)
                  if (i < 65000)
                    saved_state.asregs.profile_hist[n] = i + 1;
                    saved_state.asregs.profile_hist[n] = i + 1;
                }
                }
 
 
            }
            }
        }
        }
#endif
#endif
    }
    }
  if (saved_state.asregs.insn_end == loop.end)
  if (saved_state.asregs.insn_end == loop.end)
    {
    {
      saved_state.asregs.cregs.named.sr += SR_RC_INCREMENT;
      saved_state.asregs.cregs.named.sr += SR_RC_INCREMENT;
      if (SR_RC)
      if (SR_RC)
        insn_ptr = loop.start;
        insn_ptr = loop.start;
      else
      else
        {
        {
          saved_state.asregs.insn_end = mem_end;
          saved_state.asregs.insn_end = mem_end;
          loop.end = PT2H (0);
          loop.end = PT2H (0);
        }
        }
      goto loop;
      goto loop;
    }
    }
 
 
  if (saved_state.asregs.exception == SIGILL
  if (saved_state.asregs.exception == SIGILL
      || saved_state.asregs.exception == SIGBUS)
      || saved_state.asregs.exception == SIGBUS)
    {
    {
      insn_ptr -= 2;
      insn_ptr -= 2;
    }
    }
  /* Check for SIGBUS due to insn fetch.  */
  /* Check for SIGBUS due to insn fetch.  */
  else if (! saved_state.asregs.exception)
  else if (! saved_state.asregs.exception)
    saved_state.asregs.exception = SIGBUS;
    saved_state.asregs.exception = SIGBUS;
 
 
  saved_state.asregs.ticks += get_now () - tick_start;
  saved_state.asregs.ticks += get_now () - tick_start;
  saved_state.asregs.cycles += cycles;
  saved_state.asregs.cycles += cycles;
  saved_state.asregs.stalls += stalls;
  saved_state.asregs.stalls += stalls;
  saved_state.asregs.memstalls += memstalls;
  saved_state.asregs.memstalls += memstalls;
  saved_state.asregs.insts += insts;
  saved_state.asregs.insts += insts;
  saved_state.asregs.pc = PH2T (insn_ptr);
  saved_state.asregs.pc = PH2T (insn_ptr);
#ifndef PR
#ifndef PR
  saved_state.asregs.sregs.named.pr = PR;
  saved_state.asregs.sregs.named.pr = PR;
#endif
#endif
 
 
  saved_state.asregs.prevlock = prevlock;
  saved_state.asregs.prevlock = prevlock;
  saved_state.asregs.thislock = thislock;
  saved_state.asregs.thislock = thislock;
 
 
  if (profile_file)
  if (profile_file)
    {
    {
      dump_profile ();
      dump_profile ();
    }
    }
 
 
  signal (SIGFPE, prev_fpe);
  signal (SIGFPE, prev_fpe);
  signal (SIGINT, prev);
  signal (SIGINT, prev);
}
}
 
 
int
int
sim_write (sd, addr, buffer, size)
sim_write (sd, addr, buffer, size)
     SIM_DESC sd;
     SIM_DESC sd;
     SIM_ADDR addr;
     SIM_ADDR addr;
     unsigned char *buffer;
     unsigned char *buffer;
     int size;
     int size;
{
{
  int i;
  int i;
 
 
  init_pointers ();
  init_pointers ();
 
 
  for (i = 0; i < size; i++)
  for (i = 0; i < size; i++)
    {
    {
      saved_state.asregs.memory[(MMASKB & (addr + i)) ^ endianb] = buffer[i];
      saved_state.asregs.memory[(MMASKB & (addr + i)) ^ endianb] = buffer[i];
    }
    }
  return size;
  return size;
}
}
 
 
int
int
sim_read (sd, addr, buffer, size)
sim_read (sd, addr, buffer, size)
     SIM_DESC sd;
     SIM_DESC sd;
     SIM_ADDR addr;
     SIM_ADDR addr;
     unsigned char *buffer;
     unsigned char *buffer;
     int size;
     int size;
{
{
  int i;
  int i;
 
 
  init_pointers ();
  init_pointers ();
 
 
  for (i = 0; i < size; i++)
  for (i = 0; i < size; i++)
    {
    {
      buffer[i] = saved_state.asregs.memory[(MMASKB & (addr + i)) ^ endianb];
      buffer[i] = saved_state.asregs.memory[(MMASKB & (addr + i)) ^ endianb];
    }
    }
  return size;
  return size;
}
}
 
 
static int gdb_bank_number;
static int gdb_bank_number;
enum {
enum {
  REGBANK_MACH = 15,
  REGBANK_MACH = 15,
  REGBANK_IVN  = 16,
  REGBANK_IVN  = 16,
  REGBANK_PR   = 17,
  REGBANK_PR   = 17,
  REGBANK_GBR  = 18,
  REGBANK_GBR  = 18,
  REGBANK_MACL = 19
  REGBANK_MACL = 19
};
};
 
 
int
int
sim_store_register (sd, rn, memory, length)
sim_store_register (sd, rn, memory, length)
     SIM_DESC sd;
     SIM_DESC sd;
     int rn;
     int rn;
     unsigned char *memory;
     unsigned char *memory;
     int length;
     int length;
{
{
  unsigned val;
  unsigned val;
 
 
  init_pointers ();
  init_pointers ();
  val = swap (* (int *) memory);
  val = swap (* (int *) memory);
  switch (rn)
  switch (rn)
    {
    {
    case SIM_SH_R0_REGNUM: case SIM_SH_R1_REGNUM: case SIM_SH_R2_REGNUM:
    case SIM_SH_R0_REGNUM: case SIM_SH_R1_REGNUM: case SIM_SH_R2_REGNUM:
    case SIM_SH_R3_REGNUM: case SIM_SH_R4_REGNUM: case SIM_SH_R5_REGNUM:
    case SIM_SH_R3_REGNUM: case SIM_SH_R4_REGNUM: case SIM_SH_R5_REGNUM:
    case SIM_SH_R6_REGNUM: case SIM_SH_R7_REGNUM: case SIM_SH_R8_REGNUM:
    case SIM_SH_R6_REGNUM: case SIM_SH_R7_REGNUM: case SIM_SH_R8_REGNUM:
    case SIM_SH_R9_REGNUM: case SIM_SH_R10_REGNUM: case SIM_SH_R11_REGNUM:
    case SIM_SH_R9_REGNUM: case SIM_SH_R10_REGNUM: case SIM_SH_R11_REGNUM:
    case SIM_SH_R12_REGNUM: case SIM_SH_R13_REGNUM: case SIM_SH_R14_REGNUM:
    case SIM_SH_R12_REGNUM: case SIM_SH_R13_REGNUM: case SIM_SH_R14_REGNUM:
    case SIM_SH_R15_REGNUM:
    case SIM_SH_R15_REGNUM:
      saved_state.asregs.regs[rn] = val;
      saved_state.asregs.regs[rn] = val;
      break;
      break;
    case SIM_SH_PC_REGNUM:
    case SIM_SH_PC_REGNUM:
      saved_state.asregs.pc = val;
      saved_state.asregs.pc = val;
      break;
      break;
    case SIM_SH_PR_REGNUM:
    case SIM_SH_PR_REGNUM:
      PR = val;
      PR = val;
      break;
      break;
    case SIM_SH_GBR_REGNUM:
    case SIM_SH_GBR_REGNUM:
      GBR = val;
      GBR = val;
      break;
      break;
    case SIM_SH_VBR_REGNUM:
    case SIM_SH_VBR_REGNUM:
      VBR = val;
      VBR = val;
      break;
      break;
    case SIM_SH_MACH_REGNUM:
    case SIM_SH_MACH_REGNUM:
      MACH = val;
      MACH = val;
      break;
      break;
    case SIM_SH_MACL_REGNUM:
    case SIM_SH_MACL_REGNUM:
      MACL = val;
      MACL = val;
      break;
      break;
    case SIM_SH_SR_REGNUM:
    case SIM_SH_SR_REGNUM:
      SET_SR (val);
      SET_SR (val);
      break;
      break;
    case SIM_SH_FPUL_REGNUM:
    case SIM_SH_FPUL_REGNUM:
      FPUL = val;
      FPUL = val;
      break;
      break;
    case SIM_SH_FPSCR_REGNUM:
    case SIM_SH_FPSCR_REGNUM:
      SET_FPSCR (val);
      SET_FPSCR (val);
      break;
      break;
    case SIM_SH_FR0_REGNUM: case SIM_SH_FR1_REGNUM: case SIM_SH_FR2_REGNUM:
    case SIM_SH_FR0_REGNUM: case SIM_SH_FR1_REGNUM: case SIM_SH_FR2_REGNUM:
    case SIM_SH_FR3_REGNUM: case SIM_SH_FR4_REGNUM: case SIM_SH_FR5_REGNUM:
    case SIM_SH_FR3_REGNUM: case SIM_SH_FR4_REGNUM: case SIM_SH_FR5_REGNUM:
    case SIM_SH_FR6_REGNUM: case SIM_SH_FR7_REGNUM: case SIM_SH_FR8_REGNUM:
    case SIM_SH_FR6_REGNUM: case SIM_SH_FR7_REGNUM: case SIM_SH_FR8_REGNUM:
    case SIM_SH_FR9_REGNUM: case SIM_SH_FR10_REGNUM: case SIM_SH_FR11_REGNUM:
    case SIM_SH_FR9_REGNUM: case SIM_SH_FR10_REGNUM: case SIM_SH_FR11_REGNUM:
    case SIM_SH_FR12_REGNUM: case SIM_SH_FR13_REGNUM: case SIM_SH_FR14_REGNUM:
    case SIM_SH_FR12_REGNUM: case SIM_SH_FR13_REGNUM: case SIM_SH_FR14_REGNUM:
    case SIM_SH_FR15_REGNUM:
    case SIM_SH_FR15_REGNUM:
      SET_FI (rn - SIM_SH_FR0_REGNUM, val);
      SET_FI (rn - SIM_SH_FR0_REGNUM, val);
      break;
      break;
    case SIM_SH_DSR_REGNUM:
    case SIM_SH_DSR_REGNUM:
      DSR = val;
      DSR = val;
      break;
      break;
    case SIM_SH_A0G_REGNUM:
    case SIM_SH_A0G_REGNUM:
      A0G = val;
      A0G = val;
      break;
      break;
    case SIM_SH_A0_REGNUM:
    case SIM_SH_A0_REGNUM:
      A0 = val;
      A0 = val;
      break;
      break;
    case SIM_SH_A1G_REGNUM:
    case SIM_SH_A1G_REGNUM:
      A1G = val;
      A1G = val;
      break;
      break;
    case SIM_SH_A1_REGNUM:
    case SIM_SH_A1_REGNUM:
      A1 = val;
      A1 = val;
      break;
      break;
    case SIM_SH_M0_REGNUM:
    case SIM_SH_M0_REGNUM:
      M0 = val;
      M0 = val;
      break;
      break;
    case SIM_SH_M1_REGNUM:
    case SIM_SH_M1_REGNUM:
      M1 = val;
      M1 = val;
      break;
      break;
    case SIM_SH_X0_REGNUM:
    case SIM_SH_X0_REGNUM:
      X0 = val;
      X0 = val;
      break;
      break;
    case SIM_SH_X1_REGNUM:
    case SIM_SH_X1_REGNUM:
      X1 = val;
      X1 = val;
      break;
      break;
    case SIM_SH_Y0_REGNUM:
    case SIM_SH_Y0_REGNUM:
      Y0 = val;
      Y0 = val;
      break;
      break;
    case SIM_SH_Y1_REGNUM:
    case SIM_SH_Y1_REGNUM:
      Y1 = val;
      Y1 = val;
      break;
      break;
    case SIM_SH_MOD_REGNUM:
    case SIM_SH_MOD_REGNUM:
      SET_MOD (val);
      SET_MOD (val);
      break;
      break;
    case SIM_SH_RS_REGNUM:
    case SIM_SH_RS_REGNUM:
      RS = val;
      RS = val;
      break;
      break;
    case SIM_SH_RE_REGNUM:
    case SIM_SH_RE_REGNUM:
      RE = val;
      RE = val;
      break;
      break;
    case SIM_SH_SSR_REGNUM:
    case SIM_SH_SSR_REGNUM:
      SSR = val;
      SSR = val;
      break;
      break;
    case SIM_SH_SPC_REGNUM:
    case SIM_SH_SPC_REGNUM:
      SPC = val;
      SPC = val;
      break;
      break;
    /* The rn_bank idiosyncracies are not due to hardware differences, but to
    /* The rn_bank idiosyncracies are not due to hardware differences, but to
       a weird aliasing naming scheme for sh3 / sh3e / sh4.  */
       a weird aliasing naming scheme for sh3 / sh3e / sh4.  */
    case SIM_SH_R0_BANK0_REGNUM: case SIM_SH_R1_BANK0_REGNUM:
    case SIM_SH_R0_BANK0_REGNUM: case SIM_SH_R1_BANK0_REGNUM:
    case SIM_SH_R2_BANK0_REGNUM: case SIM_SH_R3_BANK0_REGNUM:
    case SIM_SH_R2_BANK0_REGNUM: case SIM_SH_R3_BANK0_REGNUM:
    case SIM_SH_R4_BANK0_REGNUM: case SIM_SH_R5_BANK0_REGNUM:
    case SIM_SH_R4_BANK0_REGNUM: case SIM_SH_R5_BANK0_REGNUM:
    case SIM_SH_R6_BANK0_REGNUM: case SIM_SH_R7_BANK0_REGNUM:
    case SIM_SH_R6_BANK0_REGNUM: case SIM_SH_R7_BANK0_REGNUM:
      if (saved_state.asregs.bfd_mach == bfd_mach_sh2a)
      if (saved_state.asregs.bfd_mach == bfd_mach_sh2a)
        {
        {
          rn -= SIM_SH_R0_BANK0_REGNUM;
          rn -= SIM_SH_R0_BANK0_REGNUM;
          saved_state.asregs.regstack[gdb_bank_number].regs[rn] = val;
          saved_state.asregs.regstack[gdb_bank_number].regs[rn] = val;
        }
        }
      else
      else
      if (SR_MD && SR_RB)
      if (SR_MD && SR_RB)
        Rn_BANK (rn - SIM_SH_R0_BANK0_REGNUM) = val;
        Rn_BANK (rn - SIM_SH_R0_BANK0_REGNUM) = val;
      else
      else
        saved_state.asregs.regs[rn - SIM_SH_R0_BANK0_REGNUM] = val;
        saved_state.asregs.regs[rn - SIM_SH_R0_BANK0_REGNUM] = val;
      break;
      break;
    case SIM_SH_R0_BANK1_REGNUM: case SIM_SH_R1_BANK1_REGNUM:
    case SIM_SH_R0_BANK1_REGNUM: case SIM_SH_R1_BANK1_REGNUM:
    case SIM_SH_R2_BANK1_REGNUM: case SIM_SH_R3_BANK1_REGNUM:
    case SIM_SH_R2_BANK1_REGNUM: case SIM_SH_R3_BANK1_REGNUM:
    case SIM_SH_R4_BANK1_REGNUM: case SIM_SH_R5_BANK1_REGNUM:
    case SIM_SH_R4_BANK1_REGNUM: case SIM_SH_R5_BANK1_REGNUM:
    case SIM_SH_R6_BANK1_REGNUM: case SIM_SH_R7_BANK1_REGNUM:
    case SIM_SH_R6_BANK1_REGNUM: case SIM_SH_R7_BANK1_REGNUM:
      if (saved_state.asregs.bfd_mach == bfd_mach_sh2a)
      if (saved_state.asregs.bfd_mach == bfd_mach_sh2a)
        {
        {
          rn -= SIM_SH_R0_BANK1_REGNUM;
          rn -= SIM_SH_R0_BANK1_REGNUM;
          saved_state.asregs.regstack[gdb_bank_number].regs[rn + 8] = val;
          saved_state.asregs.regstack[gdb_bank_number].regs[rn + 8] = val;
        }
        }
      else
      else
      if (SR_MD && SR_RB)
      if (SR_MD && SR_RB)
        saved_state.asregs.regs[rn - SIM_SH_R0_BANK1_REGNUM] = val;
        saved_state.asregs.regs[rn - SIM_SH_R0_BANK1_REGNUM] = val;
      else
      else
        Rn_BANK (rn - SIM_SH_R0_BANK1_REGNUM) = val;
        Rn_BANK (rn - SIM_SH_R0_BANK1_REGNUM) = val;
      break;
      break;
    case SIM_SH_R0_BANK_REGNUM: case SIM_SH_R1_BANK_REGNUM:
    case SIM_SH_R0_BANK_REGNUM: case SIM_SH_R1_BANK_REGNUM:
    case SIM_SH_R2_BANK_REGNUM: case SIM_SH_R3_BANK_REGNUM:
    case SIM_SH_R2_BANK_REGNUM: case SIM_SH_R3_BANK_REGNUM:
    case SIM_SH_R4_BANK_REGNUM: case SIM_SH_R5_BANK_REGNUM:
    case SIM_SH_R4_BANK_REGNUM: case SIM_SH_R5_BANK_REGNUM:
    case SIM_SH_R6_BANK_REGNUM: case SIM_SH_R7_BANK_REGNUM:
    case SIM_SH_R6_BANK_REGNUM: case SIM_SH_R7_BANK_REGNUM:
      SET_Rn_BANK (rn - SIM_SH_R0_BANK_REGNUM, val);
      SET_Rn_BANK (rn - SIM_SH_R0_BANK_REGNUM, val);
      break;
      break;
    case SIM_SH_TBR_REGNUM:
    case SIM_SH_TBR_REGNUM:
      TBR = val;
      TBR = val;
      break;
      break;
    case SIM_SH_IBNR_REGNUM:
    case SIM_SH_IBNR_REGNUM:
      IBNR = val;
      IBNR = val;
      break;
      break;
    case SIM_SH_IBCR_REGNUM:
    case SIM_SH_IBCR_REGNUM:
      IBCR = val;
      IBCR = val;
      break;
      break;
    case SIM_SH_BANK_REGNUM:
    case SIM_SH_BANK_REGNUM:
      /* This is a pseudo-register maintained just for gdb.
      /* This is a pseudo-register maintained just for gdb.
         It tells us what register bank gdb would like to read/write.  */
         It tells us what register bank gdb would like to read/write.  */
      gdb_bank_number = val;
      gdb_bank_number = val;
      break;
      break;
    case SIM_SH_BANK_MACL_REGNUM:
    case SIM_SH_BANK_MACL_REGNUM:
      saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_MACL] = val;
      saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_MACL] = val;
      break;
      break;
    case SIM_SH_BANK_GBR_REGNUM:
    case SIM_SH_BANK_GBR_REGNUM:
      saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_GBR] = val;
      saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_GBR] = val;
      break;
      break;
    case SIM_SH_BANK_PR_REGNUM:
    case SIM_SH_BANK_PR_REGNUM:
      saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_PR] = val;
      saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_PR] = val;
      break;
      break;
    case SIM_SH_BANK_IVN_REGNUM:
    case SIM_SH_BANK_IVN_REGNUM:
      saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_IVN] = val;
      saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_IVN] = val;
      break;
      break;
    case SIM_SH_BANK_MACH_REGNUM:
    case SIM_SH_BANK_MACH_REGNUM:
      saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_MACH] = val;
      saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_MACH] = val;
      break;
      break;
    default:
    default:
      return 0;
      return 0;
    }
    }
  return -1;
  return -1;
}
}
 
 
int
int
sim_fetch_register (sd, rn, memory, length)
sim_fetch_register (sd, rn, memory, length)
     SIM_DESC sd;
     SIM_DESC sd;
     int rn;
     int rn;
     unsigned char *memory;
     unsigned char *memory;
     int length;
     int length;
{
{
  int val;
  int val;
 
 
  init_pointers ();
  init_pointers ();
  switch (rn)
  switch (rn)
    {
    {
    case SIM_SH_R0_REGNUM: case SIM_SH_R1_REGNUM: case SIM_SH_R2_REGNUM:
    case SIM_SH_R0_REGNUM: case SIM_SH_R1_REGNUM: case SIM_SH_R2_REGNUM:
    case SIM_SH_R3_REGNUM: case SIM_SH_R4_REGNUM: case SIM_SH_R5_REGNUM:
    case SIM_SH_R3_REGNUM: case SIM_SH_R4_REGNUM: case SIM_SH_R5_REGNUM:
    case SIM_SH_R6_REGNUM: case SIM_SH_R7_REGNUM: case SIM_SH_R8_REGNUM:
    case SIM_SH_R6_REGNUM: case SIM_SH_R7_REGNUM: case SIM_SH_R8_REGNUM:
    case SIM_SH_R9_REGNUM: case SIM_SH_R10_REGNUM: case SIM_SH_R11_REGNUM:
    case SIM_SH_R9_REGNUM: case SIM_SH_R10_REGNUM: case SIM_SH_R11_REGNUM:
    case SIM_SH_R12_REGNUM: case SIM_SH_R13_REGNUM: case SIM_SH_R14_REGNUM:
    case SIM_SH_R12_REGNUM: case SIM_SH_R13_REGNUM: case SIM_SH_R14_REGNUM:
    case SIM_SH_R15_REGNUM:
    case SIM_SH_R15_REGNUM:
      val = saved_state.asregs.regs[rn];
      val = saved_state.asregs.regs[rn];
      break;
      break;
    case SIM_SH_PC_REGNUM:
    case SIM_SH_PC_REGNUM:
      val = saved_state.asregs.pc;
      val = saved_state.asregs.pc;
      break;
      break;
    case SIM_SH_PR_REGNUM:
    case SIM_SH_PR_REGNUM:
      val = PR;
      val = PR;
      break;
      break;
    case SIM_SH_GBR_REGNUM:
    case SIM_SH_GBR_REGNUM:
      val = GBR;
      val = GBR;
      break;
      break;
    case SIM_SH_VBR_REGNUM:
    case SIM_SH_VBR_REGNUM:
      val = VBR;
      val = VBR;
      break;
      break;
    case SIM_SH_MACH_REGNUM:
    case SIM_SH_MACH_REGNUM:
      val = MACH;
      val = MACH;
      break;
      break;
    case SIM_SH_MACL_REGNUM:
    case SIM_SH_MACL_REGNUM:
      val = MACL;
      val = MACL;
      break;
      break;
    case SIM_SH_SR_REGNUM:
    case SIM_SH_SR_REGNUM:
      val = GET_SR ();
      val = GET_SR ();
      break;
      break;
    case SIM_SH_FPUL_REGNUM:
    case SIM_SH_FPUL_REGNUM:
      val = FPUL;
      val = FPUL;
      break;
      break;
    case SIM_SH_FPSCR_REGNUM:
    case SIM_SH_FPSCR_REGNUM:
      val = GET_FPSCR ();
      val = GET_FPSCR ();
      break;
      break;
    case SIM_SH_FR0_REGNUM: case SIM_SH_FR1_REGNUM: case SIM_SH_FR2_REGNUM:
    case SIM_SH_FR0_REGNUM: case SIM_SH_FR1_REGNUM: case SIM_SH_FR2_REGNUM:
    case SIM_SH_FR3_REGNUM: case SIM_SH_FR4_REGNUM: case SIM_SH_FR5_REGNUM:
    case SIM_SH_FR3_REGNUM: case SIM_SH_FR4_REGNUM: case SIM_SH_FR5_REGNUM:
    case SIM_SH_FR6_REGNUM: case SIM_SH_FR7_REGNUM: case SIM_SH_FR8_REGNUM:
    case SIM_SH_FR6_REGNUM: case SIM_SH_FR7_REGNUM: case SIM_SH_FR8_REGNUM:
    case SIM_SH_FR9_REGNUM: case SIM_SH_FR10_REGNUM: case SIM_SH_FR11_REGNUM:
    case SIM_SH_FR9_REGNUM: case SIM_SH_FR10_REGNUM: case SIM_SH_FR11_REGNUM:
    case SIM_SH_FR12_REGNUM: case SIM_SH_FR13_REGNUM: case SIM_SH_FR14_REGNUM:
    case SIM_SH_FR12_REGNUM: case SIM_SH_FR13_REGNUM: case SIM_SH_FR14_REGNUM:
    case SIM_SH_FR15_REGNUM:
    case SIM_SH_FR15_REGNUM:
      val = FI (rn - SIM_SH_FR0_REGNUM);
      val = FI (rn - SIM_SH_FR0_REGNUM);
      break;
      break;
    case SIM_SH_DSR_REGNUM:
    case SIM_SH_DSR_REGNUM:
      val = DSR;
      val = DSR;
      break;
      break;
    case SIM_SH_A0G_REGNUM:
    case SIM_SH_A0G_REGNUM:
      val = SEXT (A0G);
      val = SEXT (A0G);
      break;
      break;
    case SIM_SH_A0_REGNUM:
    case SIM_SH_A0_REGNUM:
      val = A0;
      val = A0;
      break;
      break;
    case SIM_SH_A1G_REGNUM:
    case SIM_SH_A1G_REGNUM:
      val = SEXT (A1G);
      val = SEXT (A1G);
      break;
      break;
    case SIM_SH_A1_REGNUM:
    case SIM_SH_A1_REGNUM:
      val = A1;
      val = A1;
      break;
      break;
    case SIM_SH_M0_REGNUM:
    case SIM_SH_M0_REGNUM:
      val = M0;
      val = M0;
      break;
      break;
    case SIM_SH_M1_REGNUM:
    case SIM_SH_M1_REGNUM:
      val = M1;
      val = M1;
      break;
      break;
    case SIM_SH_X0_REGNUM:
    case SIM_SH_X0_REGNUM:
      val = X0;
      val = X0;
      break;
      break;
    case SIM_SH_X1_REGNUM:
    case SIM_SH_X1_REGNUM:
      val = X1;
      val = X1;
      break;
      break;
    case SIM_SH_Y0_REGNUM:
    case SIM_SH_Y0_REGNUM:
      val = Y0;
      val = Y0;
      break;
      break;
    case SIM_SH_Y1_REGNUM:
    case SIM_SH_Y1_REGNUM:
      val = Y1;
      val = Y1;
      break;
      break;
    case SIM_SH_MOD_REGNUM:
    case SIM_SH_MOD_REGNUM:
      val = MOD;
      val = MOD;
      break;
      break;
    case SIM_SH_RS_REGNUM:
    case SIM_SH_RS_REGNUM:
      val = RS;
      val = RS;
      break;
      break;
    case SIM_SH_RE_REGNUM:
    case SIM_SH_RE_REGNUM:
      val = RE;
      val = RE;
      break;
      break;
    case SIM_SH_SSR_REGNUM:
    case SIM_SH_SSR_REGNUM:
      val = SSR;
      val = SSR;
      break;
      break;
    case SIM_SH_SPC_REGNUM:
    case SIM_SH_SPC_REGNUM:
      val = SPC;
      val = SPC;
      break;
      break;
    /* The rn_bank idiosyncracies are not due to hardware differences, but to
    /* The rn_bank idiosyncracies are not due to hardware differences, but to
       a weird aliasing naming scheme for sh3 / sh3e / sh4.  */
       a weird aliasing naming scheme for sh3 / sh3e / sh4.  */
    case SIM_SH_R0_BANK0_REGNUM: case SIM_SH_R1_BANK0_REGNUM:
    case SIM_SH_R0_BANK0_REGNUM: case SIM_SH_R1_BANK0_REGNUM:
    case SIM_SH_R2_BANK0_REGNUM: case SIM_SH_R3_BANK0_REGNUM:
    case SIM_SH_R2_BANK0_REGNUM: case SIM_SH_R3_BANK0_REGNUM:
    case SIM_SH_R4_BANK0_REGNUM: case SIM_SH_R5_BANK0_REGNUM:
    case SIM_SH_R4_BANK0_REGNUM: case SIM_SH_R5_BANK0_REGNUM:
    case SIM_SH_R6_BANK0_REGNUM: case SIM_SH_R7_BANK0_REGNUM:
    case SIM_SH_R6_BANK0_REGNUM: case SIM_SH_R7_BANK0_REGNUM:
      if (saved_state.asregs.bfd_mach == bfd_mach_sh2a)
      if (saved_state.asregs.bfd_mach == bfd_mach_sh2a)
        {
        {
          rn -= SIM_SH_R0_BANK0_REGNUM;
          rn -= SIM_SH_R0_BANK0_REGNUM;
          val = saved_state.asregs.regstack[gdb_bank_number].regs[rn];
          val = saved_state.asregs.regstack[gdb_bank_number].regs[rn];
        }
        }
      else
      else
      val = (SR_MD && SR_RB
      val = (SR_MD && SR_RB
             ? Rn_BANK (rn - SIM_SH_R0_BANK0_REGNUM)
             ? Rn_BANK (rn - SIM_SH_R0_BANK0_REGNUM)
             : saved_state.asregs.regs[rn - SIM_SH_R0_BANK0_REGNUM]);
             : saved_state.asregs.regs[rn - SIM_SH_R0_BANK0_REGNUM]);
      break;
      break;
    case SIM_SH_R0_BANK1_REGNUM: case SIM_SH_R1_BANK1_REGNUM:
    case SIM_SH_R0_BANK1_REGNUM: case SIM_SH_R1_BANK1_REGNUM:
    case SIM_SH_R2_BANK1_REGNUM: case SIM_SH_R3_BANK1_REGNUM:
    case SIM_SH_R2_BANK1_REGNUM: case SIM_SH_R3_BANK1_REGNUM:
    case SIM_SH_R4_BANK1_REGNUM: case SIM_SH_R5_BANK1_REGNUM:
    case SIM_SH_R4_BANK1_REGNUM: case SIM_SH_R5_BANK1_REGNUM:
    case SIM_SH_R6_BANK1_REGNUM: case SIM_SH_R7_BANK1_REGNUM:
    case SIM_SH_R6_BANK1_REGNUM: case SIM_SH_R7_BANK1_REGNUM:
      if (saved_state.asregs.bfd_mach == bfd_mach_sh2a)
      if (saved_state.asregs.bfd_mach == bfd_mach_sh2a)
        {
        {
          rn -= SIM_SH_R0_BANK1_REGNUM;
          rn -= SIM_SH_R0_BANK1_REGNUM;
          val = saved_state.asregs.regstack[gdb_bank_number].regs[rn + 8];
          val = saved_state.asregs.regstack[gdb_bank_number].regs[rn + 8];
        }
        }
      else
      else
      val = (! SR_MD || ! SR_RB
      val = (! SR_MD || ! SR_RB
             ? Rn_BANK (rn - SIM_SH_R0_BANK1_REGNUM)
             ? Rn_BANK (rn - SIM_SH_R0_BANK1_REGNUM)
             : saved_state.asregs.regs[rn - SIM_SH_R0_BANK1_REGNUM]);
             : saved_state.asregs.regs[rn - SIM_SH_R0_BANK1_REGNUM]);
      break;
      break;
    case SIM_SH_R0_BANK_REGNUM: case SIM_SH_R1_BANK_REGNUM:
    case SIM_SH_R0_BANK_REGNUM: case SIM_SH_R1_BANK_REGNUM:
    case SIM_SH_R2_BANK_REGNUM: case SIM_SH_R3_BANK_REGNUM:
    case SIM_SH_R2_BANK_REGNUM: case SIM_SH_R3_BANK_REGNUM:
    case SIM_SH_R4_BANK_REGNUM: case SIM_SH_R5_BANK_REGNUM:
    case SIM_SH_R4_BANK_REGNUM: case SIM_SH_R5_BANK_REGNUM:
    case SIM_SH_R6_BANK_REGNUM: case SIM_SH_R7_BANK_REGNUM:
    case SIM_SH_R6_BANK_REGNUM: case SIM_SH_R7_BANK_REGNUM:
      val = Rn_BANK (rn - SIM_SH_R0_BANK_REGNUM);
      val = Rn_BANK (rn - SIM_SH_R0_BANK_REGNUM);
      break;
      break;
    case SIM_SH_TBR_REGNUM:
    case SIM_SH_TBR_REGNUM:
      val = TBR;
      val = TBR;
      break;
      break;
    case SIM_SH_IBNR_REGNUM:
    case SIM_SH_IBNR_REGNUM:
      val = IBNR;
      val = IBNR;
      break;
      break;
    case SIM_SH_IBCR_REGNUM:
    case SIM_SH_IBCR_REGNUM:
      val = IBCR;
      val = IBCR;
      break;
      break;
    case SIM_SH_BANK_REGNUM:
    case SIM_SH_BANK_REGNUM:
      /* This is a pseudo-register maintained just for gdb.
      /* This is a pseudo-register maintained just for gdb.
         It tells us what register bank gdb would like to read/write.  */
         It tells us what register bank gdb would like to read/write.  */
      val = gdb_bank_number;
      val = gdb_bank_number;
      break;
      break;
    case SIM_SH_BANK_MACL_REGNUM:
    case SIM_SH_BANK_MACL_REGNUM:
      val = saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_MACL];
      val = saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_MACL];
      break;
      break;
    case SIM_SH_BANK_GBR_REGNUM:
    case SIM_SH_BANK_GBR_REGNUM:
      val = saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_GBR];
      val = saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_GBR];
      break;
      break;
    case SIM_SH_BANK_PR_REGNUM:
    case SIM_SH_BANK_PR_REGNUM:
      val = saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_PR];
      val = saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_PR];
      break;
      break;
    case SIM_SH_BANK_IVN_REGNUM:
    case SIM_SH_BANK_IVN_REGNUM:
      val = saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_IVN];
      val = saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_IVN];
      break;
      break;
    case SIM_SH_BANK_MACH_REGNUM:
    case SIM_SH_BANK_MACH_REGNUM:
      val = saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_MACH];
      val = saved_state.asregs.regstack[gdb_bank_number].regs[REGBANK_MACH];
      break;
      break;
    default:
    default:
      return 0;
      return 0;
    }
    }
  * (int *) memory = swap (val);
  * (int *) memory = swap (val);
  return -1;
  return -1;
}
}
 
 
int
int
sim_trace (sd)
sim_trace (sd)
     SIM_DESC sd;
     SIM_DESC sd;
{
{
  tracing = 1;
  tracing = 1;
  sim_resume (sd, 0, 0);
  sim_resume (sd, 0, 0);
  tracing = 0;
  tracing = 0;
  return 1;
  return 1;
}
}
 
 
void
void
sim_stop_reason (sd, reason, sigrc)
sim_stop_reason (sd, reason, sigrc)
     SIM_DESC sd;
     SIM_DESC sd;
     enum sim_stop *reason;
     enum sim_stop *reason;
     int *sigrc;
     int *sigrc;
{
{
  /* The SH simulator uses SIGQUIT to indicate that the program has
  /* The SH simulator uses SIGQUIT to indicate that the program has
     exited, so we must check for it here and translate it to exit.  */
     exited, so we must check for it here and translate it to exit.  */
  if (saved_state.asregs.exception == SIGQUIT)
  if (saved_state.asregs.exception == SIGQUIT)
    {
    {
      *reason = sim_exited;
      *reason = sim_exited;
      *sigrc = saved_state.asregs.regs[5];
      *sigrc = saved_state.asregs.regs[5];
    }
    }
  else
  else
    {
    {
      *reason = sim_stopped;
      *reason = sim_stopped;
      *sigrc = saved_state.asregs.exception;
      *sigrc = saved_state.asregs.exception;
    }
    }
}
}
 
 
void
void
sim_info (sd, verbose)
sim_info (sd, verbose)
     SIM_DESC sd;
     SIM_DESC sd;
     int verbose;
     int verbose;
{
{
  double timetaken =
  double timetaken =
    (double) saved_state.asregs.ticks / (double) now_persec ();
    (double) saved_state.asregs.ticks / (double) now_persec ();
  double virttime = saved_state.asregs.cycles / 36.0e6;
  double virttime = saved_state.asregs.cycles / 36.0e6;
 
 
  callback->printf_filtered (callback, "\n\n# instructions executed  %10d\n",
  callback->printf_filtered (callback, "\n\n# instructions executed  %10d\n",
                             saved_state.asregs.insts);
                             saved_state.asregs.insts);
  callback->printf_filtered (callback, "# cycles                 %10d\n",
  callback->printf_filtered (callback, "# cycles                 %10d\n",
                             saved_state.asregs.cycles);
                             saved_state.asregs.cycles);
  callback->printf_filtered (callback, "# pipeline stalls        %10d\n",
  callback->printf_filtered (callback, "# pipeline stalls        %10d\n",
                             saved_state.asregs.stalls);
                             saved_state.asregs.stalls);
  callback->printf_filtered (callback, "# misaligned load/store  %10d\n",
  callback->printf_filtered (callback, "# misaligned load/store  %10d\n",
                             saved_state.asregs.memstalls);
                             saved_state.asregs.memstalls);
  callback->printf_filtered (callback, "# real time taken        %10.4f\n",
  callback->printf_filtered (callback, "# real time taken        %10.4f\n",
                             timetaken);
                             timetaken);
  callback->printf_filtered (callback, "# virtual time taken     %10.4f\n",
  callback->printf_filtered (callback, "# virtual time taken     %10.4f\n",
                             virttime);
                             virttime);
  callback->printf_filtered (callback, "# profiling size         %10d\n",
  callback->printf_filtered (callback, "# profiling size         %10d\n",
                             sim_profile_size);
                             sim_profile_size);
  callback->printf_filtered (callback, "# profiling frequency    %10d\n",
  callback->printf_filtered (callback, "# profiling frequency    %10d\n",
                             saved_state.asregs.profile);
                             saved_state.asregs.profile);
  callback->printf_filtered (callback, "# profile maxpc          %10x\n",
  callback->printf_filtered (callback, "# profile maxpc          %10x\n",
                             (1 << sim_profile_size) << PROFILE_SHIFT);
                             (1 << sim_profile_size) << PROFILE_SHIFT);
 
 
  if (timetaken != 0)
  if (timetaken != 0)
    {
    {
      callback->printf_filtered (callback, "# cycles/second          %10d\n",
      callback->printf_filtered (callback, "# cycles/second          %10d\n",
                                 (int) (saved_state.asregs.cycles / timetaken));
                                 (int) (saved_state.asregs.cycles / timetaken));
      callback->printf_filtered (callback, "# simulation ratio       %10.4f\n",
      callback->printf_filtered (callback, "# simulation ratio       %10.4f\n",
                                 virttime / timetaken);
                                 virttime / timetaken);
    }
    }
}
}
 
 
void
void
sim_set_profile (n)
sim_set_profile (n)
     int n;
     int n;
{
{
  saved_state.asregs.profile = n;
  saved_state.asregs.profile = n;
}
}
 
 
void
void
sim_set_profile_size (n)
sim_set_profile_size (n)
     int n;
     int n;
{
{
  sim_profile_size = n;
  sim_profile_size = n;
}
}
 
 
SIM_DESC
SIM_DESC
sim_open (kind, cb, abfd, argv)
sim_open (kind, cb, abfd, argv)
     SIM_OPEN_KIND kind;
     SIM_OPEN_KIND kind;
     host_callback *cb;
     host_callback *cb;
     struct bfd *abfd;
     struct bfd *abfd;
     char **argv;
     char **argv;
{
{
  char **p;
  char **p;
  int endian_set = 0;
  int endian_set = 0;
  int i;
  int i;
  union
  union
    {
    {
      int i;
      int i;
      short s[2];
      short s[2];
      char c[4];
      char c[4];
    }
    }
  mem_word;
  mem_word;
 
 
  sim_kind = kind;
  sim_kind = kind;
  myname = argv[0];
  myname = argv[0];
  callback = cb;
  callback = cb;
 
 
  for (p = argv + 1; *p != NULL; ++p)
  for (p = argv + 1; *p != NULL; ++p)
    {
    {
      if (strcmp (*p, "-E") == 0)
      if (strcmp (*p, "-E") == 0)
        {
        {
          ++p;
          ++p;
          if (*p == NULL)
          if (*p == NULL)
            {
            {
              /* FIXME: This doesn't use stderr, but then the rest of the
              /* FIXME: This doesn't use stderr, but then the rest of the
                 file doesn't either.  */
                 file doesn't either.  */
              callback->printf_filtered (callback, "Missing argument to `-E'.\n");
              callback->printf_filtered (callback, "Missing argument to `-E'.\n");
              return 0;
              return 0;
            }
            }
          target_little_endian = strcmp (*p, "big") != 0;
          target_little_endian = strcmp (*p, "big") != 0;
          endian_set = 1;
          endian_set = 1;
        }
        }
      else if (isdigit (**p))
      else if (isdigit (**p))
        parse_and_set_memory_size (*p);
        parse_and_set_memory_size (*p);
    }
    }
 
 
  if (abfd != NULL && ! endian_set)
  if (abfd != NULL && ! endian_set)
      target_little_endian = ! bfd_big_endian (abfd);
      target_little_endian = ! bfd_big_endian (abfd);
 
 
  if (abfd)
  if (abfd)
    init_dsp (abfd);
    init_dsp (abfd);
 
 
  for (i = 4; (i -= 2) >= 0; )
  for (i = 4; (i -= 2) >= 0; )
    mem_word.s[i >> 1] = i;
    mem_word.s[i >> 1] = i;
  global_endianw = mem_word.i >> (target_little_endian ? 0 : 16) & 0xffff;
  global_endianw = mem_word.i >> (target_little_endian ? 0 : 16) & 0xffff;
 
 
  for (i = 4; --i >= 0; )
  for (i = 4; --i >= 0; )
    mem_word.c[i] = i;
    mem_word.c[i] = i;
  endianb = mem_word.i >> (target_little_endian ? 0 : 24) & 0xff;
  endianb = mem_word.i >> (target_little_endian ? 0 : 24) & 0xff;
 
 
  /* fudge our descriptor for now */
  /* fudge our descriptor for now */
  return (SIM_DESC) 1;
  return (SIM_DESC) 1;
}
}
 
 
static void
static void
parse_and_set_memory_size (str)
parse_and_set_memory_size (str)
     char *str;
     char *str;
{
{
  int n;
  int n;
 
 
  n = strtol (str, NULL, 10);
  n = strtol (str, NULL, 10);
  if (n > 0 && n <= 24)
  if (n > 0 && n <= 24)
    sim_memory_size = n;
    sim_memory_size = n;
  else
  else
    callback->printf_filtered (callback, "Bad memory size %d; must be 1 to 24, inclusive\n", n);
    callback->printf_filtered (callback, "Bad memory size %d; must be 1 to 24, inclusive\n", n);
}
}
 
 
void
void
sim_close (sd, quitting)
sim_close (sd, quitting)
     SIM_DESC sd;
     SIM_DESC sd;
     int quitting;
     int quitting;
{
{
  /* nothing to do */
  /* nothing to do */
}
}
 
 
SIM_RC
SIM_RC
sim_load (sd, prog, abfd, from_tty)
sim_load (sd, prog, abfd, from_tty)
     SIM_DESC sd;
     SIM_DESC sd;
     char *prog;
     char *prog;
     bfd *abfd;
     bfd *abfd;
     int from_tty;
     int from_tty;
{
{
  extern bfd *sim_load_file (); /* ??? Don't know where this should live.  */
  extern bfd *sim_load_file (); /* ??? Don't know where this should live.  */
  bfd *prog_bfd;
  bfd *prog_bfd;
 
 
  prog_bfd = sim_load_file (sd, myname, callback, prog, abfd,
  prog_bfd = sim_load_file (sd, myname, callback, prog, abfd,
                            sim_kind == SIM_OPEN_DEBUG,
                            sim_kind == SIM_OPEN_DEBUG,
                            0, sim_write);
                            0, sim_write);
 
 
  /* Set the bfd machine type.  */
  /* Set the bfd machine type.  */
  if (prog_bfd)
  if (prog_bfd)
    saved_state.asregs.bfd_mach = bfd_get_mach (prog_bfd);
    saved_state.asregs.bfd_mach = bfd_get_mach (prog_bfd);
  else if (abfd)
  else if (abfd)
    saved_state.asregs.bfd_mach = bfd_get_mach (abfd);
    saved_state.asregs.bfd_mach = bfd_get_mach (abfd);
  else
  else
    saved_state.asregs.bfd_mach = 0;
    saved_state.asregs.bfd_mach = 0;
 
 
  if (prog_bfd == NULL)
  if (prog_bfd == NULL)
    return SIM_RC_FAIL;
    return SIM_RC_FAIL;
  if (abfd == NULL)
  if (abfd == NULL)
    bfd_close (prog_bfd);
    bfd_close (prog_bfd);
  return SIM_RC_OK;
  return SIM_RC_OK;
}
}
 
 
SIM_RC
SIM_RC
sim_create_inferior (sd, prog_bfd, argv, env)
sim_create_inferior (sd, prog_bfd, argv, env)
     SIM_DESC sd;
     SIM_DESC sd;
     struct bfd *prog_bfd;
     struct bfd *prog_bfd;
     char **argv;
     char **argv;
     char **env;
     char **env;
{
{
  /* Clear the registers. */
  /* Clear the registers. */
  memset (&saved_state, 0,
  memset (&saved_state, 0,
          (char*) &saved_state.asregs.end_of_registers - (char*) &saved_state);
          (char*) &saved_state.asregs.end_of_registers - (char*) &saved_state);
 
 
  /* Set the PC.  */
  /* Set the PC.  */
  if (prog_bfd != NULL)
  if (prog_bfd != NULL)
    saved_state.asregs.pc = bfd_get_start_address (prog_bfd);
    saved_state.asregs.pc = bfd_get_start_address (prog_bfd);
 
 
  /* Set the bfd machine type.  */
  /* Set the bfd machine type.  */
  if (prog_bfd != NULL)
  if (prog_bfd != NULL)
    saved_state.asregs.bfd_mach = bfd_get_mach (prog_bfd);
    saved_state.asregs.bfd_mach = bfd_get_mach (prog_bfd);
 
 
  /* Record the program's arguments. */
  /* Record the program's arguments. */
  prog_argv = argv;
  prog_argv = argv;
 
 
  return SIM_RC_OK;
  return SIM_RC_OK;
}
}
 
 
void
void
sim_do_command (sd, cmd)
sim_do_command (sd, cmd)
     SIM_DESC sd;
     SIM_DESC sd;
     char *cmd;
     char *cmd;
{
{
  char *sms_cmd = "set-memory-size";
  char *sms_cmd = "set-memory-size";
  int cmdsize;
  int cmdsize;
 
 
  if (cmd == NULL || *cmd == '\0')
  if (cmd == NULL || *cmd == '\0')
    {
    {
      cmd = "help";
      cmd = "help";
    }
    }
 
 
  cmdsize = strlen (sms_cmd);
  cmdsize = strlen (sms_cmd);
  if (strncmp (cmd, sms_cmd, cmdsize) == 0
  if (strncmp (cmd, sms_cmd, cmdsize) == 0
      && strchr (" \t", cmd[cmdsize]) != NULL)
      && strchr (" \t", cmd[cmdsize]) != NULL)
    {
    {
      parse_and_set_memory_size (cmd + cmdsize + 1);
      parse_and_set_memory_size (cmd + cmdsize + 1);
    }
    }
  else if (strcmp (cmd, "help") == 0)
  else if (strcmp (cmd, "help") == 0)
    {
    {
      (callback->printf_filtered) (callback,
      (callback->printf_filtered) (callback,
                                   "List of SH simulator commands:\n\n");
                                   "List of SH simulator commands:\n\n");
      (callback->printf_filtered) (callback, "set-memory-size <n> -- Set the number of address bits to use\n");
      (callback->printf_filtered) (callback, "set-memory-size <n> -- Set the number of address bits to use\n");
      (callback->printf_filtered) (callback, "\n");
      (callback->printf_filtered) (callback, "\n");
    }
    }
  else
  else
    {
    {
      (callback->printf_filtered) (callback, "Error: \"%s\" is not a valid SH simulator command.\n", cmd);
      (callback->printf_filtered) (callback, "Error: \"%s\" is not a valid SH simulator command.\n", cmd);
    }
    }
}
}
 
 
void
void
sim_set_callbacks (p)
sim_set_callbacks (p)
     host_callback *p;
     host_callback *p;
{
{
  callback = p;
  callback = p;
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.