#include "config.h"

#include <signal.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "mn10300_sim.h"
#include "simops.h"
#include "sys/syscall.h"
#include "bfd.h"
#include <errno.h>
#include <sys/stat.h>
#include <sys/times.h>
#include <sys/time.h>

#define REG0(X) ((X) & 0x3)
#define REG1(X) (((X) & 0xc) >> 2)
#define REG0_4(X) (((X) & 0x30) >> 4)
#define REG0_8(X) (((X) & 0x300) >> 8)
#define REG1_8(X) (((X) & 0xc00) >> 10)
#define REG0_16(X) (((X) & 0x30000) >> 16)
#define REG1_16(X) (((X) & 0xc0000) >> 18)

/* mov imm8, dn */
void OP_8000 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG0_8 (insn)] = SEXT8 (insn & 0xff);
}

/* mov dm, dn */
void OP_80 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG0 (insn)] = State.regs[REG_D0 + REG1 (insn)];
}

/* mov dm, an */
void OP_F1E0 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_A0 + REG0 (insn)] = State.regs[REG_D0 + REG1 (insn)];
}

/* mov am, dn */
void OP_F1D0 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG0 (insn)] = State.regs[REG_A0 + REG1 (insn)];
}

/* mov imm8, an */
void OP_9000 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_A0 + REG0_8 (insn)] = insn & 0xff;
}

/* mov am, an */
void OP_90 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_A0 + REG0 (insn)] = State.regs[REG_A0 + REG1 (insn)];
}

/* mov sp, an */
void OP_3C (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_A0 + REG0 (insn)] = State.regs[REG_SP];
}

/* mov am, sp */
void OP_F2F0 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_SP] = State.regs[REG_A0 + REG1 (insn)];
}

/* mov psw, dn */
void OP_F2E4 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG0 (insn)] = PSW;
}

/* mov dm, psw */
void OP_F2F3 (insn, extension)
     unsigned long insn, extension;
{
  PSW = State.regs[REG_D0 + REG1 (insn)];
}

/* mov mdr, dn */
void OP_F2E0 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG0 (insn)] = State.regs[REG_MDR];
}

/* mov dm, mdr */
void OP_F2F2 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_MDR] = State.regs[REG_D0 + REG1 (insn)];
}

/* mov (am), dn */
void OP_70 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG1 (insn)]
    = load_word (State.regs[REG_A0 + REG0 (insn)]);
}

/* mov (d8,am), dn */
void OP_F80000 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG1_8 (insn)]
    = load_word ((State.regs[REG_A0 + REG0_8 (insn)] + SEXT8 (insn & 0xff)));
}

/* mov (d16,am), dn */
void OP_FA000000 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG1_16 (insn)]
    = load_word ((State.regs[REG_A0 + REG0_16 (insn)]
		  + SEXT16 (insn & 0xffff)));
}

/* mov (d32,am), dn */
void OP_FC000000 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG1_16 (insn)]
    = load_word ((State.regs[REG_A0 + REG0_16 (insn)]
		  + ((insn & 0xffff) << 16) + extension));
}

/* mov (d8,sp), dn */
void OP_5800 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG0_8 (insn)]
    = load_word (State.regs[REG_SP] + (insn & 0xff));
}

/* mov (d16,sp), dn */
void OP_FAB40000 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG0_16 (insn)]
    = load_word (State.regs[REG_SP] + (insn & 0xffff));
}

/* mov (d32,sp), dn */
void OP_FCB40000 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG0_16 (insn)]
    = load_word (State.regs[REG_SP] + (((insn & 0xffff) << 16) + extension));
}

/* mov (di,am), dn */
void OP_F300 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG0_4 (insn)]
    = load_word ((State.regs[REG_A0 + REG0 (insn)]
		  + State.regs[REG_D0 + REG1 (insn)]));
}

/* mov (abs16), dn */
void OP_300000 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG0_16 (insn)] = load_word ((insn & 0xffff));
}

/* mov (abs32), dn */
void OP_FCA40000 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG0_16 (insn)]
    = load_word ((((insn & 0xffff) << 16) + extension));
}

/* mov (am), an */
void OP_F000 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_A0 + REG1 (insn)]
    = load_word (State.regs[REG_A0 + REG0 (insn)]);
}

/* mov (d8,am), an */
void OP_F82000 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_A0 + REG1_8 (insn)]
    = load_word ((State.regs[REG_A0 + REG0_8 (insn)]
		  + SEXT8 (insn & 0xff)));
}

/* mov (d16,am), an */
void OP_FA200000 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_A0 + REG1_16 (insn)]
    = load_word ((State.regs[REG_A0 + REG0_16 (insn)]
		  + SEXT16 (insn & 0xffff)));
}

/* mov (d32,am), an */
void OP_FC200000 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_A0 + REG1_16 (insn)]
    = load_word ((State.regs[REG_A0 + REG0_16 (insn)]
		  + ((insn & 0xffff) << 16) + extension));
}

/* mov (d8,sp), an */
void OP_5C00 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_A0 + REG0_8 (insn)]
    = load_word (State.regs[REG_SP] + (insn & 0xff));
}

/* mov (d16,sp), an */
void OP_FAB00000 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_A0 + REG0_16 (insn)]
    = load_word (State.regs[REG_SP] + (insn & 0xffff));
}

/* mov (d32,sp), an */
void OP_FCB00000 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_A0 + REG0_16 (insn)]
    = load_word (State.regs[REG_SP] + (((insn & 0xffff) << 16) + extension));
}

/* mov (di,am), an */
void OP_F380 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_A0 + REG0_4 (insn)]
    = load_word ((State.regs[REG_A0 + REG0 (insn)]
		 + State.regs[REG_D0 + REG1 (insn)]));
}

/* mov (abs16), an */
void OP_FAA00000 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_A0 + REG0_16 (insn)] = load_word ((insn & 0xffff));
}

/* mov (abs32), an */
void OP_FCA00000 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_A0 + REG0_16 (insn)]
    = load_word ((((insn & 0xffff) << 16) + extension));
}

/* mov (d8,am), sp */
void OP_F8F000 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_SP]
    = load_word ((State.regs[REG_A0 + REG0_8 (insn)]
		  + SEXT8 (insn & 0xff)));
}

/* mov dm, (an) */
void OP_60 (insn, extension)
     unsigned long insn, extension;
{
  store_word (State.regs[REG_A0 + REG0 (insn)],
	      State.regs[REG_D0 + REG1 (insn)]);
}

/* mov dm, (d8,an) */
void OP_F81000 (insn, extension)
     unsigned long insn, extension;
{
  store_word ((State.regs[REG_A0 + REG0_8 (insn)] + SEXT8 (insn & 0xff)),
	      State.regs[REG_D0 + REG1_8 (insn)]);
}

/* mov dm (d16,an) */
void OP_FA100000 (insn, extension)
     unsigned long insn, extension;
{
  store_word ((State.regs[REG_A0 + REG0_16 (insn)] + SEXT16 (insn & 0xffff)),
	      State.regs[REG_D0 + REG1_16 (insn)]);
}

/* mov dm (d32,an) */
void OP_FC100000 (insn, extension)
     unsigned long insn, extension;
{
  store_word ((State.regs[REG_A0 + REG0_16 (insn)]
	       + ((insn & 0xffff) << 16) + extension),
	      State.regs[REG_D0 + REG1_16 (insn)]);
}

/* mov dm, (d8,sp) */
void OP_4200 (insn, extension)
     unsigned long insn, extension;
{
  store_word (State.regs[REG_SP] + (insn & 0xff),
	      State.regs[REG_D0 + REG1_8 (insn)]);
}

/* mov dm, (d16,sp) */
void OP_FA910000 (insn, extension)
     unsigned long insn, extension;
{
  store_word (State.regs[REG_SP] + (insn & 0xffff),
	      State.regs[REG_D0 + REG1_16 (insn)]);
}

/* mov dm, (d32,sp) */
void OP_FC910000 (insn, extension)
     unsigned long insn, extension;
{
  store_word (State.regs[REG_SP] + (((insn & 0xffff) << 16) + extension),
	      State.regs[REG_D0 + REG1_16 (insn)]);
}

/* mov dm, (di,an) */
void OP_F340 (insn, extension)
     unsigned long insn, extension;
{
  store_word ((State.regs[REG_A0 + REG0 (insn)]
	       + State.regs[REG_D0 + REG1 (insn)]),
	      State.regs[REG_D0 + REG0_4 (insn)]);
}

/* mov dm, (abs16) */
void OP_10000 (insn, extension)
     unsigned long insn, extension;
{
  store_word ((insn & 0xffff), State.regs[REG_D0 + REG1_16 (insn)]);
}

/* mov dm, (abs32) */
void OP_FC810000 (insn, extension)
     unsigned long insn, extension;
{
  store_word ((((insn & 0xffff) << 16) + extension), 
	      State.regs[REG_D0 + REG1_16 (insn)]);
}

/* mov am, (an) */
void OP_F010 (insn, extension)
     unsigned long insn, extension;
{
  store_word (State.regs[REG_A0 + REG0 (insn)],
	      State.regs[REG_A0 + REG1 (insn)]);
}

/* mov am, (d8,an) */
void OP_F83000 (insn, extension)
     unsigned long insn, extension;
{
  store_word ((State.regs[REG_A0 + REG0_8 (insn)] + SEXT8 (insn & 0xff)),
	      State.regs[REG_A0 + REG1_8 (insn)]);
}

/* mov am, (d16,an) */
void OP_FA300000 (insn, extension)
     unsigned long insn, extension;
{
  store_word ((State.regs[REG_A0 + REG0_16 (insn)] + SEXT16 (insn & 0xffff)),
	      State.regs[REG_A0 + REG1_16 (insn)]);
}

/* mov am, (d32,an) */
void OP_FC300000 (insn, extension)
     unsigned long insn, extension;
{
  store_word ((State.regs[REG_A0 + REG0_16 (insn)]
	       + ((insn & 0xffff) << 16) + extension),
	      State.regs[REG_A0 + REG1_16 (insn)]);
}

/* mov am, (d8,sp) */
void OP_4300 (insn, extension)
     unsigned long insn, extension;
{
  store_word (State.regs[REG_SP] + (insn & 0xff),
	      State.regs[REG_A0 + REG1_8 (insn)]);
}

/* mov am, (d16,sp) */
void OP_FA900000 (insn, extension)
     unsigned long insn, extension;
{
  store_word (State.regs[REG_SP] + (insn & 0xffff),
	      State.regs[REG_A0 + REG1_16 (insn)]);
}

/* mov am, (d32,sp) */
void OP_FC900000 (insn, extension)
     unsigned long insn, extension;
{
  store_word (State.regs[REG_SP] + (((insn & 0xffff) << 16) + extension),
	      State.regs[REG_A0 + REG1_16 (insn)]);
}

/* mov am, (di,an) */
void OP_F3C0 (insn, extension)
     unsigned long insn, extension;
{
  store_word ((State.regs[REG_A0 + REG0 (insn)]
	       + State.regs[REG_D0 + REG1 (insn)]),
	      State.regs[REG_A0 + REG0_4 (insn)]);
}

/* mov am, (abs16) */
void OP_FA800000 (insn, extension)
     unsigned long insn, extension;
{
  store_word ((insn & 0xffff), State.regs[REG_A0 + REG1_16 (insn)]);
}

/* mov am, (abs32) */
void OP_FC800000 (insn, extension)
     unsigned long insn, extension;
{
  store_word ((((insn & 0xffff) << 16) + extension), State.regs[REG_A0 + REG1_16 (insn)]);
}

/* mov sp, (d8,an) */
void OP_F8F400 (insn, extension)
     unsigned long insn, extension;
{
  store_word (State.regs[REG_A0 + REG0_8 (insn)] + SEXT8 (insn & 0xff),
	      State.regs[REG_SP]);
}

/* mov imm16, dn */
void OP_2C0000 (insn, extension)
     unsigned long insn, extension;
{
  unsigned long value;

  value = SEXT16 (insn & 0xffff);
  State.regs[REG_D0 + REG0_16 (insn)] = value;
}

/* mov imm32,dn */
void OP_FCCC0000 (insn, extension)
     unsigned long insn, extension;
{
  unsigned long value;

  value = ((insn & 0xffff) << 16) + extension;
  State.regs[REG_D0 + REG0_16 (insn)] = value;
}

/* mov imm16, an */
void OP_240000 (insn, extension)
     unsigned long insn, extension;
{
  unsigned long value;

  value = insn & 0xffff;
  State.regs[REG_A0 + REG0_16 (insn)] = value;
}

