finished init routine

and better implemented sys calls
This commit is contained in:
Torsten Ruger 2015-06-25 16:31:09 +03:00
parent cedc6e1b61
commit 32e1903884
10 changed files with 57 additions and 26 deletions

View File

@ -14,6 +14,7 @@ module Arm
def initialize(first, attributes) def initialize(first, attributes)
super(attributes) super(attributes)
raise "no target" if first.nil?
@first = first @first = first
opcode = @attributes[:opcode].to_s opcode = @attributes[:opcode].to_s
if opcode.length == 3 and opcode[0] == "b" if opcode.length == 3 and opcode[0] == "b"
@ -32,7 +33,7 @@ module Arm
case @attributes[:opcode] case @attributes[:opcode]
when :b, :call when :b, :call
arg = @first arg = @first
#puts "BLAB #{arg.inspect}" puts "BLAB #{arg.class}"
if arg.is_a?(Virtual::Block) or arg.is_a?(Parfait::Method) if arg.is_a?(Virtual::Block) or arg.is_a?(Parfait::Method)
#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,

View File

@ -4,7 +4,7 @@ module Arm
def run block def run block
block.codes.dup.each do |code| block.codes.dup.each do |code|
next unless code.is_a? Register::LoadConstant next unless code.is_a? Register::LoadConstant
load = ArmMachine.ldr( code.value , code.constant ) load = ArmMachine.ldr( code.register , code.constant )
block.replace(code , load ) block.replace(code , load )
#puts "replaced #{load.inspect.to_s[0..1000]}" #puts "replaced #{load.inspect.to_s[0..1000]}"
end end

View File

@ -1,17 +1,37 @@
module Arm module Arm
class SyscallImplementation class SyscallImplementation
CALLS_CODES = { :putstring => 4 , :exit => 0 }
def run block def run block
block.codes.dup.each do |code| block.codes.dup.each do |code|
next unless code.is_a? Register::Syscall next unless code.is_a? Register::Syscall
raise "uups" unless code.name == :putstring new_codes = []
new_codes = [ ArmMachine.mov( :r1 , 20 ) ] int_code = CALLS_CODES[code.name]
new_codes << ArmMachine.ldr( :r0 , Virtual::Slot::MESSAGE_REGISTER, Virtual::SELF_INDEX) raise "Not implemented syscall, #{code.name}" unless int_code
new_codes << ArmMachine.mov( :r7 , 4 ) send( code.name , int_code , new_codes )
new_codes << ArmMachine.swi( 0 )
block.replace(code , new_codes ) block.replace(code , new_codes )
end end
end end
def putstring int_code , codes
codes << ArmMachine.mov( :r1 , 20 ) # String length, obvious TODO
codes << ArmMachine.ldr( :r0 , Virtual::Slot::MESSAGE_REGISTER, Virtual::SELF_INDEX)
syscall(int_code , codes )
end
def exit int_code , codes
syscall int_code , codes
end
private
# syscall is always triggered by swi(0)
# The actual code (ie the index of the kernel function) is in r7
def syscall int_code , codes
codes << ArmMachine.mov( :r7 , int_code )
codes << ArmMachine.swi( 0 )
end
end end
Virtual.machine.add_pass "Arm::SyscallImplementation" Virtual.machine.add_pass "Arm::SyscallImplementation"
end end

View File

@ -62,6 +62,11 @@ module Parfait
kernel.get_instance_method :main kernel.get_instance_method :main
end end
def get_init
kernel = get_class_by_name :Kernel
kernel.get_instance_method :__init__
end
# this is the way to instantiate classes (not Parfait::Class.new) # this is the way to instantiate classes (not Parfait::Class.new)
# so we get and keep exactly one per name # so we get and keep exactly one per name
def get_class_by_name name def get_class_by_name name

View File

