diff --git a/lib/risc/builtin.rb b/lib/risc/builtin.rb index 988ec2a0..11553f10 100644 --- a/lib/risc/builtin.rb +++ b/lib/risc/builtin.rb @@ -51,8 +51,8 @@ module Risc Risc.operators.each do |op| #compilers << operator_compiler( int_type , op) end - [:putint, :div4, :div10 , :<,:<= , :>=, :>].each do |f| #div4 is just a forward declaration - #compilers << compiler_for( int_type , Integer , f) + [ :div4, :<,:<= , :>=, :> , :div10 ].each do |f| #div4 is just a forward declaration + compilers << compiler_for( int_type , Integer , f) end compilers end diff --git a/lib/risc/builtin/integer.rb b/lib/risc/builtin/integer.rb index eba3fc37..94c699d8 100644 --- a/lib/risc/builtin/integer.rb +++ b/lib/risc/builtin/integer.rb @@ -14,19 +14,25 @@ module Risc # return new int with result def div4(context) compiler = compiler_for(:Integer,:div4 ,{}) - 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 - compiler.add_mom( Mom::ReturnSequence.new) + 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( :> ) @@ -53,33 +59,35 @@ module Risc # - return def comparison( operator ) compiler = compiler_for(:Integer, operator ,{other: :Integer }) - builder = compiler.builder(compiler.source) - 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 - compiler.add_mom( Mom::ReturnSequence.new) + compiler.add_code Comparison.new("comparison" , operator) return compiler end - - # not implemented, would need a itos and that needs "new" (wip) - def putint(context) - compiler = compiler_for(:Integer,:putint ,{}) - compiler.add_mom( Mom::ReturnSequence.new) - return compiler + class Comparison < ::Mom::Instruction + attr_reader :operator + def initialize(name , operator) + @operator = operator + end + def to_risc(compiler) + builder = compiler.builder(compiler.source) + 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 @@ -115,67 +123,71 @@ module Risc # 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 ) - s = "div_10 " compiler = compiler_for(:Integer,:div10 ,{}) - 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 - - compiler.add_mom( Mom::ReturnSequence.new) + 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 diff --git a/test/risc/builtin/test_integer.rb b/test/risc/builtin/test_integer.rb new file mode 100644 index 00000000..a48ea153 --- /dev/null +++ b/test/risc/builtin/test_integer.rb @@ -0,0 +1,78 @@ +require_relative "helper" + +module Risc + module Builtin + class TestIntDiv4 < BootTest + def setup + super + @method = get_compiler(:div4) + end + def test_has_get_internal + assert_equal Mom::MethodCompiler , @method.class + end + def test_mom_length + assert_equal 5 , @method.mom_instructions.length + end + def test_compile + assert_equal Risc::MethodCompiler , @method.to_risc.class + end + def test_risc_length + assert_equal 47 , @method.to_risc.risc_instructions.length + end + end + class TestIntDiv10 < BootTest + def setup + super + @method = get_compiler(:div10) + end + def test_has_get_internal + assert_equal Mom::MethodCompiler , @method.class + end + def test_mom_length + assert_equal 5 , @method.mom_instructions.length + end + def test_compile + assert_equal Risc::MethodCompiler , @method.to_risc.class + end + def test_risc_length + assert_equal 76 , @method.to_risc.risc_instructions.length + end + end + class TestIntComp1 < BootTest + def setup + super + @method = get_compiler(:<) + end + def test_has_get_internal + assert_equal Mom::MethodCompiler , @method.class + end + def test_mom_length + assert_equal 5 , @method.mom_instructions.length + end + def test_compile + assert_equal Risc::MethodCompiler , @method.to_risc.class + end + def test_risc_length + assert_equal 27 , @method.to_risc.risc_instructions.length + end + end + class TestIntComp2 < BootTest + def setup + super + @method = get_compiler(:>=) + end + def test_has_get_internal + assert_equal Mom::MethodCompiler , @method.class + end + def test_mom_length + assert_equal 5 , @method.mom_instructions.length + end + def test_compile + assert_equal Risc::MethodCompiler , @method.to_risc.class + end + def test_risc_length + assert_equal 27 , @method.to_risc.risc_instructions.length + end + end + end +end diff --git a/test/risc/test_builtin.rb b/test/risc/test_builtin.rb index eb26f545..0829039d 100644 --- a/test/risc/test_builtin.rb +++ b/test/risc/test_builtin.rb @@ -14,7 +14,7 @@ module Risc assert_equal Array, @functions.class end def test_boot_function_length - assert_equal 9, @functions.length + assert_equal 15, @functions.length end def test_boot_function_first assert_equal Mom::MethodCompiler, @functions.first.class