mirror of
https://github.com/aap/pdp6.git
synced 2026-01-24 11:31:15 +00:00
1579 lines
35 KiB
C
1579 lines
35 KiB
C
#include "pdp6.h"
|
|
|
|
int dotrace = 1;
|
|
Apr apr;
|
|
|
|
void
|
|
trace(char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
if(!dotrace)
|
|
return;
|
|
va_start(ap, fmt);
|
|
vfprintf(stdout, fmt, ap);
|
|
va_end(ap);
|
|
}
|
|
|
|
void
|
|
decode_ch(Apr *apr)
|
|
{
|
|
int ir6_8;
|
|
ir6_8 = apr->ir>>9 & 7;
|
|
apr->ch_inc = apr->ch_inc_op = apr->ch_n_inc_op = 0;
|
|
apr->ch_load = apr->ch_dep = 0;
|
|
if((apr->ir & 0770000) == 0130000){
|
|
apr->ch_inc = ((ir6_8 & 5) == 4 || ir6_8 == 3) && !apr->chf5;
|
|
apr->ch_inc_op = apr->ch_inc && !apr->chf7;
|
|
apr->ch_n_inc_op = (ir6_8 & 5) == 5 && !apr->chf5 ||
|
|
apr->ch_inc && apr->chf7;
|
|
apr->ch_load = (ir6_8 & 6) == 4 && apr->chf5;
|
|
apr->ch_dep = (ir6_8 & 6) == 6 && apr->chf5;
|
|
}
|
|
if(apr->ch_inc_op || apr->ch_n_inc_op || apr->ch_load)
|
|
apr->fac_inh = 1;
|
|
if(apr->ch_n_inc_op || apr->ch_load)
|
|
apr->fc_e = 1;
|
|
if(apr->ch_dep || apr->ch_inc_op)
|
|
apr->fc_e_pse = 1;
|
|
if(apr->ch_dep)
|
|
apr->sac_inh = 1;
|
|
}
|
|
|
|
void
|
|
decode_2xx(Apr *apr)
|
|
{
|
|
apr->ir_fwt = (apr->inst & 0760) == 0200;
|
|
apr->ir_fwt_swap = 0;
|
|
apr->fwt_00 = apr->fwt_01 = apr->fwt_10 = apr->fwt_11 = 0;
|
|
if(apr->ir_fwt){
|
|
apr->ir_fwt_swap = (apr->inst & 0774) == 0204;
|
|
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;
|
|
if(apr->fwt_00 || apr->fwt_01 || apr->fwt_11)
|
|
apr->fac_inh = 1;
|
|
if(apr->fwt_00)
|
|
apr->fc_e = 1;
|
|
if(apr->fwt_11)
|
|
apr->fc_e_pse = 1;
|
|
if(apr->fwt_10)
|
|
apr->sac_inh = apr->sc_e = 1;
|
|
}
|
|
apr->fc_c_acrt = (apr->inst & 0776) == 0262;
|
|
apr->fc_c_aclt = apr->inst == 0251 || apr->inst == 0267;
|
|
|
|
apr->ir_md = (apr->inst & 0760) == 0220;
|
|
if(apr->ir_md){
|
|
if((apr->inst & 03) != 1)
|
|
apr->fc_e = 1;
|
|
if((apr->inst & 03) == 2)
|
|
apr->sac_inh = 1;
|
|
if(apr->inst & 02)
|
|
apr->sc_e = 1;
|
|
if((apr->inst & 0774) == 0224)
|
|
apr->fac2 = 1;
|
|
if(((apr->inst & 0774) == 0224 || (apr->inst & 0770) == 0230) &&
|
|
!apr->sac_inh)
|
|
apr->sac2 = 1;
|
|
}
|
|
|
|
apr->shift_op = (apr->inst & 0770) == 0240 &&
|
|
(apr->inst & 03) != 3;
|
|
if(apr->shift_op && apr->inst & 04)
|
|
apr->fac2 = apr->sac2 = 1;
|
|
|
|
if(apr->inst == EXCH)
|
|
apr->fc_e_pse = 1;
|
|
if((apr->inst & 0774) == 0254)
|
|
apr->fac_inh = 1;
|
|
if(apr->inst == XCT)
|
|
apr->fac_inh = apr->fc_e = 1;
|
|
|
|
apr->ir_jp = (apr->inst & 0770) == 0260;
|
|
if(apr->ir_jp){
|
|
apr->e_long = 1;
|
|
if(apr->inst == PUSHJ)
|
|
apr->sc_e = apr->mb_pc_sto = 1;
|
|
if(apr->inst == PUSH)
|
|
apr->sc_e = apr->fc_e = 1;
|
|
if((apr->inst & 0776) == 0264) /* JSR, JSP */
|
|
apr->mb_pc_sto = apr->fac_inh = 1;
|
|
if(apr->inst == POP || apr->inst == JSR || apr->inst == JSA)
|
|
apr->sc_e = 1;
|
|
}
|
|
|
|
apr->ir_as = (apr->inst & 0770) == 0270;
|
|
}
|
|
|
|
void
|
|
decodeir(Apr *apr)
|
|
{
|
|
bool iot_a, jrst_a, uuo_a;
|
|
|
|
apr->inst = apr->ir>>9 & 0777;
|
|
apr->fac_inh = 0;
|
|
apr->fc_e = 0;
|
|
apr->fc_e_pse = 0;
|
|
apr->e_long = 0;
|
|
apr->mb_pc_sto = 0;
|
|
apr->sc_e = 0;
|
|
apr->sac_inh = 0;
|
|
apr->sac2 = 0;
|
|
|
|
decode_ch(apr);
|
|
|
|
apr->ir_fp = (apr->inst & 0740) == 0140;
|
|
if(apr->ir_fp){
|
|
apr->fc_e = 1;
|
|
if(apr->inst & 02) /* M, B */
|
|
apr->sc_e = 1;
|
|
if((apr->inst & 03) == 2)
|
|
apr->sac_inh = 1;
|
|
if((apr->inst & 03) == 1)
|
|
apr->sac2 = 1;
|
|
}
|
|
|
|
decode_2xx(apr);
|
|
|
|
/* ACCP v MEMAC */
|
|
apr->ir_accp = apr->ir_memac = apr->ir_memac_mem = apr->ir_memac_ac = 0;
|
|
if((apr->inst & 0700) == 0300){
|
|
apr->ir_memac = apr->inst & 060;
|
|
apr->ir_accp = !apr->ir_memac;
|
|
apr->ir_memac_mem = apr->ir_memac && apr->inst & 010;
|
|
apr->ir_memac_ac = apr->ir_memac && !apr->ir_memac_mem;
|
|
if(apr->ir_memac_mem)
|
|
apr->fac_inh = apr->fc_e_pse = 1;
|
|
if(apr->ir_accp && apr->inst & 010)
|
|
apr->fc_e = 1;
|
|
apr->e_long = 1;
|
|
if(apr->ir_accp)
|
|
apr->sac_inh = 1;
|
|
}
|
|
|
|
/* 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;
|
|
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;
|
|
if(apr->ir_hwt){
|
|
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->hwt_00)
|
|
apr->fc_e = 1;
|
|
if(apr->hwt_11)
|
|
apr->fac_inh = 1;
|
|
if(apr->hwt_10 || apr->hwt_11)
|
|
apr->fc_e_pse = 1;
|
|
if(apr->hwt_10)
|
|
apr->sac_inh = 1;
|
|
}
|
|
|
|
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;
|
|
if(apr->boole_as_00)
|
|
apr->fc_e = 1;
|
|
if(apr->boole_as_10 || apr->boole_as_11)
|
|
apr->fc_e_pse = 1;
|
|
if(apr->boole_as_10)
|
|
apr->sac_inh = 1;
|
|
}
|
|
|
|
/* ACBM */
|
|
apr->ir_acbm = (apr->inst & 0700) == 0600;
|
|
if(apr->ir_acbm){
|
|
if(apr->inst & 010)
|
|
apr->fc_e = 1;
|
|
apr->e_long = 1;
|
|
if(!(apr->inst & 60))
|
|
apr->sac_inh = 1;
|
|
}
|
|
|
|
if(!(apr->ir & 0740) && (apr->fwt_11 || apr->hwt_11 || apr->ir_memac_mem))
|
|
apr->sac_inh = 1;
|
|
|
|
uuo_a = (apr->inst & 0700) == 0;
|
|
iot_a = (apr->inst & 0700) == 0700;
|
|
jrst_a = apr->inst == 0254;
|
|
// 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;
|
|
apr->ir_iot = !apr->ex_ir_uuo && iot_a;
|
|
apr->iot_blk = apr->ir_iot && (apr->ir & 0240) == 0;
|
|
apr->iot_dataio = apr->ir_iot && (apr->ir & 0240) == 0040;
|
|
|
|
if(apr->ir_jrst)
|
|
apr->mb_pc_sto = 1;
|
|
|
|
if(apr->ex_ir_uuo || apr->ir_iot)
|
|
apr->fac_inh = 1;
|
|
if(apr->iot_blk)
|
|
apr->fc_e_pse = 1;
|
|
if(apr->iot_dataio && apr->ir & 0100) /* DATAO */
|
|
apr->fc_e = 1;
|
|
/* No need to check PC +1 for E LONG, it's already implied.
|
|
* We have to wait until ET5 for PC SET */
|
|
if(apr->ir_iot && (apr->inst & 0300) == 0300 || /* CONSZ, CONSO */
|
|
apr->mb_pc_sto)
|
|
apr->e_long = 1;
|
|
if(apr->ir_iot && (apr->ir & 0140) == 040) /* DATAI, CONI */
|
|
apr->sc_e = 1;
|
|
}
|
|
|
|
void
|
|
swap(word *a, word *b)
|
|
{
|
|
word tmp;
|
|
tmp = *a;
|
|
*a = *b;
|
|
*b = tmp;
|
|
}
|
|
|
|
bool
|
|
accp_et_al_test(Apr *apr)
|
|
{
|
|
bool lt, cond;
|
|
// 5-9
|
|
lt = !!(apr->ar & SGN) != apr->ar_cry0_xor_cry1;
|
|
cond = (apr->inst & 2) && apr->ar == 0 ||
|
|
(apr->ir_accp || apr->ir_memac) && (apr->inst & 1) && lt;
|
|
return cond != !!(apr->inst & 040);
|
|
}
|
|
|
|
bool
|
|
selected_flag(Apr *apr)
|
|
{
|
|
// 5-12
|
|
return 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;
|
|
}
|
|
|
|
void
|
|
selected_flags_clr(Apr *apr)
|
|
{
|
|
// 6-10
|
|
if(apr->ir & 0400) apr->ar_ov_flag = 0;
|
|
if(apr->ir & 0200) apr->ar_cry0_flag = 0;
|
|
if(apr->ir & 0100) apr->ar_cry1_flag = 0;
|
|
if(apr->ir & 0040) apr->ar_pc_chg_flag = 0;
|
|
}
|
|
|
|
bool
|
|
pc_set_enable(Apr *apr)
|
|
{
|
|
// 5-12
|
|
return apr->inst == AOBJP && !(apr->ar & SGN) ||
|
|
apr->inst == AOBJN && apr->ar & SGN ||
|
|
apr->ir_memac_ac && accp_et_al_test(apr) ||
|
|
apr->inst == JFCL && selected_flag(apr);
|
|
}
|
|
|
|
bool
|
|
pc_inc_enable(Apr *apr)
|
|
{
|
|
// 5-12
|
|
return (apr->ir_accp || apr->ir_acbm || apr->ir_memac_mem) && accp_et_al_test(apr) ||
|
|
apr->ir_iot && ((apr->inst & 0340) == 0300 && apr->ar == 0 ||
|
|
(apr->inst & 0340) == 0340 && apr->ar != 0);
|
|
}
|
|
|
|
void
|
|
ar_cry(Apr *apr)
|
|
{
|
|
// 6-10
|
|
apr->ar_cry0_xor_cry1 = apr->ar_cry0 != apr->ar_cry1 &&
|
|
!((apr->inst & 0700) == 0300 &&
|
|
(apr->inst & 0060) != 0020);
|
|
}
|
|
|
|
void
|
|
ar_cry_in(Apr *apr, word c)
|
|
{
|
|
word a;
|
|
a = (apr->ar & 0377777777777) + c;
|
|
apr->ar += c;
|
|
apr->ar_cry0 = !!(apr->ar & 01000000000000);
|
|
apr->ar_cry1 = !!(a & 0400000000000);
|
|
apr->ar &= FW;
|
|
ar_cry(apr);
|
|
}
|
|
|
|
void
|
|
set_ex_mode_sync(Apr *apr, bool value)
|
|
{
|
|
apr->ex_mode_sync = value;
|
|
if(apr->ex_mode_sync)
|
|
apr->ex_user = 1; // 5-13
|
|
}
|
|
|
|
void
|
|
set_pi_cyc(Apr *apr, bool value)
|
|
{
|
|
apr->pi_cyc = value;
|
|
if(apr->pi_cyc)
|
|
apr->ex_pi_sync = 1; // 5-13
|
|
}
|
|
|
|
// PI REQ depends on PIR, PIH, PI_ACTIVE
|
|
void
|
|
recalc_pi_req(Apr *apr)
|
|
{
|
|
int chan;
|
|
u8 req;
|
|
// 8-3
|
|
apr->pi_req = 0;
|
|
if(apr->pi_active){
|
|
req = apr->pir & ~apr->pih;
|
|
for(chan = 0100; chan; chan >>= 1)
|
|
if(req & chan){
|
|
apr->pi_req = chan;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
set_mc_rq(Apr *apr, bool value)
|
|
{
|
|
apr->mc_rq = value; // 7-9
|
|
if(value && (apr->mc_rd || apr->mc_wr)){
|
|
membus0 |= MEMBUS_RQ_CYC;
|
|
wakemem();
|
|
}else
|
|
membus0 &= ~MEMBUS_RQ_CYC;
|
|
}
|
|
|
|
void
|
|
set_mc_wr(Apr *apr, bool value)
|
|
{
|
|
apr->mc_wr = value; // 7-9
|
|
if(value)
|
|
membus0 |= MEMBUS_WR_RQ;
|
|
else
|
|
membus0 &= ~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)
|
|
membus0 |= MEMBUS_RD_RQ;
|
|
else
|
|
membus0 &= ~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
|
|
membus0 &= ~0007777777761;
|
|
membus0 |= ma_fmc_select ? MEMBUS_MA_FMC_SEL1 : MEMBUS_MA_FMC_SEL0;
|
|
membus0 |= (apr->ma&01777) << 4;
|
|
membus0 |= (apr->rla&017) << 14;
|
|
membus0 |= apr->rla & 0020 ? MEMBUS_MA21_1|MEMBUS_MA21 : MEMBUS_MA21_0;
|
|
membus0 |= apr->rla & 0040 ? MEMBUS_MA20_1 : MEMBUS_MA20_0;
|
|
membus0 |= apr->rla & 0100 ? MEMBUS_MA19_1 : MEMBUS_MA19_0;
|
|
membus0 |= apr->rla & 0200 ? MEMBUS_MA18_1 : MEMBUS_MA18_0;
|
|
membus0 |= apr->ma & 01 ? MEMBUS_MA35_1 : MEMBUS_MA35_0;
|
|
return ma_ok;
|
|
}
|
|
|
|
pulse(kt4);
|
|
pulse(mc_rs_t0);
|
|
pulse(mc_addr_ack);
|
|
pulse(key_rd_wr_ret);
|
|
pulse(it1);
|
|
pulse(at1);
|
|
pulse(at0);
|
|
pulse(iat0);
|
|
pulse(et10);
|
|
pulse(mc_wr_rs);
|
|
pulse(mc_rd_rq_pulse);
|
|
pulse(mc_wr_rq_pulse);
|
|
pulse(mc_rdwr_rq_pulse);
|
|
pulse(mc_rd_wr_rs_pulse);
|
|
|
|
// TODO: find A LONG
|
|
|
|
pulse(pi_reset){
|
|
trace("PI RESET\n");
|
|
apr->pi_active = 0; // 8-4
|
|
apr->pih = 0; // 8-4
|
|
apr->pir = 0; // 8-4
|
|
recalc_pi_req(apr); // 8-4
|
|
apr->pio = 0; // 8-3
|
|
}
|
|
|
|
pulse(ar_flag_clr){
|
|
trace("AR FLAG CLR\n");
|
|
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
|
|
ar_cry(apr);
|
|
apr->chf7 = 0; // 6-19
|
|
}
|
|
|
|
pulse(ar_flag_set){
|
|
trace("AR FLAG SET\n");
|
|
apr->ar_ov_flag = !!(apr->mb & 0400000000000); // 6-10
|
|
apr->ar_cry0_flag = !!(apr->mb & 0200000000000); // 6-10
|
|
apr->ar_cry1_flag = !!(apr->mb & 0100000000000); // 6-10
|
|
apr->ar_pc_chg_flag = !!(apr->mb & 0040000000000); // 6-10
|
|
ar_cry(apr);
|
|
apr->chf7 = !!(apr->mb & 0020000000000); // 6-19
|
|
if(apr->mb & 0010000000000)
|
|
set_ex_mode_sync(apr, 1); // 5-13
|
|
}
|
|
|
|
// TODO
|
|
pulse(mp_clr){
|
|
apr->chf5 = 0; // 6-19
|
|
apr->shf1 = 0; // 6-20
|
|
}
|
|
|
|
pulse(mr_clr){
|
|
trace("MR CLR\n");
|
|
apr->ir = 0; // 5-7
|
|
apr->mq = 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
|
|
|
|
set_ex_mode_sync(apr, 0); // 5-13
|
|
apr->ex_uuo_sync = 0; // 5-13
|
|
apr->ex_pi_sync = 0; // 5-13
|
|
|
|
apr->a_long = 0; // nowhere to be found :(
|
|
apr->ar_com_cont = 0; // 6-9
|
|
mp_clr(apr);
|
|
// TODO: DS CLR
|
|
|
|
/* 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->art3_ret = NULL;
|
|
apr->sct2_ret = NULL;
|
|
}
|
|
|
|
pulse(ex_clr){
|
|
apr->pr = 0; // 5-13, 7-4
|
|
apr->rlr = 0; // 5-13, 7-5
|
|
}
|
|
|
|
pulse(mr_start){
|
|
trace("MR START\n");
|
|
// IOB RESET
|
|
apr->cpa_iot_user = 0; // 8-5
|
|
apr->cpa_illeg_op = 0; // 8-5
|
|
apr->cpa_non_exist_mem = 0; // 8-5
|
|
apr->cpa_clock_en = 0; // 8-5
|
|
apr->cpa_clock_flag = 0; // 8-5
|
|
apr->cpa_pc_chg_en = 0; // 8-5
|
|
apr->cpa_pdl_ov = 0; // 8-5
|
|
apr->cpa_arov_en = 0; // 8-5
|
|
apr->cpa_pia33 = 0; // 8-5
|
|
apr->cpa_pia34 = 0; // 8-5
|
|
apr->cpa_pia35 = 0; // 8-5
|
|
|
|
// PI
|
|
apr->pi_ov = 0; // 8-4
|
|
set_pi_cyc(apr, 0); // 8-4
|
|
nextpulse(apr, pi_reset); // 8-4
|
|
ar_flag_clr(apr); // 6-10
|
|
|
|
nextpulse(apr, ex_clr);
|
|
apr->ex_user = 0; // 5-13
|
|
apr->ex_ill_op = 0; // 5-13
|
|
apr->rla = 0;
|
|
}
|
|
|
|
pulse(mr_pwr_clr){
|
|
trace("MR PWR CLR\n");
|
|
apr->run = 0; // 5-1
|
|
/* order matters because of EX PI SYNC */
|
|
// TODO: is this correct then?
|
|
nextpulse(apr, mr_start); // 5-2
|
|
nextpulse(apr, mr_clr); // 5-2
|
|
}
|
|
|
|
pulse(st7){
|
|
trace("ST7\n");
|
|
}
|
|
|
|
/*
|
|
* Shift subroutines
|
|
*/
|
|
|
|
pulse(ar_sh_lt){
|
|
}
|
|
|
|
pulse(mq_sh_lt){
|
|
}
|
|
|
|
pulse(ar_sh_rt){
|
|
}
|
|
|
|
pulse(mq_sh_rt){
|
|
}
|
|
|
|
pulse(sct2){
|
|
trace("SCT2\n");
|
|
nextpulse(apr, apr->sct2_ret);
|
|
}
|
|
|
|
pulse(sct1){
|
|
trace("SCT1\n");
|
|
apr->sc = apr->sc+1 & 0777; // 6-16
|
|
// TODO: implement shifts
|
|
if(apr->shift_op && !(apr->mb & RSGN)){
|
|
ar_sh_lt(apr);
|
|
mq_sh_lt(apr);
|
|
}
|
|
if(apr->shift_op && (apr->mb & RSGN)){
|
|
ar_sh_rt(apr);
|
|
mq_sh_rt(apr);
|
|
}
|
|
nextpulse(apr, apr->sc == 0777 ? sct2 : sct1);
|
|
}
|
|
|
|
pulse(sct0){
|
|
trace("SCT0\n");
|
|
nextpulse(apr, apr->sc == 0777 ? sct2 : sct1);
|
|
}
|
|
|
|
pulse(sht1a){
|
|
trace("SHT1A\n");
|
|
apr->shf1 = 0; // 6-20
|
|
nextpulse(apr, et10);
|
|
}
|
|
|
|
pulse(sht1){
|
|
trace("SHT1\n");
|
|
if(apr->mb & 0400000)
|
|
apr->sc = ~apr->sc & 0777;
|
|
apr->shf1 = 1; // 6-20
|
|
apr->sct2_ret = sht1a;
|
|
nextpulse(apr, sct0);
|
|
}
|
|
|
|
pulse(sht0){
|
|
trace("SHT0\n");
|
|
apr->sc = apr->sc+1 & 0777; // 6-16
|
|
}
|
|
|
|
/*
|
|
* AR subroutines
|
|
*/
|
|
|
|
pulse(art3){
|
|
trace("ART3\n");
|
|
apr->ar_com_cont = 0; // 6-9
|
|
nextpulse(apr, apr->art3_ret);
|
|
}
|
|
|
|
pulse(ar_cry_comp){
|
|
trace("AR CRY COMP\n");
|
|
apr->ar = ~apr->ar & FW; // 6-8
|
|
nextpulse(apr, art3); // 6-9
|
|
}
|
|
|
|
pulse(ar_pm1_t1){
|
|
trace("AR AR+-1 T1\n");
|
|
ar_cry_in(apr, 1);
|
|
if(apr->iot_blk || apr->inst == 0252 || apr->inst == 0253 ||
|
|
apr->ir_jp && !(apr->inst & 0004))
|
|
ar_cry_in(apr, 01000000);
|
|
nextpulse(apr, apr->ar_com_cont ? ar_cry_comp : art3);
|
|
}
|
|
|
|
pulse(ar_pm1_t0){
|
|
trace("AR AR+-1 T0\n");
|
|
apr->ar = ~apr->ar & FW; // 6-8
|
|
apr->ar_com_cont = 1; // 6-9
|
|
nextpulse(apr, ar_pm1_t1);
|
|
}
|
|
|
|
pulse(ar_negate_t0){
|
|
trace("AR NEGATE T0\n");
|
|
apr->ar = ~apr->ar & FW; // 6-8
|
|
nextpulse(apr, ar_pm1_t1);
|
|
}
|
|
|
|
pulse(ar_ast2){
|
|
trace("AR2\n");
|
|
ar_cry_in(apr, (~apr->ar & apr->mb) << 1);
|
|
nextpulse(apr, apr->ar_com_cont ? ar_cry_comp : art3);
|
|
}
|
|
|
|
pulse(ar_ast1){
|
|
trace("AR AST1\n");
|
|
apr->ar ^= apr->mb;
|
|
nextpulse(apr, ar_ast2);
|
|
}
|
|
|
|
pulse(ar_ast0){
|
|
trace("AR AST0\n");
|
|
apr->ar = ~apr->ar & FW; // 6-8
|
|
apr->ar_com_cont = 1; // 6-9
|
|
nextpulse(apr, ar_ast1);
|
|
}
|
|
|
|
/*
|
|
* Priority Interrupt
|
|
*/
|
|
|
|
#define IA_NOT_INT ((!apr->pi_req || apr->pi_cyc) && apr->ia_inh)
|
|
|
|
pulse(pir_stb){
|
|
trace("PIR STB\n");
|
|
apr->pir |= apr->pio & iobus1; // 8-3
|
|
recalc_pi_req(apr); // 8-3
|
|
}
|
|
|
|
pulse(pi_sync){
|
|
trace("PI SYNC\n");
|
|
if(!apr->pi_cyc)
|
|
pir_stb(apr); // 8-4
|
|
if(apr->pi_req && !apr->pi_cyc)
|
|
nextpulse(apr, iat0); // 5-3
|
|
if(IA_NOT_INT)
|
|
nextpulse(apr, apr->if1a ? it1 : at1); // 5-3
|
|
// no longer needed
|
|
apr->ia_inh = 0;
|
|
}
|
|
|
|
/*
|
|
* Store
|
|
*/
|
|
|
|
pulse(st3){
|
|
trace("ST3\n");
|
|
apr->sf3 = 0;
|
|
}
|
|
|
|
pulse(st2){
|
|
trace("ST2\n");
|
|
apr->sf3 = 1;
|
|
nextpulse(apr, mc_rd_wr_rs_pulse);
|
|
}
|
|
|
|
pulse(st1){
|
|
trace("ST1\n");
|
|
apr->sf3 = 1;
|
|
nextpulse(apr, mc_wr_rq_pulse);
|
|
}
|
|
|
|
/*
|
|
* Execute
|
|
*/
|
|
|
|
pulse(et10){
|
|
trace("ET10\n");
|
|
|
|
if(apr->pi_hold){
|
|
apr->pi_ov = 0;
|
|
apr->pi_cyc = 0;
|
|
}
|
|
if(apr->ir_jrst || apr->inst == PUSHJ || apr->inst == PUSH)
|
|
apr->ma |= apr->mb & RT;
|
|
if((apr->fc_e_pse || apr->sc_e) &&
|
|
!(apr->ir_jp || apr->inst == EXCH || apr->ch_dep))
|
|
apr->mb = apr->ar;
|
|
if(apr->ir_jp && !(apr->inst & 04))
|
|
swap(&apr->mb, &apr->ar);
|
|
if(apr->ir_memac || apr->ir_as){
|
|
apr->ar_cry0_flag = apr->ar_cry0;
|
|
apr->ar_cry1_flag = apr->ar_cry1;
|
|
}
|
|
|
|
if(apr->hwt_10 || apr->hwt_11 || apr->fwt_10 || apr->fwt_11 ||
|
|
apr->ir_memac_mem)
|
|
apr->mb = apr->ar;
|
|
if(apr->ir_fwt && !apr->ar_cry0 && apr->ar_cry1 ||
|
|
(apr->ir_memac || apr->ir_as) && apr->ar_cry0 != apr->ar_cry1){
|
|
apr->ar_ov_flag = 1; // 6-10
|
|
if(apr->cpa_arov_en)
|
|
;
|
|
}
|
|
if(apr->ir_jp && !(apr->inst & 04) && apr->ar_cry0){
|
|
apr->cpa_pdl_ov = 1;
|
|
;
|
|
}
|
|
if(apr->inst == JFCL)
|
|
selected_flags_clr(apr);
|
|
nextpulse(apr, apr->sc_e ? st1 :
|
|
apr->fc_e_pse ? st2 :
|
|
st3);
|
|
}
|
|
|
|
pulse(et9){
|
|
bool pc_inc;
|
|
|
|
trace("ET9\n");
|
|
pc_inc = apr->inst == JSR || apr->inst == JSA || pc_inc_enable(apr);
|
|
if(pc_inc)
|
|
apr->pc = apr->pc+1 & FW;
|
|
if((apr->pc_set || pc_inc) && !(apr->ir_jrst && apr->ir & 0100)){
|
|
apr->ar_pc_chg_flag = 1;
|
|
if(apr->cpa_pc_chg_en)
|
|
;
|
|
}
|
|
|
|
if(apr->ir_acbm || apr->ir_jp && apr->inst != JSR)
|
|
swap(&apr->mb, &apr->ar);
|
|
if(apr->ir_jrst || apr->inst == PUSHJ || apr->inst == PUSH)
|
|
apr->ma = 0;
|
|
if(apr->inst == JSR)
|
|
apr->chf7 = 0;
|
|
nextpulse(apr, et10);
|
|
}
|
|
|
|
pulse(et8){
|
|
trace("ET8\n");
|
|
if(apr->pc_set)
|
|
apr->pc |= apr->ma; // 5-12
|
|
if(apr->inst == JSR)
|
|
apr->ex_ill_op = 0;
|
|
nextpulse(apr, et9);
|
|
}
|
|
|
|
pulse(et7){
|
|
trace("ET7\n");
|
|
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)
|
|
apr->ar = ~apr->ar;
|
|
nextpulse(apr, et8);
|
|
}
|
|
|
|
pulse(et6){
|
|
trace("ET6\n");
|
|
if(apr->mb_pc_sto || apr->inst == JSA)
|
|
apr->mb |= apr->pc;
|
|
if(apr->inst == PUSHJ || apr->inst == JSR || apr->inst == JSP){
|
|
// 6-4
|
|
if(apr->ar_ov_flag) apr->mb |= 0400000000000;
|
|
if(apr->ar_cry0_flag) apr->mb |= 0200000000000;
|
|
if(apr->ar_cry1_flag) apr->mb |= 0100000000000;
|
|
if(apr->ar_pc_chg_flag) apr->mb |= 0040000000000;
|
|
if(apr->chf7) apr->mb |= 0020000000000;
|
|
if(apr->ex_user) apr->mb |= 0010000000000;
|
|
}
|
|
|
|
if(apr->ir_acbm && (apr->inst & 060) == 020) /* Z */
|
|
apr->mb &= apr->ar;
|
|
nextpulse(apr, et7);
|
|
}
|
|
|
|
pulse(et5){
|
|
trace("ET5\n");
|
|
if(apr->mb_pc_sto)
|
|
apr->mb = 0;
|
|
|
|
if(apr->ir_acbm)
|
|
apr->ar = ~apr->ar;
|
|
|
|
// 5-12
|
|
apr->pc_set = apr->ir_jp && !(apr->inst == PUSH || apr->inst == POP) ||
|
|
apr->ir_jrst ||
|
|
pc_set_enable(apr);
|
|
nextpulse(apr, apr->e_long || apr->pc_set ? et6 : et10);
|
|
}
|
|
|
|
pulse(et4){
|
|
bool hwt_lt, hwt_rt;
|
|
|
|
trace("ET4\n");
|
|
apr->et4_ar_pse = 0; // 5-5
|
|
|
|
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))
|
|
apr->ar = ~apr->ar & FW; // 6-8
|
|
|
|
hwt_lt = apr->ir_hwt && !(apr->inst & 040);
|
|
hwt_rt = apr->ir_hwt && apr->inst & 040;
|
|
if(hwt_rt && apr->inst & 020 && (!(apr->inst & 010) || apr->mb & RSGN))
|
|
apr->ar = apr->ar & ~LT | ~apr->ar & LT;
|
|
if(hwt_lt && apr->inst & 020 && (!(apr->inst & 010) || apr->mb & SGN))
|
|
apr->ar = apr->ar & ~RT | ~apr->ar & RT;
|
|
if(hwt_lt)
|
|
apr->ar = apr->ar & ~LT | apr->mb & LT;
|
|
if(hwt_rt)
|
|
apr->ar = apr->ar & ~RT | apr->mb & RT;
|
|
|
|
if(apr->ir_fwt_swap)
|
|
swap(&apr->mb, &apr->ar); // 6-3
|
|
|
|
if(apr->ir_acbm)
|
|
swap(&apr->mb, &apr->ar);
|
|
nextpulse(apr, et5);
|
|
}
|
|
|
|
pulse(et3){
|
|
trace("ET3\n");
|
|
|
|
if(apr->inst == POPJ || apr->inst == BLT)
|
|
apr->ma = apr->mb & RT; // 7-3
|
|
|
|
// 5-9
|
|
if(apr->ir_fwt && ((apr->inst & 0774) == 0210 ||
|
|
(apr->inst & 0774) == 0214 && apr->ar & SGN)){
|
|
apr->et4_ar_pse = 1; // 5-5
|
|
apr->art3_ret = et4;
|
|
nextpulse(apr, ar_negate_t0);
|
|
return;
|
|
}
|
|
|
|
if(apr->ir_as){
|
|
apr->et4_ar_pse = 1; // 5-5
|
|
apr->art3_ret = et4;
|
|
nextpulse(apr, apr->inst & 4 ? ar_ast0 : ar_ast1);
|
|
return;
|
|
}
|
|
|
|
if(apr->ir_accp){
|
|
apr->et4_ar_pse = 1; // 5-5
|
|
apr->art3_ret = et4;
|
|
nextpulse(apr, ar_ast0);
|
|
return;
|
|
}
|
|
if(apr->ir_memac){
|
|
apr->et4_ar_pse = 1; // 5-5
|
|
apr->art3_ret = et4;
|
|
nextpulse(apr, (apr->inst & 070) == 040 ? ar_pm1_t1 : // +1
|
|
(apr->inst & 070) == 060 ? ar_pm1_t0 : // -1
|
|
et4);
|
|
return;
|
|
}
|
|
if(apr->inst == AOBJP || apr->inst == AOBJN ||
|
|
apr->inst == PUSHJ || apr->inst == PUSH){
|
|
apr->et4_ar_pse = 1; // 5-5
|
|
apr->art3_ret = et4;
|
|
nextpulse(apr, ar_pm1_t1);
|
|
return;
|
|
}
|
|
if(apr->inst == POP || apr->inst == POPJ){
|
|
apr->et4_ar_pse = 1; // 5-5
|
|
apr->art3_ret = et4;
|
|
nextpulse(apr, ar_pm1_t0);
|
|
return;
|
|
}
|
|
nextpulse(apr, apr->shift_op ? sht1 : et4);
|
|
};
|
|
|
|
pulse(et1){
|
|
trace("ET1\n");
|
|
|
|
if(apr->ex_ir_uuo)
|
|
apr->ex_ill_op = 1; // 5-13
|
|
if(apr->ir_jrst && apr->ir & 040)
|
|
apr->ex_mode_sync = 1; // 5-13
|
|
if(apr->ir_jrst && apr->ir & 0100)
|
|
ar_flag_set(apr);
|
|
if(apr->ir_jrst && apr->ir & 0400 ||
|
|
apr->iot_dataio && !apr->pi_ov && apr->pi_cyc)
|
|
if(apr->pi_active){
|
|
// TODO: check if this correct
|
|
apr->pih &= apr->pi_req-1; // 8-3
|
|
recalc_pi_req(apr);
|
|
}
|
|
|
|
if(apr->ir_boole && (apr->ir_boole_op == 06 ||
|
|
apr->ir_boole_op == 011 ||
|
|
apr->ir_boole_op == 014))
|
|
apr->ar ^= apr->mb; // 6-8
|
|
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->ar &= apr->mb; // 6-8
|
|
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))
|
|
apr->ar |= apr->mb; // 6-8
|
|
if(apr->ir_fwt_swap ||
|
|
apr->ir_hwt && apr->inst & 04)
|
|
apr->mb = apr->mb<<18 & LT | apr->mb>>18 & RT; // 6-3
|
|
if(apr->ir_hwt && apr->inst & 030)
|
|
apr->ar = 0; // 6-8
|
|
if(apr->inst == POPJ)
|
|
apr->ma = 0;
|
|
if(apr->shift_op && apr->mb & 0400000)
|
|
sht0(apr); // 6-20
|
|
|
|
if(apr->ir_acbm){
|
|
apr->mb &= apr->ar;
|
|
if((apr->inst & 060) == 040) /* C */
|
|
apr->ar ^= apr->mb;
|
|
if((apr->inst & 060) == 060) /* O */
|
|
apr->ar |= apr->mb;
|
|
}
|
|
nextpulse(apr, et3);
|
|
}
|
|
|
|
pulse(et0){
|
|
trace("ET0\n");
|
|
|
|
if(!((apr->ch_inc_op || apr->ch_n_inc_op) && apr->inst != IBP ||
|
|
apr->ex_ir_uuo || apr->iot_blk || apr->inst == BLT || apr->inst == XCT ||
|
|
apr->key_exec && !apr->run ||
|
|
apr->pi_cyc))
|
|
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 & 0100)
|
|
ar_flag_clr(apr);
|
|
// TODO: subroutines
|
|
nextpulse(apr, et1);
|
|
}
|
|
|
|
pulse(et0a){
|
|
trace("ET0A\n");
|
|
|
|
// 8-4
|
|
apr->pi_hold = (!apr->ir_iot || !apr->pi_ov && apr->iot_dataio) &&
|
|
apr->pi_cyc;
|
|
if(apr->pi_hold){
|
|
apr->pih |= apr->pi_req; // 8-3
|
|
recalc_pi_req(apr);
|
|
}
|
|
// 5-1
|
|
if(apr->key_ex_sync)
|
|
apr->key_ex_st = 1;
|
|
if(apr->key_dep_sync)
|
|
apr->key_dep_st = 1;
|
|
if(apr->key_inst_stop ||
|
|
apr->ir_jrst && apr->ir & 0200 && !apr->ex_user)
|
|
apr->run = 0;
|
|
|
|
if(apr->ir_boole && (apr->ir_boole_op == 00 ||
|
|
apr->ir_boole_op == 03 ||
|
|
apr->ir_boole_op == 014 ||
|
|
apr->ir_boole_op == 017))
|
|
apr->ar = 0; // 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))
|
|
apr->ar = ~apr->ar & FW; // 6-8
|
|
if(apr->fwt_00 || apr->fwt_11 || apr->hwt_11 || apr->ir_memac_mem)
|
|
apr->ar = apr->mb; // 6-8
|
|
if(apr->fwt_01 || apr->fwt_10)
|
|
apr->mb = apr->ar; // 6-3
|
|
if(apr->inst == EXCH || apr->inst == JSP ||
|
|
apr->hwt_10)
|
|
swap(&apr->mb, &apr->ar); // 6-3
|
|
if(apr->inst == POP || apr->inst == POPJ || apr->inst == JRA)
|
|
apr->mb = apr->mq; // 6-3
|
|
if(apr->inst == FSC || apr->shift_op)
|
|
apr->sc |= ~apr->mb & 0377 | ~apr->mb>>9 & 0400; // 6-15
|
|
|
|
if(apr->ir_acbm && apr->inst & 1 ||
|
|
apr->inst == JSA)
|
|
apr->mb = apr->mb<<18 & LT | apr->mb>>18 & RT; // 6-3
|
|
}
|
|
|
|
/*
|
|
* Fetch
|
|
*/
|
|
|
|
pulse(ft6a){
|
|
trace("FT6A\n");
|
|
apr->f6a = 0; // 5-4
|
|
et0a(apr); // 5-5
|
|
nextpulse(apr, et0); // 5-5
|
|
}
|
|
|
|
pulse(ft7){
|
|
trace("FT7\n");
|
|
apr->f6a = 1; // 5-4
|
|
nextpulse(apr, apr->mc_split_cyc_sync ? mc_rd_rq_pulse :
|
|
mc_rdwr_rq_pulse);
|
|
}
|
|
|
|
pulse(ft6){
|
|
trace("FT6\n");
|
|
apr->f6a = 1; // 5-4
|
|
nextpulse(apr, mc_rd_rq_pulse);
|
|
}
|
|
|
|
pulse(ft5){
|
|
trace("FT5\n");
|
|
apr->ma = apr->mb & RT; // 7-3
|
|
nextpulse(apr, apr->fc_e ? ft6 :
|
|
apr->fc_e_pse ? ft7 :
|
|
ft6a);
|
|
}
|
|
|
|
pulse(ft4a){
|
|
trace("FT4A\n");
|
|
apr->f4a = 0; // 5-4
|
|
apr->ma = 0; // 7-3
|
|
swap(&apr->mb, &apr->mq); // 6-3, 6-13
|
|
nextpulse(apr, ft5); // 5-4
|
|
}
|
|
|
|
pulse(ft4){
|
|
trace("FT4\n");
|
|
apr->mq = apr->mb; // 6-13
|
|
apr->f4a = 1; // 5-4
|
|
nextpulse(apr, mc_rd_rq_pulse);
|
|
}
|
|
|
|
pulse(ft3){
|
|
trace("FT3\n");
|
|
apr->ma = apr->mb & RT; // 7-3
|
|
swap(&apr->mb, &apr->ar); // 6-3
|
|
nextpulse(apr, ft4); // 5-4
|
|
}
|
|
|
|
pulse(ft1a){
|
|
trace("FT1A\n");
|
|
apr->f1a = 0; // 5-4
|
|
if(apr->fac2)
|
|
apr->ma = apr->ma+1 & 017; // 7-1, 7-5
|
|
else
|
|
apr->ma = 0; // 7-3
|
|
if(!(apr->fc_c_aclt || apr->fc_c_acrt))
|
|
swap(&apr->mb, &apr->ar); // 6-3
|
|
if(apr->fc_c_aclt)
|
|
apr->mb = apr->mb<<18 & LT | apr->mb>>18 & RT; // 6-3
|
|
nextpulse(apr, apr->fac2 ? ft4 : // 5-4
|
|
apr->fc_c_aclt || apr->fc_c_acrt ? ft3 : // 5-4
|
|
ft5); // 5-4
|
|
}
|
|
|
|
pulse(ft1){
|
|
trace("FT1\n");
|
|
apr->ma = apr->ir>>5 & 017; // 7-3
|
|
apr->f1a = 1; // 5-4
|
|
nextpulse(apr, mc_rd_rq_pulse);
|
|
}
|
|
|
|
pulse(ft0){
|
|
trace("FT0\n");
|
|
nextpulse(apr, apr->fac_inh ? ft5 : ft1); // 5-4
|
|
}
|
|
|
|
/*
|
|
* Address
|
|
*/
|
|
|
|
pulse(at5){
|
|
trace("AT5\n");
|
|
apr->a_long = 1; // nowhere to be found :(
|
|
apr->af0 = 1; // 5-3
|
|
apr->ma = apr->mb & RT; // 7-3
|
|
apr->ir &= ~037; // 5-7
|
|
nextpulse(apr, mc_rd_rq_pulse);
|
|
}
|
|
|
|
pulse(at4){
|
|
trace("AT4\n");
|
|
apr->ar &= ~LT; // 6-8
|
|
// TODO: what is MC DR SPLIT?
|
|
if(apr->sw_addr_stop || apr->key_mem_stop)
|
|
apr->mc_split_cyc_sync = 1; // 7-9
|
|
nextpulse(apr, apr->ir & 020 ? at5 : ft0); // 5-3, 5-4
|
|
}
|
|
|
|
pulse(at3a){
|
|
trace("AT3A\n");
|
|
apr->af3a = 0; // 5-3
|
|
apr->mb = apr->ar; // 6-3
|
|
nextpulse(apr, at4); // 5-3
|
|
}
|
|
|
|
pulse(at3){
|
|
trace("AT3\n");
|
|
apr->af3 = 0; // 5-3
|
|
apr->ma = 0; // 7-3
|
|
apr->af3a = 1; // 5-3
|
|
apr->art3_ret = at3a;
|
|
nextpulse(apr, ar_ast1);
|
|
}
|
|
|
|
pulse(at2){
|
|
trace("AT2\n");
|
|
apr->a_long = 1; // nowhere to be found :(
|
|
apr->ma = apr->ir & 017; // 7-3
|
|
apr->af3 = 1; // 5-3
|
|
nextpulse(apr, mc_rd_rq_pulse);
|
|
}
|
|
|
|
pulse(at1){
|
|
trace("AT1\n");
|
|
apr->ex_uuo_sync = 1; // 5-13
|
|
nextpulse(apr, (apr->ir & 017) == 0 ? at4 : at2); // 5-3
|
|
}
|
|
|
|
pulse(at0){
|
|
trace("AT0\n");
|
|
apr->ar &= ~RT; // 6-8
|
|
apr->ar |= apr->mb & RT; // 6-8
|
|
apr->ir |= apr->mb>>18 & 037; // 5-7
|
|
decodeir(apr);
|
|
apr->ma = 0; // 7-3
|
|
apr->af0 = 0; // 5-3
|
|
nextpulse(apr, pi_sync); // 8-4
|
|
}
|
|
|
|
/*
|
|
* Instruction
|
|
*/
|
|
|
|
pulse(it1a){
|
|
trace("IT1A\n");
|
|
apr->if1a = 0; // 5-3
|
|
apr->ir |= apr->mb>>18 & 0777740; // 5-7
|
|
if(apr->ma & 0777760)
|
|
set_key_rim_sbr(apr, 0); // 5-2
|
|
nextpulse(apr, at0); // 5-3
|
|
}
|
|
|
|
pulse(it1){
|
|
trace("IT1\n");
|
|
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->if1a = 1; // 5-3
|
|
nextpulse(apr, mc_rd_rq_pulse); // 7-8
|
|
}
|
|
|
|
pulse(iat0){
|
|
trace("IAT0\n");
|
|
// have to call directly because PI CYC sets EX PI SYNC
|
|
mr_clr(apr); // 5-2
|
|
set_pi_cyc(apr, 1); // 8-4
|
|
nextpulse(apr, it1); // 5-3
|
|
}
|
|
|
|
pulse(it0){
|
|
trace("IT0\n");
|
|
apr->ma = 0; // 7-3
|
|
// have to call directly because IF1A is set with a delay
|
|
mr_clr(apr); // 5-2
|
|
apr->if1a = 1; // 5-3
|
|
nextpulse(apr, pi_sync); // 8-4
|
|
}
|
|
|
|
/*
|
|
* Memory Control
|
|
*/
|
|
|
|
pulse(mai_addr_ack){
|
|
trace("MAI ADDR ACK\n");
|
|
nextpulse(apr, mc_addr_ack); // 7-8
|
|
}
|
|
|
|
pulse(mai_rd_rs){
|
|
trace("MAI RD RS\n");
|
|
/* we do this here instead of whenever MC RD is set; 7-6, 7-9 */
|
|
apr->mb = membus1;
|
|
if(apr->ma == apr->mas)
|
|
apr->mi = apr->mb; // 7-7
|
|
if(!apr->mc_stop)
|
|
nextpulse(apr, mc_rs_t0); // 7-8
|
|
}
|
|
|
|
pulse(mc_rs_t1){
|
|
trace("MC RS T1\n");
|
|
set_mc_rd(apr, 0); // 7-9
|
|
if(apr->key_ex_nxt || apr->key_dep_nxt)
|
|
apr->mi = apr->mb; // 7-7
|
|
|
|
if(apr->key_rd_wr) nextpulse(apr, key_rd_wr_ret); // 5-2
|
|
if(apr->sf3) nextpulse(apr, st3);
|
|
if(apr->f6a) nextpulse(apr, ft6a);
|
|
if(apr->f4a) nextpulse(apr, ft4a);
|
|
if(apr->f1a) nextpulse(apr, ft1a);
|
|
if(apr->af0) nextpulse(apr, at0);
|
|
if(apr->af3) nextpulse(apr, at3);
|
|
if(apr->if1a) nextpulse(apr, it1a); // 5-3
|
|
}
|
|
|
|
pulse(mc_rs_t0){
|
|
trace("MC RS T0\n");
|
|
// apr->mc_stop = 0; // ?? not found on 7-9
|
|
nextpulse(apr, mc_rs_t1); // 7-8
|
|
}
|
|
|
|
pulse(mc_wr_rs){
|
|
trace("MC WR RS\n");
|
|
if(apr->ma == apr->mas)
|
|
apr->mi = apr->mb; // 7-7
|
|
membus1 = apr->mb; // 7-8
|
|
membus0 |= MEMBUS_MAI_WR_RS; // 7-8
|
|
wakemem();
|
|
if(!apr->mc_stop)
|
|
nextpulse(apr, mc_rs_t0); // 7-8
|
|
}
|
|
|
|
pulse(mc_addr_ack){
|
|
trace("MC ADDR ACK\n");
|
|
set_mc_rq(apr, 0); // 7-9
|
|
if(!apr->mc_rd && apr->mc_wr)
|
|
nextpulse(apr, mc_wr_rs); // 7-8
|
|
}
|
|
|
|
pulse(mc_non_exist_rd){
|
|
trace("MC NON EXIST RD\n");
|
|
if(!apr->mc_stop)
|
|
nextpulse(apr, mc_rs_t0); // 7-8
|
|
}
|
|
|
|
pulse(mc_non_exist_mem_rst){
|
|
trace("MC NON EXIST MEM RST\n");
|
|
nextpulse(apr, mc_addr_ack); // 7-8
|
|
if(apr->mc_rd)
|
|
nextpulse(apr, mc_non_exist_rd); // 7-9
|
|
}
|
|
|
|
pulse(mc_non_exist_mem){
|
|
trace("MC NON EXIST MEM\n");
|
|
apr->cpa_non_exist_mem = 1; // 8-5
|
|
// TODO: IOB PI REQ CPA PIA
|
|
if(!apr->sw_mem_disable)
|
|
nextpulse(apr, mc_non_exist_mem_rst); // 7-9
|
|
}
|
|
|
|
pulse(mc_illeg_address){
|
|
trace("MC ILLEG ADDRESS\n");
|
|
apr->cpa_illeg_op = 1; // 8-5
|
|
// TODO: IOB PI REQ CPA PIA
|
|
nextpulse(apr, st7); // 5-6
|
|
}
|
|
|
|
pulse(mc_stop_1){
|
|
trace("MC STOP <- (1)\n");
|
|
apr->mc_stop = 1; // 7-9
|
|
if(apr->key_mem_cont)
|
|
nextpulse(apr, kt4); // 5-2
|
|
}
|
|
|
|
pulse(mc_rq_pulse){
|
|
bool ma_ok;
|
|
trace("MC RQ PULSE\n");
|
|
/* have to call this to set flags, do relocation and set address */
|
|
ma_ok = relocate(apr);
|
|
apr->mc_stop = 0; // 7-9
|
|
/* hack to catch non-existent memory */
|
|
apr->extpulse |= 4;
|
|
if(ma_ok || apr->ex_inh_rel)
|
|
set_mc_rq(apr, 1); // 7-9
|
|
else
|
|
nextpulse(apr, mc_illeg_address); // 7-9
|
|
if(apr->key_mem_stop || apr->ma == apr->mas && apr->sw_addr_stop)
|
|
nextpulse(apr, mc_stop_1); // 7-9
|
|
}
|
|
|
|
pulse(mc_rdwr_rq_pulse){
|
|
trace("MC RD/RW RQ PULSE\n");
|
|
set_mc_rd(apr, 1); // 7-9
|
|
set_mc_wr(apr, 1); // 7-9
|
|
apr->mb = 0; // 7-8
|
|
apr->mc_stop_sync = 1; // 7-9
|
|
nextpulse(apr, mc_rq_pulse); // 7-8
|
|
}
|
|
|
|
pulse(mc_rd_rq_pulse){
|
|
trace("MC RD RQ PULSE\n");
|
|
set_mc_rd(apr, 1); // 7-9
|
|
set_mc_wr(apr, 0); // 7-9
|
|
apr->mb = 0; // 7-8
|
|
nextpulse(apr, mc_rq_pulse); // 7-8
|
|
}
|
|
|
|
pulse(mc_split_rd_rq){
|
|
trace("MC SPLIT RD RQ\n");
|
|
nextpulse(apr, mc_rd_rq_pulse); // 7-8
|
|
}
|
|
|
|
pulse(mc_wr_rq_pulse){
|
|
trace("MC WR RQ PULSE\n");
|
|
set_mc_rd(apr, 0); // 7-9
|
|
set_mc_wr(apr, 1); // 7-9
|
|
nextpulse(apr, mc_rq_pulse); // 7-8
|
|
}
|
|
|
|
pulse(mc_split_wr_rq){
|
|
trace("MC SPLIT WR RQ\n");
|
|
nextpulse(apr, mc_wr_rq_pulse); // 7-8
|
|
}
|
|
|
|
pulse(mc_rd_wr_rs_pulse){
|
|
trace("MC RD/WR RS PULSE\n");
|
|
nextpulse(apr, apr->mc_split_cyc_sync ? mc_split_wr_rq : mc_wr_rs); // 7-8
|
|
}
|
|
|
|
/*
|
|
* Keys
|
|
*/
|
|
|
|
// some helpers, all on 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)
|
|
|
|
pulse(key_rd_wr_ret){
|
|
trace("KEY RD WR RET\n");
|
|
apr->key_rd_wr = 0; // 5-2
|
|
// apr->ex_ill_op = 0; // ?? not found on 5-13
|
|
nextpulse(apr, kt4); // 5-2
|
|
}
|
|
|
|
pulse(key_rd){
|
|
trace("KEY RD\n");
|
|
apr->key_rd_wr = 1; // 5-2
|
|
nextpulse(apr, mc_rd_rq_pulse); // 7-8
|
|
}
|
|
|
|
pulse(key_wr){
|
|
trace("KEY WR\n");
|
|
apr->key_rd_wr = 1; // 5-2
|
|
apr->mb = apr->ar; // 6-3
|
|
nextpulse(apr, mc_wr_rq_pulse); // 7-8
|
|
}
|
|
|
|
pulse(key_go){
|
|
trace("KEY GO\n");
|
|
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
|
|
nextpulse(apr, it0); // 5-3
|
|
}
|
|
|
|
pulse(kt4){
|
|
trace("KT4\n");
|
|
if(apr->run && (apr->key_ex_st || apr->key_dep_st))
|
|
nextpulse(apr, key_go); // 5-2
|
|
// TODO check repeat switch
|
|
}
|
|
|
|
pulse(kt3){
|
|
trace("KT3\n");
|
|
if(apr->key_readin || apr->key_start)
|
|
apr->pc |= apr->ma; // 5-12
|
|
if(KEY_EXECUTE){
|
|
apr->mb = apr->ar; // 6-3
|
|
nextpulse(apr, it1a); // 5-3
|
|
nextpulse(apr, kt4); // 5-2
|
|
}
|
|
if(KEY_EX_EX_NXT)
|
|
nextpulse(apr, key_rd); // 5-2
|
|
if(KEY_DP_DP_NXT)
|
|
nextpulse(apr, key_wr); // 5-2
|
|
if(apr->key_start || apr->key_readin || apr->key_inst_cont)
|
|
nextpulse(apr, key_go); // 5-2
|
|
}
|
|
|
|
pulse(kt2){
|
|
trace("KT2\n");
|
|
if(KEY_MA_MAS)
|
|
apr->ma |= apr->mas; // 7-1
|
|
if(KEY_EXECUTE_DP_DPNXT)
|
|
apr->ar |= apr->data; // 5-2
|
|
nextpulse(apr, kt3); // 5-2
|
|
}
|
|
|
|
pulse(kt1){
|
|
trace("KT1\n");
|
|
if(apr->key_io_reset)
|
|
nextpulse(apr, mr_start); // 5-2
|
|
if(KEY_MANUAL && !apr->key_mem_cont)
|
|
nextpulse(apr, mr_clr); // 5-2
|
|
if(KEY_CLR_RIM)
|
|
set_key_rim_sbr(apr, 0); // 5-2
|
|
if(apr->key_mem_cont && apr->mc_stop)
|
|
nextpulse(apr, mc_rs_t0); // 7-8
|
|
if(KEY_MANUAL && apr->mc_stop && apr->mc_stop_sync && !apr->key_mem_cont)
|
|
nextpulse(apr, mc_wr_rs); // 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)
|
|
apr->ar = 0; // 5-2
|
|
|
|
nextpulse(apr, kt2); // 5-2
|
|
}
|
|
|
|
pulse(kt0a){
|
|
trace("KT0A\n");
|
|
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)
|
|
nextpulse(apr, kt1); // 5-2
|
|
}
|
|
|
|
pulse(kt0){
|
|
trace("KT0\n");
|
|
nextpulse(apr, kt0a); // 5-2
|
|
}
|
|
|
|
pulse(key_manual){
|
|
trace("KEY MANUAL\n");
|
|
nextpulse(apr, kt0); // 5-2
|
|
}
|
|
|
|
void
|
|
nextpulse(Apr *apr, Pulse *p)
|
|
{
|
|
if(apr->nnextpulses >= MAXPULSE){
|
|
fprintf(stderr, "error: too many next pulses\n");
|
|
exit(1);
|
|
}
|
|
apr->nlist[apr->nnextpulses++] = p;
|
|
}
|
|
|
|
void*
|
|
aprmain(void *p)
|
|
{
|
|
Apr *apr;
|
|
Pulse **tmp;
|
|
int i;
|
|
|
|
apr = (Apr*)p;
|
|
apr->clist = apr->pulses1;
|
|
apr->nlist = apr->pulses2;
|
|
apr->ncurpulses = 0;
|
|
apr->nnextpulses = 0;
|
|
apr->ia_inh = 0;
|
|
|
|
nextpulse(apr, mr_pwr_clr);
|
|
while(apr->sw_power){
|
|
apr->ncurpulses = apr->nnextpulses;
|
|
apr->nnextpulses = 0;
|
|
tmp = apr->clist; apr->clist = apr->nlist; apr->nlist = tmp;
|
|
|
|
for(i = 0; i < apr->ncurpulses; i++)
|
|
apr->clist[i](apr);
|
|
|
|
/* KEY MANUAL */
|
|
if(apr->extpulse & 1){
|
|
apr->extpulse &= ~1;
|
|
nextpulse(apr, key_manual);
|
|
}
|
|
/* KEY INST STOP */
|
|
if(apr->extpulse & 2){
|
|
apr->extpulse &= ~2;
|
|
apr->run = 0;
|
|
// cleared after PI SYNC
|
|
apr->ia_inh = 1;
|
|
}
|
|
if(membus0 & MEMBUS_MAI_ADDR_ACK){
|
|
membus0 &= ~MEMBUS_MAI_ADDR_ACK;
|
|
apr->extpulse &= ~4;
|
|
nextpulse(apr, mai_addr_ack);
|
|
}
|
|
if(membus0 & MEMBUS_MAI_RD_RS){
|
|
membus0 &= ~MEMBUS_MAI_RD_RS;
|
|
nextpulse(apr, mai_rd_rs);
|
|
}
|
|
if(apr->extpulse & 4){
|
|
apr->extpulse &= ~4;
|
|
if(apr->mc_rq && !apr->mc_stop)
|
|
nextpulse(apr, mc_non_exist_mem); // 7-9
|
|
}
|
|
}
|
|
printf("power off\n");
|
|
return NULL;
|
|
}
|