/* mov imm32, an */
void OP_FCDC0000 (insn, extension)
     unsigned long insn, extension;
{
  unsigned long value;

  value = ((insn & 0xffff) << 16) + extension;
  State.regs[REG_A0 + REG0_16 (insn)] = value;
}

/* movbu (am), dn */
void OP_F040 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG1 (insn)]
    = load_byte (State.regs[REG_A0 + REG0 (insn)]);
}

/* movbu (d8,am), dn */
void OP_F84000 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG1_8 (insn)]
    = load_byte ((State.regs[REG_A0 + REG0_8 (insn)]
		  + SEXT8 (insn & 0xff)));
}

/* movbu (d16,am), dn */
void OP_FA400000 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG1_16 (insn)]
    = load_byte ((State.regs[REG_A0 + REG0_16 (insn)]
		  + SEXT16 (insn & 0xffff)));
}

/* movbu (d32,am), dn */
void OP_FC400000 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG1_16 (insn)]
    = load_byte ((State.regs[REG_A0 + REG0_16 (insn)]
		  + ((insn & 0xffff) << 16) + extension));
}

/* movbu (d8,sp), dn */
void OP_F8B800 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG0_8 (insn)]
    = load_byte ((State.regs[REG_SP] + (insn & 0xff)));
}

/* movbu (d16,sp), dn */
void OP_FAB80000 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG0_16 (insn)]
    = load_byte ((State.regs[REG_SP] + (insn & 0xffff)));
}

/* movbu (d32,sp), dn */
void OP_FCB80000 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG0_16 (insn)]
    = load_byte (State.regs[REG_SP] + (((insn & 0xffff) << 16) + extension));
}

/* movbu (di,am), dn */
void OP_F400 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG0_4 (insn)]
    = load_byte ((State.regs[REG_A0 + REG0 (insn)]
		  + State.regs[REG_D0 + REG1 (insn)]));
}

/* movbu (abs16), dn */
void OP_340000 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG0_16 (insn)] = load_byte ((insn & 0xffff));
}

/* movbu (abs32), dn */
void OP_FCA80000 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG0_16 (insn)]
    = load_byte ((((insn & 0xffff) << 16) + extension));
}

/* movbu dm, (an) */
void OP_F050 (insn, extension)
     unsigned long insn, extension;
{
  store_byte (State.regs[REG_A0 + REG0 (insn)],
	      State.regs[REG_D0 + REG1 (insn)]);
}

/* movbu dm, (d8,an) */
void OP_F85000 (insn, extension)
     unsigned long insn, extension;
{
  store_byte ((State.regs[REG_A0 + REG0_8 (insn)] + SEXT8 (insn & 0xff)),
	      State.regs[REG_D0 + REG1_8 (insn)]);
}

/* movbu dm, (d16,an) */
void OP_FA500000 (insn, extension)
     unsigned long insn, extension;
{
  store_byte ((State.regs[REG_A0 + REG0_16 (insn)] + SEXT16 (insn & 0xffff)),
	      State.regs[REG_D0 + REG1_16 (insn)]);
}

/* movbu dm, (d32,an) */
void OP_FC500000 (insn, extension)
     unsigned long insn, extension;
{
  store_byte ((State.regs[REG_A0 + REG0_16 (insn)]
	       + ((insn & 0xffff) << 16) + extension),
	      State.regs[REG_D0 + REG1_16 (insn)]);
}

/* movbu dm, (d8,sp) */
void OP_F89200 (insn, extension)
     unsigned long insn, extension;
{
  store_byte (State.regs[REG_SP] + (insn & 0xff),
	      State.regs[REG_D0 + REG1_8 (insn)]);
}

/* movbu dm, (d16,sp) */
void OP_FA920000 (insn, extension)
     unsigned long insn, extension;
{
  store_byte (State.regs[REG_SP] + (insn & 0xffff),
	      State.regs[REG_D0 + REG1_16 (insn)]);
}

/* movbu dm (d32,sp) */
void OP_FC920000 (insn, extension)
     unsigned long insn, extension;
{
  store_byte (State.regs[REG_SP] + (((insn & 0xffff) << 16) + extension),
	      State.regs[REG_D0 + REG1_16 (insn)]);
}

/* movbu dm, (di,an) */
void OP_F440 (insn, extension)
     unsigned long insn, extension;
{
  store_byte ((State.regs[REG_A0 + REG0 (insn)]
	       + State.regs[REG_D0 + REG1 (insn)]),
	      State.regs[REG_D0 + REG0_4 (insn)]);
}

/* movbu dm, (abs16) */
void OP_20000 (insn, extension)
     unsigned long insn, extension;
{
  store_byte ((insn & 0xffff), State.regs[REG_D0 + REG1_16 (insn)]);
}

/* movbu dm, (abs32) */
void OP_FC820000 (insn, extension)
     unsigned long insn, extension;
{
  store_byte ((((insn & 0xffff) << 16) + extension), State.regs[REG_D0 + REG1_16 (insn)]);
}

/* movhu (am), dn */
void OP_F060 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG1 (insn)]
    = load_half (State.regs[REG_A0 + REG0 (insn)]);
}

/* movhu (d8,am), dn */
void OP_F86000 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG1_8 (insn)]
    = load_half ((State.regs[REG_A0 + REG0_8 (insn)]
		  + SEXT8 (insn & 0xff)));
}

/* movhu (d16,am), dn */
void OP_FA600000 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG1_16 (insn)]
    = load_half ((State.regs[REG_A0 + REG0_16 (insn)]
		  + SEXT16 (insn & 0xffff)));
}

/* movhu (d32,am), dn */
void OP_FC600000 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG1_16 (insn)]
    = load_half ((State.regs[REG_A0 + REG0_16 (insn)]
		  + ((insn & 0xffff) << 16) + extension));
}

/* movhu (d8,sp) dn */
void OP_F8BC00 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG0_8 (insn)]
    = load_half ((State.regs[REG_SP] + (insn & 0xff)));
}

/* movhu (d16,sp), dn */
void OP_FABC0000 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG0_16 (insn)]
    = load_half ((State.regs[REG_SP] + (insn & 0xffff)));
}

/* movhu (d32,sp), dn */
void OP_FCBC0000 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG0_16 (insn)]
    = load_half (State.regs[REG_SP] + (((insn & 0xffff) << 16) + extension));
}

/* movhu (di,am), dn */
void OP_F480 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG0_4 (insn)]
    = load_half ((State.regs[REG_A0 + REG0 (insn)]
		  + State.regs[REG_D0 + REG1 (insn)]));
}

/* movhu (abs16), dn */
void OP_380000 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG0_16 (insn)] = load_half ((insn & 0xffff));
}

/* movhu (abs32), dn */
void OP_FCAC0000 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG0_16 (insn)]
    = load_half ((((insn & 0xffff) << 16) + extension));
}

/* movhu dm, (an) */
void OP_F070 (insn, extension)
     unsigned long insn, extension;
{
  store_half (State.regs[REG_A0 + REG0 (insn)],
	      State.regs[REG_D0 + REG1 (insn)]);
}

/* movhu dm, (d8,an) */
void OP_F87000 (insn, extension)
     unsigned long insn, extension;
{
  store_half ((State.regs[REG_A0 + REG0_8 (insn)] + SEXT8 (insn & 0xff)),
	      State.regs[REG_D0 + REG1_8 (insn)]);
}

/* movhu dm, (d16,an) */
void OP_FA700000 (insn, extension)
     unsigned long insn, extension;
{
  store_half ((State.regs[REG_A0 + REG0_16 (insn)] + SEXT16 (insn & 0xffff)),
	      State.regs[REG_D0 + REG1_16 (insn)]);
}

/* movhu dm, (d32,an) */
void OP_FC700000 (insn, extension)
     unsigned long insn, extension;
{
  store_half ((State.regs[REG_A0 + REG0_16 (insn)]
	       + ((insn & 0xffff) << 16) + extension),
	      State.regs[REG_D0 + REG1_16 (insn)]);
}

/* movhu dm,(d8,sp) */
void OP_F89300 (insn, extension)
     unsigned long insn, extension;
{
  store_half (State.regs[REG_SP] + (insn & 0xff),
	      State.regs[REG_D0 + REG1_8 (insn)]);
}

/* movhu dm,(d16,sp) */
void OP_FA930000 (insn, extension)
     unsigned long insn, extension;
{
  store_half (State.regs[REG_SP] + (insn & 0xffff),
	      State.regs[REG_D0 + REG1_16 (insn)]);
}

/* movhu dm,(d32,sp) */
void OP_FC930000 (insn, extension)
     unsigned long insn, extension;
{
  store_half (State.regs[REG_SP] + (((insn & 0xffff) << 16) + extension),
	      State.regs[REG_D0 + REG1_16 (insn)]);
}

/* movhu dm, (di,an) */
void OP_F4C0 (insn, extension)
     unsigned long insn, extension;
{
  store_half ((State.regs[REG_A0 + REG0 (insn)]
	       + State.regs[REG_D0 + REG1 (insn)]),
	      State.regs[REG_D0 + REG0_4 (insn)]);
}

/* movhu dm, (abs16) */
void OP_30000 (insn, extension)
     unsigned long insn, extension;
{
  store_half ((insn & 0xffff), State.regs[REG_D0 + REG1_16 (insn)]);
}

/* movhu dm, (abs32) */
void OP_FC830000 (insn, extension)
     unsigned long insn, extension;
{
  store_half ((((insn & 0xffff) << 16) + extension), State.regs[REG_D0 + REG1_16 (insn)]);
}

/* ext dn */
void OP_F2D0 (insn, extension)
     unsigned long insn, extension;
{
  if (State.regs[REG_D0 + REG0 (insn)] & 0x80000000)
    State.regs[REG_MDR] = -1;
  else
    State.regs[REG_MDR] = 0;
}

/* extb dn */
void OP_10 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG0 (insn)] = SEXT8 (State.regs[REG_D0 + REG0 (insn)]);
}

/* extbu dn */
void OP_14 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG0 (insn)] &= 0xff;
}

/* exth dn */
void OP_18 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG0 (insn)]
    = SEXT16 (State.regs[REG_D0 + REG0 (insn)]);
}

/* exthu dn */
void OP_1C (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG0 (insn)] &= 0xffff;
}

/* movm (sp), reg_list */
void OP_CE00 (insn, extension)
     unsigned long insn, extension;
{
  unsigned long sp = State.regs[REG_SP];
  unsigned long mask;

  mask = insn & 0xff;

  if (mask & 0x8)
    {
      sp += 4;
      State.regs[REG_LAR] = load_word (sp);
      sp += 4;
      State.regs[REG_LIR] = load_word (sp);
      sp += 4;
      State.regs[REG_MDR] = load_word (sp);
      sp += 4;
      State.regs[REG_A0 + 1] = load_word (sp);
      sp += 4;
      State.regs[REG_A0] = load_word (sp);
      sp += 4;
      State.regs[REG_D0 + 1] = load_word (sp);
      sp += 4;
      State.regs[REG_D0] = load_word (sp);
      sp += 4;
    }

  if (mask & 0x10)
    {
      State.regs[REG_A0 + 3] = load_word (sp);
      sp += 4;
    }

  if (mask & 0x20)
    {
      State.regs[REG_A0 + 2] = load_word (sp);
      sp += 4;
    }

  if (mask & 0x40)
    {
      State.regs[REG_D0 + 3] = load_word (sp);
      sp += 4;
    }

  if (mask & 0x80)
    {
      State.regs[REG_D0 + 2] = load_word (sp);
      sp += 4;
    }

  /* And make sure to update the stack pointer.  */
  State.regs[REG_SP] = sp;
}

/* movm reg_list, (sp) */
void OP_CF00 (insn, extension)
     unsigned long insn, extension;
{
  unsigned long sp = State.regs[REG_SP];
  unsigned long mask;

  mask = insn & 0xff;

  if (mask & 0x80)
    {
      sp -= 4;
      store_word (sp, State.regs[REG_D0 + 2]);
    }

  if (mask & 0x40)
    {
      sp -= 4;
      store_word (sp, State.regs[REG_D0 + 3]);
    }

  if (mask & 0x20)
    {
      sp -= 4;
      store_word (sp, State.regs[REG_A0 + 2]);
    }

  if (mask & 0x10)
    {
      sp -= 4;
      store_word (sp, State.regs[REG_A0 + 3]);
    }

  if (mask & 0x8)
    {
      sp -= 4;
      store_word (sp, State.regs[REG_D0]);
      sp -= 4;
      store_word (sp, State.regs[REG_D0 + 1]);
      sp -= 4;
      store_word (sp, State.regs[REG_A0]);
      sp -= 4;
      store_word (sp, State.regs[REG_A0 + 1]);
      sp -= 4;
      store_word (sp, State.regs[REG_MDR]);
      sp -= 4;
      store_word (sp, State.regs[REG_LIR]);
      sp -= 4;
      store_word (sp, State.regs[REG_LAR]);
      sp -= 4;
    }

  /* And make sure to update the stack pointer.  */
  State.regs[REG_SP] = sp;
}

