about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNakidai <nakidai@disroot.org>2025-07-24 08:30:00 +0300
committerNakidai <nakidai@disroot.org>2025-07-24 08:30:00 +0300
commitf09b4adbc7776cfce4c3762968edc82460956f92 (patch)
tree9a46545219a636ad89d5025c2776a8e08a112c83
downloadpps-f09b4adbc7776cfce4c3762968edc82460956f92.tar.gz
pps-f09b4adbc7776cfce4c3762968edc82460956f92.zip
Add code v1.0.0
-rw-r--r--.gitignore1
-rw-r--r--Makefile3
-rw-r--r--README22
-rw-r--r--example.S67
-rw-r--r--pps.c108
5 files changed, 201 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..bf3e96e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+pps
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..f47c4cb
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,3 @@
+all: pps
+clean:
+	rm -f pps
diff --git a/README b/README
new file mode 100644
index 0000000..5651f66
--- /dev/null
+++ b/README
@@ -0,0 +1,22 @@
+Prototype Processor aSsembler
+
+computer architecture[1] is by qubane[2];
+assembler is by nakidai[3] and released in public domain
+
+pros:
+- factored out emit() function so it can be replaced with something more
+  suitable for your specific use case
+- case insensitive where not needed
+- `inc' mnemonic that includes some other file
+cons:
+- doesn't handle comments very good, but still (start line with `; ' to make
+  one)
+- code is garbage a little
+other:
+- lda instruction uses atoi for number converting, hence number base there is 10
+- register check is case insensitive by 1 letter, so e.g. ACC can be named as a,
+  AcC, acC, AR etc
+
+[1] https://docs.google.com/spreadsheets/d/1ESjhZcvpGmuHCNxgOESfSy-MXQoqrMqCyCDJyvDhRMM/edit?usp=sharing
+[2] https://github.com/qubane
+[3] https://nakidai.ru
diff --git a/example.S b/example.S
new file mode 100644
index 0000000..530501a
--- /dev/null
+++ b/example.S
@@ -0,0 +1,67 @@
+; Fibonacci sequence program by qubane
+
+; address for var A
+CA
+MOVC MR
+
+; write 0
+WT
+
+; address for var B
+LDA 1
+MOVC MR
+
+; write 1
+WT
+
+; loop start
+; load address for var A
+CA
+MOVC MR
+
+; move var A to BR
+RD
+MOV BR
+
+; load address for var B
+CA
+LDA 1
+MOVC MR
+
+; read var B
+RD
+
+; A + B -> B
+ADD
+WT
+
+; move A + B to BR
+MOV BR
+
+; load address for var A
+CA
+; clear carry flag
+AND
+MOVC MR
+
+; read var A
+RD
+
+; compute -(A - B)
+SUB
+
+MOV BR
+
+CA
+SUB
+
+; write B - A to var A
+WT
+
+; load jump address
+CA
+; reset carry flag
+and
+LDA 1
+LDA 2
+MOVC PC
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]);
+}