From 8876526e956781c1b3e6a19cfc13af406af47546 Mon Sep 17 00:00:00 2001 From: johannst Date: Sun, 8 Dec 2024 22:49:14 +0000 Subject: deploy: 5f90bf71ab2d347fbe2d0dc89b71ab5d6e923b46 --- bf/all.html | 1 + bf/index.html | 16 + bf/sidebar-items.js | 1 + bf_vm/all.html | 1 - bf_vm/index.html | 16 - bf_vm/sidebar-items.js | 1 - crates.js | 4 +- search-index.js | 4 +- search.desc/bf/bf-desc-0-.js | 1 + search.desc/bf_vm/bf_vm-desc-0-.js | 1 - src-files.js | 4 +- src/bf/bf.rs.html | 585 +++++++++++++++++++++++++++++++++++++ src/bf_vm/bf_vm.rs.html | 585 ------------------------------------- 13 files changed, 610 insertions(+), 610 deletions(-) create mode 100644 bf/all.html create mode 100644 bf/index.html create mode 100644 bf/sidebar-items.js delete mode 100644 bf_vm/all.html delete mode 100644 bf_vm/index.html delete mode 100644 bf_vm/sidebar-items.js create mode 100644 search.desc/bf/bf-desc-0-.js delete mode 100644 search.desc/bf_vm/bf_vm-desc-0-.js create mode 100644 src/bf/bf.rs.html delete mode 100644 src/bf_vm/bf_vm.rs.html diff --git a/bf/all.html b/bf/all.html new file mode 100644 index 0000000..77b63d3 --- /dev/null +++ b/bf/all.html @@ -0,0 +1 @@ +List of all items in this crate

List of all items

\ No newline at end of file diff --git a/bf/index.html b/bf/index.html new file mode 100644 index 0000000..05273e9 --- /dev/null +++ b/bf/index.html @@ -0,0 +1,16 @@ +bf - Rust

Crate bf

source
Expand description

Brainfuck VM.

+

This example implements a simple +brainfuck interpreter +[BrainfuckInterp] and a jit compiler [BrainfuckJit].

+

Brainfuck is an esoteric programming languge existing of 8 commands.

