CCL Home Page
Up Directory CCL c50lib.c
/* =======================================================================
   C50LIB.C - Library of routines for building TMS320C50 simulators
   Copyright (C) 1996 Will Ware

   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
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

   ======================================================================= */

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "c50lib.h"

/* ======================================================================= */
/*                           #define statements                            */
/* ======================================================================= */

#ifndef QUASISTATIC
#define QUASISTATIC static
#endif

#define NUM_OPCODES  (sizeof(opcodes) / sizeof(opcodes[0]))
#define read_bit(var, bit)    ((int) (((var) >> (bit)) & 1))
#define set_bit(var, flag, bit)  \
    var = (var & ~(1 << bit)) | (flag ? (1 << bit) : 0)
#define SIGN_BIT 0x80000000L
#define SIGN32(n)  ((n) & SIGN_BIT)

typedef void (*voidfunc) (void);

typedef struct
  {
    voidfunc f;
    char *opname;
    int andmask, pattern;
    voidfunc rpt_prep;
  }
instruction_format;

enum PHASE
  {
    FETCH = 0, DECODE = 1, OPERAND = 2, EXECUTE = 3
  };

typedef struct
  {
    char valid;
    int instruction;
    voidfunc f;
    uint operand_address, spare_arg;
    long int operand, old_accum;
  }
pipeline_layer;

QUASISTATIC pipeline_layer pipeline[4];

/* ======================================================================= */
/*                           Static Functions                              */
/* ======================================================================= */

static int on_chip_ram (int a);
static int get_operand_address (enum PHASE);
static long int sign_extend (long int x, int n);
static void sign_extend_operand (void);
static void get_operand (void);
static int check_ar_lock (int arx);
static int bcnd_helper (int instruc);
static int detect_overflow (long number_added);
static void saturate_overflow (long number_added);
static void add_operand (int c_in);
static void sub_operand (int c_in);
static long int shifted_p (void);
static void repeat_instruction (void);
static int c50_hardware_pop (void);
static void c50_hardware_push (int d);
static void check_dmov_okay (int addr, char *instruc_name);
static int lookup (int instruc);
static void service_pending_interrupts (void);

static void Blkd_rpt_prep (void);
static void Tblr_rpt_prep (void);

static void Abs (void);
static void Add1 (void);
static void Add2 (void);
static void Add3 (void);
static void Add4 (void);
static void Addc (void);
static void Addb (void);
static void Adds (void);
static void Addt (void);
static void Adrk (void);
static void And1 (void);
static void And2 (void);
static void And3 (void);
static void Andb (void);
static void Apac (void);
static void Apl1 (void);
static void Apl2 (void);
static void B (void);
static void Bd (void);
static void Bacc (void);
static void Baccd (void);
static void Banz (void);
static void Banzd (void);
static void Bcnd (void);
static void Bcndd (void);
static void Bit (void);
static void Bitt (void);
static void Bldd1 (void);
static void Bldd2 (void);
static void Bldd3 (void);
static void Bldd4 (void);
static void Bldp (void);
static void Blpd1 (void);
static void Blpd2 (void);
static void Cala (void);
static void Calad (void);
static void Call (void);
static void Calld (void);
static void Cc (void);
static void Ccd (void);
static void Clrc_ovm (void);
static void Clrc_sxm (void);
static void Clrc_hm (void);
static void Clrc_tc (void);
static void Clrc_c (void);
static void Clrc_cnf (void);
static void Clrc_intm (void);
static void Clrc_xf (void);
static void Cmpl (void);
static void Cmpr (void);
static void Cpl1 (void);
static void Cpl2 (void);
static void Crgt (void);
static void Crlt (void);
static void Dmov (void);
static void Exar (void);
static void Idle (void);
static void Idle2 (void);
static void In (void);
static void Intr (void);
static void Lacb (void);
static void Lacc1 (void);
static void Lacc2 (void);
static void Lacc3 (void);
static void Lacl1 (void);
static void Lacl2 (void);
static void Lact (void);
static void Lamm (void);
static void Lar1 (void);
static void Lar2 (void);
static void Lar3 (void);
static void Ldp1 (void);
static void Ldp2 (void);
static void Lmmr (void);
static void Lph (void);
static void Lst1 (void);
static void Lst2 (void);
static void Lt (void);
static void Lta (void);
static void Ltd (void);
static void Ltp (void);
static void Lts (void);
static void Mac (void);
static void Macd (void);
static void Madd (void);
static void Mads (void);
static void Mar (void);
static void Mpy1 (void);
static void Mpy2 (void);
static void Mpy3 (void);
static void Mpya (void);
static void Mpys (void);
static void Mpyu (void);
static void Neg (void);
static void Nmi (void);
static void Nop (void);
static void Norm (void);
static void Opl1 (void);
static void Opl2 (void);
static void Or1 (void);
static void Or2 (void);
static void Or3 (void);
static void Orb (void);
static void Out (void);
static void Pac (void);
static void Pop (void);
static void Popd (void);
static void Pshd (void);
static void Push (void);
static void Ret (void);
static void Retd (void);
static void Retc (void);
static void Retcd (void);
static void Rete (void);
static void Reti (void);
static void Rol (void);
static void Rolb (void);
static void Ror (void);
static void Rorb (void);
static void Rpt1 (void);
static void Rpt2 (void);
static void Rpt3 (void);
static void Rptb (void);
static void Rptz (void);
static void Sacb (void);
static void Sach (void);
static void Sacl (void);
static void Samm (void);
static void Sar (void);
static void Sath (void);
static void Satl (void);
static void Sbb (void);
static void Sbbb (void);
static void Sbrk (void);
static void Setc_ovm (void);
static void Setc_sxm (void);
static void Setc_hm (void);
static void Setc_tc (void);
static void Setc_c (void);
static void Setc_cnf (void);
static void Setc_intm (void);
static void Setc_xf (void);
static void Sfl (void);
static void Sflb (void);
static void Sfr (void);
static void Sfrb (void);
static void Smmr (void);
static void Spac (void);
static void Sph (void);
static void Spl (void);
static void Splk (void);
static void Spm (void);
static void Sqra (void);
static void Sqrs (void);
static void Sst1 (void);
static void Sst2 (void);
static void Sub1 (void);
static void Sub2 (void);
static void Sub3 (void);
static void Sub4 (void);
static void Subb (void);
static void Subc (void);
static void Subs (void);
static void Subt (void);
static void Tblr (void);
static void Tblw (void);
static void Xc (void);
static void Xor1 (void);
static void Xor2 (void);
static void Xor3 (void);
static void Xorb (void);
static void Xpl1 (void);
static void Xpl2 (void);
static void Zalr (void);
static void Zap (void);
static void Zpr (void);

/* ======================================================================= */
/*                           Public Variables                              */
/* ======================================================================= */

/* Registers */

int program_ram, ovly;
int arp, ov, ovm, intm, dp;	/* st0 */
int arb, cnf, tc, sxm, c, hm, fsm, xf, fo, txm, pm;	/* st1 */
long int accumulator, accb, p_register;
uint pc;
int dbmr, treg0, treg1, treg2, trm, _stack[8], _sp, ar[8], arcr;
int mp_mc_mode;
int bio;
int drr, dxr, tim, prd, imr, greg;

/* Registers that didn't appear in the C25 */
int ifr, pmst, rptc, brcr, pasr, paer, indx, cbsr1, cber1, cbsr2, cber2;
int cbcr, bmar, spc, tcr, pdwsr, iowsr, cwsr;
int trcv, tdxr, tspc, tcsr, trta, trad;

/* What the hell is braf? */
int braf;

unsigned long int steps_taken, cycles;

char error_string[100];

/* ======================================================================= */
/*                           Static Variables                              */
/* ======================================================================= */

static int
  ar_lock[8], program_memory_accesses, saram_accesses, daram_accesses,
  io_port_accesses, pending_interrupts, idle_mode = 0, pfc,
  repeating;

static enum PHASE processor_phase;

