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, as) 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