clean and work on labels

This commit is contained in:
Torsten Ruger 2014-04-21 17:27:05 +03:00
parent f0c0166d1f
commit ff38bde44e
7 changed files with 70 additions and 54 deletions

View File

@ -18,9 +18,15 @@ First instructions are in fact assembling correctly. Meaning i have tests, and i
Step 2 Step 2
------ ------
Package the code into an executable. Run that and verufy it's output. Package the code into an executable. Run that and verify it's output. But full elf support (including externs) is eluding me for now.
Currently hangin on the elf format. Still, this has proven to be a good review point for the arcitecture and means no libc for now.
Full rationale on the web (pages rep for now), but it means starting an extra step
Step 2.1
--------
Start implementing syscalls and the functionality we actually need from c (basic io only really)
Step 3 Step 3
------- -------

View File

@ -1,4 +1,7 @@
class Asm::Arm::AddrTableObject module Asm
module Arm
class AddrTableObject
def initialize def initialize
@table = [] @table = []
@const = [] @const = []
@ -31,4 +34,6 @@ class Asm::Arm::AddrTableObject
io.write_uint32 const io.write_uint32 const
end end
end end
end
end
end end

View File

@ -1,5 +1,5 @@
require 'asm/assembler' require 'asm/assembler'
require "asm/arm/addr_table_object"
module Asm module Asm
module Arm module Arm

View File

@ -29,12 +29,12 @@ module Asm
# Build representation for target address # Build representation for target address
def build_operand(arg) def build_operand(arg)
#str / ldr are _seruous instructions. With BIG possibilities no half are implemented #str / ldr are _seruous instructions. With BIG possibilities no half are implemented
if (arg.is_a?(Asm::RegisterArgNode))
@i = 0 @i = 0
@pre_post_index = 0 @pre_post_index = 0
@w = 0 @w = 0
@rn = reg_ref(arg)
@operand = 0 @operand = 0
if (arg.is_a?(Asm::RegisterArgNode))
@rn = reg_ref(arg)
if (false ) #argr.op and argr.right.is_a?(Asm::NumLiteralArgNode)) if (false ) #argr.op and argr.right.is_a?(Asm::NumLiteralArgNode))
@ -55,17 +55,13 @@ module Asm
else else
# raise Asm::AssemblyError.new(Asm::ERRSTR_INVALID_ARG, arg) # raise Asm::AssemblyError.new(Asm::ERRSTR_INVALID_ARG, arg)
end end
elsif (arg.is_a?(Asm::LabelEquivAddrArgNode) or arg.is_a?(Asm::NumEquivAddrArgNode)) elsif (arg.is_a?(Asm::LabelRefArgNode) or arg.is_a?(Asm::NumEquivAddrArgNode))
@i = 0
@pre_post_index = 1 @pre_post_index = 1
@w = 0
@rn = 15 # pc @rn = 15 # pc
@operand = 0
@use_addrtable_reloc = true @use_addrtable_reloc = true
@addrtable_reloc_target = arg @addrtable_reloc_target = arg
else else
puts "Invalid #{arg.inspect}" raise Asm::AssemblyError.new(Asm::ERRSTR_INVALID_ARG + " " + arg.inspect, arg.inspect)
raise Asm::AssemblyError.new(Asm::ERRSTR_INVALID_ARG, arg.inspect)
end end
end end
@ -81,7 +77,7 @@ module Asm
(pre_post_index << 12+4+4+1+1+1+1) | (i << 12+4+4+1+1+1+1+1) | (pre_post_index << 12+4+4+1+1+1+1) | (i << 12+4+4+1+1+1+1+1) |
(inst_class << 12+4+4+1+1+1+1+1+1) | (cond << 12+4+4+1+1+1+1+1+1+2) (inst_class << 12+4+4+1+1+1+1+1+1) | (cond << 12+4+4+1+1+1+1+1+1+2)
if (@use_addrtable_reloc) if (@use_addrtable_reloc)
closest_addrtable = Asm::Arm.closest_addrtable(as) # closest_addrtable = Asm::Arm.closest_addrtable(as)
if (@addrtable_reloc_target.is_a?(Asm::LabelEquivAddrArgNode)) if (@addrtable_reloc_target.is_a?(Asm::LabelEquivAddrArgNode))
obj = ast_asm.object_for_label(@addrtable_reloc_target.label, inst) obj = ast_asm.object_for_label(@addrtable_reloc_target.label, inst)
ref_label = closest_addrtable.add_label(obj) ref_label = closest_addrtable.add_label(obj)

View File

@ -17,7 +17,9 @@ module Asm
end end
def add_relocation(*args) def add_relocation(*args)
@relocations << Asm::Relocation.new(*args) reloc = Asm::Relocation.new(*args)
raise "reloc #{reloc.inspect}"
@relocations << reloc
end end
def assemble(io) def assemble(io)
@ -27,6 +29,7 @@ module Asm
@relocations.delete_if do |reloc| @relocations.delete_if do |reloc|
io.seek reloc.position io.seek reloc.position
puts "reloc #{reloc.inspect}"
if (reloc.label.extern?) if (reloc.label.extern?)
reloc.handler.call(io, io.tell, reloc.type) reloc.handler.call(io, io.tell, reloc.type)
else else

View File

@ -8,18 +8,25 @@ class TestExtern < MiniTest::Test
@generator = Asm::Arm::CodeGenerator.new @generator = Asm::Arm::CodeGenerator.new
end end
def test_generate_small def test_extern
@generator.instance_eval { @generator.instance_eval {
ldr r0, "hello world" #1 push lr
bl :printf #2 ldr r0, "hello world".to_sym
mov r7, 1 #3 mov r7, 4 #4 is write
swi 0 #4 4 instruction x 4 == 16 swi 0
pop pc
mov r7, 1 #1 == exit
swi 0
} }
write(7 , 'label')
end
#helper to write the file
def write len ,name
writer = Asm::ObjectWriter.new(Elf::Constants::TARGET_ARM) writer = Asm::ObjectWriter.new(Elf::Constants::TARGET_ARM)
assembly = @generator.assemble assembly = @generator.assemble
assert_equal 20 , assembly.length assert_equal len * 4 , assembly.length
writer.set_text assembly writer.set_text assembly
writer.save('small_test.o') writer.save("#{name}_test.o")
end end
end end

View File

@ -15,8 +15,7 @@ class TestSmallProg < MiniTest::Test
def test_generate_small def test_generate_small
@generator.instance_eval { @generator.instance_eval {
mov r0, 5 #1 mov r0, 5 #1
loop_start = label loop_start = label!
loop_start.set!
subs r0, r0, 1 #2 subs r0, r0, 1 #2
bne loop_start #3 bne loop_start #3
mov r7, 1 #4 mov r7, 1 #4
@ -48,6 +47,6 @@ class TestSmallProg < MiniTest::Test
assembly = @generator.assemble assembly = @generator.assemble
assert_equal len * 4 , assembly.length assert_equal len * 4 , assembly.length
writer.set_text assembly writer.set_text assembly
writer.save('#{name}_test.o') writer.save("#{name}_test.o")
end end
end end