static instruction_format opcodes[] =
{
  {Abs, "Abs", 0xFFFF, 0xBE00, NULL},

  {Add1, "Add1", 0xF000, 0x2000, NULL},
  {Add2, "Add2", 0xFF00, 0xB800, NULL},
  {Add3, "Add3", 0xFFF0, 0xBF90, NULL},
  {Add4, "Add4", 0xFF00, 0x6100, NULL},

  {Addb, "Addb", 0xFFFF, 0xBE10, NULL},

  {Addc, "Addc", 0xFF00, 0x6000, NULL},

  {Adds, "Adds", 0xFF00, 0x6200, NULL},

  {Addt, "Addt", 0xFF00, 0x6300, NULL},

  {Adrk, "Adrk", 0xFF00, 0x7800, NULL},

  {And1, "And1", 0xFF00, 0x6E00, NULL},
  {And2, "And2", 0xFFF0, 0xBFB0, NULL},
  {And3, "And3", 0xFFFF, 0xBE81, NULL},

  {Andb, "Andb", 0xFFFF, 0xBE12, NULL},

  {Apac, "Apac", 0xFFFF, 0xBE04, NULL},

  {Apl1, "Apl1", 0xFF00, 0x5A00, NULL},
  {Apl2, "Apl2", 0xFF00, 0x5E00, NULL},

  {B, "B", 0xFF80, 0x7980, NULL},
  {Bd, "Bd", 0xFF80, 0x7D80, NULL},

  {Bacc, "Bacc", 0xFFFF, 0xBE20, NULL},
  {Baccd, "Baccd", 0xFFFF, 0xBE21, NULL},

  {Banz, "Banz", 0xFF80, 0x7B80, NULL},
  {Banzd, "Banzd", 0xFF80, 0x7F80, NULL},

  {Bcnd, "Bcnd", 0xFC00, 0xE000, NULL},
  {Bcndd, "Bcndd", 0xFC00, 0xF000, NULL},

  {Bit, "Bit", 0xF000, 0x4000, NULL},

  {Bitt, "Bitt", 0xFF00, 0x6F00, NULL},


  /* need implementing */
  {Bldd1, "Bldd1", 0xFF00, 0xA800, Blkd_rpt_prep},
  {Bldd2, "Bldd2", 0xFF00, 0xA900, Blkd_rpt_prep},
  {Bldd3, "Bldd3", 0xFF00, 0xAC00, Blkd_rpt_prep},
  {Bldd4, "Bldd4", 0xFF00, 0xAD00, Blkd_rpt_prep},

  {Bldp, "Bldp", 0xFF00, 0x5700, Blkd_rpt_prep},

  {Blpd1, "Blpd1", 0xFF00, 0xA500, Blkd_rpt_prep},
  {Blpd2, "Blpd2", 0xFF00, 0xA400, Blkd_rpt_prep},

  {Cala, "Cala", 0xFFFF, 0xBE30, NULL},

  {Calad, "Calad", 0xFFFF, 0xBE3D, NULL},

  {Call, "Call", 0xFF00, 0x7A00, NULL},

  {Calld, "Calld", 0xFF00, 0x7E00, NULL},

  {Cc, "Cc", 0xFC00, 0xE800, NULL},

  {Ccd, "Ccd", 0xFC00, 0xF800, NULL},

  {Clrc_ovm, "Clrc_ovm", 0xFFFF, 0xBE42, NULL},
  {Clrc_sxm, "Clrc_sxm", 0xFFFF, 0xBE46, NULL},
  {Clrc_hm, "Clrc_hm", 0xFFFF, 0xBE48, NULL},
  {Clrc_tc, "Clrc_tc", 0xFFFF, 0xBE4A, NULL},
  {Clrc_c, "Clrc_c", 0xFFFF, 0xBE4E, NULL},
  {Clrc_cnf, "Clrc_cnf", 0xFFFF, 0xBE44, NULL},
  {Clrc_intm, "Clrc_intm", 0xFFFF, 0xBE40, NULL},
  {Clrc_xf, "Clrc_xf", 0xFFFF, 0xBE4C, NULL},

  {Cmpl, "Cmpl", 0xFFFF, 0xBE01, NULL},

  {Cmpr, "Cmpr", 0xFFFC, 0xBE44, NULL},

  {Cpl1, "Cpl1", 0xFF00, 0x5B00, NULL},
  {Cpl2, "Cpl2", 0xFF00, 0x5F00, NULL},

  {Crgt, "Crgt", 0xFFFF, 0xBE1B, NULL},		/* one of these is a typo in */

  {Crlt, "Crlt", 0xFFFF, 0xBE1B, NULL},		/* the TI data book */

  {Dmov, "Dmov", 0xFF00, 0x7700, NULL},

  {Exar, "Exar", 0xFFFF, 0xBE1D, NULL},

  {Idle, "Idle", 0xFFFF, 0xBE22, NULL},

  {Idle2, "Idle2", 0xFF00, 0xBE23, NULL},

  {In, "In", 0xFF00, 0xAF00, NULL},

  {Intr, "Intr", 0xFFE0, 0xBE60, NULL},

  {Lacb, "Lacb", 0xFFFF, 0xBE1F, NULL},

  {Lacc1, "Lacc1", 0xF000, 0x1000, NULL},
  {Lacc2, "Lacc2", 0xFFF0, 0xBF80, NULL},
  {Lacc3, "Lacc3", 0xFF00, 0x6A00, NULL},

  {Lacl1, "Lacl1", 0xFF00, 0x6900, NULL},
  {Lacl2, "Lacl2", 0xFF00, 0xB900, NULL},

  {Lact, "Lact", 0xFF00, 0x6B00, NULL},

  {Lamm, "Lamm", 0xFF00, 0x0800, NULL},

  {Lar1, "Lar1", 0xF800, 0x0000, NULL},
  {Lar2, "Lar2", 0xF800, 0xB000, NULL},
  {Lar3, "Lar3", 0xFFF8, 0xBF08, NULL},

  {Ldp1, "Ldp1", 0xFF00, 0x0D00, NULL},
  {Ldp2, "Ldp2", 0xFE00, 0xBC00, NULL},

  {Lmmr, "Lmmr", 0xFF00, 0x8900, NULL},

  {Lph, "Lph", 0xFF00, 0x7500, NULL},

  {Lst1, "Lst1", 0xFF00, 0x0E00, NULL},
  {Lst2, "Lst2", 0xFF00, 0x0F00, NULL},

  {Lt, "Lt", 0xFF00, 0x7300, NULL},

  {Lta, "Lta", 0xFF00, 0x7000, NULL},

  {Ltd, "Ltd", 0xFF00, 0x7200, NULL},

  {Ltp, "Ltp", 0xFF00, 0x7100, NULL},

  {Lts, "Lts", 0xFF00, 0x7400, NULL},

  {Mac, "Mac", 0xFF00, 0xA200, NULL},

  {Macd, "Macd", 0xFF00, 0xA300, NULL},

  {Madd, "Madd", 0xFF00, 0xAB00, NULL},

  {Mads, "Mads", 0xFF00, 0xAA00, NULL},

  /* Nop comes early in the table, otherwise it's decoded as Mar.
   * Functionally it doesn't matter, but it makes listings more confusing.
   */
  {Nop, "Nop", 0xFFFF, 0x8B00, NULL},

  {Mar, "Mar", 0xFF00, 0x8B00, NULL},

  {Mpy1, "Mpy1", 0xFF00, 0x5400, NULL},
  {Mpy2, "Mpy2", 0xE000, 0xC000, NULL},
  {Mpy3, "Mpy3", 0xFFFF, 0xBE80, NULL},

  {Mpya, "Mpya", 0xFF00, 0x5000, NULL},

  {Mpys, "Mpys", 0xFF00, 0x5100, NULL},

  {Mpyu, "Mpyu", 0xFF00, 0x5500, NULL},

  {Neg, "Neg", 0xFFFF, 0xBE02, NULL},

  {Nmi, "Nmi", 0xFFFF, 0xBE52, NULL},

  {Norm, "Norm", 0xFF80, 0xA080, NULL},

  {Opl1, "Opl1", 0xFF00, 0x5900, NULL},
  {Opl2, "Opl2", 0xFF00, 0x5D00, NULL},

  {Or1, "Or1", 0xFF00, 0x6D00, NULL},
  {Or2, "Or2", 0xFFF0, 0xBFC0, NULL},
  {Or3, "Or3", 0xFFFF, 0xBE82, NULL},

  {Orb, "Orb", 0xFFFF, 0xBE13, NULL},

  {Out, "Out", 0xFF00, 0x0C00, NULL},

  {Pac, "Pac", 0xFFFF, 0xBE03, NULL},

  {Pop, "Pop", 0xFFFF, 0xBE32, NULL},

  {Popd, "Popd", 0xFF00, 0x8A00, NULL},

  {Pshd, "Pshd", 0xFF00, 0x7600, NULL},

  {Push, "Push", 0xFFFF, 0xBE3C, NULL},

  {Ret, "Ret", 0xFFFF, 0xEF00, NULL},

  {Retd, "Retd", 0xFFFF, 0xFF00, NULL},

  {Retc, "Retc", 0xFC00, 0xEE00, NULL},

  {Retcd, "Retcd", 0xFC00, 0xFE00, NULL},

  {Rete, "Rete", 0xFFFF, 0xBE3A, NULL},

  {Reti, "Reti", 0xFFFF, 0xBE38, NULL},

  {Rol, "Rol", 0xFF00, 0xBE0C, NULL},

  {Rolb, "Rolb", 0xFF00, 0xBE14, NULL},

  {Ror, "Ror", 0xFF00, 0xBE0D, NULL},

  {Rorb, "Rorb", 0xFF00, 0xBE15, NULL},

  {Rpt1, "Rpt1", 0xFF00, 0x0B00, NULL},
  {Rpt2, "Rpt2", 0xFFFF, 0xBEC4, NULL},
  {Rpt3, "Rpt3", 0xFF00, 0xBB00, NULL},

  {Rptb, "Rptb", 0xFF00, 0xBEC6, NULL},

  {Rptz, "Rptz", 0xFF00, 0xBEC5, NULL},

  {Sacb, "Sacb", 0xFF00, 0xBE1E, NULL},

  {Sach, "Sach", 0xF800, 0x9800, NULL},

  {Sacl, "Sacl", 0xF800, 0x9000, NULL},

  {Samm, "Samm", 0xFF00, 0x8800, NULL},

  {Sar, "Sar", 0xF800, 0x8000, NULL},

  {Sath, "Sath", 0xFFFF, 0xBE5A, NULL},		/* another pair of typos in */

  {Satl, "Satl", 0xFFFF, 0xBE5A, NULL},		/* the TI data book */

  {Sbb, "Sbb", 0xFFFF, 0xBE18, NULL},

  {Sbbb, "Sbbb", 0xFFFF, 0xBE19, NULL},

  {Sbrk, "Sbrk", 0xFF00, 0x7C00, NULL},

  {Setc_ovm, "Setc_ovm", 0xFFFF, 0xBE43, NULL},
  {Setc_sxm, "Setc_sxm", 0xFFFF, 0xBE47, NULL},
  {Setc_hm, "Setc_hm", 0xFFFF, 0xBE49, NULL},
  {Setc_tc, "Setc_tc", 0xFFFF, 0xBE4B, NULL},
  {Setc_c, "Setc_c", 0xFFFF, 0xBE4F, NULL},
  {Setc_cnf, "Setc_cnf", 0xFFFF, 0xBE4D, NULL},
  {Setc_intm, "Setc_intm", 0xFFFF, 0xBE45, NULL},
  {Setc_xf, "Setc_xf", 0xFFFF, 0xBE41, NULL},

  {Sfl, "Sfl", 0xFFFF, 0xBE09, NULL},

  {Sflb, "Sflb", 0xFFFF, 0xBE16, NULL},

  {Sfr, "Sfr", 0xFFFF, 0xBE0A, NULL},

  {Sfrb, "Sfrb", 0xFFFF, 0xBE17, NULL},

  {Smmr, "Smmr", 0xFF00, 0x0900, NULL},

  {Spac, "Spac", 0xFFFF, 0xBE05, NULL},

  {Sph, "Sph", 0xFF00, 0x8D00, NULL},

  {Spl, "Spl", 0xFF00, 0x8C00, NULL},

  {Splk, "Splk", 0xFF00, 0xAE00, NULL},

  {Spm, "Spm", 0xFFFC, 0xBF00, NULL},

  {Sqra, "Sqra", 0xFF00, 0x5200, NULL},

  {Sqrs, "Sqrs", 0xFF00, 0x5300, NULL},

  {Sst1, "Sst1", 0xFF00, 0x8E00, NULL},
  {Sst2, "Sst2", 0xFF00, 0x8F00, NULL},

  {Sub1, "Sub1", 0xF000, 0x3000, NULL},
  {Sub2, "Sub2", 0xFF00, 0x6500, NULL},
  {Sub3, "Sub3", 0xFF00, 0xBA00, NULL},
  {Sub4, "Sub4", 0xFFF0, 0xBFA0, NULL},

  {Subb, "Subb", 0xFF00, 0x6400, NULL},

  {Subc, "Subc", 0xFF00, 0x0A00, NULL},

  {Subs, "Subs", 0xFF00, 0x6600, NULL},

  {Subt, "Subt", 0xFF00, 0x6700, NULL},

  {Tblr, "Tblr", 0xFF00, 0xA600, NULL},

  {Tblw, "Tblw", 0xFF00, 0xA700, NULL},

  {Xc, "Xc", 0xEC00, 0xE400, NULL},

  {Xor1, "Xor1", 0xFF00, 0x6C00, NULL},
  {Xor2, "Xor2", 0xFFF0, 0xBFD0, NULL},
  {Xor3, "Xor3", 0xFFFF, 0xBE83, NULL},

  {Xorb, "Xorb", 0xFFFF, 0xBE1A, NULL},

  {Xpl1, "Xpl1", 0xFF00, 0x5800, NULL},
  {Xpl2, "Xpl2", 0xFF00, 0x5C00, NULL},

  {Zalr, "Zalr", 0xFF00, 0x6800, NULL},

  {Zap, "Zap", 0xFFFF, 0xBE59, NULL},

  {Zpr, "Zpr", 0xFFFF, 0xBE58, NULL}
};

