From 314da51aaf68fd420add9d8096635202aa777964 Mon Sep 17 00:00:00 2001 From: Anton Lydike Date: Sat, 21 Aug 2021 21:24:21 +0200 Subject: [PATCH] added various (bad) example programs --- programs/Makefile | 12 +++++ programs/README.md | 15 ++++++ programs/simple.c | 104 ++++++++++++++++++++++++++++++++++++++++ programs/spawn.c | 115 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 246 insertions(+) create mode 100644 programs/Makefile create mode 100644 programs/README.md create mode 100644 programs/simple.c create mode 100644 programs/spawn.c diff --git a/programs/Makefile b/programs/Makefile new file mode 100644 index 0000000..af679be --- /dev/null +++ b/programs/Makefile @@ -0,0 +1,12 @@ + +CC = riscv32-unknown-elf-gcc +CFLAGS = -nostdlib -mcmodel=medany -Wall -Wextra -pedantic-errors -T ../linker.ld + +simple: + $(CC) $(CFLAGS) -o simple simple.c + +spawn: + $(CC) $(CFLAGS) -o spawn spawn.c + +all: simple spawn + diff --git a/programs/README.md b/programs/README.md new file mode 100644 index 0000000..ef084b3 --- /dev/null +++ b/programs/README.md @@ -0,0 +1,15 @@ +# EMBARK example programs + +Note that these programs are of poor quality. + +* `simple.c` does some arithmetic in a loop, occasionally prints something rather random (the sequence goes `90,90,90,2386,2386,ae86,520c,1cbde,...`) +* `spawn.c` this thing spawn a new thread and exits when the thread overwrites a value. + +## Compiling + +The important thing when compiling user binaries are the following: + + * `-mcmodel=medany` makes all address loads pc-relative. This allows for relocating binaries without much effort. This only works, if the addresses are larger than signed 12 bit number, so make sure you programs are located far enough into memory. (the default linker script takes care of that) + * `-T ../linker.ld` use the kernel linker script. This packs everything nice and close and sets the `__global_pointer$` etc up. + + If you don't want to worry, use the makefile `make all`. diff --git a/programs/simple.c b/programs/simple.c new file mode 100644 index 0000000..43e22ae --- /dev/null +++ b/programs/simple.c @@ -0,0 +1,104 @@ + +#define TEXT_IO_ADDR 0xff0000 +#define TEXT_IO_BUFLEN 64 + +void dbgln(char*, int); +char* itoa (int value, char* str, int base); + + +char text[48] = "the number is "; + +int main() { + dbgln("main", 4); + int a = 144; + while (1) { + for (int i = 0; i < 10000; i++) { + for (int j = 0; j < 10000; j++) { + a ^= (((a<<16) ^ a) & i) << 4; + a ^= ((a & (j << 4)) >> 3) ^ (i*j); + } + itoa(a, &text[14], 16); + dbgln(text, 32); + } + __asm__("ebreak"); + } + + return a; +} + +void dbgln(char* text, int len) +{ + while (len > TEXT_IO_BUFLEN) { + dbgln(text, TEXT_IO_BUFLEN); + text += TEXT_IO_BUFLEN; + len -= TEXT_IO_BUFLEN; + } + + char* ioaddr = (char*) TEXT_IO_ADDR + 4; + + for (int i = 0; i < len; i++) { + if (*text == 0) + break; + *ioaddr++ = *text++; + } + + if (len < TEXT_IO_BUFLEN) + *ioaddr = '\n'; + + // write a 1 to the start of the textIO to signal a buffer flush + *((char*) TEXT_IO_ADDR) = 1; +} + +char alpha[16] = "0123456789abcdef"; +char* itoa (int value, char* str, int base) +{ + if (base > 16 || base < 2) { + *str++ = '?'; + return str; + } + + if (value < 0) { + *str++ = '-'; + value *= -1; + } + + int digits = 0; + int num = 0; + // reverse number + do { + num = num * base; + num += value % base; + value = value / base; + digits++; + } while (value > 0); + + value = num; + do { + num = value % base; + value = value / base; + *str++ = alpha[num]; + digits--; + } + while (digits > 0); + + return str; +} + +void _start() { + __asm__( + ".option push\n" + ".option norelax\n" + " la gp, _gp\n" + ".option pop\n" + ); + + dbgln("start", 5); + int exit_code = main(); + dbgln("end", 3); + + __asm__( + "mv a0, %0\n" + "li a7, 5\n" + "ecall" :: "r"(exit_code) + ); +} \ No newline at end of file diff --git a/programs/spawn.c b/programs/spawn.c new file mode 100644 index 0000000..b575bb6 --- /dev/null +++ b/programs/spawn.c @@ -0,0 +1,115 @@ + +#define TEXT_IO_ADDR 0xff0000 +#define TEXT_IO_BUFLEN 64 + +void dbgln(char*, int); +char* itoa (int value, char* str, int base); + +int thread(void* args); + +int main() { + dbgln("main", 4); + + int arg = 144; + + __asm__( + "mv a0, %0\n" + "mv a1, %1\n" + "li a7, 1\n" + "ecall" :: "r"(thread), "r"(&arg) + ); + + while (arg == 144) {} + __asm__("ebreak"); + + return 0; +} + +int thread(void* args) +{ + int arg = *((int*) args); + char buff[32] = "the magic number is: "; + char* end = itoa(arg, &buff[21], 10); + dbgln(buff, (int)(end - buff)); + + // *((int*) args) = 0; + + return arg; +} + +void dbgln(char* text, int len) +{ + while (len > TEXT_IO_BUFLEN) { + dbgln(text, TEXT_IO_BUFLEN); + text += TEXT_IO_BUFLEN; + len -= TEXT_IO_BUFLEN; + } + + char* ioaddr = (char*) TEXT_IO_ADDR + 4; + + for (int i = 0; i < len; i++) { + if (*text == 0) + break; + *ioaddr++ = *text++; + } + + if (len < TEXT_IO_BUFLEN) + *ioaddr = '\n'; + + // write a 1 to the start of the textIO to signal a buffer flush + *((char*) TEXT_IO_ADDR) = 1; +} + +char alpha[16] = "0123456789abcdef"; +char* itoa (int value, char* str, int base) +{ + if (base > 16 || base < 2) { + *str++ = '?'; + return str; + } + + if (value < 0) { + *str++ = '-'; + value *= -1; + } + + int digits = 0; + int num = 0; + // reverse number + do { + num = num * base; + num += value % base; + value = value / base; + digits++; + } while (value > 0); + + value = num; + do { + num = value % base; + value = value / base; + *str++ = alpha[num]; + digits--; + } + while (digits > 0); + + return str; +} + +void _start() { + __asm__( + ".option push\n" + ".option norelax\n" + " la gp, _gp\n" + ".option pop\n" + ); + + dbgln("start", 5); + int exit_code = main(); + dbgln("end", 3); + + __asm__( + "mv a0, %0\n" + "li a7, 5\n" + "ecall" :: "r"(exit_code) + ); +} \ No newline at end of file