expand constant load

slightly hacky, but in good tradition
previous implementation only worked until 16 significant bits, which is getting to little
this one just keeps adding more instructions to arrive at the constant by force
There are surely cleverer ways of doing this, ie by using the barrel shifter
A start on #15, admittedly a hack
This commit is contained in:
Torsten Ruger 2018-08-31 23:28:31 +03:00
parent b2339dc330
commit c3b026a180
2 changed files with 30 additions and 17 deletions

View File

@ -62,21 +62,25 @@ module Arm
# happen, and so they are split into two instructions. An exeption is thrown, that triggers # happen, and so they are split into two instructions. An exeption is thrown, that triggers
# some position handling and an @extra add instruction generated. # some position handling and an @extra add instruction generated.
def handle_numeric(right) def handle_numeric(right)
if (right.fits_u8?) return right if (right.fits_u8?) # no shifting needed
operand = right # no shifting needed if (op_with_rot = calculate_u8_with_rr(right))
elsif (op_with_rot = calculate_u8_with_rr(right)) return op_with_rot
operand = op_with_rot end
else unless @extra
unless @extra # puts "RELINK L at #{Risc::Position.get(self)}"
@extra = 1 # use sub for sub and add for add, ie same as opcode
# puts "RELINK L at #{Risc::Position.get(self)}" insert ArmMachine.send( opcode , result , result , 0 ) #noop
# use sub for sub and add for add, ie same as opcode @extra = @next
insert ArmMachine.send( opcode , result , result , 0 ) #noop end
end shift = 0xFF
operand = nil
until( operand )
mask = 0xFFFFFFFF ^ shift
# now we can do the actual breaking of instruction, by splitting the operand # now we can do the actual breaking of instruction, by splitting the operand
operand = calculate_u8_with_rr( right & 0xFFFFFF00 ) operand = calculate_u8_with_rr( right & mask )
raise "no fit for #{right} in #{self}" unless operand @next.set_value(right & shift )
@next.set_value(right & 0xFF ) raise "internal #{shift} for #{self}" if shift > 0xFFFFFF
shift = (shift << 8) + 0xFF
end end
return operand return operand
end end
@ -97,9 +101,12 @@ module Arm
right = Risc::Position.get(left) - 8 right = Risc::Position.get(left) - 8
right -= Risc::Position.get(self).at right -= Risc::Position.get(self).at
if( (right < 0) && ((opcode == :add) || (opcode == :sub)) ) 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 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 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 raise "No negatives implemented #{self} #{right} " if right < 0
return :pc , right return :pc , right
else else

View File

@ -76,11 +76,11 @@ module Arm
code = @machine.add( :r1 , :r2 , :r3 , shift_lsr: 8) code = @machine.add( :r1 , :r2 , :r3 , shift_lsr: 8)
assert_code code , :add , [0x23,0x14,0x92,0xe0] #e0 92 14 23 assert_code code , :add , [0x23,0x14,0x92,0xe0] #e0 92 14 23
end end
def test_big_add def test_add_big
code = @machine.add :r1 , :r1, 0x220 code = @machine.add :r1 , :r1, 0x220
assert_code code , :add , [0x22,0x1e,0x91,0xe2] #e2 91 1e 22 assert_code code , :add , [0x22,0x1e,0x91,0xe2] #e2 91 1e 22
end end
def test_too_big_add def test_add_2ins
code = @machine.add :r1 , :r1, 0x222 code = @machine.add :r1 , :r1, 0x222
Risc::Position.create(code).set(0) Risc::Position.create(code).set(0)
# add 0x02 (first instruction) and then 0x220 shifted # add 0x02 (first instruction) and then 0x220 shifted
@ -88,6 +88,12 @@ module Arm
# added extra instruction to add "extra" # added extra instruction to add "extra"
assert_code code.next , :add , [0x22,0x10,0x91,0xe2] #e2 91 10 22 assert_code code.next , :add , [0x22,0x10,0x91,0xe2] #e2 91 10 22
end 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) def label( pos = 0x22 + 8)
addr = FakeAddress.new(pos) addr = FakeAddress.new(pos)