/* ======================================================================= */
/*                              Accessing Memory                           */
/* ======================================================================= */

/* Some memory blocks are internal to the C50 */

static int on_chip_rom[0x800];
static int on_chip_saram[0x2400];	/* single-access-per-cycle SRAM */
static int on_chip_daram_b0[0x100];	/* double-access-per-cycle SRAM */
static int on_chip_daram_b1[0x200];
static int on_chip_daram_b2[0x20];

void
write_program_memory (uint a, int d)
{
  if (!mp_mc_mode && a < 0x800)
    {
      on_chip_rom[a] = d;
      program_memory_accesses++;
      return;
    }

  if (a >= 0x800 && a < 0x2C00 && program_ram)
    {
      on_chip_saram[a - 0x800] = d;
      return;
    }

  if (cnf && a >= 0xFE00)
    {
      on_chip_daram_b0[a - 0xFE00] = d;
      return;
    }

  write_program_off_chip (a, d);
}

int
read_program_memory (uint a)
{
  if (!mp_mc_mode && a < 0x800)
    {
      program_memory_accesses++;
      return on_chip_rom[a];
    }

  if (a >= 0x800 && a < 0x2C00 && program_ram)
    {
      return on_chip_saram[a - 0x800];
      saram_accesses++;
    }

  if (cnf && a >= 0xFE00)
    {
      return on_chip_daram_b0[a - 0xFE00];
      daram_accesses++;
    }

  return read_program_off_chip (a);
}

static int memory_mapped_oops;

static int *
memory_mapped_stuff (uint addr)
{
  switch (addr)
    {
    case 0x04:			/* Processor registers */
      return &imr;
    case 0x05:
      return &greg;
    case 0x06:
      return 𝔦
    case 0x07:
      return &pmst;
    case 0x08:
      return &rptc;
    case 0x09:
      return &brcr;
    case 0x0A:
      return &pasr;
    case 0x0B:
      return &paer;
    case 0x0C:
      return &treg0;
    case 0x0D:
      return &treg1;
    case 0x0E:
      return &treg2;
    case 0x0F:
      return &dbmr;
    case 0x10:
      return &ar[0];
    case 0x11:
      return &ar[1];
    case 0x12:
      return &ar[2];
    case 0x13:
      return &ar[3];
    case 0x14:
      return &ar[4];
    case 0x15:
      return &ar[5];
    case 0x16:
      return &ar[6];
    case 0x17:
      return &ar[7];
    case 0x18:
      return &indx;
    case 0x19:
      return &arcr;
    case 0x1A:
      return &cbsr1;
    case 0x1B:
      return &cber1;
    case 0x1C:
      return &cbsr2;
    case 0x1D:
      return &cber2;
    case 0x1E:
      return &cbcr;
    case 0x1F:
      return &bmar;

    case 0x20:			/* Peripheral registers */
      return &drr;
    case 0x21:
      return &dxr;
    case 0x22:
      return &spc;

    case 0x24:
      return &tim;
    case 0x25:
      return &prd;
    case 0x26:
      return &tcr;

    case 0x28:
      return &pdwsr;
    case 0x29:
      return &iowsr;
    case 0x2A:
      return &cwsr;

    case 0x30:
      return &trcv;
    case 0x31:
      return &tdxr;
    case 0x32:
      return &tspc;
    case 0x33:
      return &tcsr;
    case 0x34:
      return &trta;
    case 0x35:
      return &trad;
    }

  sprintf (error_string,
	   "Undefined memory-mapped address %04X", addr);
  handle_error ();
  return &memory_mapped_oops;
}

void
write_data_memory (uint a, int d)
{
  if (a < 0x50)
    {
      *memory_mapped_stuff (a) = d;
      return;
    }

  if (a >= 0x50 && a < 0x60)
    {
      io_port_accesses++;
      write_io_port (a, d);
      return;
    }

  if (a >= 0x60 && a < 0x80)
    {
      daram_accesses++;
      on_chip_daram_b2[a - 0x60] = d;
      return;
    }

  if (a >= 0x80 && a < 0x100)
    {
      sprintf (error_string,
	       "Attempt to write to reserved data memory at %04X", a);
      handle_error ();
      return;
    }

  if (a >= 0x100 && a < 0x300)
    {
      if (!cnf)
	{
	  daram_accesses++;
	  on_chip_daram_b0[a - 0x100] = d;
	}
      else
	{
	  sprintf (error_string,
		   "Attempt to write to reserved data memory at %04X", a);
	  handle_error ();
	}
      return;
    }

  if (a >= 0x300 && a < 0x500)
    {
      daram_accesses++;
      on_chip_daram_b1[a - 0x300] = d;
      return;
    }

  if (a >= 0x500 && a < 0x800)
    {
      sprintf (error_string,
	       "Attempt to write to reserved data memory at %04X", a);
      handle_error ();
      return;
    }

  if (a >= 0x800 && a < 0x2C00 && ovly)
    {
      saram_accesses++;
      on_chip_saram[a - 0x800] = d;
      return;
    }

  write_data_off_chip (a, d);
}

int
read_data_memory (uint a)
{
  if (a < 0x50)
    return *memory_mapped_stuff (a);

  if (a >= 0x50 && a < 0x60)
    {
      io_port_accesses++;
      return read_io_port (a);
    }

  if (a >= 0x60 && a < 0x80)
    {
      daram_accesses++;
      return on_chip_daram_b2[a - 0x60];
    }

  if (a >= 0x80 && a < 0x100)
    {
      sprintf (error_string,
	       "Attempt to write to reserved data memory at %04X", a);
      handle_error ();
      return 0;
    }

  if (a >= 0x100 && a < 0x300)
    {
      if (!cnf)
	{
	  daram_accesses++;
	  return on_chip_daram_b0[a - 0x100];
	}
      else
	{
	  sprintf (error_string,
		   "Attempt to write to reserved data memory at %04X", a);
	  handle_error ();
	}
      return 0;
    }

  if (a >= 0x300 && a < 0x500)
    {
      daram_accesses++;
      return on_chip_daram_b1[a - 0x300];
    }

  if (a >= 0x500 && a < 0x800)
    {
      sprintf (error_string,
	       "Attempt to write to reserved data memory at %04X", a);
      handle_error ();
      return 0;
    }

  if (a >= 0x800 && a < 0x2C00 && ovly)
    {
      saram_accesses++;
      return on_chip_saram[a - 0x800];
    }

  return read_data_off_chip (a);
}

/* ======================================================================= */
/*                      Instruction helpers                                */
/* ======================================================================= */

static int
on_chip_ram (int a)
{
  if (a < 0x80)
    return 1;

  if (a >= 0x100 && a < 0x300)
    return !cnf;

  if (a >= 0x300 && a < 0x500)
    return 1;

  if (a >= 0x800 && a < 0x2C00)
    return ovly;

  return 0;
}

