OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-7.1/] [sim/] [rx/] [rx.c] - Diff between revs 834 and 842

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

Rev 834 Rev 842
/* rx.c --- opcode semantics for stand-alone RX simulator.
/* rx.c --- opcode semantics for stand-alone RX simulator.
 
 
Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
Contributed by Red Hat, Inc.
Contributed by Red Hat, Inc.
 
 
This file is part of the GNU simulators.
This file is part of the GNU simulators.
 
 
This program is free software; you can redistribute it and/or modify
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
(at your option) any later version.
 
 
This program is distributed in the hope that it will be useful,
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
GNU General Public License for more details.
 
 
You should have received a copy of the GNU General Public License
You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
#include <signal.h>
#include <signal.h>
 
 
#include "opcode/rx.h"
#include "opcode/rx.h"
#include "cpu.h"
#include "cpu.h"
#include "mem.h"
#include "mem.h"
#include "syscalls.h"
#include "syscalls.h"
#include "fpu.h"
#include "fpu.h"
#include "err.h"
#include "err.h"
 
 
#define tprintf if (trace) printf
#define tprintf if (trace) printf
 
 
jmp_buf decode_jmp_buf;
jmp_buf decode_jmp_buf;
unsigned int rx_cycles = 0;
unsigned int rx_cycles = 0;
 
 
static int size2bytes[] = {
static int size2bytes[] = {
  4, 1, 1, 1, 2, 2, 2, 3, 4
  4, 1, 1, 1, 2, 2, 2, 3, 4
};
};
 
 
typedef struct {
typedef struct {
  unsigned long dpc;
  unsigned long dpc;
} RX_Data;
} RX_Data;
 
 
#define rx_abort() _rx_abort(__FILE__, __LINE__)
#define rx_abort() _rx_abort(__FILE__, __LINE__)
static void
static void
_rx_abort (const char *file, int line)
_rx_abort (const char *file, int line)
{
{
  if (strrchr (file, '/'))
  if (strrchr (file, '/'))
    file = strrchr (file, '/') + 1;
    file = strrchr (file, '/') + 1;
  fprintf(stderr, "abort at %s:%d\n", file, line);
  fprintf(stderr, "abort at %s:%d\n", file, line);
  abort();
  abort();
}
}
 
 
static int
static int
rx_get_byte (void *vdata)
rx_get_byte (void *vdata)
{
{
  int saved_trace = trace;
  int saved_trace = trace;
  unsigned char rv;
  unsigned char rv;
 
 
  if (trace == 1)
  if (trace == 1)
    trace = 0;
    trace = 0;
 
 
  RX_Data *rx_data = (RX_Data *)vdata;
  RX_Data *rx_data = (RX_Data *)vdata;
  if (rx_big_endian)
  if (rx_big_endian)
    /* See load.c for an explanation of this.  */
    /* See load.c for an explanation of this.  */
    rv = mem_get_pc (rx_data->dpc ^ 3);
    rv = mem_get_pc (rx_data->dpc ^ 3);
  else
  else
    rv = mem_get_pc (rx_data->dpc);
    rv = mem_get_pc (rx_data->dpc);
  rx_data->dpc ++;
  rx_data->dpc ++;
  trace = saved_trace;
  trace = saved_trace;
  return rv;
  return rv;
}
}
 
 
static int
static int
get_op (RX_Opcode_Decoded *rd, int i)
get_op (RX_Opcode_Decoded *rd, int i)
{
{
  RX_Opcode_Operand *o = rd->op + i;
  RX_Opcode_Operand *o = rd->op + i;
  int addr, rv = 0;
  int addr, rv = 0;
 
 
  switch (o->type)
  switch (o->type)
    {
    {
    case RX_Operand_None:
    case RX_Operand_None:
      rx_abort ();
      rx_abort ();
 
 
    case RX_Operand_Immediate:  /* #addend */
    case RX_Operand_Immediate:  /* #addend */
      return o->addend;
      return o->addend;
 
 
    case RX_Operand_Register:   /* Rn */
    case RX_Operand_Register:   /* Rn */
      rv = get_reg (o->reg);
      rv = get_reg (o->reg);
      break;
      break;
 
 
    case RX_Operand_Predec:     /* [-Rn] */
    case RX_Operand_Predec:     /* [-Rn] */
      put_reg (o->reg, get_reg (o->reg) - size2bytes[o->size]);
      put_reg (o->reg, get_reg (o->reg) - size2bytes[o->size]);
      /* fall through */
      /* fall through */
    case RX_Operand_Postinc:    /* [Rn+] */
    case RX_Operand_Postinc:    /* [Rn+] */
    case RX_Operand_Indirect:   /* [Rn + addend] */
    case RX_Operand_Indirect:   /* [Rn + addend] */
 
 
      addr = get_reg (o->reg) + o->addend;
      addr = get_reg (o->reg) + o->addend;
      switch (o->size)
      switch (o->size)
        {
        {
        case RX_AnySize:
        case RX_AnySize:
          rx_abort ();
          rx_abort ();
 
 
        case RX_Byte: /* undefined extension */
        case RX_Byte: /* undefined extension */
        case RX_UByte:
        case RX_UByte:
        case RX_SByte:
        case RX_SByte:
          rv = mem_get_qi (addr);
          rv = mem_get_qi (addr);
          break;
          break;
 
 
        case RX_Word: /* undefined extension */
        case RX_Word: /* undefined extension */
        case RX_UWord:
        case RX_UWord:
        case RX_SWord:
        case RX_SWord:
          rv = mem_get_hi (addr);
          rv = mem_get_hi (addr);
          break;
          break;
 
 
        case RX_3Byte:
        case RX_3Byte:
          rv = mem_get_psi (addr);
          rv = mem_get_psi (addr);
          break;
          break;
 
 
        case RX_Long:
        case RX_Long:
          rv = mem_get_si (addr);
          rv = mem_get_si (addr);
          break;
          break;
        }
        }
 
 
      if (o->type == RX_Operand_Postinc)
      if (o->type == RX_Operand_Postinc)
        put_reg (o->reg, get_reg (o->reg) + size2bytes[o->size]);
        put_reg (o->reg, get_reg (o->reg) + size2bytes[o->size]);
 
 
      break;
      break;
 
 
    case RX_Operand_Condition:  /* eq, gtu, etc */
    case RX_Operand_Condition:  /* eq, gtu, etc */
      return condition_true (o->reg);
      return condition_true (o->reg);
 
 
    case RX_Operand_Flag:       /* [UIOSZC] */
    case RX_Operand_Flag:       /* [UIOSZC] */
      return (regs.r_psw & (1 << o->reg)) ? 1 : 0;
      return (regs.r_psw & (1 << o->reg)) ? 1 : 0;
    }
    }
 
 
  /* if we've gotten here, we need to clip/extend the value according
  /* if we've gotten here, we need to clip/extend the value according
     to the size.  */
     to the size.  */
  switch (o->size)
  switch (o->size)
    {
    {
    case RX_AnySize:
    case RX_AnySize:
      rx_abort ();
      rx_abort ();
 
 
    case RX_Byte: /* undefined extension */
    case RX_Byte: /* undefined extension */
      rv |= 0xdeadbe00; /* keep them honest */
      rv |= 0xdeadbe00; /* keep them honest */
      break;
      break;
 
 
    case RX_UByte:
    case RX_UByte:
      rv &= 0xff;
      rv &= 0xff;
      break;
      break;
 
 
    case RX_SByte:
    case RX_SByte:
      rv = sign_ext (rv, 8);
      rv = sign_ext (rv, 8);
      break;
      break;
 
 
    case RX_Word: /* undefined extension */
    case RX_Word: /* undefined extension */
      rv |= 0xdead0000; /* keep them honest */
      rv |= 0xdead0000; /* keep them honest */
      break;
      break;
 
 
    case RX_UWord:
    case RX_UWord:
      rv &=  0xffff;
      rv &=  0xffff;
      break;
      break;
 
 
    case RX_SWord:
    case RX_SWord:
      rv = sign_ext (rv, 16);
      rv = sign_ext (rv, 16);
      break;
      break;
 
 
    case RX_3Byte:
    case RX_3Byte:
      rv &= 0xffffff;
      rv &= 0xffffff;
      break;
      break;
 
 
    case RX_Long:
    case RX_Long:
      break;
      break;
    }
    }
  return rv;
  return rv;
}
}
 
 
static void
static void
put_op (RX_Opcode_Decoded *rd, int i, int v)
put_op (RX_Opcode_Decoded *rd, int i, int v)
{
{
  RX_Opcode_Operand *o = rd->op + i;
  RX_Opcode_Operand *o = rd->op + i;
  int addr;
  int addr;
 
 
  switch (o->size)
  switch (o->size)
    {
    {
    case RX_AnySize:
    case RX_AnySize:
      if (o->type != RX_Operand_Register)
      if (o->type != RX_Operand_Register)
        rx_abort ();
        rx_abort ();
      break;
      break;
 
 
    case RX_Byte: /* undefined extension */
    case RX_Byte: /* undefined extension */
      v |= 0xdeadbe00; /* keep them honest */
      v |= 0xdeadbe00; /* keep them honest */
      break;
      break;
 
 
    case RX_UByte:
    case RX_UByte:
      v &= 0xff;
      v &= 0xff;
      break;
      break;
 
 
    case RX_SByte:
    case RX_SByte:
      v = sign_ext (v, 8);
      v = sign_ext (v, 8);
      break;
      break;
 
 
    case RX_Word: /* undefined extension */
    case RX_Word: /* undefined extension */
      v |= 0xdead0000; /* keep them honest */
      v |= 0xdead0000; /* keep them honest */
      break;
      break;
 
 
    case RX_UWord:
    case RX_UWord:
      v &=  0xffff;
      v &=  0xffff;
      break;
      break;
 
 
    case RX_SWord:
    case RX_SWord:
      v = sign_ext (v, 16);
      v = sign_ext (v, 16);
      break;
      break;
 
 
    case RX_3Byte:
    case RX_3Byte:
      v &= 0xffffff;
      v &= 0xffffff;
      break;
      break;
 
 
    case RX_Long:
    case RX_Long:
      break;
      break;
    }
    }
 
 
  switch (o->type)
  switch (o->type)
    {
    {
    case RX_Operand_None:
    case RX_Operand_None:
      /* Opcodes like TST and CMP use this.  */
      /* Opcodes like TST and CMP use this.  */
      break;
      break;
 
 
    case RX_Operand_Immediate:  /* #addend */
    case RX_Operand_Immediate:  /* #addend */
    case RX_Operand_Condition:  /* eq, gtu, etc */
    case RX_Operand_Condition:  /* eq, gtu, etc */
      rx_abort ();
      rx_abort ();
 
 
    case RX_Operand_Register:   /* Rn */
    case RX_Operand_Register:   /* Rn */
      put_reg (o->reg, v);
      put_reg (o->reg, v);
      break;
      break;
 
 
    case RX_Operand_Predec:     /* [-Rn] */
    case RX_Operand_Predec:     /* [-Rn] */
      put_reg (o->reg, get_reg (o->reg) - size2bytes[o->size]);
      put_reg (o->reg, get_reg (o->reg) - size2bytes[o->size]);
      /* fall through */
      /* fall through */
    case RX_Operand_Postinc:    /* [Rn+] */
    case RX_Operand_Postinc:    /* [Rn+] */
    case RX_Operand_Indirect:   /* [Rn + addend] */
    case RX_Operand_Indirect:   /* [Rn + addend] */
 
 
      addr = get_reg (o->reg) + o->addend;
      addr = get_reg (o->reg) + o->addend;
      switch (o->size)
      switch (o->size)
        {
        {
        case RX_AnySize:
        case RX_AnySize:
          rx_abort ();
          rx_abort ();
 
 
        case RX_Byte: /* undefined extension */
        case RX_Byte: /* undefined extension */
        case RX_UByte:
        case RX_UByte:
        case RX_SByte:
        case RX_SByte:
          mem_put_qi (addr, v);
          mem_put_qi (addr, v);
          break;
          break;
 
 
        case RX_Word: /* undefined extension */
        case RX_Word: /* undefined extension */
        case RX_UWord:
        case RX_UWord:
        case RX_SWord:
        case RX_SWord:
          mem_put_hi (addr, v);
          mem_put_hi (addr, v);
          break;
          break;
 
 
        case RX_3Byte:
        case RX_3Byte:
          mem_put_psi (addr, v);
          mem_put_psi (addr, v);
          break;
          break;
 
 
        case RX_Long:
        case RX_Long:
          mem_put_si (addr, v);
          mem_put_si (addr, v);
          break;
          break;
        }
        }
 
 
      if (o->type == RX_Operand_Postinc)
      if (o->type == RX_Operand_Postinc)
        put_reg (o->reg, get_reg (o->reg) + size2bytes[o->size]);
        put_reg (o->reg, get_reg (o->reg) + size2bytes[o->size]);
 
 
      break;
      break;
 
 
    case RX_Operand_Flag:       /* [UIOSZC] */
    case RX_Operand_Flag:       /* [UIOSZC] */
      if (v)
      if (v)
        regs.r_psw |= (1 << o->reg);
        regs.r_psw |= (1 << o->reg);
      else
      else
        regs.r_psw &= ~(1 << o->reg);
        regs.r_psw &= ~(1 << o->reg);
      break;
      break;
    }
    }
}
}
 
 
#define PD(x) put_op (&opcode, 0, x)
#define PD(x) put_op (&opcode, 0, x)
#define PS(x) put_op (&opcode, 1, x)
#define PS(x) put_op (&opcode, 1, x)
#define PS2(x) put_op (&opcode, 2, x)
#define PS2(x) put_op (&opcode, 2, x)
#define GD() get_op (&opcode, 0)
#define GD() get_op (&opcode, 0)
#define GS() get_op (&opcode, 1)
#define GS() get_op (&opcode, 1)
#define GS2() get_op (&opcode, 2)
#define GS2() get_op (&opcode, 2)
#define DSZ() size2bytes[opcode.op[0].size]
#define DSZ() size2bytes[opcode.op[0].size]
#define SSZ() size2bytes[opcode.op[0].size]
#define SSZ() size2bytes[opcode.op[0].size]
#define S2SZ() size2bytes[opcode.op[0].size]
#define S2SZ() size2bytes[opcode.op[0].size]
 
 
/* "Universal" sources.  */
/* "Universal" sources.  */
#define US1() ((opcode.op[2].type == RX_Operand_None) ? GD() : GS())
#define US1() ((opcode.op[2].type == RX_Operand_None) ? GD() : GS())
#define US2() ((opcode.op[2].type == RX_Operand_None) ? GS() : GS2())
#define US2() ((opcode.op[2].type == RX_Operand_None) ? GS() : GS2())
 
 
static void
static void
push(int val)
push(int val)
{
{
  int rsp = get_reg (sp);
  int rsp = get_reg (sp);
  rsp -= 4;
  rsp -= 4;
  put_reg (sp, rsp);
  put_reg (sp, rsp);
  mem_put_si (rsp, val);
  mem_put_si (rsp, val);
}
}
 
 
/* Just like the above, but tag the memory as "pushed pc" so if anyone
/* Just like the above, but tag the memory as "pushed pc" so if anyone
   tries to write to it, it will cause an error.  */
   tries to write to it, it will cause an error.  */
