start by moving positioned(module) to position(class)
This commit is contained in:
parent
43d5521cfc
commit
d65a982454
@ -47,12 +47,12 @@ module Arm
|
|||||||
# relative addressing for jumps/calls
|
# relative addressing for jumps/calls
|
||||||
# but because of the arm "theoretical" 3- stage pipeline,
|
# but because of the arm "theoretical" 3- stage pipeline,
|
||||||
# we have to subtract 2 words (fetch/decode)
|
# we have to subtract 2 words (fetch/decode)
|
||||||
arg = Positioned.position(@first) - Positioned.position(self) - 8
|
arg = Risc::Position.position(@first) - Risc::Position.position(self) - 8
|
||||||
when Parfait::BinaryCode
|
when Parfait::BinaryCode
|
||||||
# But, for methods, this happens to be the size of the object header,
|
# But, for methods, this happens to be the size of the object header,
|
||||||
# so there it balances out, but not blocks
|
# so there it balances out, but not blocks
|
||||||
# have to use the code, not the method object for methods
|
# have to use the code, not the method object for methods
|
||||||
arg = Positioned.position(@first) - Positioned.position(self) + 4
|
arg = Risc::Position.position(@first) - Risc::Position.position(self) + 4
|
||||||
else
|
else
|
||||||
arg = @first
|
arg = @first
|
||||||
end
|
end
|
||||||
|
@ -22,7 +22,7 @@ module Arm
|
|||||||
end
|
end
|
||||||
|
|
||||||
def set_position( position , count )
|
def set_position( position , count )
|
||||||
Positioned.set_position(self,position)
|
Risc::Position.set_position(self,position)
|
||||||
position += byte_length
|
position += byte_length
|
||||||
if self.next
|
if self.next
|
||||||
count += 1 #assumes 4 byte instructions, as does the whole setup
|
count += 1 #assumes 4 byte instructions, as does the whole setup
|
||||||
|
@ -95,7 +95,7 @@ module Arm
|
|||||||
(@left.is_a?(Symbol) and !Risc::RiscValue.look_like_reg(@left)))
|
(@left.is_a?(Symbol) and !Risc::RiscValue.look_like_reg(@left)))
|
||||||
# do pc relative addressing with the difference to the instuction
|
# do pc relative addressing with the difference to the instuction
|
||||||
# 8 is for the funny pipeline adjustment (ie pointing to fetch and not execute)
|
# 8 is for the funny pipeline adjustment (ie pointing to fetch and not execute)
|
||||||
right = Positioned.position(@left) - Positioned.position(self) - 8
|
right = Risc::Position.position(@left) - Risc::Position.position(self) - 8
|
||||||
if( (right < 0) && ((opcode == :add) || (opcode == :sub)) )
|
if( (right < 0) && ((opcode == :add) || (opcode == :sub)) )
|
||||||
right *= -1 # this works as we never issue sub only add
|
right *= -1 # this works as we never issue sub only add
|
||||||
set_opcode :sub # so (as we can't change the sign permanently) we can change the opcode
|
set_opcode :sub # so (as we can't change the sign permanently) we can change the opcode
|
||||||
|
@ -27,7 +27,7 @@ module Elf
|
|||||||
type.each_method do |f|
|
type.each_method do |f|
|
||||||
f.cpu_instructions.each do |label|
|
f.cpu_instructions.each do |label|
|
||||||
next unless label.is_a?(Risc::Label)
|
next unless label.is_a?(Risc::Label)
|
||||||
add_symbol "#{type.name}::#{f.name}:#{label.name}" , Positioned.position(label)
|
add_symbol "#{type.name}::#{f.name}:#{label.name}" , Risc::Position.position(label)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -37,12 +37,12 @@ module Elf
|
|||||||
if( slot.respond_to? :sof_reference_name )
|
if( slot.respond_to? :sof_reference_name )
|
||||||
label = "#{slot.sof_reference_name}"
|
label = "#{slot.sof_reference_name}"
|
||||||
else
|
else
|
||||||
label = "#{slot.class.name}::#{Positioned.position(slot).to_s(16)}"
|
label = "#{slot.class.name}::#{Position.position(slot).to_s(16)}"
|
||||||
end
|
end
|
||||||
label += "=#{slot}" if slot.is_a?(Symbol) or slot.is_a?(String)
|
label += "=#{slot}" if slot.is_a?(Symbol) or slot.is_a?(String)
|
||||||
add_symbol label , Positioned.position(slot)
|
add_symbol label , Position.position(slot)
|
||||||
if slot.is_a?(Parfait::TypedMethod)
|
if slot.is_a?(Parfait::TypedMethod)
|
||||||
add_symbol slot.name.to_s , Positioned.position(slot.binary)
|
add_symbol slot.name.to_s , Position.position(slot.binary)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -20,7 +20,7 @@ module Risc
|
|||||||
end
|
end
|
||||||
|
|
||||||
require_relative "risc/padding"
|
require_relative "risc/padding"
|
||||||
require_relative "risc/positioned"
|
require_relative "risc/position"
|
||||||
|
|
||||||
require "parfait"
|
require "parfait"
|
||||||
require_relative "risc/machine"
|
require_relative "risc/machine"
|
||||||
|
@ -46,7 +46,7 @@ module Risc
|
|||||||
|
|
||||||
# labels have the same position as their next
|
# labels have the same position as their next
|
||||||
def set_position( position , count = 0)
|
def set_position( position , count = 0)
|
||||||
Positioned.set_position(self,position)
|
Position.set_position(self,position)
|
||||||
self.next.set_position(position,count) if self.next
|
self.next.set_position(position,count) if self.next
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ module Risc
|
|||||||
def position_all
|
def position_all
|
||||||
translate_arm unless @translated
|
translate_arm unless @translated
|
||||||
#need the initial jump at 0 and then functions
|
#need the initial jump at 0 and then functions
|
||||||
Positioned.set_position(binary_init,0)
|
Position.set_position(binary_init,0)
|
||||||
cpu_init.set_position( 12 ,0)
|
cpu_init.set_position( 12 ,0)
|
||||||
@code_start = position_objects( binary_init.padded_length )
|
@code_start = position_objects( binary_init.padded_length )
|
||||||
# and then everything code
|
# and then everything code
|
||||||
@ -91,7 +91,7 @@ module Risc
|
|||||||
# 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 )
|
||||||
Positioned.set_position(objekt,at)
|
Position.set_position(objekt,at)
|
||||||
before = at
|
before = at
|
||||||
at += objekt.padded_length
|
at += objekt.padded_length
|
||||||
log.debug "Object #{objekt.class}:#{before.to_s(16)} len: #{(at - before).to_s(16)}"
|
log.debug "Object #{objekt.class}:#{before.to_s(16)} len: #{(at - before).to_s(16)}"
|
||||||
@ -114,7 +114,7 @@ module Risc
|
|||||||
before = at
|
before = at
|
||||||
nekst = method.binary
|
nekst = method.binary
|
||||||
while(nekst)
|
while(nekst)
|
||||||
Positioned.set_position(nekst , at)
|
Position.set_position(nekst , at)
|
||||||
at += nekst.padded_length
|
at += nekst.padded_length
|
||||||
nekst = nekst.next
|
nekst = nekst.next
|
||||||
end
|
end
|
||||||
|
47
lib/risc/position.rb
Normal file
47
lib/risc/position.rb
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
module Risc
|
||||||
|
# Positions are very different during compilation and run-time.
|
||||||
|
# At run-time they are inherrent to the object, and fixed.
|
||||||
|
# While during compilation we can move things about, and do not use the
|
||||||
|
# objects memory position at all.
|
||||||
|
#
|
||||||
|
# Furthermore, there are differnet kind of positions during compilation.
|
||||||
|
# Off course the object position as hinted above, but also instruction
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
# While the Position objects transmit the change that (re) positioning
|
||||||
|
# entails to affected objects.
|
||||||
|
|
||||||
|
class Position
|
||||||
|
@positions = {}
|
||||||
|
|
||||||
|
def self.positions
|
||||||
|
@positions
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.position(object)
|
||||||
|
pos = self.positions[object]
|
||||||
|
if pos == nil
|
||||||
|
str = "position accessed but not set, "
|
||||||
|
str += "0x#{object.object_id.to_s(16)}\n"
|
||||||
|
str += "for #{object.class} byte_length #{object.byte_length if object.respond_to?(:byte_length)} for #{object.inspect[0...130]}"
|
||||||
|
raise str
|
||||||
|
end
|
||||||
|
pos
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.set_position( object , pos )
|
||||||
|
raise "Position must be number not :#{pos}:" unless pos.is_a?(Numeric)
|
||||||
|
# resetting of position used to be error, but since relink and dynamic instruction size it is ok.
|
||||||
|
# in measures (of 32)
|
||||||
|
#puts "Setting #{pos} for #{self.class}"
|
||||||
|
old = Position.positions[object]
|
||||||
|
if old != nil and ((old - pos).abs > 10000)
|
||||||
|
raise "position set again #{pos}!=#{old} for #{object}"
|
||||||
|
end
|
||||||
|
self.positions[object] = pos
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -1,33 +0,0 @@
|
|||||||
# Helper module that extract position attribute.
|
|
||||||
module Positioned
|
|
||||||
@positions = {}
|
|
||||||
|
|
||||||
def self.positions
|
|
||||||
@positions
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.position(object)
|
|
||||||
pos = self.positions[object]
|
|
||||||
if pos == nil
|
|
||||||
str = "position accessed but not set, "
|
|
||||||
str += "0x#{object.object_id.to_s(16)}\n"
|
|
||||||
str += "for #{object.class} byte_length #{object.byte_length if object.respond_to?(:byte_length)} for #{object.inspect[0...130]}"
|
|
||||||
raise str
|
|
||||||
end
|
|
||||||
pos
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.set_position( object , pos )
|
|
||||||
raise "Position must be number not :#{pos}:" unless pos.is_a?(Numeric)
|
|
||||||
# resetting of position used to be error, but since relink and dynamic instruction size it is ok.
|
|
||||||
# in measures (of 32)
|
|
||||||
#puts "Setting #{pos} for #{self.class}"
|
|
||||||
old = Positioned.positions[object]
|
|
||||||
if old != nil and ((old - pos).abs > 10000)
|
|
||||||
raise "position set again #{pos}!=#{old} for #{object}"
|
|
||||||
end
|
|
||||||
self.positions[object] = pos
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
end
|
|
@ -41,7 +41,7 @@ module Risc
|
|||||||
def write_debug
|
def write_debug
|
||||||
@machine.objects.each do |id , objekt|
|
@machine.objects.each do |id , objekt|
|
||||||
next if objekt.is_a?(Risc::Label)
|
next if objekt.is_a?(Risc::Label)
|
||||||
log.debug "Linked #{objekt.class}:0x#{objekt.object_id.to_s(16)} at 0x#{Positioned.position(objekt).to_s(16)} / 0x#{objekt.padded_length.to_s(16)}"
|
log.debug "Linked #{objekt.class}:0x#{objekt.object_id.to_s(16)} at 0x#{Position.position(objekt).to_s(16)} / 0x#{objekt.padded_length.to_s(16)}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -71,16 +71,16 @@ module Risc
|
|||||||
# Write any object just logs a bit and passes to write_any_out
|
# Write any object just logs a bit and passes to write_any_out
|
||||||
def write_any( obj )
|
def write_any( obj )
|
||||||
write_any_log( obj , "Write")
|
write_any_log( obj , "Write")
|
||||||
if @stream.length != Positioned.position(obj)
|
if @stream.length != Position.position(obj)
|
||||||
raise "Write #{obj.class}:0x#{obj.object_id.to_s(16)} at 0x#{stream_position.to_s(16)} not 0x#{Positioned.position(obj).to_s(16)}"
|
raise "Write #{obj.class}:0x#{obj.object_id.to_s(16)} at 0x#{stream_position.to_s(16)} not 0x#{Position.position(obj).to_s(16)}"
|
||||||
end
|
end
|
||||||
write_any_out(obj)
|
write_any_out(obj)
|
||||||
write_any_log( obj , "Wrote")
|
write_any_log( obj , "Wrote")
|
||||||
Positioned.position(obj)
|
Position.position(obj)
|
||||||
end
|
end
|
||||||
|
|
||||||
def write_any_log( obj , at)
|
def write_any_log( obj , at)
|
||||||
log.debug "#{at} #{obj.class}:0x#{obj.object_id.to_s(16)} at stream 0x#{stream_position.to_s(16)} pos:0x#{Positioned.position(obj).to_s(16)} , 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:0x#{Position.position(obj).to_s(16)} , len:0x#{obj.padded_length.to_s(16)}"
|
||||||
end
|
end
|
||||||
|
|
||||||
# Most objects are the same and get passed to write_object
|
# Most objects are the same and get passed to write_object
|
||||||
@ -108,14 +108,14 @@ module Risc
|
|||||||
log.debug "type #{obj_written} , total #{obj_written + indexed_written} (array #{indexed_written})"
|
log.debug "type #{obj_written} , total #{obj_written + indexed_written} (array #{indexed_written})"
|
||||||
log.debug "Len = 0x#{object.get_length.to_s(16)} , inst =0x#{object.get_type.instance_length.to_s(16)}" if object.is_a? Parfait::Type
|
log.debug "Len = 0x#{object.get_length.to_s(16)} , inst =0x#{object.get_type.instance_length.to_s(16)}" if object.is_a? Parfait::Type
|
||||||
pad_after( obj_written + indexed_written )
|
pad_after( obj_written + indexed_written )
|
||||||
Positioned.position(object)
|
Position.position(object)
|
||||||
end
|
end
|
||||||
|
|
||||||
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 !@machine.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#{Position.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
|
||||||
end
|
end
|
||||||
@ -178,7 +178,7 @@ module Risc
|
|||||||
raise "length mismatch #{str.length} != #{string.char_length}" if str.length != string.char_length
|
raise "length mismatch #{str.length} != #{string.char_length}" if str.length != string.char_length
|
||||||
end
|
end
|
||||||
str = string.to_s if string.is_a? Symbol
|
str = string.to_s if string.is_a? Symbol
|
||||||
log.debug "#{string.class} is #{string} at 0x#{Positioned.position(string).to_s(16)} length 0x#{string.length.to_s(16)}"
|
log.debug "#{string.class} is #{string} at 0x#{Position.position(string).to_s(16)} length 0x#{string.length.to_s(16)}"
|
||||||
write_checked_string(string , str)
|
write_checked_string(string , str)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -206,7 +206,7 @@ module Risc
|
|||||||
when Fixnum
|
when Fixnum
|
||||||
@stream.write_signed_int_32(object)
|
@stream.write_signed_int_32(object)
|
||||||
else
|
else
|
||||||
@stream.write_signed_int_32(Positioned.position(object) + @load_at)
|
@stream.write_signed_int_32(Position.position(object) + @load_at)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -18,9 +18,9 @@ module Arm
|
|||||||
def test_method_call
|
def test_method_call
|
||||||
Risc.machine.boot
|
Risc.machine.boot
|
||||||
bin = Parfait::BinaryCode.new(1)
|
bin = Parfait::BinaryCode.new(1)
|
||||||
Positioned.set_position(bin , 0x20)
|
Risc::Position.set_position(bin , 0x20)
|
||||||
code = @machine.call( bin ,{} )#this jumps to the next instruction
|
code = @machine.call( bin ,{} )#this jumps to the next instruction
|
||||||
Positioned.set_position(code , 0)
|
Risc::Position.set_position(code , 0)
|
||||||
assert_code code , :call, [0x09,0x0,0x0,0xeb]
|
assert_code code , :call, [0x09,0x0,0x0,0xeb]
|
||||||
end
|
end
|
||||||
def test_swi
|
def test_swi
|
||||||
|
@ -22,7 +22,7 @@ module Arm
|
|||||||
end
|
end
|
||||||
def test_mov_big
|
def test_mov_big
|
||||||
code = @machine.mov :r0, 0x222 # is not 8 bit and can't be rotated by the arm system in one instruction
|
code = @machine.mov :r0, 0x222 # is not 8 bit and can't be rotated by the arm system in one instruction
|
||||||
code.set_position(0)
|
code.set_position(0,0)
|
||||||
begin # mov 512(0x200) = e3 a0 0c 02 add 34(0x22) = e2 90 00 22
|
begin # mov 512(0x200) = e3 a0 0c 02 add 34(0x22) = e2 90 00 22
|
||||||
assert_code code , :mov , [ 0x02,0x0c,0xb0,0xe3]
|
assert_code code , :mov , [ 0x02,0x0c,0xb0,0xe3]
|
||||||
rescue Risc::LinkException
|
rescue Risc::LinkException
|
||||||
|
@ -25,7 +25,7 @@ module Risc
|
|||||||
end
|
end
|
||||||
def test_has_positions
|
def test_has_positions
|
||||||
@machine.objects.each do |id,obj|
|
@machine.objects.each do |id,obj|
|
||||||
assert Positioned.position(obj)
|
assert Position.position(obj)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
require_relative "../helper"
|
require_relative "../helper"
|
||||||
|
|
||||||
class TestPositioned < MiniTest::Test
|
class TestPosition < MiniTest::Test
|
||||||
def setup
|
def setup
|
||||||
Risc.machine.boot unless Risc.machine.booted
|
Risc.machine.boot unless Risc.machine.booted
|
||||||
end
|
end
|
||||||
@ -22,10 +22,10 @@ class TestPositioned < MiniTest::Test
|
|||||||
assert_equal 32 , word.padded_length
|
assert_equal 32 , word.padded_length
|
||||||
end
|
end
|
||||||
def test_raises_no_init
|
def test_raises_no_init
|
||||||
assert_raises { Positioned.position(self)}
|
assert_raises { Position.position(self)}
|
||||||
end
|
end
|
||||||
def test_raises_set_nil
|
def test_raises_set_nil
|
||||||
assert_raises { Positioned.set_position(self,nil)}
|
assert_raises { Position.set_position(self,nil)}
|
||||||
end
|
end
|
||||||
def test_raises_reset_far
|
def test_raises_reset_far
|
||||||
assert_raises do
|
assert_raises do
|
||||||
|
Loading…
Reference in New Issue
Block a user