static int
get_operand_address (enum PHASE ph)
{
  int i, mask, r, s, carry;

  if ((pipeline[ph].instruction & 0x80) == 0)
    r = ((dp << 7) & 0xFF80) | (pipeline[ph].instruction & 0x7F);
  else
    {
      /* handle updates to AR(ARP) and ARP */
      r = ar[arp];
      s = ar[0];
      switch ((pipeline[ph].instruction >> 4) & 7)
	{
	case 0:
	  break;
	case 1:
	  ar[arp]--;
	  ar_lock[arp] = 1;
	  break;
	case 2:
	  ar[arp]++;
	  ar_lock[arp] = 1;
	  break;
	case 3:
	  sprintf (error_string,
		   "Bad addressing mode in instruction at %04X", pc);
	  handle_error ();
	  break;
	case 4:
	  carry = 0;
	  for (i = 0; i < 16; i++)
	    {
	      mask = 1 << (15 - i);
	      carry = ((ar[arp] & mask) ? 1 : 0)
		- ((s & mask) ? 1 : 0)
		- carry;
	      ar[arp] = (ar[arp] & ~mask) + ((carry & 1) ? mask : 0);
	      carry = (carry >> 1) & 1;
	    }
	  ar_lock[arp] = 1;
	  break;
	case 5:
	  ar[arp] -= ar[0];
	  ar_lock[arp] = 1;
	  break;
	case 6:
	  ar[arp] += ar[0];
	  ar_lock[arp] = 1;
	  break;
	case 7:
	  carry = 0;
	  for (i = 0; i < 16; i++)
	    {
	      mask = 1 << (15 - i);
	      carry += ((ar[arp] & mask) ? 1 : 0)
		+ ((s & mask) ? 1 : 0);
	      ar[arp] = (ar[arp] & ~mask) + ((carry & 1) ? mask : 0);
	      carry = (carry >> 1) & 1;
	    }
	  ar_lock[arp] = 1;
	  break;
	}
      if (pipeline[ph].instruction & 8)
	{
	  arb = arp;
	  arp = (pipeline[ph].instruction & 7);
	}
    }
  pipeline[ph].operand_address = r;
  return r;
}

static int
check_ar_lock (int arx)
{
  if ((ar_lock[0] && arx == 0)
      || (ar_lock[1] && arx == 1)
      || (ar_lock[2] && arx == 2)
      || (ar_lock[3] && arx == 3)
      || (ar_lock[4] && arx == 4)
      || (ar_lock[5] && arx == 5)
      || (ar_lock[6] && arx == 6)
      || (ar_lock[7] && arx == 7))
    return 1;
  return 0;
}

static long int
sign_extend (long int x, int n)
{
  long int y;

  y = ((long int) 1) << (n - 1);
  if (x & y)
    x |= -y;
  else
    x &= y - 1;
  return x;
}

static void
sign_extend_operand (void)
{
  if (sxm)
    pipeline[EXECUTE].operand =
      sign_extend (pipeline[EXECUTE].operand, 16);
}

static int
bcnd_helper (int instruc)
{
  int m = 0, mask;

  /* check the TP bits */
  switch (instruc & 0x300)
    {
    case 0x000:
      return !bio;
    case 0x100:
      return tc;
    case 0x200:
      return !tc;
    case 0x300:
      /* we're not testing TP, fall thru to flags */
      break;
    }

  /* check the ZLVC bits */
  mask = instruc & 0x0F;
  if (c)
    m |= 1;
  if (ov)
    m |= 2;
  if (accumulator < 0)
    m |= 4;
  if (accumulator == 0)
    m |= 8;
  return (m & mask) == ((instruc >> 4) & mask);
}

static void
get_operand (void)
{
  pipeline[OPERAND].old_accum = accumulator;
  pipeline[OPERAND].operand =
    read_data_memory (pipeline[OPERAND].operand_address);
}

static int
detect_overflow (long number_added)
{
  if (!SIGN32 (number_added))
    if (!SIGN32 (pipeline[EXECUTE].old_accum)
	&& SIGN32 (accumulator))
      return 1;
  if (SIGN32 (number_added))
    if (SIGN32 (pipeline[EXECUTE].old_accum)
	&& !SIGN32 (accumulator))
      return 1;
  return 0;
}

static void
saturate_overflow (long number_added)
{
  if (!SIGN32 (number_added))
    accumulator = ~SIGN_BIT;
  else
    accumulator = SIGN_BIT;
}

static void
add_operand (int c_in)
{
  int i;
  long mask;

  pipeline[EXECUTE].old_accum = accumulator;
  for (i = 0, mask = SIGN_BIT; i < 32; i++, mask >>= 1)
    {
      if ((accumulator & pipeline[EXECUTE].operand) & mask)
	{
	  c = 1;
	  goto c_done;
	}
      if ((~accumulator & ~pipeline[EXECUTE].operand) & mask)
	{
	  c = 0;
	  goto c_done;
	}
    }
  c = c_in;
c_done:
  if (c_in)
    pipeline[EXECUTE].operand++;
  accumulator += pipeline[EXECUTE].operand;
  if (detect_overflow (pipeline[EXECUTE].operand))
    {
      ov = 1;
      if (ovm)
	saturate_overflow (pipeline[EXECUTE].operand);
    }
}

static void
sub_operand (int c_in)
{
  if (c_in)
    pipeline[EXECUTE].operand++;
  pipeline[EXECUTE].operand = -pipeline[EXECUTE].operand;
  add_operand (0);
}

static long int
shifted_p (void)
{
  long int shp;

  switch (pm)
    {
    case 0:
      return p_register;
    case 1:
      return p_register << 1;
    case 2:
      return p_register << 4;
    default:
      shp = p_register >> 6;
      if (p_register & SIGN_BIT)
	shp |= 0xFC000000L;
      return shp;
    }
}

/* ? ? ? ? */
static void
repeat_instruction (void)
{
#if 0
  voidfunc g;
  int i, init_rptc;

  instruction = read_program_memory (pc++);
  i = lookup (instruction);
  if (i == -1)
    {
      sprintf (error_string,
	       "Trying to repeat unknown opcode at address %04X", pc - 1);
      handle_error ();
      return;
    }
  repeating = 1;
  g = opcodes[i].rpt_prep;
  if (g != NULL)
    (*g) ();
  g = opcodes[i].f;
  init_rptc = rptc;
  while (rptc >= 0)
    {
      (*g) ();
      rptc--;
    }
  burn_cycles (opcodes[i].cycle_type, init_rptc + 1);
  repeating = 0;
  rptc = 0;
#endif
  /* I haven't given a lot of thought yet to how to do repeat
   * instructions for the C50.
   */
}

static int
c50_hardware_pop (void)
{
  _sp = (_sp - 1) & 7;
  return _stack[_sp];
}

static void
c50_hardware_push (int d)
{
  _stack[_sp] = d;
  _sp = (_sp + 1) & 7;
}

static void
check_dmov_okay (int addr, char *instruc_name)
{
  /* For the instructions DMOV, LTD, and MACD, both addr and addr+1
     must be in on-chip ram for the data move to work. */
  if (on_chip_ram (addr) && on_chip_ram (addr + 1))
    return;
  sprintf (error_string,
	   "Instruction %s at %04X using non-internal "
	   "data memory at address %04X", instruc_name, pc, addr);
  handle_error ();
}

/* ======================================================================= */
/*                       Lookup table, advance                             */
/* ======================================================================= */

static int
lookup (int instruc)
{
  int i;

  for (i = 0; i < NUM_OPCODES; i++)
    if ((instruc & opcodes[i].andmask) ==
	opcodes[i].pattern)
      return i;
  return -1;
}

char *
disassemble (int instruc)
{
  int i;

  if ((i = lookup (instruc)) != -1)
    return opcodes[i].opname;
  return "ILLEGAL";
}

void
advance (void)
{
  int i;

  service_pending_interrupts ();
  if (idle_mode)
    {
      /* the whole pipeline stands still */
      cycles++;
      if (idle_mode < 2)
	{
	  tim--;
	  if (tim == 0)
	    c50_interrupt (TINT);
	}
      return;
    }

  /* Move the whole pipeline down one */
  memcpy (&pipeline[EXECUTE], &pipeline[OPERAND],
	  sizeof (pipeline_layer));
  memcpy (&pipeline[OPERAND], &pipeline[DECODE],
	  sizeof (pipeline_layer));

  /* Clear all memory access counts */

  program_memory_accesses = 0;
  saram_accesses = 0;
  daram_accesses = 0;
  io_port_accesses = 0;

  /* Fetch an instruction (unless repeating) */

  if (rptc == 0)
    {
      memcpy (&pipeline[DECODE], &pipeline[FETCH],
	      sizeof (pipeline_layer));
      pipeline[FETCH].instruction = read_program_memory (pc++);
      i = lookup (pipeline[FETCH].instruction);

      if (i != -1)
	{
	  pipeline[FETCH].valid = 1;
	  pipeline[FETCH].f = opcodes[i].f;
	}
      else
	pipeline[FETCH].valid = 0;
    }

  /* Do the stuff currently in pipeline */

  for (i = 0; i < 8; i++)
    ar_lock[i] = 0;

  processor_phase = DECODE;
  if (pipeline[DECODE].valid)
    (*pipeline[DECODE].f) ();

  processor_phase = OPERAND;
  if (pipeline[OPERAND].valid)
    (*pipeline[OPERAND].f) ();

  processor_phase = EXECUTE;
  if (pipeline[EXECUTE].valid)
    (*pipeline[EXECUTE].f) ();

  while (daram_accesses > 0 || saram_accesses > 0
	 || program_memory_accesses > 0 || io_port_accesses > 0)
    {
      cycles++;
      daram_accesses -= 2;
      saram_accesses--;
      program_memory_accesses--;
      io_port_accesses--;
    }
  steps_taken++;

  if (rptc != 0) rptc--;
}

void
c50_reset (void)
{
  int i;

  pipeline[EXECUTE].valid = 0;
  pipeline[OPERAND].valid = 0;
  pipeline[DECODE].valid = 0;
  pipeline[FETCH].valid = 0;

  pc = 0;
  _sp = 0;
  rptc = 0;
  for (i = 0; i < 8; i++)
    {
      _stack[i] = 0;
      ar[i] = 0;
    }
  ov = 0;
  intm = 1;
  cnf = 0;
  sxm = 1;
  c = 1;
  hm = 1;
  fsm = 1;
  xf = 1;
  fo = 0;
  txm = 0;
  pm = 0;
  tim = 0xFFFF;
  prd = 0xFFFF;
  greg = 0;
  repeating = 0;
  idle_mode = 0;
  steps_taken = 0;
  cycles = 0;
}

/* ======================================================================= */
/*                                Interrupts                               */
/* ======================================================================= */