/* clr dn */
void OP_0 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_D0 + REG1 (insn)] = 0;

  PSW |= PSW_Z;
  PSW &= ~(PSW_V | PSW_C | PSW_N);
}

/* add dm,dn */
void OP_E0 (insn, extension)
     unsigned long insn, extension;
{
  int z, c, n, v;
  unsigned long reg1, reg2, value;

  reg1 = State.regs[REG_D0 + REG1 (insn)];
  reg2 = State.regs[REG_D0 + REG0 (insn)];
  value = reg1 + reg2;
  State.regs[REG_D0 + REG0 (insn)] = value;

  z = (value == 0);
  n = (value & 0x80000000);
  c = (value < reg1) || (value < reg2);
  v = ((reg2 & 0x80000000) == (reg1 & 0x80000000)
       && (reg2 & 0x80000000) != (value & 0x80000000));

  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | ( n ? PSW_N : 0)
	  | (c ? PSW_C : 0) | (v ? PSW_V : 0));
}

/* add dm, an */
void OP_F160 (insn, extension)
     unsigned long insn, extension;
{
  int z, c, n, v;
  unsigned long reg1, reg2, value;

  reg1 = State.regs[REG_D0 + REG1 (insn)];
  reg2 = State.regs[REG_A0 + REG0 (insn)];
  value = reg1 + reg2;
  State.regs[REG_A0 + REG0 (insn)] = value;

  z = (value == 0);
  n = (value & 0x80000000);
  c = (value < reg1) || (value < reg2);
  v = ((reg2 & 0x80000000) == (reg1 & 0x80000000)
       && (reg2 & 0x80000000) != (value & 0x80000000));

  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | ( n ? PSW_N : 0)
	  | (c ? PSW_C : 0) | (v ? PSW_V : 0));
}

/* add am, dn */
void OP_F150 (insn, extension)
     unsigned long insn, extension;
{
  int z, c, n, v;
  unsigned long reg1, reg2, value;

  reg1 = State.regs[REG_A0 + REG1 (insn)];
  reg2 = State.regs[REG_D0 + REG0 (insn)];
  value = reg1 + reg2;
  State.regs[REG_D0 + REG0 (insn)] = value;

  z = (value == 0);
  n = (value & 0x80000000);
  c = (value < reg1) || (value < reg2);
  v = ((reg2 & 0x80000000) == (reg1 & 0x80000000)
       && (reg2 & 0x80000000) != (value & 0x80000000));

  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | ( n ? PSW_N : 0)
	  | (c ? PSW_C : 0) | (v ? PSW_V : 0));
}

/* add am,an */
void OP_F170 (insn, extension)
     unsigned long insn, extension;
{
  int z, c, n, v;
  unsigned long reg1, reg2, value;

  reg1 = State.regs[REG_A0 + REG1 (insn)];
  reg2 = State.regs[REG_A0 + REG0 (insn)];
  value = reg1 + reg2;
  State.regs[REG_A0 + REG0 (insn)] = value;

  z = (value == 0);
  n = (value & 0x80000000);
  c = (value < reg1) || (value < reg2);
  v = ((reg2 & 0x80000000) == (reg1 & 0x80000000)
       && (reg2 & 0x80000000) != (value & 0x80000000));

  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | ( n ? PSW_N : 0)
	  | (c ? PSW_C : 0) | (v ? PSW_V : 0));
}

/* add imm8, dn */
void OP_2800 (insn, extension)
     unsigned long insn, extension;
{
  int z, c, n, v;
  unsigned long reg1, imm, value;

  reg1 = State.regs[REG_D0 + REG0_8 (insn)];
  imm = SEXT8 (insn & 0xff);
  value = reg1 + imm;
  State.regs[REG_D0 + REG0_8 (insn)] = value;

  z = (value == 0);
  n = (value & 0x80000000);
  c = (value < reg1) || (value < imm);
  v = ((reg1 & 0x80000000) == (imm & 0x80000000)
       && (reg1 & 0x80000000) != (value & 0x80000000));

  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | ( n ? PSW_N : 0)
	  | (c ? PSW_C : 0) | (v ? PSW_V : 0));
}

/* add imm16, dn */
void OP_FAC00000 (insn, extension)
     unsigned long insn, extension;
{
  int z, c, n, v;
  unsigned long reg1, imm, value;

  reg1 = State.regs[REG_D0 + REG0_16 (insn)];
  imm = SEXT16 (insn & 0xffff);
  value = reg1 + imm;
  State.regs[REG_D0 + REG0_16 (insn)] = value;

  z = (value == 0);
  n = (value & 0x80000000);
  c = (value < reg1) || (value < imm);
  v = ((reg1 & 0x80000000) == (imm & 0x80000000)
       && (reg1 & 0x80000000) != (value & 0x80000000));

  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | ( n ? PSW_N : 0)
	  | (c ? PSW_C : 0) | (v ? PSW_V : 0));
}

/* add imm32,dn */
void OP_FCC00000 (insn, extension)
     unsigned long insn, extension;
{
  int z, c, n, v;
  unsigned long reg1, imm, value;

  reg1 = State.regs[REG_D0 + REG0_16 (insn)];
  imm = ((insn & 0xffff) << 16) + extension;
  value = reg1 + imm;
  State.regs[REG_D0 + REG0_16 (insn)] = value;

  z = (value == 0);
  n = (value & 0x80000000);
  c = (value < reg1) || (value < imm);
  v = ((reg1 & 0x80000000) == (imm & 0x80000000)
       && (reg1 & 0x80000000) != (value & 0x80000000));

  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | ( n ? PSW_N : 0)
	  | (c ? PSW_C : 0) | (v ? PSW_V : 0));
}

/* add imm8, an */
void OP_2000 (insn, extension)
     unsigned long insn, extension;
{
  int z, c, n, v;
  unsigned long reg1, imm, value;

  reg1 = State.regs[REG_A0 + REG0_8 (insn)];
  imm = SEXT8 (insn & 0xff);
  value = reg1 + imm;
  State.regs[REG_A0 + REG0_8 (insn)] = value;

  z = (value == 0);
  n = (value & 0x80000000);
  c = (value < reg1) || (value < imm);
  v = ((reg1 & 0x80000000) == (imm & 0x80000000)
       && (reg1 & 0x80000000) != (value & 0x80000000));

  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | ( n ? PSW_N : 0)
	  | (c ? PSW_C : 0) | (v ? PSW_V : 0));
}

/* add imm16, an */
void OP_FAD00000 (insn, extension)
     unsigned long insn, extension;
{
  int z, c, n, v;
  unsigned long reg1, imm, value;

  reg1 = State.regs[REG_A0 + REG0_16 (insn)];
  imm = SEXT16 (insn & 0xffff);
  value = reg1 + imm;
  State.regs[REG_A0 + REG0_16 (insn)] = value;

  z = (value == 0);
  n = (value & 0x80000000);
  c = (value < reg1) || (value < imm);
  v = ((reg1 & 0x80000000) == (imm & 0x80000000)
       && (reg1 & 0x80000000) != (value & 0x80000000));

  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | ( n ? PSW_N : 0)
	  | (c ? PSW_C : 0) | (v ? PSW_V : 0));
}

/* add imm32, an */
void OP_FCD00000 (insn, extension)
     unsigned long insn, extension;
{
  int z, c, n, v;
  unsigned long reg1, imm, value;

  reg1 = State.regs[REG_A0 + REG0_16 (insn)];
  imm = ((insn & 0xffff) << 16) + extension;
  value = reg1 + imm;
  State.regs[REG_A0 + REG0_16 (insn)] = value;

  z = (value == 0);
  n = (value & 0x80000000);
  c = (value < reg1) || (value < imm);
  v = ((reg1 & 0x80000000) == (imm & 0x80000000)
       && (reg1 & 0x80000000) != (value & 0x80000000));

  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | ( n ? PSW_N : 0)
	  | (c ? PSW_C : 0) | (v ? PSW_V : 0));
}

/* add imm8, sp */
void OP_F8FE00 (insn, extension)
     unsigned long insn, extension;
{
  unsigned long reg1, imm, value;

  reg1 = State.regs[REG_SP];
  imm = SEXT8 (insn & 0xff);
  value = reg1 + imm;
  State.regs[REG_SP] = value;
}

/* add imm16,sp */
void OP_FAFE0000 (insn, extension)
     unsigned long insn, extension;
{
  unsigned long reg1, imm, value;

  reg1 = State.regs[REG_SP];
  imm = SEXT16 (insn & 0xffff);
  value = reg1 + imm;
  State.regs[REG_SP] = value;
}

/* add imm32, sp */
void OP_FCFE0000 (insn, extension)
     unsigned long insn, extension;
{
  unsigned long reg1, imm, value;

  reg1 = State.regs[REG_SP];
  imm = ((insn & 0xffff) << 16) + extension;
  value = reg1 + imm;
  State.regs[REG_SP] = value;
}

/* addc dm,dn */
void OP_F140 (insn, extension)
     unsigned long insn, extension;
{
  int z, c, n, v;
  unsigned long reg1, reg2, value;

  reg1 = State.regs[REG_D0 + REG1 (insn)];
  reg2 = State.regs[REG_D0 + REG0 (insn)];
  value = reg1 + reg2 + ((PSW & PSW_C) != 0);
  State.regs[REG_D0 + REG0 (insn)] = value;

  z = (value == 0);
  n = (value & 0x80000000);
  c = (value < reg1) || (value < reg2);
  v = ((reg2 & 0x80000000) == (reg1 & 0x80000000)
       && (reg2 & 0x80000000) != (value & 0x80000000));

  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | ( n ? PSW_N : 0)
	  | (c ? PSW_C : 0) | (v ? PSW_V : 0));
}

/* sub dm, dn */
void OP_F100 (insn, extension)
     unsigned long insn, extension;
{
  int z, c, n, v;
  unsigned long reg1, reg2, value;

  reg1 = State.regs[REG_D0 + REG1 (insn)];
  reg2 = State.regs[REG_D0 + REG0 (insn)];
  value = reg2 - reg1;
  State.regs[REG_D0 + REG0 (insn)] = value;

  z = (value == 0);
  n = (value & 0x80000000);
  c = (reg1 > reg2);
  v = ((reg2 & 0x80000000) != (reg1 & 0x80000000)
       && (reg2 & 0x80000000) != (value & 0x80000000));

  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | ( n ? PSW_N : 0)
	  | (c ? PSW_C : 0) | (v ? PSW_V : 0));
}

/* sub dm, an */
void OP_F120 (insn, extension)
     unsigned long insn, extension;
{
  int z, c, n, v;
  unsigned long reg1, reg2, value;

  reg1 = State.regs[REG_D0 + REG1 (insn)];
  reg2 = State.regs[REG_A0 + REG0 (insn)];
  value = reg2 - reg1;
  State.regs[REG_A0 + REG0 (insn)] = value;

  z = (value == 0);
  n = (value & 0x80000000);
  c = (reg1 > reg2);
  v = ((reg2 & 0x80000000) != (reg1 & 0x80000000)
       && (reg2 & 0x80000000) != (value & 0x80000000));

  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | ( n ? PSW_N : 0)
	  | (c ? PSW_C : 0) | (v ? PSW_V : 0));
}

/* sub am, dn */
void OP_F110 (insn, extension)
     unsigned long insn, extension;
{
  int z, c, n, v;
  unsigned long reg1, reg2, value;

  reg1 = State.regs[REG_A0 + REG1 (insn)];
  reg2 = State.regs[REG_D0 + REG0 (insn)];
  value = reg2 - reg1;
  State.regs[REG_D0 + REG0 (insn)] = value;

  z = (value == 0);
  n = (value & 0x80000000);
  c = (reg1 > reg2);
  v = ((reg2 & 0x80000000) != (reg1 & 0x80000000)
       && (reg2 & 0x80000000) != (value & 0x80000000));

  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | ( n ? PSW_N : 0)
	  | (c ? PSW_C : 0) | (v ? PSW_V : 0));
}

