propagate instruction positions
still overlapping onto binaries, but a start
This commit is contained in:
parent
f35ee6425a
commit
8d953a619f
@ -24,8 +24,8 @@ module Arm
|
|||||||
def insert(instruction)
|
def insert(instruction)
|
||||||
super
|
super
|
||||||
my_pos = Risc::Position.get(self)
|
my_pos = Risc::Position.get(self)
|
||||||
# set my position to set next according to rules
|
listener = Risc::InstructionListener.new( instruction , my_pos.get_code )
|
||||||
Risc::InstructionListener.init(instruction , my_pos.get_code)
|
my_pos.position_listener(listener)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -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 :info
|
log_level :debug
|
||||||
|
|
||||||
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)
|
||||||
@ -48,7 +48,7 @@ module Risc
|
|||||||
def set_pc( pos )
|
def set_pc( pos )
|
||||||
raise "Not int #{pos}" unless pos.is_a? Numeric
|
raise "Not int #{pos}" unless pos.is_a? Numeric
|
||||||
position = Position.at(pos)
|
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)
|
if position.is_a?(CodeListener)
|
||||||
raise "Setting Code #{clock}-#{position}, #{position.method}"
|
raise "Setting Code #{clock}-#{position}, #{position.method}"
|
||||||
#return set_pc(position.at + Parfait::BinaryCode.byte_offset)
|
#return set_pc(position.at + Parfait::BinaryCode.byte_offset)
|
||||||
|
@ -123,7 +123,7 @@ module Risc
|
|||||||
type.methods.each_method do |method|
|
type.methods.each_method do |method|
|
||||||
last_code = CodeListener.init(method.binary , code_start)
|
last_code = CodeListener.init(method.binary , code_start)
|
||||||
first_position = InstructionListener.init(method.cpu_instructions, method.binary)
|
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
|
last_code.position_listener( prev_code.object) if prev_code
|
||||||
prev_code = last_code
|
prev_code = last_code
|
||||||
code_start = last_code.next_slot
|
code_start = last_code.next_slot
|
||||||
|
@ -15,11 +15,10 @@ module Risc
|
|||||||
class InstructionListener
|
class InstructionListener
|
||||||
attr_reader :instruction , :binary
|
attr_reader :instruction , :binary
|
||||||
def initialize(instruction , binary)
|
def initialize(instruction , binary)
|
||||||
pos = 0
|
|
||||||
@instruction = instruction
|
@instruction = instruction
|
||||||
@binary = binary
|
@binary = binary
|
||||||
end
|
end
|
||||||
def init(at, binary)
|
def old_code(at, binary)
|
||||||
@binary = binary
|
@binary = binary
|
||||||
instruction.address.set_value(at) if instruction.is_a?(Label)
|
instruction.address.set_value(at) if instruction.is_a?(Label)
|
||||||
return if at == 0 and binary.nil?
|
return if at == 0 and binary.nil?
|
||||||
@ -39,6 +38,10 @@ module Risc
|
|||||||
Position.set(@instruction.next, nekst , binary)
|
Position.set(@instruction.next, nekst , binary)
|
||||||
end
|
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
|
# initialize the dependency graph for instructions
|
||||||
#
|
#
|
||||||
# starting from the given instruction, create Positions
|
# starting from the given instruction, create Positions
|
||||||
@ -50,6 +53,7 @@ module Risc
|
|||||||
# set all positions in the chain
|
# set all positions in the chain
|
||||||
def self.init( instruction , code )
|
def self.init( instruction , code )
|
||||||
raise "Not Binary Code #{code.class}" unless code.is_a?(Parfait::BinaryCode)
|
raise "Not Binary Code #{code.class}" unless code.is_a?(Parfait::BinaryCode)
|
||||||
|
raise "Must init with instruction, not nil" unless instruction
|
||||||
first = nil
|
first = nil
|
||||||
while(instruction)
|
while(instruction)
|
||||||
position = Position.new(instruction , -1)
|
position = Position.new(instruction , -1)
|
||||||
|
@ -57,10 +57,10 @@ module Risc
|
|||||||
end
|
end
|
||||||
|
|
||||||
def set(int)
|
def set(int)
|
||||||
same = int == self.at
|
return int if int == self.at
|
||||||
Position.set_to(self , int)
|
Position.set_to(self , int)
|
||||||
@at = int
|
@at = int
|
||||||
trigger(:position_changed , self ) unless same
|
trigger(:position_changed , self )
|
||||||
int
|
int
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -79,6 +79,7 @@ module Risc
|
|||||||
|
|
||||||
def next_slot
|
def next_slot
|
||||||
return -1 if at < 0
|
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
|
at + object.byte_length
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -103,6 +104,8 @@ module Risc
|
|||||||
self.positions.has_key?(object)
|
self.positions.has_key?(object)
|
||||||
end
|
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)
|
def self.get(object)
|
||||||
pos = self.positions[object]
|
pos = self.positions[object]
|
||||||
if pos == nil
|
if pos == nil
|
||||||
@ -116,17 +119,21 @@ module Risc
|
|||||||
pos
|
pos
|
||||||
end
|
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)
|
def self.set_to( position , to)
|
||||||
postest = Position.positions[position.object] unless to < 0
|
postest = Position.positions[position.object] unless to < 0
|
||||||
raise "Mismatch #{position}" if postest and postest != position
|
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
|
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}"
|
raise "Mismatch (at #{pos.to_s(16)}) was:#{position} #{position.class} #{position.object} , should #{testing}#{testing.class}"
|
||||||
end
|
end
|
||||||
self.positions[position.object] = position
|
self.positions[position.object] = position
|
||||||
@reverse_cache[to] = position unless position.object.is_a? Label
|
@reverse_cache[to] = position unless position.object.is_a?(Label)
|
||||||
log.debug "Set #{position} (#{to.to_s(16)}) for #{position.class}"
|
log.debug "Set #{position} (#{to.to_s(16)}) for #{position.object.class} #{position.object.object_id.to_s(16)}"
|
||||||
position
|
position
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -82,7 +82,7 @@ module Arm
|
|||||||
end
|
end
|
||||||
def test_too_big_add
|
def test_too_big_add
|
||||||
code = @machine.add :r1 , :r1, 0x222
|
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
|
# add 0x02 (first instruction) and then 0x220 shifted
|
||||||
assert_code code , :add , [0x02,0x1c,0x91,0xe2] #e2 91 1e 02
|
assert_code code , :add , [0x02,0x1c,0x91,0xe2] #e2 91 1e 02
|
||||||
# added extra instruction to add "extra"
|
# added extra instruction to add "extra"
|
||||||
@ -90,15 +90,16 @@ module Arm
|
|||||||
end
|
end
|
||||||
|
|
||||||
def label( pos = 0x12 + 8)
|
def label( pos = 0x12 + 8)
|
||||||
l = Risc::Label.new("some" , "Label" , FakeAddress.new(2))
|
addr = Risc::Position.new(FakeAddress.new(2) , 2)
|
||||||
Risc::Position.set(l.address , 0x22 + 8)
|
l = Risc::Label.new("some" , "Label" , addr.object)
|
||||||
Risc::Position.set(l , pos , @binary)
|
Risc::Position.new(l , 0x22 + 8)
|
||||||
|
#Risc::Position.set(l , pos , @binary)
|
||||||
l
|
l
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_move_object
|
def test_move_object
|
||||||
code = @machine.add( :r1 , label)
|
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
|
assert_code code , :add , [0x22,0x10,0x9f,0xe2] #e2 9f 10 22
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -26,6 +26,9 @@ module Parfait
|
|||||||
def test_data_length
|
def test_data_length
|
||||||
assert_equal 13 , @code.data_length
|
assert_equal 13 , @code.data_length
|
||||||
end
|
end
|
||||||
|
def test_padded_length
|
||||||
|
assert_equal 16*4 , @code.padded_length
|
||||||
|
end
|
||||||
def test_byte_length
|
def test_byte_length
|
||||||
assert_equal 13*4 , @code.byte_length
|
assert_equal 13*4 , @code.byte_length
|
||||||
end
|
end
|
||||||
|
@ -5,8 +5,14 @@ module Risc
|
|||||||
def padded_length
|
def padded_length
|
||||||
4
|
4
|
||||||
end
|
end
|
||||||
|
def byte_length
|
||||||
|
4
|
||||||
|
end
|
||||||
end
|
end
|
||||||
class DummyInstruction < Dummy
|
class DummyInstruction < Dummy
|
||||||
include Util::List
|
include Util::List
|
||||||
|
def initialize(nekst = nil)
|
||||||
|
@next = nekst
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,28 +1,6 @@
|
|||||||
require_relative "helper"
|
require_relative "helper"
|
||||||
|
|
||||||
module Risc
|
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
|
class TestPositionTranslated < MiniTest::Test
|
||||||
def setup
|
def setup
|
||||||
machine = Risc.machine.boot
|
machine = Risc.machine.boot
|
||||||
@ -34,11 +12,11 @@ module Risc
|
|||||||
|
|
||||||
def test_bin_propagates_existing
|
def test_bin_propagates_existing
|
||||||
@binary.extend_to(16)
|
@binary.extend_to(16)
|
||||||
Position.set( @binary , 0 , @method)
|
CodeListener.init( @binary , 0 )
|
||||||
assert_equal @binary.padded_length , Position.get(@binary.next).at
|
assert_equal @binary.padded_length , Position.get(@binary.next).at
|
||||||
end
|
end
|
||||||
def test_bin_propagates_after
|
def test_bin_propagates_after
|
||||||
Position.set( @binary , 0 , Parfait.object_space.get_main)
|
CodeListener.init( @binary , 0 )
|
||||||
@binary.extend_to(16)
|
@binary.extend_to(16)
|
||||||
assert_equal @binary.padded_length , Position.get(@binary.next).at
|
assert_equal @binary.padded_length , Position.get(@binary.next).at
|
||||||
end
|
end
|
||||||
|
@ -6,40 +6,40 @@ module Risc
|
|||||||
def setup
|
def setup
|
||||||
Risc.machine.boot
|
Risc.machine.boot
|
||||||
@binary = Parfait::BinaryCode.new(1)
|
@binary = Parfait::BinaryCode.new(1)
|
||||||
#Position.set(@binary , 0 , Parfait.object_space.get_main)
|
@instruction = DummyInstruction.new(DummyInstruction.new)
|
||||||
@label = DummyInstruction.new
|
@position = InstructionListener.init(@instruction , @binary)
|
||||||
end
|
end
|
||||||
def test_init
|
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
|
end
|
||||||
def test_init_fail
|
def test_init_fail
|
||||||
assert_raises {InstructionListener.init(@label , nil)}
|
assert_raises {InstructionListener.init(@instruction , nil)}
|
||||||
end
|
end
|
||||||
def pest_set_instr
|
def test_init_fail_nil
|
||||||
pos = Position.set( @label , 8 , @binary)
|
assert_raises {InstructionListener.init(nil , @binary)}
|
||||||
assert_equal InstructionPosition , pos.class
|
|
||||||
end
|
end
|
||||||
def pest_label_set_int
|
def test_listener_method
|
||||||
Position.set( @label , 8 , @binary)
|
listener = InstructionListener.new( @instruction , @binary )
|
||||||
assert_equal 8 , @label.address.value
|
listener.position_changed(@position)
|
||||||
end
|
end
|
||||||
def pest_label_reset_int
|
def test_ins_propagates
|
||||||
Position.set( @label , 8 , @binary)
|
assert_equal (-1) , Position.get(@instruction.next).at
|
||||||
Position.set( @label , 18 , @binary)
|
@position.set( 8 )
|
||||||
assert_equal 18 , @label.address.value
|
assert_equal 12 , Position.get(@instruction.next).at
|
||||||
end
|
end
|
||||||
def pest_ins_propagates
|
def test_ins_propagates_again
|
||||||
@label.set_next Arm::ArmMachine.b( @label)
|
test_ins_propagates
|
||||||
Position.set( @label , 8 , @binary)
|
@position.set( 12 )
|
||||||
assert_equal 8 , Position.get(@label.next).at
|
assert_equal 16 , Position.get(@instruction.next).at
|
||||||
end
|
end
|
||||||
def pest_ins_propagates_again
|
def test_label_has_no_length
|
||||||
second = Arm::ArmMachine.b( @label)
|
label = Label.new("Hi","Ho" , FakeAddress.new(5) , @instruction)
|
||||||
@label.set_next(second)
|
InstructionListener.init(label , @binary)
|
||||||
Position.set( @label , 8 , @binary)
|
Position.get(label).set(10)
|
||||||
Position.set(second , 12 , @binary)
|
assert_equal 10 , Position.get(@instruction).at
|
||||||
Position.set( @label , 8 , @binary)
|
|
||||||
assert_equal 8 , Position.get(@label.next).at
|
|
||||||
end
|
end
|
||||||
def pest_label_at
|
def pest_label_at
|
||||||
branch = Branch.new("b" , @label)
|
branch = Branch.new("b" , @label)
|
||||||
|
@ -64,7 +64,7 @@ module Risc
|
|||||||
class TestPositionEvents < MiniTest::Test
|
class TestPositionEvents < MiniTest::Test
|
||||||
def setup
|
def setup
|
||||||
Position.clear_positions
|
Position.clear_positions
|
||||||
@instruciton = DummyInstruction.new
|
@instruction = DummyInstruction.new
|
||||||
@position = Position.new(@instruction , 0)
|
@position = Position.new(@instruction , 0)
|
||||||
@listener = PositionListener.new( @instruction )
|
@listener = PositionListener.new( @instruction )
|
||||||
end
|
end
|
||||||
|
@ -45,7 +45,7 @@ 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 "0x5ed4" , Position.get(@machine.cpu_init.first).to_s
|
assert_equal "0x5e08" , Position.get(@machine.cpu_init.first).to_s
|
||||||
end
|
end
|
||||||
def pest_cpu_bin
|
def pest_cpu_bin
|
||||||
assert_equal "0x5ecc" , Position.get(@machine.cpu_init).to_s
|
assert_equal "0x5ecc" , Position.get(@machine.cpu_init).to_s
|
||||||
|
Loading…
Reference in New Issue
Block a user