rubyx/lib/arm/instructions/stack_instruction.rb
2016-12-14 13:43:13 +02:00

83 lines
2.3 KiB
Ruby

module Arm
# ADDRESSING MODE 4
class StackInstruction < Register::Instruction
include Constants
include Attributed
def initialize(first , attributes)
super(nil)
@attributes = attributes
@first = first
@attributes[:update_status] = 0 if @attributes[:update_status] == nil
@attributes[:condition_code] = :al if @attributes[:condition_code] == nil
@attributes[:opcode] = attributes[:opcode]
@operand = 0
# @attributes[:update_status]= 0
@rn = :r0 # register zero = zero bit pattern
# downward growing, decrement before memory access
# official ARM style stack as used by gas
end
def assemble(io)
# don't overwrite instance variables, to make assembly repeatable
operand = @operand
if (@first.is_a?(Array))
operand = 0
@first.each do |r|
raise "nil register in push, index #{r}- #{inspect}" if r.nil?
operand = operand | (1 << reg_code(r))
end
else
raise "invalid operand argument #{inspect}"
end
write_base = 1
if (opcode == :push)
pre_post_index = 1
up_down = 0
is_pop = 0
else #pop
pre_post_index = 0
up_down = 1
is_pop = 1
end
instuction_class = 0b10 # OPC_STACK
cond = @attributes[:condition_code].is_a?(Symbol) ? COND_CODES[@attributes[:condition_code]] : @attributes[:condition_code]
@rn = :sp # sp register
#assemble of old
val = operand
val = val | (reg_code(@rn) << 16)
val = val | (is_pop << 16+4) #20
val = val | (write_base << 16+4+ 1)
val = val | (@attributes[:update_status] << 16+4+ 1+1)
val = val | (up_down << 16+4+ 1+1+1)
val = val | (pre_post_index << 16+4+ 1+1+1+1)#24
val = val | (instuction_class << 16+4+ 1+1+1+1 +2)
val = val | (cond << 16+4+ 1+1+1+1 +2+2)
io.write_uint32 val
end
def is_push?
opcode == :push
end
def is_pop?
!is_push?
end
def uses
is_push? ? regs : []
end
def assigns
is_pop? ? regs : []
end
def regs
@first
end
def to_s
"#{opcode} [#{@first.join(',') }] #{super}"
end
end
end