/* sub am, an */
void OP_F130 (insn, extension)
     unsigned long insn, extension;
{
  int z, c, n, v;
  unsigned long reg1, reg2, value;

  reg1 = State.regs[REG_A0 + REG1 (insn)];
  reg2 = State.regs[REG_A0 + REG0 (insn)];
  value = reg2 - reg1;
  State.regs[REG_A0 + REG0 (insn)] = value;

  z = (value == 0);
  n = (value & 0x80000000);
  c = (reg1 > reg2);
  v = ((reg2 & 0x80000000) != (reg1 & 0x80000000)
       && (reg2 & 0x80000000) != (value & 0x80000000));

  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | ( n ? PSW_N : 0)
	  | (c ? PSW_C : 0) | (v ? PSW_V : 0));
}

/* sub imm32, dn */
void OP_FCC40000 (insn, extension)
     unsigned long insn, extension;
{
  int z, c, n, v;
  unsigned long reg1, imm, value;

  reg1 = State.regs[REG_D0 + REG0_16 (insn)];
  imm = ((insn & 0xffff) << 16) + extension;
  value = reg1 - imm;
  State.regs[REG_D0 + REG0_16 (insn)] = value;

  z = (value == 0);
  n = (value & 0x80000000);
  c = (reg1 < imm);
  v = ((reg1 & 0x80000000) != (imm & 0x80000000)
       && (reg1 & 0x80000000) != (value & 0x80000000));

  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | ( n ? PSW_N : 0)
	  | (c ? PSW_C : 0) | (v ? PSW_V : 0));
}

/* sub imm32, an */
void OP_FCD40000 (insn, extension)
     unsigned long insn, extension;
{
  int z, c, n, v;
  unsigned long reg1, imm, value;

  reg1 = State.regs[REG_A0 + REG0_16 (insn)];
  imm = ((insn & 0xffff) << 16) + extension;
  value = reg1 - imm;
  State.regs[REG_A0 + REG0_16 (insn)] = value;

  z = (value == 0);
  n = (value & 0x80000000);
  c = (reg1 < imm);
  v = ((reg1 & 0x80000000) != (imm & 0x80000000)
       && (reg1 & 0x80000000) != (value & 0x80000000));

  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | ( n ? PSW_N : 0)
	  | (c ? PSW_C : 0) | (v ? PSW_V : 0));
}

/* subc dm, dn */
void OP_F180 (insn, extension)
     unsigned long insn, extension;
{
  int z, c, n, v;
  unsigned long reg1, reg2, value;

  reg1 = State.regs[REG_D0 + REG1 (insn)];
  reg2 = State.regs[REG_D0 + REG0 (insn)];
  value = reg2 - reg1 - ((PSW & PSW_C) != 0);
  State.regs[REG_D0 + REG0 (insn)] = value;

  z = (value == 0);
  n = (value & 0x80000000);
  c = (reg1 > reg2);
  v = ((reg2 & 0x80000000) != (reg1 & 0x80000000)
       && (reg2 & 0x80000000) != (value & 0x80000000));

  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | ( n ? PSW_N : 0)
	  | (c ? PSW_C : 0) | (v ? PSW_V : 0));
}

/* mul dm, dn */
void OP_F240 (insn, extension)
     unsigned long insn, extension;
{
  unsigned long long temp;
  int n, z;

  temp = ((signed long)State.regs[REG_D0 + REG0 (insn)]
          *  (signed long)State.regs[REG_D0 + REG1 (insn)]);
  State.regs[REG_D0 + REG0 (insn)] = temp & 0xffffffff;
  State.regs[REG_MDR] = (temp & 0xffffffff00000000LL) >> 32;;
  z = (State.regs[REG_D0 + REG0 (insn)] == 0);
  n = (State.regs[REG_D0 + REG0 (insn)] & 0x80000000) != 0;
  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | (n ? PSW_N : 0));
}

/* mulu dm, dn */
void OP_F250 (insn, extension)
     unsigned long insn, extension;
{
  unsigned long long temp;
  int n, z;

  temp = (State.regs[REG_D0 + REG0 (insn)]
          *  State.regs[REG_D0 + REG1 (insn)]);
  State.regs[REG_D0 + REG0 (insn)] = temp & 0xffffffff;
  State.regs[REG_MDR] = (temp & 0xffffffff00000000LL) >> 32;
  z = (State.regs[REG_D0 + REG0 (insn)] == 0);
  n = (State.regs[REG_D0 + REG0 (insn)] & 0x80000000) != 0;
  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | (n ? PSW_N : 0));
}

/* div dm, dn */
void OP_F260 (insn, extension)
     unsigned long insn, extension;
{
  long long temp;
  int n, z;

  temp = State.regs[REG_MDR];
  temp <<= 32;
  temp |= State.regs[REG_D0 + REG0 (insn)];
  State.regs[REG_MDR] = temp % (long)State.regs[REG_D0 + REG1 (insn)];
  temp /= (long)State.regs[REG_D0 + REG1 (insn)];
  State.regs[REG_D0 + REG0 (insn)] = temp & 0xffffffff;
  z = (State.regs[REG_D0 + REG0 (insn)] == 0);
  n = (State.regs[REG_D0 + REG0 (insn)] & 0x80000000) != 0;
  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | (n ? PSW_N : 0));
}

/* divu dm, dn */
void OP_F270 (insn, extension)
     unsigned long insn, extension;
{
  unsigned long long temp;
  int n, z;

  temp = State.regs[REG_MDR];
  temp <<= 32;
  temp |= State.regs[REG_D0 + REG0 (insn)];
  State.regs[REG_MDR] = temp % State.regs[REG_D0 + REG1 (insn)];
  temp /= State.regs[REG_D0 + REG1 (insn)];
  State.regs[REG_D0 + REG0 (insn)] = temp & 0xffffffff;
  z = (State.regs[REG_D0 + REG0 (insn)] == 0);
  n = (State.regs[REG_D0 + REG0 (insn)] & 0x80000000) != 0;
  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | (n ? PSW_N : 0));
}

/* inc dn */
void OP_40 (insn, extension)
     unsigned long insn, extension;
{
  int z,n,c,v;
  unsigned int value, imm, reg1;

  reg1 = State.regs[REG_D0 + REG1 (insn)];
  imm = 1;
  value = reg1 + imm;
  State.regs[REG_D0 + REG1 (insn)] = value;

  z = (value == 0);
  n = (value & 0x80000000);
  c = (reg1 < imm);
  v = ((reg1 & 0x80000000) == (imm & 0x80000000)
       && (reg1 & 0x80000000) != (value & 0x80000000));

  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | ( n ? PSW_N : 0)
	  | (c ? PSW_C : 0) | (v ? PSW_V : 0));
}

/* inc an */
void OP_41 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_A0 + REG1 (insn)] += 1;
}

/* inc4 an */
void OP_50 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_A0 + REG0 (insn)] += 4;
}

/* cmp imm8, dn */
void OP_A000 (insn, extension)
     unsigned long insn, extension;
{
  int z, c, n, v;
  unsigned long reg1, imm, value;

  reg1 = State.regs[REG_D0 + REG0_8 (insn)];
  imm = SEXT8 (insn & 0xff);
  value = reg1 - imm;

  z = (value == 0);
  n = (value & 0x80000000);
  c = (reg1 < imm);
  v = ((reg1 & 0x80000000) != (imm & 0x80000000)
       && (reg1 & 0x80000000) != (value & 0x80000000));

  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | ( n ? PSW_N : 0)
	  | (c ? PSW_C : 0) | (v ? PSW_V : 0));
}

/* cmp dm, dn */
void OP_A0 (insn, extension)
     unsigned long insn, extension;
{
  int z, c, n, v;
  unsigned long reg1, reg2, value;

  reg1 = State.regs[REG_D0 + REG1 (insn)];
  reg2 = State.regs[REG_D0 + REG0 (insn)];
  value = reg2 - reg1;

  z = (value == 0);
  n = (value & 0x80000000);
  c = (reg1 > reg2);
  v = ((reg2 & 0x80000000) != (reg1 & 0x80000000)
       && (reg2 & 0x80000000) != (value & 0x80000000));

  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | ( n ? PSW_N : 0)
	  | (c ? PSW_C : 0) | (v ? PSW_V : 0));
}

/* cmp dm, an */
void OP_F1A0 (insn, extension)
     unsigned long insn, extension;
{
  int z, c, n, v;
  unsigned long reg1, reg2, value;

  reg1 = State.regs[REG_D0 + REG1 (insn)];
  reg2 = State.regs[REG_A0 + REG0 (insn)];
  value = reg2 - reg1;

  z = (value == 0);
  n = (value & 0x80000000);
  c = (reg1 > reg2);
  v = ((reg2 & 0x80000000) != (reg1 & 0x80000000)
       && (reg2 & 0x80000000) != (value & 0x80000000));

  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | ( n ? PSW_N : 0)
	  | (c ? PSW_C : 0) | (v ? PSW_V : 0));
}

/* cmp am, dn */
void OP_F190 (insn, extension)
     unsigned long insn, extension;
{
  int z, c, n, v;
  unsigned long reg1, reg2, value;

  reg1 = State.regs[REG_A0 + REG1 (insn)];
  reg2 = State.regs[REG_D0 + REG0 (insn)];
  value = reg2 - reg1;

  z = (value == 0);
  n = (value & 0x80000000);
  c = (reg1 > reg2);
  v = ((reg2 & 0x80000000) != (reg1 & 0x80000000)
       && (reg2 & 0x80000000) != (value & 0x80000000));

  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | ( n ? PSW_N : 0)
	  | (c ? PSW_C : 0) | (v ? PSW_V : 0));
}

/* cmp imm8, an */
void OP_B000 (insn, extension)
     unsigned long insn, extension;
{
  int z, c, n, v;
  unsigned long reg1, imm, value;

  reg1 = State.regs[REG_A0 + REG0_8 (insn)];
  imm = insn & 0xff;
  value = reg1 - imm;

  z = (value == 0);
  n = (value & 0x80000000);
  c = (reg1 < imm);
  v = ((reg1 & 0x80000000) != (imm & 0x80000000)
       && (reg1 & 0x80000000) != (value & 0x80000000));

  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | ( n ? PSW_N : 0)
	  | (c ? PSW_C : 0) | (v ? PSW_V : 0));
}

/* cmp am, an */
void OP_B0 (insn, extension)
     unsigned long insn, extension;
{
  int z, c, n, v;
  unsigned long reg1, reg2, value;

  reg1 = State.regs[REG_A0 + REG1 (insn)];
  reg2 = State.regs[REG_A0 + REG0 (insn)];
  value = reg2 - reg1;

  z = (value == 0);
  n = (value & 0x80000000);
  c = (reg1 > reg2);
  v = ((reg2 & 0x80000000) != (reg1 & 0x80000000)
       && (reg2 & 0x80000000) != (value & 0x80000000));

  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | ( n ? PSW_N : 0)
	  | (c ? PSW_C : 0) | (v ? PSW_V : 0));
}

/* cmp imm16, dn */
void OP_FAC80000 (insn, extension)
     unsigned long insn, extension;
{
  int z, c, n, v;
  unsigned long reg1, imm, value;

  reg1 = State.regs[REG_D0 + REG0_16 (insn)];
  imm = SEXT16 (insn & 0xffff);
  value = reg1 - imm;

  z = (value == 0);
  n = (value & 0x80000000);
  c = (reg1 < imm);
  v = ((reg1 & 0x80000000) != (imm & 0x80000000)
       && (reg1 & 0x80000000) != (value & 0x80000000));

  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | ( n ? PSW_N : 0)
	  | (c ? PSW_C : 0) | (v ? PSW_V : 0));
}

/* cmp imm32, dn */
void OP_FCC80000 (insn, extension)
     unsigned long insn, extension;
{
  int z, c, n, v;
  unsigned long reg1, imm, value;

  reg1 = State.regs[REG_D0 + REG0_16 (insn)];
  imm = ((insn & 0xffff) << 16) + extension;
  value = reg1 - imm;

  z = (value == 0);
  n = (value & 0x80000000);
  c = (reg1 < imm);
  v = ((reg1 & 0x80000000) != (imm & 0x80000000)
       && (reg1 & 0x80000000) != (value & 0x80000000));

  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | ( n ? PSW_N : 0)
	  | (c ? PSW_C : 0) | (v ? PSW_V : 0));
}

