introduce the LabeListener to move instructions along when first code position changes

This commit is contained in:
Torsten Ruger 2018-06-09 22:13:43 +03:00
parent ec1d38f5a6
commit c7ad1d98ca
7 changed files with 94 additions and 12 deletions

View File

@ -14,7 +14,7 @@ module Risc
# fire events for changed pc and register contents
include Util::Eventable
include Util::Logging
log_level :debug
log_level :info
attr_reader :instruction , :clock , :pc # current instruction and pc
attr_reader :registers # the registers, 16 (a hash, sym -> contents)

View File

@ -120,12 +120,13 @@ module Risc
Parfait.object_space.types.values.each do |type|
next unless type.methods
type.methods.each_method do |method|
Position.log.debug "Position starts for method #{method.name}"
last_code = CodeListener.init(method.binary)
last_code.set(code_start)
first_position = InstructionListener.init(method.cpu_instructions, method.binary)
first_position.set( code_start + Parfait::BinaryCode.byte_offset)
code_start = last_code.next_slot
#next unless method.name == :main or method.name == :__init__
Position.log.debug "Method start #{code_start.to_s(16)} #{method.name}"
code_pos = CodeListener.init(method.binary)
InstructionListener.init(method.cpu_instructions, method.binary)
code_pos.position_listener( LabelListener.new(method.cpu_instructions))
code_pos.set(code_start)
code_start = Position.get(method.binary.last_code).next_slot
end
end
#Position.set( first_method.cpu_instructions, code_start + Parfait::BinaryCode.byte_offset , first_method.binary)

View File

@ -25,6 +25,7 @@ module Risc
# Taking into account that BinaryCodes only take 13 instructions,
# meaning that chain may have to be extended
def position_changing(position , to)
Position.log.debug "Changing #{position} to #{to.to_s(16)}, bin #{Position.get(@binary)}"
update_index(to)
instruction = position.object
return unless instruction.next
@ -40,7 +41,7 @@ module Risc
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
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

View File

@ -0,0 +1,39 @@
module Risc
# LabelListener is the one point that connects the BinaryCode
# and Instruction positions.
#
# LabelListener is instantiated with the first label of a Method
# and attached to the first BinaryCode.
#
# When the code moves, the label position is updated.
#
# The first code may get pushed by a previous method, and there is otherwise
# no way to react to this.
class LabelListener
attr_reader :label
# initialize with the first label of the method
def initialize(label)
@label = label
end
# The incoming position is the first BinaryCode of the method
# We simply position the Label (instance, see initialize) as the
# first entry in the BinaryCode, at BinaryCode.byte_offset
def position_changed(position)
label_pos = Position.get(@label)
label_pos.set(position + Parfait::BinaryCode.byte_offset)
end
# don't react to insertion, as the CodeListener will take care
def position_inserted(position)
end
# dont react, as we do the work in position_changed
def position_changing(position , to)
end
end
end

View File

@ -190,3 +190,4 @@ end
require_relative "position_listener"
require_relative "instruction_listener"
require_relative "code_listener"
require_relative "label_listener"

View File

@ -0,0 +1,25 @@
require_relative "helper"
module Risc
class TestLabelListener < MiniTest::Test
def setup
Risc.machine.boot
@label = Label.new("Hi","Ho" , FakeAddress.new(5))
@label_pos = Position.new(@label , -1)
@code = Parfait::BinaryCode.new(1)
@code_pos = Position.new(@code , -1)
@code_pos.position_listener( LabelListener.new(@label))
end
def test_move
@code_pos.set(0)
assert_equal 8 , @label_pos.at
end
def test_move_twice
@code_pos.set(0)
@code_pos.set(0x40)
assert_equal 72 , @label_pos.at
end
end
end

View File

@ -34,6 +34,18 @@ module Risc
assert_equal 5, count
end
end
class TestMachinePos < MiniTest::Test
def setup
@machine = Risc.machine.boot
@machine.translate(:arm)
@machine.position_all
end
def test_positions_set
@machine.objects.each do |id,obj|
assert Position.get(obj).valid? , "#{Position.get(obj)} , #{obj.object_id.to_s(16)}"
end
end
end
class TestMachineInit < MiniTest::Test
def setup
@machine = Risc.machine.boot
@ -45,10 +57,7 @@ module Risc
assert_equal 0 , Position.get(@machine.cpu_init).at
end
def test_cpu_at
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
assert_equal "0x5eb4" , Position.get(@machine.cpu_init.first).to_s
end
def test_cpu_label
assert_equal Position , Position.get(@machine.cpu_init.first).class
@ -61,5 +70,11 @@ module Risc
bin = Parfait.object_space.get_init.binary.next
assert 0 != bin.get_word(0) , "index 0 is 0 #{bin.inspect}"
end
def test_positions_set
@machine.objects.each do |id,obj|
assert Position.get(obj).valid? , "#{Position.get(obj)} , #{obj.object_id.to_s(16)}"
end
end
end
end