1
0
mirror of https://github.com/aap/pdp6.git synced 2026-01-17 00:33:57 +00:00
aap.pdp6/apr.c
2015-11-04 11:21:36 +01:00

1111 lines
22 KiB
C

#include "pdp6.h"
/* external pulses:
* KEY MANUAL
* MAI-CMC ADDR ACK
* MAI RD RS
*/
Apr apr;
void
decode_ch(void)
{
int ir6_8;
ir6_8 = apr.ir>>9 & 7;
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;
}else{
apr.ch_inc = apr.ch_inc_op = apr.ch_n_inc_op = 0;
apr.ch_load = apr.ch_dep = 0;
}
}
void
decode_2xx(void)
{
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.inst >= 0244 && apr.inst <= 0246 ||
(apr.inst & 0774) == 0234)
apr.fac2 = 1;
apr.fc_c_acrt = (apr.inst & 0776) == 0262;
apr.fc_c_aclt = apr.inst == 0251 || apr.inst == 0267;
}
void
decodeir(void)
{
bool iot_a, jrst_a, uuo_a;
apr.inst = apr.ir>>9 & 0777;
apr.fac2 = 0;
apr.boole_as_00 = apr.boole_as_01 = 0;
apr.boole_as_10 = apr.boole_as_11 = 0;
apr.hwt_00 = apr.hwt_01 = apr.hwt_10 = apr.hwt_11 = 0;
apr.ir_memac = apr.ir_memac_mem = 0;
decode_ch();
decode_2xx();
/* ACCP v MEMAC */
if((apr.inst & 0700) == 0300){
apr.ir_memac = apr.inst & 0060;
apr.ir_memac_mem = apr.ir_memac && apr.inst & 0010;
}
/* BOOLE */
apr.ir_boole = (apr.inst & 0700) == 0400;
if(apr.ir_boole)
apr.ir_boole_op = apr.inst>>2 & 017;
/* HWT */
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.ir_boole || (apr.inst & 770) == 0270){
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;
}
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 & 0000240) == 0;
apr.iot_dataio = apr.ir_iot && (apr.ir & 0000240) == 0040;
}
void
swap(word *a, word *b)
{
word tmp;
tmp = *a;
*a = *b;
*b = tmp;
}
void
ar_add(word w)
{
int a, b, s;
a = apr.ar>>35 & 1;
b = w>>35 & 1;
apr.ar += w;
s = apr.ar>>35 & 3;
apr.ar &= FW;
apr.ar_cry0 = !!(s & 2);
apr.ar_cry1 = s-a-b;
}
void
set_ex_mode_sync(bool value)
{
apr.ex_mode_sync = value;
if(apr.ex_mode_sync)
apr.ex_user = 1; // 5-13
}
void
set_pi_cyc(bool value)
{
apr.pi_cyc = value;
if(!apr.pi_cyc)
apr.ex_pi_sync = 1; // 5-13
}
void
recalc_pi_req(void)
{
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(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(bool value)
{
apr.mc_wr = value; // 7-9
if(value)
membus0 |= MEMBUS_WR_RQ;
else
membus0 &= ~MEMBUS_WR_RQ;
set_mc_rq(apr.mc_rq);
}
void
set_mc_rd(bool value)
{
apr.mc_rd = value; // 7-9
if(value)
membus0 |= MEMBUS_RD_RQ;
else
membus0 &= ~MEMBUS_RD_RQ;
set_mc_rq(apr.mc_rq);
}
void
set_key_rim_sbr(bool value)
{
// not sure if this is correct
apr.key_rim_sbr = value | apr.sw_rim_maint; // 5-2
}
bool
calcaddr(void)
{
u8 ma18_25;
bool ma_ok, ma_fmc_select;
// 5-13
apr.ex_inh_rel = !apr.ex_user || apr.ex_pi_sync ||
(apr.ma & 0777760) == 0 || apr.ex_ill_op;
// 7-4
ma18_25 = apr.ma>>10 & 0377;
ma_ok = ma18_25 <= apr.pr;
// 7-2
ma_fmc_select = !apr.key_rim_sbr && (apr.ma & 0777760) == 0;
// 7-5
apr.rla = ma18_25;
if(!apr.ex_inh_rel)
apr.rla += apr.rlr;
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(it1);
pulse(at1);
pulse(at0);
pulse(iat0);
pulse(mc_wr_rs);
pulse(mc_rd_rq_pulse);
pulse(mc_wr_rq_pulse);
pulse(mc_rdwr_rq_pulse);
// TODO: find A LONG
pulse(pi_reset){
printf("PI RESET\n");
apr.pi_active = 0; // 8-4
apr.pih = 0; // 8-4
apr.pir = 0; // 8-4
recalc_pi_req(); // 8-4
apr.pio = 0; // 8-3
return NULL;
}
pulse(ar_flag_clr){
printf("AR FLAG CLR\n");
apr.pc_chg_flag = 0; // 6-10
apr.ar_ov_flag = 0; // 6-10
apr.ar_cry0_flag = 0; // 6-10
apr.ar_cry1_flag = 0; // 6-10
apr.chf7 = 0; // 6-19
return NULL;
}
// TODO
pulse(mp_clr){
apr.chf5 = 0; // 6-19
return NULL;
}
pulse(mr_clr){
printf("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(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 :(
mp_clr();
// 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.mc_rst1_ret = NULL;
apr.art3_ret = NULL;
return NULL;
}
pulse(mr_start){
printf("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
apr.pi_ov = 0; // 8-4
set_pi_cyc(0); // 8-4
pi_reset(); // 8-4
ar_flag_clr(); // 6-10
apr.ex_user = 0; // 5-13
apr.ex_ill_op = 0; // 5-13
apr.pr = 0; // 5-13, 7-4
apr.rlr = 0; // 5-13, 7-5
apr.rla = 0;
// apr.ex_user = 1;
// apr.rlr = 2;
// apr.pr = 1;
return NULL;
}
pulse(mr_pwr_clr){
printf("MR PWR CLR\n");
apr.run = 0; // 5-1
/* order matters because of EX PI SYNC */
mr_start(); // 5-2
mr_clr(); // 5-2
return NULL;
}
pulse(st7){
printf("ST7\n");
return NULL;
}
/*
* AR
*/
// very temporary
pulse(art3){
// apr.ar_com_cont = 0;
return apr.art3_ret;
}
pulse(ar_pm1_t1){
printf("AR AR+-1 T1\n");
ar_add(1);
return apr.art3_ret;
}
pulse(ar_negate_t0){
printf("AR NEGATE T0\n");
apr.ar = ~apr.ar & FW;
return ar_pm1_t1;
}
pulse(ar_ast1){
printf("AR AST1,2\n");
// TODO
ar_add(apr.mb);
return art3;
}
/*
* Priority Interrupt
*/
pulse(pir_stb){
printf("PIR STB\n");
apr.pir |= apr.pio & iobus1;
recalc_pi_req(); // 8-3
return NULL;
}
pulse(pi_sync){
printf("PI SYNC\n");
if(!apr.pi_cyc)
pir_stb();
// 5-3
if(apr.pi_req && !apr.pi_cyc)
return iat0;
// TODO: IA INH/AT INH
if(apr.if1a)
return it1;
return at1;
}
/*
* Execute
*/
pulse(et10){
printf("ET10\n");
if(apr.hwt_10 || apr.hwt_11 || apr.fwt_10 || apr.fwt_11)
apr.mb = apr.ar;
if(apr.ir_fwt && !apr.ar_cry0 && apr.ar_cry1)
apr.ar_ov_flag = 1; // 6-10
return NULL;
}
pulse(et6){
printf("ET6\n");
return NULL;
}
pulse(et5){
printf("ET5\n");
// if(apr.e_long)
// return et6;
return et10;
}
pulse(et4){
bool hwt_lt, hwt_rt;
printf("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
return et5;
}
pulse(et3){
printf("ET3\n");
// 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;
return ar_negate_t0;
}
return et4;
};
pulse(et1){
printf("ET1\n");
if(apr.ex_ir_uuo)
apr.ex_ill_op = 1; // 5-13
if(apr.ir_jrst && apr.ir & 0000040)
apr.ex_mode_sync = 1; // 5-13
if(apr.ir_jrst && apr.ir & 0000400 ||
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();
}
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 & 0004)
apr.mb = apr.mb<<18 & LT | apr.mb>>18 & RT; // 6-3
if(apr.ir_hwt && apr.inst & 0030)
apr.ar = 0; // 6-8
return et3;
}
pulse(et0){
printf("ET0\n");
if(!(apr.ch_inc_op && apr.inst != 0133 ||
apr.ch_n_inc_op && apr.inst != 0133 ||
apr.ex_ir_uuo || apr.iot_blk || apr.inst == 0256 ||
apr.key_execute && !apr.run || apr.pi_cyc))
apr.pc = apr.pc+1 & RT;
apr.ar_cry0 = 0; // 6-10
apr.ar_cry1 = 0; // 6-10
// TODO: subroutines
return et1;
}
pulse(et0a){
printf("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();
}
// 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 & 0000200) && !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.ar = apr.mb; // 6-8
if(apr.fwt_01 || apr.fwt_10)
apr.mb = apr.ar; // 6-3
if(apr.inst == 0250 || /* EXCH */
apr.hwt_10)
swap(&apr.mb, &apr.ar); // 6-3
return NULL;
}
/*
* Fetch
*/
pulse(ft6a){
printf("FT6A\n");
apr.f6a = 0; // 5-4
et0a(); // 5-5
return et0; // 5-5
}
pulse(ft7){
printf("FT7\n");
apr.f6a = 1; // 5-4
apr.mc_rst1_ret = ft6a;
if(apr.mc_split_cyc_sync)
return mc_rd_rq_pulse;
return mc_rdwr_rq_pulse;
}
pulse(ft6){
printf("FT6\n");
apr.f6a = 1; // 5-4
apr.mc_rst1_ret = ft6a;
return mc_rd_rq_pulse;
}
pulse(ft5){
bool fc_e, fc_e_pse;
printf("FT5\n");
apr.ma = apr.mb & RT; // 7-3
// 5-4
fc_e = (apr.inst & 0710) == 0610 || /* ACBM DIR */
(apr.inst & 0770) == 0310 || /* ACCP DIR */
apr.boole_as_00 || apr.ch_n_inc_op || apr.ch_load ||
apr.fwt_00 || apr.hwt_00 ||
apr.iot_dataio && (apr.ir & 0100) || /* DATAO */
(apr.inst & 0740) == 0140 || /* IR FP */
(apr.inst & 0760) == 0220 &&
(apr.inst & 0003) != 1 || /* MD FC(E) */
apr.inst == 0256 || /* XCT */
(apr.inst & 0776) == 0260; /* PUSH */
fc_e_pse = apr.boole_as_10 || apr.boole_as_11 ||
apr.ch_dep || apr.ch_inc_op ||
apr.fwt_11 || apr.hwt_10 || apr.hwt_11 ||
apr.iot_blk ||
apr.inst == 0250 || /* EXCH */
apr.ir_memac_mem;
if(fc_e)
return ft6;
if(fc_e_pse)
return ft7;
return ft6a;
}
pulse(ft4a){
printf("FT4A\n");
apr.f4a = 0; // 5-4
apr.ma = 0; // 7-3
swap(&apr.mb, &apr.mq); // 6-3, 6-13
return ft5; // 5-4
}
pulse(ft4){
printf("FT4\n");
apr.mq = apr.mb; // 6-13
apr.f4a = 1; // 5-4
apr.mc_rst1_ret = ft4a;
return mc_rd_rq_pulse;
}
pulse(ft3){
printf("FT3\n");
apr.ma = apr.mb & RT; // 7-3
swap(&apr.mb, &apr.ar); // 6-3
return ft4; // 5-4
}
pulse(ft1a){
printf("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
if(apr.fac2)
return ft4; // 5-4
if(apr.fc_c_aclt || apr.fc_c_acrt)
return ft3; // 5-4
return ft5; // 5-4
}
pulse(ft1){
printf("FT1\n");
apr.ma = apr.ir>>5 & 017; // 7-3
apr.f1a = 1; // 5-4
apr.mc_rst1_ret = ft1a;
return mc_rd_rq_pulse;
}
pulse(ft0){
bool fac_inh;
printf("FT0\n");
// 5-4
fac_inh = apr.ch_inc_op || apr.ch_n_inc_op || apr.ch_load ||
apr.ex_ir_uuo ||
apr.fwt_00 || apr.fwt_01 || apr.fwt_11 || apr.hwt_11 ||
(apr.inst & 0703) == 0503 || apr.ir_iot ||
(apr.inst & 0774) == 0254 || /* 254-257 */
(apr.inst & 0776) == 0264 || /* JSR, JSP */
apr.ir_memac_mem;
if(fac_inh)
return ft5; // 5-4
return ft1; // 5-4
}
/*
* Address
*/
pulse(at5){
printf("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
apr.mc_rst1_ret = at0;
return mc_rd_rq_pulse;
}
pulse(at4){
printf("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
if(apr.ir & 020)
return at5; // 5-3
return ft0; // 5-4
}
pulse(at3a){
printf("AT3A\n");
apr.af3a = 0; // 5-3
apr.mb = apr.ar; // 6-3
return at4; // 5-3
}
pulse(at3){
printf("AT3\n");
apr.af3 = 0; // 5-3
apr.ma = 0; // 7-3
apr.af3a = 1; // 5-3
apr.art3_ret = at3a;
return ar_ast1;
}
pulse(at2){
printf("AT2\n");
apr.a_long = 1; // nowhere to be found :(
apr.ma = apr.ir & 017; // 7-3
apr.af3 = 1; // 5-3
apr.mc_rst1_ret = at3;
return mc_rd_rq_pulse;
}
pulse(at1){
printf("AT1\n");
apr.ex_uuo_sync = 1; // 5-13
if((apr.ir & 017) == 0)
return at4; // 5-3
return at2; // 5-3
}
pulse(at0){
printf("AT0\n");
apr.ar &= ~RT; // 6-8
apr.ar |= apr.mb & RT; // 6-8
apr.ir |= apr.mb>>18 & 037; // 5-7
decodeir();
apr.ma = 0; // 7-3
apr.af0 = 0; // 5-3
return pi_sync; // 8-4
}
/*
* Instruction
*/
pulse(iat0){
printf("IAT0\n");
mr_clr();
set_pi_cyc(1);
return it1;
}
pulse(it1a){
printf("IT1A\n");
apr.if1a = 0;
apr.ir |= apr.mb>>18 & 0777740; // 5-7
if(apr.ma & 0777760)
set_key_rim_sbr(0); // 5-2
return at0;
}
pulse(it1){
printf("IT1\n");
hword n;
u8 r;
if(apr.pi_cyc){
// 7-3
r = apr.pi_req;
for(n = 7; !(r & 1); n--, r >>= 1);
apr.ma = 040 | n<<1;
}else
apr.ma = apr.pc; // 7-3
if(apr.pi_ov)
apr.ma = (apr.ma+1)&RT; // 7-3
apr.if1a = 1;
apr.mc_rst1_ret = it1a;
return mc_rd_rq_pulse;
}
pulse(it0){
printf("IT0\n");
apr.ma = 0;
mr_clr();
apr.if1a = 1; // 5-3
return pi_sync; // 8-4
}
/*
* Memory Control
*/
pulse(mc_rs_t1){
printf("MC RS T1\n");
set_mc_rd(0);
if(apr.key_ex_next || apr.key_dep_next)
apr.mi = apr.mb; // 7-7
return apr.mc_rst1_ret;
}
pulse(mc_rs_t0){
printf("MC RS T0\n");
apr.mc_stop = 0;
return mc_rs_t1;
}
pulse(mc_wr_rs){
printf("MC WR RS\n");
if(apr.ma == apr.mas)
apr.mi = apr.mb; // 7-7
membus1 = apr.mb;
membus0 |= MEMBUS_MAI_WR_RS;
wakemem();
if(!apr.mc_stop)
return mc_rs_t0;
return NULL;
}
pulse(mc_addr_ack){
printf("MC ADDR ACK\n");
set_mc_rq(0);
if(!apr.mc_rd && apr.mc_wr)
return mc_wr_rs;
return NULL;
}
pulse(mc_non_exist_rd){
printf("MC NON EXIST RD\n");
if(!apr.mc_stop)
return mc_rs_t0;
return NULL;
}
pulse(mc_non_exist_mem_rst){
printf("MC NON EXIST MEM RST\n");
if(apr.mc_rd){
/* call directly - no other pulses after it in this case */
mc_addr_ack();
return mc_non_exist_rd;
}else
return mc_addr_ack();
return NULL;
}
pulse(mc_non_exist_mem){
printf("MC NON EXIST MEM\n");
apr.cpa_non_exist_mem = 1;
// TODO: IOB PI REQ CPA PIA
if(!apr.sw_mem_disable)
return mc_non_exist_mem_rst;
return NULL;
}
pulse(mc_illeg_address){
printf("MC ILLEG ADDRESS\n");
apr.cpa_illeg_op = 1;
// TODO: IOB PI REQ CPA PIA
return st7;
}
pulse(mc_rq_pulse){
printf("MC RQ PULSE\n");
apr.mc_stop = 0; // 7-9
/* catch non-existent memory */
apr.extpulse |= 4;
if(calcaddr() == 0 && !apr.ex_inh_rel)
return mc_illeg_address;
set_mc_rq(1);
if(apr.key_mem_stop || apr.ma == apr.mas && apr.sw_addr_stop){
apr.mc_stop = 1; // 7-9
// TODO: what is this? does it make any sense?
if(apr.key_mem_cont)
return kt4;
}
return NULL;
}
pulse(mc_rdwr_rq_pulse){
printf("MC RD/RW RQ PULSE\n");
set_mc_rd(1); // 7-9
set_mc_wr(1); // 7-9
apr.mb = 0;
apr.mc_stop_sync = 1; // 7-9
return mc_rq_pulse;
}
pulse(mc_rd_rq_pulse){
printf("MC RD RQ PULSE\n");
set_mc_rd(1); // 7-9
set_mc_wr(0); // 7-9
apr.mb = 0;
return mc_rq_pulse;
}
pulse(mc_split_rd_rq){
printf("MC SPLIT RD RQ\n");
return mc_rd_rq_pulse;
}
pulse(mc_wr_rq_pulse){
printf("MC WR RQ PULSE\n");
set_mc_rd(0); // 7-9
set_mc_wr(1); // 7-9
return mc_rq_pulse;
}
pulse(mc_split_wr_rq){
printf("MC SPLIT WR RQ\n");
return mc_wr_rq_pulse;
}
pulse(mc_rd_wr_rs_pulse){
printf("MC RD/WR RS PULSE\n");
return apr.mc_split_cyc_sync ? mc_split_wr_rq : mc_wr_rs;
}
/*
* Keys
*/
pulse(key_rd_wr_ret){
printf("KEY RD WR RET\n");
apr.key_rd_wr = 0; // 5-2
// apr.ex_ill_op = 0; // ?? not found on 5-13
return kt4; // 5-2
}
pulse(key_rd){
printf("KEY RD\n");
apr.key_rd_wr = 1; // 5-2
apr.mc_rst1_ret = key_rd_wr_ret;
return mc_rd_rq_pulse;
}
pulse(key_wr){
printf("KEY WR\n");
apr.key_rd_wr = 1; // 5-2
apr.mb = apr.ar; // 6-3
apr.mc_rst1_ret = key_rd_wr_ret;
return mc_wr_rq_pulse;
}
pulse(key_go){
printf("KEY GO\n");
apr.run = 1;
apr.key_ex_st = 0;
apr.key_dep_st = 0;
apr.key_ex_sync = 0;
apr.key_dep_sync = 0;
return it0;
}
pulse(kt4){
printf("KT4\n");
if(apr.run &&
(apr.key_ex || apr.key_ex_next || apr.key_dep || apr.key_dep_next))
return key_go; // 5-2
// TODO check repeat switch
return NULL;
}
pulse(kt3){
printf("KT3\n");
if(apr.key_readin || apr.key_start)
apr.pc = apr.ma; // 5-12
if(apr.key_execute && !apr.run){
apr.mb = apr.ar; // 6-3
// TODO: go to KT4 to check repeat (when processor is idle)
return it1a; // 5-3
}
if(apr.key_ex || apr.key_ex_next)
return key_rd; // 5-2
if(apr.key_dep || apr.key_dep_next)
return key_wr; // 5-2
if(apr.key_start || apr.key_readin || apr.key_inst_cont)
return key_go; // 5-4
return NULL;
}
#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_next || apr.key_dep_next || apr.key_execute ||\
apr.key_io_reset)
pulse(kt12){
printf("KT1,2\n");
if(apr.key_io_reset)
mr_start(); // 5-2
if(KEY_MANUAL && !apr.key_mem_cont)
mr_clr(); // 5-2
if(!(apr.key_readin || apr.key_inst_cont || apr.key_mem_cont))
set_key_rim_sbr(0); // 5-2
if(apr.key_readin){
set_key_rim_sbr(1); // 5-2
apr.ma = apr.mas;
}
if(apr.key_start)
apr.ma = apr.mas;
if(apr.key_execute && !apr.run)
apr.ar = apr.data;
if(apr.key_ex)
apr.ma = apr.mas;
if(apr.key_ex_next)
apr.ma = (apr.ma+1)&RT;
if(apr.key_dep){
apr.ma = apr.mas;
apr.ar = apr.data;
}
if(apr.key_dep_next){
apr.ma = (apr.ma+1)&RT;
apr.ar = apr.data;
}
if(apr.key_mem_cont && apr.mc_stop)
return mc_rs_t0;
if(KEY_MANUAL && apr.mc_stop && apr.mc_stop_sync && !apr.key_mem_cont){
/* Finish rd/wr which should stop the processor.
* Set flag to continue at KT3 */
apr.extpulse |= 2;
return mc_wr_rs;
}
return kt3; // 5-2
}
pulse(kt0a){
printf("KT0A\n");
apr.key_ex_st = 0; // 5-1
apr.key_dep_st = 0; // 5-1
apr.key_ex_sync = apr.key_ex || apr.key_ex_next; // 5-1
apr.key_dep_sync = apr.key_dep || apr.key_dep_next; // 5-1
if(!apr.run || apr.key_mem_cont)
return kt12; // 5-2
return NULL;
}
pulse(kt0){
printf("KT0\n");
return kt0a; // 5-2
}
pulse(key_manual){
printf("KEY MANUAL\n");
return kt0; // 5-2
}
pulse(mai_addr_ack){
printf("MAI ADDR ACK\n");
return mc_addr_ack;
}
pulse(mai_rd_rs){
printf("MAI RD RS\n");
apr.mb = membus1;
if(apr.ma == apr.mas)
apr.mi = apr.mb; // 7-7
if(!apr.mc_stop)
return mc_rs_t0;
return NULL;
}
void*
aprmain(void *p)
{
mr_pwr_clr();
while(apr.sw_power){
if(apr.extpulse & 1){
if(apr.nextpulse)
printf("whaa: cpu wasn't idle\n");
apr.extpulse &= ~1;
apr.nextpulse = key_manual;
}
if(apr.nextpulse)
apr.nextpulse = apr.nextpulse();
else if(membus0 & MEMBUS_MAI_ADDR_ACK){
membus0 &= ~MEMBUS_MAI_ADDR_ACK;
apr.extpulse &= ~4;
apr.nextpulse = mai_addr_ack;
}else if(membus0 & MEMBUS_MAI_RD_RS){
membus0 &= ~MEMBUS_MAI_RD_RS;
apr.nextpulse = mai_rd_rs;
}else if(apr.extpulse & 2){
/* continue at KT3 after finishing rd/wr from a stop */
apr.extpulse &= ~2;
apr.nextpulse = kt3;
}else if(apr.extpulse & 4){
apr.extpulse &= ~4;
if(apr.mc_rq && !apr.mc_stop)
apr.nextpulse = mc_non_exist_mem;
}
}
printf("power off\n");
return NULL;
}