boppi/test.boppi.iloc

533 lines
35 KiB
Plaintext

fst_ptr <- 0
slot1 <- 4
header <- 8
off_oref <- -8
off_osize <- -4
off_next <- 0
off_size <- 4
// memlib - simple memory allocator for ILOC
//
// This library maintains a single-linked list (of monotonically increasing addresses) of free
// slots in memory and a reference count for occupied slots. Each slot contains a tuple `(next
// free slot address,size)` followed by `size` free bytes. The memory is initiliased with a
// pointer to the first free slot at `#fst_ptr` and one free slot at `#slot1` of size
// `brk-slot1-header`. When a piece of memory is requested for allocation, a tuple
// `(reference count, size)` followed by `size` bytes for the object is formed. The calling
// convention of the functions in this library consists of pushing the return address followed by
// any arguments (in order) to the stack. Any return values will be pushed to the stack likewise.
//
// Requires a register `brk` for the highest address available for heap allocation.
// Requires an instruction `halt` when memory runs out
//
// @author Frank Wibbelink
// initialise
memlib_: loadI 0 => m_0
loadI @slot1 => m_1
subI brk,@slot1 => m_2
subI m_2,@header => m_2
storeAI m_1 => m_0,@fst_ptr // pointer to first slot
storeAI m_0 => m_1,@off_next // next slot is null
storeAI m_2 => m_1,@off_size // first slot size
jumpI -> ememlib_
// allocate memory
// searches through the free slots for either a slot size of ~~exactly #4+8 or a size of~~ at
// least #4+16
// stack: [return address, object size] -> [object address]
memalloc: loadI 0 => m_0
pop => m_s // load size
loadI @fst_ptr => m_p // load previous address (base pointer)
loadAI m_p,@off_next => m_c // load current address (first slot)
ma_loop: cmp_EQ m_0,m_c => m_1 // check if address pointer is null
cbr m_1 -> ma_null,ma_cont // if null, go to end and return null pointer
ma_cont: loadAI m_c,@off_size => m_1 // load slot size
cmp_EQ m_1,m_s => m_2 // check if request fits exactly
cbr m_2 -> ma_yxct,ma_nxct
ma_nxct: subI m_1,@header => m_1 // subtract free slot size
cmp_GE m_1,m_s => m_1 // check if request fits
cbr m_1 -> ma_found,ma_next
ma_next: i2i m_c => m_p
loadAI m_p,@off_next => m_c
jumpI -> ma_loop
ma_yxct: loadAI m_c,@off_next => m_n // location of next free slot
jumpI -> ma_final
ma_found: addI m_s,@header => m_1
add m_1,m_c => m_n // location of new free slot
loadAI m_c,@off_size => m_1
subI m_1,@header => m_1
sub m_1,m_s => m_1 // size of new free slot
storeAI m_1 => m_n,@off_size
loadAI m_c,@off_next => m_1 // location of next free slot
storeAI m_1 => m_n,@off_next
ma_final: storeAI m_n => m_p,@off_next // link previous free slot to new
addI m_c,@header => m_c // move to object location
loadI 1 => m_1
storeAI m_1 => m_c,@off_oref // set reference count to 1
storeAI m_s => m_c,@off_osize // set object size
ma_zerc: cbr m_s -> ma_zerl,ma_null // zero memory
ma_zerl: subI m_s,1 => m_s
cstoreAO m_0 => m_c,m_s
jumpI -> ma_zerc
ma_null: pop => m_1 // load return address
push m_c // store object address
jump -> m_1
// increase reference count of object
// stack: [return address, object address] -> []
memaddref: loadI 0 => m_0
pop => m_n // load object address
cmp_EQ m_0,m_n => m_1
cbr m_1 -> mr_ynul,mr_nnul // check if null pointer
mr_ynul: haltI 1865445997
mr_nnul: loadAI m_n,@off_oref => m_1
addI m_1,1 => m_1
storeAI m_1 => m_n,@off_oref
pop => m_1 // load return address
jump -> m_1
// decrease reference count of object
// frees memory if count goes to zero
// stack: [return address, object address] -> []
memfree: loadI 0 => m_0
pop => m_n // load object address
cmp_EQ m_0,m_n => m_1
cbr m_1 -> mf_ynul,mf_nnul // check if null pointer
mf_ynul: haltI 1865442925
mf_nnul: loadAI m_n,@off_oref => m_1
subI m_1,1 => m_1
cmp_GT m_1,m_0 => m_2
cbr m_2 -> mf_exit,mf_free
mf_exit: storeAI m_1 => m_n,@off_oref
pop => m_1 // load return address
jump -> m_1
mf_free: subI m_n,@header => m_n
loadI @fst_ptr => m_p
loadAI m_p,@off_next => m_c
mf_loop: cmp_EQ m_0,m_c => m_1 // loop until the surrounding free blocks are found
cbr m_1 -> mf_halt,mf_cont // check if address pointer is null
mf_halt: haltI 1882220141 // halt program; object beyond last free slot (or memory corrupted)
mf_cont: cmp_EQ m_c,m_n => m_1
cbr m_1 -> mf_hal2,mf_con2
mf_hal2: haltI 1717855853 // halt program; object is free slot
mf_con2: cmp_LE m_c,m_n => m_1
cbr m_1 -> mf_next,mf_done
mf_next: i2i m_c => m_p
loadAI m_p,@off_next => m_c
jumpI -> mf_loop
mf_done: loadAI m_p,@off_size => m_1
addI m_1,@header => m_1
add m_1,m_p => m_2
cmp_EQ m_2,m_n => m_2
cbr m_2 -> mf_yprv,mf_nprv
mf_yprv: loadAI m_n,@off_size => m_2 // merge with previous free slot
add m_1,m_2 => m_1 // new size of previous free slot
storeAI m_1 => m_p,@off_size
i2i m_p => m_n
jumpI -> mf_dprv
mf_nprv: storeAI m_n => m_p,@off_next // link previous free slot with new
mf_dprv: loadAI m_n,@off_size => m_1
addI m_1,@header => m_1
add m_1,m_n => m_2
cmp_EQ m_2,m_c => m_2
cbr m_2 -> mf_ynxt,mf_nnxt
mf_ynxt: loadAI m_c,@off_size => m_2 // merge with next free slot
add m_1,m_2 => m_1 // new size of next free slot
storeAI m_1 => m_n,@off_size
loadAI m_c,@off_next => m_1
storeAI m_1 => m_n,@off_next // move link of next's next to new free slot
pop => m_1 // load return address
jump -> m_1
mf_nnxt: storeAI m_c => m_n,@off_next // link new free slot with next
pop => m_1 // load return address
jump -> m_1
// copy object to location
// stack: [return address, object address, destination] -> []
memcopy: loadI 0 => m_0
haltI 1835626101 // unimplemented
pop => m_1 // load return address
jump -> m_1
ememlib_: nop
// end of memlib
// stdlib - generic subroutines for ILOC
//
// This library contains a few common subroutines for Boppi.
//
// @author Frank Wibbelink
// initialise
stdlib_: jumpI -> estdlib_
// write a boolean to output
// stack: [return address, bool] -> []
stdbout: pop => m_1 // get boolean
loadI 0 => m_2 // load zero-length string
push m_2
cbr m_1 -> sbout_t,sbout_f
sbout_t: cout "true"
jumpI -> sbout_e
sbout_f: cout "false"
sbout_e: pop => m_1 // load return address
jump -> m_1
// write an array of characters (a string) to output
// stack: [return address, address] -> []
stdsout: pop => m_1 // get address
loadAI m_1,@off_osize => m_2 // get length
sout_lc: cbr m_2 -> sout_ll,sout_le // check if any character to push
sout_ll: subI m_2,1 => m_2 // iterate backward
cloadAO m_1,m_2 => m_c // get character
cpush m_c // push character
jumpI -> sout_lc // repeat
sout_le: loadAI m_1,@off_osize => m_2 // get length
push m_2 // push string length
cout "" // print string
pop => m_1 // get return address
jump -> m_1
// read a character from input
// stack: [return address] -> [char]
stdcin: cin "" // get line
pop => m_1 // get length
cbr m_1 -> scin_t,stdcin // repeat until at least one character
scin_t: cpop => m_2 // save character
scin_lc: subI m_1,1 => m_1 // decrement char count
cbr m_1 -> scin_ll,scin_le
scin_ll: cpop => m_0 // discard character
jumpI -> scin_lc // repeat
scin_le: loadI 0 => m_0 // reset zero register
pop => m_1 // get return address
cpush m_2 // push result character
jump -> m_1
// read an array of characters (a string) from input
// the memalloc label cannot be used, so address 28 is used instead
// stack: [return address] -> [address]
stdsin: cin "" // get line
pop => m_2 // get length
push m_2 // save length
loadI #ssin_a => m_1 // call malloc
push m_1 // call malloc
push m_2 // call malloc
loadI 28 => m_c // call malloc
jump -> m_c // call malloc
ssin_a: pop => m_1 // get array address
pop => m_2 // get length
i2i m_1 => m_n // load character iterator
ssin_c: cbr m_2 -> ssin_l,ssin_e // pop characters into the array
ssin_l: subI m_2,1 => m_2
cpop => m_c // pop character
cstore m_c => m_n // save character
addI m_n,1 => m_n // increment iterator
jumpI -> ssin_c
ssin_e: pop => m_2 // get return address
push m_1 // push array address
jump -> m_2
estdlib_: nop
// end of stdlib
loadI 0 => r_nul // initialise zero register
loadI 217 => r_arp // malloc
push r_arp // malloc
loadI 28 => r_arp // malloc
push r_arp // malloc
jumpI -> memalloc // malloc
pop => r_arp // malloc
addI r_arp,16 => r_arp // construct main AR
jumpI -> s0 // define f1 - jump over body
nop // define f1 - entry point
addI r_arp,0 => r_1 // add offset
load r_1 => r_1 // load address
storeAI r_1 => r_arp,-12 // define f1 - move result
loadAI r_arp,-8 => r_2 // load ref count
loadI 1 => r_1 // one
cmp_LE r_2,r_1 => r_2 // check more than one ref
cbr r_2 -> ycl1,ncl2 // remove vars if last reference
ycl1: nop // cleanup target
ncl2: nop // no cleanup target
loadAI r_arp,-8 => r_1 // define f1 - load return address
jump -> r_1 // define f1 - go to return address
s0: nop // define f1 - skip target
loadI 238 => r_1 // malloc
push r_1 // malloc
loadI 12 => r_1 // malloc
push r_1 // malloc
jumpI -> memalloc // malloc
pop => r_1 // malloc
loadI 220 => r_2 // define f1 - load target address
storeAI r_2 => r_1,0 // define f1 - set target address
storeAI r_arp => r_1,4 // define f1 - copy ARP
loadI 20 => r_2 // define f1 - load AR size
storeAI r_2 => r_1,8 // define f1 - set AR size
storeAI r_1 => r_arp,4 // define f1 - set function reference
i2i r_arp => ART // AR incRef
cmp_NE ART,r_nul => r_1 // AR incRef
cbr r_1 -> aril3,arid4 // AR incRef
aril3: loadI 253 => r_1 // AR incRef
push r_1 // AR incRef
subI ART,16 => r_1 // AR incRef
push r_1 // AR incRef
jumpI -> memaddref // AR incRef
loadAI ART,-16 => ART // AR incRef
cmp_NE ART,r_nul => r_1 // AR incRef
cbr r_1 -> aril3,arid4 // AR incRef
arid4: nop // AR incRef
loadI 0 => r_1 // false
cbr r_1 -> if_t5,if_e7 //
if_t5: nop //
addI r_arp,4 => r_1 // add offset
load r_1 => r_1 // load address
loadI 266 => r_3 // memaddref
push r_3 // memaddref
push r_1 // memaddref
jumpI -> memaddref // memaddref
loadAI r_1,4 => r_2 // add new reference
i2i r_2 => ART // AR incRef
cmp_NE ART,r_nul => r_3 // AR incRef
cbr r_3 -> aril8,arid9 // AR incRef
aril8: loadI 275 => r_3 // AR incRef
push r_3 // AR incRef
subI ART,16 => r_3 // AR incRef
push r_3 // AR incRef
jumpI -> memaddref // AR incRef
loadAI ART,-16 => ART // AR incRef
cmp_NE ART,r_nul => r_3 // AR incRef
cbr r_3 -> aril8,arid9 // AR incRef
arid9: nop // AR incRef
addI r_arp,0 => r_2 // add offset
load r_2 => r_3 // load reference
cmp_EQ r_3,r_nul => r_4 // remove old reference
cbr r_4 -> ynul10,nnul11 // remove old reference
nnul11: nop // remove old reference
loadI 288 => r_4 // free
push r_4 // free
push r_3 // free
jumpI -> memfree // free
loadAI r_3,4 => r_3 // remove old reference
i2i r_3 => ART // AR decRef
cmp_NE ART,r_nul => r_4 // AR decRef
cbr r_4 -> ardl12,ardd13 // AR decRef
ardl12: loadI 297 => r_4 // AR decRef
push r_4 // AR decRef
subI ART,16 => r_4 // AR decRef
push r_4 // AR decRef
jumpI -> memfree // AR decRef
loadAI ART,-16 => ART // AR decRef
cmp_NE ART,r_nul => r_4 // AR decRef
cbr r_4 -> ardl12,ardd13 // AR decRef
ardd13: nop // AR decRef
ynul10: nop // remove old reference
store r_1 => r_2 // to f
load r_2 => r_3 // load reference
loadI 308 => r_5 // memaddref
push r_5 // memaddref
push r_3 // memaddref
jumpI -> memaddref // memaddref
loadAI r_3,4 => r_4 // add new reference
i2i r_4 => ART // AR incRef
cmp_NE ART,r_nul => r_5 // AR incRef
cbr r_5 -> aril14,arid15 // AR incRef
aril14: loadI 317 => r_5 // AR incRef
push r_5 // AR incRef
subI ART,16 => r_5 // AR incRef
push r_5 // AR incRef
jumpI -> memaddref // AR incRef
loadAI ART,-16 => ART // AR incRef
cmp_NE ART,r_nul => r_5 // AR incRef
cbr r_5 -> aril14,arid15 // AR incRef
arid15: nop // AR incRef
cmp_EQ r_1,r_nul => r_3 // remove old reference
cbr r_3 -> ynul16,nnul17 // remove old reference
nnul17: nop // remove old reference
loadI 328 => r_3 // free
push r_3 // free
push r_1 // free
jumpI -> memfree // free
loadAI r_1,4 => r_1 // remove old reference
i2i r_1 => ART // AR decRef
cmp_NE ART,r_nul => r_3 // AR decRef
cbr r_3 -> ardl18,ardd19 // AR decRef
ardl18: loadI 337 => r_3 // AR decRef
push r_3 // AR decRef
subI ART,16 => r_3 // AR decRef
push r_3 // AR decRef
jumpI -> memfree // AR decRef
loadAI ART,-16 => ART // AR decRef
cmp_NE ART,r_nul => r_3 // AR decRef
cbr r_3 -> ardl18,ardd19 // AR decRef
ardd19: nop // AR decRef
ynul16: nop // remove old reference
addI r_arp,0 => r_4 // add offset
load r_4 => r_4 // load address
loadI 348 => r_2 // memaddref
push r_2 // memaddref
push r_4 // memaddref
jumpI -> memaddref // memaddref
loadAI r_4,4 => r_3 // add new reference
i2i r_3 => ART // AR incRef
cmp_NE ART,r_nul => r_2 // AR incRef
cbr r_2 -> aril20,arid21 // AR incRef
aril20: loadI 357 => r_2 // AR incRef
push r_2 // AR incRef
subI ART,16 => r_2 // AR incRef
push r_2 // AR incRef
jumpI -> memaddref // AR incRef
loadAI ART,-16 => ART // AR incRef
cmp_NE ART,r_nul => r_2 // AR incRef
cbr r_2 -> aril20,arid21 // AR incRef
arid21: nop // AR incRef
addI r_arp,0 => r_2 // add offset
load r_2 => r_1 // load reference
cmp_EQ r_1,r_nul => r_3 // remove old reference
cbr r_3 -> ynul22,nnul23 // remove old reference
nnul23: nop // remove old reference
loadI 370 => r_3 // free
push r_3 // free
push r_1 // free
jumpI -> memfree // free
loadAI r_1,4 => r_1 // remove old reference
i2i r_1 => ART // AR decRef
cmp_NE ART,r_nul => r_3 // AR decRef
cbr r_3 -> ardl24,ardd25 // AR decRef
ardl24: loadI 379 => r_3 // AR decRef
push r_3 // AR decRef
subI ART,16 => r_3 // AR decRef
push r_3 // AR decRef
jumpI -> memfree // AR decRef
loadAI ART,-16 => ART // AR decRef
cmp_NE ART,r_nul => r_3 // AR decRef
cbr r_3 -> ardl24,ardd25 // AR decRef
ardd25: nop // AR decRef
ynul22: nop // remove old reference
store r_4 => r_2 // to f
load r_2 => r_3 // load reference
loadI 390 => r_5 // memaddref
push r_5 // memaddref
push r_3 // memaddref
jumpI -> memaddref // memaddref
loadAI r_3,4 => r_1 // add new reference
i2i r_1 => ART // AR incRef
cmp_NE ART,r_nul => r_5 // AR incRef
cbr r_5 -> aril26,arid27 // AR incRef
aril26: loadI 399 => r_5 // AR incRef
push r_5 // AR incRef
subI ART,16 => r_5 // AR incRef
push r_5 // AR incRef
jumpI -> memaddref // AR incRef
loadAI ART,-16 => ART // AR incRef
cmp_NE ART,r_nul => r_5 // AR incRef
cbr r_5 -> aril26,arid27 // AR incRef
arid27: nop // AR incRef
if_e7: nop // end target
loadI 409 => r_3 // malloc
push r_3 // malloc
loadI 8 => r_3 // malloc
push r_3 // malloc
jumpI -> memalloc // malloc
pop => r_3 // malloc
loadI 2 => r_2 // 2
storeAI r_2 => r_3,0 // store array element
loadI 2 => r_4 // 2
storeAI r_4 => r_3,4 // store array element
addI r_arp,8 => r_2 // add offset
load r_2 => r_1 // load reference
cmp_EQ r_1,r_nul => r_4 // remove old reference
cbr r_4 -> ynul28,nnul29 // remove old reference
nnul29: nop // remove old reference
loadI 423 => r_4 // free
push r_4 // free
push r_1 // free
jumpI -> memfree // free
ynul28: nop // remove old reference
store r_3 => r_2 // to arr
load r_2 => r_4 // load reference
loadI 430 => r_5 // memaddref
push r_5 // memaddref
push r_4 // memaddref
jumpI -> memaddref // memaddref
cmp_EQ r_3,r_nul => r_4 // remove old reference
cbr r_4 -> ynul30,nnul31 // remove old reference
nnul31: nop // remove old reference
loadI 437 => r_4 // free
push r_4 // free
push r_3 // free
jumpI -> memfree // free
ynul30: nop // remove old reference
addI r_arp,8 => r_2 // add offset
load r_2 => r_2 // get array object
loadI 0 => r_4 // 0
loadAI r_2,-4 => r_3 // check array index
divI r_3,4 => r_3 // check array index
cmp_LT r_4,r_3 => r_3 // check array index
cmp_GE r_4,r_nul => r_1 // check array index
and r_3,r_1 => r_1 // check array index
cbr r_1 -> nob33,oob32 // check array index
oob32: haltI 1634692962 // array index out of bounds
nob33: multI r_4,4 => r_4 // multiply index by size
add r_2,r_4 => r_2 // get array index address
load r_2 => r_2 // load address
addI r_arp,8 => r_1 // add offset
load r_1 => r_1 // get array object
loadI 1 => r_3 // 1
loadAI r_1,-4 => r_5 // check array index
divI r_5,4 => r_5 // check array index
cmp_LT r_3,r_5 => r_5 // check array index
cmp_GE r_3,r_nul => r_4 // check array index
and r_5,r_4 => r_4 // check array index
cbr r_4 -> nob35,oob34 // check array index
oob34: haltI 1634692962 // array index out of bounds
nob35: multI r_3,4 => r_3 // multiply index by size
add r_1,r_3 => r_1 // get array index address
load r_1 => r_1 // load address
add r_2,r_1 => r_2 // +
out "",r_2 //
loadAI r_arp,0 => r_1 // remove reference get var
cmp_EQ r_1,r_nul => r_3 // remove reference
cbr r_3 -> ynul36,nnul37 // remove reference
nnul37: nop // remove reference
loadI 474 => r_3 // free
push r_3 // free
push r_1 // free
jumpI -> memfree // free
loadAI r_1,4 => r_1 // remove reference
i2i r_1 => ART // AR decRef
cmp_NE ART,r_nul => r_3 // AR decRef
cbr r_3 -> ardl38,ardd39 // AR decRef
ardl38: loadI 483 => r_3 // AR decRef
push r_3 // AR decRef
subI ART,16 => r_3 // AR decRef
push r_3 // AR decRef
jumpI -> memfree // AR decRef
loadAI ART,-16 => ART // AR decRef
cmp_NE ART,r_nul => r_3 // AR decRef
cbr r_3 -> ardl38,ardd39 // AR decRef
ardd39: nop // AR decRef
ynul36: nop // remove reference
loadAI r_arp,4 => r_1 // remove reference get var
cmp_EQ r_1,r_nul => r_3 // remove reference
cbr r_3 -> ynul40,nnul41 // remove reference
nnul41: nop // remove reference
loadI 496 => r_3 // free
push r_3 // free
push r_1 // free
jumpI -> memfree // free
loadAI r_1,4 => r_1 // remove reference
i2i r_1 => ART // AR decRef
cmp_NE ART,r_nul => r_3 // AR decRef
cbr r_3 -> ardl42,ardd43 // AR decRef
ardl42: loadI 505 => r_3 // AR decRef
push r_3 // AR decRef
subI ART,16 => r_3 // AR decRef
push r_3 // AR decRef
jumpI -> memfree // AR decRef
loadAI ART,-16 => ART // AR decRef
cmp_NE ART,r_nul => r_3 // AR decRef
cbr r_3 -> ardl42,ardd43 // AR decRef
ardd43: nop // AR decRef
ynul40: nop // remove reference
loadAI r_arp,8 => r_1 // remove reference get var
cmp_EQ r_1,r_nul => r_3 // remove reference
cbr r_3 -> ynul44,nnul45 // remove reference
nnul45: nop // remove reference
loadI 518 => r_3 // free
push r_3 // free
push r_1 // free
jumpI -> memfree // free
ynul44: nop // remove reference
subI r_arp,16 => r_arp // deconstruct main AR
loadI 524 => r_2 // free
push r_2 // free
push r_arp // free
jumpI -> memfree // free