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
# 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

View File

@ -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)