Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
executable file 187 lines (151 sloc) 3.96 KB
#!/usr/bin/env ruby
require './common'
class BFCore
def initialize(g)
@g = g
end
def gen_prologue(data)
g = @g
g.comment('interpreter check')
# Test for cell wrap != 256
g.emit '>[-]<[-]++++++++[>++++++++<-]>[<++++>-]<[>>'
# Print message 'Sorry this program needs an 8bit interpreter\n'
g.emit '>++++[<++++>-]<+[>++++++>+++++++>++>+++>+++++<<<<<-]>>>>>--.<<<-'
g.emit '-------.+++..+++++++.>--.<-----.<++.+.>-.>.<---.++.---.<--.>+++.'
g.emit '<------.>-----.>.<+.<++++..-.>+++++.>.<<---.>-----.>.>+++++.<<<+'
g.emit '.>-----.+++++++++++.>.<<+++++++.+++++.>.<---------.>--.--.++.<.>'
g.emit '++.<.>--.<<++++++++++.'
# endif
g.emit '<<[-]]'
# Test for cell wrap != 256 and flip condition
g.emit '>[-]<[-]++++++++[>++++++++<-]>[<++++>-]+<[>-<[-]]>[-<'
g.comment('init data')
data.each do |d, i|
raise if i > 65535
hi = i / 256
lo = i % 256
ptr = MEM + MEM_BLK_LEN * hi + MEM_CTL_LEN + lo * (BITS / 8)
g.add_word(ptr, d)
end
g.comment('prologue')
g.add(RUNNING, 1)
g.emit '['
#g.emit '@'
end
def gen_core
g = @g
gen_mem_load
gen_mem_store
g.move_word(NPC, PC)
end
def gen_mem_load
g = @g
g.comment 'memory (load)'
g.decloop(LOAD_REQ) {
g.move_ptr(MEM)
g.set_ptr(0)
if $bfs24
g.decloop(MEM_A-1) {
g.move_word(MEM_A, MEM_A + MEM_BLK_LEN*256)
g.move_ptr(MEM_A + MEM_BLK_LEN*256)
g.set_ptr(MEM_A)
g.add(MEM_USE+1, 1)
}
end
g.decloop(MEM_A) {
g.move_word(MEM_A, MEM_A + MEM_BLK_LEN)
g.move_ptr(MEM_A + MEM_BLK_LEN)
g.set_ptr(MEM_A)
g.add(MEM_USE, 1)
}
256.times{|al|
g.move_ptr(MEM_A + 1)
g.ifzero(1) do
g.copy_word(MEM_CTL_LEN + al * (BITS / 8), MEM_V, MEM_WRK + 2)
end
g.add(MEM_A + 1, -1)
}
g.clear(MEM_A + 1)
g.decloop(MEM_USE) {
g.move_word(MEM_V, MEM_V - MEM_BLK_LEN)
g.move_ptr(MEM_V - MEM_BLK_LEN)
g.set_ptr(MEM_V)
}
if $bfs24
g.decloop(MEM_USE+1) {
g.move_word(MEM_V, MEM_V - MEM_BLK_LEN*256)
g.move_ptr(MEM_V - MEM_BLK_LEN*256)
g.set_ptr(MEM_V)
}
end
g.move_ptr(0)
g.set_ptr(MEM)
g.clear_word(A)
g.move_word(MEM + MEM_V, A)
}
end
def gen_mem_store
g = @g
g.comment 'memory (store)'
g.decloop(STORE_REQ) {
g.move_ptr(MEM)
g.set_ptr(0)
if $bfs24
g.decloop(MEM_A-1) {
g.move_word(MEM_V, MEM_V + MEM_BLK_LEN*256)
g.move_word(MEM_A, MEM_A + MEM_BLK_LEN*256)
g.move_ptr(MEM_A + MEM_BLK_LEN*256)
g.set_ptr(MEM_A)
g.add(MEM_USE+1, 1)
}
end
g.decloop(MEM_A) {
g.move_word(MEM_V, MEM_V + MEM_BLK_LEN)
g.move_word(MEM_A, MEM_A + MEM_BLK_LEN)
g.move_ptr(MEM_A + MEM_BLK_LEN)
g.set_ptr(MEM_A)
g.add(MEM_USE, 1)
}
# VH VL 0 AL 1
256.times{|al|
g.move_ptr(MEM_A + 1)
g.ifzero(1) do
g.clear_word(MEM_CTL_LEN + al * (BITS / 8))
g.move_word(MEM_V, MEM_CTL_LEN + al * (BITS / 8))
end
g.add(MEM_A + 1, -1)
}
g.clear(MEM_A + 1)
g.move_ptr(MEM_USE)
g.emit '[-' + '<' * MEM_BLK_LEN + ']'
if $bfs24
g.move_ptr(MEM_USE+1)
g.emit '[-' + '<' * (MEM_BLK_LEN*256) + ']'
end
g.move_ptr(0)
g.set_ptr(MEM)
}
end
def gen_epilogue
g = @g
g.comment('epilogue')
g.move_ptr(RUNNING)
g.emit ']'
# endif for cell size check. (should be [-]] but we already have a zero)
g.emit ']'
# EOL at EOF
g.comment('[...THE END...]')
end
end
if __FILE__ == $0
require './bfasm'
require './bfgen'
bfa = BFAsm.new
code, data = bfa.parse(File.read(ARGV[0]))
g = BFGen.new
bfc = BFCore.new(g)
bfc.gen_prologue(data)
bfa.emit(g)
bfc.gen_core
bfc.gen_epilogue
end