/* cmp imm16, an */
void OP_FAD80000 (insn, extension)
     unsigned long insn, extension;
{
  int z, c, n, v;
  unsigned long reg1, imm, value;

  reg1 = State.regs[REG_A0 + REG0_16 (insn)];
  imm = insn & 0xffff;
  value = reg1 - imm;

  z = (value == 0);
  n = (value & 0x80000000);
  c = (reg1 < imm);
  v = ((reg1 & 0x80000000) != (imm & 0x80000000)
       && (reg1 & 0x80000000) != (value & 0x80000000));

  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | ( n ? PSW_N : 0)
	  | (c ? PSW_C : 0) | (v ? PSW_V : 0));
}

/* cmp imm32, an */
void OP_FCD80000 (insn, extension)
     unsigned long insn, extension;
{
  int z, c, n, v;
  unsigned long reg1, imm, value;

  reg1 = State.regs[REG_A0 + REG0_16 (insn)];
  imm = ((insn & 0xffff) << 16) + extension;
  value = reg1 - imm;

  z = (value == 0);
  n = (value & 0x80000000);
  c = (reg1 < imm);
  v = ((reg1 & 0x80000000) != (imm & 0x80000000)
       && (reg1 & 0x80000000) != (value & 0x80000000));

  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | ( n ? PSW_N : 0)
	  | (c ? PSW_C : 0) | (v ? PSW_V : 0));
}

/* and dm, dn */
void OP_F200 (insn, extension)
     unsigned long insn, extension;
{
  int n, z;

  State.regs[REG_D0 + REG0 (insn)] &= State.regs[REG_D0 + REG1 (insn)];
  z = (State.regs[REG_D0 + REG0 (insn)] == 0);
  n = (State.regs[REG_D0 + REG0 (insn)] & 0x80000000) != 0;
  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | (n ? PSW_N : 0));
}

/* and imm8, dn */
void OP_F8E000 (insn, extension)
     unsigned long insn, extension;
{
  int n, z;

  State.regs[REG_D0 + REG0_8 (insn)] &= (insn & 0xff);
  z = (State.regs[REG_D0 + REG0_8 (insn)] == 0);
  n = (State.regs[REG_D0 + REG0_8 (insn)] & 0x80000000) != 0;
  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | (n ? PSW_N : 0));
}

/* and imm16, dn */
void OP_FAE00000 (insn, extension)
     unsigned long insn, extension;
{
  int n, z;

  State.regs[REG_D0 + REG0_16 (insn)] &= (insn & 0xffff);
  z = (State.regs[REG_D0 + REG0_16 (insn)] == 0);
  n = (State.regs[REG_D0 + REG0_16 (insn)] & 0x80000000) != 0;
  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | (n ? PSW_N : 0));
}

/* and imm32, dn */
void OP_FCE00000 (insn, extension)
     unsigned long insn, extension;
{
  int n, z;

  State.regs[REG_D0 + REG0_16 (insn)]
    &= ((insn & 0xffff) << 16) + extension;
  z = (State.regs[REG_D0 + REG0_16 (insn)] == 0);
  n = (State.regs[REG_D0 + REG0_16 (insn)] & 0x80000000) != 0;
  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | (n ? PSW_N : 0));
}

/* and imm16, psw */
void OP_FAFC0000 (insn, extension)
     unsigned long insn, extension;
{
  PSW &= (insn & 0xffff);
}

/* or dm, dn*/
void OP_F210 (insn, extension)
     unsigned long insn, extension;
{
  int n, z;

  State.regs[REG_D0 + REG0 (insn)] |= State.regs[REG_D0 + REG1 (insn)];
  z = (State.regs[REG_D0 + REG0 (insn)] == 0);
  n = (State.regs[REG_D0 + REG0 (insn)] & 0x80000000) != 0;
  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | (n ? PSW_N : 0));
}

/* or imm8, dn */
void OP_F8E400 (insn, extension)
     unsigned long insn, extension;
{
  int n, z;

  State.regs[REG_D0 + REG0_8 (insn)] |= insn & 0xff;
  z = (State.regs[REG_D0 + REG0_8 (insn)] == 0);
  n = (State.regs[REG_D0 + REG0_8 (insn)] & 0x80000000) != 0;
  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | (n ? PSW_N : 0));
}

/* or imm16, dn*/
void OP_FAE40000 (insn, extension)
     unsigned long insn, extension;
{
  int n, z;

  State.regs[REG_D0 + REG0_16 (insn)] |= insn & 0xffff;
  z = (State.regs[REG_D0 + REG0_16 (insn)] == 0);
  n = (State.regs[REG_D0 + REG0_16 (insn)] & 0x80000000) != 0;
  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | (n ? PSW_N : 0));
}

/* or imm32, dn */
void OP_FCE40000 (insn, extension)
     unsigned long insn, extension;
{
  int n, z;

  State.regs[REG_D0 + REG0_16 (insn)]
    |= ((insn & 0xffff) << 16) + extension;
  z = (State.regs[REG_D0 + REG0_16 (insn)] == 0);
  n = (State.regs[REG_D0 + REG0_16 (insn)] & 0x80000000) != 0;
  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | (n ? PSW_N : 0));
}

/* or imm16,psw */
void OP_FAFD0000 (insn, extension)
     unsigned long insn, extension;
{
  PSW |= (insn & 0xffff);
}

/* xor dm, dn */
void OP_F220 (insn, extension)
     unsigned long insn, extension;
{
  int n, z;

  State.regs[REG_D0 + REG0 (insn)] ^= State.regs[REG_D0 + REG1 (insn)];
  z = (State.regs[REG_D0 + REG0 (insn)] == 0);
  n = (State.regs[REG_D0 + REG0 (insn)] & 0x80000000) != 0;
  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | (n ? PSW_N : 0));
}

/* xor imm16, dn */
void OP_FAE80000 (insn, extension)
     unsigned long insn, extension;
{
  int n, z;

  State.regs[REG_D0 + REG0_16 (insn)] ^= insn & 0xffff;
  z = (State.regs[REG_D0 + REG0_16 (insn)] == 0);
  n = (State.regs[REG_D0 + REG0_16 (insn)] & 0x80000000) != 0;
  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | (n ? PSW_N : 0));
}

/* xor imm32, dn */
void OP_FCE80000 (insn, extension)
     unsigned long insn, extension;
{
  int n, z;

  State.regs[REG_D0 + REG0_16 (insn)]
    ^= ((insn & 0xffff) << 16) + extension;
  z = (State.regs[REG_D0 + REG0_16 (insn)] == 0);
  n = (State.regs[REG_D0 + REG0_16 (insn)] & 0x80000000) != 0;
  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | (n ? PSW_N : 0));
}

/* not dn */
void OP_F230 (insn, extension)
     unsigned long insn, extension;
{
  int n, z;

  State.regs[REG_D0 + REG0 (insn)] = ~State.regs[REG_D0 + REG0 (insn)];
  z = (State.regs[REG_D0 + REG0 (insn)] == 0);
  n = (State.regs[REG_D0 + REG0 (insn)] & 0x80000000) != 0;
  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | (n ? PSW_N : 0));
}

/* btst imm8, dn */
void OP_F8EC00 (insn, extension)
     unsigned long insn, extension;
{
  unsigned long temp;
  int z, n;

  temp = State.regs[REG_D0 + REG0_8 (insn)];
  temp &= (insn & 0xff);
  n = (temp & 0x80000000) != 0;
  z = (temp == 0);
  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= (z ? PSW_Z : 0) | (n ? PSW_N : 0);
}

/* btst imm16, dn */
void OP_FAEC0000 (insn, extension)
     unsigned long insn, extension;
{
  unsigned long temp;
  int z, n;

  temp = State.regs[REG_D0 + REG0_16 (insn)];
  temp &= (insn & 0xffff);
  n = (temp & 0x80000000) != 0;
  z = (temp == 0);
  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= (z ? PSW_Z : 0) | (n ? PSW_N : 0);
}

/* btst imm32, dn */
void OP_FCEC0000 (insn, extension)
     unsigned long insn, extension;
{
  unsigned long temp;
  int z, n;

  temp = State.regs[REG_D0 + REG0_16 (insn)];
  temp &= ((insn & 0xffff) << 16) + extension;
  n = (temp & 0x80000000) != 0;
  z = (temp == 0);
  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= (z ? PSW_Z : 0) | (n ? PSW_N : 0);
}

/* btst imm8,(abs32) */
void OP_FE020000 (insn, extension)
     unsigned long insn, extension;
{
  unsigned long temp;
  int n, z;

  temp = load_byte (((insn & 0xffff) << 16) | (extension >> 8));
  temp &= (extension & 0xff);
  n = (temp & 0x80000000) != 0;
  z = (temp == 0);
  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= (z ? PSW_Z : 0) | (n ? PSW_N : 0);
}

/* btst imm8,(d8,an) */
void OP_FAF80000 (insn, extension)
     unsigned long insn, extension;
{
  unsigned long temp;
  int n, z;

  temp = load_byte ((State.regs[REG_A0 + REG0_16 (insn)]
                     + SEXT8 ((insn & 0xff00) >> 8)));
  temp &= (insn & 0xff);
  n = (temp & 0x80000000) != 0;
  z = (temp == 0);
  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= (z ? PSW_Z : 0) | (n ? PSW_N : 0);
}

/* bset dm, (an) */
void OP_F080 (insn, extension)
     unsigned long insn, extension;
{
  unsigned long temp;
  int z;

  temp = load_byte (State.regs[REG_A0 + REG0 (insn)]);
  z = (temp & State.regs[REG_D0 + REG1 (insn)]) == 0;
  temp |= State.regs[REG_D0 + REG1 (insn)];
  store_byte (State.regs[REG_A0 + REG0 (insn)], temp);
  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= (z ? PSW_Z : 0);
}

/* bset imm8, (abs32) */
void OP_FE000000 (insn, extension)
     unsigned long insn, extension;
{
  unsigned long temp;
  int z;

  temp = load_byte (((insn & 0xffff) << 16 | (extension >> 8)));
  z = (temp & (extension & 0xff)) == 0;
  temp |= (extension & 0xff);
  store_byte ((((insn & 0xffff) << 16) | (extension >> 8)), temp);
  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= (z ? PSW_Z : 0);
}

/* bset imm8,(d8,an) */
void OP_FAF00000 (insn, extension)
     unsigned long insn, extension;
{
  unsigned long temp;
  int z;

  temp = load_byte ((State.regs[REG_A0 + REG0_16 (insn)]
                     + SEXT8 ((insn & 0xff00) >> 8)));
  z = (temp & (insn & 0xff)) == 0;
  temp |= (insn & 0xff);
  store_byte ((State.regs[REG_A0 + REG0_16 (insn)]
	       + SEXT8 ((insn & 0xff00) >> 8)), temp);
  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= (z ? PSW_Z : 0);
}

/* bclr dm, (an) */
void OP_F090 (insn, extension)
     unsigned long insn, extension;
{
  unsigned long temp;
  int z;

  temp = load_byte (State.regs[REG_A0 + REG0 (insn)]);
  z = (temp & State.regs[REG_D0 + REG1 (insn)]) == 0;
  temp = temp & ~State.regs[REG_D0 + REG1 (insn)];
  store_byte (State.regs[REG_A0 + REG0 (insn)], temp);
  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= (z ? PSW_Z : 0);
}

/* bclr imm8, (abs32) */
void OP_FE010000 (insn, extension)
     unsigned long insn, extension;
{
  unsigned long temp;
  int z;

  temp = load_byte (((insn & 0xffff) << 16) | (extension >> 8));
  z = (temp & (extension & 0xff)) == 0;
  temp = temp & ~(extension & 0xff);
  store_byte (((insn & 0xffff) << 16) | (extension >> 8), temp);
  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= (z ? PSW_Z : 0);
}

/* bclr imm8,(d8,an) */
void OP_FAF40000 (insn, extension)
     unsigned long insn, extension;
{
  unsigned long temp;
  int z;

  temp = load_byte ((State.regs[REG_A0 + REG0_16 (insn)]
                     + SEXT8 ((insn & 0xff00) >> 8)));
  z = (temp & (insn & 0xff)) == 0;
  temp = temp & ~(insn & 0xff);
  store_byte ((State.regs[REG_A0 + REG0_16 (insn)]
	       + SEXT8 ((insn & 0xff00) >> 8)), temp);
  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= (z ? PSW_Z : 0);
}

/* asr dm, dn */
void OP_F2B0 (insn, extension)
     unsigned long insn, extension;
{
  long temp;
  int z, n, c;

  temp = State.regs[REG_D0 + REG0 (insn)];
  c = temp & 1;
  temp >>= State.regs[REG_D0 + REG1 (insn)];
  State.regs[REG_D0 + REG0 (insn)] = temp;
  z = (State.regs[REG_D0 + REG0 (insn)] == 0);
  n = (State.regs[REG_D0 + REG0 (insn)] & 0x80000000) != 0;
  PSW &= ~(PSW_Z | PSW_N | PSW_C);
  PSW |= ((z ? PSW_Z : 0) | (n ? PSW_N : 0) | (c ? PSW_C : 0));
}

