about summary refs log tree commit diff
path: root/pps.c
diff options
context:
space:
mode:
Diffstat (limited to 'pps.c')
-rw-r--r--pps.c108
1 files changed, 108 insertions, 0 deletions
diff --git a/pps.c b/pps.c
new file mode 100644
index 0000000..1bcba88
--- /dev/null
+++ b/pps.c
@@ -0,0 +1,108 @@
+/*
+ * Prototype Processor aSsembler
+ *
+ * Computer architecture is by qubane
+ * Assembler is by nakidai and released in public domain
+ */
+
+#include <ctype.h>
+#include <err.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#define LINESZ 128
+
+#define is(x, y) if (!strcmp((x), (y)))
+
+char line[LINESZ];
+
+void parsefile(const char *);
+
+void emit(char inst)
+{
+	printf("%04b\n", (int)inst);
+}
+
+void tolowers(char *s)
+{
+	for (; *s; ++s)
+		*s = tolower(*s);
+}
+
+int parsereg(const char *name)
+{
+	switch (*name)
+	{
+	case 'b': return 0;
+	case 'm': return 1;
+	case 'p': return 2;
+	default:  return -1;
+	}
+}
+
+void parseline(char *line, const char *path, size_t n)
+{
+	char *arg = strchr(line, ' '),
+	     *end = strchr(line, '\n');
+
+	arg && (*arg = 0);
+	end && (*end = 0);
+
+	if (!*line)
+		return;
+
+	tolowers(line);
+
+	if (!arg++)
+		is (line, "ca")       emit(8);
+		else is (line, "add") emit(9);
+		else is (line, "sub") emit(10);
+		else is (line, "and") emit(11);
+		else is (line, "or")  emit(12);
+		else is (line, "xor") emit(13);
+		else is (line, "rd")  emit(14);
+		else is (line, "wt")  emit(15);
+		else is (line, ";")   ;
+		else errx(1, "%s:%d: invalid instruction: %s", path, n, line);
+	else
+		is (line, "lda")
+			emit(atoi(arg));
+		else is (line, "movc")
+			if (tolowers(arg), parsereg(arg) < 0)
+				errx(1, "%s:%lu: invalid instruction: %s %s", path, n, line, arg);
+			else
+				emit(4 + parsereg(arg));
+		else is (line, "mov")
+			if (tolowers(arg), parsereg(arg) != 0)
+				errx(1, "%s:%lu: invalid instruction: %s %s", path, n, line, arg);
+			else
+				emit(7);
+		else is (line, "inc") parsefile(arg);
+		else is (line, ";");
+		else errx(1, "%s:%lu invalid instruction: %s %s", path, n, line, arg);
+}
+
+void parsefile(const char *file)
+{
+	FILE *fp = fopen(file, "r");
+	size_t n = 0;
+
+	if (!fp)
+		err(1, "fopen(%s)", file);
+
+	while (fgets(line, sizeof(line), fp))
+		parseline(line, file, n++);
+
+	if (ferror(fp))
+		err(1, "fgets(%s)", file);
+}
+
+int main(int argc, char **argv)
+{
+	if (!argv[1] || !*argv[1])
+		return fprintf(stderr, "usage: %s <filename>\n", *argv), 1;
+	parsefile(argv[1]);
+}