|
/* =======================================================================
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;
}
}
|