From 922959191d973ff82eb28ff8d3d8a1772a0b8120 Mon Sep 17 00:00:00 2001 From: zongor Date: Sat, 20 Sep 2025 12:49:01 -0700 Subject: [PATCH] cleanup / prepwork for assembler. --- src/common.h | 3 ++ src/opcodes.h | 132 +++++++++++++++++++++++------------------------- src/str.c | 106 +++++++++++++++++++++++++++++++++++++- src/str.h | 3 ++ src/test.c | 3 +- src/test.h | 5 ++ src/vm.c | 103 ------------------------------------- test/fib.asm | 63 ++++++++++++----------- test/hello.asm | 12 +++-- test/simple.asm | 15 ++++-- 10 files changed, 234 insertions(+), 211 deletions(-) diff --git a/src/common.h b/src/common.h index 5abd9b8..83f28eb 100644 --- a/src/common.h +++ b/src/common.h @@ -16,4 +16,7 @@ typedef int32_t i32; #define USED(x) ((void)(x)) +#define AS_INT(v) ((i32)(v)) +#define AS_UINT(v) ((u32)(v)) + #endif diff --git a/src/opcodes.h b/src/opcodes.h index 1d72e4b..a14f142 100644 --- a/src/opcodes.h +++ b/src/opcodes.h @@ -4,55 +4,57 @@ #include "common.h" typedef enum { - OP_HALT, /* halt : terminate execution */ - OP_JMP, /* jump : jump to address dest unconditionally */ - OP_JMPF, /* jmpf : jump to address dest if flag is ne 0 */ - OP_CALL, /* call : creates a new frame */ - OP_RETURN, /* retn : returns from a frame to the parent frame */ - OP_LOAD, /* load : dest = &[next memory location] */ - OP_LOAD_IMM, /* load : dest = &[next memory location] */ - OP_STORE, /* stor : next memory location = src1 as float */ - OP_PUSH, /* push : push str ref from register onto the stack and copy str */ - OP_POP, /* pop : pop int from stack onto the register */ - OP_REG_MOV, /* rmov : dest = src1 */ - OP_SYSCALL, /* sysc : */ - OP_ADD_INT, /* addi : dest = src1 + src2 */ - OP_SUB_INT, /* subi : dest = src1 - src2 */ - OP_MUL_INT, /* muli : dest = src1 * src2 */ - OP_DIV_INT, /* divi : dest = src1 / src2 */ - OP_ADD_UINT, /* addu : dest = src1 + src2 */ - OP_SUB_UINT, /* subu : dest = src1 - src2 */ - OP_MUL_UINT, /* mulu : dest = src1 * src2 */ - OP_DIV_UINT, /* divu : dest = src1 / src2 */ - OP_ADD_REAL, /* addr : dest = src1 + src2 */ - OP_SUB_REAL, /* subr : dest = src1 - src2 */ - OP_MUL_REAL, /* mulr : dest = src1 * src2 */ - OP_DIV_REAL, /* divr : dest = src1 / src2 */ - OP_INT_TO_REAL, /* itor : dest = src1 as real */ - OP_UINT_TO_REAL, /* utor : dest = src1 as real */ - OP_REAL_TO_INT, /* rtoi : dest = src1 as int */ - OP_REAL_TO_UINT, /* rtou : dest = src1 as uint */ - OP_JEQ_INT, /* jeqi : jump to address dest if src1 as int == src2 as int */ - OP_JGT_INT, /* jgti : jump to address dest if src1 as int > src2 as int*/ - OP_JLT_INT, /* jlti : jump to address dest if src1 as int < src2 as int */ - OP_JLE_INT, /* jlei : jump to address dest if src1 as int <= src2 as int */ - OP_JGE_INT, /* jgei : jump to address dest if src1 as int >= src2 as int*/ - OP_JEQ_UINT, /* jequ : jump to address dest if src1 as int == src2 as uint */ - OP_JGT_UINT, /* jgtu : jump to address dest if src1 as int > src2 as uint*/ - OP_JLT_UINT, /* jltu : jump to address dest if src1 as int < src2 as uint */ - OP_JLE_UINT, /* jleu : jump to address dest if src1 as int <= src2 as uint */ - OP_JGE_UINT, /* jgeu : jump to address dest if src1 as int >= src2 as uint*/ - OP_JEQ_REAL, /* jeqr : jump to address dest if src1 as real == src2 as real */ - OP_JGE_REAL, /* jgtr : jump to address dest if src1 as real >= src2 as real */ - OP_JGT_REAL, /* jltr : jump to address dest if src1 as real > src2 as real */ - OP_JLT_REAL, /* jler : jump to address dest if src1 as real < src2 as real */ - OP_JLE_REAL, /* jger : jump to address dest if src1 as real <= src2 as real */ - OP_STRLEN, /* strl : dest = length of str at src1 ptr */ - OP_STREQ, /* steq : dest = src1 ptr string == src2 ptr string */ - OP_STRCAT, /* scat : dest = ptr of src1 ptr string + src2 ptr string */ - OP_STR_GET_CHAR, /* sgch : dest = ptr of src1 ptr string, src2 index of string */ - OP_STR_FIND_CHAR, /* sfch : dest = ptr of src1 ptr string, src2 uint8 char */ - OP_STR_SLICE, /* ssli : dest = ptr of src1 ptr string, src2 start index, src3 end index */ + OP_HALT, /* halt : terminate execution */ + OP_JMP, /* jump : jump to address dest unconditionally */ + OP_JMPF, /* jmpf : jump to address dest if flag is ne 0 */ + OP_CALL, /* call : creates a new frame */ + OP_RETURN, /* retn : returns from a frame to the parent frame */ + OP_LOAD, /* load : dest = &[next memory location] */ + OP_LOAD_IMM, /* load : dest = &[next memory location] */ + OP_STORE, /* stor : next memory location = src1 as float */ + OP_PUSH, /* push : push str ref from register onto the stack and copy str */ + OP_POP, /* pop : pop int from stack onto the register */ + OP_REG_MOV, /* rmov : dest = src1 */ + OP_SYSCALL, /* sysc : */ + OP_ADD_INT, /* addi : dest = src1 + src2 */ + OP_SUB_INT, /* subi : dest = src1 - src2 */ + OP_MUL_INT, /* muli : dest = src1 * src2 */ + OP_DIV_INT, /* divi : dest = src1 / src2 */ + OP_ADD_UINT, /* addu : dest = src1 + src2 */ + OP_SUB_UINT, /* subu : dest = src1 - src2 */ + OP_MUL_UINT, /* mulu : dest = src1 * src2 */ + OP_DIV_UINT, /* divu : dest = src1 / src2 */ + OP_ADD_REAL, /* addr : dest = src1 + src2 */ + OP_SUB_REAL, /* subr : dest = src1 - src2 */ + OP_MUL_REAL, /* mulr : dest = src1 * src2 */ + OP_DIV_REAL, /* divr : dest = src1 / src2 */ + OP_INT_TO_REAL, /* itor : dest = src1 as real */ + OP_UINT_TO_REAL, /* utor : dest = src1 as real */ + OP_REAL_TO_INT, /* rtoi : dest = src1 as int */ + OP_REAL_TO_UINT, /* rtou : dest = src1 as uint */ + OP_JEQ_INT, /* jeqi : jump to address dest if src1 as int == src2 as int */ + OP_JGT_INT, /* jgti : jump to address dest if src1 as int > src2 as int*/ + OP_JLT_INT, /* jlti : jump to address dest if src1 as int < src2 as int */ + OP_JLE_INT, /* jlei : jump to address dest if src1 as int <= src2 as int */ + OP_JGE_INT, /* jgei : jump to address dest if src1 as int >= src2 as int*/ + OP_JEQ_UINT, /* jequ : jump to address dest if src1 as int == src2 as uint */ + OP_JGT_UINT, /* jgtu : jump to address dest if src1 as int > src2 as uint*/ + OP_JLT_UINT, /* jltu : jump to address dest if src1 as int < src2 as uint */ + OP_JLE_UINT, /* jleu : jump to address dest if src1 as int <= src2 as uint */ + OP_JGE_UINT, /* jgeu : jump to address dest if src1 as int >= src2 as uint*/ + OP_JEQ_REAL, /* jeqr : jump to address dest if src1 as real == src2 as real */ + OP_JGE_REAL, /* jgtr : jump to address dest if src1 as real >= src2 as real */ + OP_JGT_REAL, /* jltr : jump to address dest if src1 as real > src2 as real */ + OP_JLT_REAL, /* jler : jump to address dest if src1 as real < src2 as real */ + OP_JLE_REAL, /* jger : jump to address dest if src1 as real <= src2 as real */ + OP_STRLEN, /* strl : dest = length of str at src1 ptr */ + OP_STREQ, /* steq : dest = src1 ptr string == src2 ptr string */ + OP_STRCAT, /* scat : dest = ptr of src1 ptr string + src2 ptr string */ + OP_STR_GET_CHAR, /* sgch : dest = ptr of src1 ptr string, src2 index of string + */ + OP_STR_FIND_CHAR, /* sfch : dest = ptr of src1 ptr string, src2 uint8 char */ + OP_STR_SLICE, /* ssli : dest = ptr of src1 ptr string, src2 start index, src3 + end index */ OP_INT_TO_STRING, /* itos : dest = src1 as str */ OP_UINT_TO_STRING, /* utos : dest = src1 as str */ OP_REAL_TO_STRING, /* rtos : dest = src1 as str */ @@ -99,38 +101,30 @@ typedef struct device_s { } Device; #define MEMORY_SIZE 1024 /*(640 * 480 + 65536)*/ -#define CODE_SIZE 128 /*8192*/ +#define CODE_SIZE 128 /*8192*/ #define FRAMES_SIZE 128 #define STACK_SIZE 256 #define DEVICES_SIZE 8 typedef struct vm_s { - u32 pc; /* program counter */ - u32 cp; /* code pointer (last allocated opcode) */ - u32 fp; /* frame pointer (current frame) */ - u32 sp; /* stack pointer (top of stack) */ - u32 rp; /* return stack pointer (top of stack) */ - u32 mp; /* memory pointer (last allocated value) */ - u32 dc; /* device count */ - u32 flag; /* flag (temporary results like SYSCALL status) */ - Frame frames[FRAMES_SIZE]; /* function call frames */ - u32 stack[STACK_SIZE]; /* main stack */ + u32 pc; /* program counter */ + u32 cp; /* code pointer (last allocated opcode) */ + u32 fp; /* frame pointer (current frame) */ + u32 sp; /* stack pointer (top of stack) */ + u32 rp; /* return stack pointer (top of stack) */ + u32 mp; /* memory pointer (last allocated value) */ + u32 dc; /* device count */ + u32 flag; /* flag (temporary results like SYSCALL status) */ + Frame frames[FRAMES_SIZE]; /* function call frames */ + u32 stack[STACK_SIZE]; /* main stack */ u32 return_stack[STACK_SIZE]; /* return stack (for call recursion) */ Device devices[DEVICES_SIZE]; /* device definitions */ u8 code[CODE_SIZE]; /* code block */ u8 memory[MEMORY_SIZE]; /* memory block */ } VM; -#define AS_INT(v) ((i32)(v)) -#define AS_UINT(v) ((u32)(v)) -#define AS_FIXED(v) ((float)(i32)(v) / 65536.0f) -#define TO_FIXED(f) ((u32)((i32)( \ - ((f) >= 0.0f) ? ((f) * 65536.0f + 0.5f) : ((f) * 65536.0f - 0.5f) \ -))) - #define read_u8(vm, location, addr) ((vm)->location[addr]) #define read_u16(vm, location, addr) \ - (((uint16_t)(vm)->location[(addr)] << 8) | \ - ((uint16_t)(vm)->location[(addr) + 1])) + (((u16)(vm)->location[(addr)] << 8) | ((u16)(vm)->location[(addr) + 1])) #define read_u32(vm, location, addr) \ (((u32)(vm)->location[(addr)] << 24) | \ ((u32)(vm)->location[(addr) + 1] << 16) | \ diff --git a/src/str.c b/src/str.c index 8db4401..19ed6d8 100644 --- a/src/str.c +++ b/src/str.c @@ -41,4 +41,108 @@ u32 strnlen(const char *str, u32 max_len) { ; /* twiddle thumbs, 'i' is doing all the work*/ } return i; -} \ No newline at end of file +} + + +/* Static digit lookup table (0-9) */ +const char digits[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; + +/* Writes decimal digits of 'value' backwards into 'buf_end' (inclusive), + stopping at 'buf_start'. Returns pointer to first written digit. */ +char *write_digits_backwards(u32 value, char *buf_end, char *buf_start) { + char *p = buf_end; + if (value == 0) { + *--p = '0'; + } else { + u32 num = value; + while (num && p > buf_start) { + *--p = digits[num % 10]; + num /= 10; + } + } + return p; +} + +void uint_to_string(u32 value, char *buffer) { + char temp[16]; + char *start; + char *end = temp + sizeof(temp) - 1; + *end = '\0'; + start = write_digits_backwards(value, end, temp); + strcopy(buffer, start, end - start + 1); /* +1 for null terminator */ +} + +void int_to_string(i32 value, char *buffer) { + char temp[17]; /* Extra space for '-' */ + i32 negative = 0; + u32 abs_value; + char *end = temp + sizeof(temp) - 1; + *end = '\0'; + + if (value == (-2147483647 - 1)) { /* INT32_MIN */ + strcopy(buffer, "-2147483648", 12); + return; + } + + if (value == 0) { + *--end = '0'; + } else { + if (value < 0) { + negative = 1; + abs_value = (u32)(-value); + } else { + abs_value = (u32)value; + } + + end = write_digits_backwards(abs_value, end, temp); + + if (negative) { + *--end = '-'; + } + } + + strcopy(buffer, end, temp + sizeof(temp) - end); +} + +void fixed_to_string(i32 value, char *buffer) { + char temp[32]; + i32 negative; + u32 int_part; + u32 frac_part, frac_digits; + char *end = temp + sizeof(temp) - 1; + *end = '\0'; + + negative = 0; + if (value < 0) { + negative = 1; + value = -value; + } + + int_part = AS_UINT(value >> 16); + frac_part = AS_UINT(value & 0xFFFF); + + /* Convert fractional part to 5 decimal digits */ + frac_digits = (frac_part * 100000U) / 65536U; + + /* Trim trailing zeros */ + while (frac_digits > 0 && frac_digits % 10 == 0) { + frac_digits /= 10; + } + + if (frac_digits > 0) { + end = write_digits_backwards(frac_digits, end, temp); + *--end = '.'; + } + + if (int_part == 0 && frac_digits == 0) { + *--end = '0'; + } else { + end = write_digits_backwards(int_part, end, temp); + } + + if (negative) { + *--end = '-'; + } + + strcopy(buffer, end, temp + sizeof(temp) - end); +} diff --git a/src/str.h b/src/str.h index 2756702..460abee 100644 --- a/src/str.h +++ b/src/str.h @@ -6,5 +6,8 @@ i32 strcopy(char* to, const char *from, u32 length); u32 strlen(const char* str); bool streq(const char *s1, const char *s2); +char *write_digits_backwards(u32 value, char *buf_end, char *buf_start); +void int_to_string(i32 value, char *buffer); +void fixed_to_string(i32 value, char *buffer); #endif diff --git a/src/test.c b/src/test.c index 101169d..cd312ca 100644 --- a/src/test.c +++ b/src/test.c @@ -48,8 +48,7 @@ bool compile_internal_test(const char *filename, VM *vm) { bool test_simple_compile(VM *vm) { u32 ptr; - u32 newline_addr = - str_alloc(vm, &vm->frames[vm->fp], "\n", 2); + /*u32 newline_addr = str_alloc(vm, &vm->frames[vm->fp], "\n", 2);*/ u32 terminal_path_addr = str_alloc(vm, &vm->frames[vm->fp], "/dev/term/0", 12); vm->code[vm->cp++] = OP_LOAD; diff --git a/src/test.h b/src/test.h index 800ab0b..7cf5d2c 100644 --- a/src/test.h +++ b/src/test.h @@ -3,6 +3,11 @@ #include "opcodes.h" +#define AS_FIXED(v) ((float)(i32)(v) / 65536.0f) +#define TO_FIXED(f) ((u32)((i32)( \ + ((f) >= 0.0f) ? ((f) * 65536.0f + 0.5f) : ((f) * 65536.0f - 0.5f) \ +))) + /* Test function type definition */ typedef bool (*TestFunction)(VM *vm); diff --git a/src/vm.c b/src/vm.c index 7a892e6..187b293 100644 --- a/src/vm.c +++ b/src/vm.c @@ -488,106 +488,3 @@ bool step_vm(VM *vm) { } return false; /* something bad happened */ } - -/* Static digit lookup table (0-9) */ -const char digits[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; - -/* Writes decimal digits of 'value' backwards into 'buf_end' (inclusive), - stopping at 'buf_start'. Returns pointer to first written digit. */ -char *write_digits_backwards(u32 value, char *buf_end, char *buf_start) { - char *p = buf_end; - if (value == 0) { - *--p = '0'; - } else { - u32 num = value; - while (num && p > buf_start) { - *--p = digits[num % 10]; - num /= 10; - } - } - return p; -} - -void uint_to_string(u32 value, char *buffer) { - char temp[16]; - char *start; - char *end = temp + sizeof(temp) - 1; - *end = '\0'; - start = write_digits_backwards(value, end, temp); - strcopy(buffer, start, end - start + 1); /* +1 for null terminator */ -} - -void int_to_string(i32 value, char *buffer) { - char temp[17]; /* Extra space for '-' */ - i32 negative = 0; - u32 abs_value; - char *end = temp + sizeof(temp) - 1; - *end = '\0'; - - if (value == (-2147483647 - 1)) { /* INT32_MIN */ - strcopy(buffer, "-2147483648", 12); - return; - } - - if (value == 0) { - *--end = '0'; - } else { - if (value < 0) { - negative = 1; - abs_value = (u32)(-value); - } else { - abs_value = (u32)value; - } - - end = write_digits_backwards(abs_value, end, temp); - - if (negative) { - *--end = '-'; - } - } - - strcopy(buffer, end, temp + sizeof(temp) - end); -} - -void fixed_to_string(i32 value, char *buffer) { - char temp[32]; - i32 negative; - u32 int_part; - u32 frac_part, frac_digits; - char *end = temp + sizeof(temp) - 1; - *end = '\0'; - - negative = 0; - if (value < 0) { - negative = 1; - value = -value; - } - - int_part = AS_UINT(value >> 16); - frac_part = AS_UINT(value & 0xFFFF); - - /* Convert fractional part to 5 decimal digits */ - frac_digits = (frac_part * 100000U) / 65536U; - - /* Trim trailing zeros */ - while (frac_digits > 0 && frac_digits % 10 == 0) { - frac_digits /= 10; - } - - if (frac_digits > 0) { - end = write_digits_backwards(frac_digits, end, temp); - *--end = '.'; - } - - if (int_part == 0 && frac_digits == 0) { - *--end = '0'; - } else { - end = write_digits_backwards(int_part, end, temp); - } - - if (negative) { - *--end = '-'; - } - - strcopy(buffer, end, temp + sizeof(temp) - end); -} diff --git a/test/fib.asm b/test/fib.asm index 14810c7..caff979 100644 --- a/test/fib.asm +++ b/test/fib.asm @@ -1,29 +1,34 @@ -main: - lodi $0 35 - pshi $0 - call &fib - popi $0 - itos $1 $0 - puts $1 - halt -fib: - popi $0 - lodi $1 2 - lodi $2 &base_case - jlti $2 $0 $1 - lodi $2 2 - subi $4 $0 $3 - pshi $4 - call &fib - lodi $2 1 - subi $4 $0 $3 - pshi $4 - call &fib - popi $4 - popi $5 - addi $6 $5 $4 - pshi $6 - retn -base_case: - pshi $0 - retn +.text + main: + load $0 35 + push $0 + call &fib + pop $0 + itos $1 $0 + load $2, &terminal_str + slen $4, $3 + sysc DEVICE_WRITE, 3, $2 ; print(sum.toS()) + halt + fib: + popi $0 + load $1 2 + lodi $2 &base_case + jlti $2 $0 $1 + load $2 2 + subi $4 $0 $3 + push $4 + call &fib + load $2 1 + subi $4 $0 $3 + push $4 + call &fib + pop $4 + pop $5 + addi $6 $5 $4 + push $6 + retn + base_case: + push $0 + retn +.data + terminal_str: "/dev/term/0" diff --git a/test/hello.asm b/test/hello.asm index b69d985..8d10572 100644 --- a/test/hello.asm +++ b/test/hello.asm @@ -1,5 +1,11 @@ +.text hello: - "nuqneH 'u'?" - puts &hello + load $1 &hello_str + load $2, &terminal_str + slen $4, $3 + sysc DEVICE_WRITE, 3, $2 ; print(sum.toS()) halt - \ No newline at end of file + +.data + terminal_str: "/dev/term/0" + hello_str: "nuqneH 'u'?" diff --git a/test/simple.asm b/test/simple.asm index 33970b6..8bb3c11 100644 --- a/test/simple.asm +++ b/test/simple.asm @@ -1,7 +1,14 @@ +.text main: - loadu $0 1 - loadu $1 2 + limm $0 1.0 + limm $1 2.0 addu $2 $1 $0 utos $3 $2 - puts $3 - halt + load $2, &terminal_str + slen $4, $3 + sysc DEVICE_WRITE, 3, $2 ; print(sum.toS()) + halt + +.data + terminal_str: "/dev/term/0" + \ No newline at end of file