From a46b2d5c56d8b7f7799c4061d9c81637e50830fc Mon Sep 17 00:00:00 2001 From: Torsten Ruger Date: Fri, 29 May 2015 12:33:40 +0300 Subject: [PATCH] update to use parfait not virtual more ripples reverting to integers (not virtual::integer) --- lib/arm/instruction.rb | 18 ++++--------- lib/arm/instructions/call_instruction.rb | 18 +++++-------- lib/arm/instructions/compare_instruction.rb | 28 +++++++++---------- lib/arm/instructions/logic_instruction.rb | 30 +++++++++------------ lib/arm/instructions/memory_instruction.rb | 16 +++++------ lib/arm/instructions/move_instruction.rb | 4 +-- lib/parfait.rb | 1 + 7 files changed, 49 insertions(+), 66 deletions(-) diff --git a/lib/arm/instruction.rb b/lib/arm/instruction.rb index 6a8719e0..80f79a18 100644 --- a/lib/arm/instruction.rb +++ b/lib/arm/instruction.rb @@ -8,6 +8,8 @@ module Arm # - Move # - Call class Instruction class Instruction + include Positioned + def initialize options @attributes = options end @@ -15,28 +17,18 @@ module Arm def opcode @attributes[:opcode] end - def position - raise "position accessed but not set at #{length} for #{self.inspect}" if @position == nil - @position - end - def set_position pos - # resetting of position used to be error, but since relink and dynamic instruction size it is ok. in measures - if @position != nil and ((@position - pos).abs > 32) - raise "position set again #{pos}!=#{@position} for #{self}" - end - @position = pos - end + # this is giving read access to the attributes hash via .attibute syntax # so for an instruction pop you can write pop.opcode to get the :opcode attribute # TODDO: review (don't remember what the "set_" stuff was for) - def method_missing name , *args , &block + def method_missing name , *args , &block return super unless (args.length <= 1) or block_given? set , attribute = name.to_s.split("set_") if set == "" @attributes[attribute.to_sym] = args[0] || 1 - return self + return self else return super end diff --git a/lib/arm/instructions/call_instruction.rb b/lib/arm/instructions/call_instruction.rb index cdc53a79..94de8769 100644 --- a/lib/arm/instructions/call_instruction.rb +++ b/lib/arm/instructions/call_instruction.rb @@ -33,33 +33,27 @@ module Arm when :b, :call arg = @first #puts "BLAB #{arg.inspect}" - if( arg.is_a? Fixnum ) #HACK to not have to change the code just now - arg = Virtual::IntegerConstant.new( arg ) - end - if arg.is_a?(Virtual::Block) or arg.is_a?(Virtual::CompiledMethodInfo) + if arg.is_a?(Virtual::Block) or arg.is_a?(Parfait::Method) #relative addressing for jumps/calls diff = arg.position - self.position # but because of the arm "theoretical" 3- stage pipeline, we have to subtract 2 words (fetch/decode) # But, for methods, this happens to be the size of the object header, so there it balances out, but not blocks diff -= 8 if arg.is_a?(Virtual::Block) - arg = Virtual::IntegerConstant.new(diff) + arg = diff end - if (arg.is_a?(Virtual::IntegerConstant)) - jmp_val = arg.integer >> 2 + if (arg.is_a?(Numeric)) + jmp_val = arg >> 2 packed = [jmp_val].pack('l') # signed 32-bit, condense to 24-bit # TODO add check that the value fits into 24 bits io << packed[0,3] else - raise "else not coded arg =#{arg}: #{inspect}" + raise "else not coded arg =\n#{arg.to_s[0..1000]}: #{inspect[0..1000]}" end io.write_uint8 op_bit_code | (COND_CODES[@attributes[:condition_code]] << 4) when :swi arg = @first - if( arg.is_a? Fixnum ) #HACK to not have to change the code just now - arg = Virtual::IntegerConstant.new( arg ) - end - if (arg.is_a?(Virtual::IntegerConstant)) + if (arg.is_a?(Numeric)) packed = [arg.integer].pack('L')[0,3] io << packed io.write_uint8 0b1111 | (COND_CODES[@attributes[:condition_code]] << 4) diff --git a/lib/arm/instructions/compare_instruction.rb b/lib/arm/instructions/compare_instruction.rb index d7075d4a..f23914eb 100644 --- a/lib/arm/instructions/compare_instruction.rb +++ b/lib/arm/instructions/compare_instruction.rb @@ -1,19 +1,19 @@ module Arm class CompareInstruction < Instruction include Arm::Constants - + def initialize(left , right , attributes) super(attributes) @left = left @right = right.is_a?(Fixnum) ? IntegerConstant.new(right) : right @attributes[:condition_code] = :al if @attributes[:condition_code] == nil @operand = 0 - @immediate = 0 + @immediate = 0 @attributes[:update_status] = 1 @rn = left @rd = :r0 end - + def assemble(io) # don't overwrite instance variables, to make assembly repeatable rn = @rn @@ -21,16 +21,16 @@ module Arm immediate = @immediate arg = @right - if arg.is_a?(Virtual::ObjectConstant) + if arg.is_a?(Parfait::Object) # do pc relative addressing with the difference to the instuction # 8 is for the funny pipeline adjustment (ie oc pointing to fetch and not execute) - arg = Virtual::IntegerConstant.new( arg.position - self.position - 8 ) + arg = arg.position - self.position - 8 rn = :pc end - if( arg.is_a? Fixnum ) #HACK to not have to change the code just now + if( arg.is_a? Symbol ) arg = Register::RegisterReference.new( arg ) end - if (arg.is_a?(Virtual::IntegerConstant)) + if (arg.is_a?(Numeric)) if (arg.fits_u8?) # no shifting needed operand = arg.integer @@ -54,7 +54,7 @@ module Arm # ror #0 == rrx raise "cannot rotate by zero #{arg} #{inspect}" end - + arg1 = arg.value if (arg1.is_a?(Virtual::IntegerConstant)) if (arg1.value >= 32) @@ -72,16 +72,16 @@ module Arm raise "invalid operand argument #{arg.inspect} , #{inspect}" end instuction_class = 0b00 # OPC_DATA_PROCESSING - val = (operand.is_a?(Symbol) or operand.is_a?(::Register::RegisterReference)) ? reg_code(operand) : operand + val = (operand.is_a?(Symbol) or operand.is_a?(::Register::RegisterReference)) ? reg_code(operand) : operand val = 0 if val == nil val = shift(val , 0) raise inspect unless reg_code(@rd) - val |= shift(reg_code(@rd) , 12) - val |= shift(reg_code(rn) , 12+4) - val |= shift(@attributes[:update_status] , 12+4+4)#20 + val |= shift(reg_code(@rd) , 12) + val |= shift(reg_code(rn) , 12+4) + val |= shift(@attributes[:update_status] , 12+4+4)#20 val |= shift(op_bit_code , 12+4+4 +1) - val |= shift(immediate , 12+4+4 +1+4) - val |= shift(instuction_class , 12+4+4 +1+4+1) + val |= shift(immediate , 12+4+4 +1+4) + val |= shift(instuction_class , 12+4+4 +1+4+1) val |= shift(cond_bit_code , 12+4+4 +1+4+1+2) io.write_uint32 val end diff --git a/lib/arm/instructions/logic_instruction.rb b/lib/arm/instructions/logic_instruction.rb index 9b9a4cbb..046ab492 100644 --- a/lib/arm/instructions/logic_instruction.rb +++ b/lib/arm/instructions/logic_instruction.rb @@ -2,21 +2,21 @@ module Arm class LogicInstruction < Instruction include Arm::Constants # result = left op right - # + # # Logic instruction are your basic operator implementation. But unlike the (normal) code we write # these Instructions must have "place" to write their results. Ie when you write 4 + 5 in ruby - # the result is sort of up in the air, but with Instructions the result must be assigned + # the result is sort of up in the air, but with Instructions the result must be assigned def initialize(result , left , right , attributes = {}) super(attributes) @result = result @left = left - @right = right.is_a?(Fixnum) ? Virtual::IntegerConstant.new(right) : right + @right = right @attributes[:update_status] = 0 if @attributes[:update_status] == nil @attributes[:condition_code] = :al if @attributes[:condition_code] == nil @operand = 0 raise "Left arg must be given #{inspect}" unless @left - @immediate = 0 + @immediate = 0 end attr_accessor :result , :left , :right @@ -27,17 +27,13 @@ module Arm immediate = @immediate right = @right - if @left.is_a?(Virtual::ObjectConstant) + if @left.is_a?(Parfait::Object) # do pc relative addressing with the difference to the instuction # 8 is for the funny pipeline adjustment (ie pointing to fetch and not execute) - right = @left.position - self.position - 8 + right = @left.position - self.position - 8 left = :pc end - # automatic wrapping, for machine internal code and testing - if( right.is_a? Fixnum ) - right = Virtual::IntegerConstant.new( right ) - end - if (right.is_a?(Virtual::IntegerConstant)) + if (right.is_a?(Numeric)) if (right.fits_u8?) # no shifting needed operand = right.integer @@ -58,12 +54,12 @@ module Arm instuction_class = 0b00 # OPC_DATA_PROCESSING val = shift(operand , 0) val |= shift(op , 0) # any barral action, is already shifted - val |= shift(reg_code(@result) , 12) - val |= shift(reg_code(left) , 12+4) - val |= shift(@attributes[:update_status] , 12+4+4)#20 + val |= shift(reg_code(@result) , 12) + val |= shift(reg_code(left) , 12+4) + val |= shift(@attributes[:update_status] , 12+4+4)#20 val |= shift(op_bit_code , 12+4+4 +1) - val |= shift(immediate , 12+4+4 +1+4) - val |= shift(instuction_class , 12+4+4 +1+4+1) + val |= shift(immediate , 12+4+4 +1+4) + val |= shift(instuction_class , 12+4+4 +1+4+1) val |= shift(cond_bit_code , 12+4+4 +1+4+1+2) io.write_uint32 val end @@ -71,7 +67,7 @@ module Arm raise "Not integer #{val}:#{val.class} #{inspect}" unless val.is_a? Fixnum val << by end - + def uses ret = [] ret << @left.register if @left and not @left.is_a? Constant diff --git a/lib/arm/instructions/memory_instruction.rb b/lib/arm/instructions/memory_instruction.rb index 95832c97..2362141c 100644 --- a/lib/arm/instructions/memory_instruction.rb +++ b/lib/arm/instructions/memory_instruction.rb @@ -1,7 +1,7 @@ module Arm # ADDRESSING MODE 2 # Implemented: immediate offset with offset=0 - + class MemoryInstruction < Instruction include Arm::Constants def initialize result , left , right = nil , attributes = {} @@ -46,14 +46,14 @@ module Arm end end end - elsif (arg.is_a?(Virtual::ObjectConstant) ) #use pc relative + elsif (arg.is_a?(Parfait::Object) ) #use pc relative rn = :pc operand = arg.position - self.position - 8 #stringtable is after code add_offset = 1 if (operand.abs > 4095) raise "reference offset too large/small (max 4095) #{arg} #{inspect}" end - elsif( arg.is_a?(Virtual::IntegerConstant) ) + elsif( arg.is_a?(Numeric) ) #TODO untested brach, probably not working raise "is this working ?? #{arg} #{inspect}" @pre_post_index = 1 @@ -75,7 +75,7 @@ module Arm byte_access = opcode.to_s[-1] == "b" ? 1 : 0 #B (byte) flag instuction_class = 0b01 # OPC_MEMORY_ACCESS if (operand.is_a?(Symbol) or operand.is_a?(::Register::RegisterReference)) - val = reg_code(operand) + val = reg_code(operand) @pre_post_index = 0 i = 1 # not quite sure about this, but it gives the output of as. read read read. else @@ -83,15 +83,15 @@ module Arm val = operand end val = shift(val , 0 ) # for the test - val |= shift(reg_code(@result) , 12 ) - val |= shift(reg_code(rn) , 12+4) #16 + val |= shift(reg_code(@result) , 12 ) + val |= shift(reg_code(rn) , 12+4) #16 val |= shift(@is_load , 12+4 +4) val |= shift(w , 12+4 +4+1) val |= shift(byte_access , 12+4 +4+1+1) val |= shift(add_offset , 12+4 +4+1+1+1) val |= shift(@pre_post_index, 12+4 +4+1+1+1+1)#24 val |= shift(i , 12+4 +4+1+1+1+1 +1) - val |= shift(instuction_class,12+4 +4+1+1+1+1 +1+1) + val |= shift(instuction_class,12+4 +4+1+1+1+1 +1+1) val |= shift(cond_bit_code , 12+4 +4+1+1+1+1 +1+1+2) io.write_uint32 val end @@ -109,4 +109,4 @@ module Arm [@result.register] end end -end \ No newline at end of file +end diff --git a/lib/arm/instructions/move_instruction.rb b/lib/arm/instructions/move_instruction.rb index ef23af34..f07a8ac1 100644 --- a/lib/arm/instructions/move_instruction.rb +++ b/lib/arm/instructions/move_instruction.rb @@ -36,7 +36,7 @@ module Arm operand = @operand immediate = @immediate right = @from - if right.is_a?(Virtual::ObjectConstant) + if right.is_a?(Parfait::Object) r_pos = right.position # do pc relative addressing with the difference to the instuction # 8 is for the funny pipeline adjustment (ie pc pointing to fetch and not execute) @@ -44,7 +44,7 @@ module Arm puts "Position #{r_pos} from #{self.position} = #{right}" rn = :pc end - if (right.is_a?(Virtual::IntegerConstant)) + if (right.is_a?(Numeric)) if (right.fits_u8?) # no shifting needed operand = right.integer diff --git a/lib/parfait.rb b/lib/parfait.rb index a59599af..565ad99f 100644 --- a/lib/parfait.rb +++ b/lib/parfait.rb @@ -1,4 +1,5 @@ require "parfait/value" +require "parfait/integer" require "parfait/object" require "parfait/module" require "parfait/class"