diff --git a/lib/arm/instructions/logic_instruction.rb b/lib/arm/instructions/logic_instruction.rb index 0fe9d231..20fff7ef 100644 --- a/lib/arm/instructions/logic_instruction.rb +++ b/lib/arm/instructions/logic_instruction.rb @@ -91,10 +91,10 @@ module Arm if( @left.is_a?(Parfait::Object) or @left.is_a?(Risc::Label) or (@left.is_a?(Symbol) and !Risc::RiscValue.look_like_reg(@left))) left = @left - left = @left.address if left.is_a?(Risc::Label) # do pc relative addressing with the difference to the instuction # 8 is for the funny pipeline adjustment (ie pointing to fetch and not execute) - right = Risc::Position.get(left) - Risc::Position.get(self) - 8 + right = Risc::Position.get(left) - 8 + right -= Risc::Position.get(self).at if( (right < 0) && ((opcode == :add) || (opcode == :sub)) ) right *= -1 # this works as we never issue sub only add set_opcode :sub # so (as we can't change the sign permanently) we can change the opcode diff --git a/lib/parfait/binary_code.rb b/lib/parfait/binary_code.rb index 7eed8440..9ed41117 100644 --- a/lib/parfait/binary_code.rb +++ b/lib/parfait/binary_code.rb @@ -46,6 +46,11 @@ module Parfait end end + def ensure_next + extend_one unless @next + @next + end + def each_block( &block ) block.call( self ) @next.each_block( &block ) if @next diff --git a/lib/risc/position/instruction_listener.rb b/lib/risc/position/instruction_listener.rb index 4781b5c1..c783e146 100644 --- a/lib/risc/position/instruction_listener.rb +++ b/lib/risc/position/instruction_listener.rb @@ -39,9 +39,33 @@ module Risc end def position_changed(position) + fix_binary my_pos = Position.get(@instruction) my_pos.set(position.at + position.object.byte_length) end + + # check that the binary we use is the one where the current position falls + # if not move up and register/unregister (soon) + def fix_binary + return if Position.get(@instruction).at == -1 + count = 0 + org_pos = Position.get(@binary) + return if org_pos.at == -1 + while( !pos_in_binary) + @binary = @binary.ensure_next + count += 1 + raise "Positions messed #{Position.get(@instruction)}:#{org_pos}" + end + end + + def pos_in_binary + me = Position.get(@instruction) + bin = Position.get(@binary) + return false if me < bin + return false if me > (bin + @binary.padded_length) + return true + end + # initialize the dependency graph for instructions # # starting from the given instruction, create Positions diff --git a/lib/risc/position/position.rb b/lib/risc/position/position.rb index 9a9983fb..c25f5b85 100644 --- a/lib/risc/position/position.rb +++ b/lib/risc/position/position.rb @@ -73,6 +73,17 @@ module Risc offset = offset.at if offset.is_a?(Position) @at - offset end + + def <(right) + right = right.at if right.is_a?(Position) + @at < right + end + + def >(right) + right = right.at if right.is_a?(Position) + @at > right + end + def to_s "0x#{@at.to_s(16)}" end @@ -129,7 +140,7 @@ module Risc @reverse_cache.delete(position.at) unless position.object.is_a?(Label) testing = self.at( position.at ) unless position.at < 0 if testing and testing.object.class != position.object.class - raise "Mismatch (at #{pos.to_s(16)}) was:#{position} #{position.class} #{position.object} , should #{testing}#{testing.class}" + raise "Mismatch (at #{to.to_s(16)}) was:#{position} #{position.class} #{position.object} , should #{testing}#{testing.class}" end self.positions[position.object] = position @reverse_cache[to] = position unless position.object.is_a?(Label) diff --git a/test/arm/test_logic.rb b/test/arm/test_logic.rb index 015ae1fe..929a466b 100644 --- a/test/arm/test_logic.rb +++ b/test/arm/test_logic.rb @@ -90,16 +90,15 @@ module Arm end def label( pos = 0x12 + 8) - addr = Risc::Position.new(FakeAddress.new(2) , 2) - l = Risc::Label.new("some" , "Label" , addr.object) - Risc::Position.new(l , 0x22 + 8) + label = Risc::Label.new("some" , "Label" , FakeAddress.new(pos)) + Risc::Position.new(label , pos) #Risc::Position.set(l , pos , @binary) - l + label end def test_move_object code = @machine.add( :r1 , label) - Risc::Position.new(code,0) + Risc::Position.new(code,12) assert_code code , :add , [0x22,0x10,0x9f,0xe2] #e2 9f 10 22 end diff --git a/test/parfait/test_binary_code.rb b/test/parfait/test_binary_code.rb index 1288e9e8..c0fc0e08 100644 --- a/test/parfait/test_binary_code.rb +++ b/test/parfait/test_binary_code.rb @@ -23,6 +23,10 @@ module Parfait def test_next_nil assert_nil @code.next end + def test_ensure_next + assert BinaryCode , @code.ensure_next.class + assert @code.next + end def test_data_length assert_equal 13 , @code.data_length end diff --git a/test/risc/position/test_instruction_listener.rb b/test/risc/position/test_instruction_listener.rb index 1fce97f7..cc807877 100644 --- a/test/risc/position/test_instruction_listener.rb +++ b/test/risc/position/test_instruction_listener.rb @@ -6,6 +6,7 @@ module Risc def setup Risc.machine.boot @binary = Parfait::BinaryCode.new(1) + @bin_pos = Position.new(@binary,0) @instruction = DummyInstruction.new(DummyInstruction.new) @position = InstructionListener.init(@instruction , @binary) end @@ -41,13 +42,34 @@ module Risc Position.get(label).set(10) assert_equal 10 , Position.get(@instruction).at end - def test_label_at - branch = Branch.new("b" , @label) - Position.new(@label , 8 ) + def test_label_at_branch + label = Label.new("Hi","Ho" , FakeAddress.new(5) , @instruction) + branch = Branch.new("b" , label) + Position.new(label , 8 ) Position.new(branch , 8 ) at_8 = Position.at(8) assert_equal Position , at_8.class assert_equal Branch , at_8.object.class end end + class TestInstructionListenerBig < MiniTest::Test + def setup + Risc.machine.boot + @binary = Parfait::BinaryCode.new(1) + @bin_pos = Position.new(@binary,0) + @instruction = DummyInstruction.new + 13.times {@instruction.last.insert(DummyInstruction.new) } + @position = InstructionListener.init(@instruction , @binary) + @position.set(8) + end + def test_padding + assert_equal 64 , @binary.padded_length + end + def test_last + assert_equal 72 , Position.get(@instruction.last).at + end + def test_next + assert @binary.next + end + end end diff --git a/test/risc/position/test_position.rb b/test/risc/position/test_position.rb index 8c42eca8..fe228115 100644 --- a/test/risc/position/test_position.rb +++ b/test/risc/position/test_position.rb @@ -49,6 +49,9 @@ module Risc res = @pos - Position.new(@pos,4) assert_equal 1 , res end + def test_lg + assert @pos > Position.new(@pos,4) + end def test_tos assert_equal "0x5" , @pos.to_s end