@ -1,18 +1,24 @@
module Builtin module Builtin
module Kernel module Kernel
module ClassMethods module ClassMethods
# this is the really really first place the machine starts. # this is the really really first place the machine starts (apart from the jump here)
# it isn't really a function, ie it is jumped to (not called), exits and may not return # it isn't really a function, ie it is jumped to (not called), exits and may not return
# so it is responsible for initial setup (and relocation) # so it is responsible for initial setup
def __init__ context def __init__ context
function = Virtual::CompiledMethodInfo.create_method(:Kernel,:__init__ , []) function = Virtual::CompiledMethodInfo.create_method(:Kernel,:__init__ , [])
# puts "INIT LAYOUT #{function.get_layout.get_layout}"
function.info.return_type = Virtual::Integer function.info.return_type = Virtual::Integer
main = Virtual.machine.space.get_main # no method enter or return (automatically added), remove
me = Virtual::Self.new(Virtual::Reference) function.info.blocks.first.codes.pop # no Method enter
code = Virtual::Set.new(me , Virtual::Self.new(me.type)) function.info.blocks.last.codes.pop # no Method return
function.info.add_code(code) #Set up the Space as self upon init
function.info.add_code Virtual::MethodCall.new(main) space = Parfait::Space.object_space
function.info.add_code Register::LoadConstant.new( space , Virtual::Slot::SELF_REGISTER)
message_ind = space.get_layout().index_of( :next_message )
# Load the message to message register (0)
function.info.add_code Register::GetSlot.new( Virtual::Slot::SELF_REGISTER , message_ind , Virtual::Slot::MESSAGE_REGISTER)
# now we are set up to issue a call to the main
function.info.add_code Virtual::MethodCall.new(Virtual.machine.space.get_main)
emit_syscall( function , :exit )
return function return function
end end
def putstring context def putstring context
@ -49,7 +55,7 @@ module Builtin
space_tmp = Register::RegisterReference.tmp_reg space_tmp = Register::RegisterReference.tmp_reg
ind = Parfait::Space.object_space.get_layout().index_of( :syscall_message ) ind = Parfait::Space.object_space.get_layout().index_of( :syscall_message )
raise "index not found for :syscall_message" unless ind raise "index not found for :syscall_message" unless ind
function.info.add_code Register::LoadConstant.new( space_tmp , Parfait::Space.object_space ) function.info.add_code Register::LoadConstant.new( Parfait::Space.object_space , space_tmp)
function.info.add_code Register::SetSlot.new( Virtual::Slot::MESSAGE_REGISTER , space_tmp , ind) function.info.add_code Register::SetSlot.new( Virtual::Slot::MESSAGE_REGISTER , space_tmp , ind)
end end
def restore_message(function) def restore_message(function)

View File

@ -1,14 +1,14 @@
module Register module Register
# load a constant into a register # load a constant into a register
# #
# first argument is the register the constant is loaded into # first is the actual constant, either immediate register or object reference (from the space)
# second is the actual constant # second argument is the register the constant is loaded into
class LoadConstant < Instruction class LoadConstant < Instruction
def initialize value , constant def initialize constant , register
@value = value @register = register
@constant = constant @constant = constant
end end
attr_accessor :value , :constant attr_accessor :register , :constant
end end
end end

View File

@ -34,7 +34,7 @@ module Register
# a temporary place to store the new frame # a temporary place to store the new frame
frame_tmp = space_tmp.next_reg_use frame_tmp = space_tmp.next_reg_use
# move the spave to it's register (mov instruction gets the address of the object) # move the spave to it's register (mov instruction gets the address of the object)
new_codes = [ LoadConstant.new( space_tmp , Parfait::Space.object_space )] new_codes = [ LoadConstant.new( Parfait::Space.object_space , space_tmp )]
# find index in the space where to grab frame/message # find index in the space where to grab frame/message
ind = Parfait::Space.object_space.get_layout().index_of( kind ) ind = Parfait::Space.object_space.get_layout().index_of( kind )
raise "index not found for #{kind}.#{kind.class}" unless ind raise "index not found for #{kind}.#{kind.class}" unless ind

View File

@ -33,7 +33,7 @@ module Register
tmp = RegisterReference.tmp_reg tmp = RegisterReference.tmp_reg
# for constants we have to "move" the constants value # for constants we have to "move" the constants value
if( code.from.is_a?(Parfait::Value) or code.from.is_a?(Symbol)) if( code.from.is_a?(Parfait::Value) or code.from.is_a?(Symbol))
move1 = LoadConstant.new( tmp , code.from ) move1 = LoadConstant.new( code.from , tmp )
else # while otherwise we "load" else # while otherwise we "load"
move1 = GetSlot.new( code.from.reg , code.from.index , tmp ) move1 = GetSlot.new( code.from.reg , code.from.index , tmp )
end end

View File

@ -103,10 +103,9 @@ module Virtual
end end
obj = @class_mappings[:Kernel ] obj = @class_mappings[:Kernel ]
# create dummy main first, __init__ calls it # create dummy main first, __init__ calls it
[:putstring,:exit,:__send ].each do |f| [:putstring,:exit,:__send , :__init__ ].each do |f|
obj.add_instance_method Builtin::Kernel.send(f , nil) obj.add_instance_method Builtin::Kernel.send(f , nil)
end end
underscore_init = obj.add_instance_method Builtin::Kernel.send(:__init__, nil)
obj = @class_mappings[:Integer ] obj = @class_mappings[:Integer ]
[:putint,:fibo].each do |f| [:putint,:fibo].each do |f|

View File

@ -123,7 +123,7 @@ module Virtual
def boot def boot
boot_parfait! boot_parfait!
@init = Block.new("init",nil) @init = Block.new("init",nil)
@init.add_code Register::RegisterMain.new( self.space.get_main ) @init.add_code Register::RegisterMain.new( self.space.get_init )
@booted = true @booted = true
end end