diff --git a/lib/asm/arm/instruction.rb b/lib/asm/arm/instruction.rb index 938360e2..0080505a 100644 --- a/lib/asm/arm/instruction.rb +++ b/lib/asm/arm/instruction.rb @@ -31,7 +31,7 @@ module Asm @opcode = opcode.downcase.to_sym @args = args end - attr_reader :opcode, :args + attr_reader :opcode, :args , :position def affect_status @s @@ -55,7 +55,7 @@ module Asm builder.cond = COND_CODES[@cond] builder.rd = reg_ref(args[0]) builder.rn = reg_ref(args[1]) - builder.build_operand args[2] + builder.build_operand args[2] , self.position builder.assemble io, as when :cmn, :cmp, :teq, :tst builder = NormalBuilder.new(OPC_DATA_PROCESSING, OPCODES[opcode], 1) diff --git a/lib/asm/arm/normal_builder.rb b/lib/asm/arm/normal_builder.rb index d1a5f328..b75b0c49 100644 --- a/lib/asm/arm/normal_builder.rb +++ b/lib/asm/arm/normal_builder.rb @@ -43,7 +43,14 @@ module Asm end # Build representation for source value - def build_operand(arg) + def build_operand(arg , position = 0) + #position only needed for calculating relative addresses to data objects + #there is a design stink here which makes my head ache. But shanti shanti + if arg.is_a?(Asm::DataObject) + # do pc relative addressing with the difference to the instuction + # 8 is for the funny pipeline adjustment (ie oc pointing to fetch and not execute) + arg = Asm::NumLiteralNode.new( arg.position - position - 8 ) + end if (arg.is_a?(Asm::NumLiteralNode)) if (arg.value.fits_u8?) # no shifting needed @@ -82,10 +89,7 @@ module Asm end @operand = rm_ref | (shift_op << 4) | (shift_imm << 4+3) - elsif arg.is_a?(Asm::DataObject) - # do pc relative addressing with the difference to the instuction else - puts "#{self.inspect}" raise Asm::AssemblyError.new(Asm::ERRSTR_INVALID_ARG + " " + arg.inspect, arg) end end diff --git a/lib/asm/data_object.rb b/lib/asm/data_object.rb index c081b6ab..e9ff555c 100644 --- a/lib/asm/data_object.rb +++ b/lib/asm/data_object.rb @@ -4,6 +4,10 @@ module Asm @data = data end + def position + throw "Not set" unless @address + @address + end def at address @address = address end diff --git a/test/label_test.rb b/test/label_test.rb deleted file mode 100644 index 462772fd..00000000 --- a/test/label_test.rb +++ /dev/null @@ -1,42 +0,0 @@ -require_relative 'helper' - -#try to call an extern function - -class TestExtern < MiniTest::Test - # need a code generator, for arm - def setup - @generator = Asm::Arm::ArmAssembler.new - end - - def test_extern - hello = "Hello Raisa"+ "\n\x00" - @generator.instance_eval { - mov r7, 4 #4 == write - mov r0 , 1 #stdout - add r1 , pc , hello # address of "hello Raisa" - mov r2 , 12 # length of hello - swi 0 - mov r7, 1 #1 == exit - swi 0 - } - @generator.add_string(hello) - write(7 , 'label') - end - #helper to write the file - def write len ,name - writer = Asm::ObjectWriter.new(Elf::Constants::TARGET_ARM) - assembly = @generator.assemble_to_string - #assert_equal len * 4 , assembly.length - writer.set_text assembly - writer.save("#{name}_test.o") - end -end -# _start copied from dietc -# mov fp, #0 @ clear the frame pointer -# ldr a1, [sp] @ argc -# add a2, sp, #4 @ argv -# ldr ip, .L3 -# add a3, a2, a1, lsl #2 @ &argv[argc] -# add a3, a3, #4 @ envp -# str a3, [ip, #0] @ environ = envp -# bl main diff --git a/test/small_program_test.rb b/test/small_program_test.rb index 33479e4c..9ffcc79c 100644 --- a/test/small_program_test.rb +++ b/test/small_program_test.rb @@ -12,7 +12,7 @@ class TestSmallProg < MiniTest::Test @generator = Asm::Arm::ArmAssembler.new end - def test_generate_small + def test_loop @generator.instance_eval { mov r0, 5 #1 loop_start = label! @@ -21,9 +21,23 @@ class TestSmallProg < MiniTest::Test mov r7, 1 #4 swi 0 #5 5 instructions } - write( 5 , "small" ) + write( 5 , "loop" ) end - + + def test_hello + hello = "Hello Raisa"+ "\n\x00" + @generator.instance_eval { + mov r7, 4 # 4 == write + mov r0 , 1 # stdout + add r1 , pc , hello # address of "hello Raisa" + mov r2 , hello.length + swi 0 #software interupt, ie kernel syscall + mov r7, 1 # 1 == exit + swi 0 + } + write(7 , 'label') + end + #test dropped along with functionality, didn't work and not needed (yet?) TODO def no_test_extern @generator.instance_eval { @@ -51,3 +65,12 @@ class TestSmallProg < MiniTest::Test writer.save("#{name}_test.o") end end +# _start copied from dietc +# mov fp, #0 @ clear the frame pointer +# ldr a1, [sp] @ argc +# add a2, sp, #4 @ argv +# ldr ip, .L3 +# add a3, a2, a1, lsl #2 @ &argv[argc] +# add a3, a3, #4 @ envp +# str a3, [ip, #0] @ environ = envp +# bl main