ref: 198ac4e7f585d07df010456ad25ffcd047f6340d
parent: 61271a867e20a6b9c3d4de8a1ee209b1af2f3ecd
author: mkf <mkf@cloud9p.org>
date: Wed Jul 3 07:24:49 EDT 2024
5552: import skel
--- a/5551e.c
+++ b/5551e.c
@@ -1,18 +1,25 @@
-/* 5551 cpu emulator */
+/* 5552 cpu emulator */
+#include "5552.h"
-#include <stdbool.h>
-#include <stdio.h>
+struct mach
+{
+ word reg[REGS];
+
+
+ /* both are nibbles currently, but for convience */
+ word op;
+ word mode;
-#include "5551.h"
+ word arg1;
+ word arg2;
+
+ byte mem[MMAX];
+};
-typedef struct
+/*
+int
+btoi(int b[], int len)
{
- bool flags[8];
- int regs[8];
-}reg_t;
-
-int btoi(bool b[], int len)
-{
char arr[10];
int res = 0, i = 0, j = len;
while (i <= len)
@@ -21,28 +28,327 @@
i++;
j--;
}
- sscanf(arr, "%d", &res);
+ sscanf(arr, "%d", &res);
return res;
}
+*/
+int
+mach_drd(word dev, word src, word dst)
+{
+ switch(dev)
+ {
+ case REG:
+ regs[dst] = regs[src];
+ break;
+ case MEM:
+ regs[dst] = mem[src];
+ break;
+ case GPIO:
+ switch(src)
+ {
+ case SERIAL:
+ read(0, regs+dst, sizeof(Word));
+ break;
+ default:
+ break;
+ }
+ default:
+ break;
+ }
+}
-int main()
+int
+mach_dwr(word dev, word src, word dst)
{
+ switch(dev)
+ {
+ case REG:
+ regs[src] = regs[dst];
+ break;
+ case MEM:
+ regs[src] = mem[dst];
+ break;
+ case GPIO:
+ switch(dst)
+ {
+ case SERIAL:
+ write(0, regs+src, sizeof(Word));
+ break;
+ default:
+ break;
+ }
+ default:
+ break;
+ }
+}
- reg_t r;
- unsigned int memory[MMAX];
- memory[MMAX-1] = -1;
+int
+mach_dwr(word dev, word src, word dst)
+{
+ switch(dev)
+ {
+ case REG:
+ regs[src] = regs[dst];
+ break;
+ case MEM:
+ regs[src] = mem[dst];
+ break;
+ case GPIO:
+ switch(dst)
+ {
+ case SERIAL:
+ write(0, regs+src, sizeof(Word));
+ break;
+ default:
+ break;
+ }
+ default:
+ break;
+ }
+}
+int
+mach_not(word mode, word arg1, word arg2)
+{
+ switch(mode)
+ {
+ case REG:
+ regs[RES] = ~regs[arg1];
+ break;
+ case INLINE:
+ regs[RES] = ~((arg1 << (sizeof Word) * 8) & arg2);
+ break;
+ case DIRECT:
+ default:
+ break;
+ }
+}
+
+int
+mach_and(Word mode, Word arg1, Word arg2)
+{
+ switch(mode)
+ {
+ case REG:
+ regs[RES] = regs[arg1] & regs[arg2];
+ break;
+ case INLINE:
+ regs[RES] = arg1 & arg2;
+ break;
+ case DIRECT:
+ regs[RES] = regs[arg1] & arg2;
+ break;
+ default:
+ break;
+ }
+}
+
+int
+mach_nor(Word mode, Word arg1, Word arg2)
+{
+ switch(mode)
+ {
+ case REG:
+ regs[RES] = !(regs[arg1] | regs[arg2]);
+ break;
+ case INLINE:
+ regs[RES] = !(arg1 | arg2);
+ break;
+ case DIRECT:
+ regs[RES] = !(regs[arg1] & arg2);
+ break;
+ default:
+ break;
+ }
+}
+
+int
+mach_xor(Word mode, Word arg1, Word arg2)
+{
+ switch(mode)
+ {
+ case REG:
+ regs[RES] = regs[arg1] ^ regs[arg2];
+ break;
+ case INLINE:
+ regs[RES] = arg1 ^ arg2;
+ break;
+ case DIRECT:
+ regs[RES] = regs[arg1] ^ arg2;
+ break;
+ default:
+ break;
+ }
+}
+
+int
+mach_add(Word mode, Word arg1, Word arg2)
+{
+ int result;
+
+ switch(mode)
+ {
+ case REG:
+ result = (int)regs[arg1] + (int)regs[arg2];
+ break;
+ case INLINE:
+ result = (int)arg1 + (int)arg2;
+ break;
+ case DIRECT:
+ result = (int)regs[arg1] + (int)arg2;
+ break;
+ default:
+ break;
+ }
+ if(intsize(result) > sizeof Word)
+ regs[CRR] = (Word)(result % 2 << (sizeof Word * 8));
+ regs[RES] = (Word)result;
+}
+
+int
+mach_sub(Word mode, Word arg1, Word arg2)
+{
+ int result;
+
+ switch(mode)
+ {
+ case REG:
+ result = (int)regs[arg1] - (int)regs[arg2];
+ break;
+ case INLINE:
+ result = (int)arg1 - (int)arg2;
+ break;
+ case DIRECT:
+ result = (int)regs[arg1] - (int)arg2;
+ break;
+ default:
+ break;
+ }
+ if(intsize(result) > sizeof Word * 8)
+ regs[CRR] = (Word)(result % 2 << (sizeof Word * 8));
+ regs[RES] = (Word)result;
+}
+
+int
+mach_mul(Word mode, Word arg1, Word arg2)
+{
+ int result;
+
+ switch(mode)
+ {
+ case REG:
+ result = (int)regs[arg1] * (int)regs[arg2];
+ break;
+ case INLINE:
+ result = (int)arg1 * (int)arg2;
+ break;
+ case DIRECT:
+ result = (int)regs[arg1] * (int)arg2;
+ break;
+ default:
+ break;
+ }
+ if(intsize(result) > sizeof Word * 8)
+ regs[CRR] = (Word)(result % 2 << (sizeof Word * 8));
+ regs[RES] = (Word)result;
+}
+
+int
+mach_div(Word mode, Word arg1, Word arg2)
+{
+ int result;
+
+ switch(mode)
+ {
+ case REG:
+ result = (int)regs[arg1] / (int)regs[arg2];
+ break;
+ case INLINE:
+ result = (int)arg1 / (int)arg2;
+ break;
+ case DIRECT:
+ result = (int)regs[arg1] / (int)arg2;
+ break;
+ default:
+ break;
+ }
+ regs[RES] = (Word)result;
+}
+
+int
+mach_mul(Word mode, Word arg1, Word arg2)
+{
+ int result;
+
+ switch(mode)
+ {
+ case REG:
+ result = (int)regs[arg1] * (int)regs[arg2];
+ break;
+ case INLINE:
+ result = (int)arg1 * (int)arg2;
+ break;
+ case DIRECT:
+ result = (int)regs[arg1] * (int)arg2;
+ break;
+ default:
+ break;
+ }
+ if(intsize(result) > sizeof Word * 8)
+ regs[CRR] = (Word)(result % 2 << (sizeof Word * 8));
+ regs[RES] = (Word)result;
+}
+
+void
+main(void)
+{
+ char *input;
+ void *buf;
+ int arg, prev;
+
+ input = malloc(OPLEN);
+ if(input < 0)
+ panic("Not enough memory\n");
+
+ mach.reg[STATE] = ON;
+
+ while(mach.state == ON)
+ {
+ if(read(1, buf, 3) < 3)
+ {
+ panic("EOF?\n");
+ }
+
+ mach.op = buf[0] >> 4;
+ mach.mode = buf[0] & (1 << 4) - 1;
+ mach.arg1 = buf[1];
+ mach.arg2 = buf[2];
+
+ for(int i = 0; i < sizeof(optab) ; i++)
+ {
+ if(mach.op == operators[i].op)
+ {
+ operators[i].exec(mach.mode, mach.arg1, mach.arg2);
+ break;
+ }
+
+ }
+ }
+}
+
+int
+main(void)
+{
char string[16];
r.flags[ON] = 1;
r.flags[NSIGN] = false;
unsigned int op, a, b, c, ind = 0;
- bool barr[10];
-
- /* there is no space between op and args
- since some can have no args */
+ bool barr[10];
+
+ /* there is no space between op and args
+ since some can have no args */
while(r.flags[ON] && scanf("%u %[^\n]", &op, string))
{
-
sscanf(string, "%u %u %u", &a, &b, &c);
switch(op)
{
--- /dev/null
+++ b/5552.h
@@ -1,0 +1,136 @@
+#define MMAX 1 << 8
+#define OPLEN 16
+#define REGS 16
+#define INSTLEN 3
+
+
+/* internal */
+enum
+{
+ WARN,
+ ERR,
+
+ SFLAG,
+}
+
+/* ops */
+enum
+{
+ DRD, /* read from device */
+ DWR, /* write to device */
+
+ NOT,
+ AND,
+ NOR,
+ XOR,
+
+ ADD,
+ SUB,
+
+ INC,
+ DEC,
+
+ MUL,
+ DIV,
+
+ SHR,
+ SHL,
+
+ JMP,
+};
+
+/* registers */
+enum
+{
+ ZERO,
+ ONE,
+
+ DUP,
+ FLAGS,
+
+ PC,
+ STATE,
+}
+
+/* devices */
+enum
+{
+ REG,
+ MEM,
+ SIO,
+ TP0,
+};
+
+/* states */
+typedef enum
+{
+ OFF,
+ ON,
+ DED,
+}State;
+
+typedef int Word;
+typedef char Byte;
+
+typedef struct
+{
+ int inst;
+ int arg1;
+ int arg2;
+ int line;
+}Op;
+
+typedef struct
+{
+ char *name;
+ int pc;
+}Label;
+
+extern Op program[];
+extern Label labels[];
+
+void panic(char *msg);
+
+/* emulator */
+int mach_drd(Word dev, Word src, Word dst);
+int mach_dwr(Word mode, Word arg1, Word arg2);
+
+int mach_not(Word mode, Word arg1, Word arg2);
+int mach_and(Word mode, Word arg1, Word arg2);
+int mach_nor(Word mode, Word arg1, Word arg2);
+int mach_xor(Word mode, Word arg1, Word arg2);
+
+int mach_add(Word mode, Word arg1, Word arg2);
+int mach_sub(Word mode, Word arg1, Word arg2);
+
+int mach_inc(Word mode, Word arg1, Word arg2);
+int mach_dec(Word mode, Word arg1, Word arg2);
+
+int mach_mul(Word mode, Word arg1, Word arg2);
+int mach_div(Word mode, Word arg1, Word arg2);
+
+int mach_shr(Word mode, Word arg1, Word arg2);
+int mach_shl(Word mode, Word arg1, Word arg2);
+int mach_jmp(Word mode, Word arg1, Word arg2);
+
+/* lint */
+int lint_drd(Word mode, Word arg1, Word arg2);
+int lint_dwr(Word mode, Word arg1, Word arg2);
+
+int lint_not(Word mode, Word arg1, Word arg2);
+int lint_and(Word mode, Word arg1, Word arg2);
+int lint_nor(Word mode, Word arg1, Word arg2);
+int lint_xor(Word mode, Word arg1, Word arg2);
+
+int lint_add(Word mode, Word arg1, Word arg2);
+int lint_sub(Word mode, Word arg1, Word arg2);
+
+int lint_inc(Word mode, Word arg1, Word arg2);
+int lint_dec(Word mode, Word arg1, Word arg2);
+
+int lint_mul(Word mode, Word arg1, Word arg2);
+int lint_div(Word mode, Word arg1, Word arg2);
+
+int lint_shr(Word mode, Word arg1, Word arg2);
+int lint_shl(Word mode, Word arg1, Word arg2);
+int lint_jmp(Word mode, Word arg1, Word arg2);
--- /dev/null
+++ b/5552a.c
@@ -1,0 +1,267 @@
+#include "port.h"
+#include "5552.h"
+
+char*
+readin(char *in, int len)
+{
+ memset(in, 1, len);
+ for(int i = 0 ; i < len || in+i ; i++)
+ read(1, in+i, 1);
+
+ return in;
+}
+
+void
+asmtobin(char *in)
+{
+ int tmp = 0, len;
+ char *buf;
+
+ len = strlen(in);
+ for(int i = 0 ; i < len && in[i] ; i++)
+ {
+ if(in[i] == '\t')
+ continue;
+ else if(in[i] == '\n' || in[i] == '\0')
+ {
+ buf[tmp++] = '\0';
+ tmp = 0;
+ tobin(buf);
+ }
+ buf[tmp++] = in[i];
+ }
+}
+
+void
+tobin(char *line)
+{
+ int *inst, *arg1, *arg2;
+
+ match(line, inst, arg1, arg2);
+}
+
+int
+matchinst(char *s)
+{
+ int inst = -1;
+
+ if(!strcmp(s, "DRD"))
+ inst = DRD;
+ if(!strcmp(s, "DWR"))
+ inst = DWR;
+
+ if(!strcmp(s, "NOT"))
+ inst = NOT;
+ if(!strcmp(s, "AND"))
+ inst = AND;
+ if(!strcmp(s, "NOR"))
+ inst = NOR;
+ if(!strcmp(s, "XOR"))
+ inst = XOR;
+
+ if(!strcmp(s, "ADD"))
+ inst = ADD;
+ if(!strcmp(s, "SUB"))
+ inst = SUB;
+
+ if(!strcmp(s, "INC"))
+ inst = INC;
+ if(!strcmp(s, "DEC"))
+ inst = DEC;
+
+ if(!strcmp(s, "MUL"))
+ inst = MUL;
+ if(!strcmp(s, "DIV"))
+ inst = DIV;
+
+ if(!strcmp(s, "SHR"))
+ inst = SHR;
+ if(!strcmp(s, "SHL"))
+ inst = SHL;
+
+ if(!strcmp(s, "JMP"))
+ inst = JMP;
+
+ if(inst == -1)
+ sysfatal("No instruction found for %s", s);
+
+ return inst;
+}
+
+void
+addlabel(char *name)
+{
+ for(int i = 0 ; i < lc ; i++)
+ {
+ if(!strcmp(labels[i].name, name))
+ sysfatal("duplicate label %s\t
+ "prev pc: %x\t"
+ "curr pc: %x", name, labels[i].pc, pc);
+ }
+
+ labels[lc].name = name;
+ labels[lc].pc = pc;
+
+ lc++;
+}
+
+void
+matchline(char *line)
+{
+ int len, spaces[2], scount = 0;
+
+ len = strlen(line);
+ for(int i = 0 ; i < len ; i++)
+ {
+ if(line[i] == ' ')
+ {
+ if(scount < 2)
+ spaces[scount++] = i;
+ else
+ {
+ fprint(2, "Too many spaces in the line:\n"
+ "\t%s\n\t", line);
+ for(int j = 0 ; j < i ; j++)
+ fprint(2, " ");
+
+ fprint(2, "^\n");
+ sysfatal("Too many spaces.");
+ }
+
+ }
+ else if(line[i] == ':' && line[i+1] == '\n' && scount == 0)
+ {
+ addlabel(line);
+ return;
+ }
+ }
+
+ for(int i = 0 ; i < scount ; i++)
+ line[spaces[i]] = '\0';
+
+ program[pc].inst = matchinst(line);
+ if(scount == 1)
+ program[pc].arg1 = atoi(line+spaces[0]);
+ else if(scount == 2)
+ program[pc].arg2 = atoi(line+spaces[1]);
+ pc++
+}
+
+void
+lint(void)
+{
+ int res, totalres[2] = {0, 0};
+
+ for(int i = 0 ; i < pc ; i++)
+ {
+ res = lintop(program[i]);
+ if(res & WARN)
+ totalres[WARN]++;
+ if(res & ERR)
+ totalres[ERR]++;
+ }
+ if(totalres[WARN] || totalres[ERR])
+ fprint(2, "%d warnnings and %d errors detected\n",
+ totalres[WARN], totalres[ERR]);
+}
+
+int
+lintop(int linenumber)
+{
+ Op op = program[linenumber];
+ for(int i ; i < sizeof(instructions) / sizeof(Inst) ; i++)
+ {
+ if(op.inst == instructions[i].inst)
+ return instructions[i].lint(op.mode, op.arg1, op.arg2);
+ }
+}
+
+void
+asm(int flags)
+{
+ asm2bin(input);
+ if(flags & SFLAG)
+ {
+ for(int i = 0 ; i < pc ; i++)
+ {
+ write(0, program[i].inst, sizeof(Word));
+ write(0, program[i].mode, sizeof(Word));
+ write(0, program[i].arg1, sizeof(Word));
+ write(0, program[i].arg2, sizeof(Word));
+ }
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ unsigned int inst, a, b, c;
+ char string[32], op[4];
+ while(scanf("%s %[^\n;]%*c", op, string) > 0)
+ {
+ sscanf(string, "%u %u %u", &a, &b, &c);
+ if(!strcmp(op, "DIE"))
+ inst = DIE;
+ if(!strcmp(op, "OUT"))
+ inst = OUT;
+ if(!strcmp(op, "NOT"))
+ inst = NOT;
+ if(!strcmp(op, "AND"))
+ inst = AND;
+ if(!strcmp(op, "NOR"))
+ inst = NOR;
+ if(!strcmp(op, "XOR"))
+ inst = XOR;
+ if(!strcmp(op, "SUB"))
+ inst = SUB;
+ if(!strcmp(op, "ADD"))
+ inst = ADD;
+ if(!strcmp(op, "SHR"))
+ inst = SHR;
+ if(!strcmp(op, "SHL"))
+ inst = SHL;
+ if(!strcmp(op, "PUT"))
+ inst = PUT;
+ if(!strcmp(op, "MOV"))
+ inst = MOV;
+ if(!strcmp(op, "LDM"))
+ inst = LDM;
+ if(!strcmp(op, "NTH"))
+ inst = NTH;
+
+ switch(inst)
+ {
+ /* no args */
+ case DIE:
+ printf("%u\n", inst);
+ break;
+ /* one arg */
+ case NOT:
+ case OUT:
+ printf("%u %u\n", inst, a);
+ break;
+ /* two args */
+ case PUT:
+ case MOV:
+ case LDM:
+ printf("%u %u %u\n", inst, a, b);
+ break;
+ /* three args */
+ case AND:
+ case NOR:
+ case XOR:
+ case SUB:
+ case SHL:
+ case SHR:
+ case ADD:
+ case NTH:
+ printf("%u %u %u %u\n", inst, a, b, c);
+ break;
+ /* should this ever happen? */
+ default:
+ fprintf(stderr, "unkown instr.\n");
+ return -1;
+
+ }
+ }
+ return 0;
+}
--- /dev/null
+++ b/5552l.c
@@ -1,0 +1,1 @@
+#include "5552.h"