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)
This commit is contained in:
parent
cf94227b2c
commit
ec1d38f5a6
lib
test/risc/position
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user