diff --git a/Makefile b/Makefile index 359fd8e..3302df2 100644 --- a/Makefile +++ b/Makefile @@ -39,8 +39,8 @@ endif # --- MODE & PLATFORM SPECIFIC FLAGS --- ifeq ($(BUILD_MODE), release) - CORE_CFLAGS += -O2 -DNDEBUG - PLATFORM_CFLAGS += -O2 -DNDEBUG + CORE_CFLAGS += -Ofast -DNDEBUG + PLATFORM_CFLAGS += -Ofast -DNDEBUG LDFLAGS += -s TARGET_SUFFIX := -release else diff --git a/bench/run.sh b/bench/run.sh index e8b3327..c964959 100755 --- a/bench/run.sh +++ b/bench/run.sh @@ -46,8 +46,4 @@ echo "test input" | time ../build/linux/undar-linux-release -t "../test/$FILENAM # Undâr Implementation (binary) print_section "undar ($FILENAME.rom)" -echo "test input" | time ../build/linux/undar-linux-release -t "../test/$FILENAME.rom" - -# Undâr RISC Implementation (hardcoded) -print_section "undar ($FILENAME)" -echo "test input" | time ../../undar-lang-risc/out/linux/tui/undar +echo "test input" | time ../build/linux/undar-linux-release -t "../test/$FILENAME.rom" \ No newline at end of file diff --git a/src/tools/assembler/assembler.c b/src/tools/assembler/assembler.c index 5d73fde..87fa5a2 100644 --- a/src/tools/assembler/assembler.c +++ b/src/tools/assembler/assembler.c @@ -418,7 +418,7 @@ bool define_global(VM *vm, ScopeTable *st) { break; } case TOKEN_LITERAL_REAL: { - fixed_t out = float_to_fixed(atof(value.start)); + r32 out = float_to_real(atof(value.start)); u32 addr = vm->mp; write_u32(vm, memory, addr, out); @@ -1183,7 +1183,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { break; } case TOKEN_LITERAL_REAL: { - fixed_t out = float_to_fixed(atof(value.start)); + r32 out = float_to_real(atof(value.start)); emit_u32(vm, out); break; } diff --git a/src/tools/compiler/compiler.c b/src/tools/compiler/compiler.c index cc1890a..fff5266 100644 --- a/src/tools/compiler/compiler.c +++ b/src/tools/compiler/compiler.c @@ -280,7 +280,7 @@ bool define_global(VM *vm, ScopeTable *st) { break; } case TOKEN_LITERAL_REAL: { - fixed_t out = float_to_fixed(atof(value.start)); + r32 out = float_to_real(atof(value.start)); u32 addr = vm->mp; write_u32(vm, memory, addr, out); @@ -1045,7 +1045,7 @@ void emit_bytecode(VM *vm, char *source, ScopeTable *st) { break; } case TOKEN_LITERAL_REAL: { - fixed_t out = float_to_fixed(atof(value.start)); + r32 out = float_to_real(atof(value.start)); emit_u32(vm, out); break; } diff --git a/src/vm/fixed.c b/src/vm/fixed.c index 540cf40..b27f21b 100644 --- a/src/vm/fixed.c +++ b/src/vm/fixed.c @@ -1,18 +1,18 @@ #include "fixed.h" -fixed_t int_to_fixed(i32 i) { return i << 16; } +r32 int_to_real(i32 i) { return i << 16; } -i32 fixed_to_int(fixed_t f) { return f >> 16; } +i32 real_to_int(r32 f) { return f >> 16; } -fixed_t float_to_fixed(f32 f) { return (fixed_t)(f * 65536.0f); } +r32 float_to_real(f32 f) { return (r32)(f * 65536.0f); } -f32 fixed_to_float(fixed_t f) { return (f32)f / 65536.0f; } +f32 real_to_float(r32 f) { return (f32)f / 65536.0f; } -fixed_t fixed_add(fixed_t a, fixed_t b) { return a + b; } +r32 real_add(r32 a, r32 b) { return a + b; } -fixed_t fixed_sub(fixed_t a, fixed_t b) { return a - b; } +r32 real_sub(r32 a, r32 b) { return a - b; } -fixed_t fixed_mul(fixed_t a, fixed_t b) { +r32 real_mul(r32 a, r32 b) { i32 src1_whole = (i32)a >> 16; i32 src2_whole = (i32)b >> 16; @@ -29,7 +29,7 @@ fixed_t fixed_mul(fixed_t a, fixed_t b) { return result; } -fixed_t fixed_div(fixed_t a, fixed_t b) { +r32 real_div(r32 a, r32 b) { i32 result; i32 src1_val = (i32)a; @@ -44,18 +44,18 @@ fixed_t fixed_div(fixed_t a, fixed_t b) { return result; } -i32 fixed_eq(fixed_t a, fixed_t b) { return a == b; } +i32 real_eq(r32 a, r32 b) { return a == b; } -i32 fixed_ne(fixed_t a, fixed_t b) { return a != b; } +i32 real_ne(r32 a, r32 b) { return a != b; } -i32 fixed_lt(fixed_t a, fixed_t b) { return a < b; } +i32 real_lt(r32 a, r32 b) { return a < b; } -i32 fixed_le(fixed_t a, fixed_t b) { return a <= b; } +i32 real_le(r32 a, r32 b) { return a <= b; } -i32 fixed_gt(fixed_t a, fixed_t b) { return a > b; } +i32 real_gt(r32 a, r32 b) { return a > b; } -i32 fixed_ge(fixed_t a, fixed_t b) { return a >= b; } +i32 real_ge(r32 a, r32 b) { return a >= b; } -fixed_t fixed_neg(fixed_t f) { return -f; } +r32 real_neg(r32 f) { return -f; } -fixed_t fixed_abs(fixed_t f) { return (f < 0) ? -f : f; } +r32 real_abs(r32 f) { return (f < 0) ? -f : f; } diff --git a/src/vm/fixed.h b/src/vm/fixed.h index c48f99a..1ffdc21 100644 --- a/src/vm/fixed.h +++ b/src/vm/fixed.h @@ -1,36 +1,28 @@ -#ifndef FIXED_H -#define FIXED_H +#ifndef REAL_H +#define REAL_H #include "common.h" -typedef i32 fixed_t; +typedef i32 r32; -#define FIXED_ONE 0x00010000L /* 1.0 in Q16.16 */ -#define FIXED_ZERO 0x00000000L /* 0.0 in Q16.16 */ -#define FIXED_HALF 0x00008000L /* 0.5 in Q16.16 */ -#define FIXED_PI 0x0003243FL /* 3.14159 */ -#define FIXED_E 0x0002B7E1L /* 2.71828 */ -#define FIXED_MAX 0x7FFFFFFFL /* Maximum positive value */ -#define FIXED_MIN 0x80000000L /* Minimum negative value */ +r32 int_to_real(i32 i); +i32 real_to_int(r32 f); +r32 float_to_real(f32 f); +f32 real_to_float(r32 f); -fixed_t int_to_fixed(i32 i); -i32 fixed_to_int(fixed_t f); -fixed_t float_to_fixed(f32 f); -f32 fixed_to_float(fixed_t f); +r32 real_add(r32 a, r32 b); +r32 real_sub(r32 a, r32 b); +r32 real_mul(r32 a, r32 b); +r32 real_div(r32 a, r32 b); -fixed_t fixed_add(fixed_t a, fixed_t b); -fixed_t fixed_sub(fixed_t a, fixed_t b); -fixed_t fixed_mul(fixed_t a, fixed_t b); -fixed_t fixed_div(fixed_t a, fixed_t b); +i32 real_eq(r32 a, r32 b); +i32 real_ne(r32 a, r32 b); +i32 real_lt(r32 a, r32 b); +i32 real_le(r32 a, r32 b); +i32 real_gt(r32 a, r32 b); +i32 real_ge(r32 a, r32 b); -i32 fixed_eq(fixed_t a, fixed_t b); -i32 fixed_ne(fixed_t a, fixed_t b); -i32 fixed_lt(fixed_t a, fixed_t b); -i32 fixed_le(fixed_t a, fixed_t b); -i32 fixed_gt(fixed_t a, fixed_t b); -i32 fixed_ge(fixed_t a, fixed_t b); - -fixed_t fixed_neg(fixed_t f); -fixed_t fixed_abs(fixed_t f); +r32 real_neg(r32 f); +r32 real_abs(r32 f); #endif diff --git a/src/vm/opcodes.h b/src/vm/opcodes.h index dbb7b73..d14d8ae 100644 --- a/src/vm/opcodes.h +++ b/src/vm/opcodes.h @@ -97,13 +97,13 @@ typedef enum { OP_MAX_OPCODE /* not really an opcode but used to check max length of ops */ } Opcode; -#define MAX_LOCALS 32 +#define MAX_LOCALS 256 typedef struct frame_s { - u32 locals[MAX_LOCALS]; /* $0-$31 */ - u32 start; /* start of memory block */ - u32 end; /* end of memory block */ - u32 return_reg; /* register to store return value in parent */ - u32 heap_mask; /* bitfield: 1 bit per register (R0=bit0, R1=bit1, etc) */ + u32 heap_mask[8]; + u32 locals[MAX_LOCALS]; /* $0-$255 */ + u32 start; /* start of memory block */ + u32 end; /* end of memory block */ + u8 return_reg; /* register to store return value in parent */ } Frame; typedef enum { diff --git a/src/vm/vm.c b/src/vm/vm.c index 7d6c3bd..7d3b14c 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -5,6 +5,7 @@ #include "libc.h" #include "opcodes.h" +#define MAX_LEN_REAL32 12 #define MAX_LEN_INT32 11 const char radix_set[11] = "0123456789"; @@ -59,16 +60,20 @@ const char radix_set[11] = "0123456789"; /* Set heap status for a register in current frame */ void set_heap_status(VM *vm, u8 reg, bool is_heap) { + u32 index = reg / 32; + u32 mask = 1 << (reg % 32); + if (is_heap) { - vm->frames[vm->fp].heap_mask |= (1 << reg); + vm->frames[vm->fp].heap_mask[index] |= mask; } else { - vm->frames[vm->fp].heap_mask &= ~(1 << reg); + vm->frames[vm->fp].heap_mask[index] &= ~mask; } } /* Check if register contains heap pointer */ bool is_heap_value(VM *vm, u8 reg) { - return (vm->frames[vm->fp].heap_mask >> reg) & 1; + u32 index = reg / 32; + return (vm->frames[vm->fp].heap_mask[index] >> (reg % 32)) & 1; } u32 str_alloc(VM *vm, Frame *frame, const char *str, u32 length) { @@ -101,7 +106,7 @@ bool step_vm(VM *vm) { case OP_CALL: { u8 N, return_reg, src_reg, args[MAX_LOCALS]; Frame *child; - u32 jmp, heap_mask, i; + u32 jmp, mask, i; jmp = read_u32(vm, code, vm->pc); vm->pc += 4; @@ -126,15 +131,15 @@ bool step_vm(VM *vm) { child->start = vm->mp; child->end = vm->mp; child->return_reg = 0; - child->heap_mask = 0; - heap_mask = 0; for (i = 0; i < N; i++) { src_reg = args[i]; child->locals[i] = frame->locals[src_reg]; - heap_mask |= ((frame->heap_mask >> src_reg) & 1) << i; + mask = 1 << (src_reg % 32); + if (frame->heap_mask[src_reg / 32] & mask) { + child->heap_mask[i / 32] |= 1 << (i % 32); + } } - child->heap_mask = heap_mask; vm->pc = jmp; return true; @@ -166,10 +171,10 @@ bool step_vm(VM *vm) { memcopy(vm->memory + new_ptr + 4, vm->memory + ptr + 4, size); parent->end += size + 4; parent->locals[parent->return_reg] = new_ptr; - parent->heap_mask |= (1 << parent->return_reg); + parent->heap_mask[parent->return_reg / 32] |= (1 << parent->return_reg); } else { parent->locals[parent->return_reg] = value; - parent->heap_mask &= ~(1 << parent->return_reg); + parent->heap_mask[parent->return_reg / 32] &= ~(1 << parent->return_reg); } } @@ -796,7 +801,7 @@ bool step_vm(VM *vm) { vm->pc++; dest = read_u8(vm, code, vm->pc); vm->pc++; - frame->locals[dest] = fixed_mul(frame->locals[src1], frame->locals[src2]); + frame->locals[dest] = real_mul(frame->locals[src1], frame->locals[src2]); return true; } @@ -808,7 +813,7 @@ bool step_vm(VM *vm) { vm->pc++; dest = read_u8(vm, code, vm->pc); vm->pc++; - frame->locals[dest] = fixed_div(frame->locals[src1], frame->locals[src2]); + frame->locals[dest] = real_div(frame->locals[src1], frame->locals[src2]); return true; } @@ -820,7 +825,7 @@ bool step_vm(VM *vm) { vm->pc++; dest = read_u8(vm, code, vm->pc); vm->pc++; - frame->locals[dest] = fixed_add(frame->locals[src1], frame->locals[src2]); + frame->locals[dest] = real_add(frame->locals[src1], frame->locals[src2]); return true; } @@ -832,7 +837,7 @@ bool step_vm(VM *vm) { vm->pc++; dest = read_u8(vm, code, vm->pc); vm->pc++; - frame->locals[dest] = fixed_sub(frame->locals[src1], frame->locals[src2]); + frame->locals[dest] = real_sub(frame->locals[src1], frame->locals[src2]); return true; } case OP_REAL_TO_INT: { @@ -844,7 +849,7 @@ bool step_vm(VM *vm) { vm->pc++; value = frame->locals[src1]; - frame->locals[dest] = fixed_to_int(value); + frame->locals[dest] = real_to_int(value); return true; } @@ -854,7 +859,7 @@ bool step_vm(VM *vm) { vm->pc++; dest = read_u8(vm, code, vm->pc); vm->pc++; - frame->locals[dest] = int_to_fixed(frame->locals[src1]); + frame->locals[dest] = int_to_real(frame->locals[src1]); return true; } case OP_REAL_TO_NAT: { @@ -865,7 +870,7 @@ bool step_vm(VM *vm) { dest = read_u8(vm, code, vm->pc); vm->pc++; value = frame->locals[src1]; - frame->locals[dest] = fixed_to_int(value); + frame->locals[dest] = real_to_int(value); return true; } case OP_NAT_TO_REAL: { @@ -874,7 +879,7 @@ bool step_vm(VM *vm) { vm->pc++; dest = read_u8(vm, code, vm->pc); vm->pc++; - frame->locals[dest] = int_to_fixed(frame->locals[src1]); + frame->locals[dest] = int_to_real(frame->locals[src1]); return true; } case OP_JEQ_NAT: { @@ -989,46 +994,47 @@ bool step_vm(VM *vm) { return true; } case OP_REAL_TO_STRING: { - i32 q; - u8 dest, src1, int_part, frac_part; - u32 i = 0, j = 0; - char buffer[12]; + char buffer[MAX_LEN_REAL32]; + r32 q; + bool neg; + u8 dest, src1; + i32 int_part; + u32 frac_part; + u32 i = MAX_LEN_REAL32; src1 = read_u8(vm, code, vm->pc); vm->pc++; dest = read_u8(vm, code, vm->pc); vm->pc++; - q = (i32)frame->locals[src1]; + q = (r32)frame->locals[src1]; if (q < 0) { - buffer[i++] = '-'; q = -q; } int_part = q >> 16; frac_part = q & 0xFFFF; - if (int_part == 0) { - buffer[i++] = radix_set[0]; - } else { - char tmp[16]; - i32 tmp_i = 0; - while (int_part > 0) { - tmp[tmp_i++] = radix_set[int_part % 10]; - int_part /= 10; - } - while (tmp_i > 0) { - buffer[i++] = tmp[--tmp_i]; - } - } + do { + buffer[--i] = radix_set[frac_part % 10]; + frac_part /= 10; + } while (frac_part > 0); - buffer[i++] = '.'; - for (j = 0; j < 6; j++) { - frac_part *= 10; - buffer[i++] = radix_set[frac_part >> 16]; - frac_part &= 0xFFFF; - } + buffer[--i] = '.'; - frame->locals[dest] = str_alloc(vm, frame, buffer + i, 12 - i); + neg = int_part < 0; + + if (neg) + int_part = -int_part; + + do { + buffer[--i] = radix_set[int_part % 10]; + int_part /= 10; + } while (int_part > 0); + + if (neg) + buffer[--i] = '-'; + + frame->locals[dest] = str_alloc(vm, frame, buffer + i, MAX_LEN_REAL32 - i); set_heap_status(vm, dest, true); /* Mark as heap pointer */ return true; } diff --git a/test/paint-bw.ul.ir b/test/paint-bw.ul.ir index 9c3d77d..b1a77cf 100644 --- a/test/paint-bw.ul.ir +++ b/test/paint-bw.ul.ir @@ -97,6 +97,7 @@ function main () { // Flush and exit exit 0; +} function set_color_if_clicked (int click_x $0, int click_y $1, int box_x $2, int box_y $3, byte check_color $4, int bsize $5) {