2018-05-10 19:56:12 +02:00
|
|
|
module Risc
|
|
|
|
module Position
|
|
|
|
|
2018-05-11 17:36:45 +02:00
|
|
|
# Instructions are also a linked list, but their position is not really
|
|
|
|
# the position of the object.
|
|
|
|
# Rather it is the position of the assembled code in the binary.
|
|
|
|
# (Luckily arm is sane, so this is realtively simple)
|
|
|
|
#
|
|
|
|
# Really we only need to calculate Positions at a jump, so between the
|
|
|
|
# Jump and the label it jumps too. The other instructions are "just" fill.
|
|
|
|
# But off course we need to propagate positions to get it right.
|
|
|
|
#
|
|
|
|
# Assembled instructions are kept in BinaryCode objects.
|
|
|
|
# When propagating positions we have to see that the next position assembles into
|
|
|
|
# the same BinaryCode, or else move it and the code along
|
|
|
|
#
|
2018-05-10 19:56:12 +02:00
|
|
|
class InstructionPosition < ObjectPosition
|
|
|
|
attr_reader :instruction , :binary
|
|
|
|
def initialize(instruction, pos , binary)
|
2018-05-24 13:27:53 +02:00
|
|
|
raise "not set #{binary}" if pos != 0 and !binary.is_a?(Parfait::BinaryCode)
|
2018-05-23 20:34:49 +02:00
|
|
|
super(instruction,pos)
|
2018-05-10 19:56:12 +02:00
|
|
|
@instruction = instruction
|
|
|
|
@binary = binary
|
|
|
|
end
|
2018-05-25 18:03:46 +02:00
|
|
|
def init(at, binary)
|
2018-05-28 17:20:09 +02:00
|
|
|
@binary = binary
|
2018-05-30 23:07:58 +02:00
|
|
|
instruction.address.set_value(at) if instruction.is_a?(Label)
|
2018-05-24 13:27:53 +02:00
|
|
|
return if at == 0 and binary.nil?
|
2018-05-28 10:45:04 +02:00
|
|
|
raise "faux pas" if at < Position.get(binary).at
|
2018-05-24 13:27:53 +02:00
|
|
|
return unless @instruction.next
|
|
|
|
nekst = at + @instruction.byte_length
|
|
|
|
diff = nekst - Position.get(@binary).at
|
|
|
|
Position.log.debug "Diff: #{diff.to_s(16)} , next #{nekst.to_s(16)} , binary #{Position.get(@binary)}"
|
|
|
|
raise "Invalid position #{diff.to_s(16)} , next #{nekst.to_s(16)} #{self}" if diff < 8
|
2018-05-28 17:20:09 +02:00
|
|
|
if( (diff % (binary.padded_length - @instruction.byte_length)) == 0 )
|
|
|
|
binary.extend_one unless binary.next
|
|
|
|
binary = binary.next
|
|
|
|
raise "end of line " unless binary
|
|
|
|
nekst = Position.get(binary).at + Parfait::BinaryCode.byte_offset
|
2018-05-24 13:27:53 +02:00
|
|
|
Position.log.debug "Jump to: #{nekst.to_s(16)}"
|
2018-05-11 17:36:45 +02:00
|
|
|
end
|
2018-05-28 17:20:09 +02:00
|
|
|
Position.set(@instruction.next, nekst , binary)
|
2018-05-10 19:56:12 +02:00
|
|
|
end
|
|
|
|
|
2018-05-25 18:03:46 +02:00
|
|
|
def reset_to(pos , binary)
|
2018-05-28 10:45:04 +02:00
|
|
|
super(pos , binary)
|
2018-05-28 17:20:09 +02:00
|
|
|
init(pos , binary)
|
2018-05-24 13:27:53 +02:00
|
|
|
Position.log.debug "ResetInstruction (#{pos.to_s(16)}) #{instruction}"
|
2018-05-10 19:56:12 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|