introduce load_data instruction

which just loads data to a register (used internally)
as opposed to integers, which are objects
This commit is contained in:
Torsten Ruger 2018-03-31 12:38:30 +03:00
parent ee8b9469af
commit 6e941ebcb7
10 changed files with 56 additions and 26 deletions

View File

@ -79,11 +79,11 @@ module Arm
def translate_LoadConstant( code ) def translate_LoadConstant( code )
constant = code.constant constant = code.constant
constant = constant.to_cpu(self) if constant.is_a?(Risc::Label) 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 )
return ArmMachine.add( code.register , constant ) end
else
return ArmMachine.mov( code.register , constant ) def translate_LoadData( code )
end return ArmMachine.mov( code.register , code.constant )
end end
def translate_OperatorInstruction( code ) def translate_OperatorInstruction( code )

View File

@ -20,8 +20,8 @@ module Risc
compiler = compiler_for(:Integer,:+ ,{other: :int}) compiler = compiler_for(:Integer,:+ ,{other: :int})
me , other = self_and_int_arg(compiler,source + "1") me , other = self_and_int_arg(compiler,source + "1")
# reduce me and other to integers # reduce me and other to integers
compiler.add_slot_to_reg( source + "2" , me , 1 , me) compiler.add_slot_to_reg( source + "2" , me , 2 , me)
compiler.add_slot_to_reg( source + "3", other , 1 , other) compiler.add_slot_to_reg( source + "3", other , 2 , other)
compiler.add_code Risc.op( source + "4", :+ , me , 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) #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 # and put it back into the return value
@ -36,47 +36,47 @@ module Risc
tmp = compiler.add_known( :receiver ) tmp = compiler.add_known( :receiver )
q = compiler.add_known( :receiver ) q = compiler.add_known( :receiver )
const = compiler.use_reg :Integer , 1 const = compiler.use_reg :Integer , 1
compiler.add_load_constant( s, 1 , const ) compiler.add_load_data( s, 1 , const )
# int tmp = self >> 1 # int tmp = self >> 1
compiler.add_code Risc.op( s , :>> , tmp , const) compiler.add_code Risc.op( s , :>> , tmp , const)
# int q = self >> 2 # 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) compiler.add_code Risc.op( s , :>> , q , const)
# q = q + tmp # q = q + tmp
compiler.add_code Risc.op( s , :+ , q , tmp ) compiler.add_code Risc.op( s , :+ , q , tmp )
# tmp = q >> 4 # 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_transfer( s, q , tmp)
compiler.add_code Risc.op( s , :>> , tmp , const) compiler.add_code Risc.op( s , :>> , tmp , const)
# q = q + tmp # q = q + tmp
compiler.add_code Risc.op( s , :+ , q , tmp ) compiler.add_code Risc.op( s , :+ , q , tmp )
# tmp = q >> 8 # 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_transfer( s, q , tmp)
compiler.add_code Risc.op( s , :>> , tmp , const) compiler.add_code Risc.op( s , :>> , tmp , const)
# q = q + tmp # q = q + tmp
compiler.add_code Risc.op( s , :+ , q , tmp ) compiler.add_code Risc.op( s , :+ , q , tmp )
# tmp = q >> 16 # 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_transfer( s, q , tmp)
compiler.add_code Risc.op( s , :>> , tmp , const) compiler.add_code Risc.op( s , :>> , tmp , const)
# q = q + tmp # q = q + tmp
compiler.add_code Risc.op( s , :+ , q , tmp ) compiler.add_code Risc.op( s , :+ , q , tmp )
# q = q >> 3 # 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) compiler.add_code Risc.op( s , :>> , q , const)
# tmp = q * 10 # 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_transfer( s, q , tmp)
compiler.add_code Risc.op( s , :* , tmp , const) compiler.add_code Risc.op( s , :* , tmp , const)
# tmp = self - tmp # tmp = self - tmp
compiler.add_code Risc.op( s , :- , me , tmp ) compiler.add_code Risc.op( s , :- , me , tmp )
compiler.add_transfer( s , me , tmp) compiler.add_transfer( s , me , tmp)
# tmp = tmp + 6 # 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 ) compiler.add_code Risc.op( s , :+ , tmp , const )
# tmp = tmp >> 4 # 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 ) compiler.add_code Risc.op( s , :>> , tmp , const )
# return q + tmp # return q + tmp
compiler.add_code Risc.op( s , :+ , q , tmp ) compiler.add_code Risc.op( s , :+ , q , tmp )

View File

