initial commit

This commit is contained in:
ipc 2022-01-31 16:58:03 +01:00
commit 4f262166f7
12 changed files with 1333 additions and 0 deletions

22
Makefile Normal file
View File

@ -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

13
README Normal file
View File

@ -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

271
cpu.c Normal file
View 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);
}
}

313
mcim.c Normal file
View File

@ -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;
}

53
mcim.h Normal file
View File

@ -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);

586
mcimc.c Normal file
View File

@ -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" }
};

27
mcimc.h Normal file
View File

@ -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;

5
sample/init.s Normal file
View File

@ -0,0 +1,5 @@
li %0 $0
li %0 $1
add %0 %1 %0
li %2 $0
sys %2

12
sample/l1.s Normal file
View File

@ -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

4
sample/mem.s Normal file
View File

@ -0,0 +1,4 @@
li %0 $020002
sw %0 $100
sw %0 $200
sys %0

6
sample/sys.s Normal file
View File

@ -0,0 +1,6 @@
j start
; SYSE ($0)
exit: li %0 $0 sys %0 jr %3
; SYSW ($2)
write: li %0 $2 jr %3

21
sample/write.s Normal file
View File

@ -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