fix (re)positioning when link exceptions are thrown

slow design, but sort of works
This commit is contained in:
Torsten Ruger 2018-05-01 19:48:11 +03:00
parent 1c52ab6b67
commit 6be28e7f55
3 changed files with 33 additions and 29 deletions

View File

@ -11,26 +11,9 @@ module Risc
@code = code @code = code
end end
# write into the given BinaryCode instance
# LinkException may be thrown, possibly several times
# So repeat until it works
def assemble( instruction )
not_ok = 1
while(not_ok)
begin
#puts "Not ok #{not_ok}"
#FIXME really need to reposition here, so jumps go right
assemble_all(instruction)
not_ok = false
rescue LinkException
not_ok += 1
end
end
end
# Go through and assemble all instructions. # Go through and assemble all instructions.
# Assembly may cause LinkException, which is caught by caller # Assembly may cause LinkException, which is caught by caller
def assemble_all( instruction ) def assemble( instruction )
@index = 1 @index = 1
while(instruction) while(instruction)
instruction.assemble(self) instruction.assemble(self)

View File

@ -79,14 +79,15 @@ module Risc
cpu_init.set_position( 0 ) cpu_init.set_position( 0 )
#Positioned.set_position(cpu_init.first , 0) #Positioned.set_position(cpu_init.first , 0)
Positioned.set_position(binary_init,0) Positioned.set_position(binary_init,0)
at = position_objects( binary_init.padded_length ) @code_start = position_objects( binary_init.padded_length )
# and then everything code # and then everything code
position_code_from( at ) position_code
end end
# go through everything that is not code (BinaryCode) and set position # go through everything that is not code (BinaryCode) and set position
# padded_length is what determines an objects (byte) length # padded_length is what determines an objects (byte) length
def position_objects( at ) # return final position that is stored in code_start
def position_objects(at)
# want to have the objects first in the executable # want to have the objects first in the executable
objects.each do | id , objekt| objects.each do | id , objekt|
next if objekt.is_a?( Parfait::BinaryCode) or objekt.is_a?( Risc::Label ) next if objekt.is_a?( Parfait::BinaryCode) or objekt.is_a?( Risc::Label )
@ -98,9 +99,13 @@ module Risc
# Position all BinaryCode. # Position all BinaryCode.
# #
# So that all code from one method is layed out linearly (for debuggin) # So that all code from one method is layed out linearly (for debugging)
# we go through methods, and then through all codes from the method # we go through methods, and then through all codes from the method
def position_code_from( at ) #
# start at @code_start. The method is called until
# assembly stops throwing errors
def position_code
at = @code_start
objects.each do |id , method| objects.each do |id , method|
next unless method.is_a? Parfait::TypedMethod next unless method.is_a? Parfait::TypedMethod
log.debug "POS1 #{method.name}:#{at.to_s(16)}" log.debug "POS1 #{method.name}:#{at.to_s(16)}"
@ -119,16 +124,32 @@ module Risc
# Create Binary code for all methods and the initial jump # Create Binary code for all methods and the initial jump
# BinaryWriter handles the writing from instructions into BinaryCode objects # BinaryWriter handles the writing from instructions into BinaryCode objects
#
# current (poor) design throws an exception when the assembly can't fit
# constant loads into one instruction.
#
def create_binary def create_binary
not_ok = 1
while(not_ok)
begin
return do_create_binary
rescue LinkException
not_ok += 1
puts "relink no #{not_ok}"
position_code
end
end
end
# have to retry until it works. Unfortunately (FIXME) jumps can go be both
# directions, and so already assembled codes get wrong by moving/ inserting
# instructions. And we end up assmebling all code again :-(
def do_create_binary
objects.each do |id , method| objects.each do |id , method|
next unless method.is_a? Parfait::TypedMethod next unless method.is_a? Parfait::TypedMethod
writer = BinaryWriter.new(method.binary) writer = BinaryWriter.new(method.binary)
writer.assemble(method.cpu_instructions) writer.assemble(method.cpu_instructions)
end end
puts "CPU init"
puts cpu_init.first.inspect[0...130]
puts Parfait.object_space.get_init.risc_instructions.inspect[0...130]
puts Parfait.object_space.get_init.cpu_instructions.inspect[0...130]
BinaryWriter.new(binary_init).assemble(cpu_init) BinaryWriter.new(binary_init).assemble(cpu_init)
end end

View File

@ -9,7 +9,7 @@ module Risc
class TextWriter class TextWriter
include Logging include Logging
log_level :debug log_level :info
MARKER = 0xBAD4C0DE MARKER = 0xBAD4C0DE
@ -109,7 +109,7 @@ module Risc
def write_object_check(object) def write_object_check(object)
log.debug "Write object #{object.class} #{object.inspect[0..100]}" log.debug "Write object #{object.class} #{object.inspect[0..100]}"
#Only initially created codes are collected. Binary_init and method "tails" not #Only initially created codes are collected. Binary_init and method "tails" not
if !@objects.has_key?(object.object_id) and !object.is_a?(Parfait::BinaryCode) if !@machine.objects.has_key?(object.object_id) and !object.is_a?(Parfait::BinaryCode)
log.debug "Object at 0x#{Positioned.position(object).to_s(16)}:#{object.get_type()}" log.debug "Object at 0x#{Positioned.position(object).to_s(16)}:#{object.get_type()}"
raise "Object(0x#{object.object_id.to_s(16)}) not linked #{object.inspect}" raise "Object(0x#{object.object_id.to_s(16)}) not linked #{object.inspect}"
end end