implement offset addressing for load (ie reg+num)
This commit is contained in:
parent
2784a8da98
commit
5127deeeff
@ -28,32 +28,25 @@ module Asm
|
|||||||
|
|
||||||
# Build representation for target address
|
# Build representation for target address
|
||||||
def build_operand(arg)
|
def build_operand(arg)
|
||||||
#str / ldr are _seruous instructions. With BIG possibilities no half are implemented
|
#str / ldr are _serious instructions. With BIG possibilities not half are implemented
|
||||||
@i = 0
|
@i = 0
|
||||||
@pre_post_index = 0
|
@pre_post_index = 0
|
||||||
@w = 0
|
@w = 0
|
||||||
@operand = 0
|
@operand = 0
|
||||||
if (arg.is_a?(Asm::RegisterNode))
|
if (arg.is_a?(Asm::RegisterNode))
|
||||||
@rn = reg_ref(arg)
|
@rn = reg_ref(arg)
|
||||||
|
if(arg.offset != 0)
|
||||||
if (false ) #argr.op and argr.right.is_a?(Asm::NumLiteralNode))
|
@operand = arg.offset
|
||||||
|
if (@operand < 0)
|
||||||
# this if was buggy even before
|
|
||||||
# but as mentioned here we'd have to implement the options
|
|
||||||
# though a better syntax will have to be found
|
|
||||||
val = argr.right.value
|
|
||||||
if (val < 0)
|
|
||||||
@add_offset = 0
|
@add_offset = 0
|
||||||
val *= -1
|
#TODO test/check/understand
|
||||||
|
@operand *= -1
|
||||||
else
|
else
|
||||||
@add_offset = 1
|
@add_offset = 1
|
||||||
end
|
end
|
||||||
if (val.abs > 4095)
|
if (@operand.abs > 4095)
|
||||||
raise Asm::AssemblyError.new('reference offset too large/small (max 4095)', argr.right)
|
raise Asm::AssemblyError.new('reference offset too large/small (max 4095)', argr.right)
|
||||||
end
|
end
|
||||||
@operand = val
|
|
||||||
else
|
|
||||||
# raise Asm::AssemblyError.new(Asm::ERRSTR_INVALID_ARG, arg)
|
|
||||||
end
|
end
|
||||||
elsif (arg.is_a?(Asm::LabelRefNode) or arg.is_a?(Asm::NumLiteralNode))
|
elsif (arg.is_a?(Asm::LabelRefNode) or arg.is_a?(Asm::NumLiteralNode))
|
||||||
@pre_post_index = 1
|
@pre_post_index = 1
|
||||||
|
@ -11,10 +11,22 @@ module Asm
|
|||||||
attr_accessor :type, :value, :argument
|
attr_accessor :type, :value, :argument
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Registers have off course a name (r1-16 for arm)
|
||||||
|
# but also refer to an address. In other words they can be an operand for instructions.
|
||||||
|
# Arm has addressing modes abound, and so can add to a register before actually using it
|
||||||
|
# If can actually shift or indeed shift what it adds, but not implemented
|
||||||
class RegisterNode < Node
|
class RegisterNode < Node
|
||||||
attr_accessor :name
|
attr_accessor :name , :offset
|
||||||
def initialize name
|
def initialize name
|
||||||
@name = name
|
@name = name
|
||||||
|
@offset = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
# this is for the dsl, so we can write pretty code like r1 + 4
|
||||||
|
# when we want to access the next word (4) after r1
|
||||||
|
def + number
|
||||||
|
@offset = number
|
||||||
|
self
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ class TestArmAsm < MiniTest::Test
|
|||||||
end
|
end
|
||||||
def test_ldr2
|
def test_ldr2
|
||||||
code = @generator.instance_eval { ldr r0, r0 + 4 }.first
|
code = @generator.instance_eval { ldr r0, r0 + 4 }.first
|
||||||
assert_code code, :ldr , [0x00,0x00,0x90,0xe5] #e5 90 00 00
|
assert_code code, :ldr , [0x04,0x00,0x90,0xe5] #e5 90 00 04
|
||||||
end
|
end
|
||||||
def test_ldrb
|
def test_ldrb
|
||||||
code = @generator.instance_eval { ldrb r0, r0 }.first
|
code = @generator.instance_eval { ldrb r0, r0 }.first
|
||||||
|
Loading…
Reference in New Issue
Block a user