diff --git a/lib/arm/instructions/logic_instruction.rb b/lib/arm/instructions/logic_instruction.rb index c454ddda..a31a8c57 100644 --- a/lib/arm/instructions/logic_instruction.rb +++ b/lib/arm/instructions/logic_instruction.rb @@ -62,21 +62,25 @@ module Arm # happen, and so they are split into two instructions. An exeption is thrown, that triggers # some position handling and an @extra add instruction generated. def handle_numeric(right) - if (right.fits_u8?) - operand = right # no shifting needed - elsif (op_with_rot = calculate_u8_with_rr(right)) - operand = op_with_rot - else - unless @extra - @extra = 1 - # puts "RELINK L at #{Risc::Position.get(self)}" - # use sub for sub and add for add, ie same as opcode - insert ArmMachine.send( opcode , result , result , 0 ) #noop - end + return right if (right.fits_u8?) # no shifting needed + if (op_with_rot = calculate_u8_with_rr(right)) + return op_with_rot + end + unless @extra + # puts "RELINK L at #{Risc::Position.get(self)}" + # use sub for sub and add for add, ie same as opcode + insert ArmMachine.send( opcode , result , result , 0 ) #noop + @extra = @next + end + shift = 0xFF + operand = nil + until( operand ) + mask = 0xFFFFFFFF ^ shift # 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} in #{self}" unless operand - @next.set_value(right & 0xFF ) + operand = calculate_u8_with_rr( right & mask ) + @next.set_value(right & shift ) + raise "internal #{shift} for #{self}" if shift > 0xFFFFFF + shift = (shift << 8) + 0xFF end return operand end @@ -97,9 +101,12 @@ module Arm right = Risc::Position.get(left) - 8 right -= Risc::Position.get(self).at if( (right < 0) && ((opcode == :add) || (opcode == :sub)) ) + puts "Inverting, was #{right} , new #{-1*right}" + puts "left #{left.class} #{Risc::Position.get(left)}" + puts "self #{Risc::Position.get(self)}" right *= -1 # this works as we never issue sub only add set_opcode :sub # so (as we can't change the sign permanently) we can change the opcode - end # and the sign even for sub (becuase we created them) + end # and the sign even for sub (beucase we created them) raise "No negatives implemented #{self} #{right} " if right < 0 return :pc , right else diff --git a/test/arm/test_logic.rb b/test/arm/test_logic.rb index 91b65a36..1c1b0fff 100644 --- a/test/arm/test_logic.rb +++ b/test/arm/test_logic.rb @@ -76,11 +76,11 @@ module Arm code = @machine.add( :r1 , :r2 , :r3 , shift_lsr: 8) assert_code code , :add , [0x23,0x14,0x92,0xe0] #e0 92 14 23 end - def test_big_add + def test_add_big code = @machine.add :r1 , :r1, 0x220 assert_code code , :add , [0x22,0x1e,0x91,0xe2] #e2 91 1e 22 end - def test_too_big_add + def test_add_2ins code = @machine.add :r1 , :r1, 0x222 Risc::Position.create(code).set(0) # add 0x02 (first instruction) and then 0x220 shifted @@ -88,6 +88,12 @@ module Arm # added extra instruction to add "extra" assert_code code.next , :add , [0x22,0x10,0x91,0xe2] #e2 91 10 22 end + def test_add_3ins + code = @machine.add :r1 , :r1, 0x29d84 + assert_code code , :add , [0x02,0x18,0x91,0xe2] + assert_code code.next , :add , [0x9d,0x1c,0x91,0xe2] + assert_code code.next.next , :add , [0x84,0x10,0x91,0xe2] + end def label( pos = 0x22 + 8) addr = FakeAddress.new(pos)