diff --git a/lib/risc/position/instruction_listener.rb b/lib/risc/position/instruction_listener.rb index 5287823f..3919862a 100644 --- a/lib/risc/position/instruction_listener.rb +++ b/lib/risc/position/instruction_listener.rb @@ -24,15 +24,16 @@ module Risc # Taking into account that BinaryCodes only take 13 instructions, # meaning that chain may have to be extended def position_changed(position) - fix_binary - my_pos = Position.get(@instruction) next_pos = position.at + position.object.byte_length + fix_binary_for(next_pos) + my_pos = Position.get(@instruction) diff = next_pos - Position.get(@binary).at - Position.log.debug "Diff: #{diff.to_s(16)} , next #{next_pos.to_s(16)} , binary #{Position.get(@binary)}" + Position.log.debug "Diff: 0x#{diff.to_s(16)} , next 0x#{next_pos.to_s(16)} , binary #{Position.get(@binary)}" raise "Invalid position #{diff.to_s(16)} , next #{next_pos.to_s(16)} #{position}" if diff < 8 if( (diff % (@binary.padded_length - @instruction.byte_length)) == 0 ) @binary = @binary.ensure_next next_pos = Position.get(@binary).at + Parfait::BinaryCode.byte_offset + #Insert/Position the jump (its missing) Position.log.debug "Jump to: #{next_pos.to_s(16)}" end my_pos.set(next_pos) @@ -66,24 +67,26 @@ module Risc # 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 + # + # Because the position for the @instruction may not be set yet, + # we use the one that it will be set to (the arg) + def fix_binary_for(new_pos) raise "Binary has no position (-1)" if Position.get(@binary).at == -1 - return if Position.get(@instruction).at == -1 count = 0 - org_pos = Position.get(@binary) - return if org_pos.at == -1 - while( !pos_in_binary) + bin_pos = Position.get(@binary) + while( !pos_in_binary(new_pos)) @binary = @binary.ensure_next count += 1 - raise "Positions messed #{Position.get(@instruction)}:#{org_pos}" + raise "Positions too far out (#{count}) #{Position.get(@instruction)}:#{bin_pos}" if count > 5 end end - def pos_in_binary - me = Position.get(@instruction) + # check if the given position is inside the @binary + # ie not below start or above end + def pos_in_binary(new_pos) bin = Position.get(@binary) - return false if me < bin - return false if me > (bin + @binary.padded_length) + return false if bin > new_pos + return false if new_pos > (bin + @binary.padded_length) return true end diff --git a/lib/risc/position/position.rb b/lib/risc/position/position.rb index 09cab3ac..77f54f13 100644 --- a/lib/risc/position/position.rb +++ b/lib/risc/position/position.rb @@ -108,6 +108,12 @@ module Risc "0x#{@at.to_s(16)}" end + def object_class + return :object if @object.is_a?(Parfait::Object) + return :object if @object.class.name.include?("Test") + :instruction + end + def next_slot return -1 if at < 0 self.log.debug "Next Slot @#{at.to_s(16)} for #{object.class} == #{(at + object.byte_length).to_s(16)}" @@ -159,12 +165,12 @@ module Risc raise "Mismatch #{position}" if postest and postest != position @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 #{to.to_s(16)}) was:#{position} #{position.class} #{position.object} , should #{testing}#{testing.class}" + if testing and testing.object_class != position.object_class + raise "Mismatch (at #{to.to_s(16)}) new:#{position} #{position.object.class} , was:#{testing}#{testing.object.class}" end self.positions[position.object] = position @reverse_cache[to] = position unless position.object.is_a?(Label) - log.debug "Set #{position} (#{to.to_s(16)}) for #{position.object.class} #{position.object.object_id.to_s(16)}" + log.debug "Set #{position} to 0x#{to.to_s(16)} for #{position.object.class} #{position.object.object_id.to_s(16)}" position end end diff --git a/test/arm/test_move.rb b/test/arm/test_move.rb index 45e82c70..3fda4141 100644 --- a/test/arm/test_move.rb +++ b/test/arm/test_move.rb @@ -26,7 +26,7 @@ module Arm end def test_mov_big code = @machine.mov :r0, 0x222 # is not 8 bit and can't be rotated by the arm system in one instruction - Risc::Position.set(code,0, nil) + Risc::Position.new(code,0) # mov 512(0x200) = e3 a0 0c 02 add 34(0x22) = e2 90 00 22 assert_code code , :mov , [ 0x02,0x0c,0xb0,0xe3] assert_code code.next , :add , [ 0x22,0x00,0x90,0xe2] diff --git a/test/risc/position/test_instruction_listener1.rb b/test/risc/position/test_instruction_listener1.rb index cce7a910..c9906a45 100644 --- a/test/risc/position/test_instruction_listener1.rb +++ b/test/risc/position/test_instruction_listener1.rb @@ -5,7 +5,7 @@ module Risc def setup Risc.machine.boot @binary = Parfait::BinaryCode.new(1) - @bin_pos = Position.new(@binary,0) + @bin_pos = CodeListener.init(@binary,0) @instruction = DummyInstruction.new 13.times {@instruction.last.insert(DummyInstruction.new) } @position = InstructionListener.init(@instruction , @binary) @@ -28,5 +28,10 @@ module Risc @instruction.insert DummyInstruction.new assert_equal 76 , Position.get(@instruction.last).at end + def test_pushes_after_insert + @instruction.insert DummyInstruction.new + @position.set(12) + assert_equal 80 , Position.get(@instruction.last).at + end end end diff --git a/test/risc/position/test_position2.rb b/test/risc/position/test_position2.rb index 414083fa..6a7c2b19 100644 --- a/test/risc/position/test_position2.rb +++ b/test/risc/position/test_position2.rb @@ -28,6 +28,12 @@ module Risc pos = @pos.set(10) assert_equal 10 , pos end + def test_object_class_test + assert_equal :object , @pos.object_class + end + def test_object_class_instr + assert_equal :instruction , Position.new(Label.new("hi","ho",FakeAddress.new(1)),4).object_class + end def test_at pos = Position.at(5) assert_equal 5 , pos.at