rubyx/lib/asm/arm/code_generator.rb

107 lines
2.4 KiB
Ruby
Raw Normal View History

require 'asm/arm/arm_assembler'
require 'asm/arm/instruction'
2014-04-17 14:35:55 +02:00
require_relative 'generator_label'
require 'asm/nodes'
require 'stream_reader'
require 'stringio'
2014-04-16 11:02:28 +02:00
class Asm::Arm::CodeGenerator
def initialize
@asm = Asm::Assembler.new
@externs = []
end
2014-04-16 11:02:28 +02:00
def data(str)
@asm.add_object Asm::DataObject.new(str)
end
2014-04-16 11:02:28 +02:00
%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]
}
}
2014-04-16 11:02:28 +02:00
def instruction(name, *args)
node = Asm::InstructionNode.new
node.opcode = name.to_s
node.args = []
2014-04-16 11:02:28 +02:00
args.each { |arg|
if (arg.is_a?(Array))
if (arg[0] == :reg)
node.args << Asm::RegisterArgNode.new { |n|
n.name = arg[1]
}
end
2014-04-16 11:02:28 +02:00
elsif (arg.is_a?(Integer))
node.args << Asm::NumLiteralArgNode.new { |n|
n.value = arg
}
elsif (arg.is_a?(Symbol))
node.args << Asm::LabelRefArgNode.new { |n|
n.label = arg.to_s
}
2014-04-17 14:35:55 +02:00
elsif (arg.is_a?(Asm::Arm::GeneratorLabel) or arg.is_a?(Asm::Arm::GeneratorExternLabel))
2014-04-16 11:02:28 +02:00
node.args << arg
else
raise 'Invalid argument `%s\' for instruction' % arg.inspect
end
2014-04-16 11:02:28 +02:00
}
2014-04-16 11:02:28 +02:00
@asm.add_object Asm::Arm::Instruction.new(node)
end
2014-04-16 11:02:28 +02:00
%w(adc add and bic eor orr rsb rsc sbc sub mov mvn cmn cmp teq tst b bl bx swi strb
).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
}
}
}
2014-04-16 11:02:28 +02:00
def label
2014-04-17 14:35:55 +02:00
Asm::Arm::GeneratorLabel.new(@asm)
2014-04-16 11:02:28 +02:00
end
2014-04-16 11:02:28 +02:00
def label!
2014-04-17 14:35:55 +02:00
lbl = Asm::Arm::GeneratorLabel.new(@asm)
2014-04-16 11:02:28 +02:00
lbl.set!
lbl
end
2014-04-16 11:02:28 +02:00
def extern(sym)
if (lbl = @externs.find { |extern| extern.name == sym })
lbl
else
@externs << lbl = GeneratorExternLabel.new(sym)
@asm.add_object lbl
lbl
end
end
2014-04-16 11:02:28 +02:00
def assemble
io = StringIO.new
@asm.assemble(io)
io.string
end
def relocations
@asm.relocations
end
end