Torsten Rüger
fa0aa30386
Since Builtin generates risc, just like mom instructions, it was a design mistake to put builtin into risc in the first place. Now that borders are coming more into focus, it make much more sense to have the builtin in mom. In fact the instructions should be moved out and a seperate invocation mechanism used , so functions can be parsed, not generated (wip)
210 lines
7.2 KiB
Ruby
210 lines
7.2 KiB
Ruby
module Mom
|
|
module Builtin
|
|
# integer related kernel functions
|
|
# all these functions (return the function they implement) assume interger input
|
|
# Also the returned integer object has to be passed in to avoid having to allocate it.
|
|
#
|
|
# This means the methods will have to be renamed at some point and wrapped
|
|
module Integer
|
|
module ClassMethods
|
|
include CompileHelper
|
|
|
|
# div by 4, ie shift right by 2
|
|
# Mostly created for testing at this point, as it is short
|
|
# return new int with result
|
|
def div4(context)
|
|
compiler = compiler_for(:Integer,:div4 ,{})
|
|
compiler.add_code Div4.new("div4")
|
|
return compiler
|
|
end
|
|
class Div4 < ::Mom::Instruction
|
|
def to_risc(compiler)
|
|
builder = compiler.builder(compiler.source)
|
|
integer_tmp = builder.allocate_int
|
|
builder.build do
|
|
integer_self! << message[:receiver]
|
|
integer_self.reduce_int
|
|
integer_1! << 2
|
|
integer_self.op :>> , integer_1
|
|
integer_tmp[Parfait::Integer.integer_index] << integer_self
|
|
message[:return_value] << integer_tmp
|
|
end
|
|
return compiler
|
|
end
|
|
end
|
|
|
|
# implemented by the comparison
|
|
def >( context )
|
|
comparison( :> )
|
|
end
|
|
# implemented by the comparison
|
|
def <( context )
|
|
comparison( :< )
|
|
end
|
|
# implemented by the comparison
|
|
def <=( context )
|
|
comparison( :<= )
|
|
end
|
|
# implemented by the comparison
|
|
def >=( context )
|
|
comparison( :>= )
|
|
end
|
|
|
|
# all (four) comparison operation are quite similar and implemented here
|
|
# - reduce the ints (assume int as input)
|
|
# - subtract the fixnums
|
|
# - check for minus ( < and > )
|
|
# - also check for zero (<= and >=)
|
|
# - load true or false object into return, depending on check
|
|
# - return
|
|
def comparison( operator )
|
|
compiler = compiler_for(:Integer, operator ,{other: :Integer })
|
|
compiler.add_code Comparison.new("comparison" , operator)
|
|
return compiler
|
|
end
|
|
class Comparison < ::Mom::Instruction
|
|
attr_reader :operator
|
|
def initialize(name , operator)
|
|
super(name)
|
|
@operator = operator
|
|
end
|
|
def to_risc(compiler)
|
|
builder = compiler.builder(compiler.source)
|
|
operator = @operator # make accessible in block
|
|
builder.build do
|
|
integer! << message[:receiver]
|
|
integer.reduce_int
|
|
integer_reg! << message[:arguments]
|
|
integer_reg << integer_reg[Parfait::NamedList.type_length + 0] #"other" is at index 0
|
|
integer_reg.reduce_int
|
|
swap_names(:integer , :integer_reg) if(operator.to_s.start_with?('<') )
|
|
integer.op :- , integer_reg
|
|
if_minus false_label
|
|
if_zero( false_label ) if operator.to_s.length == 1
|
|
object! << Parfait.object_space.true_object
|
|
branch merge_label
|
|
add_code false_label
|
|
object << Parfait.object_space.false_object
|
|
add_code merge_label
|
|
message[:return_value] << object
|
|
end
|
|
return compiler
|
|
end
|
|
end
|
|
|
|
# implemented all known binary operators that map straight to machine codes
|
|
# this function (similar to comparison):
|
|
# - unpacks the intergers to fixnum
|
|
# - applies the operator (at a risc level)
|
|
# - gets a new integer and stores the result
|
|
# - returns the new int
|
|
def operator_method( op_sym )
|
|
compiler = compiler_for(:Integer, op_sym ,{other: :Integer })
|
|
compiler.add_code OperatorInstruction.new("operator" , op_sym)
|
|
return compiler
|
|
end
|
|
class OperatorInstruction < ::Mom::Instruction
|
|
attr_reader :operator
|
|
def initialize(name , operator)
|
|
super(name)
|
|
@operator = operator
|
|
end
|
|
|
|
def to_risc(compiler)
|
|
builder = compiler.builder(compiler.source)
|
|
integer_tmp = builder.allocate_int
|
|
operator = @operator # make accessible in block
|
|
builder.build do
|
|
integer! << message[:receiver]
|
|
integer.reduce_int
|
|
integer_reg! << message[:arguments]
|
|
integer_reg << integer_reg[Parfait::NamedList.type_length + 0] #"other" is at index 0
|
|
integer_reg.reduce_int
|
|
integer.op operator , integer_reg
|
|
integer_tmp[Parfait::Integer.integer_index] << integer
|
|
message[:return_value] << integer_tmp
|
|
end
|
|
return compiler
|
|
end
|
|
end
|
|
|
|
# as the name suggests, this devides the integer (self) by ten
|
|
#
|
|
# This version is lifted from some arm assembler tricks and is _much_
|
|
# faster than the general div versions. I think it was about three
|
|
# times less instructions. Useful for itos
|
|
#
|
|
# In fact it is possible to generate specific div function for any given
|
|
# integer and some are even more faster (as eg div4).
|
|
def div10( context )
|
|
compiler = compiler_for(:Integer,:div10 ,{})
|
|
compiler.add_code Div10.new("div10")
|
|
return compiler
|
|
end
|
|
class Div10 < ::Mom::Instruction
|
|
def to_risc(compiler)
|
|
s = "div_10 "
|
|
builder = compiler.builder(compiler.source)
|
|
integer_tmp = builder.allocate_int
|
|
builder.build do
|
|
integer_self! << message[:receiver]
|
|
integer_self.reduce_int
|
|
integer_1! << integer_self
|
|
integer_reg! << integer_self
|
|
|
|
integer_const! << 1
|
|
integer_1.op :>> , integer_const
|
|
|
|
integer_const << 2
|
|
integer_reg.op :>> , integer_const
|
|
integer_reg.op :+ , integer_1
|
|
|
|
integer_const << 4
|
|
integer_1 << integer_reg
|
|
integer_reg.op :>> , integer_1
|
|
|
|
integer_reg.op :+ , integer_1
|
|
|
|
integer_const << 8
|
|
integer_1 << integer_reg
|
|
integer_1.op :>> , integer_const
|
|
|
|
integer_reg.op :+ , integer_1
|
|
|
|
integer_const << 16
|
|
integer_1 << integer_reg
|
|
integer_1.op :>> , integer_const
|
|
|
|
integer_reg.op :+ , integer_1
|
|
|
|
integer_const << 3
|
|
integer_reg.op :>> , integer_const
|
|
|
|
integer_const << 10
|
|
integer_1 << integer_reg
|
|
integer_1.op :* , integer_const
|
|
|
|
integer_self.op :- , integer_1
|
|
integer_1 << integer_self
|
|
|
|
integer_const << 6
|
|
integer_1.op :+ , integer_const
|
|
|
|
integer_const << 4
|
|
integer_1.op :>> , integer_const
|
|
|
|
integer_reg.op :+ , integer_1
|
|
|
|
integer_tmp[Parfait::Integer.integer_index] << integer_reg
|
|
message[:return_value] << integer_tmp
|
|
|
|
end
|
|
return compiler
|
|
end
|
|
end
|
|
end
|
|
extend ClassMethods
|
|
end
|
|
end
|
|
end
|