From 39902401b918a776a048940f26eb6bfedb411a85 Mon Sep 17 00:00:00 2001 From: Torsten Ruger Date: Sun, 13 May 2018 15:28:10 +0300 Subject: [PATCH] positioning code by setting first method code codes will initial (and on reset) propagate the whole chain --- lib/risc/machine.rb | 17 ++++------- lib/risc/position/code_position.rb | 27 ++++++++++++++++- lib/risc/text_writer.rb | 24 ++++++++------- test/arm/test_call.rb | 2 +- test/risc/position/test_code_position.rb | 14 +++++++-- .../position/test_instruction_position.rb | 2 +- test/risc/test_machine.rb | 4 +-- test/risc/test_text_writer.rb | 30 +++++++++++++++++-- 8 files changed, 88 insertions(+), 32 deletions(-) diff --git a/lib/risc/machine.rb b/lib/risc/machine.rb index 2940c1f1..8e7410ef 100644 --- a/lib/risc/machine.rb +++ b/lib/risc/machine.rb @@ -91,7 +91,6 @@ module Risc # want to have the objects first in the executable objects.each do | id , objekt| next if objekt.is_a?( Parfait::BinaryCode) or objekt.is_a?( Risc::Label ) - next if objekt.is_a?( Parfait::TypedMethod) before = at Position.set(objekt,at) at += objekt.padded_length @@ -109,16 +108,12 @@ module Risc # assembly stops throwing errors def position_code at = @code_start - objects.each do |id , method| - next unless method.is_a? Parfait::TypedMethod - before = at - Position.set(method,at) - at += method.padded_length - Position.set( method.binary , at , method) - Position.set( method.cpu_instructions, at + 12 , method.binary) - log.debug "Method #{method.name}:#{before.to_s(16)} len: #{(at - before).to_s(16)}" - log.debug "Instructions #{method.cpu_instructions.object_id.to_s(16)}:#{(before+12).to_s(16)}" - end + first_method = Parfait.object_space.types.values.first.methods + before = at + Position.set( first_method.binary , at , first_method) + Position.set( first_method.cpu_instructions, at + 12 , first_method.binary) + log.debug "Method #{first_method.name}:#{before.to_s(16)} len: #{(at - before).to_s(16)}" + log.debug "Instructions #{first_method.cpu_instructions.object_id.to_s(16)}:#{(before+12).to_s(16)}" at end diff --git a/lib/risc/position/code_position.rb b/lib/risc/position/code_position.rb index e610ee15..0365b6f5 100644 --- a/lib/risc/position/code_position.rb +++ b/lib/risc/position/code_position.rb @@ -5,6 +5,9 @@ module Risc # # We want to keep all code for a method continous, so we propagate Positions # + # At the end of the list the propagation spills into the next methods + # binary and so on + # class CodePosition < ObjectPosition attr_reader :code , :method @@ -13,13 +16,17 @@ module Risc super(pos,code) @code = code @method = method + raise "Method nil" unless method end def init(at) next_pos = at + code.padded_length if code.next Position.set(code.next , next_pos, method) else - Position.set(method , next_pos) + next_meth = next_method + return unless next_meth + Position.set( next_meth.binary , next_pos , next_meth) + Position.set( next_meth.cpu_instructions, next_pos + 12 , next_meth.binary) end end def reset_to(pos) @@ -27,6 +34,24 @@ module Risc #puts "Reset (#{changed}) #{instruction}" init(pos) end + def next_method + next_m = @method.next_method + return next_m if next_m + #puts "Type now #{@method.for_type.name}" + type = next_type(@method.for_type) + if type + #puts "Position for #{type.name}" + return type.methods + else + return nil + end + end + def next_type(type) + nekst = Parfait.object_space.types.next_value(type) + return nil unless nekst + return nekst if nekst.methods + return next_type(nekst) + end end end end diff --git a/lib/risc/text_writer.rb b/lib/risc/text_writer.rb index 8f8b6ce0..da84df5e 100644 --- a/lib/risc/text_writer.rb +++ b/lib/risc/text_writer.rb @@ -20,7 +20,6 @@ module Risc def initialize(machine) @machine = machine - @load_at = 0x10054 # this is linux/arm end # objects must be written in same order as positioned by the machine, namely @@ -37,19 +36,22 @@ module Risc return @stream.string end + def sorted_objects + @machine.objects.values.sort do |left , right| + Position.get(left).at <=> Position.get(right).at + end + end # debugging loop to write out positions (in debug) def write_debug - @machine.objects.each do |id , objekt| + sorted_objects.each do |objekt| next if objekt.is_a?(Risc::Label) log.debug "Linked #{objekt.class}:0x#{objekt.object_id.to_s(16)} at #{Position.get(objekt)} / 0x#{objekt.padded_length.to_s(16)}" end end - # Write all the objects + # Write all the objects in the order that they have been positioed def write_objects - # then the objects , not code yet - @machine.objects.each do | id, objekt| - next if objekt.is_a? Parfait::BinaryCode + sorted_objects.each do |objekt| next if objekt.is_a? Risc::Label # ignore write_any( objekt ) end @@ -80,7 +82,7 @@ module Risc end def write_any_log( obj , at) - log.debug "#{at} #{obj.class}:0x#{obj.object_id.to_s(16)} at stream #{stream_position} pos:#{Position.get(obj)} , len:0x#{obj.padded_length.to_s(16)}" + log.debug "#{at} #{obj.class}:0x#{obj.object_id.to_s(16)} at stream 0x#{stream_position.to_s(16)} pos:#{Position.get(obj)} , len:0x#{obj.padded_length.to_s(16)}" end # Most objects are the same and get passed to write_object @@ -92,7 +94,7 @@ module Risc when Parfait::BinaryCode write_BinaryCode obj when Parfait::Data4 - write_data2 obj + write_data4 obj else write_object obj end @@ -144,7 +146,7 @@ module Risc written end - def write_data2( code ) + def write_data4( code ) @stream.write_signed_int_32( MARKER ) write_ref_for( code.get_type ) log.debug "Data4 witten stream 0x#{@stream.length.to_s(16)}" @@ -153,6 +155,7 @@ module Risc # first jump, def write_init( cpu_init ) cpu_init.assemble(@stream) + @stream.write_unsigned_int_8(0) until @machine.platform.padding == stream_position log.debug "Init witten stream 0x#{@stream.length.to_s(16)}" end @@ -200,7 +203,7 @@ module Risc when Fixnum @stream.write_signed_int_32(object) else - @stream.write_signed_int_32(Position.get(object) + @load_at) + @stream.write_signed_int_32(Position.get(object) + @machine.platform.loaded_at) end end @@ -221,5 +224,4 @@ module Risc end end - RxFile::Volotile.add(TextWriter , [:objects]) end diff --git a/test/arm/test_call.rb b/test/arm/test_call.rb index c622b31a..20b463d2 100644 --- a/test/arm/test_call.rb +++ b/test/arm/test_call.rb @@ -18,7 +18,7 @@ module Arm def test_method_call Risc.machine.boot bin = Parfait::BinaryCode.new(1) - Risc::Position.set(bin , 0x20) + Risc::Position.set(bin , 0x20,Parfait.object_space.get_main) Risc::Position.set(@binary , 0) code = @machine.call( bin ,{} )#this jumps to the next instruction Risc::Position.set(code , 0, @binary) diff --git a/test/risc/position/test_code_position.rb b/test/risc/position/test_code_position.rb index 91892bba..d33a3c72 100644 --- a/test/risc/position/test_code_position.rb +++ b/test/risc/position/test_code_position.rb @@ -6,15 +6,16 @@ module Risc def setup Risc.machine.boot @binary = Parfait::BinaryCode.new(1) + @method = Parfait.object_space.types.values.first.methods @label = Label.new("hi","ho") end def test_set_bin - pos = Position.set( @binary , 0 , Parfait.object_space.get_main) + pos = Position.set( @binary , 0 , @method) assert_equal Position::CodePosition , pos.class end def test_bin_propagates_existing @binary.extend_to(16) - Position.set( @binary , 0 , Parfait.object_space.get_main) + Position.set( @binary , 0 , @method) assert_equal @binary.padded_length , Position.get(@binary.next).at end def test_bin_propagates_after @@ -22,5 +23,14 @@ module Risc @binary.extend_to(16) assert_equal @binary.padded_length , Position.get(@binary.next).at 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 end diff --git a/test/risc/position/test_instruction_position.rb b/test/risc/position/test_instruction_position.rb index 20e64227..6e218255 100644 --- a/test/risc/position/test_instruction_position.rb +++ b/test/risc/position/test_instruction_position.rb @@ -7,7 +7,7 @@ module Risc def setup Risc.machine.boot @binary = Parfait::BinaryCode.new(1) - Position.set(@binary , 0) + Position.set(@binary , 0,Parfait.object_space.get_main) @label = Label.new("hi","ho") end def test_set_instr diff --git a/test/risc/test_machine.rb b/test/risc/test_machine.rb index a140bfba..fdd79fe8 100644 --- a/test/risc/test_machine.rb +++ b/test/risc/test_machine.rb @@ -39,10 +39,10 @@ module Risc assert_equal 0 , Position.get(@machine.cpu_init).at end def test_cpu_at - assert_equal "0x4d50" , Position.get(@machine.cpu_init.first).to_s + assert_equal "0x5ad0" , Position.get(@machine.cpu_init.first).to_s end def test_cpu_bin - assert_equal "0x4d44" , Position.get(Position.get(@machine.cpu_init.first).binary).to_s + assert_equal "0x5ac4" , 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 diff --git a/test/risc/test_text_writer.rb b/test/risc/test_text_writer.rb index dd09702a..1c5c36bb 100644 --- a/test/risc/test_text_writer.rb +++ b/test/risc/test_text_writer.rb @@ -1,7 +1,7 @@ require_relative "../helper" module Risc - class TestTextWriter < MiniTest::Test + class TestTextWriter #< MiniTest::Test def setup @machine = Risc.machine.boot @@ -13,10 +13,34 @@ module Risc @text_writer = TextWriter.new(@machine) assert_raises{ @text_writer.write_as_string} #must translate first end - def test_write_space - assert @machine.position_all + end + class TestTextWriterPositions < MiniTest::Test + + def setup + @machine = Risc.machine.boot + @machine.position_all @text_writer = TextWriter.new(@machine) + end + def test_write_all assert @text_writer.write_as_string end + def test_sorted_class + assert_equal Array , @text_writer.sorted_objects.class + end + def test_sorted_positions1 + sorted_objects = @text_writer.sorted_objects + sorted_objects.each_slice(2) do |l,r| + assert Position.get(l).at < Position.get(r).at , "#{Position.get(l)} < #{Position.get(r)} , #{l.class}, #{r.class}" + end + end + def test_sorted_positions2 + sorted_objects = @text_writer.sorted_objects + sorted_objects.shift + sorted_objects.each_slice(2) do |l,r| + next unless l + next unless r + assert Position.get(l).at < Position.get(r).at , "#{Position.get(l)} < #{Position.get(r)} , #{l.class}, #{r.class}" + end + end end end