From f9dc374430be11b7ef9f6e6e312212d00c6a5b55 Mon Sep 17 00:00:00 2001 From: zongor Date: Mon, 5 Jan 2026 22:20:48 -0800 Subject: [PATCH] Update specification. --- SPECIFICATION.org | 167 ++++++++++++++++++++++------------------------ vm/vm.c | 3 +- 2 files changed, 82 insertions(+), 88 deletions(-) diff --git a/SPECIFICATION.org b/SPECIFICATION.org index 6230b8f..1da4ae7 100644 --- a/SPECIFICATION.org +++ b/SPECIFICATION.org @@ -33,95 +33,89 @@ During compilation constants and local variables are put onto 'mem' *** All 32 bit instructions (registers are all 32 bit values) **** Type A: [8:opcode][8:dest][8:src1][8:src2] -- call : dest num-of-args ptr-to-function -- return : dest return-arg 0 -- syscall : id num-of-args ptr-to-memory -- load-indirect-8 : dest src1 0 -- load-indirect-16 : dest src1 0 -- load-indirect-32 : dest src1 0 -- load-absolute-8 : dest src1 0 -- load-absolute-16 : dest src1 0 -- load-absolute-32 : dest src1 0 -- load-offset-8 : dest src1 src2 -- load-offset-16 : dest src1 src2 -- load-offset-32 : dest src1 src2 -- store-absolute-8 : dest src1 0 -- store-indirect-8 : dest src1 0 -- store-offset-8 : dest src1 src2 -- store-absolute-16 : dest src1 0 -- store-indirect-16 : dest src1 0 -- store-offset-16 : dest src1 src2 -- store-absolute-32 : dest src1 0 -- store-indirect-32 : dest src1 0 -- store-offset-32 : dest src1 src2 -- alloc : dest size 0 -- memset-8 : dest src1 count -- memset-16 : dest src1 count -- memset-32 : dest src1 count -- memcpy-8 : dest src1 count -- memcpy-16 : dest src1 count -- memcpy-32 : dest src1 count -- mov : dest src1 0 -- add-int : dest src1 src2 -- sub-int : dest src1 src2 -- mul-int : dest src1 src2 -- div-int : dest src1 src2 -- neg-int : dest src1 src2 -- abs-int : dest src1 src2 -- add-nat : dest src1 src2 -- sub-nat : dest src1 src2 -- mul-nat : dest src1 src2 -- div-nat : dest src1 src2 -- neg-nat : dest src1 src2 -- abs-nat : dest src1 src2 -- add-real : dest src1 src2 -- sub-real : dest src1 src2 -- mul-real : dest src1 src2 -- div-real : dest src1 src2 -- neg-real : dest src1 src2 -- abs-real : dest src1 src2 -- int-to-real : dest src1 src2 -- int-to-nat : dest src1 src2 -- nat-to-real : dest src1 src2 -- nat-to-int : dest src1 src2 -- real-to-int : dest src1 src2 -- real-to-nat : dest src1 src2 -- shift-left : dest src1 src2 -- shift-right : dest src1 src2 -- shift-right-extend : dest src1 src2 -- and : dest src1 src2 -- or : dest src1 src2 -- xor : dest src1 src2 -- jump-absolute : dest 0 0 -- jump-offset : dest src1 0 -- jmp-flag : dest 0 0 | jump if flag > 0 -- jeq-int : dest src1 src2 -- jne-int : dest src1 src2 -- jgt-int : dest src1 src2 -- jlt-int : dest src1 src2 -- jle-int : dest src1 src2 -- jge-int : dest src1 src2 -- jeq-nat : dest src1 src2 -- jne-nat : dest src1 src2 -- jgt-nat : dest src1 src2 -- jlt-nat : dest src1 src2 -- jle-nat : dest src1 src2 -- jge-nat : dest src1 src2 -- jeq-real : dest src1 src2 -- jne-real : dest src1 src2 -- jgt-real : dest src1 src2 -- jlt-real : dest src1 src2 -- jle-real : dest src1 src2 -- jge-real : dest src1 src2 - **** Type B: [8:opcode][8:dest][16:immediate] -- load-immediate : dest imm : for small 16 bit consts, and lower part of 32 bit consts -- load-upper-immediate : dest imm : for large 32 bit consts - **** Type C: [8:opcode][24:immediate] -- halt : immediate is unused (all zeros) -- jump-immediate : immediate jump +| Instruction | Opcode type | opcode arguments | notes | +|--------------------+-------------+----------------------------------------------------------------------+------------------------------------------| +| halt | A | all zeros | halt execution | +| call | A | dest args return | creates a new frame | +| return | B | dest return_flags | returns from a frame to the parent frame | +| syscall | A | id args mem_ptr | does a system call based on id with args | +| load_immediate | B | locals[dest] = const as u16 | | +| load_upper_immediate | B | locals[dest] = const as u32 << 16 & 16 | | +| load_indirect_8 | A | locals[dest] = memory[locals[src1]] as u8 | | +| load_indirect_16 | A | locals[dest] = memory[locals[src1]] as u16 | | +| load_indirect_32 | A | locals[dest] = memory[locals[src1]] as u32 | | +| load_absolute_8 | A | locals[dest] = memory[src1] as u8 | | +| load_absolute_16 | A | locals[dest] = memory[src1] as u16 | | +| load_absolute_32 | A | locals[dest] = memory[src1] as u32 | | +| load_offset_8 | A | locals[dest] = memory[locals[src1] + src2] as u8 | | +| load_offset_16 | A | locals[dest] = memory[locals[src1] + src2] as u16 | | +| load_offset_32 | A | locals[dest] = memory[locals[src1] + src2] as u32 | | +| store_absolute_8 | A | memory[dest] = src1 && 0xFF | | +| store_absolute_16 | A | memory[dest] = src1 && 0xFFFF | | +| store_absolute_32 | A | memory[dest] = src1 | | +| store_indirect_8 | A | memory[dest] = locals[src1] && 0xFF | | +| store_indirect_16 | A | memory[dest] = locals[src1] && 0xFFFF | | +| store_indirect_32 | A | memory[dest] = locals[src1] | | +| store_offset_8 | A | memory[locals[dest] + src2] = locals[src1] && 0xFF | | +| store_offset_16 | A | memory[locals[dest] + src2] = locals[src1] && 0xFFFF | | +| store_offset_32 | A | memory[locals[dest] + src2] = locals[src1] | | +| alloc | A | memory[dest] = [locals[src1] as size + 4] | | +| memcpy_8 | A | memory[src1..src1+src2] = memory[dest..dest+src2] | | +| memcpy_16 | A | memory[src1..src1+src2] = memory[dest..dest+src2] | | +| memcpy_32 | A | memory[src1..src1+src2] = memory[dest..dest+src2] | | +| memset_8 | A | memory[dest..dest+src2] = local[src1] as u8 | | +| memset_16 | A | memory[dest..dest+src2] = local[src1] as u16 | | +| memset_32 | A | memory[dest..dest+src2] = local[src1] as u32 | | +| mov | A | locals[dest] = locals[src1] | | +| add_int | A | locals[dest] = locals[src1] + locals[src2] | | +| sub_int | A | locals[dest] = locals[src1] - locals[src2] | | +| mul_int | A | locals[dest] = locals[src1] * locals[src2] | | +| div_int | A | locals[dest] = locals[src1] / locals[src2] | | +| add_nat | A | locals[dest] = locals[src1] + locals[src2] | | +| sub_nat | A | locals[dest] = locals[src1] - locals[src2] | | +| mul_nat | A | locals[dest] = locals[src1] * locals[src2] | | +| div_nat | A | locals[dest] = locals[src1] / locals[src2] | | +| add_real | A | locals[dest] = locals[src1] + locals[src2] | | +| sub_real | A | locals[dest] = locals[src1] - locals[src2] | | +| mul_real | A | locals[dest] = locals[src1] * locals[src2] | | +| div_real | A | locals[dest] = locals[src1] / locals[src2] | | +| int_to_real | A | locals[dest] = locals[src1] as real | | +| int_to_nat | A | locals[dest] = locals[src1] as nat | | +| nat_to_real | A | locals[dest] = locals[src1] as real | | +| nat_to_int | A | locals[dest] = locals[src1] as int | | +| real_to_int | A | locals[dest] = locals[src1] as int | | +| real_to_nat | A | locals[dest] = locals[src1] as nat | | +| bit_shift_left | A | locals[dest] = locals[src1] << locals[src2] | | +| bit_shift_right | A | locals[dest] = locals[src1] >> locals[src2] | | +| bit_shift_r_ext | A | locals[dest] as i32 = locals[src1] >> locals[src2] | | +| bit_and | A | locals[dest] = locals[src1] & locals[src2] | | +| bit_or | A | locals[dest] = locals[src1] | locals[src2] | +| bit_xor | A | locals[dest] = locals[src1] ^ locals[src2] | | +| jump_immediate | C | jump to imm unconditionally | | +| jump_absolute | A | jump to locals[dest] unconditionally | | +| jump_offset | A | jump to locals[dest] + locals[src1] unconditionally | | +| jump_if_flag | A | jump to locals[dest] if flag > 0 | | +| jump_eq_int | A | jump to locals[dest] if locals[src1] as int == locals[src2] as int | | +| jump_neq_int | A | jump to locals[dest] if locals[src1] as int != locals[src2] as int | | +| jump_gt_int | A | jump to locals[dest] if locals[src1] as int > locals[src2] as int | | +| jump_lt_int | A | jump to locals[dest] if locals[src1] as int < locals[src2] as int | | +| jump_le_int | A | jump to locals[dest] if locals[src1] as int <= locals[src2] as int | | +| jump_ge_int | A | jump to locals[dest] if locals[src1] as int >= locals[src2] as int | | +| jump_eq_nat | A | jump to locals[dest] if locals[src1] as nat == locals[src2] as nat | | +| jump_neq_nat | A | jump to locals[dest] if locals[src1] as nat != locals[src2] as nat | | +| jump_gt_nat | A | jump to locals[dest] if locals[src1] as nat > locals[src2] as nat | | +| jump_lt_nat | A | jump to locals[dest] if locals[src1] as nat < locals[src2] as nat | | +| jump_le_nat | A | jump to locals[dest] if locals[src1] as nat <= locals[src2] as nat | | +| jump_ge_nat | A | jump to locals[dest] if locals[src1] as nat >= locals[src2] as nat | | +| jump_eq_real | A | jump to locals[dest] if locals[src1] as real == locals[src2] as real | | +| jump_neq_real | A | jump to locals[dest] if locals[src1] as real != locals[src2] as real | | +| jump_ge_real | A | jump to locals[dest] if locals[src1] as real >= locals[src2] as real | | +| jump_gt_real | A | jump to locals[dest] if locals[src1] as real > locals[src2] as real | | +| jump_lt_real | A | jump to locals[dest] if locals[src1] as real < locals[src2] as real | | +| jump_le_real | A | jump to locals[dest] if locals[src1] as real <= locals[src2] as real | | ** Maybe more flexible calling convention? @@ -157,4 +151,3 @@ Copy the new sized value and put it at the current end of the heap. Update the new pointer’s local position. Add the new size to the mp. Repeat for each returned value that is a replaced heap value. - diff --git a/vm/vm.c b/vm/vm.c index 8ce28b8..8c7b426 100644 --- a/vm/vm.c +++ b/vm/vm.c @@ -55,7 +55,8 @@ bool step_vm() { u32 i, size = 0; u32 return_local = fp + dest; u32 return_value = READ_U32(return_local); - bool is_ptr = imm >> 31; + bool is_ptr = (((u16)(1)) << 15) & imm; + bool replaces_value = (((u16)(1)) << 14) & imm; /* reset mp to saved mp, use header size to get "real" start of frame */ u32 frame_start = fp - FRAME_HEADER_SIZE;