diff --git a/lib/risc/position.rb b/lib/risc/position.rb index c87123e0..e0fee773 100644 --- a/lib/risc/position.rb +++ b/lib/risc/position.rb @@ -9,44 +9,14 @@ module Risc # positions, that do not reflect the position of the object, but of the # assembled instruction in the binary. # - # The Position class keeps a hash of all compile time positions. + # The Position module keeps a hash of all compile time positions. # - # While the Position objects transmit the change that (re) positioning + # While the (different)Position objects transmit the change that (re) positioning # entails to affected objects. - class Position + module Position @positions = {} - attr_reader :at - - def initialize( at ) - @at = at - raise "not int #{self}-#{at}" unless @at.is_a?(Integer) - end - - def +(offset) - offset = offset.at if offset.is_a?(Position) - @at + offset - end - def -(offset) - offset = offset.at if offset.is_a?(Position) - @at - offset - end - def to_s - "0x#{@at.to_s(16)}" - end - # just a callback after creation AND insertion - def init(pos) - end - def reset_to(pos) - return false if pos == at - if((at - pos).abs > 1000) - raise "position set too far off #{pos}!=#{at} for #{object}:#{object.class}" - end - @at = pos - true - end - def self.positions @positions end @@ -91,58 +61,15 @@ module Risc def self.for_at(object , at , extra) case object when Parfait::BinaryCode - BPosition.new(object,at , extra) + CodePosition.new(object,at , extra) when Arm::Instruction , Risc::Label - IPosition.new(object,at , extra) + InstructionPosition.new(object,at , extra) else - Position.new(at) + ObjectPosition.new(at) end end end - - # handle event propagation - class IPosition < Position - attr_reader :instruction , :binary - def initialize(instruction, pos , binary) - raise "not set " unless binary - super(pos) - @instruction = instruction - @binary = binary - end - - def init(at) - return unless instruction.next - at += instruction.byte_length - bin = binary - if( 12 == at % 60) - at = 12 - bin = binary.next - end - Position.set(instruction.next, at , binary) - end - - def reset_to(pos) - super(pos) - #puts "Reset (#{changed}) #{instruction}" - init(pos) - end - - end - class BPosition < Position - attr_reader :code , :method - def initialize(code, pos , method) - super(pos) - @code = code - @method = method - end - def init(at) - return unless code.next - Position.set(code.next , at + code.padded_length, method) - end - def reset_to(pos) - super(pos) - #puts "Reset (#{changed}) #{instruction}" - init(pos) - end - end end +require_relative "position/object_position" +require_relative "position/instruction_position" +require_relative "position/code_position" diff --git a/lib/risc/position/code_position.rb b/lib/risc/position/code_position.rb new file mode 100644 index 00000000..88992e77 --- /dev/null +++ b/lib/risc/position/code_position.rb @@ -0,0 +1,22 @@ +module Risc + module Position + + class CodePosition < ObjectPosition + attr_reader :code , :method + def initialize(code, pos , method) + super(pos) + @code = code + @method = method + end + def init(at) + return unless code.next + Position.set(code.next , at + code.padded_length, method) + end + def reset_to(pos) + super(pos) + #puts "Reset (#{changed}) #{instruction}" + init(pos) + end + end + end +end diff --git a/lib/risc/position/instruction_position.rb b/lib/risc/position/instruction_position.rb new file mode 100644 index 00000000..8eec7c7b --- /dev/null +++ b/lib/risc/position/instruction_position.rb @@ -0,0 +1,31 @@ +module Risc + module Position + + class InstructionPosition < ObjectPosition + attr_reader :instruction , :binary + def initialize(instruction, pos , binary) + raise "not set " unless binary + super(pos) + @instruction = instruction + @binary = binary + end + + def init(at) + return unless instruction.next + at += instruction.byte_length + bin = binary + if( 12 == at % 60) + at = 12 + bin = binary.next + end + Position.set(instruction.next, at , binary) + end + + def reset_to(pos) + super(pos) + #puts "Reset (#{changed}) #{instruction}" + init(pos) + end + end + end +end diff --git a/lib/risc/position/object_position.rb b/lib/risc/position/object_position.rb new file mode 100644 index 00000000..a483525b --- /dev/null +++ b/lib/risc/position/object_position.rb @@ -0,0 +1,36 @@ +module Risc + module Position + class ObjectPosition + attr_reader :at + + def initialize( at ) + @at = at + raise "not int #{self}-#{at}" unless @at.is_a?(Integer) + end + + def +(offset) + offset = offset.at if offset.is_a?(ObjectPosition) + @at + offset + end + + def -(offset) + offset = offset.at if offset.is_a?(ObjectPosition) + @at - offset + end + def to_s + "0x#{@at.to_s(16)}" + end + # just a callback after creation AND insertion + def init(pos) + end + def reset_to(pos) + return false if pos == at + if((at - pos).abs > 1000) + raise "position set too far off #{pos}!=#{at} for #{object}:#{object.class}" + end + @at = pos + true + end + end + end +end diff --git a/test/risc/test_position2.rb b/test/risc/position/test_code_position.rb similarity index 55% rename from test/risc/test_position2.rb rename to test/risc/position/test_code_position.rb index db6e546f..91892bba 100644 --- a/test/risc/test_position2.rb +++ b/test/risc/position/test_code_position.rb @@ -8,26 +8,9 @@ module Risc @binary = Parfait::BinaryCode.new(1) @label = Label.new("hi","ho") end - def test_set_instr - pos = Position.set( @label , 0 , @binary) - assert_equal IPosition , pos.class - end def test_set_bin pos = Position.set( @binary , 0 , Parfait.object_space.get_main) - assert_equal BPosition , pos.class - end - def test_ins_propagates - @label.set_next Arm::ArmMachine.b( @label) - Position.set( @label , 0 , @binary) - assert_equal 0 , Position.get(@label.next).at - end - def test_ins_propagates_again - second = Arm::ArmMachine.b( @label) - @label.set_next(second) - Position.set( @label , 0 , @binary) - Position.set(second , 2 , @binary) - Position.set( @label , 0 , @binary) - assert_equal 0 , Position.get(@label.next).at + assert_equal Position::CodePosition , pos.class end def test_bin_propagates_existing @binary.extend_to(16) diff --git a/test/risc/position/test_instruction_position.rb b/test/risc/position/test_instruction_position.rb new file mode 100644 index 00000000..24297221 --- /dev/null +++ b/test/risc/position/test_instruction_position.rb @@ -0,0 +1,31 @@ +require_relative "../helper" + +module Risc + module Position + # tests that require a boot and test propagation + class TestPositionBasic < MiniTest::Test + def setup + Risc.machine.boot + @binary = Parfait::BinaryCode.new(1) + @label = Label.new("hi","ho") + end + def test_set_instr + pos = Position.set( @label , 0 , @binary) + assert_equal InstructionPosition , pos.class + end + def test_ins_propagates + @label.set_next Arm::ArmMachine.b( @label) + Position.set( @label , 0 , @binary) + assert_equal 0 , Position.get(@label.next).at + end + def test_ins_propagates_again + second = Arm::ArmMachine.b( @label) + @label.set_next(second) + Position.set( @label , 0 , @binary) + Position.set(second , 2 , @binary) + Position.set( @label , 0 , @binary) + assert_equal 0 , Position.get(@label.next).at + end + end + end +end diff --git a/test/risc/position/test_object_position.rb b/test/risc/position/test_object_position.rb new file mode 100644 index 00000000..9f5c7da2 --- /dev/null +++ b/test/risc/position/test_object_position.rb @@ -0,0 +1,47 @@ +require_relative "../helper" + +module Risc + module Position + # tests that do no require a boot and only test basic positioning + class TestPositionBasic < MiniTest::Test + + def test_creation_ok + assert ObjectPosition.new(0) + end + def test_creation_fail + assert_raises {Position.new("0")} + end + def test_add + res = ObjectPosition.new(0) + 5 + assert_equal 5 , res + end + def test_sub + res = ObjectPosition.new(5) - 1 + assert_equal 4 , res + end + def test_sub_pos + res = ObjectPosition.new(5) - ObjectPosition.new(1) + assert_equal 4 , res + end + def test_set + pos = Position.set(self , 5) + assert_equal 5 , pos.at + end + def tet_tos + assert_equal "0x10" , Position.set(self).to_s + end + def test_reset_ok + pos = Position.set(self , 5) + pos = Position.set(self , 10) + assert_equal 10 , pos.at + end + def test_reset_fail + Position.set(self , 5) + assert_raises{Position.set(self , 10000)} + end + def test_raises_set_nil + assert_raises { Position.set(self,nil)} + end + end + end +end diff --git a/test/risc/test_machine.rb b/test/risc/test_machine.rb index aac13731..b88f0e8a 100644 --- a/test/risc/test_machine.rb +++ b/test/risc/test_machine.rb @@ -41,5 +41,20 @@ module Risc def test_has_jump assert_equal "ea0011f4" , @machine.binary_init.get_word(1).to_s(16) end + def test_pos_bin + assert_equal "0x0" , Position.get(@machine.binary_init).to_s + end + def test_pos_cpu + assert_equal 12 , Position.get(@machine.cpu_init).at + end + def test_cpu_at + assert_equal 3 , Position.get(@machine.cpu_init.first).at + end + def test_cpu_bin + assert_equal "0x3ed8" , Position.get(Position.get(@machine.cpu_init.first).binary).to_s + end + def test_cpu_label + assert_equal Position::InstructionPosition , Position.get(@machine.cpu_init.first).class + end end end diff --git a/test/risc/test_position1.rb b/test/risc/test_position1.rb deleted file mode 100644 index a11111af..00000000 --- a/test/risc/test_position1.rb +++ /dev/null @@ -1,45 +0,0 @@ -require_relative "../helper" - -module Risc - # tests that do no require a boot and only test basic positioning - class TestPositionBasic < MiniTest::Test - - def test_creation_ok - assert Position.new(0) - end - def test_creation_fail - assert_raises {Position.new("0")} - end - def test_add - res = Position.new(0) + 5 - assert_equal 5 , res - end - def test_sub - res = Position.new(5) - 1 - assert_equal 4 , res - end - def test_sub_pos - res = Position.new(5) - Position.new(1) - assert_equal 4 , res - end - def test_set - pos = Position.set(self , 5) - assert_equal 5 , pos.at - end - def tet_tos - assert_equal "0x10" , Position.set(self).to_s - end - def test_reset_ok - pos = Position.set(self , 5) - pos = Position.set(self , 10) - assert_equal 10 , pos.at - end - def test_reset_fail - Position.set(self , 5) - assert_raises{Position.set(self , 10000)} - end - def test_raises_set_nil - assert_raises { Position.set(self,nil)} - end - end -end