/* asr imm8, dn */
void OP_F8C800 (insn, extension)
     unsigned long insn, extension;
{
  long temp;
  int z, n, c;

  temp = State.regs[REG_D0 + REG0_8 (insn)];
  c = temp & 1;
  temp >>= (insn & 0xff);
  State.regs[REG_D0 + REG0_8 (insn)] = temp;
  z = (State.regs[REG_D0 + REG0_8 (insn)] == 0);
  n = (State.regs[REG_D0 + REG0_8 (insn)] & 0x80000000) != 0;
  PSW &= ~(PSW_Z | PSW_N | PSW_C);
  PSW |= ((z ? PSW_Z : 0) | (n ? PSW_N : 0) | (c ? PSW_C : 0));
}

/* lsr dm, dn */
void OP_F2A0 (insn, extension)
     unsigned long insn, extension;
{
  int z, n, c;

  c = State.regs[REG_D0 + REG0 (insn)] & 1;
  State.regs[REG_D0 + REG0 (insn)]
    >>= State.regs[REG_D0 + REG1 (insn)];
  z = (State.regs[REG_D0 + REG0 (insn)] == 0);
  n = (State.regs[REG_D0 + REG0 (insn)] & 0x80000000) != 0;
  PSW &= ~(PSW_Z | PSW_N | PSW_C);
  PSW |= ((z ? PSW_Z : 0) | (n ? PSW_N : 0) | (c ? PSW_C : 0));
}

/* lsr imm8, dn */
void OP_F8C400 (insn, extension)
     unsigned long insn, extension;
{
  int z, n, c;

  c = State.regs[REG_D0 + REG0_8 (insn)] & 1;
  State.regs[REG_D0 + REG0_8 (insn)] >>=  (insn & 0xff);
  z = (State.regs[REG_D0 + REG0_8 (insn)] == 0);
  n = (State.regs[REG_D0 + REG0_8 (insn)] & 0x80000000) != 0;
  PSW &= ~(PSW_Z | PSW_N | PSW_C);
  PSW |= ((z ? PSW_Z : 0) | (n ? PSW_N : 0) | (c ? PSW_C : 0));
}

/* asl dm, dn */
void OP_F290 (insn, extension)
     unsigned long insn, extension;
{
  int n, z;

  State.regs[REG_D0 + REG0 (insn)]
    <<= State.regs[REG_D0 + REG1 (insn)];
  z = (State.regs[REG_D0 + REG0 (insn)] == 0);
  n = (State.regs[REG_D0 + REG0 (insn)] & 0x80000000) != 0;
  PSW &= ~(PSW_Z | PSW_N);
  PSW |= ((z ? PSW_Z : 0) | (n ? PSW_N : 0));
}

/* asl imm8, dn */
void OP_F8C000 (insn, extension)
     unsigned long insn, extension;
{
  int n, z;

  State.regs[REG_D0 + REG0_8 (insn)] <<= (insn & 0xff);
  z = (State.regs[REG_D0 + REG0_8 (insn)] == 0);
  n = (State.regs[REG_D0 + REG0_8 (insn)] & 0x80000000) != 0;
  PSW &= ~(PSW_Z | PSW_N);
  PSW |= ((z ? PSW_Z : 0) | (n ? PSW_N : 0));
}

/* asl2 dn */
void OP_54 (insn, extension)
     unsigned long insn, extension;
{
  int n, z;

  State.regs[REG_D0 + REG0 (insn)] <<= 2;
  z = (State.regs[REG_D0 + REG0 (insn)] == 0);
  n = (State.regs[REG_D0 + REG0 (insn)] & 0x80000000) != 0;
  PSW &= ~(PSW_Z | PSW_N);
  PSW |= ((z ? PSW_Z : 0) | (n ? PSW_N : 0));
}

/* ror dn */
void OP_F284 (insn, extension)
     unsigned long insn, extension;
{
  unsigned long value;
  int c,n,z;

  value = State.regs[REG_D0 + REG0 (insn)];
  c = (value & 0x1);

  value >>= 1;
  value |= ((PSW & PSW_C) != 0) ? 0x80000000 : 0;
  State.regs[REG_D0 + REG0 (insn)] = value;
  z = (value == 0);
  n = (value & 0x80000000) != 0;
  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | (n ? PSW_N : 0) | (c ? PSW_C : 0));
}

/* rol dn */
void OP_F280 (insn, extension)
     unsigned long insn, extension;
{
  unsigned long value;
  int c,n,z;

  value = State.regs[REG_D0 + REG0 (insn)];
  c = (value & 0x80000000) ? 1 : 0;

  value <<= 1;
  value |= ((PSW & PSW_C) != 0);
  State.regs[REG_D0 + REG0 (insn)] = value;
  z = (value == 0);
  n = (value & 0x80000000) != 0;
  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | (n ? PSW_N : 0) | (c ? PSW_C : 0));
}

/* beq label:8 */
void OP_C800 (insn, extension)
     unsigned long insn, extension;
{
  /* The dispatching code will add 2 after we return, so
     we subtract two here to make things right.  */
  if (PSW & PSW_Z)
    State.regs[REG_PC] += SEXT8 (insn & 0xff) - 2;
}

/* bne label:8 */
void OP_C900 (insn, extension)
     unsigned long insn, extension;
{
  /* The dispatching code will add 2 after we return, so
     we subtract two here to make things right.  */
  if (!(PSW & PSW_Z))
    State.regs[REG_PC] += SEXT8 (insn & 0xff) - 2;
}

/* bgt label:8 */
void OP_C100 (insn, extension)
     unsigned long insn, extension;
{
  /* The dispatching code will add 2 after we return, so
     we subtract two here to make things right.  */
  if (!((PSW & PSW_Z)
        || (((PSW & PSW_N) != 0) ^ ((PSW & PSW_V) != 0))))
    State.regs[REG_PC] += SEXT8 (insn & 0xff) - 2;
}

/* bge label:8 */
void OP_C200 (insn, extension)
     unsigned long insn, extension;
{
  /* The dispatching code will add 2 after we return, so
     we subtract two here to make things right.  */
  if (!(((PSW & PSW_N) != 0) ^ ((PSW & PSW_V) != 0)))
    State.regs[REG_PC] += SEXT8 (insn & 0xff) - 2;
}

/* ble label:8 */
void OP_C300 (insn, extension)
     unsigned long insn, extension;
{
  /* The dispatching code will add 2 after we return, so
     we subtract two here to make things right.  */
  if ((PSW & PSW_Z)
       || (((PSW & PSW_N) != 0) ^ ((PSW & PSW_V) != 0)))
    State.regs[REG_PC] += SEXT8 (insn & 0xff) - 2;
}

/* blt label:8 */
void OP_C000 (insn, extension)
     unsigned long insn, extension;
{
  /* The dispatching code will add 2 after we return, so
     we subtract two here to make things right.  */
  if (((PSW & PSW_N) != 0) ^ ((PSW & PSW_V) != 0))
    State.regs[REG_PC] += SEXT8 (insn & 0xff) - 2;
}

/* bhi label:8 */
void OP_C500 (insn, extension)
     unsigned long insn, extension;
{
  /* The dispatching code will add 2 after we return, so
     we subtract two here to make things right.  */
  if (!(((PSW & PSW_C) != 0) || (PSW & PSW_Z) != 0))
    State.regs[REG_PC] += SEXT8 (insn & 0xff) - 2;
}

/* bcc label:8 */
void OP_C600 (insn, extension)
     unsigned long insn, extension;
{
  /* The dispatching code will add 2 after we return, so
     we subtract two here to make things right.  */
  if (!(PSW & PSW_C))
    State.regs[REG_PC] += SEXT8 (insn & 0xff) - 2;
}

/* bls label:8 */
void OP_C700 (insn, extension)
     unsigned long insn, extension;
{
  /* The dispatching code will add 2 after we return, so
     we subtract two here to make things right.  */
  if (((PSW & PSW_C) != 0) || (PSW & PSW_Z) != 0)
    State.regs[REG_PC] += SEXT8 (insn & 0xff) - 2;
}

/* bcs label:8 */
void OP_C400 (insn, extension)
     unsigned long insn, extension;
{
  /* The dispatching code will add 2 after we return, so
     we subtract two here to make things right.  */
  if (PSW & PSW_C)
    State.regs[REG_PC] += SEXT8 (insn & 0xff) - 2;
}

/* bvc label:8 */
void OP_F8E800 (insn, extension)
     unsigned long insn, extension;
{
  /* The dispatching code will add 3 after we return, so
     we subtract two here to make things right.  */
  if (!(PSW & PSW_V))
    State.regs[REG_PC] += SEXT8 (insn & 0xff) - 3;
}

/* bvs label:8 */
void OP_F8E900 (insn, extension)
     unsigned long insn, extension;
{
  /* The dispatching code will add 3 after we return, so
     we subtract two here to make things right.  */
  if (PSW & PSW_V)
    State.regs[REG_PC] += SEXT8 (insn & 0xff) - 3;
}

/* bnc label:8 */
void OP_F8EA00 (insn, extension)
     unsigned long insn, extension;
{
  /* The dispatching code will add 3 after we return, so
     we subtract two here to make things right.  */
  if (!(PSW & PSW_N))
    State.regs[REG_PC] += SEXT8 (insn & 0xff) - 3;
}

/* bns label:8 */
void OP_F8EB00 (insn, extension)
     unsigned long insn, extension;
{
  /* The dispatching code will add 3 after we return, so
     we subtract two here to make things right.  */
  if (PSW & PSW_N)
    State.regs[REG_PC] += SEXT8 (insn & 0xff) - 3;
}

/* bra label:8 */
void OP_CA00 (insn, extension)
     unsigned long insn, extension;
{
  /* The dispatching code will add 2 after we return, so
     we subtract two here to make things right.  */
  State.regs[REG_PC] += SEXT8 (insn & 0xff) - 2;
}

/* leq */
void OP_D8 (insn, extension)
     unsigned long insn, extension;
{
  /* The dispatching code will add 1 after we return, so
     we subtract one here to make things right.  */
  if (PSW & PSW_Z)
    State.regs[REG_PC] = State.regs[REG_LAR] - 4 - 1;
}

/* lne */
void OP_D9 (insn, extension)
     unsigned long insn, extension;
{
  /* The dispatching code will add 1 after we return, so
     we subtract one here to make things right.  */
  if (!(PSW & PSW_Z))
    State.regs[REG_PC] = State.regs[REG_LAR] - 4 - 1;
}

/* lgt */
void OP_D1 (insn, extension)
     unsigned long insn, extension;
{
  /* The dispatching code will add 1 after we return, so
     we subtract one here to make things right.  */
  if (!((PSW & PSW_Z)
        || (((PSW & PSW_N) != 0) ^ ((PSW & PSW_V) != 0))))
    State.regs[REG_PC] = State.regs[REG_LAR] - 4 - 1;
}

/* lge */
void OP_D2 (insn, extension)
     unsigned long insn, extension;
{
  /* The dispatching code will add 1 after we return, so
     we subtract one here to make things right.  */
  if (!(((PSW & PSW_N) != 0) ^ ((PSW & PSW_V) != 0)))
    State.regs[REG_PC] = State.regs[REG_LAR] - 4 - 1;
}

/* lle */
void OP_D3 (insn, extension)
     unsigned long insn, extension;
{
  /* The dispatching code will add 1 after we return, so
     we subtract one here to make things right.  */
  if ((PSW & PSW_Z)
       || (((PSW & PSW_N) != 0) ^ ((PSW & PSW_V) != 0)))
    State.regs[REG_PC] = State.regs[REG_LAR] - 4 - 1;
}

/* llt */
void OP_D0 (insn, extension)
     unsigned long insn, extension;
{
  /* The dispatching code will add 1 after we return, so
     we subtract one here to make things right.  */
  if (((PSW & PSW_N) != 0) ^ ((PSW & PSW_V) != 0))
    State.regs[REG_PC] = State.regs[REG_LAR] - 4 - 1;
}

/* lhi */
void OP_D5 (insn, extension)
     unsigned long insn, extension;
{
  /* The dispatching code will add 1 after we return, so
     we subtract one here to make things right.  */
  if (!(((PSW & PSW_C) != 0) || (PSW & PSW_Z) != 0))
    State.regs[REG_PC] = State.regs[REG_LAR] - 4 - 1;
}