void
c50_interrupt (enum int_type n)
{
  switch (n)
    {
    case RS:
      c50_reset ();
      return;
    case INT0:
      pending_interrupts |= 1;
      return;
    case INT1:
      pending_interrupts |= 2;
      return;
    case INT2:
      pending_interrupts |= 4;
      return;
    case TINT:
      tim += prd;
      pending_interrupts |= 8;
      return;
    case RINT:
      pending_interrupts |= 0x10;
      return;
    case XINT:
      pending_interrupts |= 0x20;
      return;
    case TRAP:
      c50_hardware_push (pc);
      pc = 0x001E;
      intm = 1;
      idle_mode = 0;
      return;
    default:
      sprintf (error_string, "Illegal interrupt");
      handle_error ();
      break;
    }
}

static int
try_interrupt_bit (int n, int addr)
{
  if (read_bit (imr & pending_interrupts, n))
    {
      pending_interrupts &= ~(1 << n);
      c50_hardware_push (pc);
      pc = addr;
      intm = 1;
      idle_mode = 0;
      return 1;
    }
  return 0;
}

static void
service_pending_interrupts (void)
{
  if (intm)
    return;
  if (try_interrupt_bit (0, 0x0002))
    return;
  if (try_interrupt_bit (1, 0x0004))
    return;
  if (try_interrupt_bit (2, 0x0006))
    return;
  if (try_interrupt_bit (3, 0x0018))
    return;
  if (try_interrupt_bit (4, 0x001A))
    return;
  if (try_interrupt_bit (5, 0x001C))
    return;
}

/* ======================================================================= */
/*                              C50 instructions                           */
/* ======================================================================= */

/* Ancillary Functions */

static void
Blkd_rpt_prep (void)
{
  pfc = read_program_memory (pc++);
}

static void
Tblr_rpt_prep (void)
{
  pfc = (int) accumulator;
}

/* Real C50 Instructions */

static void
Abs (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      /* exceptional case for 0x80000000, depending on OVF flag */
      if (accumulator == 0x80000000L)
	{
	  if (ovm)
	    accumulator = ~SIGN_BIT;
	  ov = 1;
	}
      else if (accumulator & SIGN_BIT)
	accumulator = -accumulator;
      break;
    }
}

static void
Add1 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      sign_extend_operand ();
      pipeline[EXECUTE].operand
	<<= (pipeline[EXECUTE].instruction >> 8) & 0x0F;
      add_operand (0);
      break;
    }
}

static void
Add2 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      pipeline[EXECUTE].operand = pipeline[EXECUTE].instruction & 0xFF;
      add_operand (0);
      break;
    }
}

static void
Add3 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      /* The next fetched word is an argument for this operation
       * so mark it as an invalid instruction, so we don't try to
       * execute it later.
       */
      pipeline[FETCH].valid = 0;
      break;
    case OPERAND:
      break;
    case EXECUTE:
      pipeline[EXECUTE].operand = pipeline[OPERAND].instruction;
      sign_extend_operand ();
      pipeline[EXECUTE].operand
	<<= (pipeline[EXECUTE].instruction & 0x0F);
      add_operand (0);
      break;
    }
}

static void
Add4 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      pipeline[EXECUTE].operand <<= 16;
      add_operand (0);
      break;
    }
}

static void
Addb (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      pipeline[EXECUTE].operand = accb;
      add_operand (c);
      break;
    }
}

static void
Addc (void)
{
  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      add_operand (c);
      break;
    }
}

static void
Adds (void)
{
  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      pipeline[EXECUTE].operand &= 0xFFFF;
      add_operand (0);
      break;
    }
}

static void
Addt (void)
{
  int shift;

  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      shift = treg1 & 15;
      pipeline[EXECUTE].operand <<= shift;
      add_operand (0);
      break;
    }
}

static void
Adrk (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      if (!ar_lock[arp])
	ar[arp] += pipeline[EXECUTE].instruction & 0xFF;
      break;
    }
}

static void
And1 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      accumulator &= pipeline[EXECUTE].operand;
      break;
    }
}

static void
And2 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      /* The next fetched word is an argument for this operation
       * so mark it as an invalid instruction, so we don't try to
       * execute it later.
       */
      pipeline[FETCH].valid = 0;
      pipeline[DECODE].operand = pipeline[FETCH].instruction & 0xFFFF;
      break;
    case OPERAND:
      break;
    case EXECUTE:
      accumulator &= pipeline[EXECUTE].operand;
      break;
    }
}

static void
And3 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      /* The next fetched word is an argument for this operation
       * so mark it as an invalid instruction, so we don't try to
       * execute it later.
       */
      pipeline[FETCH].valid = 0;
      pipeline[DECODE].operand = pipeline[FETCH].instruction << 16;
      break;
    case OPERAND:
      break;
    case EXECUTE:
      accumulator &= pipeline[EXECUTE].operand;
      break;
    }
}

static void
Andb (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      accumulator &= accb;
      break;
    }
}

static void
Apac (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      pipeline[EXECUTE].operand = shifted_p ();
      add_operand (0);
      break;
    }
}

static void
Apl1 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      write_data_memory (pipeline[EXECUTE].operand_address,
			 pipeline[EXECUTE].operand & dbmr);
      break;
    }
}

static void
Apl2 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      pipeline[FETCH].valid = 0;
      pipeline[DECODE].spare_arg = pipeline[FETCH].instruction;
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      write_data_memory (pipeline[EXECUTE].operand_address,
			 pipeline[EXECUTE].operand &
			 pipeline[EXECUTE].spare_arg);
      break;
    }
}

static void
B (void)
{
  switch (processor_phase)
    {
    case DECODE:
      pipeline[FETCH].valid = 0;
      get_operand_address (DECODE);
      break;
    case OPERAND:
      pipeline[FETCH].valid = 0;
      break;
    case EXECUTE:
      pipeline[FETCH].valid = 0;
      pc = pipeline[OPERAND].instruction;
      break;
    }
}

static void
Bd (void)
{
  switch (processor_phase)
    {
    case DECODE:
      pipeline[FETCH].valid = 0;
      get_operand_address (DECODE);
      break;
    case OPERAND:
      break;
    case EXECUTE:
      pc = pipeline[OPERAND].instruction;
      break;
    }
}

static void
Bacc (void)
{
  switch (processor_phase)
    {
    case DECODE:
      pc = (int) accumulator;
      break;
    case OPERAND:
      break;
    case EXECUTE:
      break;
    }
}

static void
Baccd (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      pc = (int) accumulator;
      break;
    }
}

static void
Banz (void)
{
  switch (processor_phase)
    {
    case DECODE:
      pipeline[FETCH].valid = 0;
      if (ar[arp])
	pc = pipeline[FETCH].instruction;
      break;
    case OPERAND:
      break;
    case EXECUTE:
      break;
    }
}

static void
Banzd (void)
{
  switch (processor_phase)
    {
    case DECODE:
      pipeline[FETCH].valid = 0;
      pipeline[DECODE].spare_arg = pipeline[FETCH].instruction;
      break;
    case OPERAND:
      break;
    case EXECUTE:
      if (ar[arp])
	pc = pipeline[EXECUTE].spare_arg;
      break;
    }
}

static void
Bcnd (void)
{
  switch (processor_phase)
    {
    case DECODE:
      pipeline[FETCH].valid = 0;
      if (bcnd_helper (pipeline[DECODE].instruction))
	pc = pipeline[FETCH].instruction;
      break;
    case OPERAND:
      break;
    case EXECUTE:
      break;
    }
}

static void
Bcndd (void)
{
  switch (processor_phase)
    {
    case DECODE:
      pipeline[FETCH].valid = 0;
      pipeline[DECODE].spare_arg = pipeline[FETCH].instruction;
      break;
    case OPERAND:
      break;
    case EXECUTE:
      if (bcnd_helper (pipeline[EXECUTE].instruction))
	pc = pipeline[EXECUTE].spare_arg;
      break;
    }
}

static void
Bit (void)
{
  int shift;

  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      shift = 15 - ((pipeline[EXECUTE].instruction >> 8) & 15);
      tc = (int) ((pipeline[EXECUTE].operand >> shift) & 1);
      break;
    }
}

static void
Bitt (void)
{
  int shift;

  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      shift = 15 - (treg1 & 15);
      tc = (int) ((pipeline[EXECUTE].operand >> shift) & 1);
      break;
    }
}

/* they're c50-ish, but they don't do anything yet */

static void
Bldd1 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      break;
    }
}

static void
Bldd2 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      break;
    }
}

static void
Bldd3 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      break;
    }
}

static void
Bldd4 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      break;
    }
}

static void
Bldp (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      break;
    }
}

static void
Blpd1 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      break;
    }
}

static void
Blpd2 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      break;
    }
}

static void
Cala (void)
{
  switch (processor_phase)
    {
    case DECODE:
      c50_hardware_push (pc);
      pc = (int) accumulator;
      break;
    case OPERAND:
      break;
    case EXECUTE:
      break;
    }
}

static void
Calad (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      c50_hardware_push (pc);
      pc = (int) accumulator;
      break;
    }
}

static void
Call (void)
{
  switch (processor_phase)
    {
    case DECODE:
      pipeline[FETCH].valid = 0;
      get_operand_address (DECODE);
      break;
    case OPERAND:
      pipeline[FETCH].valid = 0;
      break;
    case EXECUTE:
      pipeline[FETCH].valid = 0;
      c50_hardware_push (pc);
      pc = pipeline[OPERAND].instruction;
      break;
    }
}

static void
Calld (void)
{
  switch (processor_phase)
    {
    case DECODE:
      pipeline[FETCH].valid = 0;
      get_operand_address (DECODE);
      break;
    case OPERAND:
      break;
    case EXECUTE:
      c50_hardware_push (pc);
      pc = pipeline[OPERAND].instruction;
      break;
    }
}

static void
Cc (void)
{
  switch (processor_phase)
    {
    case DECODE:
      pipeline[FETCH].valid = 0;
      get_operand_address (DECODE);
      pipeline[DECODE].spare_arg =
	bcnd_helper (pipeline[DECODE].instruction);
      break;
    case OPERAND:
      if (pipeline[OPERAND].spare_arg)
	pipeline[FETCH].valid = 0;
      break;
    case EXECUTE:
      if (pipeline[EXECUTE].spare_arg)
	{
	  pipeline[FETCH].valid = 0;
	  c50_hardware_push (pc);
	  pc = pipeline[OPERAND].spare_arg;
	}
      break;
    }
}

