rubyx/lib/asm/memory_instruction.rb
2014-04-25 11:56:53 +03:00

80 lines
2.6 KiB
Ruby

require "asm/nodes"
module Asm
# ADDRESSING MODE 2
# Implemented: immediate offset with offset=0
class MemoryInstruction < Instruction
include Asm::InstructionTools
def initialize(opcode , args)
super( opcode , args )
@inst_class = OPC_MEMORY_ACCESS
@i = 0 #I flag (third bit)
@pre_post_index = 0 #P flag
@add_offset = 0 #U flag
@byte_access = opcode.to_s[-1] == "b" ? 1 : 0 #B (byte) flag
@w = 0 #W flag
@is_load = opcode.to_s[0] == "l" ? 1 : 0 #L (load) flag
@rn = reg "r0" # register zero = zero bit pattern
@rd = reg "r0" # register zero = zero bit pattern
end
attr_accessor :inst_class, :i, :pre_post_index, :add_offset,
:byte_access, :w, :is_load, :rn, :rd
# Build representation for target address
def build
if( @is_load )
@rd = args[0]
arg = args[1]
else #store
@rd = args[1]
arg = args[0]
end
#str / ldr are _serious instructions. With BIG possibilities not half are implemented
if (arg.is_a?(Asm::Register))
@rn = arg
if(arg.offset != 0)
@operand = arg.offset
if (@operand < 0)
@add_offset = 0
#TODO test/check/understand
@operand *= -1
else
@add_offset = 1
end
if (@operand.abs > 4095)
raise Asm::AssemblyError.new("reference offset too large/small (max 4095) #{argr.right}" )
end
end
elsif (arg.is_a?(Asm::Label) or arg.is_a?(Asm::NumLiteral))
@pre_post_index = 1
@rn = pc
@use_addrtable_reloc = true
@addrtable_reloc_target = arg
else
raise Asm::AssemblyError.new("invalid operand argument #{arg.inspect}")
end
end
def assemble(io)
build
#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
# so it doesn't matter. Will see
@add_offset = 1
@pre_post_index = 1
val = operand
val |= (rd.bits << 12 )
val |= (rn.bits << 12+4) #16
val |= (is_load << 12+4 +4)
val |= (w << 12+4 +4+1)
val |= (byte_access << 12+4 +4+1+1)
val |= (add_offset << 12+4 +4+1+1+1)
val |= (pre_post_index << 12+4 +4+1+1+1+1)#24
val |= (i << 12+4 +4+1+1+1+1 +1)
val |= (inst_class << 12+4 +4+1+1+1+1 +1+1)
val |= (cond_bit_code << 12+4 +4+1+1+1+1 +1+1+2)
io.write_uint32 val
end
end
end