removed the (too) fancy dsl. Also introduce register indirection
This commit is contained in:
parent
6433a394e7
commit
36f237c633
@ -23,7 +23,7 @@ module Arm
|
|||||||
immediate = @immediate
|
immediate = @immediate
|
||||||
|
|
||||||
arg = @right
|
arg = @right
|
||||||
if arg.is_a?(Vm::StringConstant)
|
if arg.is_a?(Vm::ObjectConstant)
|
||||||
# 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 oc pointing to fetch and not execute)
|
# 8 is for the funny pipeline adjustment (ie oc pointing to fetch and not execute)
|
||||||
arg = Vm::IntegerConstant.new( arg.position - self.position - 8 )
|
arg = Vm::IntegerConstant.new( arg.position - self.position - 8 )
|
||||||
|
@ -50,20 +50,21 @@ module Arm
|
|||||||
'a3' => 2, 'a4' => 3, 'v1' => 4, 'v2' => 5, 'v3' => 6, 'v4' => 7, 'v5' => 8,
|
'a3' => 2, 'a4' => 3, 'v1' => 4, 'v2' => 5, 'v3' => 6, 'v4' => 7, 'v5' => 8,
|
||||||
'v6' => 9, 'rfp' => 9, 'sl' => 10, 'fp' => 11, 'ip' => 12, 'sp' => 13,
|
'v6' => 9, 'rfp' => 9, 'sl' => 10, 'fp' => 11, 'ip' => 12, 'sp' => 13,
|
||||||
'lr' => 14, 'pc' => 15 }
|
'lr' => 14, 'pc' => 15 }
|
||||||
def reg name
|
def reg r_name
|
||||||
code = reg_code name
|
code = reg_code r_name
|
||||||
raise "no such register #{name}" unless code
|
raise "no such register #{r_name}" unless code
|
||||||
Arm::Register.new(name.to_sym , code )
|
Arm::Register.new(r_name.to_sym , code )
|
||||||
end
|
end
|
||||||
def reg_code name
|
def reg_code r_name
|
||||||
if name.is_a? Vm::Word
|
raise "double r #{r_name}" if( :rr1 == r_name)
|
||||||
name = "r#{name.register}"
|
if r_name.is_a? Vm::Word
|
||||||
|
r_name = r_name.register_symbol
|
||||||
end
|
end
|
||||||
if name.is_a? Fixnum
|
if r_name.is_a? Fixnum
|
||||||
name = "r#{name}"
|
r_name = "r#{r_name}"
|
||||||
end
|
end
|
||||||
r = REGISTERS[name.to_s]
|
r = REGISTERS[r_name.to_s]
|
||||||
raise "no reg #{name}" if r == nil
|
raise "no reg #{r_name}" if r == nil
|
||||||
r
|
r
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ module Arm
|
|||||||
immediate = @immediate
|
immediate = @immediate
|
||||||
|
|
||||||
right = @right
|
right = @right
|
||||||
if @left.is_a?(Vm::StringConstant)
|
if @left.is_a?(Vm::ObjectConstant)
|
||||||
# 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 = @left.position - self.position - 8
|
right = @left.position - self.position - 8
|
||||||
@ -36,7 +36,7 @@ module Arm
|
|||||||
right = Vm::IntegerConstant.new( right )
|
right = Vm::IntegerConstant.new( right )
|
||||||
end
|
end
|
||||||
if (right.is_a?(Vm::IntegerConstant))
|
if (right.is_a?(Vm::IntegerConstant))
|
||||||
if (right.integer.fits_u8?)
|
if true #TODO (right.integer.fits_u8?)
|
||||||
# no shifting needed
|
# no shifting needed
|
||||||
operand = right.integer
|
operand = right.integer
|
||||||
immediate = 1
|
immediate = 1
|
||||||
|
@ -29,14 +29,14 @@ module Arm
|
|||||||
add_offset = @add_offset
|
add_offset = @add_offset
|
||||||
|
|
||||||
arg = @left
|
arg = @left
|
||||||
arg = "r#{arg.register}".to_sym if( arg.is_a? Vm::Word )
|
arg = arg.register_symbol if( arg.is_a? Vm::Word )
|
||||||
#str / ldr are _serious instructions. With BIG possibilities not half are implemented
|
#str / ldr are _serious instructions. With BIG possibilities not half are implemented
|
||||||
if (arg.is_a?(Symbol)) #symbol is register
|
if (arg.is_a?(Symbol)) #symbol is register
|
||||||
rn = arg
|
rn = arg
|
||||||
if @right
|
if @right
|
||||||
operand = @right
|
operand = @right
|
||||||
#TODO better test, this operand integer (register) does not work. but sleep first
|
#TODO better test, this operand integer (register) does not work. but sleep first
|
||||||
operand = operand.register if operand.is_a? Vm::Integer
|
operand = operand.register_symbol if operand.is_a? Vm::Integer
|
||||||
unless( operand.is_a? Symbol)
|
unless( operand.is_a? Symbol)
|
||||||
puts "operand #{operand.inspect}"
|
puts "operand #{operand.inspect}"
|
||||||
if (operand < 0)
|
if (operand < 0)
|
||||||
@ -51,7 +51,7 @@ module Arm
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elsif (arg.is_a?(Vm::StringConstant) ) #use pc relative
|
elsif (arg.is_a?(Vm::ObjectConstant) ) #use pc relative
|
||||||
rn = :pc
|
rn = :pc
|
||||||
operand = arg.position - self.position - 8 #stringtable is after code
|
operand = arg.position - self.position - 8 #stringtable is after code
|
||||||
add_offset = 1
|
add_offset = 1
|
||||||
|
@ -12,10 +12,11 @@ module Arm
|
|||||||
|
|
||||||
@immediate = 0
|
@immediate = 0
|
||||||
@rn = :r0 # register zero = zero bit pattern
|
@rn = :r0 # register zero = zero bit pattern
|
||||||
# raise inspect if to.is_a?(Vm::Value) and
|
raise inspect if to.is_a?(Vm::Value) and
|
||||||
# from.is_a?(Vm::Value) and
|
from.is_a?(Vm::Value) and
|
||||||
# !@attributes[:shift_lsr] and
|
!@attributes[:shift_lsr] and
|
||||||
# to.register == from.register
|
to.register_symbol == from.register_symbol
|
||||||
|
raise "uups " if @to.register_symbol == :rr1
|
||||||
end
|
end
|
||||||
|
|
||||||
# arm intrucions are pretty sensible, and always 4 bytes (thumb not supported)
|
# arm intrucions are pretty sensible, and always 4 bytes (thumb not supported)
|
||||||
@ -30,7 +31,7 @@ module Arm
|
|||||||
immediate = @immediate
|
immediate = @immediate
|
||||||
|
|
||||||
right = @from
|
right = @from
|
||||||
if right.is_a?(Vm::StringConstant)
|
if right.is_a?(Vm::ObjectConstant)
|
||||||
# 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 oc pointing to fetch and not execute)
|
# 8 is for the funny pipeline adjustment (ie oc pointing to fetch and not execute)
|
||||||
right = Vm::IntegerConstant.new( right.position - self.position - 8 )
|
right = Vm::IntegerConstant.new( right.position - self.position - 8 )
|
||||||
|
@ -9,6 +9,7 @@ module Ast
|
|||||||
|
|
||||||
if receiver.name == :self
|
if receiver.name == :self
|
||||||
function = context.current_class.get_or_create_function(name)
|
function = context.current_class.get_or_create_function(name)
|
||||||
|
value = Vm::Integer.new(Vm::Function::RECEIVER_REG)
|
||||||
elsif receiver.is_a? ModuleName
|
elsif receiver.is_a? ModuleName
|
||||||
c_name = receiver.name
|
c_name = receiver.name
|
||||||
clazz = context.object_space.get_or_create_class c_name
|
clazz = context.object_space.get_or_create_class c_name
|
||||||
@ -23,6 +24,7 @@ module Ast
|
|||||||
else
|
else
|
||||||
# should be case switch for basic tyes and dynamic dispatch for objects reference
|
# should be case switch for basic tyes and dynamic dispatch for objects reference
|
||||||
value = context.locals[receiver.name]
|
value = context.locals[receiver.name]
|
||||||
|
raise "no value" unless value
|
||||||
function = context.current_class.get_or_create_function(name)
|
function = context.current_class.get_or_create_function(name)
|
||||||
end
|
end
|
||||||
raise "No such method error #{clazz.to_s}:#{name}" if function == nil
|
raise "No such method error #{clazz.to_s}:#{name}" if function == nil
|
||||||
|
@ -12,13 +12,12 @@ module Ast
|
|||||||
args << arg_value
|
args << arg_value
|
||||||
end
|
end
|
||||||
# class depends on receiver
|
# class depends on receiver
|
||||||
|
me = Vm::Integer.new( Vm::Function::RECEIVER_REG )
|
||||||
if receiver.nil?
|
if receiver.nil?
|
||||||
clazz = context.current_class
|
clazz = context.current_class
|
||||||
me = Vm::Integer.new( Vm::Function::RECEIVER_REG )
|
|
||||||
else
|
else
|
||||||
c = context.object_space.get_or_create_class receiver.name.to_sym
|
c = context.object_space.get_or_create_class receiver.name.to_sym
|
||||||
clazz = c.meta_class
|
clazz = c.meta_class
|
||||||
raise "get the constant loaded to 1"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function = Vm::Function.new(name , me , args )
|
function = Vm::Function.new(name , me , args )
|
||||||
@ -38,10 +37,10 @@ module Ast
|
|||||||
end
|
end
|
||||||
|
|
||||||
return_reg = Vm::Integer.new(7)
|
return_reg = Vm::Integer.new(7)
|
||||||
if last_compiled.is_a?(Vm::IntegerConstant) or last_compiled.is_a?(Vm::StringConstant)
|
if last_compiled.is_a?(Vm::IntegerConstant) or last_compiled.is_a?(Vm::ObjectConstant)
|
||||||
return_reg.load into , last_compiled if last_compiled.register != return_reg.register
|
return_reg.load into , last_compiled if last_compiled.register_symbol != return_reg.register_symbol
|
||||||
else
|
else
|
||||||
return_reg.move( into, last_compiled ) if last_compiled.register != return_reg.register
|
return_reg.move( into, last_compiled ) if last_compiled.register_symbol != return_reg.register_symbol
|
||||||
end
|
end
|
||||||
function.set_return return_reg
|
function.set_return return_reg
|
||||||
|
|
||||||
|
@ -18,7 +18,6 @@ module Ast
|
|||||||
end
|
end
|
||||||
|
|
||||||
l_val = left.compile(context , into)
|
l_val = left.compile(context , into)
|
||||||
into = into.scope binding
|
|
||||||
|
|
||||||
case operator
|
case operator
|
||||||
when ">"
|
when ">"
|
||||||
@ -33,7 +32,7 @@ module Ast
|
|||||||
code = l_val.equals into , r_val
|
code = l_val.equals into , r_val
|
||||||
when "+"
|
when "+"
|
||||||
res = context.function.new_local
|
res = context.function.new_local
|
||||||
into.res = l_val + r_val
|
into.add res , l_val , r_val
|
||||||
code = res
|
code = res
|
||||||
when "-"
|
when "-"
|
||||||
res = context.function.new_local
|
res = context.function.new_local
|
||||||
|
@ -7,10 +7,10 @@ module Ast
|
|||||||
# copied from function expression: TODO make function
|
# copied from function expression: TODO make function
|
||||||
|
|
||||||
return_reg = Vm::Integer.new(7)
|
return_reg = Vm::Integer.new(7)
|
||||||
if expression_value.is_a?(Vm::IntegerConstant) or expression_value.is_a?(Vm::StringConstant)
|
if expression_value.is_a?(Vm::IntegerConstant) or expression_value.is_a?(Vm::ObjectConstant)
|
||||||
return_reg.load into , expression_value
|
return_reg.load into , expression_value
|
||||||
else
|
else
|
||||||
return_reg.move( into, expression_value ) if expression_value.register != return_reg.register
|
return_reg.move( into, expression_value ) if expression_value.register_symbol != return_reg.register_symbol
|
||||||
end
|
end
|
||||||
#function.set_return return_reg
|
#function.set_return return_reg
|
||||||
return return_reg
|
return return_reg
|
||||||
|
@ -19,8 +19,8 @@ module Boot
|
|||||||
# The at_index is just "below" the api, somehting we need but don't want to expose, so we can't code the above in ruby
|
# The at_index is just "below" the api, somehting we need but don't want to expose, so we can't code the above in ruby
|
||||||
def _get_instance_variable context , name = Vm::Integer
|
def _get_instance_variable context , name = Vm::Integer
|
||||||
get_function = Vm::Function.new(:_get_instance_variable , Vm::Integer , [ Vm::Integer ] , Vm::Integer )
|
get_function = Vm::Function.new(:_get_instance_variable , Vm::Integer , [ Vm::Integer ] , Vm::Integer )
|
||||||
me = get_function.args[0]
|
me = get_function.receiver
|
||||||
var_name = get_function.args[1]
|
var_name = get_function.args.first
|
||||||
return_to = get_function.return_type
|
return_to = get_function.return_type
|
||||||
index_function = context.object_space.get_or_create_class(:Object).get_or_create_function(:index_of)
|
index_function = context.object_space.get_or_create_class(:Object).get_or_create_function(:index_of)
|
||||||
b = get_function.body
|
b = get_function.body
|
||||||
|
@ -36,7 +36,7 @@ module Core
|
|||||||
putint_function = Vm::Function.new(:putint , Vm::Integer , [] , Vm::Integer )
|
putint_function = Vm::Function.new(:putint , Vm::Integer , [] , Vm::Integer )
|
||||||
buffer = Vm::StringConstant.new(" ") # create a buffer
|
buffer = Vm::StringConstant.new(" ") # create a buffer
|
||||||
context.object_space.add_object buffer # and save it (function local variable: a no no)
|
context.object_space.add_object buffer # and save it (function local variable: a no no)
|
||||||
int = putint_function.args.first
|
int = putint_function.receiver
|
||||||
moved_int = putint_function.new_local
|
moved_int = putint_function.new_local
|
||||||
utoa = context.object_space.get_or_create_class(:Object).get_or_create_function(:utoa)
|
utoa = context.object_space.get_or_create_class(:Object).get_or_create_function(:utoa)
|
||||||
b = putint_function.body
|
b = putint_function.body
|
||||||
@ -44,7 +44,7 @@ module Core
|
|||||||
#b.a buffer => int # string to write to
|
#b.a buffer => int # string to write to
|
||||||
|
|
||||||
b.add( int , buffer ,nil ) # string to write to
|
b.add( int , buffer ,nil ) # string to write to
|
||||||
b.a int + (buffer.length-3) => int
|
b.add(int , int , buffer.length - 3)
|
||||||
b.call( utoa )
|
b.call( utoa )
|
||||||
# And now we "just" have to print it, using the write_stdout
|
# And now we "just" have to print it, using the write_stdout
|
||||||
b.add( int , buffer , nil ) # string to write to
|
b.add( int , buffer , nil ) # string to write to
|
||||||
@ -60,13 +60,13 @@ module Core
|
|||||||
# arguments: string address , integer
|
# arguments: string address , integer
|
||||||
def utoa context
|
def utoa context
|
||||||
utoa_function = Vm::Function.new(:utoa , Vm::Integer , [ Vm::Integer ] , Vm::Integer )
|
utoa_function = Vm::Function.new(:utoa , Vm::Integer , [ Vm::Integer ] , Vm::Integer )
|
||||||
str_addr = utoa_function.args[0]
|
str_addr = utoa_function.receiver
|
||||||
number = utoa_function.args[1]
|
number = utoa_function.args.first
|
||||||
remainder = utoa_function.new_local
|
remainder = utoa_function.new_local
|
||||||
Vm::RegisterMachine.instance.div10( utoa_function.body , number , remainder )
|
Vm::RegisterMachine.instance.div10( utoa_function.body , number , remainder )
|
||||||
# make char out of digit (by using ascii encoding) 48 == "0"
|
# make char out of digit (by using ascii encoding) 48 == "0"
|
||||||
b = utoa_function.body.scope binding
|
b = utoa_function.body
|
||||||
b.remainder = remainder + 48
|
b.add(remainder , remainder , 48)
|
||||||
b.strb( remainder, str_addr )
|
b.strb( remainder, str_addr )
|
||||||
b.sub( str_addr, str_addr , 1 )
|
b.sub( str_addr, str_addr , 1 )
|
||||||
b.cmp( number , 0 )
|
b.cmp( number , 0 )
|
||||||
@ -80,26 +80,26 @@ module Core
|
|||||||
# not my hand off course, found in the net from a basic introduction
|
# not my hand off course, found in the net from a basic introduction
|
||||||
def fibo context
|
def fibo context
|
||||||
fibo_function = Vm::Function.new(:fibo , Vm::Integer , [] , Vm::Integer )
|
fibo_function = Vm::Function.new(:fibo , Vm::Integer , [] , Vm::Integer )
|
||||||
result = Vm::Integer.new(7)
|
result = fibo_function.return_type
|
||||||
int = fibo_function.args[0]
|
int = fibo_function.receiver
|
||||||
count = fibo_function.new_local
|
count = fibo_function.new_local
|
||||||
f1 = fibo_function.new_local
|
f1 = fibo_function.new_local
|
||||||
f2 = fibo_function.new_local
|
f2 = fibo_function.new_local
|
||||||
b = fibo_function.body.scope binding
|
b = fibo_function.body
|
||||||
|
|
||||||
b.a int == 1
|
b.cmp int , 1
|
||||||
b.mov( result, int , condition_code: :le)
|
b.mov( result, int , condition_code: :le)
|
||||||
b.mov( :pc , :lr , condition_code: :le)
|
b.mov( :pc , :lr , condition_code: :le)
|
||||||
b.push [ count , f1 , f2 , :lr]
|
b.push [ count , f1 , f2 , :lr]
|
||||||
b.f1 = 1
|
b.mov f1 , 1
|
||||||
b.f2 = 0
|
b.mov f2 , 0
|
||||||
b.count = int - 2
|
b.sub count , int , 2
|
||||||
|
|
||||||
l = fibo_function.body.new_block("loop").scope binding
|
l = fibo_function.body.new_block("loop")
|
||||||
|
|
||||||
l.f1 = f1 + f2
|
l.add f1 , f1 , f2
|
||||||
l.f2 = f1 - f2
|
l.sub f2 , f1 , f2
|
||||||
l.count = (count - 1).set_update_status
|
l.sub count , count , 1 , set_update_status: 1
|
||||||
l.bpl( l )
|
l.bpl( l )
|
||||||
l.mov( result , f1 )
|
l.mov( result , f1 )
|
||||||
fibo_function.set_return result
|
fibo_function.set_return result
|
||||||
|
@ -24,14 +24,3 @@ module Support
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class Binding
|
|
||||||
#these are defined in 2.1 and thus the definitions should be conditional. TODO
|
|
||||||
def local_variable_defined? sym
|
|
||||||
vars = eval("local_variables")
|
|
||||||
vars.include? sym
|
|
||||||
end
|
|
||||||
def local_variable_get sym
|
|
||||||
eval(sym.to_s)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
@ -32,14 +32,8 @@ module Vm
|
|||||||
attr_reader :name , :next , :codes , :function
|
attr_reader :name , :next , :codes , :function
|
||||||
|
|
||||||
def add_code(kode)
|
def add_code(kode)
|
||||||
if kode.is_a? Hash
|
|
||||||
raise "Hack only for 1 element #{inspect} #{kode.inspect}" unless kode.length == 1
|
|
||||||
instruction , result = kode.first
|
|
||||||
instruction.assign result
|
|
||||||
kode = instruction
|
|
||||||
end
|
|
||||||
raise "alarm #{kode}" if kode.is_a? Word
|
raise "alarm #{kode}" if kode.is_a? Word
|
||||||
raise "alarm #{kode}" unless kode.is_a? Code
|
raise "alarm #{kode.class} #{kode}" unless kode.is_a? Code
|
||||||
@insert_at.codes << kode
|
@insert_at.codes << kode
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
@ -70,27 +64,8 @@ module Vm
|
|||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
# to use the assignment syntax (see method_missing) the scope must be set, so variables can be resolved
|
# sugar to create instructions easily.
|
||||||
# The scope you set should be a binding (literally, the kernel.binding)
|
# any method will be passed on to the RegisterMachine and the result added to the block
|
||||||
# The function return the block, so it can be chained into an assignment
|
|
||||||
# Example (coding a function ) and having variable int defined
|
|
||||||
# b = function.body.scope(binding)
|
|
||||||
# b.int = 5 will create a mov instruction to set the register that int points to
|
|
||||||
def scope where
|
|
||||||
@scope = where
|
|
||||||
self
|
|
||||||
end
|
|
||||||
|
|
||||||
# sugar to create instructions easily. Actually just got double sweet with two versions:
|
|
||||||
# 1 for any method that ends in = we evaluate the method name in the current scope (see scope())
|
|
||||||
# for the result we call assign with the right value. The resulting instruction is added to
|
|
||||||
# the block.
|
|
||||||
# Thus we emulate assignment,
|
|
||||||
# Example: block b
|
|
||||||
# b.variable = value looks like what it does, but actually generates
|
|
||||||
# an instruction for the block (mov or add)
|
|
||||||
#
|
|
||||||
# 2- any other method will be passed on to the RegisterMachine and the result added to the block
|
|
||||||
# With this trick we can write what looks like assembler,
|
# With this trick we can write what looks like assembler,
|
||||||
# Example b.instance_eval
|
# Example b.instance_eval
|
||||||
# mov( r1 , r2 )
|
# mov( r1 , r2 )
|
||||||
@ -98,16 +73,8 @@ module Vm
|
|||||||
# end
|
# end
|
||||||
# mov and add will be called on Machine and generate Inststuction that are then added
|
# mov and add will be called on Machine and generate Inststuction that are then added
|
||||||
# to the block
|
# to the block
|
||||||
|
# also symbols are supported and wrapped as register usages (for bare metal programming)
|
||||||
def method_missing(meth, *args, &block)
|
def method_missing(meth, *args, &block)
|
||||||
var = meth.to_s[0 ... -1]
|
|
||||||
if( args.length == 1) and ( meth.to_s[-1] == "=" )
|
|
||||||
if @scope.local_variable_defined? var.to_sym
|
|
||||||
l_val = @scope.local_variable_get var.to_sym
|
|
||||||
return add_code l_val.assign(args[0])
|
|
||||||
else
|
|
||||||
return super
|
|
||||||
end
|
|
||||||
end
|
|
||||||
add_code RegisterMachine.instance.send(meth , *args)
|
add_code RegisterMachine.instance.send(meth , *args)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ require_relative "meta_class"
|
|||||||
module Vm
|
module Vm
|
||||||
# class is mainly a list of functions with a name (for now)
|
# class is mainly a list of functions with a name (for now)
|
||||||
# layout of object is seperated into Layout
|
# layout of object is seperated into Layout
|
||||||
class BootClass < Code
|
class BootClass < ObjectConstant
|
||||||
def initialize name , context , super_class = :Object
|
def initialize name , context , super_class = :Object
|
||||||
super()
|
super()
|
||||||
@context = context
|
@context = context
|
||||||
|
@ -9,15 +9,23 @@ module Vm
|
|||||||
@value = value
|
@value = value
|
||||||
@args = args
|
@args = args
|
||||||
@function = function
|
@function = function
|
||||||
|
raise "oh #{name} " unless value
|
||||||
end
|
end
|
||||||
attr_reader :function , :args , :name , :value
|
attr_reader :function , :args , :name , :value
|
||||||
|
|
||||||
def load_args into
|
def load_args into
|
||||||
|
if value.is_a?(IntegerConstant) or value.is_a?(ObjectConstant)
|
||||||
|
function.receiver.load into , value
|
||||||
|
else
|
||||||
|
raise "meta #{name} " if value.is_a? MetaClass
|
||||||
|
function.receiver.move( into, value ) if value.register_symbol != function.receiver.register_symbol
|
||||||
|
end
|
||||||
|
raise "function call '#{name}' has #{args.length} arguments, but function has #{function.args.length}" if args.length != function.args.length
|
||||||
args.each_with_index do |arg , index|
|
args.each_with_index do |arg , index|
|
||||||
if arg.is_a?(IntegerConstant) or arg.is_a?(StringConstant)
|
if arg.is_a?(IntegerConstant) or arg.is_a?(StringConstant)
|
||||||
function.args[index].load into , arg
|
function.args[index].load into , arg
|
||||||
else
|
else
|
||||||
function.args[index].move( into, arg ) if arg.register != function.args[index].register
|
function.args[index].move( into, arg ) if arg.register_symbol != function.args[index].register_symbol
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -43,5 +43,6 @@ module Vm
|
|||||||
def assemble(io)
|
def assemble(io)
|
||||||
raise "Not implemented #{self.inspect}"
|
raise "Not implemented #{self.inspect}"
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
@ -9,6 +9,10 @@ module Vm
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# another abstract "marker" class (so we can check for it)
|
||||||
|
# derived classes are Boot/Meta Clas and StringConstant
|
||||||
|
class ObjectConstant < Constant
|
||||||
|
end
|
||||||
|
|
||||||
class IntegerConstant < Constant
|
class IntegerConstant < Constant
|
||||||
def initialize int
|
def initialize int
|
||||||
@ -25,7 +29,7 @@ module Vm
|
|||||||
# Currently string are stored "inline" , ie in the code segment.
|
# Currently string are stored "inline" , ie in the code segment.
|
||||||
# Mainly because that works an i aint no elf expert.
|
# Mainly because that works an i aint no elf expert.
|
||||||
|
|
||||||
class StringConstant < Constant
|
class StringConstant < ObjectConstant
|
||||||
attr_reader :string
|
attr_reader :string
|
||||||
# currently aligned to 4 (ie padded with 0) and off course 0 at the end
|
# currently aligned to 4 (ie padded with 0) and off course 0 at the end
|
||||||
def initialize str
|
def initialize str
|
||||||
|
@ -27,16 +27,16 @@ module Vm
|
|||||||
|
|
||||||
class Function < Code
|
class Function < Code
|
||||||
|
|
||||||
TYPE_REG = 0
|
TYPE_REG = :r0
|
||||||
RECEIVER_REG = 1
|
RECEIVER_REG = :r1
|
||||||
RETURN_REG = 7
|
RETURN_REG = :r7
|
||||||
|
|
||||||
def initialize(name , receiver = Vm::Integer , args = [] , return_type = Vm::Integer)
|
def initialize(name , receiver = Vm::Integer , args = [] , return_type = Vm::Integer)
|
||||||
super()
|
super()
|
||||||
@name = name.to_sym
|
@name = name.to_sym
|
||||||
if receiver.is_a?(Value)
|
if receiver.is_a?(Value)
|
||||||
@receiver = receiver
|
@receiver = receiver
|
||||||
raise "arg in non std register #{arg.inspect}" unless RECEIVER_REG == receiver.register
|
raise "arg in non std register #{arg.inspect}" unless RECEIVER_REG == receiver.register_symbol
|
||||||
else
|
else
|
||||||
@receiver = receiver.new(RECEIVER_REG)
|
@receiver = receiver.new(RECEIVER_REG)
|
||||||
end
|
end
|
||||||
@ -45,9 +45,9 @@ module Vm
|
|||||||
args.each_with_index do |arg , i|
|
args.each_with_index do |arg , i|
|
||||||
if arg.is_a?(Value)
|
if arg.is_a?(Value)
|
||||||
@args[i] = arg
|
@args[i] = arg
|
||||||
raise "arg in non std register #{arg.inspect}" unless (i+1+RECEIVER_REG) == arg.register
|
raise "arg in non std register #{arg.inspect}" unless RECEIVER_REG == arg.used_register.next_reg(i - 1)
|
||||||
else
|
else
|
||||||
@args[i] = arg.new(i+1+RECEIVER_REG)
|
@args[i] = arg.new(RegisterUse.new(RECEIVER_REG).next_reg(i + 1))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
set_return return_type
|
set_return return_type
|
||||||
@ -59,12 +59,12 @@ module Vm
|
|||||||
@blocks = []
|
@blocks = []
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_reader :args , :entry , :exit , :body , :name , :return_type , :revceiver
|
attr_reader :args , :entry , :exit , :body , :name , :return_type , :receiver
|
||||||
|
|
||||||
def set_return type_or_value
|
def set_return type_or_value
|
||||||
@return_type = type_or_value || Vm::Integer
|
@return_type = type_or_value || Vm::Integer
|
||||||
if @return_type.is_a?(Value)
|
if @return_type.is_a?(Value)
|
||||||
raise "return in non std register #{@return_type.inspect}" unless RETURN_REG == @return_type.register
|
raise "return in non std register #{@return_type.inspect}" unless RETURN_REG == @return_type.register_symbol
|
||||||
else
|
else
|
||||||
@return_type = @return_type.new(RETURN_REG)
|
@return_type = @return_type.new(RETURN_REG)
|
||||||
end
|
end
|
||||||
@ -76,7 +76,7 @@ module Vm
|
|||||||
def new_local type = Vm::Integer
|
def new_local type = Vm::Integer
|
||||||
register = args.length + 1 + @locals.length # one for the receiver implicit arg
|
register = args.length + 1 + @locals.length # one for the receiver implicit arg
|
||||||
l = type.new(register + 1) # one for the type register 0, TODO add type as arg0 implicitly
|
l = type.new(register + 1) # one for the type register 0, TODO add type as arg0 implicitly
|
||||||
puts "new local #{l.register}"
|
puts "new local #{l.register_symbol}"
|
||||||
# raise "Register overflow in function #{name}" if l.register > 6
|
# raise "Register overflow in function #{name}" if l.register > 6
|
||||||
@locals << l
|
@locals << l
|
||||||
l
|
l
|
||||||
@ -84,13 +84,13 @@ module Vm
|
|||||||
#BUG - must save receiver
|
#BUG - must save receiver
|
||||||
|
|
||||||
def save_locals context , into
|
def save_locals context , into
|
||||||
save = args.collect{|a| a.register } + @locals.collect{|l| l.register}
|
save = args.collect{|a| a.register_symbol } + @locals.collect{|l| l.register_symbol}
|
||||||
into.push(save) unless save.empty?
|
into.push(save) unless save.empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
def restore_locals context , into
|
def restore_locals context , into
|
||||||
#TODO assumes allocation in order, as the pop must be get regs in ascending order (also push)
|
#TODO assumes allocation in order, as the pop must be get regs in ascending order (also push)
|
||||||
restore = args.collect{|a| a.register } + @locals.collect{|l| l.register}
|
restore = args.collect{|a| a.register_symbol } + @locals.collect{|l| l.register_symbol}
|
||||||
into.pop(restore) unless restore.empty?
|
into.pop(restore) unless restore.empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -68,16 +68,6 @@ module Vm
|
|||||||
@right = right
|
@right = right
|
||||||
super(options)
|
super(options)
|
||||||
end
|
end
|
||||||
# this is used to write code that looks like assignment
|
|
||||||
# So instructions can be created without the result (register) set, and this assigns where
|
|
||||||
# the reuslt after the fact, but usually in the same line
|
|
||||||
# Example (with block b, and variables int,a,b): b.int = a + b
|
|
||||||
# a + b actually creates an add instruction while the b.int= assigns the result to int
|
|
||||||
# b.add( int , a , b) is an alternative (assmbler style) way of writing the same.
|
|
||||||
def assign left
|
|
||||||
@result = left
|
|
||||||
self
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
class MathInstruction < Instruction
|
class MathInstruction < Instruction
|
||||||
def initialize first , options = {}
|
def initialize first , options = {}
|
||||||
@ -96,7 +86,7 @@ module Vm
|
|||||||
def initialize to , from , options = {}
|
def initialize to , from , options = {}
|
||||||
@to = to
|
@to = to
|
||||||
@from = from
|
@from = from
|
||||||
raise inspect unless from
|
raise "move must have from set #{inspect}" unless from
|
||||||
super(options)
|
super(options)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -8,7 +8,7 @@ module Vm
|
|||||||
# PS: can't say i fancy the << self syntax and am considerernig adding a keyword for it, like meta
|
# PS: can't say i fancy the << self syntax and am considerernig adding a keyword for it, like meta
|
||||||
# In effect it is a very similar construct to def self.function(...)
|
# In effect it is a very similar construct to def self.function(...)
|
||||||
# So one could write def meta.function(...) and thus define on the meta-class
|
# So one could write def meta.function(...) and thus define on the meta-class
|
||||||
class MetaClass < Code
|
class MetaClass < ObjectConstant
|
||||||
# no name, nor nothing. as this is just the object really
|
# no name, nor nothing. as this is just the object really
|
||||||
|
|
||||||
def initialize(object)
|
def initialize(object)
|
||||||
|
@ -108,6 +108,7 @@ module Vm
|
|||||||
options = {} if options == nil
|
options = {} if options == nil
|
||||||
options.merge defaults
|
options.merge defaults
|
||||||
options[:opcode] = inst
|
options[:opcode] = inst
|
||||||
|
first = Vm::Integer.new(first) if first.is_a? Symbol
|
||||||
clazz.new(first , options)
|
clazz.new(first , options)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -118,6 +119,8 @@ module Vm
|
|||||||
create_method(inst) do |left ,right , options = nil|
|
create_method(inst) do |left ,right , options = nil|
|
||||||
options = {} if options == nil
|
options = {} if options == nil
|
||||||
options.merge defaults
|
options.merge defaults
|
||||||
|
left = Vm::Integer.new(left) if left.is_a? Symbol
|
||||||
|
right = Vm::Integer.new(right) if right.is_a? Symbol
|
||||||
options[:opcode] = inst
|
options[:opcode] = inst
|
||||||
clazz.new(left , right ,options)
|
clazz.new(left , right ,options)
|
||||||
end
|
end
|
||||||
@ -130,6 +133,9 @@ module Vm
|
|||||||
options = {} if options == nil
|
options = {} if options == nil
|
||||||
options.merge defaults
|
options.merge defaults
|
||||||
options[:opcode] = inst
|
options[:opcode] = inst
|
||||||
|
result = Vm::Integer.new(result) if result.is_a? Symbol
|
||||||
|
left = Vm::Integer.new(left) if left.is_a? Symbol
|
||||||
|
right = Vm::Integer.new(right) if right.is_a? Symbol
|
||||||
clazz.new(result, left , right ,options)
|
clazz.new(result, left , right ,options)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -53,9 +53,23 @@ module Vm
|
|||||||
# but which register can be changed, and _all_ instructions sharing the RegisterUse then use that register
|
# but which register can be changed, and _all_ instructions sharing the RegisterUse then use that register
|
||||||
# In other words a simple level of indirection, or change from value to reference sematics.
|
# In other words a simple level of indirection, or change from value to reference sematics.
|
||||||
class RegisterUse
|
class RegisterUse
|
||||||
attr_accessor :register
|
attr_accessor :symbol
|
||||||
def initialize r
|
def initialize r
|
||||||
@register = r
|
if( r.is_a? Fixnum)
|
||||||
|
r = "r#{r}".to_sym
|
||||||
|
end
|
||||||
|
raise "wrong type for register init #{r}" unless r.is_a? Symbol
|
||||||
|
raise "double r #{r}" if r == :rr1
|
||||||
|
@symbol = r
|
||||||
|
end
|
||||||
|
|
||||||
|
#helper methods to calculate with register symbols
|
||||||
|
def next_reg by = 1
|
||||||
|
int = @symbol[1,3].to_i
|
||||||
|
"r#{int + by}".to_sym
|
||||||
|
end
|
||||||
|
def next_reg_use by = 1
|
||||||
|
RegisterUse.new( next_reg(by) )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -66,23 +80,21 @@ module Vm
|
|||||||
|
|
||||||
attr_accessor :used_register
|
attr_accessor :used_register
|
||||||
|
|
||||||
def register
|
def register_symbol
|
||||||
@used_register.register
|
@used_register.symbol
|
||||||
end
|
end
|
||||||
|
|
||||||
def inspect
|
def inspect
|
||||||
self.class.name + "(r#{used_register.register})"
|
"#{self.class.name} (#{register_symbol})"
|
||||||
end
|
end
|
||||||
def to_s
|
def to_s
|
||||||
inspect
|
inspect
|
||||||
end
|
end
|
||||||
def initialize reg
|
def initialize reg
|
||||||
if reg.is_a? Fixnum
|
if reg.is_a? RegisterUse
|
||||||
@used_register = RegisterUse.new(reg)
|
|
||||||
else
|
|
||||||
@used_register = reg
|
@used_register = reg
|
||||||
|
else
|
||||||
|
@used_register = RegisterUse.new(reg)
|
||||||
end
|
end
|
||||||
raise inspect if reg == nil
|
|
||||||
end
|
end
|
||||||
def length
|
def length
|
||||||
4
|
4
|
||||||
@ -98,21 +110,6 @@ module Vm
|
|||||||
|
|
||||||
class Integer < Word
|
class Integer < Word
|
||||||
|
|
||||||
# part of the dsl.
|
|
||||||
# Gets called with either fixnum/IntegerConstant or an Instruction (usually logic, iw add...)
|
|
||||||
# For instructions we flip, ie call the assign on the instruction
|
|
||||||
# but for constants we have to create instruction first (mov)
|
|
||||||
def assign other
|
|
||||||
other = Vm::IntegerConstant.new(other) if other.is_a? Fixnum
|
|
||||||
if other.is_a?(Vm::IntegerConstant) or other.is_a?(Vm::Integer)
|
|
||||||
class_for(MoveInstruction).new( self , other , :opcode => :mov)
|
|
||||||
elsif other.is_a?(Vm::StringConstant) # pc relative addressing
|
|
||||||
class_for(LogicInstruction).new(self , other , nil , opcode: :add)
|
|
||||||
else
|
|
||||||
other.assign(self)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def less_or_equal block , right
|
def less_or_equal block , right
|
||||||
RegisterMachine.instance.integer_less_or_equal block , self , right
|
RegisterMachine.instance.integer_less_or_equal block , self , right
|
||||||
end
|
end
|
||||||
@ -155,7 +152,9 @@ module Vm
|
|||||||
block.mov( self , right ) #move the value
|
block.mov( self , right ) #move the value
|
||||||
elsif right.is_a? StringConstant
|
elsif right.is_a? StringConstant
|
||||||
block.add( self , right , nil) #move the address, by "adding" to pc, ie pc relative
|
block.add( self , right , nil) #move the address, by "adding" to pc, ie pc relative
|
||||||
block.mov( Integer.new(register+1) , right.length ) #and the length HACK TODO
|
block.mov( Integer.new(self.used_register.next_reg) , right.length ) #and the length HACK TODO
|
||||||
|
elsif right.is_a?(BootClass) or right.is_a?(MetaClass)
|
||||||
|
block.add( self , right , nil) #move the address, by "adding" to pc, ie pc relative
|
||||||
else
|
else
|
||||||
raise "unknown #{right.inspect}"
|
raise "unknown #{right.inspect}"
|
||||||
end
|
end
|
||||||
|
@ -21,7 +21,8 @@ def minus(a,b)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
putint(times(7,6))
|
tim = times(7,6)
|
||||||
|
tim.putint()
|
||||||
HERE
|
HERE
|
||||||
@should = [0x0,0x40,0x2d,0xe9,0x2,0x30,0x41,0xe0,0x3,0x70,0xa0,0xe1,0x0,0x80,0xbd,0xe8,0x0,0x40,0x2d,0xe9,0x2,0x30,0x41,0xe0,0x3,0x70,0xa0,0xe1,0x0,0x80,0xbd,0xe8]
|
@should = [0x0,0x40,0x2d,0xe9,0x2,0x30,0x41,0xe0,0x3,0x70,0xa0,0xe1,0x0,0x80,0xbd,0xe8,0x0,0x40,0x2d,0xe9,0x2,0x30,0x41,0xe0,0x3,0x70,0xa0,0xe1,0x0,0x80,0xbd,0xe8]
|
||||||
@output = " 42 "
|
@output = " 42 "
|
||||||
|
@ -5,7 +5,8 @@ class TestPutint < MiniTest::Test
|
|||||||
|
|
||||||
def test_putint
|
def test_putint
|
||||||
@string_input = <<HERE
|
@string_input = <<HERE
|
||||||
putint( 42 )
|
fourty_two = 42
|
||||||
|
fourty_two.putint()
|
||||||
HERE
|
HERE
|
||||||
@should = [0x0,0x40,0x2d,0xe9,0x1,0x20,0xa0,0xe1,0x20,0x10,0x8f,0xe2,0x9,0x10,0x81,0xe2,0xe9,0xff,0xff,0xeb,0x14,0x10,0x8f,0xe2,0xc,0x20,0xa0,0xe3,0x1,0x0,0xa0,0xe3,0x4,0x70,0xa0,0xe3,0x0,0x0,0x0,0xef,0x0,0x70,0xa0,0xe1,0x0,0x80,0xbd,0xe8,0x0,0x40,0x2d,0xe9,0x1,0x20,0xa0,0xe1,0x20,0x10,0x8f,0xe2,0x9,0x10,0x81,0xe2,0xe9,0xff,0xff,0xeb,0x14,0x10,0x8f,0xe2,0xc,0x20,0xa0,0xe3,0x1,0x0,0xa0,0xe3,0x4,0x70,0xa0,0xe3,0x0,0x0,0x0,0xef,0x0,0x70,0xa0,0xe1,0x0,0x80,0xbd,0xe8]
|
@should = [0x0,0x40,0x2d,0xe9,0x1,0x20,0xa0,0xe1,0x20,0x10,0x8f,0xe2,0x9,0x10,0x81,0xe2,0xe9,0xff,0xff,0xeb,0x14,0x10,0x8f,0xe2,0xc,0x20,0xa0,0xe3,0x1,0x0,0xa0,0xe3,0x4,0x70,0xa0,0xe3,0x0,0x0,0x0,0xef,0x0,0x70,0xa0,0xe1,0x0,0x80,0xbd,0xe8,0x0,0x40,0x2d,0xe9,0x1,0x20,0xa0,0xe1,0x20,0x10,0x8f,0xe2,0x9,0x10,0x81,0xe2,0xe9,0xff,0xff,0xeb,0x14,0x10,0x8f,0xe2,0xc,0x20,0xa0,0xe3,0x1,0x0,0xa0,0xe3,0x4,0x70,0xa0,0xe3,0x0,0x0,0x0,0xef,0x0,0x70,0xa0,0xe1,0x0,0x80,0xbd,0xe8]
|
||||||
@output = " 42 "
|
@output = " 42 "
|
||||||
@ -14,4 +15,3 @@ HERE
|
|||||||
write "putint"
|
write "putint"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -14,8 +14,8 @@ def fibonaccir( n )
|
|||||||
return a + b
|
return a + b
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
fib = fibonaccir( 10 )
|
||||||
putint(fibonaccir( 10 ))
|
fib.putint()
|
||||||
HERE
|
HERE
|
||||||
@should = [0x0,0x40,0x2d,0xe9,0x1,0x0,0x51,0xe3,0xe,0x0,0x0,0xda,0x1,0x20,0x41,0xe2,0x6,0x0,0x2d,0xe9,0x2,0x10,0xa0,0xe1,0xf8,0xff,0xff,0xeb,0x6,0x0,0xbd,0xe8,0x7,0x30,0xa0,0xe1,0x2,0x40,0x41,0xe2,0x1e,0x0,0x2d,0xe9,0x4,0x10,0xa0,0xe1,0xf2,0xff,0xff,0xeb,0x1e,0x0,0xbd,0xe8,0x7,0x50,0xa0,0xe1,0x5,0x60,0x83,0xe0,0x6,0x70,0xa0,0xe1,0x0,0x0,0x0,0xea,0x1,0x70,0xa0,0xe1,0x0,0x80,0xbd,0xe8,0x0,0x40,0x2d,0xe9,0x1,0x0,0x51,0xe3,0xe,0x0,0x0,0xda,0x1,0x20,0x41,0xe2,0x6,0x0,0x2d,0xe9,0x2,0x10,0xa0,0xe1,0xf8,0xff,0xff,0xeb,0x6,0x0,0xbd,0xe8,0x7,0x30,0xa0,0xe1,0x2,0x40,0x41,0xe2,0x1e,0x0,0x2d,0xe9,0x4,0x10,0xa0,0xe1,0xf2,0xff,0xff,0xeb,0x1e,0x0,0xbd,0xe8,0x7,0x50,0xa0,0xe1,0x5,0x60,0x83,0xe0,0x6,0x70,0xa0,0xe1,0x0,0x0,0x0,0xea,0x1,0x70,0xa0,0xe1,0x0,0x80,0xbd,0xe8]
|
@should = [0x0,0x40,0x2d,0xe9,0x1,0x0,0x51,0xe3,0xe,0x0,0x0,0xda,0x1,0x20,0x41,0xe2,0x6,0x0,0x2d,0xe9,0x2,0x10,0xa0,0xe1,0xf8,0xff,0xff,0xeb,0x6,0x0,0xbd,0xe8,0x7,0x30,0xa0,0xe1,0x2,0x40,0x41,0xe2,0x1e,0x0,0x2d,0xe9,0x4,0x10,0xa0,0xe1,0xf2,0xff,0xff,0xeb,0x1e,0x0,0xbd,0xe8,0x7,0x50,0xa0,0xe1,0x5,0x60,0x83,0xe0,0x6,0x70,0xa0,0xe1,0x0,0x0,0x0,0xea,0x1,0x70,0xa0,0xe1,0x0,0x80,0xbd,0xe8,0x0,0x40,0x2d,0xe9,0x1,0x0,0x51,0xe3,0xe,0x0,0x0,0xda,0x1,0x20,0x41,0xe2,0x6,0x0,0x2d,0xe9,0x2,0x10,0xa0,0xe1,0xf8,0xff,0xff,0xeb,0x6,0x0,0xbd,0xe8,0x7,0x30,0xa0,0xe1,0x2,0x40,0x41,0xe2,0x1e,0x0,0x2d,0xe9,0x4,0x10,0xa0,0xe1,0xf2,0xff,0xff,0xeb,0x1e,0x0,0xbd,0xe8,0x7,0x50,0xa0,0xe1,0x5,0x60,0x83,0xe0,0x6,0x70,0xa0,0xe1,0x0,0x0,0x0,0xea,0x1,0x70,0xa0,0xe1,0x0,0x80,0xbd,0xe8]
|
||||||
@output = " 55 "
|
@output = " 55 "
|
||||||
|
@ -16,8 +16,8 @@ def fibonaccit(n) # n == r0
|
|||||||
end #r5 <- r0 - 1 n=n-1 through r5 tmp
|
end #r5 <- r0 - 1 n=n-1 through r5 tmp
|
||||||
return b
|
return b
|
||||||
end # r0 <- r5
|
end # r0 <- r5
|
||||||
|
fibo = fibonaccit( 10 )
|
||||||
putint(fibonaccit( 10 ))
|
fibo.putint()
|
||||||
HERE
|
HERE
|
||||||
@should = [0x0,0x40,0x2d,0xe9,0x0,0x20,0xa0,0xe3,0x1,0x30,0xa0,0xe3,0x1,0x0,0x51,0xe3,0x6,0x0,0x0,0xda,0x2,0x40,0xa0,0xe1,0x3,0x20,0xa0,0xe1,0x3,0x50,0x84,0xe0,0x5,0x30,0xa0,0xe1,0x1,0x60,0x41,0xe2,0x6,0x10,0xa0,0xe1,0xf6,0xff,0xff,0xea,0x3,0x70,0xa0,0xe1,0x0,0x80,0xbd,0xe8,0x0,0x40,0x2d,0xe9,0x0,0x20,0xa0,0xe3,0x1,0x30,0xa0,0xe3,0x1,0x0,0x51,0xe3,0x6,0x0,0x0,0xda,0x2,0x40,0xa0,0xe1,0x3,0x20,0xa0,0xe1,0x3,0x50,0x84,0xe0,0x5,0x30,0xa0,0xe1,0x1,0x60,0x41,0xe2,0x6,0x10,0xa0,0xe1,0xf6,0xff,0xff,0xea,0x3,0x70,0xa0,0xe1,0x0,0x80,0xbd,0xe8]
|
@should = [0x0,0x40,0x2d,0xe9,0x0,0x20,0xa0,0xe3,0x1,0x30,0xa0,0xe3,0x1,0x0,0x51,0xe3,0x6,0x0,0x0,0xda,0x2,0x40,0xa0,0xe1,0x3,0x20,0xa0,0xe1,0x3,0x50,0x84,0xe0,0x5,0x30,0xa0,0xe1,0x1,0x60,0x41,0xe2,0x6,0x10,0xa0,0xe1,0xf6,0xff,0xff,0xea,0x3,0x70,0xa0,0xe1,0x0,0x80,0xbd,0xe8,0x0,0x40,0x2d,0xe9,0x0,0x20,0xa0,0xe3,0x1,0x30,0xa0,0xe3,0x1,0x0,0x51,0xe3,0x6,0x0,0x0,0xda,0x2,0x40,0xa0,0xe1,0x3,0x20,0xa0,0xe1,0x3,0x50,0x84,0xe0,0x5,0x30,0xa0,0xe1,0x1,0x60,0x41,0xe2,0x6,0x10,0xa0,0xe1,0xf6,0xff,0xff,0xea,0x3,0x70,0xa0,0xe1,0x0,0x80,0xbd,0xe8]
|
||||||
@output = " 55 "
|
@output = " 55 "
|
||||||
@ -31,8 +31,8 @@ HERE
|
|||||||
def test_kernel_fibo
|
def test_kernel_fibo
|
||||||
int = Vm::Integer.new(1)
|
int = Vm::Integer.new(1)
|
||||||
fibo = @object_space.get_or_create_class(:Object).get_or_create_function(:fibo)
|
fibo = @object_space.get_or_create_class(:Object).get_or_create_function(:fibo)
|
||||||
main = @object_space.main.scope binding
|
main = @object_space.main
|
||||||
main.int = 10
|
main.mov int , 10
|
||||||
ret = main.call( fibo )
|
ret = main.call( fibo )
|
||||||
main.mov( :r1 , :r7 )
|
main.mov( :r1 , :r7 )
|
||||||
putint = @object_space.get_or_create_class(:Object).get_or_create_function(:putint)
|
putint = @object_space.get_or_create_class(:Object).get_or_create_function(:putint)
|
||||||
|
Loading…
Reference in New Issue
Block a user