diff --git a/lib/asm/arm/arm_assembler.rb b/lib/asm/arm/arm_assembler.rb index 0c635a37..de6eb412 100644 --- a/lib/asm/arm/arm_assembler.rb +++ b/lib/asm/arm/arm_assembler.rb @@ -1,8 +1,104 @@ require 'asm/assembler' require "asm/arm/addr_table_object" +require 'asm/arm/arm_assembler' +require 'asm/arm/instruction' +require 'asm/arm/generator_label' +require 'asm/nodes' +require 'stream_reader' +require 'stringio' +require "asm/data_object" + module Asm module Arm + class ArmAssembler < Asm::Assembler + + def add_data(str) + add_object Asm::DataObject.new(str) + end + + %w(r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 + r13 r14 r15 a1 a2 a3 a4 v1 v2 v3 v4 v5 v6 + rfp sl fp ip sp lr pc + ).each { |reg| + define_method(reg) { + [:reg, reg] + } + } + + def instruction(name, *args) + node = Asm::InstructionNode.new + node.opcode = name.to_s + node.args = [] + + args.each { |arg| + if (arg.is_a?(Array)) + if (arg[0] == :reg) + node.args << Asm::RegisterNode.new(arg[1]) + end + elsif (arg.is_a?(Integer)) + node.args << Asm::NumLiteralNode.new(arg) + elsif (arg.is_a?(Symbol)) + node.args << Asm::LabelRefNode.new(arg.to_s) + elsif (arg.is_a?(Asm::Arm::GeneratorLabel) or arg.is_a?(Asm::Arm::GeneratorExternLabel)) + node.args << arg + else + raise 'Invalid argument `%s\' for instruction' % arg.inspect + end + } + + add_object Asm::Arm::Instruction.new(node) + end + + %w(adc add and bic eor orr rsb rsc sbc sub mov mvn cmn cmp teq tst b bl bx + push pop swi str strb ldr ldrb + ).each { |inst| + define_method(inst) { |*args| + instruction inst.to_sym, *args + } + define_method(inst+'s') { |*args| + instruction (inst+'s').to_sym, *args + } + %w(al eq ne cs mi hi cc pl ls vc lt le ge gt vs + ).each { |cond_suffix| + define_method(inst+cond_suffix) { |*args| + instruction (inst+cond_suffix).to_sym, *args + } + define_method(inst+'s'+cond_suffix) { |*args| + instruction (inst+'s'+cond_suffix).to_sym, *args + } + } + } + + def label + Asm::Arm::GeneratorLabel.new(self) + end + + def label! + lbl = Asm::Arm::GeneratorLabel.new(self) + lbl.set! + lbl + end + + #externs dropped for now + def extern(sym) + if (lbl = @externs.find { |extern| extern.name == sym }) + lbl + else + @externs << lbl = Asm::Arm::GeneratorExternLabel.new(sym) + add_object lbl + lbl + end + end + + def assemble_to_string + io = StringIO.new + assemble(io) + io.string + end + + end + # Relocation constants # Note that in this assembler, a relocation simply means any # reference to a label that can only be determined at assembly time diff --git a/lib/asm/arm/code_generator.rb b/lib/asm/arm/code_generator.rb deleted file mode 100644 index 66ea9750..00000000 --- a/lib/asm/arm/code_generator.rb +++ /dev/null @@ -1,102 +0,0 @@ -require 'asm/arm/arm_assembler' -require 'asm/arm/instruction' -require_relative 'generator_label' -require 'asm/nodes' -require 'stream_reader' -require 'stringio' -require "asm/data_object" - -class Asm::Arm::CodeGenerator - def initialize - @asm = Asm::Assembler.new -# @externs = [] - end - - def data(str) - @asm.add_object Asm::DataObject.new(str) - end - - %w(r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 - r13 r14 r15 a1 a2 a3 a4 v1 v2 v3 v4 v5 v6 - rfp sl fp ip sp lr pc - ).each { |reg| - define_method(reg) { - [:reg, reg] - } - } - - def instruction(name, *args) - node = Asm::InstructionNode.new - node.opcode = name.to_s - node.args = [] - - args.each { |arg| - if (arg.is_a?(Array)) - if (arg[0] == :reg) - node.args << Asm::RegisterNode.new(arg[1]) - end - elsif (arg.is_a?(Integer)) - node.args << Asm::NumLiteralNode.new(arg) - elsif (arg.is_a?(Symbol)) - node.args << Asm::LabelRefNode.new(arg.to_s) - elsif (arg.is_a?(Asm::Arm::GeneratorLabel) or arg.is_a?(Asm::Arm::GeneratorExternLabel)) - node.args << arg - else - raise 'Invalid argument `%s\' for instruction' % arg.inspect - end - } - - @asm.add_object Asm::Arm::Instruction.new(node) - end - - %w(adc add and bic eor orr rsb rsc sbc sub mov mvn cmn cmp teq tst b bl bx - push pop swi str strb ldr ldrb - ).each { |inst| - define_method(inst) { |*args| - instruction inst.to_sym, *args - } - define_method(inst+'s') { |*args| - instruction (inst+'s').to_sym, *args - } - %w(al eq ne cs mi hi cc pl ls vc lt le ge gt vs - ).each { |cond_suffix| - define_method(inst+cond_suffix) { |*args| - instruction (inst+cond_suffix).to_sym, *args - } - define_method(inst+'s'+cond_suffix) { |*args| - instruction (inst+'s'+cond_suffix).to_sym, *args - } - } - } - - def label - Asm::Arm::GeneratorLabel.new(@asm) - end - - def label! - lbl = Asm::Arm::GeneratorLabel.new(@asm) - lbl.set! - lbl - end - - #externs dropped for now - def extern(sym) - if (lbl = @externs.find { |extern| extern.name == sym }) - lbl - else - @externs << lbl = Asm::Arm::GeneratorExternLabel.new(sym) - @asm.add_object lbl - lbl - end - end - - def assemble - io = StringIO.new - @asm.assemble(io) - io.string - end - - def relocations - @asm.relocations - end -end diff --git a/lib/asm/arm/instruction.rb b/lib/asm/arm/instruction.rb index b3d8d3cc..feecdea5 100644 --- a/lib/asm/arm/instruction.rb +++ b/lib/asm/arm/instruction.rb @@ -74,7 +74,7 @@ module Asm :vs => 0b0110 } - RelocHandler = Asm::Arm.method(:write_resolved_relocation) + RelocHandler = nil # Asm::Arm.method(:write_resolved_relocation) def assemble(io, as) s = @s ? 1 : 0 diff --git a/test/helper.rb b/test/helper.rb index a8fe5550..12e5a7c5 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -30,4 +30,4 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'test')) require 'crystal' require 'asm/object_writer' -require "asm/arm/code_generator" +require "asm/arm/arm_assembler" diff --git a/test/label_test.rb b/test/label_test.rb index a810d6e5..8f2bcc69 100644 --- a/test/label_test.rb +++ b/test/label_test.rb @@ -5,7 +5,7 @@ require_relative 'helper' class TestExtern < MiniTest::Test # need a code generator, for arm def setup - @generator = Asm::Arm::CodeGenerator.new + @generator = Asm::Arm::ArmAssembler.new end def test_extern @@ -24,7 +24,7 @@ class TestExtern < MiniTest::Test #helper to write the file def write len ,name writer = Asm::ObjectWriter.new(Elf::Constants::TARGET_ARM) - assembly = @generator.assemble + assembly = @generator.assemble_to_string assert_equal len * 4 , assembly.length writer.set_text assembly writer.save("#{name}_test.o") diff --git a/test/small_program_test.rb b/test/small_program_test.rb index d399854a..33479e4c 100644 --- a/test/small_program_test.rb +++ b/test/small_program_test.rb @@ -9,7 +9,7 @@ require_relative 'helper' class TestSmallProg < MiniTest::Test # need a code generator, for arm def setup - @generator = Asm::Arm::CodeGenerator.new + @generator = Asm::Arm::ArmAssembler.new end def test_generate_small @@ -45,7 +45,7 @@ class TestSmallProg < MiniTest::Test #helper to write the file def write len ,name writer = Asm::ObjectWriter.new(Elf::Constants::TARGET_ARM) - assembly = @generator.assemble + assembly = @generator.assemble_to_string assert_equal len * 4 , assembly.length writer.set_text assembly writer.save("#{name}_test.o") diff --git a/test/test_crystal.rb b/test/test_crystal.rb index 54f4cb0d..390ba77f 100644 --- a/test/test_crystal.rb +++ b/test/test_crystal.rb @@ -1,5 +1,5 @@ require_relative 'helper' -require "asm/arm/code_generator" +require "asm/arm/arm_assembler" # try to test that the generation of basic instructions works # one instruction at a time, reverse testing from objdump --demangle -Sfghxp @@ -9,7 +9,7 @@ require "asm/arm/code_generator" class TestArmAsm < MiniTest::Test # need a code generator, for arm def setup - @generator = Asm::Arm::CodeGenerator.new + @generator = Asm::Arm::ArmAssembler.new end # code is what the generator spits out, at least one instruction worth (.first) @@ -17,7 +17,7 @@ class TestArmAsm < MiniTest::Test # is reversed and in 4 bytes as ruby can only do 31 bits and so we can't test with just one int (?) def assert_code code , op , should assert_equal op , code.opcode - binary = @generator.assemble + binary = @generator.assemble_to_string assert_equal 4 , binary.length index = 0 binary.each_byte do |byte | diff --git a/unused/code_generator.rb b/unused/code_generator.rb index 04221581..25c516ba 100644 --- a/unused/code_generator.rb +++ b/unused/code_generator.rb @@ -1,7 +1,7 @@ require "asm/arm/code_generator" if (__FILE__ == $0) - gen = Asm::Arm::CodeGenerator.new + gen = Asm::Arm::ArmAssembler.new gen.instance_eval { mov r0, 5 @@ -13,10 +13,10 @@ if (__FILE__ == $0) swi 0 } - gen.data("printf"+ "\x00") + gen.add_data("printf"+ "\x00") require 'asm/object_writer' writer = Asm::ObjectWriter.new(Elf::Constants::TARGET_ARM) - writer.set_text gen.assemble + writer.set_text gen.assemble_to_string begin