getting instruction repositioning right

big bug hunt, involving complicated maths (%)
This commit is contained in:
Torsten Ruger 2018-05-24 14:27:53 +03:00
parent 0293320bb8
commit 8d510c2e7e
8 changed files with 62 additions and 44 deletions

View File

@ -25,8 +25,11 @@ module Parfait
end end
def extend_one() def extend_one()
@next = BinaryCode.new(1) @next = BinaryCode.new(1)
#puts "extending #{total_size - data_length} in #{self}" if Risc::Position.set?(self)
Risc::Position.reset(self) if Risc::Position.set?(self) Risc::Position.log.debug "extending #{total_size - data_length} in #{self}"
my_pos = Risc::Position.get(self)
Risc::Position.reset(my_pos , my_pos.at)
end
end end
def each( &block ) def each( &block )

View File

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

View File

@ -74,7 +74,7 @@ module Risc
def position_all def position_all
raise "Not translated " unless @translated raise "Not translated " unless @translated
#need the initial jump at 0 and then functions #need the initial jump at 0 and then functions
Position.set(cpu_init , 0 , cpu_init) Position.set(cpu_init , 0 , nil)
@code_start = position_objects( @platform.padding ) @code_start = position_objects( @platform.padding )
# and then everything code # and then everything code
position_code position_code
@ -131,7 +131,7 @@ module Risc
def boot def boot
initialize initialize
Position.positions.clear Position.clear_positions
@objects = nil @objects = nil
@translated = false @translated = false
boot_parfait! boot_parfait!

View File

@ -16,21 +16,22 @@ module Risc
module Position module Position
include Util::Logging include Util::Logging
log_level :debug log_level :info
@positions = {} @positions = {}
@reverse_cache = {}
def self.positions def self.positions
@positions @positions
end end
def self.at( int ) def self.clear_positions
self.positions.each do |object , position| @positions = {}
next unless position.at == int @reverse_cache = {}
return position unless position.is_a?(InstructionPosition)
return position unless position.instruction.is_a?(Label)
end end
nil
def self.at( int )
@reverse_cache[int]
end end
def self.set?(object) def self.set?(object)
@ -48,30 +49,40 @@ module Risc
pos pos
end end
# set to the same position as before, thus triggering whatever code that propagates
# position _must have been set, otherwise raises
def self.reset(obj) def self.reset(obj)
old = self.get(obj) old = self.get(obj)
old.reset_to( old.at ) old.reset_to( old.at )
end end
def self.set( object , pos , extra = nil)
# resetting of position used to be error, but since relink and dynamic instruction size it is ok. # resetting of position used to be error, but since relink and dynamic instruction size it is ok.
# in measures # in measures
log.debug "Setting #{pos.to_s(16)} for #{object.class}-#{object}" #
old = Position.positions[object] # reseting to the same position as before, triggers code that propagates
testing = self.at( pos ) def self.reset(position , to)
if old != nil log.debug "ReSetting #{position}, to:#{to.to_s(16)}, for #{position.object.class}-#{position.object}"
raise "Mismatch was:#{old}#{old.class} , should #{testing}#{testing.class}" if testing and testing.class != old.class position.reset_to(to)
old.reset_to(pos) if testing = @reverse_cache[ to ]
log.debug "Reset #{pos.to_s(16)} for #{old.class}" if testing.class != position.class
return old raise "Mismatch (at #{to.to_s(16)}) new:#{position}:#{position.class} , was #{testing}:#{testing.class}"
end end
@reverse_cache.delete(to)
end
@reverse_cache[position.at] = position
log.debug "Reset #{position} (#{to.to_s(16)}) for #{position.class}"
return position
end
def self.set( object , pos , extra = nil)
old = Position.positions[object]
return self.reset(old , pos) if old
log.debug "Setting #{pos.to_s(16)} for #{object.class}-#{object}"
testing = self.at( pos )
position = for_at( object , pos , extra) position = for_at( object , pos , extra)
raise "Mismatch was:#{position}#{position.class} , should #{testing}#{testing.class}" if testing and testing.class != old.class raise "Mismatch (at #{pos.to_s(16)}) was:#{position} #{position.class} #{position.object} , should #{testing}#{testing.class}" if testing and testing.class != position.class
self.positions[object] = position self.positions[object] = position
position.init(pos) position.init(pos)
log.debug "Set #{pos.to_s(16)} for #{position.class}" @reverse_cache[position.at] = position
log.debug "Set #{position} (#{pos.to_s(16)}) for #{position.class}"
position position
end end

