diff --git a/lib/risc/instructions/operator_instruction.rb b/lib/risc/instructions/operator_instruction.rb index 73c4b705..a0d877bb 100644 --- a/lib/risc/instructions/operator_instruction.rb +++ b/lib/risc/instructions/operator_instruction.rb @@ -3,33 +3,42 @@ module Risc def self.operators [:+, :-, :>>, :<<, :*, :&, :|] end - # Destructive operator instructions on the two registers given + + # Operator instructions on the first two registers given + # # Result into the last register # - # left = left OP right + # result = left OP right # # With OP being the normal logical and mathematical operations provided by # cpus. Ie "+" , "-", ">>", "<<", "*", "&", "|" # + # Result may be nil, then register is autogenerated + # class OperatorInstruction < Instruction - def initialize( source , operator , left , right ) + def initialize( source , operator , left , right , result = nil) super(source) operator = operator.value if operator.is_a?(Sol::Constant) @operator = operator raise "unsuported operator :#{operator}:#{operator.class}:" unless Risc.operators.include?(operator) @left = left @right = right - raise "Not register #{left}" unless RegisterValue.look_like_reg(left) - raise "Not register #{right}" unless RegisterValue.look_like_reg(right) + raise "Not register #{left}" unless left.is_a?(RegisterValue) + raise "Not register #{right}" unless right.is_a?(RegisterValue) + unless result + result = RegisterValue.new("op_#{operator}_#{object_id.to_s(16)}".to_sym , :Integer) + end + raise "Not register #{result}" unless result.is_a?(RegisterValue) + @result = result end - attr_reader :operator, :left , :right + attr_reader :operator, :left , :right , :result def to_s class_source "#{left} #{operator} #{right}" end end - def self.op( source , operator , left , right ) - OperatorInstruction.new( source , operator , left , right ) + def self.op( source , operator , left , right , result = nil) + OperatorInstruction.new( source , operator , left , right , result) end end diff --git a/lib/risc/register_value.rb b/lib/risc/register_value.rb index 3d1d5664..efce6039 100644 --- a/lib/risc/register_value.rb +++ b/lib/risc/register_value.rb @@ -23,6 +23,7 @@ module Risc extra = {} unless extra @extra = extra @symbol = reg + raise "not Symbol #{symbol}:#{symbol.class}" unless symbol.is_a?(Symbol) raise "Not Hash #{extra}" unless extra.is_a?(Hash) known_type(type) end diff --git a/test/risc/instructions/test_operator_instruction.rb b/test/risc/instructions/test_operator_instruction.rb new file mode 100644 index 00000000..d9b26453 --- /dev/null +++ b/test/risc/instructions/test_operator_instruction.rb @@ -0,0 +1,23 @@ +require_relative "../helper" + +module Risc + class TestOperatorInstruction < MiniTest::Test + def setup + Parfait.boot!({}) + @left = RegisterValue.new(:left , :Integer) + @right = RegisterValue.new(:right , :Integer) + end + def risc(i) + @left.op :- , @right + end + def test_min + assert_operator 1 , :- , :left , :right , "op_-_" + end + def test_reg + result = risc(1).result + assert_equal RegisterValue , result.class + assert_equal "Integer_Type" , result.type.name + assert result.symbol.to_s.start_with?("op_-_") + end + end +end diff --git a/test/support/risc_assert.rb b/test/support/risc_assert.rb index ca5b4347..2cb15b2d 100644 --- a/test/support/risc_assert.rb +++ b/test/support/risc_assert.rb @@ -94,7 +94,7 @@ module Minitest assert_equal Risc::Branch , branch.class , "Class at:#{branch_i}" assert_label branch.label , label_name , "Label at #{branch_i}" end - def assert_operator ins_i , op , left , right + def assert_operator ins_i , op , left , right , result if(ins_i.is_a?(Integer)) ins = risc(ins_i) else @@ -105,6 +105,7 @@ module Minitest assert_equal op , ins.operator assert_register :left , left , ins.left , ins_i assert_register :right , right , ins.right, ins_i + assert_register :result , result , ins.result, ins_i end def assert_zero ins_i , label assert_equal Integer , ins_i.class, "assert_zero #{ins_i}"