From 8d953a619f925b7ea6fb2d0af28f4b1d7019402b Mon Sep 17 00:00:00 2001 From: Torsten Ruger Date: Tue, 5 Jun 2018 18:11:25 +0300 Subject: [PATCH] propagate instruction positions still overlapping onto binaries, but a start --- lib/arm/instructions/instruction.rb | 4 +- lib/risc/interpreter.rb | 4 +- lib/risc/machine.rb | 2 +- lib/risc/position/instruction_listener.rb | 8 ++- lib/risc/position/position.rb | 19 ++++--- test/arm/test_logic.rb | 11 ++-- test/parfait/test_binary_code.rb | 3 ++ test/risc/position/helper.rb | 6 +++ test/risc/position/test_code_position.rb | 26 +--------- .../position/test_instruction_listener.rb | 50 +++++++++---------- test/risc/position/test_position.rb | 2 +- test/risc/test_machine.rb | 2 +- 12 files changed, 68 insertions(+), 69 deletions(-) diff --git a/lib/arm/instructions/instruction.rb b/lib/arm/instructions/instruction.rb index b814dbc8..cecb4517 100644 --- a/lib/arm/instructions/instruction.rb +++ b/lib/arm/instructions/instruction.rb @@ -24,8 +24,8 @@ module Arm def insert(instruction) super my_pos = Risc::Position.get(self) - # set my position to set next according to rules - Risc::InstructionListener.init(instruction , my_pos.get_code) + listener = Risc::InstructionListener.new( instruction , my_pos.get_code ) + my_pos.position_listener(listener) end end end diff --git a/lib/risc/interpreter.rb b/lib/risc/interpreter.rb index 2c0a5e6c..260e70c2 100644 --- a/lib/risc/interpreter.rb +++ b/lib/risc/interpreter.rb @@ -14,7 +14,7 @@ module Risc # fire events for changed pc and register contents include Util::Eventable include Util::Logging - log_level :info + log_level :debug attr_reader :instruction , :clock , :pc # current instruction and pc attr_reader :registers # the registers, 16 (a hash, sym -> contents) @@ -48,7 +48,7 @@ module Risc def set_pc( pos ) raise "Not int #{pos}" unless pos.is_a? Numeric position = Position.at(pos) - raise "No position #{pos.to_s(16)}" unless position + raise "No position at 0x#{pos.to_s(16)}" unless position if position.is_a?(CodeListener) raise "Setting Code #{clock}-#{position}, #{position.method}" #return set_pc(position.at + Parfait::BinaryCode.byte_offset) diff --git a/lib/risc/machine.rb b/lib/risc/machine.rb index 3fac8854..0af309d5 100644 --- a/lib/risc/machine.rb +++ b/lib/risc/machine.rb @@ -123,7 +123,7 @@ module Risc type.methods.each_method do |method| last_code = CodeListener.init(method.binary , code_start) first_position = InstructionListener.init(method.cpu_instructions, method.binary) - first_position.set_position( code_start + Parfait::BinaryCode.byte_offset) + first_position.set( code_start + Parfait::BinaryCode.byte_offset) last_code.position_listener( prev_code.object) if prev_code prev_code = last_code code_start = last_code.next_slot diff --git a/lib/risc/position/instruction_listener.rb b/lib/risc/position/instruction_listener.rb index 728d32b1..4781b5c1 100644 --- a/lib/risc/position/instruction_listener.rb +++ b/lib/risc/position/instruction_listener.rb @@ -15,11 +15,10 @@ module Risc class InstructionListener attr_reader :instruction , :binary def initialize(instruction , binary) - pos = 0 @instruction = instruction @binary = binary end - def init(at, binary) + def old_code(at, binary) @binary = binary instruction.address.set_value(at) if instruction.is_a?(Label) return if at == 0 and binary.nil? @@ -39,6 +38,10 @@ module Risc Position.set(@instruction.next, nekst , binary) end + def position_changed(position) + my_pos = Position.get(@instruction) + my_pos.set(position.at + position.object.byte_length) + end # initialize the dependency graph for instructions # # starting from the given instruction, create Positions @@ -50,6 +53,7 @@ module Risc # set all positions in the chain def self.init( instruction , code ) raise "Not Binary Code #{code.class}" unless code.is_a?(Parfait::BinaryCode) + raise "Must init with instruction, not nil" unless instruction first = nil while(instruction) position = Position.new(instruction , -1) diff --git a/lib/risc/position/position.rb b/lib/risc/position/position.rb index 7e950bc7..9a9983fb 100644 --- a/lib/risc/position/position.rb +++ b/lib/risc/position/position.rb @@ -57,10 +57,10 @@ module Risc end def set(int) - same = int == self.at + return int if int == self.at Position.set_to(self , int) @at = int - trigger(:position_changed , self ) unless same + trigger(:position_changed , self ) int end @@ -79,6 +79,7 @@ module Risc 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)}" at + object.byte_length end @@ -103,6 +104,8 @@ module Risc self.positions.has_key?(object) end + # get a position from the cache (object -> position) + # unless it's a label, then get the position of it's next def self.get(object) pos = self.positions[object] if pos == nil @@ -116,17 +119,21 @@ module Risc pos end + # populate the position caches (forward and revese) with the given position + # forward caches object -> position + # reverse caches position.at > position + # Labels do not participatein reverse cache def self.set_to( position , to) postest = Position.positions[position.object] unless to < 0 raise "Mismatch #{position}" if postest and postest != position - @reverse_cache.delete(position.at) unless position.object.is_a? Label + @reverse_cache.delete(position.at) unless position.object.is_a?(Label) testing = self.at( position.at ) unless position.at < 0 - if testing and testing.class != position.class + 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}" 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.class}" + @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)}" position end end diff --git a/test/arm/test_logic.rb b/test/arm/test_logic.rb index 6ac32081..015ae1fe 100644 --- a/test/arm/test_logic.rb +++ b/test/arm/test_logic.rb @@ -82,7 +82,7 @@ module Arm end def test_too_big_add code = @machine.add :r1 , :r1, 0x222 - Risc::Position.set(code,0,nil) + Risc::Position.new(code,0) # add 0x02 (first instruction) and then 0x220 shifted assert_code code , :add , [0x02,0x1c,0x91,0xe2] #e2 91 1e 02 # added extra instruction to add "extra" @@ -90,15 +90,16 @@ module Arm end def label( pos = 0x12 + 8) - l = Risc::Label.new("some" , "Label" , FakeAddress.new(2)) - Risc::Position.set(l.address , 0x22 + 8) - Risc::Position.set(l , pos , @binary) + addr = Risc::Position.new(FakeAddress.new(2) , 2) + l = Risc::Label.new("some" , "Label" , addr.object) + Risc::Position.new(l , 0x22 + 8) + #Risc::Position.set(l , pos , @binary) l end def test_move_object code = @machine.add( :r1 , label) - Risc::Position.set(code,0,@binary) + Risc::Position.new(code,0) 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 aca39fb3..1288e9e8 100644 --- a/test/parfait/test_binary_code.rb +++ b/test/parfait/test_binary_code.rb @@ -26,6 +26,9 @@ module Parfait def test_data_length assert_equal 13 , @code.data_length end + def test_padded_length + assert_equal 16*4 , @code.padded_length + end def test_byte_length assert_equal 13*4 , @code.byte_length end diff --git a/test/risc/position/helper.rb b/test/risc/position/helper.rb index 92f585e1..2e009502 100644 --- a/test/risc/position/helper.rb +++ b/test/risc/position/helper.rb @@ -5,8 +5,14 @@ module Risc def padded_length 4 end + def byte_length + 4 + end end class DummyInstruction < Dummy include Util::List + def initialize(nekst = nil) + @next = nekst + end end end diff --git a/test/risc/position/test_code_position.rb b/test/risc/position/test_code_position.rb index 20cb6456..a32e0634 100644 --- a/test/risc/position/test_code_position.rb +++ b/test/risc/position/test_code_position.rb @@ -1,28 +1,6 @@ require_relative "helper" module Risc - # tests that require a boot and test propagation - class TestPositionBasic < MiniTest::Test - def setup - Risc.machine.boot - @binary = Parfait::BinaryCode.new(1) - @method = Parfait.object_space.types.values.first.methods - @label = Risc.label("hi","ho") - end - def test_set_bin - pos = Position.set( @binary , 0 , @method) - assert_equal CodePosition , pos.class - end - def test_type - pos = Position.set( @binary , 0 , @method) - assert_equal "Word_Type" , pos.method.for_type.name - end - def test_next - pos = Position.set( @binary , 0 , @method) - type = pos.next_type(pos.method.for_type) - assert_equal "Integer_Type" , type.name - end - end class TestPositionTranslated < MiniTest::Test def setup machine = Risc.machine.boot @@ -34,11 +12,11 @@ module Risc def test_bin_propagates_existing @binary.extend_to(16) - Position.set( @binary , 0 , @method) + CodeListener.init( @binary , 0 ) assert_equal @binary.padded_length , Position.get(@binary.next).at end def test_bin_propagates_after - Position.set( @binary , 0 , Parfait.object_space.get_main) + CodeListener.init( @binary , 0 ) @binary.extend_to(16) assert_equal @binary.padded_length , Position.get(@binary.next).at end diff --git a/test/risc/position/test_instruction_listener.rb b/test/risc/position/test_instruction_listener.rb index 29134856..96374758 100644 --- a/test/risc/position/test_instruction_listener.rb +++ b/test/risc/position/test_instruction_listener.rb @@ -6,40 +6,40 @@ module Risc def setup Risc.machine.boot @binary = Parfait::BinaryCode.new(1) - #Position.set(@binary , 0 , Parfait.object_space.get_main) - @label = DummyInstruction.new + @instruction = DummyInstruction.new(DummyInstruction.new) + @position = InstructionListener.init(@instruction , @binary) end def test_init - assert InstructionListener.init(@label , @binary) + assert InstructionListener.init(@instruction , @binary) + end + def test_pos_not_set + assert_equal (-1), @position.at end def test_init_fail - assert_raises {InstructionListener.init(@label , nil)} + assert_raises {InstructionListener.init(@instruction , nil)} end - def pest_set_instr - pos = Position.set( @label , 8 , @binary) - assert_equal InstructionPosition , pos.class + def test_init_fail_nil + assert_raises {InstructionListener.init(nil , @binary)} end - def pest_label_set_int - Position.set( @label , 8 , @binary) - assert_equal 8 , @label.address.value + def test_listener_method + listener = InstructionListener.new( @instruction , @binary ) + listener.position_changed(@position) end - def pest_label_reset_int - Position.set( @label , 8 , @binary) - Position.set( @label , 18 , @binary) - assert_equal 18 , @label.address.value + def test_ins_propagates + assert_equal (-1) , Position.get(@instruction.next).at + @position.set( 8 ) + assert_equal 12 , Position.get(@instruction.next).at end - def pest_ins_propagates - @label.set_next Arm::ArmMachine.b( @label) - Position.set( @label , 8 , @binary) - assert_equal 8 , Position.get(@label.next).at + def test_ins_propagates_again + test_ins_propagates + @position.set( 12 ) + assert_equal 16 , Position.get(@instruction.next).at end - def pest_ins_propagates_again - second = Arm::ArmMachine.b( @label) - @label.set_next(second) - Position.set( @label , 8 , @binary) - Position.set(second , 12 , @binary) - Position.set( @label , 8 , @binary) - assert_equal 8 , Position.get(@label.next).at + def test_label_has_no_length + label = Label.new("Hi","Ho" , FakeAddress.new(5) , @instruction) + InstructionListener.init(label , @binary) + Position.get(label).set(10) + assert_equal 10 , Position.get(@instruction).at end def pest_label_at branch = Branch.new("b" , @label) diff --git a/test/risc/position/test_position.rb b/test/risc/position/test_position.rb index 3c6a8eb1..ce4a6589 100644 --- a/test/risc/position/test_position.rb +++ b/test/risc/position/test_position.rb @@ -64,7 +64,7 @@ module Risc class TestPositionEvents < MiniTest::Test def setup Position.clear_positions - @instruciton = DummyInstruction.new + @instruction = DummyInstruction.new @position = Position.new(@instruction , 0) @listener = PositionListener.new( @instruction ) end diff --git a/test/risc/test_machine.rb b/test/risc/test_machine.rb index daf66317..e5d5cf78 100644 --- a/test/risc/test_machine.rb +++ b/test/risc/test_machine.rb @@ -45,7 +45,7 @@ module Risc assert_equal 0 , Position.get(@machine.cpu_init).at end def test_cpu_at - assert_equal "0x5ed4" , Position.get(@machine.cpu_init.first).to_s + assert_equal "0x5e08" , Position.get(@machine.cpu_init.first).to_s end def pest_cpu_bin assert_equal "0x5ecc" , Position.get(@machine.cpu_init).to_s