Created
October 30, 2022 15:10
-
-
Save ClarkeRemy/202248bd57063f86bd03f6f321167ddd to your computer and use it in GitHub Desktop.
unfinished fib vm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
fn fib (input:usize)->usize{ | |
const KIBI : usize = {let (mut x, mut times) = (2,0); loop{if times == 10 {break x} times+=1; x*=2}}; | |
const MEBI : usize = KIBI*KIBI; | |
const WORD_SIZE : usize = core::mem::size_of::<usize>(); | |
const TRUE : usize = true as usize; | |
const FALSE : usize = false as usize; | |
const INST_REG : usize = 7; | |
const STACK_REG : usize = 6; | |
static mut INST: [u8; KIBI] = [0;KIBI]; | |
static mut STACK : [u8; MEBI] = [0;MEBI]; | |
static mut REG : [usize; 8] = [0;8]; | |
fn next()->usize{unsafe{let x = INST[REG[INST_REG]] as usize; REG[INST_REG]-=1; x}} | |
fn what_regs()->[usize;2]{ | |
let r1 = next(); | |
let r2 = next(); | |
[r1,r2] | |
} | |
fn cmp(){unsafe{ | |
// CMP reg[usize] reg[usize] (3 bytes) | |
let [r1,r2] = what_regs(); | |
REG[r1] = (REG[r1] == REG[r2]) as usize; | |
}} | |
fn add(){unsafe{ | |
// ADD reg[usize] reg[usize] (3 bytes) | |
let [r1,r2] = what_regs(); | |
REG[r1] = REG[r1].wrapping_add(REG[r2]); | |
}} | |
fn dec(){unsafe{/* NOT reg[usize] (2 bytes) */ let r = next(); REG[r]= !REG[r]}} | |
fn xor(){unsafe{ | |
// ADD reg[usize] reg[usize] (3 bytes) | |
let [r1,r2] = what_regs(); | |
REG[r1] = REG[r1] ^ REG[r2]; | |
}} | |
fn jmpz(){unsafe{ | |
// JMPZ reg[bool] reg[inst_addr] (3 bytes) // jump if zero | |
let [r1,r2] = what_regs(); | |
if REG[r1] != 0 {return;} | |
REG[INST_REG]=REG[r2]; | |
}} | |
fn load(){unsafe{ | |
// LOAD reg[addr] (2 bytes) | |
let r = next(); | |
let mut tmp = 0_usize; | |
for _ in 0..WORD_SIZE { | |
tmp |= STACK[REG[r]] as usize; | |
tmp <<= 8; | |
REG[r]+=1; | |
} | |
REG[r]=tmp; | |
}} | |
fn store(){unsafe{ | |
// STORE reg[val] reg[stack_addr] (3 bytes) | |
let [r1, r2] = what_regs(); | |
const BYTE_MASK : usize = 0xff_usize; | |
let mut val = REG[r1]; | |
let mut addr = REG[r2]; | |
for _ in 0..WORD_SIZE { | |
STACK[addr] = (val & BYTE_MASK) as u8; | |
val >>= 8; | |
addr += 1; | |
} | |
}} | |
// fn swap(){unsafe{ | |
// // SWAP reg reg (3 bytes) | |
// let [r1,r2] = what_regs(); | |
// core::mem::swap(&mut REG[r1], &mut REG[r2]); | |
// }} | |
fn lit(){unsafe{ | |
// LIT reg val // pulls vall from the inst_stack (1+WORD_SIZE bytes) | |
let r = next(); | |
for _ in 0..WORD_SIZE { | |
REG[r] <<= 8; | |
REG[r] |= INST[INST_REG] as usize; | |
INST[INST_REG]-=1; | |
} | |
}} | |
fn copy(){unsafe{ | |
// COPY reg reg (3 bytes) // copies r1<-r2 | |
let [r1,r2] = what_regs(); | |
REG[r1]=REG[r2]; | |
}} | |
// byte code applays over usizes | |
// INST receiver giver | |
#[repr(u8)]enum I{ | |
END = 0, | |
CMP, // CMP reg[usize] reg[usize] (3 bytes) // 1 if equal (true) | |
ADD, // ADD reg[usize] reg[usize] (3 bytes) | |
NOT, // NOT reg[usize] (2 bytes) // decrement register | |
XOR, // XOR reg[usize] reg[usize] (3 bytes) | |
JMPZ, // JMPZ reg[bool] reg[inst_addr] (3 bytes) // jump if zero | |
LOAD, // LOAD reg[addr] (2 bytes) | |
STORE, // STORE reg[val] reg[stack_addr] (3 bytes) | |
// SWAP, // SWAP reg reg (3 bytes) | |
LIT, // LIT reg val // pulls vall from the inst_stack (1+WORD_SIZE bytes) | |
COPY, // COPY reg reg (3 bytes) | |
} | |
// call pushes inst_reg to stack | |
// CALL reg reg |inst [stack_reg inst_reg inst_addr]=>continuation | |
// ret pop inst_addr from stack, and move it to inst_reg | |
// RET reg reg |inst [stack_reg inst_reg] | |
unsafe{ | |
REG[0]=input; | |
REG[INST_REG]=KIBI-1; | |
} | |
#[cfg(target_pointer_width = "32")] macro_rules! word_size {() => {"%def WORD_SIZE 4"};} | |
#[cfg(target_pointer_width = "64")] macro_rules! word_size {() => {"%def WORD_SIZE 8"};} | |
let code = concat!(word_size!(), | |
" | |
%def R0 #0 ;; IO Reg | |
%def R1 #1 | |
%def F_PTR 4 ;; Function pointer | |
%def R_PTR 5 ;; Return|Args pointer | |
%def S_PTR 6 ;; Stack pointer | |
%def I_PTR 7 ;; Instruction pointer | |
%macro ZERO 1 | |
XOR %1 %1 | |
%endmacro | |
%macro GOTO 1 | |
LIT I_PTR %1 | |
%endmacro | |
%macro CALL 1 | |
LIT F_PTR %1 | |
GOTO @_CALL | |
%endmacro | |
%macro RET 0 | |
GOTO @_RET | |
%endmacro | |
%macro OFFSET_STORE %2 ;; tramples the R1 registers | |
LIT R1 %2 | |
ADD R1 S_PTR | |
STORE %1 R1 | |
%endmacro | |
FIB_GUARD: ;; this is likely unneeded | |
LIT S_PTR 1 ;; set start of stack | |
ZERO R1 | |
CMP R1 R0 | |
NOT R1 | |
JMPZ R1 @DONE | |
;; LIT R_PTR 0 | |
;; OFFSET_STORE R_PTR 0 ;; return value | |
OFFSET_STORE R0 WORD_SIZE | |
LIT R_PTR 1 | |
OFFSET_STORE R_PTR [WORD_SIZE * 2] | |
LIT R_PTR 0 | |
OFFSET_STORE R_PTR [WORD_SIZE * 3] | |
COPY R_PTR S_PTR | |
ADD S_PTR [WORD_SIZE * 4] | |
CALL @FIB | |
LIT R1 [WORD_SIZE * 4] | |
NOT R1 | |
LIT R2 1 | |
ADD R1 R2 | |
ADD S_PTR R1 | |
GOTO @DONE | |
;; the recursive stack will be like so | |
;;0n FIB_GUARD [ret0] ;; [F|R|S|I] | |
;;1n FIB_1 [ret_addr_0]:[ret1|(args 3)][INST_1] ;; S_PTR == 0 | |
;;2n FIB_2 [ret_addr_1]:[ret0|(args 3)][INST_2] ;; S_PTR == OFFSET | |
;; ... | |
;;xn FIB_FINAL [ret_addr_prev] | |
FIB: | |
LIT R1 1 ;; [0x08|0x01|0x00_00_00_00_00_00_00_01] example byte code | |
CMP R1 R0 | |
JMPZ R1 @ITER | |
GOTO @DONE | |
ITER: | |
;; move forward WORD_SIZE bytes to reserve space for the return value | |
ADD S_PTR WORD_SIZE | |
;; allocate args and return to stack | |
;; Args => answer_addr<-(countdown - 1, current + prev, current) | |
;; Increment S_PTR to FIB function offet | |
CALL @FIB | |
;; Decrement S_PTR to FIB original position | |
RET | |
_CALL: | |
STORE I_PTR S_PTR | |
COPY I_PTR F_PTR | |
_RET: | |
COPY R1 S_PTR | |
LOAD R1 | |
COPY I_PTR R1 | |
DONE: | |
END | |
"); | |
// fn fib_iter(countdown:usize, current:usize,prev:usize)->usize{ | |
// if countdown == 0 {return 0;} // instruction 1 DONE | |
// if countdown == 1 {return current} // instruction 2 | |
// fib_iter(countdown -1 , current + prev, current) // instruction 3 | |
// } | |
// fib_iter(input, 1, 0) | |
// return REG[0]; | |
return 0 | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment