diff --git a/src/chalk/codegen.cr b/src/chalk/codegen.cr index d9c826a..53e8068 100644 --- a/src/chalk/codegen.cr +++ b/src/chalk/codegen.cr @@ -8,11 +8,6 @@ module Chalk class CodeGenerator include Emitter - # The register into which the return value of a function is stored. - RETURN_REG = 14 - # The register into which the "stack pointer" is stored. - STACK_REG = 13 - # Gets the instructions currently emitted by this code generator. getter instructions @@ -42,10 +37,7 @@ module Chalk # `#generate!` call. def generate!(tree, function : Trees::TreeFunction | Builtin::BuiltinFunction, table, target, free) start_at = free - # Move I to stack - setis - # Get to correct stack position - addi STACK_REG + to_stack # Store variables store (start_at - 1) unless start_at == 0 # Increment I and stack position @@ -67,10 +59,7 @@ module Chalk # Reduce stack pointer load free, start_at opr TokenType::OpSub, STACK_REG, free - # Move I to stack - setis - # Get to correct stack position - addi STACK_REG + to_stack # Restore restore (start_at - 1) unless start_at == 0 # Get call value into target diff --git a/src/chalk/compiler.cr b/src/chalk/compiler.cr index 602cd8b..a02f898 100644 --- a/src/chalk/compiler.cr +++ b/src/chalk/compiler.cr @@ -53,11 +53,11 @@ module Chalk end @logger.debug("Done creating symbol table") - table["draw"] = FunctionEntry.new Builtin::InlineDrawFunction.new table["get_key"] = FunctionEntry.new Builtin::InlineAwaitKeyFunction.new - table["get_font"] = FunctionEntry.new Builtin::InlineGetFontFunction.new table["set_delay"] = FunctionEntry.new Builtin::InlineSetDelayFunction.new table["get_delay"] = FunctionEntry.new Builtin::InlineGetDelayFunction.new + table["set_sound"] = FunctionEntry.new Builtin::InlineSetSoundFunction.new + table["draw_number"] = FunctionEntry.new Builtin::InlineDrawNumberFunction.new return table end diff --git a/src/chalk/emitter.cr b/src/chalk/emitter.cr index 1e96aea..5dd106d 100644 --- a/src/chalk/emitter.cr +++ b/src/chalk/emitter.cr @@ -1,8 +1,19 @@ module Chalk module Compiler + # The register into which the return value of a function is stored. + RETURN_REG = 14 + # The register into which the "stack pointer" is stored. + STACK_REG = 13 + # Module to emit instructions and store # them into an existing array. module Emitter + # Moves I to the next available value on the stack. + def to_stack + setis + addi STACK_REG + end + # Emits an instruction to load a *value* into a register, *into*. def load(into, value) inst = Ir::LoadInstruction.new into, value.to_i32 diff --git a/src/chalk/inline.cr b/src/chalk/inline.cr index 9a0b4d0..ce028cc 100644 --- a/src/chalk/inline.cr +++ b/src/chalk/inline.cr @@ -3,21 +3,6 @@ require "./type" module Chalk module Builtin - # Inline function to draw sprite at address I. - class InlineDrawFunction < InlineFunction - def generate!(emitter, params, table, target, free) - if !params[2].is_a?(Trees::TreeLit) - raise "Third parameter must be a constant." - end - emitter.generate! params[0], table, free, free + 1 - emitter.generate! params[1], table, free + 1, free + 2 - emitter.instructions << Ir::DrawInstruction.new free, free + 1, params[2].as(Trees::TreeLit).lit.to_i32 - end - def type - return Compiler::FunctionType.new([Compiler::Type::U8] * 3, Compiler::Type::U0) - end - end - # Inline function to await for a key and return it. class InlineAwaitKeyFunction < InlineFunction def generate!(emitter, params, table, target, free) @@ -28,17 +13,6 @@ module Chalk end end - # Inline function to get font for a given value. - class InlineGetFontFunction < InlineFunction - def generate!(emitter, params, table, target, free) - emitter.generate! params[0], table, free, free + 1 - emitter.instructions << Ir::GetFontInstruction.new free - end - def type - return Compiler::FunctionType.new([Compiler::Type::U8], Compiler::Type::U0) - end - end - # Inline function to set the delay timer. class InlineSetDelayFunction < InlineFunction def generate!(emitter, params, table, target, free) @@ -60,5 +34,52 @@ module Chalk return Compiler::FunctionType.new(([] of Compiler::Type), Compiler::Type::U8) end end + + # Function to set the sound timer. + class InlineSetSoundFunction < InlineFunction + def generate!(emitter, params, table, target, free) + emitter.generate! params[0], table, free, free + 1 + emitter.instructions << Ir::SetSoundTimerInstruction.new free + end + + def type + return Compiler::FunctionType.new([Compiler::Type::U8], Compiler::Type::U0) + end + end + + # Function to draw numbers. + class InlineDrawNumberFunction < InlineFunction + def generate!(emitter, params, table, target, free) + emitter.to_stack + # Save variables from R0-R2 + emitter.store 0x2 + emitter.load free, 0x3 + emitter.addi free + # Write BCD values to I + emitter.generate! params[0], table, free, free + 1 + emitter.instructions << Ir::BCDInstruction.new free + emitter.restore 0x2 + # Get the coordinates + free = 3 if free < 3 + emitter.generate! params[1], table, free, free + 1 + emitter.generate! params[2], table, free + 1, free + 2 + # Draw + emitter.instructions << Ir::GetFontInstruction.new 0x0 + emitter.instructions << Ir::DrawInstruction.new free, free + 1, 5 + emitter.op(Compiler::TokenType::OpAdd, free, 6) + emitter.instructions << Ir::GetFontInstruction.new 0x1 + emitter.instructions << Ir::DrawInstruction.new free, free + 1, 5 + emitter.op(Compiler::TokenType::OpAdd, free, 6) + emitter.instructions << Ir::GetFontInstruction.new 0x2 + emitter.instructions << Ir::DrawInstruction.new free, free + 1, 5 + # Load variables from RO-R2 back + emitter.to_stack + emitter.restore 0x2 + end + + def type + return Compiler::FunctionType.new([Compiler::Type::U8] * 3, Compiler::Type::U0) + end + end end end