refactor memory instruction (needs better tests)
This commit is contained in:
parent
190a0ffa47
commit
5cd05f6135
@ -16,7 +16,6 @@ module Arm
|
|||||||
@attributes[:condition_code] = :al if @attributes[:condition_code] == nil
|
@attributes[:condition_code] = :al if @attributes[:condition_code] == nil
|
||||||
@operand = 0
|
@operand = 0
|
||||||
raise "alert" if right.is_a? Register::Label
|
raise "alert" if right.is_a? Register::Label
|
||||||
@pre_post_index = @attributes[:pre_post_index] ? 0 : 1 #P flag
|
|
||||||
@add_offset = @attributes[:add_offset] ? 0 : 1 #U flag
|
@add_offset = @attributes[:add_offset] ? 0 : 1 #U flag
|
||||||
@is_load = opcode.to_s[0] == "l" ? 1 : 0 #L (load) flag
|
@is_load = opcode.to_s[0] == "l" ? 1 : 0 #L (load) flag
|
||||||
end
|
end
|
||||||
@ -25,30 +24,19 @@ module Arm
|
|||||||
# don't overwrite instance variables, to make assembly repeatable
|
# don't overwrite instance variables, to make assembly repeatable
|
||||||
#TODO better test, this operand integer (register) does not work.
|
#TODO better test, this operand integer (register) does not work.
|
||||||
def assemble(io)
|
def assemble(io)
|
||||||
rn , operand , add_offset , arg = @rn , @operand , @add_offset , @left
|
arg = @left
|
||||||
arg = arg.symbol if( arg.is_a? ::Register::RegisterValue )
|
arg = arg.symbol if( arg.is_a? ::Register::RegisterValue )
|
||||||
is_reg = arg.is_a?(::Register::RegisterValue)
|
is_reg = arg.is_a?(::Register::RegisterValue)
|
||||||
if( arg.is_a?(Symbol) and not is_reg)
|
is_reg = (arg.to_s[0] == "r") if( arg.is_a?(Symbol) and not is_reg)
|
||||||
is_reg = (arg.to_s[0] == "r")
|
|
||||||
end
|
|
||||||
raise "invalid operand argument #{arg.inspect} #{inspect}" unless (is_reg )
|
raise "invalid operand argument #{arg.inspect} #{inspect}" unless (is_reg )
|
||||||
rn = arg
|
operand = get_operand
|
||||||
if @right
|
|
||||||
operand = @right
|
|
||||||
operand = operand.symbol if operand.is_a? ::Register::RegisterValue
|
|
||||||
unless( operand.is_a? Symbol) #TODO test/check/understand
|
|
||||||
add_offset = (operand < 0) ? 0 : 1
|
|
||||||
operand *= -1 if (operand < 0)
|
|
||||||
raise "offset too large (max 4095) #{arg} #{inspect}" if (@operand.abs > 4095)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
#not sure about these 2 constants. They produce the correct output for str r0 , r1
|
#not sure about these 2 constants. They produce the correct output for str r0 , r1
|
||||||
# but i can't help thinking that that is because they are not used in that instruction and
|
# but i can't help thinking that that is because they are not used in that instruction and
|
||||||
# so it doesn't matter. Will see
|
# so it doesn't matter. Will see
|
||||||
if (operand.is_a?(Symbol) or operand.is_a?(::Register::RegisterValue))
|
if (operand.is_a?(Symbol) or operand.is_a?(::Register::RegisterValue))
|
||||||
val = reg_code(operand)
|
val = reg_code(operand)
|
||||||
@pre_post_index = 0
|
|
||||||
i = 1 # not quite sure about this, but it gives the output of as. read read read.
|
i = 1 # not quite sure about this, but it gives the output of as. read read read.
|
||||||
else
|
else
|
||||||
i = 0 #I flag (third bit)
|
i = 0 #I flag (third bit)
|
||||||
@ -57,23 +45,37 @@ module Arm
|
|||||||
# testing against gnu as, setting the flag produces correct output
|
# testing against gnu as, setting the flag produces correct output
|
||||||
# but gnu as produces same output for auto_inc or not, so that seems broken
|
# but gnu as produces same output for auto_inc or not, so that seems broken
|
||||||
# luckily auto_inc is not used and even if it clobbers unused reg in soml, but still
|
# luckily auto_inc is not used and even if it clobbers unused reg in soml, but still
|
||||||
@pre_post_index = 1
|
|
||||||
op = shift_handling
|
val = shift(val , 0 )
|
||||||
val = shift(val , 0 ) # for the test
|
val |= shift(reg_code(arg) , 16)
|
||||||
val |= shift(op , 0)
|
val |= shift(i , 25)
|
||||||
|
write_val(val, io)
|
||||||
|
end
|
||||||
|
|
||||||
|
def write_val(val, io)
|
||||||
|
val |= shift(shift_handling , 0)
|
||||||
val |= shift(reg_code(@result) , 12 )
|
val |= shift(reg_code(@result) , 12 )
|
||||||
val |= shift(reg_code(rn) , 12 + 4) #16
|
val |= shift(@is_load , 20)
|
||||||
val |= shift(@is_load , 12 + 4 + 4)
|
val |= shift(byte_access , 22)
|
||||||
val |= shift(0 , 12 + 4 + 4 + 1)
|
val |= shift(add_offset , 23)
|
||||||
val |= shift(byte_access , 12 + 4 + 4 + 1 + 1)
|
val |= shift(0, 21)
|
||||||
val |= shift(add_offset , 12 + 4 + 4 + 1 + 1 + 1)
|
val |= shift(1, 24) #pre_post index , not used
|
||||||
val |= shift(@pre_post_index, 12 + 4 + 4 + 1 + 1 + 1 + 1)#24
|
|
||||||
val |= shift(i , 12 + 4 + 4 + 1 + 1 + 1 + 1 + 1)
|
|
||||||
val |= instruction_code
|
val |= instruction_code
|
||||||
val |= condition_code
|
val |= condition_code
|
||||||
io.write_uint32 val
|
io.write_uint32 val
|
||||||
end
|
end
|
||||||
|
def get_operand
|
||||||
|
return @operand unless @right
|
||||||
|
operand = @right
|
||||||
|
operand = operand.symbol if operand.is_a? ::Register::RegisterValue
|
||||||
|
unless( operand.is_a? Symbol)
|
||||||
|
# TODO test/check/understand: has no effect in current tests
|
||||||
|
# add_offset = (operand < 0) ? 0 : 1
|
||||||
|
operand *= -1 if (operand < 0)
|
||||||
|
raise "offset too large (max 4095) #{arg} #{inspect}" if (@operand.abs > 4095)
|
||||||
|
end
|
||||||
|
operand
|
||||||
|
end
|
||||||
def instuction_class
|
def instuction_class
|
||||||
0b01 # OPC_MEMORY_ACCESS
|
0b01 # OPC_MEMORY_ACCESS
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user