+
    +
  • > increment data pointer.
  • +
  • < decrement data pointer.
  • +
  • + increment data at current data pointer.
  • +
  • - decrement data at current data pointer.
  • +
  • . output data at current data pointer.
  • +
  • , read input and store at current data pointer.
  • +
  • [ jump behind matching ‘]’ if data at data pointer is zero.
  • +
  • ] jump behind matching ‘[’ if data at data pointer is non-zero.
  • +
+
\ No newline at end of file diff --git a/bf/sidebar-items.js b/bf/sidebar-items.js new file mode 100644 index 0000000..5244ce0 --- /dev/null +++ b/bf/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {}; \ No newline at end of file diff --git a/bf_vm/all.html b/bf_vm/all.html deleted file mode 100644 index 500ca86..0000000 --- a/bf_vm/all.html +++ /dev/null @@ -1 +0,0 @@ -List of all items in this crate

List of all items

\ No newline at end of file diff --git a/bf_vm/index.html b/bf_vm/index.html deleted file mode 100644 index aeef3db..0000000 --- a/bf_vm/index.html +++ /dev/null @@ -1,16 +0,0 @@ -bf_vm - Rust

Crate bf_vm

source
Expand description

Brainfuck VM.

-

This example implements a simple -brainfuck interpreter -[BrainfuckInterp] and a jit compiler [BrainfuckJit].

-

Brainfuck is an esoteric programming languge existing of 8 commands.

-
    -
  • > increment data pointer.
  • -
  • < decrement data pointer.
  • -
  • + increment data at current data pointer.
  • -
  • - decrement data at current data pointer.
  • -
  • . output data at current data pointer.
  • -
  • , read input and store at current data pointer.
  • -
  • [ jump behind matching ‘]’ if data at data pointer is zero.
  • -
  • ] jump behind matching ‘[’ if data at data pointer is non-zero.
  • -
-
\ No newline at end of file diff --git a/bf_vm/sidebar-items.js b/bf_vm/sidebar-items.js deleted file mode 100644 index 5244ce0..0000000 --- a/bf_vm/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -window.SIDEBAR_ITEMS = {}; \ No newline at end of file diff --git a/crates.js b/crates.js index d7469b6..63a44e3 100644 --- a/crates.js +++ b/crates.js @@ -1,2 +1,2 @@ -window.ALL_CRATES = ["add","bf_vm","fib","juicebox_asm","tiny_vm"]; -//{"start":21,"fragment_lengths":[5,8,6,15,10]} \ No newline at end of file +window.ALL_CRATES = ["add","bf","fib","juicebox_asm","tiny_vm"]; +//{"start":21,"fragment_lengths":[5,5,6,15,10]} \ No newline at end of file diff --git a/search-index.js b/search-index.js index 839b585..6741cea 100644 --- a/search-index.js +++ b/search-index.js @@ -1,4 +1,4 @@ -var searchIndex = new Map(JSON.parse('[["add",{"t":"","n":[],"q":[],"i":"","f":"","D":"b","p":[],"r":[],"b":[],"c":"OjAAAAAAAAA=","e":"OjAAAAAAAAA="}],["bf_vm",{"t":"","n":[],"q":[],"i":"","f":"","D":"b","p":[],"r":[],"b":[],"c":"OjAAAAAAAAA=","e":"OjAAAAAAAAA="}],["fib",{"t":"","n":[],"q":[],"i":"","f":"","D":"b","p":[],"r":[],"b":[],"c":"OjAAAAAAAAA=","e":"OjAAAAAAAAA="}],["juicebox_asm",{"t":"FFFFFPPPFGFFFFGGGGFNNNNNNNPPPPNPNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNPPPNPPNNNNNNNNNNNNNNNNNNNPNNNNNNPPPPNNNPPPPPPPPPNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNCNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPNPPPPPPNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNKKKKKKKKKKKKKKKMMMMMMMMMMMMMMM","n":["Asm","Imm16","Imm32","Imm64","Imm8","Indirect","IndirectBaseIndex","IndirectDisp","Label","MemOp","MemOp16","MemOp32","MemOp64","MemOp8","Reg16","Reg32","Reg64","Reg8","Runtime","add","","","","","","add_code","ah","al","ax","bh","bind","bl","borrow","","","","","","","","","","","","","","","","borrow_mut","","","","","","","","","","","","","","","","bp","bpl","bx","call","ch","cl","clone","","","","","clone_into","","","","","clone_to_uninit","","","","","cmovnz","cmovz","cmp","","cx","dec","","","","","","dh","di","dil","dl","drop","","dump","dx","eax","ebp","ebx","ecx","edi","edx","esi","esp","from","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","inc","","","","","","insn","into","","","","","","","","","","","","","","","","into_code","jmp","jnz","jz","mov","","","","","","","","","","","","","","","","","new","","","nop","pop","","push","","r10","r10d","r10l","r10w","r11","r11d","r11l","r11w","r12","r12d","r12l","r12w","r13","r13d","r13l","r13w","r14","r14d","r14l","r14w","r15","r15d","r15l","r15w","r8","r8d","r8l","r8w","r9","r9d","r9l","r9w","rax","rbp","rbx","rcx","rdi","rdx","ret","rsi","rsp","si","sil","sp","spl","test","","","to_owned","","","","","try_from","","","","","","","","","","","","","","","","try_into","","","","","","","","","","","","","","","","type_id","","","","","","","","","","","","","","","","with_profile","xor","Add","Call","Cmovnz","Cmovz","Cmp","Dec","Inc","Jmp","Jnz","Jz","Mov","Pop","Push","Test","Xor","add","call","cmovnz","cmovz","cmp","dec","inc","jmp","jnz","jz","mov","pop","push","test","xor"],"q":[[0,"juicebox_asm"],[309,"juicebox_asm::insn"],[339,"juicebox_asm::asm"],[340,"juicebox_asm::reg"],[341,"juicebox_asm::imm"],[342,"juicebox_asm::rt"],[343,"core::convert"],[344,"juicebox_asm::label"],[345,"alloc::vec"],[346,"core::result"],[347,"core::any"]],"i":"`````h00```````````d00000AdAn0j1313Al3B`A`C`CfnAb78;BhBbBfBd>:=987654;<<54;>>>;>>>>>><;<<:==;44444444>:=9998888877777776666666666654;>>>>>`>:=987654;>>>>>>>>>>>>>>>>>>>>>:=>>>>>54<;54<;54<;54<;54<;54<;54<;54<;555555>55;<;<>>>54;:=987654;:=987654;:=987654;```````````````DfDhDjDlDnE`EbEdEfEhEjElEnF`Fb","f":"```````````````````{{{f{bd}}hj}l}{{{f{bd}}nh}l}{{{f{bd}}hA`}l}{{{f{bd}}hn}l}{{{f{bd}}AbAb}l}{{{f{bd}}nn}l}{{{f{bAd}}c}e{{Aj{{Ah{Af}}}}}{}}````{{{f{bd}}{f{bAl}}}l}`{f{{f{c}}}{}}000000000000000{{{f{b}}}{{f{bc}}}{}}000000000000000```{{{f{bd}}n}l}``{{{f{n}}}n}{{{f{Ab}}}Ab}{{{f{j}}}j}{{{f{An}}}An}{{{f{h}}}h}{{f{f{bc}}}l{}}0000{fl}0000<<{{{f{bd}}hB`}l}{{{f{bd}}hA`}l}`{{{f{bd}}Ab}l}{{{f{bd}}Bb}l}{{{f{bd}}Bd}l}{{{f{bd}}Bf}l}={{{f{bd}}Bh}l}````{{{f{bAl}}}l}{{{f{bAd}}}l}{{{f{Ad}}}l}`````````{cc{}}00{AfB`}{BjB`}22{AfA`}{BjA`}{BlA`}{BnA`}{BjC`}{BnC`}{CbC`}{BlC`}:{AfC`}{CdC`}{CbCf}{BjCf}{ChCf}?{CjCf}{CdCf}{BlCf}{AfCf}{ClCf}{CnCf}{BnCf}{cc{}}0000{hBh}11{hBb}2{hBf}{hBd}4{{{f{bd}}Bh}l}{{{f{bd}}Ab}l}{{{f{bd}}Bb}l}{{{f{bd}}Bf}l}{{{f{bd}}Bd}l}{{{f{bd}}n}l}`{{}c{}}000000000000000{d{{D`{Af}}}}{{{f{bd}}{f{bAl}}}l}00{{{f{bd}}AnAn}l}{{{f{bd}}nCf}l}{{{f{bd}}jA`}l}{{{f{bd}}nh}l}{{{f{bd}}hAn}l}{{{f{bd}}hj}l}{{{f{bd}}AnB`}l}{{{f{bd}}hA`}l}{{{f{bd}}hAb}l}{{{f{bd}}Abh}l}{{{f{bd}}AbC`}l}{{{f{bd}}jj}l}{{{f{bd}}AbAb}l}{{{f{bd}}nn}l}{{{f{bd}}jh}l}{{{f{bd}}Anh}l}{{{f{bd}}hn}l}{{}d}{{}Al}{{}Ad}{{{f{bd}}}l}{{{f{bd}}n}l}{{{f{bd}}j}l}10``````````````````````````````````````2``````9?:{fc{}}0000{c{{Db{e}}}{}{}}000000000000000{{}{{Db{c}}}{}}000000000000000{fDd}0000000000000007=```````````````{{{f{bDf}}ce}l{}{}}{{{f{bDh}}c}l{}}{{{f{bDj}}ce}l{}{}}{{{f{bDl}}ce}l{}{}}{{{f{bDn}}ce}l{}{}}{{{f{bE`}}c}l{}}{{{f{bEb}}c}l{}}{{{f{bEd}}c}l{}}{{{f{bEf}}c}l{}}{{{f{bEh}}c}l{}}{{{f{bEj}}ce}l{}{}}{{{f{bEl}}c}l{}}{{{f{bEn}}c}l{}}{{{f{bF`}}ce}l{}{}}{{{f{bFb}}ce}l{}{}}","D":"L`","p":[[0,"mut"],[5,"Asm",0,339],[1,"reference"],[6,"MemOp",0],[6,"Reg16",0,340],[1,"unit"],[6,"Reg64",0,340],[5,"Imm16",0,341],[6,"Reg32",0,340],[5,"Runtime",0,342],[1,"u8"],[1,"slice"],[10,"AsRef",343],[5,"Label",0,344],[6,"Reg8",0,340],[5,"Imm8",0,341],[5,"MemOp16",0],[5,"MemOp64",0],[5,"MemOp32",0],[5,"MemOp8",0],[1,"i8"],[1,"i16"],[1,"u16"],[5,"Imm32",0,341],[1,"u32"],[1,"i32"],[5,"Imm64",0,341],[1,"i64"],[1,"u64"],[1,"isize"],[1,"usize"],[5,"Vec",345],[6,"Result",346],[5,"TypeId",347],[10,"Add",309],[10,"Call",309],[10,"Cmovnz",309],[10,"Cmovz",309],[10,"Cmp",309],[10,"Dec",309],[10,"Inc",309],[10,"Jmp",309],[10,"Jnz",309],[10,"Jz",309],[10,"Mov",309],[10,"Pop",309],[10,"Push",309],[10,"Test",309],[10,"Xor",309]],"r":[[0,339],[1,341],[2,341],[3,341],[4,341],[8,344],[14,340],[15,340],[16,340],[17,340],[18,342]],"b":[[19,"impl-Add%3CMemOp,+Reg16%3E-for-Asm"],[20,"impl-Add%3CReg64,+MemOp%3E-for-Asm"],[21,"impl-Add%3CMemOp,+Imm16%3E-for-Asm"],[22,"impl-Add%3CMemOp,+Reg64%3E-for-Asm"],[23,"impl-Add%3CReg32,+Reg32%3E-for-Asm"],[24,"impl-Add%3CReg64,+Reg64%3E-for-Asm"],[87,"impl-Cmp%3CMemOp,+Imm8%3E-for-Asm"],[88,"impl-Cmp%3CMemOp,+Imm16%3E-for-Asm"],[90,"impl-Dec%3CReg32%3E-for-Asm"],[91,"impl-Dec%3CMemOp16%3E-for-Asm"],[92,"impl-Dec%3CMemOp64%3E-for-Asm"],[93,"impl-Dec%3CMemOp32%3E-for-Asm"],[94,"impl-Dec%3CReg64%3E-for-Asm"],[95,"impl-Dec%3CMemOp8%3E-for-Asm"],[115,"impl-From%3Cu8%3E-for-Imm8"],[116,"impl-From%3Ci8%3E-for-Imm8"],[119,"impl-From%3Cu8%3E-for-Imm16"],[120,"impl-From%3Ci8%3E-for-Imm16"],[121,"impl-From%3Ci16%3E-for-Imm16"],[122,"impl-From%3Cu16%3E-for-Imm16"],[123,"impl-From%3Ci8%3E-for-Imm32"],[124,"impl-From%3Cu16%3E-for-Imm32"],[125,"impl-From%3Cu32%3E-for-Imm32"],[126,"impl-From%3Ci16%3E-for-Imm32"],[128,"impl-From%3Cu8%3E-for-Imm32"],[129,"impl-From%3Ci32%3E-for-Imm32"],[130,"impl-From%3Cu32%3E-for-Imm64"],[131,"impl-From%3Ci8%3E-for-Imm64"],[132,"impl-From%3Ci64%3E-for-Imm64"],[134,"impl-From%3Cu64%3E-for-Imm64"],[135,"impl-From%3Ci32%3E-for-Imm64"],[136,"impl-From%3Ci16%3E-for-Imm64"],[137,"impl-From%3Cu8%3E-for-Imm64"],[138,"impl-From%3Cisize%3E-for-Imm64"],[139,"impl-From%3Cusize%3E-for-Imm64"],[140,"impl-From%3Cu16%3E-for-Imm64"],[154,"impl-Inc%3CMemOp8%3E-for-Asm"],[155,"impl-Inc%3CReg32%3E-for-Asm"],[156,"impl-Inc%3CMemOp16%3E-for-Asm"],[157,"impl-Inc%3CMemOp32%3E-for-Asm"],[158,"impl-Inc%3CMemOp64%3E-for-Asm"],[159,"impl-Inc%3CReg64%3E-for-Asm"],[181,"impl-Mov%3CReg8,+Reg8%3E-for-Asm"],[182,"impl-Mov%3CReg64,+Imm64%3E-for-Asm"],[183,"impl-Mov%3CReg16,+Imm16%3E-for-Asm"],[184,"impl-Mov%3CReg64,+MemOp%3E-for-Asm"],[185,"impl-Mov%3CMemOp,+Reg8%3E-for-Asm"],[186,"impl-Mov%3CMemOp,+Reg16%3E-for-Asm"],[187,"impl-Mov%3CReg8,+Imm8%3E-for-Asm"],[188,"impl-Mov%3CMemOp,+Imm16%3E-for-Asm"],[189,"impl-Mov%3CMemOp,+Reg32%3E-for-Asm"],[190,"impl-Mov%3CReg32,+MemOp%3E-for-Asm"],[191,"impl-Mov%3CReg32,+Imm32%3E-for-Asm"],[192,"impl-Mov%3CReg16,+Reg16%3E-for-Asm"],[193,"impl-Mov%3CReg32,+Reg32%3E-for-Asm"],[194,"impl-Mov%3CReg64,+Reg64%3E-for-Asm"],[195,"impl-Mov%3CReg16,+MemOp%3E-for-Asm"],[196,"impl-Mov%3CReg8,+MemOp%3E-for-Asm"],[197,"impl-Mov%3CMemOp,+Reg64%3E-for-Asm"],[202,"impl-Pop%3CReg64%3E-for-Asm"],[203,"impl-Pop%3CReg16%3E-for-Asm"],[204,"impl-Push%3CReg64%3E-for-Asm"],[205,"impl-Push%3CReg16%3E-for-Asm"],[251,"impl-Test%3CReg64,+Reg64%3E-for-Asm"],[252,"impl-Test%3CMemOp,+Imm16%3E-for-Asm"],[253,"impl-Test%3CReg32,+Reg32%3E-for-Asm"]],"c":"OjAAAAAAAAA=","e":"OzAAAAEAAPMADgAUAAUAGwADACAARQBoAAgAdAABAHgABwCBAAQAhwAGAJsABQCzABMAywApAPYAPQA1AQAAOAEBAA=="}],["tiny_vm",{"t":"PPPPPPPFPPPFPGGFNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNHHHNNNNNNNNNNNNNNNNNNNNNNN","n":["A","Add","Addi","B","Branch","BranchZero","C","Fixup","Halt","Load","LoadImm","PhysAddr","Store","TinyInsn","TinyReg","TinyVm","bind","borrow","","","","","borrow_mut","","","","","clone","","clone_into","","clone_to_uninit","","dump","eq","","fmt","","from","","","","","interp","into","","","","","","jit","make_tinyvm_fib","make_tinyvm_jit_perf","make_tinyvm_jit_test","new","","read_mem","read_reg","to_owned","","try_from","","","","","try_into","","","","","type_id","","","","","write_mem","write_reg"],"q":[[0,"tiny_vm"],[77,"alloc::vec"],[78,"core::fmt"],[79,"core::result"],[80,"core::any"]],"i":"nf01001`000`0```bAhA`24310243434343043431024301102430```02004310243102431024300","f":"````````````````{{b{j{d{h{f}}}}}l}{j{{j{c}}}{}}0000{{{j{d}}}{{j{dc}}}{}}0000{{{j{n}}}n}{{{j{f}}}f}{{j{j{dc}}}l{}}0{jl}0{{{j{A`}}}l}{{{j{n}}{j{n}}}Ab}{{{j{f}}{j{f}}}Ab}{{{j{n}}{j{dAd}}}Af}{{{j{f}}{j{dAd}}}Af}{cc{}}0000{{{j{dA`}}}l}{AhAj}{{}c{}}00002{Al{{h{f}}}}{{}{{h{f}}}}0{{{h{f}}}A`}{Ajb}{{{j{A`}}Ah}Al}{{{j{A`}}n}Al}{jc{}}0{c{{An{e}}}{}{}}0000{{}{{An{c}}}{}}0000{jB`}0000{{{j{dA`}}AhAl}l}{{{j{dA`}}nAl}l}","D":"Dj","p":[[5,"Fixup",0],[0,"mut"],[6,"TinyInsn",0],[5,"Vec",77],[1,"reference"],[1,"unit"],[6,"TinyReg",0],[5,"TinyVm",0],[1,"bool"],[5,"Formatter",78],[8,"Result",78],[5,"PhysAddr",0],[1,"usize"],[1,"u16"],[6,"Result",79],[5,"TypeId",80]],"r":[],"b":[],"c":"OjAAAAAAAAA=","e":"OzAAAAEAACgABwABAAAABAAAAAcAAAASAA8AIwADAC0AAAA7ABAA"}]]')); +var searchIndex = new Map(JSON.parse('[["add",{"t":"","n":[],"q":[],"i":"","f":"","D":"b","p":[],"r":[],"b":[],"c":"OjAAAAAAAAA=","e":"OjAAAAAAAAA="}],["bf",{"t":"","n":[],"q":[],"i":"","f":"","D":"b","p":[],"r":[],"b":[],"c":"OjAAAAAAAAA=","e":"OjAAAAAAAAA="}],["fib",{"t":"","n":[],"q":[],"i":"","f":"","D":"b","p":[],"r":[],"b":[],"c":"OjAAAAAAAAA=","e":"OjAAAAAAAAA="}],["juicebox_asm",{"t":"FFFFFPPPFGFFFFGGGGFNNNNNNNPPPPNPNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNPPPNPPNNNNNNNNNNNNNNNNNNNPNNNNNNPPPPNNNPPPPPPPPPNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNCNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPNPPPPPPNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNKKKKKKKKKKKKKKKMMMMMMMMMMMMMMM","n":["Asm","Imm16","Imm32","Imm64","Imm8","Indirect","IndirectBaseIndex","IndirectDisp","Label","MemOp","MemOp16","MemOp32","MemOp64","MemOp8","Reg16","Reg32","Reg64","Reg8","Runtime","add","","","","","","add_code","ah","al","ax","bh","bind","bl","borrow","","","","","","","","","","","","","","","","borrow_mut","","","","","","","","","","","","","","","","bp","bpl","bx","call","ch","cl","clone","","","","","clone_into","","","","","clone_to_uninit","","","","","cmovnz","cmovz","cmp","","cx","dec","","","","","","dh","di","dil","dl","drop","","dump","dx","eax","ebp","ebx","ecx","edi","edx","esi","esp","from","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","inc","","","","","","insn","into","","","","","","","","","","","","","","","","into_code","jmp","jnz","jz","mov","","","","","","","","","","","","","","","","","new","","","nop","pop","","push","","r10","r10d","r10l","r10w","r11","r11d","r11l","r11w","r12","r12d","r12l","r12w","r13","r13d","r13l","r13w","r14","r14d","r14l","r14w","r15","r15d","r15l","r15w","r8","r8d","r8l","r8w","r9","r9d","r9l","r9w","rax","rbp","rbx","rcx","rdi","rdx","ret","rsi","rsp","si","sil","sp","spl","test","","","to_owned","","","","","try_from","","","","","","","","","","","","","","","","try_into","","","","","","","","","","","","","","","","type_id","","","","","","","","","","","","","","","","with_profile","xor","Add","Call","Cmovnz","Cmovz","Cmp","Dec","Inc","Jmp","Jnz","Jz","Mov","Pop","Push","Test","Xor","add","call","cmovnz","cmovz","cmp","dec","inc","jmp","jnz","jz","mov","pop","push","test","xor"],"q":[[0,"juicebox_asm"],[309,"juicebox_asm::insn"],[339,"juicebox_asm::asm"],[340,"juicebox_asm::reg"],[341,"juicebox_asm::imm"],[342,"juicebox_asm::rt"],[343,"core::convert"],[344,"juicebox_asm::label"],[345,"alloc::vec"],[346,"core::result"],[347,"core::any"]],"i":"`````h00```````````d00000AdAn0j1313Al3B`A`C`CfnAb78;BhBbBfBd>:=987654;<<54;>>>;>>>>>><;<<:==;44444444>:=9998888877777776666666666654;>>>>>`>:=987654;>>>>>>>>>>>>>>>>>>>>>:=>>>>>54<;54<;54<;54<;54<;54<;54<;54<;555555>55;<;<>>>54;:=987654;:=987654;:=987654;```````````````DfDhDjDlDnE`EbEdEfEhEjElEnF`Fb","f":"```````````````````{{{f{bd}}hj}l}{{{f{bd}}nh}l}{{{f{bd}}hA`}l}{{{f{bd}}hn}l}{{{f{bd}}AbAb}l}{{{f{bd}}nn}l}{{{f{bAd}}c}e{{Aj{{Ah{Af}}}}}{}}````{{{f{bd}}{f{bAl}}}l}`{f{{f{c}}}{}}000000000000000{{{f{b}}}{{f{bc}}}{}}000000000000000```{{{f{bd}}n}l}``{{{f{n}}}n}{{{f{Ab}}}Ab}{{{f{j}}}j}{{{f{An}}}An}{{{f{h}}}h}{{f{f{bc}}}l{}}0000{fl}0000<<{{{f{bd}}hB`}l}{{{f{bd}}hA`}l}`{{{f{bd}}Ab}l}{{{f{bd}}Bb}l}{{{f{bd}}Bd}l}{{{f{bd}}Bf}l}={{{f{bd}}Bh}l}````{{{f{bAl}}}l}{{{f{bAd}}}l}{{{f{Ad}}}l}`````````{cc{}}00{AfB`}{BjB`}22{AfA`}{BjA`}{BlA`}{BnA`}{BjC`}{BnC`}{CbC`}{BlC`}:{AfC`}{CdC`}{CbCf}{BjCf}{ChCf}?{CjCf}{CdCf}{BlCf}{AfCf}{ClCf}{CnCf}{BnCf}{cc{}}0000{hBh}11{hBb}2{hBf}{hBd}4{{{f{bd}}Bh}l}{{{f{bd}}Ab}l}{{{f{bd}}Bb}l}{{{f{bd}}Bf}l}{{{f{bd}}Bd}l}{{{f{bd}}n}l}`{{}c{}}000000000000000{d{{D`{Af}}}}{{{f{bd}}{f{bAl}}}l}00{{{f{bd}}AnAn}l}{{{f{bd}}nCf}l}{{{f{bd}}jA`}l}{{{f{bd}}nh}l}{{{f{bd}}hAn}l}{{{f{bd}}hj}l}{{{f{bd}}AnB`}l}{{{f{bd}}hA`}l}{{{f{bd}}hAb}l}{{{f{bd}}Abh}l}{{{f{bd}}AbC`}l}{{{f{bd}}jj}l}{{{f{bd}}AbAb}l}{{{f{bd}}nn}l}{{{f{bd}}jh}l}{{{f{bd}}Anh}l}{{{f{bd}}hn}l}{{}d}{{}Al}{{}Ad}{{{f{bd}}}l}{{{f{bd}}n}l}{{{f{bd}}j}l}10``````````````````````````````````````2``````9?:{fc{}}0000{c{{Db{e}}}{}{}}000000000000000{{}{{Db{c}}}{}}000000000000000{fDd}0000000000000007=```````````````{{{f{bDf}}ce}l{}{}}{{{f{bDh}}c}l{}}{{{f{bDj}}ce}l{}{}}{{{f{bDl}}ce}l{}{}}{{{f{bDn}}ce}l{}{}}{{{f{bE`}}c}l{}}{{{f{bEb}}c}l{}}{{{f{bEd}}c}l{}}{{{f{bEf}}c}l{}}{{{f{bEh}}c}l{}}{{{f{bEj}}ce}l{}{}}{{{f{bEl}}c}l{}}{{{f{bEn}}c}l{}}{{{f{bF`}}ce}l{}{}}{{{f{bFb}}ce}l{}{}}","D":"L`","p":[[0,"mut"],[5,"Asm",0,339],[1,"reference"],[6,"MemOp",0],[6,"Reg16",0,340],[1,"unit"],[6,"Reg64",0,340],[5,"Imm16",0,341],[6,"Reg32",0,340],[5,"Runtime",0,342],[1,"u8"],[1,"slice"],[10,"AsRef",343],[5,"Label",0,344],[6,"Reg8",0,340],[5,"Imm8",0,341],[5,"MemOp16",0],[5,"MemOp64",0],[5,"MemOp32",0],[5,"MemOp8",0],[1,"i8"],[1,"i16"],[1,"u16"],[5,"Imm32",0,341],[1,"u32"],[1,"i32"],[5,"Imm64",0,341],[1,"i64"],[1,"u64"],[1,"isize"],[1,"usize"],[5,"Vec",345],[6,"Result",346],[5,"TypeId",347],[10,"Add",309],[10,"Call",309],[10,"Cmovnz",309],[10,"Cmovz",309],[10,"Cmp",309],[10,"Dec",309],[10,"Inc",309],[10,"Jmp",309],[10,"Jnz",309],[10,"Jz",309],[10,"Mov",309],[10,"Pop",309],[10,"Push",309],[10,"Test",309],[10,"Xor",309]],"r":[[0,339],[1,341],[2,341],[3,341],[4,341],[8,344],[14,340],[15,340],[16,340],[17,340],[18,342]],"b":[[19,"impl-Add%3CMemOp,+Reg16%3E-for-Asm"],[20,"impl-Add%3CReg64,+MemOp%3E-for-Asm"],[21,"impl-Add%3CMemOp,+Imm16%3E-for-Asm"],[22,"impl-Add%3CMemOp,+Reg64%3E-for-Asm"],[23,"impl-Add%3CReg32,+Reg32%3E-for-Asm"],[24,"impl-Add%3CReg64,+Reg64%3E-for-Asm"],[87,"impl-Cmp%3CMemOp,+Imm8%3E-for-Asm"],[88,"impl-Cmp%3CMemOp,+Imm16%3E-for-Asm"],[90,"impl-Dec%3CReg32%3E-for-Asm"],[91,"impl-Dec%3CMemOp16%3E-for-Asm"],[92,"impl-Dec%3CMemOp64%3E-for-Asm"],[93,"impl-Dec%3CMemOp32%3E-for-Asm"],[94,"impl-Dec%3CReg64%3E-for-Asm"],[95,"impl-Dec%3CMemOp8%3E-for-Asm"],[115,"impl-From%3Cu8%3E-for-Imm8"],[116,"impl-From%3Ci8%3E-for-Imm8"],[119,"impl-From%3Cu8%3E-for-Imm16"],[120,"impl-From%3Ci8%3E-for-Imm16"],[121,"impl-From%3Ci16%3E-for-Imm16"],[122,"impl-From%3Cu16%3E-for-Imm16"],[123,"impl-From%3Ci8%3E-for-Imm32"],[124,"impl-From%3Cu16%3E-for-Imm32"],[125,"impl-From%3Cu32%3E-for-Imm32"],[126,"impl-From%3Ci16%3E-for-Imm32"],[128,"impl-From%3Cu8%3E-for-Imm32"],[129,"impl-From%3Ci32%3E-for-Imm32"],[130,"impl-From%3Cu32%3E-for-Imm64"],[131,"impl-From%3Ci8%3E-for-Imm64"],[132,"impl-From%3Ci64%3E-for-Imm64"],[134,"impl-From%3Cu64%3E-for-Imm64"],[135,"impl-From%3Ci32%3E-for-Imm64"],[136,"impl-From%3Ci16%3E-for-Imm64"],[137,"impl-From%3Cu8%3E-for-Imm64"],[138,"impl-From%3Cisize%3E-for-Imm64"],[139,"impl-From%3Cusize%3E-for-Imm64"],[140,"impl-From%3Cu16%3E-for-Imm64"],[154,"impl-Inc%3CMemOp8%3E-for-Asm"],[155,"impl-Inc%3CReg32%3E-for-Asm"],[156,"impl-Inc%3CMemOp16%3E-for-Asm"],[157,"impl-Inc%3CMemOp32%3E-for-Asm"],[158,"impl-Inc%3CMemOp64%3E-for-Asm"],[159,"impl-Inc%3CReg64%3E-for-Asm"],[181,"impl-Mov%3CReg8,+Reg8%3E-for-Asm"],[182,"impl-Mov%3CReg64,+Imm64%3E-for-Asm"],[183,"impl-Mov%3CReg16,+Imm16%3E-for-Asm"],[184,"impl-Mov%3CReg64,+MemOp%3E-for-Asm"],[185,"impl-Mov%3CMemOp,+Reg8%3E-for-Asm"],[186,"impl-Mov%3CMemOp,+Reg16%3E-for-Asm"],[187,"impl-Mov%3CReg8,+Imm8%3E-for-Asm"],[188,"impl-Mov%3CMemOp,+Imm16%3E-for-Asm"],[189,"impl-Mov%3CMemOp,+Reg32%3E-for-Asm"],[190,"impl-Mov%3CReg32,+MemOp%3E-for-Asm"],[191,"impl-Mov%3CReg32,+Imm32%3E-for-Asm"],[192,"impl-Mov%3CReg16,+Reg16%3E-for-Asm"],[193,"impl-Mov%3CReg32,+Reg32%3E-for-Asm"],[194,"impl-Mov%3CReg64,+Reg64%3E-for-Asm"],[195,"impl-Mov%3CReg16,+MemOp%3E-for-Asm"],[196,"impl-Mov%3CReg8,+MemOp%3E-for-Asm"],[197,"impl-Mov%3CMemOp,+Reg64%3E-for-Asm"],[202,"impl-Pop%3CReg64%3E-for-Asm"],[203,"impl-Pop%3CReg16%3E-for-Asm"],[204,"impl-Push%3CReg64%3E-for-Asm"],[205,"impl-Push%3CReg16%3E-for-Asm"],[251,"impl-Test%3CReg64,+Reg64%3E-for-Asm"],[252,"impl-Test%3CMemOp,+Imm16%3E-for-Asm"],[253,"impl-Test%3CReg32,+Reg32%3E-for-Asm"]],"c":"OjAAAAAAAAA=","e":"OzAAAAEAAPMADgAUAAUAGwADACAARQBoAAgAdAABAHgABwCBAAQAhwAGAJsABQCzABMAywApAPYAPQA1AQAAOAEBAA=="}],["tiny_vm",{"t":"PPPPPPPFPPPFPGGFNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNHHHNNNNNNNNNNNNNNNNNNNNNNN","n":["A","Add","Addi","B","Branch","BranchZero","C","Fixup","Halt","Load","LoadImm","PhysAddr","Store","TinyInsn","TinyReg","TinyVm","bind","borrow","","","","","borrow_mut","","","","","clone","","clone_into","","clone_to_uninit","","dump","eq","","fmt","","from","","","","","interp","into","","","","","","jit","make_tinyvm_fib","make_tinyvm_jit_perf","make_tinyvm_jit_test","new","","read_mem","read_reg","to_owned","","try_from","","","","","try_into","","","","","type_id","","","","","write_mem","write_reg"],"q":[[0,"tiny_vm"],[77,"alloc::vec"],[78,"core::fmt"],[79,"core::result"],[80,"core::any"]],"i":"nf01001`000`0```bAhA`24310243434343043431024301102430```02004310243102431024300","f":"````````````````{{b{j{d{h{f}}}}}l}{j{{j{c}}}{}}0000{{{j{d}}}{{j{dc}}}{}}0000{{{j{n}}}n}{{{j{f}}}f}{{j{j{dc}}}l{}}0{jl}0{{{j{A`}}}l}{{{j{n}}{j{n}}}Ab}{{{j{f}}{j{f}}}Ab}{{{j{n}}{j{dAd}}}Af}{{{j{f}}{j{dAd}}}Af}{cc{}}0000{{{j{dA`}}}l}{AhAj}{{}c{}}00002{Al{{h{f}}}}{{}{{h{f}}}}0{{{h{f}}}A`}{Ajb}{{{j{A`}}Ah}Al}{{{j{A`}}n}Al}{jc{}}0{c{{An{e}}}{}{}}0000{{}{{An{c}}}{}}0000{jB`}0000{{{j{dA`}}AhAl}l}{{{j{dA`}}nAl}l}","D":"Dj","p":[[5,"Fixup",0],[0,"mut"],[6,"TinyInsn",0],[5,"Vec",77],[1,"reference"],[1,"unit"],[6,"TinyReg",0],[5,"TinyVm",0],[1,"bool"],[5,"Formatter",78],[8,"Result",78],[5,"PhysAddr",0],[1,"usize"],[1,"u16"],[6,"Result",79],[5,"TypeId",80]],"r":[],"b":[],"c":"OjAAAAAAAAA=","e":"OzAAAAEAACgABwABAAAABAAAAAcAAAASAA8AIwADAC0AAAA7ABAA"}]]')); if (typeof exports !== 'undefined') exports.searchIndex = searchIndex; else if (window.initSearch) window.initSearch(searchIndex); -//{"start":39,"fragment_lengths":[111,114,112,7729,1542]} \ No newline at end of file +//{"start":39,"fragment_lengths":[111,111,112,7729,1542]} \ No newline at end of file diff --git a/search.desc/bf/bf-desc-0-.js b/search.desc/bf/bf-desc-0-.js new file mode 100644 index 0000000..1b793fd --- /dev/null +++ b/search.desc/bf/bf-desc-0-.js @@ -0,0 +1 @@ +searchState.loadedDescShard("bf", 0, "Brainfuck VM.") \ No newline at end of file diff --git a/search.desc/bf_vm/bf_vm-desc-0-.js b/search.desc/bf_vm/bf_vm-desc-0-.js deleted file mode 100644 index 0387065..0000000 --- a/search.desc/bf_vm/bf_vm-desc-0-.js +++ /dev/null @@ -1 +0,0 @@ -searchState.loadedDescShard("bf_vm", 0, "Brainfuck VM.") \ No newline at end of file diff --git a/src-files.js b/src-files.js index 9762bfa..e351449 100644 --- a/src-files.js +++ b/src-files.js @@ -1,3 +1,3 @@ -var srcIndex = new Map(JSON.parse('[["add",["",[],["add.rs"]]],["bf_vm",["",[],["bf_vm.rs"]]],["fib",["",[],["fib.rs"]]],["juicebox_asm",["",[["insn",[],["add.rs","call.rs","cmovnz.rs","cmovz.rs","cmp.rs","dec.rs","inc.rs","jmp.rs","jnz.rs","jz.rs","mov.rs","nop.rs","pop.rs","push.rs","ret.rs","test.rs","xor.rs"]]],["asm.rs","imm.rs","insn.rs","label.rs","lib.rs","reg.rs","rt.rs"]]],["tiny_vm",["",[],["tiny_vm.rs"]]]]')); +var srcIndex = new Map(JSON.parse('[["add",["",[],["add.rs"]]],["bf",["",[],["bf.rs"]]],["fib",["",[],["fib.rs"]]],["juicebox_asm",["",[["insn",[],["add.rs","call.rs","cmovnz.rs","cmovz.rs","cmp.rs","dec.rs","inc.rs","jmp.rs","jnz.rs","jz.rs","mov.rs","nop.rs","pop.rs","push.rs","ret.rs","test.rs","xor.rs"]]],["asm.rs","imm.rs","insn.rs","label.rs","lib.rs","reg.rs","rt.rs"]]],["tiny_vm",["",[],["tiny_vm.rs"]]]]')); createSrcSidebar(); -//{"start":36,"fragment_lengths":[26,31,27,265,35]} \ No newline at end of file +//{"start":36,"fragment_lengths":[26,25,27,265,35]} \ No newline at end of file diff --git a/src/bf/bf.rs.html b/src/bf/bf.rs.html new file mode 100644 index 0000000..25b814e --- /dev/null +++ b/src/bf/bf.rs.html @@ -0,0 +1,585 @@ +bf.rs - source

bf/
bf.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
//! Brainfuck VM.
+//!
+//! This example implements a simple
+//! [brainfuck](https://en.wikipedia.org/wiki/Brainfuck) interpreter
+//! [`BrainfuckInterp`] and a jit compiler [`BrainfuckJit`].
+//!
+//! Brainfuck is an esoteric programming languge existing of 8 commands.
+//! - `>` increment data pointer.
+//! - `<` decrement data pointer.
+//! - `+` increment data at current data pointer.
+//! - `-` decrement data at current data pointer.
+//! - `.` output data at current data pointer.
+//! - `,` read input and store at current data pointer.
+//! - `[` jump behind matching ']' if data at data pointer is zero.
+//! - `]` jump behind matching '[' if data at data pointer is non-zero.
+
+use std::collections::HashMap;
+use std::io::Write;
+
+use juicebox_asm::insn::*;
+use juicebox_asm::Runtime;
+use juicebox_asm::{Asm, Imm64, Imm8, Label, MemOp, MemOp8, Reg64, Reg8};
+
+struct BrainfuckInterp {
+    pc: usize,
+    imem: Vec<char>,
+    dptr: usize,
+    dmem: [u8; 256],
+    branches: HashMap<usize, usize>,
+}
+
+impl BrainfuckInterp {
+    fn new(prog: &str) -> Result<Self, String> {
+        // Do a first pass over the bf program to filter whitespace and detect invalid tokens.
+        // Additionally validate all conditional branches, and compute their branch target.
+        let (imem, branches) = {
+            // Instruction memory holding the final bf program.
+            let mut imem = Vec::new();
+            // Helper to track index of open brackets.
+            let mut lhs_brackets = Vec::new();
+            // Mapping from branch instruction to branch target.
+            let mut branches = HashMap::new();
+
+            for (idx, token) in prog.chars().filter(|c| !c.is_whitespace()).enumerate() {
+                match token {
+                    '<' | '>' | '+' | '-' | '.' | ',' => { /* ignore valid bf tokens */ }
+                    '[' => lhs_brackets.push(idx),
+                    ']' => {
+                        if let Some(lhs) = lhs_brackets.pop() {
+                            branches.insert(lhs, idx);
+                            branches.insert(idx, lhs);
+                        } else {
+                            return Err(format!("encountered un-balanced brackets, found ']' at index {idx} without matching '['"));
+                        }
+                    }
+                    _ => return Err(format!("invalid bf token '{token}'")),
+                }
+                imem.push(token)
+            }
+
+            if !lhs_brackets.is_empty() {
+                return Err(String::from(
+                    "encountered un-balanced brackets, left-over '[' after parsing bf program",
+                ));
+            }
+
+            (imem, branches)
+        };
+
+        Ok(BrainfuckInterp {
+            pc: 0,
+            imem,
+            dptr: 0,
+            dmem: [0; 256],
+            branches,
+        })
+    }
+}
+
+fn run_interp(prog: &str) {
+    let mut vm = BrainfuckInterp::new(prog).unwrap();
+
+    loop {
+        let insn = match vm.imem.get(vm.pc) {
+            Some(insn) => insn,
+            None => break, // End of bf program.
+        };
+
+        let putchar = |val: u8| {
+            std::io::stdout()
+                .write(&[val])
+                .expect("Failed to write to stdout!");
+        };
+
+        match insn {
+            '>' => {
+                vm.dptr += 1;
+                assert!(vm.dptr < vm.dmem.len());
+            }
+            '<' => {
+                assert!(vm.dptr > 0);
+                vm.dptr -= 1;
+            }
+            '+' => {
+                vm.dmem[vm.dptr] += 1;
+            }
+            '-' => {
+                vm.dmem[vm.dptr] -= 1;
+            }
+            '.' => {
+                putchar(vm.dmem[vm.dptr]);
+            }
+            ',' => {
+                unimplemented!("getchar");
+            }
+            '[' => {
+                if vm.dmem[vm.dptr] == 0 {
+                    vm.pc = *vm.branches.get(&vm.pc).unwrap();
+                }
+            }
+            ']' => {
+                if vm.dmem[vm.dptr] != 0 {
+                    vm.pc = *vm.branches.get(&vm.pc).unwrap();
+                }
+            }
+            _ => unreachable!(),
+        }
+
+        vm.pc += 1;
+    }
+}
+
+// -- BRAINFUCK JIT --------------------------------------------------------------
+
+#[cfg(not(any(target_arch = "x86_64", target_os = "linux")))]
+compile_error!("Only supported on x86_64 with SystemV abi");
+
+struct BrainfuckJit {
+    imem: Vec<char>,
+    dmem: [u8; 256],
+}
+
+impl BrainfuckJit {
+    fn new(prog: &str) -> Result<Self, String> {
+        // Do a first pass over the bf program to filter whitespace and detect invalid tokens.
+        let imem = prog
+            .chars()
+            .filter(|c| !c.is_whitespace())
+            .map(|c| match c {
+                '<' | '>' | '+' | '-' | '.' | ',' | '[' | ']' => Ok(c),
+                _ => Err(format!("invalid bf token '{c}'")),
+            })
+            .collect::<Result<Vec<char>, String>>()?;
+
+        Ok(BrainfuckJit {
+            imem,
+            dmem: [0; 256],
+        })
+    }
+}
+
+extern "C" fn putchar(c: u8) {
+    std::io::stdout()
+        .write(&[c])
+        .expect("Failed to write to stdout!");
+}
+
+fn run_jit(prog: &str) {
+    let mut vm = BrainfuckJit::new(prog).unwrap();
+
+    // Use callee saved registers to hold vm state, such that we don't
+    // need to save any state before calling out to putchar.
+    let dmem_base = Reg64::rbx;
+    let dmem_idx = Reg64::r12;
+
+    let mut asm = Asm::new();
+    // Move data memory pointer (argument on jit entry) into correct
+    // register.
+    asm.mov(dmem_base, Reg64::rdi);
+    // Clear data memory index.
+    asm.xor(dmem_idx, dmem_idx);
+
+    // A stack of label pairs, used to link up forward and backward
+    // jumps for a given '[]' pair.
+    let mut label_stack = Vec::new();
+
+    // Generate code for each instruction in the bf program.
+    for insn in vm.imem {
+        match insn {
+            '>' => {
+                // TODO: generate runtime bounds check.
+                asm.inc(dmem_idx);
+            }
+            '<' => {
+                // TODO: generate runtime bounds check.
+                asm.dec(dmem_idx);
+            }
+            '+' => {
+                asm.inc(MemOp8::from(MemOp::IndirectBaseIndex(dmem_base, dmem_idx)));
+            }
+            '-' => {
+                asm.dec(MemOp8::from(MemOp::IndirectBaseIndex(dmem_base, dmem_idx)));
+            }
+            '.' => {
+                // Load data memory from active cell into di register,
+                // which is the first argument register according to
+                // the SystemV abi, then call into putchar. Since we
+                // stored all out vm state in callee saved registers
+                // we don't need to save any registers before the
+                // call.
+                asm.mov(Reg8::dil, MemOp::IndirectBaseIndex(dmem_base, dmem_idx));
+                asm.mov(Reg64::rax, Imm64::from(putchar as usize));
+                asm.call(Reg64::rax);
+            }
+            ',' => {
+                unimplemented!("getchar");
+            }
+            '[' => {
+                // Create new label pair.
+                label_stack.push((Label::new(), Label::new()));
+                // UNWRAP: We just pushed a new entry on the stack.
+                let label_pair = label_stack.last_mut().unwrap();
+
+                // Goto label_pair.0 if data memory at active cell is 0.
+                //   if vm.dmem[vm.dptr] == 0 goto label_pair.0
+                asm.cmp(
+                    MemOp::IndirectBaseIndex(dmem_base, dmem_idx),
+                    Imm8::from(0u8),
+                );
+                asm.jz(&mut label_pair.0);
+
+                // Bind label_pair.1 after the jump instruction, which
+                // will be the branch target for the matching ']'.
+                asm.bind(&mut label_pair.1);
+            }
+            ']' => {
+                let mut label_pair = label_stack
+                    .pop()
+                    .expect("encountered un-balanced brackets, found ']' without matching '['");
+
+                // Goto label_pair.1 if data memory at active cell is
+                // not 0.
+                //   if vm.dmem[vm.dptr] != 0 goto label_pair.1
+                asm.cmp(
+                    MemOp::IndirectBaseIndex(dmem_base, dmem_idx),
+                    Imm8::from(0u8),
+                );
+                asm.jnz(&mut label_pair.1);
+
+                // Bind label_pair.0 after the jump instruction, which
+                // is the branch target for the matching '['.
+                asm.bind(&mut label_pair.0);
+            }
+            _ => unreachable!(),
+        }
+    }
+
+    // Return from bf program.
+    asm.ret();
+
+    if !label_stack.is_empty() {
+        panic!("encountered un-balanced brackets, left-over '[' after jitting bf program")
+    }
+
+    // Execute jitted bf program.
+    let mut rt = Runtime::new();
+    let bf_entry = unsafe { rt.add_code::<extern "C" fn(*mut u8)>(asm.into_code()) };
+    bf_entry(&mut vm.dmem as *mut u8);
+}
+
+fn main() {
+    // https://en.wikipedia.org/wiki/Brainfuck#Adding_two_values
+    //let inp = "++>+++++ [<+>-] ++++++++[<++++++>-]<.";
+    //println!("add-print-7 (wikipedia.org) - interp");
+    //run_interp(inp);
+    //println!("add-print-7 (wikipedia.org) - jit");
+    //run_jit(inp);
+
+    // https://en.wikipedia.org/wiki/Brainfuck#Hello_World!
+    let inp = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.";
+    println!("hello-world (wikipedia.org) - interp");
+    run_interp(inp);
+    println!("hello-world (wikipedia.org) - jit");
+    run_jit(inp);
+
+    // https://programmingwiki.de/Brainfuck
+    let inp = ">+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-]>++++++++[<++++>-] <.>+++++++++++[<++++++++>-]<-.--------.+++.------.--------.[-]>++++++++[<++++>- ]<+.[-]++++++++++.";
+    println!("hello-world (programmingwiki.de) - interp");
+    run_interp(inp);
+    println!("hello-world (programmingwiki.de) - jit");
+    run_jit(inp);
+}
+
\ No newline at end of file diff --git a/src/bf_vm/bf_vm.rs.html b/src/bf_vm/bf_vm.rs.html deleted file mode 100644 index fd2fe24..0000000 --- a/src/bf_vm/bf_vm.rs.html +++ /dev/null @@ -1,585 +0,0 @@ -bf_vm.rs - source

bf_vm/
bf_vm.rs

-1
-2
-3
-4
-5
-6
-7
-8
-9
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-89
-90
-91
-92
-93
-94
-95
-96
-97
-98
-99
-100
-101
-102
-103
-104
-105
-106
-107
-108
-109
-110
-111
-112
-113
-114
-115
-116
-117
-118
-119
-120
-121
-122
-123
-124
-125
-126
-127
-128
-129
-130
-131
-132
-133
-134
-135
-136
-137
-138
-139
-140
-141
-142
-143
-144
-145
-146
-147
-148
-149
-150
-151
-152
-153
-154
-155
-156
-157
-158
-159
-160
-161
-162
-163
-164
-165
-166
-167
-168
-169
-170
-171
-172
-173
-174
-175
-176
-177
-178
-179
-180
-181
-182
-183
-184
-185
-186
-187
-188
-189
-190
-191
-192
-193
-194
-195
-196
-197
-198
-199
-200
-201
-202
-203
-204
-205
-206
-207
-208
-209
-210
-211
-212
-213
-214
-215
-216
-217
-218
-219
-220
-221
-222
-223
-224
-225
-226
-227
-228
-229
-230
-231
-232
-233
-234
-235
-236
-237
-238
-239
-240
-241
-242
-243
-244
-245
-246
-247
-248
-249
-250
-251
-252
-253
-254
-255
-256
-257
-258
-259
-260
-261
-262
-263
-264
-265
-266
-267
-268
-269
-270
-271
-272
-273
-274
-275
-276
-277
-278
-279
-280
-281
-282
-283
-284
-285
-286
-287
-288
-289
-290
-291
-292
//! Brainfuck VM.
-//!
-//! This example implements a simple
-//! [brainfuck](https://en.wikipedia.org/wiki/Brainfuck) interpreter
-//! [`BrainfuckInterp`] and a jit compiler [`BrainfuckJit`].
-//!
-//! Brainfuck is an esoteric programming languge existing of 8 commands.
-//! - `>` increment data pointer.
-//! - `<` decrement data pointer.
-//! - `+` increment data at current data pointer.
-//! - `-` decrement data at current data pointer.
-//! - `.` output data at current data pointer.
-//! - `,` read input and store at current data pointer.
-//! - `[` jump behind matching ']' if data at data pointer is zero.
-//! - `]` jump behind matching '[' if data at data pointer is non-zero.
-
-use std::collections::HashMap;
-use std::io::Write;
-
-use juicebox_asm::insn::*;
-use juicebox_asm::Runtime;
-use juicebox_asm::{Asm, Imm64, Imm8, Label, MemOp, MemOp8, Reg64, Reg8};
-
-struct BrainfuckInterp {
-    pc: usize,
-    imem: Vec<char>,
-    dptr: usize,
-    dmem: [u8; 256],
-    branches: HashMap<usize, usize>,
-}
-
-impl BrainfuckInterp {
-    fn new(prog: &str) -> Result<Self, String> {
-        // Do a first pass over the bf program to filter whitespace and detect invalid tokens.
-        // Additionally validate all conditional branches, and compute their branch target.
-        let (imem, branches) = {
-            // Instruction memory holding the final bf program.
-            let mut imem = Vec::new();
-            // Helper to track index of open brackets.
-            let mut lhs_brackets = Vec::new();
-            // Mapping from branch instruction to branch target.
-            let mut branches = HashMap::new();
-
-            for (idx, token) in prog.chars().filter(|c| !c.is_whitespace()).enumerate() {
-                match token {
-                    '<' | '>' | '+' | '-' | '.' | ',' => { /* ignore valid bf tokens */ }
-                    '[' => lhs_brackets.push(idx),
-                    ']' => {
-                        if let Some(lhs) = lhs_brackets.pop() {
-                            branches.insert(lhs, idx);
-                            branches.insert(idx, lhs);
-                        } else {
-                            return Err(format!("encountered un-balanced brackets, found ']' at index {idx} without matching '['"));
-                        }
-                    }
-                    _ => return Err(format!("invalid bf token '{token}'")),
-                }
-                imem.push(token)
-            }
-
-            if !lhs_brackets.is_empty() {
-                return Err(String::from(
-                    "encountered un-balanced brackets, left-over '[' after parsing bf program",
-                ));
-            }
-
-            (imem, branches)
-        };
-
-        Ok(BrainfuckInterp {
-            pc: 0,
-            imem,
-            dptr: 0,
-            dmem: [0; 256],
-            branches,
-        })
-    }
-}
-
-fn run_interp(prog: &str) {
-    let mut vm = BrainfuckInterp::new(prog).unwrap();
-
-    loop {
-        let insn = match vm.imem.get(vm.pc) {
-            Some(insn) => insn,
-            None => break, // End of bf program.
-        };
-
-        let putchar = |val: u8| {
-            std::io::stdout()
-                .write(&[val])
-                .expect("Failed to write to stdout!");
-        };
-
-        match insn {
-            '>' => {
-                vm.dptr += 1;
-                assert!(vm.dptr < vm.dmem.len());
-            }
-            '<' => {
-                assert!(vm.dptr > 0);
-                vm.dptr -= 1;
-            }
-            '+' => {
-                vm.dmem[vm.dptr] += 1;
-            }
-            '-' => {
-                vm.dmem[vm.dptr] -= 1;
-            }
-            '.' => {
-                putchar(vm.dmem[vm.dptr]);
-            }
-            ',' => {
-                unimplemented!("getchar");
-            }
-            '[' => {
-                if vm.dmem[vm.dptr] == 0 {
-                    vm.pc = *vm.branches.get(&vm.pc).unwrap();
-                }
-            }
-            ']' => {
-                if vm.dmem[vm.dptr] != 0 {
-                    vm.pc = *vm.branches.get(&vm.pc).unwrap();
-                }
-            }
-            _ => unreachable!(),
-        }
-
-        vm.pc += 1;
-    }
-}
-
-// -- BRAINFUCK JIT --------------------------------------------------------------
-
-#[cfg(not(any(target_arch = "x86_64", target_os = "linux")))]
-compile_error!("Only supported on x86_64 with SystemV abi");
-
-struct BrainfuckJit {
-    imem: Vec<char>,
-    dmem: [u8; 256],
-}
-
-impl BrainfuckJit {
-    fn new(prog: &str) -> Result<Self, String> {
-        // Do a first pass over the bf program to filter whitespace and detect invalid tokens.
-        let imem = prog
-            .chars()
-            .filter(|c| !c.is_whitespace())
-            .map(|c| match c {
-                '<' | '>' | '+' | '-' | '.' | ',' | '[' | ']' => Ok(c),
-                _ => Err(format!("invalid bf token '{c}'")),
-            })
-            .collect::<Result<Vec<char>, String>>()?;
-
-        Ok(BrainfuckJit {
-            imem,
-            dmem: [0; 256],
-        })
-    }
-}
-
-extern "C" fn putchar(c: u8) {
-    std::io::stdout()
-        .write(&[c])
-        .expect("Failed to write to stdout!");
-}
-
-fn run_jit(prog: &str) {
-    let mut vm = BrainfuckJit::new(prog).unwrap();
-
-    // Use callee saved registers to hold vm state, such that we don't
-    // need to save any state before calling out to putchar.
-    let dmem_base = Reg64::rbx;
-    let dmem_idx = Reg64::r12;
-
-    let mut asm = Asm::new();
-    // Move data memory pointer (argument on jit entry) into correct
-    // register.
-    asm.mov(dmem_base, Reg64::rdi);
-    // Clear data memory index.
-    asm.xor(dmem_idx, dmem_idx);
-
-    // A stack of label pairs, used to link up forward and backward
-    // jumps for a given '[]' pair.
-    let mut label_stack = Vec::new();
-
-    // Generate code for each instruction in the bf program.
-    for insn in vm.imem {
-        match insn {
-            '>' => {
-                // TODO: generate runtime bounds check.
-                asm.inc(dmem_idx);
-            }
-            '<' => {
-                // TODO: generate runtime bounds check.
-                asm.dec(dmem_idx);
-            }
-            '+' => {
-                asm.inc(MemOp8::from(MemOp::IndirectBaseIndex(dmem_base, dmem_idx)));
-            }
-            '-' => {
-                asm.dec(MemOp8::from(MemOp::IndirectBaseIndex(dmem_base, dmem_idx)));
-            }
-            '.' => {
-                // Load data memory from active cell into di register,
-                // which is the first argument register according to
-                // the SystemV abi, then call into putchar. Since we
-                // stored all out vm state in callee saved registers
-                // we don't need to save any registers before the
-                // call.
-                asm.mov(Reg8::dil, MemOp::IndirectBaseIndex(dmem_base, dmem_idx));
-                asm.mov(Reg64::rax, Imm64::from(putchar as usize));
-                asm.call(Reg64::rax);
-            }
-            ',' => {
-                unimplemented!("getchar");
-            }
-            '[' => {
-                // Create new label pair.
-                label_stack.push((Label::new(), Label::new()));
-                // UNWRAP: We just pushed a new entry on the stack.
-                let label_pair = label_stack.last_mut().unwrap();
-
-                // Goto label_pair.0 if data memory at active cell is 0.
-                //   if vm.dmem[vm.dptr] == 0 goto label_pair.0
-                asm.cmp(
-                    MemOp::IndirectBaseIndex(dmem_base, dmem_idx),
-                    Imm8::from(0u8),
-                );
-                asm.jz(&mut label_pair.0);
-
-                // Bind label_pair.1 after the jump instruction, which
-                // will be the branch target for the matching ']'.
-                asm.bind(&mut label_pair.1);
-            }
-            ']' => {
-                let mut label_pair = label_stack
-                    .pop()
-                    .expect("encountered un-balanced brackets, found ']' without matching '['");
-
-                // Goto label_pair.1 if data memory at active cell is
-                // not 0.
-                //   if vm.dmem[vm.dptr] != 0 goto label_pair.1
-                asm.cmp(
-                    MemOp::IndirectBaseIndex(dmem_base, dmem_idx),
-                    Imm8::from(0u8),
-                );
-                asm.jnz(&mut label_pair.1);
-
-                // Bind label_pair.0 after the jump instruction, which
-                // is the branch target for the matching '['.
-                asm.bind(&mut label_pair.0);
-            }
-            _ => unreachable!(),
-        }
-    }
-
-    // Return from bf program.
-    asm.ret();
-
-    if !label_stack.is_empty() {
-        panic!("encountered un-balanced brackets, left-over '[' after jitting bf program")
-    }
-
-    // Execute jitted bf program.
-    let mut rt = Runtime::new();
-    let bf_entry = unsafe { rt.add_code::<extern "C" fn(*mut u8)>(asm.into_code()) };
-    bf_entry(&mut vm.dmem as *mut u8);
-}
-
-fn main() {
-    // https://en.wikipedia.org/wiki/Brainfuck#Adding_two_values
-    //let inp = "++>+++++ [<+>-] ++++++++[<++++++>-]<.";
-    //println!("add-print-7 (wikipedia.org) - interp");
-    //run_interp(inp);
-    //println!("add-print-7 (wikipedia.org) - jit");
-    //run_jit(inp);
-
-    // https://en.wikipedia.org/wiki/Brainfuck#Hello_World!
-    let inp = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.";
-    println!("hello-world (wikipedia.org) - interp");
-    run_interp(inp);
-    println!("hello-world (wikipedia.org) - jit");
-    run_jit(inp);
-
-    // https://programmingwiki.de/Brainfuck
-    let inp = ">+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-]>++++++++[<++++>-] <.>+++++++++++[<++++++++>-]<-.--------.+++.------.--------.[-]>++++++++[<++++>- ]<+.[-]++++++++++.";
-    println!("hello-world (programmingwiki.de) - interp");
-    run_interp(inp);
-    println!("hello-world (programmingwiki.de) - jit");
-    run_jit(inp);
-}
-
\ No newline at end of file -- cgit v1.2.3