From fcc8379cc36eebb18d9de96012d75c9037a7d4c9 Mon Sep 17 00:00:00 2001 From: Dominic Grimm Date: Tue, 4 Apr 2023 14:07:21 +0200 Subject: [PATCH] Update --- README.md | 2 +- examples/testforth.asm | 163 +++++++++++++++++++++++-------- examples/testforth.fth | 2 + hence/src/assembler.rs | 15 +++ hence/src/emulator.rs | 2 +- henceforth/templates/default.asm | 95 ++++++++---------- 6 files changed, 182 insertions(+), 97 deletions(-) diff --git a/README.md b/README.md index 52c3156..fd9a876 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # hence -Virtual CPU with Assembler and Emulator. +Virtual CPU with Assembler and Emulator and Forth compiler included. ## Architecture diff --git a/examples/testforth.asm b/examples/testforth.asm index 0f34411..bf2d9ef 100644 --- a/examples/testforth.asm +++ b/examples/testforth.asm @@ -13,11 +13,12 @@ .define_eval prev, OFFSET .bytes CORE_U16_MAX, CORE_U16_MAX + .bytes CORE_U16_MAX .define_eval JUMP_TABLE_CONDITIONS_SIZE, (OFFSET - prev) .org prev .delete prev -.define_eval JUMP_TABLE_WORDS_SIZE, (0 * 2) +.define_eval JUMP_TABLE_WORDS_SIZE, (1 * 2) .define_eval JUMP_TABLE_PTR, (MAIN_JUMPER - JUMP_TABLE_CONDITIONS_SIZE - JUMP_TABLE_WORDS_SIZE) .debug JUMP_TABLE_CONDITIONS_SIZE, JUMP_TABLE_WORDS_SIZE, (JUMP_TABLE_CONDITIONS_SIZE + JUMP_TABLE_WORDS_SIZE / 2), JUMP_TABLE_PTR @@ -29,6 +30,8 @@ .define_eval counter, (counter + 2) .define_eval jump_table_conditions_else_0, (JUMP_TABLE_PTR + counter) .define_eval counter, (counter + 2) + .define_eval jump_table_conditions_if_1, (JUMP_TABLE_PTR + counter) + .define_eval counter, (counter + 2) .delete counter .define_eval MEM_JUMP_TABLE_LEN, (JUMP_TABLE_CONDITIONS_SIZE + JUMP_TABLE_WORDS_SIZE / 2) @@ -52,23 +55,40 @@ tlr CORE_REG_A .endmacro -; setup jump table - ; condition 0 - .std_get jump_table_conditions_if_0 +.macro jump_table_pull_ptr, jump_table_pull_ptr_arg_0_ptr + .std_get jump_table_pull_ptr_arg_0_ptr tls - .std_get (jump_table_conditions_if_0 + 1) + .std_get (jump_table_pull_ptr_arg_0_ptr + 1) tls dbg pop pop +.endmacro + +; setup jump table + ; conditions + ; condition 0 + ; if + .jump_table_pull_ptr jump_table_conditions_if_0 + + ; else + .jump_table_pull_ptr jump_table_conditions_else_0 + ; condition 1 + ; if + .jump_table_pull_ptr jump_table_conditions_if_1 + +.macro self_ref, self_ref_arg_0_ptr + .std_rset CORE_REG_A, self_ref_arg_0_ptr + .std_set self_ref_arg_0_ptr +.endmacro ; reference MEM_CALL_STACK_PTR to itself -.std_rset CORE_REG_A, MEM_CALL_STACK_PTR -.std_set MEM_CALL_STACK_PTR +.self_ref MEM_CALL_STACK_PTR ; reference MEM_ALLOC_PTR to itself -.std_rset CORE_REG_A, MEM_ALLOC_PTR -.std_set MEM_ALLOC_PTR +.self_ref MEM_ALLOC_PTR + +.delete_macro self_ref .std_jump MAIN_JUMPER @@ -101,50 +121,20 @@ return_call_stack_jump: get tlr CORE_REG_PC -.define_eval prev, OFFSET - .std_rset CORE_REG_C, CORE_U16_MAX - .std_rset CORE_REG_D, CORE_U16_MAX - ts call_stack_jump - tlr CORE_REG_PC -.define_eval CALL_STACK_JUMP_SIZE, (OFFSET - prev) -.org prev -.delete prev - .macro call_stack_jump, call_stack_jump_arg_0_label - .define_eval prev, OFFSET - .define offset_till_end, (OFFSET - prev * -1 + CALL_STACK_JUMP_COND_IF_ELSE_SIZE) - .std_rset CORE_REG_C, call_stack_jump_arg_0_label - .std_rset CORE_REG_D, (OFFSET + offset_till_end) + .std_rset CORE_REG_D, (OFFSET + 7) ts call_stack_jump tlr CORE_REG_PC - - .delete prev, offset_till_end .endmacro -.define_eval prev, OFFSET - .std_ld - tlr CORE_REG_A - .std_rset CORE_REG_C, CORE_U16_MAX - .std_rset CORE_REG_D, CORE_U16_MAX - ts call_stack_jump - tlrc CORE_REG_PC -.define_eval CALL_STACK_JUMP_COND_IF_SIZE, (OFFSET - prev) -.org prev -.delete prev - .macro call_stack_jump_cond_if, call_stack_jump_cond_if_arg_0_if_label - .define_eval prev, OFFSET - .define offset_till_end, (OFFSET - prev * -1 + CALL_STACK_JUMP_COND_IF_ELSE_SIZE) - .std_ld tlr CORE_REG_A .std_rset CORE_REG_C, call_stack_jump_cond_if_arg_0_if_label - .std_rset CORE_REG_D, (OFFSET + offset_till_end) + .std_rset CORE_REG_D, (OFFSET + 7) ts call_stack_jump tlrc CORE_REG_PC - - .delete prev, offset_till_end .endmacro .define_eval prev, OFFSET @@ -188,6 +178,21 @@ return_call_stack_jump: ; data ; strings + data_strings_0: + .bytes 0x48 + .bytes 0x65 + .bytes 0x6c + .bytes 0x6c + .bytes 0x6f + .bytes 0x20 + .bytes 0x77 + .bytes 0x6f + .bytes 0x72 + .bytes 0x6c + .bytes 0x64 + .bytes 0x21 + data_strings_end_0: + ; conditions ; condition: 0 @@ -205,8 +210,42 @@ return_call_stack_jump: .std_set CORE_MEM_OUT .return_call_stack_jump + ; condition: 1 + conditions_if_1: + push 32 + .std_ld + tlr CORE_REG_A + .std_set CORE_MEM_OUT + .std_rset CORE_REG_A, '\n' + .std_set CORE_MEM_CHR + .return_call_stack_jump + ; words + words_0: + push 40 + push 2 + .stack_transfer_alu + .std_alu CORE_ALU_ADD + tls + .return_call_stack_jump + + +; static jump table +.define_eval prev, OFFSET + ; conditions + ; condition: 0 + .org jump_table_conditions_if_0 + .bytes conditions_if_0 + .org jump_table_conditions_else_0 + .bytes conditions_else_0 + + ; condition: 1 + .org jump_table_conditions_if_1 + .bytes conditions_if_1 + +.org prev +.delete prev ; main main: @@ -224,4 +263,46 @@ main: .call_stack_jump_cond_if_else conditions_if_0, conditions_else_0 .std_rset CORE_REG_A, '\n' .std_set CORE_MEM_CHR + push 1 + dbg + .call_stack_jump_cond_if conditions_if_1 + .call_stack_jump words_0 + dbg + .call_stack_jump words_0 + dbg + .std_rset CORE_REG_A, ' ' + .std_set CORE_MEM_CHR + .std_rset CORE_REG_B, data_strings_0 + loop_strings_0: + tsr CORE_REG_B + get + tlr CORE_REG_A + .std_set CORE_MEM_CHR + .std_rset CORE_REG_A, 1 + .std_alu CORE_ALU_ADD + tlr CORE_REG_B + .std_rset CORE_REG_A, data_strings_end_0 + .std_alu CORE_ALU_GT + tlr CORE_REG_A + .std_cond_jump loop_strings_0 + .std_rset CORE_REG_A, '\n' + .std_set CORE_MEM_CHR + .std_rset CORE_REG_A, ' ' + .std_set CORE_MEM_CHR + set + .std_rset CORE_REG_B, data_strings_0 + loop_strings_0: + tsr CORE_REG_B + get + tlr CORE_REG_A + .std_set CORE_MEM_CHR + .std_rset CORE_REG_A, 1 + .std_alu CORE_ALU_ADD + tlr CORE_REG_B + .std_rset CORE_REG_A, data_strings_end_0 + .std_alu CORE_ALU_GT + tlr CORE_REG_A + .std_cond_jump loop_strings_0 + .std_rset CORE_REG_A, '\n' + .std_set CORE_MEM_CHR .std_stop diff --git a/examples/testforth.fth b/examples/testforth.fth index 316ff98..d11b7e2 100644 --- a/examples/testforth.fth +++ b/examples/testforth.fth @@ -5,4 +5,6 @@ : borg debug ; 42 42 = debug if 69 . else 420 . then cr +1 debug if 32 . cr else then +test debug test debug space ." Hello world!" cr space space ." Hello world!" cr diff --git a/hence/src/assembler.rs b/hence/src/assembler.rs index 248c443..565aa29 100644 --- a/hence/src/assembler.rs +++ b/hence/src/assembler.rs @@ -131,6 +131,21 @@ impl Assembler { Ok(None) } + "debug_program" => { + let start = args[0].resolve_number(self)?; + let end = args[1].resolve_number(self)?; + println!( + "=== Hexdump [0x{:0>4x}..0x{:0>4x}] ===\n{}\n================================", + start, + end, + rhexdump::hexdump_offset( + &self.program[start as usize..end as usize], + start as u32, + ) + ); + + Ok(None) + } "define" => { let name = match &args[0] { arg::Arg::Variable(x) | arg::Arg::String(x) => x, diff --git a/hence/src/emulator.rs b/hence/src/emulator.rs index 64ed074..cddf1f1 100644 --- a/hence/src/emulator.rs +++ b/hence/src/emulator.rs @@ -292,7 +292,7 @@ impl Emulator { 0x0c => { self.set_memory(self.tmp, self.reg_a)?; } - _ => bail!("Invalid opcode: 0x{:0>4x}", self.reg_opc), + _ => bail!("Invalid opcode: 0x{:0>2x}", self.reg_opc), } Ok(()) diff --git a/henceforth/templates/default.asm b/henceforth/templates/default.asm index 78ee4c5..db7280c 100644 --- a/henceforth/templates/default.asm +++ b/henceforth/templates/default.asm @@ -1,7 +1,3 @@ -{%- macro escape_name(name) -%} -{% if name.starts_with('"') %}{{ name }}{% else %}"{{ name }}"{% endif %} -{%- endmacro -%} - ; Generated by Henceforth {{ env!("CARGO_PKG_VERSION") }} ({{ env!("CARGO_PKG_REPOSITORY") }}) .include "$lib/core.asm" @@ -62,26 +58,41 @@ tlr CORE_REG_A .endmacro +.macro jump_table_pull_ptr, jump_table_pull_ptr_arg_0_ptr + .std_get jump_table_pull_ptr_arg_0_ptr + tls + .std_get (jump_table_pull_ptr_arg_0_ptr + 1) + tls + dbg + pop + pop +.endmacro + ; setup jump table ; conditions {%- for c in conditions %} ; condition {{ c.id }} - .std_get jump_table_conditions_if_{{ c.id }} - tls - .std_get (jump_table_conditions_if_{{ c.id }} + 1) - tls - dbg - pop - pop + ; if + .jump_table_pull_ptr jump_table_conditions_if_{{ c.id }} + {%- if !c.data.1.is_empty() %} + + ; else + .jump_table_pull_ptr jump_table_conditions_else_{{ c.id }} + {%- endif %} {%- endfor %} +.macro self_ref, self_ref_arg_0_ptr + .std_rset CORE_REG_A, self_ref_arg_0_ptr + .std_set self_ref_arg_0_ptr +.endmacro + ; reference MEM_CALL_STACK_PTR to itself -.std_rset CORE_REG_A, MEM_CALL_STACK_PTR -.std_set MEM_CALL_STACK_PTR +.self_ref MEM_CALL_STACK_PTR ; reference MEM_ALLOC_PTR to itself -.std_rset CORE_REG_A, MEM_ALLOC_PTR -.std_set MEM_ALLOC_PTR +.self_ref MEM_ALLOC_PTR + +.delete_macro self_ref .std_jump MAIN_JUMPER @@ -114,50 +125,20 @@ return_call_stack_jump: get tlr CORE_REG_PC -.define_eval prev, OFFSET - .std_rset CORE_REG_C, CORE_U16_MAX - .std_rset CORE_REG_D, CORE_U16_MAX - ts call_stack_jump - tlr CORE_REG_PC -.define_eval CALL_STACK_JUMP_SIZE, (OFFSET - prev) -.org prev -.delete prev - .macro call_stack_jump, call_stack_jump_arg_0_label - .define_eval prev, OFFSET - .define offset_till_end, (OFFSET - prev * -1 + CALL_STACK_JUMP_COND_IF_ELSE_SIZE) - .std_rset CORE_REG_C, call_stack_jump_arg_0_label - .std_rset CORE_REG_D, (OFFSET + offset_till_end) + .std_rset CORE_REG_D, (OFFSET + 7) ts call_stack_jump tlr CORE_REG_PC - - .delete prev, offset_till_end .endmacro -.define_eval prev, OFFSET - .std_ld - tlr CORE_REG_A - .std_rset CORE_REG_C, CORE_U16_MAX - .std_rset CORE_REG_D, CORE_U16_MAX - ts call_stack_jump - tlrc CORE_REG_PC -.define_eval CALL_STACK_JUMP_COND_IF_SIZE, (OFFSET - prev) -.org prev -.delete prev - .macro call_stack_jump_cond_if, call_stack_jump_cond_if_arg_0_if_label - .define_eval prev, OFFSET - .define offset_till_end, (OFFSET - prev * -1 + CALL_STACK_JUMP_COND_IF_ELSE_SIZE) - .std_ld tlr CORE_REG_A .std_rset CORE_REG_C, call_stack_jump_cond_if_arg_0_if_label - .std_rset CORE_REG_D, (OFFSET + offset_till_end) + .std_rset CORE_REG_D, (OFFSET + 7) ts call_stack_jump tlrc CORE_REG_PC - - .delete prev, offset_till_end .endmacro .define_eval prev, OFFSET @@ -204,9 +185,6 @@ return_call_stack_jump: {%- for s in strings %} {% let bytes = s.data.as_bytes() -%} data_strings_{{ s.id }}: - {% let name = snailquote::escape(s.data) -%} - ; original : {% call escape_name(name) %} - ; size : {{ bytes.len() }} {%- for byte in bytes %} .bytes {{ "0x{:02x}"|format(byte) }} {%- endfor %} @@ -221,28 +199,37 @@ return_call_stack_jump: {{ ins }} {%- endfor %} .return_call_stack_jump + {%- if !c.data.1.is_empty() %} conditions_else_{{ c.id }}: {%- for ins in c.data.1 %} {{ ins }} {%- endfor %} .return_call_stack_jump + {%- endif %} {% endfor %} ; words {%- for w in words %} words_{{ w.id }}: - {% let name = snailquote::escape(w.data.0) -%} - ; name : {% call escape_name(name) %} {%- for node in w.data.1 %} {{ node }} {%- endfor %} .return_call_stack_jump {% endfor %} +; static jump table .define_eval prev, OFFSET -.org JUMP_TABLE_PTR - + ; conditions + {%- for c in conditions %} + ; condition: {{ c.id }} + .org jump_table_conditions_if_{{ c.id }} + .bytes conditions_if_{{ c.id }} + {%- if !c.data.1.is_empty() %} + .org jump_table_conditions_else_{{ c.id }} + .bytes conditions_else_{{ c.id }} + {%- endif %} + {% endfor %} .org prev .delete prev