mirror of
https://github.com/aap/pdp6.git
synced 2026-01-11 23:53:31 +00:00
3657 lines
78 KiB
C
3657 lines
78 KiB
C
#include "pdp6.h"
|
|
#include <unistd.h>
|
|
|
|
// Schematics don't have USER IOT implemented fully
|
|
#define FIX_USER_IOT
|
|
// Schematics have a bug in the divide subroutine
|
|
#define FIX_DS
|
|
// flow diagrams have it, block diagrams don't.
|
|
// should guard against firing MC RS T0 twice
|
|
// on MEM CONT when RUN is 0. Although clearing
|
|
// the SBR FF probably prevents the same after MC RS T1
|
|
#define FIX_MEMSTOP
|
|
|
|
int loginst;
|
|
|
|
enum Opcode {
|
|
FSC = 0132,
|
|
IBP = 0133,
|
|
CAO = 0133,
|
|
LDCI = 0134,
|
|
LDC = 0135,
|
|
DPCI = 0136,
|
|
DPC = 0137,
|
|
ASH = 0240,
|
|
ROT = 0241,
|
|
LSH = 0242,
|
|
ASHC = 0244,
|
|
ROTC = 0245,
|
|
LSHC = 0246,
|
|
EXCH = 0250,
|
|
BLT = 0251,
|
|
AOBJP = 0252,
|
|
AOBJN = 0253,
|
|
JRST = 0254,
|
|
JFCL = 0255,
|
|
XCT = 0256,
|
|
PUSHJ = 0260,
|
|
PUSH = 0261,
|
|
POP = 0262,
|
|
POPJ = 0263,
|
|
JSR = 0264,
|
|
JSP = 0265,
|
|
JSA = 0266,
|
|
JRA = 0267,
|
|
|
|
BLKI = 0700000,
|
|
DATAI = 0700040,
|
|
BLKO = 0700100,
|
|
DATAO = 0700140,
|
|
CONO = 0700200,
|
|
CONI = 0700240,
|
|
CONSZ = 0700300,
|
|
CONSO = 0700340
|
|
|
|
};
|
|
|
|
#define declpulse(p) \
|
|
static void p##_p(Apr *apr); \
|
|
static Pulse p = { (void (*)(void*))p##_p, #p }
|
|
|
|
#define defpulse_(p) \
|
|
static void p##_p(Apr *apr)
|
|
|
|
#define defpulse(p) \
|
|
declpulse(p); \
|
|
defpulse_(p)
|
|
|
|
static void aprcycle(void *p);
|
|
static void wake_cpa(void *dev);
|
|
static void wake_pi(void *dev);
|
|
|
|
char *apr_ident = APR_IDENT;
|
|
|
|
/*
|
|
* Pulse system
|
|
*/
|
|
|
|
static void
|
|
pfree(Apr *apr, TPulse *p)
|
|
{
|
|
p->next = apr->pfree;
|
|
apr->pfree = p;
|
|
}
|
|
|
|
/* Add a pulse to the list.
|
|
* NB: does *not* check if pulse is already queued. */
|
|
static void
|
|
pulse(Apr *apr, Pulse *p, int t)
|
|
{
|
|
TPulse *tp, **pp;
|
|
|
|
// IDEA execute pulse directly if t == 0
|
|
// currently this would break stuff, but maybe it can be fixed
|
|
|
|
assert(apr->pfree);
|
|
tp = apr->pfree;
|
|
apr->pfree = tp->next;
|
|
tp->p = p;
|
|
tp->t = t;
|
|
for(pp = &apr->pulse; *pp; pp = &(*pp)->next){
|
|
if(tp->t < (*pp)->t){
|
|
(*pp)->t -= tp->t;
|
|
break;
|
|
}
|
|
tp->t -= (*pp)->t;
|
|
}
|
|
tp->next = *pp;
|
|
*pp = tp;
|
|
}
|
|
|
|
/* Remove pulse from list. Only first. */
|
|
static void
|
|
rempulse(Apr *apr, Pulse *p)
|
|
{
|
|
TPulse *tp, **pp;
|
|
|
|
for(pp = &apr->pulse; *pp; pp = &(*pp)->next)
|
|
if((*pp)->p == p){
|
|
tp = *pp;
|
|
*pp = tp->next;
|
|
pfree(apr, tp);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
pprint(Apr *apr)
|
|
{
|
|
int t;
|
|
TPulse *p;
|
|
|
|
t = 0;
|
|
for(p = apr->pulse; p; p = p->next){
|
|
t += p->t;
|
|
trace("%s %d %d\n", p->p->n, p->t, t);
|
|
}
|
|
}
|
|
|
|
static void
|
|
tracechange(Apr *apr)
|
|
{
|
|
static char buf[256], *p;
|
|
|
|
p = buf;
|
|
if(apr->c.ar != apr->n.ar)
|
|
p += sprintf(p, " AR/%012lo", apr->n.ar);
|
|
if(apr->c.mb != apr->n.mb)
|
|
p += sprintf(p, " MB/%012lo", apr->n.mb);
|
|
if(apr->c.mq != apr->n.mq)
|
|
p += sprintf(p, " MQ/%012lo", apr->n.mq);
|
|
if(p != buf)
|
|
trace("%s\n", buf);
|
|
}
|
|
|
|
static void
|
|
tracestate(Apr *apr)
|
|
{
|
|
trace("AR/%012lo MQ/%012lo.%d MB/%012lo MA/%06o SC/%03o FE/%03o\n",
|
|
apr->c.ar, apr->c.mq, apr->mq36, apr->c.mb,
|
|
apr->ma, apr->sc, apr->fe);
|
|
}
|
|
|
|
static int
|
|
stepone(Apr *apr)
|
|
{
|
|
int i;
|
|
TPulse *p;
|
|
|
|
p = apr->pulse;
|
|
if(p == nil) return 0;
|
|
apr->pulse = p->next;
|
|
trace("pulse %s\n", p->p->n);
|
|
p->p->f(apr);
|
|
pfree(apr, p);
|
|
|
|
i = 1;
|
|
while(apr->pulse && apr->pulse->t == 0){
|
|
p = apr->pulse;
|
|
apr->pulse = p->next;
|
|
trace("pulse %s\n", p->p->n);
|
|
pfree(apr, p);
|
|
p->p->f(apr);
|
|
i++;
|
|
}
|
|
// tracechange(apr);
|
|
apr->c = apr->n;
|
|
tracestate(apr);
|
|
return i;
|
|
}
|
|
|
|
|
|
|
|
// TODO This is WIP
|
|
// TODO: can't set switches with real panel connected
|
|
|
|
#define EXDEPREGS \
|
|
X(ir)\
|
|
X(mi)\
|
|
X(data)\
|
|
X(pc)\
|
|
X(ma)\
|
|
X(mas)
|
|
#define EXDEPSREGS \
|
|
X(mb)\
|
|
X(ar)\
|
|
X(mq)
|
|
|
|
static word
|
|
ex_apr(Device *dev, const char *reg)
|
|
{
|
|
Apr *apr = (Apr*)dev;
|
|
#define X(name) if(strcmp(#name, reg) == 0) return apr->name;
|
|
EXDEPREGS
|
|
#undef X
|
|
#define X(name) if(strcmp(#name, reg) == 0) return apr->c.name;
|
|
EXDEPSREGS
|
|
#undef X
|
|
return ~0;
|
|
}
|
|
static int
|
|
dep_apr(Device *dev, const char *reg, word data)
|
|
{
|
|
Apr *apr = (Apr*)dev;
|
|
#define X(name) if(strcmp(#name, reg) == 0) { apr->name = data; return 0; }
|
|
EXDEPREGS
|
|
#undef X
|
|
#define X(name) if(strcmp(#name, reg) == 0) { apr->n.name = data; return 0; }
|
|
EXDEPSREGS
|
|
#undef X
|
|
if(strcmp("log", reg) == 0) { loginst = data; return 0; }
|
|
return 1;
|
|
}
|
|
|
|
static Device aprproto = {
|
|
nil, nil, "",
|
|
nil, nil,
|
|
nil,
|
|
ex_apr, dep_apr
|
|
};
|
|
|
|
Device*
|
|
makeapr(int argc, char *argv[])
|
|
{
|
|
Apr *apr;
|
|
Task t;
|
|
|
|
apr = malloc(sizeof(Apr));
|
|
memset(apr, 0, sizeof(Apr));
|
|
|
|
apr->dev = aprproto;
|
|
apr->dev.type = apr_ident;
|
|
|
|
apr->iobus.dev[CPA] = (Busdev){ apr, wake_cpa, 0 };
|
|
apr->iobus.dev[PI] = (Busdev){ apr, wake_pi, 0 };
|
|
|
|
t = (Task){ nil, aprcycle, apr, 1, 0 };
|
|
addtask(t);
|
|
|
|
apr->clkchan = chancreate(sizeof(int), 1);
|
|
apr->rptchan = chancreate(sizeof(int), 1);
|
|
|
|
return &apr->dev;
|
|
}
|
|
|
|
|
|
|
|
#define DBG_AR debug("AR: %012llo\n", apr->ar)
|
|
#define DBG_MB debug("MB: %012llo\n", apr->mb)
|
|
#define DBG_MQ debug("MQ: %012llo\n", apr->mq)
|
|
#define DBG_MA debug("MA: %06o\n", apr->ma)
|
|
#define DBG_IR debug("IR: %06o\n", apr->ir)
|
|
|
|
#define SWAP(a, b) apr->n.a = apr->c.b, apr->n.b = apr->c.a
|
|
#define SWAPLTRT(a) ((a)<<18 & LT | (a)>>18 & RT)
|
|
#define CONS(a, b) ((a)< | (b)&RT)
|
|
|
|
// 6-10
|
|
#define AR_OV_SET (apr->ar_cry0 != apr->ar_cry1)
|
|
#define AR0_XOR_AROV (!!(apr->c.ar & F0) != apr->ar_cry0_xor_cry1)
|
|
#define AR0_XOR_AR1 (!!(apr->c.ar & F0) != !!(apr->c.ar & F1))
|
|
#define AR0_XOR_MB0 (!!(apr->c.ar & F0) != !!(apr->c.mb & F0))
|
|
#define AR0_EQ_SC0 (!!(apr->c.ar & F0) == !!(apr->sc & 0400))
|
|
#define AR_EQ_FP_HALF ((apr->c.ar & 0377777777) == 0 && apr->c.ar & F9)
|
|
#define SET_OVERFLOW apr->ar_ov_flag = 1, recalc_cpa_req(apr)
|
|
|
|
// 6-13
|
|
#define MQ35_XOR_MB0 (!!(apr->c.mq & F35) != !!(apr->c.mb & F0))
|
|
|
|
/*
|
|
* I'm a bit inconsistent with the decoding.
|
|
* Some things are cached in variables,
|
|
* some are macros...or not even that.
|
|
*/
|
|
|
|
// 5-8
|
|
#define IR_FPCH ((apr->inst & 0700) == 0100)
|
|
|
|
// 6-19
|
|
#define CH_INC ((apr->inst == CAO || apr->inst == LDCI || apr->inst == DPCI) && !apr->chf5)
|
|
#define CH_INC_OP (CH_INC && !apr->chf7)
|
|
#define CH_N_INC_OP ((apr->inst == LDC || apr->inst == DPC) && !apr->chf5 ||\
|
|
CH_INC && apr->chf7)
|
|
// 6-20
|
|
#define CH_LOAD ((apr->inst == LDCI || apr->inst == LDC) && apr->chf5)
|
|
#define CH_DEP ((apr->inst == DPCI || apr->inst == DPC) && apr->chf5)
|
|
|
|
// 5-8
|
|
#define IR_FP ((apr->inst & 0740) == 0140)
|
|
#define IR_FAD ((apr->inst & 0770) == 0140)
|
|
#define IR_FSB ((apr->inst & 0770) == 0150)
|
|
#define IR_FMP ((apr->inst & 0770) == 0160)
|
|
#define IR_FDV ((apr->inst & 0770) == 0170)
|
|
#define IR_FP_DIR ((apr->inst & 0743) == 0140)
|
|
#define IR_FP_REM ((apr->inst & 0743) == 0141)
|
|
#define IR_FP_MEM ((apr->inst & 0743) == 0142)
|
|
#define IR_FP_BOTH ((apr->inst & 0743) == 0143)
|
|
|
|
// 5-8
|
|
#define FWT_MOVS ((apr->inst & 0770) == 0200)
|
|
#define FWT_MOVNM ((apr->inst & 0770) == 0210)
|
|
// 5-9
|
|
#define FWT_SWAP (apr->ir_fwt && (apr->inst & 014) == 004)
|
|
#define FWT_NEGATE (FWT_MOVNM && ((apr->inst & 04) == 0 || apr->c.ar & SGN))
|
|
|
|
// 5-8
|
|
#define IR_MUL ((apr->inst & 0770) == 0220)
|
|
#define IR_DIV ((apr->inst & 0770) == 0230)
|
|
#define IR_MD_FC_E (apr->ir_md && (apr->inst & 03) != 1)
|
|
#define IR_MD_FAC2 (IR_DIV && apr->ir & H6)
|
|
#define IR_MD_SC_E (apr->ir_md && apr->ir & H7)
|
|
#define IR_MD_SAC_INH (apr->ir_md && (apr->ir & (H7|H8)) == H7)
|
|
#define IR_MD_SAC2 ((IR_DIV || IR_MUL && apr->ir & H6) && !IR_MD_SAC_INH)
|
|
|
|
// 6-20
|
|
#define SH_AC2 (apr->inst == ASHC || apr->inst == ROTC || apr->inst == LSHC)
|
|
|
|
// 5-10
|
|
#define AS_ADD (apr->ir_as && !(apr->ir & H6))
|
|
#define AS_SUB (apr->ir_as && apr->ir & H6)
|
|
|
|
// 5-8
|
|
#define IR_254_7 ((apr->inst & 0774) == 0254)
|
|
// 6-18
|
|
#define BLT_DONE (apr->pi_req || !(apr->c.mq & F0))
|
|
#define BLT_LAST (apr->inst == BLT && !(apr->c.mq & F0))
|
|
|
|
// 5-10
|
|
#define JP_JMP (apr->ir_jp && apr->inst != PUSH && apr->inst != POP)
|
|
#define JP_FLAG_STOR (apr->inst == PUSHJ || apr->inst == JSR || apr->inst == JSP)
|
|
// 6-3
|
|
#define MB_PC_STO (apr->inst == PUSHJ || apr->inst == JSR || \
|
|
apr->inst == JSP || apr->ir_jrst)
|
|
|
|
// 5-9
|
|
#define IR_ACCP_MEMAC ((apr->inst & 0700) == 0300)
|
|
#define ACCP ((apr->inst & 0760) == 0300)
|
|
#define ACCP_DIR (ACCP && apr->inst & 010)
|
|
#define MEMAC_TST ((apr->inst & 0760) == 0320)
|
|
#define MEMAC_P1 ((apr->inst & 0760) == 0340)
|
|
#define MEMAC_M1 ((apr->inst & 0760) == 0360)
|
|
#define MEMAC (MEMAC_TST || MEMAC_P1 || MEMAC_M1)
|
|
#define MEMAC_MEM (MEMAC && apr->inst & 010)
|
|
#define MEMAC_AC (MEMAC && (apr->inst & 010) == 0)
|
|
#define ACCP_ETC_COND (IR_ACCP_MEMAC && apr->ir & H8 && AR0_XOR_AROV || \
|
|
(apr->ir & H7) && apr->c.ar == 0)
|
|
#define ACCP_ET_AL_TEST (ACCP_ETC_COND != !!(apr->ir & H6))
|
|
|
|
// 5-9
|
|
#define HWT_LT (apr->ir_hwt && !(apr->inst & 040))
|
|
#define HWT_RT (apr->ir_hwt && apr->inst & 040)
|
|
#define HWT_SWAP (apr->ir_hwt && apr->inst & 04)
|
|
#define HWT_AR_0 (apr->ir_hwt && apr->inst & 030)
|
|
#define HWT_LT_SET (HWT_RT && apr->inst & 020 &&\
|
|
(!(apr->inst & 010) || apr->c.mb & RSGN))
|
|
#define HWT_RT_SET (HWT_LT && apr->inst & 020 &&\
|
|
(!(apr->inst & 010) || apr->c.mb & SGN))
|
|
|
|
// 5-9
|
|
#define ACBM_DIR (apr->ir_acbm && apr->inst & 010)
|
|
#define ACBM_SWAP (apr->ir_acbm && apr->inst & 01)
|
|
#define ACBM_DN (apr->ir_acbm && (apr->inst & 060) == 000)
|
|
#define ACBM_CL (apr->ir_acbm && (apr->inst & 060) == 020)
|
|
#define ACBM_COM (apr->ir_acbm && (apr->inst & 060) == 040)
|
|
#define ACBM_SET (apr->ir_acbm && (apr->inst & 060) == 060)
|
|
|
|
// 5-8
|
|
#define UUO_A ((apr->inst & 0700) == 0)
|
|
#define IOT_A ((apr->inst & 0700) == 0700)
|
|
#define JRST_A (apr->inst == JRST)
|
|
|
|
// 8-1
|
|
#define IOT_BLKI (apr->ir_iot && apr->io_inst == BLKI)
|
|
#define IOT_DATAI (apr->ir_iot && apr->io_inst == DATAI)
|
|
#define IOT_BLKO (apr->ir_iot && apr->io_inst == BLKO)
|
|
#define IOT_DATAO (apr->ir_iot && apr->io_inst == DATAO)
|
|
#define IOT_CONO (apr->ir_iot && apr->io_inst == CONO)
|
|
#define IOT_CONI (apr->ir_iot && apr->io_inst == CONI)
|
|
#define IOT_CONSZ (apr->ir_iot && apr->io_inst == CONSZ)
|
|
#define IOT_CONSO (apr->ir_iot && apr->io_inst == CONSO)
|
|
#define IOT_BLK (apr->ir_iot && (apr->io_inst == BLKI || apr->io_inst == BLKO))
|
|
#define IOT_OUTGOING (apr->ir_iot && (apr->io_inst == DATAO || apr->io_inst == CONO))
|
|
#define IOT_STATUS (apr->ir_iot && \
|
|
(apr->io_inst == CONI || apr->io_inst == CONSZ || apr->io_inst == CONSO))
|
|
#define IOT_DATAIO (apr->ir_iot && (apr->io_inst == DATAI || apr->io_inst == DATAO))
|
|
|
|
void
|
|
decodeir(Apr *apr)
|
|
{
|
|
apr->inst = apr->ir>>9 & 0777;
|
|
apr->io_inst = apr->ir & 0700340;
|
|
|
|
// 5-7
|
|
apr->iobus.c34 &= ~037777000000LL;
|
|
apr->iobus.c34 |= apr->ir & H3 ? IOBUS_IOS3_1 : IOBUS_IOS3_0;
|
|
apr->iobus.c34 |= apr->ir & H4 ? IOBUS_IOS4_1 : IOBUS_IOS4_0;
|
|
apr->iobus.c34 |= apr->ir & H5 ? IOBUS_IOS5_1 : IOBUS_IOS5_0;
|
|
apr->iobus.c34 |= apr->ir & H6 ? IOBUS_IOS6_1 : IOBUS_IOS6_0;
|
|
apr->iobus.c34 |= apr->ir & H7 ? IOBUS_IOS7_1 : IOBUS_IOS7_0;
|
|
apr->iobus.c34 |= apr->ir & H8 ? IOBUS_IOS8_1 : IOBUS_IOS8_0;
|
|
apr->iobus.c34 |= apr->ir & H9 ? IOBUS_IOS9_1 : IOBUS_IOS9_0;
|
|
|
|
apr->ir_fp = (apr->inst & 0740) == 0140;
|
|
|
|
/* 2xx */
|
|
apr->ir_fwt = FWT_MOVS || FWT_MOVNM;
|
|
apr->fwt_00 = apr->fwt_01 = apr->fwt_10 = apr->fwt_11 = 0;
|
|
if(apr->ir_fwt){
|
|
// 5-9
|
|
apr->fwt_00 = (apr->inst & 03) == 0;
|
|
apr->fwt_01 = (apr->inst & 03) == 1;
|
|
apr->fwt_10 = (apr->inst & 03) == 2;
|
|
apr->fwt_11 = (apr->inst & 03) == 3;
|
|
}
|
|
apr->ir_md = (apr->inst & 0760) == 0220;
|
|
apr->shift_op = (apr->inst & 0770) == 0240 &&
|
|
(apr->inst & 03) != 3; // 6-20
|
|
apr->ir_jp = (apr->inst & 0770) == 0260;
|
|
apr->ir_as = (apr->inst & 0770) == 0270;
|
|
|
|
/* BOOLE */
|
|
apr->boole_as_00 = apr->boole_as_01 = 0;
|
|
apr->boole_as_10 = apr->boole_as_11 = 0;
|
|
apr->ir_boole = (apr->inst & 0700) == 0400; // 5-8
|
|
if(apr->ir_boole)
|
|
apr->ir_boole_op = apr->inst>>2 & 017;
|
|
|
|
/* HWT */
|
|
apr->hwt_00 = apr->hwt_01 = apr->hwt_10 = apr->hwt_11 = 0;
|
|
apr->ir_hwt = (apr->inst & 0700) == 0500; // 5-8
|
|
if(apr->ir_hwt){
|
|
// 5-9
|
|
apr->hwt_00 = (apr->inst & 03) == 0;
|
|
apr->hwt_01 = (apr->inst & 03) == 1;
|
|
apr->hwt_10 = (apr->inst & 03) == 2;
|
|
apr->hwt_11 = (apr->inst & 03) == 3;
|
|
}
|
|
|
|
if(apr->ir_boole || apr->ir_as){
|
|
apr->boole_as_00 = (apr->inst & 03) == 0;
|
|
apr->boole_as_01 = (apr->inst & 03) == 1;
|
|
apr->boole_as_10 = (apr->inst & 03) == 2;
|
|
apr->boole_as_11 = (apr->inst & 03) == 3;
|
|
}
|
|
|
|
/* ACBM */
|
|
apr->ir_acbm = (apr->inst & 0700) == 0600; // 5-8
|
|
|
|
// 5-13
|
|
apr->ex_ir_uuo =
|
|
UUO_A && apr->ex_uuo_sync ||
|
|
IOT_A && !apr->ex_pi_sync && apr->ex_user && !apr->cpa_iot_user ||
|
|
JRST_A && (apr->ir & 0000600) && apr->ex_user;
|
|
apr->ir_jrst = !apr->ex_ir_uuo && JRST_A; // 5-8
|
|
apr->ir_iot = !apr->ex_ir_uuo && IOT_A; // 5-8
|
|
}
|
|
|
|
void recalc_cpa_req(Apr *apr);
|
|
|
|
/*
|
|
* AR control signals
|
|
*/
|
|
|
|
#define ARLT_CLEAR apr->n.ar &= RT
|
|
#define ARRT_CLEAR apr->n.ar &= LT
|
|
#define AR_CLEAR apr->n.ar = 0
|
|
#define ARLT_COM apr->n.ar ^= LT
|
|
#define ARRT_COM apr->n.ar ^= RT
|
|
#define AR_COM apr->n.ar ^= FW
|
|
#define ARLT_FM_MB_J apr->n.ar = CONS(apr->c.mb, apr->n.ar)
|
|
#define ARRT_FM_MB_J apr->n.ar = CONS(apr->n.ar, apr->c.mb)
|
|
|
|
void
|
|
ar_jfcl_clr(Apr *apr)
|
|
{
|
|
// 6-10
|
|
if(apr->ir & H9) apr->ar_ov_flag = 0;
|
|
if(apr->ir & H10) apr->ar_cry0_flag = 0;
|
|
if(apr->ir & H11) apr->ar_cry1_flag = 0;
|
|
if(apr->ir & H12) apr->ar_pc_chg_flag = 0;
|
|
recalc_cpa_req(apr);
|
|
}
|
|
|
|
void
|
|
ar_cry(Apr *apr)
|
|
{
|
|
// 6-10
|
|
apr->ar_cry0_xor_cry1 = AR_OV_SET && !MEMAC;
|
|
}
|
|
|
|
void
|
|
ar_cry_in(Apr *apr, word c)
|
|
{
|
|
word a;
|
|
a = (apr->n.ar & ~F0) + c;
|
|
apr->n.ar += c;
|
|
if(apr->n.ar & FCRY) apr->ar_cry0 = 1;
|
|
if(a & F0) apr->ar_cry1 = 1;
|
|
apr->n.ar &= FW;
|
|
ar_cry(apr);
|
|
}
|
|
|
|
/*
|
|
* MB
|
|
*/
|
|
|
|
#define MBLT_CLEAR apr->n.mb &= RT
|
|
#define MB_CLEAR apr->n.mb = 0
|
|
|
|
/*
|
|
* PI control signals and helpers
|
|
*/
|
|
|
|
void
|
|
set_pi_cyc(Apr *apr, bool value)
|
|
{
|
|
apr->pi_cyc = value;
|
|
if(apr->pi_cyc)
|
|
apr->ex_pi_sync = 1; // 5-13
|
|
}
|
|
|
|
/* get highest priority request above highest currently held */
|
|
int
|
|
get_pi_req(Apr *apr)
|
|
{
|
|
// 8-3
|
|
int chan;
|
|
if(apr->pi_active)
|
|
for(chan = 0100; chan; chan >>= 1)
|
|
if(apr->pih & chan)
|
|
return 0;
|
|
else if(apr->pir & chan)
|
|
return chan;
|
|
return 0;
|
|
}
|
|
|
|
#define PIH_CLEAR apr->pih = 0
|
|
|
|
/* clear highest held break */
|
|
void
|
|
pih0_fm_pi_ok1(Apr *apr)
|
|
{
|
|
// 8-3
|
|
int chan;
|
|
if(apr->pi_active)
|
|
for(chan = 0100; chan; chan >>= 1)
|
|
if(apr->pih & chan){
|
|
apr->pih &= ~chan;
|
|
apr->pi_req = get_pi_req(apr);
|
|
return;
|
|
}
|
|
}
|
|
|
|
void
|
|
pih_fm_pi_ch_rq(Apr *apr)
|
|
{
|
|
// 8-3
|
|
apr->pih |= apr->pi_req;
|
|
apr->pir &= ~apr->pih;
|
|
apr->pi_req = get_pi_req(apr);
|
|
}
|
|
|
|
#define PIR_CLEAR apr->pir = 0
|
|
#define PIR_FM_IOB1 set_pir(apr, apr->iobus.c12 & 0177)
|
|
#define PIR_STB set_pir(apr, apr->iobus.c34 & apr->pio)
|
|
|
|
void
|
|
set_pir(Apr *apr, int pir)
|
|
{
|
|
// 8-3
|
|
apr->pir |= pir;
|
|
/* held breaks aren't retriggered */
|
|
apr->pir &= ~apr->pih;
|
|
apr->pi_req = get_pi_req(apr);
|
|
}
|
|
|
|
#define PIO_FM_IOB1 apr->pio |= apr->iobus.c12&0177
|
|
#define PIO0_FM_IOB1 apr->pio &= ~(apr->iobus.c12&0177)
|
|
|
|
/* Recalculate the PI requests on the IO bus from each device */
|
|
void
|
|
recalc_req(IOBus *bus)
|
|
{
|
|
int i;
|
|
int req;
|
|
req = 0;
|
|
for(i = 0; i < 128; i++)
|
|
req |= bus->dev[i].req;
|
|
bus->c34 = bus->c34&~0177LL | req&0177;
|
|
}
|
|
|
|
/* Decode pia into req and place it onto the bus */
|
|
void
|
|
setreq(IOBus *bus, int dev, u8 pia)
|
|
{
|
|
u8 req;
|
|
if(bus){
|
|
req = (0200>>pia) & 0177;
|
|
if(bus->dev[dev].req != req){
|
|
bus->dev[dev].req = req;
|
|
recalc_req(bus);
|
|
}
|
|
}
|
|
}
|
|
void
|
|
setreq2(IOBus *bus, int dev, u8 req)
|
|
{
|
|
req &= 0177;
|
|
if(bus && bus->dev[dev].req != req){
|
|
bus->dev[dev].req = req;
|
|
recalc_req(bus);
|
|
}
|
|
}
|
|
|
|
void
|
|
recalc_cpa_req(Apr *apr)
|
|
{
|
|
u8 pia = 0;
|
|
// 8-5
|
|
if(apr->cpa_illeg_op || apr->cpa_non_exist_mem || apr->cpa_pdl_ov ||
|
|
apr->cpa_clock_flag && apr->cpa_clock_enable ||
|
|
apr->ar_pc_chg_flag && apr->cpa_pc_chg_enable ||
|
|
apr->ar_ov_flag && apr->cpa_arov_enable)
|
|
pia = apr->cpa_pia;
|
|
setreq(&apr->iobus, CPA, pia);
|
|
}
|
|
|
|
void
|
|
set_mc_rq(Apr *apr, bool value)
|
|
{
|
|
apr->mc_rq = value; // 7-9
|
|
if(value && (apr->mc_rd || apr->mc_wr))
|
|
apr->membus.c12 |= MEMBUS_RQ_CYC;
|
|
else
|
|
apr->membus.c12 &= ~MEMBUS_RQ_CYC;
|
|
}
|
|
|
|
void
|
|
set_mc_wr(Apr *apr, bool value)
|
|
{
|
|
apr->mc_wr = value; // 7-9
|
|
if(value)
|
|
apr->membus.c12 |= MEMBUS_WR_RQ;
|
|
else
|
|
apr->membus.c12 &= ~MEMBUS_WR_RQ;
|
|
set_mc_rq(apr, apr->mc_rq); // 7-9
|
|
}
|
|
|
|
void
|
|
set_mc_rd(Apr *apr, bool value)
|
|
{
|
|
apr->mc_rd = value; // 7-9
|
|
if(value)
|
|
apr->membus.c12 |= MEMBUS_RD_RQ;
|
|
else
|
|
apr->membus.c12 &= ~MEMBUS_RD_RQ;
|
|
set_mc_rq(apr, apr->mc_rq); // 7-9
|
|
}
|
|
|
|
void
|
|
set_key_rim_sbr(Apr *apr, bool value)
|
|
{
|
|
// not sure if this is correct
|
|
apr->key_rim_sbr = value | apr->sw_rim_maint; // 5-2
|
|
}
|
|
|
|
/* Relocation
|
|
* MA is divided into 8:10 bits, the upper 8 bits (18-25) are relocated in RLA
|
|
* by adding RLR. If MA18-25 is above PR we have a relocation error. */
|
|
bool
|
|
relocate(Apr *apr)
|
|
{
|
|
u8 ma18_25;
|
|
bool ma_ok, ma_fmc_select;
|
|
|
|
ma18_25 = apr->ma>>10 & 0377;
|
|
apr->ex_inh_rel = !apr->ex_user || // 5-13
|
|
apr->ex_pi_sync ||
|
|
(apr->ma & 0777760) == 0 ||
|
|
apr->ex_ill_op;
|
|
ma_ok = ma18_25 <= apr->pr; // 7-4, PR18 OK
|
|
ma_fmc_select = !apr->key_rim_sbr && (apr->ma & 0777760) == 0; // 7-2
|
|
// 7-5
|
|
apr->rla = ma18_25;
|
|
if(!apr->ex_inh_rel)
|
|
apr->rla += apr->rlr;
|
|
|
|
// 7-2, 7-10
|
|
apr->membus.c12 &= ~0007777777761LL;
|
|
apr->membus.c12 |= ma_fmc_select ? MEMBUS_MA_FMC_SEL1 : MEMBUS_MA_FMC_SEL0;
|
|
apr->membus.c12 |= (apr->ma&01777) << 4;
|
|
apr->membus.c12 |= ((word)apr->rla&017) << 14;
|
|
apr->membus.c12 |= apr->rla & 0020 ? MEMBUS_MA21_1|MEMBUS_MA21 : MEMBUS_MA21_0;
|
|
apr->membus.c12 |= apr->rla & 0040 ? MEMBUS_MA20_1 : MEMBUS_MA20_0;
|
|
apr->membus.c12 |= apr->rla & 0100 ? MEMBUS_MA19_1 : MEMBUS_MA19_0;
|
|
apr->membus.c12 |= apr->rla & 0200 ? MEMBUS_MA18_1 : MEMBUS_MA18_0;
|
|
apr->membus.c12 |= apr->ma & 01 ? MEMBUS_MA35_1 : MEMBUS_MA35_0;
|
|
return ma_ok;
|
|
}
|
|
|
|
// 6-17, 6-9
|
|
#define cfac_ar_add ar_ast1
|
|
#define cfac_ar_sub ar_ast0
|
|
#define cfac_ar_negate ar_negate_t0
|
|
|
|
declpulse(kt1);
|
|
declpulse(kt4);
|
|
declpulse(key_rd_wr_ret);
|
|
declpulse(mc_rs_t0);
|
|
declpulse(mc_addr_ack);
|
|
declpulse(mc_wr_rs);
|
|
declpulse(mc_rd_rq_pulse);
|
|
declpulse(mc_split_rd_rq);
|
|
declpulse(mc_wr_rq_pulse);
|
|
declpulse(mc_rdwr_rq_pulse);
|
|
declpulse(mc_rd_wr_rs_pulse);
|
|
declpulse(it0);
|
|
declpulse(iat0);
|
|
declpulse(it1);
|
|
declpulse(it1a);
|
|
declpulse(at0);
|
|
declpulse(at1);
|
|
declpulse(at3a);
|
|
declpulse(ft0);
|
|
declpulse(ft1a);
|
|
declpulse(et4);
|
|
declpulse(et5);
|
|
declpulse(et9);
|
|
declpulse(et10);
|
|
declpulse(st7);
|
|
declpulse(ar_negate_t0);
|
|
declpulse(ar_pm1_t1);
|
|
declpulse(ar_ast0);
|
|
declpulse(ar_ast1);
|
|
declpulse(sht1a);
|
|
declpulse(cht3);
|
|
declpulse(cht3a);
|
|
declpulse(cht8a);
|
|
declpulse(lct0a);
|
|
declpulse(dst14);
|
|
declpulse(dct0a);
|
|
declpulse(mst2);
|
|
declpulse(mpt0a);
|
|
declpulse(nrt2);
|
|
declpulse(fst0a);
|
|
declpulse(fmt0a);
|
|
declpulse(fmt0b);
|
|
declpulse(fdt0a);
|
|
declpulse(fdt0b);
|
|
declpulse(fpt1a);
|
|
declpulse(fpt1b);
|
|
declpulse(nrt0_5);
|
|
declpulse(fat1a);
|
|
declpulse(fat5a);
|
|
declpulse(fat10);
|
|
|
|
// TODO: find A LONG, it probably doesn't exist
|
|
|
|
defpulse(pi_reset)
|
|
{
|
|
apr->pi_active = 0; // 8-4
|
|
PIH_CLEAR; // 8-4
|
|
PIR_CLEAR; // 8-4
|
|
apr->pi_req = get_pi_req(apr);
|
|
apr->pio = 0; // 8-3
|
|
}
|
|
|
|
static void
|
|
ar_flag_clr(Apr *apr)
|
|
{
|
|
apr->ar_ov_flag = 0; // 6-10
|
|
apr->ar_cry0_flag = 0; // 6-10
|
|
apr->ar_cry1_flag = 0; // 6-10
|
|
apr->ar_pc_chg_flag = 0; // 6-10
|
|
apr->chf7 = 0; // 6-19
|
|
recalc_cpa_req(apr);
|
|
}
|
|
|
|
static void
|
|
ar_flag_set(Apr *apr)
|
|
{
|
|
// 6-10
|
|
if(apr->c.mb & F0) apr->ar_ov_flag = 1;
|
|
if(apr->c.mb & F1) apr->ar_cry0_flag = 1;
|
|
if(apr->c.mb & F2) apr->ar_cry1_flag = 1;
|
|
if(apr->c.mb & F3) apr->ar_pc_chg_flag = 1;
|
|
if(apr->c.mb & F4) apr->chf7 = 1; // 6-19
|
|
if(apr->c.mb & F5) apr->ex_mode_sync = 1; // 5-13
|
|
#ifdef FIX_USER_IOT
|
|
if(!apr->ex_user) apr->cpa_iot_user = !!(apr->c.mb & F6);
|
|
#endif
|
|
recalc_cpa_req(apr);
|
|
}
|
|
|
|
static void
|
|
mp_clr(Apr *apr)
|
|
{
|
|
// 6-19
|
|
apr->chf1 = 0;
|
|
apr->chf2 = 0;
|
|
apr->chf3 = 0;
|
|
apr->chf4 = 0;
|
|
apr->chf5 = 0;
|
|
apr->chf6 = 0;
|
|
// 6-20
|
|
apr->lcf1 = 0;
|
|
apr->shf1 = 0;
|
|
// 6-21
|
|
apr->mpf1 = 0;
|
|
apr->mpf2 = 0;
|
|
apr->msf1 = 0; // 6-24
|
|
// 6-22
|
|
apr->fmf1 = 0;
|
|
apr->fmf2 = 0;
|
|
apr->fdf1 = 0;
|
|
apr->fdf2 = 0;
|
|
apr->faf1 = 0;
|
|
apr->faf2 = 0;
|
|
apr->faf3 = 0;
|
|
apr->faf4 = 0;
|
|
// 6-23
|
|
apr->fpf1 = 0;
|
|
apr->fpf2 = 0;
|
|
// 6-27
|
|
apr->nrf1 = 0;
|
|
apr->nrf2 = 0;
|
|
apr->nrf3 = 0;
|
|
}
|
|
|
|
static void
|
|
ds_clr(Apr *apr)
|
|
{
|
|
// 6-25, 6-26
|
|
apr->dsf1 = 0;
|
|
apr->dsf2 = 0;
|
|
apr->dsf3 = 0;
|
|
apr->dsf4 = 0;
|
|
apr->dsf5 = 0;
|
|
apr->dsf6 = 0;
|
|
apr->dsf8 = 0;
|
|
apr->dsf9 = 0;
|
|
apr->fsf1 = 0; // 6-19
|
|
}
|
|
|
|
defpulse(mr_clr)
|
|
{
|
|
apr->ir = 0; // 5-7
|
|
apr->n.mq = 0; // 6-13
|
|
apr->mq36 = 0; // 6-13
|
|
apr->sc = 0; // 6-15
|
|
apr->fe = 0; // 6-15
|
|
|
|
apr->mc_rd = 0; // 7-9
|
|
apr->mc_wr = 0; // 7-9
|
|
apr->mc_rq = 0; // 7-9
|
|
apr->mc_stop = 0; // 7-9
|
|
apr->mc_stop_sync = 0; // 7-9
|
|
apr->mc_split_cyc_sync = 0; // 7-9
|
|
|
|
if(apr->ex_mode_sync)
|
|
apr->ex_user = 1; // 5-13
|
|
apr->ex_mode_sync = 0;
|
|
apr->ex_uuo_sync = 0; // 5-13
|
|
apr->ex_pi_sync = apr->pi_cyc; // 5-13
|
|
|
|
apr->a_long = 0; // ?? nowhere to be found
|
|
apr->ar_com_cont = 0; // 6-9
|
|
mp_clr(apr); // 6-21
|
|
ds_clr(apr); // 6-26
|
|
|
|
apr->iot_go = 0; // 8-1
|
|
apr->iot_init_setup = 0;
|
|
apr->iot_final_setup = 0;
|
|
apr->iot_reset = 0;
|
|
apr->iot_go_pulse = 0;
|
|
|
|
/* sbr flip-flops */
|
|
apr->key_rd_wr = 0; // 5-2
|
|
apr->if1a = 0; // 5-3
|
|
apr->af0 = 0; // 5-3
|
|
apr->af3 = 0; // 5-3
|
|
apr->af3a = 0; // 5-3
|
|
apr->f1a = 0; // 5-4
|
|
apr->f4a = 0; // 5-4
|
|
apr->f6a = 0; // 5-4
|
|
apr->et4_ar_pse = 0; // 5-5
|
|
apr->sf3 = 0; // 5-6
|
|
apr->sf5a = 0; // 5-6
|
|
apr->sf7 = 0; // 5-6
|
|
apr->dsf7 = 0; // 6-25
|
|
apr->iot_f0a = 0; // 8-1
|
|
apr->blt_f0a = 0; // 6-18
|
|
apr->blt_f3a = 0; // 6-18
|
|
apr->blt_f5a = 0; // 6-18
|
|
apr->uuo_f1 = 0; // 5-10
|
|
apr->dcf1 = 0; // 6-20
|
|
|
|
// EX UUO SYNC
|
|
decodeir(apr);
|
|
}
|
|
|
|
defpulse(ex_clr)
|
|
{
|
|
apr->pr = 0; // 7-4
|
|
apr->rlr = 0; // 7-5
|
|
}
|
|
|
|
static void
|
|
ex_set(Apr *apr)
|
|
{
|
|
apr->pr = apr->iobus.c12>>28 & 0377; // 7-4
|
|
apr->rlr = apr->iobus.c12>>10 & 0377; // 7-5
|
|
}
|
|
|
|
defpulse(mr_start)
|
|
{
|
|
// 8-1
|
|
apr->iobus.c34 |= IOBUS_IOB_RESET;
|
|
|
|
// 8-5
|
|
apr->cpa_iot_user = 0;
|
|
apr->cpa_illeg_op = 0;
|
|
apr->cpa_non_exist_mem = 0;
|
|
apr->cpa_clock_enable = 0;
|
|
apr->cpa_clock_flag = 0;
|
|
apr->cpa_pc_chg_enable = 0;
|
|
apr->cpa_pdl_ov = 0;
|
|
apr->cpa_arov_enable = 0;
|
|
apr->cpa_pia = 0;
|
|
apr->iobus.dev[CPA].req = 0;
|
|
|
|
// PI
|
|
apr->pi_ov = 0; // 8-4
|
|
set_pi_cyc(apr, 0); // 8-4
|
|
pulse(apr, &pi_reset, 0); // 8-4
|
|
ar_flag_clr(apr); // 6-10
|
|
|
|
pulse(apr, &ex_clr, 0);
|
|
apr->ex_user = 0; // 5-13
|
|
apr->ex_ill_op = 0; // 5-13
|
|
apr->rla = 0;
|
|
}
|
|
|
|
defpulse(mr_pwr_clr)
|
|
{
|
|
apr->run = 0; // 5-1
|
|
/* order seems to matter.
|
|
* better call directly before external pulses can trigger stuff */
|
|
mr_start_p(apr); // 5-2
|
|
mr_clr_p(apr); // 5-2
|
|
}
|
|
|
|
/* CPA and PI devices */
|
|
|
|
static void
|
|
wake_cpa(void *dev)
|
|
{
|
|
Apr *apr;
|
|
IOBus *bus;
|
|
|
|
apr = dev;
|
|
bus = &apr->iobus;
|
|
if(apr->iobus.devcode != CPA)
|
|
return;
|
|
// 8-5
|
|
if(IOB_STATUS){
|
|
if(apr->cpa_pdl_ov) bus->c12 |= F19;
|
|
if(apr->cpa_iot_user) bus->c12 |= F20;
|
|
if(apr->ex_user) bus->c12 |= F21;
|
|
if(apr->cpa_illeg_op) bus->c12 |= F22;
|
|
if(apr->cpa_non_exist_mem) bus->c12 |= F23;
|
|
if(apr->cpa_clock_enable) bus->c12 |= F25;
|
|
if(apr->cpa_clock_flag) bus->c12 |= F26;
|
|
if(apr->cpa_pc_chg_enable) bus->c12 |= F28;
|
|
if(apr->ar_pc_chg_flag) bus->c12 |= F29;
|
|
if(apr->cpa_arov_enable) bus->c12 |= F31;
|
|
if(apr->ar_ov_flag) bus->c12 |= F32;
|
|
bus->c12 |= apr->cpa_pia & 7;
|
|
}
|
|
if(IOB_CONO_SET){
|
|
if(bus->c12 & F18) apr->cpa_pdl_ov = 0;
|
|
if(bus->c12 & F19) bus->c34 |= IOBUS_IOB_RESET; // 8-1
|
|
#ifdef FIX_USER_IOT
|
|
// IO reset seems to reset this too?
|
|
if(bus->c12 & F19) apr->cpa_iot_user = 0;
|
|
// these bits seem to be flipped in the schematics
|
|
if(bus->c12 & F20) apr->cpa_iot_user = 0;
|
|
if(bus->c12 & F21) apr->cpa_iot_user = 1;
|
|
#else
|
|
if(bus->c12 & F20) apr->cpa_iot_user = 1;
|
|
if(bus->c12 & F21) apr->cpa_iot_user = 0;
|
|
#endif
|
|
if(bus->c12 & F22) apr->cpa_illeg_op = 0;
|
|
if(bus->c12 & F23) apr->cpa_non_exist_mem = 0;
|
|
if(bus->c12 & F24) apr->cpa_clock_enable = 0;
|
|
if(bus->c12 & F25) apr->cpa_clock_enable = 1;
|
|
if(bus->c12 & F26) apr->cpa_clock_flag = 0;
|
|
if(bus->c12 & F27) apr->cpa_pc_chg_enable = 0;
|
|
if(bus->c12 & F28) apr->cpa_pc_chg_enable = 1;
|
|
if(bus->c12 & F29) apr->ar_pc_chg_flag = 0; // 6-10
|
|
if(bus->c12 & F30) apr->cpa_arov_enable = 0;
|
|
if(bus->c12 & F31) apr->cpa_arov_enable = 1;
|
|
if(bus->c12 & F32) apr->ar_ov_flag = 0; // 6-10
|
|
apr->cpa_pia = bus->c12 & 7;
|
|
recalc_cpa_req(apr);
|
|
}
|
|
|
|
// 5-2
|
|
if(IOB_DATAI)
|
|
apr->n.ar = apr->data;
|
|
// 5-13
|
|
if(IOB_DATAO_CLEAR)
|
|
ex_clr_p(apr);
|
|
if(IOB_DATAO_SET)
|
|
ex_set(apr);
|
|
}
|
|
|
|
static void
|
|
wake_pi(void *dev)
|
|
{
|
|
Apr *apr;
|
|
IOBus *bus;
|
|
|
|
apr = dev;
|
|
bus = &apr->iobus;
|
|
if(bus->devcode != PI)
|
|
return;
|
|
// 8-4, 8-5
|
|
if(IOB_STATUS){
|
|
trace("PI STATUS %012lo\n", bus->c12);
|
|
if(apr->pi_active) bus->c12 |= F28;
|
|
bus->c12 |= apr->pio;
|
|
}
|
|
|
|
// 8-4, 8-3
|
|
if(IOB_CONO_CLEAR){
|
|
trace("PI CONO CLEAR %012lo\n", bus->c12);
|
|
if(bus->c12 & F23)
|
|
// can call directly
|
|
pi_reset_p(apr);
|
|
}
|
|
if(IOB_CONO_SET){
|
|
trace("PI CONO SET %012lo\n", bus->c12);
|
|
if(bus->c12 & F24) PIR_FM_IOB1;
|
|
if(bus->c12 & F25) PIO_FM_IOB1;
|
|
if(bus->c12 & F26) PIO0_FM_IOB1;
|
|
if(bus->c12 & F27) apr->pi_active = 0;
|
|
if(bus->c12 & F28) apr->pi_active = 1;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* IOT
|
|
*/
|
|
|
|
defpulse(iot_t4)
|
|
{
|
|
apr->iot_reset = 0; // 8-1
|
|
}
|
|
|
|
defpulse(iot_t3a)
|
|
{
|
|
apr->iot_reset = 1; // 8-1
|
|
/* Clear what was set in IOT T2 */
|
|
apr->iobus.c34 &= ~(IOBUS_IOB_STATUS | IOBUS_IOB_DATAI);
|
|
/* and do something like IOB BUS RESET */
|
|
apr->iobus.c12 = 0;
|
|
pulse(apr, &iot_t4, 2000);
|
|
}
|
|
|
|
defpulse(iot_t3)
|
|
{
|
|
// 8-1
|
|
/* Pulses, cleared in the main loop. */
|
|
if(IOT_DATAO) apr->iobus.c34 |= IOBUS_DATAO_SET;
|
|
if(IOT_CONO) apr->iobus.c34 |= IOBUS_CONO_SET;
|
|
apr->n.ar |= apr->iobus.c12; // 6-8
|
|
pulse(apr, &et5, 200); // 5-5
|
|
}
|
|
|
|
defpulse(iot_t2)
|
|
{
|
|
// 8-1
|
|
apr->iot_go = 0;
|
|
apr->iot_init_setup = 0;
|
|
apr->iot_final_setup = 1;
|
|
/* Pulses, cleared in the main loop. */
|
|
if(IOT_DATAO) apr->iobus.c34 |= IOBUS_DATAO_CLEAR;
|
|
if(IOT_CONO) apr->iobus.c34 |= IOBUS_CONO_CLEAR;
|
|
pulse(apr, &iot_t3, 1000);
|
|
pulse(apr, &iot_t3a, 1500);
|
|
}
|
|
|
|
defpulse(iot_t0a)
|
|
{
|
|
apr->iot_f0a = 0; // 8-1
|
|
apr->ir |= H12; // 5-8
|
|
decodeir(apr);
|
|
apr->ma = 0; // 7-3
|
|
if(apr->pi_cyc && apr->ar_cry0)
|
|
apr->pi_ov = 1; // 8-4
|
|
if(!apr->pi_cyc && !apr->ar_cry0)
|
|
apr->pc = apr->pc+1 & RT; // 5-12
|
|
pulse(apr, &ft0, 200); // 5-4
|
|
}
|
|
|
|
defpulse(iot_t0)
|
|
{
|
|
apr->iot_f0a = 1; // 8-1
|
|
pulse(apr, &mc_rd_wr_rs_pulse, 0); // 7-8
|
|
}
|
|
|
|
/*
|
|
* UUO subroutine
|
|
*/
|
|
|
|
defpulse(uuo_t2)
|
|
{
|
|
apr->inst_ma = apr->ma; // remember where we got the instruction from
|
|
apr->if1a = 1; // 5-3
|
|
pulse(apr, &mc_rd_rq_pulse, 0); // 7-8
|
|
}
|
|
|
|
defpulse(uuo_t1)
|
|
{
|
|
apr->uuo_f1 = 0; // 5-10
|
|
apr->ma = apr->ma+1 & RT; // 7-3
|
|
pulse(apr, &mr_clr, 0); // 5-2
|
|
pulse(apr, &uuo_t2, 100); // 5-10
|
|
}
|
|
|
|
/*
|
|
* BLT subroutine
|
|
*/
|
|
|
|
defpulse(blt_t6)
|
|
{
|
|
SWAP(mb, ar); // 6-3
|
|
pulse(apr, &ft1a, 100); // 5-4
|
|
}
|
|
|
|
defpulse(blt_t5a)
|
|
{
|
|
apr->blt_f5a = 0; // 6-18
|
|
if(!(apr->c.mq & F0))
|
|
apr->pc = apr->pc+1 & RT; // 5-12
|
|
pulse(apr, BLT_DONE ? &et10 : &blt_t6, 0); // 5-5, 6-18
|
|
}
|
|
|
|
defpulse(blt_t5)
|
|
{
|
|
SWAP(mb, mq); // 6-17
|
|
apr->blt_f5a = 1; // 6-18
|
|
pulse(apr, &ar_pm1_t1, 0); // 6-9
|
|
}
|
|
|
|
defpulse(blt_t4)
|
|
{
|
|
SWAP(mb, ar); // 6-3
|
|
PIR_STB; // 8-4
|
|
pulse(apr, &blt_t5, 100); // 6-18
|
|
}
|
|
|
|
defpulse(blt_t3a)
|
|
{
|
|
apr->blt_f3a = 0; // 6-18
|
|
SWAP(mb, mq); // 6-17
|
|
pulse(apr, &blt_t4, 100); // 6-18
|
|
}
|
|
|
|
defpulse(blt_t3)
|
|
{
|
|
apr->blt_f3a = 1; // 6-18
|
|
pulse(apr, &ar_ast0, 0); // 6-9
|
|
}
|
|
|
|
defpulse(blt_t2)
|
|
{
|
|
ARLT_CLEAR; // 6-8
|
|
pulse(apr, &blt_t3, 100); // 6-18
|
|
}
|
|
|
|
defpulse(blt_t1)
|
|
{
|
|
SWAP(mb, ar); // 6-3
|
|
pulse(apr, &blt_t2, 100); // 6-18
|
|
}
|
|
|
|
defpulse(blt_t0a)
|
|
{
|
|
apr->blt_f0a = 0; // 6-18
|
|
apr->n.mb = apr->c.mq; // 6-3
|
|
pulse(apr, &blt_t1, 100); // 6-18
|
|
}
|
|
|
|
defpulse(blt_t0)
|
|
{
|
|
SWAP(mb, mq); // 6-17
|
|
apr->blt_f0a = 1; // 6-18
|
|
pulse(apr, &mc_wr_rq_pulse, 0); // 7-8
|
|
}
|
|
|
|
/*
|
|
* Shift subroutines
|
|
*/
|
|
|
|
// 6-14
|
|
#define SC_COM apr->sc = ~apr->sc & 0777
|
|
#define SC_INC apr->sc = apr->sc+1 & 0777
|
|
#define SC_DATA (apr->chf1 ? ~apr->c.mb>>30 & 077 | 0700 : \
|
|
apr->chf2 ? apr->c.mb>>24 & 077 : \
|
|
apr->fsf1 || apr->fpf1 || apr->faf2 ? apr->c.ar>>27 & 0777 : \
|
|
apr->fpf2 || apr->faf1 ? apr->c.mb>>27 & 0777 : 0)
|
|
#define SC_PAD apr->sc ^= SC_DATA
|
|
#define SC_CRY apr->sc = (apr->sc + ((~apr->sc & SC_DATA) << 1))&0777
|
|
// 6-7
|
|
#define SHC_ASHC (apr->inst == ASHC || apr->nrf2 || apr->faf3)
|
|
#define SHC_DIV ((IR_DIV || IR_FDV) && !apr->nrf2)
|
|
|
|
#define MS_MULT (apr->mpf1 || apr->fmf2) // 6-24
|
|
|
|
/* Shift counter */
|
|
|
|
// 6-7, 6-17, 6-13
|
|
#define AR_SH_LT apr->n.ar = apr->c.ar<<1 & 0377777777776 | ar0_shl_inp | ar35_shl_inp
|
|
#define MQ_SH_LT apr->n.mq = apr->c.mq<<1 & 0377777777776 | mq0_shl_inp | mq35_shl_inp
|
|
#define AR_SH_RT apr->n.ar = apr->c.ar>>1 & 0377777777777 | ar0_shr_inp
|
|
#define MQ_SH_RT apr->mq36 = apr->c.mq&F35, \
|
|
apr->n.mq = apr->c.mq>>1 & 0177777777777 | mq0_shr_inp | mq1_shr_inp
|
|
|
|
defpulse(sct2)
|
|
{
|
|
if(apr->shf1) pulse(apr, &sht1a, 0); // 6-20
|
|
if(apr->chf4) pulse(apr, &cht8a, 0); // 6-19
|
|
if(apr->lcf1) pulse(apr, &lct0a, 0); // 6-20
|
|
if(apr->dcf1) pulse(apr, &dct0a, 0); // 6-20
|
|
if(apr->faf3) pulse(apr, &fat5a, 0); // 6-22
|
|
}
|
|
|
|
defpulse(sct1)
|
|
{
|
|
word ar0_shl_inp, ar0_shr_inp = 0, ar35_shl_inp = 0;
|
|
word mq0_shl_inp, mq0_shr_inp, mq1_shr_inp, mq35_shl_inp = 0;
|
|
|
|
SC_INC; // 6-16
|
|
|
|
// 6-7 What a mess, and many things aren't even used here
|
|
if(apr->inst != ASH && !SHC_ASHC)
|
|
ar0_shl_inp = (apr->c.ar & F1) << 1;
|
|
else
|
|
ar0_shl_inp = apr->c.ar & F0;
|
|
|
|
if(apr->inst == ROTC)
|
|
ar0_shr_inp = (apr->c.mq & F35) << 35;
|
|
else if(apr->inst == ROT)
|
|
ar0_shr_inp = (apr->c.ar & F35) << 35;
|
|
else if(IR_DIV)
|
|
ar0_shr_inp = (~apr->c.mq & F35) << 35;
|
|
else if(apr->inst == LSH || apr->inst == LSHC || CH_LOAD)
|
|
ar0_shr_inp = 0;
|
|
else if(apr->inst == ASH || SHC_ASHC || MS_MULT || IR_FDV)
|
|
ar0_shr_inp = apr->c.ar & F0;
|
|
|
|
if(apr->inst == ROT)
|
|
ar35_shl_inp = (apr->c.ar & F0) >> 35;
|
|
else if(apr->inst == ASHC)
|
|
ar35_shl_inp = (apr->c.mq & F1) >> 34;
|
|
else if(apr->inst == ROTC || apr->inst == LSHC || SHC_DIV)
|
|
ar35_shl_inp = (apr->c.mq & F0) >> 35;
|
|
else if(CH_DEP || apr->inst == LSH || apr->inst == ASH)
|
|
ar35_shl_inp = 0;
|
|
|
|
if(SHC_ASHC){
|
|
mq0_shl_inp = apr->c.ar & F0;
|
|
mq1_shr_inp = (apr->c.ar & F35) << 34;
|
|
}else{
|
|
mq0_shl_inp = (apr->c.mq & F1) << 1;
|
|
mq1_shr_inp = (apr->c.mq & F0) >> 1;
|
|
}
|
|
|
|
if(MS_MULT && apr->sc == 0777 || SHC_ASHC)
|
|
mq0_shr_inp = apr->c.ar & F0;
|
|
else
|
|
mq0_shr_inp = (apr->c.ar & F35) << 35;
|
|
|
|
if(apr->inst == ROTC)
|
|
mq35_shl_inp = (apr->c.ar & F0) >> 35;
|
|
else if(SHC_DIV)
|
|
mq35_shl_inp = (~apr->c.ar & F0) >> 35;
|
|
else if(CH_N_INC_OP || CH_INC_OP)
|
|
mq35_shl_inp = 1;
|
|
else if(apr->inst == LSHC || SHC_ASHC || CH_DEP)
|
|
mq35_shl_inp = 0;
|
|
|
|
// 6-17
|
|
if(apr->shift_op && !(apr->c.mb & F18)){
|
|
AR_SH_LT;
|
|
MQ_SH_LT;
|
|
}
|
|
if(apr->shift_op && (apr->c.mb & F18) || apr->faf3){
|
|
AR_SH_RT;
|
|
MQ_SH_RT;
|
|
}
|
|
if(apr->chf4)
|
|
MQ_SH_LT;
|
|
if(apr->lcf1)
|
|
AR_SH_RT;
|
|
if(apr->dcf1){
|
|
AR_SH_LT;
|
|
MQ_SH_LT;
|
|
}
|
|
|
|
if(!(apr->c.mb & F18) && (apr->inst == ASH || apr->inst == ASHC) && AR0_XOR_AR1){
|
|
apr->ar_ov_flag = 1; // 6-10
|
|
recalc_cpa_req(apr);
|
|
}
|
|
pulse(apr, apr->sc == 0777 ? &sct2 : &sct1, 75); // 6-15, 6-16
|
|
}
|
|
|
|
defpulse(sct0)
|
|
{
|
|
pulse(apr, apr->sc == 0777 ? &sct2 : &sct1, 200); // 6-15, 6-16
|
|
}
|
|
|
|
/* Shift adder */
|
|
|
|
defpulse(sat3)
|
|
{
|
|
if(apr->chf2) pulse(apr, &cht3a, 0); // 6-19
|
|
if(apr->fsf1) pulse(apr, &fst0a, 0); // 6-19
|
|
if(apr->fpf1) pulse(apr, &fpt1a, 0); // 6-23
|
|
if(apr->fpf2) pulse(apr, &fpt1b, 0); // 6-23
|
|
if(apr->faf2) pulse(apr, &fat1a, 0); // 6-22
|
|
}
|
|
|
|
defpulse(sat2_1)
|
|
{
|
|
SC_CRY; // 6-15
|
|
pulse(apr, &sat3, 100); // 6-16
|
|
}
|
|
|
|
defpulse(sat2)
|
|
{
|
|
pulse(apr, &sat2_1, 50); // 6-16
|
|
}
|
|
|
|
defpulse(sat1)
|
|
{
|
|
SC_PAD; // 6-15
|
|
pulse(apr, &sat2, 200); // 6-16
|
|
}
|
|
|
|
defpulse(sat0)
|
|
{
|
|
apr->chf1 = 0; // 6-19
|
|
pulse(apr, &sat1, 150); // 6-16
|
|
}
|
|
|
|
/*
|
|
* Shift operations subroutine
|
|
*/
|
|
|
|
defpulse_(sht1a)
|
|
{
|
|
apr->shf1 = 0; // 6-20
|
|
pulse(apr, &et10, 0); // 5-5
|
|
}
|
|
|
|
defpulse(sht1)
|
|
{
|
|
if(apr->c.mb & F18)
|
|
SC_COM; // 6-15
|
|
apr->shf1 = 1; // 6-20
|
|
pulse(apr, &sct0, 0); // 6-16
|
|
}
|
|
|
|
defpulse(sht0)
|
|
{
|
|
SC_INC; // 6-16
|
|
}
|
|
|
|
/*
|
|
* Character subroutines
|
|
*/
|
|
|
|
defpulse(dct3)
|
|
{
|
|
apr->n.mb &= apr->c.ar; // 6-3
|
|
apr->chf7 = 0; // 6-19
|
|
pulse(apr, &et10, 1); // 5-5
|
|
}
|
|
|
|
defpulse(dct2)
|
|
{
|
|
AR_COM; // 6-17
|
|
pulse(apr, &dct3, 100); // 6-20
|
|
}
|
|
|
|
defpulse(dct1)
|
|
{
|
|
apr->n.ar &= apr->c.mb; // 6-8
|
|
apr->n.mb = apr->c.mq; // 6-17
|
|
pulse(apr, &dct2, 100); // 6-20
|
|
}
|
|
|
|
defpulse_(dct0a)
|
|
{
|
|
apr->dcf1 = 0; // 6-20
|
|
apr->n.mq |= apr->c.mb; // 6-13 dct0b
|
|
apr->n.mb = apr->c.mq; // 6-17
|
|
AR_COM; // 6-17
|
|
pulse(apr, &dct1, 150); // 6-20
|
|
}
|
|
|
|
defpulse(dct0)
|
|
{
|
|
apr->dcf1 = 1; // 6-20
|
|
SC_COM; // 6-15
|
|
pulse(apr, &sct0, 0); // 6-16
|
|
}
|
|
|
|
defpulse_(lct0a)
|
|
{
|
|
apr->lcf1 = 0; // 6-20
|
|
apr->n.ar &= apr->c.mb; // 6-8
|
|
apr->chf7 = 0; // 6-19
|
|
pulse(apr, &et10, 1); // 5-5
|
|
}
|
|
|
|
defpulse(lct0)
|
|
{
|
|
apr->n.ar = apr->c.mb; // 6-8
|
|
apr->n.mb = apr->c.mq; // 6-17
|
|
SC_COM; // 6-15
|
|
apr->lcf1 = 1; // 6-20
|
|
pulse(apr, &sct0, 0); // 6-16
|
|
}
|
|
|
|
defpulse(cht9)
|
|
{
|
|
apr->sc |= apr->fe; // 6-15
|
|
apr->chf5 = 1; // 6-19
|
|
apr->chf7 = 1; // 6-19
|
|
pulse(apr, &at0, 0); // 5-3
|
|
}
|
|
|
|
defpulse_(cht8a)
|
|
{
|
|
apr->chf4 = 0; // 6-19
|
|
apr->sc = 0; // 6-15
|
|
apr->ir &= ~037; // 5-7
|
|
pulse(apr, &cht9, 100); // 6-19
|
|
}
|
|
|
|
defpulse(cht8b)
|
|
{
|
|
apr->chf2 = 0; // 6-19
|
|
apr->chf6 = 0; // 6-19
|
|
apr->fe |= apr->c.mb>>30 & 077; // 6-14, 6-15
|
|
SC_COM; // 6-15
|
|
if(apr->inst == CAO)
|
|
pulse(apr, &st7, 0); // 5-6
|
|
else{
|
|
apr->chf4 = 1; // 6-19
|
|
pulse(apr, &sct0, 0); // 6-16
|
|
}
|
|
}
|
|
|
|
defpulse(cht8)
|
|
{
|
|
apr->chf6 = 1; // 6-19
|
|
pulse(apr, &mc_rd_wr_rs_pulse, 0); // 7-8
|
|
}
|
|
|
|
defpulse(cht7)
|
|
{
|
|
SC_PAD; // 6-15
|
|
if(CH_INC_OP){
|
|
SWAP(mb, ar); // 6-17
|
|
pulse(apr, &cht8, 100); // 6-19
|
|
}
|
|
if(CH_N_INC_OP)
|
|
pulse(apr, &cht8b, 100); // 6-19
|
|
}
|
|
|
|
defpulse(cht6)
|
|
{
|
|
apr->n.ar = apr->n.ar & 0007777777777 |
|
|
(((word)apr->sc & 077) << 30); // 6-9, 6-4
|
|
if(CH_INC_OP)
|
|
apr->sc = 0; // 6-15
|
|
apr->chf2 = 1; // 6-19
|
|
pulse(apr, &cht7, 150); // 6-19
|
|
}
|
|
|
|
defpulse(cht5)
|
|
{
|
|
SC_COM; // 6-15
|
|
pulse(apr, &cht6, 100); // 6-19
|
|
}
|
|
|
|
defpulse(cht4a)
|
|
{
|
|
apr->chf3 = 0; // 6-19
|
|
apr->sc |= 0433;
|
|
pulse(apr, &cht3, 0); // 6-19
|
|
}
|
|
|
|
defpulse(cht4)
|
|
{
|
|
apr->sc = 0; // 6-15
|
|
apr->chf3 = 1; // 6-19
|
|
pulse(apr, &ar_pm1_t1, 0); // 6-9
|
|
}
|
|
|
|
defpulse_(cht3a)
|
|
{
|
|
apr->chf2 = 0; // 6-19
|
|
pulse(apr, apr->sc & 0400 ? &cht5 : &cht4, 0); // 6-19
|
|
}
|
|
|
|
defpulse_(cht3)
|
|
{
|
|
apr->chf2 = 1; // 6-19
|
|
pulse(apr, &sat0, 0); // 6-16
|
|
}
|
|
|
|
defpulse(cht2)
|
|
{
|
|
SC_PAD; // 6-15
|
|
pulse(apr, &cht3, 0); // 6-19
|
|
}
|
|
|
|
defpulse(cht1)
|
|
{
|
|
apr->n.ar = apr->c.mb; // 6-8
|
|
apr->chf1 = 1; // 6-19
|
|
pulse(apr, &cht2, 100); // 6-19
|
|
}
|
|
|
|
/*
|
|
* Multiply subroutine
|
|
*/
|
|
|
|
// 6-13
|
|
#define MQ35_EQ_MQ36 ((apr->c.mq&F35) == apr->mq36)
|
|
|
|
defpulse(mst6)
|
|
{
|
|
if(apr->mpf1) pulse(apr, &mpt0a, 0); // 6-21
|
|
if(apr->fmf2) pulse(apr, &fmt0b, 0); // 6-22
|
|
}
|
|
|
|
defpulse(mst5)
|
|
{
|
|
word mq0_shr_inp, mq1_shr_inp;
|
|
|
|
mq0_shr_inp = apr->c.ar & F0; // 6-17
|
|
mq1_shr_inp = (apr->c.mq & F0) >> 1; // 6-17
|
|
MQ_SH_RT; // 6-17
|
|
apr->sc = 0; // 6-15
|
|
pulse(apr, &mst6, 100); // 6-24
|
|
}
|
|
|
|
defpulse(mst4)
|
|
{
|
|
apr->msf1 = 1; // 6-24
|
|
pulse(apr, &cfac_ar_sub, 0); // 6-17
|
|
}
|
|
|
|
defpulse(mst3a)
|
|
{
|
|
apr->msf1 = 0; // 6-24
|
|
pulse(apr, apr->sc == 0777 ? &mst5 : &mst2, 0); // 6-24
|
|
}
|
|
|
|
defpulse(mst3)
|
|
{
|
|
apr->msf1 = 1; // 6-24
|
|
pulse(apr, &cfac_ar_add, 0); // 6-17
|
|
}
|
|
|
|
defpulse(mst2_dly)
|
|
{
|
|
if(MQ35_EQ_MQ36)
|
|
pulse(apr, apr->sc == 0777 ? &mst5 : &mst2, 0); // 6-24
|
|
if(!(apr->c.mq&F35) && apr->mq36)
|
|
pulse(apr, &mst3, 0); // 6-24
|
|
if(apr->c.mq&F35 && !apr->mq36)
|
|
pulse(apr, &mst4, 0); // 6-24
|
|
}
|
|
|
|
defpulse_(mst2)
|
|
{
|
|
word ar0_shr_inp, mq0_shr_inp, mq1_shr_inp;
|
|
|
|
ar0_shr_inp = apr->c.ar & F0; // 6-7
|
|
mq0_shr_inp = (apr->c.ar & F35) << 35; // 6-7
|
|
mq1_shr_inp = (apr->c.mq & F0) >> 1; // 6-7
|
|
AR_SH_RT; // 6-17
|
|
MQ_SH_RT; // 6-17
|
|
SC_INC; // 6-16
|
|
pulse(apr, &mst2_dly, 150);
|
|
}
|
|
|
|
defpulse(mst1_dly)
|
|
{
|
|
if(MQ35_EQ_MQ36 && apr->sc != 0777)
|
|
pulse(apr, &mst2, 0); // 6-24
|
|
if(!(apr->c.mq&F35) && apr->mq36)
|
|
pulse(apr, &mst3, 0); // 6-24
|
|
if(apr->c.mq&F35 && !apr->mq36)
|
|
pulse(apr, &mst4, 0); // 6-24
|
|
}
|
|
|
|
defpulse(mst1)
|
|
{
|
|
apr->n.mq = apr->c.mb; // 6-13
|
|
apr->n.mb = apr->c.ar; // 6-3
|
|
AR_CLEAR; // 6-8
|
|
pulse(apr, &mst1_dly, 200);
|
|
}
|
|
|
|
/*
|
|
* Divide subroutine
|
|
*/
|
|
|
|
#define DS_DIV (IR_DIV & apr->ir & H6)
|
|
#define DS_DIVI (IR_DIV & !(apr->ir & H6))
|
|
|
|
#define DSF7_XOR_MQ0 (apr->dsf7 != !!(apr->c.mq & F0))
|
|
|
|
defpulse(dst21a)
|
|
{
|
|
apr->dsf9 = 0; // 6-26
|
|
SWAP(mb, mq); // 6-17
|
|
if(IR_DIV) pulse(apr, &et9, 0); // 5-5
|
|
if(apr->fdf2) pulse(apr, &fdt0b, 0); // 6-22
|
|
}
|
|
|
|
defpulse(dst21)
|
|
{
|
|
apr->dsf9 = 1; // 6-26
|
|
pulse(apr, &cfac_ar_negate, 0); // 6-17
|
|
}
|
|
|
|
defpulse(dst20)
|
|
{
|
|
apr->sc = 0; // 6-15
|
|
SWAP(mb, ar); // 6-17
|
|
pulse(apr, DSF7_XOR_MQ0 ? &dst21 : &dst21a, 100); // 6-26
|
|
}
|
|
|
|
defpulse(dst19a)
|
|
{
|
|
apr->dsf8 = 0; // 6-26
|
|
SWAP(mb, mq); // 6-17
|
|
pulse(apr, &dst20, 100); // 6-26
|
|
}
|
|
|
|
defpulse(dst19)
|
|
{
|
|
apr->dsf8 = 1; // 6-26 DST19B
|
|
pulse(apr, &cfac_ar_negate, 0); // 6-17
|
|
}
|
|
|
|
defpulse(dst18)
|
|
{
|
|
apr->dsf6 = 1; // 6-26
|
|
pulse(apr, &cfac_ar_sub, 0); // 6-17
|
|
}
|
|
|
|
defpulse(dst17a)
|
|
{
|
|
apr->dsf6 = 0; // 6-26
|
|
pulse(apr, apr->dsf7 ? &dst19 : &dst19a, 0); // 6-26
|
|
}
|
|
|
|
defpulse(dst17)
|
|
{
|
|
apr->dsf6 = 1; // 6-26
|
|
pulse(apr, &cfac_ar_add, 0); // 6-17
|
|
}
|
|
|
|
defpulse(dst16_dly)
|
|
{
|
|
if(apr->c.ar & F0)
|
|
pulse(apr, apr->c.mb & F0 ? &dst18 : &dst17, 0); // 6-26
|
|
else
|
|
pulse(apr, &dst17a, 0); // 6-26
|
|
}
|
|
|
|
defpulse(dst16)
|
|
{
|
|
word ar0_shr_inp = 0;
|
|
|
|
// 6-7
|
|
if(IR_FDV)
|
|
ar0_shr_inp = apr->c.ar & F0;
|
|
if(IR_DIV)
|
|
ar0_shr_inp = (~apr->c.mq & F35) << 35;
|
|
AR_SH_RT; // 6-17
|
|
pulse(apr, &dst16_dly, 100);
|
|
}
|
|
|
|
defpulse(dst15)
|
|
{
|
|
apr->dsf5 = 1; // 6-26
|
|
pulse(apr, &cfac_ar_add, 0); // 6-17
|
|
}
|
|
|
|
defpulse(dst14b_dly)
|
|
{
|
|
if(apr->sc == 0777)
|
|
pulse(apr, &dst16, 0); // 6-26
|
|
else
|
|
pulse(apr, MQ35_XOR_MB0 ? &dst14 : &dst15, 0); // 6-26
|
|
}
|
|
|
|
defpulse(dst14b)
|
|
{
|
|
// TODO: remove this perhaps?
|
|
pulse(apr, &dst14b_dly, 100); // 6-26
|
|
}
|
|
|
|
defpulse(dst14a)
|
|
{
|
|
word ar0_shl_inp, ar35_shl_inp;
|
|
word mq0_shl_inp, mq35_shl_inp;
|
|
|
|
apr->dsf5 = 0; // 6-26
|
|
SC_INC; // 6-16
|
|
// 6-7
|
|
ar0_shl_inp = (apr->c.ar & F1) << 1;
|
|
ar35_shl_inp = (apr->c.mq & F0) >> 35;
|
|
mq0_shl_inp = (apr->c.mq & F1) << 1;
|
|
mq35_shl_inp = (~apr->c.ar & F0) >> 35;
|
|
AR_SH_LT; // 6-17
|
|
MQ_SH_LT; // 6-17
|
|
pulse(apr, &dst14b, 0); // 6-26
|
|
}
|
|
|
|
defpulse_(dst14)
|
|
{
|
|
apr->dsf5 = 1; // 6-26
|
|
pulse(apr, &cfac_ar_sub, 0); // 6-17
|
|
}
|
|
|
|
defpulse(dst13)
|
|
{
|
|
SET_OVERFLOW; // 6-17
|
|
pulse(apr, &st7, 0); // 5-6
|
|
}
|
|
|
|
defpulse(dst12)
|
|
{
|
|
apr->dsf4 = 1; // 6-25
|
|
pulse(apr, &cfac_ar_sub, 0); // 6-17
|
|
}
|
|
|
|
defpulse(dst11a)
|
|
{
|
|
apr->dsf4 = 0; // 6-25
|
|
pulse(apr, apr->c.ar & F0 ? &dst14a : &dst13, 0); // 6-25, 6-26
|
|
}
|
|
|
|
defpulse(dst11)
|
|
{
|
|
apr->dsf4 = 1; // 6-25
|
|
pulse(apr, &cfac_ar_add, 0); // 6-17
|
|
}
|
|
|
|
defpulse(dst10b)
|
|
{
|
|
word mq0_shl_inp, mq35_shl_inp;
|
|
|
|
mq0_shl_inp = (apr->c.mq & F1) << 1; // 6-7
|
|
mq35_shl_inp = (~apr->c.ar & F0) >> 35; // 6-7
|
|
MQ_SH_LT; // 6-17
|
|
pulse(apr, apr->c.mb & F0 ? &dst11 : &dst12, 200); // 6-15
|
|
}
|
|
|
|
defpulse(dst10a)
|
|
{
|
|
word ar0_shr_inp;
|
|
|
|
apr->n.mq = apr->c.mq & ~F0 | ((apr->c.ar & F35) << 35); // 6-13
|
|
ar0_shr_inp = apr->c.ar & F0; // 6-7
|
|
AR_SH_RT; // 6-17
|
|
pulse(apr, apr->c.mb & F0 ? &dst11 : &dst12, 200); // 6-15
|
|
}
|
|
|
|
defpulse(dst10)
|
|
{
|
|
apr->dsf3 = 0; // 6-25
|
|
if(IR_FDV)
|
|
pulse(apr, &dst10a, 100); // 6-25
|
|
if(IR_DIV)
|
|
pulse(apr, &dst10b, 100); // 6-25
|
|
}
|
|
|
|
defpulse(dst9)
|
|
{
|
|
SWAP(mb, mq); // 6-17
|
|
apr->dsf3 = 1; // 6-25
|
|
pulse(apr, &cfac_ar_negate, 0); // 6-17
|
|
}
|
|
|
|
defpulse(dst8)
|
|
{
|
|
SWAP(mb, ar); // 6-17
|
|
pulse(apr, &dst9, 100); // 6-25
|
|
}
|
|
|
|
defpulse(dst7)
|
|
{
|
|
SWAP(mb, mq); // 6-17
|
|
AR_COM; // 6-17
|
|
pulse(apr, &dst10, 0); // 6-25
|
|
}
|
|
|
|
defpulse(dst6)
|
|
{
|
|
SWAP(mb, ar); // 6-17
|
|
pulse(apr, &dst7, 100); // 6-25
|
|
}
|
|
|
|
defpulse(dst5a)
|
|
{
|
|
apr->dsf2 = 0; // 6-25
|
|
#ifdef FIX_DS
|
|
/* we have to ignore the lower sign bit
|
|
* for carry propagation */
|
|
pulse(apr, apr->c.ar & 0377777777777 ?
|
|
&dst6 : &dst8, 100); // 6-25
|
|
#else
|
|
pulse(apr, apr->c.ar ? &dst6 : &dst8, 100); // 6-25
|
|
#endif
|
|
}
|
|
|
|
defpulse(dst5)
|
|
{
|
|
apr->dsf2 = 1; // 6-25
|
|
pulse(apr, &cfac_ar_negate, 0); // 6-17
|
|
}
|
|
|
|
defpulse(dst4)
|
|
{
|
|
SWAP(mb, ar); // 6-17
|
|
pulse(apr, &dst5, 100); // 6-25
|
|
}
|
|
|
|
defpulse(dst3)
|
|
{
|
|
SWAP(mb, mq); // 6-17
|
|
apr->dsf7 = 1; // 6-25
|
|
pulse(apr, &dst4, 100); // 6-25
|
|
}
|
|
|
|
defpulse(dst2)
|
|
{
|
|
SWAP(mb, mq); // 6-17
|
|
AR_CLEAR; // 6-8
|
|
pulse(apr, &dst10, 0); // 6-25
|
|
}
|
|
|
|
defpulse(dst1)
|
|
{
|
|
apr->n.mq = apr->c.mb; // 6-13
|
|
apr->n.mb = apr->c.ar; // 6-3
|
|
pulse(apr, &dst2, 150); // 6-25
|
|
}
|
|
|
|
defpulse(dst0a)
|
|
{
|
|
apr->dsf1 = 0; // 6-25
|
|
pulse(apr, DS_DIVI ? &dst1 : &dst10, 0); // 6-25
|
|
}
|
|
|
|
defpulse(dst0)
|
|
{
|
|
apr->dsf7 = 1; // 6-25
|
|
apr->dsf1 = 1; // 6-25
|
|
pulse(apr, &cfac_ar_negate, 0); // 6-17
|
|
}
|
|
|
|
defpulse(ds_div_t0)
|
|
{
|
|
apr->sc = 0733; // 6-14
|
|
}
|
|
|
|
/*
|
|
* Floating point subroutines
|
|
*/
|
|
|
|
/* Normalize return */
|
|
|
|
// 6-27
|
|
#define AR_0_AND_MQ1_0 (apr->c.ar == 0 && !(apr->c.mq & F1))
|
|
#define AR9_EQ_AR0 (!!(apr->c.ar & F9) == !!(apr->c.ar & F0))
|
|
#define NR_ROUND (apr->ir & H6 && apr->c.mq & F1 && !apr->nrf3)
|
|
|
|
defpulse(nrt6)
|
|
{
|
|
/* HACK: fake delay so values will settle */
|
|
pulse(apr, &et10, 1); // 5-5
|
|
}
|
|
|
|
defpulse(nrt5a)
|
|
{
|
|
apr->nrf1 = 0; // 6-27
|
|
apr->nrf3 = 1; // 6-27
|
|
pulse(apr, &nrt0_5, 0); // 6-27
|
|
}
|
|
|
|
defpulse(nrt5)
|
|
{
|
|
apr->nrf1 = 1; // 6-27
|
|
pulse(apr, &ar_pm1_t1, 0); // 6-9
|
|
}
|
|
|
|
defpulse(nrt4)
|
|
{
|
|
apr->n.ar = apr->n.ar&0400777777777 | ((word)apr->sc&0377)<<27; // 6-4, 6-9
|
|
pulse(apr, &nrt6, 0); // 6-27
|
|
}
|
|
|
|
defpulse(nrt31_dly)
|
|
{
|
|
pulse(apr, NR_ROUND ? &nrt5 : &nrt4, 0); // 6-27
|
|
}
|
|
|
|
defpulse(nrt3)
|
|
{
|
|
if(!(apr->sc & 0400))
|
|
SET_OVERFLOW; // 6-17
|
|
if(!(apr->c.ar & F0) || NR_ROUND)
|
|
SC_COM; // 6-15
|
|
pulse(apr, &nrt31_dly, 100); // 6-27
|
|
}
|
|
|
|
defpulse(nrt1_dly)
|
|
{
|
|
pulse(apr, AR_EQ_FP_HALF || !AR9_EQ_AR0 ? &nrt3 : &nrt2, 0); // 6-27
|
|
}
|
|
|
|
defpulse_(nrt2)
|
|
{
|
|
word ar0_shl_inp, ar35_shl_inp;
|
|
word mq0_shl_inp, mq35_shl_inp;
|
|
|
|
SC_INC; // 6-16
|
|
// 6-7
|
|
ar0_shl_inp = apr->c.ar & F0;
|
|
mq0_shl_inp = apr->c.ar & F0;
|
|
ar35_shl_inp = (apr->c.mq & F1) >> 34;
|
|
mq35_shl_inp = 0;
|
|
AR_SH_LT; // 6-17
|
|
MQ_SH_LT; // 6-17
|
|
pulse(apr, &nrt1_dly, 150); // 6-17
|
|
}
|
|
|
|
defpulse(nrt1)
|
|
{
|
|
SC_COM; // 6-15
|
|
pulse(apr, &nrt1_dly, 100); // 6-17
|
|
}
|
|
|
|
defpulse(nrt01_dly)
|
|
{
|
|
pulse(apr, AR_0_AND_MQ1_0 ? &nrt6 : &nrt1, 0); // 6-27
|
|
}
|
|
|
|
defpulse(nrt0)
|
|
{
|
|
word ar0_shr_inp;
|
|
word mq0_shr_inp, mq1_shr_inp;
|
|
|
|
SC_INC; // 6-16
|
|
// 6-7
|
|
ar0_shr_inp = apr->c.ar & F0;
|
|
mq0_shr_inp = apr->c.ar & F0;
|
|
mq1_shr_inp = (apr->c.ar & F35) << 34;
|
|
AR_SH_RT; // 6-17
|
|
MQ_SH_RT; // 6-17
|
|
pulse(apr, &nrt01_dly, 200); // 6-27
|
|
}
|
|
|
|
defpulse_(nrt0_5)
|
|
{
|
|
apr->nrf2 = 1; // 6-27
|
|
pulse(apr, &nrt0, 100); // 6-27
|
|
}
|
|
|
|
/* Scale */
|
|
|
|
defpulse(fst1)
|
|
{
|
|
SC_INC; // 6-16
|
|
}
|
|
|
|
defpulse_(fst0a)
|
|
{
|
|
apr->fsf1 = 0; // 6-19
|
|
if(!AR0_EQ_SC0)
|
|
SET_OVERFLOW; // 6-17
|
|
apr->n.ar = apr->n.ar&0400777777777 | ((word)apr->sc&0377)<<27; // 6-4, 6-9
|
|
pulse(apr, &et10, 1); // 5-5
|
|
}
|
|
|
|
defpulse(fst0)
|
|
{
|
|
apr->fsf1 = 1; // 6-19
|
|
pulse(apr, &sat0, 0); // 6-16
|
|
}
|
|
|
|
/* Exponent calculate */
|
|
|
|
// 6-23
|
|
#define AR0_XOR_FMF1 (!!(apr->c.ar & F0) != !!apr->fmf1)
|
|
#define AR0_XOR_MB0_XOR_FMF1 (AR0_XOR_FMF1 != !!(apr->c.mb & F0))
|
|
#define MB0_EQ_FMF1 (!!(apr->c.mb & F0) == !!apr->fmf1)
|
|
|
|
defpulse(fpt4)
|
|
{
|
|
// 6-22
|
|
if(apr->fmf1) pulse(apr, &fmt0a, 0);
|
|
if(apr->fdf1) pulse(apr, &fdt0a, 0);
|
|
}
|
|
|
|
defpulse(fpt3)
|
|
{
|
|
apr->fe |= apr->sc; // 6-15
|
|
apr->sc = 0; // 6-15
|
|
// 6-3, 6-4
|
|
if(apr->c.mb & F0) apr->n.mb |= 0377000000000LL;
|
|
else apr->n.mb &= ~0377000000000LL;
|
|
// 6-9, 6-4
|
|
if(apr->c.ar & F0) apr->n.ar |= 0377000000000LL;
|
|
else apr->n.ar &= ~0377000000000LL;
|
|
pulse(apr, &fpt4, 100); // 6-23
|
|
}
|
|
|
|
defpulse(fpt2)
|
|
{
|
|
SC_INC; // 6-17
|
|
}
|
|
|
|
defpulse_(fpt1b)
|
|
{
|
|
apr->fpf2 = 0; // 6-23
|
|
if(MB0_EQ_FMF1)
|
|
SC_COM; // 6-15
|
|
pulse(apr, &fpt3, 100); // 6-23
|
|
}
|
|
|
|
defpulse(fpt1aa)
|
|
{
|
|
apr->fpf2 = 1; // 6-23
|
|
pulse(apr, &sat0, 0); // 6-15
|
|
}
|
|
|
|
defpulse_(fpt1a)
|
|
{
|
|
apr->fpf1 = 0; // 6-23
|
|
if(AR0_XOR_MB0_XOR_FMF1)
|
|
pulse(apr, &fpt2, 0); // 6-23
|
|
else
|
|
SC_COM; // 6-15
|
|
pulse(apr, &fpt1aa, 100); // 6-23
|
|
}
|
|
|
|
defpulse(fpt1)
|
|
{
|
|
apr->fpf1 = 1; // 6-23
|
|
if(AR0_XOR_FMF1)
|
|
SC_COM; // 6-15
|
|
pulse(apr, &sat0, 0); // 6-16
|
|
}
|
|
|
|
defpulse(fpt0)
|
|
{
|
|
apr->sc |= 0200; // 6-14
|
|
pulse(apr, &fpt1, 100); // 6-23
|
|
}
|
|
|
|
/* Multiply */
|
|
|
|
defpulse_(fmt0b)
|
|
{
|
|
apr->fmf2 = 0; // 6-22
|
|
apr->sc |= apr->fe; // 6-15
|
|
apr->nrf2 = 1; // 6-27
|
|
pulse(apr, &nrt01_dly, 100); // 6-27
|
|
}
|
|
|
|
defpulse_(fmt0a)
|
|
{
|
|
apr->fmf1 = 0; // 6-22
|
|
apr->fmf2 = 1; // 6-22
|
|
apr->sc |= 0744; // 6-14
|
|
pulse(apr, &mst1, 0); // 6-24
|
|
}
|
|
|
|
defpulse(fmt0)
|
|
{
|
|
apr->fmf1 = 1; // 6-22
|
|
pulse(apr, &fpt0, 0); // 6-23
|
|
}
|
|
|
|
/* Divide */
|
|
|
|
defpulse(fdt1)
|
|
{
|
|
word ar0_shr_inp;
|
|
word mq0_shr_inp, mq1_shr_inp;
|
|
|
|
// 6-7
|
|
ar0_shr_inp = apr->c.ar & F0;
|
|
mq0_shr_inp = apr->c.ar & F0;
|
|
mq1_shr_inp = (apr->c.ar & F35) << 34;
|
|
AR_SH_RT; // 6-17
|
|
MQ_SH_RT; // 6-17
|
|
pulse(apr, &nrt0_5, 150); // 6-27
|
|
}
|
|
|
|
defpulse_(fdt0b)
|
|
{
|
|
apr->fdf2 = 0; // 6-22
|
|
apr->sc |= apr->fe; // 6-15
|
|
apr->nrf2 = 1; // 6-27
|
|
pulse(apr, &fdt1, 100); // 6-22
|
|
}
|
|
|
|
defpulse_(fdt0a)
|
|
{
|
|
apr->fdf1 = 0; // 6-22
|
|
apr->fdf2 = 1; // 6-22
|
|
apr->sc |= 0741; // 6-14
|
|
pulse(apr, apr->c.ar & F0 ? &dst0 : &dst10, 0); // 6-25
|
|
}
|
|
|
|
defpulse(fdt0)
|
|
{
|
|
apr->fdf1 = 1; // 6-22
|
|
pulse(apr, &fpt0, 0); // 6-23
|
|
}
|
|
|
|
/* Add/Subtract */
|
|
|
|
defpulse_(fat10)
|
|
{
|
|
apr->faf4 = 0; // 6-22
|
|
apr->faf1 = 0; // 6-22
|
|
pulse(apr, &nrt0_5, 0); // 6-27
|
|
}
|
|
|
|
defpulse(fat9)
|
|
{
|
|
apr->faf4 = 1; // 6-22
|
|
pulse(apr, &cfac_ar_add, 0); // 6-17
|
|
}
|
|
|
|
defpulse(fat8a)
|
|
{
|
|
// 6-3, 6-4
|
|
if(apr->c.mb & F0) apr->n.mb |= 0377000000000;
|
|
else apr->n.mb &= ~0377000000000;
|
|
pulse(apr, &fat9, 100); // 6-22
|
|
}
|
|
|
|
defpulse(fat8)
|
|
{
|
|
SC_PAD; // 6-15
|
|
pulse(apr, &fat8a, 50); // 6-22
|
|
}
|
|
|
|
defpulse(fat7)
|
|
{
|
|
if(apr->c.mb & F0)
|
|
SC_COM; // 6-15
|
|
pulse(apr, &fat8, 100); // 6-22
|
|
}
|
|
|
|
defpulse(fat6)
|
|
{
|
|
AR_CLEAR; // 6-8
|
|
pulse(apr, &fat5a, 0); // 6-22
|
|
}
|
|
|
|
defpulse_(fat5a)
|
|
{
|
|
apr->faf3 = 0; // 6-22
|
|
apr->sc = 0; // 6-15
|
|
apr->faf1 = 1; // 6-22
|
|
pulse(apr, &fat7, 100); // 6-22
|
|
}
|
|
|
|
defpulse(fat5)
|
|
{
|
|
// 6-9, 6-4
|
|
if(apr->c.ar & F0) apr->n.ar |= 0377000000000;
|
|
else apr->n.ar &= ~0377000000000;
|
|
apr->faf3 = 1; // 6-22
|
|
pulse(apr, &sct0, 0); // 6-16
|
|
}
|
|
|
|
defpulse(fat4)
|
|
{
|
|
pulse(apr, (apr->sc & 0700) == 0700 ? &fat5 : &fat6, 100); // 6-22
|
|
}
|
|
|
|
defpulse(fat3)
|
|
{
|
|
SC_COM; // 6-15
|
|
pulse(apr, (apr->sc & 0700) == 0700 ? &fat5 : &fat6, 150); // 6-22
|
|
}
|
|
|
|
defpulse(fat2)
|
|
{
|
|
SC_INC; // 6-16
|
|
pulse(apr, &fat3, 150); // 6-22
|
|
}
|
|
|
|
defpulse(fat1b)
|
|
{
|
|
apr->faf1 = 0; // 6-22
|
|
apr->faf2 = 1; // 6-22
|
|
}
|
|
|
|
defpulse_(fat1a)
|
|
{
|
|
apr->faf2 = 0; // 6-22
|
|
if(!!(apr->c.ar & F0) == !!(apr->sc & 0400))
|
|
SWAP(mb, ar); // 6-17
|
|
pulse(apr, apr->sc & 0400 ? &fat4 : &fat2, 0); // 6-22
|
|
}
|
|
|
|
defpulse(fat1)
|
|
{
|
|
SC_PAD; // 6-15
|
|
pulse(apr, &fat1b, 50); // 6-22
|
|
pulse(apr, &sat0, 0); // 6-16
|
|
}
|
|
|
|
defpulse(fat0)
|
|
{
|
|
if(!AR0_XOR_MB0)
|
|
SC_COM; // 6-15
|
|
apr->faf1 = 1; // 6-22
|
|
pulse(apr, &fat1, 100); // 6-22
|
|
}
|
|
|
|
/*
|
|
* Fixed point multiply
|
|
*/
|
|
|
|
defpulse(mpt2)
|
|
{
|
|
apr->n.ar = apr->c.mb; // 6-8
|
|
pulse(apr, &nrt6, 100); // 6-27
|
|
}
|
|
|
|
defpulse(mpt1)
|
|
{
|
|
apr->n.mb = apr->c.mq; // 6-17
|
|
if(apr->c.ar != 0)
|
|
SET_OVERFLOW; // 6-17
|
|
pulse(apr, &mpt2, 100); // 6-21
|
|
}
|
|
|
|
defpulse_(mpt0a)
|
|
{
|
|
apr->mpf1 = 0; // 6-21
|
|
if(!(apr->ir & H6) && apr->c.ar & F0)
|
|
AR_COM; // 6-17
|
|
if(apr->c.ar & F0 && apr->mpf2)
|
|
SET_OVERFLOW; // 6-17
|
|
if(apr->ir & H6)
|
|
pulse(apr, &nrt6, 0); // 6-27
|
|
else
|
|
pulse(apr, &mpt1, 200); // 6-21
|
|
}
|
|
|
|
defpulse(mpt0)
|
|
{
|
|
apr->sc |= 0734; // 6-14
|
|
apr->mpf1 = 1; // 6-21
|
|
if(apr->c.ar & F0 && apr->c.mb & F0)
|
|
apr->mpf2 = 1; // 6-21
|
|
pulse(apr, &mst1, 0); // 6-24
|
|
}
|
|
|
|
/*
|
|
* AR subroutines
|
|
*/
|
|
|
|
// 6-9
|
|
#define AR_SUB (AS_SUB || ACCP)
|
|
#define AR_ADD (AS_ADD)
|
|
#define AR_P1 (MEMAC_P1 || apr->inst == PUSH || apr->inst == PUSHJ || \
|
|
IOT_BLK || apr->inst == AOBJP || apr->inst == AOBJN)
|
|
#define AR_M1 (MEMAC_M1 || apr->inst == POP || apr->inst == POPJ)
|
|
#define AR_PM1_LTRT (IOT_BLK || apr->inst == AOBJP || apr->inst == AOBJN || \
|
|
apr->ir_jp && !(apr->inst & 0004))
|
|
#define AR_SBR (FWT_NEGATE || AR_ADD || AR_SUB || AR_P1 || AR_M1 || IR_FSB)
|
|
|
|
defpulse(art3)
|
|
{
|
|
apr->ar_com_cont = 0; // 6-9
|
|
|
|
if(apr->af3a) pulse(apr, &at3a, 0); // 5-3
|
|
if(apr->et4_ar_pse) pulse(apr, &et4, 0); // 5-5
|
|
if(apr->blt_f3a) pulse(apr, &blt_t3a, 0); // 6-18
|
|
if(apr->blt_f5a) pulse(apr, &blt_t5a, 0); // 6-18
|
|
if(apr->chf3) pulse(apr, &cht4a, 0); // 6-19
|
|
if(apr->msf1) pulse(apr, &mst3a, 0); // 6-24
|
|
if(apr->dsf1) pulse(apr, &dst0a, 0); // 6-25
|
|
if(apr->dsf2) pulse(apr, &dst5a, 0); // 6-25
|
|
if(apr->dsf3) pulse(apr, &dst10, 0); // 6-25
|
|
if(apr->dsf4) pulse(apr, &dst11a, 0); // 6-25
|
|
if(apr->dsf5) pulse(apr, &dst14a, 0); // 6-26
|
|
if(apr->dsf6) pulse(apr, &dst17a, 0); // 6-26
|
|
if(apr->dsf8) pulse(apr, &dst19a, 0); // 6-26
|
|
if(apr->dsf9) pulse(apr, &dst21a, 0); // 6-26
|
|
if(apr->nrf1) pulse(apr, &nrt5a, 0); // 6-27
|
|
if(apr->faf4) pulse(apr, &fat10, 0); // 6-22
|
|
}
|
|
|
|
defpulse(ar_cry_comp)
|
|
{
|
|
if(apr->ar_com_cont){
|
|
AR_COM; // 6-8
|
|
if(!apr->sw_art3_maint)
|
|
pulse(apr, &art3, 100); // 6-9
|
|
}
|
|
}
|
|
|
|
defpulse_(ar_pm1_t1)
|
|
{
|
|
if(apr->inst == BLT || AR_PM1_LTRT)
|
|
ar_cry_in(apr, 01000001); // 6-9
|
|
else
|
|
ar_cry_in(apr, 1); // 6-6
|
|
// There must be some delay after the carry is done
|
|
// but I don't quite know how this works,
|
|
// so we just use 100ns as the average value
|
|
// given in "The Evolution of the DECsystem-10"
|
|
if(!apr->ar_com_cont && !apr->sw_art3_maint)
|
|
pulse(apr, &art3, 100); // 6-9
|
|
pulse(apr, &ar_cry_comp, 100); // 6-9
|
|
}
|
|
|
|
defpulse(ar_pm1_t0)
|
|
{
|
|
AR_COM; // 6-8
|
|
apr->ar_com_cont = 1; // 6-9
|
|
pulse(apr, &ar_pm1_t1, 100); // 6-9
|
|
}
|
|
|
|
defpulse_(ar_negate_t0)
|
|
{
|
|
AR_COM; // 6-8
|
|
pulse(apr, &ar_pm1_t1, 100); // 6-9
|
|
}
|
|
|
|
defpulse(ar_ast2)
|
|
{
|
|
ar_cry_in(apr, (~apr->c.ar & apr->c.mb) << 1); // 6-8
|
|
// see comment in ar_pm1_t1
|
|
if(!apr->ar_com_cont && !apr->sw_art3_maint)
|
|
pulse(apr, &art3, 50); // 6-9
|
|
pulse(apr, &ar_cry_comp, 50); // 6-9
|
|
}
|
|
|
|
defpulse_(ar_ast1)
|
|
{
|
|
apr->n.ar ^= apr->c.mb; // 6-8
|
|
pulse(apr, &ar_ast2, 100); // 6-9
|
|
}
|
|
|
|
defpulse_(ar_ast0)
|
|
{
|
|
AR_COM; // 6-8
|
|
apr->ar_com_cont = 1; // 6-9
|
|
pulse(apr, &ar_ast1, 100); // 6-9
|
|
}
|
|
|
|
|
|
defpulse(xct_t0)
|
|
{
|
|
pulse(apr, &mr_clr, 0); // 5-2
|
|
pulse(apr, &it1a, 200); // 5-3
|
|
}
|
|
|
|
/*
|
|
* Priority Interrupt
|
|
*/
|
|
|
|
// 5-3
|
|
#define IA_NOT_INT ((!apr->pi_req || apr->pi_cyc) && !apr->ia_inh)
|
|
// 8-4
|
|
#define PI_BLK_RST (!apr->pi_ov && IOT_DATAIO)
|
|
#define PI_RST (apr->ir_jrst && apr->ir & H9 || PI_BLK_RST && apr->pi_cyc)
|
|
#define PI_HOLD ((!apr->ir_iot || PI_BLK_RST) && apr->pi_cyc)
|
|
|
|
defpulse(pi_sync)
|
|
{
|
|
if(!apr->pi_cyc)
|
|
PIR_STB; // 8-4
|
|
if(apr->pi_req && !apr->pi_cyc)
|
|
pulse(apr, &iat0, 200); // 5-3
|
|
if(IA_NOT_INT)
|
|
pulse(apr, apr->if1a ? &it1 : &at1, 200); // 5-3
|
|
}
|
|
|
|
// 5-1
|
|
#define KEY_MANUAL (apr->key_readin || apr->key_start || apr->key_inst_cont ||\
|
|
apr->key_mem_cont || apr->key_ex || apr->key_dep ||\
|
|
apr->key_ex_nxt || apr->key_dep_nxt || apr->key_exec ||\
|
|
apr->key_io_reset)
|
|
#define KEY_MA_MAS (apr->key_readin || apr->key_start ||\
|
|
apr->key_ex_sync || apr->key_dep_sync)
|
|
#define KEY_CLR_RIM (!(apr->key_readin || apr->key_inst_cont || apr->key_mem_cont))
|
|
#define KEY_EXECUTE (apr->key_exec && !apr->run)
|
|
#define KEY_EX_EX_NXT (apr->key_ex_sync || apr->key_ex_nxt)
|
|
#define KEY_DP_DP_NXT (apr->key_dep_sync || apr->key_dep_nxt)
|
|
#define KEY_EXECUTE_DP_DPNXT (KEY_EXECUTE || KEY_DP_DP_NXT)
|
|
|
|
/*
|
|
* Store
|
|
*/
|
|
|
|
// 5-6
|
|
#define SC_E (apr->inst == PUSHJ || apr->inst == PUSH || apr->inst == POP || \
|
|
apr->inst == JSR || apr->inst == JSA || IOT_DATAI || IOT_CONI || \
|
|
apr->fwt_10 || IR_MD_SC_E || IR_FP_MEM || IR_FP_BOTH)
|
|
#define SAC0 ((apr->ir & 0740) == 0)
|
|
#define SAC_INH_IF_AC_0 (SAC0 && (apr->fwt_11 || apr->hwt_11 || MEMAC_MEM))
|
|
#define SAC_INH (apr->boole_as_10 || apr->hwt_10 || BLT_LAST || ACCP || \
|
|
apr->inst == JSR || apr->fwt_10 || ACBM_DN || apr->ir_iot || \
|
|
IR_MD_SAC_INH || CH_DEP || IR_FP_MEM || IR_254_7 || \
|
|
SAC_INH_IF_AC_0)
|
|
#define SAC2 (SH_AC2 || IR_FP_REM || IR_MD_SAC2)
|
|
|
|
defpulse_(st7)
|
|
{
|
|
apr->sf7 = 0; // 5-6
|
|
if(apr->run)
|
|
pulse(apr, apr->key_ex_st || apr->key_dep_st ? &kt1 : &it0, 0); // 5-1, 5-3
|
|
if(apr->key_start || apr->key_readin || apr->key_inst_cont)
|
|
pulse(apr, &kt4, 0); // 5-2
|
|
}
|
|
|
|
defpulse(st6a)
|
|
{
|
|
apr->sf7 = 1; // 5-6
|
|
}
|
|
|
|
defpulse(st6)
|
|
{
|
|
/* We know SAC2 is asserted
|
|
* so clamp to fast memory addresses */
|
|
apr->ma = apr->ma+1 & 017; // 7-3
|
|
apr->n.mb = apr->c.mq; // 6-3
|
|
pulse(apr, &st6a, 50); // 5-6
|
|
pulse(apr, &mc_wr_rq_pulse, 0); // 7-8
|
|
}
|
|
|
|
defpulse(st5a)
|
|
{
|
|
apr->sf5a = 0; // 5-6
|
|
pulse(apr, SAC2 ? &st6 : &st7, 0); // 5-6
|
|
}
|
|
|
|
defpulse(st5)
|
|
{
|
|
apr->sf5a = 1; // 5-6
|
|
apr->ma |= apr->ir>>5 & 017; // 7-3
|
|
apr->n.mb = apr->c.ar; // 6-3
|
|
pulse(apr, &mc_wr_rq_pulse, 0); // 7-8
|
|
}
|
|
|
|
defpulse(st3a)
|
|
{
|
|
pulse(apr, &st5, 100);
|
|
}
|
|
|
|
defpulse(st3)
|
|
{
|
|
apr->sf3 = 0; // 5-6
|
|
if(SAC_INH)
|
|
pulse(apr, &st7, 0); // 5-6
|
|
else{
|
|
apr->ma = 0; // 7-3
|
|
pulse(apr, &st3a, 0); // 5-6
|
|
}
|
|
}
|
|
|
|
defpulse(st2)
|
|
{
|
|
apr->sf3 = 1; // 5-6
|
|
pulse(apr, &mc_rd_wr_rs_pulse, 0); // 7-8
|
|
}
|
|
|
|
defpulse(st1)
|
|
{
|
|
apr->sf3 = 1; // 5-6
|
|
pulse(apr, &mc_wr_rq_pulse, 0); // 7-8
|
|
}
|
|
|
|
/*
|
|
* Execute
|
|
*/
|
|
|
|
// 5-5
|
|
#define ET4_INH (apr->inst == BLT || apr->inst == XCT || apr->ex_ir_uuo || \
|
|
apr->shift_op || AR_SBR || apr->ir_md || IR_FPCH)
|
|
#define ET5_INH (apr->ir_iot || IR_FSB)
|
|
// 5-12
|
|
#define PC_P1_INH (KEY_EXECUTE || (CH_INC_OP || CH_N_INC_OP) && apr->inst != CAO || \
|
|
apr->inst == XCT || apr->ex_ir_uuo || apr->pi_cyc || \
|
|
IOT_BLK || apr->inst == BLT)
|
|
// 5-12
|
|
#define JFCL_FLAGS (apr->ir & 0400 && apr->ar_ov_flag || \
|
|
apr->ir & 0200 && apr->ar_cry0_flag || \
|
|
apr->ir & 0100 && apr->ar_cry1_flag || \
|
|
apr->ir & 0040 && apr->ar_pc_chg_flag)
|
|
#define PC_SET_ENABLE (MEMAC_AC && ACCP_ET_AL_TEST || \
|
|
apr->inst == AOBJN && apr->c.ar & SGN || \
|
|
apr->inst == AOBJP && !(apr->c.ar & SGN) || \
|
|
apr->inst == JFCL && JFCL_FLAGS)
|
|
#define PC_INC_ENABLE ((MEMAC_MEM || ACCP || apr->ir_acbm) && ACCP_ET_AL_TEST || \
|
|
IOT_CONSO && apr->c.ar != 0 || IOT_CONSZ && apr->c.ar == 0)
|
|
#define PC_SET (PC_SET_ENABLE || JP_JMP || apr->ir_jrst)
|
|
#define PC_INC_ET9 (apr->inst == JSR || apr->inst == JSA || PC_INC_ENABLE)
|
|
// 5-5
|
|
#define E_LONG (IOT_CONSZ || apr->ir_jp || apr->ir_acbm || apr->pc_set || \
|
|
MB_PC_STO || PC_INC_ET9 || IOT_CONSO || IR_ACCP_MEMAC)
|
|
|
|
defpulse_(et10)
|
|
{
|
|
bool sc_e = SC_E;
|
|
|
|
if(PI_HOLD){
|
|
// 8-4
|
|
apr->pi_ov = 0;
|
|
apr->pi_cyc = 0;
|
|
}
|
|
if(apr->inst == PUSH || apr->inst == PUSHJ || apr->ir_jrst)
|
|
apr->ma |= apr->c.mb & RT; // 7-3
|
|
if((apr->fc_e_pse || sc_e) &&
|
|
!(apr->ir_jp || apr->inst == EXCH || CH_DEP))
|
|
apr->n.mb = apr->c.ar; // 6-3
|
|
if(apr->ir_jp && !(apr->ir & H6))
|
|
SWAP(mb, ar); // 6-3
|
|
if(MEMAC || apr->ir_as){
|
|
// 6-10
|
|
if(apr->ar_cry0) apr->ar_cry0_flag = 1;
|
|
if(apr->ar_cry1) apr->ar_cry1_flag = 1;
|
|
}
|
|
if(apr->ir_fwt && !apr->ar_cry0 && apr->ar_cry1 ||
|
|
(MEMAC || apr->ir_as) && AR_OV_SET){
|
|
apr->ar_ov_flag = 1; // 6-10
|
|
recalc_cpa_req(apr);
|
|
}
|
|
if(apr->ir_jp && !(apr->ir & H6) && apr->ar_cry0){
|
|
apr->cpa_pdl_ov = 1; // 8-5
|
|
recalc_cpa_req(apr);
|
|
}
|
|
if(apr->inst == JFCL)
|
|
ar_jfcl_clr(apr); // 6-10
|
|
pulse(apr, sc_e ? &st1 : // 5-6
|
|
apr->fc_e_pse ? &st2 : // 5-6
|
|
&st3, 0); // 5-6
|
|
}
|
|
|
|
defpulse_(et9)
|
|
{
|
|
bool pc_inc;
|
|
|
|
pc_inc = PC_INC_ET9;
|
|
if(pc_inc)
|
|
apr->pc = apr->pc+1 & RT; // 5-12
|
|
if((apr->pc_set || pc_inc) && !(apr->ir_jrst && apr->ir & H11)){
|
|
apr->ar_pc_chg_flag = 1; // 6-10
|
|
recalc_cpa_req(apr);
|
|
}
|
|
|
|
if(apr->ir_acbm || apr->ir_jp && apr->inst != JSR)
|
|
SWAP(mb, ar); // 6-3
|
|
if(apr->inst == PUSH || apr->inst == PUSHJ || apr->ir_jrst)
|
|
apr->ma = 0; // 7-3
|
|
if(apr->inst == JSR)
|
|
apr->chf7 = 0; // 6-19
|
|
pulse(apr, &et10, 200); // 5-5
|
|
}
|
|
|
|
defpulse(et8)
|
|
{
|
|
if(apr->pc_set)
|
|
apr->pc |= apr->ma; // 5-12
|
|
if(apr->inst == JSR)
|
|
apr->ex_ill_op = 0; // 5-13
|
|
pulse(apr, &et9, 200); // 5-5
|
|
}
|
|
|
|
defpulse(et7)
|
|
{
|
|
if(apr->pc_set)
|
|
apr->pc = 0; // 5-12
|
|
if(apr->inst == JSR && (apr->ex_pi_sync || apr->ex_ill_op))
|
|
apr->ex_user = 0; // 5-13
|
|
if(apr->ir_acbm)
|
|
AR_COM; // 6-8
|
|
pulse(apr, &et8, 100); // 5-5
|
|
}
|
|
|
|
defpulse(et6)
|
|
{
|
|
if(MB_PC_STO || apr->inst == JSA)
|
|
apr->n.mb |= apr->pc; // 6-3
|
|
if(ACBM_CL)
|
|
apr->n.mb &= apr->c.ar; // 6-3
|
|
if(JP_FLAG_STOR){ // 6-4
|
|
// 6-4
|
|
if(apr->ar_ov_flag) apr->n.mb |= F0;
|
|
if(apr->ar_cry0_flag) apr->n.mb |= F1;
|
|
if(apr->ar_cry1_flag) apr->n.mb |= F2;
|
|
if(apr->ar_pc_chg_flag) apr->n.mb |= F3;
|
|
if(apr->chf7) apr->n.mb |= F4;
|
|
if(apr->ex_user) apr->n.mb |= F5;
|
|
#ifdef FIX_USER_IOT
|
|
if(apr->cpa_iot_user) apr->n.mb |= F6;
|
|
#endif
|
|
}
|
|
if(IOT_CONSZ || IOT_CONSO)
|
|
apr->n.ar &= apr->c.mb; // 6-8
|
|
pulse(apr, &et7, 100); // 5-5
|
|
}
|
|
|
|
defpulse_(et5)
|
|
{
|
|
if(MB_PC_STO)
|
|
MB_CLEAR; // 6-3
|
|
if(apr->ir_acbm)
|
|
AR_COM; // 6-8
|
|
apr->pc_set = PC_SET;
|
|
if(E_LONG) // 5-5
|
|
pulse(apr, &et6, 100);
|
|
else
|
|
pulse(apr, &et10, 1);
|
|
}
|
|
|
|
defpulse_(et4)
|
|
{
|
|
apr->et4_ar_pse = 0; // 5-5
|
|
if(IOT_BLK)
|
|
apr->ex_ill_op = 0; // 5-13
|
|
|
|
// 6-8
|
|
if(apr->ir_boole && (apr->ir_boole_op == 04 ||
|
|
apr->ir_boole_op == 010 ||
|
|
apr->ir_boole_op == 011 ||
|
|
apr->ir_boole_op == 014 ||
|
|
apr->ir_boole_op == 015 ||
|
|
apr->ir_boole_op == 016 ||
|
|
apr->ir_boole_op == 017))
|
|
AR_COM;
|
|
if(HWT_LT || IOT_CONO)
|
|
ARLT_FM_MB_J;
|
|
if(HWT_RT)
|
|
ARRT_FM_MB_J;
|
|
if(HWT_LT_SET)
|
|
ARLT_COM;
|
|
if(HWT_RT_SET)
|
|
ARRT_COM;
|
|
|
|
if(FWT_SWAP || IOT_BLK || apr->ir_acbm)
|
|
SWAP(mb, ar); // 6-3
|
|
|
|
if(IOT_BLK)
|
|
pulse(apr, &iot_t0, 0); // 8-1
|
|
else if(apr->ir_iot)
|
|
apr->iot_go = 1; // 8-1
|
|
if(IR_FSB)
|
|
pulse(apr, &fat0, 0); // 6-22
|
|
if(!ET5_INH)
|
|
pulse(apr, &et5, 100); // 5-5
|
|
}
|
|
|
|
defpulse(et3)
|
|
{
|
|
if(apr->ex_ir_uuo){
|
|
// MBLT <- IR(1) (UUO T0) on 6-3
|
|
apr->n.mb |= ((word)apr->ir&0777740) << 18; // 6-1
|
|
apr->ma |= F30; // 7-3
|
|
apr->uuo_f1 = 1; // 5-10
|
|
pulse(apr, &mc_wr_rq_pulse, 0); // 7-8
|
|
}
|
|
|
|
if(apr->inst == POPJ || apr->inst == BLT)
|
|
apr->ma = apr->c.mb & RT; // 7-3
|
|
|
|
// AR SBR, 6-9
|
|
if(FWT_NEGATE || IR_FSB)
|
|
pulse(apr, &ar_negate_t0, 0);
|
|
if(AR_SUB)
|
|
pulse(apr, &ar_ast0, 0);
|
|
if(AR_ADD)
|
|
pulse(apr, &ar_ast1, 0);
|
|
if(AR_M1)
|
|
pulse(apr, &ar_pm1_t0, 0);
|
|
if(AR_P1)
|
|
pulse(apr, &ar_pm1_t1, 0);
|
|
|
|
if(IR_FPCH && !(apr->ir & H3) &&
|
|
(apr->inst == 0130 || apr->inst == 0131 || !(apr->ir & H4) || !(apr->ir & H5)))
|
|
pulse(apr, &st7, 0); // 5-6
|
|
if(apr->inst == BLT)
|
|
pulse(apr, &blt_t0, 0); // 6-18
|
|
if(apr->shift_op)
|
|
pulse(apr, &sht1, 100); // 6-20
|
|
if(apr->inst == FSC){
|
|
if(apr->c.ar & F0)
|
|
pulse(apr, &fst1, 0); // 6-19
|
|
pulse(apr, &fst0, 0); // 6-19
|
|
}
|
|
if(apr->inst == XCT)
|
|
pulse(apr, &xct_t0, 0); // 5-10
|
|
if(AR_SBR)
|
|
apr->et4_ar_pse = 1; // 5-5
|
|
if(!ET4_INH)
|
|
pulse(apr, &et4, 0); // 5-5
|
|
};
|
|
|
|
defpulse(et1)
|
|
{
|
|
if(apr->ex_ir_uuo){
|
|
apr->ex_ill_op = 1; // 5-13
|
|
MBLT_CLEAR; // 6-3
|
|
}
|
|
if(apr->ir_jrst && apr->ir & H12)
|
|
apr->ex_mode_sync = 1; // 5-13
|
|
if(apr->ir_jrst && apr->ir & H11)
|
|
ar_flag_set(apr); // 6-10
|
|
if(PI_RST)
|
|
pih0_fm_pi_ok1(apr); // 8-4
|
|
|
|
// 6-3
|
|
if(apr->ir_acbm)
|
|
apr->n.mb &= apr->c.ar;
|
|
// 6-8
|
|
if(apr->ir_boole && (apr->ir_boole_op == 06 ||
|
|
apr->ir_boole_op == 011 ||
|
|
apr->ir_boole_op == 014) ||
|
|
ACBM_COM)
|
|
apr->n.ar ^= apr->c.mb;
|
|
if(apr->ir_boole && (apr->ir_boole_op == 01 ||
|
|
apr->ir_boole_op == 02 ||
|
|
apr->ir_boole_op == 015 ||
|
|
apr->ir_boole_op == 016))
|
|
apr->n.ar &= apr->c.mb;
|
|
if(apr->ir_boole && (apr->ir_boole_op == 03 ||
|
|
apr->ir_boole_op == 04 ||
|
|
apr->ir_boole_op == 07 ||
|
|
apr->ir_boole_op == 010 ||
|
|
apr->ir_boole_op == 013) ||
|
|
ACBM_SET)
|
|
apr->n.ar |= apr->c.mb;
|
|
if(HWT_AR_0 || IOT_STATUS || IOT_DATAI)
|
|
AR_CLEAR;
|
|
|
|
if(HWT_SWAP || FWT_SWAP || apr->inst == BLT)
|
|
apr->n.mb = SWAPLTRT(apr->c.mb);
|
|
|
|
if(apr->inst == POPJ || apr->ex_ir_uuo || apr->inst == BLT)
|
|
apr->ma = 0; // 7-3
|
|
if(apr->shift_op && apr->c.mb & F18)
|
|
pulse(apr, &sht0, 0); // 6-20
|
|
if(apr->inst == FSC && !(apr->c.ar & F0))
|
|
SC_COM; // 6-15
|
|
pulse(apr, &et3, 100);
|
|
}
|
|
|
|
defpulse(et0)
|
|
{
|
|
if(!PC_P1_INH)
|
|
apr->pc = apr->pc+1 & RT; // 5-12
|
|
apr->ar_cry0 = 0; // 6-10
|
|
apr->ar_cry1 = 0; // 6-10
|
|
ar_cry(apr);
|
|
if(apr->ir_jrst && apr->ir & H11)
|
|
ar_flag_clr(apr); // 6-10
|
|
if(CH_INC_OP)
|
|
pulse(apr, &cht1, 0); // 6-19
|
|
if(CH_N_INC_OP)
|
|
pulse(apr, &cht6, 0); // 6-19
|
|
if(CH_LOAD)
|
|
pulse(apr, &lct0, 0); // 6-20
|
|
if(CH_DEP)
|
|
pulse(apr, &dct0, 0); // 6-20
|
|
if(IR_MUL)
|
|
pulse(apr, &mpt0, 0); // 6-21
|
|
if(IR_FAD)
|
|
pulse(apr, &fat0, 0); // 6-22
|
|
if(IR_FMP)
|
|
pulse(apr, &fmt0, 0); // 6-22
|
|
if(IR_FDV)
|
|
pulse(apr, &fdt0, 0); // 6-22
|
|
if(IR_DIV){
|
|
pulse(apr, &ds_div_t0, 0); // 6-25
|
|
if(apr->ir & H6) // DIV
|
|
pulse(apr, apr->c.ar & F0 ? &dst3 : &dst10, 0); // 6-25
|
|
else // IDIV
|
|
pulse(apr, apr->c.ar & F0 ? &dst0 : &dst1, 0); // 6-25
|
|
}
|
|
}
|
|
|
|
defpulse(et0a)
|
|
{
|
|
if(loginst){
|
|
debug("%06o: ", apr->inst_ma);
|
|
if((apr->inst & 0700) != 0700)
|
|
debug("%s\n", mnemonics[apr->inst]);
|
|
else
|
|
debug("%s\n", iomnemonics[apr->io_inst>>5 & 7]);
|
|
}
|
|
|
|
if(PI_HOLD)
|
|
pih_fm_pi_ch_rq(apr); // 8-3, 8-4
|
|
if(apr->key_ex_sync)
|
|
apr->key_ex_st = 1; // 5-1
|
|
if(apr->key_dep_sync)
|
|
apr->key_dep_st = 1; // 5-1
|
|
if(apr->key_inst_stop ||
|
|
apr->ir_jrst && apr->ir & H10 && !apr->ex_user)
|
|
apr->run = 0; // 5-1
|
|
|
|
if(apr->ir_boole && (apr->ir_boole_op == 00 ||
|
|
apr->ir_boole_op == 03 ||
|
|
apr->ir_boole_op == 014 ||
|
|
apr->ir_boole_op == 017))
|
|
AR_CLEAR; // 6-8
|
|
if(apr->ir_boole && (apr->ir_boole_op == 02 ||
|
|
apr->ir_boole_op == 04 ||
|
|
apr->ir_boole_op == 012 ||
|
|
apr->ir_boole_op == 013 ||
|
|
apr->ir_boole_op == 015))
|
|
AR_COM; // 6-8
|
|
if(apr->fwt_00 || apr->fwt_11 || apr->hwt_11 || MEMAC_MEM ||
|
|
IOT_BLK || IOT_DATAO)
|
|
apr->n.ar = apr->c.mb; // 6-8
|
|
if(apr->fwt_01 || apr->fwt_10 || IOT_STATUS)
|
|
apr->n.mb = apr->c.ar; // 6-3
|
|
if(apr->hwt_10 || apr->inst == JSP || apr->inst == EXCH ||
|
|
apr->inst == BLT || IR_FSB)
|
|
SWAP(mb, ar); // 6-3
|
|
if(apr->inst == POP || apr->inst == POPJ || apr->inst == JRA)
|
|
apr->n.mb = apr->c.mq; // 6-3
|
|
if(ACBM_SWAP || IOT_CONO || apr->inst == JSA)
|
|
apr->n.mb = SWAPLTRT(apr->c.mb); // 6-3
|
|
if(apr->inst == FSC || apr->shift_op)
|
|
apr->sc |= ~apr->c.mb & 0377 | ~apr->c.mb>>9 & 0400; // 6-15
|
|
}
|
|
|
|
/*
|
|
* Fetch
|
|
*
|
|
* After this stage we have:
|
|
* AR = 0,E or (AC)
|
|
* MQ = 0; (AC+1) or ((AC)LT|RT) if fetched
|
|
* MB = [0?],E or (E)
|
|
*/
|
|
|
|
// 5-4
|
|
#define FAC_INH (apr->hwt_11 || apr->fwt_00 || apr->fwt_01 || apr->fwt_11 || \
|
|
apr->inst == XCT || apr->ex_ir_uuo || \
|
|
apr->inst == JSP || apr->inst == JSR || \
|
|
apr->ir_iot || IR_254_7 || MEMAC_MEM || \
|
|
CH_LOAD || CH_INC_OP || CH_N_INC_OP)
|
|
#define FAC2 (SH_AC2 || IR_MD_FAC2)
|
|
#define FC_C_ACRT (apr->inst == POP || apr->inst == POPJ)
|
|
#define FC_C_ACLT (apr->inst == JRA || apr->inst == BLT)
|
|
#define FC_E (apr->hwt_00 || apr->fwt_00 || apr->inst == XCT || \
|
|
apr->inst == PUSH || IOT_DATAO || apr->ir_fp || \
|
|
IR_MD_FC_E || CH_LOAD || CH_N_INC_OP || \
|
|
ACCP_DIR || ACBM_DIR || apr->boole_as_00)
|
|
#define FC_E_PSE (apr->hwt_10 || apr->hwt_11 || apr->fwt_11 || \
|
|
IOT_BLK || apr->inst == EXCH || CH_DEP || CH_INC_OP || \
|
|
MEMAC_MEM || apr->boole_as_10 || apr->boole_as_11)
|
|
|
|
defpulse(ft7)
|
|
{
|
|
apr->f6a = 1; // 5-4
|
|
pulse(apr, apr->mc_split_cyc_sync ? &mc_split_rd_rq : // 7-8
|
|
&mc_rdwr_rq_pulse, 0); // 7-8
|
|
}
|
|
|
|
defpulse(ft6a)
|
|
{
|
|
apr->f6a = 0; // 5-4
|
|
// HACK: if we fetch nothing at all we get to ET0(A)
|
|
// from AT4, where we clear ARLT, without simulated delay.
|
|
// In the real machines the values must have settled by then,
|
|
// so introduce a fake delay to update our state.
|
|
pulse(apr, &et0a, 1); // 5-5
|
|
pulse(apr, &et0, 1); // 5-5
|
|
pulse(apr, &et1, 100); // 5-5
|
|
}
|
|
|
|
defpulse(ft6)
|
|
{
|
|
apr->f6a = 1; // 5-4
|
|
pulse(apr, &mc_rd_rq_pulse, 0); // 7-8
|
|
}
|
|
|
|
defpulse(ft5)
|
|
{
|
|
// cache this because we need it again in ET10
|
|
apr->fc_e_pse = FC_E_PSE;
|
|
apr->ma = apr->c.mb & RT; // 7-3
|
|
pulse(apr, FC_E ? &ft6 : // 5-4
|
|
apr->fc_e_pse ? &ft7 : // 5-4
|
|
&ft6a, 0); // 5-4
|
|
}
|
|
|
|
defpulse(ft4a)
|
|
{
|
|
apr->f4a = 0; // 5-4
|
|
apr->ma = 0; // 7-3
|
|
SWAP(mb, mq); // 6-3, 6-13
|
|
pulse(apr, &ft5, 100); // 5-4
|
|
}
|
|
|
|
defpulse(ft4)
|
|
{
|
|
apr->n.mq = apr->c.mb; // 6-13
|
|
apr->f4a = 1; // 5-4
|
|
pulse(apr, &mc_rd_rq_pulse, 0); // 7-8
|
|
}
|
|
|
|
defpulse(ft3)
|
|
{
|
|
apr->ma = apr->c.mb & RT; // 7-3
|
|
SWAP(mb, ar); // 6-3
|
|
pulse(apr, &ft4, 100); // 5-4
|
|
}
|
|
|
|
defpulse_(ft1a)
|
|
{
|
|
bool acltrt = FC_C_ACLT || FC_C_ACRT;
|
|
bool fac2 = FAC2;
|
|
apr->f1a = 0; // 5-4
|
|
if(fac2)
|
|
apr->ma = apr->ma+1 & 017; // 7-1, 7-3
|
|
else
|
|
apr->ma = 0; // 7-3
|
|
if(!acltrt)
|
|
SWAP(mb, ar); // 6-3
|
|
if(FC_C_ACLT)
|
|
apr->n.mb = SWAPLTRT(apr->c.mb); // 6-3
|
|
pulse(apr, fac2 ? &ft4 : // 5-4
|
|
acltrt ? &ft3 : // 5-4
|
|
&ft5, 100); // 5-4
|
|
}
|
|
|
|
defpulse(ft1)
|
|
{
|
|
apr->ma |= apr->ir>>5 & 017; // 7-3
|
|
apr->f1a = 1; // 5-4
|
|
pulse(apr, &mc_rd_rq_pulse, 0); // 7-8
|
|
}
|
|
|
|
defpulse_(ft0)
|
|
{
|
|
pulse(apr, FAC_INH ? &ft5 : &ft1, 0); // 5-4
|
|
}
|
|
|
|
/*
|
|
* Address
|
|
*/
|
|
|
|
defpulse(at5)
|
|
{
|
|
apr->a_long = 1; // ?? nowhere to be found
|
|
apr->af0 = 1; // 5-3
|
|
apr->ma |= apr->c.mb & RT; // 7-3
|
|
apr->ir &= ~037; // 5-7
|
|
pulse(apr, &mc_rd_rq_pulse, 0); // 7-8
|
|
}
|
|
|
|
defpulse(at4)
|
|
{
|
|
ARLT_CLEAR; // 6-8
|
|
// no support for drums right now, so no MC DR SPLIT here
|
|
if(apr->sw_addr_stop || apr->key_mem_stop)
|
|
apr->mc_split_cyc_sync = 1; // 7-9
|
|
pulse(apr, apr->ir & 020 ? &at5 : &ft0, 0); // 5-3, 5-4
|
|
}
|
|
|
|
defpulse_(at3a)
|
|
{
|
|
apr->af3a = 0; // 5-3
|
|
apr->n.mb = apr->c.ar; // 6-3
|
|
pulse(apr, &at4, 100); // 5-3
|
|
}
|
|
|
|
defpulse(at3)
|
|
{
|
|
apr->af3 = 0; // 5-3
|
|
apr->ma = 0; // 7-3
|
|
apr->af3a = 1; // 5-3
|
|
pulse(apr, &ar_ast1, 0); // 6-9
|
|
}
|
|
|
|
defpulse(at2)
|
|
{
|
|
apr->a_long = 1; // ?? nowhere to be found
|
|
apr->ma |= apr->ir & 017; // 7-3
|
|
apr->af3 = 1; // 5-3
|
|
pulse(apr, &mc_rd_rq_pulse, 0); // 7-8
|
|
}
|
|
|
|
defpulse_(at1)
|
|
{
|
|
apr->ex_uuo_sync = 1; // 5-13
|
|
// decode here because of EX UUO SYNC
|
|
decodeir(apr);
|
|
pulse(apr, (apr->ir & 017) == 0 ? &at4 : &at2, 0); // 5-3
|
|
}
|
|
|
|
defpulse_(at0)
|
|
{
|
|
ARRT_FM_MB_J; // 6-8
|
|
apr->ir |= apr->c.mb>>18 & 037; // 5-7
|
|
apr->ma = 0; // 7-3
|
|
apr->af0 = 0; // 5-3
|
|
pulse(apr, &pi_sync, 0); // 8-4
|
|
}
|
|
|
|
/*
|
|
* Instruction
|
|
*/
|
|
|
|
defpulse_(it1a)
|
|
{
|
|
apr->if1a = 0; // 5-3
|
|
apr->ir |= apr->c.mb>>18 & 0777740; // 5-7
|
|
if(apr->ma & 0777760)
|
|
set_key_rim_sbr(apr, 0); // 5-2
|
|
pulse(apr, &at0, 0); // 5-3
|
|
}
|
|
|
|
defpulse_(it1)
|
|
{
|
|
if(apr->pi_cyc){
|
|
// 7-3, 8-4
|
|
apr->ma |= 040;
|
|
if(apr->pi_req & 0017) apr->ma |= 010;
|
|
if(apr->pi_req & 0063) apr->ma |= 004;
|
|
if(apr->pi_req & 0125) apr->ma |= 002;
|
|
}else
|
|
apr->ma |= apr->pc; // 7-3
|
|
if(apr->pi_ov)
|
|
apr->ma = (apr->ma+1)&RT; // 7-3
|
|
apr->inst_ma = apr->ma; // remember where we got the instruction from
|
|
apr->if1a = 1; // 5-3
|
|
pulse(apr, &mc_rd_rq_pulse, 0); // 7-8
|
|
}
|
|
|
|
defpulse_(iat0)
|
|
{
|
|
// have to call directly because PI CYC sets EX PI SYNC
|
|
mr_clr_p(apr); // 5-2
|
|
set_pi_cyc(apr, 1); // 8-4
|
|
pulse(apr, &it1, 200); // 5-3
|
|
}
|
|
|
|
defpulse_(it0)
|
|
{
|
|
apr->ma = 0; // 7-3
|
|
// have to call directly because IF1A is set with a delay
|
|
mr_clr_p(apr); // 5-2
|
|
apr->if1a = 1; // 5-3
|
|
pulse(apr, &pi_sync, 0); // 8-4
|
|
}
|
|
|
|
/*
|
|
* Memory Control
|
|
*/
|
|
|
|
defpulse(mi_fm_mb)
|
|
{
|
|
// 7-7
|
|
apr->mi |= apr->c.mb;
|
|
}
|
|
|
|
defpulse(mi_clr)
|
|
{
|
|
// 7-7
|
|
apr->mi = 0;
|
|
pulse(apr, &mi_fm_mb, 100);
|
|
}
|
|
|
|
defpulse(mai_addr_ack)
|
|
{
|
|
pulse(apr, &mc_addr_ack, 0); // 7-8
|
|
}
|
|
|
|
defpulse(mai_rd_rs)
|
|
{
|
|
if(apr->ma == apr->mas)
|
|
pulse(apr, &mi_clr, 0); // 7-7
|
|
if(!apr->mc_stop)
|
|
pulse(apr, &mc_rs_t0, 0); // 7-8
|
|
}
|
|
|
|
defpulse(mc_rs_t1)
|
|
{
|
|
set_mc_rd(apr, 0); // 7-9
|
|
if(apr->key_ex_nxt || apr->key_dep_nxt)
|
|
pulse(apr, &mi_clr, 0); // 7-7
|
|
|
|
if(apr->key_rd_wr) pulse(apr, &key_rd_wr_ret, 0); // 5-2
|
|
if(apr->sf7) pulse(apr, &st7, 0); // 5-6
|
|
if(apr->sf5a) pulse(apr, &st5a, 0); // 5-6
|
|
if(apr->sf3) pulse(apr, &st3, 0); // 5-6
|
|
if(apr->f6a) pulse(apr, &ft6a, 0); // 5-4
|
|
if(apr->f4a) pulse(apr, &ft4a, 0); // 5-4
|
|
if(apr->f1a) pulse(apr, &ft1a, 0); // 5-4
|
|
if(apr->af0) pulse(apr, &at0, 0); // 5-3
|
|
if(apr->af3) pulse(apr, &at3, 0); // 5-3
|
|
if(apr->if1a) pulse(apr, &it1a, 0); // 5-3
|
|
if(apr->iot_f0a) pulse(apr, &iot_t0a, 0); // 8-1
|
|
if(apr->blt_f0a) pulse(apr, &blt_t0a, 0); // 6-18
|
|
if(apr->blt_f3a) pulse(apr, &blt_t3a, 0); // 6-18
|
|
if(apr->blt_f5a) pulse(apr, &blt_t5a, 0); // 6-18
|
|
if(apr->uuo_f1) pulse(apr, &uuo_t1, 0); // 5-10
|
|
if(apr->chf6) pulse(apr, &cht8b, 0); // 6-19
|
|
}
|
|
|
|
defpulse_(mc_rs_t0)
|
|
{
|
|
#ifdef FIX_MEMSTOP
|
|
apr->mc_stop = 0; // ?? not found on 7-9
|
|
#endif
|
|
pulse(apr, &mc_rs_t1, 50); // 7-8
|
|
}
|
|
|
|
defpulse_(mc_wr_rs)
|
|
{
|
|
if(apr->ma == apr->mas)
|
|
pulse(apr, &mi_clr, 0); // 7-7
|
|
apr->membus.c34 |= apr->c.mb; // 7-8
|
|
apr->membus.c12 |= MEMBUS_WR_RS; // 7-8
|
|
if(!apr->mc_stop)
|
|
pulse(apr, &mc_rs_t0, 0); // 7-8
|
|
}
|
|
|
|
defpulse_(mc_addr_ack)
|
|
{
|
|
set_mc_rq(apr, 0); // 7-9
|
|
if(!apr->mc_rd && apr->mc_wr)
|
|
pulse(apr, &mc_wr_rs, 0); // 7-8
|
|
}
|
|
|
|
defpulse(mc_non_exist_rd)
|
|
{
|
|
if(!apr->mc_stop)
|
|
pulse(apr, &mc_rs_t0, 0); // 7-8
|
|
}
|
|
|
|
defpulse(mc_non_exist_mem_rst)
|
|
{
|
|
pulse(apr, &mc_addr_ack, 0); // 7-8
|
|
if(apr->mc_rd)
|
|
pulse(apr, &mc_non_exist_rd, 0); // 7-9
|
|
}
|
|
|
|
defpulse(mc_non_exist_mem)
|
|
{
|
|
apr->cpa_non_exist_mem = 1; // 8-5
|
|
recalc_cpa_req(apr);
|
|
if(!apr->sw_mem_disable)
|
|
pulse(apr, &mc_non_exist_mem_rst, 0); // 7-9
|
|
}
|
|
|
|
defpulse(mc_error_dly)
|
|
{
|
|
if(apr->mc_rq && !apr->mc_stop)
|
|
pulse(apr, &mc_non_exist_mem, 0); // 7-9
|
|
}
|
|
|
|
defpulse(mc_illeg_address)
|
|
{
|
|
apr->cpa_illeg_op = 1; // 8-5
|
|
recalc_cpa_req(apr);
|
|
pulse(apr, &st7, 100); // 5-6
|
|
}
|
|
|
|
defpulse(mc_rq_1)
|
|
{
|
|
set_mc_rq(apr, 1); // 7-9
|
|
}
|
|
|
|
defpulse(mc_stop_1)
|
|
{
|
|
// NOTE: it's important this pulse come *before* MC RS T0
|
|
apr->mc_stop = 1; // 7-9
|
|
if(apr->key_mem_cont)
|
|
pulse(apr, &kt4, 0); // 5-2
|
|
}
|
|
|
|
defpulse(mc_rq_pulse)
|
|
{
|
|
bool ma_ok;
|
|
|
|
/* have to call this to set flags, do relocation and set address */
|
|
ma_ok = relocate(apr);
|
|
apr->mc_stop = 0; // 7-9
|
|
|
|
/* this pulse is likely to be still queued. so remove first it. */
|
|
rempulse(apr, &mc_error_dly);
|
|
pulse(apr, &mc_error_dly, 100000); // 7-9
|
|
|
|
if(ma_ok || apr->ex_inh_rel)
|
|
pulse(apr, &mc_rq_1, 50);
|
|
else
|
|
pulse(apr, &mc_illeg_address, 150); // 7-9
|
|
if(apr->key_mem_stop || apr->ma == apr->mas && apr->sw_addr_stop)
|
|
pulse(apr, &mc_stop_1, 200); // 7-9
|
|
}
|
|
|
|
defpulse_(mc_rdwr_rq_pulse)
|
|
{
|
|
set_mc_rd(apr, 1); // 7-9
|
|
set_mc_wr(apr, 1); // 7-9
|
|
MB_CLEAR; // 7-8
|
|
apr->mc_stop_sync = 1; // 7-9
|
|
pulse(apr, &mc_rq_pulse, 0); // 7-8
|
|
}
|
|
|
|
defpulse_(mc_rd_rq_pulse)
|
|
{
|
|
set_mc_rd(apr, 1); // 7-9
|
|
set_mc_wr(apr, 0); // 7-9
|
|
MB_CLEAR; // 7-8
|
|
pulse(apr, &mc_rq_pulse, 0); // 7-8
|
|
}
|
|
|
|
defpulse_(mc_split_rd_rq)
|
|
{
|
|
pulse(apr, &mc_rd_rq_pulse, 0); // 7-8
|
|
}
|
|
|
|
defpulse_(mc_wr_rq_pulse)
|
|
{
|
|
set_mc_rd(apr, 0); // 7-9
|
|
set_mc_wr(apr, 1); // 7-9
|
|
pulse(apr, &mc_rq_pulse, 0); // 7-8
|
|
}
|
|
|
|
defpulse(mc_split_wr_rq)
|
|
{
|
|
pulse(apr, &mc_wr_rq_pulse, 0); // 7-8
|
|
}
|
|
|
|
defpulse_(mc_rd_wr_rs_pulse)
|
|
{
|
|
if(apr->mc_split_cyc_sync)
|
|
pulse(apr, &mc_split_wr_rq, 0); // 7-8
|
|
else
|
|
pulse(apr, &mc_wr_rs, 100); // 7-8
|
|
}
|
|
|
|
/*
|
|
* Keys
|
|
*/
|
|
|
|
defpulse_(key_rd_wr_ret)
|
|
{
|
|
apr->key_rd_wr = 0; // 5-2
|
|
// apr->ex_ill_op = 0; // ?? not found on 5-13
|
|
pulse(apr, &kt4, 0); // 5-2
|
|
}
|
|
|
|
defpulse(key_rd)
|
|
{
|
|
apr->key_rd_wr = 1; // 5-2
|
|
pulse(apr, &mc_rd_rq_pulse, 0); // 7-8
|
|
}
|
|
|
|
defpulse(key_wr)
|
|
{
|
|
apr->key_rd_wr = 1; // 5-2
|
|
apr->n.mb = apr->c.ar; // 6-3
|
|
pulse(apr, &mc_wr_rq_pulse, 0); // 7-8
|
|
}
|
|
|
|
defpulse(key_go)
|
|
{
|
|
apr->run = 1; // 5-1
|
|
apr->key_ex_st = 0; // 5-1
|
|
apr->key_dep_st = 0; // 5-1
|
|
apr->key_ex_sync = 0; // 5-1
|
|
apr->key_dep_sync = 0; // 5-1
|
|
pulse(apr, &it0, 0); // 5-3
|
|
}
|
|
|
|
defpulse_(kt4)
|
|
{
|
|
/* low end of ranges. unsure, but not totally off */
|
|
static word ranges[6] = {
|
|
3400,
|
|
41718, // *12.27
|
|
602407, // *14.44
|
|
6024079, // *10
|
|
60240792, // *10
|
|
269878748, // *4.48
|
|
};
|
|
static RtcMsg rpt = { 1, 0, nil, 0 };
|
|
|
|
if(apr->run && (apr->key_ex_st || apr->key_dep_st))
|
|
pulse(apr, &key_go, 0); // 5-2
|
|
|
|
if(apr->sw_repeat){
|
|
rpt.c = apr->rptchan;
|
|
rpt.interval = ranges[apr->speed_range];
|
|
/* TODO: is this just a multiplier */
|
|
rpt.interval *= 1 + apr->speed_set/100.0f*14.0f;
|
|
chansend(rtcchan, &rpt);
|
|
}
|
|
}
|
|
|
|
defpulse(kt3)
|
|
{
|
|
if(apr->key_readin || apr->key_start)
|
|
apr->pc |= apr->ma; // 5-12
|
|
if(KEY_EXECUTE){
|
|
apr->n.mb = apr->c.ar; // 6-3
|
|
pulse(apr, &it1a, 100); // 5-3
|
|
pulse(apr, &kt4, 0); // 5-2
|
|
}
|
|
if(KEY_EX_EX_NXT)
|
|
pulse(apr, &key_rd, 0); // 5-2
|
|
if(KEY_DP_DP_NXT)
|
|
pulse(apr, &key_wr, 0); // 5-2
|
|
if(apr->key_start || apr->key_readin || apr->key_inst_cont)
|
|
pulse(apr, &key_go, 0); // 5-2
|
|
}
|
|
|
|
defpulse(kt2)
|
|
{
|
|
if(KEY_MA_MAS)
|
|
apr->ma |= apr->mas; // 7-1
|
|
if(KEY_EXECUTE_DP_DPNXT)
|
|
apr->n.ar |= apr->data; // 5-2
|
|
pulse(apr, &kt3, 200); // 5-2
|
|
if(apr->sw_art3_maint)
|
|
pulse(apr, &art3, 0); // 6-9
|
|
}
|
|
|
|
defpulse_(kt1)
|
|
{
|
|
// has to happen before mc_stop_sync is cleared in MR CLR
|
|
// TODO: test this
|
|
if(KEY_MANUAL && apr->mc_stop && apr->mc_stop_sync && !apr->key_mem_cont)
|
|
pulse(apr, &mc_wr_rs, 0); // 7-8
|
|
if(apr->key_io_reset)
|
|
pulse(apr, &mr_start, 0); // 5-2
|
|
if(KEY_MANUAL && !apr->key_mem_cont)
|
|
pulse(apr, &mr_clr, 0); // 5-2
|
|
if(KEY_CLR_RIM)
|
|
set_key_rim_sbr(apr, 0); // 5-2
|
|
if(apr->key_mem_cont && apr->mc_stop)
|
|
pulse(apr, &mc_rs_t0, 0); // 7-8
|
|
|
|
if(apr->key_readin)
|
|
set_key_rim_sbr(apr, 1); // 5-2
|
|
if(apr->key_readin || apr->key_start)
|
|
apr->pc = 0; // 5-12
|
|
if(KEY_MA_MAS)
|
|
apr->ma = 0; // 5-2
|
|
if(apr->key_ex_nxt || apr->key_dep_nxt)
|
|
apr->ma = (apr->ma+1)&RT; // 5-2
|
|
if(KEY_EXECUTE_DP_DPNXT)
|
|
AR_CLEAR; // 5-2
|
|
|
|
pulse(apr, &kt2, 200); // 5-2
|
|
}
|
|
|
|
defpulse(kt0a)
|
|
{
|
|
apr->key_ex_st = 0; // 5-1
|
|
apr->key_dep_st = 0; // 5-1
|
|
apr->key_ex_sync = apr->key_ex; // 5-1
|
|
apr->key_dep_sync = apr->key_dep; // 5-1
|
|
if(!apr->run || apr->key_mem_cont)
|
|
// TODO: actually 0 or 100, but couldn't this
|
|
// cause kt1 to be executed multiple times?
|
|
pulse(apr, &kt1, 100); // 5-2
|
|
}
|
|
|
|
defpulse(kt0)
|
|
{
|
|
pulse(apr, &kt0a, 0); // 5-2
|
|
}
|
|
|
|
defpulse(key_manual)
|
|
{
|
|
pulse(apr, &kt0, 0); // 5-2
|
|
}
|
|
|
|
|
|
/* find out which bits were turned on */
|
|
void
|
|
updatebus(void *bus)
|
|
{
|
|
IOBus *b;
|
|
b = bus;
|
|
b->c12_pulse = (b->c12_prev ^ b->c12) & b->c12;
|
|
b->c34_pulse = (b->c34_prev ^ b->c34) & b->c34;
|
|
}
|
|
|
|
void
|
|
aprstart(Apr *apr)
|
|
{
|
|
static RtcMsg lineclk = { 1, 1, nil, 1000000000/60 };
|
|
|
|
int i;
|
|
// printf("[aprstart]\n");
|
|
|
|
apr->pfree = nil;
|
|
apr->pulse = nil;
|
|
for(i = 0; i < MAXPULSE; i++)
|
|
pfree(apr, &apr->pulses[i]);
|
|
apr->ia_inh = 0;
|
|
|
|
// must clear lest EX USER be set by MR CLR after MR START
|
|
apr->ex_mode_sync = 0;
|
|
|
|
apr->membus.c12 = 0;
|
|
apr->membus.c34 = 0;
|
|
apr->iobus.c12 = 0;
|
|
apr->iobus.c34 = 0;
|
|
|
|
pulse(apr, &mr_pwr_clr, 100); // random value
|
|
apr->powered = 1;
|
|
|
|
lineclk.c = apr->clkchan;
|
|
chansend(rtcchan, &lineclk);
|
|
}
|
|
|
|
static void
|
|
aprcycle(void *p)
|
|
{
|
|
Apr *apr;
|
|
Busdev *dev;
|
|
int i, devcode;
|
|
bool iot_go_pulse;
|
|
|
|
apr = p;
|
|
if(!apr->sw_power){
|
|
apr->powered = 0;
|
|
return;
|
|
}else if(!apr->powered)
|
|
aprstart(apr);
|
|
|
|
int foo;
|
|
if(channbrecv(apr->clkchan, &foo) == 1){
|
|
apr->cpa_clock_flag = 1;
|
|
recalc_cpa_req(apr);
|
|
}
|
|
/* This isn't correct but how else can you single step? */
|
|
// just force it OFF
|
|
if(!apr->run){
|
|
apr->cpa_clock_flag = 0;
|
|
recalc_cpa_req(apr);
|
|
}
|
|
|
|
if(channbrecv(apr->rptchan, &foo) == 1){
|
|
if(KEY_MANUAL)
|
|
pulse(apr, &kt0a, 1);
|
|
}
|
|
|
|
apr->iobus.c12_prev = apr->iobus.c12;
|
|
apr->iobus.c34_prev = apr->iobus.c34;
|
|
apr->membus.c12_prev = apr->membus.c12;
|
|
apr->membus.c34_prev = apr->membus.c34;
|
|
|
|
i = stepone(apr);
|
|
|
|
iot_go_pulse = apr->iot_go && !apr->iot_reset;
|
|
if(iot_go_pulse && !apr->iot_go_pulse){
|
|
apr->iot_init_setup = 1;
|
|
/* These are asserted during INIT SETUP, IOT T2 and FINAL SETUP.
|
|
* We clear them in IOT T3A which happens after FINAL SETUP */
|
|
if(IOT_OUTGOING) apr->iobus.c12 |= apr->c.ar;
|
|
if(IOT_STATUS) apr->iobus.c34 |= IOBUS_IOB_STATUS;
|
|
if(IOT_DATAI) apr->iobus.c34 |= IOBUS_IOB_DATAI;
|
|
pulse(apr, &iot_t2, 1000);
|
|
}
|
|
apr->iot_go_pulse = iot_go_pulse;
|
|
|
|
updatebus(&apr->iobus);
|
|
updatebus(&apr->membus);
|
|
|
|
|
|
/* Key pulses */
|
|
if(apr->extpulse & EXT_KEY_MANUAL){
|
|
apr->extpulse &= ~EXT_KEY_MANUAL;
|
|
pulse(apr, &key_manual, 1);
|
|
}
|
|
if(apr->extpulse & EXT_KEY_INST_STOP){
|
|
apr->extpulse &= ~EXT_KEY_INST_STOP;
|
|
apr->run = 0;
|
|
// hack: cleared when the pulse list was empty
|
|
apr->ia_inh = 1;
|
|
}
|
|
|
|
|
|
/* Pulses and signals through IO bus.
|
|
* NB: we interpret level signals as pulses here too. */
|
|
apr->iobus.devcode = -1;
|
|
if(apr->iobus.c34_pulse & (IOBUS_PULSES | IOBUS_IOB_STATUS | IOBUS_IOB_DATAI)){
|
|
devcode = 0;
|
|
if(apr->iobus.c34 & IOBUS_IOS3_1) devcode |= 0100;
|
|
if(apr->iobus.c34 & IOBUS_IOS4_1) devcode |= 0040;
|
|
if(apr->iobus.c34 & IOBUS_IOS5_1) devcode |= 0020;
|
|
if(apr->iobus.c34 & IOBUS_IOS6_1) devcode |= 0010;
|
|
if(apr->iobus.c34 & IOBUS_IOS7_1) devcode |= 0004;
|
|
if(apr->iobus.c34 & IOBUS_IOS8_1) devcode |= 0002;
|
|
if(apr->iobus.c34 & IOBUS_IOS9_1) devcode |= 0001;
|
|
apr->iobus.devcode = devcode;
|
|
dev = &apr->iobus.dev[devcode];
|
|
if(dev->wake)
|
|
dev->wake(dev->dev);
|
|
}
|
|
updatebus(&apr->iobus); // need this because IOB RESET can be set
|
|
if(apr->iobus.c34_pulse & IOBUS_IOB_RESET){
|
|
int d;
|
|
for(d = 0; d < 128; d++){
|
|
dev = &apr->iobus.dev[d];
|
|
if(dev->wake)
|
|
dev->wake(dev->dev);
|
|
}
|
|
}
|
|
apr->iobus.c34 &= ~(IOBUS_PULSES | IOBUS_IOB_RESET);
|
|
|
|
/* Pulses to memory */
|
|
if(apr->membus.c12_pulse & (MEMBUS_WR_RS | MEMBUS_RQ_CYC)){
|
|
wakemem(&apr->membus);
|
|
apr->membus.c12 &= ~MEMBUS_WR_RS;
|
|
}
|
|
|
|
/* Pulses from memory */
|
|
if(apr->membus.c12 & MEMBUS_MAI_ADDR_ACK){
|
|
apr->membus.c12 &= ~MEMBUS_MAI_ADDR_ACK;
|
|
// TODO: figure out a better delay
|
|
// NB: must be at least 200 because
|
|
// otherwise MC STOP won't be set in time
|
|
pulse(apr, &mai_addr_ack, 200);
|
|
}
|
|
if(apr->membus.c12 & MEMBUS_MAI_RD_RS){
|
|
apr->membus.c12 &= ~MEMBUS_MAI_RD_RS;
|
|
// TODO: as above
|
|
pulse(apr, &mai_rd_rs, 200);
|
|
}
|
|
if(apr->mc_rd && apr->membus.c34){
|
|
/* 7-6, 7-9 */
|
|
apr->n.mb |= apr->membus.c34;
|
|
apr->membus.c34 = 0;
|
|
}
|
|
|
|
if(i)
|
|
trace("--------------\n");
|
|
else
|
|
/* no longer needed */
|
|
apr->ia_inh = 0;
|
|
}
|
|
|
|
void
|
|
apr_testinst(Apr *apr)
|
|
{
|
|
apr->sw_power = 0;
|
|
aprcycle(apr);
|
|
apr->sw_power = 1;
|
|
aprcycle(apr);
|
|
|
|
while(apr->pulse)
|
|
aprcycle(apr);
|
|
apr->pc = 020;
|
|
pulse(apr, &it0, 1);
|
|
while(apr->pulse)
|
|
aprcycle(apr);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
testinst(Apr *apr)
|
|
{
|
|
int inst;
|
|
|
|
for(inst = 0; inst < 0700; inst++){
|
|
// for(inst = 0140; inst < 0141; inst++){
|
|
apr->ir = inst << 9 | 1 << 5;
|
|
decodeir(apr);
|
|
debug("%06o %6s ", apr->ir, mnemonics[inst]);
|
|
/*
|
|
debug("%s ", FAC_INH ? "FAC_INH" : " ");
|
|
debug("%s ", FAC2 ? "FAC2" : " ");
|
|
debug("%s ", FC_C_ACRT ? "FC_C_ACRT" : " ");
|
|
debug("%s ", FC_C_ACLT ? "FC_C_ACLT" : " ");
|
|
debug("%s ", FC_E ? "FC_E" : " ");
|
|
*/
|
|
debug("%s ", FC_E_PSE ? "FC_E_PSE" : " ");
|
|
debug("%s ", SC_E ? "SC_E" : " ");
|
|
debug("%s ", SAC_INH ? "SAC_INH" : " ");
|
|
debug("%s ", SAC2 ? "SAC2" : " ");
|
|
debug("\n");
|
|
// FC_E_PSE
|
|
//debug("FC_E_PSE: %d %d %d %d %d %d %d %d %d %d\n", apr->hwt_10 , apr->hwt_11 , apr->fwt_11 ,
|
|
// IOT_BLK , apr->inst == EXCH , CH_DEP , CH_INC_OP ,
|
|
// MEMAC_MEM , apr->boole_as_10 , apr->boole_as_11);
|
|
//debug("CH: %d %d %d %d %d\n", CH_INC, CH_INC_OP, CH_N_INC_OP, CH_LOAD, CH_DEP);
|
|
//debug("FAC_INH: %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
|
|
// apr->hwt_11 , apr->fwt_00 , apr->fwt_01 , apr->fwt_11 ,
|
|
// apr->inst == XCT , apr->ex_ir_uuo ,
|
|
// apr->inst == JSP , apr->inst == JSR ,
|
|
// apr->ir_iot , IR_254_7 , MEMAC_MEM ,
|
|
// CH_LOAD , CH_INC_OP , CH_N_INC_OP);
|
|
}
|
|
}
|