static void
Ccd (void)
{
  switch (processor_phase)
    {
    case DECODE:
      pipeline[FETCH].valid = 0;
      get_operand_address (DECODE);
      break;
    case OPERAND:
      break;
    case EXECUTE:
      if (bcnd_helper (pipeline[EXECUTE].instruction))
	{
	  c50_hardware_push (pc);
	  pc = pipeline[OPERAND].instruction;
	}
      break;
    }
}

static void
Clrc_ovm (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      ovm = 0;
      break;
    }
}

static void
Clrc_sxm (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      sxm = 0;
      break;
    }
}

static void
Clrc_hm (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      hm = 0;
      break;
    }
}

static void
Clrc_tc (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      tc = 0;
      break;
    }
}

static void
Clrc_c (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      c = 0;
      break;
    }
}

static void
Clrc_cnf (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      cnf = 0;
      break;
    }
}

static void
Clrc_intm (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      intm = 0;
      break;
    }
}

static void
Clrc_xf (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      xf = 0;
      break;
    }
}

static void
Cmpl (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      accumulator = ~accumulator;
      break;
    }
}

static void
Cmpr (void)
{
  unsigned u, v;

  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      u = ar[arp];
      v = arcr;
      switch (pipeline[EXECUTE].instruction & 3)
	{
	case 0:
	  tc = (u == v);
	  break;
	case 1:
	  tc = (u < v);
	  break;
	case 2:
	  tc = (u > v);
	  break;
	case 3:
	  tc = (u != v);
	  break;
	}
      break;
    }
}

static void
Cpl1 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      if (pipeline[EXECUTE].operand == dbmr)
	tc = 1;
      else
	tc = 0;
      break;
    }
}

static void
Cpl2 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      pipeline[FETCH].valid = 0;
      pipeline[DECODE].spare_arg = pipeline[FETCH].instruction;
      break;
    case OPERAND:
      break;
    case EXECUTE:
      if (pipeline[EXECUTE].spare_arg == dbmr)
	tc = 1;
      else
	tc = 0;
      break;
    }
}

static void
Crgt (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      if ((long int) accumulator < (long int) accb)
	{
	  accumulator = accb;
	  c = 0;
	}
      else
	{
	  accb = accumulator;
	  c = 1;
	}
      break;
    }
}

static void
Crlt (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      if ((long int) accumulator < (long int) accb)
	{
	  accb = accumulator;
	  c = 1;
	}
      else
	{
	  accumulator = accb;
	  c = 0;
	}
      break;
    }
}

static void
Dmov (void)
{
  uint x;

  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      break;
    case EXECUTE:
      check_dmov_okay (pipeline[EXECUTE].operand_address, "DMOV");
      x = read_data_memory (pipeline[EXECUTE].operand_address);
      pipeline[EXECUTE].operand_address++;
      write_data_memory (pipeline[EXECUTE].operand_address, x);
      break;
    }
}

static void
Exar (void)
{
  long int x;

  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      x = accumulator;
      accumulator = accb;
      accb = x;
      break;
    }
}

static void
Idle (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      intm = 0;
      idle_mode = 1;
      break;
    }
}

static void
Idle2 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      intm = 0;
      idle_mode = 2;
      break;
    }
}

static void
In (void)
{
  int port_addr;

  switch (processor_phase)
    {
    case DECODE:
      pipeline[FETCH].valid = 0;
      get_operand_address (DECODE);
      break;
    case OPERAND:
      break;
    case EXECUTE:
      port_addr = pipeline[DECODE].instruction;
      if (rptc != 0)
	while (rptc != 0)
	  {
	    write_data_memory (pipeline[EXECUTE].operand_address,
			       read_io_port (port_addr));
	    port_addr++;
	    rptc--;
	    if (rptc != 0)
	      get_operand_address (EXECUTE);
	  }
      else
	write_data_memory (pipeline[EXECUTE].operand_address,
			   read_io_port (port_addr));
      break;
    }
}

/* do this later */
static void
Intr (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      break;
    }
}

static void
Lacb (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      accumulator = accb;
      break;
    }
}

static void
Lacc1 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      sign_extend_operand ();
      accumulator
	= (pipeline[EXECUTE].operand
	   << ((pipeline[EXECUTE].instruction >> 8) & 0x0F));
      break;
    }
}

static void
Lacc2 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      pipeline[FETCH].valid = 0;
      pipeline[DECODE].operand = pipeline[FETCH].instruction;
      break;
    case OPERAND:
      break;
    case EXECUTE:
      sign_extend_operand ();
      accumulator
	= (pipeline[EXECUTE].operand
	   << (pipeline[EXECUTE].instruction & 0x0F));
      break;
    }
}

static void
Lacc3 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      accumulator = pipeline[EXECUTE].operand << 16;
      break;
    }
}

static void
Lacl1 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      accumulator = pipeline[EXECUTE].operand & 0xFFFF;
      break;
    }
}

static void
Lacl2 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      accumulator = pipeline[EXECUTE].instruction & 0xFF;
      break;
    }
}

static void
Lact (void)
{
  int shift;

  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      shift = treg1 & 15;
      sign_extend_operand ();
      pipeline[EXECUTE].operand <<= shift;
      accumulator = pipeline[EXECUTE].operand;
      break;
    }
}

static void
Lamm (void)
{
  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      pipeline[DECODE].operand_address &= 0x7F;
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      accumulator = pipeline[EXECUTE].operand;
      break;
    }
}

static void
Lar1 (void)
{
  int arx;

  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      arx = (pipeline[EXECUTE].instruction >> 8) & 0x07;
      if (pipeline[EXECUTE].instruction & 0x80)
	if (check_ar_lock (arx))
	  return;
      ar[arx] = (int) pipeline[EXECUTE].operand;
      break;
    }
}

static void
Lar2 (void)
{
  int arx;

  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      arx = (pipeline[EXECUTE].instruction >> 8) & 0x07;
      ar[arx] = (int) pipeline[EXECUTE].instruction & 0xFF;
      break;
    }
}

static void
Lar3 (void)
{
  int arx;

  switch (processor_phase)
    {
    case DECODE:
      pipeline[FETCH].valid = 0;
      pipeline[DECODE].operand = pipeline[FETCH].instruction;
      break;
    case OPERAND:
      break;
    case EXECUTE:
      arx = pipeline[EXECUTE].instruction & 0x07;
      ar[arx] = (int) pipeline[EXECUTE].operand;
      break;
    }
}

static void
Ldp1 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      dp = pipeline[EXECUTE].operand & 0x1FF;
      break;
    }
}

static void
Ldp2 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      dp = pipeline[EXECUTE].instruction & 0x1FF;
      break;
    }
}

/* do this later */
static void
Lmmr (void)
{
  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      break;
    }
}

static void
Lph (void)
{
  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      p_register = (p_register & 0xFFFFL) |
	((pipeline[EXECUTE].operand << 16) & 0xFFFF0000L);
      break;
    }
}

static void
Lst1 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      break;
    }
}

static void
Lst2 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      break;
    }
}

static void
Lt (void)
{
  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      treg0 = (int) pipeline[EXECUTE].operand;
      if (!trm)
	{
	  treg1 = treg0;
	  treg2 = treg0;
	}
      break;
    }
}

static void
Lta (void)
{
  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      treg0 = (int) pipeline[EXECUTE].operand;
      if (!trm)
	{
	  treg1 = treg0;
	  treg2 = treg0;
	}
      pipeline[EXECUTE].operand = shifted_p ();
      add_operand (0);
      break;
    }
}

static void
Ltd (void)
{
  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      pipeline[OPERAND].operand
	= read_data_memory (pipeline[OPERAND].operand_address);
      break;
    case EXECUTE:
      check_dmov_okay (pipeline[EXECUTE].operand_address, "LTD");
      treg0 = pipeline[EXECUTE].operand;
      if (!trm)
	{
	  treg1 = treg0;
	  treg2 = treg0;
	}
      write_data_memory (pipeline[EXECUTE].operand_address + 1,
			 pipeline[EXECUTE].operand);
      pipeline[EXECUTE].operand = shifted_p ();
      add_operand (0);
      break;
    }
}

static void
Ltp (void)
{
  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      treg0 = (int) pipeline[EXECUTE].operand;
      if (!trm)
	{
	  treg1 = treg0;
	  treg2 = treg0;
	}
      accumulator = shifted_p ();
    }
}

static void
Lts (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      treg0 = (int) pipeline[EXECUTE].operand;
      if (!trm)
	{
	  treg1 = treg0;
	  treg2 = treg0;
	}
      pipeline[EXECUTE].operand = shifted_p ();
      sub_operand (0);
      break;
    }
}

static void
Mac (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      if (!repeating)
	pfc = read_program_memory (pc++);
      pipeline[EXECUTE].operand = shifted_p ();
      add_operand (0);
      treg0 = (int) pipeline[EXECUTE].operand;
      if (!trm)
	{
	  treg1 = treg0;
	  treg2 = treg0;
	}
      p_register = treg0;
      p_register *= read_program_memory (pfc++);
      break;
    }
}

static void
Macd (void)
{
  int a;

  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      if (!repeating)
	pfc = read_program_memory (pc++);
      pipeline[EXECUTE].operand = shifted_p ();
      add_operand (0);
      a = get_operand_address (DECODE);
      check_dmov_okay (a, "MACD");
      treg0 = read_data_memory (a);
      if (!trm)
	{
	  treg1 = treg0;
	  treg2 = treg0;
	}
      p_register = treg0;
      p_register *= read_program_memory (pfc++);
      write_data_memory (a + 1, read_data_memory (a));
      return;
    }
}

/* do this later */
static void
Madd (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      break;
    }
}

/* do this later */
static void
Mads (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      break;
    }
}

