commit 79af4d94d841d4607bf1a84e88fcad239dfe8567
parent 49ecfefebf572d3c298ca2d0a6ed3916ee5b0cb7
Author: thing1 <l.standen@posteo.com>
Date: Sat, 4 Oct 2025 18:47:03 +0100
added command line options and cleaned up some code
Diffstat:
| M | Makefile | | | 2 | +- |
| A | arg.h | | | 49 | +++++++++++++++++++++++++++++++++++++++++++++++++ |
| M | examples/Makefile | | | 10 | +++++----- |
| M | lli.c | | | 93 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- |
| M | lli.h | | | 8 | +++++++- |
| M | lliasm.c | | | 61 | ++++++++++++++++++++++++++++++++++++++++++++++++++----------- |
6 files changed, 203 insertions(+), 20 deletions(-)
diff --git a/Makefile b/Makefile
@@ -1,4 +1,4 @@
-CFLAGS=-ggdb
+CFLAGS=-O0
all: lli lliasm
diff --git a/arg.h b/arg.h
@@ -0,0 +1,49 @@
+/*
+ * Copy me if you can.
+ * by 20h
+ */
+
+#ifndef ARG_H__
+#define ARG_H__
+
+extern char *argv0;
+
+/* use main(int argc, char *argv[]) */
+#define ARGBEGIN for (argv0 = *argv, argv++, argc--;\
+ argv[0] && argv[0][0] == '-'\
+ && argv[0][1];\
+ argc--, argv++) {\
+ char argc_;\
+ char **argv_;\
+ int brk_;\
+ if (argv[0][1] == '-' && argv[0][2] == '\0') {\
+ argv++;\
+ argc--;\
+ break;\
+ }\
+ for (brk_ = 0, argv[0]++, argv_ = argv;\
+ argv[0][0] && !brk_;\
+ argv[0]++) {\
+ if (argv_ != argv)\
+ break;\
+ argc_ = argv[0][0];\
+ switch (argc_)
+
+#define ARGEND }\
+ }
+
+#define ARGC() argc_
+
+#define EARGF(x) ((argv[0][1] == '\0' && argv[1] == NULL)?\
+ ((x), abort(), (char *)0) :\
+ (brk_ = 1, (argv[0][1] != '\0')?\
+ (&argv[0][1]) :\
+ (argc--, argv++, argv[0])))
+
+#define ARGF() ((argv[0][1] == '\0' && argv[1] == NULL)?\
+ (char *)0 :\
+ (brk_ = 1, (argv[0][1] != '\0')?\
+ (&argv[0][1]) :\
+ (argc--, argv++, argv[0])))
+
+#endif
diff --git a/examples/Makefile b/examples/Makefile
@@ -1,15 +1,15 @@
all: cat loadprog callstack print conditional
cat: cat.ll
- lliasm cat.ll cat.rom
+ lliasm -o cat.rom cat.ll
loadprog: loadprog.ll
- lliasm loadprog.ll loadprog.rom
+ lliasm -o loadprog.rom loadprog.ll
callstack: callstack.ll
- lliasm callstack.ll callstack.rom
+ lliasm -o callstack.rom callstack.ll
print: print.ll
- lliasm print.ll print.rom
+ lliasm -o print.rom print.ll
conditional: conditional.ll
- lliasm conditional.ll conditional.rom
+ lliasm -o conditional.rom conditional.ll
clean:
rm -rf *.rom
diff --git a/lli.c b/lli.c
@@ -1,7 +1,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <stdbool.h>
+#include "arg.h"
+char *argv0;
#include "lli.h"
#include "cores/unix_core.h"
@@ -29,6 +32,10 @@
s->sptr += sizeof(type); \
}
+#define SAME(s1, s2) (strcmp(s1, s2) == 0)
+
+bool debug = false;
+
mkpop(uint32_t);
mkpop(uint16_t);
mkpop(uint8_t);
@@ -41,10 +48,42 @@ mkpush(uint32_t);
mkpush(uint16_t);
mkpush(uint8_t);
+
char memory[INT32_MAX];
char *pc = &memory[0x1000];
void
+debug_console(stack *s, stack *cs) {
+ char word[64];
+ for (;;) {
+ memset(word, 0, 64);
+ printf("(0x%x) ", pc - memory);
+ scanf("%s", word);
+ while (getchar() != '\n') continue;
+ if (SAME(word, "stack") || SAME(word, "s")) {
+ if ((s->sptr - s->arr) == 0)
+ fprintf(stderr, "Stack is empty\n");
+ else {
+ for (int i = 0; i < (s->sptr - s->arr); i++)
+ printf("%d: 0x%x %d\n", i, s->arr[i], s->arr[i]);
+ }
+ }
+ else if (SAME(word, "print") || SAME(word, "p")) {
+ if ((s->sptr - s->arr) == 0)
+ fprintf(stderr, "Stack is empty\n");
+ else
+ printf("0x%x %d\n", *(s->sptr - 1) , *(s->sptr - 1));
+ }
+ else if (SAME(word, "next") || SAME(word, "n"))
+ return;
+ else if (SAME(word, "quit") || SAME(word, "q"))
+ exit(0);
+ else
+ fprintf(stderr, "unknown cmd\n");
+ }
+}
+
+void
lliexec() {
stack s = {
.cap = 512,
@@ -60,6 +99,9 @@ lliexec() {
step:
+ if (debug)
+ debug_console(&s, &cs);
+
uint8_t opcode = *(uint8_t *)pc, val8;
uint16_t val16;
uint32_t loc, val32, operand1, operand2;
@@ -161,6 +203,10 @@ step:
case MUL:
case EQU:
case NEQ:
+ case LT:
+ case GT:
+ case LTE:
+ case GTE:
operand2 = pop_uint32_t(&s);
operand1 = pop_uint32_t(&s);
switch (opcode) {
@@ -189,6 +235,22 @@ step:
val8 = (operand1 != operand2);
push_uint8_t(&s, &val8);
break;
+ case LT:
+ val8 = (operand1 < operand2);
+ push_uint8_t(&s, &val8);
+ break;
+ case GT:
+ val8 = (operand1 < operand2);
+ push_uint8_t(&s, &val8);
+ break;
+ case LTE:
+ val8 = (operand1 <= operand2);
+ push_uint8_t(&s, &val8);
+ break;
+ case GTE:
+ val8 = (operand1 <= operand2);
+ push_uint8_t(&s, &val8);
+ break;
}
break;
@@ -228,15 +290,42 @@ step:
end:
free(s.arr);
+ free(cs.arr);
+}
+
+void
+usage() {
+ fprintf(stderr, "usage: %s [-dh] file\n", argv0);
+ exit(1);
}
int
main(int argc, char **argv) {
- FILE *f = fopen(argv[1], "rb");
+ FILE *f;
+ int len;
+ ARGBEGIN {
+ case 'd': debug = true; break;
+ case 'h': usage(); break;
+ default: usage();
+ } ARGEND;
+
+ if (!*argv)
+ usage();
+
+ f = fopen(*argv, "rb");
+ if (!f) {
+ perror("failed to open file");
+ exit(1);
+ }
+ argv++;
+ if (*argv) usage();
+
+
fseek(f, 0, SEEK_END);
- int len = ftell(f);
+ len = ftell(f);
rewind(f);
+
if (len > INT32_MAX) exit(1);
fread(memory, 1, INT32_MAX, f);
fclose(f);
diff --git a/lli.h b/lli.h
@@ -12,6 +12,8 @@ typedef enum ttype {
LABEL,
PAD,
+ /* defining all the values is un-needed, but it makes debugging from hexdump easier to see all the values */
+
PUSH = 10,
PUSHA = 11,
@@ -51,8 +53,12 @@ typedef enum ttype {
EQU = 39,
NEQ = 40,
+ LT = 42,
+ GT = 43,
+ LTE = 44,
+ GTE = 45,
- HALT = 41,
+ HALT = 100,
} ttype;
typedef struct tval {
diff --git a/lliasm.c b/lliasm.c
@@ -3,7 +3,10 @@
#include <string.h>
#include <ctype.h>
#include <unistd.h>
+#include <stdbool.h>
+#include "arg.h"
+char *argv0;
#include "lli.h"
#define SAME(s1, s2) (strcmp(s1, s2) == 0)
@@ -19,6 +22,8 @@ int label_count = 0;
char buffer[INT16_MAX] = {0};
int len = 0;
+bool commentmode = false;
+
char *
drainfile(FILE *f) {
char *contents;
@@ -218,6 +223,14 @@ notnum:
val->type = EQU;
else if (SAME(word, "neq"))
val->type = NEQ;
+ else if (SAME(word, "lt"))
+ val->type = LT;
+ else if (SAME(word, "gt"))
+ val->type = GT;
+ else if (SAME(word, "lte"))
+ val->type = LTE;
+ else if (SAME(word, "gte"))
+ val->type = GTE;
/* misc */
else if (SAME(word, "halt"))
@@ -297,23 +310,47 @@ compile(tval *val, int bytesdeep) {
return bytesdeep;
}
+void
+usage() {
+ fprintf(stderr, "usage: %s [-ch] [-o out] in.ll\n", argv0);
+ exit(1);
+}
+
int
main(int argc, char **argv) {
FILE *in, *out;
- if (argc < 2)
- errormsg("No file given");
- in = fopen(argv[1], "r");
- if (!in)
- errormsg("couldn't open input");
- if (argc == 3) {
- out = fopen(argv[2], "wb");
- if (!out)
- errormsg("couldn't open output");
- } else
- out = fopen("a.rom", "wb");
+ ARGBEGIN {
+ case 'c': commentmode = true; break;
+ case 'h': usage(); break;
+ case 'o':
+ out = fopen(EARGF(usage), "wb");
+ if (!out) {
+ perror("failed to open output");
+ return 1;
+ }
+ break;
+ default: usage();
+ } ARGEND;
+
+ if (!*argv) usage();
+ if (!(in = fopen(*argv, "r"))) {
+ perror("failed to open input");
+ return 1;
+ }
+ if (!out) {
+ if (commentmode) out = stdout;
+ else out = fopen("a.rom", "wb");
+ }
+ argv++;
+ if (*argv) usage();
+
int size;
char *input = stripcomments(drainfile(in)), *swp = strdup(input), *tmp = input;
+ if (commentmode) {
+ fprintf(out, "%s", input);
+ return 0;
+ }
char *word;
tval *val;
int bytesdeep;
@@ -339,4 +376,6 @@ again:
fclose(out);
free(input);
free(swp);
+
+ return 0;
}