mirror of
https://github.com/aap/pdp6.git
synced 2026-03-06 11:23:55 +00:00
implemented threads differently
This commit is contained in:
@@ -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 $@ $<
|
||||
|
||||
18
code/main.s
18
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! > /
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
449
emu/apr.c
449
emu/apr.c
@@ -1,6 +1,49 @@
|
||||
#include "pdp6.h"
|
||||
#include <unistd.h>
|
||||
|
||||
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",
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
89
emu/main.c
89
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;
|
||||
}
|
||||
|
||||
10
emu/mem.c
10
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;
|
||||
|
||||
36
emu/pdp6.h
36
emu/pdp6.h
@@ -5,7 +5,6 @@
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <pthread.h>
|
||||
#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];
|
||||
|
||||
112
emu/pt.c
112
emu/pt.c
@@ -1,10 +1,10 @@
|
||||
#include "pdp6.h"
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <pthread.h>
|
||||
#include <poll.h>
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
34
emu/tty.c
34
emu/tty.c
@@ -2,7 +2,6 @@
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
#include <pthread.h>
|
||||
#include <poll.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
24
tools/args.h
Normal file
24
tools/args.h
Normal file
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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];
|
||||
|
||||
Reference in New Issue
Block a user