lli

A small emulated asm like lang
Log | Files | Refs

commit 23e36ee7be6254d01bee13a7d23db5ebe574e73a
parent 07cb2d7cd9b825c87aec47207073f793be320883
Author: thing1 <l.standen@posteo.com>
Date:   Sun,  5 Oct 2025 13:17:58 +0100

added full support for standard unix functions!

Diffstat:
M.gitignore | 2++
MMakefile | 2++
Mcores/unix_core.c | 83++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
Mexamples/Makefile | 6+++++-
Mexamples/callstack.ll | 2+-
Aexamples/fork.ll | 38++++++++++++++++++++++++++++++++++++++
Aexamples/fs.ll | 19+++++++++++++++++++
Mexamples/print.ll | 2+-
Mlliasm.c | 2+-
9 files changed, 147 insertions(+), 9 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -2,3 +2,5 @@ lli lliasm *.rom *.so +*.tar +*.txt diff --git a/Makefile b/Makefile @@ -8,6 +8,8 @@ lliasm: lliasm.c cc lliasm.c -o lliasm ${CFLAGS} cores: cores/* cd cores && make +tarball: + tar -cf lli.tar * install: all cp lli lliasm /usr/local/bin diff --git a/cores/unix_core.c b/cores/unix_core.c @@ -1,14 +1,64 @@ #include <stdio.h> #include <stdlib.h> +#include <stdint.h> +#include <fcntl.h> +#include <unistd.h> +#include <string.h> /* table of memory - * | function | size | - * ------------------ - * | stdin | 1 | - * | stdout | 1 | - * | stderr | 1 | + * | function | size | loc | + * +----------+------+-----+ + * | stdin | 1 | 0 | + * | stdout | 1 | 1 | + * | stderr | 1 | 2 | + * | syscall | 1 | 3 | + * | arg1 | 4 | 4 | + * | arg2 | 4 | 8 | + * | arg3 | 4 | 12 | + * | arg4 | 4 | 16 | + * | result | 4 | 20 | + * | fd | 4 | 24 | + * | read | 1 | 28 | + * | write | 1 | 29 | */ +enum syscalls { + NOP = 0, // no args + OPEN = 1, // path, 0 | 1 | 2 (read | write | append) -> id + CLOSE = 2, // id + EXIT = 3, // status + FORK = 4, // no args -> pid +}; + +static void +dosyscall(uint8_t num, int args[4], char *mem) { + int fd, pid; + switch (num) { + case NOP: return; + case OPEN: + if (args[1] == 0) + fd = open(&mem[args[0]], O_RDONLY); + else if (args[1] == 1) + fd = open(&mem[args[0]], O_RDWR | O_TRUNC | O_CREAT, 0666); + else if (args[1] == 2) + fd = open(&mem[args[0]], O_RDWR | O_APPEND | O_CREAT, 0666); + if (fd == -1) + perror("failed to open file"); + memcpy(&mem[20], &fd, sizeof(int)); + break; + case CLOSE: + close(args[0]); + break; + case EXIT: + exit(args[0]); + break; + case FORK: + pid = fork(); + memcpy(&mem[20], &pid, sizeof(int)); + break; + } +} + void onwrite(char *addr) { if (*(addr + 1)) { @@ -19,6 +69,25 @@ onwrite(char *addr) { putc(*(addr + 2), stderr); *(addr + 2) = 0; } + if (*(addr + 3)) { + int args[] = { + *(int *)(addr + 4), + *(int *)(addr + 8), + *(int *)(addr + 12), + *(int *)(addr + 16), + }; + dosyscall(*(uint8_t *)(addr + 3), args, addr); + *(addr + 3) = 0; + *(int *)(addr + 4) = 0; + *(int *)(addr + 8) = 0; + *(int *)(addr + 12) = 0; + *(int *)(addr + 16) = 0; + } + if (*(addr + 29)) { + char c = *(addr + 29); + write(*(int *)&addr[24], &c, 1); + *(addr + 29) = 0; + } } void @@ -26,4 +95,8 @@ onread(char *addr, char *ptr) { if (ptr == addr) { *ptr = getc(stdin); } + if (ptr == (addr + 28)) { + read(*(int *)&addr[24], (addr + 28), 1); + *(addr + 28) = 0; + } } diff --git a/examples/Makefile b/examples/Makefile @@ -1,4 +1,4 @@ -all: cat loadprog callstack print conditional +all: cat loadprog callstack print conditional fs fork cat: cat.ll lliasm -o cat.rom cat.ll @@ -10,6 +10,10 @@ print: print.ll lliasm -o print.rom print.ll conditional: conditional.ll lliasm -o conditional.rom conditional.ll +fs: fs.ll + lliasm -o fs.rom fs.ll +fork: fork.ll + lliasm -o fork.rom fork.ll clean: rm -rf *.rom diff --git a/examples/callstack.ll b/examples/callstack.ll @@ -1,5 +1,5 @@ |0x0 @stdin |0x1 @stdout |0x2 @stderr -|0x20 @str "hello b0 +|0x50 @str "hello b0 |0x100 @tester &str loadb &stdout storeb diff --git a/examples/fork.ll b/examples/fork.ll @@ -0,0 +1,38 @@ +(unix core) |0x0 @stdin |0x1 @stdout |0x2 @stderr |0x3 @syscall |0x4 @arg1 |0x8 @arg2 |0xc @arg3 |0x10 @arg4 |0x14 @result |0x18 @fd |0x1c @read |0x1d @write + +|0x100 @file "test.txt b0 + +@parent (writes the letter A to the file marked at @file) +&file &arg1 storei (opens the file) +#1 &arg2 storei +#1 i2b &syscall storeb + +&result loadi (gets the fd) +&fd storei + +#65 i2b &write storeb (write the letter) + +&fd loadi &arg1 storei (close the file) +#2 i2b &syscall storeb +ret + +@child (writes the letter B to stdout) +#66 i2b &stdout storeb (writes to stdout) +ret + +(main) |0x1000 +#4 i2b &syscall storeb + +&result loadi +#0 neq (if fork != 0) +&true jnz +&false jmp +@true (fork != 0) + &parent call + &end jmp +@false (fork == 0) + &child call + &end jmp +@end + +halt diff --git a/examples/fs.ll b/examples/fs.ll @@ -0,0 +1,19 @@ +(unix core) |0x0 @stdin |0x1 @stdout |0x2 @stderr |0x3 @syscall |0x4 @arg1 |0x8 @arg2 |0xc @arg3 |0x10 @arg4 |0x14 @result |0x18 @fd |0x1c @read |0x1d @write + +|0x100 @file "test.txt b0 + +(main) |0x1000 +&file &arg1 storei (load the address of file name) +#1 &arg2 storei (load the open mode) +#1 i2b &syscall storeb (open the file) + +&result loadi (move the fd to the fd register) +&fd storei + +#65 i2b &write storeb + +&fd loadi +&arg1 storei +#2 i2b &syscall storeb + +halt diff --git a/examples/print.ll b/examples/print.ll @@ -1,5 +1,5 @@ |0x0 @stdin |0x1 @stdout |0x2 @stderr (define stdin, stdout and error) -|0x10 @str "hello b32 "world b10 b0 (define the string to print, the b32, b10, and b0 are ascii for ' ', '\n' and '\0') +|0x50 @str "hello b32 "world b10 b0 (define the string to print, the b32, b10, and b0 are ascii for ' ', '\n' and '\0') |0x100 @print (define a print function) dupi (duplicate the input address, so it stays on the stack for the next call) diff --git a/lliasm.c b/lliasm.c @@ -64,7 +64,7 @@ readword(char *in) { if (!in) input = NULL; else input = in; - char *tok = strtok(input, " \n\0"); + char *tok = strtok(input, " \t\n\0"); while (tok && *tok && isblank(*tok)) tok++; return tok; }