Skip to content

Instantly share code, notes, and snippets.

@ClarkeRemy
Created October 30, 2022 15:10
Show Gist options
  • Save ClarkeRemy/202248bd57063f86bd03f6f321167ddd to your computer and use it in GitHub Desktop.
Save ClarkeRemy/202248bd57063f86bd03f6f321167ddd to your computer and use it in GitHub Desktop.
unfinished fib vm
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