static void
Mar (void)
{
  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      break;
    case EXECUTE:
      break;
    }
}

static void
Mpy1 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      p_register = pipeline[EXECUTE].operand * treg0;
      break;
    }
}

static void
Mpy2 (void)
{
  long int x;

  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      x = pipeline[EXECUTE].instruction & 0x1FFF;
      if (x & 0x1000)
	x |= 0xFFFFF000L;
      p_register = x * treg0;
      break;
    }
}

static void
Mpy3 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      pipeline[FETCH].valid = 0;
      pipeline[DECODE].operand = pipeline[FETCH].instruction;
      break;
    case OPERAND:
      break;
    case EXECUTE:
      p_register = treg0 * pipeline[EXECUTE].operand;
      break;
    }
}


static void
Mpya (void)
{
  long int x;

  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      x = pipeline[EXECUTE].operand;
      pipeline[EXECUTE].operand = shifted_p ();
      add_operand (0);
      pipeline[EXECUTE].operand = x;
      p_register = pipeline[EXECUTE].operand * treg0;
      break;
    }
}

static void
Mpys (void)
{
  long int x;

  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      x = pipeline[EXECUTE].operand;
      pipeline[EXECUTE].operand = shifted_p ();
      sub_operand (0);
      pipeline[EXECUTE].operand = x;
      p_register = pipeline[EXECUTE].operand * treg0;
      break;
    }
}

static void
Mpyu (void)
{
  unsigned long t, d;

  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      d = pipeline[EXECUTE].operand;
      t = treg1;
      p_register = d * t;
      break;
    }
}

static void
Neg (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      c = (accumulator == 0L);
      if (accumulator == SIGN_BIT)
	{
	  if (ovm)
	    accumulator = ~SIGN_BIT;
	  ov = 1;
	}
      else
	accumulator = -accumulator;
      break;
    }
}

static void
Nmi (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      break;
    }
}

static void
Nop (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      /* fine just like this */
      break;
    }
}

static void
Norm (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      if (accumulator == 0)
	tc = 1;
      else
	{
	  if (read_bit (accumulator, 31) == read_bit (accumulator, 30))
	    {
	      tc = 0;
	      accumulator <<= 1;
	      get_operand_address (EXECUTE);
	    }
	  else
	    tc = 1;
	}
      break;
    }
}

static void
Opl1 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      write_data_memory (pipeline[EXECUTE].operand_address,
			 pipeline[EXECUTE].operand | dbmr);
      break;
    }
}

static void
Opl2 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      pipeline[FETCH].valid = 0;
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      write_data_memory (pipeline[EXECUTE].operand_address,
			 pipeline[EXECUTE].operand
			 | pipeline[OPERAND].instruction);
      break;
    }
}

static void
Or1 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      accumulator |= (pipeline[EXECUTE].operand & 0xFFFF);
      break;
    }
}

static void
Or2 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      pipeline[FETCH].valid = 0;
      break;
    case OPERAND:
      break;
    case EXECUTE:
      accumulator |= ((long int) pipeline[OPERAND].instruction)
	<< (pipeline[EXECUTE].instruction & 0x0F);
      break;
    }
}

static void
Or3 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      pipeline[FETCH].valid = 0;
      break;
    case OPERAND:
      break;
    case EXECUTE:
      accumulator |= ((long int) pipeline[OPERAND].instruction) << 16;
      break;
    }
}

static void
Orb (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      accumulator |= accb;
      break;
    }
}

static void
Out (void)
{
  int port_addr;

  switch (processor_phase)
    {
    case DECODE:
      pipeline[FETCH].valid = 0;
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      port_addr = pipeline[DECODE].instruction;
      if (rptc != 0)
	while (rptc != 0)
	  {
	    write_io_port (port_addr,
			   pipeline[EXECUTE].operand);
	    port_addr++;
	    rptc--;
	    if (rptc != 0)
	      {
		get_operand_address (EXECUTE);
		get_operand ();
	      }
	  }
      else
	write_io_port (port_addr,
		       pipeline[EXECUTE].operand);
      break;
    }
}

static void
Pac (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      accumulator = shifted_p ();
      break;
    }
}

static void
Pop (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      accumulator = c50_hardware_pop ();
      break;
    }
}

static void
Popd (void)
{
  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      break;
    case EXECUTE:
      write_data_memory (pipeline[EXECUTE].operand_address,
			 c50_hardware_pop ());
      break;
    }
}

static void
Pshd (void)
{
  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      c50_hardware_push ((int) pipeline[EXECUTE].operand);
      break;
    }
}

static void
Push (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      c50_hardware_push ((int) accumulator);
      break;
    }
}

static void
Ret (void)
{
  switch (processor_phase)
    {
    case DECODE:
      pipeline[FETCH].valid = 0;
      break;
    case OPERAND:
      pipeline[FETCH].valid = 0;
      break;
    case EXECUTE:
      pipeline[FETCH].valid = 0;
      pc = c50_hardware_pop ();
      break;
    }
}

static void
Retd (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      pipeline[FETCH].valid = 0;
      pc = c50_hardware_pop ();
      break;
    }
}

static void
Retc (void)
{
  switch (processor_phase)
    {
    case DECODE:

      /* If we test the flags here, is that meaningful? But if we don't
       * test the flags here, we won't know that we should bomb the next
       * three instructions until it's too late. Some of them might try
       * to do ARAU operations in the meanwhile.
       *
       * One solution is to maintain multiple sets of registers to
       * represent the different ways the processor could go over 3 or 4
       * instructions. There can't really be 8 or 16 sets of registers.
       *
       * We'll face the same dilemma with the Cc instruction, or any
       * other conditional non-delayed thing.
       */

      pipeline[DECODE].spare_arg
	= bcnd_helper (pipeline[DECODE].instruction);
      if (pipeline[DECODE].spare_arg)
	pipeline[FETCH].valid = 0;
      break;
    case OPERAND:
      if (pipeline[OPERAND].spare_arg)
	pipeline[FETCH].valid = 0;
      break;
    case EXECUTE:
      if (pipeline[EXECUTE].spare_arg)
	{
	  pipeline[FETCH].valid = 0;
	  pc = c50_hardware_pop ();
	}
      break;
    }
}

static void
Retcd (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      if (bcnd_helper (pipeline[EXECUTE].instruction))
	{
	  pipeline[FETCH].valid = 0;
	  pc = c50_hardware_pop ();
	}
      break;
    }
}

/* do this later */
static void
Rete (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      break;
    }
}

/* do this later */
static void
Reti (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      break;
    }
}

static void
Rol (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      if (accumulator & SIGN_BIT)
	{
	  accumulator = (accumulator << 1) + c;
	  c = 1;
	}
      else
	{
	  accumulator = (accumulator << 1) + c;
	  c = 0;
	}
      break;
    }
}

static void
Rolb (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      if (accumulator & SIGN_BIT)
	{
	  if (accb & SIGN_BIT)
	    {
	      accb = (accb << 1) + c;
	      accumulator = (accumulator << 1) + 1;
	    }
	  else
	    {
	      accb = (accb << 1) + c;
	      accumulator = (accumulator << 1);
	    }
	  c = 1;
	}
      else
	{
	  if (accb & SIGN_BIT)
	    {
	      accb = (accb << 1) + c;
	      accumulator = (accumulator << 1) + 1;
	    }
	  else
	    {
	      accb = (accb << 1) + c;
	      accumulator = (accumulator << 1);
	    }
	  c = 0;
	}
      break;
    }
}

static void
Ror (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      if (accumulator & 1)
	{
	  accumulator = (accumulator >> 1) + (c ? SIGN_BIT : 0);
	  c = 1;
	}
      else
	{
	  accumulator = (accumulator >> 1) + (c ? SIGN_BIT : 0);
	  c = 0;
	}
      break;
    }
}

static void
Rorb (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      if (accb & 1)
	{
	  if (accumulator & 1)
	    {
	      accumulator = (accumulator >> 1) + (c ? SIGN_BIT : 0);
	      accb = (accb >> 1) + 1;
	    }
	  else
	    {
	      accumulator = (accumulator >> 1) + (c ? SIGN_BIT : 0);
	      accb = (accb >> 1) + 0;
	    }
	  c = 1;
	}
      else
	{
	  if (accumulator & 1)
	    {
	      accumulator = (accumulator >> 1) + (c ? SIGN_BIT : 0);
	      accb = (accb >> 1) + 1;
	    }
	  else
	    {
	      accumulator = (accumulator >> 1) + (c ? SIGN_BIT : 0);
	      accb = (accb >> 1) + 0;
	    }
	  c = 0;
	}
      break;
    }
}

static void
Rpt1 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      rptc = (int) pipeline[OPERAND].operand + 1;
      repeating = 1;
      break;
    case EXECUTE:
      break;
    }
}

static void
Rpt2 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      pipeline[FETCH].valid = 0;
      break;
    case OPERAND:
      rptc = pipeline[DECODE].instruction + 1;
      repeating = 1;
      break;
    case EXECUTE:
      break;
    }
}

static void
Rpt3 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      rptc = (pipeline[OPERAND].instruction & 0xFF) + 1;
      repeating = 1;
      break;
    case EXECUTE:
      break;
    }
}

static void
Rptb (void)
{
  switch (processor_phase)
    {
    case DECODE:
      pipeline[FETCH].valid = 0;
      break;
    case OPERAND:
      pipeline[OPERAND].spare_arg = pc;
      break;
    case EXECUTE:
      braf = 1;			/* what the hell is braf?? */
      pasr = pipeline[EXECUTE].spare_arg;
      paer = pipeline[OPERAND].instruction;
      break;
    }
}

static void
Rptz (void)
{
  switch (processor_phase)
    {
    case DECODE:
      pipeline[FETCH].valid = 0;
      break;
    case OPERAND:
      break;
    case EXECUTE:
      accumulator = 0;
      p_register = 0;
      rptc = pipeline[OPERAND].instruction;
      repeating = 1;
      break;
    }
}

