diff --git a/lib/arm/instructions/logic_instruction.rb b/lib/arm/instructions/logic_instruction.rb index 704106f1..12ef775c 100644 --- a/lib/arm/instructions/logic_instruction.rb +++ b/lib/arm/instructions/logic_instruction.rb @@ -47,7 +47,6 @@ module Arm val |= instruction_code val |= condition_code io.write_unsigned_int_32 val - assemble_extra(io) end def result @@ -71,17 +70,24 @@ module Arm unless @extra @extra = 1 #puts "RELINK L at #{self.position.to_s(16)}" + extra = ArmMachine.send( opcode , result , result , 0 ) #noop + extra.set_next( @next ) + @next = extra raise ::Risc::LinkException.new("cannot fit numeric literal argument in operand #{right.inspect}") end # now we can do the actual breaking of instruction, by splitting the operand operand = calculate_u8_with_rr( right & 0xFFFFFF00 ) raise "no fit for #{right}" unless operand # use sub for sub and add for add, ie same as opcode - @extra = ArmMachine.send( opcode , result , result , (right & 0xFF) ) + @next.set_value(right & 0xFF ) end return operand end + def set_value(val) + @right = val + end + # don't overwrite instance variables, to make assembly repeatable # this also loads constants, which are issued as pc relative adds def determine_operands @@ -101,20 +107,6 @@ module Arm end end - # by now we have the extra add so assemble that - def assemble_extra(io) - return unless @extra - if(@extra == 1) # unles things have changed and then we add a noop (to keep the length same) - @extra = ArmMachine.mov( :r1 , :r1 ) - end - @extra.assemble(io) - #puts "Assemble extra at #{val.to_s(16)}" - end - - def byte_length - @extra ? 8 : 4 - end - def to_s "#{self.class.name} #{opcode} #{@result} = #{@left} #{@right} extra=#{@extra}" end diff --git a/lib/arm/instructions/move_instruction.rb b/lib/arm/instructions/move_instruction.rb index 241c1884..7ab88e24 100644 --- a/lib/arm/instructions/move_instruction.rb +++ b/lib/arm/instructions/move_instruction.rb @@ -28,7 +28,7 @@ module Arm # know where the other object is, and that position is only set after code positions have been # determined (in link) and so see below in assemble def byte_length - @extra ? 8 : 4 + 4 end # don't overwrite instance variables, to make assembly repeatable @@ -55,8 +55,6 @@ module Arm val |= instruction_code val |= condition_code io.write_unsigned_int_32 val - # by now we have the extra add so assemble that - @extra.assemble(io) if(@extra) #puts "Assemble extra at #{val.to_s(16)}" end def instuction_class @@ -70,12 +68,15 @@ module Arm raise "No negatives implemented #{right} " if right < 0 unless @extra @extra = 1 # puts "RELINK M at #{self.position.to_s(16)}" + extra = ArmMachine.add( to , to , 0 ) #noop that we change below + extra.set_next(@next) + @next = extra raise ::Risc::LinkException.new("cannot fit numeric literal argument in operand #{right.inspect}") end # now we can do the actual breaking of instruction, by splitting the operand operand = calculate_u8_with_rr( right & 0xFFFFFF00 ) raise "no fit for #{right}" unless operand - @extra = ArmMachine.add( to , to , (right & 0xFF) ) + @next.set_value(right & 0xFF ) operand end end diff --git a/test/arm/helper.rb b/test/arm/helper.rb index 4fca2099..1c36a88d 100644 --- a/test/arm/helper.rb +++ b/test/arm/helper.rb @@ -12,7 +12,7 @@ module Arm # code is what the generator spits out, at least one instruction worth (.first) # the op code is wat was witten as assembler in the first place and the binary result - def assert_code code , op , should + def assert_code( code , op , should ) assert_equal op , code.opcode io = StringIO.new code.assemble(io) diff --git a/test/arm/test_logic.rb b/test/arm/test_logic.rb index bc9bb6f7..d3794357 100644 --- a/test/arm/test_logic.rb +++ b/test/arm/test_logic.rb @@ -83,10 +83,12 @@ module Arm def test_too_big_add code = @machine.add :r1 , :r1, 0x222 begin # add 0x02 (first instruction) and then 0x220 shifted - assert_code code , :add , [0x02,0x1c,0x91,0xe2, 0x22,0x10,0x91,0xe2] #e2 91 1e 22 + assert_code code , :add , [0x02,0x1c,0x91,0xe2] #e2 91 1e 02 rescue Risc::LinkException retry end + # added extra instruction to add "extra" + assert_code code.next , :add , [0x22,0x10,0x91,0xe2] #e2 91 10 22 end def label pos = 0x22 + 8 diff --git a/test/arm/test_move.rb b/test/arm/test_move.rb index 71f9405d..05cf535f 100644 --- a/test/arm/test_move.rb +++ b/test/arm/test_move.rb @@ -24,10 +24,11 @@ module Arm code = @machine.mov :r0, 0x222 # is not 8 bit and can't be rotated by the arm system in one instruction code.set_position(0) begin # mov 512(0x200) = e3 a0 0c 02 add 34(0x22) = e2 90 00 22 - assert_code code , :mov , [ 0x02,0x0c,0xb0,0xe3 , 0x22,0x00,0x90,0xe2] + assert_code code , :mov , [ 0x02,0x0c,0xb0,0xe3] rescue Risc::LinkException retry end + assert_code code.next , :add , [ 0x22,0x00,0x90,0xe2] end def test_mvn code = @machine.mvn :r1, 5