initial commit
This commit is contained in:
commit
4f262166f7
|
@ -0,0 +1,22 @@
|
||||||
|
PREFIX := /usr/local
|
||||||
|
LDFLAGS := -lcurses
|
||||||
|
CFLAGS := -Wall -Wmissing-prototypes -O2
|
||||||
|
CC := cc
|
||||||
|
|
||||||
|
all: mcim mcimc
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
$(CC) $(CFLAGS) -I. -c $< -o $@
|
||||||
|
|
||||||
|
mcim: mcim.o cpu.o
|
||||||
|
$(CC) $(LDFLAGS) -o $@ $^
|
||||||
|
|
||||||
|
mcimc: mcimc.o
|
||||||
|
$(CC) -I. -o $@ $^
|
||||||
|
|
||||||
|
install: mcim mcimc
|
||||||
|
mkdir -p $(PREFIX)/bin
|
||||||
|
cp $^ $(PREFIX)/bin
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f mcim mcimc mcim.o cpu.o mcimc.o
|
|
@ -0,0 +1,13 @@
|
||||||
|
mcim
|
||||||
|
|
||||||
|
b: set breakpoint on target process
|
||||||
|
l: switch to process view
|
||||||
|
m: switch to memory view
|
||||||
|
o: open executable
|
||||||
|
p: switch to tty output view
|
||||||
|
s: restart process
|
||||||
|
|
||||||
|
options:
|
||||||
|
|
||||||
|
-n: start without initial process
|
||||||
|
-t: log tty output to file
|
|
@ -0,0 +1,271 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, 2022 ipc
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "mcim.h"
|
||||||
|
|
||||||
|
uint
|
||||||
|
lget(uchar *p)
|
||||||
|
{
|
||||||
|
uint n;
|
||||||
|
|
||||||
|
n = *p;
|
||||||
|
n |= *(p+1) << 8;
|
||||||
|
n |= *(p+2) << 16;
|
||||||
|
n |= *(p+3) << 24;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MEM(p) p->mem
|
||||||
|
|
||||||
|
static uint
|
||||||
|
lcget(struct mcimp *p)
|
||||||
|
{
|
||||||
|
uint n;
|
||||||
|
|
||||||
|
n = lget(&p->MEM(p)[p->pc]);
|
||||||
|
p->pc += 4;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint
|
||||||
|
rget(struct mcimp *p)
|
||||||
|
{
|
||||||
|
uint n;
|
||||||
|
|
||||||
|
n = p->MEM(p)[p->pc];
|
||||||
|
p->pc += 1;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define R() rget(p)
|
||||||
|
#define L() lcget(p)
|
||||||
|
#define J(n) p->pc = n + p->epc
|
||||||
|
|
||||||
|
static void
|
||||||
|
lw(struct mcimp *p)
|
||||||
|
{
|
||||||
|
uint r;
|
||||||
|
uint l;
|
||||||
|
|
||||||
|
r = R();
|
||||||
|
if ((l = L() + 4) >= p->p->nmem)
|
||||||
|
return;
|
||||||
|
p->r[r] = lget(&p->MEM(p)[l+p->r[8]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
lb(struct mcimp *p)
|
||||||
|
{
|
||||||
|
uint r;
|
||||||
|
uint l;
|
||||||
|
|
||||||
|
r = R();
|
||||||
|
if ((l = L()) >= p->p->nmem)
|
||||||
|
return;
|
||||||
|
p->r[r] = p->MEM(p)[l+p->r[8]];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
li(struct mcimp *p)
|
||||||
|
{
|
||||||
|
uint r;
|
||||||
|
|
||||||
|
r = R();
|
||||||
|
p->r[r] = L();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sw(struct mcimp *p)
|
||||||
|
{
|
||||||
|
uint r;
|
||||||
|
uint l;
|
||||||
|
uint c;
|
||||||
|
|
||||||
|
r = R();
|
||||||
|
l = L();
|
||||||
|
l += p->r[8];
|
||||||
|
if (l > p->p->nmem) {
|
||||||
|
c = (l - p->p->nmem) + 4;
|
||||||
|
allocmem(p->p, c);
|
||||||
|
p->p->nmem += c;
|
||||||
|
}
|
||||||
|
p->MEM(p)[l] = p->r[r];
|
||||||
|
p->MEM(p)[l+1] = p->r[r] >> 8;
|
||||||
|
p->MEM(p)[l+2] = p->r[r] >> 16;
|
||||||
|
p->MEM(p)[l+3] = p->r[r] >> 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sb(struct mcimp *p)
|
||||||
|
{
|
||||||
|
uint r;
|
||||||
|
uint l;
|
||||||
|
uint c;
|
||||||
|
|
||||||
|
r = R();
|
||||||
|
l = L();
|
||||||
|
l += p->r[8];
|
||||||
|
if (l >= p->p->nmem) {
|
||||||
|
c = l - p->p->nmem;
|
||||||
|
allocmem(p->p, c+128);
|
||||||
|
p->p->nmem += c+128;
|
||||||
|
}
|
||||||
|
p->MEM(p)[l] = p->r[r];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add(struct mcimp *p)
|
||||||
|
{
|
||||||
|
uint r[3];
|
||||||
|
|
||||||
|
r[0] = R();
|
||||||
|
r[1] = R();
|
||||||
|
r[2] = R();
|
||||||
|
p->r[r[2]] = p->r[r[0]] + p->r[r[1]];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
addi(struct mcimp *p)
|
||||||
|
{
|
||||||
|
uint r[2];
|
||||||
|
uint l;
|
||||||
|
|
||||||
|
r[0] = R();
|
||||||
|
l = L();
|
||||||
|
r[1] = R();
|
||||||
|
p->r[r[1]] = p->r[r[0]] + l;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ble(struct mcimp *p)
|
||||||
|
{
|
||||||
|
uint r[2];
|
||||||
|
uint l;
|
||||||
|
|
||||||
|
r[0] = R();
|
||||||
|
r[1] = R();
|
||||||
|
l = L();
|
||||||
|
if (p->r[r[0]] < p->r[r[1]])
|
||||||
|
J(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bgt(struct mcimp *p)
|
||||||
|
{
|
||||||
|
uint r[2];
|
||||||
|
uint l;
|
||||||
|
|
||||||
|
r[0] = R();
|
||||||
|
r[1] = R();
|
||||||
|
l = L();
|
||||||
|
if (p->r[r[0]] > p->r[r[1]])
|
||||||
|
J(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
beq(struct mcimp *p)
|
||||||
|
{
|
||||||
|
uint r[2];
|
||||||
|
uint l;
|
||||||
|
|
||||||
|
r[0] = R();
|
||||||
|
r[1] = R();
|
||||||
|
l = L();
|
||||||
|
if (p->r[r[0]] == p->r[r[1]])
|
||||||
|
J(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bne(struct mcimp *p)
|
||||||
|
{
|
||||||
|
uint r[2];
|
||||||
|
uint l;
|
||||||
|
|
||||||
|
r[0] = R();
|
||||||
|
r[1] = R();
|
||||||
|
l = L();
|
||||||
|
if (p->r[r[0]] != p->r[r[1]])
|
||||||
|
J(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
j(struct mcimp *p)
|
||||||
|
{
|
||||||
|
J(L());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
jr(struct mcimp *p)
|
||||||
|
{
|
||||||
|
p->pc = p->r[R()];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
jal(struct mcimp *p)
|
||||||
|
{
|
||||||
|
uint pc;
|
||||||
|
|
||||||
|
pc = L();
|
||||||
|
p->r[3] = p->pc;
|
||||||
|
J(pc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sys(struct mcimp *p)
|
||||||
|
{
|
||||||
|
uint r;
|
||||||
|
|
||||||
|
r = p->r[R()];
|
||||||
|
switch (r) {
|
||||||
|
case SYSE:
|
||||||
|
p->stat |= STATEXIT;
|
||||||
|
break;
|
||||||
|
case SYSW:
|
||||||
|
if (p->p->ntty >= sizeof p->p->tty)
|
||||||
|
p->p->ntty = 0;
|
||||||
|
p->p->tty[p->p->ntty++] = p->r[1];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
err(1, "fatal: illegal syscall (%08x)\n", r);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void (*op[]) (struct mcimp *) = {
|
||||||
|
&lw, NULL, &lb, &li, &sw, NULL, &sb, NULL,
|
||||||
|
&add, &addi, NULL, NULL, NULL, &ble, &bgt, &beq,
|
||||||
|
&bne, &j, &jr, &jal, &sys
|
||||||
|
};
|
||||||
|
|
||||||
|
#define brk(p) (p->stat & STATEXIT || p->stat & STATBRK)
|
||||||
|
|
||||||
|
void
|
||||||
|
step(struct mcim *p)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
uint i;
|
||||||
|
struct mcimp *c;
|
||||||
|
|
||||||
|
for (i = 0; i < p->nproc; i++) {
|
||||||
|
n = SCHCNT;
|
||||||
|
c = &p->proc[i];
|
||||||
|
while (n-- && !brk(c))
|
||||||
|
op[p->mem[c->pc++]](c);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,313 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, 2022 ipc
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <curses.h>
|
||||||
|
#include <poll.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "mcim.h"
|
||||||
|
|
||||||
|
static char *progname;
|
||||||
|
static int dispc;
|
||||||
|
|
||||||
|
void
|
||||||
|
err(int f, char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list arg;
|
||||||
|
|
||||||
|
va_start(arg, fmt);
|
||||||
|
vfprintf(stderr, fmt, arg);
|
||||||
|
va_end(arg);
|
||||||
|
if (f) {
|
||||||
|
endwin();
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
usage(void)
|
||||||
|
{
|
||||||
|
err(1, "usage: %s [-n] [-t file] file\n", progname);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
allocmem(struct mcim *p, uint n)
|
||||||
|
{
|
||||||
|
if ((p->mem = realloc(p->mem, p->nmem+n)) == NULL)
|
||||||
|
return -1;
|
||||||
|
memset(p->mem+p->nmem, 0, n);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
loadproc(struct mcim *p, struct mcimp *c, FILE *f)
|
||||||
|
{
|
||||||
|
uchar hdr[4];
|
||||||
|
uint n;
|
||||||
|
|
||||||
|
if (fread(hdr, 1, sizeof hdr, f) < 4)
|
||||||
|
return -1;
|
||||||
|
if ((n = lget(hdr)) > MEMLIM)
|
||||||
|
return -1;
|
||||||
|
allocmem(p, n);
|
||||||
|
if (fread(p->mem+p->nmem, 1, n, f) < n)
|
||||||
|
return -1;
|
||||||
|
c->p = p;
|
||||||
|
c->epc = p->nmem;
|
||||||
|
c->pc = c->epc;
|
||||||
|
c->stat = 0;
|
||||||
|
memset(c->r, 0, sizeof c->r);
|
||||||
|
p->nmem += n;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MOVCLR(y) \
|
||||||
|
move(y, 0); \
|
||||||
|
clrtoeol()
|
||||||
|
#define MOVINFO() \
|
||||||
|
MOVCLR(p->nproc)
|
||||||
|
|
||||||
|
static void
|
||||||
|
brkp(struct mcim *p, int cmd)
|
||||||
|
{
|
||||||
|
struct mcimp *c;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
nocbreak();
|
||||||
|
echo();
|
||||||
|
MOVINFO();
|
||||||
|
scanw("%4d", &i);
|
||||||
|
if (i >= 0 && i < p->nproc) {
|
||||||
|
c = &p->proc[i];
|
||||||
|
c->stat ^= STATBRK;
|
||||||
|
}
|
||||||
|
noecho();
|
||||||
|
cbreak();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
view(struct mcim *p, int cmd)
|
||||||
|
{
|
||||||
|
char *s;
|
||||||
|
|
||||||
|
s = "lmp";
|
||||||
|
dispc = strchr(s, cmd) - s;
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
exec(struct mcim *p, int cmd)
|
||||||
|
{
|
||||||
|
char s[256];
|
||||||
|
FILE *f;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
nocbreak();
|
||||||
|
echo();
|
||||||
|
MOVINFO();
|
||||||
|
scanw("%255s", s);
|
||||||
|
if ((f = fopen(s, "r")) == NULL) {
|
||||||
|
MOVINFO();
|
||||||
|
printw("%s: couldn't open file", s);
|
||||||
|
goto enable;
|
||||||
|
}
|
||||||
|
n = loadproc(p, &p->proc[p->nproc], f);
|
||||||
|
fclose(f);
|
||||||
|
if (n == -1) {
|
||||||
|
MOVINFO();
|
||||||
|
printw("%s: invalid process", s);
|
||||||
|
} else
|
||||||
|
p->nproc++;
|
||||||
|
enable:
|
||||||
|
cbreak();
|
||||||
|
noecho();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
start(struct mcim *p, int cmd)
|
||||||
|
{
|
||||||
|
struct mcimp *c;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
i = -1;
|
||||||
|
nocbreak();
|
||||||
|
echo();
|
||||||
|
MOVINFO();
|
||||||
|
scanw("%4d", &i);
|
||||||
|
cbreak();
|
||||||
|
noecho();
|
||||||
|
if (i < 0 || i > p->nproc - 1) {
|
||||||
|
MOVINFO();
|
||||||
|
printw("%s", i<0?"bad input":"out of range");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
c = &p->proc[i];
|
||||||
|
memset(c->r, 0, sizeof c->r);
|
||||||
|
c->pc = c->epc;
|
||||||
|
c->stat = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void (*comtab[]) (struct mcim *, int) = {
|
||||||
|
&brkp,
|
||||||
|
&view,
|
||||||
|
&view,
|
||||||
|
&exec,
|
||||||
|
&view,
|
||||||
|
&start,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
get(struct mcim *p)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
char *cmd;
|
||||||
|
char *cp;
|
||||||
|
|
||||||
|
c = 0;
|
||||||
|
cmd = "blmops";
|
||||||
|
read(STDIN_FILENO, &c, 1);
|
||||||
|
if (c == 'q')
|
||||||
|
return -1;
|
||||||
|
if ((cp = strchr(cmd, c)) == NULL) {
|
||||||
|
MOVINFO();
|
||||||
|
printw("invalid command");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
comtab[cp - cmd](p, c);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pdisp(struct mcim *p)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
struct mcimp *c;
|
||||||
|
|
||||||
|
for (i = 0; i < p->nproc; i++) {
|
||||||
|
c = &p->proc[i];
|
||||||
|
MOVCLR(i);
|
||||||
|
mvprintw(i, 0, "%d %08x %08x %x ", i, c->epc, c->pc, c->stat);
|
||||||
|
for (j = 0; j < 16; j++)
|
||||||
|
printw("%x%s", c->r[j], j == 15 ? "" : ":");
|
||||||
|
}
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mdisp(struct mcim *p)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
move(0, 0);
|
||||||
|
clrtoeol();
|
||||||
|
for (i = 0; i < p->nmem; i++)
|
||||||
|
printw("%02x%s", p->mem[i],
|
||||||
|
i == p->nmem-1 || (i+1)%12 == 0 ? "\n" : " ");
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
tdisp(struct mcim *p)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
move(0, 0);
|
||||||
|
for (i = 0; i < p->ntty; i++)
|
||||||
|
printw("%c", p->tty[i]);
|
||||||
|
printw("\n");
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
void (*disptab[]) (struct mcim *) = {
|
||||||
|
&pdisp, &mdisp, &tdisp
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int iproc;
|
||||||
|
char *s;
|
||||||
|
char *ttyout;
|
||||||
|
FILE *f;
|
||||||
|
int n;
|
||||||
|
int log;
|
||||||
|
struct mcim c;
|
||||||
|
struct pollfd pfd[1];
|
||||||
|
|
||||||
|
iproc = 1;
|
||||||
|
ttyout = NULL;
|
||||||
|
f = NULL;
|
||||||
|
progname = *argv[0]!='\0'?argv[0]:"mcim";
|
||||||
|
while (--argc > 0 && (*++argv)[0] == '-')
|
||||||
|
for (s = argv[0]+1; *s != '\0'; s++)
|
||||||
|
switch (*s) {
|
||||||
|
case 'n':
|
||||||
|
iproc = 0;
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
if (argc < 2)
|
||||||
|
usage();
|
||||||
|
ttyout = argv[1];
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
memset(&c, 0, sizeof c);
|
||||||
|
if (iproc) {
|
||||||
|
if (argc < 1)
|
||||||
|
usage();
|
||||||
|
if ((f = fopen(argv[0], "rb")) == NULL)
|
||||||
|
err(1, "%s: couldn't open '%s'\n", progname, argv[0]);
|
||||||
|
c.nproc++;
|
||||||
|
n = loadproc(&c, &c.proc[0], f);
|
||||||
|
fclose(f);
|
||||||
|
if (n == -1)
|
||||||
|
err(1, "%s: bad executable\n", progname);
|
||||||
|
}
|
||||||
|
if (ttyout != NULL)
|
||||||
|
if ((f = fopen(ttyout, "w")) == NULL)
|
||||||
|
err(1, "%s: couldn't open '%s'\n", progname, ttyout);
|
||||||
|
n = 0;
|
||||||
|
log = LOGCNT;
|
||||||
|
pfd[0].fd = STDIN_FILENO;
|
||||||
|
pfd[0].events = POLLIN;
|
||||||
|
initscr();
|
||||||
|
cbreak();
|
||||||
|
noecho();
|
||||||
|
while ((n = poll(pfd, 1, 10)) != -1) {
|
||||||
|
if (pfd[0].revents & (POLLERR|POLLHUP|POLLNVAL))
|
||||||
|
break;
|
||||||
|
if (n > 0 && get(&c) == -1)
|
||||||
|
break;
|
||||||
|
disptab[dispc](&c);
|
||||||
|
step(&c);
|
||||||
|
if (c.ntty > 0 && ttyout != NULL && !--log) {
|
||||||
|
log = LOGCNT;
|
||||||
|
fseek(f, 0L, SEEK_SET);
|
||||||
|
fwrite(c.tty, 1, c.ntty, f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(c.mem);
|
||||||
|
endwin();
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, 2022 ipc
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SYSE,
|
||||||
|
SYSP,
|
||||||
|
SYSW
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MEMLIM 0xff000
|
||||||
|
#define SCHCNT 300
|
||||||
|
#define LOGCNT 50
|
||||||
|
|
||||||
|
#define STATEXIT 1 << 1
|
||||||
|
#define STATBRK 1 << 2
|
||||||
|
|
||||||
|
typedef unsigned int uint;
|
||||||
|
typedef unsigned char uchar;
|
||||||
|
|
||||||
|
struct mcimp {
|
||||||
|
struct mcim *p;
|
||||||
|
uint r[16];
|
||||||
|
uint epc;
|
||||||
|
uint pc;
|
||||||
|
uint stat;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mcim {
|
||||||
|
struct mcimp proc[4096];
|
||||||
|
uchar *mem;
|
||||||
|
uchar tty[8192];
|
||||||
|
uint ntty;
|
||||||
|
uint nproc;
|
||||||
|
uint nmem;
|
||||||
|
};
|
||||||
|
|
||||||
|
void err(int f, char *fmt, ...);
|
||||||
|
int allocmem(struct mcim *p, uint n);
|
||||||
|
uint lget(uchar *p);
|
||||||
|
void step(struct mcim *p);
|
|
@ -0,0 +1,586 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, 2022 ipc
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include "mcimc.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
IDNT,
|
||||||
|
LBL,
|
||||||
|
REG,
|
||||||
|
ADDR,
|
||||||
|
PROC
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SYMLEN 1024
|
||||||
|
#define SYMALLOC 8192
|
||||||
|
|
||||||
|
#define MAXLBL 8192
|
||||||
|
#define MAXREG 16
|
||||||
|
|
||||||
|
struct sym {
|
||||||
|
int t;
|
||||||
|
int l;
|
||||||
|
char s[SYMLEN];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ins {
|
||||||
|
char s[SYMLEN];
|
||||||
|
char fmt[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct lbl {
|
||||||
|
char s[SYMLEN];
|
||||||
|
uint addr;
|
||||||
|
int l;
|
||||||
|
struct lbl *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct sym *tab;
|
||||||
|
static struct sym *sp;
|
||||||
|
static struct lbl *lab[MAXLBL];
|
||||||
|
static struct lbl *lbp;
|
||||||
|
static int nsym;
|
||||||
|
static int asym;
|
||||||
|
static int errc;
|
||||||
|
static uchar *buf;
|
||||||
|
static int abuf;
|
||||||
|
static uint pc;
|
||||||
|
struct ins instab[];
|
||||||
|
|
||||||
|
static FILE *f;
|
||||||
|
static char in[1024];
|
||||||
|
static char *progname;
|
||||||
|
|
||||||
|
static void mfree(void);
|
||||||
|
|
||||||
|
static void
|
||||||
|
err(int f, char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list arg;
|
||||||
|
|
||||||
|
va_start(arg, fmt);
|
||||||
|
vfprintf(stderr, fmt, arg);
|
||||||
|
va_end(arg);
|
||||||
|
errc++;
|
||||||
|
if (f) {
|
||||||
|
mfree();
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
usage(void)
|
||||||
|
{
|
||||||
|
err(1, "usage: %s [-o out] file\n", progname);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mfree(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct lbl *p, *t;
|
||||||
|
|
||||||
|
free(tab);
|
||||||
|
free(buf);
|
||||||
|
for (i = 0; i < MAXLBL; i++) {
|
||||||
|
p = lab[i];
|
||||||
|
while (p != NULL) {
|
||||||
|
t = p;
|
||||||
|
p = p->next;
|
||||||
|
free(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
allocsym(long n)
|
||||||
|
{
|
||||||
|
asym += n;
|
||||||
|
if ((tab = realloc(tab, asym*sizeof(struct sym))) == NULL)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct sym *
|
||||||
|
makesym(int t, int l, char *s)
|
||||||
|
{
|
||||||
|
struct sym *p;
|
||||||
|
|
||||||
|
if ((p = malloc(sizeof(struct sym))) == NULL)
|
||||||
|
return NULL;
|
||||||
|
p->t = t;
|
||||||
|
p->l = l;
|
||||||
|
strcpy(p->s, s);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct sym *
|
||||||
|
pushsym(struct sym *p)
|
||||||
|
{
|
||||||
|
if (nsym >= asym)
|
||||||
|
if (allocsym(SYMALLOC) == -1)
|
||||||
|
return NULL;
|
||||||
|
tab[nsym++] = *p;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct lbl *
|
||||||
|
makelbp(char *s, uint n, uint l)
|
||||||
|
{
|
||||||
|
struct lbl *p;
|
||||||
|
|
||||||
|
if ((p = malloc(sizeof(struct lbl))) == NULL)
|
||||||
|
return NULL;
|
||||||
|
strcpy(p->s, s);
|
||||||
|
p->addr = n;
|
||||||
|
p->l = l;
|
||||||
|
p->next = lbp;
|
||||||
|
lbp = p;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int l = 1;
|
||||||
|
|
||||||
|
static int
|
||||||
|
cget(void)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
|
||||||
|
c = getc(f);
|
||||||
|
l += c == '\n';
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
get(struct sym **p)
|
||||||
|
{
|
||||||
|
char s[SYMLEN];
|
||||||
|
int n;
|
||||||
|
int c;
|
||||||
|
int t;
|
||||||
|
int lp;
|
||||||
|
|
||||||
|
n = 0;
|
||||||
|
t = -1;
|
||||||
|
while ((c = cget()) != EOF && isspace(c))
|
||||||
|
;
|
||||||
|
switch (c) {
|
||||||
|
case '%':
|
||||||
|
t = REG;
|
||||||
|
break;
|
||||||
|
case '$':
|
||||||
|
t = ADDR;
|
||||||
|
break;
|
||||||
|
case '.':
|
||||||
|
t = PROC;
|
||||||
|
while ((c = cget()) != EOF && c != '\n') {
|
||||||
|
if (n >= SYMLEN-1)
|
||||||
|
break;
|
||||||
|
s[n++] = c;
|
||||||
|
}
|
||||||
|
s[n] = '\0';
|
||||||
|
lp = c == '\n' ? l-1 : l;
|
||||||
|
*p = makesym(t, lp, s);
|
||||||
|
return 1;
|
||||||
|
case ';':
|
||||||
|
while ((c = cget()) != EOF && c != '\n')
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (t == -1 && isalpha(c)) {
|
||||||
|
t = IDNT;
|
||||||
|
ungetc(c, f);
|
||||||
|
while ((c = cget()) != EOF) {
|
||||||
|
if (c == ':')
|
||||||
|
t = LBL;
|
||||||
|
if (!isalnum(c))
|
||||||
|
break;
|
||||||
|
if (n >= SYMLEN-1)
|
||||||
|
break;
|
||||||
|
s[n++] = c;
|
||||||
|
}
|
||||||
|
s[n] = '\0';
|
||||||
|
lp = c == '\n' ? l-1 : l;
|
||||||
|
*p = makesym(t, lp, s);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (t == REG || t == ADDR) {
|
||||||
|
while ((c = cget()) != EOF) {
|
||||||
|
if (!isxdigit(c) && !isspace(c)) {
|
||||||
|
err(0, "%s:%d: bad address\n", in, l);
|
||||||
|
break;
|
||||||
|
} else if (!isxdigit(c))
|
||||||
|
break;
|
||||||
|
if (n >= SYMLEN-1)
|
||||||
|
break;
|
||||||
|
s[n++] = c;
|
||||||
|
}
|
||||||
|
s[n] = '\0';
|
||||||
|
lp = c == '\n' ? l-1 : l;
|
||||||
|
*p = makesym(t, lp, s);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (c != EOF) {
|
||||||
|
err(0, "%s:%d: unknown symbol\n", in, l);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
com(char *s)
|
||||||
|
{
|
||||||
|
uint n;
|
||||||
|
uchar *p;
|
||||||
|
|
||||||
|
n = 0;
|
||||||
|
for (p = (uchar*) s; *p != '\0'; p++)
|
||||||
|
n = n * 31 + *p;
|
||||||
|
return n % MAXLBL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct lbl *
|
||||||
|
lookup(char *s, int c)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
struct lbl *p;
|
||||||
|
|
||||||
|
n = com(s);
|
||||||
|
for (p = lab[n]; p != NULL; p = p->next)
|
||||||
|
if (strcmp(s, p->s) == 0)
|
||||||
|
return p;
|
||||||
|
if (c) {
|
||||||
|
if ((p = malloc(sizeof(struct lbl))) == NULL)
|
||||||
|
return NULL;
|
||||||
|
strcpy(p->s, s);
|
||||||
|
p->addr = pc;
|
||||||
|
p->next = lab[n];
|
||||||
|
lab[n] = p;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
lp(uchar *p, uint l)
|
||||||
|
{
|
||||||
|
*p = l;
|
||||||
|
*(p+1) = l >> 8;
|
||||||
|
*(p+2) = l >> 16;
|
||||||
|
*(p+3) = l >> 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
allocb(void)
|
||||||
|
{
|
||||||
|
abuf += 8192;
|
||||||
|
buf = realloc(buf, abuf);
|
||||||
|
return buf == NULL ? -1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cput(uchar c)
|
||||||
|
{
|
||||||
|
if (pc+1 >= abuf)
|
||||||
|
allocb();
|
||||||
|
buf[pc++] = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
lput(uint l)
|
||||||
|
{
|
||||||
|
if (pc+4 >= abuf)
|
||||||
|
allocb();
|
||||||
|
lp(buf+pc, l);
|
||||||
|
pc += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
reg(void)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
if (sp->t != REG)
|
||||||
|
err(0, "%s:%d: expected register\n", in, sp->l);
|
||||||
|
else if ((n = strtol(sp->s, NULL, 16)) >= MAXREG)
|
||||||
|
err(0, "%s:%d: bad register %02x\n", in, sp->l, n);
|
||||||
|
else
|
||||||
|
cput(n);
|
||||||
|
sp++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
addr(void)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
n = 0;
|
||||||
|
if (sp->t == ADDR)
|
||||||
|
n = strtol(sp->s, NULL, 16);
|
||||||
|
else if (sp->t == IDNT)
|
||||||
|
makelbp(sp->s, pc, sp->l);
|
||||||
|
else {
|
||||||
|
err(0, "%s:%d: expected immediate\n", in, sp->l);
|
||||||
|
sp++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lput(n);
|
||||||
|
sp++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gen(void);
|
||||||
|
|
||||||
|
static int
|
||||||
|
pget(char *p, char *s)
|
||||||
|
{
|
||||||
|
if (*p != '\'')
|
||||||
|
return -1;
|
||||||
|
for (p++; *p != '\0' && *p != '\''; p++)
|
||||||
|
*s++ = *p;
|
||||||
|
if (*p != '\'')
|
||||||
|
return -1;
|
||||||
|
*s = '\0';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
inc(struct sym *sp, char *p)
|
||||||
|
{
|
||||||
|
char path[1024];
|
||||||
|
char mpath[1024];
|
||||||
|
FILE *fp;
|
||||||
|
int lp;
|
||||||
|
|
||||||
|
if (pget(p, path) == -1) {
|
||||||
|
err(0, "%s:%d: expected value in include\n", in, sp->l);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fp = f;
|
||||||
|
if ((f = fopen(path, "r")) == NULL) {
|
||||||
|
err(0, "%s:%d: couldn't open '%s'\n", in, sp->l, path);
|
||||||
|
f = fp;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
strcpy(mpath, in);
|
||||||
|
strcpy(in, path);
|
||||||
|
lp = l;
|
||||||
|
gen();
|
||||||
|
f = fp;
|
||||||
|
l = lp;
|
||||||
|
strcpy(in, mpath);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct proc {
|
||||||
|
char *s;
|
||||||
|
void (*fn) (struct sym *, char *);
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct proc proctab[] = {
|
||||||
|
{ "include", &inc },
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
proc(struct sym *sp)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char *p;
|
||||||
|
char *s;
|
||||||
|
char com[1024];
|
||||||
|
|
||||||
|
p = sp->s;
|
||||||
|
s = com;
|
||||||
|
while (*p != '\0' && !isspace(*p))
|
||||||
|
*s++ = *p++;
|
||||||
|
*s = '\0';
|
||||||
|
while (isspace(*p))
|
||||||
|
p++;
|
||||||
|
for (i = 0; proctab[i].s != NULL; i++)
|
||||||
|
if (strcmp(com, proctab[i].s) == 0) {
|
||||||
|
proctab[i].fn(sp, p);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
err(0, "%s:%d: unknown directive '%s'\n", in, sp->l, com);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ins(void)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
struct ins *ip;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (sp->t == LBL) {
|
||||||
|
if (lookup(sp->s, 1) != NULL)
|
||||||
|
err(0, "%s:%d: redefining label '%s'\n", in, sp->l,
|
||||||
|
sp->s);
|
||||||
|
sp++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (sp->t != IDNT) {
|
||||||
|
err(0, "%s:%d: expected instruction\n", in, sp->l);
|
||||||
|
sp++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (ip = NULL, i = 0; i < AINS; i++)
|
||||||
|
if (strcmp(sp->s, instab[i].s) == 0) {
|
||||||
|
ip = &instab[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (ip == NULL) {
|
||||||
|
err(0, "%s:%d: invalid instruction '%s'\n", in, sp->l, sp->s);
|
||||||
|
sp++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cput(i);
|
||||||
|
sp++;
|
||||||
|
for (p = ip->fmt; *p != '\0'; p++)
|
||||||
|
switch (*p) {
|
||||||
|
case 'r':
|
||||||
|
reg();
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
addr();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
lbl(void)
|
||||||
|
{
|
||||||
|
struct lbl *p;
|
||||||
|
|
||||||
|
while (lbp != NULL) {
|
||||||
|
if ((p = lookup(lbp->s, 0)) == NULL)
|
||||||
|
err(0, "%s:%d: no such label '%s'\n", in, lbp->l,
|
||||||
|
lbp->s);
|
||||||
|
else
|
||||||
|
lp(buf+lbp->addr, p->addr);
|
||||||
|
p = lbp;
|
||||||
|
lbp = lbp->next;
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
gen(void)
|
||||||
|
{
|
||||||
|
struct sym *s;
|
||||||
|
struct sym n;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
while ((c = get(&s)) != -1)
|
||||||
|
if (c != 0) {
|
||||||
|
if (s->t == PROC)
|
||||||
|
proc(s);
|
||||||
|
else
|
||||||
|
pushsym(s);
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
n.t = -1;
|
||||||
|
pushsym(&n);
|
||||||
|
while (sp->t != -1)
|
||||||
|
ins();
|
||||||
|
sp++;
|
||||||
|
if (errc > 0) {
|
||||||
|
err(0, "%s: %d error%s\n", in, errc, errc>1?"s":"");
|
||||||
|
errc--;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
errc = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
char *out;
|
||||||
|
char *s;
|
||||||
|
int n;
|
||||||
|
uchar hd[4];
|
||||||
|
|
||||||
|
progname = *argv[0]!='\0'?argv[0]:"mcimc";
|
||||||
|
out = "a";
|
||||||
|
while (--argc > 0 && (*++argv)[0] == '-')
|
||||||
|
for (s = argv[0]+1; *s != '\0'; s++)
|
||||||
|
switch (*s) {
|
||||||
|
case 'o':
|
||||||
|
if (argc < 2)
|
||||||
|
usage();
|
||||||
|
out = argv[1];
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (argc < 1)
|
||||||
|
usage();
|
||||||
|
strcpy(in, argv[0]);
|
||||||
|
if ((f = fopen(in, "r")) == NULL)
|
||||||
|
err(1, "%s: couldn't open '%s'\n", progname, in);
|
||||||
|
if (allocsym(SYMALLOC) == -1) {
|
||||||
|
fclose(f);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
sp = tab;
|
||||||
|
allocb();
|
||||||
|
n = gen();
|
||||||
|
if (n == -1) {
|
||||||
|
mfree();
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
lbl();
|
||||||
|
if ((f = fopen(out, "wb")) == NULL)
|
||||||
|
err(1, "%s: couldn't open '%s'\n", progname, out);
|
||||||
|
lp(hd, pc);
|
||||||
|
fwrite(hd, 1, sizeof hd, f);
|
||||||
|
fwrite(buf, 1, pc, f);
|
||||||
|
fclose(f);
|
||||||
|
mfree();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ins instab[AINS] = {
|
||||||
|
{ "lw", "ri" },
|
||||||
|
{ "lwu", "ri" },
|
||||||
|
{ "lb", "ri" },
|
||||||
|
{ "li", "ri" },
|
||||||
|
{ "sw", "ri" },
|
||||||
|
{ "swu", "ri" },
|
||||||
|
{ "sb", "ri" },
|
||||||
|
{ "sr", "ri" },
|
||||||
|
{ "add", "rrr" },
|
||||||
|
{ "addi", "rir" },
|
||||||
|
{ "sub", "rrr" },
|
||||||
|
{ "mul", "rrr" },
|
||||||
|
{ "div", "rrr" },
|
||||||
|
{ "ble", "rri" },
|
||||||
|
{ "bgt", "rri" },
|
||||||
|
{ "beq", "rri" },
|
||||||
|
{ "bne", "rri" },
|
||||||
|
{ "j", "i" },
|
||||||
|
{ "jr", "r" },
|
||||||
|
{ "jal", "i" },
|
||||||
|
{ "sys", "r" }
|
||||||
|
};
|
|
@ -0,0 +1,27 @@
|
||||||
|
enum {
|
||||||
|
ALW,
|
||||||
|
ALWU,
|
||||||
|
ALB,
|
||||||
|
ALI,
|
||||||
|
ASW,
|
||||||
|
ASWU,
|
||||||
|
ASB,
|
||||||
|
ASR,
|
||||||
|
AADD,
|
||||||
|
AADDI,
|
||||||
|
ASUB,
|
||||||
|
AMUL,
|
||||||
|
ADIV,
|
||||||
|
ABLE,
|
||||||
|
ABGT,
|
||||||
|
ABEQ,
|
||||||
|
ABNE,
|
||||||
|
AJ,
|
||||||
|
AJR,
|
||||||
|
AJAL,
|
||||||
|
ASYS,
|
||||||
|
AINS
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef unsigned int uint;
|
||||||
|
typedef unsigned char uchar;
|
|
@ -0,0 +1,5 @@
|
||||||
|
li %0 $0
|
||||||
|
li %0 $1
|
||||||
|
add %0 %1 %0
|
||||||
|
li %2 $0
|
||||||
|
sys %2
|
|
@ -0,0 +1,12 @@
|
||||||
|
.include 'sys.s'
|
||||||
|
|
||||||
|
start:
|
||||||
|
jal write
|
||||||
|
li %1 $41
|
||||||
|
li %2 $7e
|
||||||
|
li %3 $1
|
||||||
|
loop:
|
||||||
|
sys %0
|
||||||
|
add %1 %3 %1
|
||||||
|
bne %1 %2 loop
|
||||||
|
jal exit
|
|
@ -0,0 +1,4 @@
|
||||||
|
li %0 $020002
|
||||||
|
sw %0 $100
|
||||||
|
sw %0 $200
|
||||||
|
sys %0
|
|
@ -0,0 +1,6 @@
|
||||||
|
j start
|
||||||
|
|
||||||
|
; SYSE ($0)
|
||||||
|
exit: li %0 $0 sys %0 jr %3
|
||||||
|
; SYSW ($2)
|
||||||
|
write: li %0 $2 jr %3
|
|
@ -0,0 +1,21 @@
|
||||||
|
; memory test
|
||||||
|
li %0 $41
|
||||||
|
sb %0 $100
|
||||||
|
li %0 $42
|
||||||
|
sb %0 $101
|
||||||
|
li %0 $43
|
||||||
|
sb %0 $102
|
||||||
|
li %0 $0
|
||||||
|
sb %0 $103
|
||||||
|
li %2 $0
|
||||||
|
li %3 $2
|
||||||
|
li %8 $100
|
||||||
|
print:
|
||||||
|
lb %1 $0
|
||||||
|
beq %1 %2 end
|
||||||
|
sys %3
|
||||||
|
addi %8 $1 %8
|
||||||
|
j print
|
||||||
|
end:
|
||||||
|
li %0 $0
|
||||||
|
sys %0
|
Loading…
Reference in New Issue