Add support for binary generation.
This commit is contained in:
parent
99a47be826
commit
cc82894454
|
@ -131,7 +131,8 @@ module Chalk
|
||||||
call tree.name
|
call tree.name
|
||||||
|
|
||||||
# Reduce stack pointer
|
# Reduce stack pointer
|
||||||
op TokenType::OpSub, STACK_REG, start_at
|
load free, start_at
|
||||||
|
opr TokenType::OpSub, STACK_REG, free
|
||||||
# Move I to stack
|
# Move I to stack
|
||||||
setis
|
setis
|
||||||
# Get to correct stack position
|
# Get to correct stack position
|
||||||
|
|
|
@ -58,11 +58,15 @@ module Chalk
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private def run_intermediate
|
private def generate_ir
|
||||||
trees = create_trees(@config.file)
|
trees = create_trees(@config.file)
|
||||||
table = process_initial(trees)
|
table = process_initial(trees)
|
||||||
raise "No main function!" unless table["main"]?
|
raise "No main function!" unless table["main"]?
|
||||||
code = generate_code(trees, table)
|
return { table, generate_code(trees, table) }
|
||||||
|
end
|
||||||
|
|
||||||
|
private def run_intermediate
|
||||||
|
table, code = generate_ir
|
||||||
code.each do |name, insts|
|
code.each do |name, insts|
|
||||||
puts "Code for #{name}:"
|
puts "Code for #{name}:"
|
||||||
insts.each { |it| puts it }
|
insts.each { |it| puts it }
|
||||||
|
@ -70,7 +74,31 @@ module Chalk
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private def generate_binary(instructions)
|
||||||
|
end
|
||||||
|
|
||||||
private def run_binary
|
private def run_binary
|
||||||
|
all_instructions = [] of Instruction
|
||||||
|
table, code = generate_ir
|
||||||
|
all_instructions.concat code["main"]
|
||||||
|
table["main"]?.as(FunctionEntry).addr = 0
|
||||||
|
all_instructions << JumpRelativeInstruction.new 0
|
||||||
|
code.delete "main"
|
||||||
|
code.each do |key, value|
|
||||||
|
table[key]?.as(FunctionEntry).addr = all_instructions.size
|
||||||
|
all_instructions.concat(value)
|
||||||
|
all_instructions << ReturnInstruction.new
|
||||||
|
end
|
||||||
|
context = InstructionContext.new table, all_instructions.size
|
||||||
|
binary = all_instructions.map_with_index { |it, i| it.to_bin(context, i).to_u16 }
|
||||||
|
file = File.open("out.ch8", "w")
|
||||||
|
binary.each do |inst|
|
||||||
|
first = (inst >> 8).to_u8
|
||||||
|
file.write_byte(first)
|
||||||
|
second = (inst & 0xff).to_u8
|
||||||
|
file.write_byte(second)
|
||||||
|
end
|
||||||
|
file.close
|
||||||
end
|
end
|
||||||
|
|
||||||
def run
|
def run
|
||||||
|
|
113
src/chalk/ir.cr
113
src/chalk/ir.cr
|
@ -2,6 +2,17 @@ require "./lexer.cr"
|
||||||
|
|
||||||
module Chalk
|
module Chalk
|
||||||
class Instruction
|
class Instruction
|
||||||
|
def to_bin(i, index)
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class InstructionContext
|
||||||
|
property table : Table
|
||||||
|
property stack : Int32
|
||||||
|
|
||||||
|
def initialize(@table, @stack)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class LoadInstruction < Instruction
|
class LoadInstruction < Instruction
|
||||||
|
@ -16,6 +27,10 @@ module Chalk
|
||||||
@register.to_s(16, io)
|
@register.to_s(16, io)
|
||||||
io << " " << @value
|
io << " " << @value
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_bin(i, index)
|
||||||
|
0x6000 | (register << 8) | value
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class LoadRegInstruction < Instruction
|
class LoadRegInstruction < Instruction
|
||||||
|
@ -31,6 +46,10 @@ module Chalk
|
||||||
io << " R"
|
io << " R"
|
||||||
@from.to_s(16, io)
|
@from.to_s(16, io)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_bin(i, index)
|
||||||
|
0x8000 | (into << 8) | (from << 4)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class OpInstruction < Instruction
|
class OpInstruction < Instruction
|
||||||
|
@ -46,6 +65,15 @@ module Chalk
|
||||||
@into.to_s(16, io)
|
@into.to_s(16, io)
|
||||||
io << " " << @value
|
io << " " << @value
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_bin(i, index)
|
||||||
|
case op
|
||||||
|
when TokenType::OpAdd
|
||||||
|
return 0x7000 | (into << 8) | value
|
||||||
|
else
|
||||||
|
raise "Invalid instruction"
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class OpRegInstruction < Instruction
|
class OpRegInstruction < Instruction
|
||||||
|
@ -62,6 +90,25 @@ module Chalk
|
||||||
io << " R"
|
io << " R"
|
||||||
@from.to_s(16, io)
|
@from.to_s(16, io)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_bin(i, index)
|
||||||
|
code = 0
|
||||||
|
case op
|
||||||
|
when TokenType::OpAdd
|
||||||
|
code = 4
|
||||||
|
when TokenType::OpSub
|
||||||
|
code = 5
|
||||||
|
when TokenType::OpOr
|
||||||
|
code = 1
|
||||||
|
when TokenType::OpAnd
|
||||||
|
code = 2
|
||||||
|
when TokenType::OpXor
|
||||||
|
code = 3
|
||||||
|
else
|
||||||
|
raise "Invalid instruction"
|
||||||
|
end
|
||||||
|
return 0x8000 | (into << 8) | (from << 4) | code
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class StoreInstruction < Instruction
|
class StoreInstruction < Instruction
|
||||||
|
@ -74,6 +121,10 @@ module Chalk
|
||||||
io << "store R"
|
io << "store R"
|
||||||
@up_to.to_s(16, io)
|
@up_to.to_s(16, io)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_bin(i, index)
|
||||||
|
return 0xf055 | (up_to << 8)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class RestoreInstruction < Instruction
|
class RestoreInstruction < Instruction
|
||||||
|
@ -86,6 +137,10 @@ module Chalk
|
||||||
io << "restore R"
|
io << "restore R"
|
||||||
@up_to.to_s(16, io)
|
@up_to.to_s(16, io)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_bin(i, index)
|
||||||
|
return 0xf065 | (up_to << 8)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class ReturnInstruction < Instruction
|
class ReturnInstruction < Instruction
|
||||||
|
@ -95,20 +150,9 @@ module Chalk
|
||||||
def to_s(io)
|
def to_s(io)
|
||||||
io << "return"
|
io << "return"
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
class JumpEqInstruction < Instruction
|
def to_bin(i, index)
|
||||||
property offset : Int32
|
return 0x00ee
|
||||||
property left : Int32
|
|
||||||
property right : Int32
|
|
||||||
|
|
||||||
def initialize(@offset, @left, @right)
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_s(io)
|
|
||||||
io << "jeq " << offset << " R"
|
|
||||||
@left.to_s(16, io)
|
|
||||||
io << " " << right
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -121,6 +165,10 @@ module Chalk
|
||||||
def to_s(io)
|
def to_s(io)
|
||||||
io << "jr " << @offset
|
io << "jr " << @offset
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_bin(i, index)
|
||||||
|
return 0x1000 | ((offset + index) * 2 + 0x200)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class SkipEqInstruction < Instruction
|
class SkipEqInstruction < Instruction
|
||||||
|
@ -135,6 +183,10 @@ module Chalk
|
||||||
@left.to_s(16, io)
|
@left.to_s(16, io)
|
||||||
io << " " << right
|
io << " " << right
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_bin(i, index)
|
||||||
|
return 0x3000 | (left << 8) | right
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class SkipNeInstruction < Instruction
|
class SkipNeInstruction < Instruction
|
||||||
|
@ -149,6 +201,10 @@ module Chalk
|
||||||
@left.to_s(16, io)
|
@left.to_s(16, io)
|
||||||
io << " " << right
|
io << " " << right
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_bin(i, index)
|
||||||
|
return 0x4000 | (left << 8) | right
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class SkipRegEqInstruction < Instruction
|
class SkipRegEqInstruction < Instruction
|
||||||
|
@ -164,6 +220,10 @@ module Chalk
|
||||||
io << " R"
|
io << " R"
|
||||||
@right.to_s(16, io)
|
@right.to_s(16, io)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_bin(i, index)
|
||||||
|
return 0x5000 | (left << 8) | (right << 4)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class SkipRegNeInstruction < Instruction
|
class SkipRegNeInstruction < Instruction
|
||||||
|
@ -179,6 +239,10 @@ module Chalk
|
||||||
io << " R"
|
io << " R"
|
||||||
@right.to_s(16, io)
|
@right.to_s(16, io)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_bin(i, index)
|
||||||
|
return 0x9000 | (left << 8) | (right << 4)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class CallInstruction < Instruction
|
class CallInstruction < Instruction
|
||||||
|
@ -190,23 +254,20 @@ module Chalk
|
||||||
def to_s(io)
|
def to_s(io)
|
||||||
io << "call " << @name
|
io << "call " << @name
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_bin(i, index)
|
||||||
|
return 0x2000 | (i.table[name]?.as(FunctionEntry).addr * 2 + 0x200)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class SetIInstruction < Instruction
|
|
||||||
property value : Int32
|
|
||||||
|
|
||||||
def initialize(@value)
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_s(io)
|
|
||||||
io << "seti " << @value
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class SetIStackInstruction < Instruction
|
class SetIStackInstruction < Instruction
|
||||||
def to_s(io)
|
def to_s(io)
|
||||||
io << "setis"
|
io << "setis"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_bin(i, index)
|
||||||
|
return 0xa000 | (i.stack * 2 + 0x200)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class AddIRegInstruction < Instruction
|
class AddIRegInstruction < Instruction
|
||||||
|
@ -219,5 +280,9 @@ module Chalk
|
||||||
io << "addi R"
|
io << "addi R"
|
||||||
reg.to_s(16, io)
|
reg.to_s(16, io)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_bin(i, index)
|
||||||
|
return 0xf000 | (reg << 8) | 0x1e
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue
Block a user