diff --git a/code/Makefile b/code/Makefile index 9a2e85f..9ccddcc 100644 --- a/code/Makefile +++ b/code/Makefile @@ -1,5 +1,8 @@ -test.rim: main.rel tty.rel - ld6 -r 100 -o test.rim main.rel tty.rel +test.rim: main.rel tty.rel pt.rel + ld6 -o test.rim main.rel tty.rel pt.rel + +test.sav: main.rel tty.rel pt.rel + ld6 -f sav -o test.sav main.rel tty.rel pt.rel %.rel: %.s as6 -o $@ $< diff --git a/code/main.s b/code/main.s index 2dc994d..79de70b 100644 --- a/code/main.s +++ b/code/main.s @@ -8,8 +8,9 @@ PRS==4 PTP==100 -EXTERNAL PUTC,PUTS -EXTERNAL GETCH,GETC +EXTERN PUTC,PUTS +EXTERN GETCH,GETC +EXTERN PTPUT ENTRY: JRST START @@ -18,11 +19,11 @@ SP: XWD -100,PDL-1 START: MOVE PDP,SP - UUO1 123 +; UUO1 123 - CONO CPA,2001 - CONO PRS,2300 - JRST . +; CONO CPA,2001 +; CONO PRS,2300 +; JRST . MOVSI AC2,440700 HRRI AC2,MSG @@ -35,11 +36,6 @@ START: MOVE PDP,SP HALT -PTPUT: CONSZ PTP,20 - JRST .-1 - DATAO PTP,AC1 - POPJ PDP, - MSG: ASCIZ /Hello, world! yo! > / diff --git a/emu/Makefile b/emu/Makefile index a26aaf6..ad732d9 100644 --- a/emu/Makefile +++ b/emu/Makefile @@ -3,7 +3,7 @@ H=pdp6.h ../tools/pdp6common.h # clang #CFLAGS= -Wno-shift-op-parentheses -Wno-logical-op-parentheses \ # -Wno-bitwise-op-parentheses -CFLAGS= -g -fno-diagnostics-show-caret \ +CFLAGS= -g -Wall -Wno-parentheses -fno-diagnostics-show-caret \ `sdl-config --cflags` `pkg-config SDL_image --cflags` LIBS= `sdl-config --libs` `pkg-config SDL_image --libs` -lpthread diff --git a/emu/apr.c b/emu/apr.c index ead5d43..6e13d23 100644 --- a/emu/apr.c +++ b/emu/apr.c @@ -1,6 +1,49 @@ #include "pdp6.h" #include +static void aprcycle(void *p); +static void wake_cpa(void *dev); +static void wake_pi(void *dev); + +void +curpulse(Apr *apr, Pulse *p) +{ + if(apr->ncurpulses >= MAXPULSE){ + fprint(stderr, "error: too many current pulses\n"); + exit(1); + } + apr->clist[apr->ncurpulses++] = p; +} + +void +nextpulse(Apr *apr, Pulse *p) +{ + if(apr->nnextpulses >= MAXPULSE){ + fprint(stderr, "error: too many next pulses\n"); + exit(1); + } + apr->nlist[apr->nnextpulses++] = p; +} + +Apr* +makeapr(void) +{ + Apr *apr; + Thread th; + + apr = malloc(sizeof(Apr)); + memset(apr, 0, sizeof(Apr)); + apr->iobus.dev[CPA] = (Busdev){ apr, wake_cpa, 0 }; + apr->iobus.dev[PI] = (Busdev){ apr, wake_pi, 0 }; + + th = (Thread){ nil, aprcycle, apr, 1, 0 }; + addthread(th); + + return apr; +} + + + #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) @@ -655,7 +698,7 @@ pulse(mr_pwr_clr){ /* CPA and PI devices */ -void +static void wake_cpa(void *dev) { Apr *apr; @@ -708,7 +751,7 @@ wake_cpa(void *dev) ex_set(apr); } -void +static void wake_pi(void *dev) { Apr *apr; @@ -2487,9 +2530,9 @@ pulse(et0a){ trace("ET0A\n"); debug("%o: ", apr->pc); if((apr->inst & 0700) != 0700) - debug("%s\n", names[apr->inst]); + debug("%s\n", mnemonics[apr->inst]); else - debug("%s\n", ionames[apr->io_inst>>5 & 7]); + debug("%s\n", iomnemonics[apr->io_inst>>5 & 7]); if(PI_HOLD) set_pih(apr, apr->pi_req); // 8-3, 8-4 @@ -3014,36 +3057,6 @@ pulse(key_manual){ nextpulse(apr, kt0); // 5-2 } -void -curpulse(Apr *apr, Pulse *p) -{ - if(apr->ncurpulses >= MAXPULSE){ - fprint(stderr, "error: too many current pulses\n"); - exit(1); - } - apr->clist[apr->ncurpulses++] = p; -} - -void -nextpulse(Apr *apr, Pulse *p) -{ - if(apr->nnextpulses >= MAXPULSE){ - fprint(stderr, "error: too many next pulses\n"); - exit(1); - } - apr->nlist[apr->nnextpulses++] = p; -} - -Apr* -makeapr(void) -{ - Apr *apr; - apr = malloc(sizeof(Apr)); - memset(apr, 0, sizeof(Apr)); - apr->iobus.dev[CPA] = (Busdev){ apr, wake_cpa, 0 }; - apr->iobus.dev[PI] = (Busdev){ apr, wake_pi, 0 }; - return apr; -} /* find out which bits were turned on */ void @@ -3057,16 +3070,10 @@ updatebus(void *bus) #define TIMESTEP (1000.0/60.0) -void* -aprmain(void *p) +void +aprstart(Apr *apr) { - Apr *apr; - Busdev *dev; - Pulse **tmp; - int i, devcode; - double lasttick, tick; - - apr = (Apr*)p; + printf("[aprstart]\n"); apr->clist = apr->pulses1; apr->nlist = apr->pulses2; apr->ncurpulses = 0; @@ -3080,262 +3087,144 @@ aprmain(void *p) apr->membus.c34 = 0; apr->iobus.c12 = 0; apr->iobus.c34 = 0; - if(apr->membus.fmem) - apr->membus.fmem->poweron(apr->membus.fmem); - for(i = 0; i < 16; i++) - if(apr->membus.cmem[i]) - apr->membus.cmem[i]->poweron(apr->membus.cmem[i]); nextpulse(apr, mr_pwr_clr); - lasttick = getms(); - while(apr->sw_power){ - apr->ncurpulses = apr->nnextpulses; - apr->nnextpulses = 0; - tmp = apr->clist; apr->clist = apr->nlist; apr->nlist = tmp; + apr->lasttick = getms(); + apr->powered = 1; +} - if(apr->pulsestepping){ - int c; - while(c = getchar(), c != EOF && c != '\n') - if(c == 'x') - apr->pulsestepping = 0; - } +static void +aprcycle(void *p) +{ + Apr *apr; + Busdev *dev; + Pulse **tmp; + int i, devcode; - tick = getms(); - if(tick-lasttick >= TIMESTEP){ - lasttick = lasttick+TIMESTEP; - apr->cpa_clock_flag = 1; - recalc_cpa_req(apr); - } + apr = p; - 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; + if(!apr->sw_power){ + apr->powered = 0; + return; + }else if(!apr->powered) + aprstart(apr); - for(i = 0; i < apr->ncurpulses; i++) - apr->clist[i](apr); + apr->ncurpulses = apr->nnextpulses; + apr->nnextpulses = 0; + tmp = apr->clist; apr->clist = apr->nlist; apr->nlist = tmp; - updatebus(&apr->iobus); - updatebus(&apr->membus); + if(apr->pulsestepping){ + int c; + while(c = getchar(), c != EOF && c != '\n') + if(c == 'x') + apr->pulsestepping = 0; + } - /* This is simplified, we have no IOT RESET, - * IOT INIT SET UP or IOT FINAL SETUP really. - * normally we'd have to wait for IOT RESET to clear here */ - if(apr->iot_go) - nextpulse(apr, iot_t2); + apr->tick = getms(); + if(apr->tick-apr->lasttick >= TIMESTEP){ + apr->lasttick = apr->lasttick+TIMESTEP; + apr->cpa_clock_flag = 1; + recalc_cpa_req(apr); + } + + 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; + + for(i = 0; i < apr->ncurpulses; i++) + apr->clist[i](apr); + + updatebus(&apr->iobus); + updatebus(&apr->membus); + + /* This is simplified, we have no IOT RESET, + * IOT INIT SET UP or IOT FINAL SETUP really. + * normally we'd have to wait for IOT RESET to clear here */ + if(apr->iot_go) + nextpulse(apr, iot_t2); - /* Key pulses */ - if(apr->extpulse & EXT_KEY_MANUAL){ - apr->extpulse &= ~EXT_KEY_MANUAL; - nextpulse(apr, key_manual); - } - 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; - } + /* Key pulses */ + if(apr->extpulse & EXT_KEY_MANUAL){ + apr->extpulse &= ~EXT_KEY_MANUAL; + nextpulse(apr, key_manual); + } + 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 */ - 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]; + /* Pulses and signals through IO bus */ + 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); + } + 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); } - 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; - apr->extpulse &= ~EXT_NONEXIT_MEM; - nextpulse(apr, mai_addr_ack); - } - if(apr->membus.c12 & MEMBUS_MAI_RD_RS){ - apr->membus.c12 &= ~MEMBUS_MAI_RD_RS; - nextpulse(apr, mai_rd_rs); - } - if(apr->mc_rd && apr->membus.c34){ - /* 7-6, 7-9 */ - apr->mb |= apr->membus.c34; - apr->membus.c34 = 0; - } - - /* TODO: do this differently because the - * memory might have been busy. */ - if(apr->extpulse & EXT_NONEXIT_MEM){ - apr->extpulse &= ~EXT_NONEXIT_MEM; - if(apr->mc_rq && !apr->mc_stop) - nextpulse(apr, mc_non_exist_mem); // 7-9 - } - - if(i) - trace("--------------\n"); - else - /* no longer needed */ - apr->ia_inh = 0; } - debug("power off\n"); - return nil; + 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; + apr->extpulse &= ~EXT_NONEXIT_MEM; + nextpulse(apr, mai_addr_ack); + } + if(apr->membus.c12 & MEMBUS_MAI_RD_RS){ + apr->membus.c12 &= ~MEMBUS_MAI_RD_RS; + nextpulse(apr, mai_rd_rs); + } + if(apr->mc_rd && apr->membus.c34){ + /* 7-6, 7-9 */ + apr->mb |= apr->membus.c34; + apr->membus.c34 = 0; + } + + /* TODO: do this differently because the + * memory might have been busy. */ + if(apr->extpulse & EXT_NONEXIT_MEM){ + apr->extpulse &= ~EXT_NONEXIT_MEM; + if(apr->mc_rq && !apr->mc_stop) + nextpulse(apr, mc_non_exist_mem); // 7-9 + } + + if(i) + trace("--------------\n"); + else + /* no longer needed */ + apr->ia_inh = 0; } -char *names[0700] = { - "UUO00", "UUO01", "UUO02", "UUO03", - "UUO04", "UUO05", "UUO06", "UUO07", - "UUO10", "UUO11", "UUO12", "UUO13", - "UUO14", "UUO15", "UUO16", "UUO17", - "UUO20", "UUO21", "UUO22", "UUO23", - "UUO24", "UUO25", "UUO26", "UUO27", - "UUO30", "UUO31", "UUO32", "UUO33", - "UUO34", "UUO35", "UUO36", "UUO37", - "UUO40", "UUO41", "UUO42", "UUO43", - "UUO44", "UUO45", "UUO46", "UUO47", - "UUO50", "UUO51", "UUO52", "UUO53", - "UUO54", "UUO55", "UUO56", "UUO57", - "UUO60", "UUO61", "UUO62", "UUO63", - "UUO64", "UUO65", "UUO66", "UUO67", - "UUO70", "UUO71", "UUO72", "UUO73", - "UUO74", "UUO75", "UUO76", "UUO77", - "XX100", "XX101", "XX102", "XX103", - "XX104", "XX105", "XX106", "XX107", - "XX110", "XX111", "XX112", "XX113", - "XX114", "XX115", "XX116", "XX117", - "XX120", "XX121", "XX122", "XX123", - "XX124", "XX125", "XX126", "XX127", - "XX130", "XX131", "FSC", "CAO", - "LDCI", "LDC", "DPCI", "DPC", - "FAD", "FADL", "FADM", "FADB", - "FADR", "FADLR", "FADMR", "FADBR", - "FSB", "FSBL", "FSBM", "FSBB", - "FSBR", "FSBLR", "FSBMR", "FSBBR", - "FMP", "FMPL", "FMPM", "FMPB", - "FMPR", "FMPLR", "FMPMR", "FMPBR", - "FDV", "FDVL", "FDVM", "FDVB", - "FDVR", "FDVLR", "FDVMR", "FDVBR", - "MOVE", "MOVEI", "MOVEM", "MOVES", - "MOVS", "MOVSI", "MOVSM", "MOVSS", - "MOVN", "MOVNI", "MOVNM", "MOVNS", - "MOVM", "MOVMI", "MOVMM", "MOVMS", - "IMUL", "IMULI", "IMULM", "IMULB", - "MUL", "MULI", "MULM", "MULB", - "IDIV", "IDIVI", "IDIVM", "IDIVB", - "DIV", "DIVI", "DIVM", "DIVB", - "ASH", "ROT", "LSH", "XX243", - "ASHC", "ROTC", "LSHC", "XX247", - "EXCH", "BLT", "AOBJP", "AOBJN", - "JRST", "JFCL", "XCT", "XX257", - "PUSHJ", "PUSH", "POP", "POPJ", - "JSR", "JSP", "JSA", "JRA", - "ADD", "ADDI", "ADDM", "ADDB", - "SUB", "SUBI", "SUBM", "SUBB", - "CAI", "CAIL", "CAIE", "CAILE", - "CAIA", "CAIGE", "CAIN", "CAIG", - "CAM", "CAML", "CAME", "CAMLE", - "CAMA", "CAMGE", "CAMN", "CAMG", - "JUMP", "JUMPL", "JUMPE", "JUMPLE", - "JUMPA", "JUMPGE", "JUMPN", "JUMPG", - "SKIP", "SKIPL", "SKIPE", "SKIPLE", - "SKIPA", "SKIPGE", "SKIPN", "SKIPG", - "AOJ", "AOJL", "AOJE", "AOJLE", - "AOJA", "AOJGE", "AOJN", "AOJG", - "AOS", "AOSL", "AOSE", "AOSLE", - "AOSA", "AOSGE", "AOSN", "AOSG", - "SOJ", "SOJL", "SOJE", "SOJLE", - "SOJA", "SOJGE", "SOJN", "SOJG", - "SOS", "SOSL", "SOSE", "SOSLE", - "SOSA", "SOSGE", "SOSN", "SOSG", - - "SETZ", "SETZI", "SETZM", "SETZB", - "AND", "ANDI", "ANDM", "ANDB", - "ANDCA", "ANDCAI", "ANDCAM", "ANDCAB", - "SETM", "SETMI", "SETMM", "SETMB", - "ANDCM", "ANDCMI", "ANDCMM", "ANDCMB", - "SETA", "SETAI", "SETAM", "SETAB", - "XOR", "XORI", "XORM", "XORB", - "IOR", "IORI", "IORM", "IORB", - "ANDCB", "ANDCBI", "ANDCBM", "ANDCBB", - "EQV", "EQVI", "EQVM", "EQVB", - "SETCA", "SETCAI", "SETCAM", "SETCAB", - "ORCA", "ORCAI", "ORCAM", "ORCAB", - "SETCM", "SETCMI", "SETCMM", "SETCMB", - "ORCM", "ORCMI", "ORCMM", "ORCMB", - "ORCB", "ORCBI", "ORCBM", "ORCBB", - "SETO", "SETOI", "SETOM", "SETOB", - - "HLL", "HLLI", "HLLM", "HLLS", - "HRL", "HRLI", "HRLM", "HRLS", - "HLLZ", "HLLZI", "HLLZM", "HLLZS", - "HRLZ", "HRLZI", "HRLZM", "HRLZS", - "HLLO", "HLLOI", "HLLOM", "HLLOS", - "HRLO", "HRLOI", "HRLOM", "HRLOS", - "HLLE", "HLLEI", "HLLEM", "HLLES", - "HRLE", "HRLEI", "HRLEM", "HRLES", - "HRR", "HRRI", "HRRM", "HRRS", - "HLR", "HLRI", "HLRM", "HLRS", - "HRRZ", "HRRZI", "HRRZM", "HRRZS", - "HLRZ", "HLRZI", "HLRZM", "HLRZS", - "HRRO", "HRROI", "HRROM", "HRROS", - "HLRO", "HLROI", "HLROM", "HLROS", - "HRRE", "HRREI", "HRREM", "HRRES", - "HLRE", "HLREI", "HLREM", "HLRES", - - "TRN", "TLN", "TRNE", "TLNE", - "TRNA", "TLNA", "TRNN", "TLNN", - "TDN", "TSN", "TDNE", "TSNE", - "TDNA", "TSNA", "TDNN", "TSNN", - "TRZ", "TLZ", "TRZE", "TLZE", - "TRZA", "TLZA", "TRZN", "TLZN", - "TDZ", "TSZ", "TDZE", "TSZE", - "TDZA", "TSZA", "TDZN", "TSZN", - "TRC", "TLC", "TRCE", "TLCE", - "TRCA", "TLCA", "TRCN", "TLCN", - "TDC", "TSC", "TDCE", "TSCE", - "TDCA", "TSCA", "TDCN", "TSCN", - "TRO", "TLO", "TROE", "TLOE", - "TROA", "TLOA", "TRON", "TLON", - "TDO", "TSO", "TDOE", "TSOE", - "TDOA", "TSOA", "TDON", "TSON", -}; - -char *ionames[] = { - "BLKI", - "DATAI", - "BLKO", - "DATAO", - "CONO", - "CONI", - "CONSZ", - "CONSO" -}; void testinst(Apr *apr) @@ -3346,7 +3235,7 @@ testinst(Apr *apr) // for(inst = 0140; inst < 0141; inst++){ apr->ir = inst << 9 | 1 << 5; decodeir(apr); - debug("%06o %6s ", apr->ir, names[inst]); + debug("%06o %6s ", apr->ir, mnemonics[inst]); /* debug("%s ", FAC_INH ? "FAC_INH" : " "); debug("%s ", FAC2 ? "FAC2" : " "); @@ -3360,8 +3249,8 @@ testinst(Apr *apr) 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 , \ +//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", diff --git a/emu/cmd.c b/emu/cmd.c index 2e8148c..445e174 100644 --- a/emu/cmd.c +++ b/emu/cmd.c @@ -200,7 +200,7 @@ dep(word addr, int fastmem, word w) static void c_ex(int argc, char *argv[]) { - char *argv0; + char *argv0 = nil; word start, end; int format, fastmem; @@ -225,7 +225,7 @@ c_ex(int argc, char *argv[]) static void c_dep(int argc, char *argv[]) { - char *argv0; + char *argv0 = nil; word start, end; word w; int fastmem; @@ -276,6 +276,7 @@ loadsav(FILE *fp) static void c_load(int argc, char *argv[]) { + char *argv0 = nil; FILE *fp; int fmt; diff --git a/emu/main.c b/emu/main.c index 5ea088b..2a74e46 100644 --- a/emu/main.c +++ b/emu/main.c @@ -74,6 +74,26 @@ err(char *fmt, ...) exit(1); } +u32 +getms(void) +{ + return SDL_GetTicks(); +} + +int +hasinput(int fd) +{ + fd_set fds; + struct timeval timeout; + + timeout.tv_sec = 0; + timeout.tv_usec = 0; + FD_ZERO(&fds); + FD_SET(fd, &fds); + return select(fd+1, &fds, NULL, NULL, &timeout) > 0; +} + + SDL_Surface* mustloadimg(const char *path) { @@ -141,14 +161,6 @@ getswitches(Element *sw, int n) return w; } -void -poweron(Apr *apr) -{ - pthread_t apr_thread; - apr->sw_power = 1; - pthread_create(&apr_thread, nil, aprmain, apr); -} - #define KEYPULSE(k) (apr->k && !oldapr.k) void @@ -170,8 +182,6 @@ updateapr(Apr *apr, Ptr *ptr) misc_l[3].state = apr->sw_repeat = misc_sw[0].state; misc_l[4].state = apr->sw_addr_stop = misc_sw[1].state; misc_l[5].state = apr->sw_power = misc_sw[2].state; - if(apr->sw_power && !oldapr.sw_power) - poweron(apr); misc_l[6].state = apr->sw_mem_disable = misc_sw[3].state; apr->data = getswitches(data_sw, 36); apr->mas = getswitches(ma_sw, 18); @@ -528,12 +538,38 @@ findlayout(int *w, int *h) *h = oppanel.pos.y + oppanel.surf->h; } -u32 -getms(void) + +Thread *threads; + +void +addthread(Thread th) { - return SDL_GetTicks(); + Thread *p; + p = malloc(sizeof(Thread)); + *p = th; + p->next = threads; + threads = p; } +void* +simthread(void *p) +{ + Thread *th; + + printf("[simthread] start\n"); + for(;;) + for(th = threads; th; th = th->next){ + th->cnt++; + if(th->cnt == th->freq){ + th->cnt = 0; + th->f(th->arg); + } + } + err("can't happen"); + return nil; +} + + void quit(int code) { @@ -550,7 +586,6 @@ usage(void) } Apr *aprs[4]; -Mem *coremems[4]; int main(int argc, char *argv[]) @@ -560,17 +595,17 @@ main(int argc, char *argv[]) SDL_MouseButtonEvent *mbev; SDL_MouseMotionEvent *mmev; Element *e; - Uint32 start, end; - int delay; int i; int w, h; - pthread_t cmd_thread; + pthread_t cmd_thread, sim_thread; const char *outfile, *ttyfile; Apr *apr; Ptr *ptr; Ptp *ptp; Tty *tty; + Mem *coremems[4]; + Mem *fastmem; outfile = "/dev/null"; ttyfile = "/tmp/6tty"; @@ -681,12 +716,14 @@ main(int argc, char *argv[]) extra_l = e; e += 1; - aprs[0] = apr = makeapr(); + fastmem = makefastmem(0); coremems[0] = makecoremem("mem_0"); coremems[1] = makecoremem("mem_1"); coremems[2] = makecoremem("mem_2"); coremems[3] = makecoremem("mem_3"); - attachmem(makefastmem(0), 0, &apr->membus, -1); + + aprs[0] = apr = makeapr(); + attachmem(fastmem, 0, &apr->membus, -1); attachmem(coremems[0], 0, &apr->membus, 0); attachmem(coremems[1], 0, &apr->membus, 1); attachmem(coremems[2], 0, &apr->membus, 2); @@ -697,10 +734,18 @@ main(int argc, char *argv[]) if(ttyfile) attachdevtty(tty, ttyfile); + /* Power on memory */ + // TODO: maybe do that somewhere else? + fastmem->poweron(fastmem); + coremems[0]->poweron(coremems[0]); + coremems[1]->poweron(coremems[1]); + coremems[2]->poweron(coremems[2]); + coremems[3]->poweron(coremems[3]); + + pthread_create(&sim_thread, nil, simthread, apr); pthread_create(&cmd_thread, nil, cmdthread, nil); for(;;){ - start = SDL_GetTicks(); while(SDL_PollEvent(&ev)) switch(ev.type){ case SDL_MOUSEMOTION: @@ -744,10 +789,6 @@ main(int argc, char *argv[]) // SDL_UnlockSurface(screen); SDL_Flip(screen); - end = SDL_GetTicks(); - delay = (1000 / 30) - (end-start); -// if(delay > 0) -// SDL_Delay(delay); } return 0; } diff --git a/emu/mem.c b/emu/mem.c index f7361a6..b340c80 100644 --- a/emu/mem.c +++ b/emu/mem.c @@ -46,7 +46,6 @@ wakecore(Mem *mem, Membus *bus) * Lower numbers have higher priority but proc 2 and 3 have * the same priority and requests are alternated between them. * If no request is made, we should already be connected to a bus */ - pthread_mutex_lock(&core->mutex); if(core->cmc_p_act < 0){ if(mem->bus[0]->c12 & MEMBUS_RQ_CYC) core->cmc_p_act = 0; @@ -65,18 +64,16 @@ wakecore(Mem *mem, Membus *bus) core->cmc_p_act = 2; else if(p3) core->cmc_p_act = 3; - else{ - pthread_mutex_unlock(&core->mutex); + else return 1; /* no request at all? */ - } } core->cmc_last_proc = core->cmc_p_act; } } - pthread_mutex_unlock(&core->mutex); /* The executing thread can only service requests from its own processor * due to synchronization with the processor's pulse cycle. */ + /* TODO: is this still true after the removal of pthreads? */ if(bus != mem->bus[core->cmc_p_act]) return 1; @@ -135,6 +132,7 @@ powercore(Mem *mem) { CMem *core; + printf("[powercore]\n"); core = mem->module; readmem(core->filename, core->core, 040000); core->cmc_aw_rq = 1; @@ -200,6 +198,7 @@ powerff(Mem *mem) { FMem *ff; + printf("[powerff]\n"); ff = mem->module; ff->fmc_act = 0; ff->fmc_wr = 0; @@ -241,7 +240,6 @@ makecoremem(const char *file) core = malloc(sizeof(CMem)); memset(core, 0, sizeof(CMem)); core->filename = file; - pthread_mutex_init(&core->mutex, nil); mem = malloc(sizeof(Mem)); mem->module = core; diff --git a/emu/pdp6.h b/emu/pdp6.h index 5c38a47..165d89e 100644 --- a/emu/pdp6.h +++ b/emu/pdp6.h @@ -5,7 +5,6 @@ #include #include #include -#include #include "../tools/pdp6common.h" #define nelem(a) (sizeof(a)/sizeof(a[0])) @@ -24,6 +23,9 @@ extern FILE *debugfp; extern int dotrace; void trace(char *fmt, ...); void debug(char *fmt, ...); +void err(char *fmt, ...); +u32 getms(void); +int hasinput(int fd); void quit(int code); void *cmdthread(void *); @@ -65,6 +67,20 @@ enum FullwordBits { F33 = 0000000000004, F34 = 0000000000002, F35 = 0000000000001 }; +typedef struct Thread Thread; +struct Thread +{ + Thread *next; /* link to next thread */ + void (*f)(void*); + void *arg; + int freq; /* how often the thread is serviced */ + int cnt; +}; + +extern Thread *threads; +void addthread(Thread th); + + /* external pulses, bits of Apr.extpulse */ enum Extpulse { EXT_KEY_MANUAL = 1, @@ -121,8 +137,6 @@ typedef struct Busdev Busdev; typedef struct IOBus IOBus; typedef struct Apr Apr; -u32 getms(void); - /* * Memory @@ -190,7 +204,6 @@ Mem *makefastmem(int p); struct CMem { const char *filename; - pthread_mutex_t mutex; word core[040000]; word cmb; @@ -294,6 +307,7 @@ struct Apr { IOBus iobus; Membus membus; + int powered; hword ir; word mi; @@ -391,6 +405,7 @@ struct Apr bool pc_set; /* needed for the emulation */ + double lasttick, tick; int extpulse; bool ia_inh; // this is asserted for some time int pulsestepping; @@ -401,9 +416,6 @@ struct Apr }; extern Apr *aprs[4]; Apr *makeapr(void); -void curpulse(Apr *apr, Pulse *p); -void nextpulse(Apr *apr, Pulse *p); -void *aprmain(void *p); /* Paper tape punch 761 */ @@ -416,7 +428,7 @@ struct Ptp bool busy, flag, b; int pia; - FILE *fp; + int fd; int waitdatao; }; Ptp *makeptp(IOBus *bus); @@ -434,7 +446,7 @@ struct Ptr bool busy, flag, b; int pia; - FILE *fp; + int fd; }; Ptr *makeptr(IOBus *bus); void ptr_setmotor(Ptr *ptr, int m); @@ -454,9 +466,3 @@ struct Tty }; Tty *maketty(IOBus *bus); void attachdevtty(Tty *tty, const char *path); - - - -// for debugging -char *names[0700]; -char *ionames[010]; diff --git a/emu/pt.c b/emu/pt.c index d253cae..502465b 100644 --- a/emu/pt.c +++ b/emu/pt.c @@ -1,10 +1,10 @@ #include "pdp6.h" #include #include +#include #include #include #include -#include #include /* TODO? implement motor delays */ @@ -24,66 +24,61 @@ recalc_ptr_req(Ptr *ptr) /* We have to punch after DATAO SET has happened. But BUSY is set by * DATAO CLEAR. So we use waitdatao to record when SET has happened */ -static void* -ptpthread(void *dev) +static void +ptpcycle(void *p) { Ptp *ptp; + uchar c; - ptp = dev; - for(;;){ - if(ptp->busy && ptp->waitdatao){ - if(ptp->fp){ - if(ptp->b) - putc((ptp->ptp & 077) | 0200, ptp->fp); - else - putc(ptp->ptp, ptp->fp); - fflush(ptp->fp); - } - ptp->busy = 0; - ptp->flag = 1; - recalc_ptp_req(ptp); + ptp = p; + if(ptp->busy && ptp->waitdatao){ + if(ptp->fd >= 0){ + if(ptp->b) + c = (ptp->ptp & 077) | 0200; + else + c = ptp->ptp; + write(ptp->fd, &c, 1); } + ptp->busy = 0; + ptp->flag = 1; + recalc_ptp_req(ptp); } - return nil; } -static void* -ptrthread(void *dev) +static void +ptrcycle(void *p) { Ptr *ptr; - int c; + uchar c; - ptr = dev; - for(;;){ - if(ptr->busy && ptr->motor_on){ - // PTR CLR - ptr->sr = 0; - ptr->ptr = 0; - next: - if(ptr->fp) - c = getc(ptr->fp); - else - c = 0; - if(c == EOF) - c = 0; - if(!ptr->b || c & 0200){ - // PTR STROBE - ptr->sr <<= 1; - ptr->ptr <<= 6; - ptr->sr |= 1; - ptr->ptr |= c & 077; - if(!ptr->b) - ptr->ptr |= c & 0300; - } - if(!ptr->b || ptr->sr & 040){ - ptr->busy = 0; - ptr->flag = 1; - }else - goto next; - recalc_ptr_req(ptr); - } + ptr = p; + if(!ptr->busy || !ptr->motor_on) + return; + + // PTR CLR + ptr->sr = 0; + ptr->ptr = 0; +next: + if(ptr->fd >= 0 && hasinput(ptr->fd)){ + if(read(ptr->fd, &c, 1) != 1) + c = 0; + }else + c = 0; + if(!ptr->b || c & 0200){ + // PTR STROBE + ptr->sr <<= 1; + ptr->ptr <<= 6; + ptr->sr |= 1; + ptr->ptr |= c & 077; + if(!ptr->b) + ptr->ptr |= c & 0300; } - return nil; + if(!ptr->b || ptr->sr & 040){ + ptr->busy = 0; + ptr->flag = 1; + }else + goto next; + recalc_ptr_req(ptr); } static void @@ -193,30 +188,35 @@ ptr_setmotor(Ptr *ptr, int m) Ptp* makeptp(IOBus *bus) { - pthread_t thread_id; Ptp *ptp; + Thread th; ptp = malloc(sizeof(Ptp)); memset(ptp, 0, sizeof(Ptp)); ptp->bus = bus; bus->dev[PTP] = (Busdev){ ptp, wake_ptp, 0 }; - pthread_create(&thread_id, nil, ptpthread, ptp); - ptp->fp = fopen("../code/ptp.out", "wb"); + th = (Thread){ nil, ptpcycle, ptp, 1, 0 }; + addthread(th); + + ptp->fd = open("../code/ptp.out", O_WRONLY | O_CREAT, 0666); return ptp; } Ptr* makeptr(IOBus *bus) { - pthread_t thread_id; Ptr *ptr; + Thread th; ptr = malloc(sizeof(Ptr)); memset(ptr, 0, sizeof(Ptr)); ptr->bus = bus; bus->dev[PTR] = (Busdev){ ptr, wake_ptr, 0 }; - pthread_create(&thread_id, nil, ptrthread, ptr); - ptr->fp = fopen("../code/test.rim", "rb"); + th = (Thread){ nil, ptrcycle, ptr, 1, 0 }; + addthread(th); + + ptr->fd = open("../code/test.rim", O_RDONLY); + return ptr; } diff --git a/emu/tty.c b/emu/tty.c index 8acee2a..4a921b5 100644 --- a/emu/tty.c +++ b/emu/tty.c @@ -2,7 +2,6 @@ #include #include #include -#include #include static void @@ -11,23 +10,23 @@ recalc_tty_req(Tty *tty) setreq(tty->bus, TTY, tty->tto_flag || tty->tti_flag ? tty->pia : 0); } -/* TODO: implement some kind of sleep if no tty is attached */ -static void* -ttythread(void *dev) +static void +ttycycle(void *p) { + Tty *tty; int n; char c; - Tty *tty; - tty = dev; - for(;;){ - while(tty->fd >= 0 && (n = read(tty->fd, &c, 1)) > 0){ - tty->tti_busy = 1; - tty->tti = c|0200; - tty->tti_busy = 0; - tty->tti_flag = 1; - recalc_tty_req(tty); - } + tty = p; + if(tty->fd >= 0 && hasinput(tty->fd)){ + tty->tti_busy = 1; + n = read(tty->fd, &c, 1); + tty->tti = c|0200; + tty->tti_busy = 0; + if(n < 0) + return; + tty->tti_flag = 1; + recalc_tty_req(tty); } } @@ -123,14 +122,17 @@ fail: Tty* maketty(IOBus *bus) { - pthread_t thread_id; Tty *tty; + Thread th; tty = malloc(sizeof(Tty)); memset(tty, 0, sizeof(Tty)); tty->fd = -1; tty->bus = bus; bus->dev[TTY] = (Busdev){ tty, wake_tty, 0 }; - pthread_create(&thread_id, nil, ttythread, tty); + + th = (Thread){ nil, ttycycle, tty, 1, 0 }; + addthread(th); + return tty; } diff --git a/tools/args.h b/tools/args.h new file mode 100644 index 0000000..0e666c1 --- /dev/null +++ b/tools/args.h @@ -0,0 +1,24 @@ +extern char *argv0; +#define USED(x) ((void)x) +#define SET(x) ((x)=0) + +#define ARGBEGIN for((argv0||(argv0=*argv)),argv++,argc--;\ + argv[0] && argv[0][0]=='-' && argv[0][1];\ + argc--, argv++) {\ + char *_args, *_argt;\ + char _argc;\ + _args = &argv[0][1];\ + if(_args[0]=='-' && _args[1]==0){\ + argc--; argv++; break;\ + }\ + _argc = 0;\ + while(*_args && (_argc = *_args++))\ + switch(_argc) +#define ARGEND SET(_argt);USED(_argt);USED(_argc);USED(_args);}USED(argv);USED(argc); +#define ARGF() (_argt=_args, _args=(char*)"",\ + (*_argt? _argt: argv[1]? (argc--, *++argv): 0)) +#define EARGF(x) (_argt=_args, _args=(char*)"",\ + (*_argt? _argt: argv[1]? (argc--, *++argv): ((x), abort(), (char*)0))) + +#define ARGC() _argc + diff --git a/tools/pdp6common.c b/tools/pdp6common.c index b7d697a..8de7f3e 100644 --- a/tools/pdp6common.c +++ b/tools/pdp6common.c @@ -42,7 +42,6 @@ readw(FILE *fp) void writewbak(word w, FILE *fp) { - unsigned char c; putc((w >> 29) & 0177, fp); putc((w >> 22) & 0177, fp); putc((w >> 15) & 0177, fp); diff --git a/tools/pdp6common.h b/tools/pdp6common.h index ddda1c6..d44f525 100644 --- a/tools/pdp6common.h +++ b/tools/pdp6common.h @@ -28,3 +28,6 @@ int issixbit(char c); word sixbit(const char *s); void unsixbit(word sx, char *s); char *disasm(word w); + +extern char *mnemonics[448]; +extern char *iomnemonics[8];