/* lcc */
void OP_D6 (insn, extension)
     unsigned long insn, extension;
{
  /* The dispatching code will add 1 after we return, so
     we subtract one here to make things right.  */
  if (!(PSW & PSW_C))
    State.regs[REG_PC] = State.regs[REG_LAR] - 4 - 1;
}

/* lls */
void OP_D7 (insn, extension)
     unsigned long insn, extension;
{
  /* The dispatching code will add 1 after we return, so
     we subtract one here to make things right.  */
  if (((PSW & PSW_C) != 0) || (PSW & PSW_Z) != 0)
    State.regs[REG_PC] = State.regs[REG_LAR] - 4 - 1;
}

/* lcs */
void OP_D4 (insn, extension)
     unsigned long insn, extension;
{
  /* The dispatching code will add 1 after we return, so
     we subtract one here to make things right.  */
  if (PSW & PSW_C)
    State.regs[REG_PC] = State.regs[REG_LAR] - 4 - 1;
}

/* lra */
void OP_DA (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_PC] = State.regs[REG_LAR] - 4 - 1;
}

/* setlb */
void OP_DB (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_LIR] = load_mem_big (State.regs[REG_PC] + 1, 4);
  State.regs[REG_LAR] = State.regs[REG_PC] + 5;
}

/* jmp (an) */
void OP_F0F4 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_PC] = State.regs[REG_A0 + REG0 (insn)] - 2;
}

/* jmp label:16 */
void OP_CC0000 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_PC] += SEXT16 (insn & 0xffff) - 3;
}

/* jmp label:32 */
void OP_DC000000 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_PC] += (((insn & 0xffffff) << 8) + extension) - 5;
}

/* call label:16,reg_list,imm8 */
void OP_CD000000 (insn, extension)
     unsigned long insn, extension;
{
  unsigned int next_pc, sp;
  unsigned long mask;

  sp = State.regs[REG_SP];
  next_pc = State.regs[REG_PC] + 5;
  State.mem[sp] = next_pc & 0xff;
  State.mem[sp+1] = (next_pc & 0xff00) >> 8;
  State.mem[sp+2] = (next_pc & 0xff0000) >> 16;
  State.mem[sp+3] = (next_pc & 0xff000000) >> 24;

  mask = insn & 0xff;

  if (mask & 0x80)
    {
      sp -= 4;
      store_word (sp, State.regs[REG_D0 + 2]);
    }

  if (mask & 0x40)
    {
      sp -= 4;
      store_word (sp, State.regs[REG_D0 + 3]);
    }

  if (mask & 0x20)
    {
      sp -= 4;
      store_word (sp, State.regs[REG_A0 + 2]);
    }

  if (mask & 0x10)
    {
      sp -= 4;
      store_word (sp, State.regs[REG_A0 + 3]);
    }

  if (mask & 0x8)
    {
      sp -= 4;
      store_word (sp, State.regs[REG_D0]);
      sp -= 4;
      store_word (sp, State.regs[REG_D0 + 1]);
      sp -= 4;
      store_word (sp, State.regs[REG_A0]);
      sp -= 4;
      store_word (sp, State.regs[REG_A0 + 1]);
      sp -= 4;
      store_word (sp, State.regs[REG_MDR]);
      sp -= 4;
      store_word (sp, State.regs[REG_LIR]);
      sp -= 4;
      store_word (sp, State.regs[REG_LAR]);
      sp -= 4;
    }

  /* Update the stack pointer, note that the register saves to do not
     modify SP.  The SP adjustment is derived totally from the imm8
     field.  */
  State.regs[REG_SP] -= extension;
  State.regs[REG_MDR] = next_pc;
  State.regs[REG_PC] += SEXT16 ((insn & 0xffff00) >> 8) - 5;
}

/* call label:32,reg_list,imm8*/
void OP_DD000000 (insn, extension)
     unsigned long insn, extension;
{
  unsigned int next_pc, sp, adjust;
  unsigned long mask;

  sp = State.regs[REG_SP];
  next_pc = State.regs[REG_PC] + 7;
  State.mem[sp] = next_pc & 0xff;
  State.mem[sp+1] = (next_pc & 0xff00) >> 8;
  State.mem[sp+2] = (next_pc & 0xff0000) >> 16;
  State.mem[sp+3] = (next_pc & 0xff000000) >> 24;

  mask = (extension & 0xff00) >> 8;

  if (mask & 0x80)
    {
      sp -= 4;
      store_word (sp, State.regs[REG_D0 + 2]);
    }

  if (mask & 0x40)
    {
      sp -= 4;
      store_word (sp, State.regs[REG_D0 + 3]);
    }

  if (mask & 0x20)
    {
      sp -= 4;
      store_word (sp, State.regs[REG_A0 + 2]);
    }

  if (mask & 0x10)
    {
      sp -= 4;
      store_word (sp, State.regs[REG_A0 + 3]);
    }

  if (mask & 0x8)
    {
      sp -= 4;
      store_word (sp, State.regs[REG_D0]);
      sp -= 4;
      store_word (sp, State.regs[REG_D0 + 1]);
      sp -= 4;
      store_word (sp, State.regs[REG_A0]);
      sp -= 4;
      store_word (sp, State.regs[REG_A0 + 1]);
      sp -= 4;
      store_word (sp, State.regs[REG_MDR]);
      sp -= 4;
      store_word (sp, State.regs[REG_LIR]);
      sp -= 4;
      store_word (sp, State.regs[REG_LAR]);
      sp -= 4;
    }

  /* Update the stack pointer, note that the register saves to do not
     modify SP.  The SP adjustment is derived totally from the imm8
     field.  */
  State.regs[REG_SP] -= (extension & 0xff);
  State.regs[REG_MDR] = next_pc;
  State.regs[REG_PC] += (((insn & 0xffffff) << 8) | ((extension & 0xff0000) >> 16)) - 7;
}

/* calls (an) */
void OP_F0F0 (insn, extension)
     unsigned long insn, extension;
{
  unsigned int next_pc, sp;

  sp = State.regs[REG_SP];
  next_pc = State.regs[REG_PC] + 2;
  State.mem[sp] = next_pc & 0xff;
  State.mem[sp+1] = (next_pc & 0xff00) >> 8;
  State.mem[sp+2] = (next_pc & 0xff0000) >> 16;
  State.mem[sp+3] = (next_pc & 0xff000000) >> 24;
  State.regs[REG_MDR] = next_pc;
  State.regs[REG_PC] = State.regs[REG_A0 + REG0 (insn)] - 2;
}

/* calls label:16 */
void OP_FAFF0000 (insn, extension)
     unsigned long insn, extension;
{
  unsigned int next_pc, sp;

  sp = State.regs[REG_SP];
  next_pc = State.regs[REG_PC] + 4;
  State.mem[sp] = next_pc & 0xff;
  State.mem[sp+1] = (next_pc & 0xff00) >> 8;
  State.mem[sp+2] = (next_pc & 0xff0000) >> 16;
  State.mem[sp+3] = (next_pc & 0xff000000) >> 24;
  State.regs[REG_MDR] = next_pc;
  State.regs[REG_PC] += SEXT16 (insn & 0xffff) - 4;
}

/* calls label:32 */
void OP_FCFF0000 (insn, extension)
     unsigned long insn, extension;
{
  unsigned int next_pc, sp;

  sp = State.regs[REG_SP];
  next_pc = State.regs[REG_PC] + 6;
  State.mem[sp] = next_pc & 0xff;
  State.mem[sp+1] = (next_pc & 0xff00) >> 8;
  State.mem[sp+2] = (next_pc & 0xff0000) >> 16;
  State.mem[sp+3] = (next_pc & 0xff000000) >> 24;
  State.regs[REG_MDR] = next_pc;
  State.regs[REG_PC] += (((insn & 0xffff) << 16) + extension) - 6;
}

/* ret reg_list, imm8 */
void OP_DF0000 (insn, extension)
     unsigned long insn, extension;
{
  unsigned int sp, offset;
  unsigned long mask;

  State.regs[REG_SP] += insn & 0xff;
  sp = State.regs[REG_SP];

  offset = -4;
  mask = (insn & 0xff00) >> 8;

  if (mask & 0x80)
    {
      State.regs[REG_D0 + 2] = load_word (sp + offset);
      offset -= 4;
    }

  if (mask & 0x40)
    {
      State.regs[REG_D0 + 3] = load_word (sp + offset);
      offset -= 4;
    }

  if (mask & 0x20)
    {
      State.regs[REG_A0 + 2] = load_word (sp + offset);
      offset -= 4;
    }

  if (mask & 0x10)
    {
      State.regs[REG_A0 + 3] = load_word (sp + offset);
      offset -= 4;
    }

  if (mask & 0x8)
    {
      State.regs[REG_D0] = load_word (sp + offset);
      offset -= 4;
      State.regs[REG_D0 + 1] = load_word (sp + offset);
      offset -= 4;
      State.regs[REG_A0] = load_word (sp + offset);
      offset -= 4;
      State.regs[REG_A0 + 1] = load_word (sp + offset);
      offset -= 4;
      State.regs[REG_MDR] = load_word (sp + offset);
      offset -= 4;
      State.regs[REG_LIR] = load_word (sp + offset);
      offset -= 4;
      State.regs[REG_LAR] = load_word (sp + offset);
      offset -= 4;
    }

  /* Restore the PC value.  */
  State.regs[REG_PC] = (State.mem[sp] | (State.mem[sp+1] << 8)
	      | (State.mem[sp+2] << 16) | (State.mem[sp+3] << 24));
  State.regs[REG_PC] -= 3;
}

/* retf reg_list,imm8 */
void OP_DE0000 (insn, extension)
     unsigned long insn, extension;
{
  unsigned int sp, offset;
  unsigned long mask;

  State.regs[REG_SP] += (insn & 0xff);
  sp = State.regs[REG_SP];
  State.regs[REG_PC] = State.regs[REG_MDR] - 3;

  offset = -4;
  mask = (insn & 0xff00) >> 8;

  if (mask & 0x80)
    {
      State.regs[REG_D0 + 2] = load_word (sp + offset);
      offset -= 4;
    }

  if (mask & 0x40)
    {
      State.regs[REG_D0 + 3] = load_word (sp + offset);
      offset -= 4;
    }

  if (mask & 0x20)
    {
      State.regs[REG_A0 + 2] = load_word (sp + offset);
      offset -= 4;
    }

  if (mask & 0x10)
    {
      State.regs[REG_A0 + 3] = load_word (sp + offset);
      offset -= 4;
    }

  if (mask & 0x8)
    {
      State.regs[REG_D0] = load_word (sp + offset);
      offset -= 4;
      State.regs[REG_D0 + 1] = load_word (sp + offset);
      offset -= 4;
      State.regs[REG_A0] = load_word (sp + offset);
      offset -= 4;
      State.regs[REG_A0 + 1] = load_word (sp + offset);
      offset -= 4;
      State.regs[REG_MDR] = load_word (sp + offset);
      offset -= 4;
      State.regs[REG_LIR] = load_word (sp + offset);
      offset -= 4;
      State.regs[REG_LAR] = load_word (sp + offset);
      offset -= 4;
    }
}

/* rets */
void OP_F0FC (insn, extension)
     unsigned long insn, extension;
{
  unsigned int sp;

  sp = State.regs[REG_SP];
  State.regs[REG_PC] = (State.mem[sp] | (State.mem[sp+1] << 8)
	      | (State.mem[sp+2] << 16) | (State.mem[sp+3] << 24));
  State.regs[REG_PC] -= 2;
}

/* rti */
void OP_F0FD (insn, extension)
     unsigned long insn, extension;
{
  unsigned int sp, next_pc;

  PSW = State.mem[sp] | (State.mem[sp + 1] << 8);
  State.regs[REG_PC] = (State.mem[sp+4] | (State.mem[sp+5] << 8)
	      | (State.mem[sp+6] << 16) | (State.mem[sp+7] << 24));
  State.regs[REG_SP] += 8;
}

/* trap */
void OP_F0FE (insn, extension)
     unsigned long insn, extension;
{
  unsigned int sp, next_pc;

  sp = State.regs[REG_SP];
  next_pc = State.regs[REG_PC] + 2;
  State.mem[sp] = next_pc & 0xff;
  State.mem[sp+1] = (next_pc & 0xff00) >> 8;
  State.mem[sp+2] = (next_pc & 0xff0000) >> 16;
  State.mem[sp+3] = (next_pc & 0xff000000) >> 24;
  State.regs[REG_PC] = 0x40000010 - 2;
}