static void
static void
pushpc(int val)
pushpc(int val)
{
{
  int rsp = get_reg (sp);
  int rsp = get_reg (sp);
  rsp -= 4;
  rsp -= 4;
  put_reg (sp, rsp);
  put_reg (sp, rsp);
  mem_put_si (rsp, val);
  mem_put_si (rsp, val);
  mem_set_content_range (rsp, rsp+3, MC_PUSHED_PC);
  mem_set_content_range (rsp, rsp+3, MC_PUSHED_PC);
}
}
 
 
static int
static int
pop()
pop()
{
{
  int rv;
  int rv;
  int rsp = get_reg (sp);
  int rsp = get_reg (sp);
  rv = mem_get_si (rsp);
  rv = mem_get_si (rsp);
  rsp += 4;
  rsp += 4;
  put_reg (sp, rsp);
  put_reg (sp, rsp);
  return rv;
  return rv;
}
}
 
 
static int
static int
poppc()
poppc()
{
{
  int rv;
  int rv;
  int rsp = get_reg (sp);
  int rsp = get_reg (sp);
  if (mem_get_content_type (rsp) != MC_PUSHED_PC)
  if (mem_get_content_type (rsp) != MC_PUSHED_PC)
    execution_error (SIM_ERR_CORRUPT_STACK, rsp);
    execution_error (SIM_ERR_CORRUPT_STACK, rsp);
  rv = mem_get_si (rsp);
  rv = mem_get_si (rsp);
  mem_set_content_range (rsp, rsp+3, MC_UNINIT);
  mem_set_content_range (rsp, rsp+3, MC_UNINIT);
  rsp += 4;
  rsp += 4;
  put_reg (sp, rsp);
  put_reg (sp, rsp);
  return rv;
  return rv;
}
}
 
 
#define MATH_OP(vop,c)                          \
#define MATH_OP(vop,c)                          \
{ \
{ \
  uma = US1(); \
  uma = US1(); \
  umb = US2(); \
  umb = US2(); \
  ll = (unsigned long long) uma vop (unsigned long long) umb vop c; \
  ll = (unsigned long long) uma vop (unsigned long long) umb vop c; \
  tprintf ("0x%x " #vop " 0x%x " #vop " 0x%x = 0x%llx\n", uma, umb, c, ll); \
  tprintf ("0x%x " #vop " 0x%x " #vop " 0x%x = 0x%llx\n", uma, umb, c, ll); \
  ma = sign_ext (uma, DSZ() * 8);                                       \
  ma = sign_ext (uma, DSZ() * 8);                                       \
  mb = sign_ext (umb, DSZ() * 8);                                       \
  mb = sign_ext (umb, DSZ() * 8);                                       \
  sll = (long long) ma vop (long long) mb vop c; \
  sll = (long long) ma vop (long long) mb vop c; \
  tprintf ("%d " #vop " %d " #vop " %d = %lld\n", ma, mb, c, sll); \
  tprintf ("%d " #vop " %d " #vop " %d = %lld\n", ma, mb, c, sll); \
  set_oszc (sll, DSZ(), (long long) ll > ((1 vop 1) ? (long long) b2mask[DSZ()] : (long long) -1)); \
  set_oszc (sll, DSZ(), (long long) ll > ((1 vop 1) ? (long long) b2mask[DSZ()] : (long long) -1)); \
  PD (sll); \
  PD (sll); \
}
}
 
 
#define LOGIC_OP(vop) \
#define LOGIC_OP(vop) \
{ \
{ \
  ma = US1(); \
  ma = US1(); \
  mb = US2(); \
  mb = US2(); \
  v = ma vop mb; \
  v = ma vop mb; \
  tprintf("0x%x " #vop " 0x%x = 0x%x\n", ma, mb, v); \
  tprintf("0x%x " #vop " 0x%x = 0x%x\n", ma, mb, v); \
  set_sz (v, DSZ()); \
  set_sz (v, DSZ()); \
  PD(v); \
  PD(v); \
}
}
 
 
#define SHIFT_OP(val, type, count, OP, carry_mask)      \
#define SHIFT_OP(val, type, count, OP, carry_mask)      \
{ \
{ \
  int i, c=0; \
  int i, c=0; \
  val = (type)US1();                            \
  val = (type)US1();                            \
  count = US2(); \
  count = US2(); \
  tprintf("%lld " #OP " %d\n", val, count); \
  tprintf("%lld " #OP " %d\n", val, count); \
  for (i = 0; i < count; i ++) \
  for (i = 0; i < count; i ++) \
    { \
    { \
      c = val & carry_mask; \
      c = val & carry_mask; \
      val OP 1; \
      val OP 1; \
    } \
    } \
  if (count) \
  if (count) \
    set_oszc (val, 4, c); \
    set_oszc (val, 4, c); \
  PD (val); \
  PD (val); \
}
}
 
 
typedef union {
typedef union {
  int i;
  int i;
  float f;
  float f;
} FloatInt;
} FloatInt;
 
 
static inline int
static inline int
float2int (float f)
float2int (float f)
{
{
  FloatInt fi;
  FloatInt fi;
  fi.f = f;
  fi.f = f;
  return fi.i;
  return fi.i;
}
}
 
 
static inline float
static inline float
int2float (int i)
int2float (int i)
{
{
  FloatInt fi;
  FloatInt fi;
  fi.i = i;
  fi.i = i;
  return fi.f;
  return fi.f;
}
}
 
 
static int
static int
fop_fadd (fp_t s1, fp_t s2, fp_t *d)
fop_fadd (fp_t s1, fp_t s2, fp_t *d)
{
{
  *d = rxfp_add (s1, s2);
  *d = rxfp_add (s1, s2);
  return 1;
  return 1;
}
}
 
 
static int
static int
fop_fmul (fp_t s1, fp_t s2, fp_t *d)
fop_fmul (fp_t s1, fp_t s2, fp_t *d)
{
{
  *d = rxfp_mul (s1, s2);
  *d = rxfp_mul (s1, s2);
  return 1;
  return 1;
}
}
 
 
static int
static int
fop_fdiv (fp_t s1, fp_t s2, fp_t *d)
fop_fdiv (fp_t s1, fp_t s2, fp_t *d)
{
{
  *d = rxfp_div (s1, s2);
  *d = rxfp_div (s1, s2);
  return 1;
  return 1;
}
}
 
 
static int
static int
fop_fsub (fp_t s1, fp_t s2, fp_t *d)
fop_fsub (fp_t s1, fp_t s2, fp_t *d)
{
{
  *d = rxfp_sub (s1, s2);
  *d = rxfp_sub (s1, s2);
  return 1;
  return 1;
}
}
 
 
#define FPPENDING() (regs.r_fpsw & (FPSWBITS_CE | (FPSWBITS_FMASK & (regs.r_fpsw << FPSW_EFSH))))
#define FPPENDING() (regs.r_fpsw & (FPSWBITS_CE | (FPSWBITS_FMASK & (regs.r_fpsw << FPSW_EFSH))))
#define FPCLEAR() regs.r_fpsw &= FPSWBITS_CLEAR
#define FPCLEAR() regs.r_fpsw &= FPSWBITS_CLEAR
#define FPCHECK() \
#define FPCHECK() \
  if (FPPENDING()) \
  if (FPPENDING()) \
    return do_fp_exception (opcode_pc)
    return do_fp_exception (opcode_pc)
 
 
#define FLOAT_OP(func) \
#define FLOAT_OP(func) \
{ \
{ \
  int do_store;   \
  int do_store;   \
  fp_t fa, fb, fc; \
  fp_t fa, fb, fc; \
  FPCLEAR(); \
  FPCLEAR(); \
  fa = GD (); \
  fa = GD (); \
  fb = GS (); \
  fb = GS (); \
  do_store = fop_##func (fa, fb, &fc); \
  do_store = fop_##func (fa, fb, &fc); \
  tprintf("%g " #func " %g = %g %08x\n", int2float(fa), int2float(fb), int2float(fc), fc); \
  tprintf("%g " #func " %g = %g %08x\n", int2float(fa), int2float(fb), int2float(fc), fc); \
  FPCHECK(); \
  FPCHECK(); \
  if (do_store) \
  if (do_store) \
    PD (fc);    \
    PD (fc);    \
  mb = 0; \
  mb = 0; \
  if ((fc & 0x80000000UL) != 0) \
  if ((fc & 0x80000000UL) != 0) \
    mb |= FLAGBIT_S; \
    mb |= FLAGBIT_S; \
  if ((fc & 0x7fffffffUL) == 0)                  \
  if ((fc & 0x7fffffffUL) == 0)                  \
    mb |= FLAGBIT_Z; \
    mb |= FLAGBIT_Z; \
  set_flags (FLAGBIT_S | FLAGBIT_Z, mb); \
  set_flags (FLAGBIT_S | FLAGBIT_Z, mb); \
}
}
 
 
#define carry (FLAG_C ? 1 : 0)
#define carry (FLAG_C ? 1 : 0)
 
 
static struct {
static struct {
  unsigned long vaddr;
  unsigned long vaddr;
  const char *str;
  const char *str;
  int signal;
  int signal;
} exception_info[] = {
} exception_info[] = {
  { 0xFFFFFFD0UL, "priviledged opcode", SIGILL },
  { 0xFFFFFFD0UL, "priviledged opcode", SIGILL },
  { 0xFFFFFFD4UL, "access violation", SIGSEGV },
  { 0xFFFFFFD4UL, "access violation", SIGSEGV },
  { 0xFFFFFFDCUL, "undefined opcode", SIGILL },
  { 0xFFFFFFDCUL, "undefined opcode", SIGILL },
  { 0xFFFFFFE4UL, "floating point", SIGFPE }
  { 0xFFFFFFE4UL, "floating point", SIGFPE }
};
};
#define EX_PRIVILEDGED  0
#define EX_PRIVILEDGED  0
#define EX_ACCESS       1
#define EX_ACCESS       1
#define EX_UNDEFINED    2
#define EX_UNDEFINED    2
#define EX_FLOATING     3
#define EX_FLOATING     3
#define EXCEPTION(n)  \
#define EXCEPTION(n)  \
  return generate_exception (n, opcode_pc)
  return generate_exception (n, opcode_pc)
 
 
#define PRIVILEDGED() \
#define PRIVILEDGED() \
  if (FLAG_PM) \
  if (FLAG_PM) \
    EXCEPTION (EX_PRIVILEDGED)
    EXCEPTION (EX_PRIVILEDGED)
 
 
static int
static int
generate_exception (unsigned long type, SI opcode_pc)
generate_exception (unsigned long type, SI opcode_pc)
{
{
  SI old_psw, old_pc, new_pc;
  SI old_psw, old_pc, new_pc;
 
 
  new_pc = mem_get_si (exception_info[type].vaddr);
  new_pc = mem_get_si (exception_info[type].vaddr);
  /* 0x00020000 is the value used to initialise the known
  /* 0x00020000 is the value used to initialise the known
     exception vectors (see rx.ld), but it is a reserved
     exception vectors (see rx.ld), but it is a reserved
     area of memory so do not try to access it, and if the
     area of memory so do not try to access it, and if the
     value has not been changed by the program then the
     value has not been changed by the program then the
     vector has not been installed.  */
     vector has not been installed.  */
  if (new_pc == 0 || new_pc == 0x00020000)
  if (new_pc == 0 || new_pc == 0x00020000)
    {
    {
      if (rx_in_gdb)
      if (rx_in_gdb)
        return RX_MAKE_STOPPED (exception_info[type].signal);
        return RX_MAKE_STOPPED (exception_info[type].signal);
 
 
      fprintf(stderr, "Unhandled %s exception at pc = %#lx\n",
      fprintf(stderr, "Unhandled %s exception at pc = %#lx\n",
              exception_info[type].str, (unsigned long) opcode_pc);
              exception_info[type].str, (unsigned long) opcode_pc);
      if (type == EX_FLOATING)
      if (type == EX_FLOATING)
        {
        {
          int mask = FPPENDING ();
          int mask = FPPENDING ();
          fprintf (stderr, "Pending FP exceptions:");
          fprintf (stderr, "Pending FP exceptions:");
          if (mask & FPSWBITS_FV)
          if (mask & FPSWBITS_FV)
            fprintf(stderr, " Invalid");
            fprintf(stderr, " Invalid");
          if (mask & FPSWBITS_FO)
          if (mask & FPSWBITS_FO)
            fprintf(stderr, " Overflow");
            fprintf(stderr, " Overflow");
          if (mask & FPSWBITS_FZ)
          if (mask & FPSWBITS_FZ)
            fprintf(stderr, " Division-by-zero");
            fprintf(stderr, " Division-by-zero");
          if (mask & FPSWBITS_FU)
          if (mask & FPSWBITS_FU)
            fprintf(stderr, " Underflow");
            fprintf(stderr, " Underflow");
          if (mask & FPSWBITS_FX)
          if (mask & FPSWBITS_FX)
            fprintf(stderr, " Inexact");
            fprintf(stderr, " Inexact");
          if (mask & FPSWBITS_CE)
          if (mask & FPSWBITS_CE)
            fprintf(stderr, " Unimplemented");
            fprintf(stderr, " Unimplemented");
          fprintf(stderr, "\n");
          fprintf(stderr, "\n");
        }
        }
      return RX_MAKE_EXITED (1);
      return RX_MAKE_EXITED (1);
    }
    }
 
 
  tprintf ("Triggering %s exception\n", exception_info[type].str);
  tprintf ("Triggering %s exception\n", exception_info[type].str);
 
 
  old_psw = regs.r_psw;
  old_psw = regs.r_psw;
  regs.r_psw &= ~ (FLAGBIT_I | FLAGBIT_U | FLAGBIT_PM);
  regs.r_psw &= ~ (FLAGBIT_I | FLAGBIT_U | FLAGBIT_PM);
  old_pc = opcode_pc;
  old_pc = opcode_pc;
  regs.r_pc = new_pc;
  regs.r_pc = new_pc;
  pushpc (old_psw);
  pushpc (old_psw);
  pushpc (old_pc);
  pushpc (old_pc);
  return RX_MAKE_STEPPED ();
  return RX_MAKE_STEPPED ();
}
}
 
 
void
void
generate_access_exception (void)
generate_access_exception (void)
{
{
  int rv;
  int rv;
 
 
  rv = generate_exception (EX_ACCESS, regs.r_pc);
  rv = generate_exception (EX_ACCESS, regs.r_pc);
  if (RX_EXITED (rv))
  if (RX_EXITED (rv))
    longjmp (decode_jmp_buf, rv);
    longjmp (decode_jmp_buf, rv);
}
}
 
 
static int
static int
do_fp_exception (unsigned long opcode_pc)
do_fp_exception (unsigned long opcode_pc)
{
{
  while (FPPENDING())
  while (FPPENDING())
    EXCEPTION (EX_FLOATING);
    EXCEPTION (EX_FLOATING);
  return RX_MAKE_STEPPED ();
  return RX_MAKE_STEPPED ();
}
}
 
 
int
int
decode_opcode ()
decode_opcode ()
{
{
  unsigned int uma=0, umb=0;
  unsigned int uma=0, umb=0;
  int ma=0, mb=0;
  int ma=0, mb=0;
  int opcode_size, v;
  int opcode_size, v;
  unsigned long long ll;
  unsigned long long ll;
  long long sll;
  long long sll;
  unsigned long opcode_pc;
  unsigned long opcode_pc;
  RX_Data rx_data;
  RX_Data rx_data;
  RX_Opcode_Decoded opcode;
  RX_Opcode_Decoded opcode;
  int rv;
  int rv;
 
 
  if ((rv = setjmp (decode_jmp_buf)))
  if ((rv = setjmp (decode_jmp_buf)))
    return rv;
    return rv;
 
 
  rx_cycles ++;
  rx_cycles ++;
 
 
  rx_data.dpc = opcode_pc = regs.r_pc;
  rx_data.dpc = opcode_pc = regs.r_pc;
  opcode_size = rx_decode_opcode (opcode_pc, &opcode, rx_get_byte, &rx_data);
  opcode_size = rx_decode_opcode (opcode_pc, &opcode, rx_get_byte, &rx_data);
  regs.r_pc += opcode_size;
  regs.r_pc += opcode_size;
 
 
  rx_flagmask = opcode.flags_s;
  rx_flagmask = opcode.flags_s;
  rx_flagand = ~(int)opcode.flags_0;
  rx_flagand = ~(int)opcode.flags_0;
  rx_flagor = opcode.flags_1;
  rx_flagor = opcode.flags_1;
 
 
  switch (opcode.id)
  switch (opcode.id)
    {
    {
    case RXO_abs:
    case RXO_abs:
      sll = GS ();
      sll = GS ();
      tprintf("|%lld| = ", sll);
      tprintf("|%lld| = ", sll);
      if (sll < 0)
      if (sll < 0)
        sll = -sll;
        sll = -sll;
      tprintf("%lld\n", sll);
      tprintf("%lld\n", sll);
      PD (sll);
      PD (sll);
      set_osz (sll, 4);
      set_osz (sll, 4);
      break;
      break;
 
 
    case RXO_adc:
    case RXO_adc:
      MATH_OP (+,carry);
      MATH_OP (+,carry);
      break;
      break;
 
 
    case RXO_add:
    case RXO_add:
      MATH_OP (+,0);
      MATH_OP (+,0);
      break;
      break;
 
 
    case RXO_and:
    case RXO_and:
      LOGIC_OP (&);
      LOGIC_OP (&);
      break;
      break;
 
 
    case RXO_bclr:
    case RXO_bclr:
      ma = GD ();
      ma = GD ();
      mb = GS ();
      mb = GS ();
      if (opcode.op[0].type == RX_Operand_Register)
      if (opcode.op[0].type == RX_Operand_Register)
        mb &= 0x1f;
        mb &= 0x1f;
      else
      else
        mb &= 0x07;
        mb &= 0x07;
      ma &= ~(1 << mb);
      ma &= ~(1 << mb);
      PD (ma);
      PD (ma);
      break;
      break;
 
 
    case RXO_bmcc:
    case RXO_bmcc:
      ma = GD ();
      ma = GD ();
      mb = GS ();
      mb = GS ();
      if (opcode.op[0].type == RX_Operand_Register)
      if (opcode.op[0].type == RX_Operand_Register)
        mb &= 0x1f;
        mb &= 0x1f;
      else
      else
        mb &= 0x07;
        mb &= 0x07;
      if (GS2 ())
      if (GS2 ())
        ma |= (1 << mb);
        ma |= (1 << mb);
      else
      else
        ma &= ~(1 << mb);
        ma &= ~(1 << mb);
      PD (ma);
      PD (ma);
      break;
      break;
 
 
    case RXO_bnot:
    case RXO_bnot:
      ma = GD ();
      ma = GD ();
      mb = GS ();
      mb = GS ();
      if (opcode.op[0].type == RX_Operand_Register)
      if (opcode.op[0].type == RX_Operand_Register)
        mb &= 0x1f;
        mb &= 0x1f;
      else
      else
        mb &= 0x07;
        mb &= 0x07;
      ma ^= (1 << mb);
      ma ^= (1 << mb);
      PD (ma);
      PD (ma);
      break;
      break;
 
 
    case RXO_branch:
    case RXO_branch:
      if (GS())
      if (GS())
        regs.r_pc = GD();
        regs.r_pc = GD();
      break;
      break;
 
 
    case RXO_branchrel:
    case RXO_branchrel:
      if (GS())
      if (GS())
        regs.r_pc += GD();
        regs.r_pc += GD();
      break;
      break;
 
 
    case RXO_brk:
    case RXO_brk:
      {
      {
        int old_psw = regs.r_psw;
        int old_psw = regs.r_psw;
        if (rx_in_gdb)
        if (rx_in_gdb)
          return RX_MAKE_HIT_BREAK ();
          return RX_MAKE_HIT_BREAK ();
        if (regs.r_intb == 0)
        if (regs.r_intb == 0)
          {
          {
            tprintf("BREAK hit, no vector table.\n");
            tprintf("BREAK hit, no vector table.\n");
            return RX_MAKE_EXITED(1);
            return RX_MAKE_EXITED(1);
          }
          }
        regs.r_psw &= ~(FLAGBIT_I | FLAGBIT_U | FLAGBIT_PM);
        regs.r_psw &= ~(FLAGBIT_I | FLAGBIT_U | FLAGBIT_PM);
        pushpc (old_psw);
        pushpc (old_psw);
        pushpc (regs.r_pc);
        pushpc (regs.r_pc);
        regs.r_pc = mem_get_si (regs.r_intb);
        regs.r_pc = mem_get_si (regs.r_intb);
      }
      }
      break;
      break;
 
 
    case RXO_bset:
    case RXO_bset:
      ma = GD ();
      ma = GD ();
      mb = GS ();
      mb = GS ();
      if (opcode.op[0].type == RX_Operand_Register)
      if (opcode.op[0].type == RX_Operand_Register)
        mb &= 0x1f;
        mb &= 0x1f;
      else
      else
        mb &= 0x07;
        mb &= 0x07;
      ma |= (1 << mb);
      ma |= (1 << mb);
      PD (ma);
      PD (ma);
      break;
      break;
 
 
    case RXO_btst:
    case RXO_btst:
      ma = GS ();
      ma = GS ();
      mb = GS2 ();
      mb = GS2 ();
      if (opcode.op[1].type == RX_Operand_Register)
      if (opcode.op[1].type == RX_Operand_Register)
        mb &= 0x1f;
        mb &= 0x1f;
      else
      else
        mb &= 0x07;
        mb &= 0x07;
      umb = ma & (1 << mb);
      umb = ma & (1 << mb);
      set_zc (! umb, umb);
      set_zc (! umb, umb);
      break;
      break;
 
 
    case RXO_clrpsw:
    case RXO_clrpsw:
      v = 1 << opcode.op[0].reg;
      v = 1 << opcode.op[0].reg;
      if (FLAG_PM
      if (FLAG_PM
          && (v == FLAGBIT_I
          && (v == FLAGBIT_I
              || v == FLAGBIT_U))
              || v == FLAGBIT_U))
        break;
        break;
      regs.r_psw &= ~v;
      regs.r_psw &= ~v;
      break;
      break;
 
 
    case RXO_div: /* d = d / s */
    case RXO_div: /* d = d / s */
      ma = GS();
      ma = GS();
      mb = GD();
      mb = GD();
      tprintf("%d / %d = ", mb, ma);
      tprintf("%d / %d = ", mb, ma);
      if (ma == 0 || (ma == -1 && (unsigned int) mb == 0x80000000))
      if (ma == 0 || (ma == -1 && (unsigned int) mb == 0x80000000))
        {
        {
          tprintf("#NAN\n");
          tprintf("#NAN\n");
          set_flags (FLAGBIT_O, FLAGBIT_O);
          set_flags (FLAGBIT_O, FLAGBIT_O);
        }
        }
      else
      else
        {
        {
          v = mb/ma;
          v = mb/ma;
          tprintf("%d\n", v);
          tprintf("%d\n", v);
          set_flags (FLAGBIT_O, 0);
          set_flags (FLAGBIT_O, 0);
          PD (v);
          PD (v);
        }
        }
      break;
      break;
 
 
    case RXO_divu: /* d = d / s */
    case RXO_divu: /* d = d / s */
      uma = GS();
      uma = GS();
      umb = GD();
      umb = GD();
      tprintf("%u / %u = ", umb, uma);
      tprintf("%u / %u = ", umb, uma);
      if (uma == 0)
      if (uma == 0)
        {
        {
          tprintf("#NAN\n");
          tprintf("#NAN\n");
          set_flags (FLAGBIT_O, FLAGBIT_O);
          set_flags (FLAGBIT_O, FLAGBIT_O);
        }
        }
      else
      else
        {
        {
          v = umb / uma;
          v = umb / uma;
          tprintf("%u\n", v);
          tprintf("%u\n", v);
          set_flags (FLAGBIT_O, 0);
          set_flags (FLAGBIT_O, 0);
          PD (v);
          PD (v);
        }
        }
      break;
      break;
 
 
    case RXO_ediv:
    case RXO_ediv:
      ma = GS();
      ma = GS();
      mb = GD();
      mb = GD();
      tprintf("%d / %d = ", mb, ma);
      tprintf("%d / %d = ", mb, ma);
      if (ma == 0 || (ma == -1 && (unsigned int) mb == 0x80000000))
      if (ma == 0 || (ma == -1 && (unsigned int) mb == 0x80000000))
        {
        {
          tprintf("#NAN\n");
          tprintf("#NAN\n");
          set_flags (FLAGBIT_O, FLAGBIT_O);
          set_flags (FLAGBIT_O, FLAGBIT_O);
        }
        }
      else
      else
        {
        {
          v = mb/ma;
          v = mb/ma;
          mb = mb%ma;
          mb = mb%ma;
          tprintf("%d, rem %d\n", v, mb);
          tprintf("%d, rem %d\n", v, mb);
          set_flags (FLAGBIT_O, 0);
          set_flags (FLAGBIT_O, 0);
          PD (v);
          PD (v);
          opcode.op[0].reg ++;
          opcode.op[0].reg ++;
          PD (mb);
          PD (mb);
        }
        }
      break;
      break;
 
 
    case RXO_edivu:
    case RXO_edivu:
      uma = GS();
      uma = GS();
      umb = GD();
      umb = GD();
      tprintf("%u / %u = ", umb, uma);
      tprintf("%u / %u = ", umb, uma);
      if (uma == 0)
      if (uma == 0)
        {
        {
          tprintf("#NAN\n");
          tprintf("#NAN\n");
          set_flags (FLAGBIT_O, FLAGBIT_O);
          set_flags (FLAGBIT_O, FLAGBIT_O);
        }
        }
      else
      else
        {
        {
          v = umb/uma;
          v = umb/uma;
          umb = umb%uma;
          umb = umb%uma;
          tprintf("%u, rem %u\n", v, umb);
          tprintf("%u, rem %u\n", v, umb);
          set_flags (FLAGBIT_O, 0);
          set_flags (FLAGBIT_O, 0);
          PD (v);
          PD (v);
          opcode.op[0].reg ++;
          opcode.op[0].reg ++;
          PD (umb);
          PD (umb);
        }
        }
      break;
      break;
 
 
    case RXO_emul:
    case RXO_emul:
      ma = GD ();
      ma = GD ();
      mb = GS ();
      mb = GS ();
      sll = (long long)ma * (long long)mb;
      sll = (long long)ma * (long long)mb;
      tprintf("%d * %d = %lld\n", ma, mb, sll);
      tprintf("%d * %d = %lld\n", ma, mb, sll);
      PD (sll);
      PD (sll);
      opcode.op[0].reg ++;
      opcode.op[0].reg ++;
      PD (sll >> 32);
      PD (sll >> 32);
      break;
      break;
 
 
    case RXO_emulu:
    case RXO_emulu:
      uma = GD ();
      uma = GD ();
      umb = GS ();
      umb = GS ();
      ll = (long long)uma * (long long)umb;
      ll = (long long)uma * (long long)umb;
      tprintf("%#x * %#x = %#llx\n", uma, umb, ll);
      tprintf("%#x * %#x = %#llx\n", uma, umb, ll);
      PD (ll);
      PD (ll);
      opcode.op[0].reg ++;
      opcode.op[0].reg ++;
      PD (ll >> 32);
      PD (ll >> 32);
      break;
      break;
 
 
    case RXO_fadd:
    case RXO_fadd:
      FLOAT_OP (fadd);
      FLOAT_OP (fadd);
      break;
      break;
 
 
    case RXO_fcmp:
    case RXO_fcmp:
      ma = GD();
      ma = GD();
      mb = GS();
      mb = GS();
      FPCLEAR ();
      FPCLEAR ();
      rxfp_cmp (ma, mb);
      rxfp_cmp (ma, mb);
      FPCHECK ();
      FPCHECK ();
      break;
      break;
 
 
    case RXO_fdiv:
    case RXO_fdiv:
      FLOAT_OP (fdiv);
      FLOAT_OP (fdiv);
      break;
      break;
 
 
    case RXO_fmul:
    case RXO_fmul:
      FLOAT_OP (fmul);
      FLOAT_OP (fmul);
      break;
      break;
 
 
    case RXO_rtfi:
    case RXO_rtfi:
      PRIVILEDGED ();
      PRIVILEDGED ();
      regs.r_psw = regs.r_bpsw;
      regs.r_psw = regs.r_bpsw;
      regs.r_pc = regs.r_bpc;
      regs.r_pc = regs.r_bpc;
      break;
      break;
 
 
    case RXO_fsub:
    case RXO_fsub:
      FLOAT_OP (fsub);
      FLOAT_OP (fsub);
      break;
      break;
 
 
    case RXO_ftoi:
    case RXO_ftoi:
      ma = GS ();
      ma = GS ();
      FPCLEAR ();
      FPCLEAR ();
      mb = rxfp_ftoi (ma, FPRM_ZERO);
      mb = rxfp_ftoi (ma, FPRM_ZERO);
      FPCHECK ();
      FPCHECK ();
      PD (mb);
      PD (mb);
      tprintf("(int) %g = %d\n", int2float(ma), mb);
      tprintf("(int) %g = %d\n", int2float(ma), mb);
      set_sz (mb, 4);
      set_sz (mb, 4);
      break;
      break;
 
 
    case RXO_int:
    case RXO_int:
      v = GS ();
      v = GS ();
      if (v == 255)
      if (v == 255)
        {
        {
          return rx_syscall (regs.r[5]);
          return rx_syscall (regs.r[5]);
        }
        }
      else
      else
        {
        {
          int old_psw = regs.r_psw;
          int old_psw = regs.r_psw;
          regs.r_psw &= ~(FLAGBIT_I | FLAGBIT_U | FLAGBIT_PM);
          regs.r_psw &= ~(FLAGBIT_I | FLAGBIT_U | FLAGBIT_PM);
          pushpc (old_psw);
          pushpc (old_psw);
          pushpc (regs.r_pc);
          pushpc (regs.r_pc);
          regs.r_pc = mem_get_si (regs.r_intb + 4 * v);
          regs.r_pc = mem_get_si (regs.r_intb + 4 * v);
        }
        }
      break;
      break;
 
 
    case RXO_itof:
    case RXO_itof:
      ma = GS ();
      ma = GS ();
      FPCLEAR ();
      FPCLEAR ();
      mb = rxfp_itof (ma, regs.r_fpsw);
      mb = rxfp_itof (ma, regs.r_fpsw);
      FPCHECK ();
      FPCHECK ();
      tprintf("(float) %d = %x\n", ma, mb);
      tprintf("(float) %d = %x\n", ma, mb);
      PD (mb);
      PD (mb);
      set_sz (ma, 4);
      set_sz (ma, 4);
      break;
      break;
 
 
    case RXO_jsr:
    case RXO_jsr:
    case RXO_jsrrel:
    case RXO_jsrrel:
      v = GD ();
      v = GD ();
      pushpc (get_reg (pc));
      pushpc (get_reg (pc));
      if (opcode.id == RXO_jsrrel)
      if (opcode.id == RXO_jsrrel)
        v += regs.r_pc;
        v += regs.r_pc;
      put_reg (pc, v);
      put_reg (pc, v);
      break;
      break;
 
 
    case RXO_machi:
    case RXO_machi:
      ll = (long long)(signed short)(GS() >> 16) * (long long)(signed short)(GS2 () >> 16);
      ll = (long long)(signed short)(GS() >> 16) * (long long)(signed short)(GS2 () >> 16);
      ll <<= 16;
      ll <<= 16;
      put_reg64 (acc64, ll + regs.r_acc);
      put_reg64 (acc64, ll + regs.r_acc);
      break;
      break;
 
 
    case RXO_maclo:
    case RXO_maclo:
      ll = (long long)(signed short)(GS()) * (long long)(signed short)(GS2 ());
      ll = (long long)(signed short)(GS()) * (long long)(signed short)(GS2 ());
      ll <<= 16;
      ll <<= 16;
      put_reg64 (acc64, ll + regs.r_acc);
      put_reg64 (acc64, ll + regs.r_acc);
      break;
      break;
 
 
    case RXO_max:
    case RXO_max:
      ma = GD();
      ma = GD();
      mb = GS();
      mb = GS();
      if (ma > mb)
      if (ma > mb)
        PD (ma);
        PD (ma);
      else
      else
        PD (mb);
        PD (mb);
      break;
      break;
 
 
    case RXO_min:
    case RXO_min:
      ma = GD();
      ma = GD();
      mb = GS();
      mb = GS();
      if (ma < mb)
      if (ma < mb)
        PD (ma);
        PD (ma);
      else
      else
        PD (mb);
        PD (mb);
      break;
      break;
 
 
    case RXO_mov:
    case RXO_mov:
      v = GS ();
      v = GS ();
      if (opcode.op[0].type == RX_Operand_Register
      if (opcode.op[0].type == RX_Operand_Register
          && opcode.op[0].reg == 16 /* PSW */)
          && opcode.op[0].reg == 16 /* PSW */)
        {
        {
          /* Special case, LDC and POPC can't ever modify PM.  */
          /* Special case, LDC and POPC can't ever modify PM.  */
          int pm = regs.r_psw & FLAGBIT_PM;
          int pm = regs.r_psw & FLAGBIT_PM;
          v &= ~ FLAGBIT_PM;
          v &= ~ FLAGBIT_PM;
          v |= pm;
          v |= pm;
          if (pm)
          if (pm)
            {
            {
              v &= ~ (FLAGBIT_I | FLAGBIT_U | FLAGBITS_IPL);
              v &= ~ (FLAGBIT_I | FLAGBIT_U | FLAGBITS_IPL);
              v |= pm;
              v |= pm;
            }
            }
        }
        }
      if (FLAG_PM)
      if (FLAG_PM)
        {
        {
          /* various things can't be changed in user mode.  */
          /* various things can't be changed in user mode.  */
          if (opcode.op[0].type == RX_Operand_Register)
          if (opcode.op[0].type == RX_Operand_Register)
            if (opcode.op[0].reg == 32)
            if (opcode.op[0].reg == 32)
              {
              {
                v &= ~ (FLAGBIT_I | FLAGBIT_U | FLAGBITS_IPL);
                v &= ~ (FLAGBIT_I | FLAGBIT_U | FLAGBITS_IPL);
                v |= regs.r_psw & (FLAGBIT_I | FLAGBIT_U | FLAGBITS_IPL);
                v |= regs.r_psw & (FLAGBIT_I | FLAGBIT_U | FLAGBITS_IPL);
              }
              }
          if (opcode.op[0].reg == 34 /* ISP */
          if (opcode.op[0].reg == 34 /* ISP */
              || opcode.op[0].reg == 37 /* BPSW */
              || opcode.op[0].reg == 37 /* BPSW */
              || opcode.op[0].reg == 39 /* INTB */
              || opcode.op[0].reg == 39 /* INTB */
              || opcode.op[0].reg == 38 /* VCT */)
              || opcode.op[0].reg == 38 /* VCT */)
            /* These are ignored.  */
            /* These are ignored.  */
            break;
            break;
        }
        }
      PD (v);
      PD (v);
      set_sz (v, DSZ());
      set_sz (v, DSZ());
      break;
      break;
 
 
    case RXO_movbi:
    case RXO_movbi:
      /* We cheat to save on code duplication. */
      /* We cheat to save on code duplication. */
      regs.r_temp = (get_reg (opcode.op[1].reg) * size2bytes[opcode.size]
      regs.r_temp = (get_reg (opcode.op[1].reg) * size2bytes[opcode.size]
                     + get_reg (opcode.op[2].reg));
                     + get_reg (opcode.op[2].reg));
      opcode.op[1].reg = r_temp_idx;
      opcode.op[1].reg = r_temp_idx;
      opcode.op[1].type = RX_Operand_Indirect;
      opcode.op[1].type = RX_Operand_Indirect;
      opcode.op[1].addend = 0;
      opcode.op[1].addend = 0;
      PD (GS ());
      PD (GS ());
      break;
      break;
 
 
    case RXO_movbir:
    case RXO_movbir:
      /* We cheat to save on code duplication. */
      /* We cheat to save on code duplication. */
      regs.r_temp = (get_reg (opcode.op[1].reg) * size2bytes[opcode.size]
      regs.r_temp = (get_reg (opcode.op[1].reg) * size2bytes[opcode.size]
                     + get_reg (opcode.op[2].reg));
                     + get_reg (opcode.op[2].reg));
      opcode.op[1].reg = r_temp_idx;
      opcode.op[1].reg = r_temp_idx;
      opcode.op[1].type = RX_Operand_Indirect;
      opcode.op[1].type = RX_Operand_Indirect;
      opcode.op[1].addend = 0;
      opcode.op[1].addend = 0;
      PS (GD ());
      PS (GD ());
      break;
      break;
 
 
    case RXO_mul:
    case RXO_mul:
      ll = (unsigned long long) US1() * (unsigned long long) US2();
      ll = (unsigned long long) US1() * (unsigned long long) US2();
      PD(ll);
      PD(ll);
      break;
      break;
 
 
    case RXO_mulhi:
    case RXO_mulhi:
      ll = (long long)(signed short)(GS() >> 16) * (long long)(signed short)(GS2 () >> 16);
      ll = (long long)(signed short)(GS() >> 16) * (long long)(signed short)(GS2 () >> 16);
      ll <<= 16;
      ll <<= 16;
      put_reg64 (acc64, ll);
      put_reg64 (acc64, ll);
      break;
      break;
 
 
    case RXO_mullo:
    case RXO_mullo:
      ll = (long long)(signed short)(GS()) * (long long)(signed short)(GS2 ());
      ll = (long long)(signed short)(GS()) * (long long)(signed short)(GS2 ());
      ll <<= 16;
      ll <<= 16;
      put_reg64 (acc64, ll);
      put_reg64 (acc64, ll);
      break;
      break;
 
 
    case RXO_mvfachi:
    case RXO_mvfachi:
      PD (get_reg (acchi));
      PD (get_reg (acchi));
      break;
      break;
 
 
    case RXO_mvfaclo:
    case RXO_mvfaclo:
      PD (get_reg (acclo));
      PD (get_reg (acclo));
      break;
      break;
 
 
    case RXO_mvfacmi:
    case RXO_mvfacmi:
      PD (get_reg (accmi));
      PD (get_reg (accmi));
      break;
      break;
 
 
    case RXO_mvtachi:
    case RXO_mvtachi:
      put_reg (acchi, GS ());
      put_reg (acchi, GS ());
      break;
      break;
 
 
    case RXO_mvtaclo:
    case RXO_mvtaclo:
      put_reg (acclo, GS ());
      put_reg (acclo, GS ());
      break;
      break;
 
 
    case RXO_mvtipl:
    case RXO_mvtipl:
      regs.r_psw &= ~ FLAGBITS_IPL;
      regs.r_psw &= ~ FLAGBITS_IPL;
      regs.r_psw |= (GS () << FLAGSHIFT_IPL) & FLAGBITS_IPL;
      regs.r_psw |= (GS () << FLAGSHIFT_IPL) & FLAGBITS_IPL;
      break;
      break;
 
 
    case RXO_nop:
    case RXO_nop:
      break;
      break;
 
 
    case RXO_or:
    case RXO_or:
      LOGIC_OP (|);
      LOGIC_OP (|);
      break;
      break;
 
 
    case RXO_popm:
    case RXO_popm:
      /* POPM cannot pop R0 (sp).  */
      /* POPM cannot pop R0 (sp).  */
      if (opcode.op[1].reg == 0 || opcode.op[2].reg == 0)
      if (opcode.op[1].reg == 0 || opcode.op[2].reg == 0)
        EXCEPTION (EX_UNDEFINED);
        EXCEPTION (EX_UNDEFINED);
      if (opcode.op[1].reg >= opcode.op[2].reg)
      if (opcode.op[1].reg >= opcode.op[2].reg)
        {
        {
          regs.r_pc = opcode_pc;
          regs.r_pc = opcode_pc;
          return RX_MAKE_STOPPED (SIGILL);
          return RX_MAKE_STOPPED (SIGILL);
        }
        }
      for (v = opcode.op[1].reg; v <= opcode.op[2].reg; v++)
      for (v = opcode.op[1].reg; v <= opcode.op[2].reg; v++)
        put_reg (v, pop ());
        put_reg (v, pop ());
      break;
      break;
 
 
    case RXO_pusha:
    case RXO_pusha:
      push (get_reg (opcode.op[1].reg) + opcode.op[1].addend);
      push (get_reg (opcode.op[1].reg) + opcode.op[1].addend);
      break;
      break;
 
 
    case RXO_pushm:
    case RXO_pushm:
      /* PUSHM cannot push R0 (sp).  */
      /* PUSHM cannot push R0 (sp).  */
      if (opcode.op[1].reg == 0 || opcode.op[2].reg == 0)
      if (opcode.op[1].reg == 0 || opcode.op[2].reg == 0)
        EXCEPTION (EX_UNDEFINED);
        EXCEPTION (EX_UNDEFINED);
      if (opcode.op[1].reg >= opcode.op[2].reg)
      if (opcode.op[1].reg >= opcode.op[2].reg)
        {
        {
          regs.r_pc = opcode_pc;
          regs.r_pc = opcode_pc;
          return RX_MAKE_STOPPED (SIGILL);
          return RX_MAKE_STOPPED (SIGILL);
        }
        }
      for (v = opcode.op[2].reg; v >= opcode.op[1].reg; v--)
      for (v = opcode.op[2].reg; v >= opcode.op[1].reg; v--)
        push (get_reg (v));
        push (get_reg (v));
      break;
      break;
 
 
    case RXO_racw:
    case RXO_racw:
      ll = get_reg64 (acc64) << GS ();
      ll = get_reg64 (acc64) << GS ();
      ll += 0x80000000ULL;
      ll += 0x80000000ULL;
      if ((signed long long)ll > (signed long long)0x00007fff00000000ULL)
      if ((signed long long)ll > (signed long long)0x00007fff00000000ULL)
        ll = 0x00007fff00000000ULL;
        ll = 0x00007fff00000000ULL;
      else if ((signed long long)ll < (signed long long)0xffff800000000000ULL)
      else if ((signed long long)ll < (signed long long)0xffff800000000000ULL)
        ll = 0xffff800000000000ULL;
        ll = 0xffff800000000000ULL;
      else
      else
        ll &= 0xffffffff00000000ULL;
        ll &= 0xffffffff00000000ULL;
      put_reg64 (acc64, ll);
      put_reg64 (acc64, ll);
      break;
      break;
 
 
    case RXO_rte:
    case RXO_rte:
      PRIVILEDGED ();
      PRIVILEDGED ();
      regs.r_pc = poppc ();
      regs.r_pc = poppc ();
      regs.r_psw = poppc ();
      regs.r_psw = poppc ();
      if (FLAG_PM)
      if (FLAG_PM)
        regs.r_psw |= FLAGBIT_U;
        regs.r_psw |= FLAGBIT_U;
      break;
      break;
 
 
    case RXO_revl:
    case RXO_revl:
      uma = GS ();
      uma = GS ();
      umb = (((uma >> 24) & 0xff)
      umb = (((uma >> 24) & 0xff)
             | ((uma >> 8) & 0xff00)
             | ((uma >> 8) & 0xff00)
             | ((uma << 8) & 0xff0000)
             | ((uma << 8) & 0xff0000)
             | ((uma << 24) & 0xff000000UL));
             | ((uma << 24) & 0xff000000UL));
      PD (umb);
      PD (umb);
      break;
      break;
 
 
    case RXO_revw:
    case RXO_revw:
      uma = GS ();
      uma = GS ();
      umb = (((uma >> 8) & 0x00ff00ff)
      umb = (((uma >> 8) & 0x00ff00ff)
             | ((uma << 8) & 0xff00ff00UL));
             | ((uma << 8) & 0xff00ff00UL));
      PD (umb);
      PD (umb);
      break;
      break;
 
 
    case RXO_rmpa:
    case RXO_rmpa:
      while (regs.r[3] != 0)
      while (regs.r[3] != 0)
        {
        {
          long long tmp;
          long long tmp;
 
 
          switch (opcode.size)
          switch (opcode.size)
            {
            {
            case RX_Long:
            case RX_Long:
              ma = mem_get_si (regs.r[1]);
              ma = mem_get_si (regs.r[1]);
              mb = mem_get_si (regs.r[2]);
              mb = mem_get_si (regs.r[2]);
              regs.r[1] += 4;
              regs.r[1] += 4;
              regs.r[2] += 4;
              regs.r[2] += 4;
              break;
              break;
            case RX_Word:
            case RX_Word:
              ma = sign_ext (mem_get_hi (regs.r[1]), 16);
              ma = sign_ext (mem_get_hi (regs.r[1]), 16);
              mb = sign_ext (mem_get_hi (regs.r[2]), 16);
              mb = sign_ext (mem_get_hi (regs.r[2]), 16);
              regs.r[1] += 2;
              regs.r[1] += 2;
              regs.r[2] += 2;
              regs.r[2] += 2;
              break;
              break;
            case RX_Byte:
            case RX_Byte:
              ma = sign_ext (mem_get_qi (regs.r[1]), 8);
              ma = sign_ext (mem_get_qi (regs.r[1]), 8);
              mb = sign_ext (mem_get_qi (regs.r[2]), 8);
              mb = sign_ext (mem_get_qi (regs.r[2]), 8);
              regs.r[1] += 1;
              regs.r[1] += 1;
              regs.r[2] += 1;
              regs.r[2] += 1;
              break;
              break;
            default:
            default:
              abort ();
              abort ();
            }
            }
          /* We do the multiply as a signed value.  */
          /* We do the multiply as a signed value.  */
          sll = (long long)ma * (long long)mb;
          sll = (long long)ma * (long long)mb;
          tprintf("        %016llx = %d * %d\n", sll, ma, mb);
          tprintf("        %016llx = %d * %d\n", sll, ma, mb);
          /* but we do the sum as unsigned, while sign extending the operands.  */
          /* but we do the sum as unsigned, while sign extending the operands.  */
          tmp = regs.r[4] + (sll & 0xffffffffUL);
          tmp = regs.r[4] + (sll & 0xffffffffUL);
          regs.r[4] = tmp & 0xffffffffUL;
          regs.r[4] = tmp & 0xffffffffUL;
          tmp >>= 32;
          tmp >>= 32;
          sll >>= 32;
          sll >>= 32;
          tmp += regs.r[5] + (sll & 0xffffffffUL);
          tmp += regs.r[5] + (sll & 0xffffffffUL);
          regs.r[5] = tmp & 0xffffffffUL;
          regs.r[5] = tmp & 0xffffffffUL;
          tmp >>= 32;
          tmp >>= 32;
          sll >>= 32;
          sll >>= 32;
          tmp += regs.r[6] + (sll & 0xffffffffUL);
          tmp += regs.r[6] + (sll & 0xffffffffUL);
          regs.r[6] = tmp & 0xffffffffUL;
          regs.r[6] = tmp & 0xffffffffUL;
          tprintf("%08lx\033[36m%08lx\033[0m%08lx\n",
          tprintf("%08lx\033[36m%08lx\033[0m%08lx\n",
                  (unsigned long) regs.r[6],
                  (unsigned long) regs.r[6],
                  (unsigned long) regs.r[5],
                  (unsigned long) regs.r[5],
                  (unsigned long) regs.r[4]);
                  (unsigned long) regs.r[4]);
 
 
          regs.r[3] --;
          regs.r[3] --;
        }
        }
      if (regs.r[6] & 0x00008000)
      if (regs.r[6] & 0x00008000)
        regs.r[6] |= 0xffff0000UL;
        regs.r[6] |= 0xffff0000UL;
      else
      else
        regs.r[6] &= 0x0000ffff;
        regs.r[6] &= 0x0000ffff;
      ma = (regs.r[6] & 0x80000000UL) ? FLAGBIT_S : 0;
      ma = (regs.r[6] & 0x80000000UL) ? FLAGBIT_S : 0;
      if (regs.r[6] != 0 && regs.r[6] != 0xffffffffUL)
      if (regs.r[6] != 0 && regs.r[6] != 0xffffffffUL)
        set_flags (FLAGBIT_O|FLAGBIT_S, ma | FLAGBIT_O);
        set_flags (FLAGBIT_O|FLAGBIT_S, ma | FLAGBIT_O);
      else
      else
        set_flags (FLAGBIT_O|FLAGBIT_S, ma);
        set_flags (FLAGBIT_O|FLAGBIT_S, ma);
      break;
      break;
 
 
    case RXO_rolc:
    case RXO_rolc:
      v = GD ();
      v = GD ();
      ma = v & 0x80000000UL;
      ma = v & 0x80000000UL;
      v <<= 1;
      v <<= 1;
      v |= carry;
      v |= carry;
      set_szc (v, 4, ma);
      set_szc (v, 4, ma);
      PD (v);
      PD (v);
      break;
      break;
 
 
    case RXO_rorc:
    case RXO_rorc:
      uma = GD ();
      uma = GD ();
      mb = uma & 1;
      mb = uma & 1;
      uma >>= 1;
      uma >>= 1;
      uma |= (carry ? 0x80000000UL : 0);
      uma |= (carry ? 0x80000000UL : 0);
      set_szc (uma, 4, mb);
      set_szc (uma, 4, mb);
      PD (uma);
      PD (uma);
      break;
      break;
 
 
    case RXO_rotl:
    case RXO_rotl:
      mb = GS ();
      mb = GS ();
      uma = GD ();
      uma = GD ();
      if (mb)
      if (mb)
        {
        {
          uma = (uma << mb) | (uma >> (32-mb));
          uma = (uma << mb) | (uma >> (32-mb));
          mb = uma & 1;
          mb = uma & 1;
        }
        }
      set_szc (uma, 4, mb);
      set_szc (uma, 4, mb);
      PD (uma);
      PD (uma);
      break;
      break;
 
 
    case RXO_rotr:
    case RXO_rotr:
      mb = GS ();
      mb = GS ();
      uma = GD ();
      uma = GD ();
      if (mb)
      if (mb)
        {
        {
          uma = (uma >> mb) | (uma << (32-mb));
          uma = (uma >> mb) | (uma << (32-mb));
          mb = uma & 0x80000000;
          mb = uma & 0x80000000;
        }
        }
      set_szc (uma, 4, mb);
      set_szc (uma, 4, mb);
      PD (uma);
      PD (uma);
      break;
      break;
 
 
    case RXO_round:
    case RXO_round:
      ma = GS ();
      ma = GS ();
      FPCLEAR ();
      FPCLEAR ();
      mb = rxfp_ftoi (ma, regs.r_fpsw);
      mb = rxfp_ftoi (ma, regs.r_fpsw);
      FPCHECK ();
      FPCHECK ();
      PD (mb);
      PD (mb);
      tprintf("(int) %g = %d\n", int2float(ma), mb);
      tprintf("(int) %g = %d\n", int2float(ma), mb);
      set_sz (mb, 4);
      set_sz (mb, 4);
      break;
      break;
 
 
    case RXO_rts:
    case RXO_rts:
      regs.r_pc = poppc ();
      regs.r_pc = poppc ();
      break;
      break;
 
 
    case RXO_rtsd:
    case RXO_rtsd:
      if (opcode.op[2].type == RX_Operand_Register)
      if (opcode.op[2].type == RX_Operand_Register)
        {
        {
          int i;
          int i;
          /* RTSD cannot pop R0 (sp).  */
          /* RTSD cannot pop R0 (sp).  */
          put_reg (0, get_reg (0) + GS() - (opcode.op[0].reg-opcode.op[2].reg+1)*4);
          put_reg (0, get_reg (0) + GS() - (opcode.op[0].reg-opcode.op[2].reg+1)*4);
          if (opcode.op[2].reg == 0)
          if (opcode.op[2].reg == 0)
            EXCEPTION (EX_UNDEFINED);
            EXCEPTION (EX_UNDEFINED);
          for (i = opcode.op[2].reg; i <= opcode.op[0].reg; i ++)
          for (i = opcode.op[2].reg; i <= opcode.op[0].reg; i ++)
            put_reg (i, pop ());
            put_reg (i, pop ());
        }
        }
      else
      else
        put_reg (0, get_reg (0) + GS());
        put_reg (0, get_reg (0) + GS());
      put_reg (pc, poppc ());
      put_reg (pc, poppc ());
      break;
      break;
 
 
    case RXO_sat:
    case RXO_sat:
      if (FLAG_O && FLAG_S)
      if (FLAG_O && FLAG_S)
        PD (0x7fffffffUL);
        PD (0x7fffffffUL);
      else if (FLAG_O && ! FLAG_S)
      else if (FLAG_O && ! FLAG_S)
        PD (0x80000000UL);
        PD (0x80000000UL);
      break;
      break;
 
 
    case RXO_sbb:
    case RXO_sbb:
      MATH_OP (-, ! carry);
      MATH_OP (-, ! carry);
      break;
      break;
 
 
    case RXO_sccnd:
    case RXO_sccnd:
      if (GS())
      if (GS())
        PD (1);
        PD (1);
      else
      else
        PD (0);
        PD (0);
      break;
      break;
 
 
    case RXO_scmpu:
    case RXO_scmpu:
      while (regs.r[3] != 0)
      while (regs.r[3] != 0)
        {
        {
          uma = mem_get_qi (regs.r[1] ++);
          uma = mem_get_qi (regs.r[1] ++);
          umb = mem_get_qi (regs.r[2] ++);
          umb = mem_get_qi (regs.r[2] ++);
          regs.r[3] --;
          regs.r[3] --;
          if (uma != umb || uma == 0)
          if (uma != umb || uma == 0)
            break;
            break;
        }
        }
      if (uma == umb)
      if (uma == umb)
        set_zc (1, 1);
        set_zc (1, 1);
      else
      else
        set_zc (0, ((int)uma - (int)umb) >= 0);
        set_zc (0, ((int)uma - (int)umb) >= 0);
      break;
      break;
 
 
    case RXO_setpsw:
    case RXO_setpsw:
      v = 1 << opcode.op[0].reg;
      v = 1 << opcode.op[0].reg;
      if (FLAG_PM
      if (FLAG_PM
          && (v == FLAGBIT_I
          && (v == FLAGBIT_I
              || v == FLAGBIT_U))
              || v == FLAGBIT_U))
        break;
        break;
      regs.r_psw |= v;
      regs.r_psw |= v;
      break;
      break;
 
 
    case RXO_smovb:
    case RXO_smovb:
      while (regs.r[3])
      while (regs.r[3])
        {
        {
          uma = mem_get_qi (regs.r[2] --);
          uma = mem_get_qi (regs.r[2] --);
          mem_put_qi (regs.r[1]--, uma);
          mem_put_qi (regs.r[1]--, uma);
          regs.r[3] --;
          regs.r[3] --;
        }
        }
      break;
      break;
 
 
    case RXO_smovf:
    case RXO_smovf:
      while (regs.r[3])
      while (regs.r[3])
        {
        {
          uma = mem_get_qi (regs.r[2] ++);
          uma = mem_get_qi (regs.r[2] ++);
          mem_put_qi (regs.r[1]++, uma);
          mem_put_qi (regs.r[1]++, uma);
          regs.r[3] --;
          regs.r[3] --;
        }
        }
      break;
      break;
 
 
    case RXO_smovu:
    case RXO_smovu:
      while (regs.r[3] != 0)
      while (regs.r[3] != 0)
        {
        {
          uma = mem_get_qi (regs.r[2] ++);
          uma = mem_get_qi (regs.r[2] ++);
          mem_put_qi (regs.r[1]++, uma);
          mem_put_qi (regs.r[1]++, uma);
          regs.r[3] --;
          regs.r[3] --;
          if (uma == 0)
          if (uma == 0)
            break;
            break;
        }
        }
      break;
      break;
 
 
    case RXO_shar: /* d = ma >> mb */
    case RXO_shar: /* d = ma >> mb */
      SHIFT_OP (sll, int, mb, >>=, 1);
      SHIFT_OP (sll, int, mb, >>=, 1);
      break;
      break;
 
 
    case RXO_shll: /* d = ma << mb */
    case RXO_shll: /* d = ma << mb */
      SHIFT_OP (ll, int, mb, <<=, 0x80000000UL);
      SHIFT_OP (ll, int, mb, <<=, 0x80000000UL);
      break;
      break;
 
 
    case RXO_shlr: /* d = ma >> mb */
    case RXO_shlr: /* d = ma >> mb */
      SHIFT_OP (ll, unsigned int, mb, >>=, 1);
      SHIFT_OP (ll, unsigned int, mb, >>=, 1);
      break;
      break;
 
 
    case RXO_sstr:
    case RXO_sstr:
      switch (opcode.size)
      switch (opcode.size)
        {
        {
        case RX_Long:
        case RX_Long:
          while (regs.r[3] != 0)
          while (regs.r[3] != 0)
            {
            {
              mem_put_si (regs.r[1], regs.r[2]);
              mem_put_si (regs.r[1], regs.r[2]);
              regs.r[1] += 4;
              regs.r[1] += 4;
              regs.r[3] --;
              regs.r[3] --;
            }
            }
          break;
          break;
        case RX_Word:
        case RX_Word:
          while (regs.r[3] != 0)
          while (regs.r[3] != 0)
            {
            {
              mem_put_hi (regs.r[1], regs.r[2]);
              mem_put_hi (regs.r[1], regs.r[2]);
              regs.r[1] += 2;
              regs.r[1] += 2;
              regs.r[3] --;
              regs.r[3] --;
            }
            }
          break;
          break;
        case RX_Byte:
        case RX_Byte:
          while (regs.r[3] != 0)
          while (regs.r[3] != 0)
            {
            {
              mem_put_qi (regs.r[1], regs.r[2]);
              mem_put_qi (regs.r[1], regs.r[2]);
              regs.r[1] ++;
              regs.r[1] ++;
              regs.r[3] --;
              regs.r[3] --;
            }
            }
          break;
          break;
        default:
        default:
          abort ();
          abort ();
        }
        }
      break;
      break;
 
 
    case RXO_stcc:
    case RXO_stcc:
      if (GS2())
      if (GS2())
        PD (GS ());
        PD (GS ());
      break;
      break;
 
 
    case RXO_stop:
    case RXO_stop:
      PRIVILEDGED ();
      PRIVILEDGED ();
      regs.r_psw |= FLAGBIT_I;
      regs.r_psw |= FLAGBIT_I;
      return RX_MAKE_STOPPED(0);
      return RX_MAKE_STOPPED(0);
 
 
    case RXO_sub:
    case RXO_sub:
      MATH_OP (-, 0);
      MATH_OP (-, 0);
      break;
      break;
 
 
    case RXO_suntil:
    case RXO_suntil:
      if (regs.r[3] == 0)
      if (regs.r[3] == 0)
        break;
        break;
      switch (opcode.size)
      switch (opcode.size)
        {
        {
        case RX_Long:
        case RX_Long:
          uma = get_reg (2);
          uma = get_reg (2);
          while (regs.r[3] != 0)
          while (regs.r[3] != 0)
            {
            {
              regs.r[3] --;
              regs.r[3] --;
              umb = mem_get_si (get_reg (1));
              umb = mem_get_si (get_reg (1));
              regs.r[1] += 4;
              regs.r[1] += 4;
              if (umb == uma)
              if (umb == uma)
                break;
                break;
            }
            }
          break;
          break;
        case RX_Word:
        case RX_Word:
          uma = get_reg (2) & 0xffff;
          uma = get_reg (2) & 0xffff;
          while (regs.r[3] != 0)
          while (regs.r[3] != 0)
            {
            {
              regs.r[3] --;
              regs.r[3] --;
              umb = mem_get_hi (get_reg (1));
              umb = mem_get_hi (get_reg (1));
              regs.r[1] += 2;
              regs.r[1] += 2;
              if (umb == uma)
              if (umb == uma)
                break;
                break;
            }
            }
          break;
          break;
        case RX_Byte:
        case RX_Byte:
          uma = get_reg (2) & 0xff;
          uma = get_reg (2) & 0xff;
          while (regs.r[3] != 0)
          while (regs.r[3] != 0)
            {
            {
              regs.r[3] --;
              regs.r[3] --;
              umb = mem_get_qi (regs.r[1]);
              umb = mem_get_qi (regs.r[1]);
              regs.r[1] += 1;
              regs.r[1] += 1;
              if (umb == uma)
              if (umb == uma)
                break;
                break;
            }
            }
          break;
          break;
        default:
        default:
          abort();
          abort();
        }
        }
      if (uma == umb)
      if (uma == umb)
        set_zc (1, 1);
        set_zc (1, 1);
      else
      else
        set_zc (0, ((int)uma - (int)umb) >= 0);
        set_zc (0, ((int)uma - (int)umb) >= 0);
      break;
      break;
 
 
    case RXO_swhile:
    case RXO_swhile:
      if (regs.r[3] == 0)
      if (regs.r[3] == 0)
        break;
        break;
      switch (opcode.size)
      switch (opcode.size)
        {
        {
        case RX_Long:
        case RX_Long:
          uma = get_reg (2);
          uma = get_reg (2);
          while (regs.r[3] != 0)
          while (regs.r[3] != 0)
            {
            {
              regs.r[3] --;
              regs.r[3] --;
              umb = mem_get_si (get_reg (1));
              umb = mem_get_si (get_reg (1));
              regs.r[1] += 4;
              regs.r[1] += 4;
              if (umb != uma)
              if (umb != uma)
                break;
                break;
            }
            }
          break;
          break;
        case RX_Word:
        case RX_Word:
          uma = get_reg (2) & 0xffff;
          uma = get_reg (2) & 0xffff;
          while (regs.r[3] != 0)
          while (regs.r[3] != 0)
            {
            {
              regs.r[3] --;
              regs.r[3] --;
              umb = mem_get_hi (get_reg (1));
              umb = mem_get_hi (get_reg (1));
              regs.r[1] += 2;
              regs.r[1] += 2;
              if (umb != uma)
              if (umb != uma)
                break;
                break;
            }
            }
          break;
          break;
        case RX_Byte:
        case RX_Byte:
          uma = get_reg (2) & 0xff;
          uma = get_reg (2) & 0xff;
          while (regs.r[3] != 0)
          while (regs.r[3] != 0)
            {
            {
              regs.r[3] --;
              regs.r[3] --;
              umb = mem_get_qi (regs.r[1]);
              umb = mem_get_qi (regs.r[1]);
              regs.r[1] += 1;
              regs.r[1] += 1;
              if (umb != uma)
              if (umb != uma)
                break;
                break;
            }
            }
          break;
          break;
        default:
        default:
          abort();
          abort();
        }
        }
      if (uma == umb)
      if (uma == umb)
        set_zc (1, 1);
        set_zc (1, 1);
      else
      else
        set_zc (0, ((int)uma - (int)umb) >= 0);
        set_zc (0, ((int)uma - (int)umb) >= 0);
      break;
      break;
 
 
    case RXO_wait:
    case RXO_wait:
      PRIVILEDGED ();
      PRIVILEDGED ();
      regs.r_psw |= FLAGBIT_I;
      regs.r_psw |= FLAGBIT_I;
      return RX_MAKE_STOPPED(0);
      return RX_MAKE_STOPPED(0);
 
 
    case RXO_xchg:
    case RXO_xchg:
      v = GS (); /* This is the memory operand, if any.  */
      v = GS (); /* This is the memory operand, if any.  */
      PS (GD ()); /* and this may change the address register.  */
      PS (GD ()); /* and this may change the address register.  */
      PD (v);
      PD (v);
      break;
      break;
 
 
    case RXO_xor:
    case RXO_xor:
      LOGIC_OP (^);
      LOGIC_OP (^);
      break;
      break;
 
 
    default:
    default:
      EXCEPTION (EX_UNDEFINED);
      EXCEPTION (EX_UNDEFINED);
    }
    }
 
 
  return RX_MAKE_STEPPED ();
  return RX_MAKE_STEPPED ();
}
}
 
 

powered by: WebSVN 2.1.0

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