View File

@ -31,9 +31,9 @@ module Risc
end end
end end
def reset_to(pos) def reset_to(pos)
super(pos)
Position.log.debug "Reset (#{pos.to_s(16)}) #{code}"
init(pos) init(pos)
super(pos)
Position.log.debug "ResetCode (#{pos.to_s(16)}) #{code}"
end end
def next_method def next_method
next_m = @method.next_method next_m = @method.next_method

View File

@ -17,28 +17,32 @@ module Risc
class InstructionPosition < ObjectPosition class InstructionPosition < ObjectPosition
attr_reader :instruction , :binary attr_reader :instruction , :binary
def initialize(instruction, pos , binary) def initialize(instruction, pos , binary)
raise "not set " unless binary raise "not set #{binary}" if pos != 0 and !binary.is_a?(Parfait::BinaryCode)
super(instruction,pos) super(instruction,pos)
@instruction = instruction @instruction = instruction
@binary = binary @binary = binary
end end
def init(at) def init(at)
diff = at - Position.get(@binary).at return if at == 0 and binary.nil?
if( diff % 60 == 13*4) return unless @instruction.next
nekst = at + @instruction.byte_length
diff = nekst - Position.get(@binary).at
Position.log.debug "Diff: #{diff.to_s(16)} , next #{nekst.to_s(16)} , binary #{Position.get(@binary)}"
raise "Invalid position #{diff.to_s(16)} , next #{nekst.to_s(16)} #{self}" if diff < 8
if( (diff % @binary.padded_length ) == 0 )
@binary.extend_one unless @binary.next @binary.extend_one unless @binary.next
@binary = @binary.next @binary = @binary.next
raise "end of line " unless @binary raise "end of line " unless @binary
at = Position.get(@binary).at + Parfait::BinaryCode.offset nekst = Position.get(@binary).at + Parfait::BinaryCode.offset
Position.log.debug "Jump to: #{nekst.to_s(16)}"
end end
return unless @instruction.next Position.set(@instruction.next, nekst , @binary)
at += @instruction.byte_length
Position.set(@instruction.next, at , @binary)
end end
def reset_to(pos) def reset_to(pos)
super(pos)
Position.log.debug "Reset (#{pos}) #{instruction}"
init(pos) init(pos)
super(pos)
Position.log.debug "ResetInstruction (#{pos.to_s(16)}) #{instruction}"
end end
end end
end end

View File

@ -23,15 +23,15 @@ module Risc
second = Arm::ArmMachine.b( @label) second = Arm::ArmMachine.b( @label)
@label.set_next(second) @label.set_next(second)
Position.set( @label , 8 , @binary) Position.set( @label , 8 , @binary)
Position.set(second , 2 , @binary) Position.set(second , 12 , @binary)
Position.set( @label , 8 , @binary) Position.set( @label , 8 , @binary)
assert_equal 8 , Position.get(@label.next).at assert_equal 8 , Position.get(@label.next).at
end end
def test_label_at def test_label_at
branch = Branch.new("b" , @label) branch = Branch.new("b" , @label)
Position.set(@label , 4 , @binary) Position.set(@label , 8 , @binary)
Position.set(branch , 4 , @binary) Position.set(branch , 8 , @binary)
at_4 = Position.at(4) at_4 = Position.at(8)
assert_equal InstructionPosition , at_4.class assert_equal InstructionPosition , at_4.class
assert_equal Branch , at_4.instruction.class assert_equal Branch , at_4.instruction.class
end end

View File

@ -29,10 +29,10 @@ module Risc
assert_equal 0 , Position.get(@machine.cpu_init).at assert_equal 0 , Position.get(@machine.cpu_init).at
end end
def test_cpu_at def test_cpu_at
assert_equal "0x5bd8" , Position.get(@machine.cpu_init.first).to_s assert_equal "0x5714" , Position.get(@machine.cpu_init.first).to_s
end end
def test_cpu_bin def test_cpu_bin
assert_equal "0x5bcc" , Position.get(Position.get(@machine.cpu_init.first).binary).to_s assert_equal "0x570c" , Position.get(Position.get(@machine.cpu_init.first).binary).to_s
end end
def test_cpu_label def test_cpu_label
assert_equal Position::InstructionPosition , Position.get(@machine.cpu_init.first).class assert_equal Position::InstructionPosition , Position.get(@machine.cpu_init.first).class