lli

A small emulated asm like lang
Log | Files | Refs

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:
MMakefile | 2+-
Aarg.h | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Mexamples/Makefile | 10+++++-----
Mlli.c | 93+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Mlli.h | 8+++++++-
Mlliasm.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; }