wm: 5552

Download patch

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"