From ec1d38f5a6648f2482931a27ea5246d8adb608cd Mon Sep 17 00:00:00 2001 From: Torsten Ruger Date: Sat, 9 Jun 2018 17:41:39 +0300 Subject: [PATCH] reimplement instruction listeners with indexes easier to understand, as indexes map to Binarycode indexes, and can thus later be used to assemble directoy into the code Almost no change in tests (now only multiples of 4 addresses allowed) --- lib/parfait/binary_code.rb | 6 + lib/risc/position/code_listener.rb | 4 +- lib/risc/position/instruction_listener.rb | 105 +++++++----------- .../position/test_instruction_listener.rb | 6 +- 4 files changed, 50 insertions(+), 71 deletions(-) diff --git a/lib/parfait/binary_code.rb b/lib/parfait/binary_code.rb index 15b88148..3c865d81 100644 --- a/lib/parfait/binary_code.rb +++ b/lib/parfait/binary_code.rb @@ -47,6 +47,12 @@ module Parfait @next end + def last_code + last = self + last = last.next while(last.next) + last + end + def each_block( &block ) block.call( self ) @next.each_block( &block ) if @next diff --git a/lib/risc/position/code_listener.rb b/lib/risc/position/code_listener.rb index 60c6381b..bf5d1f79 100644 --- a/lib/risc/position/code_listener.rb +++ b/lib/risc/position/code_listener.rb @@ -10,10 +10,10 @@ module Risc class CodeListener def position_inserted(position) - Position.log.debug "extending one in #{self}" + Position.log.debug "extending one at #{position}" pos = CodeListener.init( position.object.next ) - pos.set( position + position.object.padded_length) return unless position.valid? + pos.set( position + position.object.padded_length) set_jump_for(position) end diff --git a/lib/risc/position/instruction_listener.rb b/lib/risc/position/instruction_listener.rb index cf7d0e73..ed4d5c94 100644 --- a/lib/risc/position/instruction_listener.rb +++ b/lib/risc/position/instruction_listener.rb @@ -2,7 +2,7 @@ module Risc # Instructions are also a linked list, but their position is not really # the position of the object. # Rather it is the position of the assembled code in the binary. - # (Luckily arm is sane, so this is realtively simple) + # (Luckily arm is sane, so this is relatively simple) # # Really we only need to calculate Positions at a jump, so between the # Jump and the label it jumps too. The other instructions are "just" fill. @@ -13,85 +13,62 @@ module Risc # the same BinaryCode, or else move it and the code along # class InstructionListener - attr_reader :instruction , :binary - def initialize(instruction , binary) - @instruction = instruction + attr_reader :binary + + def initialize(binary) @binary = binary + @index = -1 end - def position_changing(position , to) - - end - - # if the position of the instruction before us changes, we need to - # adjust the position of this instruction accordingly + # if the position of the instruction changes, we need to adjust the position + # of the next instruction accordingly (if present) # Taking into account that BinaryCodes only take 13 instructions, # meaning that chain may have to be extended - def position_changed(position) - 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: 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)}" + def position_changing(position , to) + update_index(to) + instruction = position.object + return unless instruction.next + if @index == (Parfait::BinaryCode.data_length - 1 ) + nekst_pos_diff = @binary.padded_length + else + nekst_pos_diff = @index * 4 + instruction.byte_length end - my_pos.set(next_pos) + Position.log.debug "Nekst + #{nekst_pos_diff + Parfait::BinaryCode.byte_offset}" + nekst = Position.get(position.object.next) + nekst.set(Position.get(@binary) + nekst_pos_diff + Parfait::BinaryCode.byte_offset) + end + + def update_index(to) + index = (to - Position.get(@binary).at) / 4 + raise "Invalid negative index #{@index} , #{Position.get(@binary)}" if index < Parfait::BinaryCode.type_length + while(index >= (Parfait::BinaryCode.memory_size - 1) ) + @binary = @binary.ensure_next + index = (to - Position.get(@binary).at) / 4 + end + @index = index - 2 + raise "Invalid negative index #{@index} , #{Position.get(@binary)}" if index < 0 + end + + def position_changed(position) + #code moved to position_changing end # When this is called, only the actual insert has happened (keeping the # position logic out of the instruction assembly). # - # This event happens at the listener that was dependent on the position - # before the insert, ie: + # This event happens at the listener of the positionwhere the insert happens, ie: # position : the arg is the first instruction in the chain where insert happened # position.object.next : is the newly inserted instruction we need to setup - # @instruction : previously dependent on position, now on inserted's position # # So we need to : - # - move the listener self to listen to the inserted instruction # - add a listener for the new instruction (to listen to the arg) - # - set the new position (moving the chain along) + # - trigger change for this (fake) to set position of inserted def position_inserted(position) inserted = position.object.next - raise "uups" unless inserted ## TODO: remove - position.remove_position_listener(self) new_pos = Position.new(inserted , -1) - new_pos.position_listener(self) + new_pos.position_listener(InstructionListener.new(@binary)) - listen = InstructionListener.new(inserted , @binary) - position.position_listener(listen) - - position.trigger_changed - end - - # check that the binary we use is the one where the current position falls - # if not move up and register/unregister (soon) - # - # 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 - count = 0 - bin_pos = Position.get(@binary) - while( !pos_in_binary(new_pos)) - @binary = @binary.ensure_next - count += 1 - raise "Positions too far out (#{count}) #{Position.get(@instruction)}:#{bin_pos}" if count > 5 - end - end - - # 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 bin > new_pos - return false if new_pos > (bin + @binary.padded_length) - return true + position.trigger_changing(position.at) end # initialize the dependency graph for instructions @@ -110,12 +87,8 @@ module Risc while(instruction) position = Position.new(instruction , -1) first = position unless first - nekst = instruction.next - if nekst - listener = InstructionListener.new( nekst , code ) - position.position_listener(listener) - end - instruction = nekst + position.position_listener(InstructionListener.new( code )) + instruction = instruction.next end first end diff --git a/test/risc/position/test_instruction_listener.rb b/test/risc/position/test_instruction_listener.rb index 4e1d1c68..45d57f1e 100644 --- a/test/risc/position/test_instruction_listener.rb +++ b/test/risc/position/test_instruction_listener.rb @@ -24,7 +24,7 @@ module Risc end def test_listener_method @position.set(8) - listener = InstructionListener.new( @instruction , @binary ) + listener = InstructionListener.new( @binary ) listener.position_changed(@position) end def test_ins_propagates @@ -40,8 +40,8 @@ module Risc 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 + Position.get(label).set(12) + assert_equal 12 , Position.get(@instruction).at end def test_label_at_branch label = Label.new("Hi","Ho" , FakeAddress.new(5) , @instruction)