/* syscall */
void OP_F020 (insn, extension)
     unsigned long insn, extension;
{
  /* We use this for simulated system calls; we may need to change
     it to a reserved instruction if we conflict with uses at
     Matsushita.  */
  int save_errno = errno;	
  errno = 0;

/* Registers passed to trap 0 */

/* Function number.  */
#define FUNC   (State.regs[0])

/* Parameters.  */
#define PARM1   (State.regs[1])
#define PARM2   (load_word (State.regs[REG_SP] + 12))
#define PARM3   (load_word (State.regs[REG_SP] + 16))

/* Registers set by trap 0 */

#define RETVAL State.regs[0]	/* return value */
#define RETERR State.regs[1]	/* return error code */

/* Turn a pointer in a register into a pointer into real memory. */

#define MEMPTR(x) (State.mem + x)

  switch (FUNC)
    {
#if !defined(__GO32__) && !defined(_WIN32)
      case SYS_fork:
      RETVAL = fork ();
      break;
    case SYS_execve:
      RETVAL = execve (MEMPTR (PARM1), (char **) MEMPTR (PARM2),
		       (char **)MEMPTR (PARM3));
      break;
#ifdef SYS_execv
    case SYS_execv:
      RETVAL = execve (MEMPTR (PARM1), (char **) MEMPTR (PARM2), NULL);
      break;
#endif
#endif

    case SYS_read:
      RETVAL = mn10300_callback->read (mn10300_callback, PARM1,
				    MEMPTR (PARM2), PARM3);
      break;
    case SYS_write:
      RETVAL = (int)mn10300_callback->write (mn10300_callback, PARM1,
					     MEMPTR (PARM2), PARM3);
      break;
    case SYS_lseek:
      RETVAL = mn10300_callback->lseek (mn10300_callback, PARM1, PARM2, PARM3);
      break;
    case SYS_close:
      RETVAL = mn10300_callback->close (mn10300_callback, PARM1);
      break;
    case SYS_open:
      RETVAL = mn10300_callback->open (mn10300_callback, MEMPTR (PARM1), PARM2);
      break;
    case SYS_exit:
      /* EXIT - caller can look in PARM1 to work out the 
	 reason */
      if (PARM1 == 0xdead)
	State.exception = SIGABRT;
      else
	State.exception = SIGQUIT;
      State.exited = 1;
      break;

    case SYS_stat:	/* added at hmsi */
      /* stat system call */
      {
	struct stat host_stat;
	reg_t buf;

	RETVAL = stat (MEMPTR (PARM1), &host_stat);
	
	buf = PARM2;

	/* Just wild-assed guesses.  */
	store_half (buf, host_stat.st_dev);
	store_half (buf + 2, host_stat.st_ino);
	store_word (buf + 4, host_stat.st_mode);
	store_half (buf + 8, host_stat.st_nlink);
	store_half (buf + 10, host_stat.st_uid);
	store_half (buf + 12, host_stat.st_gid);
	store_half (buf + 14, host_stat.st_rdev);
	store_word (buf + 16, host_stat.st_size);
	store_word (buf + 20, host_stat.st_atime);
	store_word (buf + 28, host_stat.st_mtime);
	store_word (buf + 36, host_stat.st_ctime);
      }
      break;

    case SYS_chown:
      RETVAL = chown (MEMPTR (PARM1), PARM2, PARM3);
      break;
    case SYS_chmod:
      RETVAL = chmod (MEMPTR (PARM1), PARM2);
      break;
#ifdef SYS_time
    case SYS_time:
      RETVAL = time ((void*) MEMPTR (PARM1));
      break;
#endif
#ifdef SYS_times
    case SYS_times:
      {
	struct tms tms;
	RETVAL = times (&tms);
	store_word (PARM1, tms.tms_utime);
	store_word (PARM1 + 4, tms.tms_stime);
	store_word (PARM1 + 8, tms.tms_cutime);
	store_word (PARM1 + 12, tms.tms_cstime);
	break;
      }
#endif
    case SYS_gettimeofday:
      {
	struct timeval t;
	struct timezone tz;
	RETVAL = gettimeofday (&t, &tz);
	store_word (PARM1, t.tv_sec);
	store_word (PARM1 + 4, t.tv_usec);
	store_word (PARM2, tz.tz_minuteswest);
	store_word (PARM2 + 4, tz.tz_dsttime);
	break;
      }
#ifdef SYS_utime
    case SYS_utime:
      /* Cast the second argument to void *, to avoid type mismatch
	 if a prototype is present.  */
      RETVAL = utime (MEMPTR (PARM1), (void *) MEMPTR (PARM2));
      break;
#endif
    default:
      abort ();
    }
  RETERR = errno;
  errno = save_errno;
}

/* rtm */
void OP_F0FF (insn, extension)
     unsigned long insn, extension;
{
 abort ();
}

/* nop */
void OP_CB (insn, extension)
     unsigned long insn, extension;
{
}

/* putx dm,dm */
void OP_F500 (insn, extension)
     unsigned long insn, extension;
{
  State.regs[REG_MDRQ] = State.regs[REG_D0 + REG0 (insn)];
}

/* getx dm,dm */
void OP_F6F0 (insn, extension)
     unsigned long insn, extension;
{
  int z, n;
  z = (State.regs[REG_MDRQ] == 0);
  n = ((State.regs[REG_MDRQ] & 0x80000000) != 0);
  State.regs[REG_D0 + REG0 (insn)] = State.regs[REG_MDRQ];

  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= (z ? PSW_Z : 0) | (n ? PSW_N : 0);
}

/* mulq dm,dn */
void OP_F600 (insn, extension)
     unsigned long insn, extension;
{
  unsigned long long temp;
  int n, z;

  temp = ((signed long)State.regs[REG_D0 + REG0 (insn)]
          *  (signed long)State.regs[REG_D0 + REG1 (insn)]);
  State.regs[REG_D0 + REG0 (insn)] = temp & 0xffffffff;
  State.regs[REG_MDRQ] = (temp & 0xffffffff00000000LL) >> 32;;
  z = (State.regs[REG_D0 + REG0 (insn)] == 0);
  n = (State.regs[REG_D0 + REG0 (insn)] & 0x80000000) != 0;
  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | (n ? PSW_N : 0));
}

/* mulq imm8,dn */
void OP_F90000 (insn, extension)
     unsigned long insn, extension;
{
  unsigned long long temp;
  int n, z;

  temp = ((signed long)State.regs[REG_D0 + REG0_8 (insn)]
          * (signed long)SEXT8 (insn & 0xff));
  State.regs[REG_D0 + REG0_8 (insn)] = temp & 0xffffffff;
  State.regs[REG_MDRQ] = (temp & 0xffffffff00000000LL) >> 32;;
  z = (State.regs[REG_D0 + REG0_8 (insn)] == 0);
  n = (State.regs[REG_D0 + REG0_8 (insn)] & 0x80000000) != 0;
  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | (n ? PSW_N : 0));
}

/* mulq imm16,dn */
void OP_FB000000 (insn, extension)
     unsigned long insn, extension;
{
  unsigned long long temp;
  int n, z;

  temp = ((signed long)State.regs[REG_D0 + REG0_16 (insn)]
          * (signed long)SEXT16 (insn & 0xffff));
  State.regs[REG_D0 + REG0_16 (insn)] = temp & 0xffffffff;
  State.regs[REG_MDRQ] = (temp & 0xffffffff00000000LL) >> 32;;
  z = (State.regs[REG_D0 + REG0_16 (insn)] == 0);
  n = (State.regs[REG_D0 + REG0_16 (insn)] & 0x80000000) != 0;
  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | (n ? PSW_N : 0));
}

/* mulq imm32,dn */
void OP_FD000000 (insn, extension)
     unsigned long insn, extension;
{
  unsigned long long temp;
  int n, z;

  temp = ((signed long)State.regs[REG_D0 + REG0_16 (insn)]
          * (signed long)(((insn & 0xffff) << 16) + extension));
  State.regs[REG_D0 + REG0_16 (insn)] = temp & 0xffffffff;
  State.regs[REG_MDRQ] = (temp & 0xffffffff00000000LL) >> 32;;
  z = (State.regs[REG_D0 + REG0_16 (insn)] == 0);
  n = (State.regs[REG_D0 + REG0_16 (insn)] & 0x80000000) != 0;
  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | (n ? PSW_N : 0));
}

/* mulqu dm,dn */
void OP_F610 (insn, extension)
     unsigned long insn, extension;
{
  unsigned long long temp;
  int n, z;

  temp = (State.regs[REG_D0 + REG0 (insn)] * State.regs[REG_D0 + REG1 (insn)]);
  State.regs[REG_D0 + REG0 (insn)] = temp & 0xffffffff;
  State.regs[REG_MDRQ] = (temp & 0xffffffff00000000LL) >> 32;;
  z = (State.regs[REG_D0 + REG0 (insn)] == 0);
  n = (State.regs[REG_D0 + REG0 (insn)] & 0x80000000) != 0;
  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | (n ? PSW_N : 0));
}

/* mulqu imm8,dn */
void OP_F91400 (insn, extension)
     unsigned long insn, extension;
{
  unsigned long long temp;
  int n, z;

  temp = (State.regs[REG_D0 + REG0_8 (insn)] * SEXT8 (insn & 0xff));
  State.regs[REG_D0 + REG0_8 (insn)] = temp & 0xffffffff;
  State.regs[REG_MDRQ] = (temp & 0xffffffff00000000LL) >> 32;;
  z = (State.regs[REG_D0 + REG0_8 (insn)] == 0);
  n = (State.regs[REG_D0 + REG0_8 (insn)] & 0x80000000) != 0;
  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | (n ? PSW_N : 0));
}

/* mulqu imm16,dn */
void OP_FB140000 (insn, extension)
     unsigned long insn, extension;
{
  unsigned long long temp;
  int n, z;

  temp = (State.regs[REG_D0 + REG0_16 (insn)] * SEXT16 (insn & 0xffff));
  State.regs[REG_D0 + REG0_16 (insn)] = temp & 0xffffffff;
  State.regs[REG_MDRQ] = (temp & 0xffffffff00000000LL) >> 32;;
  z = (State.regs[REG_D0 + REG0_16 (insn)] == 0);
  n = (State.regs[REG_D0 + REG0_16 (insn)] & 0x80000000) != 0;
  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | (n ? PSW_N : 0));
}

/* mulqu imm32,dn */
void OP_FD140000 (insn, extension)
     unsigned long insn, extension;
{
  unsigned long long temp;
  int n, z;

  temp = (State.regs[REG_D0 + REG0_16 (insn)]
          * (((insn & 0xffff) << 16) + extension));
  State.regs[REG_D0 + REG0_16 (insn)] = temp & 0xffffffff;
  State.regs[REG_MDRQ] = (temp & 0xffffffff00000000LL) >> 32;;
  z = (State.regs[REG_D0 + REG0_16 (insn)] == 0);
  n = (State.regs[REG_D0 + REG0_16 (insn)] & 0x80000000) != 0;
  PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V);
  PSW |= ((z ? PSW_Z : 0) | (n ? PSW_N : 0));
}

/* sat16 dm,dn */
void OP_F640 (insn, extension)
     unsigned long insn, extension;
{
  int temp;

  temp = State.regs[REG_D0 + REG1 (insn)];
  temp = (temp > 0x7fff ? 0x7fff : temp);
  temp = (temp < -0x8000 ? -0x8000 : temp);
  State.regs[REG_D0 + REG0 (insn)] = temp;
}

/* sat24 dm,dn */
void OP_F650 (insn, extension)
     unsigned long insn, extension;
{
  int temp;

  temp = State.regs[REG_D0 + REG1 (insn)];
  temp = (temp > 0x7fffff ? 0x7fffff : temp);
  temp = (temp < -0x800000 ? -0x800000 : temp);
  State.regs[REG_D0 + REG0 (insn)] = temp;
}

/* bsch dm,dn */
void OP_F670 (insn, extension)
     unsigned long insn, extension;
{
  int temp, c;

  temp = State.regs[REG_D0 + REG1 (insn)];
  temp <<= (State.regs[REG_D0 + REG0 (insn)] & 0x1f);
  c = (temp != 0 ? 1 : 0);
  PSW &= ~(PSW_C);
  PSW |= (c ? PSW_C : 0);
}

/* breakpoint */
void
OP_FF (insn, extension)
     unsigned long insn, extension;
{
  State.exception = SIGTRAP;
  PC -= 1;
}

