finished init routine
and better implemented sys calls
This commit is contained in:
parent
cedc6e1b61
commit
32e1903884
@ -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,
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user