diff --git a/lib/asm/arm_assembler.rb b/lib/asm/arm_assembler.rb index db950a52..50cd2589 100644 --- a/lib/asm/arm_assembler.rb +++ b/lib/asm/arm_assembler.rb @@ -25,7 +25,7 @@ module Asm end attr_reader :values , :position - def instruction(name, *args) + def instruction(clazz,name, *args) opcode = name.to_s arg_nodes = [] @@ -43,28 +43,35 @@ module Asm end } - add_value Asm::Instruction.new(opcode , arg_nodes) + add_value clazz.new(opcode , arg_nodes) + end + + + def self.define_instruction(inst , clazz ) + define_method(inst) do |*args| + instruction clazz , inst.to_sym, *args + end + define_method(inst+'s') do |*args| + instruction clazz , (inst+'s').to_sym, *args + end + %w(al eq ne cs mi hi cc pl ls vc lt le ge gt vs).each do |cond_suffix| + define_method(inst+cond_suffix) do |*args| + instruction clazz , (inst+cond_suffix).to_sym, *args + end + define_method(inst+'s'+cond_suffix) do |*args| + instruction clazz , (inst+'s'+cond_suffix).to_sym, *args + end + end + end + + ["push", "pop"].each do |inst| + define_instruction(inst , StackInstruction) 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 - } - } - } + swi str strb ldr ldrb ).each do |inst| + define_instruction(inst , Instruction) + end def assemble_to_string #put the strings at the end of the assembled code. diff --git a/lib/asm/instruction.rb b/lib/asm/instruction.rb index b29219fa..4016abac 100644 --- a/lib/asm/instruction.rb +++ b/lib/asm/instruction.rb @@ -2,7 +2,6 @@ require "asm/assembly_error" require "asm/instruction_tools" require "asm/normal_builder" require "asm/memory_access_builder" -require "asm/stack_builder" require "asm/label" module Asm @@ -14,7 +13,7 @@ module Asm def initialize(opcode , args) opcode = opcode.downcase - @cond = :al + @cond = 0b1011 if (opcode =~ /(#{COND_POSTFIXES})$/) @cond = $1.to_sym opcode = opcode[0..-3] @@ -78,18 +77,6 @@ module Asm builder.rd = reg_ref(args[0]) builder.build_operand args[1] builder.assemble io, as, self - when :push, :pop - # downward growing, decrement before memory access - # official ARM style stack as used by gas - if (opcode == :push) - builder = StackBuilder.new(1,0,1,0) - else - builder = StackBuilder.new(0,1,1,1) - end - builder.cond = COND_CODES[@cond] - builder.rn = 13 # sp - builder.build_operand args - builder.assemble io, as when :b, :bl arg = args[0] if arg.is_a? Label diff --git a/lib/asm/stack_builder.rb b/lib/asm/stack_builder.rb deleted file mode 100644 index ac3156bf..00000000 --- a/lib/asm/stack_builder.rb +++ /dev/null @@ -1,45 +0,0 @@ -module Asm - # ADDRESSING MODE 4 - class StackBuilder - include Asm::InstructionTools - - def initialize(pre_post, up_down, write, store_load) - @cond = 0b1110 - @inst_class = Asm::Instruction::OPC_STACK - @pre_post_index = 0 - @up_down = 0 - @s = 0 - @write_base = 0 - @store_load = 0 - @rn = 0 - @operand = 0 - @pre_post_index = pre_post - @up_down = up_down - @write_base = write - @store_load = store_load - end - attr_accessor :cond, :inst_class, :pre_post_index, :up_down, - :s, :write_base, :store_load, :rn, :operand - - # Build representation for source value - def build_operand(arg) - if (arg.is_a?(Array)) - @operand = 0 - arg.each do |reg | - reg = reg_ref(reg) - @operand |= (1 << reg) - end - else - raise Asm::AssemblyError.new("invalid operand argument #{arg.inspect}") - end - end - - def assemble(io, as) - val = operand | (rn << 16) | (store_load << 16+4) | - (write_base << 16+4+1) | (s << 16+4+1+1) | (up_down << 16+4+1+1+1) | - (pre_post_index << 16+4+1+1+1+1) | (inst_class << 16+4+1+1+1+1+2) | - (cond << 16+4+1+1+1+1+2+2) - io.write_uint32 val - end - end -end diff --git a/lib/asm/stack_instruction.rb b/lib/asm/stack_instruction.rb new file mode 100644 index 00000000..9533a99c --- /dev/null +++ b/lib/asm/stack_instruction.rb @@ -0,0 +1,65 @@ +require "asm/instruction" + +module Asm + # ADDRESSING MODE 4 + class StackInstruction < Instruction + include Asm::InstructionTools + + def initialize(opcode , args) + super(opcode,args) + @operand = 0 + @cond = 0b1110 + @inst_class = Asm::Instruction::OPC_STACK + @s = 0 + @rn = 0 + # downward growing, decrement before memory access + # official ARM style stack as used by gas + @write_base = 1 + if (opcode == :push) + @pre_post_index = 1 + @up_down = 0 + @store_load = 0 + else #pop + @pre_post_index = 0 + @up_down = 1 + @store_load = 1 + end + end + attr_accessor :cond, :inst_class, :pre_post_index, :up_down, + :s, :write_base, :store_load, :rn, :operand + + def assemble(io, as) + cond = @cond.is_a?(Symbol) ? COND_CODES[@cond] : @cond + rn = 13 # sp + build_operand args + + #assemble of old + val = @operand + val |= (rn << 16) + val |= (store_load << 16+4) #20 + val |= (write_base << 16+4+ 1) + val |= (s << 16+4+ 1+1) + val |= (up_down << 16+4+ 1+1+1) + val |= (pre_post_index << 16+4+ 1+1+1+1)#24 + val |= (inst_class << 16+4+ 1+1+1+1 +2) + val |= (cond << 16+4+ 1+1+1+1 +2+2) + puts "#{self.inspect}" + io.write_uint32 val + end + + private + # Build representation for source value + def build_operand(arg) + if (arg.is_a?(Array)) + @operand = 0 + arg.each do |reg | + reg = reg_ref(reg) + @operand |= (1 << reg) + end + else + raise Asm::AssemblyError.new("invalid operand argument #{arg.inspect}") + end + end + + end +end diff --git a/lib/crystal.rb b/lib/crystal.rb index e604a2b1..f792f601 100644 --- a/lib/crystal.rb +++ b/lib/crystal.rb @@ -1,2 +1,3 @@ +require "asm/stack_instruction" require "asm/arm_assembler" require "elf/object_writer"