moving instrctions into own folders and arm machine out of the way
This commit is contained in:
@ -1,24 +1,7 @@
|
||||
module Register
|
||||
|
||||
# The register machine model is close to current hardware and has following instruction classes
|
||||
# - Memory
|
||||
# - Stack
|
||||
# - Logic
|
||||
# - Math
|
||||
# - Control/Compare
|
||||
# - Move
|
||||
# - Call
|
||||
|
||||
# Instruction derives from Code, for the assembly api
|
||||
|
||||
class Instruction < Virtual::Object
|
||||
def initialize options
|
||||
@attributes = options
|
||||
end
|
||||
attr_reader :attributes
|
||||
def opcode
|
||||
@attributes[:opcode]
|
||||
end
|
||||
class Instruction
|
||||
|
||||
# returns an array of registers (RegisterReferences) that this instruction uses.
|
||||
# ie for r1 = r2 + r3
|
||||
# which in assembler is add r1 , r2 , r3
|
||||
@ -48,136 +31,4 @@ module Register
|
||||
end
|
||||
end
|
||||
|
||||
class StackInstruction < Instruction
|
||||
def initialize first , options = {}
|
||||
@first = first
|
||||
super(options)
|
||||
end
|
||||
# when calling we place a dummy push/pop in the stream and calculate later what registers actually need saving
|
||||
def set_registers regs
|
||||
@first = regs.collect{ |r| r.symbol }
|
||||
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.collect {|f| f.to_asm}.join(',') }] #{super}"
|
||||
end
|
||||
end
|
||||
class MemoryInstruction < Instruction
|
||||
def initialize result , left , right = nil , options = {}
|
||||
@result = result
|
||||
@left = left
|
||||
@right = right
|
||||
super(options)
|
||||
end
|
||||
def uses
|
||||
ret = [@left.register ]
|
||||
ret << @right.register unless @right.nil?
|
||||
ret
|
||||
end
|
||||
def assigns
|
||||
[@result.register]
|
||||
end
|
||||
end
|
||||
class LogicInstruction < Instruction
|
||||
# result = left op right
|
||||
#
|
||||
# Logic instruction are your basic operator implementation. But unlike the (normal) code we write
|
||||
# these Instructions must have "place" to write their results. Ie when you write 4 + 5 in ruby
|
||||
# the result is sort of up in the air, but with Instructions the result must be assigned
|
||||
def initialize result , left , right , options = {}
|
||||
@result = result
|
||||
@left = left
|
||||
@right = right.is_a?(Fixnum) ? Virtual::IntegerConstant.new(right) : right
|
||||
super(options)
|
||||
end
|
||||
attr_accessor :result , :left , :right
|
||||
def uses
|
||||
ret = []
|
||||
ret << @left.register if @left and not @left.is_a? Constant
|
||||
ret << @right.register if @right and not @right.is_a?(Constant)
|
||||
ret
|
||||
end
|
||||
def assigns
|
||||
[@result.register]
|
||||
end
|
||||
end
|
||||
class CompareInstruction < Instruction
|
||||
def initialize left , right , options = {}
|
||||
@left = left
|
||||
@right = right.is_a?(Fixnum) ? IntegerConstant.new(right) : right
|
||||
super(options)
|
||||
end
|
||||
def uses
|
||||
ret = [@left.register ]
|
||||
ret << @right.register unless @right.is_a? Constant
|
||||
ret
|
||||
end
|
||||
def assigns
|
||||
[]
|
||||
end
|
||||
def to_s
|
||||
"#{opcode} #{@left.to_asm} , #{@right.to_asm} #{super}"
|
||||
end
|
||||
end
|
||||
class MoveInstruction < Instruction
|
||||
def initialize to , from , options = {}
|
||||
@to = to
|
||||
@from = from.is_a?(Fixnum) ? Virtual::IntegerConstant.new(from) : from
|
||||
raise "move must have from set #{inspect}" unless from
|
||||
super(options)
|
||||
end
|
||||
attr_accessor :to , :from
|
||||
def uses
|
||||
@from.is_a?(Constant) ? [] : [@from.register]
|
||||
end
|
||||
def assigns
|
||||
[@to.register]
|
||||
end
|
||||
end
|
||||
class CallInstruction < Instruction
|
||||
def initialize first , options = {}
|
||||
@first = first
|
||||
super(options)
|
||||
opcode = @attributes[:opcode].to_s
|
||||
if opcode.length == 3 and opcode[0] == "b"
|
||||
@attributes[:condition_code] = opcode[1,2].to_sym
|
||||
@attributes[:opcode] = :b
|
||||
end
|
||||
if opcode.length == 6 and opcode[0] == "c"
|
||||
@attributes[:condition_code] = opcode[4,2].to_sym
|
||||
@attributes[:opcode] = :call
|
||||
end
|
||||
end
|
||||
def uses
|
||||
if opcode == :call
|
||||
@first.args.collect {|arg| arg.register }
|
||||
else
|
||||
[]
|
||||
end
|
||||
end
|
||||
def assigns
|
||||
if opcode == :call
|
||||
[RegisterReference.new(RegisterMachine.instance.return_register)]
|
||||
else
|
||||
[]
|
||||
end
|
||||
end
|
||||
def to_s
|
||||
"#{opcode} #{@first.to_asm} #{super}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Reference in New Issue
Block a user