From 6e941ebcb7ad052fc683227c5d67cd15ba42637a Mon Sep 17 00:00:00 2001 From: Torsten Ruger Date: Sat, 31 Mar 2018 12:38:30 +0300 Subject: [PATCH] introduce load_data instruction which just loads data to a register (used internally) as opposed to integers, which are objects --- lib/arm/translator.rb | 10 +++---- lib/risc/builtin/integer.rb | 22 +++++++-------- lib/risc/instruction.rb | 1 + lib/risc/instructions/load_constant.rb | 2 +- lib/risc/instructions/load_data.rb | 27 +++++++++++++++++++ lib/risc/interpreter.rb | 1 + lib/risc/method_compiler.rb | 3 ++- .../interpreter/{test_add.rb => test_mod.rb} | 2 +- test/risc/interpreter/test_plus.rb | 2 +- test/risc/interpreter/test_return_call.rb | 12 ++++----- 10 files changed, 56 insertions(+), 26 deletions(-) create mode 100644 lib/risc/instructions/load_data.rb rename test/risc/interpreter/{test_add.rb => test_mod.rb} (98%) diff --git a/lib/arm/translator.rb b/lib/arm/translator.rb index 02d44725..966763a1 100644 --- a/lib/arm/translator.rb +++ b/lib/arm/translator.rb @@ -79,11 +79,11 @@ module Arm def translate_LoadConstant( code ) constant = code.constant constant = constant.to_cpu(self) if constant.is_a?(Risc::Label) - if constant.is_a?(Parfait::Object) or constant.is_a?(Symbol) or constant.is_a?(Risc::Label) - return ArmMachine.add( code.register , constant ) - else - return ArmMachine.mov( code.register , constant ) - end + return ArmMachine.add( code.register , constant ) + end + + def translate_LoadData( code ) + return ArmMachine.mov( code.register , code.constant ) end def translate_OperatorInstruction( code ) diff --git a/lib/risc/builtin/integer.rb b/lib/risc/builtin/integer.rb index 2709f784..2b9d874a 100644 --- a/lib/risc/builtin/integer.rb +++ b/lib/risc/builtin/integer.rb @@ -20,8 +20,8 @@ module Risc compiler = compiler_for(:Integer,:+ ,{other: :int}) me , other = self_and_int_arg(compiler,source + "1") # reduce me and other to integers - compiler.add_slot_to_reg( source + "2" , me , 1 , me) - compiler.add_slot_to_reg( source + "3", other , 1 , other) + compiler.add_slot_to_reg( source + "2" , me , 2 , me) + compiler.add_slot_to_reg( source + "3", other , 2 , other) compiler.add_code Risc.op( source + "4", :+ , me , other) #TODO must get an Integer and put the value there then return the integer (object not value) # and put it back into the return value @@ -36,47 +36,47 @@ module Risc tmp = compiler.add_known( :receiver ) q = compiler.add_known( :receiver ) const = compiler.use_reg :Integer , 1 - compiler.add_load_constant( s, 1 , const ) + compiler.add_load_data( s, 1 , const ) # int tmp = self >> 1 compiler.add_code Risc.op( s , :>> , tmp , const) # int q = self >> 2 - compiler.add_load_constant( s , 2 , const) + compiler.add_load_data( s , 2 , const) compiler.add_code Risc.op( s , :>> , q , const) # q = q + tmp compiler.add_code Risc.op( s , :+ , q , tmp ) # tmp = q >> 4 - compiler.add_load_constant( s , 4 , const) + compiler.add_load_data( s , 4 , const) compiler.add_transfer( s, q , tmp) compiler.add_code Risc.op( s , :>> , tmp , const) # q = q + tmp compiler.add_code Risc.op( s , :+ , q , tmp ) # tmp = q >> 8 - compiler.add_load_constant( s , 8 , const) + compiler.add_load_data( s , 8 , const) compiler.add_transfer( s, q , tmp) compiler.add_code Risc.op( s , :>> , tmp , const) # q = q + tmp compiler.add_code Risc.op( s , :+ , q , tmp ) # tmp = q >> 16 - compiler.add_load_constant( s , 16 , const) + compiler.add_load_data( s , 16 , const) compiler.add_transfer( s, q , tmp) compiler.add_code Risc.op( s , :>> , tmp , const) # q = q + tmp compiler.add_code Risc.op( s , :+ , q , tmp ) # q = q >> 3 - compiler.add_load_constant( s , 3 , const) + compiler.add_load_data( s , 3 , const) compiler.add_code Risc.op( s , :>> , q , const) # tmp = q * 10 - compiler.add_load_constant( s , 10 , const) + compiler.add_load_data( s , 10 , const) compiler.add_transfer( s, q , tmp) compiler.add_code Risc.op( s , :* , tmp , const) # tmp = self - tmp compiler.add_code Risc.op( s , :- , me , tmp ) compiler.add_transfer( s , me , tmp) # tmp = tmp + 6 - compiler.add_load_constant( s , 6 , const) + compiler.add_load_data( s , 6 , const) compiler.add_code Risc.op( s , :+ , tmp , const ) # tmp = tmp >> 4 - compiler.add_load_constant( s , 4 , const) + compiler.add_load_data( s , 4 , const) compiler.add_code Risc.op( s , :>> , tmp , const ) # return q + tmp compiler.add_code Risc.op( s , :+ , q , tmp ) diff --git a/lib/risc/instruction.rb b/lib/risc/instruction.rb index 0ded966e..b0e3d3f6 100644 --- a/lib/risc/instruction.rb +++ b/lib/risc/instruction.rb @@ -59,6 +59,7 @@ require_relative "instructions/slot_to_reg" require_relative "instructions/reg_to_byte" require_relative "instructions/byte_to_reg" require_relative "instructions/load_constant" +require_relative "instructions/load_data" require_relative "instructions/syscall" require_relative "instructions/function_call" require_relative "instructions/function_return" diff --git a/lib/risc/instructions/load_constant.rb b/lib/risc/instructions/load_constant.rb index b6f7875e..07fd6d72 100644 --- a/lib/risc/instructions/load_constant.rb +++ b/lib/risc/instructions/load_constant.rb @@ -20,7 +20,7 @@ module Risc private def constant_str case @constant - when String , Symbol , Fixnum , Integer + when String , Symbol @constant.to_s else if( @constant.respond_to? :sof_reference_name ) diff --git a/lib/risc/instructions/load_data.rb b/lib/risc/instructions/load_data.rb new file mode 100644 index 00000000..19dc3bf6 --- /dev/null +++ b/lib/risc/instructions/load_data.rb @@ -0,0 +1,27 @@ +module Risc + # load raw data into a register + # + # This is not really used by the compiler, or to be more precise: not used during the + # compilation of ruby code. Ruby code works on Objects only + # + # But for Builtin methods, methods that are created programatically and form the runtime, + # it can be handy to load an integer directly withou the object overhead. + # + class LoadData < Instruction + def initialize( source , constant , register) + super(source) + @register = register + @constant = constant + raise "Not Integer #{constant}" unless constant.is_a?(Integer) + end + attr_accessor :register , :constant + + def to_s + class_source "#{register} <- #{constant}" + end + + end + def self.load_data( source , constant , register ) + LoadData.new( source , constant , register) + end +end diff --git a/lib/risc/interpreter.rb b/lib/risc/interpreter.rb index 7806aa1c..29af8a06 100644 --- a/lib/risc/interpreter.rb +++ b/lib/risc/interpreter.rb @@ -125,6 +125,7 @@ module Risc set_register( to , value ) true end + alias :execute_LoadData :execute_LoadConstant def execute_SlotToReg object = get_register( @instruction.array ) diff --git a/lib/risc/method_compiler.rb b/lib/risc/method_compiler.rb index 793e529f..50ae327f 100644 --- a/lib/risc/method_compiler.rb +++ b/lib/risc/method_compiler.rb @@ -92,7 +92,8 @@ module Risc # for computationally building code (ie writing assembler) these short cuts # help to instantiate risc instructions and add them immediately - [:label, :reg_to_slot , :slot_to_reg , :load_constant, :function_return , :function_call, + [:label, :reg_to_slot , :slot_to_reg , :load_constant, :load_data, + :function_return , :function_call, :transfer , :reg_to_slot , :byte_to_reg , :reg_to_byte].each do |method| define_method("add_#{method}".to_sym) do |*args| add_code Risc.send( method , *args ) diff --git a/test/risc/interpreter/test_add.rb b/test/risc/interpreter/test_mod.rb similarity index 98% rename from test/risc/interpreter/test_add.rb rename to test/risc/interpreter/test_mod.rb index e086b1e9..cedd3ee3 100644 --- a/test/risc/interpreter/test_add.rb +++ b/test/risc/interpreter/test_mod.rb @@ -1,7 +1,7 @@ require_relative "helper" module Risc - class InterpreterAdd < MiniTest::Test + class InterpreterMod < MiniTest::Test include Ticker def setup diff --git a/test/risc/interpreter/test_plus.rb b/test/risc/interpreter/test_plus.rb index a3c5fa1b..c7c8d75c 100644 --- a/test/risc/interpreter/test_plus.rb +++ b/test/risc/interpreter/test_plus.rb @@ -31,7 +31,7 @@ module Risc assert_equal 9 , sl.index assert_equal :r3 , sl.register.symbol end - def test_slot2 #load arg from args + def est_slot2 #load arg from args sl = ticks( 48 ) assert_equal SlotToReg , sl.class assert_equal :r2 , sl.array.symbol #load from message diff --git a/test/risc/interpreter/test_return_call.rb b/test/risc/interpreter/test_return_call.rb index 5a9d5029..9055d959 100644 --- a/test/risc/interpreter/test_return_call.rb +++ b/test/risc/interpreter/test_return_call.rb @@ -22,12 +22,12 @@ module Risc SlotToReg, RegToSlot, LoadConstant, SlotToReg, RegToSlot, LoadConstant, SlotToReg, RegToSlot, SlotToReg, LoadConstant, FunctionCall, Label, SlotToReg, SlotToReg, SlotToReg, - LoadConstant, OperatorInstruction, LoadConstant, OperatorInstruction, OperatorInstruction, - LoadConstant, Transfer, OperatorInstruction, OperatorInstruction, LoadConstant, - Transfer, OperatorInstruction, OperatorInstruction, LoadConstant, Transfer, - OperatorInstruction, OperatorInstruction, LoadConstant, OperatorInstruction, LoadConstant, - Transfer, OperatorInstruction, OperatorInstruction, Transfer, LoadConstant, - OperatorInstruction, LoadConstant, OperatorInstruction, OperatorInstruction, RegToSlot, + LoadData, OperatorInstruction, LoadData, OperatorInstruction, OperatorInstruction, + LoadData, Transfer, OperatorInstruction, OperatorInstruction, LoadData, + Transfer, OperatorInstruction, OperatorInstruction, LoadData, Transfer, + OperatorInstruction, OperatorInstruction, LoadData, OperatorInstruction, LoadData, + Transfer, OperatorInstruction, OperatorInstruction, Transfer, LoadData, + OperatorInstruction, LoadData, OperatorInstruction, OperatorInstruction, RegToSlot, SlotToReg, SlotToReg, RegToSlot, SlotToReg, SlotToReg, FunctionReturn, SlotToReg, SlotToReg, RegToSlot, SlotToReg, SlotToReg, RegToSlot, SlotToReg, SlotToReg, RegToSlot,