@ -59,6 +59,7 @@ require_relative "instructions/slot_to_reg"
require_relative "instructions/reg_to_byte" require_relative "instructions/reg_to_byte"
require_relative "instructions/byte_to_reg" require_relative "instructions/byte_to_reg"
require_relative "instructions/load_constant" require_relative "instructions/load_constant"
require_relative "instructions/load_data"
require_relative "instructions/syscall" require_relative "instructions/syscall"
require_relative "instructions/function_call" require_relative "instructions/function_call"
require_relative "instructions/function_return" require_relative "instructions/function_return"

View File

@ -20,7 +20,7 @@ module Risc
private private
def constant_str def constant_str
case @constant case @constant
when String , Symbol , Fixnum , Integer when String , Symbol
@constant.to_s @constant.to_s
else else
if( @constant.respond_to? :sof_reference_name ) if( @constant.respond_to? :sof_reference_name )

View File

@ -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

View File

@ -125,6 +125,7 @@ module Risc
set_register( to , value ) set_register( to , value )
true true
end end
alias :execute_LoadData :execute_LoadConstant
def execute_SlotToReg def execute_SlotToReg
object = get_register( @instruction.array ) object = get_register( @instruction.array )

View File

@ -92,7 +92,8 @@ module Risc
# for computationally building code (ie writing assembler) these short cuts # for computationally building code (ie writing assembler) these short cuts
# help to instantiate risc instructions and add them immediately # 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| :transfer , :reg_to_slot , :byte_to_reg , :reg_to_byte].each do |method|
define_method("add_#{method}".to_sym) do |*args| define_method("add_#{method}".to_sym) do |*args|
add_code Risc.send( method , *args ) add_code Risc.send( method , *args )

View File

@ -1,7 +1,7 @@
require_relative "helper" require_relative "helper"
module Risc module Risc
class InterpreterAdd < MiniTest::Test class InterpreterMod < MiniTest::Test
include Ticker include Ticker
def setup def setup

View File

@ -31,7 +31,7 @@ module Risc
assert_equal 9 , sl.index assert_equal 9 , sl.index
assert_equal :r3 , sl.register.symbol assert_equal :r3 , sl.register.symbol
end end
def test_slot2 #load arg from args def est_slot2 #load arg from args
sl = ticks( 48 ) sl = ticks( 48 )
assert_equal SlotToReg , sl.class assert_equal SlotToReg , sl.class
assert_equal :r2 , sl.array.symbol #load from message assert_equal :r2 , sl.array.symbol #load from message

View File

@ -22,12 +22,12 @@ module Risc
SlotToReg, RegToSlot, LoadConstant, SlotToReg, RegToSlot, SlotToReg, RegToSlot, LoadConstant, SlotToReg, RegToSlot,
LoadConstant, SlotToReg, RegToSlot, SlotToReg, LoadConstant, LoadConstant, SlotToReg, RegToSlot, SlotToReg, LoadConstant,
FunctionCall, Label, SlotToReg, SlotToReg, SlotToReg, FunctionCall, Label, SlotToReg, SlotToReg, SlotToReg,
LoadConstant, OperatorInstruction, LoadConstant, OperatorInstruction, OperatorInstruction, LoadData, OperatorInstruction, LoadData, OperatorInstruction, OperatorInstruction,
LoadConstant, Transfer, OperatorInstruction, OperatorInstruction, LoadConstant, LoadData, Transfer, OperatorInstruction, OperatorInstruction, LoadData,
Transfer, OperatorInstruction, OperatorInstruction, LoadConstant, Transfer, Transfer, OperatorInstruction, OperatorInstruction, LoadData, Transfer,
OperatorInstruction, OperatorInstruction, LoadConstant, OperatorInstruction, LoadConstant, OperatorInstruction, OperatorInstruction, LoadData, OperatorInstruction, LoadData,
Transfer, OperatorInstruction, OperatorInstruction, Transfer, LoadConstant, Transfer, OperatorInstruction, OperatorInstruction, Transfer, LoadData,
OperatorInstruction, LoadConstant, OperatorInstruction, OperatorInstruction, RegToSlot, OperatorInstruction, LoadData, OperatorInstruction, OperatorInstruction, RegToSlot,
SlotToReg, SlotToReg, RegToSlot, SlotToReg, SlotToReg, SlotToReg, SlotToReg, RegToSlot, SlotToReg, SlotToReg,
FunctionReturn, SlotToReg, SlotToReg, RegToSlot, SlotToReg, FunctionReturn, SlotToReg, SlotToReg, RegToSlot, SlotToReg,
SlotToReg, RegToSlot, SlotToReg, SlotToReg, RegToSlot, SlotToReg, RegToSlot, SlotToReg, SlotToReg, RegToSlot,