static void
Sacb (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      accb = accumulator;
      break;
    }
}

static void
Sach (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      pipeline[EXECUTE].operand = accumulator;
      pipeline[EXECUTE].operand
	<<= (pipeline[EXECUTE].instruction >> 8) & 7;
      write_data_memory (pipeline[EXECUTE].operand_address,
			 (int) (pipeline[EXECUTE].operand >> 16));
      break;
    }
}

static void
Sacl (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      pipeline[EXECUTE].operand = accumulator;
      pipeline[EXECUTE].operand
	<<= (pipeline[EXECUTE].instruction >> 8) & 7;
      write_data_memory (pipeline[EXECUTE].operand_address,
			 (int) pipeline[EXECUTE].operand);
      break;
    }
}

static void
Samm (void)
{
  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      pipeline[DECODE].operand_address &= 0x7F;
      break;
    case OPERAND:
      break;
    case EXECUTE:
      if (check_ar_lock (pipeline[EXECUTE].operand_address - 0x10))
	return;
      write_data_memory (pipeline[EXECUTE].operand_address,
			 (int) accumulator);
      break;
    }
}

static void
Sar (void)
{
  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      break;
    case EXECUTE:
      write_data_memory (pipeline[EXECUTE].operand_address,
			 ar[(pipeline[EXECUTE].instruction >> 8) & 7]);
      break;
    }
}

static void
Sath (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      if (treg1 & 0x10)
	accumulator <<= 16;
      break;
    }
}

static void
Satl (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      accumulator <<= (treg1 & 0x0F);
      break;
    }
}

static void
Sbb (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      pipeline[EXECUTE].operand = accb;
      sub_operand (0);
      break;
    }
}

static void
Sbbb (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      pipeline[EXECUTE].operand = accb;
      sub_operand (c);
      break;
    }
}

static void
Sbrk (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      if (!ar_lock[arp])
	ar[arp] -= pipeline[EXECUTE].instruction & 0xFF;
      break;
    }
}

static void
Setc_ovm (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      ovm = 1;
      break;
    }
}

static void
Setc_sxm (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      sxm = 1;
      break;
    }
}

static void
Setc_hm (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      hm = 1;
      break;
    }
}

static void
Setc_tc (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      tc = 1;
      break;
    }
}

static void
Setc_c (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      c = 1;
      break;
    }
}

static void
Setc_cnf (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      cnf = 1;
      break;
    }
}

static void
Setc_intm (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      intm = 1;
      break;
    }
}

static void
Setc_xf (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      xf = 1;
      break;
    }
}

static void
Sfl (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      c = (accumulator * SIGN_BIT) ? 1 : 0;
      accumulator <<= 1;
      break;
    }
}

static void
Sflb (void)
{
  int x;

  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      x = (accb * SIGN_BIT) ? 1 : 0;
      accb <<= 1;
      c = (accumulator * SIGN_BIT) ? 1 : 0;
      accumulator = (accumulator << 1) + x;
      break;
    }
}

static void
Sfr (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      c = accumulator & 1;
      if (sxm && (accumulator & SIGN_BIT))
	accumulator = SIGN_BIT | (accumulator >> 1);
      else
	accumulator >>= 1;
      break;
    }
}

static void
Sfrb (void)
{
  int x;

  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      x = accumulator & 1;
      if (sxm && (accumulator & SIGN_BIT))
	accumulator = SIGN_BIT | (accumulator >> 1);
      else
	accumulator >>= 1;
      c = accb & 1;
      accb = (accumulator >> 1) + (x ? SIGN_BIT : 0);
      break;
    }
}

static void
Smmr (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      break;
    }
}

static void
Spac (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      pipeline[EXECUTE].operand = shifted_p ();
      sub_operand (0);
      break;
    }
}

static void
Sph (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      pipeline[EXECUTE].operand = shifted_p ();
      write_data_memory (pipeline[EXECUTE].operand_address,
			 (int) (pipeline[EXECUTE].operand >> 16));
      break;
    }
}

static void
Spl (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      pipeline[EXECUTE].operand = shifted_p ();
      write_data_memory (pipeline[EXECUTE].operand_address,
			 (int) pipeline[EXECUTE].operand);
      break;
    }
}

static void
Splk (void)
{
  switch (processor_phase)
    {
    case DECODE:
      pipeline[FETCH].valid = 0;
      get_operand_address (DECODE);
      break;
    case OPERAND:
      break;
    case EXECUTE:
      write_data_memory (pipeline[EXECUTE].operand_address,
			 pipeline[OPERAND].instruction);
      break;
    }
}

static void
Spm (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      pm = pipeline[EXECUTE].instruction & 3;
      break;
    }
}

static void
Sqra (void)
{
  long int x;

  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      x = pipeline[EXECUTE].operand;
      pipeline[EXECUTE].operand = shifted_p ();
      add_operand (0);
      treg1 = (int) x;
      p_register = treg1;
      p_register *= p_register;
      break;
    }
}

static void
Sqrs (void)
{
  long int x;

  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      x = pipeline[EXECUTE].operand;
      pipeline[EXECUTE].operand = shifted_p ();
      sub_operand (0);
      treg1 = (int) x;
      p_register = treg1;
      p_register *= p_register;
      break;
    }
}

static void
Sst1 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      break;
    }
}

static void
Sst2 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      break;
    }
}

static void
Sub1 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      sign_extend_operand ();
      pipeline[EXECUTE].operand
	<<= (pipeline[EXECUTE].instruction >> 8) & 0x0F;
      sub_operand (0);
      break;
    }
}

static void
Sub2 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      pipeline[EXECUTE].operand <<= 16;
      add_operand (0);
      break;
    }
}

static void
Sub3 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      pipeline[EXECUTE].operand = pipeline[EXECUTE].instruction & 0xFF;
      sub_operand (0);
      break;
    }
}

static void
Sub4 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      pipeline[FETCH].valid = 0;
      break;
    case OPERAND:
      break;
    case EXECUTE:
      pipeline[EXECUTE].operand = pipeline[OPERAND].instruction;
      sign_extend_operand ();
      pipeline[EXECUTE].operand
	<<= (pipeline[EXECUTE].instruction & 0x0F);
      add_operand (0);
      break;
    }
}

static void
Subb (void)
{
  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      sub_operand (c);
      break;
    }
}

static void
Subc (void)
{
  long int alu_out;

  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      sign_extend_operand ();
      pipeline[EXECUTE].operand <<= 15;
      alu_out = accumulator - pipeline[EXECUTE].operand;
      if (alu_out >= 0)
	accumulator = (alu_out << 1) + 1;
      else
	accumulator <<= 1;
      break;
    }
}

static void
Subs (void)
{
  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      sub_operand (0);
      break;
    }
}

static void
Subt (void)
{
  int shift;

  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      shift = treg1 & 15;
      pipeline[EXECUTE].operand <<= shift;
      sub_operand (0);
      break;
    }
}

static void
Tblr (void)
{
  int mcs;

  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      break;
    case EXECUTE:
      mcs = pfc;
      pfc = accumulator & 0xFF;
      if (rptc != 0)
	while (rptc != 0)
	  {
	    write_data_memory (pipeline[EXECUTE].operand_address,
			       read_program_memory (pfc));
	    pfc++;
	    rptc--;
	    if (rptc != 0)
	      get_operand_address (EXECUTE);
	  }
      else
	write_data_memory (pipeline[EXECUTE].operand_address,
			   read_program_memory (pfc));
      pfc = mcs;
      break;
    }
}

static void
Tblw (void)
{
  int mcs;

  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      break;
    case EXECUTE:
      mcs = pfc;
      pfc = accumulator & 0xFF;
      if (rptc != 0)
	while (rptc != 0)
	  {
	    write_program_memory
	      (pfc,
	       read_data_memory (pipeline[EXECUTE].operand_address));
	    pfc++;
	    rptc--;
	    if (rptc != 0)
	      get_operand_address (EXECUTE);
	  }
      else
	write_program_memory
	  (pfc,
	   read_data_memory (pipeline[EXECUTE].operand_address));
      pfc = mcs;
      break;
    }
}

static void
Xc (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      break;
    }
}

static void
Xor1 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      accumulator ^= (pipeline[EXECUTE].operand & 0xFFFF);
      break;
    }
}

static void
Xor2 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      pipeline[FETCH].valid = 0;
      break;
    case OPERAND:
      break;
    case EXECUTE:
      accumulator ^=
	(pipeline[EXECUTE].operand
	 << (pipeline[OPERAND].instruction & 0x03));
      break;
    }
}

static void
Xor3 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      pipeline[FETCH].valid = 0;
      break;
    case OPERAND:
      break;
    case EXECUTE:
      accumulator ^= pipeline[EXECUTE].operand << 16;
      break;
    }
}

static void
Xorb (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      accumulator ^= accb;
      break;
    }
}

static void
Xpl1 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      write_data_memory (pipeline[EXECUTE].operand_address,
			 pipeline[EXECUTE].operand ^ dbmr);
      break;
    }
}

static void
Xpl2 (void)
{
  switch (processor_phase)
    {
    case DECODE:
      pipeline[FETCH].valid = 0;
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      write_data_memory (pipeline[EXECUTE].operand_address,
			 pipeline[EXECUTE].operand
			 ^ pipeline[EXECUTE].instruction);
      break;
    }
}

static void
Zalr (void)
{
  switch (processor_phase)
    {
    case DECODE:
      get_operand_address (DECODE);
      break;
    case OPERAND:
      get_operand ();
      break;
    case EXECUTE:
      accumulator = (pipeline[EXECUTE].operand << 16) + 0x8000L;
      break;
    }
}

static void
Zap (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      accumulator = 0;
      p_register = 0;
      break;
    }
}

static void
Zpr (void)
{
  switch (processor_phase)
    {
    case DECODE:
      break;
    case OPERAND:
      break;
    case EXECUTE:
      p_register = 0;
      break;
    }
}
Modified: Sat Mar 30 17:00:00 1996 GMT
Page accessed 1228 times since Sat Apr 17 22:02:50 1999 GMT