From bf1502e9eee1f0cfd069e91317cf0881285a7e9c Mon Sep 17 00:00:00 2001 From: aap Date: Sun, 14 Apr 2024 17:41:05 +0200 Subject: [PATCH] new emulator; will replace the other one eventually --- newemu/Makefile | 11 + newemu/args.h | 27 + newemu/audio.c | 66 + newemu/chargen.inc | 781 +++++++ newemu/common.c | 240 ++ newemu/common.h | 34 + newemu/dc.c | 182 ++ newemu/dis340.c | 632 +++++ newemu/ge.c | 172 ++ newemu/instgen.inc | 5486 ++++++++++++++++++++++++++++++++++++++++++++ newemu/main.c | 293 +++ newemu/panel10.c | 102 + newemu/panel6.c | 91 + newemu/pdp6.c | 2776 ++++++++++++++++++++++ newemu/pdp6.h | 323 +++ newemu/pt.c | 266 +++ newemu/tty.c | 134 ++ newemu/ut.c | 616 +++++ 18 files changed, 12232 insertions(+) create mode 100644 newemu/Makefile create mode 100644 newemu/args.h create mode 100644 newemu/audio.c create mode 100644 newemu/chargen.inc create mode 100644 newemu/common.c create mode 100644 newemu/common.h create mode 100644 newemu/dc.c create mode 100644 newemu/dis340.c create mode 100644 newemu/ge.c create mode 100644 newemu/instgen.inc create mode 100644 newemu/main.c create mode 100644 newemu/panel10.c create mode 100644 newemu/panel6.c create mode 100644 newemu/pdp6.c create mode 100644 newemu/pdp6.h create mode 100644 newemu/pt.c create mode 100644 newemu/tty.c create mode 100644 newemu/ut.c diff --git a/newemu/Makefile b/newemu/Makefile new file mode 100644 index 0000000..ec5576c --- /dev/null +++ b/newemu/Makefile @@ -0,0 +1,11 @@ +INC= +LIBS=-lpthread -lm -lSDL2 +#CFLAGS=-Wall -Wextra -g -O3 +#CFLAGS=-g -O3 -mcpu=cortex-a53 -mtune=cortex-a53 +CFLAGS=-g -Wall -Wno-parentheses + +pdp6: main.c panel6.c pdp6.c tty.c pt.c dis340.c dc.c ut.c ge.c audio.c common.c + cc $(CFLAGS) -o $@ $^ $(INC) $(LIBS) + +run: pdp6 + ./pdp6 diff --git a/newemu/args.h b/newemu/args.h new file mode 100644 index 0000000..830e3a1 --- /dev/null +++ b/newemu/args.h @@ -0,0 +1,27 @@ +#ifndef USED +#define USED(x) ((void)x) +#endif +#define SET(x) ((x)=0) + +extern char *argv0; + +#define ARGBEGIN for((void)(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/newemu/audio.c b/newemu/audio.c new file mode 100644 index 0000000..cb24181 --- /dev/null +++ b/newemu/audio.c @@ -0,0 +1,66 @@ +#include "common.h" +#include "pdp6.h" + +#include + +static SDL_AudioDeviceID dev; +static int nsamples; +static u64 nexttime; + +#define SAMPLE_TIME (1000000000/48000) + +void +initmusic(void) +{ + SDL_AudioSpec spec; + + SDL_Init(SDL_INIT_AUDIO); + + memset(&spec, 0, sizeof(spec)); + spec.freq = 48000; + spec.format = AUDIO_U8; + spec.channels = 1; + spec.samples = 1024; // whatever this is + spec.callback = nil; + dev = SDL_OpenAudioDevice(nil, 0, &spec, nil, 0); +} + +void +stopmusic(void) +{ + if(dev == 0) + return; + + SDL_PauseAudioDevice(dev, 1); + SDL_ClearQueuedAudio(dev); + nsamples = 0; + nexttime = 0; +} + +void +svc_music(PDP6 *pdp) +{ + u8 s; + + if(dev == 0 || nexttime >= simtime) + return; + + if(nexttime == 0) + nexttime = simtime + SAMPLE_TIME; + else + nexttime += SAMPLE_TIME; + + // queue up a few samples + if(nsamples < 10) { + nsamples++; + // then start playing + if(nsamples == 10) + SDL_PauseAudioDevice(dev, 0); + } + + s = 0; + for(int i = 0; i < 6; i++) + if(pdp->mi & (1< +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "common.h" + +void +panic(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); + exit(1); +} +int +hasinput(int fd) +{ + fd_set fds; + struct timeval timeout; + + if(fd < 0) return 0; + + timeout.tv_sec = 0; + timeout.tv_usec = 0; + FD_ZERO(&fds); + FD_SET(fd, &fds); + return select(fd+1, &fds, NULL, NULL, &timeout) > 0; +} + +int +dial(const char *host, int port) +{ + char portstr[32]; + int sockfd; + struct addrinfo *result, *rp, hints; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + snprintf(portstr, 32, "%d", port); + if(getaddrinfo(host, portstr, &hints, &result)){ + perror("error: getaddrinfo"); + return -1; + } + + for(rp = result; rp; rp = rp->ai_next){ + sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); + if(sockfd < 0) + continue; + if(connect(sockfd, rp->ai_addr, rp->ai_addrlen) >= 0) + goto win; + close(sockfd); + } + freeaddrinfo(result); + perror("error"); + return -1; + +win: + freeaddrinfo(result); + return sockfd; +} + +int +serve1(int port) +{ + int sockfd, confd; + socklen_t len; + struct sockaddr_in server, client; + int x; + + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if(sockfd < 0){ + perror("error: socket"); + return -1; + } + + x = 1; + setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void *)&x, sizeof x); + + memset(&server, 0, sizeof(server)); + server.sin_family = AF_INET; + server.sin_addr.s_addr = INADDR_ANY; + server.sin_port = htons(port); + if(bind(sockfd, (struct sockaddr*)&server, sizeof(server)) < 0){ + perror("error: bind"); + return -1; + } + listen(sockfd, 5); + len = sizeof(client); + confd = accept(sockfd, (struct sockaddr*)&client, &len), + close(sockfd); + if(confd >= 0) + return confd; + perror("error: accept"); + return -1; +} +void +nodelay(int fd) +{ + int flag = 1; + setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag)); +} + + +void* +createseg(const char *name, size_t sz) +{ + int fd; + void *p; + + mode_t mask = umask(0); + fd = open(name, O_RDWR|O_CREAT, 0666); + umask(mask); + // if we try to open a /tmp file owned by another user + // with O_CREAT, the above will fail (even for root). + // so try again without O_CREAT + if(fd == -1) + fd = open(name, O_RDWR); + if(fd == -1) { + fprintf(stderr, "couldn't open file %s\n", name); + return nil; + } + ftruncate(fd, sz); + p = mmap(nil, sz, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if(p == MAP_FAILED) { + fprintf(stderr, "couldn't mmap file\n"); + return nil; + } + + return p; +} +void* +attachseg(const char *name, size_t sz) +{ + int fd; + void *p; + + fd = open(name, O_RDWR); + if(fd == -1) { + fprintf(stderr, "couldn't open file %s\n", name); + return nil; + } + p = mmap(NULL, sz, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if(p == MAP_FAILED) { + fprintf(stderr, "couldn't mmap file\n"); + return nil; + } + + return p; +} + +static struct timespec starttime; +void +inittime(void) +{ + clock_gettime(CLOCK_MONOTONIC, &starttime); +} +u64 +gettime(void) +{ + struct timespec tm; + u64 t; + clock_gettime(CLOCK_MONOTONIC, &tm); + tm.tv_sec -= starttime.tv_sec; + t = tm.tv_nsec; + t += (u64)tm.tv_sec * 1000 * 1000 * 1000; + return t; +} +void +nsleep(u64 ns) +{ + struct timespec tm; + tm.tv_sec = ns / (1000 * 1000 * 1000); + tm.tv_nsec = ns % (1000 * 1000 * 1000); + nanosleep(&tm, nil); +} + + + +static int +isdelim(char c) +{ + return c == '\0' || strchr(" \t\n;'\"", c) != nil; +} + +/* have to free argv[0] and argv to clean up */ +char** +split(char *line, int *pargc) +{ + int argc, n; + char **argv, *lp, delim; + + n = strlen(line)+1; + // just allocate enough + lp = (char*)malloc(2*n); + argv = (char**)malloc(sizeof(char*)*n); + argc = 0; + for(; *line; line++) { + while(isspace(*line)) line++; + if(*line == '\0') + break; + argv[argc++] = lp; + if(*line == '"' || *line == '\'') { + delim = *line++; + while(*line && *line != delim) { + if(*line == '\\') + line++; + *lp++ = *line++; + } + } else { + while(!isdelim(*line)) { + if(*line == '\\') + line++; + *lp++ = *line++; + } + } + *lp++ = '\0'; + } + if(pargc) *pargc = argc; + argv[argc++] = nil; + + return argv; +} diff --git a/newemu/common.h b/newemu/common.h new file mode 100644 index 0000000..dde462f --- /dev/null +++ b/newemu/common.h @@ -0,0 +1,34 @@ +#include +#include +#include +#include +#include + +//typedef uint64_t u64; +typedef unsigned long long u64; +typedef uint32_t u32; +typedef uint16_t u16; +typedef uint8_t u8; +typedef int64_t i64; +typedef int32_t i32; +typedef int16_t i16; +typedef int8_t i8; +#define nil NULL + +#define nelem(array) (sizeof(array)/sizeof(array[0])) + +void panic(const char *fmt, ...); +int hasinput(int fd); +int dial(const char *host, int port); +int serve1(int port); +void nodelay(int fd); + +void *createseg(const char *name, size_t sz); +void *attachseg(const char *name, size_t sz); + +void inittime(void); +u64 gettime(void); +void nsleep(u64 ns); +#define NEVER (~0) + +char **split(char *line, int *pargc); diff --git a/newemu/dc.c b/newemu/dc.c new file mode 100644 index 0000000..cc33030 --- /dev/null +++ b/newemu/dc.c @@ -0,0 +1,182 @@ +#include "common.h" +#include "pdp6.h" + +#define IOB pdp->iob + +static void calc_dc_req(PDP6 *pdp, Dc136 *dc); + +static void +dbda_swap(Dc136 *dc) +{ + dc->dbda_move = 0; + dc->darq = 0; + dc->dbrq = 1; + if(dc->inout) // out + dc->da = dc->db; + else { + dc->db = dc->da; + dc->da = 0; + } +//printf("DB req %012llo\n", dc->db); +} + +/* + * bits per char ch mode shifts per char chars per word + * 6 0 0 0 6 + * 12 1 0 2 3 + * 18 1 1 3 2 + * 36 0 1 0 1 + */ +#define NSHIFT ((0xE0 >> (dc->ch_mode*2)) & 3) +#define NCHARS ((02316 >> (dc->ch_mode*3)) & 7) +#define DC_SCT_DONE (dc->sct == NSHIFT) +#define DC_CCT_DONE (dc->cct == NCHARS-1) + +static void +dashcp0(Dc136 *dc, Word inp) +{ +cp0: + // DASH CP0 + if(dc->darq) + dc->data_clbd = 1; + + // 1μs dly + + // DASH CP1 + if(DC_CCT_DONE) { + dc->cct = 0; + if(dc->dbda_move && !dc->darq) + dbda_swap(dc); + else + dc->darq = 1; + } else if(DC_SCT_DONE) { + // CCT CONT + dc->sct = 0; + dc->cct = (dc->cct+1) & 7; + } else { + // SCT CONT + dc->sct = (dc->sct+1) & 3; + + // DASH LT + dc->da = dc->da<<6 | inp; + goto cp0; + } +} + +int +dctkgv(Dc136 *dc, int dev, int ch, int rt) +{ + int ret; + if(dc->device != dev) + return 0; + + switch(dev) { + case 1: case 2: + if(rt) { + ret = dc->da & 077; + ret = (ret<<3 | ret>>3) & 077; + ch = (ch<<3 | ch>>3) & 077; + dc->da = dc->da>>6 | (Word)ch<<30; + } else { + case 3: case 4: + ret = (dc->da>>30) & 077; + ch &= 077; + dc->da = dc->da<<6 | ch; + } + break; + default: // shouldn't happen + return 0; + } + dc->da &= FW; + dashcp0(dc, ch); + calc_dc_req(dc->pdp, dc); + return ret; +} + +static void +handle_dc(PDP6 *pdp, IOdev *dev, int cmd) +{ + Dc136 *dc = (Dc136*)dev->dev; + + bool s0 = dc->darq && dc->dbda_move; + switch(cmd) { + case IOB_RESET: + dc->db = 0; + dc->da = 0; // hack so DB isn't overwritten again + case IOB_CONO_CLR: + dc->sct = 0; + dc->cct = 0; + dc->data_clbd = 0; + dc->dbda_move = 0; + dc->darq = 0; + dc->dbrq = 0; + dc->inout = 0; + dc->ch_mode = 0; + dc->device = 0; + dc->pia = 0; + + dc->db = dc->da; + dc->da = 0; + break; + + case IOB_CONO_SET: + if(IOB & F23) dc->data_clbd = 1; + if(IOB & F24) dc->dbda_move = 1; + if(IOB & F25) dc->darq = 1; + if(IOB & F26) dc->dbrq = 1; + if(IOB & F27) dc->inout = 1; + dc->ch_mode |= (IOB>>6)&3; + dc->device |= (IOB>>3)&7; + dc->pia |= IOB&7; + break; + + case IOB_DATAO_CLR: + dc->db = 0; + dc->dbrq = 0; + break; + case IOB_DATAO_SET: + dc->db |= IOB; + dc->dbda_move = 1; + break; + + case IOB_DATAI: + IOB |= dc->db; + dc->dbrq = 0; + dc->dbda_move = 1; + break; + + case IOB_STATUS: + IOB |= dc->cct<<13; + if(dc->data_clbd) IOB |= F23; + if(dc->dbda_move) IOB |= F24; + if(dc->darq) IOB |= F25; + if(dc->dbrq) IOB |= F26; + if(dc->inout) IOB |= F27; + IOB |= dc->ch_mode<<6; + IOB |= dc->device<<3; + IOB |= dc->pia; + break; + } + bool s1 = dc->darq && dc->dbda_move; + if(s1 && !s0) + dbda_swap(dc); + calc_dc_req(pdp, dc); +} + +static Dc136 dc; +static IOdev dc_dev = { 0, 0200, &dc, handle_dc, nil }; + +static void +calc_dc_req(PDP6 *pdp, Dc136 *dc) +{ + setreq(pdp, &dc_dev, dc->pia && dc->dbrq ? 0200>>dc->pia : 0); +} + +Dc136* +attach_dc(PDP6 *pdp) +{ + dc.pdp = pdp; + installdev(pdp, &dc_dev); + + return &dc; +} diff --git a/newemu/dis340.c b/newemu/dis340.c new file mode 100644 index 0000000..3cb9c4e --- /dev/null +++ b/newemu/dis340.c @@ -0,0 +1,632 @@ +#include "common.h" +#include "pdp6.h" + +#include + +enum Modes +{ + PM, + XYM, + SM, + CM, + VM, + VCM, + IM, + SBM +}; + +struct Dis340 +{ + int fd; + + /* 344 interface for PDP-6. + * no schematics unfortunately */ + int pia_data; + int pia_spec; + Word ib; /* interface buffer */ + int ibc; /* number of words in IB */ + + /* 340 display and 342 char gen */ + Hword br; /* 18 bits */ + int mode; /* 3 bits */ + int i; /* intensity - 3 bits */ + int sz; /* scale - 2 bits */ + int brm; /* 7 bits */ + int s; /* shift - 4 bits */ + int x, y; /* 10 bits */ + /* flip flops */ + int stop; + int halt; + int move; + int lp_find; + int lp_flag; + int lp_enable; + int rfd; + int hef, vef; + /* br shifted for IM and CM */ + int pnts; + int chrs; + /* values for BRM counting */ + int brm_add; + int brm_comp; + + int penx, peny; + int pen; + + /* 342 char gen */ + int shift; + int *cp; /* current char pointer */ + + u64 simtime, lasttime; + u64 inputtimer; + int state; + int pnt; + u32 cmdbuf[128]; + u32 ncmds; +}; + +#define LDB(p, s, w) ((w)>>(p) & (1<<(s))-1) +#define IOB pdp->iob +static void calc_dis_req(PDP6 *pdp, Dis340 *dis); + + +static void +addcmd(Dis340 *dis, u32 cmd) +{ + dis->cmdbuf[dis->ncmds++] = cmd; + if(dis->ncmds == nelem(dis->cmdbuf)) { + if(write(dis->fd, dis->cmdbuf, sizeof(dis->cmdbuf)) < sizeof(dis->cmdbuf)) + dis->fd = -1; + dis->ncmds = 0; + } +} + +static void +agedisplay(Dis340 *dis) +{ + if(dis->fd < 0) + return; + u32 cmd = 511<<23; + assert(dis->lasttime <= dis->simtime); + u64 dt = (dis->simtime - dis->lasttime)/1000; + while(dt >= 511) { + dis->lasttime += 511*1000; + addcmd(dis, cmd); + dt = (dis->simtime - dis->lasttime)/1000; + } +} + +static void +intensify(Dis340 *dis) +{ + if(dis->pen && dis->lp_enable) { + int dx = dis->penx - dis->x; + int dy = dis->peny - dis->y; + if(dx*dx + dy*dy <= 4) + dis->lp_find = 1; + } + if(dis->fd >= 0){ + agedisplay(dis); + u32 cmd; + cmd = dis->x; + cmd |= dis->y<<10; + cmd |= dis->i<<20; + int dt = (dis->simtime - dis->lasttime)/1000; + cmd |= dt<<23; + dis->lasttime = dis->simtime; + addcmd(dis, cmd); + } +} + +enum { + ST_IDLE, + ST_DATA_SYNC, + ST_READ_TO_S, + ST_DLY_IDP, + ST_IDP, + ST_XY_INTENSIFY, + ST_SEQ_DLY, + ST_CHAR, + ST_CHAR_INT, + ST_RFD, +}; + + +static void +rfd(Dis340 *dis) +{ + dis->rfd = 1; + dis->hef = 0; + dis->vef = 0; +} + +static void +escape(Dis340 *dis) +{ + dis->mode = 0; + dis->lp_find = 0; +} + +static void +initiate(Dis340 *dis) +{ + dis->shift = 0; + + dis->lp_enable = 0; // TODO: not in schematics? + dis->lp_find = 0; + dis->lp_flag = 0; + dis->stop = 0; + escape(dis); + + dis->state = ST_RFD; +} + +static void +resume(Dis340 *dis) +{ + dis->lp_enable = 0; + dis->lp_find = 0; + dis->lp_flag = 0; + if(dis->mode != CM) { + dis->simtime += 1000; + dis->state = ST_SEQ_DLY; + } +} + +/* figure out add and complement values for COUNT BRM */ +static void +initbrm(Dis340 *dis) +{ + int m; + int dx, dy, d; + + dis->brm_add = 1; + + dx = LDB(0, 7, dis->br); + dy = LDB(8, 7, dis->br); + d = dx > dy ? dx : dy; + for(m = 0100; m > 040; m >>= 1) + if(d & m) + break; + else + dis->brm_add *= 2; + dis->brm_comp = dis->brm_add - 1; +} + +static void +read_to_mode(Dis340 *dis) +{ + dis->mode = LDB(13, 3, dis->br); + if(dis->br & 0010000) + dis->lp_enable = !!(dis->br & 04000); +} + +static void +shift_s(Dis340 *dis) +{ + dis->s >>= 1; + dis->pnts <<= 4; + dis->chrs <<= 6; +} + +static void +count_brm(Dis340 *dis) +{ + dis->brm = ((dis->brm+dis->brm_add) ^ dis->brm_comp) & 0177; + shift_s(dis); +} + +static void +count_x(Dis340 *dis, int s, int r, int l) +{ + if(r) dis->x += s; + if(l) dis->x -= s; + if(r || l) dis->move = dis->mode != CM; + if(dis->x >= 1024 || dis->x < 0) dis->hef = 1; + dis->x &= 01777; + if(dis->mode == IM && dis->s&1) + dis->halt = 1; +} + +static void +count_y(Dis340 *dis, int s, int u, int d) +{ + if(u) dis->y += s; + if(d) dis->y -= s; + if(u || d) dis->move = dis->mode != CM; // actually in count_x + if(dis->y >= 1024 || dis->y < 0) dis->vef = 1; + dis->y &= 01777; + dis->lp_flag |= dis->lp_find && dis->lp_enable; +} + +static void +getdir(int brm, int xy, int c, int *pos, int *neg) +{ + int dir; + int foo; + + foo = ~brm & c; + dir = foo&0001 && xy&0100 || + foo&0002 && xy&0040 || + foo&0004 && xy&0020 || + foo&0010 && xy&0010 || + foo&0020 && xy&0004 || + foo&0040 && xy&0002 || + foo&0100 && xy&0001; + *pos = 0; + *neg = 0; + if(dir){ + if(xy & 0200) + *neg = 1; + else + *pos = 1; + } +} + +#include "chargen.inc" + +static void +cycle_dis(PDP6 *pdp, IOdev *dev, int pwr) +{ + Dis340 *dis = (Dis340*)dev->dev; + int halt, pnt, r, l, u, d, c, brm; + + if(!pwr) { + dis->simtime = simtime; + agedisplay(dis); + return; + } + + agedisplay(dis); + if(dis->inputtimer < simtime) { + dis->inputtimer = simtime + 30000000; + if(hasinput(dis->fd)) { + u32 cmds[512]; + int n = read(dis->fd, cmds, sizeof(cmds)); + n /= 4; + for(int i = 0; i < n; i++) { + u32 cmd = cmds[i]; + dis->peny = cmd & 01777; + dis->penx = (cmd>>10) & 01777; + dis->pen = (cmd>>20) & 1; + } + } + } + + int doreq = 0; + // catch up with CPU + while(dis->simtime < simtime) { + doreq = 1; + switch(dis->state) { + case ST_IDLE: + if(dis->rfd && dis->ibc > 0) + dis->state = ST_DATA_SYNC; + else + dis->simtime = simtime; + break; + + case ST_DATA_SYNC: + // CLR BR + dis->br = 0; + dis->rfd = 0; + + // CLR BRM + dis->brm = 0; + dis->halt = 0; + dis->move = 0; + dis->s = 0; // CLEAR S + dis->hef = 0; // CLR CF + dis->vef = 0; // CLR CF + + dis->simtime += 2800; + dis->state = ST_READ_TO_S; + break; + + case ST_READ_TO_S: + // READ TO S + dis->lp_flag |= dis->lp_find && dis->lp_enable; + if(dis->mode == IM) dis->s |= 010; + if(dis->mode == CM) dis->s |= 004; + + // LOAD BR + dis->br |= dis->ib>>18 & RT; + dis->pnts = dis->br; + dis->chrs = dis->br; + initbrm(dis); + + // SHIFT IB + dis->ib = dis->ib<<18 & LT; + dis->ibc--; + + dis->state = ST_DLY_IDP; + break; + + case ST_DLY_IDP: + if(dis->move && dis->br&0200000) + intensify(dis); + dis->simtime += 500; + dis->state = ST_IDP; + break; + case ST_IDP: + dis->state = ST_IDLE; + switch(dis->mode) { + case PM: + // TODO: what is RI? + read_to_mode(dis); + /* PM PULSE */ + if(dis->br & 010) dis->i = LDB(0, 3, dis->br); + if(dis->br & 0100) dis->sz = LDB(4, 2, dis->br); + if(dis->br & 02000) dis->stop = 1; + else dis->state = ST_RFD; + break; + + case XYM: + if(dis->lp_flag) + break; + if(dis->br & 0200000){ + // Y START + read_to_mode(dis); + dis->y = 0; // CLEAR Y + dis->simtime += 200; + dis->y |= dis->br & 01777; // LOAD Y + if(dis->br & 0002000) + dis->simtime += 35000; + }else{ + // X START + read_to_mode(dis); + dis->simtime += 35000; + dis->x = 0; // CLEAR X + // 200ns parallel to above dly + dis->x |= dis->br & 01777; // LOAD X + } + dis->state = ST_XY_INTENSIFY; + break; + + case IM: + halt = dis->halt; + count_brm(dis); + pnt = LDB(16, 4, dis->pnts); + r = (pnt & 014) == 010; + l = (pnt & 014) == 014; + u = (pnt & 003) == 002; + d = (pnt & 003) == 003; + goto count_xy; + + case VM: + case VCM: + halt = dis->halt; + brm = dis->brm; + count_brm(dis); + /* actually the complement inputs to COUNT BRM + * but it's easier to find them out after the addition. */ + c = dis->brm^brm; + getdir(brm, LDB(0, 8, dis->br), c, &r, &l); + getdir(brm, LDB(8, 8, dis->br), c, &u, &d); + +count_xy: + count_y(dis, 1<sz, u, d); + count_x(dis, 1<sz, r, l); + if(halt) { + /* at COUNT X */ + if(dis->br & 0400000) + escape(dis); + dis->state = ST_RFD; + } else { + // dly started by COUNT BRM + dis->simtime += 1000; + dis->state = ST_SEQ_DLY; + } + break; + + case CM: + /* Tell CG to start */ + dis->cp = chars[LDB(12, 6, dis->chrs) + dis->shift]; + dis->state = ST_CHAR; + break; + } + break; + + case ST_CHAR: + pnt = dis->pnt = *dis->cp++; + if(pnt == 0) { +end: + /* end of character */ + if(dis->s & 1) + dis->state = ST_RFD; + else { + shift_s(dis); + dis->state = ST_DLY_IDP; + } + break; + } + if(pnt & 040) { + /* escape from char */ + escape(dis); + dis->state = ST_RFD; + break; + } + if(pnt & 0100) { + /* carriage return */ + dis->x = 0; + goto end; // maybe? + } + if(pnt & 0200) { + /* shift in */ + dis->shift = 0; + goto end; + } + if(pnt & 0400) { + /* shift out */ + dis->shift = 64; + goto end; + } + /* cg count */ + r = (pnt & 014) == 010; + l = (pnt & 014) == 014; + u = (pnt & 003) == 002; + d = (pnt & 003) == 003; + count_y(dis, 1<sz, u, d); + count_x(dis, 1<sz, r, l); + dis->simtime += 1000; + dis->state = ST_CHAR_INT; + break; + + case ST_CHAR_INT: + if(dis->pnt & 020) + intensify(dis); + dis->simtime += 500; + dis->state = ST_CHAR; + break; + + case ST_SEQ_DLY: + dis->state = ST_IDLE; + if(dis->mode == VM && dis->brm == 0177) + dis->halt = 1; + if(dis->hef || dis->vef){ + escape(dis); + if(dis->mode == VCM) + dis->state = ST_RFD; + }else if(!dis->rfd && !dis->lp_flag) + dis->state = ST_DLY_IDP; + break; + + case ST_XY_INTENSIFY: + if(dis->br & 0002000) + intensify(dis); + dis->simtime += 500; + dis->state = ST_RFD; + break; + + case ST_RFD: + rfd(dis); + dis->state = ST_IDLE; + break; + } + } + + // could be more efficient with this + if(doreq) calc_dis_req(pdp, dis); +} + +static void +handle_dis(PDP6 *pdp, IOdev *dev, int cmd) +{ + Dis340 *dis = (Dis340*)dev->dev; + + switch(cmd) { + case IOB_RESET: + dis->pia_data = 0; + dis->pia_spec = 0; + + dis->ib = 0; + dis->ibc = 0; + + initiate(dis); + break; + + case IOB_CONO_CLR: + dis->pia_data = 0; + dis->pia_spec = 0; + return; + case IOB_CONO_SET: +// TODO: according to .INFO.;340 INFO more stuff: +// 24 clear no ink mode +// 25 set no ink mode +// 26 clear half word mode +// 27 set half word mode +// 28 resume display + dis->pia_data |= IOB & 7; + dis->pia_spec |= IOB>>3 & 7; + + if(IOB & F29) + initiate(dis); + else + resume(dis); // not sure about this + break; + + case IOB_DATAO_CLR: + dis->ib = 0; + dis->ibc = 0; + return; + case IOB_DATAO_SET: + dis->ib |= IOB; + dis->ibc = 2; + break; + + case IOB_STATUS: +#if 0 +// like this in the manual + if(dis->lp_flag) IOB |= F25; + if(dis->hef || dis->vef) IOB |= F26; +#else +// according to .INFO.;340 INFO + IOB |= dis->mode<<15; + // VECT CONT LP?? + if(dis->vef) IOB |= F24; + if(dis->lp_flag) IOB |= F25; + if(dis->hef) IOB |= F26; +#endif + if(dis->stop && dis->br&01000) IOB |= F27; + if(dis->ibc == 0 && dis->rfd) IOB |= F28; + IOB |= (dis->pia_spec & 7) << 3; + IOB |= dis->pia_data & 7; + return; + + case IOB_DATAI: + IOB |= dis->x; + IOB |= dis->y << 18; + return; + + } + calc_dis_req(pdp, dis); +} + +static Dis340 dis; +static IOdev dis_dev = { 0, 0130, &dis, handle_dis, cycle_dis }; + +static void +calc_dis_req(PDP6 *pdp, Dis340 *dis) +{ + int data, spec; + u8 req_data, req_spec; + + data = dis->ibc == 0 && dis->rfd; + spec = dis->lp_flag || + dis->hef || dis->vef || + dis->stop && dis->br&01000; + req_data = data ? 0200 >> dis->pia_data : 0; + req_spec = spec ? 0200 >> dis->pia_spec : 0; + + setreq(pdp, &dis_dev, req_data | req_spec); +} + +// stub +static void +handle_joy(PDP6 *pdp, IOdev *dev, int cmd) +{ + switch(cmd) { + case IOB_DATAI: + IOB |= FW; + break; + } +} +static IOdev joy_dev = { 0, 0420, nil, handle_joy, nil }; + +Dis340* +attach_dis(PDP6 *pdp) +{ + dis.fd = -1; + installdev(pdp, &dis_dev); + + installdev(pdp, &joy_dev); + + return &dis; +} + +void +dis_connect(Dis340 *dis, int fd) +{ + if(dis->fd >= 0) + close(dis->fd); + dis->fd = fd; +} diff --git a/newemu/ge.c b/newemu/ge.c new file mode 100644 index 0000000..2a3d177 --- /dev/null +++ b/newemu/ge.c @@ -0,0 +1,172 @@ +#include "common.h" +#include "pdp6.h" + +#include + +#define IOB pdp->iob + +typedef struct GEcon GEcon; +struct GEcon { + int out_pia; + bool out_ready; + bool out_busy; + u8 out_chr; + u8 out_lp; + int out_port; + int out_state; + u64 out_timer; + + int in_pia; + bool in_ready; + u8 in_chr; +}; + +static void calc_ge_req(PDP6 *pdp, GEcon *ge); + +static void +handle_gtyi(PDP6 *pdp, IOdev *dev, int cmd) +{ + GEcon *ge = (GEcon*)dev->dev; + + switch(cmd) { + case IOB_RESET: + case IOB_CONO_CLR: + ge->in_pia = 0; + ge->in_ready = 0; + break; + case IOB_CONO_SET: + ge->in_pia |= IOB & 7; + break; + case IOB_STATUS: + IOB |= ge->in_pia; + if(ge->in_ready) IOB |= F32; + return; + case IOB_DATAI: + IOB |= ge->in_chr; + ge->in_ready = 0; + break; + } + calc_ge_req(pdp, ge); +} + +static void +handle_gtyo(PDP6 *pdp, IOdev *dev, int cmd) +{ + GEcon *ge = (GEcon*)dev->dev; + + switch(cmd) { + case IOB_RESET: + case IOB_CONO_CLR: + ge->out_pia = 0; + ge->out_ready = 0; + ge->out_busy = 0; + ge->out_chr = 0; + ge->out_state = 0; + break; + case IOB_CONO_SET: + ge->out_pia |= IOB & 7; + // init somehow + if(IOB & F28) { + ge->out_busy = 0; + ge->out_ready = 1; + } + break; + case IOB_DATAO_CLR: + ge->out_chr = 0; + ge->out_ready = 0; + ge->out_busy = 1; + break; + case IOB_DATAO_SET: + ge->out_chr |= (IOB & 0177)^0177; + ge->out_chr = (ge->out_chr<<1 | ge->out_chr>>6) & 0177; + ge->out_lp ^= ge->out_chr; + + ge->out_timer = simtime + 1000000; + break; + case IOB_STATUS: + IOB |= ge->out_pia; + if(ge->out_ready) IOB |= F29; + return; + } + calc_ge_req(pdp, ge); +} + +static void +cycle_ge(PDP6 *pdp, IOdev *dev, int pwr) +{ + GEcon *ge = (GEcon*)dev->dev; + + if(!pwr) { + return; + } + + // TODO: actually connect this to consoles + + if(ge->out_busy && ge->out_timer < simtime) { + switch(ge->out_state) { + case 0: // wait for msg start + if(ge->out_chr == 1) { + ge->out_state = 1; + ge->out_lp = 0; + } + break; + case 1: // read port to write to + if((ge->out_chr & 0147) == 0140) { + ge->out_state = 2; + ge->out_port = (ge->out_chr>>3) & 7; + } else + ge->out_state = 0; + break; + case 2: // read status code (always 0 for us) + if(ge->out_chr == 0) + ge->out_state = 3; + else + ge->out_state = 0; + break; + case 3: // read start of message + if(ge->out_chr == 2) + ge->out_state = 4; + break; + case 4: // the actual message + if(ge->out_chr == 3) + ge->out_state = 5; + else + printf("GE %d: %o\n", ge->out_port, ge->out_chr); + break; + case 5: // checksum + if(ge->out_lp != 0) + printf("GE checksum error %o\n", ge->out_lp); + ge->out_state = 0; + break; + } + ge->out_ready = 1; + ge->out_busy = 0; + calc_ge_req(pdp, ge); + } +} + +static GEcon gecon; +static IOdev gtyi_dev = { 0, 0070, &gecon, handle_gtyi, nil }; +static IOdev gtyo_dev = { 0, 0750, &gecon, handle_gtyo, cycle_ge }; + +static void +calc_ge_req(PDP6 *pdp, GEcon *ge) +{ + int ireq = 0; + if(ge->in_pia && ge->in_ready) + ireq = 0200>>ge->in_pia; + setreq(pdp, >yi_dev, ireq); + + int oreq = 0; + if(ge->out_pia && ge->out_ready) + oreq = 0200>>ge->out_pia; + setreq(pdp, >yo_dev, oreq); + +} + +void +attach_ge(PDP6 *pdp) +{ + installdev(pdp, >yi_dev); + installdev(pdp, >yo_dev); +} diff --git a/newemu/instgen.inc b/newemu/instgen.inc new file mode 100644 index 0000000..261c3f7 --- /dev/null +++ b/newemu/instgen.inc @@ -0,0 +1,5486 @@ +case 0100: goto nop; +case 0101: goto nop; +case 0102: goto nop; +case 0103: goto nop; +case 0104: goto nop; +case 0105: goto nop; +case 0106: goto nop; +case 0107: goto nop; +case 0110: goto nop; +case 0111: goto nop; +case 0112: goto nop; +case 0113: goto nop; +case 0114: goto nop; +case 0115: goto nop; +case 0116: goto nop; +case 0117: goto nop; +case 0120: goto nop; +case 0121: goto nop; +case 0122: goto nop; +case 0123: goto nop; +case 0124: goto nop; +case 0125: goto nop; +case 0126: goto nop; +case 0127: goto nop; +case 0130: goto nop; +case 0131: goto nop; +case 0200: + AR_FM_MB_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + FWT_OV; + goto et10; +case 0201: + MB_FM_AR_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + FWT_OV; + goto et10; +case 0202: + MB_FM_AR_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + FWT_OV; + MB_FM_AR_J; + goto et10; +case 0203: + AR_FM_MB_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + FWT_OV; + MB_FM_AR_J; + goto et10; +case 0204: + AR_FM_MB_J; + P(ET0); + DLY(100); + MB_SWAP; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + P(ET5); + FWT_OV; + goto et10; +case 0205: + MB_FM_AR_J; + P(ET0); + DLY(100); + MB_SWAP; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + P(ET5); + FWT_OV; + goto et10; +case 0206: + MB_FM_AR_J; + P(ET0); + DLY(100); + MB_SWAP; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + P(ET5); + FWT_OV; + MB_FM_AR_J; + goto et10; +case 0207: + AR_FM_MB_J; + P(ET0); + DLY(100); + MB_SWAP; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + P(ET5); + FWT_OV; + MB_FM_AR_J; + goto et10; +case 0210: + AR_FM_MB_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + SBR(AR_NEGATE,et4_ar_pause); + P(ET4); + DLY(100); + P(ET5); + FWT_OV; + goto et10; +case 0211: + MB_FM_AR_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + SBR(AR_NEGATE,et4_ar_pause); + P(ET4); + DLY(100); + P(ET5); + FWT_OV; + goto et10; +case 0212: + MB_FM_AR_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + SBR(AR_NEGATE,et4_ar_pause); + P(ET4); + DLY(100); + P(ET5); + FWT_OV; + MB_FM_AR_J; + goto et10; +case 0213: + AR_FM_MB_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + SBR(AR_NEGATE,et4_ar_pause); + P(ET4); + DLY(100); + P(ET5); + FWT_OV; + MB_FM_AR_J; + goto et10; +case 0214: + AR_FM_MB_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + if(AR_NEG) + SBR(AR_NEGATE,et4_ar_pause); + P(ET4); + DLY(100); + P(ET5); + FWT_OV; + goto et10; +case 0215: + MB_FM_AR_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + if(AR_NEG) + SBR(AR_NEGATE,et4_ar_pause); + P(ET4); + DLY(100); + P(ET5); + FWT_OV; + goto et10; +case 0216: + MB_FM_AR_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + if(AR_NEG) + SBR(AR_NEGATE,et4_ar_pause); + P(ET4); + DLY(100); + P(ET5); + FWT_OV; + MB_FM_AR_J; + goto et10; +case 0217: + AR_FM_MB_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + if(AR_NEG) + SBR(AR_NEGATE,et4_ar_pause); + P(ET4); + DLY(100); + P(ET5); + FWT_OV; + MB_FM_AR_J; + goto et10; + +case 0240: + if(MB&F18) goto neg_240; + SC_FM_MB; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + DLY(100); + P(SHT1); + SBR(SCT_ASHLT,shf1); + P(SHT1A); + goto et10; +neg_240: + SC_FM_MB; + P(ET0); + DLY(100); + P(ET1); + SC_INC; + P(SHT1); + DLY(100); + P(ET3); + DLY(100); + SC_COM; + P(SHT1); + SBR(SCT_ASHRT,shf1); + P(SHT1A); + goto et10; +case 0241: + if(MB&F18) goto neg_241; + SC_FM_MB; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + DLY(100); + P(SHT1); + SBR(SCT_ROTLT,shf1); + P(SHT1A); + goto et10; +neg_241: + SC_FM_MB; + P(ET0); + DLY(100); + P(ET1); + SC_INC; + P(SHT1); + DLY(100); + P(ET3); + DLY(100); + SC_COM; + P(SHT1); + SBR(SCT_ROTRT,shf1); + P(SHT1A); + goto et10; +case 0242: + if(MB&F18) goto neg_242; + SC_FM_MB; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + DLY(100); + P(SHT1); + SBR(SCT_LSHLT,shf1); + P(SHT1A); + goto et10; +neg_242: + SC_FM_MB; + P(ET0); + DLY(100); + P(ET1); + SC_INC; + P(SHT1); + DLY(100); + P(ET3); + DLY(100); + SC_COM; + P(SHT1); + SBR(SCT_LSHRT,shf1); + P(SHT1A); + goto et10; +case 0244: + if(MB&F18) goto neg_244; + SC_FM_MB; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + DLY(100); + P(SHT1); + SBR(SCT_ASHCLT,shf1); + P(SHT1A); + goto et10; +neg_244: + SC_FM_MB; + P(ET0); + DLY(100); + P(ET1); + SC_INC; + P(SHT1); + DLY(100); + P(ET3); + DLY(100); + SC_COM; + P(SHT1); + SBR(SCT_ASHCRT,shf1); + P(SHT1A); + goto et10; +case 0245: + if(MB&F18) goto neg_245; + SC_FM_MB; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + DLY(100); + P(SHT1); + SBR(SCT_ROTCLT,shf1); + P(SHT1A); + goto et10; +neg_245: + SC_FM_MB; + P(ET0); + DLY(100); + P(ET1); + SC_INC; + P(SHT1); + DLY(100); + P(ET3); + DLY(100); + SC_COM; + P(SHT1); + SBR(SCT_ROTCRT,shf1); + P(SHT1A); + goto et10; +case 0246: + if(MB&F18) goto neg_246; + SC_FM_MB; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + DLY(100); + P(SHT1); + SBR(SCT_LSHCLT,shf1); + P(SHT1A); + goto et10; +neg_246: + SC_FM_MB; + P(ET0); + DLY(100); + P(ET1); + SC_INC; + P(SHT1); + DLY(100); + P(ET3); + DLY(100); + SC_COM; + P(SHT1); + SBR(SCT_LSHCRT,shf1); + P(SHT1A); + goto et10; + +case 0270: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + AR_ADD; + P(ET3); + P(ET4); + DLY(100); + P(ET5); + AR_SET_OV_CRY; + goto et10; +case 0271: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + AR_ADD; + P(ET3); + P(ET4); + DLY(100); + P(ET5); + AR_SET_OV_CRY; + goto et10; +case 0272: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + AR_ADD; + P(ET3); + P(ET4); + DLY(100); + P(ET5); + AR_SET_OV_CRY; + MB_FM_AR_J; + goto et10; +case 0273: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + AR_ADD; + P(ET3); + P(ET4); + DLY(100); + P(ET5); + AR_SET_OV_CRY; + MB_FM_AR_J; + goto et10; +case 0274: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + AR_SUB; + P(ET3); + P(ET4); + DLY(100); + P(ET5); + AR_SET_OV_CRY; + goto et10; +case 0275: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + AR_SUB; + P(ET3); + P(ET4); + DLY(100); + P(ET5); + AR_SET_OV_CRY; + goto et10; +case 0276: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + AR_SUB; + P(ET3); + P(ET4); + DLY(100); + P(ET5); + AR_SET_OV_CRY; + MB_FM_AR_J; + goto et10; +case 0277: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + AR_SUB; + P(ET3); + P(ET4); + DLY(100); + P(ET5); + AR_SET_OV_CRY; + MB_FM_AR_J; + goto et10; + +case 0300: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_SUB,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + P(ET9); + DLY(200); + goto et10; +case 0301: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_SUB,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = AR_LESS; + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(test) + SKIP; + P(ET9); + DLY(200); + goto et10; +case 0302: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_SUB,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = AR_ZERO; + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(test) + SKIP; + P(ET9); + DLY(200); + goto et10; +case 0303: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_SUB,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = (AR_LESS || AR_ZERO); + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(test) + SKIP; + P(ET9); + DLY(200); + goto et10; +case 0304: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_SUB,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SKIP; + P(ET9); + DLY(200); + goto et10; +case 0305: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_SUB,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = !AR_LESS; + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(test) + SKIP; + P(ET9); + DLY(200); + goto et10; +case 0306: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_SUB,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = !AR_ZERO; + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(test) + SKIP; + P(ET9); + DLY(200); + goto et10; +case 0307: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_SUB,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = !(AR_LESS || AR_ZERO); + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(test) + SKIP; + P(ET9); + DLY(200); + goto et10; +case 0310: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_SUB,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + P(ET9); + DLY(200); + goto et10; +case 0311: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_SUB,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = AR_LESS; + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(test) + SKIP; + P(ET9); + DLY(200); + goto et10; +case 0312: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_SUB,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = AR_ZERO; + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(test) + SKIP; + P(ET9); + DLY(200); + goto et10; +case 0313: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_SUB,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = (AR_LESS || AR_ZERO); + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(test) + SKIP; + P(ET9); + DLY(200); + goto et10; +case 0314: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_SUB,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SKIP; + P(ET9); + DLY(200); + goto et10; +case 0315: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_SUB,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = !AR_LESS; + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(test) + SKIP; + P(ET9); + DLY(200); + goto et10; +case 0316: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_SUB,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = !AR_ZERO; + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(test) + SKIP; + P(ET9); + DLY(200); + goto et10; +case 0317: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_SUB,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = !(AR_LESS || AR_ZERO); + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(test) + SKIP; + P(ET9); + DLY(200); + goto et10; +case 0320: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + P(ET9); + DLY(200); + AR_SET_OV_CRY; + goto et10; +case 0321: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = AR_NEG; + P(ET6); + DLY(100); + if(test) + PC_CLR; + P(ET7); + DLY(100); + if(test) + PC_FM_MA_1; + P(ET8); + DLY(200); + if(test) + PC_CHG; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + goto et10; +case 0322: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = AR_ZERO; + P(ET6); + DLY(100); + if(test) + PC_CLR; + P(ET7); + DLY(100); + if(test) + PC_FM_MA_1; + P(ET8); + DLY(200); + if(test) + PC_CHG; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + goto et10; +case 0323: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = (AR_NEG || AR_ZERO); + P(ET6); + DLY(100); + if(test) + PC_CLR; + P(ET7); + DLY(100); + if(test) + PC_FM_MA_1; + P(ET8); + DLY(200); + if(test) + PC_CHG; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + goto et10; +case 0324: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + P(ET6); + DLY(100); + PC_CLR; + P(ET7); + DLY(100); + PC_FM_MA_1; + P(ET8); + DLY(200); + PC_CHG; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + goto et10; +case 0325: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = !AR_NEG; + P(ET6); + DLY(100); + if(test) + PC_CLR; + P(ET7); + DLY(100); + if(test) + PC_FM_MA_1; + P(ET8); + DLY(200); + if(test) + PC_CHG; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + goto et10; +case 0326: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = !AR_ZERO; + P(ET6); + DLY(100); + if(test) + PC_CLR; + P(ET7); + DLY(100); + if(test) + PC_FM_MA_1; + P(ET8); + DLY(200); + if(test) + PC_CHG; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + goto et10; +case 0327: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = !(AR_NEG || AR_ZERO); + P(ET6); + DLY(100); + if(test) + PC_CLR; + P(ET7); + DLY(100); + if(test) + PC_FM_MA_1; + P(ET8); + DLY(200); + if(test) + PC_CHG; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + goto et10; +case 0330: + AR_FM_MB_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + P(ET9); + DLY(200); + AR_SET_OV_CRY; + MB_FM_AR_J; + goto et10; +case 0331: + AR_FM_MB_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = AR_NEG; + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(test) + SKIP; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + MB_FM_AR_J; + goto et10; +case 0332: + AR_FM_MB_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = AR_ZERO; + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(test) + SKIP; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + MB_FM_AR_J; + goto et10; +case 0333: + AR_FM_MB_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = (AR_NEG || AR_ZERO); + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(test) + SKIP; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + MB_FM_AR_J; + goto et10; +case 0334: + AR_FM_MB_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SKIP; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + MB_FM_AR_J; + goto et10; +case 0335: + AR_FM_MB_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = !AR_NEG; + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(test) + SKIP; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + MB_FM_AR_J; + goto et10; +case 0336: + AR_FM_MB_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = !AR_ZERO; + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(test) + SKIP; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + MB_FM_AR_J; + goto et10; +case 0337: + AR_FM_MB_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = !(AR_NEG || AR_ZERO); + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(test) + SKIP; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + MB_FM_AR_J; + goto et10; +case 0340: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_INC,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + P(ET9); + DLY(200); + AR_SET_OV_CRY; + goto et10; +case 0341: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_INC,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = AR_NEG; + P(ET6); + DLY(100); + if(test) + PC_CLR; + P(ET7); + DLY(100); + if(test) + PC_FM_MA_1; + P(ET8); + DLY(200); + if(test) + PC_CHG; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + goto et10; +case 0342: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_INC,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = AR_ZERO; + P(ET6); + DLY(100); + if(test) + PC_CLR; + P(ET7); + DLY(100); + if(test) + PC_FM_MA_1; + P(ET8); + DLY(200); + if(test) + PC_CHG; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + goto et10; +case 0343: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_INC,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = (AR_NEG || AR_ZERO); + P(ET6); + DLY(100); + if(test) + PC_CLR; + P(ET7); + DLY(100); + if(test) + PC_FM_MA_1; + P(ET8); + DLY(200); + if(test) + PC_CHG; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + goto et10; +case 0344: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_INC,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + P(ET6); + DLY(100); + PC_CLR; + P(ET7); + DLY(100); + PC_FM_MA_1; + P(ET8); + DLY(200); + PC_CHG; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + goto et10; +case 0345: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_INC,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = !AR_NEG; + P(ET6); + DLY(100); + if(test) + PC_CLR; + P(ET7); + DLY(100); + if(test) + PC_FM_MA_1; + P(ET8); + DLY(200); + if(test) + PC_CHG; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + goto et10; +case 0346: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_INC,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = !AR_ZERO; + P(ET6); + DLY(100); + if(test) + PC_CLR; + P(ET7); + DLY(100); + if(test) + PC_FM_MA_1; + P(ET8); + DLY(200); + if(test) + PC_CHG; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + goto et10; +case 0347: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_INC,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = !(AR_NEG || AR_ZERO); + P(ET6); + DLY(100); + if(test) + PC_CLR; + P(ET7); + DLY(100); + if(test) + PC_FM_MA_1; + P(ET8); + DLY(200); + if(test) + PC_CHG; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + goto et10; +case 0350: + AR_FM_MB_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_INC,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + P(ET9); + DLY(200); + AR_SET_OV_CRY; + MB_FM_AR_J; + goto et10; +case 0351: + AR_FM_MB_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_INC,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = AR_NEG; + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(test) + SKIP; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + MB_FM_AR_J; + goto et10; +case 0352: + AR_FM_MB_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_INC,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = AR_ZERO; + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(test) + SKIP; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + MB_FM_AR_J; + goto et10; +case 0353: + AR_FM_MB_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_INC,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = (AR_NEG || AR_ZERO); + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(test) + SKIP; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + MB_FM_AR_J; + goto et10; +case 0354: + AR_FM_MB_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_INC,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SKIP; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + MB_FM_AR_J; + goto et10; +case 0355: + AR_FM_MB_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_INC,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = !AR_NEG; + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(test) + SKIP; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + MB_FM_AR_J; + goto et10; +case 0356: + AR_FM_MB_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_INC,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = !AR_ZERO; + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(test) + SKIP; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + MB_FM_AR_J; + goto et10; +case 0357: + AR_FM_MB_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_INC,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = !(AR_NEG || AR_ZERO); + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(test) + SKIP; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + MB_FM_AR_J; + goto et10; +case 0360: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_DEC,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + P(ET9); + DLY(200); + AR_SET_OV_CRY; + goto et10; +case 0361: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_DEC,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = AR_NEG; + P(ET6); + DLY(100); + if(test) + PC_CLR; + P(ET7); + DLY(100); + if(test) + PC_FM_MA_1; + P(ET8); + DLY(200); + if(test) + PC_CHG; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + goto et10; +case 0362: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_DEC,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = AR_ZERO; + P(ET6); + DLY(100); + if(test) + PC_CLR; + P(ET7); + DLY(100); + if(test) + PC_FM_MA_1; + P(ET8); + DLY(200); + if(test) + PC_CHG; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + goto et10; +case 0363: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_DEC,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = (AR_NEG || AR_ZERO); + P(ET6); + DLY(100); + if(test) + PC_CLR; + P(ET7); + DLY(100); + if(test) + PC_FM_MA_1; + P(ET8); + DLY(200); + if(test) + PC_CHG; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + goto et10; +case 0364: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_DEC,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + P(ET6); + DLY(100); + PC_CLR; + P(ET7); + DLY(100); + PC_FM_MA_1; + P(ET8); + DLY(200); + PC_CHG; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + goto et10; +case 0365: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_DEC,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = !AR_NEG; + P(ET6); + DLY(100); + if(test) + PC_CLR; + P(ET7); + DLY(100); + if(test) + PC_FM_MA_1; + P(ET8); + DLY(200); + if(test) + PC_CHG; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + goto et10; +case 0366: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_DEC,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = !AR_ZERO; + P(ET6); + DLY(100); + if(test) + PC_CLR; + P(ET7); + DLY(100); + if(test) + PC_FM_MA_1; + P(ET8); + DLY(200); + if(test) + PC_CHG; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + goto et10; +case 0367: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_DEC,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = !(AR_NEG || AR_ZERO); + P(ET6); + DLY(100); + if(test) + PC_CLR; + P(ET7); + DLY(100); + if(test) + PC_FM_MA_1; + P(ET8); + DLY(200); + if(test) + PC_CHG; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + goto et10; +case 0370: + AR_FM_MB_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_DEC,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + P(ET9); + DLY(200); + AR_SET_OV_CRY; + MB_FM_AR_J; + goto et10; +case 0371: + AR_FM_MB_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_DEC,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = AR_NEG; + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(test) + SKIP; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + MB_FM_AR_J; + goto et10; +case 0372: + AR_FM_MB_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_DEC,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = AR_ZERO; + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(test) + SKIP; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + MB_FM_AR_J; + goto et10; +case 0373: + AR_FM_MB_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_DEC,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = (AR_NEG || AR_ZERO); + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(test) + SKIP; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + MB_FM_AR_J; + goto et10; +case 0374: + AR_FM_MB_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_DEC,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SKIP; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + MB_FM_AR_J; + goto et10; +case 0375: + AR_FM_MB_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_DEC,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = !AR_NEG; + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(test) + SKIP; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + MB_FM_AR_J; + goto et10; +case 0376: + AR_FM_MB_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_DEC,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = !AR_ZERO; + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(test) + SKIP; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + MB_FM_AR_J; + goto et10; +case 0377: + AR_FM_MB_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + SBR(AR_DEC,et4_ar_pause); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + test = !(AR_NEG || AR_ZERO); + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(test) + SKIP; + P(ET9); + DLY(200); + AR_SET_OV_CRY; + MB_FM_AR_J; + goto et10; + +case 0400: + AR_CLR; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0401: + AR_CLR; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0402: + AR_CLR; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0403: + AR_CLR; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0404: + P(ET0); + DLY(100); + AR_FM_MB_0; + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0405: + P(ET0); + DLY(100); + AR_FM_MB_0; + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0406: + P(ET0); + DLY(100); + AR_FM_MB_0; + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0407: + P(ET0); + DLY(100); + AR_FM_MB_0; + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0410: + AR_COM; + P(ET0); + DLY(100); + AR_FM_MB_0; + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0411: + AR_COM; + P(ET0); + DLY(100); + AR_FM_MB_0; + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0412: + AR_COM; + P(ET0); + DLY(100); + AR_FM_MB_0; + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0413: + AR_COM; + P(ET0); + DLY(100); + AR_FM_MB_0; + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0414: + AR_CLR; + P(ET0); + DLY(100); + AR_FM_MB_1; + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0415: + AR_CLR; + P(ET0); + DLY(100); + AR_FM_MB_1; + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0416: + AR_CLR; + P(ET0); + DLY(100); + AR_FM_MB_1; + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0417: + AR_CLR; + P(ET0); + DLY(100); + AR_FM_MB_1; + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0420: + AR_COM; + P(ET0); + DLY(100); + AR_FM_MB_1; + P(ET1); + DLY(100); + P(ET3); + AR_COM; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0421: + AR_COM; + P(ET0); + DLY(100); + AR_FM_MB_1; + P(ET1); + DLY(100); + P(ET3); + AR_COM; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0422: + AR_COM; + P(ET0); + DLY(100); + AR_FM_MB_1; + P(ET1); + DLY(100); + P(ET3); + AR_COM; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0423: + AR_COM; + P(ET0); + DLY(100); + AR_FM_MB_1; + P(ET1); + DLY(100); + P(ET3); + AR_COM; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0424: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0425: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0426: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0427: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0430: + P(ET0); + DLY(100); + AR_FM_MB_C; + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0431: + P(ET0); + DLY(100); + AR_FM_MB_C; + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0432: + P(ET0); + DLY(100); + AR_FM_MB_C; + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0433: + P(ET0); + DLY(100); + AR_FM_MB_C; + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0434: + P(ET0); + DLY(100); + AR_FM_MB_1; + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0435: + P(ET0); + DLY(100); + AR_FM_MB_1; + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0436: + P(ET0); + DLY(100); + AR_FM_MB_1; + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0437: + P(ET0); + DLY(100); + AR_FM_MB_1; + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0440: + P(ET0); + DLY(100); + AR_FM_MB_1; + P(ET1); + DLY(100); + P(ET3); + AR_COM; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0441: + P(ET0); + DLY(100); + AR_FM_MB_1; + P(ET1); + DLY(100); + P(ET3); + AR_COM; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0442: + P(ET0); + DLY(100); + AR_FM_MB_1; + P(ET1); + DLY(100); + P(ET3); + AR_COM; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0443: + P(ET0); + DLY(100); + AR_FM_MB_1; + P(ET1); + DLY(100); + P(ET3); + AR_COM; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0444: + P(ET0); + DLY(100); + AR_FM_MB_C; + P(ET1); + DLY(100); + P(ET3); + AR_COM; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0445: + P(ET0); + DLY(100); + AR_FM_MB_C; + P(ET1); + DLY(100); + P(ET3); + AR_COM; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0446: + P(ET0); + DLY(100); + AR_FM_MB_C; + P(ET1); + DLY(100); + P(ET3); + AR_COM; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0447: + P(ET0); + DLY(100); + AR_FM_MB_C; + P(ET1); + DLY(100); + P(ET3); + AR_COM; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0450: + AR_COM; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0451: + AR_COM; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0452: + AR_COM; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0453: + AR_COM; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0454: + AR_COM; + P(ET0); + DLY(100); + AR_FM_MB_1; + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0455: + AR_COM; + P(ET0); + DLY(100); + AR_FM_MB_1; + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0456: + AR_COM; + P(ET0); + DLY(100); + AR_FM_MB_1; + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0457: + AR_COM; + P(ET0); + DLY(100); + AR_FM_MB_1; + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0460: + AR_CLR; + P(ET0); + DLY(100); + AR_FM_MB_C; + P(ET1); + DLY(100); + P(ET3); + AR_COM; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0461: + AR_CLR; + P(ET0); + DLY(100); + AR_FM_MB_C; + P(ET1); + DLY(100); + P(ET3); + AR_COM; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0462: + AR_CLR; + P(ET0); + DLY(100); + AR_FM_MB_C; + P(ET1); + DLY(100); + P(ET3); + AR_COM; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0463: + AR_CLR; + P(ET0); + DLY(100); + AR_FM_MB_C; + P(ET1); + DLY(100); + P(ET3); + AR_COM; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0464: + AR_COM; + P(ET0); + DLY(100); + AR_FM_MB_0; + P(ET1); + DLY(100); + P(ET3); + AR_COM; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0465: + AR_COM; + P(ET0); + DLY(100); + AR_FM_MB_0; + P(ET1); + DLY(100); + P(ET3); + AR_COM; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0466: + AR_COM; + P(ET0); + DLY(100); + AR_FM_MB_0; + P(ET1); + DLY(100); + P(ET3); + AR_COM; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0467: + AR_COM; + P(ET0); + DLY(100); + AR_FM_MB_0; + P(ET1); + DLY(100); + P(ET3); + AR_COM; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0470: + P(ET0); + DLY(100); + AR_FM_MB_0; + P(ET1); + DLY(100); + P(ET3); + AR_COM; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0471: + P(ET0); + DLY(100); + AR_FM_MB_0; + P(ET1); + DLY(100); + P(ET3); + AR_COM; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0472: + P(ET0); + DLY(100); + AR_FM_MB_0; + P(ET1); + DLY(100); + P(ET3); + AR_COM; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0473: + P(ET0); + DLY(100); + AR_FM_MB_0; + P(ET1); + DLY(100); + P(ET3); + AR_COM; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0474: + AR_CLR; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + AR_COM; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0475: + AR_CLR; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + AR_COM; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0476: + AR_CLR; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + AR_COM; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0477: + AR_CLR; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + AR_COM; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; + +case 0500: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBLT_J; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0501: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBLT_J; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0502: + SWAP_MB_AR; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBLT_J; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0503: + AR_FM_MB_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBLT_J; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0504: + P(ET0); + DLY(100); + MB_SWAP; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBLT_J; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0505: + P(ET0); + DLY(100); + MB_SWAP; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBLT_J; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0506: + SWAP_MB_AR; + P(ET0); + DLY(100); + MB_SWAP; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBLT_J; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0507: + AR_FM_MB_J; + P(ET0); + DLY(100); + MB_SWAP; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBLT_J; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0510: + P(ET0); + DLY(100); + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBLT_J; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0511: + P(ET0); + DLY(100); + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBLT_J; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0512: + SWAP_MB_AR; + P(ET0); + DLY(100); + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBLT_J; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0513: + AR_FM_MB_J; + P(ET0); + DLY(100); + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBLT_J; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0514: + P(ET0); + DLY(100); + MB_SWAP; + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBLT_J; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0515: + P(ET0); + DLY(100); + MB_SWAP; + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBLT_J; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0516: + SWAP_MB_AR; + P(ET0); + DLY(100); + MB_SWAP; + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBLT_J; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0517: + AR_FM_MB_J; + P(ET0); + DLY(100); + MB_SWAP; + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBLT_J; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0520: + P(ET0); + DLY(100); + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBLT_J; + ARRT_COM; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0521: + P(ET0); + DLY(100); + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBLT_J; + ARRT_COM; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0522: + SWAP_MB_AR; + P(ET0); + DLY(100); + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBLT_J; + ARRT_COM; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0523: + AR_FM_MB_J; + P(ET0); + DLY(100); + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBLT_J; + ARRT_COM; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0524: + P(ET0); + DLY(100); + MB_SWAP; + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBLT_J; + ARRT_COM; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0525: + P(ET0); + DLY(100); + MB_SWAP; + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBLT_J; + ARRT_COM; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0526: + SWAP_MB_AR; + P(ET0); + DLY(100); + MB_SWAP; + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBLT_J; + ARRT_COM; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0527: + AR_FM_MB_J; + P(ET0); + DLY(100); + MB_SWAP; + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBLT_J; + ARRT_COM; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0530: + P(ET0); + DLY(100); + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBLT_J; + if(MB&F0) + ARRT_COM; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0531: + P(ET0); + DLY(100); + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBLT_J; + if(MB&F0) + ARRT_COM; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0532: + SWAP_MB_AR; + P(ET0); + DLY(100); + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBLT_J; + if(MB&F0) + ARRT_COM; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0533: + AR_FM_MB_J; + P(ET0); + DLY(100); + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBLT_J; + if(MB&F0) + ARRT_COM; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0534: + P(ET0); + DLY(100); + MB_SWAP; + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBLT_J; + if(MB&F0) + ARRT_COM; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0535: + P(ET0); + DLY(100); + MB_SWAP; + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBLT_J; + if(MB&F0) + ARRT_COM; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0536: + SWAP_MB_AR; + P(ET0); + DLY(100); + MB_SWAP; + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBLT_J; + if(MB&F0) + ARRT_COM; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0537: + AR_FM_MB_J; + P(ET0); + DLY(100); + MB_SWAP; + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBLT_J; + if(MB&F0) + ARRT_COM; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0540: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBRT_J; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0541: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBRT_J; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0542: + SWAP_MB_AR; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBRT_J; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0543: + AR_FM_MB_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBRT_J; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0544: + P(ET0); + DLY(100); + MB_SWAP; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBRT_J; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0545: + P(ET0); + DLY(100); + MB_SWAP; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBRT_J; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0546: + SWAP_MB_AR; + P(ET0); + DLY(100); + MB_SWAP; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBRT_J; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0547: + AR_FM_MB_J; + P(ET0); + DLY(100); + MB_SWAP; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBRT_J; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0550: + P(ET0); + DLY(100); + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBRT_J; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0551: + P(ET0); + DLY(100); + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBRT_J; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0552: + SWAP_MB_AR; + P(ET0); + DLY(100); + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBRT_J; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0553: + AR_FM_MB_J; + P(ET0); + DLY(100); + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBRT_J; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0554: + P(ET0); + DLY(100); + MB_SWAP; + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBRT_J; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0555: + P(ET0); + DLY(100); + MB_SWAP; + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBRT_J; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0556: + SWAP_MB_AR; + P(ET0); + DLY(100); + MB_SWAP; + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBRT_J; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0557: + AR_FM_MB_J; + P(ET0); + DLY(100); + MB_SWAP; + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBRT_J; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0560: + P(ET0); + DLY(100); + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBRT_J; + ARLT_COM; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0561: + P(ET0); + DLY(100); + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBRT_J; + ARLT_COM; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0562: + SWAP_MB_AR; + P(ET0); + DLY(100); + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBRT_J; + ARLT_COM; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0563: + AR_FM_MB_J; + P(ET0); + DLY(100); + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBRT_J; + ARLT_COM; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0564: + P(ET0); + DLY(100); + MB_SWAP; + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBRT_J; + ARLT_COM; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0565: + P(ET0); + DLY(100); + MB_SWAP; + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBRT_J; + ARLT_COM; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0566: + SWAP_MB_AR; + P(ET0); + DLY(100); + MB_SWAP; + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBRT_J; + ARLT_COM; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0567: + AR_FM_MB_J; + P(ET0); + DLY(100); + MB_SWAP; + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBRT_J; + ARLT_COM; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0570: + P(ET0); + DLY(100); + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBRT_J; + if(MB&F18) + ARLT_COM; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0571: + P(ET0); + DLY(100); + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBRT_J; + if(MB&F18) + ARLT_COM; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0572: + SWAP_MB_AR; + P(ET0); + DLY(100); + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBRT_J; + if(MB&F18) + ARLT_COM; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0573: + AR_FM_MB_J; + P(ET0); + DLY(100); + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBRT_J; + if(MB&F18) + ARLT_COM; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0574: + P(ET0); + DLY(100); + MB_SWAP; + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBRT_J; + if(MB&F18) + ARLT_COM; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0575: + P(ET0); + DLY(100); + MB_SWAP; + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBRT_J; + if(MB&F18) + ARLT_COM; + P(ET4); + DLY(100); + P(ET5); + goto et10; +case 0576: + SWAP_MB_AR; + P(ET0); + DLY(100); + MB_SWAP; + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBRT_J; + if(MB&F18) + ARLT_COM; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; +case 0577: + AR_FM_MB_J; + P(ET0); + DLY(100); + MB_SWAP; + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBRT_J; + if(MB&F18) + ARLT_COM; + P(ET4); + DLY(100); + P(ET5); + MB_FM_AR_J; + goto et10; + +case 0600: + P(ET0); + DLY(100); + MB_FM_AR_0; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SWAP_MB_AR; + P(ET9); + DLY(200); + goto et10; +case 0601: + MB_SWAP; + P(ET0); + DLY(100); + MB_FM_AR_0; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SWAP_MB_AR; + P(ET9); + DLY(200); + goto et10; +case 0602: + P(ET0); + DLY(100); + MB_FM_AR_0; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(AR_ZERO) + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + MB_FM_AR_J; + goto et10; +case 0603: + MB_SWAP; + P(ET0); + DLY(100); + MB_FM_AR_0; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(AR_ZERO) + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + MB_FM_AR_J; + goto et10; +case 0604: + P(ET0); + DLY(100); + MB_FM_AR_0; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + goto et10; +case 0605: + MB_SWAP; + P(ET0); + DLY(100); + MB_FM_AR_0; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + goto et10; +case 0606: + P(ET0); + DLY(100); + MB_FM_AR_0; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(!AR_ZERO) + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + MB_FM_AR_J; + goto et10; +case 0607: + MB_SWAP; + P(ET0); + DLY(100); + MB_FM_AR_0; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(!AR_ZERO) + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + MB_FM_AR_J; + goto et10; +case 0610: + P(ET0); + DLY(100); + MB_FM_AR_0; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SWAP_MB_AR; + P(ET9); + DLY(200); + goto et10; +case 0611: + MB_SWAP; + P(ET0); + DLY(100); + MB_FM_AR_0; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SWAP_MB_AR; + P(ET9); + DLY(200); + goto et10; +case 0612: + P(ET0); + DLY(100); + MB_FM_AR_0; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(AR_ZERO) + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + MB_FM_AR_J; + goto et10; +case 0613: + MB_SWAP; + P(ET0); + DLY(100); + MB_FM_AR_0; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(AR_ZERO) + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + MB_FM_AR_J; + goto et10; +case 0614: + P(ET0); + DLY(100); + MB_FM_AR_0; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + goto et10; +case 0615: + MB_SWAP; + P(ET0); + DLY(100); + MB_FM_AR_0; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + goto et10; +case 0616: + P(ET0); + DLY(100); + MB_FM_AR_0; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(!AR_ZERO) + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + MB_FM_AR_J; + goto et10; +case 0617: + MB_SWAP; + P(ET0); + DLY(100); + MB_FM_AR_0; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(!AR_ZERO) + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + MB_FM_AR_J; + goto et10; +case 0620: + P(ET0); + DLY(100); + MB_FM_AR_0; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + MB_FM_AR_0; + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SWAP_MB_AR; + P(ET9); + DLY(200); + goto et10; +case 0621: + MB_SWAP; + P(ET0); + DLY(100); + MB_FM_AR_0; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + MB_FM_AR_0; + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SWAP_MB_AR; + P(ET9); + DLY(200); + goto et10; +case 0622: + P(ET0); + DLY(100); + MB_FM_AR_0; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + MB_FM_AR_0; + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(AR_ZERO) + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + MB_FM_AR_J; + goto et10; +case 0623: + MB_SWAP; + P(ET0); + DLY(100); + MB_FM_AR_0; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + MB_FM_AR_0; + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(AR_ZERO) + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + MB_FM_AR_J; + goto et10; +case 0624: + P(ET0); + DLY(100); + MB_FM_AR_0; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + MB_FM_AR_0; + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + goto et10; +case 0625: + MB_SWAP; + P(ET0); + DLY(100); + MB_FM_AR_0; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + MB_FM_AR_0; + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + goto et10; +case 0626: + P(ET0); + DLY(100); + MB_FM_AR_0; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + MB_FM_AR_0; + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(!AR_ZERO) + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + MB_FM_AR_J; + goto et10; +case 0627: + MB_SWAP; + P(ET0); + DLY(100); + MB_FM_AR_0; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + MB_FM_AR_0; + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(!AR_ZERO) + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + MB_FM_AR_J; + goto et10; +case 0630: + P(ET0); + DLY(100); + MB_FM_AR_0; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + MB_FM_AR_0; + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SWAP_MB_AR; + P(ET9); + DLY(200); + goto et10; +case 0631: + MB_SWAP; + P(ET0); + DLY(100); + MB_FM_AR_0; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + MB_FM_AR_0; + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SWAP_MB_AR; + P(ET9); + DLY(200); + goto et10; +case 0632: + P(ET0); + DLY(100); + MB_FM_AR_0; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + MB_FM_AR_0; + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(AR_ZERO) + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + MB_FM_AR_J; + goto et10; +case 0633: + MB_SWAP; + P(ET0); + DLY(100); + MB_FM_AR_0; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + MB_FM_AR_0; + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(AR_ZERO) + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + MB_FM_AR_J; + goto et10; +case 0634: + P(ET0); + DLY(100); + MB_FM_AR_0; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + MB_FM_AR_0; + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + goto et10; +case 0635: + MB_SWAP; + P(ET0); + DLY(100); + MB_FM_AR_0; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + MB_FM_AR_0; + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + goto et10; +case 0636: + P(ET0); + DLY(100); + MB_FM_AR_0; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + MB_FM_AR_0; + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(!AR_ZERO) + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + MB_FM_AR_J; + goto et10; +case 0637: + MB_SWAP; + P(ET0); + DLY(100); + MB_FM_AR_0; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + MB_FM_AR_0; + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(!AR_ZERO) + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + MB_FM_AR_J; + goto et10; +case 0640: + P(ET0); + DLY(100); + ACBM_COM; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SWAP_MB_AR; + P(ET9); + DLY(200); + goto et10; +case 0641: + MB_SWAP; + P(ET0); + DLY(100); + ACBM_COM; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SWAP_MB_AR; + P(ET9); + DLY(200); + goto et10; +case 0642: + P(ET0); + DLY(100); + ACBM_COM; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(AR_ZERO) + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + MB_FM_AR_J; + goto et10; +case 0643: + MB_SWAP; + P(ET0); + DLY(100); + ACBM_COM; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(AR_ZERO) + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + MB_FM_AR_J; + goto et10; +case 0644: + P(ET0); + DLY(100); + ACBM_COM; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + goto et10; +case 0645: + MB_SWAP; + P(ET0); + DLY(100); + ACBM_COM; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + goto et10; +case 0646: + P(ET0); + DLY(100); + ACBM_COM; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(!AR_ZERO) + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + MB_FM_AR_J; + goto et10; +case 0647: + MB_SWAP; + P(ET0); + DLY(100); + ACBM_COM; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(!AR_ZERO) + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + MB_FM_AR_J; + goto et10; +case 0650: + P(ET0); + DLY(100); + ACBM_COM; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SWAP_MB_AR; + P(ET9); + DLY(200); + goto et10; +case 0651: + MB_SWAP; + P(ET0); + DLY(100); + ACBM_COM; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SWAP_MB_AR; + P(ET9); + DLY(200); + goto et10; +case 0652: + P(ET0); + DLY(100); + ACBM_COM; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(AR_ZERO) + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + MB_FM_AR_J; + goto et10; +case 0653: + MB_SWAP; + P(ET0); + DLY(100); + ACBM_COM; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(AR_ZERO) + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + MB_FM_AR_J; + goto et10; +case 0654: + P(ET0); + DLY(100); + ACBM_COM; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + goto et10; +case 0655: + MB_SWAP; + P(ET0); + DLY(100); + ACBM_COM; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + goto et10; +case 0656: + P(ET0); + DLY(100); + ACBM_COM; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(!AR_ZERO) + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + MB_FM_AR_J; + goto et10; +case 0657: + MB_SWAP; + P(ET0); + DLY(100); + ACBM_COM; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(!AR_ZERO) + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + MB_FM_AR_J; + goto et10; +case 0660: + P(ET0); + DLY(100); + ACBM_SET; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SWAP_MB_AR; + P(ET9); + DLY(200); + goto et10; +case 0661: + MB_SWAP; + P(ET0); + DLY(100); + ACBM_SET; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SWAP_MB_AR; + P(ET9); + DLY(200); + goto et10; +case 0662: + P(ET0); + DLY(100); + ACBM_SET; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(AR_ZERO) + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + MB_FM_AR_J; + goto et10; +case 0663: + MB_SWAP; + P(ET0); + DLY(100); + ACBM_SET; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(AR_ZERO) + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + MB_FM_AR_J; + goto et10; +case 0664: + P(ET0); + DLY(100); + ACBM_SET; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + goto et10; +case 0665: + MB_SWAP; + P(ET0); + DLY(100); + ACBM_SET; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + goto et10; +case 0666: + P(ET0); + DLY(100); + ACBM_SET; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(!AR_ZERO) + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + MB_FM_AR_J; + goto et10; +case 0667: + MB_SWAP; + P(ET0); + DLY(100); + ACBM_SET; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(!AR_ZERO) + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + MB_FM_AR_J; + goto et10; +case 0670: + P(ET0); + DLY(100); + ACBM_SET; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SWAP_MB_AR; + P(ET9); + DLY(200); + goto et10; +case 0671: + MB_SWAP; + P(ET0); + DLY(100); + ACBM_SET; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SWAP_MB_AR; + P(ET9); + DLY(200); + goto et10; +case 0672: + P(ET0); + DLY(100); + ACBM_SET; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(AR_ZERO) + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + MB_FM_AR_J; + goto et10; +case 0673: + MB_SWAP; + P(ET0); + DLY(100); + ACBM_SET; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(AR_ZERO) + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + MB_FM_AR_J; + goto et10; +case 0674: + P(ET0); + DLY(100); + ACBM_SET; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + goto et10; +case 0675: + MB_SWAP; + P(ET0); + DLY(100); + ACBM_SET; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + goto et10; +case 0676: + P(ET0); + DLY(100); + ACBM_SET; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(!AR_ZERO) + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + MB_FM_AR_J; + goto et10; +case 0677: + MB_SWAP; + P(ET0); + DLY(100); + ACBM_SET; + P(ET1); + DLY(100); + P(ET3); + SWAP_MB_AR; + P(ET4); + DLY(100); + AR_COM; + P(ET5); + DLY(100); + P(ET6); + DLY(100); + AR_COM; + P(ET7); + DLY(100); + P(ET8); + DLY(200); + if(!AR_ZERO) + SKIP; + SWAP_MB_AR; + P(ET9); + DLY(200); + MB_FM_AR_J; + goto et10; diff --git a/newemu/main.c b/newemu/main.c new file mode 100644 index 0000000..200dbf0 --- /dev/null +++ b/newemu/main.c @@ -0,0 +1,293 @@ +#include "common.h" +#include "pdp6.h" +#include "args.h" + +#include +#include +#include + +#include + +u64 simtime; +u64 realtime; + +typedef struct Panel Panel; +void updateswitches(PDP6 *pdp, Panel *panel); +void updatelights(PDP6 *pdp, Panel *panel); +void lightsoff(Panel *panel); +Panel *getpanel(void); + + +// tmp +extern Word memory[01000000]; +extern Word fmem[020]; + +#define I(op, ac, i, x, y)\ + ((Word)(op)<<27 |\ + (Word)(ac)<<23 |\ + (Word)(i)<<22 |\ + (Word)(x)<<18 |\ + (Word)(y)) + +#define IO(op, dev, i, x, y)\ + ((Word)(7)<<33 |\ + (Word)(dev)<<24 |\ + (Word)(op)<<23 |\ + (Word)(i)<<22 |\ + (Word)(x)<<18 |\ + (Word)(y)) + +Hword +readmemory(const char *path) +{ + char line[128], *p; + Hword a, pc; + Word d; + FILE *f; + + f = fopen(path, "r"); + if(f == NULL) { + printf("couldn't open file %s\n", path); + return 0; + } + + pc = 0; + while(p = fgets(line, sizeof(line), f)) { + if(*p == 'd') { + p++; + sscanf(p, "%o %llo", &a, &d); + memory[a] = d; + } else if(*p == 'g') { + p++; + sscanf(p, "%o", &pc); + break; + } + } + + fclose(f); + return pc; +} + +const bool throttle = 1; + +// TODO: this sucks +Dis340 *dis; +Ux555 *ux1; +Ux555 *ux2; +Ux555 *ux3; +Ux555 *ux4; + +void +configmachine(PDP6 *pdp) +{ + uxmount(ux1, "t/systemdis.dtr"); +// uxmount(ux1, "t/system.dtr"); +// uxmount(ux2, "t/syseng.dtr"); + uxmount(ux2, "t/its138.dtr"); +// uxmount(ux3, "t/foo.dtr"); + uxmount(ux3, "t/music.dtr"); + + /* MACDMP RIM loader */ + memory[000] = 0255000000000; + memory[001] = 0205000255000; + memory[002] = 0700200635550; + memory[003] = 0700600011577; + memory[004] = 0721200223110; + memory[005] = 0720200004010; + memory[006] = 0720340001000; + memory[007] = 0254000000006; + memory[010] = 0720040000013; + memory[011] = 0345540000006; + memory[012] = 0602540777777; + memory[013] = 0000000000013; + memory[014] = 0254000000006; + + /* PTR RIM loader */ + memory[020] = 0710600000060; + memory[021] = 0710740000010; + memory[022] = 0254000000021; + memory[023] = 0710440000026; + memory[024] = 0710740000010; + memory[025] = 0254000000024; + memory[027] = 0254000000021; + pdp->pc = 020; + +// pdp->pc = readmemory("t/pdp6.part3.oct"); + // part3: assumes non-existent memory at 777777 at PC=2004 + // assumes reader motor will be off +// memory[0101] |= I(0, 1, 0, 0, 0); // disable device tests in part3 + // part4: start with 1 in switches, flip back to 0 at some point +// pdp->pc = readmemory("t/ddt.16k.oct"); + pdp->pc = readmemory("t/ddt.d16k.oct"); // needs moby +// pdp->pc = readmemory("t/nts.lisp.u16k.oct"); +// pdp->pc = readmemory("t/nts.teco6.u256k.oct"); +// pdp->pc = readmemory("t/spcwar.oct"); +// pdp->pc = readmemory("t/hello.oct"); +// pdp->pc = readmemory("t/its138.oct"); +// pdp->pc = readmemory("t/music.oct"); +} + +int domusic = 0; + +void +initemu(PDP6 *pdp) +{ + memset(pdp, 0, sizeof(*pdp)); + + predecode(); + + initdevs(pdp); + attach_ptp(pdp); + attach_ptr(pdp); + attach_tty(pdp); + dis = attach_dis(pdp); + Dc136 *dc = attach_dc(pdp); + Ut551 *ut = attach_ut(pdp, dc); + ux1 = attach_ux(ut, 1); + ux2 = attach_ux(ut, 2); + ux3 = attach_ux(ut, 3); + ux4 = attach_ux(ut, 4); + // stub for ITS + attach_ge(pdp); + + + srand(time(NULL)); + pwrclr(pdp); + cycle_io(pdp, 0); + +if(domusic) initmusic(); +} + +void +emu(PDP6 *pdp, Panel *panel) +{ + bool key_manual; + bool key_inst_stop; + bool power; + + updateswitches(pdp, panel); + + inittime(); + simtime = 0; //gettime(); + pdp->clk_timer = 0; + for(;;) { + key_manual = pdp->key_manual; + key_inst_stop = pdp->key_inst_stop; + power = pdp->sw_power; + updateswitches(pdp, panel); + + if(pdp->sw_power) { + if(pdp->key_manual && !key_manual) + kt0(pdp); + if(pdp->key_inst_stop && !key_inst_stop) { + clr_run(pdp); + pdp->ia_inh = 1; + pdp->ia_inh_timer = simtime + 100000; + } + + if(pdp->ia_inh && simtime > pdp->ia_inh_timer) + pdp->ia_inh = 0; + + if(pdp->cycling) { + // avg: 1.4 - 1.7μs + cycle(pdp); +svc_music(pdp); + } else { + simtime += 1500; // keep things running + + pdp->ia_inh = 0; +stopmusic(); + } + updatelights(pdp, panel); + + cycle_io(pdp, 1); + + if(throttle) while(realtime < simtime) realtime = gettime(); + } else { +stopmusic(); + if(power) + pwrclr(pdp); + + lightsoff(panel); + + if(throttle) + simtime = gettime(); + else + simtime += 1500; + cycle_io(pdp, 0); + } + +// cli(pdp); + } +} + +char *argv0; +void +usage(void) +{ + fprintf(stderr, "usage: %s [-h host] [-p port]\n", argv0); + exit(1); +} + +void +inthandler(int sig) +{ + exit(0); +} + +int +main(int argc, char *argv[]) +{ + Panel *panel; + PDP6 pdp6, *pdp = &pdp6; + + const char *host; + int port; + + host = "localhost"; + port = 3400; + ARGBEGIN { + case 'h': + host = EARGF(usage()); + break; + case 'p': + port = atoi(EARGF(usage())); + break; + default: + usage(); + } ARGEND; + + panel = getpanel(); + if(panel == nil) { + fprintf(stderr, "can't find operator panel\n"); + return 1; + } + + atexit(exitcleanup); + signal(SIGPIPE, SIG_IGN); + signal(SIGINT, inthandler); + + addcleanup((void (*)(void*))lightsoff, panel); + + initemu(pdp); + configmachine(pdp); + + int dis_fd = dial(host, port); + if(dis_fd < 0) + printf("can't open display\n"); + nodelay(dis_fd); + dis_connect(dis, dis_fd); + +// const char *tape = "t/hello.rim"; +// const char *tape = "t/ptp_test.rim"; + const char *tape = "t/bla.txt"; + pdp->ptr_fd = open(tape, O_RDONLY); + pdp->ptp_fd = open("out.ptp", O_CREAT|O_WRONLY|O_TRUNC, 0644); + + pdp->tty_fd = open("/tmp/tty", O_RDWR); + if(pdp->tty_fd < 0) + printf("can't open /tmp/tty\n"); + + emu(pdp, panel); + return 0; // can't happen +} diff --git a/newemu/panel10.c b/newemu/panel10.c new file mode 100644 index 0000000..594893f --- /dev/null +++ b/newemu/panel10.c @@ -0,0 +1,102 @@ +#include "common.h" +#include "panel_pidp10.h" +#include "pdp6.h" + +void +updateswitches(PDP6 *pdp, Panel *panel) +{ + int sw3 = panel->sw3; + int sw4 = panel->sw4; + + // TODO: make sure "opposite" keys are not down at the same time + pdp->key_start = !!(sw3 & KEY_START); + pdp->key_read_in = !!(sw3 & KEY_READIN); + pdp->key_dep = !!(sw3 & KEY_DEP); + pdp->key_dep_nxt = !!(sw3 & KEY_DEP_NEXT); + pdp->key_ex = !!(sw3 & KEY_EX); + pdp->key_ex_nxt = !!(sw3 & KEY_EX_NEXT); + pdp->key_io_reset = !!(sw3 & KEY_RESET); + pdp->key_execute = !!(sw3 & KEY_XCT) && !pdp->run; + pdp->key_mem_stop = !!(sw4 & SW_SING_CYC); + pdp->key_inst_stop = !!(sw4 & SW_SING_INST) || !!(sw3 & KEY_STOP); + + pdp->sw_power = 1; + pdp->sw_mem_disable = !!(sw4 & SW_NXM_STOP); + pdp->sw_addr_stop = !!(sw4 & SW_ADR_STOP); + pdp->sw_repeat = !!(sw4 & SW_REPT); + + pdp->datasw = panel->sw0 | (Word)panel->sw1<<18; + pdp->mas = panel->sw2; + + if(pdp->mc_stop) { + pdp->key_inst_cont = 0; + pdp->key_mem_cont = !!(sw3 & KEY_CONT); + } else { + pdp->key_inst_cont = !!(sw3 & KEY_CONT); + pdp->key_mem_cont = 0; + } + + // this sucks a bit + pdp->ptr_tape_feed = 0; + pdp->ptp_tape_feed = 0; + pdp->sw_ptr_motor_on = 0; + pdp->sw_ptr_motor_off = 0; + + pdp->key_manual = + pdp->key_start || + pdp->key_read_in || + pdp->key_inst_cont || + pdp->key_io_reset || + pdp->key_execute || + pdp->key_ex || pdp->key_ex_nxt || + pdp->key_dep || pdp->key_dep_nxt; + + pdp->dotrace = !!(sw4 & SW_PAR_STOP); +} + +void +updatelights(PDP6 *pdp, Panel *panel) +{ + int l; + + panel->lights0 = pdp->mi & 0777777; + panel->lights1 = (pdp->mi>>18) & 0777777; + panel->lights2 = pdp->ma & 0777777; + panel->lights3 = pdp->ir & 0777777; + panel->lights4 = pdp->pc & 0777777; + + l = pdp->pio; + l |= pdp->iob_req << 7; + l |= L5_POWER; + if(pdp->mc_stop) + l |= L5_MC_STOP; + if(pdp->ex_user) + l |= L5_USER_MODE; + panel->lights5 = l; + + l = pdp->pir; + l |= pdp->pih << 7; + if(pdp->run) + l |= L6_RUN; + if(pdp->pi_on) + l |= L6_PI_ON; + panel->lights6 = l; +} + +void +lightsoff(Panel *panel) +{ + panel->lights0 = 0; + panel->lights1 = 0; + panel->lights2 = 0; + panel->lights3 = 0; + panel->lights4 = 0; + panel->lights5 = 0; + panel->lights6 = 0; +} + +Panel* +getpanel(void) +{ + return attachseg("/tmp/pdp10_panel", sizeof(Panel)); +} diff --git a/newemu/panel6.c b/newemu/panel6.c new file mode 100644 index 0000000..a7a037d --- /dev/null +++ b/newemu/panel6.c @@ -0,0 +1,91 @@ +#include "common.h" +#include "../panel/panel6.h" +#include "pdp6.h" + +void +updateswitches(PDP6 *pdp, Panel6 *panel) +{ + int sw3 = panel->sw3; + + pdp->key_start = !!(sw3 & KEY_START); + pdp->key_read_in = !!(sw3 & KEY_READIN); + pdp->key_inst_cont = !!(sw3 & KEY_INST_CONT); + pdp->key_mem_cont = !!(sw3 & KEY_MEM_CONT); + pdp->key_inst_stop = !!(sw3 & KEY_INST_STOP); + pdp->key_mem_stop = !!(sw3 & KEY_MEM_STOP); + pdp->key_io_reset = !!(sw3 & KEY_IO_RESET); + pdp->key_execute = !!(sw3 & KEY_EXEC) && !pdp->run; + pdp->key_dep = !!(sw3 & KEY_DEP); + pdp->key_dep_nxt = !!(sw3 & KEY_DEP_NXT); + pdp->key_ex = !!(sw3 & KEY_EX); + pdp->key_ex_nxt = !!(sw3 & KEY_EX_NXT); + + pdp->sw_power = !!(panel->sw3 & SW_POWER); + pdp->sw_mem_disable = !!(sw3 & SW_MEM_DISABLE); + pdp->sw_addr_stop = !!(sw3 & SW_ADDR_STOP); + pdp->sw_repeat = !!(sw3 & SW_REPEAT); + + pdp->datasw = panel->sw0 | (Word)panel->sw1<<18; + pdp->mas = panel->sw2; + + pdp->ptr_tape_feed = !!(panel->sw4 & KEY_PTR_FEED); + pdp->ptp_tape_feed = !!(panel->sw4 & KEY_PTP_FEED); + pdp->sw_ptr_motor_on = !!(panel->sw4 & KEY_MOTOR_ON); + pdp->sw_ptr_motor_off = !!(panel->sw4 & KEY_MOTOR_OFF); + + pdp->key_manual = + pdp->key_start || + pdp->key_read_in || + pdp->key_inst_cont || + pdp->key_io_reset || + pdp->key_execute || + pdp->key_ex || pdp->key_ex_nxt || + pdp->key_dep || pdp->key_dep_nxt; + + + pdp->dotrace = 0; +} + +void +updatelights(PDP6 *pdp, Panel6 *panel) +{ + int l; + + panel->lights0 = pdp->mi & 0777777; + panel->lights1 = (pdp->mi>>18) & 0777777; + panel->lights2 = pdp->ma & 0777777; + panel->lights3 = pdp->ir & 0777777; + panel->lights4 = pdp->pc & 0777777; + + l = pdp->pio; + if(pdp->run) l |= L5_RUN; + if(pdp->pi_on) l |= L5_PI_ON; + if(pdp->mc_stop) l |= L5_MC_STOP; + if(pdp->sw_mem_disable) l |= L5_MEM_DISABLE; + if(pdp->sw_addr_stop) l |= L5_ADDR_STOP; + if(pdp->sw_repeat) l |= L5_REPEAT; + l |= L5_POWER; + panel->lights5 = l; + + l = pdp->pir; + l |= pdp->pih<<7; + panel->lights6 = l; +} + +void +lightsoff(Panel6 *panel) +{ + panel->lights0 = 0; + panel->lights1 = 0; + panel->lights2 = 0; + panel->lights3 = 0; + panel->lights4 = 0; + panel->lights5 = 0; + panel->lights6 = 0; +} + +Panel6* +getpanel(void) +{ + return attachseg("/tmp/pdp6_panel", sizeof(Panel6)); +} diff --git a/newemu/pdp6.c b/newemu/pdp6.c new file mode 100644 index 0000000..f63d19c --- /dev/null +++ b/newemu/pdp6.c @@ -0,0 +1,2776 @@ +#include "common.h" +#include "pdp6.h" +#include "args.h" + +#include +#include +#include + +#include + +#if 1 +#define P(name) pulse(pdp, #name) +#define DLY(ns) simtime += ns +// can be turned into nop - only for accuracy +#define FF(ff, val) (pdp->ff = val) +#else +#define P(name) +#define DLY(ns) simtime += ns; +#define FF(ff, val) 0 // will be optimized out +#endif + +#define SBR(sbr, ff) (FF(ff,1), sbr, FF(ff,0)) + +enum { + // UUOs and IOTs are remapped, other opcodes serve as states directly. + // since there are 64 UUO opcodes we should have enough space + IOT_BLKI = 0, + IOT_DATAI, + IOT_BLKO, + IOT_DATAO, + IOT_CONO, + IOT_CONI, + IOT_CONSZ, + IOT_CONSO, + + UUO, + + KT1, + IT0, + // for memory returns + KEY_RDWR_RET, + IT1A, + AT0, + AT3, + FT1A, + FT4A, + FT6A, + ST3, + ST5A, + ST7, + UUOT1, + BLTT0A, + IOTT0A, + CH_INC_OP, + CH_NOT_INC_OP, + CH_LOAD, + CH_DEP, + CHT8B, + + NOP +}; + +#define FCRY 01000000000000 +#define NF0 0377777777777 +#define NF01 0177777777777 +#define H6 0004000 +#define H9 0000400 +#define H10 0000200 +#define H11 0000100 +#define H12 0000040 +#define EXPBITS 0377000000000 +#define MANTBITS 0000777777777 + +enum { + CODE_UUO = 01, + // these can turn into UUO + // depending on processor state + CODE_IOT = 02, + CODE_JRST = 04, + // need CHF5 and CHF7 for decoding + CODE_CHAR = 010, + + // standard bits + CODE_FAC_INH = 020, + CODE_FAC2 = 040, + CODE_FCCACLT = 0100, + CODE_FCCACRT = 0200, + CODE_FAC2_ETC = CODE_FAC2|CODE_FCCACLT|CODE_FCCACRT, + CODE_FCE = 0400, + CODE_FCE_PSE = 01000, + CODE_SAC_INH = 02000, + CODE_SAC0_INH = 04000, + CODE_SAC2 = 010000, + CODE_SCE = 020000, + CODE_PC_INC_INH = 040000, + CODE_PI_HOLD = 0100000, +}; +Code codetab[01000]; +Code iotcodetab[8]; + + +#define AR pdp->ar +#define MQ pdp->mq +#define MQ36 pdp->mq36 +#define MB pdp->mb +#define MI pdp->mi +#define IR pdp->ir +#define MA pdp->ma +#define PC pdp->pc +#define FE pdp->fe +#define SC pdp->sc +#define IOB pdp->iob + +#define SWAP(A,B) (t = A, A = B, B = t) +#define SWAPLTRT(a) ((a)<<18 & LT | (a)>>18 & RT) +#define EXP_CLR(reg) (reg = reg&F0 ? reg|EXPBITS : reg&~EXPBITS) + +#define AR_ZERO (AR == 0) +#define AR_NEG !!(AR & F0) +#define AR_OV (pdp->ar_cry0 != pdp->ar_cry1) +#define AR_LESS (AR_NEG != AR_OV) +#define SELECTED_FLAGS (IR & 0740 &\ + (pdp->ar_ov_flag<<8 | pdp->ar_cry0_flag<<7 |\ + pdp->ar_cry1_flag<<6 | pdp->ar_pc_chg_flag<<5)) + +#define MB_NEG !!(MB & F0) +#define MQ_NEG !!(MQ & F0) +#define SC_NEG !!(SC & 0400) + +// AR +#define AR_CLR (AR = 0) +#define ARLT_CLR (AR &= RT) +#define ARLT_COM (AR ^= LT) +#define ARRT_COM (AR ^= RT) +#define AR_COM (AR ^= FW) +#define AR_FM_MB_C (AR ^= MB) +#define AR_FM_MB_0 (AR &= MB) +#define AR_FM_MB_1 (AR |= MB) +#define AR_FM_MBLT_J (AR = MB< | AR&RT) +#define AR_FM_MBRT_J (AR = AR< | MB&RT) +#define AR_FM_MB_J (AR = MB) +#define AR_FM_SC_J (AR = AR&~EXPBITS | ((Word)SC&0377)<<27) +#define AR_ADD ar_add(pdp) +#define AR_SUB ar_sub(pdp) +#define AR_INC ar_inc(pdp) +#define AR_INC_LTRT ar_inc_ltrt(pdp) +#define AR_DEC ar_dec(pdp) +#define AR_DEC_LTRT ar_dec_ltrt(pdp) +#define AR_NEGATE ar_negate(pdp) +#define AR_SET_OV_CRY ar_set_ov_cry(pdp) + +// MQ +#define MQ_CLR (MQ = 0) +#define MQ_FM_MB_J (MQ = MB) + +// MB +#define MB_CLR (MB = 0) +#define MBLT_CLR (MB &= RT) +#define MB_FM_AR_0 (MB &= AR) +#define MB_FM_AR_1 (MB |= AR) +#define MB_FM_AR_J (MB = AR) +#define MB_FM_MQ_0 (MB &= MQ) +#define MB_FM_MQ_1 (MB |= MQ) +#define MB_FM_MQ_J (MB = MQ) +#define MB_SWAP (MB = (MB<<18 | MB>>18) & FW) +#define MB_FM_PC_1 (MB |= PC) +#define MB_FM_MISC_BITS mb_fm_misc_bits(pdp) +#define SWAP_MB_AR SWAP(MB,AR) +#define SWAP_MB_MQ SWAP(MB,MQ) + +// MA +#define MA_CLR (MA = 0) +#define MA_FM_MBRT_1 (MA |= MB & RT) +#define MA_INC (MA = (MA+1)&0777777) +#define MA_INC4 (MA = (MA+1)&017) // not quite correct, but good enough, only used for AC2 + +// IR +#define IR_CLR (IR = 0) + +// PC +#define PC_CLR (PC = 0) +#define PC_FM_MA_1 (PC |= MA) +#define PC_INC (PC = (PC+1) & RT) +#define PC_CHG pc_chg(pdp) + +// FE +#define FE_CLR (FE = 0) +#define FE_FM_SC_1 (FE |= SC) +#define FE_FM_MB_1 (FE |= (MB>>30)&077) + +// SC +#define SC_CLR (SC = 0) +#define SC_COM (SC ^= 0777) +#define SC_INC (SC = (SC+1) & 0777) +#define SC_FM_MB (SC |= (~MB>>9)&0400 | ~MB&0377) +#define SC_PAD(x) (SC ^= x) +#define SC_ADD(x) sc_add(pdp, x) +#define SC_FM_FE_1 (SC |= FE) + +#define MR_CLR mr_clr(pdp) +#define FWT_OV if(!pdp->ar_cry0 && pdp->ar_cry1) ar_set_ov(pdp) +#define PDL_OV if(pdp->ar_cry0) cpa_set_pdl_ov(pdp) +#define SKIP (PC_INC, PC_CHG) +#define ACBM_COM (t = MB & AR, AR ^= MB, MB = t) +#define ACBM_SET (t = MB & AR, AR |= MB, MB = t) +#define NR_ROUND (!pdp->nrf3 && IR&H6 && MQ&F1) + +#define trace if(pdp->dotrace) printf + +void +pulse(PDP6 *pdp, const char *name) +{ + trace("%s", name); +// trace("\tAR/%012llo MQ/%012llo MB/%012llo", AR, MQ, MB); +// trace(" SC/%03o FE/%03o", SC, FE); + trace("\tMB/%012llo AR/%012llo MQ/%012llo", MB, AR, MQ); + trace(" FE/%03o SC/%03o", FE, SC); + trace(" IR/%06o PC/%06o MA/%06o", IR, PC, MA); + trace(" %llu", simtime); + trace("\n"); +} + +static IOdev *devs_code[0200]; +static IOdev *devs[0200]; +static int numdevs; + +void handle_cpa(PDP6 *pdp, IOdev *dev, int cmd); +void handle_pi(PDP6 *pdp, IOdev *dev, int cmd); +static IOdev cpa_dev = { 0, 0, nil, handle_cpa, nil }; +static IOdev pi_dev = { 0, 4, nil, handle_pi, nil }; + + +// use as template +void handle_null(PDP6 *pdp, IOdev *dev, int cmd) { +printf("IOT with unimplemented device %06o %06o %03o %o\n", PC, IR, (IR>>6)&0774, cmd); + switch(cmd) { + case IOB_RESET: + break; + case IOB_CONO_CLR: + break; + case IOB_CONO_SET: + break; + case IOB_DATAO_CLR: + break; + case IOB_DATAO_SET: + break; + case IOB_DATAI: + break; + case IOB_STATUS: + break; + } +} +static IOdev null_dev = { 0, 0, nil, handle_null, nil }; + +void +io_reset(PDP6 *pdp) +{ + for(int i = 0; i < numdevs; i++) + devs[i]->handler(pdp, devs[i], IOB_RESET); +} + +static void +calc_iob_req(PDP6 *pdp) +{ + pdp->iob_req = 0; + for(int i = 0; i < numdevs; i++) + pdp->iob_req |= devs[i]->req; +} + +// need to call this for all sorts of devices +void +setreq(PDP6 *pdp, IOdev *dev, u8 req) +{ + req &= 0177; + if(dev->req != req) { + dev->req = req; + calc_iob_req(pdp); + } +} + + +Hword maxmem = 256*1024; +Word memory[01000000]; +Word fmem[020]; + +static void cpa_set_illeg_op(PDP6 *pdp); +static void cpa_set_nomem(PDP6 *pdp); + +static int +reloc(PDP6 *pdp) +{ + if(pdp->ex_user && !pdp->ex_pi_sync && MA >= 020 && !pdp->ex_ill_op) { + pdp->rla = (MA + pdp->rlr) & RT; + DLY(100); + if((MA & 0776000) > pdp->pr) { + cpa_set_illeg_op(pdp); + DLY(100); + pdp->state = ST7; + return 1; + } + } else + pdp->rla = MA; + return 0; +} + +static int +mc_rq(PDP6 *pdp, int ret) +{ + pdp->state = ret; + pdp->mc_stop = pdp->key_mem_stop || pdp->sw_addr_stop && MA == pdp->mas; + return reloc(pdp); +} + +static int +mc_nxm(PDP6 *pdp) +{ +printf("no mem %06o PC %06o\n", MA, PC); + if(pdp->mc_stop) { + pdp->cycling = 0; + return 0; + } + cpa_set_nomem(pdp); + if(pdp->sw_mem_disable) { + pdp->cycling = 0; + return 0; + } + // restart + FF(mc_rq, 0); + FF(mc_rd, 0); + return 1; +} + +static void +rdrq(PDP6 *pdp, int ret) +{ + FF(mc_rd, 1); + FF(mc_wr, 0); + MB = 0; + if(mc_rq(pdp, ret)) + return; + + FF(mc_rq, 1); + // timing from F-67_162_161C_Apr66.pdf + if(MA < 020 && !pdp->key_rim_sbr) { + DLY(380); + MB |= fmem[MA]; + } else if(pdp->rla < maxmem) { + DLY(2750); + MB |= memory[pdp->rla]; + } else { + mc_nxm(pdp); + return; + } + + // restart + FF(mc_rq, 0); + if(MA == pdp->mas) + MI = MB; + if(pdp->mc_stop) + pdp->cycling = 0; + else + FF(mc_rd, 0); +trace("RD\t\t%06o %06o %d -> %012llo\n", MA, pdp->rla, pdp->key_rim_sbr, MB); +} + +static void +wrrq(PDP6 *pdp, int ret) +{ + FF(mc_rd, 0); + FF(mc_wr, 1); + if(mc_rq(pdp, ret)) + return; + + FF(mc_rq, 1); + // timing from F-67_162_161C_Apr66.pdf + if(MA < 020 && !pdp->key_rim_sbr) { + DLY(420); + fmem[MA] = MB; + FF(mc_rq, 0); + } else if(pdp->rla < maxmem) { + DLY(750); + memory[pdp->rla] = MB; + FF(mc_rq, 0); + } else { + if(mc_nxm(pdp)) { + if(MA == pdp->mas) + MI = MB; + } + return; + } + + // restart + FF(mc_rq, 0); + if(MA == pdp->mas) + MI = MB; + if(pdp->mc_stop) + pdp->cycling = 0; + else + FF(mc_rd, 0); +trace("WR\t\t%06o %06o %d <- %012llo\n", MA, pdp->rla, pdp->key_rim_sbr, MB); +} + +// TODO: actually do these properly + +void +rdwrrq(PDP6 *pdp, int ret) +{ + rdrq(pdp, ret); +} + +void +wrrs(PDP6 *pdp, int ret) +{ + wrrq(pdp, ret); +} + + + + +void mr_start(PDP6 *pdp); +void mr_clr(PDP6 *pdp); +void pi_reset(PDP6 *pdp); + +void +initdevs(PDP6 *pdp) +{ + for(int i = 0; i < 0200; i++) + devs_code[i] = &null_dev; + numdevs = 0; + installdev(pdp, &cpa_dev); + installdev(pdp, &pi_dev); +} + +void +installdev(PDP6 *pdp, IOdev *dev) +{ + devs_code[dev->devcode >> 2] = devs[numdevs++] = dev; +} + +void +cycle_io(PDP6 *pdp, int pwr) +{ + for(int i = 0; i < numdevs; i++) + if(devs[i]->cycle) + devs[i]->cycle(pdp, devs[i], pwr); +} + +void +pwrclr(PDP6 *pdp) +{ + for(int i = 0; i < numdevs; i++) + devs[i]->req = 0; + pdp->iob_req = 0; + + AR = (rand() | (Word)rand()<<18) & FW; + MQ = (rand() | (Word)rand()<<18) & FW; + MB = (rand() | (Word)rand()<<18) & FW; + MI = (rand() | (Word)rand()<<18) & FW; + PC = rand() & RT; + MA = rand() & RT; + IR = rand() & RT; + + pdp->run = 0; + mr_start(pdp); + mr_clr(pdp); +} + +void +mr_start(PDP6 *pdp) +{ + pdp->pi_cyc = 0; + pdp->pi_ov = 0; + pi_reset(pdp); + + pdp->ex_user = 0; + pdp->ex_ill_op = 0; + pdp->pr = 0; + pdp->rlr = 0; + + pdp->ar_pc_chg_flag = 0; + pdp->ar_ov_flag = 0; + pdp->ar_cry0_flag = 0; + pdp->ar_cry1_flag = 0; + pdp->chf7 = 0; + + pdp->cpa_iot_user = 0; + pdp->cpa_illeg_op = 0; + pdp->cpa_non_exist_mem = 0; + pdp->cpa_clock_enable = 0; + pdp->cpa_clock_flag = 0; + pdp->cpa_pc_chg_enable = 0; + pdp->cpa_pdl_ov = 0; + pdp->cpa_arov_enable = 0; + pdp->cpa_pia = 0; + setreq(pdp, &cpa_dev, 0); + + io_reset(pdp); +} + +void +mr_clr(PDP6 *pdp) +{ + MQ_CLR; + MQ36 = 0; + IR_CLR; + FE_CLR; + SC_CLR; + if(pdp->ex_mode_sync) + pdp->ex_user = 1; + pdp->ex_mode_sync = 0; + FF(ex_uuo_sync, 0); + pdp->ex_pi_sync = pdp->pi_cyc; + + FF(iot_go, 0); + + FF(ar_com_cont, 0); + + FF(key_rd_wr, 0); + FF(if1a, 0); + FF(af0, 0); + FF(af3, 0); + FF(af3a, 0); + FF(f1a, 0); + FF(f4a, 0); + FF(f6a, 0); + FF(et4_ar_pause, 0); + FF(sf3, 0); + FF(sf5a, 0); + FF(sf7, 0); + pdp->dsf7 = 0; + FF(iot_f0a, 0); + FF(blt_f0a, 0); + FF(blt_f3a, 0); + FF(blt_f5a, 0); + FF(uuo_f1, 0); + FF(dcf1, 0); + + // MP CLR + FF(chf1, 0); + FF(chf2, 0); + FF(chf3, 0); + FF(chf4, 0); + pdp->chf5 = 0; + FF(chf6, 0); + FF(lcf1, 0); + FF(shf1, 0); + FF(mpf1, 0); + pdp->mpf2 = 0; + FF(msf1, 0); + FF(fmf1, 0); + FF(fmf2, 0); + FF(fdf1, 0); + FF(fdf2, 0); + FF(faf1, 0); + FF(faf2, 0); + FF(faf3, 0); + FF(faf4, 0); + FF(fpf1, 0); + FF(fpf2, 0); + FF(nrf1, 0); + FF(nrf2, 0); + pdp->nrf3 = 0; + + // DS CLR + FF(dsf1, 0); + FF(dsf2, 0); + FF(dsf3, 0); + FF(dsf4, 0); + FF(dsf5, 0); + FF(dsf6, 0); + FF(dsf8, 0); + FF(dsf9, 0); + FF(fsf1, 0); +} + +// PDP-1 equivalences: +// PIH = B4 +// PIR = B3 +// REQ = B2 latched and gated by PIO +// PIO = B1 +static void calc_req(PDP6 *pdp) { + u8 r; + if(!pdp->pi_active) { + pdp->pi_req = 0; + return; + } + for(r = 0100; r; r >>= 1) { + if(pdp->pih & r) + r = 0; + else if(pdp->pir & r) + break; + } + pdp->pi_req = r; +} +static void pir_set(PDP6 *pdp, u8 pir) { + if(pir == 0) return; // common case + pdp->pir |= pir; + pdp->pir &= ~pdp->pih; + calc_req(pdp); +} + +static void pi_hold(PDP6 *pdp) { + // accept break + pdp->pih |= pdp->pi_req; + pdp->pir &= ~pdp->pih; + calc_req(pdp); +} + +static void pi_rst(PDP6 *pdp) { + // clear highest break + if(!pdp->pi_active) + return; + for(u8 r = 0100; r; r >>= 1) + if(pdp->pih & r) { + pdp->pih &= ~r; + calc_req(pdp); + break; + } +} + +// exit PI cycle +static void pi_exit(PDP6 *pdp) { + pdp->pi_ov = 0; + pdp->pi_cyc = 0; +} + +void +pi_reset(PDP6 *pdp) +{ + pdp->pi_active = 0; + pdp->pih = 0; + pdp->pir = 0; + pdp->pio = 0; + // therefore: + pdp->pi_req = 0; +} + +void +handle_pi(PDP6 *pdp, IOdev *dev, int cmd) +{ + switch(cmd) { + case IOB_CONO_CLR: + if(IOB & F23) pi_reset(pdp); + break; + case IOB_CONO_SET: +// TODO: actually set&clear at the same time should complement + if(IOB & F24) pir_set(pdp, IOB & 0177); + if(IOB & F25) pdp->pio |= IOB & 0177; + if(IOB & F26) pdp->pio &= ~IOB & 0177; + if(IOB & F27) pdp->pi_active = 0; + if(IOB & F28) pdp->pi_active = 1; + calc_req(pdp); + break; + case IOB_STATUS: + if(pdp->pi_active) IOB |= F28; + IOB |= pdp->pio; + break; + } +} + +#define PIR_STB pir_set(pdp, pdp->iob_req & pdp->pio) +#define PI_HOLD (pdp->pi_cyc && (!(pdp->code&CODE_IOT) || !pdp->pi_ov && (pdp->code&CODE_PI_HOLD))) + + + + +void +calc_cpa_req(PDP6 *pdp) +{ + if(pdp->cpa_pia && + (pdp->cpa_illeg_op || + pdp->cpa_non_exist_mem || + pdp->cpa_pdl_ov || + pdp->cpa_clock_enable && pdp->cpa_clock_flag || + pdp->cpa_pc_chg_enable && pdp->ar_pc_chg_flag || + pdp->cpa_arov_enable && pdp->ar_ov_flag)) + setreq(pdp, &cpa_dev, 0200>>pdp->cpa_pia); + else + setreq(pdp, &cpa_dev, 0); +} + +void +handle_cpa(PDP6 *pdp, IOdev *dev, int cmd) +{ + switch(cmd) { + case IOB_RESET: + pdp->cpa_iot_user = 0; + break; + case IOB_CONO_SET: +// TODO: actually set&clear at the same time should complement + if(IOB & F18) pdp->cpa_pdl_ov = 0; + if(IOB & F20) pdp->cpa_iot_user = 0; + if(IOB & F21) pdp->cpa_iot_user = 1; + if(IOB & F22) pdp->cpa_illeg_op = 0; + if(IOB & F23) pdp->cpa_non_exist_mem = 0; + if(IOB & F24) pdp->cpa_clock_enable = 0; + if(IOB & F25) pdp->cpa_clock_enable = 1; + if(IOB & F26) pdp->cpa_clock_flag = 0; + if(IOB & F27) pdp->cpa_pc_chg_enable = 0; + if(IOB & F28) pdp->cpa_pc_chg_enable = 1; + if(IOB & F29) pdp->ar_pc_chg_flag = 0; + if(IOB & F30) pdp->cpa_arov_enable = 0; + if(IOB & F31) pdp->cpa_arov_enable = 1; + if(IOB & F32) pdp->ar_ov_flag = 0; + pdp->cpa_pia = IOB & 7; + if(IOB & F19) io_reset(pdp); + calc_cpa_req(pdp); + break; + case IOB_DATAO_CLR: + pdp->pr = 0; + pdp->rlr = 0; + break; + case IOB_DATAO_SET: + pdp->pr = (IOB>>18) & 0776000; + pdp->rlr = IOB & 0776000; + break; + case IOB_DATAI: + IOB |= pdp->datasw; + break; + case IOB_STATUS: + if(pdp->cpa_pdl_ov) IOB |= F19; + if(pdp->cpa_iot_user) IOB |= F20; + if(pdp->ex_user) IOB |= F21; + if(pdp->cpa_illeg_op) IOB |= F22; + if(pdp->cpa_non_exist_mem) IOB |= F23; + if(pdp->cpa_clock_enable) IOB |= F25; + if(pdp->cpa_clock_flag) IOB |= F26; + if(pdp->cpa_pc_chg_enable) IOB |= F28; + if(pdp->ar_pc_chg_flag) IOB |= F29; + if(pdp->cpa_arov_enable) IOB |= F31; + if(pdp->ar_ov_flag) IOB |= F32; + IOB |= pdp->cpa_pia; + break; + } +} + + +static void add(PDP6 *pdp, Word x) { + DLY(100); // just a guess + if((AR&~F0) + (x&~F0) & F0) pdp->ar_cry1 = 1; + AR += x; + if(AR & FCRY) pdp->ar_cry0 = 1; + AR &= FW; +} +static void ar_inc(PDP6 *pdp) { add(pdp, 1); } +static void ar_inc_ltrt(PDP6 *pdp) { add(pdp, 01000001); } +static void ar_add(PDP6 *pdp) { + DLY(100); + add(pdp, MB); +} +static void ar_sub(PDP6 *pdp) { + AR ^= FW; + DLY(100); + ar_add(pdp); + AR ^= FW; + DLY(100); +} +static void ar_dec(PDP6 *pdp) { + AR ^= FW; + DLY(100); + ar_inc(pdp); + AR ^= FW; + DLY(100); +} +static void ar_dec_ltrt(PDP6 *pdp) { + AR ^= FW; + DLY(100); + ar_inc_ltrt(pdp); + AR ^= FW; + DLY(100); +} +static void ar_negate(PDP6 *pdp) { + AR ^= FW; + DLY(100); + ar_inc(pdp); +} + +// TODO: only call if flag changes? +static void pc_chg(PDP6 *pdp) { pdp->ar_pc_chg_flag = 1; calc_cpa_req(pdp); } +static void ar_set_ov(PDP6 *pdp) { pdp->ar_ov_flag = 1; calc_cpa_req(pdp); } +static void cpa_set_pdl_ov(PDP6 *pdp) { pdp->cpa_pdl_ov = 1; calc_cpa_req(pdp); } +static void cpa_set_illeg_op(PDP6 *pdp) { pdp->cpa_illeg_op = 1; calc_cpa_req(pdp); } +static void cpa_set_nomem(PDP6 *pdp) { pdp->cpa_non_exist_mem = 1; calc_cpa_req(pdp); } +static void cpa_set_clock(PDP6 *pdp) { pdp->cpa_clock_flag = 1; calc_cpa_req(pdp); } + +static void ar_flag_clr(PDP6 *pdp) { + pdp->ar_ov_flag = 0; + pdp->ar_cry0_flag = 0; + pdp->ar_cry1_flag = 0; + pdp->ar_pc_chg_flag = 0; + pdp->chf7 = 0; + // perhaps unnecessary because flags are changed again + // by ar_flag_set + calc_cpa_req(pdp); +} +static void ar_flag_set(PDP6 *pdp) { + if(MB & F0) pdp->ar_ov_flag = 1; + if(MB & F1) pdp->ar_cry0_flag = 1; + if(MB & F2) pdp->ar_cry1_flag = 1; + if(MB & F3) pdp->ar_pc_chg_flag = 1; + if(MB & F4) pdp->chf7 = 1; + if(MB & F5) pdp->ex_mode_sync = 1; + if(!pdp->ex_user) pdp->cpa_iot_user = !!(MB & F6); + calc_cpa_req(pdp); +} +static void mb_fm_misc_bits(PDP6 *pdp){ + if(pdp->ar_ov_flag) MB |= F0; + if(pdp->ar_cry0_flag) MB |= F1; + if(pdp->ar_cry1_flag) MB |= F2; + if(pdp->ar_pc_chg_flag) MB |= F3; + if(pdp->chf7) MB |= F4; + if(pdp->ex_user) MB |= F5; + if(pdp->cpa_iot_user) MB |= F6; +} +static void ar_set_ov_cry(PDP6 *pdp) { + if(AR_OV) ar_set_ov(pdp); + if(pdp->ar_cry0) pdp->ar_cry0_flag = 1; + if(pdp->ar_cry1) pdp->ar_cry1_flag = 1; +} +static void ar_jfcl_clr(PDP6 *pdp) { + if(IR & H9) pdp->ar_ov_flag = 0; + if(IR & H10) pdp->ar_cry0_flag = 0; + if(IR & H11) pdp->ar_cry1_flag = 0; + if(IR & H12) pdp->ar_pc_chg_flag = 0; + calc_cpa_req(pdp); +} + +// TODO: all MQ right shifts shift into MQ36 +static void ash_lt_ov(PDP6 *pdp) { if((AR ^ (AR<<1))&F0) ar_set_ov(pdp); } +static void ashrt(PDP6 *pdp) { AR = AR&F0 | (AR>>1); } +static void lshrt(PDP6 *pdp) { AR = AR>>1; } +static void rotrt(PDP6 *pdp) { AR = (AR<<35)&F0 | (AR>>1); } +static void ashlt(PDP6 *pdp) { ash_lt_ov(pdp); AR = AR&F0 | (AR<<1)&NF0; } +static void lshlt(PDP6 *pdp) { AR = (AR<<1)&FW; } +static void rotlt(PDP6 *pdp) { AR = (AR<<1)&FW | (AR>>35)&F35; } +static void ashcrt(PDP6 *pdp) { + MQ = AR&F0 | (AR<<34)&F1 | (MQ>>1)&NF01; + AR = AR&F0 | (AR>>1); +} +static void lshcrt(PDP6 *pdp) { + MQ = (AR<<35)&F0 | (MQ>>1); + AR = AR>>1; +} +static void rotcrt(PDP6 *pdp) { + Word t = (AR<<35)&F0 | (MQ>>1); + AR = (MQ<<35)&F0 | (AR>>1); + MQ = t; +} +static void ashclt(PDP6 *pdp) { + ash_lt_ov(pdp); + AR = AR&F0 | (AR<<1)&NF0 | (MQ>>34)&F35; + MQ = AR&F0 | (MQ<<1)&NF0; +} +static void lshclt(PDP6 *pdp) { + AR = (AR<<1)&FW | (MQ>>35)&F35; + MQ = (MQ<<1)&FW; +} +static void rotclt(PDP6 *pdp) { + Word t = (AR<<1)&FW | (MQ>>35)&F35; + MQ = (MQ<<1)&FW | (AR>>35)&F35; + AR = t; +} +static void char_first(PDP6 *pdp) { + MQ = (MQ<<1)&FW | 1; +} +static void ch_dep(PDP6 *pdp) { + AR = (AR<<1)&FW | 0; + MQ = (MQ<<1)&FW | 0; +} + + +static void +sc_add(PDP6 *pdp, int x) +{ + FF(chf1, 0); + P(SAT0); + DLY(150); + P(SAT1); + // really SC PAD + SC = (SC+x)&0777; + DLY(200); + P(SAT2); + DLY(50); + // SC CRY + P(SAT21); + DLY(100); + P(SAT3); +} + +static void +sc_count(PDP6 *pdp, void (*shift)(PDP6*)) +{ + P(SCT0); + DLY(200); + + while(SC != 0777) { + SC_INC; + shift(pdp); + P(SCT1); + DLY(75); + } + + P(SCT2); +} +#define SCT_ASHLT sc_count(pdp, ashlt) +#define SCT_ASHRT sc_count(pdp, ashrt) +#define SCT_ROTLT sc_count(pdp, rotlt) +#define SCT_ROTRT sc_count(pdp, rotrt) +#define SCT_LSHLT sc_count(pdp, lshlt) +#define SCT_LSHRT sc_count(pdp, lshrt) +#define SCT_ASHCLT sc_count(pdp, ashclt) +#define SCT_ASHCRT sc_count(pdp, ashcrt) +#define SCT_ROTCLT sc_count(pdp, rotclt) +#define SCT_ROTCRT sc_count(pdp, rotcrt) +#define SCT_LSHCLT sc_count(pdp, lshclt) +#define SCT_LSHCRT sc_count(pdp, lshcrt) + +static void +multiply(PDP6 *pdp) +{ + MQ_FM_MB_J; + MB_FM_AR_J; + P(MST1); + AR_CLR; + DLY(200); +loop: + if((MQ&1) != MQ36) { + if(MQ36) { + P(MST3); + SBR(AR_ADD, msf1); + } else { + P(MST4); + SBR(AR_SUB, msf1); + } + P(MST3A); + } + if(SC == 0777) { + SC_CLR; + MQ = AR&F0 | MQ>>1; + P(MST5); + DLY(100); + P(MST6); + return; + } + SC_INC; + MQ36 = MQ&1; + MQ = (AR<<35)&F0 | (MQ>>1); + AR = AR&F0 | (AR>>1); + P(MST2); + DLY(150); + goto loop; +} + +// return 1 on overflow +static int +divide(PDP6 *pdp) +{ + Word t; + P(DST10); + DLY(100); + if(IR & 0100000) { // FDV + MQ = MQ&NF0 | (AR<<35)&F0; + ashrt(pdp); + P(DST10A); + DLY(200); + } else { // DIV + MQ = (MQ<<1)&FW | ((AR>>35)^1); + P(DST10B); + DLY(200); + } + if(MB_NEG) { + P(DST11); + SBR(AR_ADD, dsf4); + } else { + P(DST12); + SBR(AR_SUB, dsf4); + } + P(DST11A); + if(!AR_NEG) { + P(DST13); + ar_set_ov(pdp); + return 1; + } +loop: + SC_INC; + t = (AR<<1)&FW | (MQ>>35)&F35; + MQ = (MQ<<1)&FW | (~AR>>35)&F35; + AR = t; + P(DST14A); + P(DST14B); + DLY(100); + if(SC != 0777) { + if((MQ ^ (MB>>35))&1) { + P(DST14); + SBR(AR_SUB, dsf5); + } else { + P(DST15); + SBR(AR_ADD, dsf5); + } + goto loop; + } + if(IR & 0100000) // FDV + ashrt(pdp); + else // DIV + AR = (~MQ&1)<<35 | AR>>1; + P(DST16); + DLY(100); + if(AR_NEG) { + if(!MB_NEG) { + P(DST17); + SBR(AR_ADD, dsf6); + } else { + P(DST18); + SBR(AR_SUB, dsf6); + } + } + P(DST17A); + if(pdp->dsf7) { + P(DST19); + SBR(AR_NEGATE, dsf8); + } + SWAP_MB_MQ; + P(DST19A); + DLY(100); + SC_CLR; + SWAP_MB_AR; + P(DST20); + DLY(100); + if(pdp->dsf7 != MQ_NEG) { + P(DST21); + SBR(AR_NEGATE, dsf9); + } + P(DST21A); + SWAP_MB_MQ; + return 0; +} + +static void +exp_calc(PDP6 *pdp, int mult) +{ + P(FPT0); + SC |= 0200; + P(FPT01); + if(AR_NEG != mult) + SC_COM; + P(FPT1); + DLY(100); + SBR(SC_ADD((AR>>27)&0777), fpf1); + if((AR_NEG == MB_NEG) != mult) { + SC_COM; + } else { + SC_INC; + P(FPT2); + } + P(FPT1A); + DLY(100); + P(FPT1AA); + SBR(SC_ADD((MB>>27)&0777), fpf2); + P(FPT1B); + if(MB_NEG == mult) + SC_COM; + DLY(100); + FE_FM_SC_1; + SC_CLR; + EXP_CLR(AR); + EXP_CLR(MB); + P(FPT3); + DLY(100); + P(FPT4); +} + +void +decode(PDP6 *pdp) +{ + pdp->estate = IR>>9; + pdp->code = codetab[pdp->estate]; + + // special handling + if(pdp->code & (CODE_SAC0_INH|CODE_UUO|CODE_IOT|CODE_JRST|CODE_CHAR)) { + if(pdp->code & CODE_SAC0_INH) { + if(((IR>>5)&017)==0) + pdp->code |= CODE_SAC_INH; + } if(pdp->code & CODE_IOT) { + if(pdp->ex_user && !pdp->cpa_iot_user && !pdp->ex_pi_sync) { + pdp->code = codetab[0]; + } else { + pdp->estate = (IR>>5)&7; + pdp->code = iotcodetab[pdp->estate]; + } + } else if(pdp->code & CODE_JRST) { + if(pdp->ex_user && (IR&(H9|H10))) + pdp->code = codetab[0]; + } else if(pdp->code & CODE_CHAR) { + if(!pdp->chf5) { + // first part + pdp->code = pdp->estate == 0133 ? 0 : CODE_PC_INC_INH; + if((pdp->estate&5) != 5 && !pdp->chf7) { + pdp->estate = CH_INC_OP; + pdp->code |= CODE_FAC_INH | CODE_FCE_PSE; + } else { + pdp->estate = CH_NOT_INC_OP; + pdp->code |= CODE_FAC_INH | CODE_FCE; + } + } else { + // second part + if((pdp->estate&6) == 4) { + pdp->estate = CH_LOAD; + pdp->code = CODE_FAC_INH | CODE_FCE; + } else if((pdp->estate&6) == 6) { + pdp->estate = CH_DEP; + pdp->code = CODE_FCE_PSE | CODE_SAC_INH; + } else + pdp->estate = NOP; // should be impossible + } + } + + if(pdp->code & CODE_UUO) + pdp->estate = UUO; + } +} + + +void +kt0(PDP6 *pdp) +{ + P(KT0); + + pdp->key_ex_st = 0; + pdp->key_dep_st = 0; + pdp->key_ex_sync = pdp->key_ex; + pdp->key_dep_sync = pdp->key_dep; + P(KT0A); + if(!pdp->run || pdp->key_mem_cont) { + if(pdp->key_mem_cont) { + pdp->mc_stop = 0; + FF(mc_rd, 0); + } else + pdp->state = KT1; // hack, key cycle not so useful for mem cont + pdp->cycling = 1; + } +} + +void +start_measure(PDP6 *pdp) +{ + pdp->sim_start = simtime; + pdp->real_start = gettime(); +} + +void +end_measure(PDP6 *pdp) +{ + pdp->sim_end = simtime; + pdp->real_end = gettime(); + u64 sim_diff = pdp->sim_end - pdp->sim_start; + u64 real_diff = pdp->real_end - pdp->real_start; + printf("ran for:\n"); + printf("real: %lld\n", real_diff); + printf("sim : %lld\n", sim_diff); + printf("%% : %f\n", (double)sim_diff/real_diff); +} + +void +clr_run(PDP6 *pdp) +{ + if(pdp->run) end_measure(pdp); + pdp->run = 0; +} + +void +key_go(PDP6 *pdp) +{ + pdp->run = 1; +start_measure(pdp); + pdp->key_ex_st = 0; + pdp->key_dep_st = 0; + pdp->key_ex_sync = 0; + pdp->key_dep_sync = 0; + pdp->cycling = 1; + pdp->state = IT0; + P(KEY_GO); +} + +#define IO_PULSE(cmd) devs_code[(IR>>8)&0177]->handler(pdp, devs_code[(IR>>8)&0177], cmd) + +#define MEM_RQ(type, state, ff) \ + FF(ff, 1); \ + type(pdp, state); \ + break; +#define MEM_RET(state, ff) \ + case state: \ + FF(ff, 0); + +#define CLK_INTERVAL 16666667 + +void +cycle(PDP6 *pdp) +{ + int test; + Word t; + + while(pdp->clk_timer < simtime) { + pdp->clk_timer += CLK_INTERVAL; + cpa_set_clock(pdp); + } + switch(pdp->state){ + case KT1: + DLY(100); + if(pdp->key_read_in || pdp->key_start || pdp->key_inst_cont || + pdp->key_ex || pdp->key_ex_nxt || + pdp->key_dep || pdp->key_dep_nxt || + pdp->key_execute || pdp->key_io_reset) + MR_CLR; +// we don't even come here with key_mem_cont + if(!(pdp->key_read_in || pdp->key_inst_cont || pdp->key_mem_cont)) + pdp->key_rim_sbr = 0; + if(pdp->key_read_in) { + MA_CLR; + PC_CLR; + pdp->key_rim_sbr = 1; + } + if(pdp->key_start) { + MA_CLR; + PC_CLR; + } + if(pdp->key_execute) + AR_CLR; + if(pdp->key_ex_sync) + MA_CLR; + if(pdp->key_ex_nxt) + MA_INC; + if(pdp->key_dep_sync) { + MA_CLR; + AR_CLR; + } + if(pdp->key_dep_nxt) { + MA_INC; + AR_CLR; + } + if(pdp->key_io_reset) + mr_start(pdp); + P(KT1); + DLY(200); + + + if(pdp->key_read_in || pdp->key_start) + MA |= pdp->mas; + if(pdp->key_execute) + AR |= pdp->datasw; + if(pdp->key_ex_sync) + MA |= pdp->mas; + if(pdp->key_dep_sync) { + MA |= pdp->mas; + AR |= pdp->datasw; + } + if(pdp->key_dep_nxt) + AR |= pdp->datasw; + P(KT2); + DLY(200); + + + if(pdp->key_read_in || pdp->key_start) + PC_FM_MA_1; + if(pdp->key_execute) + MB_FM_AR_J; + P(KT3); + + if(pdp->key_ex_sync || pdp->key_ex_nxt) { + MEM_RQ(rdrq, KEY_RDWR_RET, key_rd_wr); + // -------------------- + } + if(pdp->key_dep_sync || pdp->key_dep_nxt) { + MB_FM_AR_J; + MEM_RQ(wrrq, KEY_RDWR_RET, key_rd_wr); + // -------------------- + } + + pdp->cycling = 0; + if(pdp->key_execute) { + pdp->cycling = 1; + DLY(100); + goto it1a; + } + if(pdp->key_start || pdp->key_read_in || pdp->key_inst_cont) + key_go(pdp); + break; + + MEM_RET(KEY_RDWR_RET, key_rd_wr); + pdp->ex_ill_op = 0; + P(KEY_RDWR_RET); + if(pdp->key_ex_nxt || pdp->key_dep_nxt) + MI = MB; + P(KT4); + pdp->cycling = 0; + if(pdp->run && (pdp->key_ex_st || pdp->key_ex_st)) + key_go(pdp); + break; + + case IT0: + MA_CLR; + MR_CLR; + P(IT0); + FF(if1a, 1); + + P(PI_SYNC); + if(!pdp->pi_cyc) + PIR_STB; + + DLY(200); + + + if(pdp->pi_req && !pdp->pi_cyc) { +iat0: MR_CLR; + pdp->pi_cyc = 1; + pdp->ex_pi_sync = 1; + P(IAT0); + + DLY(200); + } else if(pdp->ia_inh) { + pdp->cycling = 0; + break; + } + + if(pdp->pi_cyc) { + MA = 040; + if(pdp->pi_req & 0017) MA |= 010; + if(pdp->pi_req & 0063) MA |= 004; + if(pdp->pi_req & 0125) MA |= 002; + if(pdp->pi_ov) MA |= 1; + } else + MA |= PC; + P(IT1); + + MEM_RQ(rdrq, IT1A, if1a); + // -------------------- +it1a: MEM_RET(IT1A, if1a); + IR |= (MB>>18) & 0777740; + if((MA & 0777760) != 0) pdp->key_rim_sbr = 0; + P(IT1A); + +at0: MEM_RET(AT0, af0); + AR_FM_MBRT_J; + IR |= (MB>>18) & 037; + MA_CLR; + P(AT0); + + P(PI_SYNC); + if(!pdp->pi_cyc) + PIR_STB; + + DLY(200); + + if(pdp->pi_req && !pdp->pi_cyc) + goto iat0; + else if(pdp->ia_inh) { + pdp->cycling = 0; + break; + } + + FF(ex_uuo_sync, 1); + P(AT1); + + if(IR & 017) { + MA |= IR & 017; + P(AT2); + + MEM_RQ(rdrq, AT3, af3); + // -------------------- + MEM_RET(AT3, af3); + MA_CLR; + P(AT3); + + SBR(AR_ADD, af3a); + + MB_FM_AR_J; + P(AT3A); + + DLY(200); + } + + AR &= RT; + P(AT4); + + if(IR & 020) { + MA_FM_MBRT_1; + IR &= 0777740; + P(AT5); + + MEM_RQ(rdrq, AT0, af0); + // -------------------- + } + +ft0: P(FT0); + decode(pdp); + if(!(pdp->code & CODE_FAC_INH)) { + MA |= (IR>>5) & 017; + P(FT1); + + MEM_RQ(rdrq, FT1A, f1a); + // -------------------- +ft1a: MEM_RET(FT1A, f1a); + if(pdp->code & CODE_FAC2) MA_INC4; + else MA_CLR; + if(pdp->code & CODE_FCCACLT) MB_SWAP; + else if(pdp->code & CODE_FCCACRT) ; // nothing + else SWAP_MB_AR; + P(FT1A); + + DLY(100); + + if(pdp->code & CODE_FAC2_ETC) { + if(pdp->code & (CODE_FCCACLT|CODE_FCCACRT)) { + MA_FM_MBRT_1; + SWAP_MB_AR; + P(FT3); + + DLY(100); + } + + MQ_FM_MB_J; + P(FT4); + + MEM_RQ(rdrq, FT4A, f4a); + // -------------------- + MEM_RET(FT4A, f4a); + MA_CLR; + SWAP_MB_MQ; + P(FT4A); + + DLY(100); + } // FAC2_ETC + } // FAC_INH + + MA_FM_MBRT_1; + P(FT5); + + if(pdp->code & CODE_FCE) { + P(FT6); + + MEM_RQ(rdrq, FT6A, f6a); + // -------------------- + } else if(pdp->code & CODE_FCE_PSE) { + P(FT7); + + MEM_RQ(rdwrrq, FT6A, f6a); + // -------------------- + } + MEM_RET(FT6A, f6a); + P(FT6A); + + // ET0A + if(PI_HOLD) + pi_hold(pdp); + if(pdp->key_ex_sync) pdp->key_ex_st = 1; + if(pdp->key_dep_sync) pdp->key_dep_st = 1; + if(pdp->key_inst_stop) clr_run(pdp); + + // ET0 + if(!pdp->pi_cyc && !(pdp->code & CODE_PC_INC_INH) && !pdp->key_execute) + PC_INC; + pdp->ar_cry0 = 0; + pdp->ar_cry1 = 0; + + // dispatch to instruction + pdp->state = pdp->estate; + break; + + case UUO: + P(ET0); + DLY(100); + MA_CLR; + MBLT_CLR; + pdp->ex_ill_op = 1; + P(ET1); + DLY(100); + MA |= 040; + P(ET3); + MB |= (Word)(IR&0777740) << 18; + P(UUO_T0); + + MEM_RQ(wrrq, UUOT1, uuo_f1); + // -------------------- + MEM_RET(UUOT1, uuo_f1); + MA_INC; + MR_CLR; + P(UUO_T1); + DLY(100); + P(UUO_T2); + MEM_RQ(rdrq, IT1A, if1a); + // -------------------- + + case 0132: // FSC + SC_FM_MB; + P(ET0); + DLY(100); + if(!AR_NEG) + SC_COM; + P(ET1); + DLY(100); + P(ET3); + if(AR_NEG) { + SC_INC; + P(FST1); + } + P(FST0); + SBR(SC_ADD((AR>>27)&0777), fsf1); + if(AR_NEG != SC_NEG) + ar_set_ov(pdp); + AR_FM_SC_J; + P(FST0A); + goto et10; + + // FAD + case 0140: + case 0141: + case 0142: + case 0143: + case 0144: + case 0145: + case 0146: + case 0147: + P(ET0); +fat0: + if(AR_NEG == MB_NEG) + SC_COM; + FF(faf1, 1); + P(FAT0); + DLY(100); + SC_PAD((MB>>27)&0777); + P(FAT1); + FF(faf1, 0); + P(FAT1B); + SBR(SC_ADD((AR>>27)&0777), faf2); + if(AR_NEG == SC_NEG) + SWAP_MB_AR; + P(FAT1A); + if(!SC_NEG) { + SC_INC; + P(FAT2); + DLY(150); + SC_COM; + P(FAT3); + DLY(150); + } else { + P(FAT4); + DLY(100); + } + if((SC&0700)==0700) { + P(FAT5); + EXP_CLR(AR); + SBR(SCT_ASHCRT, faf3); + } else { + AR_CLR; + P(FAT6); + } + SC_CLR; + FF(faf1, 1); + P(FAT5A); + DLY(100); + if(MB_NEG) + SC_COM; + P(FAT7); + DLY(100); + SC_PAD((MB>>27)&0777); + P(FAT8); + DLY(50); + EXP_CLR(MB); + P(FAT8A); + DLY(100); + P(FAT9); + SBR(AR_ADD, faf4); + FF(faf1, 0); + P(FAT10); + goto nrt05; + + // FSB + case 0150: + case 0151: + case 0152: + case 0153: + case 0154: + case 0155: + case 0156: + case 0157: + SWAP_MB_AR; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + SBR(AR_NEGATE, et4_ar_pause); + P(ET4); + goto fat0; + + // FMP + case 0160: + case 0161: + case 0162: + case 0163: + case 0164: + case 0165: + case 0166: + case 0167: + P(ET0); + P(FMT0); + SBR(exp_calc(pdp, 1), fmf1); + SC |= 0744; + P(FMT0A); + SBR(multiply(pdp), fmf2); + SC_FM_FE_1; + pdp->nrf2 = 1; + P(FMT0B); + goto nrt0dly; + + // FDV + case 0170: + case 0171: + case 0172: + case 0173: + case 0174: + case 0175: + case 0176: + case 0177: + P(ET0); + P(FDT0); + SBR(exp_calc(pdp, 0), fdf1); + SC |= 0741; + P(FDT0A); + FF(fdf2, 1); + if(AR_NEG) { + pdp->dsf7 = 1; + P(DST0); + SBR(AR_NEGATE, dsf1); + P(DST0A); + } + if(divide(pdp)) + goto st7; + FF(fdf2, 0); + SC_FM_FE_1; + pdp->nrf2 = 1; + P(FDT0B); + DLY(100); + ashcrt(pdp); + P(FDT1); + goto nrt05; + + + // Normalize return +nrt05: + FF(nrf2, 1); + P(NRT05); + DLY(100); + SC_INC; + ashcrt(pdp); + P(NRT0); + P(NRT01); + DLY(200); +nrt0dly: +// fm entry + if(AR_ZERO && !(MQ&F1)) + goto nrt6; + SC_COM; + P(NRT1); + DLY(100); + while((AR&MANTBITS)!=0400000000 && + AR_NEG == !!(AR&F9)) { + SC_INC; + ashclt(pdp); + P(NRT2); + DLY(150); + } + if(!SC_NEG) + ar_set_ov(pdp); + if(!AR_NEG || NR_ROUND) + SC_COM; + P(NRT3); + P(NRT31); + DLY(100); + if(NR_ROUND) { + P(NRT5); + SBR(AR_INC, nrf1); + pdp->nrf3 = 1; + P(NRT5A); + goto nrt05; + } + AR_FM_SC_J; + P(NRT4); +nrt6: + P(NRT6); + if(pdp->code & CODE_SCE) + MB_FM_AR_J; + goto et10; + + case CH_INC_OP: + P(ET0); + AR_FM_MB_J; + FF(chf1, 1); + P(CHT1); + DLY(100); + SC_PAD((~MB>>30)&077 | 0700); + P(CHT2); + for(;;) { + P(CHT3); + SBR(SC_ADD((MB>>24)&077), chf2); + P(CHT3A); + if(SC_NEG) + break; + SC_CLR; + P(CHT4); + SBR(AR_INC, chf3); + SC |= 0433; + P(CHT4A); + } + SC_COM; + P(CHT5); + DLY(100); + AR = (AR&~0770000000000) | (Word)(SC&077)<<30; + SC_CLR; + if(0) { + case CH_NOT_INC_OP: + P(ET0); + } + FF(chf2, 1); + P(CHT6); + DLY(150); + SC_PAD((MB>>24)&077); + if(pdp->state == CH_INC_OP) + SWAP_MB_AR; + P(CHT7); + DLY(100); + if(pdp->state == CH_INC_OP) { + P(CHT8); + MEM_RQ(wrrs, CHT8B, chf6); + // -------------------- + } + MEM_RET(CHT8B, chf6); + FF(chf2, 0); + FE_FM_MB_1; + SC_COM; + P(CHT8B); + if((IR&0777000) == 0133000) + goto st7; + SBR(sc_count(pdp, char_first), chf4); + SC_CLR; + IR &= ~037; + P(CHT8A); + DLY(100); + SC_FM_FE_1; + pdp->chf5 = 1; + pdp->chf7 = 1; + P(CHT9); + goto at0; + + case CH_LOAD: + P(ET0); + AR_FM_MB_J; + MB_FM_MQ_J; + SC_COM; + P(LCT0); + SBR(sc_count(pdp, lshrt), lcf1); + AR_FM_MB_0; + pdp->chf7 = 0; + P(LCT0A); + goto et10; + + case CH_DEP: + P(ET0); + SC_COM; + P(DCT0); + SBR(sc_count(pdp, ch_dep), dcf1); + t = MB; + MB_FM_MQ_J; + MQ |= t; + AR_COM; + P(DCT0A); // and B + DLY(150); + AR_FM_MB_0; + MB_FM_MQ_J; + P(DCT1); + DLY(100); + AR_COM; + P(DCT2); + DLY(100); + MB_FM_AR_0; + pdp->chf7 = 0; + P(DCT3); + goto et10; + + // IMUL + case 0220: + case 0221: + case 0222: + case 0223: + P(ET0); + SC |= 0734; + if(MB & AR & F0) + pdp->mpf2 = 1; + P(MPT0); + SBR(multiply(pdp), mpf1); + if(AR_NEG) { + if(pdp->mpf2) + ar_set_ov(pdp); + AR_COM; + } + P(MPT0A); + MB_FM_MQ_J; + if(AR) + ar_set_ov(pdp); + P(MPT1); + DLY(100); + AR_FM_MB_J; + P(MPT2); + DLY(100); + goto nrt6; + + // MUL + case 0224: + case 0225: + case 0226: + case 0227: + P(ET0); + SC |= 0734; + if(MB & AR & F0) + pdp->mpf2 = 1; + P(MPT0); + SBR(multiply(pdp), mpf1); + if(AR_NEG) { + if(pdp->mpf2) + ar_set_ov(pdp); + } + P(MPT0A); + goto nrt6; + + // IDIV + case 0230: + case 0231: + case 0232: + case 0233: + P(ET0); + SC |= 0733; + P(DS_DIV_T0); + if(AR_NEG) { + pdp->dsf7 = 1; + P(DST0); + SBR(AR_NEGATE, dsf1); + P(DST0A); + } + MQ_FM_MB_J; + MB_FM_AR_J; + P(DST1); + DLY(150); + SWAP_MB_MQ; + AR_CLR; + P(DST2); + goto div; + + // DIV + case 0234: + case 0235: + case 0236: + case 0237: + P(ET0); + SC |= 0733; + P(DS_DIV_T0); + if(AR_NEG) { + SWAP_MB_MQ; + pdp->dsf7 = 1; + P(DST3); + DLY(100); + SWAP_MB_AR; + P(DST4); + DLY(100); + P(DST5); + SBR(AR_NEGATE, dsf2); + P(DST5A); + // bug in schematics: have to ignore AR0 + if(AR&NF0) { + SWAP_MB_AR; + P(DST6); + DLY(100); + SWAP_MB_MQ; + AR_COM; + P(DST7); + } else { + SWAP_MB_AR; + P(DST8); + DLY(100); + SWAP_MB_MQ; + P(DST9); + SBR(AR_NEGATE, dsf3); + } + } +div: + if(divide(pdp)) + goto st7; + P(ET9); + DLY(200); + if(pdp->code & CODE_SCE) + MB_FM_AR_J; + goto et10; + +#include "instgen.inc" + + case 0250: // EXCH + SWAP_MB_AR; +nop: + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + goto et10; + + case 0251: // BLT + SWAP_MB_AR; + P(ET0); + DLY(100); + MB_SWAP; + MA_CLR; + P(ET1); + DLY(100); + MA_FM_MBRT_1; + P(ET3); + SWAP_MB_MQ; + P(BLT_T0); + MEM_RQ(wrrq, BLTT0A, blt_f0a); + // -------------------- + MEM_RET(BLTT0A, blt_f0a); + MB_FM_MQ_J; + P(BLT_T0A); + DLY(100); + SWAP_MB_AR; + P(BLT_T1); + DLY(100); + ARLT_CLR; + P(BLT_T2); + DLY(100); + P(BLT_T3); + SBR(AR_SUB, blt_f3a); + SWAP_MB_MQ; + P(BLT_T3A); + DLY(100); + SWAP_MB_AR; + P(BLT_T4); + PIR_STB; + DLY(100); + SWAP_MB_MQ; + P(BLT_T5); + SBR(AR_INC_LTRT, blt_f5a); + if(!(MQ & F0)) { + PC_INC; + pdp->code |= CODE_SAC_INH; + } + P(BLT_T5A); + if(!(MQ & F0) || pdp->pi_req) + goto et10; + SWAP_MB_AR; + P(BLT_T6); + DLY(100); + goto ft1a; + + case 0252: // AOBJP + case 0253: // AOBJN + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + SBR(AR_INC_LTRT, et4_ar_pause); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + // can't be bothered to split them just for this + test = AR_NEG == (pdp->state&1); + P(ET6); + DLY(100); + if(test) + PC_CLR; + P(ET7); + DLY(100); + if(test) + PC_FM_MA_1; + P(ET8); + DLY(200); + if(test) + PC_CHG; + P(ET9); + DLY(200); + goto et10; + + case 0254: // JRST + if(pdp->ir & H10) clr_run(pdp); + if(pdp->ir & H11) ar_flag_clr(pdp); + P(ET0); + DLY(100); + if(pdp->ir & H9) pi_rst(pdp); + if(pdp->ir & H11) ar_flag_set(pdp); + if(pdp->ir & H12) pdp->ex_mode_sync = 1; + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + MB_CLR; + P(ET5); + DLY(100); + MB_FM_PC_1; + P(ET6); + DLY(100); + PC_CLR; + P(ET7); + DLY(100); + PC_FM_MA_1; + P(ET8); + DLY(200); + if(!(pdp->ir & H11)) PC_CHG; + MA_CLR; + P(ET9); + DLY(200); + MA_FM_MBRT_1; + goto et10; + + case 0255: // JFCL + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + P(ET6); + DLY(100); + test = SELECTED_FLAGS; + if(test) PC_CLR; + P(ET7); + DLY(100); + if(test) PC_FM_MA_1; + P(ET8); + DLY(200); + if(test) PC_CHG; + P(ET9); + DLY(200); + ar_jfcl_clr(pdp); + goto et10; + + + case 0256: // XCT + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + MR_CLR; + DLY(200); + goto it1a; + + case 0257: // NOP + goto nop; + + case 0260: // PUSHJ + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + SBR(AR_INC_LTRT, et4_ar_pause); + P(ET4); + DLY(100); + MB_CLR; + P(ET5); + DLY(100); + MB_FM_PC_1; + MB_FM_MISC_BITS; + P(ET6); + DLY(100); + PC_CLR; + P(ET7); + DLY(100); + PC_FM_MA_1; + P(ET8); + DLY(200); + SWAP_MB_AR; + PC_CHG; + MA_CLR; + P(ET9); + DLY(200); + MA_FM_MBRT_1; + SWAP_MB_AR; + PDL_OV; + goto et10; + + case 0261: // PUSH + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + SBR(AR_INC_LTRT, et4_ar_pause); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SWAP_MB_AR; + MA_CLR; + P(ET9); + DLY(200); + MA_FM_MBRT_1; + SWAP_MB_AR; + PDL_OV; + goto et10; + + case 0262: // POP + MB_FM_MQ_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + SBR(AR_DEC_LTRT, et4_ar_pause); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + P(ET6); + DLY(100); + P(ET7); + DLY(100); + P(ET8); + DLY(200); + SWAP_MB_AR; + P(ET9); + DLY(200); + SWAP_MB_AR; + PDL_OV; + goto et10; + + case 0263: // POPJ + MB_FM_MQ_J; + P(ET0); + DLY(100); + MA_CLR; + P(ET1); + DLY(100); + MA_FM_MBRT_1; + P(ET3); + SBR(AR_DEC_LTRT, et4_ar_pause); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + P(ET6); + DLY(100); + PC_CLR; + P(ET7); + DLY(100); + PC_FM_MA_1; + P(ET8); + DLY(200); + SWAP_MB_AR; + PC_CHG; + P(ET9); + DLY(200); + SWAP_MB_AR; + PDL_OV; + goto et10; + + case 0264: // JSR + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + MB_CLR; + P(ET5); + DLY(100); + MB_FM_PC_1; + MB_FM_MISC_BITS; + P(ET6); + DLY(100); + PC_CLR; + if(pdp->ex_pi_sync || pdp->ex_ill_op) + pdp->ex_user = 0; + P(ET7); + DLY(100); + PC_FM_MA_1; + pdp->ex_ill_op = 0; + P(ET8); + DLY(200); + SKIP; + pdp->chf7 = 0; + P(ET9); + DLY(200); + goto et10; + + case 0265: // JSP + SWAP_MB_AR; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + MB_CLR; + P(ET5); + DLY(100); + MB_FM_PC_1; + MB_FM_MISC_BITS; + P(ET6); + DLY(100); + PC_CLR; + P(ET7); + DLY(100); + PC_FM_MA_1; + P(ET8); + DLY(200); + SWAP_MB_AR; + PC_CHG; + P(ET9); + DLY(200); + goto et10; + + case 0266: // JSA + MB_SWAP; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + MB_FM_PC_1; + P(ET6); + DLY(100); + PC_CLR; + P(ET7); + DLY(100); + PC_FM_MA_1; + P(ET8); + DLY(200); + SWAP_MB_AR; + SKIP; + P(ET9); + DLY(200); + goto et10; + + case 0267: // JRA + MB_FM_MQ_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + P(ET4); + DLY(100); + P(ET5); + DLY(100); + P(ET6); + DLY(100); + PC_CLR; + P(ET7); + DLY(100); + PC_FM_MA_1; + P(ET8); + DLY(200); + SWAP_MB_AR; + PC_CHG; + P(ET9); + DLY(200); + goto et10; + + + +et10: + if(PI_HOLD) + pi_exit(pdp); + P(ET10); + + if(pdp->code & CODE_SCE) { + P(ST1); + + MEM_RQ(wrrq, ST3, sf3); + // -------------------- + } else if(pdp->code & CODE_FCE_PSE) { + P(ST2); + + MEM_RQ(wrrs, ST3, sf3); + // -------------------- + } + + MEM_RET(ST3, sf3); + if(!(pdp->code & CODE_SAC_INH)) + MA_CLR; + P(ST3); + + if(!(pdp->code & CODE_SAC_INH)) { + P(ST3A); + + DLY(100); + + MA |= (IR>>5) & 017; + MB_FM_AR_J; + P(ST5); + + MEM_RQ(wrrq, ST5A, sf5a); + // -------------------- + MEM_RET(ST5A, sf5a); + P(ST5A); + + if(pdp->code & CODE_SAC2) { + MA_INC4; + MB = MQ; + P(ST6); + + P(ST6A); + + MEM_RQ(wrrq, ST7, sf7); + // -------------------- + } + } // SAC_INH + +st7: MEM_RET(ST7, sf7); + P(ST7); + + if(pdp->run) { + if(pdp->key_ex_st || pdp->key_dep_st) + pdp->state = KT1; + else + pdp->state = IT0; + } else + // TODO: KT4 to repeat + pdp->cycling = 0; + break; + + case IOT_BLKI: + case IOT_BLKO: + AR_FM_MB_J; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + SBR(AR_INC_LTRT, et4_ar_pause); + SWAP_MB_AR; + pdp->ex_ill_op = 0; + P(ET4); + P(IOT_T0); + MEM_RQ(wrrs, IOTT0A, iot_f0a); + // -------------------- + MEM_RET(IOTT0A, iot_f0a); + IR |= H12; + MA_CLR; + if(pdp->pi_cyc) { + if(pdp->ar_cry0) + pdp->pi_ov = 1; + } else { + if(!pdp->ar_cry0) + PC_INC; + } + P(IOT_T0A); + DLY(200); + goto ft0; + + /* In the following instructions we're ignoring + * the FINAL SETUP and IOT RESET delays. + * for more timing accuracy we will need IOT RESET eventually. */ + case IOT_DATAI: + P(ET0); + DLY(100); + AR_CLR; + if(pdp->pi_cyc && !pdp->pi_ov) + pi_rst(pdp); + P(ET1); + DLY(100); + P(ET3); + FF(iot_go, 1); + P(ET4); + IO_PULSE(IOB_DATAI); + DLY(1000); // initial setup + FF(iot_go, 0); + P(IOT_T2); + DLY(1000); // restart + AR |= IOB; + P(IOT_T3); + DLY(200); + IOB = 0; // approx + P(ET5); + MB_FM_AR_J; + goto et10; + + case IOT_CONI: + case IOT_CONSZ: + case IOT_CONSO: + AR_FM_MB_J; + P(ET0); + DLY(100); + AR_CLR; + P(ET1); + DLY(100); + P(ET3); + FF(iot_go, 1); + P(ET4); + IOB = 0; + IO_PULSE(IOB_STATUS); + DLY(1000); // initial setup + FF(iot_go, 0); + P(IOT_T2); + DLY(1000); // restart + AR |= IOB; + P(IOT_T3); + DLY(200); + IOB = 0; // approx + P(ET5); + if(pdp->state == IOT_CONI) + MB_FM_AR_J; + else { + DLY(100); + AR_FM_MB_0; + P(ET6); + DLY(100); + P(ET7); + P(ET8); + DLY(200); + if(pdp->state == IOT_CONSZ && AR_ZERO || + pdp->state == IOT_CONSO && !AR_ZERO) + SKIP; + P(ET9); + DLY(200); + } + goto et10; + + case IOT_DATAO: + AR_FM_MB_J; + P(ET0); + DLY(100); + if(pdp->pi_cyc && !pdp->pi_ov) + pi_rst(pdp); + P(ET1); + DLY(100); + P(ET3); + FF(iot_go, 1); + P(ET4); + IOB |= AR; + DLY(1000); // initial setup + FF(iot_go, 0); + P(IOT_T2); + IO_PULSE(IOB_DATAO_CLR); + DLY(1000); // restart + P(IOT_T3); + IO_PULSE(IOB_DATAO_SET); + DLY(200); + IOB = 0; // approx + P(ET5); + goto et10; + + case IOT_CONO: + MB_SWAP; + P(ET0); + DLY(100); + P(ET1); + DLY(100); + P(ET3); + AR_FM_MBLT_J; + FF(iot_go, 1); + P(ET4); + IOB |= AR; + DLY(1000); // initial setup + FF(iot_go, 0); + P(IOT_T2); + IO_PULSE(IOB_CONO_CLR); + DLY(1000); // restart + P(IOT_T3); + IO_PULSE(IOB_CONO_SET); + DLY(200); + IOB = 0; // approx + P(ET5); + goto et10; + + default: + printf("unknown state %o\n", pdp->state); + pdp->cycling = 0; + break; + } +} + +enum { + IR0 = 0400, + IR1 = 0200, + IR2 = 0100, + IR3 = 0040, + IR4 = 0020, + IR5 = 0010, + IR6 = 0004, + IR7 = 0002, + IR8 = 0001 +}; + +void +predecode(void) +{ + Code code, sac2; + int ir; + + for(ir = 0; ir < 01000; ir++) { + code = 0; + switch(ir&0700) { + case 0000: + code |= CODE_UUO | CODE_FAC_INH | CODE_PC_INC_INH; + break; + + case 0100: + switch(ir&0770) { + case 0130: + switch(ir) { + case 0132: // FSC + break; + + case 0133: // IBP + case 0134: // ILDB + case 0135: // LDB + case 0136: // IDPB + case 0137: // DPB + code |= CODE_CHAR; + break; + } + break; + + case 0140: // FAD + case 0150: // FSB + case 0160: // FMP + case 0170: // FDV + code |= CODE_FCE; + switch(ir&3) { + case 0: break; + case 1: code |= CODE_SAC2; break; + case 2: code |= CODE_SCE | CODE_SAC_INH; break; + case 3: code |= CODE_SCE; break; + } + break; + } + break; + + case 0200: + switch(ir&0770) { + case 0200: // FWT + case 0210: + switch(ir&3) { + case 0: code |= CODE_FAC_INH | CODE_FCE; break; + case 1: code |= CODE_FAC_INH; break; + case 2: code |= CODE_SCE | CODE_SAC_INH; break; + case 3: code |= CODE_FAC_INH | CODE_FCE_PSE | CODE_SAC0_INH; break; + } + break; + + case 0220: // IMUL/MUL + sac2 = ir&IR6 ? CODE_SAC2 : 0; + goto md; + case 0230: // IDIV/DIV + if(ir&IR6) code |= CODE_FAC2; + sac2 = CODE_SAC2; + md: + switch(ir&3) { + case 0: code |= CODE_FCE | sac2; break; + case 1: code |= sac2; break; + case 2: code |= CODE_FCE | CODE_SCE | CODE_SAC_INH; break; + case 3: code |= CODE_FCE | CODE_SCE | sac2; break; + } + break; + + case 0240: // Shift/Rot + switch(ir) case 0244: case 0245: case 0246: + code |= CODE_FAC2 | CODE_SAC2; + break; + case 0250: // Misc + case 0260: + switch(ir) { + case 0250: // EXCH + code |= CODE_FCE_PSE; + break; + case 0251: // BLT + code |= CODE_FCCACLT | CODE_PC_INC_INH; + break; + case 0252: // AOBJP + case 0253: // AOBJN + break; + case 0254: // JRST + code |= CODE_JRST | CODE_FAC_INH | CODE_SAC_INH; + break; + case 0255: // JFCL + code |= CODE_FAC_INH | CODE_SAC_INH; + break; + case 0256: // XCT + code |= CODE_FAC_INH | CODE_SAC_INH | CODE_FCE | CODE_PC_INC_INH; + break; + case 0257: + code |= CODE_FAC_INH | CODE_SAC_INH; + break; + case 0260: // PUSHJ + code |= CODE_SCE; + break; + case 0261: // PUSH + code |= CODE_FCE | CODE_SCE; + break; + case 0262: // POP + code |= CODE_FCCACRT | CODE_SCE; + break; + case 0263: // POPJ + code |= CODE_FCCACRT; + break; + case 0264: // JSR + code |= CODE_FAC_INH | CODE_SCE | CODE_SAC_INH; + break; + case 0265: // JSP + code |= CODE_FAC_INH; + break; + case 0266: // JSA + code |= CODE_SCE; + break; + case 0267: // JRA + code |= CODE_FCCACLT; + break; + } + break; + + case 0270: // ADD/SUB + goto boole_as; + } + break; + + case 0300: // ACCP, MEMAC + switch(ir&0760) { + case 0300: // ACCP + if(ir&IR5) + code |= CODE_FCE; + code |= CODE_SAC_INH; + break; + case 0320: // MEMAC TST + case 0340: // MEMAC +1 + case 0360: // MEMAC -1 + if(ir&IR5) + code |= CODE_FAC_INH | CODE_FCE_PSE | CODE_SAC0_INH; + break; + } + break; + + case 0400: // BOOLE + boole_as: + switch(ir&3) { + case 0: code |= CODE_FCE; break; + case 1: break; + case 2: code |= CODE_FCE_PSE | CODE_SAC_INH; break; + case 3: code |= CODE_FCE_PSE; break; + } + break; + + case 0500: // HWT + switch(ir&3) { + case 0: code |= CODE_FCE; break; + case 1: break; + case 2: code |= CODE_FCE_PSE | CODE_SAC_INH; break; + case 3: code |= CODE_FAC_INH | CODE_FCE_PSE | CODE_SAC0_INH; break; + } + break; + + case 0600: // ACBM + if(ir&IR5) + code |= CODE_FCE; + if((ir&060) == 0) + code |= CODE_SAC_INH; + break; + + case 0700: + code |= CODE_IOT; + break; + } + codetab[ir] = code; + } + + for(ir = 0; ir < 8; ir++) { + code = CODE_IOT | CODE_FAC_INH | CODE_SAC_INH; + switch(ir) { + case IOT_BLKI: + code |= CODE_FCE_PSE | CODE_PC_INC_INH; + break; + + case IOT_DATAI: + code |= CODE_SCE | CODE_PI_HOLD; + break; + + case IOT_BLKO: + code |= CODE_FCE_PSE | CODE_PC_INC_INH; + break; + + case IOT_DATAO: + code |= CODE_FCE | CODE_PI_HOLD; + break; + + case IOT_CONO: + break; + + case IOT_CONI: + code |= CODE_SCE; + break; + + case IOT_CONSZ: + break; + + case IOT_CONSO: + break; + + } + iotcodetab[ir] = code; + } +/* +#define X(bit) if(code & bit) printf("\t%s", #bit); else printf("\t\t"); + for(ir = 0; ir < 01000; ir++) { + code = codetab[ir]; + printf("%03o", ir); + X(CODE_UUO) + X(CODE_IOT) + X(CODE_JRST) + X(CODE_CHAR) + X(CODE_FAC_INH) + X(CODE_FAC2) + X(CODE_FCCACLT) + X(CODE_FCCACRT) + X(CODE_FCE) + X(CODE_FCE_PSE) + X(CODE_SAC_INH) + X(CODE_SAC0_INH) + X(CODE_SAC2) + X(CODE_SCE) + printf("\n"); + } +*/ +} + + +/* Not sure where to put this atm */ + +int ncleanups; +struct { + void (*func)(void *arg); + void *arg; +} cleanups[1000]; + +void +exitcleanup(void) +{ + for(int i = 0; i < ncleanups; i++) + cleanups[i].func(cleanups[i].arg); +} + +void +addcleanup(void (*func)(void*), void *arg) +{ + cleanups[ncleanups].func = func; + cleanups[ncleanups].arg = arg; + ncleanups++; +} diff --git a/newemu/pdp6.h b/newemu/pdp6.h new file mode 100644 index 0000000..eb72e94 --- /dev/null +++ b/newemu/pdp6.h @@ -0,0 +1,323 @@ +#include + +typedef u64 Word; +typedef u32 Hword; + +typedef struct PDP6 PDP6; + + +void addcleanup(void (*func)(void*), void *arg); +void exitcleanup(void); + + +#define F0 0400000000000 +#define F1 0200000000000 +#define F2 0100000000000 +#define F3 0040000000000 +#define F4 0020000000000 +#define F5 0010000000000 +#define F6 0004000000000 +#define F7 0002000000000 +#define F8 0001000000000 +#define F9 0000400000000 +#define F10 0000200000000 +#define F11 0000100000000 +#define F12 0000040000000 +#define F13 0000020000000 +#define F14 0000010000000 +#define F15 0000004000000 +#define F16 0000002000000 +#define F17 0000001000000 +#define F18 0000000400000 +#define F19 0000000200000 +#define F20 0000000100000 +#define F21 0000000040000 +#define F22 0000000020000 +#define F23 0000000010000 +#define F24 0000000004000 +#define F25 0000000002000 +#define F26 0000000001000 +#define F27 0000000000400 +#define F28 0000000000200 +#define F29 0000000000100 +#define F30 0000000000040 +#define F31 0000000000020 +#define F32 0000000000010 +#define F33 0000000000004 +#define F34 0000000000002 +#define F35 0000000000001 +#define LT 0777777000000 +#define RT 0777777 +#define FW 0777777777777 + +typedef u32 Code; +struct PDP6 +{ + int cycling; + int state, estate; + Code code; + + bool key_start; + bool key_read_in; + bool key_mem_stop; + bool key_mem_cont; + bool key_inst_stop; + bool key_inst_cont; + bool key_ex; + bool key_ex_nxt; + bool key_dep; + bool key_dep_nxt; + bool key_io_reset; + bool key_execute; + + bool key_manual; // for convenience + + bool sw_power; + bool sw_mem_disable; + bool sw_addr_stop; + bool sw_repeat; + + bool run; + bool key_rim_sbr; + bool mc_stop; + + bool key_ex_st; + bool key_dep_st; + bool key_ex_sync; + bool key_dep_sync; + + Word ar; + Word mq; + u8 mq36; + Word mb; + Word mi; + Word datasw; + Hword pc; + Hword ma; + Hword mas; + Hword ir; + + Hword fe, sc; // 9 bits + + Word iob; + u8 iob_req; + + // SBR flip flops + // memory + bool key_rd_wr; + bool if1a; + bool af0, af3; + bool f1a, f4a, f6a; + bool sf3, sf5a, sf7; + bool uuo_f1; + bool blt_f0a; + bool iot_f0a; + bool chf6; + // AR + bool ar_com_cont; + bool af3a; + bool et4_ar_pause; + bool chf3; + bool blt_f3a, blt_f5a; + bool faf4; + bool msf1; + bool nrf1; + bool dsf1, dsf2, dsf3, dsf4, dsf5, dsf6, dsf8, dsf9; + // shift count + bool shf1; + bool chf4, lcf1, dcf1, faf3; + // SC add + bool chf2; + bool fsf1; + bool faf2; + bool fpf1, fpf2; + // exponent + bool fmf1; + bool fdf1; + // multiply + bool mpf1; + bool fmf2; + // divide + bool fdf2; + + // misc FFs + bool faf1; // SC PAD enable + bool chf1; // SC PAD enable + bool nrf2; // ASHC enable + bool nrf3; // NR ROUND disable + bool dsf7; // division sign flag + bool mpf2; // multiply sign flag + bool iot_go; + + // char state + bool chf5, chf7; + + bool pi_active; + bool pi_cyc, pi_ov; + bool pi_on; + u8 pio, pir, pih, pi_req; + + bool ex_user; + bool ex_mode_sync; + bool ex_pi_sync; + bool ex_uuo_sync; + bool ex_ill_op; + Hword pr, rlr, rla; + + bool mc_rq, mc_rd, mc_wr; + + bool cpa_iot_user; + bool cpa_illeg_op; + bool cpa_non_exist_mem; + bool cpa_clock_enable; + bool cpa_clock_flag; + bool cpa_pc_chg_enable; + bool cpa_pdl_ov; + bool cpa_arov_enable; + u8 cpa_pia; + + + bool ar_cry0, ar_cry1; + bool ar_cry0_flag, ar_cry1_flag; + bool ar_ov_flag; + bool ar_pc_chg_flag; + + + /* PTP */ + bool sw_ptr_motor_on; + bool sw_ptr_motor_off; + bool ptp_tape_feed; + bool ptp_motor_on; + bool ptp_busy; + bool ptp_flag; + bool ptp_b; + u8 ptp; + int ptp_pia; + int ptp_fd; + u64 ptp_punch_timer; + u64 ptp_motor_off_timer; + u64 ptp_motor_on_timer; + + + /* PTR */ + bool ptr_tape_feed; + bool ptr_motor_on; + bool ptr_clutch; + u8 ptr_sr; + Word ptr; + bool ptr_busy; + bool ptr_flag; + bool ptr_b; + int ptr_pia; + int ptr_fd; + u64 ptr_timer; + + + /* TTY */ + u8 tty_pia; + bool tto_busy; + bool tto_flag; + bool tto_active; + u8 tto; + bool tti_busy; + bool tti_flag; + u8 tti; + // + int tty_baud, tty_dly; + int tty_fd; + int tti_state; + u64 tti_timer; + u64 tto_timer; + + + bool dotrace; + u64 clk_timer; + + /* temp - for time measurement */ + u64 sim_start, sim_end; + u64 real_start, real_end; + + bool ia_inh; + u64 ia_inh_timer; +}; + +void predecode(void); +void pwrclr(PDP6 *pdp); +void kt0(PDP6 *pdp); +void cycle(PDP6 *pdp); +void clr_run(PDP6 *pdp); + +extern u64 simtime; +extern u64 realtime; + + +enum { + IOB_CONO_CLR, + IOB_CONO_SET, + IOB_DATAO_CLR, + IOB_DATAO_SET, + IOB_DATAI, + IOB_STATUS, + IOB_RESET +}; + +typedef struct IOdev IOdev; +struct IOdev { + u8 req; + int devcode; + void *dev; + void (*handler)(PDP6 *pdp, IOdev *dev, int cmd); + void (*cycle)(PDP6 *pdp, IOdev *dev, int pwr); +}; +void initdevs(PDP6 *pdp); +void installdev(PDP6 *pdp, IOdev *dev); +void cycle_io(PDP6 *pdp, int pwr); +void setreq(PDP6 *pdp, IOdev *dev, u8 req); + +void attach_ptp(PDP6 *pdp); +void ptr_set_motor(PDP6 *pdp, int state); +void attach_ptr(PDP6 *pdp); +void attach_tty(PDP6 *pdp); + + +typedef struct Dis340 Dis340; +Dis340 *attach_dis(PDP6 *pdp); +void dis_connect(Dis340 *dis, int fd); + + +typedef struct Dc136 Dc136; +struct Dc136 +{ + PDP6 *pdp; + + int pia; + int device; + int ch_mode; + + Word da; + Word db; + int cct; + int sct; + + bool data_clbd; + bool dbda_move; + bool darq; + bool dbrq; + bool inout; +}; +Dc136 *attach_dc(PDP6 *pdp); +int dctkgv(Dc136 *dc, int dev, int ch, int rt); + +typedef struct Ux555 Ux555; +typedef struct Ut551 Ut551; +Ut551 *attach_ut(PDP6 *pdp, Dc136 *dc); +Ux555 *attach_ux(Ut551 *ut, int num); +void uxmount(Ux555 *ux, const char *path); +void uxunmount(Ux555 *ux); + +void attach_ge(PDP6 *pdp); + + +void initmusic(void); +void stopmusic(void); +void svc_music(PDP6 *pdp); diff --git a/newemu/pt.c b/newemu/pt.c new file mode 100644 index 0000000..a54f471 --- /dev/null +++ b/newemu/pt.c @@ -0,0 +1,266 @@ +#include "common.h" +#include "pdp6.h" + +#include + +#define IOB pdp->iob +#define PTP_DLY 15797788 // 63.3 chars per second +#define PTR_DLY 2500000 // 400 chars per second + + + +/* PTP */ + +static void calc_ptp_req(PDP6 *pdp); + +static void +handle_ptp(PDP6 *pdp, IOdev *dev, int cmd) +{ + switch(cmd) { + case IOB_RESET: + case IOB_CONO_CLR: + pdp->ptp_b = 0; + pdp->ptp_busy = 0; + pdp->ptp_flag = 0; + pdp->ptp_pia = 0; + break; + + case IOB_CONO_SET: + if(IOB & F30) pdp->ptp_b = 1; + if(IOB & F31) pdp->ptp_busy = 1; + if(IOB & F32) pdp->ptp_flag = 1; + pdp->ptp_pia |= IOB & 7; + break; + + case IOB_STATUS: + if(pdp->ptp_b) IOB |= F30; + if(pdp->ptp_busy) IOB |= F31; + if(pdp->ptp_flag) IOB |= F32; + IOB |= pdp->ptp_pia; + return; + + case IOB_DATAO_CLR: + pdp->ptp_busy = 1; + pdp->ptp_flag = 0; + pdp->ptp = 0; + return; + + case IOB_DATAO_SET: + pdp->ptp |= IOB & 0377; + break; + } + calc_ptp_req(pdp); +} + +static void +ptp_set_motor(PDP6 *pdp, int state) +{ + if(pdp->ptp_motor_on == state) + return; + pdp->ptp_motor_on = state; + if(!pdp->ptp_motor_on) + pdp->ptp_motor_on_timer = NEVER; + else + pdp->ptp_punch_timer = simtime + PTP_DLY; +} + +static void +cycle_ptp(PDP6 *pdp, IOdev *dev, int pwr) +{ + u8 c; + bool go; + + if(!pwr) { + pdp->ptp_motor_on = 0; + pdp->ptp_motor_on_timer = NEVER; + return; + } + + go = pdp->ptp_busy || pdp->ptp_tape_feed; + if(go) { + pdp->ptp_motor_off_timer = simtime + 5000000000; + if(pdp->ptp_motor_on_timer == NEVER) + pdp->ptp_motor_on_timer = simtime + 1000000000; + } + + if(!pdp->ptp_motor_on && pdp->ptp_motor_on_timer < simtime) + ptp_set_motor(pdp, 1); + if(pdp->ptp_motor_off_timer < simtime) + ptp_set_motor(pdp, 0); + + if(!pdp->ptp_motor_on) + return; + if(pdp->ptp_punch_timer < simtime) { + // reluctance pickup + pdp->ptp_punch_timer = simtime + PTP_DLY; + if(pdp->ptp_busy) // PTP READY + c = (pdp->ptp_b ? pdp->ptp&077|0200 : pdp->ptp); + else if(pdp->ptp_tape_feed) + c = 0; + else + return; + + if(pdp->ptp_fd >= 0) + if(write(pdp->ptp_fd, &c, 1) <= 0) { + close(pdp->ptp_fd); + pdp->ptp_fd = -1; + } + + // PTP DONE + if(pdp->ptp_busy) { + pdp->ptp_busy = 0; + pdp->ptp_flag = 1; + calc_ptp_req(pdp); + } + } +} + +static IOdev ptp_dev = { 0, 0100, handle_ptp, cycle_ptp }; + +static void +calc_ptp_req(PDP6 *pdp) +{ + if(pdp->ptp_pia && pdp->ptp_flag) + setreq(pdp, &ptp_dev, 0200>>pdp->ptp_pia); + else + setreq(pdp, &ptp_dev, 0); +} + +void +attach_ptp(PDP6 *pdp) +{ + installdev(pdp, &ptp_dev); +} + +/* PTR */ + +static void calc_ptr_req(PDP6 *pdp); + +void +ptr_set_motor(PDP6 *pdp, int state) +{ + if(pdp->ptr_motor_on == state) + return; + pdp->ptr_motor_on = state; + + if(pdp->ptr_motor_on) + pdp->ptr_busy = 0; + pdp->ptr_flag = 1; + calc_ptr_req(pdp); +} + +static void +ptr_set_busy(PDP6 *pdp) +{ + if(!pdp->ptr_busy) { + // PTR CLR + pdp->ptr_sr = 0; + pdp->ptr = 0; + } + pdp->ptr_busy = 1; +} + +static void +handle_ptr(PDP6 *pdp, IOdev *dev, int cmd) +{ + switch(cmd) { + case IOB_RESET: + // hack for easier use. NB: this breaks diagnostics + ptr_set_motor(pdp, 1); + case IOB_CONO_CLR: + pdp->ptr_b = 0; + pdp->ptr_busy = 0; + pdp->ptr_flag = 0; + pdp->ptr_pia = 0; + break; + + case IOB_CONO_SET: + if(IOB & F27) ptr_set_motor(pdp, 1); // not in schematics, can we turn it off too? + if(IOB & F30) pdp->ptr_b = 1; + if(IOB & F31) ptr_set_busy(pdp); + if(IOB & F32) pdp->ptr_flag = 1; + pdp->ptr_pia |= IOB & 7; + break; + + case IOB_STATUS: + if(pdp->ptr_motor_on) IOB |= F27; + if(pdp->ptr_b) IOB |= F30; + if(pdp->ptr_busy) IOB |= F31; + if(pdp->ptr_flag) IOB |= F32; + IOB |= pdp->ptr_pia; + return; + + case IOB_DATAI: + IOB |= pdp->ptr; + pdp->ptr_flag = 0; + // actually after DATAI negated + ptr_set_busy(pdp); + break; + } + calc_ptr_req(pdp); +} + +static void +cycle_ptr(PDP6 *pdp, IOdev *dev, int pwr) +{ + bool clutch; + u8 c; + + if(!pwr) return; + + if(pdp->sw_ptr_motor_on) ptr_set_motor(pdp, 1); + if(pdp->sw_ptr_motor_off) ptr_set_motor(pdp, 0); + + clutch = pdp->ptr_motor_on && (pdp->ptr_busy | pdp->ptr_tape_feed); + if(clutch && !pdp->ptr_clutch) { + // start motion + pdp->ptr_timer = simtime + PTR_DLY; + } + pdp->ptr_clutch = clutch; + if(!pdp->ptr_clutch || pdp->ptr_timer >= simtime) + return; + pdp->ptr_timer = simtime + PTR_DLY; + + if(!hasinput(pdp->ptr_fd)) + return; + if(read(pdp->ptr_fd, &c, 1) <= 0) { + close(pdp->ptr_fd); + pdp->ptr_fd = -1; + return; + } + if(pdp->ptr_busy && (c & 0200 || !pdp->ptr_b)) { + // PTR STROBE + // actually 400μs after feed hole edge + pdp->ptr_sr = (pdp->ptr_sr<<1) | 1; + pdp->ptr <<= 6; + if(pdp->ptr_b) + pdp->ptr |= c & 077; + else + pdp->ptr |= c; + + // PTR TRAIL + // only if busy but that's guaranteed here + if(!pdp->ptr_b || pdp->ptr_sr & 040) { + pdp->ptr_busy = 0; + pdp->ptr_flag = 1; + calc_ptr_req(pdp); + } + } +} + +static IOdev ptr_dev = { 0, 0104, nil, handle_ptr, cycle_ptr }; + +static void +calc_ptr_req(PDP6 *pdp) +{ + if(pdp->ptr_pia && pdp->ptr_flag) + setreq(pdp, &ptr_dev, 0200>>pdp->ptr_pia); + else + setreq(pdp, &ptr_dev, 0); +} + +void +attach_ptr(PDP6 *pdp) +{ + installdev(pdp, &ptr_dev); +} diff --git a/newemu/tty.c b/newemu/tty.c new file mode 100644 index 0000000..af6116d --- /dev/null +++ b/newemu/tty.c @@ -0,0 +1,134 @@ +#include "common.h" +#include "pdp6.h" + +#include + +#define IOB pdp->iob + +static void calc_tty_req(PDP6 *pdp); + +static void +handle_tty(PDP6 *pdp, IOdev *dev, int cmd) +{ + switch(cmd) { + case IOB_RESET: + pdp->tty_pia = 0; + pdp->tto_busy = 0; + pdp->tto_flag = 0; + pdp->tti_busy = 0; + pdp->tti_flag = 0; + pdp->tti_timer = 0; + break; + case IOB_CONO_CLR: + pdp->tty_pia = 0; + return; + case IOB_CONO_SET: + pdp->tty_pia |= IOB & 7; + if(IOB & F32) pdp->tto_flag = 1; + if(IOB & F31) pdp->tto_busy = 1; + if(IOB & F30) pdp->tti_flag = 1; + if(IOB & F29) pdp->tti_busy = 1; + if(IOB & F28) pdp->tto_flag = 0; + if(IOB & F27) pdp->tto_busy = 0; + if(IOB & F26) pdp->tti_flag = 0; + if(IOB & F25) pdp->tti_busy = 0; + break; + case IOB_DATAO_CLR: + pdp->tto_busy = 1; + pdp->tto_flag = 0; + break; + case IOB_DATAO_SET: + pdp->tto |= IOB & 0377; + pdp->tto_active = 1; // not really, but close enough + pdp->tto_timer = simtime + pdp->tty_dly*11; + break; + case IOB_DATAI: + pdp->tti_flag = 0; + IOB |= pdp->tti; + break; + case IOB_STATUS: + IOB |= pdp->tty_pia; + if(pdp->tto_flag) IOB |= F32; + if(pdp->tto_busy) IOB |= F31; + if(pdp->tti_flag) IOB |= F30; + if(pdp->tti_busy) IOB |= F29; + return; + } + calc_tty_req(pdp); +} + +static void +cycle_tty(PDP6 *pdp, IOdev *dev, int pwr) +{ + if(!pwr) { + pdp->tto_active = 0; + pdp->tti_state = 0; + return; + } + + if(pdp->tto_active && pdp->tto_timer < simtime) { + pdp->tto_active = 0; + if(pdp->tty_fd >= 0) { + char c = pdp->tto & 0177; + write(pdp->tty_fd, &c, 1); + } + pdp->tto = 0; + pdp->tto_busy = 0; + pdp->tto_flag = 1; + calc_tty_req(pdp); + } + + // timing is awkward right now, we think in bit-times + // 11 bits per char (start, 8 bit chars, 2 stop) + // t=0 read char + // t=9 set flag (simulate reading done) + // t=11 ready to accept next char + if(pdp->tti_timer < simtime) { + pdp->tti_timer = simtime + pdp->tty_dly; + if(pdp->tti_state == 0) { + if(hasinput(pdp->tty_fd)) { + char c; + if(read(pdp->tty_fd, &c, 1) <= 0) { + close(pdp->tty_fd); + pdp->tty_fd = -1; + return; + } + pdp->tti = c; + pdp->tti_busy = 1; + pdp->tti_flag = 0; + calc_tty_req(pdp); + + pdp->tti_timer += pdp->tty_dly*8; + pdp->tti_state = 1; + } + } else { + if(pdp->tti_busy) { + pdp->tti_busy = 0; + pdp->tti_flag = 1; + calc_tty_req(pdp); + + pdp->tti_timer += pdp->tty_dly; + pdp->tti_state = 0; + } + } + } +} + +static IOdev tty_dev = { 0, 0120, nil, handle_tty, cycle_tty }; + +static void +calc_tty_req(PDP6 *pdp) +{ + if(pdp->tty_pia && (pdp->tti_flag || pdp->tto_flag)) + setreq(pdp, &tty_dev, 0200>>pdp->tty_pia); + else + setreq(pdp, &tty_dev, 0); +} + +void +attach_tty(PDP6 *pdp) +{ + pdp->tty_baud = 110; + pdp->tty_dly = 1000000000 / pdp->tty_baud; + installdev(pdp, &tty_dev); +} diff --git a/newemu/ut.c b/newemu/ut.c new file mode 100644 index 0000000..f73d533 --- /dev/null +++ b/newemu/ut.c @@ -0,0 +1,616 @@ +#include "common.h" +#include "pdp6.h" + +#include +#include + +#define MOVEDLY 33333 +// very approximate, unfortunately no hard data for this +#define STARTDLY 200000000 +#define STOPDLY 100000000 // not sure how to use this one here +#define TURNDLY 250000000 +// ~350 lines per inch, ~4.56in per block +// again very approximate +#define STARTDIST 7*350 +#define STOPDIST 8*350 +// after turnaround we will have passed the location that we turned at +// TENDMP assumes one block of turnaround space +// MACDMP assumes two +#define TURNDIST 2*350 + +struct Ux555 +{ + int fd; + + u8 *buf; + int size, pos; + bool written; + bool flapping; + u64 timer; + bool tp; + + bool wrlock; + int num; // 0-7 + // from controller: + int go; + int rev; +}; + +struct Ut551 +{ + Dc136 *dc; + int dcdev; + + Ux555 *transports[8]; + Ux555 *sel; + + bool btm_sw; + + bool units_select; + bool tape_end_en; + bool jb_done_en; + bool go; + bool rev; + bool time_en; + int time; + int fcn; + int units; + int pia; + + bool incomp_block; + bool wren; + bool time_flag; + bool info_error; + bool illegal_op; + bool tape_end_flag; + bool jb_done_flag; + + int utek; + bool uteck; + + int lb; + int rwb; + int wb; + + int tbm; + int tdata; + int tmk; + int tct; + + int ramp; // read amplifiers + int state; + bool start_dly; + u64 dlyend; +}; + + + +Ux555* +attach_ux(Ut551 *ut, int num) +{ + int i; + Ux555 *ux = malloc(sizeof(Ux555)); + + ux->fd = -1; + ux->buf = nil; + ux->size = 0; + ux->pos = 0; + ux->tp = 0; + + ux->wrlock = 0; + ux->num = num & 7; + ux->go = 0; + ux->rev = 0; + + for(i = 0; i < 8; i++) + if(ut->transports[i] == nil) { + ut->transports[i] = ux; + break; + } + + addcleanup((void (*)(void*))uxunmount, ux); + + return ux; +} + +void +uxunmount(Ux555 *ux) +{ + if(ux->fd < 0) + return; + + if(ux->written) { + lseek(ux->fd, 0, SEEK_SET); + write(ux->fd, ux->buf, ux->size); + } + + close(ux->fd); + ux->fd = -1; + + free(ux->buf); + ux->buf = nil; +} + +void +uxmount(Ux555 *ux, const char *path) +{ + uxunmount(ux); + + ux->fd = open(path, O_RDWR); + if(ux->fd < 0) { + ux->fd = open(path, O_RDONLY); + if(ux->fd < 0) { + fprintf(stderr, "can't open file <%s>\n", path); + return; + } + ux->wrlock = 1; + } + ux->size = lseek(ux->fd, 0, SEEK_END); + ux->buf = malloc(ux->size); + lseek(ux->fd, 0, SEEK_SET); + read(ux->fd, ux->buf, ux->size); + ux->written = 0; + ux->pos = 100; + ux->flapping = ux->pos >= ux->size; // hopefully always true + ux->tp = 0; + ux->go = 0; + ux->rev = 0; +printf("μt unit %d file <%s>, len %d lock? %d\n", ux->num, path, ux->size, ux->wrlock); +} + +static void +uxmove(Ux555 *ux) +{ + if(!ux->go || ux->timer >= simtime) + return; + ux->timer += MOVEDLY; + if(ux->rev) { + if(--ux->pos < 0) +//printf("flap back\n"), + ux->flapping = 1; + } else { + if(++ux->pos >= ux->size) +//printf("flap fwd\n"), + ux->flapping = 1; + } + if(!ux->flapping) + ux->tp = 1; +} + +static void +uxsetmotion(Ux555 *ux, int go, int rev) +{ + if(ux->go != go) { + if(!ux->go) { +//printf("start transport\n"); + // start transport + ux->timer = simtime + STARTDLY; + ux->pos += rev ? -STARTDIST : STARTDIST; + } else { + // stop transport +//printf("stop transport\n"); + ux->pos += ux->rev ? -STOPDIST : STOPDIST; + } + ux->go = go; + } else if(ux->go && ux->rev != rev) { +//printf("turn transport\n"); + // turn around transport + ux->timer = simtime + TURNDLY; + ux->pos += rev ? -TURNDIST : TURNDIST; + } + ux->rev = rev; +} + + + + +#define IOB pdp->iob + +enum { + RW_NULL, + RW_RQ, + RW_ACTIVE, +}; + +#define UT_DN (ut->fcn == 0) +#define UT_RDA (ut->fcn == 1) +#define UT_RDBM (ut->fcn == 2) +#define UT_RDD (ut->fcn == 3) +#define UT_WRTM (ut->fcn == 4) +#define UT_WRA (ut->fcn == 5) +#define UT_WRBM (ut->fcn == 6) +#define UT_WRD (ut->fcn == 7) +#define UT_WRITE (ut->fcn & 4) +#define UT_READ !UT_WRITE +#define UT_ALL (UT_RDA || UT_WRA) +#define UT_BM (UT_RDBM || UT_WRBM) +#define UT_DATA (UT_RDD || UT_WRD) + +#define MK_BM_SPACE ((ut->tmk & 0477) == 0425) +#define MK_BM_SYNC (ut->tmk == 0751) +#define MK_DATA_SYNC (ut->tmk == 0632) +#define MK_BM_END (ut->tmk == 0526) +#define MK_FWD_DATA_END (ut->tmk == 0773 || ut->tmk == 0473) +#define MK_REV_DATA_END (ut->tmk == 0610 || ut->tmk == 0410) +#define MK_END (ut->tmk == 0622) +#define MK_DATA (ut->tmk == 0470) +#define MK_DATA_END (MK_FWD_DATA_END || MK_REV_DATA_END) + +#define UTE_DC_DISCONNECT (ut->dc->darq || ut->dc->device != ut->dcdev) +#define UTE_MK (MK_BM_END || MK_BM_SYNC || MK_DATA_END || MK_DATA_SYNC || MK_DATA) + +static void calc_ut_req(PDP6 *pdp, Ut551 *ut); + +static int +utsel(Ut551 *ut) +{ + int i, num, nsel; + + num = ut->units; + // weirdness: ~UNITS SELECT only disables 0 and 1 + if(!ut->units_select && num < 2) + num = -1; + + nsel = 0; + ut->sel = nil; + for(i = 0; i < 8; i++) + if(ut->transports[i] && ut->transports[i]->num == num) { + ut->sel = ut->transports[i]; + nsel++; + } + if(nsel != 1) + ut->sel = nil; + return nsel; +} + +static void +tp0(Ut551 *ut) +{ + Ux555 *ux = ut->sel; + + if(ut->state == RW_ACTIVE) { + ut->wren = 1; + + if(UT_WRITE) { + // RWB(J)->WB + ut->wb = (ut->rwb >> (ut->tct?0:3))&7; + if(ut->rev) ut->wb ^= 7; + if(ux->wrlock) + ut->illegal_op = 1; + } + } +} + +static void +tp1(Ut551 *ut) +{ + // write complement - rather useless for us here + if(UT_WRITE) + ut->wb ^= 7; + + // advance TMK + if(!ut->start_dly && !UT_WRTM) + ut->tmk = ((ut->tmk<<1) | (ut->ramp>>3)&1)&0777 | ut->tmk&0400; + + // strobe data into RWB + if(ut->state == RW_ACTIVE && UT_READ) { + int c = ut->rev && !UT_RDBM ? 7 : 0; + if(ut->tct) + ut->rwb |= ut->ramp&7 ^ c; + else + ut->rwb |= (ut->ramp&7 ^ c) << 3; + } +} + +static void +tp2(Ut551 *ut) +{ + bool wasdone = ut->jb_done_flag; + + if(ut->state == RW_ACTIVE) { + if(ut->tct) { + // RW EVEN + ut->lb ^= ~ut->rwb & 077; + if(UT_READ && (ut->tdata&0102)==0) { + // RWB<->DC + ut->rwb |= dctkgv(ut->dc, ut->dcdev, ut->rwb, ut->rev && !UT_RDBM); + if(UTE_DC_DISCONNECT) + ut->incomp_block = 1; + } + } + ut->tct ^= 1; + + if(UT_BM && MK_BM_END) + ut->jb_done_flag = 1; + + if(!UT_ALL && (MK_BM_SYNC || MK_DATA_SYNC)) { + ut->info_error = 1; + ut->state = RW_NULL; + } + } else + ut->tct = 0; + + if(ut->uteck && UTE_MK != (ut->utek==040)) + ut->info_error = 1; + + if(!MK_BM_SPACE) + ut->utek = (ut->utek>>1) | (ut->utek&1)<<5; + + + // only interested in rising edges here + int tbmedge = ~ut->tbm; + if(MK_BM_SYNC) ut->tbm = 010 | ut->tbm>>1; + else if(MK_BM_SPACE) ut->tbm >>= 1; + tbmedge &= ut->tbm; + + // need both rising and falling edges + int tdedge = ut->tdata; + if(MK_DATA_SYNC) ut->tdata = 0200 | ut->tdata>>1; + else if(MK_DATA_END) ut->tdata >>= 1; + tdedge ^= ut->tdata; + + if(tdedge & ut->tdata & 0100) + ut->lb = 0; + + if(ut->state == RW_RQ) { + if(UT_BM && tbmedge & 1 || + UT_ALL && tbmedge & 010 || + UT_DATA && tdedge & ut->tdata & 0100) + ut->state = RW_ACTIVE; + } else if(ut->state == RW_ACTIVE && UT_DATA && (tdedge & ~ut->tdata & 2)) { + if(UTE_DC_DISCONNECT) + ut->jb_done_flag = 1; + else + ut->state = RW_RQ; + } + + if(ut->jb_done_flag && !wasdone) + ut->state = RW_NULL; +} + +static void +tp3(Ut551 *ut) +{ + if(ut->state == RW_ACTIVE && !ut->tct) + ut->rwb = 0; + + if(UT_READ && (UT_ALL | UT_DATA) && ut->tdata & 1 && + ut->lb != 077) + ut->info_error = 1; + + if(ut->tbm & 1) { + if(MK_BM_SPACE) + ut->utek = 040; + else + ut->uteck = 1; + } + if(MK_BM_SYNC) + ut->uteck = 0; + + if(MK_END) { + ut->tape_end_flag = 1; + ut->state = RW_NULL; + } +} + +static void +tp4(Ut551 *ut) +{ + if(ut->state != RW_ACTIVE) + ut->wren = 0; + else if(!ut->tct) { + if(UT_WRITE && UT_DATA && ut->tdata & 2) + ut->rwb |= ut->lb; + if(UT_WRITE && (ut->tdata&0102)==0 || UT_WRTM) { + // RWB<->DC + // writing - so no need to check RDBM + ut->rwb |= dctkgv(ut->dc, ut->dcdev, ut->rwb, ut->rev); + if(UTE_DC_DISCONNECT) + ut->incomp_block = 1; + } + } +} + +static void +cycle_ut(PDP6 *pdp, IOdev *dev, int pwr) +{ + int i; + Ut551 *ut = (Ut551*)dev->dev; + Ux555 *ux; + + if(!pwr) { + ut->dlyend = NEVER; + return; + } + + int doreq = 0; + if(ut->start_dly && ut->dlyend < simtime) { +//printf("delay done\n"); + ut->dlyend = NEVER; + ut->start_dly = 0; + ut->time_flag = 1; + if(utsel(ut) != 1) { + ut->go = 0; + ut->illegal_op = 1; + } + if(UT_WRTM != ut->btm_sw) + ut->illegal_op = 1; + if(UT_WRTM) + ut->state = RW_ACTIVE; + else if(!UT_DN) + ut->state = RW_RQ; + doreq = 1; + } + + if(ut->tape_end_flag) + ut->go = 0; + + // move transports + ux = ut->sel; + if(ux) + uxsetmotion(ux, ut->go, ut->rev); + for(i = 0; i < 8; i++) + if(ut->transports[i]) + uxmove(ut->transports[i]); + + if(ux && ux->tp) { + ux->tp = 0; + doreq = 1; + + // rising edge of time track + int mask = ux->rev ? 017 : 0; + ut->ramp = ux->buf[ux->pos] ^ mask; + + // which fires TP0 - write load + tp0(ut); + + // write back at some point + if(UT_WRITE && ut->wren && !ux->wrlock) { + if(UT_WRTM && ut->btm_sw) + ux->buf[ux->pos] = ((ut->wb<<1)&010 | ut->wb) ^ mask; + else + ux->buf[ux->pos] = (ut->ramp&010 | ut->wb) ^ mask; + ux->written = 1; + } + + // ca 16.6μs later + + // falling edge of time track + // write complement - read strobe + tp1(ut); + // NB we don't also write the complement + tp2(ut); + tp3(ut); + tp4(ut); + } + + if(doreq) calc_ut_req(pdp, ut); +} + +static void +handle_ut(PDP6 *pdp, IOdev *dev, int cmd) +{ + Ut551 *ut = (Ut551*)dev->dev; + + switch(cmd) { + case IOB_RESET: + case IOB_CONO_CLR: + ut->incomp_block = 0; + ut->wren = 0; + ut->time_flag = 0; + ut->info_error = 0; + ut->illegal_op = 0; + ut->tape_end_flag = 0; + ut->jb_done_flag = 0; + + ut->units_select = 0; + ut->tape_end_en = 0; + ut->jb_done_en = 0; + ut->go = 0; + ut->rev = 0; + ut->time_en = 0; + ut->time = 0; + ut->fcn = 0; + ut->units = 0; + ut->pia = 0; + + ut->state = RW_NULL; + break; + + case IOB_CONO_SET: +//printf("CONO UT %o (PC %06o)\n", (int)IOB&0777777, pdp->pc); + if(IOB & F1) ut->units_select = 1; + if(IOB & F2) ut->tape_end_en = 1; + if(IOB & F3) ut->jb_done_en = 1; + if(IOB & F4) ut->go = 1; + if(IOB & F5) ut->rev = 1; + if(IOB & F6) ut->time_en = 1; + ut->time |= (IOB>>27) & 3; + ut->fcn |= (IOB>>24) & 7; + ut->units |= (IOB>>21) & 7; + ut->pia |= (IOB>>18) & 7; + + // command is effective before selection changes + if(ut->sel) uxsetmotion(ut->sel, ut->go, ut->rev); + + utsel(ut); + + if(ut->time == 0) { + // bit strange for DN and WRTM + ut->state = RW_RQ; + } else { + static int dlytab[4] = { 0, 35000000, 225000000, 300000000 }; + ut->dlyend = simtime + dlytab[ut->time]; + ut->start_dly = 1; + // T CLEAR + ut->tbm = 0; + ut->tdata = 0; + ut->tmk = 0; + ut->uteck = 0; + } + break; + + case IOB_STATUS: + if(ut->units_select) IOB |= F19; + if(ut->tape_end_en) IOB |= F20; + if(ut->jb_done_en) IOB |= F21; + if(ut->go) IOB |= F22; + if(ut->rev) IOB |= F23; + if(ut->time_en) IOB |= F24; + IOB |= ut->time << 9; + IOB |= ut->fcn << 6; + IOB |= ut->units << 3; + IOB |= ut->pia; + break; + } + calc_ut_req(pdp, ut); +} + +static void +handle_uts(PDP6 *pdp, IOdev *dev, int cmd) +{ + Ut551 *ut = (Ut551*)dev->dev; + + switch(cmd) { + case IOB_STATUS: + if(ut->start_dly) IOB |= F25; + if(ut->state == RW_RQ) IOB |= F26; + if(ut->state == RW_ACTIVE) IOB |= F27; + if(ut->state == RW_NULL) IOB |= F28; + if(ut->incomp_block) IOB |= F29; + if(ut->wren) IOB |= F30; + if(ut->time_flag) IOB |= F31; + if(ut->info_error) IOB |= F32; + if(ut->illegal_op) IOB |= F33; + if(ut->tape_end_flag) IOB |= F34; + if(ut->jb_done_flag) IOB |= F35; + break; + } +} + +static Ut551 ut; +static IOdev ut_dev = { 0, 0210, &ut, handle_ut, cycle_ut }; +static IOdev uts_dev = { 0, 0214, &ut, handle_uts, nil }; + +static void +calc_ut_req(PDP6 *pdp, Ut551 *ut) +{ + int req = 0; + if(ut->pia && + (ut->time_flag && ut->time_en || + ut->jb_done_flag && ut->jb_done_en || + ut->tape_end_flag && ut->tape_end_en || + ut->illegal_op || ut->info_error)) + req = 0200>>ut->pia; + setreq(pdp, &ut_dev, req); +} + +Ut551* +attach_ut(PDP6 *pdp, Dc136 *dc) +{ + ut.dc = dc; + ut.dcdev = 1; + installdev(pdp, &ut_dev); + installdev(pdp, &uts_dev); + return &ut; +}