lift label out of the code generator

This commit is contained in:
Torsten Ruger 2014-04-16 12:02:28 +03:00
parent e47b1dcadd
commit 5bd4be313c
2 changed files with 104 additions and 109 deletions

View File

@ -5,125 +5,102 @@ require 'asm/parser'
require 'stream_reader' require 'stream_reader'
require 'stringio' require 'stringio'
module Asm
module Arm
class CodeGenerator class Asm::Arm::CodeGenerator
def initialize def initialize
@asm = Asm::Assembler.new @asm = Asm::Assembler.new
@externs = [] @externs = []
end end
def data(str) def data(str)
@asm.add_object Asm::DataObject.new(str) @asm.add_object Asm::DataObject.new(str)
end end
%w(r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 %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 r13 r14 r15 a1 a2 a3 a4 v1 v2 v3 v4 v5 v6
rfp sl fp ip sp lr pc rfp sl fp ip sp lr pc
).each { |reg| ).each { |reg|
define_method(reg) { define_method(reg) {
[:reg, reg] [:reg, reg]
} }
} }
def instruction(name, *args) def instruction(name, *args)
node = Asm::Parser::InstructionNode.new node = Asm::InstructionNode.new
node.opcode = name.to_s node.opcode = name.to_s
node.args = [] node.args = []
args.each { |arg| args.each { |arg|
if (arg.is_a?(Array)) if (arg.is_a?(Array))
if (arg[0] == :reg) if (arg[0] == :reg)
node.args << Asm::Parser::RegisterArgNode.new { |n| node.args << Asm::RegisterArgNode.new { |n|
n.name = arg[1] n.name = arg[1]
}
end
elsif (arg.is_a?(Integer))
node.args << Asm::Parser::NumLiteralArgNode.new { |n|
n.value = arg
}
elsif (arg.is_a?(Symbol))
node.args << Asm::Parser::LabelRefArgNode.new { |n|
n.label = arg.to_s
}
elsif (arg.is_a?(GeneratorLabel) or arg.is_a?(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 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
} }
end
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
}
elsif (arg.is_a?(GeneratorLabel) or arg.is_a?(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 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
}
}
}
class GeneratorLabel < Asm::LabelObject def label
def initialize(asm) GeneratorLabel.new(@asm)
@asm = asm end
end
def set!
@asm.add_object self
end
end
class GeneratorExternLabel < Asm::LabelObject def label!
def initialize(name) lbl = GeneratorLabel.new(@asm)
@name = name lbl.set!
extern! lbl
end end
attr_reader :name
end
def label def extern(sym)
GeneratorLabel.new(@asm) if (lbl = @externs.find { |extern| extern.name == sym })
end lbl
else
def label! @externs << lbl = GeneratorExternLabel.new(sym)
lbl = GeneratorLabel.new(@asm) @asm.add_object lbl
lbl.set! lbl
lbl
end
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
def assemble
io = StringIO.new
@asm.assemble(io)
io.string
end
def relocations
@asm.relocations
end
end end
end end
end
def assemble
io = StringIO.new
@asm.assemble(io)
io.string
end
def relocations
@asm.relocations
end
end

View File

@ -0,0 +1,18 @@
require "asm/label_object"
class Asm::Arm::GeneratorLabel < Asm::LabelObject
def initialize(asm)
@asm = asm
end
def set!
@asm.add_object self
end
end
class Asm::Arm::GeneratorExternLabel < Asm::LabelObject
def initialize(name)
@name = name
extern!
end
attr_reader :name
end