added various (bad) example programs
This commit is contained in:
parent
3b93b864ac
commit
314da51aaf
12
programs/Makefile
Normal file
12
programs/Makefile
Normal file
@ -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
|
||||
|
15
programs/README.md
Normal file
15
programs/README.md
Normal file
@ -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`.
|
104
programs/simple.c
Normal file
104
programs/simple.c
Normal file
@ -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)
|
||||
);
|
||||
}
|
115
programs/spawn.c
Normal file
115
programs/spawn.c
Normal file
@ -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)
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue
Block a user